diff --git a/.gitignore b/.gitignore
index 44e4f858d9..3abba0aea7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -13,6 +13,7 @@
######################
esp32/build/
esp32/build-*/
+esp32/factory_fw/binary/
mpy-cross/build/*
# This map file is generated here instead of the build folder...
mpy-cross/*.map
diff --git a/.gitmodules b/.gitmodules
index c986704caa..f4334e16d4 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,20 +1,36 @@
+[submodule "lib/asf4"]
+ path = lib/asf4
+ url = https://github.com/adafruit/asf4
[submodule "lib/axtls"]
path = lib/axtls
url = https://github.com/pfalcon/axtls
- branch = micropython
+[submodule "lib/berkeley-db-1.xx"]
+ path = lib/berkeley-db-1.xx
+ url = https://github.com/pfalcon/berkeley-db-1.xx
+[submodule "lib/btstack"]
+ path = lib/btstack
+ url = https://github.com/bluekitchen/btstack.git
[submodule "lib/libffi"]
path = lib/libffi
url = https://github.com/atgreen/libffi
[submodule "lib/lwip"]
path = lib/lwip
url = https://git.savannah.gnu.org/r/lwip.git
-[submodule "lib/berkeley-db-1.xx"]
- path = lib/berkeley-db-1.xx
- url = https://github.com/pfalcon/berkeley-db-1.xx
-[submodule "lib/stm32lib"]
- path = lib/stm32lib
- url = https://github.com/micropython/stm32lib
- branch = work-F4-1.13.1+F7-1.5.0+L4-1.3.0
+[submodule "lib/mbedtls"]
+ path = lib/mbedtls
+ url = https://github.com/ARMmbed/mbedtls.git
+[submodule "lib/mynewt-nimble"]
+ path = lib/mynewt-nimble
+ url = https://github.com/apache/mynewt-nimble.git
[submodule "lib/nrfx"]
path = lib/nrfx
url = https://github.com/NordicSemiconductor/nrfx.git
+[submodule "lib/nxp_driver"]
+ path = lib/nxp_driver
+ url = https://github.com/hathach/nxp_driver.git
+[submodule "lib/stm32lib"]
+ path = lib/stm32lib
+ url = https://github.com/micropython/stm32lib
+[submodule "lib/tinyusb"]
+ path = lib/tinyusb
+ url = https://github.com/hathach/tinyusb
diff --git a/Jenkinsfile b/Jenkinsfile
index 28fdf0b66a..2a12d0b01a 100644
--- a/Jenkinsfile
+++ b/Jenkinsfile
@@ -1,5 +1,5 @@
def buildVersion
-def boards_to_build = ["WiPy", "LoPy", "SiPy", "GPy", "FiPy", "LoPy4"]
+def boards_to_build = ["WiPy", "LoPy", "GPy", "FiPy", "LoPy4"]
def variants_to_build = [ "PYBYTES" ]
// FIXME: there must be a better way of adding PYGATE to Jenkins, but it evades me :(
def pygate_boards_to_build = ["WiPy", "GPy", "LoPy4"]
@@ -12,11 +12,12 @@ node {
stage('Checkout') {
checkout scm
sh 'rm -rf esp-idf'
- sh 'git clone --recursive -b idf_v3.3.1 https://github.com/pycom/pycom-esp-idf.git esp-idf'
+ sh 'git clone --recursive -b idf_v4.1 git@github.com:pycom/pycom-esp-idf.git esp-idf'
IDF_HASH=get_idf_hash()
dir('esp-idf'){
sh 'git checkout ' + IDF_HASH
sh 'git submodule update --init --recursive'
+ sh 'git clean -d -f -f'
}
}
@@ -84,13 +85,13 @@ for (variant in variants_to_build) {
def boardBuild(name, variant, open_thread) {
return {
release_dir = "${JENKINS_HOME}/release/${JOB_NAME}/" + PYCOM_VERSION + "/" + GIT_TAG + "/"
- sh '''export PATH=$PATH:/opt/xtensa-esp32-elf/bin;
+ sh '''export PATH=$PATH:/opt/2020r3/xtensa-esp32-elf/bin/;
export IDF_PATH=${WORKSPACE}/esp-idf;
make -C esp32 clean BOARD=''' + name.toUpperCase() + ' VARIANT=' + variant
- sh '''export PATH=$PATH:/opt/xtensa-esp32-elf/bin;
+ sh '''export PATH=$PATH:/opt/2020r3/xtensa-esp32-elf/bin/;
export IDF_PATH=${WORKSPACE}/esp-idf;
make -C esp32 -j2 release BOARD=''' + name.toUpperCase() + ' VARIANT=' + variant + ' OPENTHREAD=' + open_thread
- sh 'mkdir -p ' + release_dir + variant + '/'
+ sh 'mkdir -p ' + release_dir + variant + '/'
sh 'cp esp32/build-' + variant + '/' + name + '-' + PYCOM_VERSION + '.tar.gz ' + release_dir + variant + '/'
sh 'mv esp32/build-' + variant + '/' + name.toUpperCase() + '/release/application.elf ' + release_dir + variant + '/' + name + "-" + PYCOM_VERSION + '-application.elf'
}
diff --git a/README.md b/README.md
index 13446f79da..9a755c9e67 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
The MicroPython project
=======================
-
+
This is the MicroPython project, which aims to put an implementation
@@ -41,7 +41,7 @@ Additional components:
The subdirectories above may include READMEs with additional info.
"make" is used to build the components, or "gmake" on BSD-based systems.
-You will also need bash and Python (at least 2.7 or 3.3).
+You will also need bash and Python 3.
The ESP32 version
-----------------
@@ -51,15 +51,16 @@ the Espressif website:
- for 64-bit Linux::
- https://dl.espressif.com/dl/xtensa-esp32-elf-linux64-1.22.0-80-g6c4433a-5.2.0.tar.gz
+ https://dl.espressif.com/dl/xtensa-esp32-elf-gcc8_4_0-esp-2020r3-linux-amd64.tar.gz
- for 32-bit Linux::
- https://dl.espressif.com/dl/xtensa-esp32-elf-linux32-1.22.0-80-g6c4433a-5.2.0.tar.gz
+ https://dl.espressif.com/dl/xtensa-esp32-elf-gcc8_4_0-esp-2020r3-linux-i686.tar.gz
- for Mac OS:
- https://dl.espressif.com/dl/xtensa-esp32-elf-osx-1.22.0-80-g6c4433a-5.2.0.tar.gz
+ https://dl.espressif.com/dl/xtensa-esp32-elf-gcc8_4_0-esp-2020r3-macos.tar.gz
+
To use it, you will need to update your ``PATH`` environment variable in ``~/.bash_profile`` file. To make ``xtensa-esp32-elf`` available for all terminal sessions, add the following line to your ``~/.bash_profile`` file::
@@ -74,7 +75,7 @@ Then when you need the toolchain you can type ``get_esp32`` on the command line
You also need the ESP IDF along side this repository in order to build the ESP32 port.
To get it:
- $ git clone --recursive -b idf_v3.3.1 https://github.com/pycom/pycom-esp-idf.git
+ $ git clone --recursive -b idf_v4.1 https://github.com/pycom/pycom-esp-idf.git
After cloning, if you did not specify the --recursive option, make sure to checkout all the submodules:
@@ -128,8 +129,7 @@ By default, both bootloader and application are built. To build them separately:
$ cd esp32
$ make clean
- $ make TARGET=boot
- $ make TARGET=app
+ $ make release
$ make flash
You can change the board type by using the BOARD variable:
@@ -141,7 +141,7 @@ You can change the board type by using the BOARD variable:
We currently support the following BOARD types:
- WIPY LOPY SIPY GPY FIPY LOPY4
+ WIPY LOPY GPY FIPY LOPY4
For OEM modules, please use the following BOARD type:
@@ -155,7 +155,7 @@ G01: GPY
To specify a serial port other than /dev/ttyUSB0, use ESPPORT variable:
$ # On MacOS
- $ make ESPPORT=/dev/tty.usbserial-DQ008HQY flash
+ $ make ESPPORT=/dev/tty.usbmodemPy8eaa911 flash
$ # On Windows
$ make ESPPORT=COM3 flash
$ # On linux
@@ -179,7 +179,7 @@ To create a release package that can be flashed with the Pycom firmware tool:
To create a release package for all currently supported Pycom boards:
$ cd esp32
- $ for BOARD in WIPY LOPY SIPY GPY FIPY LOPY4; do make BOARD=$BOARD clean && make BOARD=$BOARD release; done
+ $ for BOARD in WIPY LOPY GPY FIPY LOPY4; do make BOARD=$BOARD clean && make BOARD=$BOARD release; done
To specify a directory other than the default build/ directory:
@@ -190,7 +190,7 @@ To specify a directory other than the default build/ directory:
To create a release package for all currently supported Pycom boards in a directory other than the default build/ directory:
$ cd esp32
- $ for BOARD in WIPY LOPY SIPY GPY FIPY LOPY4; do make BOARD=$BOARD clean && make BOARD=$BOARD RELEASE_DIR=~/pycom-packages release; done
+ $ for BOARD in WIPY LOPY GPY FIPY LOPY4; do make BOARD=$BOARD clean && make BOARD=$BOARD RELEASE_DIR=~/pycom-packages release; done
To inclue a step for copying IDF libs from IDF_PATH specify the following variable in the make command
@@ -206,81 +206,4 @@ To Disable RGB Led control use the following make variable
## Steps for using Secure Boot and Flash Encryption
-### Summary
-
-1. Obtain keys (for Secure Boot and Flash Encryption)
-2. Flash keys and parameters in efuses
-3. Compile bootloader and application with `make SECURE=on`
-4. Flash: bootloader-digest at address 0x0 and encrypted; all the others (partitions and application) encrypted, too.
-
-### Prerequisites
-
- $ export IDF_PATH=
- $ cd esp32
-
-Hold valid keys for Flash Encryption and Secure Boot; they can be generated randomly with the following commands:
-
- python $IDF_PATH/components/esptool_py/esptool/espsecure.py generate_flash_encryption_key flash_encryption_key.bin
- python $IDF_PATH/components/esptool_py/esptool/espsecure.py generate_signing_key secure_boot_signing_key.pem
-
-The Secure Boot key `secure_boot_signing_key.pem` has to be transformed into `secure-bootloader-key.bin`, to be burnt into efuses. This can be done in 2 ways:
-
- python $IDF_PATH/components/esptool_py/esptool/espefuse.py extract_public_key --keyfile secure_boot_signing_key.pem signature_verification_key.bin
-
- # or, as an artifact of the make build process, on the same directory level as Makefile
- make BOARD=GPY SECURE=on TARGET=boot
-
-Flash keys (`flash_encryption_key.bin` and `secure-bootloader-key.bin`) into the efuses (write and read protected):
-
-**_Note: Irreversible operations_**
-
- # Burning Encryption Key
- python $IDF_PATH/components/esptool_py/esptool/espefuse.py --port /dev/ttyUSB0 burn_key flash_encryption flash_encryption_key.bin
- # Burning Secure Boot Key
- python $IDF_PATH/components/esptool_py/esptool/espefuse.py --port /dev/ttyUSB0 burn_key secure_boot secure-bootloader-key.bin
- # Enabling Flash Encryption mechanism
- python $IDF_PATH/components/esptool_py/esptool/espefuse.py --port /dev/ttyUSB0 burn_efuse FLASH_CRYPT_CNT
- # Configuring Flash Encryption to use all address bits togheter with Encryption key (max value 0x0F)
- python $IDF_PATH/components/esptool_py/esptool/espefuse.py --port /dev/ttyUSB0 burn_efuse FLASH_CRYPT_CONFIG 0x0F
- # Enabling Secure Boot mechanism
- python $IDF_PATH/components/esptool_py/esptool/espefuse.py --port /dev/ttyUSB0 burn_efuse ABS_DONE_0
-
-**_If the keys are not written in efuse, before flashing the bootloader, then random keys will be generated by the ESP32, they can never be read nor re-written, so bootloader can never be updated. Even more, the application can be re-flashed (by USB) just 3 more times._**
-
-### Makefile options:
-
- make BOARD=GPY SECURE=on SECURE_KEY=secure_boot_signing_key.pem ENCRYPT_KEY=flash_encryption_key.bin
-
-- `SECURE=on` is the main flag; it's not optional
-- if `SECURE=on` by default:
- - encryption is enabled
- - secure_boot_signing_key.pem is the secure boot key, located relatively to Makefile
- - flash_encryption_key.bin is the flash encryption key, located relatively to Makefile
-
-For flashing the bootloader digest and the encrypted versions of all binaries:
-
- make BOARD=GPY SECURE=on flash
-
-### Flashing
-
-For flashing the bootloader-reflash-digest.bin has to be written at address 0x0, instead of the bootloader.bin (at address 0x1000).
-
-Build is done using `SECURE=on` option; additionally, all the binaries are pre-encrypted.
-
- make BOARD=GPY clean
- make BOARD=GPY SECURE=on
- make BOARD=GPY SECURE=on flash
-
-Manual flash command:
-
- python $IDF_PATH/components/esptool_py/esptool/esptool.py --chip esp32 --port /dev/ttyUSB0 --baud 921600 --before no_reset --after no_reset write_flash -z --flash_mode dio --flash_freq 80m --flash_size detect 0x0 build/GPY/release/bootloader/bootloader-reflash-digest.bin_enc 0x8000 build/GPY/release/lib/partitions.bin_enc 0x10000 build/GPY/release/gpy.bin_enc_0x10000
-
-### OTA update
-
-The OTA should be done using the pre-encrypted application image.
-
-Because the encryption is done based on the physical flash address, there are 2 application binaries generated:
-- gpy.bin_enc_0x10000 which has to be written at default factory address: 0x10000
-- gpy.bin_enc_0x1A0000 which has to be written at the ota_0 partition address (0x1A0000)
-
-*__Hint:__ on micropython interface, the method `pycom.ota_slot()` responds with the address of the next OTA partition available (either 0x10000 or 0x1A0000).*
+For Secure Boot and Flash Encryption please check: https://docs.pycom.io/advance/encryption/
diff --git a/drivers/bus/qspi.h b/drivers/bus/qspi.h
index 31c9d14fca..c82796fac5 100644
--- a/drivers/bus/qspi.h
+++ b/drivers/bus/qspi.h
@@ -28,6 +28,8 @@
#include "py/mphal.h"
+#define MP_SPI_ADDR_IS_32B(addr) (addr & 0xff000000)
+
enum {
MP_QSPI_IOCTL_INIT,
MP_QSPI_IOCTL_DEINIT,
@@ -54,4 +56,19 @@ typedef struct _mp_soft_qspi_obj_t {
extern const mp_qspi_proto_t mp_soft_qspi_proto;
+static inline uint8_t mp_spi_set_addr_buff(uint8_t *buf, uint32_t addr) {
+ if (MP_SPI_ADDR_IS_32B(addr)) {
+ buf[0] = addr >> 24;
+ buf[1] = addr >> 16;
+ buf[2] = addr >> 8;
+ buf[3] = addr;
+ return 4;
+ } else {
+ buf[0] = addr >> 16;
+ buf[1] = addr >> 8;
+ buf[2] = addr;
+ return 3;
+ }
+}
+
#endif // MICROPY_INCLUDED_DRIVERS_BUS_QSPI_H
diff --git a/drivers/bus/softqspi.c b/drivers/bus/softqspi.c
index 10c5992466..71ab559768 100644
--- a/drivers/bus/softqspi.c
+++ b/drivers/bus/softqspi.c
@@ -168,9 +168,10 @@ STATIC void mp_soft_qspi_write_cmd_data(void *self_in, uint8_t cmd, size_t len,
STATIC void mp_soft_qspi_write_cmd_addr_data(void *self_in, uint8_t cmd, uint32_t addr, size_t len, const uint8_t *src) {
mp_soft_qspi_obj_t *self = (mp_soft_qspi_obj_t*)self_in;
- uint8_t cmd_buf[4] = {cmd, addr >> 16, addr >> 8, addr};
+ uint8_t cmd_buf[5] = {cmd};
+ uint8_t addr_len = mp_spi_set_addr_buff(&cmd_buf[1], addr);
CS_LOW(self);
- mp_soft_qspi_transfer(self, 4, cmd_buf, NULL);
+ mp_soft_qspi_transfer(self, addr_len + 1, cmd_buf, NULL);
mp_soft_qspi_transfer(self, len, src, NULL);
CS_HIGH(self);
}
@@ -186,10 +187,11 @@ STATIC uint32_t mp_soft_qspi_read_cmd(void *self_in, uint8_t cmd, size_t len) {
STATIC void mp_soft_qspi_read_cmd_qaddr_qdata(void *self_in, uint8_t cmd, uint32_t addr, size_t len, uint8_t *dest) {
mp_soft_qspi_obj_t *self = (mp_soft_qspi_obj_t*)self_in;
- uint8_t cmd_buf[7] = {cmd, addr >> 16, addr >> 8, addr};
+ uint8_t cmd_buf[7] = {cmd};
+ uint8_t addr_len = mp_spi_set_addr_buff(&cmd_buf[1], addr);
CS_LOW(self);
mp_soft_qspi_transfer(self, 1, cmd_buf, NULL);
- mp_soft_qspi_qwrite(self, 6, &cmd_buf[1]); // 3 addr bytes, 1 extra byte (0), 2 dummy bytes (4 dummy cycles)
+ mp_soft_qspi_qwrite(self, addr_len + 3, &cmd_buf[1]); // 3/4 addr bytes, 1 extra byte (0), 2 dummy bytes (4 dummy cycles)
mp_soft_qspi_qread(self, len, dest);
CS_HIGH(self);
}
diff --git a/drivers/cc3000/inc/cc3000_common.h b/drivers/cc3000/inc/cc3000_common.h
index aa16242310..d0c4b1d4b9 100644
--- a/drivers/cc3000/inc/cc3000_common.h
+++ b/drivers/cc3000/inc/cc3000_common.h
@@ -165,7 +165,7 @@ extern int CC3000_EXPORT(errno);
//*****************************************************************************
// Compound Types
//*****************************************************************************
-typedef INT32 time_t;
+typedef INT32 cc3000_time_t;
typedef UINT32 clock_t;
typedef INT32 suseconds_t;
@@ -173,7 +173,7 @@ typedef struct cc3000_timeval cc3000_timeval;
struct cc3000_timeval
{
- time_t tv_sec; /* seconds */
+ cc3000_time_t tv_sec; /* seconds */
suseconds_t tv_usec; /* microseconds */
};
diff --git a/drivers/cyw43/README.md b/drivers/cyw43/README.md
new file mode 100644
index 0000000000..5af6f65580
--- /dev/null
+++ b/drivers/cyw43/README.md
@@ -0,0 +1,17 @@
+CYW43xx WiFi SoC driver
+=======================
+
+This is a driver for the CYW43xx WiFi SoC.
+
+There are four layers to the driver:
+
+1. SDIO bus interface, provided by the host device/system.
+
+2. Low-level CYW43xx interface, managing the bus, control messages, Ethernet
+ frames and asynchronous events. Includes download of SoC firmware. The
+ header file `cyw43_ll.h` defines the interface to this layer.
+
+3. Mid-level CYW43xx control, to control and set WiFi parameters and manage
+ events. See `cyw43_ctrl.c`.
+
+4. TCP/IP bindings to lwIP. See `cyw43_lwip.c`.
diff --git a/drivers/cyw43/cyw43.h b/drivers/cyw43/cyw43.h
new file mode 100644
index 0000000000..d7f08cb5df
--- /dev/null
+++ b/drivers/cyw43/cyw43.h
@@ -0,0 +1,135 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018-2019 Damien P. George
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#ifndef MICROPY_INCLUDED_STM32_CYW43_H
+#define MICROPY_INCLUDED_STM32_CYW43_H
+
+#include "lwip/netif.h"
+#include "lwip/dhcp.h"
+#include "lib/netutils/dhcpserver.h"
+#include "drivers/cyw43/cyw43_ll.h"
+
+// For trace_flags
+#define CYW43_TRACE_ASYNC_EV (0x0001)
+#define CYW43_TRACE_ETH_TX (0x0002)
+#define CYW43_TRACE_ETH_RX (0x0004)
+#define CYW43_TRACE_ETH_FULL (0x0008)
+#define CYW43_TRACE_MAC (0x0010)
+
+// Return value of cyw43_wifi_link_status
+#define CYW43_LINK_DOWN (0)
+#define CYW43_LINK_JOIN (1)
+#define CYW43_LINK_NOIP (2)
+#define CYW43_LINK_UP (3)
+#define CYW43_LINK_FAIL (-1)
+#define CYW43_LINK_NONET (-2)
+#define CYW43_LINK_BADAUTH (-3)
+
+typedef struct _cyw43_t {
+ cyw43_ll_t cyw43_ll;
+
+ uint8_t itf_state;
+ uint32_t trace_flags;
+
+ // State for async events
+ volatile uint32_t wifi_scan_state;
+ uint32_t wifi_join_state;
+ void *wifi_scan_env;
+ int (*wifi_scan_cb)(void*, const cyw43_ev_scan_result_t*);
+
+ // Pending things to do
+ bool pend_disassoc;
+ bool pend_rejoin;
+ bool pend_rejoin_wpa;
+
+ // AP settings
+ uint8_t ap_channel;
+ uint8_t ap_auth;
+ uint8_t ap_ssid_len;
+ uint8_t ap_key_len;
+ uint8_t ap_ssid[32];
+ uint8_t ap_key[64];
+
+ // lwIP data
+ struct netif netif[2];
+ struct dhcp dhcp_client;
+ dhcp_server_t dhcp_server;
+} cyw43_t;
+
+extern cyw43_t cyw43_state;
+extern void (*cyw43_poll)(void);
+extern uint32_t cyw43_sleep;
+
+void cyw43_init(cyw43_t *self);
+void cyw43_deinit(cyw43_t *self);
+
+int cyw43_ioctl(cyw43_t *self, uint32_t cmd, size_t len, uint8_t *buf, uint32_t iface);
+int cyw43_send_ethernet(cyw43_t *self, int itf, size_t len, const void *buf, bool is_pbuf);
+
+int cyw43_wifi_pm(cyw43_t *self, uint32_t pm);
+int cyw43_wifi_link_status(cyw43_t *self, int itf);
+void cyw43_wifi_set_up(cyw43_t *self, int itf, bool up);
+int cyw43_wifi_get_mac(cyw43_t *self, int itf, uint8_t mac[6]);
+int cyw43_wifi_scan(cyw43_t *self, cyw43_wifi_scan_options_t *opts, void *env, int (*result_cb)(void*, const cyw43_ev_scan_result_t*));
+
+static inline bool cyw43_wifi_scan_active(cyw43_t *self) {
+ return self->wifi_scan_state == 1;
+}
+
+int cyw43_wifi_join(cyw43_t *self, size_t ssid_len, const uint8_t *ssid, size_t key_len, const uint8_t *key, uint32_t auth_type, const uint8_t *bssid, uint32_t channel);
+int cyw43_wifi_leave(cyw43_t *self, int itf);
+
+static inline void cyw43_wifi_ap_get_ssid(cyw43_t *self, size_t *len, const uint8_t **buf) {
+ *len = self->ap_ssid_len;
+ *buf = self->ap_ssid;
+}
+
+static inline void cyw43_wifi_ap_set_channel(cyw43_t *self, uint32_t channel) {
+ self->ap_channel = channel;
+}
+
+static inline void cyw43_wifi_ap_set_ssid(cyw43_t *self, size_t len, const uint8_t *buf) {
+ self->ap_ssid_len = MIN(len, sizeof(self->ap_ssid));
+ memcpy(self->ap_ssid, buf, self->ap_ssid_len);
+}
+
+static inline void cyw43_wifi_ap_set_password(cyw43_t *self, size_t len, const uint8_t *buf) {
+ self->ap_key_len = MIN(len, sizeof(self->ap_key));
+ memcpy(self->ap_key, buf, self->ap_key_len);
+}
+
+static inline void cyw43_wifi_ap_set_auth(cyw43_t *self, uint32_t auth) {
+ self->ap_auth = auth;
+}
+
+void cyw43_wifi_ap_get_stas(cyw43_t *self, int *num_stas, uint8_t *macs);
+
+void cyw43_tcpip_init(cyw43_t *self, int itf);
+void cyw43_tcpip_deinit(cyw43_t *self, int itf);
+void cyw43_tcpip_set_link_up(cyw43_t *self, int itf);
+void cyw43_tcpip_set_link_down(cyw43_t *self, int itf);
+int cyw43_tcpip_link_status(cyw43_t *self, int itf);
+
+#endif // MICROPY_INCLUDED_STM32_CYW43_H
diff --git a/drivers/cyw43/cyw43_ctrl.c b/drivers/cyw43/cyw43_ctrl.c
new file mode 100644
index 0000000000..cc1fbecde8
--- /dev/null
+++ b/drivers/cyw43/cyw43_ctrl.c
@@ -0,0 +1,591 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018-2019 Damien P. George
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include
+#include
+
+#include "py/mphal.h"
+#include "drivers/cyw43/cyw43.h"
+#include "pendsv.h"
+#include "sdio.h"
+
+#define CYW_ENTER MICROPY_PY_LWIP_ENTER
+#define CYW_EXIT MICROPY_PY_LWIP_EXIT
+
+#ifdef pyb_pin_WL_HOST_WAKE
+#define USE_SDIOIT (0)
+#else
+#define USE_SDIOIT (1)
+#endif
+
+#define CYW43_SLEEP_MAX (50)
+
+#define WIFI_JOIN_STATE_ACTIVE (0x0001)
+#define WIFI_JOIN_STATE_FAIL (0x0002)
+#define WIFI_JOIN_STATE_NONET (0x0003)
+#define WIFI_JOIN_STATE_BADAUTH (0x0004)
+#define WIFI_JOIN_STATE_AUTH (0x0200)
+#define WIFI_JOIN_STATE_LINK (0x0400)
+#define WIFI_JOIN_STATE_KEYED (0x0800)
+#define WIFI_JOIN_STATE_ALL (0x0e01)
+
+cyw43_t cyw43_state;
+void (*cyw43_poll)(void);
+uint32_t cyw43_sleep;
+
+STATIC void cyw43_poll_func(void);
+STATIC void cyw43_wifi_ap_init(cyw43_t *self);
+STATIC void cyw43_wifi_ap_set_up(cyw43_t *self, bool up);
+
+static inline uint32_t cyw43_get_be16(const uint8_t *buf) {
+ return buf[0] << 8 | buf[1];
+}
+
+static inline uint32_t cyw43_get_be32(const uint8_t *buf) {
+ return buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3];
+}
+
+static inline void cyw43_delay_ms(uint32_t ms) {
+ mp_hal_delay_ms(ms);
+}
+
+/*******************************************************************************/
+// Initialisation and polling
+
+void cyw43_init(cyw43_t *self) {
+ #ifdef pyb_pin_WL_HOST_WAKE
+ mp_hal_pin_config(pyb_pin_WL_HOST_WAKE, MP_HAL_PIN_MODE_INPUT, MP_HAL_PIN_PULL_NONE, 0);
+ #endif
+ mp_hal_pin_config(pyb_pin_WL_REG_ON, MP_HAL_PIN_MODE_OUTPUT, MP_HAL_PIN_PULL_NONE, 0);
+ mp_hal_pin_low(pyb_pin_WL_REG_ON);
+ #ifdef pyb_pin_WL_RFSW_VDD
+ mp_hal_pin_config(pyb_pin_WL_RFSW_VDD, MP_HAL_PIN_MODE_OUTPUT, MP_HAL_PIN_PULL_NONE, 0); // RF-switch power
+ mp_hal_pin_low(pyb_pin_WL_RFSW_VDD);
+ #endif
+
+ cyw43_ll_init(&self->cyw43_ll, self);
+
+ self->itf_state = 0;
+ self->wifi_scan_state = 0;
+ self->wifi_join_state = 0;
+ self->pend_disassoc = false;
+ self->pend_rejoin= false;
+ self->pend_rejoin_wpa = false;
+ self->ap_channel = 3;
+ self->ap_ssid_len = 0;
+ self->ap_key_len = 0;
+
+ cyw43_poll = NULL;
+}
+
+void cyw43_deinit(cyw43_t *self) {
+ CYW_ENTER
+
+ cyw43_ll_bus_sleep(&self->cyw43_ll, true);
+ cyw43_delay_ms(2);
+ cyw43_tcpip_deinit(self, 0);
+ cyw43_tcpip_deinit(self, 1);
+
+ self->itf_state = 0;
+
+ // Disable async polling
+ SDMMC1->MASK &= ~SDMMC_MASK_SDIOITIE;
+ cyw43_poll = NULL;
+
+ #ifdef pyb_pin_WL_RFSW_VDD
+ // Turn the RF-switch off
+ mp_hal_pin_low(pyb_pin_WL_RFSW_VDD);
+ #endif
+
+ // Power down the WL chip and the SDIO bus
+ mp_hal_pin_low(pyb_pin_WL_REG_ON);
+ sdio_deinit();
+
+ CYW_EXIT
+}
+
+STATIC int cyw43_ensure_up(cyw43_t *self) {
+ if (cyw43_poll != NULL) {
+ cyw43_ll_bus_sleep(&self->cyw43_ll, false);
+ return 0;
+ }
+
+ CYW_ENTER
+
+ // Disable the netif if it was previously up
+ cyw43_tcpip_deinit(self, CYW43_ITF_STA);
+ cyw43_tcpip_deinit(self, CYW43_ITF_AP);
+ self->itf_state = 0;
+
+ // Reset and power up the WL chip
+ mp_hal_pin_low(pyb_pin_WL_REG_ON);
+ cyw43_delay_ms(20);
+ mp_hal_pin_high(pyb_pin_WL_REG_ON);
+ cyw43_delay_ms(50);
+
+ // Initialise SDIO bus
+ // IRQ priority only needs to be higher than CYW_ENTER/EXIT protection (PENDSV)
+ sdio_init(NVIC_EncodePriority(NVIC_PRIORITYGROUP_4, 14, 0));
+
+ // Initialise the low-level driver
+ uint8_t mac[6];
+ mp_hal_get_mac(MP_HAL_MAC_WLAN0, mac);
+ int ret = cyw43_ll_bus_init(&self->cyw43_ll, mac);
+
+ if (ret != 0) {
+ CYW_EXIT
+ return ret;
+ }
+
+ // Enable async events from low-level driver
+ cyw43_sleep = CYW43_SLEEP_MAX;
+ cyw43_poll = cyw43_poll_func;
+ #if USE_SDIOIT
+ SDMMC1->MASK |= SDMMC_MASK_SDIOITIE;
+ #else
+ extern void extint_set(const pin_obj_t *pin, uint32_t mode);
+ extint_set(pyb_pin_WL_HOST_WAKE, GPIO_MODE_IT_FALLING);
+ #endif
+
+ CYW_EXIT
+
+ return ret;
+}
+
+// This function must always be executed at the level where CYW_ENTER is effectively active
+STATIC void cyw43_poll_func(void) {
+ if (cyw43_poll == NULL) {
+ // Poll scheduled during deinit, just ignore it
+ return;
+ }
+
+ cyw43_t *self = &cyw43_state;
+ cyw43_ll_process_packets(&self->cyw43_ll);
+
+ if (self->pend_disassoc) {
+ self->pend_disassoc = false;
+ cyw43_ll_ioctl(&self->cyw43_ll, CYW43_IOCTL_SET_DISASSOC, 0, NULL, CYW43_ITF_STA);
+ }
+
+ if (self->pend_rejoin_wpa) {
+ self->pend_rejoin_wpa = false;
+ cyw43_ll_wifi_set_wpa_auth(&self->cyw43_ll);
+ }
+
+ if (self->pend_rejoin) {
+ self->pend_rejoin = false;
+ cyw43_ll_wifi_rejoin(&self->cyw43_ll);
+ self->wifi_join_state = WIFI_JOIN_STATE_ACTIVE;
+ }
+
+ if (cyw43_sleep == 0) {
+ cyw43_ll_bus_sleep(&self->cyw43_ll, true);
+ #if !USE_SDIOIT
+ sdio_deinit(); // save power while WLAN bus sleeps
+ #endif
+ }
+
+ #if USE_SDIOIT
+ SDMMC1->MASK |= SDMMC_MASK_SDIOITIE;
+ #endif
+}
+
+/*******************************************************************************/
+// Callback interface to low-level driver
+
+int cyw43_cb_read_host_interrupt_pin(void *cb_data) {
+ #ifdef pyb_pin_WL_HOST_WAKE
+ return mp_hal_pin_read(pyb_pin_WL_HOST_WAKE);
+ #else
+ return mp_hal_pin_read(pyb_pin_WL_SDIO_1);
+ #endif
+}
+
+void cyw43_cb_ensure_awake(void *cb_data) {
+ cyw43_sleep = CYW43_SLEEP_MAX;
+ #if !USE_SDIOIT
+ if (__HAL_RCC_SDMMC1_IS_CLK_DISABLED()) {
+ __HAL_RCC_SDMMC1_CLK_ENABLE(); // enable SDIO peripheral
+ sdio_enable_high_speed_4bit();
+ }
+ #endif
+}
+
+STATIC const char *cyw43_async_event_name_table[89] = {
+ [0 ... 88] = NULL,
+ [CYW43_EV_SET_SSID] = "SET_SSID",
+ [CYW43_EV_JOIN] = "JOIN",
+ [CYW43_EV_AUTH] = "AUTH",
+ [CYW43_EV_DEAUTH_IND] = "DEAUTH_IND",
+ [CYW43_EV_ASSOC] = "ASSOC",
+ [CYW43_EV_DISASSOC] = "DISASSOC",
+ [CYW43_EV_DISASSOC_IND] = "DISASSOC_IND",
+ [CYW43_EV_LINK] = "LINK",
+ [CYW43_EV_PSK_SUP] = "PSK_SUP",
+ [CYW43_EV_ESCAN_RESULT] = "ESCAN_RESULT",
+ [CYW43_EV_CSA_COMPLETE_IND] = "CSA_COMPLETE_IND",
+ [CYW43_EV_ASSOC_REQ_IE] = "ASSOC_REQ_IE",
+ [CYW43_EV_ASSOC_RESP_IE] = "ASSOC_RESP_IE",
+};
+
+STATIC void cyw43_dump_async_event(const cyw43_async_event_t *ev) {
+ printf("[% 8d] ASYNC(%04x,",
+ (int)mp_hal_ticks_ms(),
+ (unsigned int)ev->flags
+ );
+ if (ev->event_type < MP_ARRAY_SIZE(cyw43_async_event_name_table)
+ && cyw43_async_event_name_table[ev->event_type] != NULL) {
+ printf("%s", cyw43_async_event_name_table[ev->event_type]);
+ } else {
+ printf("%u", (unsigned int)ev->event_type);
+ }
+ printf(",%u,%u,%u)\n",
+ (unsigned int)ev->status,
+ (unsigned int)ev->reason,
+ (unsigned int)ev->interface
+ );
+}
+
+void cyw43_cb_process_async_event(void *cb_data, const cyw43_async_event_t *ev) {
+ cyw43_t *self = cb_data;
+
+ if (self->trace_flags & CYW43_TRACE_ASYNC_EV) {
+ cyw43_dump_async_event(ev);
+ }
+
+ if (ev->event_type == CYW43_EV_ESCAN_RESULT && self->wifi_scan_state == 1) {
+ // Escan result event
+ if (ev->status == 8) {
+ // Partial result
+ int ret = self->wifi_scan_cb(self->wifi_scan_env, &ev->u.scan_result);
+ if (ret != 0) {
+ // TODO need to abort scan, or just ignore any more results
+ }
+ } else if (ev->status == 0) {
+ // Scan complete
+ self->wifi_scan_state = 2;
+ }
+
+ } else if (ev->event_type == CYW43_EV_DISASSOC) {
+ cyw43_tcpip_set_link_down(self, CYW43_ITF_STA);
+ self->wifi_join_state = 0x0000;
+
+ /*
+ } else if (ev->event_type == CYW43_EV_DISASSOC_IND) {
+ if (ev->interface == CYW43_ITF_AP) {
+ // Station disassociated with our AP, let DHCP server know so it can free the IP address
+ dhcp_server_disassoc(&self->dhcp_server, buf + 24);
+ }
+ */
+
+ // WiFi join events
+ } else if (ev->event_type == CYW43_EV_PRUNE) {
+ if (ev->status == 0 && ev->reason == 8) {
+ // RSN mismatch, retry join with WPA auth
+ self->pend_rejoin = true;
+ self->pend_rejoin_wpa = true;
+ pendsv_schedule_dispatch(PENDSV_DISPATCH_CYW43, cyw43_poll_func);
+ }
+ } else if (ev->event_type == CYW43_EV_SET_SSID) {
+ if (ev->status == 0) {
+ // Success setting SSID
+ } else if (ev->status == 3 && ev->reason == 0) {
+ self->wifi_join_state = WIFI_JOIN_STATE_NONET;
+ // No matching SSID found (could be out of range, or down)
+ } else {
+ // Other failure setting SSID
+ self->wifi_join_state = WIFI_JOIN_STATE_FAIL;
+ }
+ } else if (ev->event_type == CYW43_EV_AUTH) {
+ if (ev->status == 0) {
+ self->wifi_join_state |= WIFI_JOIN_STATE_AUTH;
+ } else if (ev->status == 6) {
+ // Unsolicited auth packet, ignore it
+ } else {
+ // Cannot authenticate
+ self->wifi_join_state = WIFI_JOIN_STATE_BADAUTH;
+ }
+ } else if (ev->event_type == CYW43_EV_DEAUTH_IND) {
+ if (ev->status == 0 && ev->reason == 2) {
+ // Deauth, probably because password was wrong; disassociate
+ self->pend_disassoc = true;
+ pendsv_schedule_dispatch(PENDSV_DISPATCH_CYW43, cyw43_poll_func);
+ }
+ } else if (ev->event_type == CYW43_EV_LINK) {
+ if (ev->status == 0) {
+ if (ev->flags & 1) {
+ // Link is up
+ if (ev->interface == CYW43_ITF_STA) {
+ self->wifi_join_state |= WIFI_JOIN_STATE_LINK;
+ } else {
+ cyw43_tcpip_set_link_up(self, ev->interface);
+ }
+ } else {
+ // Link is down
+ cyw43_tcpip_set_link_down(self, ev->interface);
+ }
+ }
+ } else if (ev->event_type == CYW43_EV_PSK_SUP) {
+ if (ev->status == 6) { // WLC_SUP_KEYED
+ self->wifi_join_state |= WIFI_JOIN_STATE_KEYED;
+ } else if ((ev->status == 4 || ev->status == 8 || ev->status == 11) && ev->reason == 15) {
+ // Timeout waiting for key exchange M1/M3/G1
+ // Probably at edge of the cell, retry
+ self->pend_rejoin = true;
+ pendsv_schedule_dispatch(PENDSV_DISPATCH_CYW43, cyw43_poll_func);
+ } else {
+ // PSK_SUP failure
+ self->wifi_join_state = WIFI_JOIN_STATE_BADAUTH;
+ }
+ }
+
+ if (self->wifi_join_state == WIFI_JOIN_STATE_ALL) {
+ // STA connected
+ self->wifi_join_state = WIFI_JOIN_STATE_ACTIVE;
+ cyw43_tcpip_set_link_up(self, CYW43_ITF_STA);
+ }
+}
+
+/*******************************************************************************/
+// Ioctl and Ethernet interface
+
+int cyw43_ioctl(cyw43_t *self, uint32_t cmd, size_t len, uint8_t *buf, uint32_t iface) {
+ int ret = cyw43_ensure_up(self);
+ if (ret) {
+ return ret;
+ }
+
+ CYW_ENTER
+ ret = cyw43_ll_ioctl(&self->cyw43_ll, cmd, len, buf, iface);
+ CYW_EXIT
+
+ return ret;
+}
+
+int cyw43_send_ethernet(cyw43_t *self, int itf, size_t len, const void *buf, bool is_pbuf) {
+ int ret = cyw43_ensure_up(self);
+ if (ret) {
+ return ret;
+ }
+
+ CYW_ENTER
+ ret = cyw43_ll_send_ethernet(&self->cyw43_ll, itf, len, buf, is_pbuf);
+ CYW_EXIT
+
+ return ret;
+}
+
+/*******************************************************************************/
+// WiFi control
+
+STATIC int cyw43_wifi_on(cyw43_t *self, uint32_t country) {
+ int ret = cyw43_ensure_up(self);
+ if (ret) {
+ return ret;
+ }
+
+ #ifdef pyb_pin_WL_RFSW_VDD
+ // Turn the RF-switch on
+ mp_hal_pin_high(pyb_pin_WL_RFSW_VDD);
+ #endif
+
+ CYW_ENTER
+ ret = cyw43_ll_wifi_on(&self->cyw43_ll, country);
+ CYW_EXIT
+
+ return ret;
+}
+
+int cyw43_wifi_pm(cyw43_t *self, uint32_t pm_in) {
+ int ret = cyw43_ensure_up(self);
+ if (ret) {
+ return ret;
+ }
+
+ // pm_in: 0x00adbrrm
+ uint32_t pm = pm_in & 0xf;
+ uint32_t pm_sleep_ret = (pm_in >> 4) & 0xff;
+ uint32_t li_bcn = (pm_in >> 12) & 0xf;
+ uint32_t li_dtim = (pm_in >> 16) & 0xf;
+ uint32_t li_assoc = (pm_in >> 20) & 0xf;
+
+ CYW_ENTER
+ ret = cyw43_ll_wifi_pm(&self->cyw43_ll, pm, pm_sleep_ret, li_bcn, li_dtim, li_assoc);
+ CYW_EXIT
+
+ return ret;
+}
+
+int cyw43_wifi_get_mac(cyw43_t *self, int itf, uint8_t mac[6]) {
+ mp_hal_get_mac(MP_HAL_MAC_WLAN0, &mac[0]);
+ return 0;
+}
+
+#define MAKE_COUNTRY(a, b, rev) ((a) | (b) << 8 | (rev) << 16)
+
+void cyw43_wifi_set_up(cyw43_t *self, int itf, bool up) {
+ if (up) {
+ if (self->itf_state == 0) {
+ uint32_t country;
+ extern char pyb_country_code[2];
+ if (pyb_country_code[0] == '\0' || pyb_country_code[1] == '\0') {
+ country = MAKE_COUNTRY('X', 'X', 17); // default to world-wide (passive ch 12-14)
+ } else {
+ country = MAKE_COUNTRY(pyb_country_code[0], pyb_country_code[1], 0);
+ }
+ if (cyw43_wifi_on(self, country) != 0) {
+ return;
+ }
+ cyw43_wifi_pm(self, 10 << 20 | 1 << 16 | 1 << 12 | 20 << 4 | 2);
+ }
+ if (itf == CYW43_ITF_AP) {
+ cyw43_wifi_ap_init(self);
+ cyw43_wifi_ap_set_up(self, true);
+ }
+ if ((self->itf_state & (1 << itf)) == 0) {
+ CYW_ENTER
+ cyw43_tcpip_deinit(self, itf);
+ cyw43_tcpip_init(self, itf);
+ self->itf_state |= 1 << itf;
+ CYW_EXIT
+ }
+ } else {
+ if (itf == CYW43_ITF_AP) {
+ cyw43_wifi_ap_set_up(self, false);
+ }
+ }
+}
+
+int cyw43_wifi_scan(cyw43_t *self, cyw43_wifi_scan_options_t *opts, void *env, int (*result_cb)(void*, const cyw43_ev_scan_result_t*)) {
+ if (self->itf_state == 0) {
+ return -1;
+ }
+
+ cyw43_ensure_up(self);
+
+ CYW_ENTER
+
+ // Set state and callback data
+ self->wifi_scan_state = 1;
+ self->wifi_scan_env = env;
+ self->wifi_scan_cb = result_cb;
+
+ // Start the scan
+ int ret = cyw43_ll_wifi_scan(&self->cyw43_ll, opts);
+
+ CYW_EXIT
+
+ return ret;
+}
+
+int cyw43_wifi_link_status(cyw43_t *self, int itf) {
+ if (itf == CYW43_ITF_STA) {
+ int s = self->wifi_join_state & 0xf;
+ if (s == WIFI_JOIN_STATE_ACTIVE) {
+ return CYW43_LINK_JOIN;
+ } else if (s == WIFI_JOIN_STATE_FAIL) {
+ return CYW43_LINK_FAIL;
+ } else if (s == WIFI_JOIN_STATE_NONET) {
+ return CYW43_LINK_NONET;
+ } else if (s == WIFI_JOIN_STATE_BADAUTH) {
+ return CYW43_LINK_BADAUTH;
+ } else {
+ return CYW43_LINK_DOWN;
+ }
+ } else {
+ return CYW43_LINK_DOWN;
+ }
+}
+
+/*******************************************************************************/
+// WiFi STA
+
+int cyw43_wifi_join(cyw43_t *self, size_t ssid_len, const uint8_t *ssid, size_t key_len, const uint8_t *key, uint32_t auth_type, const uint8_t *bssid, uint32_t channel) {
+ int ret = cyw43_ensure_up(self);
+ if (ret) {
+ return ret;
+ }
+
+ CYW_ENTER
+
+ ret = cyw43_ll_wifi_join(&self->cyw43_ll, ssid_len, ssid, key_len, key, auth_type, bssid, channel);
+
+ if (ret == 0) {
+ // Wait for responses: EV_AUTH, EV_LINK, EV_SET_SSID, EV_PSK_SUP
+ // Will get EV_DEAUTH_IND if password is invalid
+ self->wifi_join_state = WIFI_JOIN_STATE_ACTIVE;
+
+ if (auth_type == 0) {
+ // For open security we don't need EV_PSK_SUP, so set that flag indicator now
+ self->wifi_join_state |= WIFI_JOIN_STATE_KEYED;
+ }
+ }
+
+ CYW_EXIT
+
+ return ret;
+}
+
+int cyw43_wifi_leave(cyw43_t *self, int itf) {
+ // Disassociate with SSID
+ return cyw43_ioctl(self, CYW43_IOCTL_SET_DISASSOC, 0, NULL, itf);
+}
+
+/*******************************************************************************/
+// WiFi AP
+
+STATIC void cyw43_wifi_ap_init(cyw43_t *self) {
+ int ret = cyw43_ensure_up(self);
+ if (ret) {
+ return;
+ }
+
+ CYW_ENTER
+ cyw43_ll_wifi_ap_init(&self->cyw43_ll, self->ap_ssid_len, self->ap_ssid, self->ap_auth, self->ap_key_len, self->ap_key, self->ap_channel);
+ CYW_EXIT
+}
+
+STATIC void cyw43_wifi_ap_set_up(cyw43_t *self, bool up) {
+ int ret = cyw43_ensure_up(self);
+ if (ret) {
+ return;
+ }
+
+ CYW_ENTER
+ cyw43_ll_wifi_ap_set_up(&self->cyw43_ll, up);
+ CYW_EXIT
+}
+
+void cyw43_wifi_ap_get_stas(cyw43_t *self, int *num_stas, uint8_t *macs) {
+ int ret = cyw43_ensure_up(self);
+ if (ret) {
+ return;
+ }
+
+ CYW_ENTER
+ cyw43_ll_wifi_ap_get_stas(&self->cyw43_ll, num_stas, macs);
+ CYW_EXIT
+}
diff --git a/drivers/cyw43/cyw43_ll.h b/drivers/cyw43/cyw43_ll.h
new file mode 100644
index 0000000000..879367a2ed
--- /dev/null
+++ b/drivers/cyw43/cyw43_ll.h
@@ -0,0 +1,135 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018-2019 Damien P. George
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#ifndef MICROPY_INCLUDED_STM32_CYW43_LL_H
+#define MICROPY_INCLUDED_STM32_CYW43_LL_H
+
+// IOCTL commands
+#define CYW43_IOCTL_GET_SSID (0x32)
+#define CYW43_IOCTL_GET_CHANNEL (0x3a)
+#define CYW43_IOCTL_SET_DISASSOC (0x69)
+#define CYW43_IOCTL_GET_ANTDIV (0x7e)
+#define CYW43_IOCTL_SET_ANTDIV (0x81)
+#define CYW43_IOCTL_SET_MONITOR (0xd9)
+#define CYW43_IOCTL_GET_VAR (0x20c)
+#define CYW43_IOCTL_SET_VAR (0x20f)
+
+// Async events, event_type field
+#define CYW43_EV_SET_SSID (0)
+#define CYW43_EV_JOIN (1)
+#define CYW43_EV_AUTH (3)
+#define CYW43_EV_DEAUTH_IND (6)
+#define CYW43_EV_ASSOC (7)
+#define CYW43_EV_DISASSOC (11)
+#define CYW43_EV_DISASSOC_IND (12)
+#define CYW43_EV_LINK (16)
+#define CYW43_EV_PRUNE (23)
+#define CYW43_EV_PSK_SUP (46)
+#define CYW43_EV_ESCAN_RESULT (69)
+#define CYW43_EV_CSA_COMPLETE_IND (80)
+#define CYW43_EV_ASSOC_REQ_IE (87)
+#define CYW43_EV_ASSOC_RESP_IE (88)
+
+enum {
+ CYW43_ITF_STA,
+ CYW43_ITF_AP,
+};
+
+typedef struct _cyw43_ev_scan_result_t {
+ uint32_t _0[5];
+ uint8_t bssid[6];
+ uint16_t _1[2];
+ uint8_t ssid_len;
+ uint8_t ssid[32];
+ uint32_t _2[5];
+ uint16_t channel;
+ uint16_t _3;
+ uint8_t auth_mode;
+ int16_t rssi;
+} cyw43_ev_scan_result_t;
+
+typedef struct _cyw43_async_event_t {
+ uint16_t _0;
+ uint16_t flags;
+ uint32_t event_type;
+ uint32_t status;
+ uint32_t reason;
+ uint8_t _1[30];
+ uint8_t interface;
+ uint8_t _2;
+ union {
+ cyw43_ev_scan_result_t scan_result;
+ } u;
+} cyw43_async_event_t;
+
+typedef struct _cyw43_wifi_scan_options_t {
+ uint32_t version;
+ uint16_t action;
+ uint16_t _;
+ uint32_t ssid_len; // 0 to select all
+ uint8_t ssid[32];
+ uint8_t bssid[6];
+ int8_t bss_type; // fill with 0xff to select all
+ int8_t scan_type; // 0=active, 1=passive
+ int32_t nprobes;
+ int32_t active_time;
+ int32_t passive_time;
+ int32_t home_time;
+ int32_t channel_num;
+ uint16_t channel_list[1];
+} cyw43_wifi_scan_options_t;
+
+typedef struct _cyw43_ll_t {
+ uint32_t opaque[528];
+} cyw43_ll_t;
+
+void cyw43_ll_init(cyw43_ll_t *self, void *cb_data);
+void cyw43_ll_deinit(cyw43_ll_t *self);
+
+int cyw43_ll_bus_init(cyw43_ll_t *self, const uint8_t *mac);
+void cyw43_ll_bus_sleep(cyw43_ll_t *self, bool can_sleep);
+void cyw43_ll_process_packets(cyw43_ll_t *self);
+int cyw43_ll_ioctl(cyw43_ll_t *self, uint32_t cmd, size_t len, uint8_t *buf, uint32_t iface);
+int cyw43_ll_send_ethernet(cyw43_ll_t *self, int itf, size_t len, const void *buf, bool is_pbuf);
+
+int cyw43_ll_wifi_on(cyw43_ll_t *self, uint32_t country);
+int cyw43_ll_wifi_pm(cyw43_ll_t *self, uint32_t pm, uint32_t pm_sleep_ret, uint32_t li_bcn, uint32_t li_dtim, uint32_t li_assoc);
+int cyw43_ll_wifi_scan(cyw43_ll_t *self, cyw43_wifi_scan_options_t *opts);
+
+int cyw43_ll_wifi_join(cyw43_ll_t *self, size_t ssid_len, const uint8_t *ssid, size_t key_len, const uint8_t *key, uint32_t auth_type, const uint8_t *bssid, uint32_t channel);
+void cyw43_ll_wifi_set_wpa_auth(cyw43_ll_t *self);
+void cyw43_ll_wifi_rejoin(cyw43_ll_t *self);
+
+int cyw43_ll_wifi_ap_init(cyw43_ll_t *self, size_t ssid_len, const uint8_t *ssid, uint32_t auth, size_t key_len, const uint8_t *key, uint32_t channel);
+int cyw43_ll_wifi_ap_set_up(cyw43_ll_t *self, bool up);
+int cyw43_ll_wifi_ap_get_stas(cyw43_ll_t *self, int *num_stas, uint8_t *macs);
+
+// Callbacks to be provided by mid-level interface
+int cyw43_cb_read_host_interrupt_pin(void *cb_data);
+void cyw43_cb_ensure_awake(void *cb_data);
+void cyw43_cb_process_async_event(void *cb_data, const cyw43_async_event_t *ev);
+void cyw43_cb_process_ethernet(void *cb_data, int itf, size_t len, const uint8_t *buf);
+
+#endif // MICROPY_INCLUDED_STM32_CYW43_LL_H
diff --git a/drivers/cyw43/cyw43_lwip.c b/drivers/cyw43/cyw43_lwip.c
new file mode 100644
index 0000000000..f3ca59e3a4
--- /dev/null
+++ b/drivers/cyw43/cyw43_lwip.c
@@ -0,0 +1,198 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018-2019 Damien P. George
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include
+#include
+
+#include "py/mphal.h"
+#include "lib/netutils/netutils.h"
+#include "lwip/etharp.h"
+#include "lwip/dns.h"
+#include "lwip/apps/mdns.h"
+#include "drivers/cyw43/cyw43.h"
+
+STATIC void cyw43_ethernet_trace(cyw43_t *self, struct netif *netif, size_t len, const void *data, unsigned int flags) {
+ bool is_tx = flags & NETUTILS_TRACE_IS_TX;
+ if ((is_tx && (self->trace_flags & CYW43_TRACE_ETH_TX))
+ || (!is_tx && (self->trace_flags & CYW43_TRACE_ETH_RX))) {
+ const uint8_t *buf;
+ if (len == (size_t)-1) {
+ // data is a pbuf
+ const struct pbuf *pbuf = data;
+ buf = pbuf->payload;
+ len = pbuf->len; // restricted to print only the first chunk of the pbuf
+ } else {
+ // data is actual data buffer
+ buf = data;
+ }
+
+ if (self->trace_flags & CYW43_TRACE_MAC) {
+ printf("[% 8d] ETH%cX itf=%c%c len=%u", (int)mp_hal_ticks_ms(), is_tx ? 'T' : 'R', netif->name[0], netif->name[1], len);
+ printf(" MAC type=%d subtype=%d data=", buf[0] >> 2 & 3, buf[0] >> 4);
+ for (size_t i = 0; i < len; ++i) {
+ printf(" %02x", buf[i]);
+ }
+ printf("\n");
+ return;
+ }
+
+ if (self->trace_flags & CYW43_TRACE_ETH_FULL) {
+ flags |= NETUTILS_TRACE_PAYLOAD;
+ }
+ netutils_ethernet_trace(MP_PYTHON_PRINTER, len, buf, flags);
+ }
+}
+
+STATIC err_t cyw43_netif_output(struct netif *netif, struct pbuf *p) {
+ cyw43_t *self = netif->state;
+ if (self->trace_flags != 0) {
+ cyw43_ethernet_trace(self, netif, (size_t)-1, p, NETUTILS_TRACE_IS_TX | NETUTILS_TRACE_NEWLINE);
+ }
+ int itf = netif->name[1] - '0';
+ int ret = cyw43_send_ethernet(self, itf, p->tot_len, (void*)p, true);
+ if (ret) {
+ printf("[CYW43] send_ethernet failed: %d\n", ret);
+ return ERR_IF;
+ }
+ return ERR_OK;
+}
+
+STATIC err_t cyw43_netif_init(struct netif *netif) {
+ netif->linkoutput = cyw43_netif_output;
+ netif->output = etharp_output;
+ netif->mtu = 1500;
+ netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET | NETIF_FLAG_IGMP;
+ cyw43_wifi_get_mac(netif->state, netif->name[1] - '0', netif->hwaddr);
+ netif->hwaddr_len = sizeof(netif->hwaddr);
+ return ERR_OK;
+}
+
+void cyw43_tcpip_init(cyw43_t *self, int itf) {
+ ip_addr_t ipconfig[4];
+ #if LWIP_IPV6
+ #define IP(x) ((x).u_addr.ip4)
+ #else
+ #define IP(x) (x)
+ #endif
+ if (itf == 0) {
+ // need to zero out to get isconnected() working
+ IP4_ADDR(&IP(ipconfig[0]), 0, 0, 0, 0);
+ IP4_ADDR(&IP(ipconfig[2]), 192, 168, 0, 1);
+ } else {
+ IP4_ADDR(&IP(ipconfig[0]), 192, 168, 4, 1);
+ IP4_ADDR(&IP(ipconfig[2]), 192, 168, 4, 1);
+ }
+ IP4_ADDR(&IP(ipconfig[1]), 255, 255, 255, 0);
+ IP4_ADDR(&IP(ipconfig[3]), 8, 8, 8, 8);
+ #undef IP
+
+ struct netif *n = &self->netif[itf];
+ n->name[0] = 'w';
+ n->name[1] = '0' + itf;
+ #if LWIP_IPV6
+ netif_add(n, &ipconfig[0].u_addr.ip4, &ipconfig[1].u_addr.ip4, &ipconfig[2].u_addr.ip4, self, cyw43_netif_init, ethernet_input);
+ #else
+ netif_add(n, &ipconfig[0], &ipconfig[1], &ipconfig[2], self, cyw43_netif_init, netif_input);
+ #endif
+ netif_set_hostname(n, "PYBD");
+ netif_set_default(n);
+ netif_set_up(n);
+
+ if (itf == CYW43_ITF_STA) {
+ dns_setserver(0, &ipconfig[3]);
+ dhcp_set_struct(n, &self->dhcp_client);
+ dhcp_start(n);
+ } else {
+ dhcp_server_init(&self->dhcp_server, &ipconfig[0], &ipconfig[1]);
+ }
+
+ #if LWIP_MDNS_RESPONDER
+ // TODO better to call after IP address is set
+ char mdns_hostname[9];
+ memcpy(&mdns_hostname[0], "PYBD", 4);
+ mp_hal_get_mac_ascii(MP_HAL_MAC_WLAN0, 8, 4, &mdns_hostname[4]);
+ mdns_hostname[8] = '\0';
+ mdns_resp_add_netif(n, mdns_hostname, 60);
+ #endif
+}
+
+void cyw43_tcpip_deinit(cyw43_t *self, int itf) {
+ struct netif *n = &self->netif[itf];
+ if (itf == CYW43_ITF_STA) {
+ dhcp_stop(n);
+ } else {
+ dhcp_server_deinit(&self->dhcp_server);
+ }
+ #if LWIP_MDNS_RESPONDER
+ mdns_resp_remove_netif(n);
+ #endif
+ for (struct netif *netif = netif_list; netif != NULL; netif = netif->next) {
+ if (netif == n) {
+ netif_remove(netif);
+ netif->ip_addr.addr = 0;
+ netif->flags = 0;
+ }
+ }
+}
+
+void cyw43_cb_process_ethernet(void *cb_data, int itf, size_t len, const uint8_t *buf) {
+ cyw43_t *self = cb_data;
+ struct netif *netif = &self->netif[itf];
+ if (self->trace_flags) {
+ cyw43_ethernet_trace(self, netif, len, buf, NETUTILS_TRACE_NEWLINE);
+ }
+ if (netif->flags & NETIF_FLAG_LINK_UP) {
+ struct pbuf *p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
+ if (p != NULL) {
+ pbuf_take(p, buf, len);
+ if (netif->input(p, netif) != ERR_OK) {
+ pbuf_free(p);
+ }
+ }
+ }
+}
+
+void cyw43_tcpip_set_link_up(cyw43_t *self, int itf) {
+ netif_set_link_up(&self->netif[itf]);
+}
+
+void cyw43_tcpip_set_link_down(cyw43_t *self, int itf) {
+ netif_set_link_down(&self->netif[itf]);
+}
+
+int cyw43_tcpip_link_status(cyw43_t *self, int itf) {
+ struct netif *netif = &self->netif[itf];
+ if ((netif->flags & (NETIF_FLAG_UP | NETIF_FLAG_LINK_UP))
+ == (NETIF_FLAG_UP | NETIF_FLAG_LINK_UP)) {
+ if (netif->ip_addr.addr != 0) {
+ return CYW43_LINK_UP;
+ } else {
+ return CYW43_LINK_NOIP;
+ }
+ } else {
+ return cyw43_wifi_link_status(self, itf);
+ }
+}
diff --git a/drivers/cyw43/cywbt.c b/drivers/cyw43/cywbt.c
new file mode 100644
index 0000000000..79318f4483
--- /dev/null
+++ b/drivers/cyw43/cywbt.c
@@ -0,0 +1,275 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019-2020 Damien P. George
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include
+#include
+
+#include "py/runtime.h"
+#include "py/mphal.h"
+#include "pin_static_af.h"
+#include "uart.h"
+#include "extmod/modbluetooth_hci.h"
+
+#if MICROPY_PY_NETWORK_CYW43
+
+extern const char fw_4343WA1_7_45_98_50_start;
+#define CYWBT_FW_ADDR (&fw_4343WA1_7_45_98_50_start + 749 * 512 + 29 * 256)
+
+/******************************************************************************/
+// CYW BT HCI low-level driver
+
+STATIC void cywbt_wait_cts_low(void) {
+ mp_hal_pin_config(pyb_pin_BT_CTS, MP_HAL_PIN_MODE_INPUT, MP_HAL_PIN_PULL_UP, 0);
+ for (int i = 0; i < 200; ++i) {
+ if (mp_hal_pin_read(pyb_pin_BT_CTS) == 0) {
+ break;
+ }
+ mp_hal_delay_ms(1);
+ }
+ mp_hal_pin_config_alt_static(pyb_pin_BT_CTS, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_UP, STATIC_AF_USART6_CTS);
+}
+
+STATIC int cywbt_hci_cmd_raw(size_t len, uint8_t *buf) {
+ uart_tx_strn(&mp_bluetooth_hci_uart_obj, (void*)buf, len);
+ for (int i = 0; i < 6; ++i) {
+ while (!uart_rx_any(&mp_bluetooth_hci_uart_obj)) {
+ MICROPY_EVENT_POLL_HOOK
+ }
+ buf[i] = uart_rx_char(&mp_bluetooth_hci_uart_obj);
+ }
+
+ // expect a comand complete event (event 0x0e)
+ if (buf[0] != 0x04 || buf[1] != 0x0e) {
+ printf("unknown response: %02x %02x %02x %02x\n", buf[0], buf[1], buf[2], buf[3]);
+ return -1;
+ }
+
+ /*
+ if buf[3:6] != cmd[:3]:
+ print('response doesn\'t match cmd:', cmd, ev)
+ return b''
+ */
+
+ int sz = buf[2] - 3;
+ for (int i = 0; i < sz; ++i) {
+ while (!uart_rx_any(&mp_bluetooth_hci_uart_obj)) {
+ MICROPY_EVENT_POLL_HOOK
+ }
+ buf[i] = uart_rx_char(&mp_bluetooth_hci_uart_obj);
+ }
+
+ return 0;
+}
+
+STATIC int cywbt_hci_cmd(int ogf, int ocf, size_t param_len, const uint8_t *param_buf) {
+ uint8_t *buf = mp_bluetooth_hci_cmd_buf;
+ buf[0] = 0x01;
+ buf[1] = ocf;
+ buf[2] = ogf << 2 | ocf >> 8;
+ buf[3] = param_len;
+ if (param_len) {
+ memcpy(buf + 4, param_buf, param_len);
+ }
+ return cywbt_hci_cmd_raw(4 + param_len, buf);
+}
+
+STATIC void put_le16(uint8_t *buf, uint16_t val) {
+ buf[0] = val;
+ buf[1] = val >> 8;
+}
+
+STATIC void put_le32(uint8_t *buf, uint32_t val) {
+ buf[0] = val;
+ buf[1] = val >> 8;
+ buf[2] = val >> 16;
+ buf[3] = val >> 24;
+}
+
+STATIC int cywbt_set_baudrate(uint32_t baudrate) {
+ uint8_t buf[6];
+ put_le16(buf, 0);
+ put_le32(buf + 2, baudrate);
+ return cywbt_hci_cmd(0x3f, 0x18, 6, buf);
+}
+
+// download firmware
+STATIC int cywbt_download_firmware(const uint8_t *firmware) {
+ cywbt_hci_cmd(0x3f, 0x2e, 0, NULL);
+
+ bool last_packet = false;
+ while (!last_packet) {
+ uint8_t *buf = mp_bluetooth_hci_cmd_buf;
+ memcpy(buf + 1, firmware, 3);
+ firmware += 3;
+ last_packet = buf[1] == 0x4e;
+ if (buf[2] != 0xfc) {
+ printf("fail1 %02x\n", buf[2]);
+ break;
+ }
+ uint8_t len = buf[3];
+
+ memcpy(buf + 4, firmware, len);
+ firmware += len;
+
+ buf[0] = 1;
+ cywbt_hci_cmd_raw(4 + len, buf);
+ if (buf[0] != 0) {
+ printf("fail3 %02x\n", buf[0]);
+ break;
+ }
+ }
+
+ // RF switch must select high path during BT patch boot
+ mp_hal_pin_config(pyb_pin_WL_GPIO_1, MP_HAL_PIN_MODE_INPUT, MP_HAL_PIN_PULL_UP, 0);
+ mp_hal_delay_ms(10); // give some time for CTS to go high
+ cywbt_wait_cts_low();
+ mp_hal_pin_config(pyb_pin_WL_GPIO_1, MP_HAL_PIN_MODE_INPUT, MP_HAL_PIN_PULL_DOWN, 0); // Select chip antenna (could also select external)
+
+ mp_bluetooth_hci_uart_set_baudrate(115200);
+ cywbt_set_baudrate(3000000);
+ mp_bluetooth_hci_uart_set_baudrate(3000000);
+
+ return 0;
+}
+
+int mp_bluetooth_hci_controller_init(void) {
+ // This is called immediately after the UART is initialised during stack initialisation.
+
+ mp_hal_pin_output(pyb_pin_BT_REG_ON);
+ mp_hal_pin_low(pyb_pin_BT_REG_ON);
+ mp_hal_pin_input(pyb_pin_BT_HOST_WAKE);
+ mp_hal_pin_output(pyb_pin_BT_DEV_WAKE);
+ mp_hal_pin_low(pyb_pin_BT_DEV_WAKE);
+
+ // TODO don't select antenna if wifi is enabled
+ mp_hal_pin_config(pyb_pin_WL_GPIO_4, MP_HAL_PIN_MODE_OUTPUT, MP_HAL_PIN_PULL_NONE, 0); // RF-switch power
+ mp_hal_pin_high(pyb_pin_WL_GPIO_4); // Turn the RF-switch on
+
+ return 0;
+}
+
+int mp_bluetooth_hci_controller_activate(void) {
+ uint8_t buf[256];
+
+ mp_hal_pin_low(pyb_pin_BT_REG_ON);
+ mp_bluetooth_hci_uart_set_baudrate(115200);
+ mp_hal_delay_ms(100);
+ mp_hal_pin_high(pyb_pin_BT_REG_ON);
+ cywbt_wait_cts_low();
+
+ // Reset
+ cywbt_hci_cmd(0x03, 0x0003, 0, NULL);
+
+ // Change baudrate
+ cywbt_set_baudrate(3000000);
+ mp_bluetooth_hci_uart_set_baudrate(3000000);
+
+ cywbt_download_firmware((const uint8_t*)CYWBT_FW_ADDR);
+
+ // Reset
+ cywbt_hci_cmd(0x03, 0x0003, 0, NULL);
+
+ // Set BD_ADDR (sent as little endian)
+ uint8_t bdaddr[6];
+ mp_hal_get_mac(MP_HAL_MAC_BDADDR, bdaddr);
+ buf[0] = bdaddr[5];
+ buf[1] = bdaddr[4];
+ buf[2] = bdaddr[3];
+ buf[3] = bdaddr[2];
+ buf[4] = bdaddr[1];
+ buf[5] = bdaddr[0];
+ cywbt_hci_cmd(0x3f, 0x0001, 6, buf);
+
+ // Set local name
+ // memset(buf, 0, 248);
+ // memcpy(buf, "PYBD-BLE", 8);
+ // cywbt_hci_cmd(0x03, 0x0013, 248, buf);
+
+ // Configure sleep mode
+ cywbt_hci_cmd(0x3f, 0x27, 12, (const uint8_t*)"\x01\x02\x02\x00\x00\x00\x01\x00\x00\x00\x00\x00");
+
+ // HCI_Write_LE_Host_Support
+ cywbt_hci_cmd(3, 109, 2, (const uint8_t*)"\x01\x00");
+
+ mp_hal_pin_high(pyb_pin_BT_DEV_WAKE); // let sleep
+
+ return 0;
+}
+
+int mp_bluetooth_hci_controller_deactivate(void) {
+ mp_hal_pin_low(pyb_pin_BT_REG_ON);
+
+ return 0;
+}
+
+#ifdef pyb_pin_BT_DEV_WAKE
+STATIC uint32_t bt_sleep_ticks;
+#endif
+
+int mp_bluetooth_hci_controller_sleep_maybe(void) {
+ #ifdef pyb_pin_BT_DEV_WAKE
+ if (mp_hal_pin_read(pyb_pin_BT_DEV_WAKE) == 0) {
+ if (mp_hal_ticks_ms() - bt_sleep_ticks > 500) {
+ mp_hal_pin_high(pyb_pin_BT_DEV_WAKE); // let sleep
+ }
+ }
+ #endif
+ return 0;
+}
+
+bool mp_bluetooth_hci_controller_woken(void) {
+ #ifdef pyb_pin_BT_HOST_WAKE
+ bool host_wake = mp_hal_pin_read(pyb_pin_BT_HOST_WAKE);
+ /*
+ // this is just for info/tracing purposes
+ static bool last_host_wake = false;
+ if (host_wake != last_host_wake) {
+ printf("HOST_WAKE change %d -> %d\n", last_host_wake, host_wake);
+ last_host_wake = host_wake;
+ }
+ */
+ return host_wake;
+ #else
+ return true;
+ #endif
+}
+
+int mp_bluetooth_hci_controller_wakeup(void) {
+ #ifdef pyb_pin_BT_DEV_WAKE
+ bt_sleep_ticks = mp_hal_ticks_ms();
+
+ if (mp_hal_pin_read(pyb_pin_BT_DEV_WAKE) == 1) {
+ mp_hal_pin_low(pyb_pin_BT_DEV_WAKE); // wake up
+ // Use delay_us rather than delay_ms to prevent running the scheduler (which
+ // might result in more BLE operations).
+ mp_hal_delay_us(5000); // can't go lower than this
+ }
+ #endif
+
+ return 0;
+}
+
+#endif
diff --git a/drivers/cyw43/libcyw43.a b/drivers/cyw43/libcyw43.a
new file mode 100644
index 0000000000..7d0ff93dcb
Binary files /dev/null and b/drivers/cyw43/libcyw43.a differ
diff --git a/drivers/dht/dht.c b/drivers/dht/dht.c
index 5d92ae39a3..81754ac15f 100644
--- a/drivers/dht/dht.c
+++ b/drivers/dht/dht.c
@@ -32,6 +32,11 @@
#include "extmod/machine_pulse.h"
#include "drivers/dht/dht.h"
+// Allow the open-drain-high call to be DHT specific for ports that need it
+#ifndef mp_hal_pin_od_high_dht
+#define mp_hal_pin_od_high_dht mp_hal_pin_od_high
+#endif
+
STATIC mp_obj_t dht_readinto(mp_obj_t pin_in, mp_obj_t buf_in) {
mp_hal_pin_obj_t pin = mp_hal_get_pin_obj(pin_in);
mp_hal_pin_open_drain(pin);
@@ -40,11 +45,11 @@ STATIC mp_obj_t dht_readinto(mp_obj_t pin_in, mp_obj_t buf_in) {
mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_WRITE);
if (bufinfo.len < 5) {
- mp_raise_ValueError("buffer too small");
+ mp_raise_ValueError(MP_ERROR_TEXT("buffer too small"));
}
// issue start command
- mp_hal_pin_od_high(pin);
+ mp_hal_pin_od_high_dht(pin);
mp_hal_delay_ms(250);
mp_hal_pin_od_low(pin);
mp_hal_delay_ms(18);
@@ -52,7 +57,7 @@ STATIC mp_obj_t dht_readinto(mp_obj_t pin_in, mp_obj_t buf_in) {
mp_uint_t irq_state = mp_hal_quiet_timing_enter();
// release the line so the device can respond
- mp_hal_pin_od_high(pin);
+ mp_hal_pin_od_high_dht(pin);
mp_hal_delay_us_fast(10);
// wait for device to respond
diff --git a/drivers/dht/dht.py b/drivers/dht/dht.py
index eed61df7c9..1163b382bb 100644
--- a/drivers/dht/dht.py
+++ b/drivers/dht/dht.py
@@ -6,6 +6,7 @@
except:
from pyb import dht_readinto
+
class DHTBase:
def __init__(self, pin):
self.pin = pin
@@ -14,9 +15,10 @@ def __init__(self, pin):
def measure(self):
buf = self.buf
dht_readinto(self.pin, buf)
- if (buf[0] + buf[1] + buf[2] + buf[3]) & 0xff != buf[4]:
+ if (buf[0] + buf[1] + buf[2] + buf[3]) & 0xFF != buf[4]:
raise Exception("checksum error")
+
class DHT11(DHTBase):
def humidity(self):
return self.buf[0]
@@ -24,12 +26,13 @@ def humidity(self):
def temperature(self):
return self.buf[2]
+
class DHT22(DHTBase):
def humidity(self):
return (self.buf[0] << 8 | self.buf[1]) * 0.1
def temperature(self):
- t = ((self.buf[2] & 0x7f) << 8 | self.buf[3]) * 0.1
+ t = ((self.buf[2] & 0x7F) << 8 | self.buf[3]) * 0.1
if self.buf[2] & 0x80:
t = -t
return t
diff --git a/drivers/display/lcd160cr.py b/drivers/display/lcd160cr.py
index dd9ab9985b..f792418aa2 100644
--- a/drivers/display/lcd160cr.py
+++ b/drivers/display/lcd160cr.py
@@ -29,16 +29,17 @@
460800: 8,
}
+
class LCD160CR:
def __init__(self, connect=None, *, pwr=None, i2c=None, spi=None, i2c_addr=98):
- if connect in ('X', 'Y', 'XY', 'YX'):
+ if connect in ("X", "Y", "XY", "YX"):
i = connect[-1]
j = connect[0]
- y = j + '4'
- elif connect == 'C':
+ y = j + "4"
+ elif connect == "C":
i = 2
j = 2
- y = 'A7'
+ y = "A7"
else:
if pwr is None or i2c is None or spi is None:
raise ValueError('must specify valid "connect" or all of "pwr", "i2c" and "spi"')
@@ -74,8 +75,8 @@ def __init__(self, connect=None, *, pwr=None, i2c=None, spi=None, i2c_addr=98):
# set default orientation and window
self.set_orient(PORTRAIT)
- self._fcmd2b('> 3)
+ return ((b & 0xF8) << 8) | ((g & 0xFC) << 3) | (r >> 3)
@staticmethod
def clip_line(c, w, h):
@@ -207,43 +208,43 @@ def set_power(self, on):
sleep_ms(15)
def set_orient(self, orient):
- self._fcmd2('= 0x200:
- self._send(ar[n:n + 0x200])
+ self._send(ar[n : n + 0x200])
n += 0x200
else:
self._send(ar[n:])
while n < self.w * self.h * 2:
- self._send(b'\x00')
+ self._send(b"\x00")
n += 1
#### TEXT COMMANDS ####
def set_pos(self, x, y):
- self._fcmd2('= self.w or y >= self.h:
@@ -348,19 +354,19 @@ def rect(self, x, y, w, h, cmd=0x72):
y = 0
if cmd == 0x51 or cmd == 0x72:
# draw interior
- self._fcmd2b('> 7 != 0
def get_touch(self):
- self._send(b'\x02T') # implicit LCD output flush
+ self._send(b"\x02T") # implicit LCD output flush
b = self.buf[4]
self._waitfor(3, b)
return b[1] >> 7, b[2], b[3]
@@ -424,40 +430,42 @@ def get_touch(self):
#### ADVANCED COMMANDS ####
def set_spi_win(self, x, y, w, h):
- pack_into(' 32:
- raise ValueError('length must be 32 or less')
- self._fcmd2(' 0xffff:
- raise ValueError('length must be 65535 or less')
+ if l > 0xFFFF:
+ raise ValueError("length must be 65535 or less")
self.oflush()
- self._fcmd2(' 0:
- s = '%6.3fV' % data[i]
+ s = "%6.3fV" % data[i]
else:
- s = '%5.1f°C' % data[i]
+ s = "%5.1f°C" % data[i]
if lcd.h == 160:
lcd.set_font(1, bold=0, scale=1)
else:
lcd.set_font(1, bold=0, scale=1, trans=1)
- lcd.set_pos(45, lcd.h-60 + i * 16)
+ lcd.set_pos(45, lcd.h - 60 + i * 16)
lcd.write(s)
+
def test_features(lcd, orient=lcd160cr.PORTRAIT):
# if we run on pyboard then use ADC and RTC features
try:
import pyb
- adc = pyb.ADCAll(12, 0xf0000)
+
+ adc = pyb.ADCAll(12, 0xF0000)
rtc = pyb.RTC()
except:
adc = None
@@ -53,7 +57,7 @@ def test_features(lcd, orient=lcd160cr.PORTRAIT):
# create M-logo
mlogo = framebuf.FrameBuffer(bytearray(17 * 17 * 2), 17, 17, framebuf.RGB565)
mlogo.fill(0)
- mlogo.fill_rect(1, 1, 15, 15, 0xffffff)
+ mlogo.fill_rect(1, 1, 15, 15, 0xFFFFFF)
mlogo.vline(4, 4, 12, 0)
mlogo.vline(8, 1, 12, 0)
mlogo.vline(12, 4, 12, 0)
@@ -80,15 +84,18 @@ def test_features(lcd, orient=lcd160cr.PORTRAIT):
if tx2 >= 0 and ty2 >= 0 and tx2 < w and ty2 < h:
tx, ty = tx2, ty2
else:
- tx = (tx + 1) % w
- ty = (ty + 1) % h
+ tx = (tx + 1) % w
+ ty = (ty + 1) % h
# create and show the inline framebuf
fbuf.fill(lcd.rgb(128 + int(64 * math.cos(0.1 * i)), 128, 192))
- fbuf.line(w // 2, h // 2,
+ fbuf.line(
+ w // 2,
+ h // 2,
w // 2 + int(40 * math.cos(0.2 * i)),
h // 2 + int(40 * math.sin(0.2 * i)),
- lcd.rgb(128, 255, 64))
+ lcd.rgb(128, 255, 64),
+ )
fbuf.hline(0, ty, w, lcd.rgb(64, 64, 64))
fbuf.vline(tx, 0, h, lcd.rgb(64, 64, 64))
fbuf.rect(tx - 3, ty - 3, 7, 7, lcd.rgb(64, 64, 64))
@@ -97,9 +104,12 @@ def test_features(lcd, orient=lcd160cr.PORTRAIT):
y = h // 2 - 8 + int(32 * math.sin(0.05 * i + phase))
fbuf.blit(mlogo, x, y)
for j in range(-3, 3):
- fbuf.text('MicroPython',
- 5, h // 2 + 9 * j + int(20 * math.sin(0.1 * (i + j))),
- lcd.rgb(128 + 10 * j, 0, 128 - 10 * j))
+ fbuf.text(
+ "MicroPython",
+ 5,
+ h // 2 + 9 * j + int(20 * math.sin(0.1 * (i + j))),
+ lcd.rgb(128 + 10 * j, 0, 128 - 10 * j),
+ )
lcd.show_framebuf(fbuf)
# show results from the ADC
@@ -111,7 +121,10 @@ def test_features(lcd, orient=lcd160cr.PORTRAIT):
lcd.set_pos(2, 0)
lcd.set_font(1)
t = rtc.datetime()
- lcd.write('%4d-%02d-%02d %2d:%02d:%02d.%01d' % (t[0], t[1], t[2], t[4], t[5], t[6], t[7] // 100000))
+ lcd.write(
+ "%4d-%02d-%02d %2d:%02d:%02d.%01d"
+ % (t[0], t[1], t[2], t[4], t[5], t[6], t[7] // 100000)
+ )
# compute the frame rate
t1 = time.ticks_us()
@@ -120,13 +133,14 @@ def test_features(lcd, orient=lcd160cr.PORTRAIT):
# show the frame rate
lcd.set_pos(2, 9)
- lcd.write('%.2f fps' % (1000000 / dt))
+ lcd.write("%.2f fps" % (1000000 / dt))
+
def test_mandel(lcd, orient=lcd160cr.PORTRAIT):
# set orientation and clear screen
lcd = get_lcd(lcd)
lcd.set_orient(orient)
- lcd.set_pen(0, 0xffff)
+ lcd.set_pen(0, 0xFFFF)
lcd.erase()
# function to compute Mandelbrot pixels
@@ -148,24 +162,26 @@ def in_set(c):
spi = lcd.fast_spi()
# draw the Mandelbrot set line-by-line
- hh = ((h - 1) / 3.2)
- ww = ((w - 1) / 2.4)
+ hh = (h - 1) / 3.2
+ ww = (w - 1) / 2.4
for v in range(h):
for u in range(w):
c = in_set((v / hh - 2.3) + (u / ww - 1.2) * 1j)
if c < 16:
rgb = c << 12 | c << 6
else:
- rgb = 0xf800 | c << 6
+ rgb = 0xF800 | c << 6
line[2 * u] = rgb
line[2 * u + 1] = rgb >> 8
spi.write(line)
+
def test_all(lcd, orient=lcd160cr.PORTRAIT):
lcd = get_lcd(lcd)
test_features(lcd, orient)
test_mandel(lcd, orient)
-print('To run all tests: test_all()')
-print('Individual tests are: test_features, test_mandel')
+
+print("To run all tests: test_all()")
+print("Individual tests are: test_features, test_mandel")
print(' argument should be a connection, eg "X", or an LCD160CR object')
diff --git a/drivers/display/ssd1306.py b/drivers/display/ssd1306.py
index 178b4911d7..6359c85eaa 100644
--- a/drivers/display/ssd1306.py
+++ b/drivers/display/ssd1306.py
@@ -5,23 +5,23 @@
# register definitions
-SET_CONTRAST = const(0x81)
-SET_ENTIRE_ON = const(0xa4)
-SET_NORM_INV = const(0xa6)
-SET_DISP = const(0xae)
-SET_MEM_ADDR = const(0x20)
-SET_COL_ADDR = const(0x21)
-SET_PAGE_ADDR = const(0x22)
+SET_CONTRAST = const(0x81)
+SET_ENTIRE_ON = const(0xA4)
+SET_NORM_INV = const(0xA6)
+SET_DISP = const(0xAE)
+SET_MEM_ADDR = const(0x20)
+SET_COL_ADDR = const(0x21)
+SET_PAGE_ADDR = const(0x22)
SET_DISP_START_LINE = const(0x40)
-SET_SEG_REMAP = const(0xa0)
-SET_MUX_RATIO = const(0xa8)
-SET_COM_OUT_DIR = const(0xc0)
-SET_DISP_OFFSET = const(0xd3)
-SET_COM_PIN_CFG = const(0xda)
-SET_DISP_CLK_DIV = const(0xd5)
-SET_PRECHARGE = const(0xd9)
-SET_VCOM_DESEL = const(0xdb)
-SET_CHARGE_PUMP = const(0x8d)
+SET_SEG_REMAP = const(0xA0)
+SET_MUX_RATIO = const(0xA8)
+SET_COM_OUT_DIR = const(0xC0)
+SET_DISP_OFFSET = const(0xD3)
+SET_COM_PIN_CFG = const(0xDA)
+SET_DISP_CLK_DIV = const(0xD5)
+SET_PRECHARGE = const(0xD9)
+SET_VCOM_DESEL = const(0xDB)
+SET_CHARGE_PUMP = const(0x8D)
# Subclassing FrameBuffer provides support for graphics primitives
# http://docs.micropython.org/en/latest/pyboard/library/framebuf.html
@@ -37,27 +37,37 @@ def __init__(self, width, height, external_vcc):
def init_display(self):
for cmd in (
- SET_DISP | 0x00, # off
+ SET_DISP | 0x00, # off
# address setting
- SET_MEM_ADDR, 0x00, # horizontal
+ SET_MEM_ADDR,
+ 0x00, # horizontal
# resolution and layout
SET_DISP_START_LINE | 0x00,
- SET_SEG_REMAP | 0x01, # column addr 127 mapped to SEG0
- SET_MUX_RATIO, self.height - 1,
- SET_COM_OUT_DIR | 0x08, # scan from COM[N] to COM0
- SET_DISP_OFFSET, 0x00,
- SET_COM_PIN_CFG, 0x02 if self.height == 32 else 0x12,
+ SET_SEG_REMAP | 0x01, # column addr 127 mapped to SEG0
+ SET_MUX_RATIO,
+ self.height - 1,
+ SET_COM_OUT_DIR | 0x08, # scan from COM[N] to COM0
+ SET_DISP_OFFSET,
+ 0x00,
+ SET_COM_PIN_CFG,
+ 0x02 if self.width > 2 * self.height else 0x12,
# timing and driving scheme
- SET_DISP_CLK_DIV, 0x80,
- SET_PRECHARGE, 0x22 if self.external_vcc else 0xf1,
- SET_VCOM_DESEL, 0x30, # 0.83*Vcc
+ SET_DISP_CLK_DIV,
+ 0x80,
+ SET_PRECHARGE,
+ 0x22 if self.external_vcc else 0xF1,
+ SET_VCOM_DESEL,
+ 0x30, # 0.83*Vcc
# display
- SET_CONTRAST, 0xff, # maximum
- SET_ENTIRE_ON, # output follows RAM contents
- SET_NORM_INV, # not inverted
+ SET_CONTRAST,
+ 0xFF, # maximum
+ SET_ENTIRE_ON, # output follows RAM contents
+ SET_NORM_INV, # not inverted
# charge pump
- SET_CHARGE_PUMP, 0x10 if self.external_vcc else 0x14,
- SET_DISP | 0x01): # on
+ SET_CHARGE_PUMP,
+ 0x10 if self.external_vcc else 0x14,
+ SET_DISP | 0x01,
+ ): # on
self.write_cmd(cmd)
self.fill(0)
self.show()
@@ -92,24 +102,21 @@ def show(self):
class SSD1306_I2C(SSD1306):
- def __init__(self, width, height, i2c, addr=0x3c, external_vcc=False):
+ def __init__(self, width, height, i2c, addr=0x3C, external_vcc=False):
self.i2c = i2c
self.addr = addr
self.temp = bytearray(2)
+ self.write_list = [b"\x40", None] # Co=0, D/C#=1
super().__init__(width, height, external_vcc)
def write_cmd(self, cmd):
- self.temp[0] = 0x80 # Co=1, D/C#=0
+ self.temp[0] = 0x80 # Co=1, D/C#=0
self.temp[1] = cmd
self.i2c.writeto(self.addr, self.temp)
def write_data(self, buf):
- self.temp[0] = self.addr << 1
- self.temp[1] = 0x40 # Co=0, D/C#=1
- self.i2c.start()
- self.i2c.write(self.temp)
- self.i2c.write(buf)
- self.i2c.stop()
+ self.write_list[1] = buf
+ self.i2c.writevto(self.addr, self.write_list)
class SSD1306_SPI(SSD1306):
@@ -123,6 +130,7 @@ def __init__(self, width, height, spi, dc, res, cs, external_vcc=False):
self.res = res
self.cs = cs
import time
+
self.res(1)
time.sleep_ms(1)
self.res(0)
diff --git a/drivers/ksz8851/ksz8851.c b/drivers/ksz8851/ksz8851.c
index 9c686eed93..b88c0b823f 100644
--- a/drivers/ksz8851/ksz8851.c
+++ b/drivers/ksz8851/ksz8851.c
@@ -51,8 +51,8 @@ static IRAM_ATTR void ksz8851ProcessInterrupt(void);
static void init_spi(void) {
portDISABLE_INTERRUPTS();
// this is SpiNum_SPI2
- DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI_CLK_EN_2);
- DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI_RST_2);
+ DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI2_CLK_EN);
+ DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI2_RST);
// configure the SPI port
spi_attr_t spi_attr = {.mode = SpiMode_Master, .subMode = SpiSubMode_0, .speed = SpiSpeed_8MHz,
diff --git a/drivers/memory/spiflash.c b/drivers/memory/spiflash.c
index d72603f648..e870d39f5f 100644
--- a/drivers/memory/spiflash.c
+++ b/drivers/memory/spiflash.c
@@ -45,15 +45,16 @@
#define CMD_CHIP_ERASE (0xc7)
#define CMD_C4READ (0xeb)
+// 32 bit addressing commands
+#define CMD_WRITE_32 (0x12)
+#define CMD_READ_32 (0x13)
+#define CMD_SEC_ERASE_32 (0x21)
+#define CMD_C4READ_32 (0xec)
+
#define WAIT_SR_TIMEOUT (1000000)
#define PAGE_SIZE (256) // maximum bytes we can write in one SPI transfer
-#define SECTOR_SIZE (4096) // size of erase sector
-
-// Note: this code is not reentrant with this shared buffer
-STATIC uint8_t buf[SECTOR_SIZE] __attribute__((aligned(4)));
-STATIC mp_spiflash_t *bufuser; // current user of buf
-STATIC uint32_t bufsec; // current sector stored in buf; 0xffffffff if invalid
+#define SECTOR_SIZE MP_SPIFLASH_ERASE_BLOCK_SIZE
STATIC void mp_spiflash_acquire_bus(mp_spiflash_t *self) {
const mp_spiflash_config_t *c = self->config;
@@ -81,18 +82,26 @@ STATIC void mp_spiflash_write_cmd_data(mp_spiflash_t *self, uint8_t cmd, size_t
}
}
-STATIC void mp_spiflash_write_cmd_addr_data(mp_spiflash_t *self, uint8_t cmd, uint32_t addr, size_t len, const uint8_t *src) {
+STATIC void mp_spiflash_transfer_cmd_addr_data(mp_spiflash_t *self, uint8_t cmd, uint32_t addr, size_t len, const uint8_t *src, uint8_t *dest) {
const mp_spiflash_config_t *c = self->config;
if (c->bus_kind == MP_SPIFLASH_BUS_SPI) {
- uint8_t buf[4] = {cmd, addr >> 16, addr >> 8, addr};
+ uint8_t buf[5] = {cmd, 0};
+ uint8_t buff_len = 1 + mp_spi_set_addr_buff(&buf[1], addr);
mp_hal_pin_write(c->bus.u_spi.cs, 0);
- c->bus.u_spi.proto->transfer(c->bus.u_spi.data, 4, buf, NULL);
- if (len) {
+ c->bus.u_spi.proto->transfer(c->bus.u_spi.data, buff_len, buf, NULL);
+ if (len && (src != NULL)) {
c->bus.u_spi.proto->transfer(c->bus.u_spi.data, len, src, NULL);
+ } else if (len && (dest != NULL)) {
+ c->bus.u_spi.proto->transfer(c->bus.u_spi.data, len, dest, dest);
}
+
mp_hal_pin_write(c->bus.u_spi.cs, 1);
} else {
- c->bus.u_qspi.proto->write_cmd_addr_data(c->bus.u_qspi.data, cmd, addr, len, src);
+ if (dest != NULL) {
+ c->bus.u_qspi.proto->read_cmd_qaddr_qdata(c->bus.u_qspi.data, cmd, addr, len, dest);
+ } else {
+ c->bus.u_qspi.proto->write_cmd_addr_data(c->bus.u_qspi.data, cmd, addr, len, src);
+ }
}
}
@@ -112,40 +121,29 @@ STATIC uint32_t mp_spiflash_read_cmd(mp_spiflash_t *self, uint8_t cmd, size_t le
STATIC void mp_spiflash_read_data(mp_spiflash_t *self, uint32_t addr, size_t len, uint8_t *dest) {
const mp_spiflash_config_t *c = self->config;
+ uint8_t cmd;
if (c->bus_kind == MP_SPIFLASH_BUS_SPI) {
- uint8_t buf[4] = {CMD_READ, addr >> 16, addr >> 8, addr};
- mp_hal_pin_write(c->bus.u_spi.cs, 0);
- c->bus.u_spi.proto->transfer(c->bus.u_spi.data, 4, buf, NULL);
- c->bus.u_spi.proto->transfer(c->bus.u_spi.data, len, dest, dest);
- mp_hal_pin_write(c->bus.u_spi.cs, 1);
+ cmd = MP_SPI_ADDR_IS_32B(addr) ? CMD_READ_32 : CMD_READ;
} else {
- c->bus.u_qspi.proto->read_cmd_qaddr_qdata(c->bus.u_qspi.data, CMD_C4READ, addr, len, dest);
+ cmd = MP_SPI_ADDR_IS_32B(addr) ? CMD_C4READ_32 : CMD_C4READ;
}
+ mp_spiflash_transfer_cmd_addr_data(self, cmd, addr, len, NULL, dest);
}
STATIC void mp_spiflash_write_cmd(mp_spiflash_t *self, uint8_t cmd) {
mp_spiflash_write_cmd_data(self, cmd, 0, 0);
}
-STATIC void mp_spiflash_write_cmd_addr(mp_spiflash_t *self, uint8_t cmd, uint32_t addr) {
- mp_spiflash_write_cmd_addr_data(self, cmd, addr, 0, NULL);
-}
-
STATIC int mp_spiflash_wait_sr(mp_spiflash_t *self, uint8_t mask, uint8_t val, uint32_t timeout) {
uint8_t sr;
- for (; timeout; --timeout) {
+ do {
sr = mp_spiflash_read_cmd(self, CMD_RDSR, 1);
if ((sr & mask) == val) {
- break;
+ return 0; // success
}
- }
- if ((sr & mask) == val) {
- return 0; // success
- } else if (timeout == 0) {
- return -MP_ETIMEDOUT;
- } else {
- return -MP_EIO;
- }
+ } while (timeout--);
+
+ return -MP_ETIMEDOUT;
}
STATIC int mp_spiflash_wait_wel1(mp_spiflash_t *self) {
@@ -156,6 +154,10 @@ STATIC int mp_spiflash_wait_wip0(mp_spiflash_t *self) {
return mp_spiflash_wait_sr(self, 1, 0, WAIT_SR_TIMEOUT);
}
+static inline void mp_spiflash_deepsleep_internal(mp_spiflash_t *self, int value) {
+ mp_spiflash_write_cmd(self, value ? 0xb9 : 0xab); // sleep/wake
+}
+
void mp_spiflash_init(mp_spiflash_t *self) {
self->flags = 0;
@@ -169,6 +171,9 @@ void mp_spiflash_init(mp_spiflash_t *self) {
mp_spiflash_acquire_bus(self);
+ // Ensure SPI flash is out of sleep mode
+ mp_spiflash_deepsleep_internal(self, 0);
+
#if defined(CHECK_DEVID)
// Validate device id
uint32_t devid = mp_spiflash_read_cmd(self, CMD_RD_DEVID, 3);
@@ -192,7 +197,17 @@ void mp_spiflash_init(mp_spiflash_t *self) {
mp_spiflash_release_bus(self);
}
-STATIC int mp_spiflash_erase_sector(mp_spiflash_t *self, uint32_t addr) {
+void mp_spiflash_deepsleep(mp_spiflash_t *self, int value) {
+ if (value) {
+ mp_spiflash_acquire_bus(self);
+ }
+ mp_spiflash_deepsleep_internal(self, value);
+ if (!value) {
+ mp_spiflash_release_bus(self);
+ }
+}
+
+STATIC int mp_spiflash_erase_block_internal(mp_spiflash_t *self, uint32_t addr) {
// enable writes
mp_spiflash_write_cmd(self, CMD_WREN);
@@ -203,13 +218,14 @@ STATIC int mp_spiflash_erase_sector(mp_spiflash_t *self, uint32_t addr) {
}
// erase the sector
- mp_spiflash_write_cmd_addr(self, CMD_SEC_ERASE, addr);
+ uint8_t cmd = MP_SPI_ADDR_IS_32B(addr) ? CMD_SEC_ERASE_32 : CMD_SEC_ERASE;
+ mp_spiflash_transfer_cmd_addr_data(self, cmd, addr, 0, NULL, NULL);
// wait WIP=0
return mp_spiflash_wait_wip0(self);
}
-STATIC int mp_spiflash_write_page(mp_spiflash_t *self, uint32_t addr, const uint8_t *src) {
+STATIC int mp_spiflash_write_page(mp_spiflash_t *self, uint32_t addr, size_t len, const uint8_t *src) {
// enable writes
mp_spiflash_write_cmd(self, CMD_WREN);
@@ -220,26 +236,72 @@ STATIC int mp_spiflash_write_page(mp_spiflash_t *self, uint32_t addr, const uint
}
// write the page
- mp_spiflash_write_cmd_addr_data(self, CMD_WRITE, addr, PAGE_SIZE, src);
+ uint8_t cmd = MP_SPI_ADDR_IS_32B(addr) ? CMD_WRITE_32 : CMD_WRITE;
+ mp_spiflash_transfer_cmd_addr_data(self, cmd, addr, len, src, NULL);
// wait WIP=0
return mp_spiflash_wait_wip0(self);
}
+/******************************************************************************/
+// Interface functions that go direct to the SPI flash device
+
+int mp_spiflash_erase_block(mp_spiflash_t *self, uint32_t addr) {
+ mp_spiflash_acquire_bus(self);
+ int ret = mp_spiflash_erase_block_internal(self, addr);
+ mp_spiflash_release_bus(self);
+ return ret;
+}
+
void mp_spiflash_read(mp_spiflash_t *self, uint32_t addr, size_t len, uint8_t *dest) {
if (len == 0) {
return;
}
mp_spiflash_acquire_bus(self);
- if (bufuser == self && bufsec != 0xffffffff) {
+ mp_spiflash_read_data(self, addr, len, dest);
+ mp_spiflash_release_bus(self);
+}
+
+int mp_spiflash_write(mp_spiflash_t *self, uint32_t addr, size_t len, const uint8_t *src) {
+ mp_spiflash_acquire_bus(self);
+ int ret = 0;
+ uint32_t offset = addr & (PAGE_SIZE - 1);
+ while (len) {
+ size_t rest = PAGE_SIZE - offset;
+ if (rest > len) {
+ rest = len;
+ }
+ ret = mp_spiflash_write_page(self, addr, rest, src);
+ if (ret != 0) {
+ break;
+ }
+ len -= rest;
+ addr += rest;
+ src += rest;
+ offset = 0;
+ }
+ mp_spiflash_release_bus(self);
+ return ret;
+}
+
+/******************************************************************************/
+// Interface functions that use the cache
+
+void mp_spiflash_cached_read(mp_spiflash_t *self, uint32_t addr, size_t len, uint8_t *dest) {
+ if (len == 0) {
+ return;
+ }
+ mp_spiflash_acquire_bus(self);
+ mp_spiflash_cache_t *cache = self->config->cache;
+ if (cache->user == self && cache->block != 0xffffffff) {
uint32_t bis = addr / SECTOR_SIZE;
uint32_t bie = (addr + len - 1) / SECTOR_SIZE;
- if (bis <= bufsec && bufsec <= bie) {
+ if (bis <= cache->block && cache->block <= bie) {
// Read straddles current buffer
size_t rest = 0;
- if (bis < bufsec) {
+ if (bis < cache->block) {
// Read direct from flash for first part
- rest = bufsec * SECTOR_SIZE - addr;
+ rest = cache->block * SECTOR_SIZE - addr;
mp_spiflash_read_data(self, addr, rest, dest);
len -= rest;
dest += rest;
@@ -250,7 +312,7 @@ void mp_spiflash_read(mp_spiflash_t *self, uint32_t addr, size_t len, uint8_t *d
if (rest > len) {
rest = len;
}
- memcpy(dest, &buf[offset], rest);
+ memcpy(dest, &cache->buf[offset], rest);
len -= rest;
if (len == 0) {
mp_spiflash_release_bus(self);
@@ -265,7 +327,7 @@ void mp_spiflash_read(mp_spiflash_t *self, uint32_t addr, size_t len, uint8_t *d
mp_spiflash_release_bus(self);
}
-STATIC void mp_spiflash_flush_internal(mp_spiflash_t *self) {
+STATIC void mp_spiflash_cache_flush_internal(mp_spiflash_t *self) {
#if USE_WR_DELAY
if (!(self->flags & 1)) {
return;
@@ -273,15 +335,18 @@ STATIC void mp_spiflash_flush_internal(mp_spiflash_t *self) {
self->flags &= ~1;
+ mp_spiflash_cache_t *cache = self->config->cache;
+
// Erase sector
- int ret = mp_spiflash_erase_sector(self, bufsec * SECTOR_SIZE);
+ int ret = mp_spiflash_erase_block_internal(self, cache->block * SECTOR_SIZE);
if (ret != 0) {
return;
}
// Write
for (int i = 0; i < 16; i += 1) {
- int ret = mp_spiflash_write_page(self, bufsec * SECTOR_SIZE + i * PAGE_SIZE, buf + i * PAGE_SIZE);
+ uint32_t addr = cache->block * SECTOR_SIZE + i * PAGE_SIZE;
+ int ret = mp_spiflash_write_page(self, addr, PAGE_SIZE, cache->buf + i * PAGE_SIZE);
if (ret != 0) {
return;
}
@@ -289,48 +354,50 @@ STATIC void mp_spiflash_flush_internal(mp_spiflash_t *self) {
#endif
}
-void mp_spiflash_flush(mp_spiflash_t *self) {
+void mp_spiflash_cache_flush(mp_spiflash_t *self) {
mp_spiflash_acquire_bus(self);
- mp_spiflash_flush_internal(self);
+ mp_spiflash_cache_flush_internal(self);
mp_spiflash_release_bus(self);
}
-STATIC int mp_spiflash_write_part(mp_spiflash_t *self, uint32_t addr, size_t len, const uint8_t *src) {
+STATIC int mp_spiflash_cached_write_part(mp_spiflash_t *self, uint32_t addr, size_t len, const uint8_t *src) {
// Align to 4096 sector
uint32_t offset = addr & 0xfff;
uint32_t sec = addr >> 12;
addr = sec << 12;
// Restriction for now, so we don't need to erase multiple pages
- if (offset + len > sizeof(buf)) {
- printf("mp_spiflash_write_part: len is too large\n");
+ if (offset + len > SECTOR_SIZE) {
+ printf("mp_spiflash_cached_write_part: len is too large\n");
return -MP_EIO;
}
+ mp_spiflash_cache_t *cache = self->config->cache;
+
// Acquire the sector buffer
- if (bufuser != self) {
- if (bufuser != NULL) {
- mp_spiflash_flush(bufuser);
+ if (cache->user != self) {
+ if (cache->user != NULL) {
+ mp_spiflash_cache_flush(cache->user);
}
- bufuser = self;
- bufsec = 0xffffffff;
+ cache->user = self;
+ cache->block = 0xffffffff;
}
- if (bufsec != sec) {
+ if (cache->block != sec) {
// Read sector
#if USE_WR_DELAY
- if (bufsec != 0xffffffff) {
- mp_spiflash_flush_internal(self);
+ if (cache->block != 0xffffffff) {
+ mp_spiflash_cache_flush_internal(self);
}
#endif
- mp_spiflash_read_data(self, addr, SECTOR_SIZE, buf);
+ mp_spiflash_read_data(self, addr, SECTOR_SIZE, cache->buf);
}
#if USE_WR_DELAY
- bufsec = sec;
+ cache->block = sec;
// Just copy to buffer
- memcpy(buf + offset, src, len);
+ memcpy(cache->buf + offset, src, len);
// And mark dirty
self->flags |= 1;
@@ -338,10 +405,10 @@ STATIC int mp_spiflash_write_part(mp_spiflash_t *self, uint32_t addr, size_t len
uint32_t dirty = 0;
for (size_t i = 0; i < len; ++i) {
- if (buf[offset + i] != src[i]) {
- if (buf[offset + i] != 0xff) {
+ if (cache->buf[offset + i] != src[i]) {
+ if (cache->buf[offset + i] != 0xff) {
// Erase sector
- int ret = mp_spiflash_erase_sector(self, addr);
+ int ret = mp_spiflash_erase_block_internal(self, addr);
if (ret != 0) {
return ret;
}
@@ -353,14 +420,14 @@ STATIC int mp_spiflash_write_part(mp_spiflash_t *self, uint32_t addr, size_t len
}
}
- bufsec = sec;
+ cache->block = sec;
// Copy new block into buffer
- memcpy(buf + offset, src, len);
+ memcpy(cache->buf + offset, src, len);
// Write sector in pages of 256 bytes
for (size_t i = 0; i < 16; ++i) {
if (dirty & (1 << i)) {
- int ret = mp_spiflash_write_page(self, addr + i * PAGE_SIZE, buf + i * PAGE_SIZE);
+ int ret = mp_spiflash_write_page(self, addr + i * PAGE_SIZE, PAGE_SIZE, cache->buf + i * PAGE_SIZE);
if (ret != 0) {
return ret;
}
@@ -372,22 +439,23 @@ STATIC int mp_spiflash_write_part(mp_spiflash_t *self, uint32_t addr, size_t len
return 0; // success
}
-int mp_spiflash_write(mp_spiflash_t *self, uint32_t addr, size_t len, const uint8_t *src) {
+int mp_spiflash_cached_write(mp_spiflash_t *self, uint32_t addr, size_t len, const uint8_t *src) {
uint32_t bis = addr / SECTOR_SIZE;
uint32_t bie = (addr + len - 1) / SECTOR_SIZE;
mp_spiflash_acquire_bus(self);
- if (bufuser == self && bis <= bufsec && bie >= bufsec) {
+ mp_spiflash_cache_t *cache = self->config->cache;
+ if (cache->user == self && bis <= cache->block && bie >= cache->block) {
// Write straddles current buffer
uint32_t pre;
uint32_t offset;
- if (bufsec * SECTOR_SIZE >= addr) {
- pre = bufsec * SECTOR_SIZE - addr;
+ if (cache->block * SECTOR_SIZE >= addr) {
+ pre = cache->block * SECTOR_SIZE - addr;
offset = 0;
} else {
pre = 0;
- offset = addr - bufsec * SECTOR_SIZE;
+ offset = addr - cache->block * SECTOR_SIZE;
}
// Write buffered part first
@@ -397,7 +465,7 @@ int mp_spiflash_write(mp_spiflash_t *self, uint32_t addr, size_t len, const uint
len = len_in_buf - (SECTOR_SIZE - offset);
len_in_buf = SECTOR_SIZE - offset;
}
- memcpy(&buf[offset], &src[pre], len_in_buf);
+ memcpy(&cache->buf[offset], &src[pre], len_in_buf);
self->flags |= 1; // Mark dirty
// Write part before buffer sector
@@ -406,7 +474,7 @@ int mp_spiflash_write(mp_spiflash_t *self, uint32_t addr, size_t len, const uint
if (rest == 0) {
rest = SECTOR_SIZE;
}
- int ret = mp_spiflash_write_part(self, addr, rest, src);
+ int ret = mp_spiflash_cached_write_part(self, addr, rest, src);
if (ret != 0) {
mp_spiflash_release_bus(self);
return ret;
@@ -427,7 +495,7 @@ int mp_spiflash_write(mp_spiflash_t *self, uint32_t addr, size_t len, const uint
if (rest > len) {
rest = len;
}
- int ret = mp_spiflash_write_part(self, addr, rest, src);
+ int ret = mp_spiflash_cached_write_part(self, addr, rest, src);
if (ret != 0) {
mp_spiflash_release_bus(self);
return ret;
diff --git a/drivers/memory/spiflash.h b/drivers/memory/spiflash.h
index 03bad5296a..96dfdeeab6 100644
--- a/drivers/memory/spiflash.h
+++ b/drivers/memory/spiflash.h
@@ -29,11 +29,23 @@
#include "drivers/bus/spi.h"
#include "drivers/bus/qspi.h"
+#define MP_SPIFLASH_ERASE_BLOCK_SIZE (4096) // must be a power of 2
+
enum {
MP_SPIFLASH_BUS_SPI,
MP_SPIFLASH_BUS_QSPI,
};
+struct _mp_spiflash_t;
+
+// A cache must be provided by the user in the config struct. The same cache
+// struct can be shared by multiple SPI flash instances.
+typedef struct _mp_spiflash_cache_t {
+ uint8_t buf[MP_SPIFLASH_ERASE_BLOCK_SIZE] __attribute__((aligned(4)));
+ struct _mp_spiflash_t *user; // current user of buf, for shared use
+ uint32_t block; // current block stored in buf; 0xffffffff if invalid
+} mp_spiflash_cache_t;
+
typedef struct _mp_spiflash_config_t {
uint32_t bus_kind;
union {
@@ -47,6 +59,7 @@ typedef struct _mp_spiflash_config_t {
const mp_qspi_proto_t *proto;
} u_qspi;
} bus;
+ mp_spiflash_cache_t *cache; // can be NULL if cache functions not used
} mp_spiflash_config_t;
typedef struct _mp_spiflash_t {
@@ -55,8 +68,16 @@ typedef struct _mp_spiflash_t {
} mp_spiflash_t;
void mp_spiflash_init(mp_spiflash_t *self);
-void mp_spiflash_flush(mp_spiflash_t *self);
+void mp_spiflash_deepsleep(mp_spiflash_t *self, int value);
+
+// These functions go direct to the SPI flash device
+int mp_spiflash_erase_block(mp_spiflash_t *self, uint32_t addr);
void mp_spiflash_read(mp_spiflash_t *self, uint32_t addr, size_t len, uint8_t *dest);
int mp_spiflash_write(mp_spiflash_t *self, uint32_t addr, size_t len, const uint8_t *src);
+// These functions use the cache (which must already be configured)
+void mp_spiflash_cache_flush(mp_spiflash_t *self);
+void mp_spiflash_cached_read(mp_spiflash_t *self, uint32_t addr, size_t len, uint8_t *dest);
+int mp_spiflash_cached_write(mp_spiflash_t *self, uint32_t addr, size_t len, const uint8_t *src);
+
#endif // MICROPY_INCLUDED_DRIVERS_MEMORY_SPIFLASH_H
diff --git a/drivers/nrf24l01/nrf24l01.py b/drivers/nrf24l01/nrf24l01.py
index a95d2b5cac..76d55312f8 100644
--- a/drivers/nrf24l01/nrf24l01.py
+++ b/drivers/nrf24l01/nrf24l01.py
@@ -5,49 +5,50 @@
import utime
# nRF24L01+ registers
-CONFIG = const(0x00)
-EN_RXADDR = const(0x02)
-SETUP_AW = const(0x03)
-SETUP_RETR = const(0x04)
-RF_CH = const(0x05)
-RF_SETUP = const(0x06)
-STATUS = const(0x07)
-RX_ADDR_P0 = const(0x0a)
-TX_ADDR = const(0x10)
-RX_PW_P0 = const(0x11)
+CONFIG = const(0x00)
+EN_RXADDR = const(0x02)
+SETUP_AW = const(0x03)
+SETUP_RETR = const(0x04)
+RF_CH = const(0x05)
+RF_SETUP = const(0x06)
+STATUS = const(0x07)
+RX_ADDR_P0 = const(0x0A)
+TX_ADDR = const(0x10)
+RX_PW_P0 = const(0x11)
FIFO_STATUS = const(0x17)
-DYNPD = const(0x1c)
+DYNPD = const(0x1C)
# CONFIG register
-EN_CRC = const(0x08) # enable CRC
-CRCO = const(0x04) # CRC encoding scheme; 0=1 byte, 1=2 bytes
-PWR_UP = const(0x02) # 1=power up, 0=power down
-PRIM_RX = const(0x01) # RX/TX control; 0=PTX, 1=PRX
+EN_CRC = const(0x08) # enable CRC
+CRCO = const(0x04) # CRC encoding scheme; 0=1 byte, 1=2 bytes
+PWR_UP = const(0x02) # 1=power up, 0=power down
+PRIM_RX = const(0x01) # RX/TX control; 0=PTX, 1=PRX
# RF_SETUP register
-POWER_0 = const(0x00) # -18 dBm
-POWER_1 = const(0x02) # -12 dBm
-POWER_2 = const(0x04) # -6 dBm
-POWER_3 = const(0x06) # 0 dBm
-SPEED_1M = const(0x00)
-SPEED_2M = const(0x08)
-SPEED_250K = const(0x20)
+POWER_0 = const(0x00) # -18 dBm
+POWER_1 = const(0x02) # -12 dBm
+POWER_2 = const(0x04) # -6 dBm
+POWER_3 = const(0x06) # 0 dBm
+SPEED_1M = const(0x00)
+SPEED_2M = const(0x08)
+SPEED_250K = const(0x20)
# STATUS register
-RX_DR = const(0x40) # RX data ready; write 1 to clear
-TX_DS = const(0x20) # TX data sent; write 1 to clear
-MAX_RT = const(0x10) # max retransmits reached; write 1 to clear
+RX_DR = const(0x40) # RX data ready; write 1 to clear
+TX_DS = const(0x20) # TX data sent; write 1 to clear
+MAX_RT = const(0x10) # max retransmits reached; write 1 to clear
# FIFO_STATUS register
-RX_EMPTY = const(0x01) # 1 if RX FIFO is empty
+RX_EMPTY = const(0x01) # 1 if RX FIFO is empty
# constants for instructions
-R_RX_PL_WID = const(0x60) # read RX payload width
-R_RX_PAYLOAD = const(0x61) # read RX payload
-W_TX_PAYLOAD = const(0xa0) # write TX payload
-FLUSH_TX = const(0xe1) # flush TX FIFO
-FLUSH_RX = const(0xe2) # flush RX FIFO
-NOP = const(0xff) # use to read STATUS register
+R_RX_PL_WID = const(0x60) # read RX payload width
+R_RX_PAYLOAD = const(0x61) # read RX payload
+W_TX_PAYLOAD = const(0xA0) # write TX payload
+FLUSH_TX = const(0xE1) # flush TX FIFO
+FLUSH_RX = const(0xE2) # flush RX FIFO
+NOP = const(0xFF) # use to read STATUS register
+
class NRF24L01:
def __init__(self, spi, cs, ce, channel=46, payload_size=16):
@@ -84,7 +85,7 @@ def __init__(self, spi, cs, ce, channel=46, payload_size=16):
self.reg_write(SETUP_RETR, (6 << 4) | 8)
# set rf power and speed
- self.set_power_speed(POWER_3, SPEED_250K) # Best for point to point links
+ self.set_power_speed(POWER_3, SPEED_250K) # Best for point to point links
# init CRC
self.set_crc(2)
@@ -218,7 +219,7 @@ def send(self, buf, timeout=500):
start = utime.ticks_ms()
result = None
while result is None and utime.ticks_diff(utime.ticks_ms(), start) < timeout:
- result = self.send_done() # 1 == success, 2 == fail
+ result = self.send_done() # 1 == success, 2 == fail
if result == 2:
raise OSError("send failed")
@@ -232,18 +233,18 @@ def send_start(self, buf):
self.spi.readinto(self.buf, W_TX_PAYLOAD)
self.spi.write(buf)
if len(buf) < self.payload_size:
- self.spi.write(b'\x00' * (self.payload_size - len(buf))) # pad out data
+ self.spi.write(b"\x00" * (self.payload_size - len(buf))) # pad out data
self.cs(1)
# enable the chip so it can send the data
self.ce(1)
- utime.sleep_us(15) # needs to be >10us
+ utime.sleep_us(15) # needs to be >10us
self.ce(0)
# returns None if send still in progress, 1 for success, 2 for fail
def send_done(self):
if not (self.reg_read(STATUS) & (TX_DS | MAX_RT)):
- return None # tx not finished
+ return None # tx not finished
# either finished or failed: get and clear status flags, power down
status = self.reg_write(STATUS, RX_DR | TX_DS | MAX_RT)
diff --git a/drivers/nrf24l01/nrf24l01test.py b/drivers/nrf24l01/nrf24l01test.py
index 876b2bbfa2..14efbffd2a 100644
--- a/drivers/nrf24l01/nrf24l01test.py
+++ b/drivers/nrf24l01/nrf24l01test.py
@@ -14,25 +14,28 @@
# master may be a slow device. Value tested with Pyboard, ESP32 and ESP8266.
_SLAVE_SEND_DELAY = const(10)
-if sys.platform == 'pyboard':
- cfg = {'spi': 2, 'miso': 'Y7', 'mosi': 'Y8', 'sck': 'Y6', 'csn': 'Y5', 'ce': 'Y4'}
-elif sys.platform == 'esp8266': # Hardware SPI
- cfg = {'spi': 1, 'miso': 12, 'mosi': 13, 'sck': 14, 'csn': 4, 'ce': 5}
-elif sys.platform == 'esp32': # Software SPI
- cfg = {'spi': -1, 'miso': 32, 'mosi': 33, 'sck': 25, 'csn': 26, 'ce': 27}
+if sys.platform == "pyboard":
+ cfg = {"spi": 2, "miso": "Y7", "mosi": "Y8", "sck": "Y6", "csn": "Y5", "ce": "Y4"}
+elif sys.platform == "esp8266": # Hardware SPI
+ cfg = {"spi": 1, "miso": 12, "mosi": 13, "sck": 14, "csn": 4, "ce": 5}
+elif sys.platform == "esp32": # Software SPI
+ cfg = {"spi": -1, "miso": 32, "mosi": 33, "sck": 25, "csn": 26, "ce": 27}
else:
- raise ValueError('Unsupported platform {}'.format(sys.platform))
+ raise ValueError("Unsupported platform {}".format(sys.platform))
+
+# Addresses are in little-endian format. They correspond to big-endian
+# 0xf0f0f0f0e1, 0xf0f0f0f0d2
+pipes = (b"\xe1\xf0\xf0\xf0\xf0", b"\xd2\xf0\xf0\xf0\xf0")
-pipes = (b'\xf0\xf0\xf0\xf0\xe1', b'\xf0\xf0\xf0\xf0\xd2')
def master():
- csn = Pin(cfg['csn'], mode=Pin.OUT, value=1)
- ce = Pin(cfg['ce'], mode=Pin.OUT, value=0)
- if cfg['spi'] == -1:
- spi = SPI(-1, sck=Pin(cfg['sck']), mosi=Pin(cfg['mosi']), miso=Pin(cfg['miso']))
+ csn = Pin(cfg["csn"], mode=Pin.OUT, value=1)
+ ce = Pin(cfg["ce"], mode=Pin.OUT, value=0)
+ if cfg["spi"] == -1:
+ spi = SPI(-1, sck=Pin(cfg["sck"]), mosi=Pin(cfg["mosi"]), miso=Pin(cfg["miso"]))
nrf = NRF24L01(spi, csn, ce, payload_size=8)
else:
- nrf = NRF24L01(SPI(cfg['spi']), csn, ce, payload_size=8)
+ nrf = NRF24L01(SPI(cfg["spi"]), csn, ce, payload_size=8)
nrf.open_tx_pipe(pipes[0])
nrf.open_rx_pipe(1, pipes[1])
@@ -43,16 +46,16 @@ def master():
num_failures = 0
led_state = 0
- print('NRF24L01 master mode, sending %d packets...' % num_needed)
+ print("NRF24L01 master mode, sending %d packets..." % num_needed)
while num_successes < num_needed and num_failures < num_needed:
# stop listening and send packet
nrf.stop_listening()
millis = utime.ticks_ms()
- led_state = max(1, (led_state << 1) & 0x0f)
- print('sending:', millis, led_state)
+ led_state = max(1, (led_state << 1) & 0x0F)
+ print("sending:", millis, led_state)
try:
- nrf.send(struct.pack('ii', millis, led_state))
+ nrf.send(struct.pack("ii", millis, led_state))
except OSError:
pass
@@ -67,43 +70,50 @@ def master():
timeout = True
if timeout:
- print('failed, response timed out')
+ print("failed, response timed out")
num_failures += 1
else:
# recv packet
- got_millis, = struct.unpack('i', nrf.recv())
+ (got_millis,) = struct.unpack("i", nrf.recv())
# print response and round-trip delay
- print('got response:', got_millis, '(delay', utime.ticks_diff(utime.ticks_ms(), got_millis), 'ms)')
+ print(
+ "got response:",
+ got_millis,
+ "(delay",
+ utime.ticks_diff(utime.ticks_ms(), got_millis),
+ "ms)",
+ )
num_successes += 1
# delay then loop
utime.sleep_ms(250)
- print('master finished sending; successes=%d, failures=%d' % (num_successes, num_failures))
+ print("master finished sending; successes=%d, failures=%d" % (num_successes, num_failures))
+
def slave():
- csn = Pin(cfg['csn'], mode=Pin.OUT, value=1)
- ce = Pin(cfg['ce'], mode=Pin.OUT, value=0)
- if cfg['spi'] == -1:
- spi = SPI(-1, sck=Pin(cfg['sck']), mosi=Pin(cfg['mosi']), miso=Pin(cfg['miso']))
+ csn = Pin(cfg["csn"], mode=Pin.OUT, value=1)
+ ce = Pin(cfg["ce"], mode=Pin.OUT, value=0)
+ if cfg["spi"] == -1:
+ spi = SPI(-1, sck=Pin(cfg["sck"]), mosi=Pin(cfg["mosi"]), miso=Pin(cfg["miso"]))
nrf = NRF24L01(spi, csn, ce, payload_size=8)
else:
- nrf = NRF24L01(SPI(cfg['spi']), csn, ce, payload_size=8)
+ nrf = NRF24L01(SPI(cfg["spi"]), csn, ce, payload_size=8)
nrf.open_tx_pipe(pipes[1])
nrf.open_rx_pipe(1, pipes[0])
nrf.start_listening()
- print('NRF24L01 slave mode, waiting for packets... (ctrl-C to stop)')
+ print("NRF24L01 slave mode, waiting for packets... (ctrl-C to stop)")
while True:
if nrf.any():
while nrf.any():
buf = nrf.recv()
- millis, led_state = struct.unpack('ii', buf)
- print('received:', millis, led_state)
+ millis, led_state = struct.unpack("ii", buf)
+ print("received:", millis, led_state)
for led in leds:
if led_state & 1:
led.on()
@@ -116,23 +126,25 @@ def slave():
utime.sleep_ms(_SLAVE_SEND_DELAY)
nrf.stop_listening()
try:
- nrf.send(struct.pack('i', millis))
+ nrf.send(struct.pack("i", millis))
except OSError:
pass
- print('sent response')
+ print("sent response")
nrf.start_listening()
+
try:
import pyb
+
leds = [pyb.LED(i + 1) for i in range(4)]
except:
leds = []
-print('NRF24L01 test module loaded')
-print('NRF24L01 pinout for test:')
-print(' CE on', cfg['ce'])
-print(' CSN on', cfg['csn'])
-print(' SCK on', cfg['sck'])
-print(' MISO on', cfg['miso'])
-print(' MOSI on', cfg['mosi'])
-print('run nrf24l01test.slave() on slave, then nrf24l01test.master() on master')
+print("NRF24L01 test module loaded")
+print("NRF24L01 pinout for test:")
+print(" CE on", cfg["ce"])
+print(" CSN on", cfg["csn"])
+print(" SCK on", cfg["sck"])
+print(" MISO on", cfg["miso"])
+print(" MOSI on", cfg["mosi"])
+print("run nrf24l01test.slave() on slave, then nrf24l01test.master() on master")
diff --git a/drivers/onewire/ds18x20.py b/drivers/onewire/ds18x20.py
index bf06094835..ad2d9f52cd 100644
--- a/drivers/onewire/ds18x20.py
+++ b/drivers/onewire/ds18x20.py
@@ -4,8 +4,9 @@
from micropython import const
_CONVERT = const(0x44)
-_RD_SCRATCH = const(0xbe)
-_WR_SCRATCH = const(0x4e)
+_RD_SCRATCH = const(0xBE)
+_WR_SCRATCH = const(0x4E)
+
class DS18X20:
def __init__(self, onewire):
@@ -13,7 +14,7 @@ def __init__(self, onewire):
self.buf = bytearray(9)
def scan(self):
- return [rom for rom in self.ow.scan() if rom[0] == 0x10 or rom[0] == 0x28]
+ return [rom for rom in self.ow.scan() if rom[0] in (0x10, 0x22, 0x28)]
def convert_temp(self):
self.ow.reset(True)
@@ -26,7 +27,7 @@ def read_scratch(self, rom):
self.ow.writebyte(_RD_SCRATCH)
self.ow.readinto(self.buf)
if self.ow.crc8(self.buf):
- raise Exception('CRC error')
+ raise Exception("CRC error")
return self.buf
def write_scratch(self, rom, buf):
@@ -40,12 +41,12 @@ def read_temp(self, rom):
if rom[0] == 0x10:
if buf[1]:
t = buf[0] >> 1 | 0x80
- t = -((~t + 1) & 0xff)
+ t = -((~t + 1) & 0xFF)
else:
t = buf[0] >> 1
return t - 0.25 + (buf[7] - buf[6]) / buf[7]
else:
t = buf[1] << 8 | buf[0]
- if t & 0x8000: # sign bit set
- t = -((t ^ 0xffff) + 1)
+ if t & 0x8000: # sign bit set
+ t = -((t ^ 0xFFFF) + 1)
return t / 16
diff --git a/drivers/onewire/onewire.py b/drivers/onewire/onewire.py
index 3309ba0d27..4c6da741c7 100644
--- a/drivers/onewire/onewire.py
+++ b/drivers/onewire/onewire.py
@@ -1,16 +1,17 @@
# 1-Wire driver for MicroPython
# MIT license; Copyright (c) 2016 Damien P. George
-from micropython import const
import _onewire as _ow
+
class OneWireError(Exception):
pass
+
class OneWire:
- SEARCH_ROM = const(0xf0)
- MATCH_ROM = const(0x55)
- SKIP_ROM = const(0xcc)
+ SEARCH_ROM = 0xF0
+ MATCH_ROM = 0x55
+ SKIP_ROM = 0xCC
def __init__(self, pin):
self.pin = pin
@@ -44,14 +45,14 @@ def write(self, buf):
def select_rom(self, rom):
self.reset()
- self.writebyte(MATCH_ROM)
+ self.writebyte(self.MATCH_ROM)
self.write(rom)
def scan(self):
devices = []
diff = 65
rom = False
- for i in range(0xff):
+ for i in range(0xFF):
rom, diff = self._search_rom(rom, diff)
if rom:
devices += [rom]
@@ -62,7 +63,7 @@ def scan(self):
def _search_rom(self, l_rom, diff):
if not self.reset():
return None, 0
- self.writebyte(SEARCH_ROM)
+ self.writebyte(self.SEARCH_ROM)
if not l_rom:
l_rom = bytearray(8)
rom = bytearray(8)
@@ -73,10 +74,10 @@ def _search_rom(self, l_rom, diff):
for bit in range(8):
b = self.readbit()
if self.readbit():
- if b: # there are no devices or there is an error on the bus
+ if b: # there are no devices or there is an error on the bus
return None, 0
else:
- if not b: # collision, two devices with different bit meaning
+ if not b: # collision, two devices with different bit meaning
if diff > i or ((l_rom[byte] & (1 << bit)) and diff != i):
b = 1
next_diff = i
diff --git a/drivers/sdcard/sdcard.py b/drivers/sdcard/sdcard.py
index 8f28b476e2..c991fe5608 100644
--- a/drivers/sdcard/sdcard.py
+++ b/drivers/sdcard/sdcard.py
@@ -27,15 +27,15 @@
_CMD_TIMEOUT = const(100)
_R1_IDLE_STATE = const(1 << 0)
-#R1_ERASE_RESET = const(1 << 1)
+# R1_ERASE_RESET = const(1 << 1)
_R1_ILLEGAL_COMMAND = const(1 << 2)
-#R1_COM_CRC_ERROR = const(1 << 3)
-#R1_ERASE_SEQUENCE_ERROR = const(1 << 4)
-#R1_ADDRESS_ERROR = const(1 << 5)
-#R1_PARAMETER_ERROR = const(1 << 6)
-_TOKEN_CMD25 = const(0xfc)
-_TOKEN_STOP_TRAN = const(0xfd)
-_TOKEN_DATA = const(0xfe)
+# R1_COM_CRC_ERROR = const(1 << 3)
+# R1_ERASE_SEQUENCE_ERROR = const(1 << 4)
+# R1_ADDRESS_ERROR = const(1 << 5)
+# R1_PARAMETER_ERROR = const(1 << 6)
+_TOKEN_CMD25 = const(0xFC)
+_TOKEN_STOP_TRAN = const(0xFD)
+_TOKEN_DATA = const(0xFE)
class SDCard:
@@ -47,7 +47,7 @@ def __init__(self, spi, cs):
self.dummybuf = bytearray(512)
self.tokenbuf = bytearray(1)
for i in range(512):
- self.dummybuf[i] = 0xff
+ self.dummybuf[i] = 0xFF
self.dummybuf_memoryview = memoryview(self.dummybuf)
# initialise the card
@@ -72,7 +72,7 @@ def init_card(self):
# clock card at least 100 cycles with cs high
for i in range(16):
- self.spi.write(b'\xff')
+ self.spi.write(b"\xff")
# CMD0: init card; should return _R1_IDLE_STATE (allow 5 attempts)
for _ in range(5):
@@ -82,7 +82,7 @@ def init_card(self):
raise OSError("no SD card")
# CMD8: determine card version
- r = self.cmd(8, 0x01aa, 0x87, 4)
+ r = self.cmd(8, 0x01AA, 0x87, 4)
if r == _R1_IDLE_STATE:
self.init_card_v2()
elif r == (_R1_IDLE_STATE | _R1_ILLEGAL_COMMAND):
@@ -96,15 +96,15 @@ def init_card(self):
raise OSError("no response from SD card")
csd = bytearray(16)
self.readinto(csd)
- if csd[0] & 0xc0 == 0x40: # CSD version 2.0
- self.sectors = ((csd[8] << 8 | csd[9]) + 1) * 2014
- elif csd[0] & 0xc0 == 0x00: # CSD version 1.0 (old, <=2GB)
+ if csd[0] & 0xC0 == 0x40: # CSD version 2.0
+ self.sectors = ((csd[8] << 8 | csd[9]) + 1) * 1024
+ elif csd[0] & 0xC0 == 0x00: # CSD version 1.0 (old, <=2GB)
c_size = csd[6] & 0b11 | csd[7] << 2 | (csd[8] & 0b11000000) << 4
c_size_mult = ((csd[9] & 0b11) << 1) | csd[10] >> 7
self.sectors = (c_size + 1) * (2 ** (c_size_mult + 2))
else:
raise OSError("SD card CSD format not supported")
- #print('sectors', self.sectors)
+ # print('sectors', self.sectors)
# CMD16: set block length to 512 bytes
if self.cmd(16, 512, 0) != 0:
@@ -118,7 +118,7 @@ def init_card_v1(self):
self.cmd(55, 0, 0)
if self.cmd(41, 0, 0) == 0:
self.cdv = 512
- #print("[SDCard] v1 card")
+ # print("[SDCard] v1 card")
return
raise OSError("timeout waiting for v1 card")
@@ -130,7 +130,7 @@ def init_card_v2(self):
if self.cmd(41, 0x40000000, 0) == 0:
self.cmd(58, 0, 0, 4)
self.cdv = 1
- #print("[SDCard] v2 card")
+ # print("[SDCard] v2 card")
return
raise OSError("timeout waiting for v2 card")
@@ -148,47 +148,50 @@ def cmd(self, cmd, arg, crc, final=0, release=True, skip1=False):
self.spi.write(buf)
if skip1:
- self.spi.readinto(self.tokenbuf, 0xff)
+ self.spi.readinto(self.tokenbuf, 0xFF)
# wait for the response (response[7] == 0)
for i in range(_CMD_TIMEOUT):
- self.spi.readinto(self.tokenbuf, 0xff)
+ self.spi.readinto(self.tokenbuf, 0xFF)
response = self.tokenbuf[0]
if not (response & 0x80):
# this could be a big-endian integer that we are getting here
for j in range(final):
- self.spi.write(b'\xff')
+ self.spi.write(b"\xff")
if release:
self.cs(1)
- self.spi.write(b'\xff')
+ self.spi.write(b"\xff")
return response
# timeout
self.cs(1)
- self.spi.write(b'\xff')
+ self.spi.write(b"\xff")
return -1
def readinto(self, buf):
self.cs(0)
# read until start byte (0xff)
- while True:
- self.spi.readinto(self.tokenbuf, 0xff)
- if self.tokenbuf[0] == 0xfe:
+ for i in range(_CMD_TIMEOUT):
+ self.spi.readinto(self.tokenbuf, 0xFF)
+ if self.tokenbuf[0] == _TOKEN_DATA:
break
+ else:
+ self.cs(1)
+ raise OSError("timeout waiting for response")
# read data
mv = self.dummybuf_memoryview
if len(buf) != len(mv):
- mv = mv[:len(buf)]
+ mv = mv[: len(buf)]
self.spi.write_readinto(mv, buf)
# read checksum
- self.spi.write(b'\xff')
- self.spi.write(b'\xff')
+ self.spi.write(b"\xff")
+ self.spi.write(b"\xff")
self.cs(1)
- self.spi.write(b'\xff')
+ self.spi.write(b"\xff")
def write(self, token, buf):
self.cs(0)
@@ -196,72 +199,74 @@ def write(self, token, buf):
# send: start of block, data, checksum
self.spi.read(1, token)
self.spi.write(buf)
- self.spi.write(b'\xff')
- self.spi.write(b'\xff')
+ self.spi.write(b"\xff")
+ self.spi.write(b"\xff")
# check the response
- if (self.spi.read(1, 0xff)[0] & 0x1f) != 0x05:
+ if (self.spi.read(1, 0xFF)[0] & 0x1F) != 0x05:
self.cs(1)
- self.spi.write(b'\xff')
+ self.spi.write(b"\xff")
return
# wait for write to finish
- while self.spi.read(1, 0xff)[0] == 0:
+ while self.spi.read(1, 0xFF)[0] == 0:
pass
self.cs(1)
- self.spi.write(b'\xff')
+ self.spi.write(b"\xff")
def write_token(self, token):
self.cs(0)
self.spi.read(1, token)
- self.spi.write(b'\xff')
+ self.spi.write(b"\xff")
# wait for write to finish
- while self.spi.read(1, 0xff)[0] == 0x00:
+ while self.spi.read(1, 0xFF)[0] == 0x00:
pass
self.cs(1)
- self.spi.write(b'\xff')
-
- def count(self):
- return self.sectors
+ self.spi.write(b"\xff")
def readblocks(self, block_num, buf):
nblocks = len(buf) // 512
- assert nblocks and not len(buf) % 512, 'Buffer length is invalid'
+ assert nblocks and not len(buf) % 512, "Buffer length is invalid"
if nblocks == 1:
# CMD17: set read address for single block
- if self.cmd(17, block_num * self.cdv, 0) != 0:
- raise OSError(5) # EIO
- # receive the data
+ if self.cmd(17, block_num * self.cdv, 0, release=False) != 0:
+ # release the card
+ self.cs(1)
+ raise OSError(5) # EIO
+ # receive the data and release card
self.readinto(buf)
else:
# CMD18: set read address for multiple blocks
- if self.cmd(18, block_num * self.cdv, 0) != 0:
- raise OSError(5) # EIO
+ if self.cmd(18, block_num * self.cdv, 0, release=False) != 0:
+ # release the card
+ self.cs(1)
+ raise OSError(5) # EIO
offset = 0
mv = memoryview(buf)
while nblocks:
+ # receive the data and release card
self.readinto(mv[offset : offset + 512])
offset += 512
nblocks -= 1
- if self.cmd(12, 0, 0xff, skip1=True):
- raise OSError(5) # EIO
+ if self.cmd(12, 0, 0xFF, skip1=True):
+ raise OSError(5) # EIO
def writeblocks(self, block_num, buf):
nblocks, err = divmod(len(buf), 512)
- assert nblocks and not err, 'Buffer length is invalid'
+ assert nblocks and not err, "Buffer length is invalid"
if nblocks == 1:
# CMD24: set write address for single block
if self.cmd(24, block_num * self.cdv, 0) != 0:
- raise OSError(5) # EIO
+ raise OSError(5) # EIO
# send the data
self.write(_TOKEN_DATA, buf)
else:
# CMD25: set write address for first block
if self.cmd(25, block_num * self.cdv, 0) != 0:
- raise OSError(5) # EIO
+ raise OSError(5) # EIO
# send the data
offset = 0
mv = memoryview(buf)
@@ -270,3 +275,7 @@ def writeblocks(self, block_num, buf):
offset += 512
nblocks -= 1
self.write_token(_TOKEN_STOP_TRAN)
+
+ def ioctl(self, op, arg):
+ if op == 4: # get number of blocks
+ return self.sectors
diff --git a/drivers/sdcard/sdtest.py b/drivers/sdcard/sdtest.py
index 438baa245d..018ef7c64a 100644
--- a/drivers/sdcard/sdtest.py
+++ b/drivers/sdcard/sdtest.py
@@ -1,57 +1,61 @@
# Test for sdcard block protocol
# Peter hinch 30th Jan 2016
-import os, sdcard, pyb
+import os, sdcard, machine
-def sdtest():
- sd = sdcard.SDCard(pyb.SPI(1), pyb.Pin.board.X21) # Compatible with PCB
- pyb.mount(sd, '/fc')
- print('Filesystem check')
- print(os.listdir('/fc'))
-
- line = 'abcdefghijklmnopqrstuvwxyz\n'
- lines = line * 200 # 5400 chars
- short = '1234567890\n'
- fn = '/fc/rats.txt'
+def sdtest():
+ spi = machine.SPI(1)
+ spi.init() # Ensure right baudrate
+ sd = sdcard.SDCard(spi, machine.Pin.board.X21) # Compatible with PCB
+ vfs = os.VfsFat(sd)
+ os.mount(vfs, "/fc")
+ print("Filesystem check")
+ print(os.listdir("/fc"))
+
+ line = "abcdefghijklmnopqrstuvwxyz\n"
+ lines = line * 200 # 5400 chars
+ short = "1234567890\n"
+
+ fn = "/fc/rats.txt"
print()
- print('Multiple block read/write')
- with open(fn,'w') as f:
+ print("Multiple block read/write")
+ with open(fn, "w") as f:
n = f.write(lines)
- print(n, 'bytes written')
+ print(n, "bytes written")
n = f.write(short)
- print(n, 'bytes written')
+ print(n, "bytes written")
n = f.write(lines)
- print(n, 'bytes written')
+ print(n, "bytes written")
- with open(fn,'r') as f:
+ with open(fn, "r") as f:
result1 = f.read()
- print(len(result1), 'bytes read')
+ print(len(result1), "bytes read")
- fn = '/fc/rats1.txt'
+ fn = "/fc/rats1.txt"
print()
- print('Single block read/write')
- with open(fn,'w') as f:
- n = f.write(short) # one block
- print(n, 'bytes written')
+ print("Single block read/write")
+ with open(fn, "w") as f:
+ n = f.write(short) # one block
+ print(n, "bytes written")
- with open(fn,'r') as f:
+ with open(fn, "r") as f:
result2 = f.read()
- print(len(result2), 'bytes read')
+ print(len(result2), "bytes read")
- pyb.mount(None, '/fc')
+ os.umount("/fc")
print()
- print('Verifying data read back')
+ print("Verifying data read back")
success = True
- if result1 == ''.join((lines, short, lines)):
- print('Large file Pass')
+ if result1 == "".join((lines, short, lines)):
+ print("Large file Pass")
else:
- print('Large file Fail')
+ print("Large file Fail")
success = False
if result2 == short:
- print('Small file Pass')
+ print("Small file Pass")
else:
- print('Small file Fail')
+ print("Small file Fail")
success = False
print()
- print('Tests', 'passed' if success else 'failed')
+ print("Tests", "passed" if success else "failed")
diff --git a/drivers/sx127x/radio.h b/drivers/sx127x/radio.h
index 0202ae51a0..b9e926f813 100644
--- a/drivers/sx127x/radio.h
+++ b/drivers/sx127x/radio.h
@@ -1,20 +1,36 @@
-/*
- / _____) _ | |
-( (____ _____ ____ _| |_ _____ ____| |__
- \____ \| ___ | (_ _) ___ |/ ___) _ \
- _____) ) ____| | | || |_| ____( (___| | | |
-(______/|_____)_|_|_| \__)_____)\____)_| |_|
- (C)2013 Semtech
-
-Description: Generic radio driver definition
-
-License: Revised BSD License, see LICENSE.TXT file include in the project
-
-Maintainer: Miguel Luis and Gregory Cristian
-*/
+/*!
+ * \file radio.h
+ *
+ * \brief Radio driver API definition
+ *
+ * \copyright Revised BSD License, see section \ref LICENSE.
+ *
+ * \code
+ * ______ _
+ * / _____) _ | |
+ * ( (____ _____ ____ _| |_ _____ ____| |__
+ * \____ \| ___ | (_ _) ___ |/ ___) _ \
+ * _____) ) ____| | | || |_| ____( (___| | | |
+ * (______/|_____)_|_|_| \__)_____)\____)_| |_|
+ * (C)2013-2017 Semtech
+ *
+ * \endcode
+ *
+ * \author Miguel Luis ( Semtech )
+ *
+ * \author Gregory Cristian ( Semtech )
+ */
#ifndef __RADIO_H__
#define __RADIO_H__
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+// #include
+// #include
+
#define RADIO_IRQ_FLAG_RX_TIMEOUT ( 0x01 )
#define RADIO_IRQ_FLAG_RX_DONE ( 0x02 )
#define RADIO_IRQ_FLAG_RX_ERROR ( 0x04 )
@@ -59,7 +75,7 @@ typedef struct
* \param [IN] size Received buffer size
* \param [IN] timestamp timestamp of the packet in us
* \param [IN] rssi RSSI value computed while receiving the frame [dBm]
- * \param [IN] snr Raw SNR value given by the radio hardware
+ * \param [IN] snr SNR value computed while receiving the frame [dB]
* FSK : N/A ( set to 0 )
* LoRa: SNR value in dB
* \param [IN] sf Spreading factor of the packet received (6 - 12)
@@ -297,14 +313,14 @@ struct Radio_s
* \param [IN]: addr Register address
* \param [IN]: data New register value
*/
- void ( *Write )( uint8_t addr, uint8_t data );
+ void ( *Write )( uint16_t addr, uint8_t data );
/*!
* \brief Reads the radio register at the specified address
*
* \param [IN]: addr Register address
* \retval data Register value
*/
- uint8_t ( *Read )( uint8_t addr );
+ uint8_t ( *Read )( uint16_t addr );
/*!
* \brief Writes multiple radio registers starting at address
*
@@ -312,7 +328,7 @@ struct Radio_s
* \param [IN] buffer Buffer containing the new register's values
* \param [IN] size Number of registers to be written
*/
- void ( *WriteBuffer )( uint8_t addr, uint8_t *buffer, uint8_t size );
+ void ( *WriteBuffer )( uint16_t addr, uint8_t *buffer, uint8_t size );
/*!
* \brief Reads multiple radio registers starting at address
*
@@ -320,7 +336,7 @@ struct Radio_s
* \param [OUT] buffer Buffer where to copy the registers data
* \param [IN] size Number of registers to be read
*/
- void ( *ReadBuffer )( uint8_t addr, uint8_t *buffer, uint8_t size );
+ void ( *ReadBuffer )( uint16_t addr, uint8_t *buffer, uint8_t size );
/*!
* \brief Sets the maximum payload length.
*
@@ -340,6 +356,37 @@ struct Radio_s
* \brief Manually resets Lora chip.
*/
void ( *Reset )( void );
+ /*!
+ * \brief Gets the time required for the board plus radio to get out of sleep.[ms]
+ *
+ * \retval time Radio plus board wakeup time in ms.
+ */
+ uint32_t ( *GetWakeupTime )( void );
+ /*!
+ * \brief Process radio irq
+ */
+ void ( *IrqProcess )( void );
+ /*
+ * The next functions are available only on SX126x radios.
+ */
+ /*!
+ * \brief Sets the radio in reception mode with Max LNA gain for the given time
+ *
+ * \remark Available on SX126x radios only.
+ *
+ * \param [IN] timeout Reception timeout [ms]
+ * [0: continuous, others timeout]
+ */
+ void ( *RxBoosted )( uint32_t timeout );
+ /*!
+ * \brief Sets the Rx duty cycle management parameters
+ *
+ * \remark Available on SX126x radios only.
+ *
+ * \param [in] rxTime Structure describing reception timeout value
+ * \param [in] sleepTime Structure describing sleep timeout value
+ */
+ void ( *SetRxDutyCycle ) ( uint32_t rxTime, uint32_t sleepTime );
};
/*!
@@ -350,4 +397,8 @@ struct Radio_s
*/
extern const struct Radio_s Radio;
+#ifdef __cplusplus
+}
+#endif
+
#endif // __RADIO_H__
diff --git a/drivers/sx127x/sx1272/sx1272.c b/drivers/sx127x/sx1272/sx1272.c
index b78bae1465..478c712d76 100644
--- a/drivers/sx127x/sx1272/sx1272.c
+++ b/drivers/sx127x/sx1272/sx1272.c
@@ -11,25 +11,35 @@
* This file contains code under the following copyright and licensing notices.
* The code has been changed but otherwise retained.
*/
-
-/*
- / _____) _ | |
-( (____ _____ ____ _| |_ _____ ____| |__
- \____ \| ___ | (_ _) ___ |/ ___) _ \
- _____) ) ____| | | || |_| ____( (___| | | |
-(______/|_____)_|_|_| \__)_____)\____)_| |_|
- (C)2013 Semtech
-
-Description: Generic SX1272 driver implementation
-
-License: Revised BSD License, see LICENSE.TXT file include in the project
-
-Maintainer: Miguel Luis and Gregory Cristian
-*/
+/*!
+ * \file sx1272.c
+ *
+ * \brief SX1272 driver implementation
+ *
+ * \copyright Revised BSD License, see section \ref LICENSE.
+ *
+ * \code
+ * ______ _
+ * / _____) _ | |
+ * ( (____ _____ ____ _| |_ _____ ____| |__
+ * \____ \| ___ | (_ _) ___ |/ ___) _ \
+ * _____) ) ____| | | || |_| ____( (___| | | |
+ * (______/|_____)_|_|_| \__)_____)\____)_| |_|
+ * (C)2013-2017 Semtech
+ *
+ * \endcode
+ *
+ * \author Miguel Luis ( Semtech )
+ *
+ * \author Gregory Cristian ( Semtech )
+ */
#include
#include
#include "board.h"
+#include "lora/utilities.h"
+#include "lora/system/timer.h"
#include "radio.h"
+#include "lora/system/delay.h"
#include "sx1272.h"
#include "sx1272-board.h"
#include "esp_attr.h"
@@ -49,6 +59,15 @@ typedef struct
uint8_t Value;
}RadioRegisters_t;
+/*!
+ * FSK bandwidth definition
+ */
+typedef struct
+{
+ uint32_t bandwidth;
+ uint8_t RegValue;
+}FskBandwidth_t;
+
/*
* Private functions prototypes
@@ -77,6 +96,13 @@ void SX1272WriteFifo( uint8_t *buffer, uint8_t size );
*/
void SX1272ReadFifo( uint8_t *buffer, uint8_t size );
+/*!
+ * \brief Sets the SX1272 operating mode
+ *
+ * \param [IN] opMode New operating mode
+ */
+void SX1272SetOpMode( uint8_t opMode );
+
/*
* SX1272 DIO IRQ callback functions prototype
*/
@@ -84,47 +110,47 @@ void SX1272ReadFifo( uint8_t *buffer, uint8_t size );
/*!
* \brief Common DIO IRQ callback
*/
-static void SX1272OnDioIrq (void);
+static void SX1272OnDioIrq (void *context);
/*!
* \brief DIO 0 IRQ callback
*/
-void SX1272OnDio0Irq( void );
+void SX1272OnDio0Irq( void* context );
/*!
* \brief DIO 1 IRQ callback
*/
-void SX1272OnDio1Irq( void );
+void SX1272OnDio1Irq( void* context );
/*!
* \brief DIO 2 IRQ callback
*/
-void SX1272OnDio2Irq( void );
+void SX1272OnDio2Irq( void* context );
/*!
* \brief DIO 3 IRQ callback
*/
-void SX1272OnDio3Irq( void );
+void SX1272OnDio3Irq( void* context );
/*!
* \brief DIO 4 IRQ callback
*/
-void SX1272OnDio4Irq( void );
+void SX1272OnDio4Irq( void* context );
/*!
* \brief DIO 5 IRQ callback
*/
-void SX1272OnDio5Irq( void );
+void SX1272OnDio5Irq( void* context );
/*!
* \brief Tx & Rx timeout timer callback
*/
-void SX1272OnTimeoutIrq( void );
+void SX1272OnTimeoutIrq( void* context );
/*!
* \brief General radio flags check callback
*/
-void SX1272RadioFlagsIrq (void);
+void SX1272RadioFlagsIrq (void *context);
/*
* Private global constants
@@ -142,6 +168,35 @@ const RadioRegisters_t RadioRegsInit[] = RADIO_INIT_REGISTERS_VALUE;
*/
#define RSSI_OFFSET -139
+/*!
+ * Precomputed FSK bandwidth registers values
+ */
+const FskBandwidth_t FskBandwidths[] =
+{
+ { 2600 , 0x17 },
+ { 3100 , 0x0F },
+ { 3900 , 0x07 },
+ { 5200 , 0x16 },
+ { 6300 , 0x0E },
+ { 7800 , 0x06 },
+ { 10400 , 0x15 },
+ { 12500 , 0x0D },
+ { 15600 , 0x05 },
+ { 20800 , 0x14 },
+ { 25000 , 0x0C },
+ { 31300 , 0x04 },
+ { 41700 , 0x13 },
+ { 50000 , 0x0B },
+ { 62500 , 0x03 },
+ { 83333 , 0x12 },
+ { 100000, 0x0A },
+ { 125000, 0x02 },
+ { 166700, 0x11 },
+ { 200000, 0x09 },
+ { 250000, 0x01 },
+ { 300000, 0x00 }, // Invalid Bandwidth
+};
+
/*
* Private global variables
*/
@@ -176,6 +231,7 @@ DioIrqHandler *DioIrq[] = { SX1272OnDioIrq };
static TimerEvent_t TxTimeoutTimer;
static TimerEvent_t RxTimeoutTimer;
static TimerEvent_t RadioIrqFlagsTimer;
+static TimerEvent_t RxTimeoutSyncWord;
/*
* Radio driver functions implementation
@@ -193,6 +249,8 @@ void SX1272Init( RadioEvents_t *events )
TimerInit( &RadioIrqFlagsTimer, SX1272RadioFlagsIrq );
TimerSetValue( &RadioIrqFlagsTimer, 1 );
+ TimerInit( &RxTimeoutSyncWord, SX1272OnTimeoutIrq );
+
SX1272Reset( );
SX1272SetOpMode( RF_OPMODE_SLEEP );
@@ -234,6 +292,9 @@ bool SX1272IsChannelFree( RadioModems_t modem, uint32_t freq, int16_t rssiThresh
{
bool status = true;
int16_t rssi = 0;
+ uint32_t carrierSenseTime = 0;
+
+ SX1272SetSleep( );
SX1272SetModem( modem );
@@ -243,17 +304,19 @@ bool SX1272IsChannelFree( RadioModems_t modem, uint32_t freq, int16_t rssiThresh
DelayMs( 1 );
+ carrierSenseTime = TimerGetCurrentTime( );
+
// Perform carrier sense for maxCarrierSenseTime
- do {
+ while( TimerGetElapsedTime( carrierSenseTime ) < maxCarrierSenseTime )
+ {
rssi = SX1272ReadRssi( modem );
- if( rssi > rssiThresh ) {
+ if( rssi > rssiThresh )
+ {
status = false;
break;
}
- DelayMs( 1 );
- maxCarrierSenseTime -= 1;
- } while( maxCarrierSenseTime > 0 );
+ }
SX1272SetSleep( );
return status;
}
@@ -294,6 +357,27 @@ uint32_t SX1272Random( void )
return rnd;
}
+/*!
+ * Returns the known FSK bandwidth registers value
+ *
+ * \param [IN] bandwidth Bandwidth value in Hz
+ * \retval regValue Bandwidth register value.
+ */
+static uint8_t GetFskBandwidthRegValue( uint32_t bandwidth )
+{
+ uint8_t i;
+
+ for( i = 0; i < ( sizeof( FskBandwidths ) / sizeof( FskBandwidth_t ) ) - 1; i++ )
+ {
+ if( ( bandwidth >= FskBandwidths[i].bandwidth ) && ( bandwidth < FskBandwidths[i + 1].bandwidth ) )
+ {
+ return FskBandwidths[i].RegValue;
+ }
+ }
+ // ERROR: Value not found
+ while( 1 );
+}
+
IRAM_ATTR void SX1272SetRxConfig( RadioModems_t modem, uint32_t bandwidth,
uint32_t datarate, uint8_t coderate,
uint32_t bandwidthAfc, uint16_t preambleLen,
@@ -307,6 +391,45 @@ IRAM_ATTR void SX1272SetRxConfig( RadioModems_t modem, uint32_t bandwidth,
switch( modem )
{
case MODEM_FSK:
+ {
+ SX1272.Settings.Fsk.Bandwidth = bandwidth;
+ SX1272.Settings.Fsk.Datarate = datarate;
+ SX1272.Settings.Fsk.BandwidthAfc = bandwidthAfc;
+ SX1272.Settings.Fsk.FixLen = fixLen;
+ SX1272.Settings.Fsk.PayloadLen = payloadLen;
+ SX1272.Settings.Fsk.CrcOn = crcOn;
+ SX1272.Settings.Fsk.IqInverted = iqInverted;
+ SX1272.Settings.Fsk.RxContinuous = rxContinuous;
+ SX1272.Settings.Fsk.PreambleLen = preambleLen;
+ SX1272.Settings.Fsk.RxSingleTimeout = ( uint32_t )( symbTimeout * ( ( 1.0 / ( double )datarate ) * 8.0 ) * 1000 );
+
+ datarate = ( uint16_t )( ( double )XTAL_FREQ / ( double )datarate );
+ SX1272Write( REG_BITRATEMSB, ( uint8_t )( datarate >> 8 ) );
+ SX1272Write( REG_BITRATELSB, ( uint8_t )( datarate & 0xFF ) );
+
+ SX1272Write( REG_RXBW, GetFskBandwidthRegValue( bandwidth ) );
+ SX1272Write( REG_AFCBW, GetFskBandwidthRegValue( bandwidthAfc ) );
+
+ SX1272Write( REG_PREAMBLEMSB, ( uint8_t )( ( preambleLen >> 8 ) & 0xFF ) );
+ SX1272Write( REG_PREAMBLELSB, ( uint8_t )( preambleLen & 0xFF ) );
+
+ if( fixLen == 1 )
+ {
+ SX1272Write( REG_PAYLOADLENGTH, payloadLen );
+ }
+ else
+ {
+ SX1272Write( REG_PAYLOADLENGTH, 0xFF ); // Set payload length to the maximum
+ }
+
+ SX1272Write( REG_PACKETCONFIG1,
+ ( SX1272Read( REG_PACKETCONFIG1 ) &
+ RF_PACKETCONFIG1_CRC_MASK &
+ RF_PACKETCONFIG1_PACKETFORMAT_MASK ) |
+ ( ( fixLen == 1 ) ? RF_PACKETCONFIG1_PACKETFORMAT_FIXED : RF_PACKETCONFIG1_PACKETFORMAT_VARIABLE ) |
+ ( crcOn << 4 ) );
+ SX1272Write( REG_PACKETCONFIG2, ( SX1272Read( REG_PACKETCONFIG2 ) | RF_PACKETCONFIG2_DATAMODE_PACKET ) );
+ }
break;
case MODEM_LORA:
{
@@ -319,7 +442,7 @@ IRAM_ATTR void SX1272SetRxConfig( RadioModems_t modem, uint32_t bandwidth,
SX1272.Settings.LoRa.CrcOn = crcOn;
SX1272.Settings.LoRa.FreqHopOn = freqHopOn;
SX1272.Settings.LoRa.HopPeriod = hopPeriod;
- SX1272.Settings.LoRa.RxIqInverted = iqInverted;
+ SX1272.Settings.LoRa.IqInverted = iqInverted;
SX1272.Settings.LoRa.RxContinuous = rxContinuous;
if( datarate > 12 )
@@ -408,10 +531,39 @@ void SX1272SetTxConfig( RadioModems_t modem, int8_t power, uint32_t fdev,
SX1272SetRfTxPower( power );
-
switch( modem )
{
case MODEM_FSK:
+ {
+ SX1272.Settings.Fsk.Power = power;
+ SX1272.Settings.Fsk.Fdev = fdev;
+ SX1272.Settings.Fsk.Bandwidth = bandwidth;
+ SX1272.Settings.Fsk.Datarate = datarate;
+ SX1272.Settings.Fsk.PreambleLen = preambleLen;
+ SX1272.Settings.Fsk.FixLen = fixLen;
+ SX1272.Settings.Fsk.CrcOn = crcOn;
+ SX1272.Settings.Fsk.IqInverted = iqInverted;
+ SX1272.Settings.Fsk.TxTimeout = timeout;
+
+ fdev = ( uint16_t )( ( double )fdev / ( double )FREQ_STEP );
+ SX1272Write( REG_FDEVMSB, ( uint8_t )( fdev >> 8 ) );
+ SX1272Write( REG_FDEVLSB, ( uint8_t )( fdev & 0xFF ) );
+
+ datarate = ( uint16_t )( ( double )XTAL_FREQ / ( double )datarate );
+ SX1272Write( REG_BITRATEMSB, ( uint8_t )( datarate >> 8 ) );
+ SX1272Write( REG_BITRATELSB, ( uint8_t )( datarate & 0xFF ) );
+
+ SX1272Write( REG_PREAMBLEMSB, ( preambleLen >> 8 ) & 0x00FF );
+ SX1272Write( REG_PREAMBLELSB, preambleLen & 0xFF );
+
+ SX1272Write( REG_PACKETCONFIG1,
+ ( SX1272Read( REG_PACKETCONFIG1 ) &
+ RF_PACKETCONFIG1_CRC_MASK &
+ RF_PACKETCONFIG1_PACKETFORMAT_MASK ) |
+ ( ( fixLen == 1 ) ? RF_PACKETCONFIG1_PACKETFORMAT_FIXED : RF_PACKETCONFIG1_PACKETFORMAT_VARIABLE ) |
+ ( crcOn << 4 ) );
+ SX1272Write( REG_PACKETCONFIG2, ( SX1272Read( REG_PACKETCONFIG2 ) | RF_PACKETCONFIG2_DATAMODE_PACKET ) );
+ }
break;
case MODEM_LORA:
{
@@ -424,7 +576,7 @@ void SX1272SetTxConfig( RadioModems_t modem, int8_t power, uint32_t fdev,
SX1272.Settings.LoRa.FreqHopOn = freqHopOn;
SX1272.Settings.LoRa.HopPeriod = hopPeriod;
SX1272.Settings.LoRa.CrcOn = crcOn;
- SX1272.Settings.LoRa.TxIqInverted = iqInverted;
+ SX1272.Settings.LoRa.IqInverted = iqInverted;
SX1272.Settings.LoRa.TxTimeout = timeout;
if( datarate > 12 )
@@ -501,6 +653,15 @@ uint32_t SX1272GetTimeOnAir( RadioModems_t modem, uint8_t pktLen )
switch( modem )
{
case MODEM_FSK:
+ {
+ airTime = round( ( 8 * ( SX1272.Settings.Fsk.PreambleLen +
+ ( ( SX1272Read( REG_SYNCCONFIG ) & ~RF_SYNCCONFIG_SYNCSIZE_MASK ) + 1 ) +
+ ( ( SX1272.Settings.Fsk.FixLen == 0x01 ) ? 0.0 : 1.0 ) +
+ ( ( ( SX1272Read( REG_PACKETCONFIG1 ) & ~RF_PACKETCONFIG1_ADDRSFILTERING_MASK ) != 0x00 ) ? 1.0 : 0 ) +
+ pktLen +
+ ( ( SX1272.Settings.Fsk.CrcOn == 0x01 ) ? 2.0 : 0 ) ) /
+ SX1272.Settings.Fsk.Datarate ) * 1000 );
+ }
break;
case MODEM_LORA:
{
@@ -549,10 +710,38 @@ void SX1272Send( uint8_t *buffer, uint8_t size )
switch( SX1272.Settings.Modem )
{
case MODEM_FSK:
+ {
+ SX1272.Settings.FskPacketHandler.NbBytes = 0;
+ SX1272.Settings.FskPacketHandler.Size = size;
+
+ if( SX1272.Settings.Fsk.FixLen == false )
+ {
+ SX1272WriteFifo( ( uint8_t* )&size, 1 );
+ }
+ else
+ {
+ SX1272Write( REG_PAYLOADLENGTH, size );
+ }
+
+ if( ( size > 0 ) && ( size <= 64 ) )
+ {
+ SX1272.Settings.FskPacketHandler.ChunkSize = size;
+ }
+ else
+ {
+ memcpy1( RxTxBuffer, buffer, size );
+ SX1272.Settings.FskPacketHandler.ChunkSize = 32;
+ }
+
+ // Write payload buffer
+ SX1272WriteFifo( buffer, SX1272.Settings.FskPacketHandler.ChunkSize );
+ SX1272.Settings.FskPacketHandler.NbBytes += SX1272.Settings.FskPacketHandler.ChunkSize;
+ txTimeout = SX1272.Settings.Fsk.TxTimeout;
+ }
break;
case MODEM_LORA:
{
- if( SX1272.Settings.LoRa.TxIqInverted == true )
+ if( SX1272.Settings.LoRa.IqInverted == true )
{
SX1272Write( REG_LR_INVERTIQ, ( ( SX1272Read( REG_LR_INVERTIQ ) & RFLR_INVERTIQ_TX_MASK & RFLR_INVERTIQ_RX_MASK ) | RFLR_INVERTIQ_RX_OFF | RFLR_INVERTIQ_TX_ON ) );
SX1272Write( REG_LR_INVERTIQ2, RFLR_INVERTIQ2_ON );
@@ -588,12 +777,17 @@ void SX1272Send( uint8_t *buffer, uint8_t size )
SX1272SetTx( txTimeout );
}
-IRAM_ATTR void SX1272SetSleep( void )
+void SX1272SetSleep( void )
{
TimerStop( &RxTimeoutTimer );
TimerStop( &TxTimeoutTimer );
+ TimerStop( &RxTimeoutSyncWord );
SX1272SetOpMode( RF_OPMODE_SLEEP );
+
+ // Disable TCXO radio is in SLEEP mode
+ SX1272SetBoardTcxo( false );
+
SX1272.Settings.State = RF_IDLE;
}
@@ -601,22 +795,54 @@ void SX1272SetStby( void )
{
TimerStop( &RxTimeoutTimer );
TimerStop( &TxTimeoutTimer );
+ TimerStop( &RxTimeoutSyncWord );
SX1272SetOpMode( RF_OPMODE_STANDBY );
SX1272.Settings.State = RF_IDLE;
}
-IRAM_ATTR void SX1272SetRx( uint32_t timeout )
+void SX1272SetRx( uint32_t timeout )
{
bool rxContinuous = false;
+ TimerStop( &TxTimeoutTimer );
switch( SX1272.Settings.Modem )
{
case MODEM_FSK:
+ {
+ rxContinuous = SX1272.Settings.Fsk.RxContinuous;
+
+ // DIO0=PayloadReady
+ // DIO1=FifoLevel
+ // DIO2=SyncAddr
+ // DIO3=FifoEmpty
+ // DIO4=Preamble
+ // DIO5=ModeReady
+ SX1272Write( REG_DIOMAPPING1, ( SX1272Read( REG_DIOMAPPING1 ) & RF_DIOMAPPING1_DIO0_MASK &
+ RF_DIOMAPPING1_DIO1_MASK &
+ RF_DIOMAPPING1_DIO2_MASK ) |
+ RF_DIOMAPPING1_DIO0_00 |
+ RF_DIOMAPPING1_DIO1_00 |
+ RF_DIOMAPPING1_DIO2_11 );
+
+ SX1272Write( REG_DIOMAPPING2, ( SX1272Read( REG_DIOMAPPING2 ) & RF_DIOMAPPING2_DIO4_MASK &
+ RF_DIOMAPPING2_MAP_MASK ) |
+ RF_DIOMAPPING2_DIO4_11 |
+ RF_DIOMAPPING2_MAP_PREAMBLEDETECT );
+
+ SX1272.Settings.FskPacketHandler.FifoThresh = SX1272Read( REG_FIFOTHRESH ) & 0x3F;
+
+ SX1272Write( REG_RXCONFIG, RF_RXCONFIG_AFCAUTO_ON | RF_RXCONFIG_AGCAUTO_ON | RF_RXCONFIG_RXTRIGER_PREAMBLEDETECT );
+
+ SX1272.Settings.FskPacketHandler.PreambleDetected = false;
+ SX1272.Settings.FskPacketHandler.SyncWordDetected = false;
+ SX1272.Settings.FskPacketHandler.NbBytes = 0;
+ SX1272.Settings.FskPacketHandler.Size = 0;
+ }
break;
case MODEM_LORA:
{
- if( SX1272.Settings.LoRa.RxIqInverted == true )
+ if( SX1272.Settings.LoRa.IqInverted == true )
{
SX1272Write( REG_LR_INVERTIQ, ( ( SX1272Read( REG_LR_INVERTIQ ) & RFLR_INVERTIQ_TX_MASK & RFLR_INVERTIQ_RX_MASK ) | RFLR_INVERTIQ_RX_ON | RFLR_INVERTIQ_TX_OFF ) );
SX1272Write( REG_LR_INVERTIQ2, RFLR_INVERTIQ2_ON );
@@ -672,7 +898,14 @@ IRAM_ATTR void SX1272SetRx( uint32_t timeout )
TimerStart( &RxTimeoutTimer );
}
- if( SX1272.Settings.Modem == MODEM_LORA )
+ if( SX1272.Settings.Modem == MODEM_FSK )
+ {
+ SX1272SetOpMode( RF_OPMODE_RECEIVER );
+
+ TimerSetValue( &RxTimeoutSyncWord, SX1272.Settings.Fsk.RxSingleTimeout );
+ TimerStart( &RxTimeoutSyncWord );
+ }
+ else
{
if( rxContinuous == true )
{
@@ -687,11 +920,29 @@ IRAM_ATTR void SX1272SetRx( uint32_t timeout )
void SX1272SetTx( uint32_t timeout )
{
+ TimerStop( &RxTimeoutTimer );
+
TimerSetValue( &TxTimeoutTimer, timeout );
switch( SX1272.Settings.Modem )
{
case MODEM_FSK:
+ {
+ // DIO0=PacketSent
+ // DIO1=FifoEmpty
+ // DIO2=FifoFull
+ // DIO3=FifoEmpty
+ // DIO4=LowBat
+ // DIO5=ModeReady
+ SX1272Write( REG_DIOMAPPING1, ( SX1272Read( REG_DIOMAPPING1 ) & RF_DIOMAPPING1_DIO0_MASK &
+ RF_DIOMAPPING1_DIO1_MASK &
+ RF_DIOMAPPING1_DIO2_MASK ) |
+ RF_DIOMAPPING1_DIO1_01 );
+
+ SX1272Write( REG_DIOMAPPING2, ( SX1272Read( REG_DIOMAPPING2 ) & RF_DIOMAPPING2_DIO4_MASK &
+ RF_DIOMAPPING2_MAP_MASK ) );
+ SX1272.Settings.FskPacketHandler.FifoThresh = SX1272Read( REG_FIFOTHRESH ) & 0x3F;
+ }
break;
case MODEM_LORA:
{
@@ -737,6 +988,9 @@ void SX1272StartCad( void )
switch( SX1272.Settings.Modem )
{
case MODEM_FSK:
+ {
+
+ }
break;
case MODEM_LORA:
{
@@ -784,42 +1038,54 @@ void SX1272SetTxContinuousWave( uint32_t freq, int8_t power, uint16_t time )
int16_t SX1272ReadRssi( RadioModems_t modem )
{
- int16_t rssi = -1;
+ int16_t rssi = 0;
switch( modem )
{
case MODEM_FSK:
+ rssi = -( SX1272Read( REG_RSSIVALUE ) >> 1 );
break;
case MODEM_LORA:
rssi = RSSI_OFFSET + SX1272Read( REG_LR_RSSIVALUE );
break;
default:
+ rssi = -1;
break;
}
return rssi;
}
-void SX1272Reset( void )
-{
- if (micropy_lpwan_use_reset_pin) {
- // Set RESET pin to 1
- GpioInit( &SX1272.Reset, RADIO_RESET, PIN_OUTPUT, PIN_PUSH_PULL, PIN_NO_PULL, 1 );
-
- // Wait 2 ms
- DelayMs( 2 );
-
- // Configure RESET as input
- GpioInit( &SX1272.Reset, RADIO_RESET, PIN_INPUT, PIN_PUSH_PULL, PIN_NO_PULL, 1 );
-
- // Wait 6 ms
- DelayMs( 6 );
- } else {
- DelayMs( 2 );
- }
-}
-
IRAM_ATTR void SX1272SetOpMode( uint8_t opMode )
{
+#if defined( USE_RADIO_DEBUG )
+ switch( opMode )
+ {
+ case RF_OPMODE_TRANSMITTER:
+ SX1272DbgPinTxWrite( 1 );
+ SX1272DbgPinRxWrite( 0 );
+ break;
+ case RF_OPMODE_RECEIVER:
+ case RFLR_OPMODE_RECEIVER_SINGLE:
+ SX1272DbgPinTxWrite( 0 );
+ SX1272DbgPinRxWrite( 1 );
+ break;
+ default:
+ SX1272DbgPinTxWrite( 0 );
+ SX1272DbgPinRxWrite( 0 );
+ break;
+ }
+#endif
+ if( opMode == RF_OPMODE_SLEEP )
+ {
+ SX1272SetAntSwLowPower( true );
+ }
+ else
+ {
+ // Enable TCXO if operating mode different from SLEEP.
+ SX1272SetBoardTcxo( true );
+ SX1272SetAntSwLowPower( false );
+ SX1272SetAntSw( opMode );
+ }
SX1272Write( REG_OPMODE, ( SX1272Read( REG_OPMODE ) & RF_OPMODE_MASK ) | opMode );
}
@@ -860,51 +1126,55 @@ IRAM_ATTR void SX1272SetModem( RadioModems_t modem )
}
}
-IRAM_ATTR void SX1272Write( uint8_t addr, uint8_t data )
+IRAM_ATTR void SX1272Write( uint16_t addr, uint8_t data )
{
- SX1272WriteBuffer( addr, &data, 1 );
+ uint16_t data16 = data;
+ data16 = (data16<<8) + (addr|0x80);
+ //NSS = 0;
+ GPIO_REG_WRITE(GPIO_OUT_W1TC_REG, 1 << LPWAN_NCS_PIN_NUMBER);
+
+ SpiIn0Out16(&SX1272.Spi, data16);
+
+ //NSS = 1;
+ GPIO_REG_WRITE(GPIO_OUT_W1TS_REG, 1 << LPWAN_NCS_PIN_NUMBER);
}
-IRAM_ATTR uint8_t SX1272Read( uint8_t addr )
+IRAM_ATTR uint8_t SX1272Read( uint16_t addr )
{
uint8_t data;
- SX1272ReadBuffer( addr, &data, 1 );
+ //NSS = 0;
+ GPIO_REG_WRITE(GPIO_OUT_W1TC_REG, 1 << LPWAN_NCS_PIN_NUMBER);
+
+ data = SpiIn8Out16(&SX1272.Spi, addr&0x7F);
+
+ //NSS = 1;
+ GPIO_REG_WRITE(GPIO_OUT_W1TS_REG, 1 << LPWAN_NCS_PIN_NUMBER);
+
return data;
}
-IRAM_ATTR void SX1272WriteBuffer( uint8_t addr, uint8_t *buffer, uint8_t size )
+IRAM_ATTR void SX1272WriteBuffer( uint16_t addr, uint8_t *buffer, uint8_t size )
{
- uint8_t i;
-
//NSS = 0;
- GpioWrite( &SX1272.Spi.Nss, 0 );
+ GPIO_REG_WRITE(GPIO_OUT_W1TC_REG, 1 << LPWAN_NCS_PIN_NUMBER);
SpiInOut( &SX1272.Spi, addr | 0x80 );
- for( i = 0; i < size; i++ )
- {
- SpiInOut( &SX1272.Spi, buffer[i] );
- }
+ SpiOutBuf(&SX1272.Spi, buffer, size);
//NSS = 1;
- GpioWrite( &SX1272.Spi.Nss, 1 );
+ GPIO_REG_WRITE(GPIO_OUT_W1TS_REG, 1 << LPWAN_NCS_PIN_NUMBER);
}
-IRAM_ATTR void SX1272ReadBuffer( uint8_t addr, uint8_t *buffer, uint8_t size )
+IRAM_ATTR void SX1272ReadBuffer( uint16_t addr, uint8_t *buffer, uint8_t size )
{
- uint8_t i;
-
//NSS = 0;
- GpioWrite( &SX1272.Spi.Nss, 0 );
+ GPIO_REG_WRITE(GPIO_OUT_W1TC_REG, 1 << LPWAN_NCS_PIN_NUMBER);
SpiInOut( &SX1272.Spi, addr & 0x7F );
-
- for( i = 0; i < size; i++ )
- {
- buffer[i] = SpiInOut( &SX1272.Spi, 0 );
- }
+ SpiInBuf(&SX1272.Spi, buffer, size);
//NSS = 1;
- GpioWrite( &SX1272.Spi.Nss, 1 );
+ GPIO_REG_WRITE(GPIO_OUT_W1TS_REG, 1 << LPWAN_NCS_PIN_NUMBER);
}
IRAM_ATTR void SX1272WriteFifo( uint8_t *buffer, uint8_t size )
@@ -924,6 +1194,10 @@ IRAM_ATTR void SX1272SetMaxPayloadLength( RadioModems_t modem, uint8_t max )
switch( modem )
{
case MODEM_FSK:
+ if( SX1272.Settings.Fsk.FixLen == false )
+ {
+ SX1272Write( REG_PAYLOADLENGTH, max );
+ }
break;
case MODEM_LORA:
SX1272Write( REG_LR_PAYLOADMAXLENGTH, max );
@@ -947,17 +1221,48 @@ void SX1272SetPublicNetwork( bool enable )
}
}
-void SX1272OnTimeoutIrq( void )
+uint32_t SX1272GetWakeupTime( void )
+{
+ return SX1272GetBoardTcxoWakeupTime( ) + RADIO_WAKEUP_TIME;
+}
+
+void SX1272OnTimeoutIrq( void* context )
{
switch( SX1272.Settings.State )
{
case RF_RX_RUNNING:
- if( SX1272.Settings.Modem == MODEM_LORA )
+ if( SX1272.Settings.Modem == MODEM_FSK )
+ {
+ SX1272.Settings.FskPacketHandler.PreambleDetected = false;
+ SX1272.Settings.FskPacketHandler.SyncWordDetected = false;
+ SX1272.Settings.FskPacketHandler.NbBytes = 0;
+ SX1272.Settings.FskPacketHandler.Size = 0;
+
+ // Clear Irqs
+ SX1272Write( REG_IRQFLAGS1, RF_IRQFLAGS1_RSSI |
+ RF_IRQFLAGS1_PREAMBLEDETECT |
+ RF_IRQFLAGS1_SYNCADDRESSMATCH );
+ SX1272Write( REG_IRQFLAGS2, RF_IRQFLAGS2_FIFOOVERRUN );
+
+ if( SX1272.Settings.Fsk.RxContinuous == true )
+ {
+ // Continuous mode restart Rx chain
+ SX1272Write( REG_RXCONFIG, SX1272Read( REG_RXCONFIG ) | RF_RXCONFIG_RESTARTRXWITHOUTPLLLOCK );
+ TimerStart( &RxTimeoutSyncWord );
+ }
+ else
+ {
+ SX1272.Settings.State = RF_IDLE;
+ TimerStop( &RxTimeoutSyncWord );
+ }
+ }
+ else // Pycom code block
{
// Clear Irq
SX1272Write( REG_LR_IRQFLAGS, RFLR_IRQFLAGS_RXTIMEOUT );
SX1272.Settings.State = RF_IDLE;
}
+
if( ( RadioEvents != NULL ) && ( RadioEvents->RxTimeout != NULL ) )
{
RadioEvents->RxTimeout( );
@@ -965,10 +1270,12 @@ void SX1272OnTimeoutIrq( void )
break;
case RF_TX_RUNNING:
// Tx timeout shouldn't happen.
- // But it has been observed that when it happens it is a result of a corrupted SPI transfer
- // it depends on the platform design.
- //
- // The workaround is to put the radio in a known state. Thus, we re-initialize it.
+ // Reported issue of SPI data corruption resulting in TX TIMEOUT
+ // is NOT related to a bug in radio transceiver.
+ // It is mainly caused by improper PCB routing of SPI lines and/or
+ // violation of SPI specifications.
+ // To mitigate redesign, Semtech offers a workaround which resets
+ // the radio transceiver and putting it into a known state.
// BEGIN WORKAROUND
@@ -1000,7 +1307,7 @@ void SX1272OnTimeoutIrq( void )
}
}
-IRAM_ATTR void SX1272RadioFlagsIrq (void) {
+IRAM_ATTR void SX1272RadioFlagsIrq (void *context) {
if (SX1272.irqFlags & RADIO_IRQ_FLAG_RX_TIMEOUT) {
SX1272.irqFlags &= ~RADIO_IRQ_FLAG_RX_TIMEOUT;
if( ( RadioEvents != NULL ) && ( RadioEvents->RxTimeout != NULL ) )
@@ -1026,7 +1333,7 @@ IRAM_ATTR void SX1272RadioFlagsIrq (void) {
}
}
-static IRAM_ATTR void SX1272OnDioIrq (void) {
+static IRAM_ATTR void SX1272OnDioIrq (void *context) {
if (SX1272.Settings.State > RF_IDLE) {
// read the the irq flags registers
uint8_t volatile irqflags1;
@@ -1036,16 +1343,16 @@ static IRAM_ATTR void SX1272OnDioIrq (void) {
case MODEM_LORA:
irqflags1 = SX1272Read(REG_LR_IRQFLAGS);
if ((irqflags1 & RFLR_IRQFLAGS_RXDONE) || (irqflags1 & RFLR_IRQFLAGS_TXDONE)) {
- SX1272OnDio0Irq();
+ SX1272OnDio0Irq( NULL );
}
if (irqflags1 & RFLR_IRQFLAGS_RXTIMEOUT) {
- SX1272OnDio1Irq();
+ SX1272OnDio1Irq( NULL );
}
if (SX1272.Settings.LoRa.FreqHopOn == true && (irqflags1 & RFLR_IRQFLAGS_FHSSCHANGEDCHANNEL)) {
- SX1272OnDio2Irq();
+ SX1272OnDio2Irq( NULL );
}
if ((irqflags1 & RFLR_IRQFLAGS_CADDETECTED) || (irqflags1 & RFLR_IRQFLAGS_CADDONE)) {
- SX1272OnDio3Irq();
+ SX1272OnDio3Irq( NULL );
}
break;
default:
@@ -1054,22 +1361,101 @@ static IRAM_ATTR void SX1272OnDioIrq (void) {
}
}
-IRAM_ATTR void SX1272OnDio0Irq( void )
+IRAM_ATTR void SX1272OnDio0Irq( void* context )
{
volatile uint8_t irqFlags = 0;
switch( SX1272.Settings.State )
{
case RF_RX_RUNNING:
+ //TimerStop( &RxTimeoutTimer );
// RxDone interrupt
switch( SX1272.Settings.Modem )
{
case MODEM_FSK:
+ if( SX1272.Settings.Fsk.CrcOn == true )
+ {
+ irqFlags = SX1272Read( REG_IRQFLAGS2 );
+ if( ( irqFlags & RF_IRQFLAGS2_CRCOK ) != RF_IRQFLAGS2_CRCOK )
+ {
+ // Clear Irqs
+ SX1272Write( REG_IRQFLAGS1, RF_IRQFLAGS1_RSSI |
+ RF_IRQFLAGS1_PREAMBLEDETECT |
+ RF_IRQFLAGS1_SYNCADDRESSMATCH );
+ SX1272Write( REG_IRQFLAGS2, RF_IRQFLAGS2_FIFOOVERRUN );
+
+ TimerStop( &RxTimeoutTimer );
+
+ if( SX1272.Settings.Fsk.RxContinuous == false )
+ {
+ TimerStop( &RxTimeoutSyncWord );
+ SX1272.Settings.State = RF_IDLE;
+ }
+ else
+ {
+ // Continuous mode restart Rx chain
+ SX1272Write( REG_RXCONFIG, SX1272Read( REG_RXCONFIG ) | RF_RXCONFIG_RESTARTRXWITHOUTPLLLOCK );
+ TimerStart( &RxTimeoutSyncWord );
+ }
+
+ if( ( RadioEvents != NULL ) && ( RadioEvents->RxError != NULL ) )
+ {
+ RadioEvents->RxError( );
+ }
+ SX1272.Settings.FskPacketHandler.PreambleDetected = false;
+ SX1272.Settings.FskPacketHandler.SyncWordDetected = false;
+ SX1272.Settings.FskPacketHandler.NbBytes = 0;
+ SX1272.Settings.FskPacketHandler.Size = 0;
+ break;
+ }
+ }
+
+ // Read received packet size
+ if( ( SX1272.Settings.FskPacketHandler.Size == 0 ) && ( SX1272.Settings.FskPacketHandler.NbBytes == 0 ) )
+ {
+ if( SX1272.Settings.Fsk.FixLen == false )
+ {
+ SX1272ReadFifo( ( uint8_t* )&SX1272.Settings.FskPacketHandler.Size, 1 );
+ }
+ else
+ {
+ SX1272.Settings.FskPacketHandler.Size = SX1272Read( REG_PAYLOADLENGTH );
+ }
+ SX1272ReadFifo( RxTxBuffer + SX1272.Settings.FskPacketHandler.NbBytes, SX1272.Settings.FskPacketHandler.Size - SX1272.Settings.FskPacketHandler.NbBytes );
+ SX1272.Settings.FskPacketHandler.NbBytes += ( SX1272.Settings.FskPacketHandler.Size - SX1272.Settings.FskPacketHandler.NbBytes );
+ }
+ else
+ {
+ SX1272ReadFifo( RxTxBuffer + SX1272.Settings.FskPacketHandler.NbBytes, SX1272.Settings.FskPacketHandler.Size - SX1272.Settings.FskPacketHandler.NbBytes );
+ SX1272.Settings.FskPacketHandler.NbBytes += ( SX1272.Settings.FskPacketHandler.Size - SX1272.Settings.FskPacketHandler.NbBytes );
+ }
+
+ TimerStop( &RxTimeoutTimer );
+
+ if( SX1272.Settings.Fsk.RxContinuous == false )
+ {
+ SX1272.Settings.State = RF_IDLE;
+ TimerStop( &RxTimeoutSyncWord );
+ }
+ else
+ {
+ // Continuous mode restart Rx chain
+ SX1272Write( REG_RXCONFIG, SX1272Read( REG_RXCONFIG ) | RF_RXCONFIG_RESTARTRXWITHOUTPLLLOCK );
+ TimerStart( &RxTimeoutSyncWord );
+ }
+
+ if( ( RadioEvents != NULL ) && ( RadioEvents->RxDone != NULL ) )
+ {
+ // TODO: Add proper handling of Timestamp and sf parameters for FSK
+ RadioEvents->RxDone( RxTxBuffer, 0, SX1272.Settings.FskPacketHandler.Size, SX1272.Settings.FskPacketHandler.RssiValue, 0, 0 );
+ }
+ SX1272.Settings.FskPacketHandler.PreambleDetected = false;
+ SX1272.Settings.FskPacketHandler.SyncWordDetected = false;
+ SX1272.Settings.FskPacketHandler.NbBytes = 0;
+ SX1272.Settings.FskPacketHandler.Size = 0;
break;
case MODEM_LORA:
{
- int8_t snr = 0;
-
// Store the packet timestamp
SX1272.Settings.LoRaPacketHandler.TimeStamp = mp_hal_ticks_us_non_blocking();
@@ -1094,24 +1480,14 @@ IRAM_ATTR void SX1272OnDio0Irq( void )
break;
}
- SX1272.Settings.LoRaPacketHandler.SnrValue = SX1272Read( REG_LR_PKTSNRVALUE );
- if( SX1272.Settings.LoRaPacketHandler.SnrValue & 0x80 ) // The SNR sign bit is 1
- {
- // Invert and divide by 4
- snr = ( ( ~SX1272.Settings.LoRaPacketHandler.SnrValue + 1 ) & 0xFF ) >> 2;
- snr = -snr;
- }
- else
- {
- // Divide by 4
- snr = ( SX1272.Settings.LoRaPacketHandler.SnrValue & 0xFF ) >> 2;
- }
+ // Returns SNR value [dB] rounded to the nearest integer value
+ SX1272.Settings.LoRaPacketHandler.SnrValue = ( ( ( int8_t )SX1272Read( REG_LR_PKTSNRVALUE ) ) + 2 ) >> 2;
int16_t rssi = SX1272Read( REG_LR_PKTRSSIVALUE );
- if( snr < 0 )
+ if( SX1272.Settings.LoRaPacketHandler.SnrValue < 0 )
{
SX1272.Settings.LoRaPacketHandler.RssiValue = RSSI_OFFSET + rssi + ( rssi >> 4 ) +
- snr;
+ SX1272.Settings.LoRaPacketHandler.SnrValue;
}
else
{
@@ -1161,7 +1537,7 @@ IRAM_ATTR void SX1272OnDio0Irq( void )
}
}
-IRAM_ATTR void SX1272OnDio1Irq( void )
+IRAM_ATTR void SX1272OnDio1Irq( void* context )
{
switch( SX1272.Settings.State )
{
@@ -1169,6 +1545,39 @@ IRAM_ATTR void SX1272OnDio1Irq( void )
switch( SX1272.Settings.Modem )
{
case MODEM_FSK:
+ // Stop timer
+ TimerStop( &RxTimeoutSyncWord );
+
+ // FifoLevel interrupt
+ // Read received packet size
+ if( ( SX1272.Settings.FskPacketHandler.Size == 0 ) && ( SX1272.Settings.FskPacketHandler.NbBytes == 0 ) )
+ {
+ if( SX1272.Settings.Fsk.FixLen == false )
+ {
+ SX1272ReadFifo( ( uint8_t* )&SX1272.Settings.FskPacketHandler.Size, 1 );
+ }
+ else
+ {
+ SX1272.Settings.FskPacketHandler.Size = SX1272Read( REG_PAYLOADLENGTH );
+ }
+ }
+ // ERRATA 3.1 - PayloadReady Set for 31.25ns if FIFO is Empty
+ //
+ // When FifoLevel interrupt is used to offload the
+ // FIFO, the microcontroller should monitor both
+ // PayloadReady and FifoLevel interrupts, and
+ // read only (FifoThreshold-1) bytes off the FIFO
+ // when FifoLevel fires
+ if( ( SX1272.Settings.FskPacketHandler.Size - SX1272.Settings.FskPacketHandler.NbBytes ) >= SX1272.Settings.FskPacketHandler.FifoThresh )
+ {
+ SX1272ReadFifo( ( RxTxBuffer + SX1272.Settings.FskPacketHandler.NbBytes ), SX1272.Settings.FskPacketHandler.FifoThresh - 1 );
+ SX1272.Settings.FskPacketHandler.NbBytes += SX1272.Settings.FskPacketHandler.FifoThresh - 1;
+ }
+ else
+ {
+ SX1272ReadFifo( ( RxTxBuffer + SX1272.Settings.FskPacketHandler.NbBytes ), SX1272.Settings.FskPacketHandler.Size - SX1272.Settings.FskPacketHandler.NbBytes );
+ SX1272.Settings.FskPacketHandler.NbBytes += ( SX1272.Settings.FskPacketHandler.Size - SX1272.Settings.FskPacketHandler.NbBytes );
+ }
break;
case MODEM_LORA:
// Sync time out
@@ -1190,6 +1599,18 @@ IRAM_ATTR void SX1272OnDio1Irq( void )
switch( SX1272.Settings.Modem )
{
case MODEM_FSK:
+ // FifoEmpty interrupt
+ if( ( SX1272.Settings.FskPacketHandler.Size - SX1272.Settings.FskPacketHandler.NbBytes ) > SX1272.Settings.FskPacketHandler.ChunkSize )
+ {
+ SX1272WriteFifo( ( RxTxBuffer + SX1272.Settings.FskPacketHandler.NbBytes ), SX1272.Settings.FskPacketHandler.ChunkSize );
+ SX1272.Settings.FskPacketHandler.NbBytes += SX1272.Settings.FskPacketHandler.ChunkSize;
+ }
+ else
+ {
+ // Write the last chunk of data
+ SX1272WriteFifo( RxTxBuffer + SX1272.Settings.FskPacketHandler.NbBytes, SX1272.Settings.FskPacketHandler.Size - SX1272.Settings.FskPacketHandler.NbBytes );
+ SX1272.Settings.FskPacketHandler.NbBytes += SX1272.Settings.FskPacketHandler.Size - SX1272.Settings.FskPacketHandler.NbBytes;
+ }
break;
case MODEM_LORA:
break;
@@ -1202,7 +1623,7 @@ IRAM_ATTR void SX1272OnDio1Irq( void )
}
}
-IRAM_ATTR void SX1272OnDio2Irq( void )
+IRAM_ATTR void SX1272OnDio2Irq( void* context )
{
switch( SX1272.Settings.State )
{
@@ -1210,6 +1631,25 @@ IRAM_ATTR void SX1272OnDio2Irq( void )
switch( SX1272.Settings.Modem )
{
case MODEM_FSK:
+ // Checks if DIO4 is connected. If it is not PreambleDetected is set to true.
+ //if( SX1272.DIO4.port == NULL ) TODO: The check needs to be updated when FSK is integrated
+ {
+ SX1272.Settings.FskPacketHandler.PreambleDetected = true;
+ }
+
+ if( ( SX1272.Settings.FskPacketHandler.PreambleDetected == true ) && ( SX1272.Settings.FskPacketHandler.SyncWordDetected == false ) )
+ {
+ TimerStop( &RxTimeoutSyncWord );
+
+ SX1272.Settings.FskPacketHandler.SyncWordDetected = true;
+
+ SX1272.Settings.FskPacketHandler.RssiValue = -( SX1272Read( REG_RSSIVALUE ) >> 1 );
+
+ SX1272.Settings.FskPacketHandler.AfcValue = ( int32_t )( double )( ( ( uint16_t )SX1272Read( REG_AFCMSB ) << 8 ) |
+ ( uint16_t )SX1272Read( REG_AFCLSB ) ) *
+ ( double )FREQ_STEP;
+ SX1272.Settings.FskPacketHandler.RxGain = ( SX1272Read( REG_LNA ) >> 5 ) & 0x07;
+ }
break;
case MODEM_LORA:
if( SX1272.Settings.LoRa.FreqHopOn == true )
@@ -1253,7 +1693,7 @@ IRAM_ATTR void SX1272OnDio2Irq( void )
}
}
-IRAM_ATTR void SX1272OnDio3Irq( void )
+IRAM_ATTR void SX1272OnDio3Irq( void* context )
{
switch( SX1272.Settings.Modem )
{
@@ -1284,11 +1724,17 @@ IRAM_ATTR void SX1272OnDio3Irq( void )
}
}
-IRAM_ATTR void SX1272OnDio4Irq( void )
+IRAM_ATTR void SX1272OnDio4Irq( void* context )
{
switch( SX1272.Settings.Modem )
{
case MODEM_FSK:
+ {
+ if( SX1272.Settings.FskPacketHandler.PreambleDetected == false )
+ {
+ SX1272.Settings.FskPacketHandler.PreambleDetected = true;
+ }
+ }
break;
case MODEM_LORA:
break;
@@ -1297,8 +1743,7 @@ IRAM_ATTR void SX1272OnDio4Irq( void )
}
}
-// not used
-void SX1272OnDio5Irq( void )
+IRAM_ATTR void SX1272OnDio5Irq( void* context )
{
switch( SX1272.Settings.Modem )
{
diff --git a/drivers/sx127x/sx1272/sx1272.h b/drivers/sx127x/sx1272/sx1272.h
index cc05dc85fd..4df4801758 100644
--- a/drivers/sx127x/sx1272/sx1272.h
+++ b/drivers/sx127x/sx1272/sx1272.h
@@ -1,20 +1,38 @@
-/*
- / _____) _ | |
-( (____ _____ ____ _| |_ _____ ____| |__
- \____ \| ___ | (_ _) ___ |/ ___) _ \
- _____) ) ____| | | || |_| ____( (___| | | |
-(______/|_____)_|_|_| \__)_____)\____)_| |_|
- (C)2013 Semtech
-
-Description: Generic SX1272 driver implementation
-
-License: Revised BSD License, see LICENSE.TXT file include in the project
-
-Maintainer: Miguel Luis and Gregory Cristian
-*/
+/*!
+ * \file sx1272.h
+ *
+ * \brief SX1272 driver implementation
+ *
+ * \copyright Revised BSD License, see section \ref LICENSE.
+ *
+ * \code
+ * ______ _
+ * / _____) _ | |
+ * ( (____ _____ ____ _| |_ _____ ____| |__
+ * \____ \| ___ | (_ _) ___ |/ ___) _ \
+ * _____) ) ____| | | || |_| ____( (___| | | |
+ * (______/|_____)_|_|_| \__)_____)\____)_| |_|
+ * (C)2013-2017 Semtech
+ *
+ * \endcode
+ *
+ * \author Miguel Luis ( Semtech )
+ *
+ * \author Gregory Cristian ( Semtech )
+ */
#ifndef __SX1272_H__
#define __SX1272_H__
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+// #include
+// #include
+// #include "gpio.h"
+// #include "spi.h"
+// #include "radio.h"
#include "sx1272Regs-Fsk.h"
#include "sx1272Regs-LoRa.h"
@@ -47,8 +65,7 @@ typedef struct
bool FixLen;
uint8_t PayloadLen;
bool CrcOn;
- bool RxIqInverted;
- bool TxIqInverted;
+ bool IqInverted;
bool RxContinuous;
uint32_t TxTimeout;
uint32_t RxSingleTimeout;
@@ -86,8 +103,7 @@ typedef struct
bool CrcOn;
bool FreqHopOn;
uint8_t HopPeriod;
- bool RxIqInverted;
- bool TxIqInverted;
+ bool IqInverted;
bool RxContinuous;
uint32_t TxTimeout;
bool PublicNetwork;
@@ -99,8 +115,8 @@ typedef struct
typedef struct
{
uint32_t TimeStamp;
- int16_t RssiValue;
int8_t SnrValue;
+ int16_t RssiValue;
uint8_t Size;
}RadioLoRaPacketHandler_t;
@@ -112,6 +128,8 @@ typedef struct
RadioState_t State;
RadioModems_t Modem;
uint32_t Channel;
+ RadioFskSettings_t Fsk;
+ RadioFskPacketHandler_t FskPacketHandler;
RadioLoRaSettings_t LoRa;
RadioLoRaPacketHandler_t LoRaPacketHandler;
}RadioSettings_t;
@@ -131,7 +149,7 @@ typedef struct SX1272_s
/*!
* Hardware IO IRQ callback function definition
*/
-typedef void ( DioIrqHandler )( void );
+typedef void ( DioIrqHandler )( void* context );
/*!
* SX1272 definitions
@@ -358,7 +376,7 @@ int16_t SX1272ReadRssi( RadioModems_t modem );
* \param [IN]: addr Register address
* \param [IN]: data New register value
*/
-void SX1272Write( uint8_t addr, uint8_t data );
+void SX1272Write( uint16_t addr, uint8_t data );
/*!
* \brief Reads the radio register at the specified address
@@ -366,7 +384,7 @@ void SX1272Write( uint8_t addr, uint8_t data );
* \param [IN]: addr Register address
* \retval data Register value
*/
-uint8_t SX1272Read( uint8_t addr );
+uint8_t SX1272Read( uint16_t addr );
/*!
* \brief Writes multiple radio registers starting at address
@@ -375,7 +393,7 @@ uint8_t SX1272Read( uint8_t addr );
* \param [IN] buffer Buffer containing the new register's values
* \param [IN] size Number of registers to be written
*/
-void SX1272WriteBuffer( uint8_t addr, uint8_t *buffer, uint8_t size );
+void SX1272WriteBuffer( uint16_t addr, uint8_t *buffer, uint8_t size );
/*!
* \brief Reads multiple radio registers starting at address
@@ -384,7 +402,7 @@ void SX1272WriteBuffer( uint8_t addr, uint8_t *buffer, uint8_t size );
* \param [OUT] buffer Buffer where to copy the registers data
* \param [IN] size Number of registers to be read
*/
-void SX1272ReadBuffer( uint8_t addr, uint8_t *buffer, uint8_t size );
+void SX1272ReadBuffer( uint16_t addr, uint8_t *buffer, uint8_t size );
/*!
* \brief Sets the maximum payload length.
@@ -409,9 +427,16 @@ void SX1272SetOpMode( uint8_t opMode );
* \param [IN] enable if true, it enables a public network
*/
void SX1272SetPublicNetwork( bool enable );
+
/*!
- * \brief Resets the SX1272
+ * \brief Gets the time required for the board plus radio to get out of sleep.[ms]
+ *
+ * \retval time Radio plus board wakeup time in ms.
*/
-void SX1272Reset( void );
+uint32_t SX1272GetWakeupTime( void );
+
+#ifdef __cplusplus
+}
+#endif
#endif // __SX1272_H__
diff --git a/drivers/sx127x/sx1272/sx1272Regs-Fsk.h b/drivers/sx127x/sx1272/sx1272Regs-Fsk.h
index cc9ab00cd9..b90259e66d 100644
--- a/drivers/sx127x/sx1272/sx1272Regs-Fsk.h
+++ b/drivers/sx127x/sx1272/sx1272Regs-Fsk.h
@@ -1,20 +1,33 @@
-/*
- / _____) _ | |
-( (____ _____ ____ _| |_ _____ ____| |__
- \____ \| ___ | (_ _) ___ |/ ___) _ \
- _____) ) ____| | | || |_| ____( (___| | | |
-(______/|_____)_|_|_| \__)_____)\____)_| |_|
- (C)2013 Semtech
-
-Description: SX1272 FSK modem registers and bits definitions
-
-License: Revised BSD License, see LICENSE.TXT file include in the project
-
-Maintainer: Miguel Luis and Gregory Cristian
-*/
+/*!
+ * \file sx1272Regs-Fsk.h
+ *
+ * \brief SX1272 FSK modem registers and bits definitions
+ *
+ * \copyright Revised BSD License, see section \ref LICENSE.
+ *
+ * \code
+ * ______ _
+ * / _____) _ | |
+ * ( (____ _____ ____ _| |_ _____ ____| |__
+ * \____ \| ___ | (_ _) ___ |/ ___) _ \
+ * _____) ) ____| | | || |_| ____( (___| | | |
+ * (______/|_____)_|_|_| \__)_____)\____)_| |_|
+ * (C)2013-2017 Semtech
+ *
+ * \endcode
+ *
+ * \author Miguel Luis ( Semtech )
+ *
+ * \author Gregory Cristian ( Semtech )
+ */
#ifndef __SX1272_REGS_FSK_H__
#define __SX1272_REGS_FSK_H__
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
/*!
* ============================================================================
* SX1272 Internal registers Address
@@ -1131,4 +1144,8 @@ Maintainer: Miguel Luis and Gregory Cristian
*/
#define RF_BITRATEFRAC_MASK 0xF0
+#ifdef __cplusplus
+}
+#endif
+
#endif // __SX1272_REGS_FSK_H__
diff --git a/drivers/sx127x/sx1272/sx1272Regs-LoRa.h b/drivers/sx127x/sx1272/sx1272Regs-LoRa.h
index 641cf27447..38bc248c7f 100644
--- a/drivers/sx127x/sx1272/sx1272Regs-LoRa.h
+++ b/drivers/sx127x/sx1272/sx1272Regs-LoRa.h
@@ -1,20 +1,33 @@
-/*
- / _____) _ | |
-( (____ _____ ____ _| |_ _____ ____| |__
- \____ \| ___ | (_ _) ___ |/ ___) _ \
- _____) ) ____| | | || |_| ____( (___| | | |
-(______/|_____)_|_|_| \__)_____)\____)_| |_|
- (C)2013 Semtech
-
-Description: SX1272 LoRa modem registers and bits definitions
-
-License: Revised BSD License, see LICENSE.TXT file include in the project
-
-Maintainer: Miguel Luis and Gregory Cristian
-*/
+/*!
+ * \file sx1272Regs-LoRa.h
+ *
+ * \brief SX1272 LoRa modem registers and bits definitions
+ *
+ * \copyright Revised BSD License, see section \ref LICENSE.
+ *
+ * \code
+ * ______ _
+ * / _____) _ | |
+ * ( (____ _____ ____ _| |_ _____ ____| |__
+ * \____ \| ___ | (_ _) ___ |/ ___) _ \
+ * _____) ) ____| | | || |_| ____( (___| | | |
+ * (______/|_____)_|_|_| \__)_____)\____)_| |_|
+ * (C)2013-2017 Semtech
+ *
+ * \endcode
+ *
+ * \author Miguel Luis ( Semtech )
+ *
+ * \author Gregory Cristian ( Semtech )
+ */
#ifndef __SX1272_REGS_LORA_H__
#define __SX1272_REGS_LORA_H__
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
/*!
* ============================================================================
* SX1272 Internal registers Address
@@ -542,4 +555,8 @@ Maintainer: Miguel Luis and Gregory Cristian
* RegFormerTemp
*/
+#ifdef __cplusplus
+}
+#endif
+
#endif // __SX1272_REGS_LORA_H__
diff --git a/drivers/sx127x/sx1276/sx1276.c b/drivers/sx127x/sx1276/sx1276.c
old mode 100755
new mode 100644
index 870c4abae1..58972924cb
--- a/drivers/sx127x/sx1276/sx1276.c
+++ b/drivers/sx127x/sx1276/sx1276.c
@@ -11,27 +11,40 @@
* This file contains code under the following copyright and licensing notices.
* The code has been changed but otherwise retained.
*/
-
-/*
- / _____) _ | |
-( (____ _____ ____ _| |_ _____ ____| |__
- \____ \| ___ | (_ _) ___ |/ ___) _ \
- _____) ) ____| | | || |_| ____( (___| | | |
-(______/|_____)_|_|_| \__)_____)\____)_| |_|
- (C)2013 Semtech
-
-Description: Generic SX1276 driver implementation
-
-License: Revised BSD License, see LICENSE.TXT file include in the project
-
-Maintainer: Miguel Luis, Gregory Cristian and Wael Guibene
-*/
+/*!
+ * \file sx1276.c
+ *
+ * \brief SX1276 driver implementation
+ *
+ * \copyright Revised BSD License, see section \ref LICENSE.
+ *
+ * \code
+ * ______ _
+ * / _____) _ | |
+ * ( (____ _____ ____ _| |_ _____ ____| |__
+ * \____ \| ___ | (_ _) ___ |/ ___) _ \
+ * _____) ) ____| | | || |_| ____( (___| | | |
+ * (______/|_____)_|_|_| \__)_____)\____)_| |_|
+ * (C)2013-2017 Semtech
+ *
+ * \endcode
+ *
+ * \author Miguel Luis ( Semtech )
+ *
+ * \author Gregory Cristian ( Semtech )
+ *
+ * \author Wael Guibene ( Semtech )
+ */
#include
#include
#include "board.h"
+#include "lora/utilities.h"
+#include "lora/system/timer.h"
#include "radio.h"
+#include "lora/system/delay.h"
#include "sx1276.h"
#include "sx1276-board.h"
+
#include "esp_attr.h"
#include "esp32_mphal.h"
@@ -49,6 +62,14 @@ typedef struct
uint8_t Value;
}RadioRegisters_t;
+/*!
+ * FSK bandwidth definition
+ */
+typedef struct
+{
+ uint32_t bandwidth;
+ uint8_t RegValue;
+}FskBandwidth_t;
/*
@@ -62,11 +83,6 @@ typedef struct
*/
static void RxChainCalibration( void );
-/*!
- * \brief Resets the SX1276
- */
-void SX1276Reset( void );
-
/*!
* \brief Sets the SX1276 in transmission mode for the given time
* \param [IN] timeout Transmission timeout [ms] [0: continuous, others timeout]
@@ -103,47 +119,47 @@ void SX1276SetOpMode( uint8_t opMode );
/*!
* \brief Common DIO IRQ callback
*/
-static void SX1276OnDioIrq (void);
+static void SX1276OnDioIrq (void *context);
/*!
* \brief DIO 0 IRQ callback
*/
-void SX1276OnDio0Irq( void );
+void SX1276OnDio0Irq( void* context );
/*!
* \brief DIO 1 IRQ callback
*/
-void SX1276OnDio1Irq( void );
+void SX1276OnDio1Irq( void* context );
/*!
* \brief DIO 2 IRQ callback
*/
-void SX1276OnDio2Irq( void );
+void SX1276OnDio2Irq( void* context );
/*!
* \brief DIO 3 IRQ callback
*/
-void SX1276OnDio3Irq( void );
+void SX1276OnDio3Irq( void* context );
/*!
* \brief DIO 4 IRQ callback
*/
-void SX1276OnDio4Irq( void );
+void SX1276OnDio4Irq( void* context );
/*!
* \brief DIO 5 IRQ callback
*/
-void SX1276OnDio5Irq( void );
+void SX1276OnDio5Irq( void* context );
/*!
* \brief Tx & Rx timeout timer callback
*/
-void SX1276OnTimeoutIrq( void );
+void SX1276OnTimeoutIrq( void* context );
/*!
* \brief General radio flags check callback
*/
-void SX1276RadioFlagsIrq (void);
+void SX1276RadioFlagsIrq (void *context);
/*
* Private global constants
@@ -162,6 +178,35 @@ const RadioRegisters_t RadioRegsInit[] = RADIO_INIT_REGISTERS_VALUE;
#define RSSI_OFFSET_LF -164
#define RSSI_OFFSET_HF -157
+/*!
+ * Precomputed FSK bandwidth registers values
+ */
+const FskBandwidth_t FskBandwidths[] =
+{
+ { 2600 , 0x17 },
+ { 3100 , 0x0F },
+ { 3900 , 0x07 },
+ { 5200 , 0x16 },
+ { 6300 , 0x0E },
+ { 7800 , 0x06 },
+ { 10400 , 0x15 },
+ { 12500 , 0x0D },
+ { 15600 , 0x05 },
+ { 20800 , 0x14 },
+ { 25000 , 0x0C },
+ { 31300 , 0x04 },
+ { 41700 , 0x13 },
+ { 50000 , 0x0B },
+ { 62500 , 0x03 },
+ { 83333 , 0x12 },
+ { 100000, 0x0A },
+ { 125000, 0x02 },
+ { 166700, 0x11 },
+ { 200000, 0x09 },
+ { 250000, 0x01 },
+ { 300000, 0x00 }, // Invalid Bandwidth
+};
+
/*
* Private global variables
*/
@@ -196,6 +241,7 @@ DioIrqHandler *DioIrq[] = { SX1276OnDioIrq };
static TimerEvent_t TxTimeoutTimer;
static TimerEvent_t RxTimeoutTimer;
static TimerEvent_t RadioIrqFlagsTimer;
+static TimerEvent_t RxTimeoutSyncWord;
/*
* Radio driver functions implementation
@@ -212,6 +258,7 @@ void SX1276Init( RadioEvents_t *events )
TimerInit( &RxTimeoutTimer, SX1276OnTimeoutIrq );
TimerInit( &RadioIrqFlagsTimer, SX1276RadioFlagsIrq );
TimerSetValue( &RadioIrqFlagsTimer, 1 );
+ TimerInit( &RxTimeoutSyncWord, SX1276OnTimeoutIrq );
SX1276Reset( );
@@ -260,6 +307,9 @@ bool SX1276IsChannelFree( RadioModems_t modem, uint32_t freq, int16_t rssiThresh
{
bool status = true;
int16_t rssi = 0;
+ uint32_t carrierSenseTime = 0;
+
+ SX1276SetSleep( );
SX1276SetModem( modem );
@@ -269,17 +319,19 @@ bool SX1276IsChannelFree( RadioModems_t modem, uint32_t freq, int16_t rssiThresh
DelayMs( 1 );
+ carrierSenseTime = TimerGetCurrentTime( );
+
// Perform carrier sense for maxCarrierSenseTime
- do {
+ while( TimerGetElapsedTime( carrierSenseTime ) < maxCarrierSenseTime )
+ {
rssi = SX1276ReadRssi( modem );
- if ( rssi > rssiThresh ) {
+ if( rssi > rssiThresh )
+ {
status = false;
break;
}
- DelayMs( 1 );
- maxCarrierSenseTime -= 1;
- } while( maxCarrierSenseTime > 0 );
+ }
SX1276SetSleep( );
return status;
}
@@ -359,6 +411,26 @@ static void RxChainCalibration( void )
SX1276SetChannel( initialFreq );
}
+/*!
+ * Returns the known FSK bandwidth registers value
+ *
+ * \param [IN] bandwidth Bandwidth value in Hz
+ * \retval regValue Bandwidth register value.
+ */
+static uint8_t GetFskBandwidthRegValue( uint32_t bandwidth )
+{
+ uint8_t i;
+
+ for( i = 0; i < ( sizeof( FskBandwidths ) / sizeof( FskBandwidth_t ) ) - 1; i++ )
+ {
+ if( ( bandwidth >= FskBandwidths[i].bandwidth ) && ( bandwidth < FskBandwidths[i + 1].bandwidth ) )
+ {
+ return FskBandwidths[i].RegValue;
+ }
+ }
+ // ERROR: Value not found
+ while( 1 );
+}
IRAM_ATTR void SX1276SetRxConfig( RadioModems_t modem, uint32_t bandwidth,
uint32_t datarate, uint8_t coderate,
@@ -373,9 +445,53 @@ IRAM_ATTR void SX1276SetRxConfig( RadioModems_t modem, uint32_t bandwidth,
switch( modem )
{
case MODEM_FSK:
+ {
+ SX1276.Settings.Fsk.Bandwidth = bandwidth;
+ SX1276.Settings.Fsk.Datarate = datarate;
+ SX1276.Settings.Fsk.BandwidthAfc = bandwidthAfc;
+ SX1276.Settings.Fsk.FixLen = fixLen;
+ SX1276.Settings.Fsk.PayloadLen = payloadLen;
+ SX1276.Settings.Fsk.CrcOn = crcOn;
+ SX1276.Settings.Fsk.IqInverted = iqInverted;
+ SX1276.Settings.Fsk.RxContinuous = rxContinuous;
+ SX1276.Settings.Fsk.PreambleLen = preambleLen;
+ SX1276.Settings.Fsk.RxSingleTimeout = ( uint32_t )( symbTimeout * ( ( 1.0 / ( double )datarate ) * 8.0 ) * 1000 );
+
+ datarate = ( uint16_t )( ( double )XTAL_FREQ / ( double )datarate );
+ SX1276Write( REG_BITRATEMSB, ( uint8_t )( datarate >> 8 ) );
+ SX1276Write( REG_BITRATELSB, ( uint8_t )( datarate & 0xFF ) );
+
+ SX1276Write( REG_RXBW, GetFskBandwidthRegValue( bandwidth ) );
+ SX1276Write( REG_AFCBW, GetFskBandwidthRegValue( bandwidthAfc ) );
+
+ SX1276Write( REG_PREAMBLEMSB, ( uint8_t )( ( preambleLen >> 8 ) & 0xFF ) );
+ SX1276Write( REG_PREAMBLELSB, ( uint8_t )( preambleLen & 0xFF ) );
+
+ if( fixLen == 1 )
+ {
+ SX1276Write( REG_PAYLOADLENGTH, payloadLen );
+ }
+ else
+ {
+ SX1276Write( REG_PAYLOADLENGTH, 0xFF ); // Set payload length to the maximum
+ }
+
+ SX1276Write( REG_PACKETCONFIG1,
+ ( SX1276Read( REG_PACKETCONFIG1 ) &
+ RF_PACKETCONFIG1_CRC_MASK &
+ RF_PACKETCONFIG1_PACKETFORMAT_MASK ) |
+ ( ( fixLen == 1 ) ? RF_PACKETCONFIG1_PACKETFORMAT_FIXED : RF_PACKETCONFIG1_PACKETFORMAT_VARIABLE ) |
+ ( crcOn << 4 ) );
+ SX1276Write( REG_PACKETCONFIG2, ( SX1276Read( REG_PACKETCONFIG2 ) | RF_PACKETCONFIG2_DATAMODE_PACKET ) );
+ }
break;
case MODEM_LORA:
{
+ if( bandwidth > 2 )
+ {
+ // Fatal error: When using LoRa modem only bandwidths 125, 250 and 500 kHz are supported
+ while( 1 );
+ }
bandwidth += 7;
SX1276.Settings.LoRa.Bandwidth = bandwidth;
SX1276.Settings.LoRa.Datarate = datarate;
@@ -386,7 +502,7 @@ IRAM_ATTR void SX1276SetRxConfig( RadioModems_t modem, uint32_t bandwidth,
SX1276.Settings.LoRa.CrcOn = crcOn;
SX1276.Settings.LoRa.FreqHopOn = freqHopOn;
SX1276.Settings.LoRa.HopPeriod = hopPeriod;
- SX1276.Settings.LoRa.RxIqInverted = iqInverted;
+ SX1276.Settings.LoRa.IqInverted = iqInverted;
SX1276.Settings.LoRa.RxContinuous = rxContinuous;
if( datarate > 12 )
@@ -448,19 +564,19 @@ IRAM_ATTR void SX1276SetRxConfig( RadioModems_t modem, uint32_t bandwidth,
if( ( bandwidth == 9 ) && ( SX1276.Settings.Channel > RF_MID_BAND_THRESH ) )
{
// ERRATA 2.1 - Sensitivity Optimization with a 500 kHz Bandwidth
- SX1276Write( REG_LR_TEST36, 0x02 );
- SX1276Write( REG_LR_TEST3A, 0x64 );
+ SX1276Write( REG_LR_HIGHBWOPTIMIZE1, 0x02 );
+ SX1276Write( REG_LR_HIGHBWOPTIMIZE2, 0x64 );
}
else if( bandwidth == 9 )
{
// ERRATA 2.1 - Sensitivity Optimization with a 500 kHz Bandwidth
- SX1276Write( REG_LR_TEST36, 0x02 );
- SX1276Write( REG_LR_TEST3A, 0x7F );
+ SX1276Write( REG_LR_HIGHBWOPTIMIZE1, 0x02 );
+ SX1276Write( REG_LR_HIGHBWOPTIMIZE2, 0x7F );
}
else
{
// ERRATA 2.1 - Sensitivity Optimization with a 500 kHz Bandwidth
- SX1276Write( REG_LR_TEST36, 0x03 );
+ SX1276Write( REG_LR_HIGHBWOPTIMIZE1, 0x03 );
}
if( datarate == 6 )
@@ -499,6 +615,36 @@ void SX1276SetTxConfig( RadioModems_t modem, int8_t power, uint32_t fdev,
switch( modem )
{
case MODEM_FSK:
+ {
+ SX1276.Settings.Fsk.Power = power;
+ SX1276.Settings.Fsk.Fdev = fdev;
+ SX1276.Settings.Fsk.Bandwidth = bandwidth;
+ SX1276.Settings.Fsk.Datarate = datarate;
+ SX1276.Settings.Fsk.PreambleLen = preambleLen;
+ SX1276.Settings.Fsk.FixLen = fixLen;
+ SX1276.Settings.Fsk.CrcOn = crcOn;
+ SX1276.Settings.Fsk.IqInverted = iqInverted;
+ SX1276.Settings.Fsk.TxTimeout = timeout;
+
+ fdev = ( uint16_t )( ( double )fdev / ( double )FREQ_STEP );
+ SX1276Write( REG_FDEVMSB, ( uint8_t )( fdev >> 8 ) );
+ SX1276Write( REG_FDEVLSB, ( uint8_t )( fdev & 0xFF ) );
+
+ datarate = ( uint16_t )( ( double )XTAL_FREQ / ( double )datarate );
+ SX1276Write( REG_BITRATEMSB, ( uint8_t )( datarate >> 8 ) );
+ SX1276Write( REG_BITRATELSB, ( uint8_t )( datarate & 0xFF ) );
+
+ SX1276Write( REG_PREAMBLEMSB, ( preambleLen >> 8 ) & 0x00FF );
+ SX1276Write( REG_PREAMBLELSB, preambleLen & 0xFF );
+
+ SX1276Write( REG_PACKETCONFIG1,
+ ( SX1276Read( REG_PACKETCONFIG1 ) &
+ RF_PACKETCONFIG1_CRC_MASK &
+ RF_PACKETCONFIG1_PACKETFORMAT_MASK ) |
+ ( ( fixLen == 1 ) ? RF_PACKETCONFIG1_PACKETFORMAT_FIXED : RF_PACKETCONFIG1_PACKETFORMAT_VARIABLE ) |
+ ( crcOn << 4 ) );
+ SX1276Write( REG_PACKETCONFIG2, ( SX1276Read( REG_PACKETCONFIG2 ) | RF_PACKETCONFIG2_DATAMODE_PACKET ) );
+ }
break;
case MODEM_LORA:
{
@@ -517,7 +663,7 @@ void SX1276SetTxConfig( RadioModems_t modem, int8_t power, uint32_t fdev,
SX1276.Settings.LoRa.FreqHopOn = freqHopOn;
SX1276.Settings.LoRa.HopPeriod = hopPeriod;
SX1276.Settings.LoRa.CrcOn = crcOn;
- SX1276.Settings.LoRa.TxIqInverted = iqInverted;
+ SX1276.Settings.LoRa.IqInverted = iqInverted;
SX1276.Settings.LoRa.TxTimeout = timeout;
if( datarate > 12 )
@@ -596,6 +742,15 @@ uint32_t SX1276GetTimeOnAir( RadioModems_t modem, uint8_t pktLen )
switch( modem )
{
case MODEM_FSK:
+ {
+ airTime = round( ( 8 * ( SX1276.Settings.Fsk.PreambleLen +
+ ( ( SX1276Read( REG_SYNCCONFIG ) & ~RF_SYNCCONFIG_SYNCSIZE_MASK ) + 1 ) +
+ ( ( SX1276.Settings.Fsk.FixLen == 0x01 ) ? 0.0 : 1.0 ) +
+ ( ( ( SX1276Read( REG_PACKETCONFIG1 ) & ~RF_PACKETCONFIG1_ADDRSFILTERING_MASK ) != 0x00 ) ? 1.0 : 0 ) +
+ pktLen +
+ ( ( SX1276.Settings.Fsk.CrcOn == 0x01 ) ? 2.0 : 0 ) ) /
+ SX1276.Settings.Fsk.Datarate ) * 1000 );
+ }
break;
case MODEM_LORA:
{
@@ -666,10 +821,38 @@ void SX1276Send( uint8_t *buffer, uint8_t size )
switch( SX1276.Settings.Modem )
{
case MODEM_FSK:
+ {
+ SX1276.Settings.FskPacketHandler.NbBytes = 0;
+ SX1276.Settings.FskPacketHandler.Size = size;
+
+ if( SX1276.Settings.Fsk.FixLen == false )
+ {
+ SX1276WriteFifo( ( uint8_t* )&size, 1 );
+ }
+ else
+ {
+ SX1276Write( REG_PAYLOADLENGTH, size );
+ }
+
+ if( ( size > 0 ) && ( size <= 64 ) )
+ {
+ SX1276.Settings.FskPacketHandler.ChunkSize = size;
+ }
+ else
+ {
+ memcpy1( RxTxBuffer, buffer, size );
+ SX1276.Settings.FskPacketHandler.ChunkSize = 32;
+ }
+
+ // Write payload buffer
+ SX1276WriteFifo( buffer, SX1276.Settings.FskPacketHandler.ChunkSize );
+ SX1276.Settings.FskPacketHandler.NbBytes += SX1276.Settings.FskPacketHandler.ChunkSize;
+ txTimeout = SX1276.Settings.Fsk.TxTimeout;
+ }
break;
case MODEM_LORA:
{
- if( SX1276.Settings.LoRa.TxIqInverted == true )
+ if( SX1276.Settings.LoRa.IqInverted == true )
{
SX1276Write( REG_LR_INVERTIQ, ( ( SX1276Read( REG_LR_INVERTIQ ) & RFLR_INVERTIQ_TX_MASK & RFLR_INVERTIQ_RX_MASK ) | RFLR_INVERTIQ_RX_OFF | RFLR_INVERTIQ_TX_ON ) );
SX1276Write( REG_LR_INVERTIQ2, RFLR_INVERTIQ2_ON );
@@ -709,8 +892,13 @@ IRAM_ATTR void SX1276SetSleep( void )
{
TimerStop( &RxTimeoutTimer );
TimerStop( &TxTimeoutTimer );
+ TimerStop( &RxTimeoutSyncWord );
SX1276SetOpMode( RF_OPMODE_SLEEP );
+
+ // Disable TCXO radio is in SLEEP mode
+ SX1276SetBoardTcxo( false );
+
SX1276.Settings.State = RF_IDLE;
}
@@ -718,6 +906,7 @@ void SX1276SetStby( void )
{
TimerStop( &RxTimeoutTimer );
TimerStop( &TxTimeoutTimer );
+ TimerStop( &RxTimeoutSyncWord );
SX1276SetOpMode( RF_OPMODE_STANDBY );
SX1276.Settings.State = RF_IDLE;
@@ -726,14 +915,45 @@ void SX1276SetStby( void )
IRAM_ATTR void SX1276SetRx( uint32_t timeout )
{
bool rxContinuous = false;
+ TimerStop( &TxTimeoutTimer );
switch( SX1276.Settings.Modem )
{
case MODEM_FSK:
+ {
+ rxContinuous = SX1276.Settings.Fsk.RxContinuous;
+
+ // DIO0=PayloadReady
+ // DIO1=FifoLevel
+ // DIO2=SyncAddr
+ // DIO3=FifoEmpty
+ // DIO4=Preamble
+ // DIO5=ModeReady
+ SX1276Write( REG_DIOMAPPING1, ( SX1276Read( REG_DIOMAPPING1 ) & RF_DIOMAPPING1_DIO0_MASK &
+ RF_DIOMAPPING1_DIO1_MASK &
+ RF_DIOMAPPING1_DIO2_MASK ) |
+ RF_DIOMAPPING1_DIO0_00 |
+ RF_DIOMAPPING1_DIO1_00 |
+ RF_DIOMAPPING1_DIO2_11 );
+
+ SX1276Write( REG_DIOMAPPING2, ( SX1276Read( REG_DIOMAPPING2 ) & RF_DIOMAPPING2_DIO4_MASK &
+ RF_DIOMAPPING2_MAP_MASK ) |
+ RF_DIOMAPPING2_DIO4_11 |
+ RF_DIOMAPPING2_MAP_PREAMBLEDETECT );
+
+ SX1276.Settings.FskPacketHandler.FifoThresh = SX1276Read( REG_FIFOTHRESH ) & 0x3F;
+
+ SX1276Write( REG_RXCONFIG, RF_RXCONFIG_AFCAUTO_ON | RF_RXCONFIG_AGCAUTO_ON | RF_RXCONFIG_RXTRIGER_PREAMBLEDETECT );
+
+ SX1276.Settings.FskPacketHandler.PreambleDetected = false;
+ SX1276.Settings.FskPacketHandler.SyncWordDetected = false;
+ SX1276.Settings.FskPacketHandler.NbBytes = 0;
+ SX1276.Settings.FskPacketHandler.Size = 0;
+ }
break;
case MODEM_LORA:
{
- if( SX1276.Settings.LoRa.RxIqInverted == true )
+ if( SX1276.Settings.LoRa.IqInverted == true )
{
SX1276Write( REG_LR_INVERTIQ, ( ( SX1276Read( REG_LR_INVERTIQ ) & RFLR_INVERTIQ_TX_MASK & RFLR_INVERTIQ_RX_MASK ) | RFLR_INVERTIQ_RX_ON | RFLR_INVERTIQ_TX_OFF ) );
SX1276Write( REG_LR_INVERTIQ2, RFLR_INVERTIQ2_ON );
@@ -748,41 +968,41 @@ IRAM_ATTR void SX1276SetRx( uint32_t timeout )
if( SX1276.Settings.LoRa.Bandwidth < 9 )
{
SX1276Write( REG_LR_DETECTOPTIMIZE, SX1276Read( REG_LR_DETECTOPTIMIZE ) & 0x7F );
- SX1276Write( REG_LR_TEST30, 0x00 );
+ SX1276Write( REG_LR_IFFREQ2, 0x00 );
switch( SX1276.Settings.LoRa.Bandwidth )
{
case 0: // 7.8 kHz
- SX1276Write( REG_LR_TEST2F, 0x48 );
+ SX1276Write( REG_LR_IFFREQ1, 0x48 );
SX1276SetChannel(SX1276.Settings.Channel + 7810 );
break;
case 1: // 10.4 kHz
- SX1276Write( REG_LR_TEST2F, 0x44 );
+ SX1276Write( REG_LR_IFFREQ1, 0x44 );
SX1276SetChannel(SX1276.Settings.Channel + 10420 );
break;
case 2: // 15.6 kHz
- SX1276Write( REG_LR_TEST2F, 0x44 );
+ SX1276Write( REG_LR_IFFREQ1, 0x44 );
SX1276SetChannel(SX1276.Settings.Channel + 15620 );
break;
case 3: // 20.8 kHz
- SX1276Write( REG_LR_TEST2F, 0x44 );
+ SX1276Write( REG_LR_IFFREQ1, 0x44 );
SX1276SetChannel(SX1276.Settings.Channel + 20830 );
break;
case 4: // 31.2 kHz
- SX1276Write( REG_LR_TEST2F, 0x44 );
+ SX1276Write( REG_LR_IFFREQ1, 0x44 );
SX1276SetChannel(SX1276.Settings.Channel + 31250 );
break;
case 5: // 41.4 kHz
- SX1276Write( REG_LR_TEST2F, 0x44 );
+ SX1276Write( REG_LR_IFFREQ1, 0x44 );
SX1276SetChannel(SX1276.Settings.Channel + 41670 );
break;
case 6: // 62.5 kHz
- SX1276Write( REG_LR_TEST2F, 0x40 );
+ SX1276Write( REG_LR_IFFREQ1, 0x40 );
break;
case 7: // 125 kHz
- SX1276Write( REG_LR_TEST2F, 0x40 );
+ SX1276Write( REG_LR_IFFREQ1, 0x40 );
break;
case 8: // 250 kHz
- SX1276Write( REG_LR_TEST2F, 0x40 );
+ SX1276Write( REG_LR_IFFREQ1, 0x40 );
break;
}
}
@@ -836,7 +1056,14 @@ IRAM_ATTR void SX1276SetRx( uint32_t timeout )
TimerStart( &RxTimeoutTimer );
}
- if( SX1276.Settings.Modem == MODEM_LORA )
+ if( SX1276.Settings.Modem == MODEM_FSK )
+ {
+ SX1276SetOpMode( RF_OPMODE_RECEIVER );
+
+ TimerSetValue( &RxTimeoutSyncWord, SX1276.Settings.Fsk.RxSingleTimeout );
+ TimerStart( &RxTimeoutSyncWord );
+ }
+ else
{
if( rxContinuous == true )
{
@@ -851,11 +1078,29 @@ IRAM_ATTR void SX1276SetRx( uint32_t timeout )
void SX1276SetTx( uint32_t timeout )
{
+ TimerStop( &RxTimeoutTimer );
+
TimerSetValue( &TxTimeoutTimer, timeout );
switch( SX1276.Settings.Modem )
{
case MODEM_FSK:
+ {
+ // DIO0=PacketSent
+ // DIO1=FifoEmpty
+ // DIO2=FifoFull
+ // DIO3=FifoEmpty
+ // DIO4=LowBat
+ // DIO5=ModeReady
+ SX1276Write( REG_DIOMAPPING1, ( SX1276Read( REG_DIOMAPPING1 ) & RF_DIOMAPPING1_DIO0_MASK &
+ RF_DIOMAPPING1_DIO1_MASK &
+ RF_DIOMAPPING1_DIO2_MASK ) |
+ RF_DIOMAPPING1_DIO1_01 );
+
+ SX1276Write( REG_DIOMAPPING2, ( SX1276Read( REG_DIOMAPPING2 ) & RF_DIOMAPPING2_DIO4_MASK &
+ RF_DIOMAPPING2_MAP_MASK ) );
+ SX1276.Settings.FskPacketHandler.FifoThresh = SX1276Read( REG_FIFOTHRESH ) & 0x3F;
+ }
break;
case MODEM_LORA:
{
@@ -901,6 +1146,9 @@ void SX1276StartCad( void )
switch( SX1276.Settings.Modem )
{
case MODEM_FSK:
+ {
+
+ }
break;
case MODEM_LORA:
{
@@ -948,11 +1196,12 @@ void SX1276SetTxContinuousWave( uint32_t freq, int8_t power, uint16_t time )
int16_t SX1276ReadRssi( RadioModems_t modem )
{
- int16_t rssi = -1;
+ int16_t rssi = 0;
switch( modem )
{
case MODEM_FSK:
+ rssi = -( SX1276Read( REG_RSSIVALUE ) >> 1 );
break;
case MODEM_LORA:
if( SX1276.Settings.Channel > RF_MID_BAND_THRESH )
@@ -965,32 +1214,43 @@ int16_t SX1276ReadRssi( RadioModems_t modem )
}
break;
default:
+ rssi = -1;
break;
}
return rssi;
}
-void SX1276Reset( void )
-{
- if (micropy_lpwan_use_reset_pin) {
- // Set RESET pin to 0
- GpioInit( &SX1276.Reset, RADIO_RESET, PIN_OUTPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 );
-
- // Wait 2 ms
- DelayMs( 2 );
-
- // Configure RESET as input
- GpioInit( &SX1276.Reset, RADIO_RESET, PIN_INPUT, PIN_PUSH_PULL, PIN_NO_PULL, 1 );
-
- // Wait 6 ms
- DelayMs( 6 );
- } else {
- DelayMs( 2 );
- }
-}
-
IRAM_ATTR void SX1276SetOpMode( uint8_t opMode )
{
+#if defined( USE_RADIO_DEBUG )
+ switch( opMode )
+ {
+ case RF_OPMODE_TRANSMITTER:
+ SX1276DbgPinTxWrite( 1 );
+ SX1276DbgPinRxWrite( 0 );
+ break;
+ case RF_OPMODE_RECEIVER:
+ case RFLR_OPMODE_RECEIVER_SINGLE:
+ SX1276DbgPinTxWrite( 0 );
+ SX1276DbgPinRxWrite( 1 );
+ break;
+ default:
+ SX1276DbgPinTxWrite( 0 );
+ SX1276DbgPinRxWrite( 0 );
+ break;
+ }
+#endif
+ if( opMode == RF_OPMODE_SLEEP )
+ {
+ SX1276SetAntSwLowPower( true );
+ }
+ else
+ {
+ // Enable TCXO if operating mode different from SLEEP.
+ SX1276SetBoardTcxo( true );
+ SX1276SetAntSwLowPower( false );
+ SX1276SetAntSw( opMode );
+ }
SX1276Write( REG_OPMODE, ( SX1276Read( REG_OPMODE ) & RF_OPMODE_MASK ) | opMode );
}
@@ -1031,51 +1291,56 @@ IRAM_ATTR void SX1276SetModem( RadioModems_t modem )
}
}
-IRAM_ATTR void SX1276Write( uint8_t addr, uint8_t data )
+IRAM_ATTR void SX1276Write( uint16_t addr, uint8_t data )
{
- SX1276WriteBuffer( addr, &data, 1 );
+ uint16_t data16 = data;
+ data16 = (data16<<8) + (addr|0x80);
+ //NSS = 0;
+ GPIO_REG_WRITE(GPIO_OUT_W1TC_REG, 1 << LPWAN_NCS_PIN_NUMBER);
+
+ SpiIn0Out16(&SX1276.Spi, data16);
+
+ //NSS = 1;
+ GPIO_REG_WRITE(GPIO_OUT_W1TS_REG, 1 << LPWAN_NCS_PIN_NUMBER);
}
-IRAM_ATTR uint8_t SX1276Read( uint8_t addr )
+IRAM_ATTR uint8_t SX1276Read( uint16_t addr )
{
uint8_t data;
- SX1276ReadBuffer( addr, &data, 1 );
+
+ //NSS = 0;
+ GPIO_REG_WRITE(GPIO_OUT_W1TC_REG, 1 << LPWAN_NCS_PIN_NUMBER);
+
+ data = SpiIn8Out16(&SX1276.Spi, addr&0x7F);
+
+ //NSS = 1;
+ GPIO_REG_WRITE(GPIO_OUT_W1TS_REG, 1 << LPWAN_NCS_PIN_NUMBER);
+
return data;
}
-IRAM_ATTR void SX1276WriteBuffer( uint8_t addr, uint8_t *buffer, uint8_t size )
+IRAM_ATTR void SX1276WriteBuffer( uint16_t addr, uint8_t *buffer, uint8_t size )
{
- uint8_t i;
-
//NSS = 0;
- GpioWrite( &SX1276.Spi.Nss, 0 );
+ GPIO_REG_WRITE(GPIO_OUT_W1TC_REG, 1 << LPWAN_NCS_PIN_NUMBER);
SpiInOut( &SX1276.Spi, addr | 0x80 );
- for( i = 0; i < size; i++ )
- {
- SpiInOut( &SX1276.Spi, buffer[i] );
- }
+ SpiOutBuf(&SX1276.Spi, buffer, size);
//NSS = 1;
- GpioWrite( &SX1276.Spi.Nss, 1 );
+ GPIO_REG_WRITE(GPIO_OUT_W1TS_REG, 1 << LPWAN_NCS_PIN_NUMBER);
}
-IRAM_ATTR void SX1276ReadBuffer( uint8_t addr, uint8_t *buffer, uint8_t size )
+IRAM_ATTR void SX1276ReadBuffer( uint16_t addr, uint8_t *buffer, uint8_t size )
{
- uint8_t i;
-
//NSS = 0;
- GpioWrite( &SX1276.Spi.Nss, 0 );
+ GPIO_REG_WRITE(GPIO_OUT_W1TC_REG, 1 << LPWAN_NCS_PIN_NUMBER);
SpiInOut( &SX1276.Spi, addr & 0x7F );
-
- for( i = 0; i < size; i++ )
- {
- buffer[i] = SpiInOut( &SX1276.Spi, 0 );
- }
+ SpiInBuf(&SX1276.Spi, buffer, size);
//NSS = 1;
- GpioWrite( &SX1276.Spi.Nss, 1 );
+ GPIO_REG_WRITE(GPIO_OUT_W1TS_REG, 1 << LPWAN_NCS_PIN_NUMBER);
}
IRAM_ATTR void SX1276WriteFifo( uint8_t *buffer, uint8_t size )
@@ -1083,7 +1348,7 @@ IRAM_ATTR void SX1276WriteFifo( uint8_t *buffer, uint8_t size )
SX1276WriteBuffer( 0, buffer, size );
}
-IRAM_ATTR void SX1276ReadFifo( uint8_t *buffer, uint8_t size )
+void SX1276ReadFifo( uint8_t *buffer, uint8_t size )
{
SX1276ReadBuffer( 0, buffer, size );
}
@@ -1095,6 +1360,10 @@ IRAM_ATTR void SX1276SetMaxPayloadLength( RadioModems_t modem, uint8_t max )
switch( modem )
{
case MODEM_FSK:
+ if( SX1276.Settings.Fsk.FixLen == false )
+ {
+ SX1276Write( REG_PAYLOADLENGTH, max );
+ }
break;
case MODEM_LORA:
SX1276Write( REG_LR_PAYLOADMAXLENGTH, max );
@@ -1118,11 +1387,41 @@ void SX1276SetPublicNetwork( bool enable )
}
}
-void SX1276OnTimeoutIrq( void )
+uint32_t SX1276GetWakeupTime( void )
+{
+ return SX1276GetBoardTcxoWakeupTime( ) + RADIO_WAKEUP_TIME;
+}
+
+void SX1276OnTimeoutIrq( void* context )
{
switch( SX1276.Settings.State )
{
case RF_RX_RUNNING:
+ if( SX1276.Settings.Modem == MODEM_FSK )
+ {
+ SX1276.Settings.FskPacketHandler.PreambleDetected = false;
+ SX1276.Settings.FskPacketHandler.SyncWordDetected = false;
+ SX1276.Settings.FskPacketHandler.NbBytes = 0;
+ SX1276.Settings.FskPacketHandler.Size = 0;
+
+ // Clear Irqs
+ SX1276Write( REG_IRQFLAGS1, RF_IRQFLAGS1_RSSI |
+ RF_IRQFLAGS1_PREAMBLEDETECT |
+ RF_IRQFLAGS1_SYNCADDRESSMATCH );
+ SX1276Write( REG_IRQFLAGS2, RF_IRQFLAGS2_FIFOOVERRUN );
+
+ if( SX1276.Settings.Fsk.RxContinuous == true )
+ {
+ // Continuous mode restart Rx chain
+ SX1276Write( REG_RXCONFIG, SX1276Read( REG_RXCONFIG ) | RF_RXCONFIG_RESTARTRXWITHOUTPLLLOCK );
+ TimerStart( &RxTimeoutSyncWord );
+ }
+ else
+ {
+ SX1276.Settings.State = RF_IDLE;
+ TimerStop( &RxTimeoutSyncWord );
+ }
+ }
if( ( RadioEvents != NULL ) && ( RadioEvents->RxTimeout != NULL ) )
{
RadioEvents->RxTimeout( );
@@ -1130,10 +1429,12 @@ void SX1276OnTimeoutIrq( void )
break;
case RF_TX_RUNNING:
// Tx timeout shouldn't happen.
- // But it has been observed that when it happens it is a result of a corrupted SPI transfer
- // it depends on the platform design.
- //
- // The workaround is to put the radio in a known state. Thus, we re-initialize it.
+ // Reported issue of SPI data corruption resulting in TX TIMEOUT
+ // is NOT related to a bug in radio transceiver.
+ // It is mainly caused by improper PCB routing of SPI lines and/or
+ // violation of SPI specifications.
+ // To mitigate redesign, Semtech offers a workaround which resets
+ // the radio transceiver and putting it into a known state.
// BEGIN WORKAROUND
@@ -1168,7 +1469,7 @@ void SX1276OnTimeoutIrq( void )
}
}
-IRAM_ATTR void SX1276RadioFlagsIrq (void) {
+IRAM_ATTR void SX1276RadioFlagsIrq (void *context) {
if (SX1276.irqFlags & RADIO_IRQ_FLAG_RX_TIMEOUT) {
SX1276.irqFlags &= ~RADIO_IRQ_FLAG_RX_TIMEOUT;
if( ( RadioEvents != NULL ) && ( RadioEvents->RxTimeout != NULL ) )
@@ -1194,7 +1495,7 @@ IRAM_ATTR void SX1276RadioFlagsIrq (void) {
}
}
-static IRAM_ATTR void SX1276OnDioIrq (void) {
+static IRAM_ATTR void SX1276OnDioIrq (void *context) {
if (SX1276.Settings.State > RF_IDLE) {
// read the the irq flags registers
uint8_t volatile irqflags1;
@@ -1204,16 +1505,16 @@ static IRAM_ATTR void SX1276OnDioIrq (void) {
case MODEM_LORA:
irqflags1 = SX1276Read(REG_LR_IRQFLAGS);
if ((irqflags1 & RFLR_IRQFLAGS_RXDONE) || (irqflags1 & RFLR_IRQFLAGS_TXDONE)) {
- SX1276OnDio0Irq();
+ SX1276OnDio0Irq(NULL);
}
if (irqflags1 & RFLR_IRQFLAGS_RXTIMEOUT) {
- SX1276OnDio1Irq();
+ SX1276OnDio1Irq(NULL);
}
if (SX1276.Settings.LoRa.FreqHopOn == true && (irqflags1 & RFLR_IRQFLAGS_FHSSCHANGEDCHANNEL)) {
- SX1276OnDio2Irq();
+ SX1276OnDio2Irq(NULL);
}
if ((irqflags1 & RFLR_IRQFLAGS_CADDETECTED) || (irqflags1 & RFLR_IRQFLAGS_CADDONE)) {
- SX1276OnDio3Irq();
+ SX1276OnDio3Irq(NULL);
}
break;
default:
@@ -1222,22 +1523,101 @@ static IRAM_ATTR void SX1276OnDioIrq (void) {
}
}
-IRAM_ATTR void SX1276OnDio0Irq( void )
+IRAM_ATTR void SX1276OnDio0Irq( void* context )
{
volatile uint8_t irqFlags = 0;
switch( SX1276.Settings.State )
{
case RF_RX_RUNNING:
+ //TimerStop( &RxTimeoutTimer );
// RxDone interrupt
switch( SX1276.Settings.Modem )
{
case MODEM_FSK:
+ if( SX1276.Settings.Fsk.CrcOn == true )
+ {
+ irqFlags = SX1276Read( REG_IRQFLAGS2 );
+ if( ( irqFlags & RF_IRQFLAGS2_CRCOK ) != RF_IRQFLAGS2_CRCOK )
+ {
+ // Clear Irqs
+ SX1276Write( REG_IRQFLAGS1, RF_IRQFLAGS1_RSSI |
+ RF_IRQFLAGS1_PREAMBLEDETECT |
+ RF_IRQFLAGS1_SYNCADDRESSMATCH );
+ SX1276Write( REG_IRQFLAGS2, RF_IRQFLAGS2_FIFOOVERRUN );
+
+ TimerStop( &RxTimeoutTimer );
+
+ if( SX1276.Settings.Fsk.RxContinuous == false )
+ {
+ TimerStop( &RxTimeoutSyncWord );
+ SX1276.Settings.State = RF_IDLE;
+ }
+ else
+ {
+ // Continuous mode restart Rx chain
+ SX1276Write( REG_RXCONFIG, SX1276Read( REG_RXCONFIG ) | RF_RXCONFIG_RESTARTRXWITHOUTPLLLOCK );
+ TimerStart( &RxTimeoutSyncWord );
+ }
+
+ if( ( RadioEvents != NULL ) && ( RadioEvents->RxError != NULL ) )
+ {
+ RadioEvents->RxError( );
+ }
+ SX1276.Settings.FskPacketHandler.PreambleDetected = false;
+ SX1276.Settings.FskPacketHandler.SyncWordDetected = false;
+ SX1276.Settings.FskPacketHandler.NbBytes = 0;
+ SX1276.Settings.FskPacketHandler.Size = 0;
+ break;
+ }
+ }
+
+ // Read received packet size
+ if( ( SX1276.Settings.FskPacketHandler.Size == 0 ) && ( SX1276.Settings.FskPacketHandler.NbBytes == 0 ) )
+ {
+ if( SX1276.Settings.Fsk.FixLen == false )
+ {
+ SX1276ReadFifo( ( uint8_t* )&SX1276.Settings.FskPacketHandler.Size, 1 );
+ }
+ else
+ {
+ SX1276.Settings.FskPacketHandler.Size = SX1276Read( REG_PAYLOADLENGTH );
+ }
+ SX1276ReadFifo( RxTxBuffer + SX1276.Settings.FskPacketHandler.NbBytes, SX1276.Settings.FskPacketHandler.Size - SX1276.Settings.FskPacketHandler.NbBytes );
+ SX1276.Settings.FskPacketHandler.NbBytes += ( SX1276.Settings.FskPacketHandler.Size - SX1276.Settings.FskPacketHandler.NbBytes );
+ }
+ else
+ {
+ SX1276ReadFifo( RxTxBuffer + SX1276.Settings.FskPacketHandler.NbBytes, SX1276.Settings.FskPacketHandler.Size - SX1276.Settings.FskPacketHandler.NbBytes );
+ SX1276.Settings.FskPacketHandler.NbBytes += ( SX1276.Settings.FskPacketHandler.Size - SX1276.Settings.FskPacketHandler.NbBytes );
+ }
+
+ TimerStop( &RxTimeoutTimer );
+
+ if( SX1276.Settings.Fsk.RxContinuous == false )
+ {
+ SX1276.Settings.State = RF_IDLE;
+ TimerStop( &RxTimeoutSyncWord );
+ }
+ else
+ {
+ // Continuous mode restart Rx chain
+ SX1276Write( REG_RXCONFIG, SX1276Read( REG_RXCONFIG ) | RF_RXCONFIG_RESTARTRXWITHOUTPLLLOCK );
+ TimerStart( &RxTimeoutSyncWord );
+ }
+
+ if( ( RadioEvents != NULL ) && ( RadioEvents->RxDone != NULL ) )
+ {
+ // TODO: Add proper handling of Timestamp and sf parameters for FSK
+ RadioEvents->RxDone( RxTxBuffer, 0, SX1276.Settings.FskPacketHandler.Size, SX1276.Settings.FskPacketHandler.RssiValue, 0, 0 );
+ }
+ SX1276.Settings.FskPacketHandler.PreambleDetected = false;
+ SX1276.Settings.FskPacketHandler.SyncWordDetected = false;
+ SX1276.Settings.FskPacketHandler.NbBytes = 0;
+ SX1276.Settings.FskPacketHandler.Size = 0;
break;
case MODEM_LORA:
{
- int8_t snr = 0;
-
// Store the packet timestamp
SX1276.Settings.LoRaPacketHandler.TimeStamp = mp_hal_ticks_us_non_blocking();
@@ -1262,31 +1642,21 @@ IRAM_ATTR void SX1276OnDio0Irq( void )
break;
}
- SX1276.Settings.LoRaPacketHandler.SnrValue = SX1276Read( REG_LR_PKTSNRVALUE );
- if( SX1276.Settings.LoRaPacketHandler.SnrValue & 0x80 ) // The SNR sign bit is 1
- {
- // Invert and divide by 4
- snr = ( ( ~SX1276.Settings.LoRaPacketHandler.SnrValue + 1 ) & 0xFF ) >> 2;
- snr = -snr;
- }
- else
- {
- // Divide by 4
- snr = ( SX1276.Settings.LoRaPacketHandler.SnrValue & 0xFF ) >> 2;
- }
+ // Returns SNR value [dB] rounded to the nearest integer value
+ SX1276.Settings.LoRaPacketHandler.SnrValue = ( ( ( int8_t )SX1276Read( REG_LR_PKTSNRVALUE ) ) + 2 ) >> 2;
int16_t rssi = SX1276Read( REG_LR_PKTRSSIVALUE );
- if( snr < 0 )
+ if( SX1276.Settings.LoRaPacketHandler.SnrValue < 0 )
{
if( SX1276.Settings.Channel > RF_MID_BAND_THRESH )
{
SX1276.Settings.LoRaPacketHandler.RssiValue = RSSI_OFFSET_HF + rssi + ( rssi >> 4 ) +
- snr;
+ SX1276.Settings.LoRaPacketHandler.SnrValue;
}
else
{
SX1276.Settings.LoRaPacketHandler.RssiValue = RSSI_OFFSET_LF + rssi + ( rssi >> 4 ) +
- snr;
+ SX1276.Settings.LoRaPacketHandler.SnrValue;
}
}
else
@@ -1344,7 +1714,7 @@ IRAM_ATTR void SX1276OnDio0Irq( void )
}
}
-IRAM_ATTR void SX1276OnDio1Irq( void )
+IRAM_ATTR void SX1276OnDio1Irq( void* context )
{
switch( SX1276.Settings.State )
{
@@ -1352,6 +1722,40 @@ IRAM_ATTR void SX1276OnDio1Irq( void )
switch( SX1276.Settings.Modem )
{
case MODEM_FSK:
+ // Stop timer
+ TimerStop( &RxTimeoutSyncWord );
+
+ // FifoLevel interrupt
+ // Read received packet size
+ if( ( SX1276.Settings.FskPacketHandler.Size == 0 ) && ( SX1276.Settings.FskPacketHandler.NbBytes == 0 ) )
+ {
+ if( SX1276.Settings.Fsk.FixLen == false )
+ {
+ SX1276ReadFifo( ( uint8_t* )&SX1276.Settings.FskPacketHandler.Size, 1 );
+ }
+ else
+ {
+ SX1276.Settings.FskPacketHandler.Size = SX1276Read( REG_PAYLOADLENGTH );
+ }
+ }
+
+ // ERRATA 3.1 - PayloadReady Set for 31.25ns if FIFO is Empty
+ //
+ // When FifoLevel interrupt is used to offload the
+ // FIFO, the microcontroller should monitor both
+ // PayloadReady and FifoLevel interrupts, and
+ // read only (FifoThreshold-1) bytes off the FIFO
+ // when FifoLevel fires
+ if( ( SX1276.Settings.FskPacketHandler.Size - SX1276.Settings.FskPacketHandler.NbBytes ) >= SX1276.Settings.FskPacketHandler.FifoThresh )
+ {
+ SX1276ReadFifo( ( RxTxBuffer + SX1276.Settings.FskPacketHandler.NbBytes ), SX1276.Settings.FskPacketHandler.FifoThresh - 1 );
+ SX1276.Settings.FskPacketHandler.NbBytes += SX1276.Settings.FskPacketHandler.FifoThresh - 1;
+ }
+ else
+ {
+ SX1276ReadFifo( ( RxTxBuffer + SX1276.Settings.FskPacketHandler.NbBytes ), SX1276.Settings.FskPacketHandler.Size - SX1276.Settings.FskPacketHandler.NbBytes );
+ SX1276.Settings.FskPacketHandler.NbBytes += ( SX1276.Settings.FskPacketHandler.Size - SX1276.Settings.FskPacketHandler.NbBytes );
+ }
break;
case MODEM_LORA:
// Sync time out
@@ -1373,6 +1777,18 @@ IRAM_ATTR void SX1276OnDio1Irq( void )
switch( SX1276.Settings.Modem )
{
case MODEM_FSK:
+ // FifoEmpty interrupt
+ if( ( SX1276.Settings.FskPacketHandler.Size - SX1276.Settings.FskPacketHandler.NbBytes ) > SX1276.Settings.FskPacketHandler.ChunkSize )
+ {
+ SX1276WriteFifo( ( RxTxBuffer + SX1276.Settings.FskPacketHandler.NbBytes ), SX1276.Settings.FskPacketHandler.ChunkSize );
+ SX1276.Settings.FskPacketHandler.NbBytes += SX1276.Settings.FskPacketHandler.ChunkSize;
+ }
+ else
+ {
+ // Write the last chunk of data
+ SX1276WriteFifo( RxTxBuffer + SX1276.Settings.FskPacketHandler.NbBytes, SX1276.Settings.FskPacketHandler.Size - SX1276.Settings.FskPacketHandler.NbBytes );
+ SX1276.Settings.FskPacketHandler.NbBytes += SX1276.Settings.FskPacketHandler.Size - SX1276.Settings.FskPacketHandler.NbBytes;
+ }
break;
case MODEM_LORA:
break;
@@ -1385,7 +1801,7 @@ IRAM_ATTR void SX1276OnDio1Irq( void )
}
}
-IRAM_ATTR void SX1276OnDio2Irq( void )
+IRAM_ATTR void SX1276OnDio2Irq( void* context )
{
switch( SX1276.Settings.State )
{
@@ -1393,6 +1809,25 @@ IRAM_ATTR void SX1276OnDio2Irq( void )
switch( SX1276.Settings.Modem )
{
case MODEM_FSK:
+ // Checks if DIO4 is connected. If it is not PreambleDetected is set to true.
+ //if( SX1276.DIO4.port == NULL ) TODO: The check needs to be updated when FSK is integrateds
+ {
+ SX1276.Settings.FskPacketHandler.PreambleDetected = true;
+ }
+
+ if( ( SX1276.Settings.FskPacketHandler.PreambleDetected == true ) && ( SX1276.Settings.FskPacketHandler.SyncWordDetected == false ) )
+ {
+ TimerStop( &RxTimeoutSyncWord );
+
+ SX1276.Settings.FskPacketHandler.SyncWordDetected = true;
+
+ SX1276.Settings.FskPacketHandler.RssiValue = -( SX1276Read( REG_RSSIVALUE ) >> 1 );
+
+ SX1276.Settings.FskPacketHandler.AfcValue = ( int32_t )( double )( ( ( uint16_t )SX1276Read( REG_AFCMSB ) << 8 ) |
+ ( uint16_t )SX1276Read( REG_AFCLSB ) ) *
+ ( double )FREQ_STEP;
+ SX1276.Settings.FskPacketHandler.RxGain = ( SX1276Read( REG_LNA ) >> 5 ) & 0x07;
+ }
break;
case MODEM_LORA:
if( SX1276.Settings.LoRa.FreqHopOn == true )
@@ -1436,7 +1871,7 @@ IRAM_ATTR void SX1276OnDio2Irq( void )
}
}
-IRAM_ATTR void SX1276OnDio3Irq( void )
+IRAM_ATTR void SX1276OnDio3Irq( void* context )
{
switch( SX1276.Settings.Modem )
{
@@ -1467,11 +1902,17 @@ IRAM_ATTR void SX1276OnDio3Irq( void )
}
}
-IRAM_ATTR void SX1276OnDio4Irq( void )
+IRAM_ATTR void SX1276OnDio4Irq( void* context )
{
switch( SX1276.Settings.Modem )
{
case MODEM_FSK:
+ {
+ if( SX1276.Settings.FskPacketHandler.PreambleDetected == false )
+ {
+ SX1276.Settings.FskPacketHandler.PreambleDetected = true;
+ }
+ }
break;
case MODEM_LORA:
break;
@@ -1480,8 +1921,7 @@ IRAM_ATTR void SX1276OnDio4Irq( void )
}
}
-// not used
-void SX1276OnDio5Irq( void )
+IRAM_ATTR void SX1276OnDio5Irq( void* context )
{
switch( SX1276.Settings.Modem )
{
diff --git a/drivers/sx127x/sx1276/sx1276.h b/drivers/sx127x/sx1276/sx1276.h
index 94a192fbd4..266dbf49dd 100755
--- a/drivers/sx127x/sx1276/sx1276.h
+++ b/drivers/sx127x/sx1276/sx1276.h
@@ -1,20 +1,38 @@
-/*
- / _____) _ | |
-( (____ _____ ____ _| |_ _____ ____| |__
- \____ \| ___ | (_ _) ___ |/ ___) _ \
- _____) ) ____| | | || |_| ____( (___| | | |
-(______/|_____)_|_|_| \__)_____)\____)_| |_|
- (C)2013 Semtech
-
-Description: Generic SX1276 driver implementation
-
-License: Revised BSD License, see LICENSE.TXT file include in the project
-
-Maintainer: Miguel Luis and Gregory Cristian
-*/
+/*!
+ * \file sx1276.h
+ *
+ * \brief SX1276 driver implementation
+ *
+ * \copyright Revised BSD License, see section \ref LICENSE.
+ *
+ * \code
+ * ______ _
+ * / _____) _ | |
+ * ( (____ _____ ____ _| |_ _____ ____| |__
+ * \____ \| ___ | (_ _) ___ |/ ___) _ \
+ * _____) ) ____| | | || |_| ____( (___| | | |
+ * (______/|_____)_|_|_| \__)_____)\____)_| |_|
+ * (C)2013-2017 Semtech
+ *
+ * \endcode
+ *
+ * \author Miguel Luis ( Semtech )
+ *
+ * \author Gregory Cristian ( Semtech )
+ */
#ifndef __SX1276_H__
#define __SX1276_H__
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+// #include
+// #include
+// #include "gpio.h"
+// #include "spi.h"
+// #include "radio.h"
#include "sx1276Regs-Fsk.h"
#include "sx1276Regs-LoRa.h"
@@ -47,8 +65,7 @@ typedef struct
bool FixLen;
uint8_t PayloadLen;
bool CrcOn;
- bool RxIqInverted;
- bool TxIqInverted;
+ bool IqInverted;
bool RxContinuous;
uint32_t TxTimeout;
uint32_t RxSingleTimeout;
@@ -86,8 +103,7 @@ typedef struct
bool CrcOn;
bool FreqHopOn;
uint8_t HopPeriod;
- bool RxIqInverted;
- bool TxIqInverted;
+ bool IqInverted;
bool RxContinuous;
uint32_t TxTimeout;
bool PublicNetwork;
@@ -99,8 +115,8 @@ typedef struct
typedef struct
{
uint32_t TimeStamp;
- int16_t RssiValue;
int8_t SnrValue;
+ int16_t RssiValue;
uint8_t Size;
}RadioLoRaPacketHandler_t;
@@ -112,6 +128,8 @@ typedef struct
RadioState_t State;
RadioModems_t Modem;
uint32_t Channel;
+ RadioFskSettings_t Fsk;
+ RadioFskPacketHandler_t FskPacketHandler;
RadioLoRaSettings_t LoRa;
RadioLoRaPacketHandler_t LoRaPacketHandler;
}RadioSettings_t;
@@ -131,7 +149,7 @@ typedef struct SX1276_s
/*!
* Hardware IO IRQ callback function definition
*/
-typedef void ( DioIrqHandler )( void );
+typedef void ( DioIrqHandler )( void* context );
/*!
* SX1276 definitions
@@ -362,7 +380,7 @@ int16_t SX1276ReadRssi( RadioModems_t modem );
* \param [IN]: addr Register address
* \param [IN]: data New register value
*/
-void SX1276Write( uint8_t addr, uint8_t data );
+void SX1276Write( uint16_t addr, uint8_t data );
/*!
* \brief Reads the radio register at the specified address
@@ -370,7 +388,7 @@ void SX1276Write( uint8_t addr, uint8_t data );
* \param [IN]: addr Register address
* \retval data Register value
*/
-uint8_t SX1276Read( uint8_t addr );
+uint8_t SX1276Read( uint16_t addr );
/*!
* \brief Writes multiple radio registers starting at address
@@ -379,7 +397,7 @@ uint8_t SX1276Read( uint8_t addr );
* \param [IN] buffer Buffer containing the new register's values
* \param [IN] size Number of registers to be written
*/
-void SX1276WriteBuffer( uint8_t addr, uint8_t *buffer, uint8_t size );
+void SX1276WriteBuffer( uint16_t addr, uint8_t *buffer, uint8_t size );
/*!
* \brief Reads multiple radio registers starting at address
@@ -388,7 +406,7 @@ void SX1276WriteBuffer( uint8_t addr, uint8_t *buffer, uint8_t size );
* \param [OUT] buffer Buffer where to copy the registers data
* \param [IN] size Number of registers to be read
*/
-void SX1276ReadBuffer( uint8_t addr, uint8_t *buffer, uint8_t size );
+void SX1276ReadBuffer( uint16_t addr, uint8_t *buffer, uint8_t size );
/*!
* \brief Sets the maximum payload length.
@@ -407,4 +425,15 @@ void SX1276SetMaxPayloadLength( RadioModems_t modem, uint8_t max );
*/
void SX1276SetPublicNetwork( bool enable );
+/*!
+ * \brief Gets the time required for the board plus radio to get out of sleep.[ms]
+ *
+ * \retval time Radio plus board wakeup time in ms.
+ */
+uint32_t SX1276GetWakeupTime( void );
+
+#ifdef __cplusplus
+}
+#endif
+
#endif // __SX1276_H__
diff --git a/drivers/sx127x/sx1276/sx1276Regs-Fsk.h b/drivers/sx127x/sx1276/sx1276Regs-Fsk.h
old mode 100755
new mode 100644
index 64ff293e2a..9808e7945b
--- a/drivers/sx127x/sx1276/sx1276Regs-Fsk.h
+++ b/drivers/sx127x/sx1276/sx1276Regs-Fsk.h
@@ -1,20 +1,33 @@
-/*
- / _____) _ | |
-( (____ _____ ____ _| |_ _____ ____| |__
- \____ \| ___ | (_ _) ___ |/ ___) _ \
- _____) ) ____| | | || |_| ____( (___| | | |
-(______/|_____)_|_|_| \__)_____)\____)_| |_|
- (C)2013 Semtech
-
-Description: SX1276 FSK modem registers and bits definitions
-
-License: Revised BSD License, see LICENSE.TXT file include in the project
-
-Maintainer: Miguel Luis and Gregory Cristian
-*/
+/*!
+ * \file sx1276Regs-Fsk.h
+ *
+ * \brief SX1276 FSK modem registers and bits definitions
+ *
+ * \copyright Revised BSD License, see section \ref LICENSE.
+ *
+ * \code
+ * ______ _
+ * / _____) _ | |
+ * ( (____ _____ ____ _| |_ _____ ____| |__
+ * \____ \| ___ | (_ _) ___ |/ ___) _ \
+ * _____) ) ____| | | || |_| ____( (___| | | |
+ * (______/|_____)_|_|_| \__)_____)\____)_| |_|
+ * (C)2013-2017 Semtech
+ *
+ * \endcode
+ *
+ * \author Miguel Luis ( Semtech )
+ *
+ * \author Gregory Cristian ( Semtech )
+ */
#ifndef __SX1276_REGS_FSK_H__
#define __SX1276_REGS_FSK_H__
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
/*!
* ============================================================================
* SX1276 Internal registers Address
@@ -1131,4 +1144,8 @@ Maintainer: Miguel Luis and Gregory Cristian
#define RF_PLL_BANDWIDTH_225 0x80
#define RF_PLL_BANDWIDTH_300 0xC0 // Default
+#ifdef __cplusplus
+}
+#endif
+
#endif // __SX1276_REGS_FSK_H__
diff --git a/drivers/sx127x/sx1276/sx1276Regs-LoRa.h b/drivers/sx127x/sx1276/sx1276Regs-LoRa.h
old mode 100755
new mode 100644
index e2fc751b3d..af9bb74b42
--- a/drivers/sx127x/sx1276/sx1276Regs-LoRa.h
+++ b/drivers/sx127x/sx1276/sx1276Regs-LoRa.h
@@ -1,20 +1,33 @@
-/*
- / _____) _ | |
-( (____ _____ ____ _| |_ _____ ____| |__
- \____ \| ___ | (_ _) ___ |/ ___) _ \
- _____) ) ____| | | || |_| ____( (___| | | |
-(______/|_____)_|_|_| \__)_____)\____)_| |_|
- (C)2013 Semtech
-
-Description: SX1276 LoRa modem registers and bits definitions
-
-License: Revised BSD License, see LICENSE.TXT file include in the project
-
-Maintainer: Miguel Luis and Gregory Cristian
-*/
+/*!
+ * \file sx1276Regs-LoRa.h
+ *
+ * \brief SX1276 LoRa modem registers and bits definitions
+ *
+ * \copyright Revised BSD License, see section \ref LICENSE.
+ *
+ * \code
+ * ______ _
+ * / _____) _ | |
+ * ( (____ _____ ____ _| |_ _____ ____| |__
+ * \____ \| ___ | (_ _) ___ |/ ___) _ \
+ * _____) ) ____| | | || |_| ____( (___| | | |
+ * (______/|_____)_|_|_| \__)_____)\____)_| |_|
+ * (C)2013-2017 Semtech
+ *
+ * \endcode
+ *
+ * \author Miguel Luis ( Semtech )
+ *
+ * \author Gregory Cristian ( Semtech )
+ */
#ifndef __SX1276_REGS_LORA_H__
#define __SX1276_REGS_LORA_H__
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
/*!
* ============================================================================
* SX1276 Internal registers Address
@@ -63,14 +76,14 @@ Maintainer: Miguel Luis and Gregory Cristian
#define REG_LR_FEIMID 0x29
#define REG_LR_FEILSB 0x2A
#define REG_LR_RSSIWIDEBAND 0x2C
-#define REG_LR_TEST2F 0x2F
-#define REG_LR_TEST30 0x30
+#define REG_LR_IFFREQ1 0x2F
+#define REG_LR_IFFREQ2 0x30
#define REG_LR_DETECTOPTIMIZE 0x31
#define REG_LR_INVERTIQ 0x33
-#define REG_LR_TEST36 0x36
+#define REG_LR_HIGHBWOPTIMIZE1 0x36
#define REG_LR_DETECTIONTHRESHOLD 0x37
#define REG_LR_SYNCWORD 0x39
-#define REG_LR_TEST3A 0x3A
+#define REG_LR_HIGHBWOPTIMIZE2 0x3A
#define REG_LR_INVERTIQ2 0x3B
// end of documented register in datasheet
@@ -562,4 +575,8 @@ Maintainer: Miguel Luis and Gregory Cristian
#define RF_PLL_BANDWIDTH_225 0x80
#define RF_PLL_BANDWIDTH_300 0xC0 // Default
+#ifdef __cplusplus
+}
+#endif
+
#endif // __SX1276_REGS_LORA_H__
diff --git a/drivers/sx1308/sx1308-spi.c b/drivers/sx1308/sx1308-spi.c
index 96deabd83d..58ec82cd49 100644
--- a/drivers/sx1308/sx1308-spi.c
+++ b/drivers/sx1308/sx1308-spi.c
@@ -83,8 +83,8 @@ Maintainer: Miguel Luis and Gregory Cristian
// VSPI => SPI_3
void sx1308_SpiInit( Spi_sx1308_t *obj) {
// this is SpiNum_SPI2
- DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI_CLK_EN);
- DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI_RST);
+ DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI2_CLK_EN);
+ DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI2_RST);
// configure the SPI port
spi_attr_t spi_attr = {.mode = SpiMode_Master, .subMode = SpiSubMode_0, .speed = SpiSpeed_8MHz,
diff --git a/drivers/wiznet5k/ethernet/socket.c b/drivers/wiznet5k/ethernet/socket.c
index ec25fcc793..3ffda3a722 100644
--- a/drivers/wiznet5k/ethernet/socket.c
+++ b/drivers/wiznet5k/ethernet/socket.c
@@ -525,6 +525,7 @@ int32_t WIZCHIP_EXPORT(recvfrom)(uint8_t sn, uint8_t * buf, uint16_t len, uint8_
// read peer's IP address, port number & packet length
sock_remained_size[sn] = head[0];
sock_remained_size[sn] = (sock_remained_size[sn] <<8) + head[1];
+ sock_remained_size[sn] -= 2; // len includes 2 len bytes
if(sock_remained_size[sn] > 1514)
{
WIZCHIP_EXPORT(close)(sn);
diff --git a/drivers/wiznet5k/ethernet/w5200/w5200.c b/drivers/wiznet5k/ethernet/w5200/w5200.c
index 8c3780792e..a84d3c9fa7 100644
--- a/drivers/wiznet5k/ethernet/w5200/w5200.c
+++ b/drivers/wiznet5k/ethernet/w5200/w5200.c
@@ -52,10 +52,19 @@
#include "w5200.h"
+#if WIZCHIP_USE_MAX_BUFFER
+// This option is intended to be used when MACRAW mode is enabled, to allow
+// the single raw socket to use all the available buffer space.
+#define SMASK (16 * 1024 - 1) /* tx buffer mask */
+#define RMASK (16 * 1024 - 1) /* rx buffer mask */
+#define SSIZE (16 * 1024) /* max tx buffer size */
+#define RSIZE (16 * 1024) /* max rx buffer size */
+#else
#define SMASK (0x7ff) /* tx buffer mask */
#define RMASK (0x7ff) /* rx buffer mask */
#define SSIZE (2048) /* max tx buffer size */
#define RSIZE (2048) /* max rx buffer size */
+#endif
#define TXBUF_BASE (0x8000)
#define RXBUF_BASE (0xc000)
diff --git a/esp32/.gitignore b/esp32/.gitignore
new file mode 100644
index 0000000000..e70c02bc5f
--- /dev/null
+++ b/esp32/.gitignore
@@ -0,0 +1,52 @@
+# Packages
+############
+
+# Logs and Databases
+######################
+*.log
+
+# VIM Swap Files
+######################
+*.swp
+
+# Build directories
+######################
+esp32/build/
+esp32/build-*/
+esp32/factory_fw/build/
+mpy-cross/build/*
+# This map file is generated here instead of the build folder...
+mpy-cross/*.map
+
+# Test failure outputs
+######################
+tests/*.exp
+tests/*.out
+
+# Python cache files
+######################
+__pycache__/
+*.pyc
+
+# Customized Makefile/project overrides
+######################
+GNUmakefile
+user.props
+.cproject
+.project
+.pydevproject
+.settings
+.launch
+.vscode
+
+# Key files (for Flash Encryption and Secure Boot)
+secure_boot_signing_key.pem
+signature_verification_key.bin
+secure-bootloader-key.bin
+flash_encryption_key.bin
+
+.DS_Store
+org.eclipse.cdt.ui.prefs
+org.eclipse.cdt.core.prefs
+language.settings.xml
+.idea
diff --git a/esp32/Makefile b/esp32/Makefile
index 5826d20992..51605d3cd7 100644
--- a/esp32/Makefile
+++ b/esp32/Makefile
@@ -14,15 +14,24 @@ ifeq ($(wildcard boards/$(BOARD)/.),)
$(error Invalid BOARD specified)
endif
-IDF_HASH=3394ee5
+IDF_HASH=264a403
+XTENSA_VERSION = "2020r3"
TARGET ?= boot_app
OEM ?= 0
+# "Small factory FW" mode is enabled by default
+# When "Small factory FW" mode is enabled the "factory" partition contains a really small FW responsible for OTA update
+# "Small factory FW" mode enables increased size of the "ota_0" partition which contains the actual real FW
+SMALL_FACTORY_FW_ENABLED ?= 1
+
# make 'release' the default build type
BTYPE ?= release
+# MDNS is disabled by default
+MOD_MDNS_ENABLED ?= 0
+
# set to 1 to enable PyEthernet board (ksz8851 chip)
PYETH_ENABLED ?= 0
@@ -46,6 +55,9 @@ else
MOD_SIGFOX_ENABLED ?= 0
endif
+# ESP-NOW is enabled by default
+MOD_ESPNOW_ENABLED ?= 1
+
# Pybytes disabled by default
PYBYTES_ENABLED ?= 0
@@ -103,7 +115,7 @@ ifeq ($(SECURE), on)
# espsecure.py generate_flash_encryption_key flash_encryption_key.bin
# Writing it is done using:
# espefuse.py --port PORT burn_key flash_encryption flash_encryption_key.bin
- ENCRYPT_KEY ?= flash_encryption_key.bin
+ ENCRYPT_KEY ?= flash_encryption_key.bin
else
$(info Use make SECURE=on [optionally SECURE_KEY ?= secure_boot_signing_key.pem] to enable Secure Boot and Flash Encryption mechanisms.)
endif # ifeq ($(SECURE), on)
@@ -123,14 +135,16 @@ CROSS_COMPILE = xtensa-esp32-elf-
ESP_IDF_PATH = $(IDF_PATH)
ESP_IDF_COMP_PATH = $(ESP_IDF_PATH)/components
-CFLAGS_XTENSA = -DESP_PLATFORM -Wpointer-arith -Wall -Werror=all -Wno-error=unused-function \
+CFLAGS_XTENSA = -DESP_PLATFORM -Wall -Werror=all -Wno-error=unused-function \
-Wno-error=unused-but-set-variable -Wno-error=unused-variable -Wl,-EL \
-mlongcalls -Wall -ffunction-sections -fdata-sections -fno-common \
-Wno-sign-compare -Wno-old-style-declaration -fstrict-volatile-bitfields \
-Wno-error=deprecated-declarations -Wno-unused-parameter -DWITH_POSIX \
+ -freorder-blocks -Wno-implicit-fallthrough
CFLAGS_XTENSA_OPT = -Os
-CFLAGS_XTENSA_PSRAM = -mfix-esp32-psram-cache-issue
+# Using -mfix-esp32-psram-cache-issue will make sure that the correct libraries, designed to workaround the PSRAM issue, are used from the Toolchain
+CFLAGS_XTENSA_PSRAM = -mfix-esp32-psram-cache-issue -mfix-esp32-psram-cache-strategy=memw
CFLAGS = $(CFLAGS_XTENSA) $(CFLAGS_XTENSA_PSRAM) $(CFLAGS_XTENSA_OPT) -nostdlib -std=gnu99 -g3 -ggdb -fstrict-volatile-bitfields -Iboards/$(BOARD)
CFLAGS += $(CFLAGS_MOD) $(CFLAGS_EXTRA)
@@ -149,19 +163,42 @@ endif
endif
endif
-LDFLAGS = -nostdlib -Wl,-Map=$(@:.elf=.map) -Wl,--no-check-sections -u call_user_start_cpu0
-LDFLAGS += -Wl,-static -Wl,--undefined=uxTopUsedPriority -Wl,--gc-sections
-
-LIBS = -L$(ESP_IDF_COMP_PATH)/esp32/lib -L$(ESP_IDF_COMP_PATH)/esp32/ld -L$(ESP_IDF_COMP_PATH)/esp32/ld/wifi_iram_noopt -L$(ESP_IDF_COMP_PATH)/bt/lib \
- -L$(ESP_IDF_COMP_PATH)/esp32 -L$(ESP_IDF_COMP_PATH)/newlib/lib -Lbootloader \
- -Llib -lnvs_flash -ltcpip_adapter -L$(BUILD) -lhal -lcore -lwps -lcoexist -lstdc++ \
- -lnet80211 -lphy -lpp -lrtc -llog -lsmartconfig -lwpa -lwpa2 -lbtdm_app -lcxx -u __cxa_guard_dummy \
- -lspi_flash -lnvs_flash -lgcc -lnghttp -ldriver -lesp32 -lexpat -lpthread -lesp_adc_cal \
- $(ESP_IDF_COMP_PATH)/newlib/lib/libm-psram-workaround.a \
- $(ESP_IDF_COMP_PATH)/newlib/lib/libc-psram-workaround.a \
- -lfreertos -ljson -ljsmn -llwip -lnewlib -lvfs -lopenssl -lmbedtls -lwpa_supplicant \
- -lxtensa-debug-module -lbt -lsdmmc -lsoc -lheap -lbootloader_support -lmicro-ecc \
- -u ld_include_panic_highint_hdl -lsmartconfig_ack -lmesh -lesp_ringbuf -lmdns -lefuse -lespcoredump -lapp_update
+# These flags are used as per the output when linking examples/wifi/scan
+# -u ld_include_panic_highint_hdl is needed so esp32/dport_panic_panic_highint_hdl.S is linked and xt_highint4 is used from there,
+# otherwise xt_highint4 is used from freertos/xtensa/xtensa_vector_defaults.S which has incorrect implementation and results DPORT core lockup
+# (check the comment in dport_panic_panic_highint_hdl.S next to ld_include_panic_highint_hdl)
+LDFLAGS = -nostdlib -u call_user_start_cpu0 -Wl,--gc-sections -Wl,-static -Wl,--start-group \
+ -u esp_app_desc -u __cxa_guard_dummy -u __cxx_fatal_exception \
+ -u ld_include_panic_highint_hdl \
+ -Wl,--undefined=uxTopUsedPriority \
+ -u newlib_include_locks_impl -u newlib_include_heap_impl -u newlib_include_syscalls_impl \
+ -Wl,--wrap=vPortCleanUpTCB \
+ -u pthread_include_pthread_impl -u pthread_include_pthread_cond_impl -u pthread_include_pthread_local_storage_impl \
+ -Wl,--end-group -Wl,-EL \
+ -fno-rtti \
+ $(CFLAGS_XTENSA_PSRAM) \
+ -Wl,-Map=$(@:.elf=.map)
+
+LIBS = -L$(ESP_IDF_COMP_PATH)/esp32/lib \
+ -L$(ESP_IDF_COMP_PATH)/esp32/ld \
+ -L$(ESP_IDF_COMP_PATH)/esp_rom/esp32/ld \
+ -L$(ESP_IDF_COMP_PATH)/esp32/ld/wifi_iram_noopt \
+ -L$(ESP_IDF_COMP_PATH)/bt/lib \
+ -L$(ESP_IDF_COMP_PATH)/esp32 \
+ -Lbootloader \
+ -Llib \
+ -L$(BUILD) \
+ -lc \
+ -lm \
+ -lgcc \
+ -lstdc++ \
+ -lnvs_flash -lesp_netif -ltcpip_adapter -llog \
+ -lspi_flash -lnvs_flash -ldriver -lesp32 -lexpat -lpthread -lesp_adc_cal \
+ -lfreertos -llwip -lnewlib -lvfs -lopenssl -lmbedtls -lwpa_supplicant \
+ -lbt -lsdmmc -lsoc -lheap -lbootloader_support \
+ -lesp_ringbuf -lefuse -lespcoredump -lapp_update \
+ -lesp_common -lesp_event -lesp_wifi -lphy -lbtdm_app -lrtc -lnet80211 \
+ -lxtensa -lpp -lcore -lmesh -lhal -lcoexist -lesp_eth -lsmartconfig -ljson -ltfmicro
ifeq ($(MOD_COAP_ENABLED), 1)
$(info COAP Module Enabled)
@@ -186,14 +223,28 @@ ifeq ($(MOD_SIGFOX_ENABLED), 1)
$(BUILD)/application.elf: sigfox/modsigfox_$(BOARD).a
endif
+ifeq ($(MOD_MDNS_ENABLED), 1)
+ $(info MDNS Module Enabled)
+ LIBS += -lmdns
+ CFLAGS += -DMOD_MDNS_ENABLED
+endif
+
ifeq ($(OPENTHREAD), on)
+ $(info OPENTHREAD enabled)
LIBS += -lopenthread
CFLAGS += -DLORA_OPENTHREAD_ENABLED
endif
+ifeq ($(MOD_ESPNOW_ENABLED), 1)
+ $(info ESP-NOW Module Enabled)
+ LIBS += -lespnow
+ CFLAGS += -DMOD_ESPNOW_ENABLED
+endif
+
# Enable or Disable LTE_LOG_BUFF
ifeq ($(BOARD), $(filter $(BOARD), GPY FIPY))
ifeq ($(LTE_LOG_BUFF),1)
+ $(info LTE_LOG_BUFF enabled)
CFLAGS += -DLTE_DEBUG_BUFF
endif #ifeq ($(LTE_LOG_BUFF),1)
endif #ifeq ($(BOARD), $(filter $(BOARD), GPY FIPY))
@@ -202,9 +253,14 @@ ifeq ($(RGB_LED),disable)
CFLAGS += -DRGB_LED_DISABLE
endif #ifeq ($(LTE_LOG_BUFF),1)
-B_LIBS = -Lbootloader/lib -Lbootloader -L$(BUILD)/bootloader -L$(ESP_IDF_COMP_PATH)/esp32/ld \
- -L$(ESP_IDF_COMP_PATH)/esp32/lib -llog -lcore -lbootloader_support \
- -lspi_flash -lsoc -lmicro-ecc -lgcc -lstdc++ -lgcov -lefuse
+B_LIBS = bootloader/lib/libbootloader_support.a \
+ bootloader/lib/libefuse.a \
+ bootloader/lib/liblog.a \
+ bootloader/lib/libmain.a \
+ bootloader/lib/libmicro-ecc.a \
+ bootloader/lib/libsoc.a \
+ bootloader/lib/libspi_flash.a \
+ -lgcc \
# objcopy paramters, to transform a binary file into an object file
OBJCOPY_EMBED_ARGS = --input-target binary --output-target elf32-xtensa-le --binary-architecture xtensa --rename-section .data=.rodata.embedded
diff --git a/esp32/application.mk b/esp32/application.mk
index 299e96f87b..5c3496d664 100644
--- a/esp32/application.mk
+++ b/esp32/application.mk
@@ -49,7 +49,7 @@ APP_INC += -I$(ESP_IDF_COMP_PATH)/soc/include
APP_INC += -I$(ESP_IDF_COMP_PATH)/soc/esp32/include
APP_INC += -I$(ESP_IDF_COMP_PATH)/expat/include
APP_INC += -I$(ESP_IDF_COMP_PATH)/freertos/include
-APP_INC += -I$(ESP_IDF_COMP_PATH)/json/include
+APP_INC += -I$(ESP_IDF_COMP_PATH)/json/cJSON
APP_INC += -I$(ESP_IDF_COMP_PATH)/expat/include
APP_INC += -I$(ESP_IDF_COMP_PATH)/lwip/include/lwip
APP_INC += -I$(ESP_IDF_COMP_PATH)/lwip/include/lwip/port
@@ -61,6 +61,7 @@ APP_INC += -I$(ESP_IDF_COMP_PATH)/newlib/include
APP_INC += -I$(ESP_IDF_COMP_PATH)/newlib/platform_include
APP_INC += -I$(ESP_IDF_COMP_PATH)/nvs_flash/include
APP_INC += -I$(ESP_IDF_COMP_PATH)/spi_flash/include
+APP_INC += -I$(ESP_IDF_COMP_PATH)/esp_netif/include
APP_INC += -I$(ESP_IDF_COMP_PATH)/tcpip_adapter/include
APP_INC += -I$(ESP_IDF_COMP_PATH)/log/include
APP_INC += -I$(ESP_IDF_COMP_PATH)/sdmmc/include
@@ -82,6 +83,7 @@ APP_INC += -I$(ESP_IDF_COMP_PATH)/bt/bluedroid/osi/include
APP_INC += -I$(ESP_IDF_COMP_PATH)/bt/bluedroid/hci/include
APP_INC += -I$(ESP_IDF_COMP_PATH)/bt/bluedroid/gki/include
APP_INC += -I$(ESP_IDF_COMP_PATH)/bt/bluedroid/api/include
+APP_INC += -I$(ESP_IDF_COMP_PATH)/bt/host/bluedroid/api/include/api
APP_INC += -I$(ESP_IDF_COMP_PATH)/bt/bluedroid/btc/include
ifeq ($(MOD_COAP_ENABLED), 1)
@@ -90,8 +92,9 @@ APP_INC += -I$(ESP_IDF_COMP_PATH)/coap/libcoap/examples
APP_INC += -I$(ESP_IDF_COMP_PATH)/coap/port/include
APP_INC += -I$(ESP_IDF_COMP_PATH)/coap/port/include/coap
endif
-
+ifeq ($(MOD_MDNS_ENABLED), 1)
APP_INC += -I$(ESP_IDF_COMP_PATH)/mdns/include
+endif
APP_INC += -I../lib/mp-readline
APP_INC += -I../lib/netutils
APP_INC += -I../lib/oofatfs
@@ -105,6 +108,46 @@ APP_INC += -I../drivers/ksz8851
endif
APP_INC += -I../ports/stm32
APP_INC += -I$(ESP_IDF_COMP_PATH)/openthread/src
+APP_INC += -I$(ESP_IDF_COMP_PATH)/bt/esp_ble_mesh/api
+APP_INC += -I$(ESP_IDF_COMP_PATH)/bt/esp_ble_mesh/api/models/include
+APP_INC += -I$(ESP_IDF_COMP_PATH)/bt/esp_ble_mesh/mesh_common/include
+APP_INC += -I$(ESP_IDF_COMP_PATH)/bt/esp_ble_mesh/api/core/include
+APP_INC += -I$(ESP_IDF_COMP_PATH)/bt/esp_ble_mesh/mesh_core
+APP_INC += -I$(ESP_IDF_COMP_PATH)/bt/esp_ble_mesh/mesh_core/include
+APP_INC += -I$(ESP_IDF_COMP_PATH)/bt/esp_ble_mesh/mesh_models/common/include
+
+
+
+#Added with idf 4.x
+APP_INC += -I$(ESP_IDF_COMP_PATH)/esp_common/include
+APP_INC += -I$(ESP_IDF_COMP_PATH)/esp_rom/include
+APP_INC += -I$(ESP_IDF_COMP_PATH)/xtensa/include
+APP_INC += -I$(ESP_IDF_COMP_PATH)/xtensa/esp32/include
+APP_INC += -I$(ESP_IDF_COMP_PATH)/driver/esp32/include
+APP_INC += -I$(ESP_IDF_COMP_PATH)/esp_wifi/include
+APP_INC += -I$(ESP_IDF_COMP_PATH)/esp_netif/include
+APP_INC += -I$(ESP_IDF_COMP_PATH)/esp_eth/include
+APP_INC += -I$(ESP_IDF_COMP_PATH)/wpa_supplicant/include/esp_supplicant
+APP_INC += -I$(ESP_IDF_COMP_PATH)/coap/libcoap/include/coap2
+APP_INC += -I$(ESP_IDF_COMP_PATH)/bt/host/bluedroid/device/include
+APP_INC += -I$(ESP_IDF_COMP_PATH)/bt/host/bluedroid/device/include/device
+APP_INC += -I$(ESP_IDF_COMP_PATH)/bt/host/bluedroid/common/include
+APP_INC += -I$(ESP_IDF_COMP_PATH)/bt/common/include
+APP_INC += -I$(ESP_IDF_COMP_PATH)/bt/host/bluedroid/stack/include
+APP_INC += -I$(ESP_IDF_COMP_PATH)/bt/common/osi/include
+APP_INC += -I$(ESP_IDF_COMP_PATH)/bt/host/bluedroid/hci/include
+APP_INC += -I$(ESP_IDF_COMP_PATH)/bt/host/bluedroid/bta/include
+APP_INC += -I$(ESP_IDF_COMP_PATH)/bt/host/bluedroid/api/include
+APP_INC += -I$(ESP_IDF_COMP_PATH)/soc/esp32/include/soc
+# Needed to find pycom_bootloader.h from pycom-esp-idf
+APP_INC += -I$(ESP_IDF_COMP_PATH)/bootloader/subproject/main
+
+# Added for Tensor Flow Micro -ML framework
+APP_INC += -Iml
+APP_INC += -I$(ESP_IDF_COMP_PATH)/tfmicro
+APP_INC += -I$(ESP_IDF_COMP_PATH)/tfmicro/third_party/flatbuffers/include
+APP_INC += -I$(ESP_IDF_COMP_PATH)/tfmicro/third_party/gemmlowp
+
APP_MAIN_SRC_C = \
main.c \
@@ -175,19 +218,30 @@ APP_MODS_SRC_C = $(addprefix mods/,\
pybsd.c \
modussl.c \
modbt.c \
+ modble_mesh.c \
modled.c \
machwdt.c \
machrmt.c \
lwipsocket.c \
machtouch.c \
- modmdns.c \
)
+
+ifeq ($(MOD_MDNS_ENABLED), 1)
+APP_MODS_SRC_C += $(addprefix mods/,\
+ modmdns.c \
+ )
+endif
ifeq ($(MOD_COAP_ENABLED), 1)
APP_INC += -Ibsdiff
APP_MODS_SRC_C += $(addprefix mods/,\
modcoap.c \
)
endif
+ifeq ($(MOD_ESPNOW_ENABLED), 1)
+APP_MODS_SRC_C += $(addprefix mods/,\
+ modespnow.c \
+ )
+endif
ifeq ($(DIFF_UPDATE_ENABLED), 1)
APP_INC += -Ibzlib/
@@ -251,6 +305,7 @@ APP_LORA_SRC_C = $(addprefix lora/,\
spi-board.c \
sx1276-board.c \
sx1272-board.c \
+ rtc-board.c \
board.c \
)
@@ -267,18 +322,29 @@ APP_MOD_MESH_SRC_C = $(addprefix mods/,\
APP_LIB_LORA_SRC_C = $(addprefix lib/lora/,\
mac/LoRaMac.c \
+ mac/LoRaMacAdr.c \
+ mac/LoRaMacClassB.c \
+ mac/LoRaMacCommands.c \
+ mac/LoRaMacConfirmQueue.c \
mac/LoRaMacCrypto.c \
+ mac/LoRaMacParser.c \
+ mac/LoRaMacSerializer.c \
+ mac/soft-se.c \
mac/region/Region.c \
+ mac/region/RegionCommon.c \
mac/region/RegionAS923.c \
mac/region/RegionAU915.c \
- mac/region/RegionCommon.c \
+ mac/region/RegionEU433.c \
mac/region/RegionEU868.c \
mac/region/RegionUS915.c \
mac/region/RegionCN470.c \
- mac/region/RegionEU433.c \
+ mac/region/RegionCN779.c \
mac/region/RegionIN865.c \
+ mac/region/RegionKR920.c \
+ mac/region/RegionRU864.c \
system/delay.c \
system/gpio.c \
+ system/systime.c \
system/timer.c \
system/crypto/aes.c \
system/crypto/cmac.c \
@@ -378,12 +444,9 @@ APP_CAN_SRC_C = $(addprefix can/,\
CAN.c \
)
-BOOT_SRC_C = $(addprefix bootloader/,\
- bootloader.c \
- bootmgr.c \
- mperror.c \
- gpio.c \
- )
+# APP_ML_SRC_C = $(addprefix ml/,\
+# magic_wand_data.c \
+# )
SFX_OBJ =
@@ -437,7 +500,7 @@ OBJ += $(addprefix $(BUILD)/, $(APP_MODS_SRC_C:.c=.o) $(APP_STM_SRC_C:.c=.o) $(S
OBJ += $(addprefix $(BUILD)/, $(APP_FATFS_SRC_C:.c=.o) $(APP_LITTLEFS_SRC_C:.c=.o) $(APP_UTIL_SRC_C:.c=.o) $(APP_TELNET_SRC_C:.c=.o))
OBJ += $(addprefix $(BUILD)/, $(APP_FTP_SRC_C:.c=.o) $(APP_CAN_SRC_C:.c=.o))
ifeq ($(PYGATE_ENABLED), 1)
-$(info Pygate Enabled)
+$(info PyGate Enabled)
OBJ += $(addprefix $(BUILD)/, $(APP_SX1308_SRC_C:.c=.o) $(APP_PYGATE_SRC_C:.c=.o))
CFLAGS += -DPYGATE_ENABLED
SRC_QSTR += $(APP_SX1308_SRC_C) $(APP_PYGATE_SRC_C)
@@ -450,10 +513,8 @@ SRC_QSTR += $(APP_KSZ8851_SRC_C) $(APP_ETHERNET_SRC_C)
endif
OBJ += $(BUILD)/pins.o
-BOOT_OBJ = $(addprefix $(BUILD)/, $(BOOT_SRC_C:.c=.o))
-
# List of sources for qstr extraction
-SRC_QSTR += $(APP_MODS_SRC_C) $(APP_UTIL_SRC_C) $(APP_STM_SRC_C) $(APP_LIB_SRC_C) $(SRC_MOD)
+SRC_QSTR += $(APP_MODS_SRC_C) $(APP_UTIL_SRC_C) $(APP_STM_SRC_C) $(APP_LIB_SRC_C) $(SRC_MOD)
ifeq ($(BOARD), $(filter $(BOARD), LOPY LOPY4 FIPY))
SRC_QSTR += $(APP_MODS_LORA_SRC_C)
endif
@@ -476,15 +537,30 @@ endif # ifeq ($(OPENTHREAD), on)
# SRC_QSTR
SRC_QSTR_AUTO_DEPS +=
-BOOT_LDFLAGS = $(LDFLAGS) -T esp32.bootloader.ld -T esp32.rom.ld -T esp32.peripherals.ld -T esp32.bootloader.rom.ld -T esp32.rom.spiram_incompatible_fns.ld -T esp32.extram.bss.ld
-
-# add the application linker script(s)
-APP_LDFLAGS += $(LDFLAGS) -T esp32_out.ld -T esp32.project.ld -T esp32.rom.ld -T esp32.peripherals.ld -T esp32.rom.libgcc.ld -T esp32.extram.bss.ld
+# These files are passed here as per esp-idf/components/bootloader/subproject/main/component.mk
+BOOT_LDFLAGS = $(LDFLAGS) -T $(ESP_IDF_COMP_PATH)/bootloader/subproject/main/ld/esp32/bootloader.ld \
+ -T $(ESP_IDF_COMP_PATH)/bootloader/subproject/main/ld/esp32/bootloader.rom.ld \
+ -T $(ESP_IDF_COMP_PATH)/esp_rom/esp32/ld/esp32.rom.ld \
+ -T $(ESP_IDF_COMP_PATH)/esp_rom/esp32/ld/esp32.rom.newlib-funcs.ld \
+ -T $(ESP_IDF_COMP_PATH)/esp32/ld/esp32.peripherals.ld \
+
+# Add the application linker script(s)
+# These files are passed here as per final build command in esp-idf fetched from the console when esp-idf/examples/wifi/scan is linked
+APP_LDFLAGS += $(LDFLAGS) -T $(BUILD)/esp32_out.ld \
+ -T esp32.extram.bss.ld \
+ -T esp32.project.ld \
+ -T esp32.peripherals.ld \
+ -T esp32.rom.ld \
+ -T esp32.rom.libgcc.ld \
+ -T esp32.rom.syscalls.ld \
+ -T esp32.rom.newlib-data.ld \
+ -T esp32.rom.newlib-time.ld
APP_LDFLAGS += $(LDFLAGS_MOD)
+
# add the application specific CFLAGS
CFLAGS += $(APP_INC) -DMICROPY_NLR_SETJMP=1 -DMBEDTLS_CONFIG_FILE='"mbedtls/esp_config.h"' -DHAVE_CONFIG_H -DESP_PLATFORM -DFFCONF_H=\"lib/oofatfs/ffconf.h\" -DWITH_POSIX
CFLAGS_SIGFOX += $(APP_INC) -DMICROPY_NLR_SETJMP=1 -DMBEDTLS_CONFIG_FILE='"mbedtls/esp_config.h"' -DHAVE_CONFIG_H -DESP_PLATFORM
-CFLAGS += -DREGION_AS923 -DREGION_AU915 -DREGION_EU868 -DREGION_US915 -DREGION_CN470 -DREGION_EU433 -DREGION_IN865 -DBASE=0 -DPYBYTES=1
+CFLAGS += -DREGION_AS923 -DREGION_AU915 -DREGION_EU868 -DREGION_US915 -DREGION_CN470 -DREGION_IN865 -DREGION_EU433 -DREGION_CN779 -DREGION_RU864 -DREGION_KR920 -DBASE=0 -DPYBYTES=1
# Specify if this is Firmware build has Pybytes enabled
ifeq ($(PYBYTES_ENABLED), 1)
@@ -499,11 +575,10 @@ FS ?= ""
ifeq ($(FS), LFS)
CFLAGS += -DFS_USE_LITTLEFS
endif
-
# add the application archive, this order is very important
APP_LIBS = -Wl,--start-group $(LIBS) $(BUILD)/application.a -Wl,--end-group -Wl,-EL
-BOOT_LIBS = -Wl,--start-group $(B_LIBS) $(BUILD)/bootloader/bootloader.a -Wl,--end-group -Wl,-EL
+BOOT_LIBS = -Wl,--start-group $(B_LIBS) -Wl,--end-group -Wl,-EL
# debug / optimization options
ifeq ($(BTYPE), debug)
@@ -569,14 +644,21 @@ ifeq ($(BOARD), FIPY)
endif
endif
-PART_BIN_8MB = $(BUILD)/lib/partitions_8MB.bin
+ifeq ($(SMALL_FACTORY_FW_ENABLED), 1)
+ PART_BIN_8MB = $(BUILD)/lib/partitions_8MB_small_factory_fw.bin
+ PART_CSV_8MB = lib/partitions_8MB_small_factory_fw.csv
+else
+ PART_BIN_8MB = $(BUILD)/lib/partitions_8MB_normal_factory_fw.bin
+ PART_CSV_8MB = lib/partitions_8MB_normal_factory_fw.csv
+endif
+
PART_BIN_4MB = $(BUILD)/lib/partitions_4MB.bin
+PART_CSV_4MB = lib/partitions_4MB.csv
+
PART_BIN_ENCRYPT_4MB = $(PART_BIN_4MB)_enc
PART_BIN_ENCRYPT_8MB = $(PART_BIN_8MB)_enc
APP_BIN_ENCRYPT = $(APP_BIN)_enc
APP_IMG = $(BUILD)/appimg.bin
-PART_CSV_8MB = lib/partitions_8MB.csv
-PART_CSV_4MB = lib/partitions_4MB.csv
APP_BIN_ENCRYPT_2_8MB = $(APP_BIN)_enc_0x210000
APP_BIN_ENCRYPT_2_4MB = $(APP_BIN)_enc_0x1C0000
@@ -695,12 +777,8 @@ endif #ifeq ($(SECURE), on)
ifeq ($(TARGET), $(filter $(TARGET), boot boot_app))
-$(BUILD)/bootloader/bootloader.a: $(BOOT_OBJ) sdkconfig.h
- $(ECHO) "AR $@"
- $(Q) rm -f $@
- $(Q) $(AR) cru $@ $^
-$(BUILD)/bootloader/bootloader.elf: $(BUILD)/bootloader/bootloader.a $(SECURE_BOOT_VERIFICATION_KEY)
+$(BUILD)/bootloader/bootloader.elf: $(SECURE_BOOT_VERIFICATION_KEY)
ifeq ($(SECURE), on)
# unpack libbootloader_support.a, and archive again using the right key for verifying signatures
$(ECHO) "Inserting verification key $(SECURE_BOOT_VERIFICATION_KEY) in $@"
@@ -717,6 +795,11 @@ ifeq ($(SECURE), on)
$(CP) libbootloader_support.a ../
$(Q) $(RM) -rf ./bootloader/lib/bootloader_support_temp
endif #ifeq ($(SECURE), on)
+ $(Q) $(MKDIR) -p $(BUILD_DIR)
+ $(Q) $(MKDIR) -p $(BUILD_DIR)/$(BOARD)
+ $(Q) $(MKDIR) -p $(BUILD_DIR)/$(BOARD)/$(BTYPE)
+ $(Q) $(MKDIR) -p $(BUILD_DIR)/$(BOARD)/$(BTYPE)/bootloader
+ $(Q) $(CP) bootloader/lib/bootloader.map $(BUILD_DIR)/$(BOARD)/$(BTYPE)/bootloader/
$(ECHO) "LINK $(CC) *** $(BOOT_LDFLAGS) *** $(BOOT_LIBS) -o $@"
$(Q) $(CC) $(BOOT_LDFLAGS) $(BOOT_LIBS) -o $@
$(Q) $(SIZE) $@
@@ -854,16 +937,16 @@ endif #ifeq ($(TARGET), $(filter $(TARGET), app boot_app))
release: $(APP_BIN) $(BOOT_BIN)
$(ECHO) "checking size of image"
- $(Q) bash tools/size_check.sh $(BOARD) $(BTYPE) $(VARIANT)
+ $(Q) bash tools/size_check.sh $(BOARD) $(BTYPE) $(VARIANT) $(SMALL_FACTORY_FW_ENABLED)
ifeq ($(SECURE), on)
- $(Q) tools/makepkg.sh $(BOARD) $(RELEASE_DIR) $(BUILD) 1
+ $(Q) tools/makepkg.sh $(BOARD) $(RELEASE_DIR) $(BUILD) 1 $(SMALL_FACTORY_FW_ENABLED)
else
- $(Q) tools/makepkg.sh $(BOARD) $(RELEASE_DIR) $(BUILD)
+ $(Q) tools/makepkg.sh $(BOARD) $(RELEASE_DIR) $(BUILD) 0 $(SMALL_FACTORY_FW_ENABLED)
endif
flash: release
$(ECHO) "checking size of image"
- $(Q) bash tools/size_check.sh $(BOARD) $(BTYPE) $(VARIANT)
+ $(Q) bash tools/size_check.sh $(BOARD) $(BTYPE) $(VARIANT) $(SMALL_FACTORY_FW_ENABLED)
$(ECHO) "Flashing project"
ifeq ($(SECURE), on)
@@ -922,9 +1005,8 @@ GEN_PINS_HDR = $(HEADER_BUILD)/pins.h
GEN_PINS_QSTR = $(BUILD)/pins_qstr.h
.NOTPARALLEL: CHECK_DEP $(OBJ)
-.NOTPARALLEL: CHECK_DEP $(BOOT_OBJ)
-
-$(BOOT_OBJ) $(OBJ): | CHECK_DEP
+.NOTPARALLEL: CHECK_DEP $(BUILD)/bootloader/bootloader.elf
+$(BUILD)/bootloader/bootloader.elf $(OBJ): | CHECK_DEP
# Making OBJ use an order-only dependency on the generated pins.h file
# has the side effect of making the pins.h file before we actually compile
@@ -933,11 +1015,12 @@ $(BOOT_OBJ) $(OBJ): | CHECK_DEP
# which source files might need it.
$(OBJ): | $(GEN_PINS_HDR)
-# Check Dependencies (IDF version, Frozen code and IDF LIBS)
+# Check Dependencies (IDF version, Frozen code, Xtensa version and IDF LIBS)
CHECK_DEP:
$(Q) bash tools/idfVerCheck.sh $(IDF_PATH) "$(IDF_HASH)"
$(Q) bash tools/mpy-build-check.sh $(BOARD) $(BTYPE) $(VARIANT)
$(Q) $(PYTHON) check_secure_boot.py --SECURE $(SECURE)
+ $(Q) $(PYTHON) check_xtensa_version.py --VERSION $(XTENSA_VERSION)
ifeq ($(COPY_IDF_LIB), 1)
$(ECHO) "COPY IDF LIBRARIES"
$(Q) $(PYTHON) get_idf_libs.py --idflibs $(IDF_PATH)/examples/wifi/scan/build
diff --git a/esp32/boards/FIPY/script b/esp32/boards/FIPY/script
deleted file mode 100644
index 461d6eb047..0000000000
--- a/esp32/boards/FIPY/script
+++ /dev/null
@@ -1,13 +0,0 @@
-[
- ["e", "0x1000", "0x40000"],
- ["e", "0x41000", "0x40000"],
- ["e", "0x81000", "0x40000"],
- ["e", "0xC1000", "0x40000"],
- ["e", "0x101000", "0x40000"],
- ["e", "0x141000", "0x40000"],
- ["e", "0x181000", "0x40000"],
- ["e", "0x1C1000", "0x40000"],
- ["w", "0x1000", "bootloader.bin"],
- ["w", "0x8000", "partitions_8MB.bin"],
- ["w", "0x10000", "fipy.bin"]
-]
diff --git a/esp32/boards/FIPY/script2 b/esp32/boards/FIPY/script2
deleted file mode 100644
index b71bcdc59b..0000000000
--- a/esp32/boards/FIPY/script2
+++ /dev/null
@@ -1,13 +0,0 @@
-{
- "version" : "2.1",
- "partitions" : {
- "factory" : ["0x10000", "0x1EF000"],
- "ota_0" : ["0x210000", "0x1EF000"],
- "otadata" : ["0x1FF000", "0x1000"]
- },
- "script" : [
- ["w", "bootloader", "bootloader.bin"],
- ["w", "partitions", "partitions_8MB.bin"],
- ["w", "factory", "fipy.bin"]
- ]
-}
diff --git a/esp32/boards/FIPY/script_8MB b/esp32/boards/FIPY/script_8MB
deleted file mode 100644
index b71bcdc59b..0000000000
--- a/esp32/boards/FIPY/script_8MB
+++ /dev/null
@@ -1,13 +0,0 @@
-{
- "version" : "2.1",
- "partitions" : {
- "factory" : ["0x10000", "0x1EF000"],
- "ota_0" : ["0x210000", "0x1EF000"],
- "otadata" : ["0x1FF000", "0x1000"]
- },
- "script" : [
- ["w", "bootloader", "bootloader.bin"],
- ["w", "partitions", "partitions_8MB.bin"],
- ["w", "factory", "fipy.bin"]
- ]
-}
diff --git a/esp32/boards/FIPY/script_8MB_enc b/esp32/boards/FIPY/script_8MB_enc
deleted file mode 100644
index 49cb0e2628..0000000000
--- a/esp32/boards/FIPY/script_8MB_enc
+++ /dev/null
@@ -1,13 +0,0 @@
-{
- "version" : "2.1",
- "partitions" : {
- "factory" : ["0x10000", "0x1EF000"],
- "ota_0" : ["0x210000", "0x1EF000"],
- "otadata" : ["0x1FF000", "0x1000"]
- },
- "script" : [
- ["w", "secureboot", "bootloader-reflash-digest.bin_enc"],
- ["w", "partitions", "partitions_8MB.bin_enc"],
- ["w", "factory", "fipy.bin_enc"]
- ]
-}
diff --git a/esp32/boards/FIPY/script_8MB_normal_factory_fw b/esp32/boards/FIPY/script_8MB_normal_factory_fw
new file mode 100644
index 0000000000..813152509a
--- /dev/null
+++ b/esp32/boards/FIPY/script_8MB_normal_factory_fw
@@ -0,0 +1,13 @@
+{
+ "version" : "2.1",
+ "partitions" : {
+ "factory" : ["0x10000", "0x1EF000"],
+ "ota_0" : ["0x210000", "0x1EF000"],
+ "otadata" : ["0x1FF000", "0x1000"]
+ },
+ "script" : [
+ ["w", "bootloader", "bootloader.bin"],
+ ["w", "partitions", "partitions_8MB_normal_factory_fw.bin"],
+ ["w", "factory", "fipy.bin"]
+ ]
+}
diff --git a/esp32/boards/FIPY/script_8MB_normal_factory_fw_enc b/esp32/boards/FIPY/script_8MB_normal_factory_fw_enc
new file mode 100644
index 0000000000..5414423927
--- /dev/null
+++ b/esp32/boards/FIPY/script_8MB_normal_factory_fw_enc
@@ -0,0 +1,13 @@
+{
+ "version" : "2.1",
+ "partitions" : {
+ "factory" : ["0x10000", "0x1EF000"],
+ "ota_0" : ["0x210000", "0x1EF000"],
+ "otadata" : ["0x1FF000", "0x1000"]
+ },
+ "script" : [
+ ["w", "secureboot", "bootloader-reflash-digest.bin_enc"],
+ ["w", "partitions", "partitions_8MB_normal_factory_fw.bin_enc"],
+ ["w", "factory", "fipy.bin_enc"]
+ ]
+}
diff --git a/esp32/boards/FIPY/script_8MB_small_factory_fw b/esp32/boards/FIPY/script_8MB_small_factory_fw
new file mode 100644
index 0000000000..9bb8445929
--- /dev/null
+++ b/esp32/boards/FIPY/script_8MB_small_factory_fw
@@ -0,0 +1,14 @@
+{
+ "version" : "2.1",
+ "partitions" : {
+ "factory" : ["0x10000", "0xFF000"],
+ "ota_0" : ["0x110000", "0x2EF000"],
+ "otadata" : ["0x10F000", "0x1000"]
+ },
+ "script" : [
+ ["w", "bootloader", "bootloader.bin"],
+ ["w", "partitions", "partitions_8MB_small_factory_fw.bin"],
+ ["w", "factory", "factory_fw.bin"],
+ ["w", "ota_0", "fipy.bin"]
+ ]
+}
diff --git a/esp32/boards/FIPY/script_8MB_small_factory_fw_enc b/esp32/boards/FIPY/script_8MB_small_factory_fw_enc
new file mode 100644
index 0000000000..574913d06c
--- /dev/null
+++ b/esp32/boards/FIPY/script_8MB_small_factory_fw_enc
@@ -0,0 +1,14 @@
+{
+ "version" : "2.1",
+ "partitions" : {
+ "factory" : ["0x10000", "0xFF000"],
+ "ota_0" : ["0x110000", "0x2EF000"],
+ "otadata" : ["0x10F000", "0x1000"]
+ },
+ "script" : [
+ ["w", "secureboot", "bootloader-reflash-digest.bin_enc"],
+ ["w", "partitions", "partitions_8MB_small_factory_fw.bin_enc"],
+ ["w", "factory", "factory_fw.bin"],
+ ["w", "ota_0", "fipy.bin"]
+ ]
+}
diff --git a/esp32/boards/GPY/script b/esp32/boards/GPY/script
deleted file mode 100644
index c710885905..0000000000
--- a/esp32/boards/GPY/script
+++ /dev/null
@@ -1,13 +0,0 @@
-[
- ["e", "0x1000", "0x40000"],
- ["e", "0x41000", "0x40000"],
- ["e", "0x81000", "0x40000"],
- ["e", "0xC1000", "0x40000"],
- ["e", "0x101000", "0x40000"],
- ["e", "0x141000", "0x40000"],
- ["e", "0x181000", "0x40000"],
- ["e", "0x1C1000", "0x40000"],
- ["w", "0x1000", "bootloader.bin"],
- ["w", "0x8000", "partitions_8MB.bin"],
- ["w", "0x10000", "gpy.bin"]
-]
diff --git a/esp32/boards/GPY/script2 b/esp32/boards/GPY/script2
deleted file mode 100644
index b71bcdc59b..0000000000
--- a/esp32/boards/GPY/script2
+++ /dev/null
@@ -1,13 +0,0 @@
-{
- "version" : "2.1",
- "partitions" : {
- "factory" : ["0x10000", "0x1EF000"],
- "ota_0" : ["0x210000", "0x1EF000"],
- "otadata" : ["0x1FF000", "0x1000"]
- },
- "script" : [
- ["w", "bootloader", "bootloader.bin"],
- ["w", "partitions", "partitions_8MB.bin"],
- ["w", "factory", "fipy.bin"]
- ]
-}
diff --git a/esp32/boards/GPY/script_8MB b/esp32/boards/GPY/script_8MB
deleted file mode 100644
index 6f2c689fee..0000000000
--- a/esp32/boards/GPY/script_8MB
+++ /dev/null
@@ -1,13 +0,0 @@
-{
- "version" : "2.1",
- "partitions" : {
- "factory" : ["0x10000", "0x1EF000"],
- "ota_0" : ["0x210000", "0x1EF000"],
- "otadata" : ["0x1FF000", "0x1000"]
- },
- "script" : [
- ["w", "bootloader", "bootloader.bin"],
- ["w", "partitions", "partitions_8MB.bin"],
- ["w", "factory", "gpy.bin"]
- ]
-}
diff --git a/esp32/boards/GPY/script_8MB _normal_factory_fw b/esp32/boards/GPY/script_8MB _normal_factory_fw
new file mode 100644
index 0000000000..465384413d
--- /dev/null
+++ b/esp32/boards/GPY/script_8MB _normal_factory_fw
@@ -0,0 +1,13 @@
+{
+ "version" : "2.1",
+ "partitions" : {
+ "factory" : ["0x10000", "0x1EF000"],
+ "ota_0" : ["0x210000", "0x1EF000"],
+ "otadata" : ["0x1FF000", "0x1000"]
+ },
+ "script" : [
+ ["w", "bootloader", "bootloader.bin"],
+ ["w", "partitions", "partitions_8MB_normal_factory_fw.bin"],
+ ["w", "factory", "gpy.bin"]
+ ]
+}
diff --git a/esp32/boards/GPY/script_8MB_enc b/esp32/boards/GPY/script_8MB_enc
deleted file mode 100644
index 93628cb3ec..0000000000
--- a/esp32/boards/GPY/script_8MB_enc
+++ /dev/null
@@ -1,13 +0,0 @@
-{
- "version" : "2.1",
- "partitions" : {
- "factory" : ["0x10000", "0x1EF000"],
- "ota_0" : ["0x210000", "0x1EF000"],
- "otadata" : ["0x1FF000", "0x1000"]
- },
- "script" : [
- ["w", "secureboot", "bootloader-reflash-digest.bin_enc"],
- ["w", "partitions", "partitions_8MB.bin_enc"],
- ["w", "factory", "gpy.bin_enc"]
- ]
-}
diff --git a/esp32/boards/GPY/script_8MB_normal_factory_fw_enc b/esp32/boards/GPY/script_8MB_normal_factory_fw_enc
new file mode 100644
index 0000000000..f4d25e26a9
--- /dev/null
+++ b/esp32/boards/GPY/script_8MB_normal_factory_fw_enc
@@ -0,0 +1,13 @@
+{
+ "version" : "2.1",
+ "partitions" : {
+ "factory" : ["0x10000", "0x1EF000"],
+ "ota_0" : ["0x210000", "0x1EF000"],
+ "otadata" : ["0x1FF000", "0x1000"]
+ },
+ "script" : [
+ ["w", "secureboot", "bootloader-reflash-digest.bin_enc"],
+ ["w", "partitions", "partitions_8MB_normal_factory_fw.bin_enc"],
+ ["w", "factory", "gpy.bin_enc"]
+ ]
+}
diff --git a/esp32/boards/GPY/script_8MB_small_factory_fw b/esp32/boards/GPY/script_8MB_small_factory_fw
new file mode 100644
index 0000000000..0f316e10b0
--- /dev/null
+++ b/esp32/boards/GPY/script_8MB_small_factory_fw
@@ -0,0 +1,14 @@
+{
+ "version" : "2.1",
+ "partitions" : {
+ "factory" : ["0x10000", "0xFF000"],
+ "ota_0" : ["0x110000", "0x2EF000"],
+ "otadata" : ["0x10F000", "0x1000"]
+ },
+ "script" : [
+ ["w", "bootloader", "bootloader.bin"],
+ ["w", "partitions", "partitions_8MB_small_factory_fw.bin"],
+ ["w", "factory", "factory_fw.bin"],
+ ["w", "ota_0", "gpy.bin"]
+ ]
+}
diff --git a/esp32/boards/GPY/script_8MB_small_factory_fw_enc b/esp32/boards/GPY/script_8MB_small_factory_fw_enc
new file mode 100644
index 0000000000..799ee9864c
--- /dev/null
+++ b/esp32/boards/GPY/script_8MB_small_factory_fw_enc
@@ -0,0 +1,14 @@
+{
+ "version" : "2.1",
+ "partitions" : {
+ "factory" : ["0x10000", "0xFF000"],
+ "ota_0" : ["0x110000", "0x2EF000"],
+ "otadata" : ["0x10F000", "0x1000"]
+ },
+ "script" : [
+ ["w", "secureboot", "bootloader-reflash-digest.bin_enc"],
+ ["w", "partitions", "partitions_8MB_small_factory_fw.bin_enc"],
+ ["w", "factory", "factory_fw.bin"],
+ ["w", "ota_0", "gpy.bin"]
+ ]
+}
diff --git a/esp32/boards/LOPY/script b/esp32/boards/LOPY/script
deleted file mode 100644
index 1d2384a490..0000000000
--- a/esp32/boards/LOPY/script
+++ /dev/null
@@ -1,13 +0,0 @@
-[
- ["e", "0x1000", "0x40000"],
- ["e", "0x41000", "0x40000"],
- ["e", "0x81000", "0x40000"],
- ["e", "0xC1000", "0x40000"],
- ["e", "0x101000", "0x40000"],
- ["e", "0x141000", "0x40000"],
- ["e", "0x181000", "0x40000"],
- ["e", "0x1C1000", "0x40000"],
- ["w", "0x1000", "bootloader.bin"],
- ["w", "0x8000", "partitions_4MB.bin"],
- ["w", "0x10000", "lopy.bin"]
-]
diff --git a/esp32/boards/LOPY/script2 b/esp32/boards/LOPY/script2
deleted file mode 100644
index 2a9d28e630..0000000000
--- a/esp32/boards/LOPY/script2
+++ /dev/null
@@ -1,13 +0,0 @@
-{
- "version" : "2.1",
- "partitions" : {
- "factory" : ["0x10000", "0x1AE000"],
- "ota_0" : ["0x1C0000", "0x1AE000"],
- "otadata" : ["0x1BE000", "0x1000"]
- },
- "script" : [
- ["w", "bootloader", "bootloader.bin"],
- ["w", "partitions", "partitions_4MB.bin"],
- ["w", "factory", "lopy.bin"]
- ]
-}
diff --git a/esp32/boards/LOPY/script_4MB b/esp32/boards/LOPY/script_4MB
deleted file mode 100644
index 2a9d28e630..0000000000
--- a/esp32/boards/LOPY/script_4MB
+++ /dev/null
@@ -1,13 +0,0 @@
-{
- "version" : "2.1",
- "partitions" : {
- "factory" : ["0x10000", "0x1AE000"],
- "ota_0" : ["0x1C0000", "0x1AE000"],
- "otadata" : ["0x1BE000", "0x1000"]
- },
- "script" : [
- ["w", "bootloader", "bootloader.bin"],
- ["w", "partitions", "partitions_4MB.bin"],
- ["w", "factory", "lopy.bin"]
- ]
-}
diff --git a/esp32/boards/LOPY/script_4MB_enc b/esp32/boards/LOPY/script_4MB_enc
deleted file mode 100644
index 9926eebfee..0000000000
--- a/esp32/boards/LOPY/script_4MB_enc
+++ /dev/null
@@ -1,13 +0,0 @@
-{
- "version" : "2.1",
- "partitions" : {
- "factory" : ["0x10000", "0x1AE000"],
- "ota_0" : ["0x1C0000", "0x1AE000"],
- "otadata" : ["0x1BE000", "0x1000"]
- },
- "script" : [
- ["w", "secureboot", "bootloader-reflash-digest.bin_enc"],
- ["w", "partitions", "partitions_4MB.bin_enc"],
- ["w", "factory", "lopy.bin_enc"]
- ]
-}
diff --git a/esp32/boards/LOPY/script_8MB b/esp32/boards/LOPY/script_8MB
deleted file mode 100644
index 2b5f44150e..0000000000
--- a/esp32/boards/LOPY/script_8MB
+++ /dev/null
@@ -1,13 +0,0 @@
-{
- "version" : "2.1",
- "partitions" : {
- "factory" : ["0x10000", "0x1EF000"],
- "ota_0" : ["0x210000", "0x1EF000"],
- "otadata" : ["0x1FF000", "0x1000"]
- },
- "script" : [
- ["w", "bootloader", "bootloader.bin"],
- ["w", "partitions", "partitions_8MB.bin"],
- ["w", "factory", "lopy.bin"]
- ]
-}
diff --git a/esp32/boards/LOPY/script_8MB_enc b/esp32/boards/LOPY/script_8MB_enc
deleted file mode 100644
index 92637fe416..0000000000
--- a/esp32/boards/LOPY/script_8MB_enc
+++ /dev/null
@@ -1,13 +0,0 @@
-{
- "version" : "2.1",
- "partitions" : {
- "factory" : ["0x10000", "0x1EF000"],
- "ota_0" : ["0x210000", "0x1EF000"],
- "otadata" : ["0x1FF000", "0x1000"]
- },
- "script" : [
- ["w", "secureboot", "bootloader-reflash-digest.bin_enc"],
- ["w", "partitions", "partitions_8MB.bin_enc"],
- ["w", "factory", "lopy.bin_enc"]
- ]
-}
diff --git a/esp32/boards/LOPY/script_8MB_normal_factory_fw b/esp32/boards/LOPY/script_8MB_normal_factory_fw
new file mode 100644
index 0000000000..52426a94ba
--- /dev/null
+++ b/esp32/boards/LOPY/script_8MB_normal_factory_fw
@@ -0,0 +1,13 @@
+{
+ "version" : "2.1",
+ "partitions" : {
+ "factory" : ["0x10000", "0x1EF000"],
+ "ota_0" : ["0x210000", "0x1EF000"],
+ "otadata" : ["0x1FF000", "0x1000"]
+ },
+ "script" : [
+ ["w", "bootloader", "bootloader.bin"],
+ ["w", "partitions", "partitions_8MB_normal_factory_fw.bin"],
+ ["w", "factory", "lopy.bin"]
+ ]
+}
diff --git a/esp32/boards/LOPY/script_8MB_normal_factory_fw_enc b/esp32/boards/LOPY/script_8MB_normal_factory_fw_enc
new file mode 100644
index 0000000000..26e4dcf615
--- /dev/null
+++ b/esp32/boards/LOPY/script_8MB_normal_factory_fw_enc
@@ -0,0 +1,13 @@
+{
+ "version" : "2.1",
+ "partitions" : {
+ "factory" : ["0x10000", "0x1EF000"],
+ "ota_0" : ["0x210000", "0x1EF000"],
+ "otadata" : ["0x1FF000", "0x1000"]
+ },
+ "script" : [
+ ["w", "secureboot", "bootloader-reflash-digest.bin_enc"],
+ ["w", "partitions", "partitions_8MB_normal_factory_fw.bin_enc"],
+ ["w", "factory", "lopy.bin_enc"]
+ ]
+}
diff --git a/esp32/boards/LOPY/script_8MB_small_factory_fw b/esp32/boards/LOPY/script_8MB_small_factory_fw
new file mode 100644
index 0000000000..f9b403a7b9
--- /dev/null
+++ b/esp32/boards/LOPY/script_8MB_small_factory_fw
@@ -0,0 +1,14 @@
+{
+ "version" : "2.1",
+ "partitions" : {
+ "factory" : ["0x10000", "0xFF000"],
+ "ota_0" : ["0x110000", "0x2EF000"],
+ "otadata" : ["0x10F000", "0x1000"]
+ },
+ "script" : [
+ ["w", "bootloader", "bootloader.bin"],
+ ["w", "partitions", "partitions_8MB_small_factory_fw.bin"],
+ ["w", "factory", "factory_fw.bin"],
+ ["w", "ota_0", "lopy.bin"]
+ ]
+}
diff --git a/esp32/boards/LOPY/script_8MB_small_factory_fw_enc b/esp32/boards/LOPY/script_8MB_small_factory_fw_enc
new file mode 100644
index 0000000000..c838829da7
--- /dev/null
+++ b/esp32/boards/LOPY/script_8MB_small_factory_fw_enc
@@ -0,0 +1,14 @@
+{
+ "version" : "2.1",
+ "partitions" : {
+ "factory" : ["0x10000", "0xFF000"],
+ "ota_0" : ["0x110000", "0x2EF000"],
+ "otadata" : ["0x10F000", "0x1000"]
+ },
+ "script" : [
+ ["w", "secureboot", "bootloader-reflash-digest.bin_enc"],
+ ["w", "partitions", "partitions_8MB_small_factory_fw.bin_enc"],
+ ["w", "factory", "factory_fw.bin"],
+ ["w", "ota_0", "lopy.bin"]
+ ]
+}
diff --git a/esp32/boards/LOPY4/script b/esp32/boards/LOPY4/script
deleted file mode 100644
index 3107266648..0000000000
--- a/esp32/boards/LOPY4/script
+++ /dev/null
@@ -1,13 +0,0 @@
-[
- ["e", "0x1000", "0x40000"],
- ["e", "0x41000", "0x40000"],
- ["e", "0x81000", "0x40000"],
- ["e", "0xC1000", "0x40000"],
- ["e", "0x101000", "0x40000"],
- ["e", "0x141000", "0x40000"],
- ["e", "0x181000", "0x40000"],
- ["e", "0x1C1000", "0x40000"],
- ["w", "0x1000", "bootloader.bin"],
- ["w", "0x8000", "partitions_8MB.bin"],
- ["w", "0x10000", "lopy4.bin"]
-]
diff --git a/esp32/boards/LOPY4/script2 b/esp32/boards/LOPY4/script2
deleted file mode 100644
index b71bcdc59b..0000000000
--- a/esp32/boards/LOPY4/script2
+++ /dev/null
@@ -1,13 +0,0 @@
-{
- "version" : "2.1",
- "partitions" : {
- "factory" : ["0x10000", "0x1EF000"],
- "ota_0" : ["0x210000", "0x1EF000"],
- "otadata" : ["0x1FF000", "0x1000"]
- },
- "script" : [
- ["w", "bootloader", "bootloader.bin"],
- ["w", "partitions", "partitions_8MB.bin"],
- ["w", "factory", "fipy.bin"]
- ]
-}
diff --git a/esp32/boards/LOPY4/script_8MB b/esp32/boards/LOPY4/script_8MB
deleted file mode 100644
index 94bbb89a4f..0000000000
--- a/esp32/boards/LOPY4/script_8MB
+++ /dev/null
@@ -1,13 +0,0 @@
-{
- "version" : "2.1",
- "partitions" : {
- "factory" : ["0x10000", "0x1EF000"],
- "ota_0" : ["0x210000", "0x1EF000"],
- "otadata" : ["0x1FF000", "0x1000"]
- },
- "script" : [
- ["w", "bootloader", "bootloader.bin"],
- ["w", "partitions", "partitions_8MB.bin"],
- ["w", "factory", "lopy4.bin"]
- ]
-}
diff --git a/esp32/boards/LOPY4/script_8MB_enc b/esp32/boards/LOPY4/script_8MB_enc
deleted file mode 100644
index 65683be9ab..0000000000
--- a/esp32/boards/LOPY4/script_8MB_enc
+++ /dev/null
@@ -1,13 +0,0 @@
-{
- "version" : "2.1",
- "partitions" : {
- "factory" : ["0x10000", "0x1EF000"],
- "ota_0" : ["0x210000", "0x1EF000"],
- "otadata" : ["0x1FF000", "0x1000"]
- },
- "script" : [
- ["w", "secureboot", "bootloader-reflash-digest.bin_enc"],
- ["w", "partitions", "partitions_8MB.bin_enc"],
- ["w", "factory", "lopy4.bin_enc"]
- ]
-}
diff --git a/esp32/boards/LOPY4/script_8MB_normal_factory_fw b/esp32/boards/LOPY4/script_8MB_normal_factory_fw
new file mode 100644
index 0000000000..496275aa79
--- /dev/null
+++ b/esp32/boards/LOPY4/script_8MB_normal_factory_fw
@@ -0,0 +1,13 @@
+{
+ "version" : "2.1",
+ "partitions" : {
+ "factory" : ["0x10000", "0x1EF000"],
+ "ota_0" : ["0x210000", "0x1EF000"],
+ "otadata" : ["0x1FF000", "0x1000"]
+ },
+ "script" : [
+ ["w", "bootloader", "bootloader.bin"],
+ ["w", "partitions", "partitions_8MB_normal_factory_fw.bin"],
+ ["w", "factory", "lopy4.bin"]
+ ]
+}
diff --git a/esp32/boards/LOPY4/script_8MB_normal_factory_fw_enc b/esp32/boards/LOPY4/script_8MB_normal_factory_fw_enc
new file mode 100644
index 0000000000..e035355fa4
--- /dev/null
+++ b/esp32/boards/LOPY4/script_8MB_normal_factory_fw_enc
@@ -0,0 +1,13 @@
+{
+ "version" : "2.1",
+ "partitions" : {
+ "factory" : ["0x10000", "0x1EF000"],
+ "ota_0" : ["0x210000", "0x1EF000"],
+ "otadata" : ["0x1FF000", "0x1000"]
+ },
+ "script" : [
+ ["w", "secureboot", "bootloader-reflash-digest.bin_enc"],
+ ["w", "partitions", "partitions_8MB_normal_factory_fw.bin_enc"],
+ ["w", "factory", "lopy4.bin_enc"]
+ ]
+}
diff --git a/esp32/boards/LOPY4/script_8MB_small_factory_fw b/esp32/boards/LOPY4/script_8MB_small_factory_fw
new file mode 100644
index 0000000000..b9739674af
--- /dev/null
+++ b/esp32/boards/LOPY4/script_8MB_small_factory_fw
@@ -0,0 +1,14 @@
+{
+ "version" : "2.1",
+ "partitions" : {
+ "factory" : ["0x10000", "0xFF000"],
+ "ota_0" : ["0x110000", "0x2EF000"],
+ "otadata" : ["0x10F000", "0x1000"]
+ },
+ "script" : [
+ ["w", "bootloader", "bootloader.bin"],
+ ["w", "partitions", "partitions_8MB_small_factory_fw.bin"],
+ ["w", "factory", "factory_fw.bin"],
+ ["w", "ota_0", "lopy4.bin"]
+ ]
+}
diff --git a/esp32/boards/LOPY4/script_8MB_small_factory_fw_enc b/esp32/boards/LOPY4/script_8MB_small_factory_fw_enc
new file mode 100644
index 0000000000..c8c1786226
--- /dev/null
+++ b/esp32/boards/LOPY4/script_8MB_small_factory_fw_enc
@@ -0,0 +1,14 @@
+{
+ "version" : "2.1",
+ "partitions" : {
+ "factory" : ["0x10000", "0xFF000"],
+ "ota_0" : ["0x110000", "0x2EF000"],
+ "otadata" : ["0x10F000", "0x1000"]
+ },
+ "script" : [
+ ["w", "secureboot", "bootloader-reflash-digest.bin_enc"],
+ ["w", "partitions", "partitions_8MB_small_factory_fw.bin_enc"],
+ ["w", "factory", "factory_fw.bin"],
+ ["w", "ota_0", "lopy4.bin"]
+ ]
+}
diff --git a/esp32/boards/SIPY/mpconfigboard.h b/esp32/boards/SIPY/mpconfigboard.h
deleted file mode 100644
index 229ea22d4b..0000000000
--- a/esp32/boards/SIPY/mpconfigboard.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2020, Pycom Limited.
- *
- * This software is licensed under the GNU GPL version 3 or any
- * later version, with permitted additional terms. For more information
- * see the Pycom Licence v1.0 document supplied with this file, or
- * available at https://www.pycom.io/opensource/licensing
- */
-
-#define SIPY
-
-#define MICROPY_HW_BOARD_NAME "SiPy"
-#define MICROPY_PY_SYS_PLATFORM "SiPy"
-#define MICROPY_HW_HB_PIN_NUM (0)
-#define MICROPY_HW_SAFE_PIN_NUM (21)
-
-#define DEFAULT_AP_SSID "sipy-wlan"
-
-#define MICROPY_HW_FLASH_SIZE (4 * 1024 * 1024)
-
-extern uint32_t micropy_hw_flash_size;
-
-extern uint32_t micropy_hw_antenna_diversity_pin_num;
-
-extern bool micropy_lpwan_use_reset_pin;
-extern uint32_t micropy_lpwan_reset_pin_num;
-extern uint32_t micropy_lpwan_reset_pin_index;
-extern void * micropy_lpwan_reset_pin;
-
-extern uint32_t micropy_lpwan_dio_pin_num;
-extern uint32_t micropy_lpwan_dio_pin_index;
-extern void * micropy_lpwan_dio_pin;
-
-extern uint32_t micropy_lpwan_ncs_pin_num;
-extern uint32_t micropy_lpwan_ncs_pin_index;
-extern void * micropy_lpwan_ncs_pin;
diff --git a/esp32/boards/SIPY/pins.csv b/esp32/boards/SIPY/pins.csv
deleted file mode 100644
index c73407844b..0000000000
--- a/esp32/boards/SIPY/pins.csv
+++ /dev/null
@@ -1,24 +0,0 @@
-G2,GPIO3,P0
-G1,GPIO1,P1
-G23,GPIO0,P2
-G24,GPIO4,P3
-G11,GPIO15,P4
-G12,GPIO5,P5
-G13,GPIO27,P6
-G14,GPIO19,P7
-G15,GPIO2,P8
-G16,GPIO12,P9
-G17,GPIO13,P10
-G22,GPIO22,P11
-G28,GPIO21,P12
-G5,GPI36,P13
-G4,GPI37,P14
-G0,GPI38,P15
-G3,GPI39,P16
-G31,GPI35,P17
-G30,GPI34,P18
-G6,GPIO32,P19
-G7,GPIO33,P20
-G8,GPIO26,P21
-G9,GPIO25,P22
-G10,GPIO14,P23
diff --git a/esp32/boards/SIPY/script b/esp32/boards/SIPY/script
deleted file mode 100644
index 562c7ac1e6..0000000000
--- a/esp32/boards/SIPY/script
+++ /dev/null
@@ -1,13 +0,0 @@
-[
- ["e", "0x1000", "0x40000"],
- ["e", "0x41000", "0x40000"],
- ["e", "0x81000", "0x40000"],
- ["e", "0xC1000", "0x40000"],
- ["e", "0x101000", "0x40000"],
- ["e", "0x141000", "0x40000"],
- ["e", "0x181000", "0x40000"],
- ["e", "0x1C1000", "0x40000"],
- ["w", "0x1000", "bootloader.bin"],
- ["w", "0x8000", "partitions_4MB.bin"],
- ["w", "0x10000", "sipy.bin"]
-]
diff --git a/esp32/boards/SIPY/script2 b/esp32/boards/SIPY/script2
deleted file mode 100644
index 00994ac431..0000000000
--- a/esp32/boards/SIPY/script2
+++ /dev/null
@@ -1,13 +0,0 @@
-{
- "version" : "2.1",
- "partitions" : {
- "factory" : ["0x10000", "0x1AE000"],
- "ota_0" : ["0x1C0000", "0x1AE000"],
- "otadata" : ["0x1BE000", "0x1000"]
- },
- "script" : [
- ["w", "bootloader", "bootloader.bin"],
- ["w", "partitions", "partitions_4MB.bin"],
- ["w", "factory", "sipy.bin"]
- ]
-}
diff --git a/esp32/boards/SIPY/script_4MB b/esp32/boards/SIPY/script_4MB
deleted file mode 100644
index 00994ac431..0000000000
--- a/esp32/boards/SIPY/script_4MB
+++ /dev/null
@@ -1,13 +0,0 @@
-{
- "version" : "2.1",
- "partitions" : {
- "factory" : ["0x10000", "0x1AE000"],
- "ota_0" : ["0x1C0000", "0x1AE000"],
- "otadata" : ["0x1BE000", "0x1000"]
- },
- "script" : [
- ["w", "bootloader", "bootloader.bin"],
- ["w", "partitions", "partitions_4MB.bin"],
- ["w", "factory", "sipy.bin"]
- ]
-}
diff --git a/esp32/boards/SIPY/script_4MB_enc b/esp32/boards/SIPY/script_4MB_enc
deleted file mode 100644
index 9fcc528fe1..0000000000
--- a/esp32/boards/SIPY/script_4MB_enc
+++ /dev/null
@@ -1,13 +0,0 @@
-{
- "version" : "2.1",
- "partitions" : {
- "factory" : ["0x10000", "0x1AE000"],
- "ota_0" : ["0x1C0000", "0x1AE000"],
- "otadata" : ["0x1BE000", "0x1000"]
- },
- "script" : [
- ["w", "secureboot", "bootloader-reflash-digest.bin_enc"],
- ["w", "partitions", "partitions_4MB.bin_enc"],
- ["w", "factory", "sipy.bin_enc"]
- ]
-}
diff --git a/esp32/boards/WIPY/script b/esp32/boards/WIPY/script
deleted file mode 100644
index 739c190a23..0000000000
--- a/esp32/boards/WIPY/script
+++ /dev/null
@@ -1,13 +0,0 @@
-[
- ["e", "0x1000", "0x40000"],
- ["e", "0x41000", "0x40000"],
- ["e", "0x81000", "0x40000"],
- ["e", "0xC1000", "0x40000"],
- ["e", "0x101000", "0x40000"],
- ["e", "0x141000", "0x40000"],
- ["e", "0x181000", "0x40000"],
- ["e", "0x1C1000", "0x40000"],
- ["w", "0x1000", "bootloader.bin"],
- ["w", "0x8000", "partitions_4MB.bin"],
- ["w", "0x10000", "wipy.bin"]
-]
diff --git a/esp32/boards/WIPY/script2 b/esp32/boards/WIPY/script2
deleted file mode 100644
index 09ed1acfa0..0000000000
--- a/esp32/boards/WIPY/script2
+++ /dev/null
@@ -1,13 +0,0 @@
-{
- "version" : "2.1",
- "partitions" : {
- "factory" : ["0x10000", "0x1AE000"],
- "ota_0" : ["0x1C0000", "0x1AE000"],
- "otadata" : ["0x1BE000", "0x1000"]
- },
- "script" : [
- ["w", "bootloader", "bootloader.bin"],
- ["w", "partitions", "partitions_4MB.bin"],
- ["w", "factory", "wipy.bin"]
- ]
-}
diff --git a/esp32/boards/WIPY/script_4MB b/esp32/boards/WIPY/script_4MB
deleted file mode 100644
index 09ed1acfa0..0000000000
--- a/esp32/boards/WIPY/script_4MB
+++ /dev/null
@@ -1,13 +0,0 @@
-{
- "version" : "2.1",
- "partitions" : {
- "factory" : ["0x10000", "0x1AE000"],
- "ota_0" : ["0x1C0000", "0x1AE000"],
- "otadata" : ["0x1BE000", "0x1000"]
- },
- "script" : [
- ["w", "bootloader", "bootloader.bin"],
- ["w", "partitions", "partitions_4MB.bin"],
- ["w", "factory", "wipy.bin"]
- ]
-}
diff --git a/esp32/boards/WIPY/script_4MB_enc b/esp32/boards/WIPY/script_4MB_enc
deleted file mode 100644
index 20b3ef72d9..0000000000
--- a/esp32/boards/WIPY/script_4MB_enc
+++ /dev/null
@@ -1,13 +0,0 @@
-{
- "version" : "2.1",
- "partitions" : {
- "factory" : ["0x10000", "0x1AE000"],
- "ota_0" : ["0x1C0000", "0x1AE000"],
- "otadata" : ["0x1BE000", "0x1000"]
- },
- "script" : [
- ["w", "secureboot", "bootloader-reflash-digest.bin_enc"],
- ["w", "partitions", "partitions_4MB.bin_enc"],
- ["w", "factory", "wipy.bin_enc"]
- ]
-}
diff --git a/esp32/boards/WIPY/script_8MB b/esp32/boards/WIPY/script_8MB
deleted file mode 100644
index 6a52655cba..0000000000
--- a/esp32/boards/WIPY/script_8MB
+++ /dev/null
@@ -1,13 +0,0 @@
-{
- "version" : "2.1",
- "partitions" : {
- "factory" : ["0x10000", "0x1EF000"],
- "ota_0" : ["0x210000", "0x1EF000"],
- "otadata" : ["0x1FF000", "0x1000"]
- },
- "script" : [
- ["w", "bootloader", "bootloader.bin"],
- ["w", "partitions", "partitions_8MB.bin"],
- ["w", "factory", "wipy.bin"]
- ]
-}
diff --git a/esp32/boards/WIPY/script_8MB_enc b/esp32/boards/WIPY/script_8MB_enc
deleted file mode 100644
index 9e5edd2288..0000000000
--- a/esp32/boards/WIPY/script_8MB_enc
+++ /dev/null
@@ -1,13 +0,0 @@
-{
- "version" : "2.1",
- "partitions" : {
- "factory" : ["0x10000", "0x1EF000"],
- "ota_0" : ["0x210000", "0x1EF000"],
- "otadata" : ["0x1FF000", "0x1000"]
- },
- "script" : [
- ["w", "secureboot", "bootloader-reflash-digest.bin_enc"],
- ["w", "partitions", "partitions_8MB.bin_enc"],
- ["w", "factory", "wipy.bin_enc"]
- ]
-}
diff --git a/esp32/boards/WIPY/script_8MB_normal_factory_fw b/esp32/boards/WIPY/script_8MB_normal_factory_fw
new file mode 100644
index 0000000000..feadc3367e
--- /dev/null
+++ b/esp32/boards/WIPY/script_8MB_normal_factory_fw
@@ -0,0 +1,13 @@
+{
+ "version" : "2.1",
+ "partitions" : {
+ "factory" : ["0x10000", "0x1EF000"],
+ "ota_0" : ["0x210000", "0x1EF000"],
+ "otadata" : ["0x1FF000", "0x1000"]
+ },
+ "script" : [
+ ["w", "bootloader", "bootloader.bin"],
+ ["w", "partitions", "partitions_8MB_normal_factory_fw.bin"],
+ ["w", "factory", "wipy.bin"]
+ ]
+}
diff --git a/esp32/boards/WIPY/script_8MB_normal_factory_fw_enc b/esp32/boards/WIPY/script_8MB_normal_factory_fw_enc
new file mode 100644
index 0000000000..31f3787c85
--- /dev/null
+++ b/esp32/boards/WIPY/script_8MB_normal_factory_fw_enc
@@ -0,0 +1,13 @@
+{
+ "version" : "2.1",
+ "partitions" : {
+ "factory" : ["0x10000", "0x1EF000"],
+ "ota_0" : ["0x210000", "0x1EF000"],
+ "otadata" : ["0x1FF000", "0x1000"]
+ },
+ "script" : [
+ ["w", "secureboot", "bootloader-reflash-digest.bin_enc"],
+ ["w", "partitions", "partitions_8MB_normal_factory_fw.bin_enc"],
+ ["w", "factory", "wipy.bin_enc"]
+ ]
+}
diff --git a/esp32/boards/WIPY/script_8MB_small_factory_fw b/esp32/boards/WIPY/script_8MB_small_factory_fw
new file mode 100644
index 0000000000..b50fedb98d
--- /dev/null
+++ b/esp32/boards/WIPY/script_8MB_small_factory_fw
@@ -0,0 +1,14 @@
+{
+ "version" : "2.1",
+ "partitions" : {
+ "factory" : ["0x10000", "0xFF000"],
+ "ota_0" : ["0x110000", "0x2EF000"],
+ "otadata" : ["0x10F000", "0x1000"]
+ },
+ "script" : [
+ ["w", "bootloader", "bootloader.bin"],
+ ["w", "partitions", "partitions_8MB_small_factory_fw.bin"],
+ ["w", "factory", "factory_fw.bin"],
+ ["w", "ota_0", "wipy.bin"]
+ ]
+}
diff --git a/esp32/boards/WIPY/script_8MB_small_factory_fw_enc b/esp32/boards/WIPY/script_8MB_small_factory_fw_enc
new file mode 100644
index 0000000000..a351061d94
--- /dev/null
+++ b/esp32/boards/WIPY/script_8MB_small_factory_fw_enc
@@ -0,0 +1,14 @@
+{
+ "version" : "2.1",
+ "partitions" : {
+ "factory" : ["0x10000", "0xFF000"],
+ "ota_0" : ["0x110000", "0x2EF000"],
+ "otadata" : ["0x10F000", "0x1000"]
+ },
+ "script" : [
+ ["w", "secureboot", "bootloader-reflash-digest.bin_enc"],
+ ["w", "partitions", "partitions_8MB_small_factory_fw.bin_enc"],
+ ["w", "factory", "factory_fw.bin"],
+ ["w", "ota_0", "wipy.bin"]
+ ]
+}
diff --git a/esp32/bootloader/bootloader.c b/esp32/bootloader/bootloader.c
deleted file mode 100644
index 90b06b81cd..0000000000
--- a/esp32/bootloader/bootloader.c
+++ /dev/null
@@ -1,969 +0,0 @@
-// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-#include
-#include
-#include
-#include
-#include
-
-#include "bootloader.h"
-#include "esp_attr.h"
-//#define LOG_LOCAL_LEVEL ESP_LOG_INFO
-#include "esp_log.h"
-#include "esp_system.h"
-
-#include "rom/cache.h"
-#include "rom/efuse.h"
-#include "rom/ets_sys.h"
-#include "rom/spi_flash.h"
-#include "rom/crc.h"
-#include "rom/rtc.h"
-#include "rom/md5_hash.h"
-#include "rom/uart.h"
-#include "rom/gpio.h"
-
-#include "soc/soc.h"
-#include "soc/cpu.h"
-#include "soc/rtc.h"
-#include "soc/dport_reg.h"
-#include "soc/io_mux_reg.h"
-#include "soc/efuse_reg.h"
-#include "soc/rtc_cntl_reg.h"
-#include "soc/timer_group_reg.h"
-#include "soc/gpio_reg.h"
-#include "soc/gpio_sig_map.h"
-
-#include "sdkconfig.h"
-#include "mpconfigboard.h"
-#include "esp_image_format.h"
-#include "esp_secure_boot.h"
-#include "esp_flash_encrypt.h"
-#include "esp_flash_partitions.h"
-#include "bootloader_flash.h"
-#include "bootmgr.h"
-#include "bootloader_random.h"
-#include "bootloader_clock.h"
-
-#include "flash_qio_mode.h"
-#include "mperror.h"
-
-
-#define MAP_ERR_MSG "Image contains multiple %s segments. Only the last one will be mapped."
-
-extern int _bss_start;
-extern int _bss_end;
-extern int _data_start;
-extern int _data_end;
-
-static const char* TAG = "boot";
-
-static const uint8_t empty_signature[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
-
-/*
-We arrive here after the bootloader finished loading the program from flash. The hardware is mostly uninitialized,
-flash cache is down and the app CPU is in reset. We do have a stack, so we can do the initialization in C.
-*/
-
-extern __attribute__((noreturn)) void mperror_fatal_error (void);
-
-static void bootloader_main();
-static void unpack_load_app(const esp_image_metadata_t* data);
-static void print_flash_info(const esp_image_header_t* pfhdr);
-static void set_cache_and_start_app(uint32_t drom_addr,
- uint32_t drom_load_addr,
- uint32_t drom_size,
- uint32_t irom_addr,
- uint32_t irom_load_addr,
- uint32_t irom_size,
- uint32_t entry_addr);
-static void update_flash_config(const esp_image_header_t* pfhdr);
-static void vddsdio_configure();
-static void flash_gpio_configure();
-static void uart_console_configure(void);
-static void wdt_reset_check(void);
-
-// static void read_mac(uint8_t* mac)
-// {
-// uint32_t mac_low = REG_READ(EFUSE_BLK0_RDATA1_REG);
-// uint32_t mac_high = REG_READ(EFUSE_BLK0_RDATA2_REG);
-
-// mac[0] = mac_high >> 8;
-// mac[1] = mac_high;
-// mac[2] = mac_low >> 24;
-// mac[3] = mac_low >> 16;
-// mac[4] = mac_low >> 8;
-// mac[5] = mac_low;
-// }
-
-/*
- * We arrive here after the ROM bootloader finished loading this second stage bootloader from flash.
- * The hardware is mostly uninitialized, flash cache is down and the app CPU is in reset.
- * We do have a stack, so we can do the initialization in C.
- */
-void call_start_cpu0()
-{
- cpu_configure_region_protection();
-
- /* Sanity check that static RAM is after the stack */
-#ifndef NDEBUG
- {
- int *sp = get_sp();
- assert(&_bss_start <= &_bss_end);
- assert(&_data_start <= &_data_end);
- assert(sp < &_bss_start);
- assert(sp < &_data_start);
- }
-#endif
-
- //Clear bss
- memset(&_bss_start, 0, (&_bss_end - &_bss_start) * sizeof(_bss_start));
-
- /* completely reset MMU for both CPUs
- (in case serial bootloader was running) */
- Cache_Read_Disable(0);
- Cache_Read_Disable(1);
- Cache_Flush(0);
- Cache_Flush(1);
- mmu_init(0);
- DPORT_REG_SET_BIT(DPORT_APP_CACHE_CTRL1_REG, DPORT_APP_CACHE_MMU_IA_CLR);
- mmu_init(1);
- DPORT_REG_CLR_BIT(DPORT_APP_CACHE_CTRL1_REG, DPORT_APP_CACHE_MMU_IA_CLR);
- /* (above steps probably unnecessary for most serial bootloader
- usage, all that's absolutely needed is that we unmask DROM0
- cache on the following two lines - normal ROM boot exits with
- DROM0 cache unmasked, but serial bootloader exits with it
- masked. However can't hurt to be thorough and reset
- everything.)
-
- The lines which manipulate DPORT_APP_CACHE_MMU_IA_CLR bit are
- necessary to work around a hardware bug.
- */
- DPORT_REG_CLR_BIT(DPORT_PRO_CACHE_CTRL1_REG, DPORT_PRO_CACHE_MASK_DROM0);
- DPORT_REG_CLR_BIT(DPORT_APP_CACHE_CTRL1_REG, DPORT_APP_CACHE_MASK_DROM0);
-
- bootloader_main();
-}
-
-
-/** @brief Load partition table
- *
- * Parse partition table, get useful data such as location of
- * OTA data partition, factory app partition, and test app partition.
- *
- * @param bs bootloader state structure used to save read data
- * @return return true if the partition table was succesfully loaded and MD5 checksum is valid.
- */
-bool load_partition_table(bootloader_state_t* bs)
-{
- const esp_partition_info_t *partitions;
- const int ESP_PARTITION_TABLE_DATA_LEN = 0xC00; /* length of actual data (signature is appended to this) */
- char *partition_usage;
- esp_err_t err;
- int num_partitions;
-
-#ifdef CONFIG_SECURE_BOOT_ENABLED
- if(esp_secure_boot_enabled()) {
- ESP_LOGI(TAG, "Verifying partition table signature...");
- err = esp_secure_boot_verify_signature(CONFIG_PARTITION_TABLE_OFFSET, ESP_PARTITION_TABLE_DATA_LEN);
- if (err != ESP_OK) {
- ESP_LOGE(TAG, "Failed to verify partition table signature.");
- return false;
- }
- ESP_LOGD(TAG, "Partition table signature verified");
- }
-#endif
-
- partitions = bootloader_mmap(CONFIG_PARTITION_TABLE_OFFSET, ESP_PARTITION_TABLE_DATA_LEN);
- if (!partitions) {
- ESP_LOGE(TAG, "bootloader_mmap(0x%x, 0x%x) failed", CONFIG_PARTITION_TABLE_OFFSET, ESP_PARTITION_TABLE_DATA_LEN);
- return false;
- }
- ESP_LOGD(TAG, "mapped partition table 0x%x at 0x%x", CONFIG_PARTITION_TABLE_OFFSET, (intptr_t)partitions);
-
- err = esp_partition_table_verify(partitions, true, &num_partitions);
- if (err != ESP_OK) {
- ESP_LOGE(TAG, "Failed to verify partition table");
- return false;
- }
-
- ESP_LOGI(TAG, "Partition Table:");
- ESP_LOGI(TAG, "## Label Usage Type ST Offset Length");
-
- for(int i = 0; i < num_partitions; i++) {
- const esp_partition_info_t *partition = &partitions[i];
- ESP_LOGD(TAG, "load partition table entry 0x%x", (intptr_t)partition);
- ESP_LOGD(TAG, "type=%x subtype=%x", partition->type, partition->subtype);
- partition_usage = "unknown";
-
- /* valid partition table */
- switch(partition->type) {
- case PART_TYPE_APP: /* app partition */
- switch(partition->subtype) {
- case PART_SUBTYPE_FACTORY: /* factory binary */
- bs->image[0] = partition->pos;
- partition_usage = "factory app";
- bs->image_count = 1;
- break;
- default:
- /* OTA binary */
- if ((partition->subtype & ~PART_SUBTYPE_OTA_MASK) == PART_SUBTYPE_OTA_FLAG) {
- bs->image[bs->image_count++] = partition->pos;
- partition_usage = "OTA app";
- } else {
- partition_usage = "Unknown app";
- }
- break;
- }
- break; /* PART_TYPE_APP */
- case PART_TYPE_DATA: /* data partition */
- switch(partition->subtype) {
- case PART_SUBTYPE_DATA_OTA: /* ota data */
- bs->ota_info = partition->pos;
- partition_usage = "OTA data";
- break;
- case PART_SUBTYPE_DATA_RF:
- partition_usage = "RF data";
- break;
- case PART_SUBTYPE_DATA_WIFI:
- partition_usage = "WiFi data";
- break;
- default:
- partition_usage = "Unknown data";
- break;
- }
- break; /* PARTITION_USAGE_DATA */
- default: /* other partition type */
- break;
- }
-
- /* print partition type info */
- ESP_LOGI(TAG, "%2d %-16s %-16s %02x %02x %08x %08x", i, partition->label, partition_usage,
- partition->type, partition->subtype,
- partition->pos.offset, partition->pos.size);
- }
-
- bootloader_munmap(partitions);
-
- ESP_LOGI(TAG,"End of partition table");
- return true;
-}
-
-static uint32_t ota_select_crc(const boot_info_t *s)
-{
- return crc32_le(UINT32_MAX, (uint8_t*)&s->ActiveImg, sizeof(boot_info_t) - sizeof(s->crc));
-}
-
-static bool ota_select_valid(const boot_info_t *s)
-{
- uint32_t _crc = ota_select_crc(s);
- ESP_LOGI(TAG, "Cal crc=%x, saved crc=%x", _crc, s->crc);
- return s->Status != UINT32_MAX && s->crc == _crc;
-}
-
-static IRAM_ATTR bool ota_write_boot_info (boot_info_t *boot_info, uint32_t offset) {
- esp_rom_spiflash_result_t write_result;
-
- boot_info->crc = ota_select_crc(boot_info);
- Cache_Read_Disable(0);
- if (ESP_ROM_SPIFLASH_RESULT_OK != esp_rom_spiflash_erase_sector(offset / 0x1000)) {
- ESP_LOGE(TAG, SPI_ERROR_LOG);
- Cache_Read_Enable(0);
- return false;
- }
-
- if (esp_flash_encryption_enabled()) {
- // if flash is encrypted, then Write is done 32B chunks
- uint8_t buff[64] __attribute__((aligned (32)));
- memcpy(buff, (void *)boot_info, sizeof(boot_info_t));
- write_result = esp_rom_spiflash_write_encrypted(offset, (void *)boot_info, 64);
- }
- else {
- write_result = esp_rom_spiflash_write(offset, (void *)boot_info, sizeof(boot_info_t));
- }
-
- if (ESP_ROM_SPIFLASH_RESULT_OK != write_result) {
- ESP_LOGE(TAG, SPI_ERROR_LOG);
- Cache_Read_Enable(0);
- return false;
- }
- Cache_Read_Enable(0);
- return true;
-}
-
-
-/* Return true if a partition has a valid app image that was successfully loaded */
-static bool get_image_from_partition(const esp_partition_pos_t *partition, esp_image_metadata_t *data)
-{
- if (partition->size == 0) {
- ESP_LOGD(TAG, "Can't boot from zero-length partition");
- return false;
- }
-
- if (bootloader_load_image(partition, data) == ESP_OK) {
- ESP_LOGI(TAG, "Loaded app from partition at offset 0x%x",
- partition->offset);
- return true;
- }
-
- return false;
-}
-
-static bool find_active_image(bootloader_state_t *bs, esp_partition_pos_t *partition)
-{
- boot_info_t *boot_info;
- boot_info_t _boot_info;
-
- if (bs->ota_info.size < 2 * sizeof(esp_ota_select_entry_t)) {
- ESP_LOGE(TAG, "ERROR: ota_info partition size %d is too small (minimum %d bytes)", bs->ota_info.size, sizeof(esp_ota_select_entry_t));
- return false;
- }
- ESP_LOGI(TAG, "Loading boot info");
- boot_info = (boot_info_t *)bootloader_mmap(bs->ota_info.offset, bs->ota_info.size);
- if (!boot_info) {
- ESP_LOGE(TAG, "bootloader_mmap(0x%x, 0x%x) failed", bs->ota_info.offset, bs->ota_info.size);
- return false;
- }
- memcpy(&_boot_info, boot_info, sizeof(boot_info_t));
- bootloader_munmap(boot_info);
- boot_info = &_boot_info;
-#ifndef RGB_LED_DISABLE
- mperror_init0();
-#endif
-
- // // check the signature fot he bootloader first
- // uint8_t signature[16];
- // calculate_signature(signature);
- // if (!memcmp(boot_info->signature, empty_signature, sizeof(boot_info->signature))) {
- // ESP_LOGI(TAG, "Writing the signature");
- // // write the signature
- // memcpy(boot_info->signature, signature, sizeof(boot_info->signature));
- // if (!ota_write_boot_info (boot_info, bs->ota_info.offset)) {
- // ESP_LOGE(TAG, "Error writing boot info");
- // mperror_fatal_error();
- // return false;
- // }
- // } else {
- // ESP_LOGI(TAG, "Comparing the signature");
- // // compare the signatures
- // if (memcmp(boot_info->signature, signature, sizeof(boot_info->signature))) {
- // // signature check failed, don't load the app!
- // mperror_fatal_error();
- // return false;
- // }
- // }
-
- if (!ota_select_valid(boot_info)) {
- ESP_LOGI(TAG, "Initializing OTA partition info");
- // init status flash
- memcpy(partition, &bs->image[0], sizeof(esp_partition_pos_t));
- boot_info->ActiveImg = IMG_ACT_FACTORY;
- boot_info->Status = IMG_STATUS_READY;
- boot_info->PrevImg = IMG_ACT_FACTORY;
- boot_info->safeboot = false;
- if (!ota_write_boot_info (boot_info, bs->ota_info.offset)) {
- ESP_LOGE(TAG, "Error writing boot info");
-#ifndef RGB_LED_DISABLE
- mperror_fatal_error();
-#endif
- return false;
- }
- return true;
- } else {
- // CRC is fine, check here the image that we need to load based on the status (ready or check)
- // if image is in status check then we must verify the MD5, and set the new status
- // if the MD5 fails, then we roll back to the previous image
-
- // do we have a new image that needs to be verified?
- if (boot_info->Status == IMG_STATUS_CHECK) {
- if (boot_info->ActiveImg == IMG_ACT_UPDATE2) {
- boot_info->ActiveImg = IMG_ACT_FACTORY; // we only have space for 1 OTA image
- }
-
- // verify the active image (ota partition)
- esp_image_metadata_t data;
- if (ESP_OK != esp_image_verify(ESP_IMAGE_VERIFY, &bs->image[boot_info->ActiveImg], &data)) {
- ets_printf("Cannot load Firmware img in the active partition! .. Defaulting back to previous partition\n");
- // switch to the previous image
- uint32_t tempimg = boot_info->ActiveImg;
- boot_info->ActiveImg = boot_info->PrevImg;
- boot_info->PrevImg = tempimg;
- }
-
- // in any case, change the status to "READY"
- boot_info->Status = IMG_STATUS_READY;
- // write the new boot info
- if (!ota_write_boot_info (boot_info, bs->ota_info.offset)) {
- ESP_LOGE(TAG, "Error writing boot info");
- mperror_fatal_error();
- return false;
- }
- }
-
- // this one might modify the boot info hence it MUST be called after
- // bootmgr_verify! (so that the changes are not saved to flash)
- ESP_LOGI(TAG, "Checking safe boot pin");
- uint32_t ActiveImg = boot_info->ActiveImg;
- uint32_t safeboot = wait_for_safe_boot (boot_info, &ActiveImg);
- if (safeboot > 0) {
- ESP_LOGI(TAG, "Safe boot requested!");
- }
- if (safeboot != boot_info->safeboot) {
- if (boot_info->safeboot == SAFE_BOOT_SW) {
- boot_info->safeboot = SAFE_BOOT_HW;
- } else {
- boot_info->safeboot = safeboot;
- }
- // write the new boot info
- if (!ota_write_boot_info (boot_info, bs->ota_info.offset)) {
- ESP_LOGE(TAG, "Error writing boot info");
- mperror_fatal_error();
- return false;
- }
- }
-
- // load the selected active image
- memcpy(partition, &bs->image[ActiveImg], sizeof(esp_partition_pos_t));
- return true;
- }
-}
-
-
-/**
- * @function : bootloader_main
- * @description: entry function of 2nd bootloader
- *
- * @inputs: void
- */
-
-static void bootloader_main()
-{
- vddsdio_configure();
- flash_gpio_configure();
- bootloader_clock_configure();
- uart_console_configure();
- ESP_LOGI(TAG, "ESP-IDF 2nd stage bootloader");
- wdt_reset_check();
-#if defined(CONFIG_SECURE_BOOT_ENABLED) || defined(CONFIG_FLASH_ENCRYPTION_ENABLED)
- esp_err_t err;
-#endif
- esp_image_header_t fhdr __attribute__((aligned (4)));
- bootloader_state_t bootloader_state __attribute__((aligned (4)));
- esp_partition_pos_t partition __attribute__((aligned (4)));
- esp_image_metadata_t image_data __attribute__((aligned (4)));
-
- memset(&bootloader_state, 0, sizeof(bootloader_state));
- ets_set_appcpu_boot_addr(0);
-
- /* disable watch dog here */
- REG_CLR_BIT( RTC_CNTL_WDTCONFIG0_REG, RTC_CNTL_WDT_FLASHBOOT_MOD_EN );
- REG_CLR_BIT( TIMG_WDTCONFIG0_REG(0), TIMG_WDT_FLASHBOOT_MOD_EN );
-
-#ifndef CONFIG_SPI_FLASH_ROM_DRIVER_PATCH
- const uint32_t spiconfig = ets_efuse_get_spiconfig();
- if(spiconfig != EFUSE_SPICONFIG_SPI_DEFAULTS && spiconfig != EFUSE_SPICONFIG_HSPI_DEFAULTS) {
- ESP_LOGE(TAG, "SPI flash pins are overridden. \"Enable SPI flash ROM driver patched functions\" must be enabled in menuconfig");
- return;
- }
-#endif
-
- esp_rom_spiflash_unlock();
-
- ESP_LOGI(TAG, "Enabling RNG early entropy source...");
- bootloader_random_enable();
-
-#if CONFIG_FLASHMODE_QIO || CONFIG_FLASHMODE_QOUT
- bootloader_enable_qio_mode();
-#endif
-
- if (bootloader_flash_read(ESP_BOOTLOADER_OFFSET, &fhdr,
- sizeof(esp_image_header_t), true) != ESP_OK) {
- ESP_LOGE(TAG, "failed to load bootloader header!");
- return;
- }
-
- // force 4MB flash size for all boards
- fhdr.spi_size = ESP_IMAGE_FLASH_SIZE_4MB;
-
- print_flash_info(&fhdr);
- update_flash_config(&fhdr);
-
- if (!load_partition_table(&bootloader_state)) {
- ESP_LOGE(TAG, "load partition table error!");
- return;
- }
-
- // check if the partition table has OTA info partition
- if (bootloader_state.ota_info.offset == 0 || !find_active_image(&bootloader_state, &partition)) {
- // nothing to load, bail out
- ESP_LOGE(TAG, "nothing to load");
-#ifndef RGB_LED_DISABLE
- mperror_fatal_error();
-#endif
- return;
- }
-
- get_image_from_partition(&partition, &image_data);
-
-#ifdef CONFIG_SECURE_BOOT_ENABLED
- // Generate secure digest from this bootloader to protect future modifications
- ESP_LOGI(TAG, "Checking secure boot...");
- err = esp_secure_boot_permanently_enable();
- if (err != ESP_OK) {
- ESP_LOGE(TAG, "Bootloader digest generation failed (%d). SECURE BOOT IS NOT ENABLED.", err);
- // Stop booting, as this could next Encrypt the whole Flash
- return;
- }
-#endif
-
-#ifdef CONFIG_FLASH_ENCRYPTION_ENABLED
- // encrypt flash
- ESP_LOGI(TAG, "Checking flash encryption...");
- bool flash_encryption_enabled = esp_flash_encryption_enabled();
- err = esp_flash_encrypt_check_and_update();
- if (err != ESP_OK) {
- ESP_LOGE(TAG, "Flash encryption check failed (%d).", err);
- return;
- }
-
- if (!flash_encryption_enabled && esp_flash_encryption_enabled()) {
- /* Flash encryption was just enabled for the first time,
- so issue a system reset to ensure flash encryption
- cache resets properly */
- ESP_LOGI(TAG, "Resetting with flash encryption enabled...");
- REG_WRITE(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_SW_SYS_RST);
- return;
- }
-#endif
-
- ESP_LOGI(TAG, "Disabling RNG early entropy source...");
- bootloader_random_disable();
-
- // copy loaded segments to RAM, set up caches for mapped segments, and start application
- ESP_LOGI(TAG, "Loading app partition at offset %08x", partition.offset);
- unpack_load_app(&image_data);
-}
-
-static void unpack_load_app(const esp_image_metadata_t* data)
-{
- uint32_t drom_addr = 0;
- uint32_t drom_load_addr = 0;
- uint32_t drom_size = 0;
- uint32_t irom_addr = 0;
- uint32_t irom_load_addr = 0;
- uint32_t irom_size = 0;
-
- // Find DROM & IROM addresses, to configure cache mappings
- for (int i = 0; i < data->image.segment_count; i++) {
- const esp_image_segment_header_t *header = &data->segments[i];
- if (header->load_addr >= SOC_IROM_LOW && header->load_addr < SOC_IROM_HIGH) {
- if (drom_addr != 0) {
- ESP_LOGE(TAG, MAP_ERR_MSG, "DROM");
- } else {
- ESP_LOGD(TAG, "Mapping segment %d as %s", i, "DROM");
- }
- drom_addr = data->segment_data[i];
- drom_load_addr = header->load_addr;
- drom_size = header->data_len;
- }
- if (header->load_addr >= SOC_DROM_LOW && header->load_addr < SOC_DROM_HIGH) {
- if (irom_addr != 0) {
- ESP_LOGE(TAG, MAP_ERR_MSG, "IROM");
- } else {
- ESP_LOGD(TAG, "Mapping segment %d as %s", i, "IROM");
- }
- irom_addr = data->segment_data[i];
- irom_load_addr = header->load_addr;
- irom_size = header->data_len;
- }
- }
-
- ESP_LOGD(TAG, "calling set_cache_and_start_app");
- set_cache_and_start_app(drom_addr,
- drom_load_addr,
- drom_size,
- irom_addr,
- irom_load_addr,
- irom_size,
- data->image.entry_addr);
-}
-
-static void set_cache_and_start_app(
- uint32_t drom_addr,
- uint32_t drom_load_addr,
- uint32_t drom_size,
- uint32_t irom_addr,
- uint32_t irom_load_addr,
- uint32_t irom_size,
- uint32_t entry_addr)
-{
- ESP_LOGD(TAG, "configure drom and irom and start");
- Cache_Read_Disable( 0 );
- Cache_Flush( 0 );
-
- /* Clear the MMU entries that are already set up,
- so the new app only has the mappings it creates.
- */
- for (int i = 0; i < DPORT_FLASH_MMU_TABLE_SIZE; i++) {
- DPORT_PRO_FLASH_MMU_TABLE[i] = DPORT_FLASH_MMU_TABLE_INVALID_VAL;
- }
-
- uint32_t drom_page_count = (drom_size + 64*1024 - 1) / (64*1024); // round up to 64k
- ESP_LOGV(TAG, "d mmu set paddr=%08x vaddr=%08x size=%d n=%d", drom_addr & 0xffff0000, drom_load_addr & 0xffff0000, drom_size, drom_page_count );
- int rc = cache_flash_mmu_set( 0, 0, drom_load_addr & 0xffff0000, drom_addr & 0xffff0000, 64, drom_page_count );
- ESP_LOGV(TAG, "rc=%d", rc );
- rc = cache_flash_mmu_set( 1, 0, drom_load_addr & 0xffff0000, drom_addr & 0xffff0000, 64, drom_page_count );
- ESP_LOGV(TAG, "rc=%d", rc );
- uint32_t irom_page_count = (irom_size + 64*1024 - 1) / (64*1024); // round up to 64k
- ESP_LOGV(TAG, "i mmu set paddr=%08x vaddr=%08x size=%d n=%d", irom_addr & 0xffff0000, irom_load_addr & 0xffff0000, irom_size, irom_page_count );
- rc = cache_flash_mmu_set( 0, 0, irom_load_addr & 0xffff0000, irom_addr & 0xffff0000, 64, irom_page_count );
- ESP_LOGV(TAG, "rc=%d", rc );
- rc = cache_flash_mmu_set( 1, 0, irom_load_addr & 0xffff0000, irom_addr & 0xffff0000, 64, irom_page_count );
- ESP_LOGV(TAG, "rc=%d", rc );
- DPORT_REG_CLR_BIT( DPORT_PRO_CACHE_CTRL1_REG, (DPORT_PRO_CACHE_MASK_IRAM0) | (DPORT_PRO_CACHE_MASK_IRAM1 & 0) | (DPORT_PRO_CACHE_MASK_IROM0 & 0) | DPORT_PRO_CACHE_MASK_DROM0 | DPORT_PRO_CACHE_MASK_DRAM1 );
- DPORT_REG_CLR_BIT( DPORT_APP_CACHE_CTRL1_REG, (DPORT_APP_CACHE_MASK_IRAM0) | (DPORT_APP_CACHE_MASK_IRAM1 & 0) | (DPORT_APP_CACHE_MASK_IROM0 & 0) | DPORT_APP_CACHE_MASK_DROM0 | DPORT_APP_CACHE_MASK_DRAM1 );
- Cache_Read_Enable( 0 );
-
- // Application will need to do Cache_Flush(1) and Cache_Read_Enable(1)
-
- ESP_LOGD(TAG, "start: 0x%08x", entry_addr);
- typedef void (*entry_t)(void);
- entry_t entry = ((entry_t) entry_addr);
-
- // TODO: we have used quite a bit of stack at this point.
- // use "movsp" instruction to reset stack back to where ROM stack starts.
- (*entry)();
-}
-
-static void update_flash_config(const esp_image_header_t* pfhdr)
-{
- uint32_t size;
- switch(pfhdr->spi_size) {
- case ESP_IMAGE_FLASH_SIZE_1MB:
- size = 1;
- break;
- case ESP_IMAGE_FLASH_SIZE_2MB:
- size = 2;
- break;
- case ESP_IMAGE_FLASH_SIZE_4MB:
- size = 4;
- break;
- case ESP_IMAGE_FLASH_SIZE_8MB:
- size = 8;
- break;
- case ESP_IMAGE_FLASH_SIZE_16MB:
- size = 16;
- break;
- default:
- size = 2;
- }
- Cache_Read_Disable( 0 );
- // Set flash chip size
- esp_rom_spiflash_config_param(g_rom_flashchip.device_id, size * 0x100000, 0x10000, 0x1000, 0x100, 0xffff);
- // TODO: set mode
- // TODO: set frequency
- Cache_Flush(0);
- Cache_Read_Enable( 0 );
-}
-
-static void print_flash_info(const esp_image_header_t* phdr)
-{
-#if (BOOT_LOG_LEVEL >= BOOT_LOG_LEVEL_NOTICE)
-
- ESP_LOGD(TAG, "magic %02x", phdr->magic );
- ESP_LOGD(TAG, "segments %02x", phdr->segment_count );
- ESP_LOGD(TAG, "spi_mode %02x", phdr->spi_mode );
- ESP_LOGD(TAG, "spi_speed %02x", phdr->spi_speed );
- ESP_LOGD(TAG, "spi_size %02x", phdr->spi_size );
-
- const char* str;
- switch ( phdr->spi_speed ) {
- case ESP_IMAGE_SPI_SPEED_40M:
- str = "40MHz";
- break;
- case ESP_IMAGE_SPI_SPEED_26M:
- str = "26.7MHz";
- break;
- case ESP_IMAGE_SPI_SPEED_20M:
- str = "20MHz";
- break;
- case ESP_IMAGE_SPI_SPEED_80M:
- str = "80MHz";
- break;
- default:
- str = "20MHz";
- break;
- }
- ESP_LOGI(TAG, "SPI Speed : %s", str );
-
- /* SPI mode could have been set to QIO during boot already,
- so test the SPI registers not the flash header */
- uint32_t spi_ctrl = REG_READ(SPI_CTRL_REG(0));
- if (spi_ctrl & SPI_FREAD_QIO) {
- str = "QIO";
- } else if (spi_ctrl & SPI_FREAD_QUAD) {
- str = "QOUT";
- } else if (spi_ctrl & SPI_FREAD_DIO) {
- str = "DIO";
- } else if (spi_ctrl & SPI_FREAD_DUAL) {
- str = "DOUT";
- } else if (spi_ctrl & SPI_FASTRD_MODE) {
- str = "FAST READ";
- } else {
- str = "SLOW READ";
- }
- ESP_LOGI(TAG, "SPI Mode : %s", str );
-
- switch ( phdr->spi_size ) {
- case ESP_IMAGE_FLASH_SIZE_1MB:
- str = "1MB";
- break;
- case ESP_IMAGE_FLASH_SIZE_2MB:
- str = "2MB";
- break;
- case ESP_IMAGE_FLASH_SIZE_4MB:
- str = "4MB";
- break;
- case ESP_IMAGE_FLASH_SIZE_8MB:
- str = "8MB";
- break;
- case ESP_IMAGE_FLASH_SIZE_16MB:
- str = "16MB";
- break;
- default:
- str = "2MB";
- break;
- }
- ESP_LOGI(TAG, "SPI Flash Size : %s", str );
-#endif
-}
-
-
-static void vddsdio_configure()
-{
-#if CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_9V
- rtc_vddsdio_config_t cfg = rtc_vddsdio_get_config();
- if (cfg.enable == 1 && cfg.tieh == 0) { // VDDSDIO regulator is enabled @ 1.8V
- cfg.drefh = 3;
- cfg.drefm = 3;
- cfg.drefl = 3;
- cfg.force = 1;
- rtc_vddsdio_set_config(cfg);
- ets_delay_us(10); // wait for regulator to become stable
- }
-#endif // CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_9V
-}
-
-
-#define FLASH_CLK_IO 6
-#define FLASH_CS_IO 11
-#define FLASH_SPIQ_IO 7
-#define FLASH_SPID_IO 8
-#define FLASH_SPIWP_IO 10
-#define FLASH_SPIHD_IO 9
-#define FLASH_IO_MATRIX_DUMMY_40M 1
-#define FLASH_IO_MATRIX_DUMMY_80M 2
-static void IRAM_ATTR flash_gpio_configure()
-{
- int spi_cache_dummy = 0;
- int drv = 2;
-#if CONFIG_FLASHMODE_QIO
- spi_cache_dummy = SPI0_R_QIO_DUMMY_CYCLELEN; //qio 3
-#elif CONFIG_FLASHMODE_QOUT
- spi_cache_dummy = SPI0_R_FAST_DUMMY_CYCLELEN; //qout 7
-#elif CONFIG_FLASHMODE_DIO
- spi_cache_dummy = SPI0_R_DIO_DUMMY_CYCLELEN; //dio 3
-#elif CONFIG_FLASHMODE_DOUT
- spi_cache_dummy = SPI0_R_FAST_DUMMY_CYCLELEN; //dout 7
-#endif
- /* dummy_len_plus values defined in ROM for SPI flash configuration */
- extern uint8_t g_rom_spiflash_dummy_len_plus[];
-#if CONFIG_ESPTOOLPY_FLASHFREQ_40M
- g_rom_spiflash_dummy_len_plus[0] = FLASH_IO_MATRIX_DUMMY_40M;
- g_rom_spiflash_dummy_len_plus[1] = FLASH_IO_MATRIX_DUMMY_40M;
- SET_PERI_REG_BITS(SPI_USER1_REG(0), SPI_USR_DUMMY_CYCLELEN_V, spi_cache_dummy + FLASH_IO_MATRIX_DUMMY_40M, SPI_USR_DUMMY_CYCLELEN_S); //DUMMY
-#elif CONFIG_ESPTOOLPY_FLASHFREQ_80M
- g_rom_spiflash_dummy_len_plus[0] = FLASH_IO_MATRIX_DUMMY_80M;
- g_rom_spiflash_dummy_len_plus[1] = FLASH_IO_MATRIX_DUMMY_80M;
- SET_PERI_REG_BITS(SPI_USER1_REG(0), SPI_USR_DUMMY_CYCLELEN_V, spi_cache_dummy + FLASH_IO_MATRIX_DUMMY_80M, SPI_USR_DUMMY_CYCLELEN_S); //DUMMY
- drv = 3;
-#endif
-
- uint32_t chip_ver = REG_GET_FIELD(EFUSE_BLK0_RDATA3_REG, EFUSE_RD_CHIP_VER_PKG);
- uint32_t pkg_ver = chip_ver & 0x7;
-
- if (pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32D2WDQ5) {
- // For ESP32D2WD the SPI pins are already configured
- // flash clock signal should come from IO MUX.
- PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CLK_U, FUNC_SD_CLK_SPICLK);
- SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, drv, FUN_DRV_S);
- } else if (pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32PICOD2) {
- // For ESP32PICOD2 the SPI pins are already configured
- // flash clock signal should come from IO MUX.
- PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CLK_U, FUNC_SD_CLK_SPICLK);
- SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, drv, FUN_DRV_S);
- } else if (pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32PICOD4) {
- // For ESP32PICOD4 the SPI pins are already configured
- // flash clock signal should come from IO MUX.
- PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CLK_U, FUNC_SD_CLK_SPICLK);
- SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, drv, FUN_DRV_S);
- } else {
- const uint32_t spiconfig = ets_efuse_get_spiconfig();
- if (spiconfig == EFUSE_SPICONFIG_SPI_DEFAULTS) {
- gpio_matrix_out(FLASH_CS_IO, SPICS0_OUT_IDX, 0, 0);
- gpio_matrix_out(FLASH_SPIQ_IO, SPIQ_OUT_IDX, 0, 0);
- gpio_matrix_in(FLASH_SPIQ_IO, SPIQ_IN_IDX, 0);
- gpio_matrix_out(FLASH_SPID_IO, SPID_OUT_IDX, 0, 0);
- gpio_matrix_in(FLASH_SPID_IO, SPID_IN_IDX, 0);
- gpio_matrix_out(FLASH_SPIWP_IO, SPIWP_OUT_IDX, 0, 0);
- gpio_matrix_in(FLASH_SPIWP_IO, SPIWP_IN_IDX, 0);
- gpio_matrix_out(FLASH_SPIHD_IO, SPIHD_OUT_IDX, 0, 0);
- gpio_matrix_in(FLASH_SPIHD_IO, SPIHD_IN_IDX, 0);
- //select pin function gpio
- PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA0_U, PIN_FUNC_GPIO);
- PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA1_U, PIN_FUNC_GPIO);
- PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA2_U, PIN_FUNC_GPIO);
- PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA3_U, PIN_FUNC_GPIO);
- PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CMD_U, PIN_FUNC_GPIO);
- // flash clock signal should come from IO MUX.
- // set drive ability for clock
- PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CLK_U, FUNC_SD_CLK_SPICLK);
- SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, drv, FUN_DRV_S);
- }
- }
-}
-
-
-static void uart_console_configure(void)
-{
-#if CONFIG_CONSOLE_UART_NONE
- ets_install_putc1(NULL);
- ets_install_putc2(NULL);
-#else // CONFIG_CONSOLE_UART_NONE
- const int uart_num = CONFIG_CONSOLE_UART_NUM;
-
- uartAttach();
- ets_install_uart_printf();
-
- // Wait for UART FIFO to be empty.
- uart_tx_wait_idle(0);
-
-#if CONFIG_CONSOLE_UART_CUSTOM
- // Some constants to make the following code less upper-case
- const int uart_tx_gpio = CONFIG_CONSOLE_UART_TX_GPIO;
- const int uart_rx_gpio = CONFIG_CONSOLE_UART_RX_GPIO;
- // Switch to the new UART (this just changes UART number used for
- // ets_printf in ROM code).
- uart_tx_switch(uart_num);
- // If console is attached to UART1 or if non-default pins are used,
- // need to reconfigure pins using GPIO matrix
- if (uart_num != 0 || uart_tx_gpio != 1 || uart_rx_gpio != 3) {
- // Change pin mode for GPIO1/3 from UART to GPIO
- PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0RXD_U, FUNC_U0RXD_GPIO3);
- PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_U0TXD_GPIO1);
- // Route GPIO signals to/from pins
- // (arrays should be optimized away by the compiler)
- const uint32_t tx_idx_list[3] = { U0TXD_OUT_IDX, U1TXD_OUT_IDX, U2TXD_OUT_IDX };
- const uint32_t rx_idx_list[3] = { U0RXD_IN_IDX, U1RXD_IN_IDX, U2RXD_IN_IDX };
- const uint32_t tx_idx = tx_idx_list[uart_num];
- const uint32_t rx_idx = rx_idx_list[uart_num];
- gpio_matrix_out(uart_tx_gpio, tx_idx, 0, 0);
- gpio_matrix_in(uart_rx_gpio, rx_idx, 0);
- }
-#endif // CONFIG_CONSOLE_UART_CUSTOM
-
- // Set configured UART console baud rate
- const int uart_baud = CONFIG_CONSOLE_UART_BAUDRATE;
- uart_div_modify(uart_num, (rtc_clk_apb_freq_get() << 4) / uart_baud);
-
-#endif // CONFIG_CONSOLE_UART_NONE
-}
-
-static void wdt_reset_cpu0_info_enable(void)
-{
- // We do not reset core1 info here because it didn't work before cpu1 was up. So we put it into call_start_cpu1.
- DPORT_REG_SET_BIT(DPORT_PRO_CPU_RECORD_CTRL_REG, DPORT_PRO_CPU_PDEBUG_ENABLE | DPORT_PRO_CPU_RECORD_ENABLE);
- DPORT_REG_CLR_BIT(DPORT_PRO_CPU_RECORD_CTRL_REG, DPORT_PRO_CPU_RECORD_ENABLE);
-}
-
-static void wdt_reset_info_dump(int cpu)
-{
- uint32_t inst = 0, pid = 0, stat = 0, data = 0, pc = 0,
- lsstat = 0, lsaddr = 0, lsdata = 0, dstat = 0;
- char *cpu_name = cpu ? "APP" : "PRO";
-
- if (cpu == 0) {
- stat = DPORT_REG_READ(DPORT_PRO_CPU_RECORD_STATUS_REG);
- pid = DPORT_REG_READ(DPORT_PRO_CPU_RECORD_PID_REG);
- inst = DPORT_REG_READ(DPORT_PRO_CPU_RECORD_PDEBUGINST_REG);
- dstat = DPORT_REG_READ(DPORT_PRO_CPU_RECORD_PDEBUGSTATUS_REG);
- data = DPORT_REG_READ(DPORT_PRO_CPU_RECORD_PDEBUGDATA_REG);
- pc = DPORT_REG_READ(DPORT_PRO_CPU_RECORD_PDEBUGPC_REG);
- lsstat = DPORT_REG_READ(DPORT_PRO_CPU_RECORD_PDEBUGLS0STAT_REG);
- lsaddr = DPORT_REG_READ(DPORT_PRO_CPU_RECORD_PDEBUGLS0ADDR_REG);
- lsdata = DPORT_REG_READ(DPORT_PRO_CPU_RECORD_PDEBUGLS0DATA_REG);
-
- } else {
- stat = DPORT_REG_READ(DPORT_APP_CPU_RECORD_STATUS_REG);
- pid = DPORT_REG_READ(DPORT_APP_CPU_RECORD_PID_REG);
- inst = DPORT_REG_READ(DPORT_APP_CPU_RECORD_PDEBUGINST_REG);
- dstat = DPORT_REG_READ(DPORT_APP_CPU_RECORD_PDEBUGSTATUS_REG);
- data = DPORT_REG_READ(DPORT_APP_CPU_RECORD_PDEBUGDATA_REG);
- pc = DPORT_REG_READ(DPORT_APP_CPU_RECORD_PDEBUGPC_REG);
- lsstat = DPORT_REG_READ(DPORT_APP_CPU_RECORD_PDEBUGLS0STAT_REG);
- lsaddr = DPORT_REG_READ(DPORT_APP_CPU_RECORD_PDEBUGLS0ADDR_REG);
- lsdata = DPORT_REG_READ(DPORT_APP_CPU_RECORD_PDEBUGLS0DATA_REG);
- }
- if (DPORT_RECORD_PDEBUGINST_SZ(inst) == 0 &&
- DPORT_RECORD_PDEBUGSTATUS_BBCAUSE(dstat) == DPORT_RECORD_PDEBUGSTATUS_BBCAUSE_WAITI) {
- ESP_LOGW(TAG, "WDT reset info: %s CPU PC=0x%x (waiti mode)", cpu_name, pc);
- } else {
- ESP_LOGW(TAG, "WDT reset info: %s CPU PC=0x%x", cpu_name, pc);
- }
- ESP_LOGD(TAG, "WDT reset info: %s CPU STATUS 0x%08x", cpu_name, stat);
- ESP_LOGD(TAG, "WDT reset info: %s CPU PID 0x%08x", cpu_name, pid);
- ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGINST 0x%08x", cpu_name, inst);
- ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGSTATUS 0x%08x", cpu_name, dstat);
- ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGDATA 0x%08x", cpu_name, data);
- ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGPC 0x%08x", cpu_name, pc);
- ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGLS0STAT 0x%08x", cpu_name, lsstat);
- ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGLS0ADDR 0x%08x", cpu_name, lsaddr);
- ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGLS0DATA 0x%08x", cpu_name, lsdata);
-}
-
-static void wdt_reset_check(void)
-{
- int wdt_rst = 0;
- RESET_REASON rst_reas[2];
-
- rst_reas[0] = rtc_get_reset_reason(0);
- rst_reas[1] = rtc_get_reset_reason(1);
- if (rst_reas[0] == RTCWDT_SYS_RESET || rst_reas[0] == TG0WDT_SYS_RESET || rst_reas[0] == TG1WDT_SYS_RESET ||
- rst_reas[0] == TGWDT_CPU_RESET || rst_reas[0] == RTCWDT_CPU_RESET) {
- ESP_LOGW(TAG, "PRO CPU has been reset by WDT.");
- wdt_rst = 1;
- }
- if (rst_reas[1] == RTCWDT_SYS_RESET || rst_reas[1] == TG0WDT_SYS_RESET || rst_reas[1] == TG1WDT_SYS_RESET ||
- rst_reas[1] == TGWDT_CPU_RESET || rst_reas[1] == RTCWDT_CPU_RESET) {
- ESP_LOGW(TAG, "APP CPU has been reset by WDT.");
- wdt_rst = 1;
- }
- if (wdt_rst) {
- // if reset by WDT dump info from trace port
- wdt_reset_info_dump(0);
- wdt_reset_info_dump(1);
- }
- wdt_reset_cpu0_info_enable();
-}
-
diff --git a/esp32/bootloader/bootloader.h b/esp32/bootloader/bootloader.h
deleted file mode 100644
index e8b8b4bb9f..0000000000
--- a/esp32/bootloader/bootloader.h
+++ /dev/null
@@ -1,98 +0,0 @@
-// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-#ifndef __BOOTLOADER_H__
-#define __BOOTLOADER_H__
-
-#include
-#include "esp_flash_data_types.h"
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-/* OTA selection structure (two copies in the OTA data partition).
- Size of 32 bytes is friendly to flash encryption */
-typedef struct {
- uint32_t ota_seq;
- uint8_t seq_label[24];
- uint32_t crc; /* CRC32 of ota_seq field only */
-} ota_select;
-
-typedef struct _boot_info_t
-{
- uint32_t ActiveImg;
- uint32_t Status;
- uint32_t PrevImg;
- uint32_t size;
- uint32_t safeboot;
- uint8_t signature[16];
- uint32_t crc;
-} boot_info_t;
-
-#define IMG_SIZE_8MB (1980 * 1024)
-#define IMG_UPDATE1_OFFSET_8MB (2112 * 1024) // taken from the partitions table
-
-#define IMG_SIZE_4MB (1720 * 1024)
-#define IMG_UPDATE1_OFFSET_4MB (1792 * 1024) // taken from the partitions table
-
-#define OTAA_DATA_SIZE (4 * 1024)
-#define OTA_DATA_INDEX 2
-#define IMG_FACTORY_OFFSET (64 * 1024)
-
-
-#define IMG_UPDATE2_OFFSET (IMG_FACTORY_OFFSET)
-
-#define IMG_STATUS_CHECK 0
-#define IMG_STATUS_READY 1
-#define IMG_STATUS_PATCH 2
-
-#define IMG_ACT_FACTORY 0
-#define IMG_ACT_UPDATE1 1
-#define IMG_ACT_UPDATE2 2
-
-#define BOOT_VERSION "V0.3"
-#define SPI_SEC_SIZE 0x1000
-
-#define PARTITIONS_COUNT_8MB 5
-#define PARTITIONS_COUNT_4MB 7
-
-#define PART_TYPE_APP 0x00
-#define PART_SUBTYPE_FACTORY 0x00
-#define PART_SUBTYPE_OTA_FLAG 0x10
-#define PART_SUBTYPE_OTA_MASK 0x0f
-#define PART_SUBTYPE_TEST 0x20
-
-#define PART_TYPE_DATA 0x01
-#define PART_SUBTYPE_DATA_OTA 0x00
-#define PART_SUBTYPE_DATA_RF 0x01
-#define PART_SUBTYPE_DATA_WIFI 0x02
-
-#define SAFE_BOOT_HW 0x01
-#define SAFE_BOOT_SW 0x02
-
-#define SPI_ERROR_LOG "spi flash error"
-
-typedef struct {
- esp_partition_pos_t ota_info;
- esp_partition_pos_t image[3];
- uint32_t image_count;
- uint32_t selected_subtype;
-} bootloader_state_t;
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __BOOTLOADER_H__ */
diff --git a/esp32/bootloader/bootmgr.c b/esp32/bootloader/bootmgr.c
deleted file mode 100644
index 2db85adddd..0000000000
--- a/esp32/bootloader/bootmgr.c
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * Copyright (c) 2020, Pycom Limited.
- *
- * This software is licensed under the GNU GPL version 3 or any
- * later version, with permitted additional terms. For more information
- * see the Pycom Licence v1.0 document supplied with this file, or
- * available at https://www.pycom.io/opensource/licensing
- */
-
-#include
-#include
-#include
-#include
-#include
-
-#include "mpconfigboard.h"
-
-#include "esp_heap_caps.h"
-#include "sdkconfig.h"
-#include "esp_system.h"
-#include "esp_spi_flash.h"
-#include "nvs_flash.h"
-
-#include "gpio.h"
-#include "mperror.h"
-#include "bootloader.h"
-
-//*****************************************************************************
-// Local Constants
-//*****************************************************************************
-#define BOOTMGR_WAIT_SAFE_MODE_0_MS 100
-
-#define BOOTMGR_WAIT_SAFE_MODE_1_MS 3000
-#define BOOTMGR_WAIT_SAFE_MODE_1_BLINK_MS 500
-
-#define BOOTMGR_WAIT_SAFE_MODE_2_MS 3000
-#define BOOTMGR_WAIT_SAFE_MODE_2_BLINK_MS 250
-
-#define BOOTMGR_WAIT_SAFE_MODE_3_MS 1500
-#define BOOTMGR_WAIT_SAFE_MODE_3_BLINK_MS 100
-
-#define BOOTMGR_SAFEBOOT_COLOR (0x2C1200)
-
-//*****************************************************************************
-// Local functions declarations
-//*****************************************************************************
-static bool wait_while_blinking (uint32_t wait_time, uint32_t period, bool force_wait);
-static bool safe_boot_request_start (uint32_t wait_time);
-
-//*****************************************************************************
-// Private data
-//*****************************************************************************
-
-static void delay_ms (uint32_t delay) {
- if (delay < 100) {
- ets_delay_us(delay * 1000);
- } else {
- uint32_t c_delay = 0;
- while (c_delay < delay) {
- ets_delay_us(50 * 1000);
- c_delay += 50;
- }
- }
-}
-
-//*****************************************************************************
-//! Wait while the safe mode pin is being held high and blink the system led
-//! with the specified period
-//*****************************************************************************
-static bool wait_while_blinking (uint32_t wait_time, uint32_t period, bool force_wait) {
- uint32_t count;
-#ifndef RGB_LED_DISABLE
- static bool toggle = true;
-#endif
- for (count = 0; (force_wait || gpio_get_level(MICROPY_HW_SAFE_PIN_NUM)) &&
- ((period * count) < wait_time); count++) {
-#ifndef RGB_LED_DISABLE
- // toggle the led
- if (toggle) {
- mperror_set_rgb_color(BOOTMGR_SAFEBOOT_COLOR);
- } else {
- mperror_set_rgb_color(0);
- }
- toggle = !toggle;
-#endif
- delay_ms(period);
- }
- return gpio_get_level(MICROPY_HW_SAFE_PIN_NUM) ? true : false;
-}
-
-static bool safe_boot_request_start (uint32_t wait_time) {
- if (gpio_get_level(MICROPY_HW_SAFE_PIN_NUM)) {
- delay_ms(wait_time);
- }
- return gpio_get_level(MICROPY_HW_SAFE_PIN_NUM) ? true : false;
-}
-
-//*****************************************************************************
-//! Check for the safe mode pin
-//*****************************************************************************
-uint32_t wait_for_safe_boot (const boot_info_t *boot_info, uint32_t *ActiveImg) {
- uint32_t ret = 0;
-
- // configure the safeboot pin
- gpio_config_t gpioconf = {.pin_bit_mask = 1ull << MICROPY_HW_SAFE_PIN_NUM,
- .mode = GPIO_MODE_INPUT,
- .pull_up_en = GPIO_PULLUP_DISABLE,
- .pull_down_en = GPIO_PULLDOWN_ENABLE,
- .intr_type = GPIO_INTR_DISABLE};
- gpio_config(&gpioconf);
-
- if (safe_boot_request_start(BOOTMGR_WAIT_SAFE_MODE_0_MS)) {
- if (wait_while_blinking(BOOTMGR_WAIT_SAFE_MODE_1_MS, BOOTMGR_WAIT_SAFE_MODE_1_BLINK_MS, false)) {
- // go back one step in time
- *ActiveImg = boot_info->PrevImg;
- if (wait_while_blinking(BOOTMGR_WAIT_SAFE_MODE_2_MS, BOOTMGR_WAIT_SAFE_MODE_2_BLINK_MS, false)) {
- // go back directly to the factory image
- *ActiveImg = IMG_ACT_FACTORY;
- wait_while_blinking(BOOTMGR_WAIT_SAFE_MODE_3_MS, BOOTMGR_WAIT_SAFE_MODE_3_BLINK_MS, true);
- }
- }
-#ifndef RGB_LED_DISABLE
- // turn off the heartbeat led
- mperror_set_rgb_color(0);
-#endif
- // request a HW safe boot
- ret = SAFE_BOOT_HW;
- }
- // deinit the safe boot pin
- gpioconf.pull_down_en = GPIO_PULLDOWN_DISABLE;
- gpio_config(&gpioconf);
- return ret;
-}
diff --git a/esp32/bootloader/bootmgr.h b/esp32/bootloader/bootmgr.h
deleted file mode 100644
index 6b1877688d..0000000000
--- a/esp32/bootloader/bootmgr.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * Copyright (c) 2020, Pycom Limited.
- *
- * This software is licensed under the GNU GPL version 3 or any
- * later version, with permitted additional terms. For more information
- * see the Pycom Licence v1.0 document supplied with this file, or
- * available at https://www.pycom.io/opensource/licensing
- */
-
-#ifndef __BOOTMGR_H
-#define __BOOTMGR_H
-
-#include "bootloader.h"
-
-bool wait_for_safe_boot (const boot_info_t *boot_info, uint32_t *ActiveImg);
-
-#endif // __BOOTMGR_H
diff --git a/esp32/bootloader/esp32.bootloader.ld b/esp32/bootloader/esp32.bootloader.ld
deleted file mode 100644
index 35f03170a3..0000000000
--- a/esp32/bootloader/esp32.bootloader.ld
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
-Linker file used to link the bootloader.
-*/
-
-
-/* Simplified memory map for the bootloader
-
- The main purpose is to make sure the bootloader can load into main memory
- without overwriting itself.
-*/
-MEMORY
-{
- /* I/O */
- dport0_seg (RW) : org = 0x3FF00000, len = 0x10
- /* IRAM POOL1, used for APP CPU cache. We can abuse it in bootloader because APP CPU is still held in reset, the main app enables APP CPU cache */
- iram_seg (RWX) : org = 0x4009FA00, len = 0x6000
- /* 64k at the end of DRAM, after ROM bootloader stack */
- dram_seg (RW) : org = 0x3FFF8000, len = 0x8000
-}
-
-/* Default entry point: */
-ENTRY(call_start_cpu0);
-
-
-SECTIONS
-{
- .iram1.text :
- {
- . = ALIGN (16);
- *(.entry.text)
- *(.init.literal)
- *(.init)
- } > iram_seg
-
-
- /* Shared RAM */
- .dram0.bss (NOLOAD) :
- {
- . = ALIGN (8);
- _bss_start = ABSOLUTE(.);
- *(.dynsbss)
- *(.sbss)
- *(.sbss.*)
- *(.gnu.linkonce.sb.*)
- *(.scommon)
- *(.sbss2)
- *(.sbss2.*)
- *(.gnu.linkonce.sb2.*)
- *(.dynbss)
- *(.bss)
- *(.bss.*)
- *(.gnu.linkonce.b.*)
- *(COMMON)
- . = ALIGN (8);
- _bss_end = ABSOLUTE(.);
- } >dram_seg
-
- .dram0.data :
- {
- _data_start = ABSOLUTE(.);
- *(.data)
- *(.data.*)
- *(.gnu.linkonce.d.*)
- *(.data1)
- *(.sdata)
- *(.sdata.*)
- *(.gnu.linkonce.s.*)
- *(.sdata2)
- *(.sdata2.*)
- *(.gnu.linkonce.s2.*)
- *(.jcr)
- _data_end = ABSOLUTE(.);
- } >dram_seg
-
- .dram0.rodata :
- {
- _rodata_start = ABSOLUTE(.);
- *(.rodata)
- *(.rodata.*)
- *(.gnu.linkonce.r.*)
- *(.rodata1)
- __XT_EXCEPTION_TABLE_ = ABSOLUTE(.);
- *(.xt_except_table)
- *(.gcc_except_table)
- *(.gnu.linkonce.e.*)
- *(.gnu.version_r)
- *(.eh_frame)
- . = (. + 3) & ~ 3;
- /* C++ constructor and destructor tables, properly ordered: */
- __init_array_start = ABSOLUTE(.);
- KEEP (*crtbegin.o(.ctors))
- KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
- KEEP (*(SORT(.ctors.*)))
- KEEP (*(.ctors))
- __init_array_end = ABSOLUTE(.);
- KEEP (*crtbegin.o(.dtors))
- KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
- KEEP (*(SORT(.dtors.*)))
- KEEP (*(.dtors))
- /* C++ exception handlers table: */
- __XT_EXCEPTION_DESCS_ = ABSOLUTE(.);
- *(.xt_except_desc)
- *(.gnu.linkonce.h.*)
- __XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.);
- *(.xt_except_desc_end)
- *(.dynamic)
- *(.gnu.version_d)
- _rodata_end = ABSOLUTE(.);
- /* Literals are also RO data. */
- _lit4_start = ABSOLUTE(.);
- *(*.lit4)
- *(.lit4.*)
- *(.gnu.linkonce.lit4.*)
- _lit4_end = ABSOLUTE(.);
- . = ALIGN(4);
- _heap_start = ABSOLUTE(.);
- } >dram_seg
-
- .iram.text :
- {
- _stext = .;
- _loader_text_start = .;
- _text_start = ABSOLUTE(.);
- *(.literal .text .literal.* .text.* .stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
- *(.iram1 .iram1.*) /* catch stray IRAM_ATTR */
- *(.fini.literal)
- *(.fini)
- *(.gnu.version)
- _text_end = ABSOLUTE(.);
- _etext = .;
- _loader_text_end = .;
- } > iram_seg
-
-}
diff --git a/esp32/bootloader/esp32.bootloader.rom.ld b/esp32/bootloader/esp32.bootloader.rom.ld
deleted file mode 100644
index 5eee90c178..0000000000
--- a/esp32/bootloader/esp32.bootloader.rom.ld
+++ /dev/null
@@ -1,4 +0,0 @@
-PROVIDE ( ets_update_cpu_frequency = 0x40008550 ); /* Updates g_ticks_per_us on the current CPU only; not on the other core */
-PROVIDE ( MD5Final = 0x4005db1c );
-PROVIDE ( MD5Init = 0x4005da7c );
-PROVIDE ( MD5Update = 0x4005da9c );
\ No newline at end of file
diff --git a/esp32/bootloader/flash_qio_mode.c b/esp32/bootloader/flash_qio_mode.c
deleted file mode 100644
index 4ccd4cc5a3..0000000000
--- a/esp32/bootloader/flash_qio_mode.c
+++ /dev/null
@@ -1,279 +0,0 @@
-// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-#include
-#include
-#include "flash_qio_mode.h"
-#include "esp_log.h"
-#include "esp_err.h"
-#include "rom/spi_flash.h"
-#include "rom/efuse.h"
-#include "soc/spi_struct.h"
-#include "soc/efuse_reg.h"
-#include "sdkconfig.h"
-
-/* SPI flash controller */
-#define SPIFLASH SPI1
-
-/* SPI commands (actual on-wire commands not SPI controller bitmasks)
- Suitable for use with the execute_flash_command static function.
-*/
-#define CMD_RDID 0x9F
-#define CMD_WRSR 0x01
-#define CMD_WRSR2 0x31 /* Not all SPI flash uses this command */
-#define CMD_WREN 0x06
-#define CMD_WRDI 0x04
-#define CMD_RDSR 0x05
-#define CMD_RDSR2 0x35 /* Not all SPI flash uses this command */
-
-static const char *TAG = "qio_mode";
-
-typedef unsigned (*read_status_fn_t)();
-typedef void (*write_status_fn_t)(unsigned);
-
-typedef struct __attribute__((packed)) {
- const char *manufacturer;
- uint8_t mfg_id; /* 8-bit JEDEC manufacturer ID */
- uint16_t flash_id; /* 16-bit JEDEC flash chip ID */
- uint16_t id_mask; /* Bits to match on in flash chip ID */
- read_status_fn_t read_status_fn;
- write_status_fn_t write_status_fn;
- uint8_t status_qio_bit;
-} qio_info_t;
-
-/* Read 8 bit status using RDSR command */
-static unsigned read_status_8b_rdsr();
-/* Read 8 bit status (second byte) using RDSR2 command */
-static unsigned read_status_8b_rdsr2();
-/* read 16 bit status using RDSR & RDSR2 (low and high bytes) */
-static unsigned read_status_16b_rdsr_rdsr2();
-
-/* Write 8 bit status using WRSR */
-static void write_status_8b_wrsr(unsigned new_status);
-/* Write 8 bit status (second byte) using WRSR2 */
-static void write_status_8b_wrsr2(unsigned new_status);
-/* Write 16 bit status using WRSR */
-static void write_status_16b_wrsr(unsigned new_status);
-
-#define ESP32_D2WD_WP_GPIO 7 /* ESP32-D2WD has this GPIO wired to WP pin of flash */
-
-#ifndef CONFIG_BOOTLOADER_SPI_WP_PIN // Set in menuconfig if SPI flasher config is set to a quad mode
-#define CONFIG_BOOTLOADER_SPI_WP_PIN ESP32_D2WD_WP_GPIO
-#endif
-
-/* Array of known flash chips and data to enable Quad I/O mode
-
- Manufacturer & flash ID can be tested by running "esptool.py
- flash_id"
-
- If manufacturer ID matches, and flash ID ORed with flash ID mask
- matches, enable_qio_mode() will execute "Read Cmd", test if bit
- number "QIE Bit" is set, and if not set it will call "Write Cmd"
- with this bit set.
-
- Searching of this table stops when the first match is found.
- */
-const static qio_info_t chip_data[] = {
-/* Manufacturer, mfg_id, flash_id, id mask, Read Status, Write Status, QIE Bit */
- { "MXIC", 0xC2, 0x2000, 0xFF00, read_status_8b_rdsr, write_status_8b_wrsr, 6 },
- { "ISSI", 0x9D, 0x4000, 0xCF00, read_status_8b_rdsr, write_status_8b_wrsr, 6 }, /* IDs 0x40xx, 0x70xx */
- { "WinBond", 0xEF, 0x4000, 0xFF00, read_status_16b_rdsr_rdsr2, write_status_16b_wrsr, 9 },
- { "GD", 0xC8, 0x6000, 0xFF00, read_status_16b_rdsr_rdsr2, write_status_16b_wrsr, 9 },
-
- /* Final entry is default entry, if no other IDs have matched.
-
- This approach works for chips including:
- GigaDevice (mfg ID 0xC8, flash IDs including 4016),
- FM25Q32 (QOUT mode only, mfg ID 0xA1, flash IDs including 4016)
- */
- { NULL, 0xFF, 0xFFFF, 0xFFFF, read_status_8b_rdsr2, write_status_8b_wrsr2, 1 },
-};
-
-#define NUM_CHIPS (sizeof(chip_data) / sizeof(qio_info_t))
-
-static esp_err_t enable_qio_mode(read_status_fn_t read_status_fn,
- write_status_fn_t write_status_fn,
- uint8_t status_qio_bit);
-
-/* Generic function to use the "user command" SPI controller functionality
- to send commands to the SPI flash and read the respopnse.
-
- The command passed here is always the on-the-wire command given to the SPI flash unit.
-*/
-static uint32_t execute_flash_command(uint8_t command, uint32_t mosi_data, uint8_t mosi_len, uint8_t miso_len);
-
-/* dummy_len_plus values defined in ROM for SPI flash configuration */
-extern uint8_t g_rom_spiflash_dummy_len_plus[];
-
-void bootloader_enable_qio_mode(void)
-{
- uint32_t old_ctrl_reg;
- uint32_t raw_flash_id;
- uint8_t mfg_id;
- uint16_t flash_id;
- int i;
-
- ESP_LOGD(TAG, "Probing for QIO mode enable...");
- esp_rom_spiflash_wait_idle(&g_rom_flashchip);
-
- /* Set up some of the SPIFLASH user/ctrl variables which don't change
- while we're probing using execute_flash_command() */
- old_ctrl_reg = SPIFLASH.ctrl.val;
- SPIFLASH.ctrl.val = SPI_WP_REG; // keep WP high while idle, otherwise leave DIO mode
- SPIFLASH.user.usr_dummy = 0;
- SPIFLASH.user.usr_addr = 0;
- SPIFLASH.user.usr_command = 1;
- SPIFLASH.user2.usr_command_bitlen = 7;
-
- raw_flash_id = execute_flash_command(CMD_RDID, 0, 0, 24);
- ESP_LOGD(TAG, "Raw SPI flash chip id 0x%x", raw_flash_id);
-
- mfg_id = raw_flash_id & 0xFF;
- flash_id = (raw_flash_id >> 16) | (raw_flash_id & 0xFF00);
- ESP_LOGD(TAG, "Manufacturer ID 0x%02x chip ID 0x%04x", mfg_id, flash_id);
-
- for (i = 0; i < NUM_CHIPS-1; i++) {
- const qio_info_t *chip = &chip_data[i];
- if (mfg_id == chip->mfg_id && (flash_id & chip->id_mask) == (chip->flash_id & chip->id_mask)) {
- ESP_LOGI(TAG, "Enabling QIO for flash chip %s", chip_data[i].manufacturer);
- break;
- }
- }
-
- if (i == NUM_CHIPS - 1) {
- ESP_LOGI(TAG, "Enabling default flash chip QIO");
- }
-
- esp_err_t res = enable_qio_mode(chip_data[i].read_status_fn,
- chip_data[i].write_status_fn,
- chip_data[i].status_qio_bit);
- if (res != ESP_OK) {
- // Restore SPI flash CTRL setting, to keep us in DIO/DOUT mode
- SPIFLASH.ctrl.val = old_ctrl_reg;
- }
-}
-
-static esp_err_t enable_qio_mode(read_status_fn_t read_status_fn,
- write_status_fn_t write_status_fn,
- uint8_t status_qio_bit)
-{
- uint32_t status;
- const uint32_t spiconfig = ets_efuse_get_spiconfig();
-
- if (spiconfig != EFUSE_SPICONFIG_SPI_DEFAULTS && spiconfig != EFUSE_SPICONFIG_HSPI_DEFAULTS) {
- // spiconfig specifies a custom efuse pin configuration. This config defines all pins -except- WP,
- // which is compiled into the bootloader instead.
- //
- // Most commonly an overriden pin mapping means ESP32-D2WD. Warn if chip is ESP32-D2WD
- // but someone has changed the WP pin assignment from that chip's WP pin.
- uint32_t pkg_ver = REG_GET_FIELD(EFUSE_BLK0_RDATA3_REG, EFUSE_RD_CHIP_VER_PKG);
-
- if (pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32D2WDQ5 && CONFIG_BOOTLOADER_SPI_WP_PIN != ESP32_D2WD_WP_GPIO) {
- ESP_LOGW(TAG, "Chip is ESP32-D2WD but flash WP pin is different value to internal flash");
- }
- }
-
- esp_rom_spiflash_wait_idle(&g_rom_flashchip);
-
- status = read_status_fn();
- ESP_LOGD(TAG, "Initial flash chip status 0x%x", status);
-
- if ((status & (1< 0;
- SPIFLASH.miso_dlen.usr_miso_dbitlen = miso_len ? (miso_len - 1) : 0;
- SPIFLASH.user.usr_mosi = mosi_len > 0;
- SPIFLASH.mosi_dlen.usr_mosi_dbitlen = mosi_len ? (mosi_len - 1) : 0;
- SPIFLASH.data_buf[0] = mosi_data;
-
- if (g_rom_spiflash_dummy_len_plus[1]) {
- /* When flash pins are mapped via GPIO matrix, need a dummy cycle before reading via MISO */
- if (miso_len > 0) {
- SPIFLASH.user.usr_dummy = 1;
- SPIFLASH.user1.usr_dummy_cyclelen = g_rom_spiflash_dummy_len_plus[1] - 1;
- } else {
- SPIFLASH.user.usr_dummy = 0;
- SPIFLASH.user1.usr_dummy_cyclelen = 0;
- }
- }
-
- SPIFLASH.cmd.usr = 1;
- while(SPIFLASH.cmd.usr != 0)
- { }
-
- return SPIFLASH.data_buf[0];
-}
diff --git a/esp32/bootloader/flash_qio_mode.h b/esp32/bootloader/flash_qio_mode.h
deleted file mode 100644
index 9efa1313e2..0000000000
--- a/esp32/bootloader/flash_qio_mode.h
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-#pragma once
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/** @brief Enable Quad I/O mode in bootloader (if configured)
- *
- * Queries attached SPI flash ID and sends correct SPI flash
- * commands to enable QIO or QOUT mode, then enables this mode.
- */
-void bootloader_enable_qio_mode(void);
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/esp32/bootloader/gpio.c b/esp32/bootloader/gpio.c
deleted file mode 100644
index c27a1de88d..0000000000
--- a/esp32/bootloader/gpio.c
+++ /dev/null
@@ -1,332 +0,0 @@
-// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-#include
-#include "esp_err.h"
-#include "esp_intr.h"
-#include "esp_intr_alloc.h"
-#include "freertos/FreeRTOS.h"
-#include "freertos/xtensa_api.h"
-#include "gpio.h"
-#include "driver/rtc_io.h"
-#include "soc/soc.h"
-#include "esp_log.h"
-
-static const char* GPIO_TAG = "gpio";
-#define GPIO_CHECK(a, str, ret_val) \
- if (!(a)) { \
- ESP_LOGE(GPIO_TAG,"%s(%d): %s", __FUNCTION__, __LINE__, str); \
- return (ret_val); \
- }
-
-const uint32_t GPIO_PIN_MUX_REG[GPIO_PIN_COUNT] = {
- GPIO_PIN_REG_0,
- GPIO_PIN_REG_1,
- GPIO_PIN_REG_2,
- GPIO_PIN_REG_3,
- GPIO_PIN_REG_4,
- GPIO_PIN_REG_5,
- GPIO_PIN_REG_6,
- GPIO_PIN_REG_7,
- GPIO_PIN_REG_8,
- GPIO_PIN_REG_9,
- GPIO_PIN_REG_10,
- GPIO_PIN_REG_11,
- GPIO_PIN_REG_12,
- GPIO_PIN_REG_13,
- GPIO_PIN_REG_14,
- GPIO_PIN_REG_15,
- GPIO_PIN_REG_16,
- GPIO_PIN_REG_17,
- GPIO_PIN_REG_18,
- GPIO_PIN_REG_19,
- 0,
- GPIO_PIN_REG_21,
- GPIO_PIN_REG_22,
- GPIO_PIN_REG_23,
- 0,
- GPIO_PIN_REG_25,
- GPIO_PIN_REG_26,
- GPIO_PIN_REG_27,
- 0,
- 0,
- 0,
- 0,
- GPIO_PIN_REG_32,
- GPIO_PIN_REG_33,
- GPIO_PIN_REG_34,
- GPIO_PIN_REG_35,
- GPIO_PIN_REG_36,
- GPIO_PIN_REG_37,
- GPIO_PIN_REG_38,
- GPIO_PIN_REG_39
-};
-
-esp_err_t gpio_pullup_en(gpio_num_t gpio_num) {
- GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG);
- REG_SET_BIT(GPIO_PIN_MUX_REG[gpio_num], FUN_PU);
- return ESP_OK;
-}
-
-esp_err_t gpio_pullup_dis(gpio_num_t gpio_num) {
- GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG);
- REG_CLR_BIT(GPIO_PIN_MUX_REG[gpio_num], FUN_PU);
- return ESP_OK;
-}
-
-esp_err_t gpio_pulldown_en(gpio_num_t gpio_num) {
- GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG);
- REG_SET_BIT(GPIO_PIN_MUX_REG[gpio_num], FUN_PD);
- return ESP_OK;
-}
-
-esp_err_t gpio_pulldown_dis(gpio_num_t gpio_num) {
- GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG);
- REG_CLR_BIT(GPIO_PIN_MUX_REG[gpio_num], FUN_PD);
- return ESP_OK;
-}
-esp_err_t gpio_set_intr_type(gpio_num_t gpio_num, gpio_int_type_t intr_type)
-{
- GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG);
- GPIO_CHECK(intr_type < GPIO_INTR_MAX, "GPIO interrupt type error", ESP_ERR_INVALID_ARG);
- GPIO.pin[gpio_num].int_type = intr_type;
- return ESP_OK;
-}
-
-esp_err_t gpio_intr_enable(gpio_num_t gpio_num)
-{
- GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG);
- if (xPortGetCoreID() == 0) {
- GPIO.pin[gpio_num].int_ena = GPIO_PRO_CPU_INTR_ENA; //enable pro cpu intr
- } else {
- GPIO.pin[gpio_num].int_ena = GPIO_APP_CPU_INTR_ENA; //enable pro cpu intr
- }
- return ESP_OK;
-}
-
-esp_err_t gpio_intr_disable(gpio_num_t gpio_num)
-{
- GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG);
- GPIO.pin[gpio_num].int_ena = 0; //disable GPIO intr
- return ESP_OK;
-}
-
-static esp_err_t gpio_output_disable(gpio_num_t gpio_num)
-{
- GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG);
- if (gpio_num < 32) {
- GPIO.enable_w1tc = (0x1 << gpio_num);
- } else {
- GPIO.enable1_w1tc.data = (0x1 << (gpio_num - 32));
- }
- return ESP_OK;
-}
-
-static esp_err_t gpio_output_enable(gpio_num_t gpio_num)
-{
- GPIO_CHECK(GPIO_IS_VALID_OUTPUT_GPIO(gpio_num), "GPIO output gpio_num error", ESP_ERR_INVALID_ARG);
- if (gpio_num < 32) {
- GPIO.enable_w1ts = (0x1 << gpio_num);
- } else {
- GPIO.enable1_w1ts.data = (0x1 << (gpio_num - 32));
- }
- return ESP_OK;
-}
-
-esp_err_t gpio_set_level(gpio_num_t gpio_num, uint32_t level)
-{
- GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG);
- if (level) {
- if (gpio_num < 32) {
- GPIO.out_w1ts = (1 << gpio_num);
- } else {
- GPIO.out1_w1ts.data = (1 << (gpio_num - 32));
- }
- } else {
- if (gpio_num < 32) {
- GPIO.out_w1tc = (1 << gpio_num);
- } else {
- GPIO.out1_w1tc.data = (1 << (gpio_num - 32));
- }
- }
- return ESP_OK;
-}
-
-int gpio_get_level(gpio_num_t gpio_num)
-{
- if (gpio_num < 32) {
- return (GPIO.in >> gpio_num) & 0x1;
- } else {
- return (GPIO.in1.data >> (gpio_num - 32)) & 0x1;
- }
-}
-
-esp_err_t gpio_set_pull_mode(gpio_num_t gpio_num, gpio_pull_mode_t pull)
-{
- GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG);
- GPIO_CHECK(pull <= GPIO_FLOATING, "GPIO pull mode error", ESP_ERR_INVALID_ARG);
- esp_err_t ret = ESP_OK;
- switch (pull) {
- case GPIO_PULLUP_ONLY:
- gpio_pulldown_dis(gpio_num);
- gpio_pullup_en(gpio_num);
- break;
- case GPIO_PULLDOWN_ONLY:
- gpio_pulldown_en(gpio_num);
- gpio_pullup_dis(gpio_num);
- break;
- case GPIO_PULLUP_PULLDOWN:
- gpio_pulldown_en(gpio_num);
- gpio_pullup_en(gpio_num);
- break;
- case GPIO_FLOATING:
- gpio_pulldown_dis(gpio_num);
- gpio_pullup_dis(gpio_num);
- break;
- default:
- ESP_LOGE(GPIO_TAG, "Unknown pull up/down mode,gpio_num=%u,pull=%u", gpio_num, pull);
- ret = ESP_ERR_INVALID_ARG;
- break;
- }
- return ret;
-}
-
-esp_err_t gpio_set_direction(gpio_num_t gpio_num, gpio_mode_t mode)
-{
- GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG);
- if (gpio_num >= 34 && (mode & (GPIO_MODE_DEF_OUTPUT))) {
- ESP_LOGE(GPIO_TAG, "io_num=%d can only be input", gpio_num);
- return ESP_ERR_INVALID_ARG;
- }
- esp_err_t ret = ESP_OK;
- if (mode & GPIO_MODE_DEF_INPUT) {
- PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[gpio_num]);
- } else {
- PIN_INPUT_DISABLE(GPIO_PIN_MUX_REG[gpio_num]);
- }
- if (mode & GPIO_MODE_DEF_OUTPUT) {
- if (gpio_num < 32) {
- GPIO.enable_w1ts = (0x1 << gpio_num);
- } else {
- GPIO.enable1_w1ts.data = (0x1 << (gpio_num - 32));
- }
- } else {
- if (gpio_num < 32) {
- GPIO.enable_w1tc = (0x1 << gpio_num);
- } else {
- GPIO.enable1_w1tc.data = (0x1 << (gpio_num - 32));
- }
- }
- if (mode & GPIO_MODE_DEF_OD) {
- GPIO.pin[gpio_num].pad_driver = 1;
- } else {
- GPIO.pin[gpio_num].pad_driver = 0;
- }
- return ret;
-}
-
-esp_err_t gpio_config(const gpio_config_t *pGPIOConfig)
-{
- uint64_t gpio_pin_mask = (pGPIOConfig->pin_bit_mask);
- uint32_t io_reg = 0;
- uint32_t io_num = 0;
- uint8_t input_en = 0;
- uint8_t output_en = 0;
- uint8_t od_en = 0;
- uint8_t pu_en = 0;
- uint8_t pd_en = 0;
- if (pGPIOConfig->pin_bit_mask == 0 || pGPIOConfig->pin_bit_mask >= (((uint64_t) 1) << GPIO_PIN_COUNT)) {
- ESP_LOGE(GPIO_TAG, "GPIO_PIN mask error ");
- return ESP_ERR_INVALID_ARG;
- }
- if ((pGPIOConfig->mode) & (GPIO_MODE_DEF_OUTPUT)) {
- //GPIO 34/35/36/37/38/39 can only be used as input mode;
- if ((gpio_pin_mask & ( GPIO_SEL_34 | GPIO_SEL_35 | GPIO_SEL_36 | GPIO_SEL_37 | GPIO_SEL_38 | GPIO_SEL_39))) {
- ESP_LOGE(GPIO_TAG, "GPIO34-39 can only be used as input mode");
- return ESP_ERR_INVALID_ARG;
- }
- }
- do {
- io_reg = GPIO_PIN_MUX_REG[io_num];
- if (((gpio_pin_mask >> io_num) & BIT(0)) && io_reg) {
- if ((pGPIOConfig->mode) & GPIO_MODE_DEF_INPUT) {
- input_en = 1;
- PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[io_num]);
- } else {
- PIN_INPUT_DISABLE(GPIO_PIN_MUX_REG[io_num]);
- }
- if ((pGPIOConfig->mode) & GPIO_MODE_DEF_OD) {
- od_en = 1;
- GPIO.pin[io_num].pad_driver = 1; /*0x01 Open-drain */
- } else {
- GPIO.pin[io_num].pad_driver = 0; /*0x00 Normal gpio output */
- }
- if ((pGPIOConfig->mode) & GPIO_MODE_DEF_OUTPUT) {
- output_en = 1;
- gpio_output_enable(io_num);
- } else {
- gpio_output_disable(io_num);
- }
- if (pGPIOConfig->pull_up_en) {
- pu_en = 1;
- gpio_pullup_en(io_num);
- } else {
- gpio_pullup_dis(io_num);
- }
- if (pGPIOConfig->pull_down_en) {
- pd_en = 1;
- gpio_pulldown_en(io_num);
- } else {
- gpio_pulldown_dis(io_num);
- }
- ESP_LOGI(GPIO_TAG, "GPIO[%d]| InputEn: %d| OutputEn: %d| OpenDrain: %d| Pullup: %d| Pulldown: %d| Intr:%d ", io_num, input_en, output_en, od_en, pu_en, pd_en, pGPIOConfig->intr_type);
- gpio_set_intr_type(io_num, pGPIOConfig->intr_type);
- if (pGPIOConfig->intr_type) {
- gpio_intr_enable(io_num);
- } else {
- gpio_intr_disable(io_num);
- }
- PIN_FUNC_SELECT(io_reg, PIN_FUNC_GPIO); /*function number 2 is GPIO_FUNC for each pin */
- }
- io_num++;
- } while (io_num < GPIO_PIN_COUNT);
- return ESP_OK;
-}
-
-esp_err_t gpio_isr_register(void (*fn)(void*), void * arg, int intr_alloc_flags, gpio_isr_handle_t *handle)
-{
- GPIO_CHECK(fn, "GPIO ISR null", ESP_ERR_INVALID_ARG);
- return esp_intr_alloc(ETS_GPIO_INTR_SOURCE, intr_alloc_flags, fn, arg, handle);
-}
-
-/*only level interrupt can be used for wake-up function*/
-esp_err_t gpio_wakeup_enable(gpio_num_t gpio_num, gpio_int_type_t intr_type)
-{
- GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG);
- esp_err_t ret = ESP_OK;
- if ((intr_type == GPIO_INTR_LOW_LEVEL) || (intr_type == GPIO_INTR_HIGH_LEVEL)) {
- GPIO.pin[gpio_num].int_type = intr_type;
- GPIO.pin[gpio_num].wakeup_enable = 0x1;
- } else {
- ESP_LOGE(GPIO_TAG, "GPIO wakeup only support Level mode,but edge mode set. gpio_num:%u", gpio_num);
- ret = ESP_ERR_INVALID_ARG;
- }
- return ret;
-}
-
-esp_err_t gpio_wakeup_disable(gpio_num_t gpio_num)
-{
- GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG);
- GPIO.pin[gpio_num].wakeup_enable = 0;
- return ESP_OK;
-}
diff --git a/esp32/bootloader/gpio.h b/esp32/bootloader/gpio.h
deleted file mode 100644
index 56e5b4f001..0000000000
--- a/esp32/bootloader/gpio.h
+++ /dev/null
@@ -1,505 +0,0 @@
-// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef _DRIVER_GPIO_H_
-#define _DRIVER_GPIO_H_
-#include "esp_err.h"
-#include
-#include "soc/gpio_reg.h"
-#include "soc/gpio_struct.h"
-#include "soc/rtc_io_reg.h"
-#include "soc/io_mux_reg.h"
-#include "soc/gpio_sig_map.h"
-#include "rom/gpio.h"
-#include "esp_attr.h"
-#include "esp_intr_alloc.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define GPIO_SEL_0 (BIT(0)) /*!< Pin 0 selected */
-#define GPIO_SEL_1 (BIT(1)) /*!< Pin 1 selected */
-#define GPIO_SEL_2 (BIT(2)) /*!< Pin 2 selected */
-#define GPIO_SEL_3 (BIT(3)) /*!< Pin 3 selected */
-#define GPIO_SEL_4 (BIT(4)) /*!< Pin 4 selected */
-#define GPIO_SEL_5 (BIT(5)) /*!< Pin 5 selected */
-#define GPIO_SEL_6 (BIT(6)) /*!< Pin 6 selected */
-#define GPIO_SEL_7 (BIT(7)) /*!< Pin 7 selected */
-#define GPIO_SEL_8 (BIT(8)) /*!< Pin 8 selected */
-#define GPIO_SEL_9 (BIT(9)) /*!< Pin 9 selected */
-#define GPIO_SEL_10 (BIT(10)) /*!< Pin 10 selected */
-#define GPIO_SEL_11 (BIT(11)) /*!< Pin 11 selected */
-#define GPIO_SEL_12 (BIT(12)) /*!< Pin 12 selected */
-#define GPIO_SEL_13 (BIT(13)) /*!< Pin 13 selected */
-#define GPIO_SEL_14 (BIT(14)) /*!< Pin 14 selected */
-#define GPIO_SEL_15 (BIT(15)) /*!< Pin 15 selected */
-#define GPIO_SEL_16 (BIT(16)) /*!< Pin 16 selected */
-#define GPIO_SEL_17 (BIT(17)) /*!< Pin 17 selected */
-#define GPIO_SEL_18 (BIT(18)) /*!< Pin 18 selected */
-#define GPIO_SEL_19 (BIT(19)) /*!< Pin 19 selected */
-
-#define GPIO_SEL_21 (BIT(21)) /*!< Pin 21 selected */
-#define GPIO_SEL_22 (BIT(22)) /*!< Pin 22 selected */
-#define GPIO_SEL_23 (BIT(23)) /*!< Pin 23 selected */
-
-#define GPIO_SEL_25 (BIT(25)) /*!< Pin 25 selected */
-#define GPIO_SEL_26 (BIT(26)) /*!< Pin 26 selected */
-#define GPIO_SEL_27 (BIT(27)) /*!< Pin 27 selected */
-
-#define GPIO_SEL_32 ((uint64_t)(((uint64_t)1)<<32)) /*!< Pin 32 selected */
-#define GPIO_SEL_33 ((uint64_t)(((uint64_t)1)<<33)) /*!< Pin 33 selected */
-#define GPIO_SEL_34 ((uint64_t)(((uint64_t)1)<<34)) /*!< Pin 34 selected */
-#define GPIO_SEL_35 ((uint64_t)(((uint64_t)1)<<35)) /*!< Pin 35 selected */
-#define GPIO_SEL_36 ((uint64_t)(((uint64_t)1)<<36)) /*!< Pin 36 selected */
-#define GPIO_SEL_37 ((uint64_t)(((uint64_t)1)<<37)) /*!< Pin 37 selected */
-#define GPIO_SEL_38 ((uint64_t)(((uint64_t)1)<<38)) /*!< Pin 38 selected */
-#define GPIO_SEL_39 ((uint64_t)(((uint64_t)1)<<39)) /*!< Pin 39 selected */
-
-#define GPIO_PIN_REG_0 PERIPHS_IO_MUX_GPIO0_U
-#define GPIO_PIN_REG_1 PERIPHS_IO_MUX_U0TXD_U
-#define GPIO_PIN_REG_2 PERIPHS_IO_MUX_GPIO2_U
-#define GPIO_PIN_REG_3 PERIPHS_IO_MUX_U0RXD_U
-#define GPIO_PIN_REG_4 PERIPHS_IO_MUX_GPIO4_U
-#define GPIO_PIN_REG_5 PERIPHS_IO_MUX_GPIO5_U
-#define GPIO_PIN_REG_6 PERIPHS_IO_MUX_SD_CLK_U
-#define GPIO_PIN_REG_7 PERIPHS_IO_MUX_SD_DATA0_U
-#define GPIO_PIN_REG_8 PERIPHS_IO_MUX_SD_DATA1_U
-#define GPIO_PIN_REG_9 PERIPHS_IO_MUX_SD_DATA2_U
-#define GPIO_PIN_REG_10 PERIPHS_IO_MUX_SD_DATA3_U
-#define GPIO_PIN_REG_11 PERIPHS_IO_MUX_SD_CMD_U
-#define GPIO_PIN_REG_12 PERIPHS_IO_MUX_MTDI_U
-#define GPIO_PIN_REG_13 PERIPHS_IO_MUX_MTCK_U
-#define GPIO_PIN_REG_14 PERIPHS_IO_MUX_MTMS_U
-#define GPIO_PIN_REG_15 PERIPHS_IO_MUX_MTDO_U
-#define GPIO_PIN_REG_16 PERIPHS_IO_MUX_GPIO16_U
-#define GPIO_PIN_REG_17 PERIPHS_IO_MUX_GPIO17_U
-#define GPIO_PIN_REG_18 PERIPHS_IO_MUX_GPIO18_U
-#define GPIO_PIN_REG_19 PERIPHS_IO_MUX_GPIO19_U
-#define GPIO_PIN_REG_20 PERIPHS_IO_MUX_GPIO20_U
-#define GPIO_PIN_REG_21 PERIPHS_IO_MUX_GPIO21_U
-#define GPIO_PIN_REG_22 PERIPHS_IO_MUX_GPIO22_U
-#define GPIO_PIN_REG_23 PERIPHS_IO_MUX_GPIO23_U
-#define GPIO_PIN_REG_25 PERIPHS_IO_MUX_GPIO25_U
-#define GPIO_PIN_REG_26 PERIPHS_IO_MUX_GPIO26_U
-#define GPIO_PIN_REG_27 PERIPHS_IO_MUX_GPIO27_U
-#define GPIO_PIN_REG_32 PERIPHS_IO_MUX_GPIO32_U
-#define GPIO_PIN_REG_33 PERIPHS_IO_MUX_GPIO33_U
-#define GPIO_PIN_REG_34 PERIPHS_IO_MUX_GPIO34_U
-#define GPIO_PIN_REG_35 PERIPHS_IO_MUX_GPIO35_U
-#define GPIO_PIN_REG_36 PERIPHS_IO_MUX_GPIO36_U
-#define GPIO_PIN_REG_37 PERIPHS_IO_MUX_GPIO37_U
-#define GPIO_PIN_REG_38 PERIPHS_IO_MUX_GPIO38_U
-#define GPIO_PIN_REG_39 PERIPHS_IO_MUX_GPIO39_U
-
-#define GPIO_APP_CPU_INTR_ENA (BIT(0))
-#define GPIO_APP_CPU_NMI_INTR_ENA (BIT(1))
-#define GPIO_PRO_CPU_INTR_ENA (BIT(2))
-#define GPIO_PRO_CPU_NMI_INTR_ENA (BIT(3))
-#define GPIO_SDIO_EXT_INTR_ENA (BIT(4))
-
-#define GPIO_MODE_DEF_INPUT (BIT0)
-#define GPIO_MODE_DEF_OUTPUT (BIT1)
-#define GPIO_MODE_DEF_OD (BIT2)
-
-#define GPIO_PIN_COUNT 40
-extern const uint32_t GPIO_PIN_MUX_REG[GPIO_PIN_COUNT];
-#define GPIO_IS_VALID_GPIO(gpio_num) ((gpio_num < GPIO_PIN_COUNT && GPIO_PIN_MUX_REG[gpio_num] != 0)) //to decide whether it is a valid GPIO number
-#define GPIO_IS_VALID_OUTPUT_GPIO(gpio_num) ((GPIO_IS_VALID_GPIO(gpio_num)) && (gpio_num < 34)) //to decide whether it can be a valid GPIO number of output mode
-
-typedef enum {
- GPIO_NUM_0 = 0, /*!< GPIO0, input and output */
- GPIO_NUM_1 = 1, /*!< GPIO1, input and output */
- GPIO_NUM_2 = 2, /*!< GPIO2, input and output */
- GPIO_NUM_3 = 3, /*!< GPIO3, input and output */
- GPIO_NUM_4 = 4, /*!< GPIO4, input and output */
- GPIO_NUM_5 = 5, /*!< GPIO5, input and output */
- GPIO_NUM_6 = 6, /*!< GPIO6, input and output */
- GPIO_NUM_7 = 7, /*!< GPIO7, input and output */
- GPIO_NUM_8 = 8, /*!< GPIO8, input and output */
- GPIO_NUM_9 = 9, /*!< GPIO9, input and output */
- GPIO_NUM_10 = 10, /*!< GPIO10, input and output */
- GPIO_NUM_11 = 11, /*!< GPIO11, input and output */
- GPIO_NUM_12 = 12, /*!< GPIO12, input and output */
- GPIO_NUM_13 = 13, /*!< GPIO13, input and output */
- GPIO_NUM_14 = 14, /*!< GPIO14, input and output */
- GPIO_NUM_15 = 15, /*!< GPIO15, input and output */
- GPIO_NUM_16 = 16, /*!< GPIO16, input and output */
- GPIO_NUM_17 = 17, /*!< GPIO17, input and output */
- GPIO_NUM_18 = 18, /*!< GPIO18, input and output */
- GPIO_NUM_19 = 19, /*!< GPIO19, input and output */
-
- GPIO_NUM_21 = 21, /*!< GPIO21, input and output */
- GPIO_NUM_22 = 22, /*!< GPIO22, input and output */
- GPIO_NUM_23 = 23, /*!< GPIO23, input and output */
-
- GPIO_NUM_25 = 25, /*!< GPIO25, input and output */
- GPIO_NUM_26 = 26, /*!< GPIO26, input and output */
- GPIO_NUM_27 = 27, /*!< GPIO27, input and output */
-
- GPIO_NUM_32 = 32, /*!< GPIO32, input and output */
- GPIO_NUM_33 = 33, /*!< GPIO32, input and output */
- GPIO_NUM_34 = 34, /*!< GPIO34, input mode only */
- GPIO_NUM_35 = 35, /*!< GPIO35, input mode only */
- GPIO_NUM_36 = 36, /*!< GPIO36, input mode only */
- GPIO_NUM_37 = 37, /*!< GPIO37, input mode only */
- GPIO_NUM_38 = 38, /*!< GPIO38, input mode only */
- GPIO_NUM_39 = 39, /*!< GPIO39, input mode only */
-} gpio_num_t;
-
-typedef enum {
- GPIO_INTR_DISABLE = 0, /*!< Disable GPIO interrupt */
- GPIO_INTR_POSEDGE = 1, /*!< GPIO interrupt type : rising edge */
- GPIO_INTR_NEGEDGE = 2, /*!< GPIO interrupt type : falling edge */
- GPIO_INTR_ANYEDGE = 3, /*!< GPIO interrupt type : both rising and falling edge */
- GPIO_INTR_LOW_LEVEL = 4, /*!< GPIO interrupt type : input low level trigger */
- GPIO_INTR_HIGH_LEVEL = 5, /*!< GPIO interrupt type : input high level trigger */
- GPIO_INTR_MAX,
-} gpio_int_type_t;
-
-typedef enum {
- GPIO_MODE_INPUT = GPIO_MODE_DEF_INPUT, /*!< GPIO mode : input only */
- GPIO_MODE_OUTPUT = GPIO_MODE_DEF_OUTPUT, /*!< GPIO mode : output only mode */
- GPIO_MODE_OUTPUT_OD = ((GPIO_MODE_DEF_OUTPUT)|(GPIO_MODE_DEF_OD)), /*!< GPIO mode : output only with open-drain mode */
- GPIO_MODE_INPUT_OUTPUT_OD = ((GPIO_MODE_DEF_INPUT)|(GPIO_MODE_DEF_OUTPUT)|(GPIO_MODE_DEF_OD)), /*!< GPIO mode : output and input with open-drain mode*/
- GPIO_MODE_INPUT_OUTPUT = ((GPIO_MODE_DEF_INPUT)|(GPIO_MODE_DEF_OUTPUT)), /*!< GPIO mode : output and input mode */
-} gpio_mode_t;
-
-typedef enum {
- GPIO_PULLUP_DISABLE = 0x0, /*!< Disable GPIO pull-up resistor */
- GPIO_PULLUP_ENABLE = 0x1, /*!< Enable GPIO pull-up resistor */
-} gpio_pullup_t;
-
-typedef enum {
- GPIO_PULLDOWN_DISABLE = 0x0, /*!< Disable GPIO pull-down resistor */
- GPIO_PULLDOWN_ENABLE = 0x1, /*!< Enable GPIO pull-down resistor */
-} gpio_pulldown_t;
-
-/**
- * @brief Configuration parameters of GPIO pad for gpio_config function
- */
-typedef struct {
- uint64_t pin_bit_mask; /*!< GPIO pin: set with bit mask, each bit maps to a GPIO */
- gpio_mode_t mode; /*!< GPIO mode: set input/output mode */
- gpio_pullup_t pull_up_en; /*!< GPIO pull-up */
- gpio_pulldown_t pull_down_en; /*!< GPIO pull-down */
- gpio_int_type_t intr_type; /*!< GPIO interrupt type */
-} gpio_config_t;
-
-typedef enum {
- GPIO_PULLUP_ONLY, /*!< Pad pull up */
- GPIO_PULLDOWN_ONLY, /*!< Pad pull down */
- GPIO_PULLUP_PULLDOWN, /*!< Pad pull up + pull down*/
- GPIO_FLOATING, /*!< Pad floating */
-} gpio_pull_mode_t;
-
-
-
-typedef intr_handle_t gpio_isr_handle_t;
-typedef void (*gpio_event_callback)(gpio_num_t gpio_intr_num);
-
-/**
- * @brief GPIO common configuration
- *
- * Configure GPIO's Mode,pull-up,PullDown,IntrType
- *
- * @param pGPIOConfig Pointer to GPIO configure struct
- *
- * @return
- * - ESP_OK success
- * - ESP_ERR_INVALID_ARG Parameter error
- *
- */
-esp_err_t gpio_config(gpio_config_t *pGPIOConfig);
-
-
-/**
- * @brief GPIO set interrupt trigger type
- *
- * @param gpio_num GPIO number. If you want to set the trigger type of e.g. of GPIO16, gpio_num should be GPIO_NUM_16 (16);
- * @param intr_type Interrupt type, select from gpio_int_type_t
- *
- * @return
- * - ESP_OK Success
- * - ESP_ERR_INVALID_ARG Parameter error
- *
- */
-esp_err_t gpio_set_intr_type(gpio_num_t gpio_num, gpio_int_type_t intr_type);
-
-/**
- * @brief Enable GPIO module interrupt signal
- *
- * @param gpio_num GPIO number. If you want to enable an interrupt on e.g. GPIO16, gpio_num should be GPIO_NUM_16 (16);
- *
- * @return
- * - ESP_OK Success
- * - ESP_ERR_INVALID_ARG Parameter error
- *
- */
-esp_err_t gpio_intr_enable(gpio_num_t gpio_num);
-
-/**
- * @brief Disable GPIO module interrupt signal
- *
- * @param gpio_num GPIO number. If you want to disable the interrupt of e.g. GPIO16, gpio_num should be GPIO_NUM_16 (16);
- *
- * @return
- * - ESP_OK success
- * - ESP_ERR_INVALID_ARG Parameter error
- *
- */
-esp_err_t gpio_intr_disable(gpio_num_t gpio_num);
-
-/**
- * @brief GPIO set output level
- *
- * @param gpio_num GPIO number. If you want to set the output level of e.g. GPIO16, gpio_num should be GPIO_NUM_16 (16);
- * @param level Output level. 0: low ; 1: high
- *
- * @return
- * - ESP_OK Success
- * - GPIO_IS_VALID_GPIO GPIO number error
- *
- */
-esp_err_t gpio_set_level(gpio_num_t gpio_num, uint32_t level);
-
-/**
- * @brief GPIO get input level
- *
- * @param gpio_num GPIO number. If you want to get the logic level of e.g. pin GPIO16, gpio_num should be GPIO_NUM_16 (16);
- *
- * @return
- * - 0 the GPIO input level is 0
- * - 1 the GPIO input level is 1
- *
- */
-int gpio_get_level(gpio_num_t gpio_num);
-
-/**
- * @brief GPIO set direction
- *
- * Configure GPIO direction,such as output_only,input_only,output_and_input
- *
- * @param gpio_num Configure GPIO pins number, it should be GPIO number. If you want to set direction of e.g. GPIO16, gpio_num should be GPIO_NUM_16 (16);
- * @param mode GPIO direction
- *
- * @return
- * - ESP_OK Success
- * - ESP_ERR_INVALID_ARG GPIO error
- *
- */
-esp_err_t gpio_set_direction(gpio_num_t gpio_num, gpio_mode_t mode);
-
-/**
- * @brief GPIO set pull
- *
- * User this Function,configure GPIO pull mode,such as pull-up,pull-down
- *
- * @param gpio_num GPIO number. If you want to set pull up or down mode for e.g. GPIO16, gpio_num should be GPIO_NUM_16 (16);
- * @param pull GPIO pull up/down mode.
- *
- * @return
- * - ESP_OK Success
- * - ESP_ERR_INVALID_ARG : Parameter error
- *
- */
-esp_err_t gpio_set_pull_mode(gpio_num_t gpio_num, gpio_pull_mode_t pull);
-
-/**
- * @brief enable GPIO wake-up function.
- *
- * @param gpio_num GPIO number.
- *
- * @param intr_type GPIO wake-up type. Only GPIO_INTR_LOW_LEVEL or GPIO_INTR_HIGH_LEVEL can be used.
- *
- * @return
- * - ESP_OK Success
- * - ESP_ERR_INVALID_ARG Parameter error
- */
-esp_err_t gpio_wakeup_enable(gpio_num_t gpio_num, gpio_int_type_t intr_type);
-
-/**
- * @brief Disable GPIO wake-up function.
- *
- * @param gpio_num GPIO number
- *
- * @return
- * - ESP_OK Success
- * - ESP_ERR_INVALID_ARG Parameter error
- */
-esp_err_t gpio_wakeup_disable(gpio_num_t gpio_num);
-
-/**
- * @brief register GPIO interrupt handler, the handler is an ISR.
- * The handler will be attached to the same CPU core that this function is running on.
- * @note
- * Users should know that which CPU is running and then pick a INUM that is not used by system.
- * We can find the information of INUM and interrupt level in soc.h.
- *
- * @param fn Interrupt handler function.
- * @param intr_alloc_flags Flags used to allocate the interrupt. One or multiple (ORred)
- * ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info.
- * @param arg Parameter for handler function
- * @param handle Pointer to return handle. If non-NULL, a handle for the interrupt will
- * be returned here.
- *
- * @return
- * - ESP_OK Success ;
- * - ESP_ERR_INVALID_ARG GPIO error
- */
-esp_err_t gpio_isr_register(void (*fn)(void*), void * arg, int intr_alloc_flags, gpio_isr_handle_t *handle);
-
-
-
-/**
- * @brief Enable pull-up on GPIO.
- *
- * @param gpio_num GPIO number
- *
- * @return
- * - ESP_OK Success
- * - ESP_ERR_INVALID_ARG Parameter error
- */
-esp_err_t gpio_pullup_en(gpio_num_t gpio_num);
-
-/**
- * @brief Disable pull-up on GPIO.
- *
- * @param gpio_num GPIO number
- *
- * @return
- * - ESP_OK Success
- * - ESP_ERR_INVALID_ARG Parameter error
- */
-esp_err_t gpio_pullup_dis(gpio_num_t gpio_num);
-
-/**
- * @brief Enable pull-down on GPIO.
- *
- * @param gpio_num GPIO number
- *
- * @return
- * - ESP_OK Success
- * - ESP_ERR_INVALID_ARG Parameter error
- */
-esp_err_t gpio_pulldown_en(gpio_num_t gpio_num);
-
-/**
- * @brief Disable pull-down on GPIO.
- *
- * @param gpio_num GPIO number
- *
- * @return
- * - ESP_OK Success
- * - ESP_ERR_INVALID_ARG Parameter error
- */
-esp_err_t gpio_pulldown_dis(gpio_num_t gpio_num);
-
-
-/**
- * *************** ATTENTION ********************/
-/**
- *@attention
- * Each GPIO has its own separate configuration register, so we do not use
- * a lock to serialize access to them. This works under the assumption that
- * no situation will occur where two tasks try to configure the same GPIO
- * pin simultaneously. It is up to the application developer to guarantee this.
- */
-
-/**
- *----------EXAMPLE TO CONFIGURE GPIO AS OUTPUT ------------ *
- * @code{c}
- * gpio_config_t io_conf;
- * io_conf.intr_type = GPIO_INTR_DISABLE; //disable interrupt
- * io_conf.mode = GPIO_MODE_OUTPUT; //set as output mode
- * io_conf.pin_bit_mask = GPIO_SEL_18 | GPIO_SEL_19; //bit mask of the pins that you want to set,e.g.GPIO18/19
- * io_conf.pull_down_en = 0; //disable pull-down mode
- * io_conf.pull_up_en = 0; //disable pull-up mode
- * gpio_config(&io_conf); //configure GPIO with the given settings
- * @endcode
- **/
-
-/**
- *----------EXAMPLE TO CONFIGURE GPIO AS OUTPUT ------------ *
- * @code{c}
- * io_conf.intr_type = GPIO_INTR_POSEDGE; //set posedge interrupt
- * io_conf.mode = GPIO_MODE_INPUT; //set as input
- * io_conf.pin_bit_mask = GPIO_SEL_4 | GPIO_SEL_5; //bit mask of the pins that you want to set, e.g.,GPIO4/5
- * io_conf.pull_down_en = 0; //disable pull-down mode
- * io_conf.pull_up_en = 1; //enable pull-up mode
- * gpio_config(&io_conf); //configure GPIO with the given settings
- * @endcode
- */
-/**
- *----------EXAMPLE TO SET ISR HANDLER ----------------------
- * @code{c}
- * gpio_isr_register(gpio_intr_test,NULL, 0); //hook the isr handler for GPIO interrupt
- * @endcode
- * @note
- * 1. user should arrange the INUMs that used, better not to use a same INUM for different interrupt.
- * 2. do not pick the INUM that already occupied by the system.
- * 3. refer to soc.h to check which INUMs that can be used.
- */
-/**
- *-------------EXAMPLE OF HANDLER FUNCTION-------------------*
- * @code{c}
- * #include "esp_attr.h"
- * void IRAM_ATTR gpio_intr_test(void* arg)
- * {
- * //GPIO intr process
- * ets_printf("in gpio_intr\n");
- * uint32_t gpio_num = 0;
- * uint32_t gpio_intr_status = READ_PERI_REG(GPIO_STATUS_REG); //read status to get interrupt status for GPIO0-31
- * uint32_t gpio_intr_status_h = READ_PERI_REG(GPIO_STATUS1_REG);//read status1 to get interrupt status for GPIO32-39
- * SET_PERI_REG_MASK(GPIO_STATUS_W1TC_REG, gpio_intr_status); //Clear intr for gpio0-gpio31
- * SET_PERI_REG_MASK(GPIO_STATUS1_W1TC_REG, gpio_intr_status_h); //Clear intr for gpio32-39
- * do {
- * if(gpio_num < 32) {
- * if(gpio_intr_status & BIT(gpio_num)) { //gpio0-gpio31
- * ets_printf("Intr GPIO%d ,val: %d\n",gpio_num,gpio_get_level(gpio_num));
- * //This is an isr handler, you should post an event to process it in RTOS queue.
- * }
- * } else {
- * if(gpio_intr_status_h & BIT(gpio_num - 32)) {
- * ets_printf("Intr GPIO%d, val : %d\n",gpio_num,gpio_get_level(gpio_num));
- * //This is an isr handler, you should post an event to process it in RTOS queue.
- * }
- * }
- * } while(++gpio_num < GPIO_PIN_COUNT);
- * }
- * @endcode
- */
-
-/**
- *----EXAMPLE OF I2C CONFIG AND PICK SIGNAL FOR IO MATRIX---*
- * @code{c}
- * gpio_config_t io_conf;
- * io_conf.intr_type = GPIO_INTR_DISABLE; //disable interrupt
- * io_conf.mode = GPIO_MODE_INPUT_OUTPUT_OD; //set as output mode
- * io_conf.pin_bit_mask = GPIO_SEL_21 | GPIO_SEL_22; //bit mask of the pins that you want to set,e.g.GPIO21/22
- * io_conf.pull_down_en = 0; //disable pull-down mode
- * io_conf.pull_up_en = 1; //enable pull-up mode
- * gpio_config(&io_conf); //configure GPIO with the given settings
- * gpio_matrix_out(21, EXT_I2C_SCL_O_IDX, 0, 0); //set output signal for io_matrix
- * gpio_matrix_out(22, EXT_I2C_SDA_O_IDX, 0, 0); //set output signal for io_matrix
- * gpio_matrix_in( 22, EXT_I2C_SDA_I_IDX, 0); //set input signal for io_matrix
- * @endcode
- *
- */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _DRIVER_GPIO_H_ */
diff --git a/esp32/bootloader/lib/bootloader.map b/esp32/bootloader/lib/bootloader.map
new file mode 100644
index 0000000000..ed2b59651d
--- /dev/null
+++ b/esp32/bootloader/lib/bootloader.map
@@ -0,0 +1,3680 @@
+Archive member included to satisfy reference by file (symbol)
+
+/home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(bootloader_start.o)
+ (call_start_cpu0)
+/home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_bootloader.o)
+ /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(bootloader_start.o) (pycom_bootloader_utility_get_selected_boot_partition)
+/home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_bootmgr.o)
+ /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_bootloader.o) (wait_for_safe_boot)
+/home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_mperror.o)
+ /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_bootmgr.o) (mperror_set_rgb_color)
+/home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_gpio.o)
+ /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_bootmgr.o) (gpio_get_level)
+/home/element/xtensa-esp32-elf-2020r3/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/no-rtti/libgcc.a(_lshrdi3.o)
+ /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_gpio.o) (__lshrdi3)
+/home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_utility.o)
+ /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(bootloader_start.o) (bootloader_utility_load_partition_table)
+/home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_common.o)
+ /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_utility.o) (bootloader_common_ota_select_crc)
+/home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(pycom_bootloader_support.o)
+ /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_bootloader.o) (pycom_read_otadata)
+/home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(flash_partitions.o)
+ /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_utility.o) (esp_partition_table_verify)
+/home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(esp_image_format.o)
+ /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_utility.o) (bootloader_load_image)
+/home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_random.o)
+ /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(esp_image_format.o) (bootloader_fill_random)
+/home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_sha.o)
+ /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_utility.o) (bootloader_sha256_start)
+/home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_esp32.o)
+ /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(bootloader_start.o) (bootloader_init)
+/home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_efuse_esp32.o)
+ /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_common.o) (bootloader_common_get_chip_revision)
+/home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_flash.o)
+ /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_utility.o) (bootloader_mmap_get_free_pages)
+/home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(flash_qio_mode.o)
+ /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_esp32.o) (bootloader_enable_qio_mode)
+/home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_init.o)
+ /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_esp32.o) (bootloader_clear_bss_section)
+/home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_clock.o)
+ /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_esp32.o) (bootloader_clock_configure)
+/home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_flash_config_esp32.o)
+ /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_esp32.o) (bootloader_flash_update_id)
+/home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/log/liblog.a(log_noos.o)
+ /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_common.o) (esp_log_early_timestamp)
+/home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/spi_flash/libspi_flash.a(spi_flash_rom_patch.o)
+ /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(flash_qio_mode.o) (esp_rom_spiflash_wait_idle)
+/home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(cpu_util.o)
+ /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(esp_image_format.o) (esp_cpu_in_ocd_debug_mode)
+/home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_wdt.o)
+ /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_init.o) (rtc_wdt_protect_off)
+/home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_init.o)
+ /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_common.o) (rtc_vddsdio_get_config)
+/home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk_init.o)
+ /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_clock.o) (rtc_clk_init)
+/home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk.o)
+ /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk_init.o) (rtc_clk_32k_enable)
+/home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_time.o)
+ /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk_init.o) (rtc_clk_cal_ratio)
+/home/element/xtensa-esp32-elf-2020r3/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/no-rtti/libgcc.a(_bswapsi2.o)
+ /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_sha.o) (__bswapsi2)
+/home/element/xtensa-esp32-elf-2020r3/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/no-rtti/libgcc.a(_divdi3.o)
+ /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk_init.o) (__divdi3)
+/home/element/xtensa-esp32-elf-2020r3/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/no-rtti/libgcc.a(_udivdi3.o)
+ /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_wdt.o) (__udivdi3)
+
+Allocating common symbols
+Common symbol size file
+
+bootloader_image_hdr
+ 0x18 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_init.o)
+
+Discarded input sections
+
+ .text 0x0000000000000000 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(bootloader_start.o)
+ .data 0x0000000000000000 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(bootloader_start.o)
+ .bss 0x0000000000000000 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(bootloader_start.o)
+ .xt.lit 0x0000000000000000 0x8 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(bootloader_start.o)
+ .xt.prop 0x0000000000000000 0x3c /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(bootloader_start.o)
+ .text 0x0000000000000000 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_bootloader.o)
+ .data 0x0000000000000000 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_bootloader.o)
+ .bss 0x0000000000000000 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_bootloader.o)
+ .xt.lit 0x0000000000000000 0x10 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_bootloader.o)
+ .xt.prop 0x0000000000000000 0xe4 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_bootloader.o)
+ .text 0x0000000000000000 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_bootmgr.o)
+ .data 0x0000000000000000 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_bootmgr.o)
+ .bss 0x0000000000000000 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_bootmgr.o)
+ .xt.lit 0x0000000000000000 0x10 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_bootmgr.o)
+ .xt.prop 0x0000000000000000 0xd8 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_bootmgr.o)
+ .literal.mperror_enable_heartbeat
+ 0x0000000000000000 0x8 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_mperror.o)
+ .literal.mperror_is_heartbeat_enabled
+ 0x0000000000000000 0x4 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_mperror.o)
+ .text 0x0000000000000000 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_mperror.o)
+ .data 0x0000000000000000 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_mperror.o)
+ .bss 0x0000000000000000 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_mperror.o)
+ .text.mperror_enable_heartbeat
+ 0x0000000000000000 0x29 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_mperror.o)
+ .text.mperror_is_heartbeat_enabled
+ 0x0000000000000000 0xb /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_mperror.o)
+ .xt.lit 0x0000000000000000 0x30 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_mperror.o)
+ .xt.prop 0x0000000000000000 0x1c8 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_mperror.o)
+ .literal.gpio_set_level
+ 0x0000000000000000 0x8 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_gpio.o)
+ .literal.gpio_set_pull_mode
+ 0x0000000000000000 0x1c /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_gpio.o)
+ .literal.gpio_set_direction
+ 0x0000000000000000 0x8 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_gpio.o)
+ .literal.gpio_isr_register
+ 0x0000000000000000 0x4 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_gpio.o)
+ .literal.gpio_wakeup_enable
+ 0x0000000000000000 0x8 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_gpio.o)
+ .literal.gpio_wakeup_disable
+ 0x0000000000000000 0x8 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_gpio.o)
+ .text 0x0000000000000000 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_gpio.o)
+ .data 0x0000000000000000 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_gpio.o)
+ .bss 0x0000000000000000 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_gpio.o)
+ .text.gpio_set_level
+ 0x0000000000000000 0x75 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_gpio.o)
+ .text.gpio_set_pull_mode
+ 0x0000000000000000 0x6f /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_gpio.o)
+ .text.gpio_set_direction
+ 0x0000000000000000 0xcf /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_gpio.o)
+ .text.gpio_isr_register
+ 0x0000000000000000 0x1c /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_gpio.o)
+ .text.gpio_wakeup_enable
+ 0x0000000000000000 0x57 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_gpio.o)
+ .text.gpio_wakeup_disable
+ 0x0000000000000000 0x38 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_gpio.o)
+ .xt.lit 0x0000000000000000 0x78 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_gpio.o)
+ .xt.prop 0x0000000000000000 0x600 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_gpio.o)
+ .data 0x0000000000000000 0x0 /home/element/xtensa-esp32-elf-2020r3/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/no-rtti/libgcc.a(_lshrdi3.o)
+ .bss 0x0000000000000000 0x0 /home/element/xtensa-esp32-elf-2020r3/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/no-rtti/libgcc.a(_lshrdi3.o)
+ .xt.prop 0x0000000000000000 0x3c /home/element/xtensa-esp32-elf-2020r3/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/no-rtti/libgcc.a(_lshrdi3.o)
+ .literal.bootloader_utility_get_selected_boot_partition
+ 0x0000000000000000 0x2c /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_utility.o)
+ .literal.bootloader_sha256_flash_contents
+ 0x0000000000000000 0x1c /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_utility.o)
+ .text 0x0000000000000000 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_utility.o)
+ .data 0x0000000000000000 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_utility.o)
+ .bss 0x0000000000000000 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_utility.o)
+ .text.bootloader_utility_get_selected_boot_partition
+ 0x0000000000000000 0xc5 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_utility.o)
+ .text.bootloader_sha256_hex_to_str
+ 0x0000000000000000 0x66 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_utility.o)
+ .text.bootloader_sha256_flash_contents
+ 0x0000000000000000 0x86 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_utility.o)
+ .xt.lit 0x0000000000000000 0x48 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_utility.o)
+ .xt.prop 0x0000000000000000 0x4e0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_utility.o)
+ .literal.bootloader_common_ota_select_valid
+ 0x0000000000000000 0x8 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_common.o)
+ .literal.bootloader_common_check_long_hold_gpio
+ 0x0000000000000000 0x28 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_common.o)
+ .literal.bootloader_common_label_search
+ 0x0000000000000000 0x18 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_common.o)
+ .literal.bootloader_common_erase_part_type_data
+ 0x0000000000000000 0x24 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_common.o)
+ .literal.bootloader_common_get_sha256_of_partition
+ 0x0000000000000000 0x24 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_common.o)
+ .literal.bootloader_common_get_active_otadata
+ 0x0000000000000000 0xc /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_common.o)
+ .literal.bootloader_common_get_partition_description
+ 0x0000000000000000 0x10 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_common.o)
+ .literal.bootloader_common_get_reset_reason
+ 0x0000000000000000 0x4 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_common.o)
+ .text 0x0000000000000000 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_common.o)
+ .data 0x0000000000000000 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_common.o)
+ .bss 0x0000000000000000 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_common.o)
+ .text.bootloader_common_ota_select_invalid
+ 0x0000000000000000 0x19 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_common.o)
+ .text.bootloader_common_ota_select_valid
+ 0x0000000000000000 0x26 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_common.o)
+ .text.bootloader_common_check_long_hold_gpio
+ 0x0000000000000000 0x9b /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_common.o)
+ .rodata.bootloader_common_label_search.str1.1
+ 0x0000000000000000 0x3 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_common.o)
+ .text.bootloader_common_label_search
+ 0x0000000000000000 0xaf /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_common.o)
+ .text.bootloader_common_erase_part_type_data
+ 0x0000000000000000 0x95 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_common.o)
+ .text.bootloader_common_get_sha256_of_partition
+ 0x0000000000000000 0xa3 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_common.o)
+ .text.bootloader_common_select_otadata
+ 0x0000000000000000 0x4d /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_common.o)
+ .text.bootloader_common_get_active_otadata
+ 0x0000000000000000 0x30 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_common.o)
+ .text.bootloader_common_get_partition_description
+ 0x0000000000000000 0x5a /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_common.o)
+ .text.bootloader_common_get_reset_reason
+ 0x0000000000000000 0x10 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_common.o)
+ .xt.lit 0x0000000000000000 0x58 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_common.o)
+ .xt.prop 0x0000000000000000 0x450 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_common.o)
+ .text 0x0000000000000000 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(pycom_bootloader_support.o)
+ .data 0x0000000000000000 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(pycom_bootloader_support.o)
+ .bss 0x0000000000000000 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(pycom_bootloader_support.o)
+ .xt.lit 0x0000000000000000 0x18 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(pycom_bootloader_support.o)
+ .xt.prop 0x0000000000000000 0xf0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(pycom_bootloader_support.o)
+ .text 0x0000000000000000 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(flash_partitions.o)
+ .data 0x0000000000000000 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(flash_partitions.o)
+ .bss 0x0000000000000000 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(flash_partitions.o)
+ .xt.lit 0x0000000000000000 0x8 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(flash_partitions.o)
+ .xt.prop 0x0000000000000000 0x78 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(flash_partitions.o)
+ .literal.bootloader_load_image_no_verify
+ 0x0000000000000000 0x4 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(esp_image_format.o)
+ .literal.esp_image_verify_bootloader_data
+ 0x0000000000000000 0x8 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(esp_image_format.o)
+ .literal.esp_image_verify_bootloader
+ 0x0000000000000000 0x4 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(esp_image_format.o)
+ .text 0x0000000000000000 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(esp_image_format.o)
+ .data 0x0000000000000000 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(esp_image_format.o)
+ .bss 0x0000000000000000 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(esp_image_format.o)
+ .text.bootloader_load_image_no_verify
+ 0x0000000000000000 0x14 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(esp_image_format.o)
+ .rodata 0x0000000000000000 0x8 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(esp_image_format.o)
+ .text.esp_image_verify_bootloader_data
+ 0x0000000000000000 0x24 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(esp_image_format.o)
+ .text.esp_image_verify_bootloader
+ 0x0000000000000000 0x1c /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(esp_image_format.o)
+ .xt.lit 0x0000000000000000 0x48 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(esp_image_format.o)
+ .xt.prop 0x0000000000000000 0x5c4 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(esp_image_format.o)
+ .text 0x0000000000000000 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_random.o)
+ .data 0x0000000000000000 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_random.o)
+ .bss 0x0000000000000000 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_random.o)
+ .xt.lit 0x0000000000000000 0x18 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_random.o)
+ .xt.prop 0x0000000000000000 0xcc /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_random.o)
+ .text 0x0000000000000000 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_sha.o)
+ .data 0x0000000000000000 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_sha.o)
+ .bss 0x0000000000000000 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_sha.o)
+ .xt.lit 0x0000000000000000 0x18 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_sha.o)
+ .xt.prop 0x0000000000000000 0x18c /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_sha.o)
+ .literal.bootloader_configure_spi_pins
+ 0x0000000000000000 0x58 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_esp32.o)
+ .text 0x0000000000000000 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_esp32.o)
+ .data 0x0000000000000000 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_esp32.o)
+ .bss 0x0000000000000000 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_esp32.o)
+ .text.bootloader_configure_spi_pins
+ 0x0000000000000000 0x16a /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_esp32.o)
+ .xt.lit 0x0000000000000000 0x18 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_esp32.o)
+ .xt.prop 0x0000000000000000 0x15c /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_esp32.o)
+ .text 0x0000000000000000 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_efuse_esp32.o)
+ .data 0x0000000000000000 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_efuse_esp32.o)
+ .bss 0x0000000000000000 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_efuse_esp32.o)
+ .xt.lit 0x0000000000000000 0x10 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_efuse_esp32.o)
+ .xt.prop 0x0000000000000000 0x6c /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_efuse_esp32.o)
+ .literal.bootloader_flash_erase_range
+ 0x0000000000000000 0xc /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_flash.o)
+ .text 0x0000000000000000 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_flash.o)
+ .data 0x0000000000000000 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_flash.o)
+ .bss 0x0000000000000000 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_flash.o)
+ .text.bootloader_flash_erase_range
+ 0x0000000000000000 0x5f /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_flash.o)
+ .xt.lit 0x0000000000000000 0x30 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_flash.o)
+ .xt.prop 0x0000000000000000 0x270 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_flash.o)
+ .text 0x0000000000000000 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(flash_qio_mode.o)
+ .data 0x0000000000000000 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(flash_qio_mode.o)
+ .bss 0x0000000000000000 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(flash_qio_mode.o)
+ .xt.lit 0x0000000000000000 0x58 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(flash_qio_mode.o)
+ .xt.prop 0x0000000000000000 0x288 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(flash_qio_mode.o)
+ .text 0x0000000000000000 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_init.o)
+ .data 0x0000000000000000 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_init.o)
+ .bss 0x0000000000000000 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_init.o)
+ .xt.lit 0x0000000000000000 0x28 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_init.o)
+ .xt.prop 0x0000000000000000 0x138 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_init.o)
+ .literal.esp_clk_apb_freq
+ 0x0000000000000000 0x4 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_clock.o)
+ .text 0x0000000000000000 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_clock.o)
+ .data 0x0000000000000000 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_clock.o)
+ .bss 0x0000000000000000 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_clock.o)
+ .text.esp_clk_apb_freq
+ 0x0000000000000000 0xd /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_clock.o)
+ .xt.lit 0x0000000000000000 0x10 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_clock.o)
+ .xt.prop 0x0000000000000000 0x78 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_clock.o)
+ .iram1.1.literal
+ 0x0000000000000000 0xc /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_flash_config_esp32.o)
+ .text 0x0000000000000000 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_flash_config_esp32.o)
+ .data 0x0000000000000000 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_flash_config_esp32.o)
+ .bss 0x0000000000000000 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_flash_config_esp32.o)
+ .iram1.1 0x0000000000000000 0x28 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_flash_config_esp32.o)
+ .rodata.CSWTCH$0
+ 0x0000000000000000 0x10 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_flash_config_esp32.o)
+ .xt.lit 0x0000000000000000 0x28 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_flash_config_esp32.o)
+ .xt.prop 0x0000000000000000 0x180 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_flash_config_esp32.o)
+ .literal.esp_log_impl_lock
+ 0x0000000000000000 0x14 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/log/liblog.a(log_noos.o)
+ .literal.esp_log_lock_impl_timeout
+ 0x0000000000000000 0x4 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/log/liblog.a(log_noos.o)
+ .literal.esp_log_impl_unlock
+ 0x0000000000000000 0x14 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/log/liblog.a(log_noos.o)
+ .literal.esp_log_early_timestamp
+ 0x0000000000000000 0x4 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/log/liblog.a(log_noos.o)
+ .text 0x0000000000000000 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/log/liblog.a(log_noos.o)
+ .data 0x0000000000000000 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/log/liblog.a(log_noos.o)
+ .bss 0x0000000000000000 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/log/liblog.a(log_noos.o)
+ .rodata.esp_log_impl_lock.str1.1
+ 0x0000000000000000 0x4e /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/log/liblog.a(log_noos.o)
+ .text.esp_log_impl_lock
+ 0x0000000000000000 0x22 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/log/liblog.a(log_noos.o)
+ .text.esp_log_lock_impl_timeout
+ 0x0000000000000000 0xd /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/log/liblog.a(log_noos.o)
+ .rodata.esp_log_impl_unlock.str1.1
+ 0x0000000000000000 0xc /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/log/liblog.a(log_noos.o)
+ .text.esp_log_impl_unlock
+ 0x0000000000000000 0x22 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/log/liblog.a(log_noos.o)
+ .text.esp_log_early_timestamp
+ 0x0000000000000000 0x1e /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/log/liblog.a(log_noos.o)
+ .rodata.__func__$2042
+ 0x0000000000000000 0x14 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/log/liblog.a(log_noos.o)
+ .rodata.__func__$2035
+ 0x0000000000000000 0x12 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/log/liblog.a(log_noos.o)
+ .bss.s_lock 0x0000000000000000 0x4 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/log/liblog.a(log_noos.o)
+ .debug_frame 0x0000000000000000 0x70 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/log/liblog.a(log_noos.o)
+ .debug_info 0x0000000000000000 0xa34 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/log/liblog.a(log_noos.o)
+ .debug_abbrev 0x0000000000000000 0x1c1 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/log/liblog.a(log_noos.o)
+ .debug_loc 0x0000000000000000 0x15 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/log/liblog.a(log_noos.o)
+ .debug_aranges
+ 0x0000000000000000 0x38 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/log/liblog.a(log_noos.o)
+ .debug_ranges 0x0000000000000000 0x28 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/log/liblog.a(log_noos.o)
+ .debug_line 0x0000000000000000 0x374 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/log/liblog.a(log_noos.o)
+ .debug_str 0x0000000000000000 0xd88 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/log/liblog.a(log_noos.o)
+ .comment 0x0000000000000000 0x26 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/log/liblog.a(log_noos.o)
+ .xt.lit 0x0000000000000000 0x20 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/log/liblog.a(log_noos.o)
+ .xt.prop 0x0000000000000000 0xd8 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/log/liblog.a(log_noos.o)
+ .literal.esp_rom_spiflash_lock
+ 0x0000000000000000 0x18 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/spi_flash/libspi_flash.a(spi_flash_rom_patch.o)
+ .literal.esp_rom_spiflash_erase_chip
+ 0x0000000000000000 0x18 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/spi_flash/libspi_flash.a(spi_flash_rom_patch.o)
+ .literal.esp_rom_spiflash_erase_block
+ 0x0000000000000000 0x34 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/spi_flash/libspi_flash.a(spi_flash_rom_patch.o)
+ .literal.esp_rom_spiflash_erase_area
+ 0x0000000000000000 0x18 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/spi_flash/libspi_flash.a(spi_flash_rom_patch.o)
+ .text 0x0000000000000000 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/spi_flash/libspi_flash.a(spi_flash_rom_patch.o)
+ .data 0x0000000000000000 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/spi_flash/libspi_flash.a(spi_flash_rom_patch.o)
+ .bss 0x0000000000000000 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/spi_flash/libspi_flash.a(spi_flash_rom_patch.o)
+ .text.esp_rom_spiflash_lock
+ 0x0000000000000000 0x4d /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/spi_flash/libspi_flash.a(spi_flash_rom_patch.o)
+ .text.esp_rom_spiflash_erase_chip
+ 0x0000000000000000 0x36 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/spi_flash/libspi_flash.a(spi_flash_rom_patch.o)
+ .text.esp_rom_spiflash_erase_block
+ 0x0000000000000000 0x84 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/spi_flash/libspi_flash.a(spi_flash_rom_patch.o)
+ .text.esp_rom_spiflash_erase_area
+ 0x0000000000000000 0x94 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/spi_flash/libspi_flash.a(spi_flash_rom_patch.o)
+ .xt.lit 0x0000000000000000 0x80 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/spi_flash/libspi_flash.a(spi_flash_rom_patch.o)
+ .xt.prop 0x0000000000000000 0x738 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/spi_flash/libspi_flash.a(spi_flash_rom_patch.o)
+ .iram1.0.literal
+ 0x0000000000000000 0x18 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(cpu_util.o)
+ .iram1.1.literal
+ 0x0000000000000000 0x10 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(cpu_util.o)
+ .iram1.2.literal
+ 0x0000000000000000 0x4 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(cpu_util.o)
+ .text 0x0000000000000000 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(cpu_util.o)
+ .data 0x0000000000000000 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(cpu_util.o)
+ .bss 0x0000000000000000 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(cpu_util.o)
+ .iram1.0 0x0000000000000000 0x83 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(cpu_util.o)
+ .iram1.1 0x0000000000000000 0x42 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(cpu_util.o)
+ .iram1.2 0x0000000000000000 0x1e /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(cpu_util.o)
+ .xt.lit 0x0000000000000000 0x20 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(cpu_util.o)
+ .xt.prop 0x0000000000000000 0xf0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(cpu_util.o)
+ .literal.rtc_wdt_get_protect_status
+ 0x0000000000000000 0x8 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_wdt.o)
+ .literal.rtc_wdt_flashboot_mode_enable
+ 0x0000000000000000 0x4 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_wdt.o)
+ .literal.rtc_wdt_feed
+ 0x0000000000000000 0x10 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_wdt.o)
+ .literal.rtc_wdt_get_timeout
+ 0x0000000000000000 0x14 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_wdt.o)
+ .literal.rtc_wdt_is_on
+ 0x0000000000000000 0x4 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_wdt.o)
+ .text 0x0000000000000000 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_wdt.o)
+ .data 0x0000000000000000 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_wdt.o)
+ .bss 0x0000000000000000 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_wdt.o)
+ .text.rtc_wdt_get_protect_status
+ 0x0000000000000000 0x1b /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_wdt.o)
+ .text.rtc_wdt_flashboot_mode_enable
+ 0x0000000000000000 0x18 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_wdt.o)
+ .text.rtc_wdt_feed
+ 0x0000000000000000 0x3e /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_wdt.o)
+ .text.rtc_wdt_get_timeout
+ 0x0000000000000000 0x4b /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_wdt.o)
+ .text.rtc_wdt_is_on
+ 0x0000000000000000 0x1a /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_wdt.o)
+ .xt.lit 0x0000000000000000 0x60 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_wdt.o)
+ .xt.prop 0x0000000000000000 0x384 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_wdt.o)
+ .literal.rtc_init
+ 0x0000000000000000 0xbc /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_init.o)
+ .text 0x0000000000000000 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_init.o)
+ .data 0x0000000000000000 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_init.o)
+ .bss 0x0000000000000000 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_init.o)
+ .text.rtc_init
+ 0x0000000000000000 0x342 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_init.o)
+ .xt.lit 0x0000000000000000 0x18 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_init.o)
+ .xt.prop 0x0000000000000000 0xfc /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_init.o)
+ .text 0x0000000000000000 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk_init.o)
+ .data 0x0000000000000000 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk_init.o)
+ .bss 0x0000000000000000 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk_init.o)
+ .xt.lit 0x0000000000000000 0x10 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk_init.o)
+ .xt.prop 0x0000000000000000 0xe4 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk_init.o)
+ .literal.rtc_clk_32k_enable_external
+ 0x0000000000000000 0x4 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk.o)
+ .literal.rtc_clk_32k_bootstrap
+ 0x0000000000000000 0x34 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk.o)
+ .literal.rtc_clk_32k_enabled
+ 0x0000000000000000 0x4 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk.o)
+ .literal.rtc_clk_apll_enable
+ 0x0000000000000000 0x54 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk.o)
+ .literal.rtc_clk_cpu_freq_to_config
+ 0x0000000000000000 0x8 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk.o)
+ .literal.rtc_clk_cpu_freq_set_xtal
+ 0x0000000000000000 0x10 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk.o)
+ .literal.rtc_clk_cpu_freq_set_config_fast
+ 0x0000000000000000 0x10 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk.o)
+ .text 0x0000000000000000 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk.o)
+ .data 0x0000000000000000 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk.o)
+ .bss 0x0000000000000000 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk.o)
+ .text.rtc_clk_32k_enable_external
+ 0x0000000000000000 0xf /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk.o)
+ .text.rtc_clk_32k_bootstrap
+ 0x0000000000000000 0x9c /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk.o)
+ .text.rtc_clk_32k_enabled
+ 0x0000000000000000 0x10 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk.o)
+ .text.rtc_clk_apll_enable
+ 0x0000000000000000 0x153 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk.o)
+ .text.rtc_clk_cpu_freq_to_config
+ 0x0000000000000000 0x5b /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk.o)
+ .text.rtc_clk_cpu_freq_set_xtal
+ 0x0000000000000000 0x1f /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk.o)
+ .text.rtc_clk_cpu_freq_set_config_fast
+ 0x0000000000000000 0x39 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk.o)
+ .xt.lit 0x0000000000000000 0xe0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk.o)
+ .xt.prop 0x0000000000000000 0x870 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk.o)
+ .literal.rtc_clk_cal
+ 0x0000000000000000 0xc /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_time.o)
+ .literal.rtc_time_us_to_slowclk
+ 0x0000000000000000 0x4 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_time.o)
+ .literal.rtc_time_get
+ 0x0000000000000000 0x18 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_time.o)
+ .text 0x0000000000000000 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_time.o)
+ .data 0x0000000000000000 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_time.o)
+ .bss 0x0000000000000000 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_time.o)
+ .text.rtc_clk_cal
+ 0x0000000000000000 0x54 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_time.o)
+ .text.rtc_time_us_to_slowclk
+ 0x0000000000000000 0x1f /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_time.o)
+ .text.rtc_time_slowclk_to_us
+ 0x0000000000000000 0x1c /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_time.o)
+ .text.rtc_time_get
+ 0x0000000000000000 0x4f /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_time.o)
+ .xt.lit 0x0000000000000000 0x30 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_time.o)
+ .xt.prop 0x0000000000000000 0x234 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_time.o)
+ .data 0x0000000000000000 0x0 /home/element/xtensa-esp32-elf-2020r3/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/no-rtti/libgcc.a(_bswapsi2.o)
+ .bss 0x0000000000000000 0x0 /home/element/xtensa-esp32-elf-2020r3/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/no-rtti/libgcc.a(_bswapsi2.o)
+ .xt.lit 0x0000000000000000 0x8 /home/element/xtensa-esp32-elf-2020r3/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/no-rtti/libgcc.a(_bswapsi2.o)
+ .xt.prop 0x0000000000000000 0x30 /home/element/xtensa-esp32-elf-2020r3/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/no-rtti/libgcc.a(_bswapsi2.o)
+ .text 0x0000000000000000 0x2aa /home/element/xtensa-esp32-elf-2020r3/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/no-rtti/libgcc.a(_divdi3.o)
+ .data 0x0000000000000000 0x0 /home/element/xtensa-esp32-elf-2020r3/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/no-rtti/libgcc.a(_divdi3.o)
+ .bss 0x0000000000000000 0x0 /home/element/xtensa-esp32-elf-2020r3/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/no-rtti/libgcc.a(_divdi3.o)
+ .debug_frame 0x0000000000000000 0x28 /home/element/xtensa-esp32-elf-2020r3/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/no-rtti/libgcc.a(_divdi3.o)
+ .eh_frame 0x0000000000000000 0x28 /home/element/xtensa-esp32-elf-2020r3/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/no-rtti/libgcc.a(_divdi3.o)
+ .debug_info 0x0000000000000000 0x114b /home/element/xtensa-esp32-elf-2020r3/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/no-rtti/libgcc.a(_divdi3.o)
+ .debug_abbrev 0x0000000000000000 0x28e /home/element/xtensa-esp32-elf-2020r3/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/no-rtti/libgcc.a(_divdi3.o)
+ .debug_loc 0x0000000000000000 0xb09 /home/element/xtensa-esp32-elf-2020r3/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/no-rtti/libgcc.a(_divdi3.o)
+ .debug_aranges
+ 0x0000000000000000 0x20 /home/element/xtensa-esp32-elf-2020r3/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/no-rtti/libgcc.a(_divdi3.o)
+ .debug_ranges 0x0000000000000000 0xa0 /home/element/xtensa-esp32-elf-2020r3/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/no-rtti/libgcc.a(_divdi3.o)
+ .debug_line 0x0000000000000000 0xadc /home/element/xtensa-esp32-elf-2020r3/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/no-rtti/libgcc.a(_divdi3.o)
+ .debug_str 0x0000000000000000 0x758 /home/element/xtensa-esp32-elf-2020r3/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/no-rtti/libgcc.a(_divdi3.o)
+ .comment 0x0000000000000000 0x26 /home/element/xtensa-esp32-elf-2020r3/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/no-rtti/libgcc.a(_divdi3.o)
+ .xt.prop 0x0000000000000000 0x1bc /home/element/xtensa-esp32-elf-2020r3/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/no-rtti/libgcc.a(_divdi3.o)
+ .data 0x0000000000000000 0x0 /home/element/xtensa-esp32-elf-2020r3/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/no-rtti/libgcc.a(_udivdi3.o)
+ .bss 0x0000000000000000 0x0 /home/element/xtensa-esp32-elf-2020r3/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/no-rtti/libgcc.a(_udivdi3.o)
+ .eh_frame 0x0000000000000000 0x28 /home/element/xtensa-esp32-elf-2020r3/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/no-rtti/libgcc.a(_udivdi3.o)
+ .xt.prop 0x0000000000000000 0x1a4 /home/element/xtensa-esp32-elf-2020r3/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/no-rtti/libgcc.a(_udivdi3.o)
+
+Memory Configuration
+
+Name Origin Length Attributes
+dport0_seg 0x000000003ff00000 0x0000000000000010 rw
+iram_loader_seg 0x0000000040078000 0x0000000000008000 xrw
+iram_seg 0x0000000040080400 0x000000000000fc00 xrw
+dram_seg 0x000000003fff0000 0x0000000000010000 rw
+*default* 0x0000000000000000 0xffffffffffffffff
+
+Linker script and memory map
+
+START GROUP
+LOAD /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a
+LOAD /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/log/liblog.a
+LOAD /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/spi_flash/libspi_flash.a
+LOAD /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/micro-ecc/libmicro-ecc.a
+LOAD /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a
+LOAD /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a
+LOAD /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/efuse/libefuse.a
+LOAD /home/element/xtensa-esp32-elf-2020r3/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/no-rtti/libgcc.a
+LOAD /home/element/xtensa-esp32-elf-2020r3/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/lib/no-rtti/libstdc++.a
+LOAD /home/element/xtensa-esp32-elf-2020r3/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/no-rtti/libgcov.a
+END GROUP
+
+.iram_loader.text
+ 0x0000000040078000 0x302e
+ 0x0000000040078000 . = ALIGN (0x10)
+ 0x0000000040078000 _loader_text_start = ABSOLUTE (.)
+ *(.stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
+ *(.iram1 .iram1.*)
+ .iram1.2.literal
+ 0x0000000040078000 0x18 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_mperror.o)
+ 0x20 (size before relaxing)
+ .iram1.12.literal
+ 0x0000000040078018 0x4 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(pycom_bootloader_support.o)
+ 0x10 (size before relaxing)
+ .iram1.0.literal
+ 0x000000004007801c 0x10 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_flash_config_esp32.o)
+ .iram1.2.literal
+ 0x000000004007802c 0x44 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_flash_config_esp32.o)
+ 0x60 (size before relaxing)
+ .iram1.3.literal
+ 0x0000000040078070 0x18 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_flash_config_esp32.o)
+ 0x1c (size before relaxing)
+ .iram1.3.literal
+ 0x0000000040078088 0x4 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(cpu_util.o)
+ .literal 0x000000004007808c 0x0 /home/element/xtensa-esp32-elf-2020r3/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/no-rtti/libgcc.a(_bswapsi2.o)
+ 0x8 (size before relaxing)
+ .literal.bootloader_clock_configure
+ 0x000000004007808c 0x1c /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_clock.o)
+ 0x2c (size before relaxing)
+ .literal.bootloader_common_ota_select_crc
+ 0x00000000400780a8 0x4 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_common.o)
+ .literal.bootloader_common_vddsdio_configure
+ 0x00000000400780ac 0x4 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_common.o)
+ 0x10 (size before relaxing)
+ .literal.bootloader_common_check_chip_validity
+ 0x00000000400780b0 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_common.o)
+ 0x4 (size before relaxing)
+ .literal.bootloader_mmap
+ 0x00000000400780b0 0x20 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_flash.o)
+ 0x28 (size before relaxing)
+ .literal.bootloader_munmap
+ 0x00000000400780d0 0x8 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_flash.o)
+ 0x14 (size before relaxing)
+ .literal.bootloader_flash_read
+ 0x00000000400780d8 0x8 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_flash.o)
+ 0x34 (size before relaxing)
+ .literal.bootloader_flash_write
+ 0x00000000400780e0 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_flash.o)
+ 0x10 (size before relaxing)
+ .literal.bootloader_flash_erase_sector
+ 0x00000000400780e0 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_flash.o)
+ 0x8 (size before relaxing)
+ .literal.bootloader_fill_random
+ 0x00000000400780e0 0x14 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_random.o)
+ 0x18 (size before relaxing)
+ .literal.bootloader_random_enable
+ 0x00000000400780f4 0x78 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_random.o)
+ .literal.bootloader_random_disable
+ 0x000000004007816c 0x1c /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_random.o)
+ 0x4c (size before relaxing)
+ .literal.bootloader_common_get_chip_revision
+ 0x0000000040078188 0xc /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_efuse_esp32.o)
+ 0x10 (size before relaxing)
+ .literal.bootloader_clock_get_rated_freq_mhz
+ 0x0000000040078194 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_efuse_esp32.o)
+ 0x4 (size before relaxing)
+ .literal.unpack_load_app
+ 0x0000000040078194 0x1c /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_utility.o)
+ 0x40 (size before relaxing)
+ .literal.set_actual_ota_seq$isra$3$part$4
+ 0x00000000400781b0 0x4 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_utility.o)
+ 0x14 (size before relaxing)
+ .literal.try_load_partition
+ 0x00000000400781b4 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_utility.o)
+ 0x4 (size before relaxing)
+ .literal.bootloader_utility_load_partition_table
+ 0x00000000400781b4 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_utility.o)
+ 0x14 (size before relaxing)
+ .literal.bootloader_reset
+ 0x00000000400781b4 0x8 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_utility.o)
+ 0x14 (size before relaxing)
+ .literal.bootloader_utility_load_boot_image
+ 0x00000000400781bc 0x4 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_utility.o)
+ 0x30 (size before relaxing)
+ .literal.bootloader_debug_buffer
+ 0x00000000400781c0 0xc /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_utility.o)
+ 0x10 (size before relaxing)
+ .literal.bootloader_sha256_start
+ 0x00000000400781cc 0x8 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_sha.o)
+ .literal.bootloader_sha256_data
+ 0x00000000400781d4 0x20 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_sha.o)
+ 0x2c (size before relaxing)
+ .literal.bootloader_sha256_finish
+ 0x00000000400781f4 0x14 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_sha.o)
+ 0x3c (size before relaxing)
+ .literal.bootloader_util_regions_overlap
+ 0x0000000040078208 0x10 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(esp_image_format.o)
+ 0x14 (size before relaxing)
+ .literal.verify_load_addresses
+ 0x0000000040078218 0x64 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(esp_image_format.o)
+ 0x7c (size before relaxing)
+ .literal.should_load
+ 0x000000004007827c 0x8 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(esp_image_format.o)
+ 0x28 (size before relaxing)
+ .literal.image_load
+ 0x0000000040078284 0x20 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(esp_image_format.o)
+ 0xb4 (size before relaxing)
+ .literal.bootloader_load_image
+ 0x00000000400782a4 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(esp_image_format.o)
+ 0x4 (size before relaxing)
+ .literal.esp_image_verify
+ 0x00000000400782a4 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(esp_image_format.o)
+ 0x4 (size before relaxing)
+ .literal.esp_partition_table_verify
+ 0x00000000400782a4 0x14 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(flash_partitions.o)
+ 0x1c (size before relaxing)
+ .literal.esp_rom_spiflash_read_status
+ 0x00000000400782b8 0xc /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/spi_flash/libspi_flash.a(spi_flash_rom_patch.o)
+ 0x14 (size before relaxing)
+ .literal.esp_rom_spiflash_wait_idle
+ 0x00000000400782c4 0x8 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/spi_flash/libspi_flash.a(spi_flash_rom_patch.o)
+ 0xc (size before relaxing)
+ .literal.esp_rom_spiflash_enable_write$constprop$6
+ 0x00000000400782cc 0x4 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/spi_flash/libspi_flash.a(spi_flash_rom_patch.o)
+ 0x14 (size before relaxing)
+ .literal.esp_rom_spiflash_program_page_internal$constprop$4
+ 0x00000000400782d0 0xc /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/spi_flash/libspi_flash.a(spi_flash_rom_patch.o)
+ 0x24 (size before relaxing)
+ .literal.esp_rom_spiflash_read_statushigh
+ 0x00000000400782dc 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/spi_flash/libspi_flash.a(spi_flash_rom_patch.o)
+ 0xc (size before relaxing)
+ .literal.esp_rom_spiflash_write_status
+ 0x00000000400782dc 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/spi_flash/libspi_flash.a(spi_flash_rom_patch.o)
+ 0x14 (size before relaxing)
+ .literal.esp_rom_spiflash_unlock
+ 0x00000000400782dc 0x8 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/spi_flash/libspi_flash.a(spi_flash_rom_patch.o)
+ 0x28 (size before relaxing)
+ .literal.esp_rom_spiflash_config_readmode
+ 0x00000000400782e4 0x20 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/spi_flash/libspi_flash.a(spi_flash_rom_patch.o)
+ 0x54 (size before relaxing)
+ .literal.esp_rom_spiflash_erase_sector
+ 0x0000000040078304 0x4 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/spi_flash/libspi_flash.a(spi_flash_rom_patch.o)
+ 0x34 (size before relaxing)
+ .literal.esp_rom_spiflash_write
+ 0x0000000040078308 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/spi_flash/libspi_flash.a(spi_flash_rom_patch.o)
+ 0x24 (size before relaxing)
+ .literal.esp_rom_spiflash_write_encrypted
+ 0x0000000040078308 0xc /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/spi_flash/libspi_flash.a(spi_flash_rom_patch.o)
+ 0x10 (size before relaxing)
+ .literal.esp_rom_spiflash_read
+ 0x0000000040078314 0x24 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/spi_flash/libspi_flash.a(spi_flash_rom_patch.o)
+ 0x70 (size before relaxing)
+ .literal.rtc_wdt_protect_off
+ 0x0000000040078338 0x8 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_wdt.o)
+ .literal.rtc_wdt_protect_on
+ 0x0000000040078340 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_wdt.o)
+ 0x4 (size before relaxing)
+ .literal.rtc_wdt_enable
+ 0x0000000040078340 0xc /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_wdt.o)
+ 0x10 (size before relaxing)
+ .literal.rtc_wdt_set_time
+ 0x000000004007834c 0x18 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_wdt.o)
+ 0x20 (size before relaxing)
+ .literal.rtc_wdt_set_stage
+ 0x0000000040078364 0x10 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_wdt.o)
+ 0x14 (size before relaxing)
+ .literal.rtc_wdt_disable
+ 0x0000000040078374 0x4 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_wdt.o)
+ 0x28 (size before relaxing)
+ .literal.rtc_wdt_set_length_of_reset_signal
+ 0x0000000040078378 0x8 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_wdt.o)
+ 0xc (size before relaxing)
+ .literal.rtc_clk_cpu_freq_to_pll_mhz
+ 0x0000000040078380 0x18 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk.o)
+ 0x30 (size before relaxing)
+ .literal.rtc_clk_bbpll_disable
+ 0x0000000040078398 0x8 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk.o)
+ 0x10 (size before relaxing)
+ .literal.rtc_clk_32k_enable_common$constprop$3
+ 0x00000000400783a0 0x10 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk.o)
+ 0x14 (size before relaxing)
+ .literal.rtc_clk_32k_enable
+ 0x00000000400783b0 0x8 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk.o)
+ 0x10 (size before relaxing)
+ .literal.rtc_clk_8m_enable
+ 0x00000000400783b8 0x8 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk.o)
+ 0x10 (size before relaxing)
+ .literal.rtc_clk_8m_enabled
+ 0x00000000400783c0 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk.o)
+ 0x4 (size before relaxing)
+ .literal.rtc_clk_8md256_enabled
+ 0x00000000400783c0 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk.o)
+ 0x4 (size before relaxing)
+ .literal.rtc_clk_slow_freq_set
+ 0x00000000400783c0 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk.o)
+ 0xc (size before relaxing)
+ .literal.rtc_clk_slow_freq_get
+ 0x00000000400783c0 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk.o)
+ 0x4 (size before relaxing)
+ .literal.rtc_clk_slow_freq_get_hz
+ 0x00000000400783c0 0x8 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk.o)
+ 0x10 (size before relaxing)
+ .literal.rtc_clk_fast_freq_set
+ 0x00000000400783c8 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk.o)
+ 0x10 (size before relaxing)
+ .literal.rtc_clk_fast_freq_get
+ 0x00000000400783c8 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk.o)
+ 0x4 (size before relaxing)
+ .literal.rtc_clk_bbpll_configure
+ 0x00000000400783c8 0x4 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk.o)
+ 0x34 (size before relaxing)
+ .literal.rtc_clk_xtal_freq_get
+ 0x00000000400783cc 0x8 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk.o)
+ .literal.rtc_clk_cpu_freq_mhz_to_config
+ 0x00000000400783d4 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk.o)
+ 0x4 (size before relaxing)
+ .literal.rtc_clk_cpu_freq_get_config
+ 0x00000000400783d4 0x4 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk.o)
+ 0x14 (size before relaxing)
+ .literal.rtc_clk_xtal_freq_update
+ 0x00000000400783d8 0x4 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk.o)
+ 0x8 (size before relaxing)
+ .literal.rtc_clk_apb_freq_update
+ 0x00000000400783dc 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk.o)
+ 0x4 (size before relaxing)
+ .literal.rtc_clk_cpu_freq_to_xtal
+ 0x00000000400783dc 0x8 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk.o)
+ 0x2c (size before relaxing)
+ .literal.rtc_clk_cpu_freq_set_config
+ 0x00000000400783e4 0x8 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk.o)
+ 0x68 (size before relaxing)
+ .literal.rtc_clk_apb_freq_get
+ 0x00000000400783ec 0xc /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk.o)
+ 0x14 (size before relaxing)
+ .iram1.2 0x00000000400783f8 0x9a /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_mperror.o)
+ 0x9e (size before relaxing)
+ 0x00000000400783f8 mperror_set_rgb_color
+ *fill* 0x0000000040078492 0x2
+ .iram1.12 0x0000000040078494 0x4f /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(pycom_bootloader_support.o)
+ 0x57 (size before relaxing)
+ 0x0000000040078494 pycom_ota_write_boot_info
+ *fill* 0x00000000400784e3 0x1
+ .iram1.0 0x00000000400784e4 0x6e /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_flash_config_esp32.o)
+ 0x00000000400784e4 bootloader_flash_cs_timing_config
+ *fill* 0x0000000040078552 0x2
+ .iram1.2 0x0000000040078554 0x1d3 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_flash_config_esp32.o)
+ 0x0000000040078554 bootloader_flash_gpio_config
+ *fill* 0x0000000040078727 0x1
+ .iram1.3 0x0000000040078728 0x92 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_flash_config_esp32.o)
+ 0x0000000040078728 bootloader_flash_dummy_config
+ *fill* 0x00000000400787ba 0x2
+ .iram1.3 0x00000000400787bc 0xe /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(cpu_util.o)
+ 0x00000000400787bc esp_cpu_in_ocd_debug_mode
+ *fill* 0x00000000400787ca 0x2
+ .iram1.1 0x00000000400787cc 0x3f /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_mperror.o)
+ *fill* 0x000000004007880b 0x0
+ *fill* 0x000000004007880b 0x0
+ *fill* 0x000000004007880b 0x0
+ *fill* 0x000000004007880b 0x0
+ *fill* 0x000000004007880b 0x0
+ *fill* 0x000000004007880b 0x0
+ *liblog.a:(.literal .text .literal.* .text.*)
+ *libgcc.a:(.literal .text .literal.* .text.*)
+ *fill* 0x000000004007880b 0x1
+ .text 0x000000004007880c 0x26 /home/element/xtensa-esp32-elf-2020r3/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/no-rtti/libgcc.a(_bswapsi2.o)
+ 0x000000004007880c __bswapsi2
+ *fill* 0x0000000040078832 0x2
+ .text 0x0000000040078834 0x18 /home/element/xtensa-esp32-elf-2020r3/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/no-rtti/libgcc.a(_lshrdi3.o)
+ 0x0000000040078834 __lshrdi3
+ *fill* 0x000000004007884c 0x0
+ .text 0x000000004007884c 0x26e /home/element/xtensa-esp32-elf-2020r3/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/no-rtti/libgcc.a(_udivdi3.o)
+ 0x000000004007884c __udivdi3
+ *libbootloader_support.a:bootloader_clock.*(.literal .text .literal.* .text.*)
+ *fill* 0x0000000040078aba 0x2
+ .text.bootloader_clock_configure
+ 0x0000000040078abc 0x86 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_clock.o)
+ 0x92 (size before relaxing)
+ 0x0000000040078abc bootloader_clock_configure
+ *fill* 0x0000000040078b42 0x0
+ *libbootloader_support.a:bootloader_common.*(.literal .text .literal.* .text.*)
+ *fill* 0x0000000040078b42 0x2
+ .text.bootloader_common_ota_select_crc
+ 0x0000000040078b44 0x14 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_common.o)
+ 0x0000000040078b44 bootloader_common_ota_select_crc
+ .text.bootloader_common_vddsdio_configure
+ 0x0000000040078b58 0x33 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_common.o)
+ 0x3a (size before relaxing)
+ 0x0000000040078b58 bootloader_common_vddsdio_configure
+ *fill* 0x0000000040078b8b 0x1
+ .text.bootloader_common_check_chip_validity
+ 0x0000000040078b8c 0x2a /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_common.o)
+ 0x2e (size before relaxing)
+ 0x0000000040078b8c bootloader_common_check_chip_validity
+ *fill* 0x0000000040078bb6 0x0
+ *fill* 0x0000000040078bb6 0x0
+ *libbootloader_support.a:bootloader_flash.*(.literal .text .literal.* .text.*)
+ *fill* 0x0000000040078bb6 0x2
+ .text.bootloader_mmap
+ 0x0000000040078bb8 0x64 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_flash.o)
+ 0x0000000040078bb8 bootloader_mmap
+ .text.bootloader_munmap
+ 0x0000000040078c1c 0x32 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_flash.o)
+ 0x0000000040078c1c bootloader_munmap
+ *fill* 0x0000000040078c4e 0x2
+ .text.bootloader_flash_read
+ 0x0000000040078c50 0xc4 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_flash.o)
+ 0x0000000040078c50 bootloader_flash_read
+ .text.bootloader_flash_write
+ 0x0000000040078d14 0x5a /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_flash.o)
+ 0x61 (size before relaxing)
+ 0x0000000040078d14 bootloader_flash_write
+ *fill* 0x0000000040078d6e 0x2
+ .text.bootloader_flash_erase_sector
+ 0x0000000040078d70 0x1a /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_flash.o)
+ 0x1e (size before relaxing)
+ 0x0000000040078d70 bootloader_flash_erase_sector
+ *fill* 0x0000000040078d8a 0x2
+ .text.bootloader_mmap_get_free_pages
+ 0x0000000040078d8c 0x7 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_flash.o)
+ 0x0000000040078d8c bootloader_mmap_get_free_pages
+ *fill* 0x0000000040078d93 0x0
+ *fill* 0x0000000040078d93 0x0
+ *fill* 0x0000000040078d93 0x0
+ *libbootloader_support.a:bootloader_random.*(.literal .text .literal.* .text.*)
+ *fill* 0x0000000040078d93 0x1
+ .text.bootloader_fill_random
+ 0x0000000040078d94 0x5b /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_random.o)
+ 0x0000000040078d94 bootloader_fill_random
+ *fill* 0x0000000040078def 0x1
+ .text.bootloader_random_enable
+ 0x0000000040078df0 0x1d5 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_random.o)
+ 0x0000000040078df0 bootloader_random_enable
+ *fill* 0x0000000040078fc5 0x3
+ .text.bootloader_random_disable
+ 0x0000000040078fc8 0x13a /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_random.o)
+ 0x0000000040078fc8 bootloader_random_disable
+ *fill* 0x0000000040079102 0x0
+ *fill* 0x0000000040079102 0x0
+ *fill* 0x0000000040079102 0x0
+ *libbootloader_support.a:bootloader_efuse_esp32.*(.literal .text .literal.* .text.*)
+ *fill* 0x0000000040079102 0x2
+ .text.bootloader_common_get_chip_revision
+ 0x0000000040079104 0x42 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_efuse_esp32.o)
+ 0x0000000040079104 bootloader_common_get_chip_revision
+ *fill* 0x0000000040079146 0x2
+ .text.bootloader_clock_get_rated_freq_mhz
+ 0x0000000040079148 0x22 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_efuse_esp32.o)
+ 0x0000000040079148 bootloader_clock_get_rated_freq_mhz
+ *fill* 0x000000004007916a 0x0
+ *fill* 0x000000004007916a 0x0
+ *libbootloader_support.a:bootloader_utility.*(.literal .text .literal.* .text.*)
+ *fill* 0x000000004007916a 0x2
+ .text.unpack_load_app
+ 0x000000004007916c 0x12c /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_utility.o)
+ .text.set_actual_ota_seq$isra$3$part$4
+ 0x0000000040079298 0x57 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_utility.o)
+ 0x5f (size before relaxing)
+ *fill* 0x00000000400792ef 0x1
+ .text.try_load_partition
+ 0x00000000400792f0 0x20 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_utility.o)
+ .text.bootloader_utility_load_partition_table
+ 0x0000000040079310 0xa3 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_utility.o)
+ 0xa7 (size before relaxing)
+ 0x0000000040079310 bootloader_utility_load_partition_table
+ *fill* 0x00000000400793b3 0x1
+ .text.bootloader_reset
+ 0x00000000400793b4 0x2b /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_utility.o)
+ 0x00000000400793b4 bootloader_reset
+ *fill* 0x00000000400793df 0x1
+ .text.bootloader_utility_load_boot_image
+ 0x00000000400793e0 0xbc /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_utility.o)
+ 0xcc (size before relaxing)
+ 0x00000000400793e0 bootloader_utility_load_boot_image
+ .text.bootloader_debug_buffer
+ 0x000000004007949c 0x1a /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_utility.o)
+ 0x1d (size before relaxing)
+ 0x000000004007949c bootloader_debug_buffer
+ *fill* 0x00000000400794b6 0x2
+ .text.index_to_partition
+ 0x00000000400794b8 0x40 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_utility.o)
+ *fill* 0x00000000400794f8 0x0
+ *fill* 0x00000000400794f8 0x0
+ *fill* 0x00000000400794f8 0x0
+ *libbootloader_support.a:bootloader_sha.*(.literal .text .literal.* .text.*)
+ .text.bootloader_sha256_start
+ 0x00000000400794f8 0x12 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_sha.o)
+ 0x00000000400794f8 bootloader_sha256_start
+ *fill* 0x000000004007950a 0x2
+ .text.bootloader_sha256_data
+ 0x000000004007950c 0xa3 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_sha.o)
+ 0xa7 (size before relaxing)
+ 0x000000004007950c bootloader_sha256_data
+ *fill* 0x00000000400795af 0x1
+ .text.bootloader_sha256_finish
+ 0x00000000400795b0 0xb8 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_sha.o)
+ 0xc0 (size before relaxing)
+ 0x00000000400795b0 bootloader_sha256_finish
+ *fill* 0x0000000040079668 0x0
+ *fill* 0x0000000040079668 0x0
+ *fill* 0x0000000040079668 0x0
+ *libbootloader_support.a:esp_image_format.*(.literal .text .literal.* .text.*)
+ .text.bootloader_util_regions_overlap
+ 0x0000000040079668 0x38 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(esp_image_format.o)
+ 0x3c (size before relaxing)
+ .text.verify_load_addresses
+ 0x00000000400796a0 0x136 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(esp_image_format.o)
+ 0x146 (size before relaxing)
+ *fill* 0x00000000400797d6 0x2
+ .text.should_load
+ 0x00000000400797d8 0x76 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(esp_image_format.o)
+ *fill* 0x000000004007984e 0x2
+ .text.image_load
+ 0x0000000040079850 0x4aa /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(esp_image_format.o)
+ 0x4ea (size before relaxing)
+ *fill* 0x0000000040079cfa 0x2
+ .text.bootloader_load_image
+ 0x0000000040079cfc 0x10 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(esp_image_format.o)
+ 0x14 (size before relaxing)
+ 0x0000000040079cfc bootloader_load_image
+ .text.esp_image_verify
+ 0x0000000040079d0c 0x10 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(esp_image_format.o)
+ 0x14 (size before relaxing)
+ 0x0000000040079d0c esp_image_verify
+ *fill* 0x0000000040079d1c 0x0
+ *fill* 0x0000000040079d1c 0x0
+ *fill* 0x0000000040079d1c 0x0
+ *libbootloader_support.a:flash_encrypt.*(.literal .text .literal.* .text.*)
+ *libbootloader_support.a:flash_partitions.*(.literal .text .literal.* .text.*)
+ .text.esp_partition_table_verify
+ 0x0000000040079d1c 0x93 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(flash_partitions.o)
+ 0x0000000040079d1c esp_partition_table_verify
+ *libbootloader_support.a:secure_boot.*(.literal .text .literal.* .text.*)
+ *libbootloader_support.a:secure_boot_signatures.*(.literal .text .literal.* .text.*)
+ *libmicro-ecc.a:*.*(.literal .text .literal.* .text.*)
+ *libspi_flash.a:*.*(.literal .text .literal.* .text.*)
+ *fill* 0x0000000040079daf 0x1
+ .text.esp_rom_spiflash_read_status
+ 0x0000000040079db0 0x5b /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/spi_flash/libspi_flash.a(spi_flash_rom_patch.o)
+ 0x0000000040079db0 esp_rom_spiflash_read_status
+ *fill* 0x0000000040079e0b 0x1
+ .text.esp_rom_spiflash_wait_idle
+ 0x0000000040079e0c 0x30 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/spi_flash/libspi_flash.a(spi_flash_rom_patch.o)
+ 0x0000000040079e0c esp_rom_spiflash_wait_idle
+ .text.esp_rom_spiflash_enable_write$constprop$6
+ 0x0000000040079e3c 0x3c /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/spi_flash/libspi_flash.a(spi_flash_rom_patch.o)
+ 0x43 (size before relaxing)
+ *fill* 0x0000000040079e78 0x0
+ .text.esp_rom_spiflash_program_page_internal$constprop$4
+ 0x0000000040079e78 0xbb /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/spi_flash/libspi_flash.a(spi_flash_rom_patch.o)
+ 0xbf (size before relaxing)
+ *fill* 0x0000000040079f33 0x1
+ .text.esp_rom_spiflash_read_statushigh
+ 0x0000000040079f34 0x21 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/spi_flash/libspi_flash.a(spi_flash_rom_patch.o)
+ 0x0000000040079f34 esp_rom_spiflash_read_statushigh
+ *fill* 0x0000000040079f55 0x3
+ .text.esp_rom_spiflash_write_status
+ 0x0000000040079f58 0x2f /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/spi_flash/libspi_flash.a(spi_flash_rom_patch.o)
+ 0x33 (size before relaxing)
+ 0x0000000040079f58 esp_rom_spiflash_write_status
+ *fill* 0x0000000040079f87 0x1
+ .text.esp_rom_spiflash_unlock
+ 0x0000000040079f88 0x62 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/spi_flash/libspi_flash.a(spi_flash_rom_patch.o)
+ 0x72 (size before relaxing)
+ 0x0000000040079f88 esp_rom_spiflash_unlock
+ *fill* 0x0000000040079fea 0x2
+ .text.esp_rom_spiflash_config_readmode
+ 0x0000000040079fec 0x28a /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/spi_flash/libspi_flash.a(spi_flash_rom_patch.o)
+ 0x0000000040079fec esp_rom_spiflash_config_readmode
+ *fill* 0x000000004007a276 0x2
+ .text.esp_rom_spiflash_erase_sector
+ 0x000000004007a278 0x81 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/spi_flash/libspi_flash.a(spi_flash_rom_patch.o)
+ 0x88 (size before relaxing)
+ 0x000000004007a278 esp_rom_spiflash_erase_sector
+ *fill* 0x000000004007a2f9 0x3
+ .text.esp_rom_spiflash_write
+ 0x000000004007a2fc 0xab /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/spi_flash/libspi_flash.a(spi_flash_rom_patch.o)
+ 0x000000004007a2fc esp_rom_spiflash_write
+ *fill* 0x000000004007a3a7 0x1
+ .text.esp_rom_spiflash_write_encrypted
+ 0x000000004007a3a8 0x58 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/spi_flash/libspi_flash.a(spi_flash_rom_patch.o)
+ 0x5c (size before relaxing)
+ 0x000000004007a3a8 esp_rom_spiflash_write_encrypted
+ .text.esp_rom_spiflash_read
+ 0x000000004007a400 0x2e0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/spi_flash/libspi_flash.a(spi_flash_rom_patch.o)
+ 0x000000004007a400 esp_rom_spiflash_read
+ *fill* 0x000000004007a6e0 0x0
+ *fill* 0x000000004007a6e0 0x0
+ *fill* 0x000000004007a6e0 0x0
+ *fill* 0x000000004007a6e0 0x0
+ *fill* 0x000000004007a6e0 0x0
+ *fill* 0x000000004007a6e0 0x0
+ *fill* 0x000000004007a6e0 0x0
+ *fill* 0x000000004007a6e0 0x0
+ *fill* 0x000000004007a6e0 0x0
+ *libsoc.a:rtc_wdt.*(.literal .text .literal.* .text.*)
+ .text.rtc_wdt_protect_off
+ 0x000000004007a6e0 0x10 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_wdt.o)
+ 0x000000004007a6e0 rtc_wdt_protect_off
+ .text.rtc_wdt_protect_on
+ 0x000000004007a6f0 0xf /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_wdt.o)
+ 0x000000004007a6f0 rtc_wdt_protect_on
+ *fill* 0x000000004007a6ff 0x1
+ .text.rtc_wdt_enable
+ 0x000000004007a700 0x2b /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_wdt.o)
+ 0x000000004007a700 rtc_wdt_enable
+ *fill* 0x000000004007a72b 0x1
+ .text.rtc_wdt_set_time
+ 0x000000004007a72c 0x4b /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_wdt.o)
+ 0x4f (size before relaxing)
+ 0x000000004007a72c rtc_wdt_set_time
+ *fill* 0x000000004007a777 0x1
+ .text.rtc_wdt_set_stage
+ 0x000000004007a778 0x7b /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_wdt.o)
+ 0x000000004007a778 rtc_wdt_set_stage
+ *fill* 0x000000004007a7f3 0x1
+ .text.rtc_wdt_disable
+ 0x000000004007a7f4 0x83 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_wdt.o)
+ 0x8f (size before relaxing)
+ 0x000000004007a7f4 rtc_wdt_disable
+ *fill* 0x000000004007a877 0x1
+ .text.rtc_wdt_set_length_of_reset_signal
+ 0x000000004007a878 0x49 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_wdt.o)
+ 0x000000004007a878 rtc_wdt_set_length_of_reset_signal
+ *fill* 0x000000004007a8c1 0x0
+ *fill* 0x000000004007a8c1 0x0
+ *fill* 0x000000004007a8c1 0x0
+ *fill* 0x000000004007a8c1 0x0
+ *fill* 0x000000004007a8c1 0x0
+ *libsoc.a:rtc_clk.*(.literal .text .literal.* .text.*)
+ *fill* 0x000000004007a8c1 0x3
+ .text.rtc_clk_cpu_freq_to_pll_mhz
+ 0x000000004007a8c4 0x95 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk.o)
+ 0x99 (size before relaxing)
+ *fill* 0x000000004007a959 0x3
+ .text.rtc_clk_bbpll_disable
+ 0x000000004007a95c 0x3a /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk.o)
+ *fill* 0x000000004007a996 0x2
+ .text.rtc_clk_32k_enable_common$constprop$3
+ 0x000000004007a998 0x72 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk.o)
+ *fill* 0x000000004007aa0a 0x2
+ .text.rtc_clk_32k_enable
+ 0x000000004007aa0c 0x3a /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk.o)
+ 0x000000004007aa0c rtc_clk_32k_enable
+ *fill* 0x000000004007aa46 0x2
+ .text.rtc_clk_8m_enable
+ 0x000000004007aa48 0x7f /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk.o)
+ 0x000000004007aa48 rtc_clk_8m_enable
+ *fill* 0x000000004007aac7 0x1
+ .text.rtc_clk_8m_enabled
+ 0x000000004007aac8 0x15 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk.o)
+ 0x000000004007aac8 rtc_clk_8m_enabled
+ *fill* 0x000000004007aadd 0x3
+ .text.rtc_clk_8md256_enabled
+ 0x000000004007aae0 0x15 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk.o)
+ 0x000000004007aae0 rtc_clk_8md256_enabled
+ *fill* 0x000000004007aaf5 0x3
+ .text.rtc_clk_slow_freq_set
+ 0x000000004007aaf8 0x44 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk.o)
+ 0x000000004007aaf8 rtc_clk_slow_freq_set
+ .text.rtc_clk_slow_freq_get
+ 0x000000004007ab3c 0x10 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk.o)
+ 0x000000004007ab3c rtc_clk_slow_freq_get
+ .text.rtc_clk_slow_freq_get_hz
+ 0x000000004007ab4c 0x26 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk.o)
+ 0x000000004007ab4c rtc_clk_slow_freq_get_hz
+ *fill* 0x000000004007ab72 0x2
+ .text.rtc_clk_fast_freq_set
+ 0x000000004007ab74 0x2c /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk.o)
+ 0x000000004007ab74 rtc_clk_fast_freq_set
+ .text.rtc_clk_fast_freq_get
+ 0x000000004007aba0 0x10 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk.o)
+ 0x000000004007aba0 rtc_clk_fast_freq_get
+ .text.rtc_clk_bbpll_configure
+ 0x000000004007abb0 0x18d /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk.o)
+ 0x000000004007abb0 rtc_clk_bbpll_configure
+ *fill* 0x000000004007ad3d 0x3
+ .text.rtc_clk_xtal_freq_get
+ 0x000000004007ad40 0x26 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk.o)
+ 0x000000004007ad40 rtc_get_xtal
+ 0x000000004007ad40 rtc_clk_xtal_freq_get
+ *fill* 0x000000004007ad66 0x2
+ .text.rtc_clk_cpu_freq_mhz_to_config
+ 0x000000004007ad68 0x57 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk.o)
+ 0x000000004007ad68 rtc_clk_cpu_freq_mhz_to_config
+ *fill* 0x000000004007adbf 0x1
+ .text.rtc_clk_cpu_freq_get_config
+ 0x000000004007adc0 0x70 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk.o)
+ 0x74 (size before relaxing)
+ 0x000000004007adc0 rtc_clk_cpu_freq_get_config
+ .text.rtc_clk_xtal_freq_update
+ 0x000000004007ae30 0x29 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk.o)
+ 0x000000004007ae30 rtc_clk_xtal_freq_update
+ *fill* 0x000000004007ae59 0x3
+ .text.rtc_clk_apb_freq_update
+ 0x000000004007ae5c 0x19 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk.o)
+ 0x000000004007ae5c rtc_clk_apb_freq_update
+ *fill* 0x000000004007ae75 0x3
+ .text.rtc_clk_cpu_freq_to_xtal
+ 0x000000004007ae78 0x72 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk.o)
+ 0x76 (size before relaxing)
+ 0x000000004007ae78 rtc_clk_cpu_freq_to_xtal
+ *fill* 0x000000004007aeea 0x2
+ .text.rtc_clk_cpu_freq_set_config
+ 0x000000004007aeec 0x115 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk.o)
+ 0x12d (size before relaxing)
+ 0x000000004007aeec rtc_clk_cpu_freq_set_config
+ *fill* 0x000000004007b001 0x3
+ .text.rtc_clk_apb_freq_get
+ 0x000000004007b004 0x2a /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk.o)
+ 0x000000004007b004 rtc_clk_apb_freq_get
+ *fill* 0x000000004007b02e 0x0
+ *fill* 0x000000004007b02e 0x0
+ *fill* 0x000000004007b02e 0x0
+ *fill* 0x000000004007b02e 0x0
+ *fill* 0x000000004007b02e 0x0
+ *fill* 0x000000004007b02e 0x0
+ *fill* 0x000000004007b02e 0x0
+ *fill* 0x000000004007b02e 0x0
+ *fill* 0x000000004007b02e 0x0
+ *fill* 0x000000004007b02e 0x0
+ *fill* 0x000000004007b02e 0x0
+ *fill* 0x000000004007b02e 0x0
+ *fill* 0x000000004007b02e 0x0
+ *fill* 0x000000004007b02e 0x0
+ *fill* 0x000000004007b02e 0x0
+ *fill* 0x000000004007b02e 0x0
+ *libefuse.a:*.*(.literal .text .literal.* .text.*)
+ *(.fini.literal)
+ *(.fini)
+ *(.gnu.version)
+ 0x000000004007b02e _loader_text_end = ABSOLUTE (.)
+
+.iram.text 0x0000000040080400 0x147e
+ 0x0000000040080400 . = ALIGN (0x10)
+ *(.entry.text)
+ *(.init.literal)
+ *(.init)
+ 0x0000000040080400 _stext = .
+ 0x0000000040080400 _text_start = ABSOLUTE (.)
+ *(.literal .text .literal.* .text.* .stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
+ .literal.call_start_cpu0
+ 0x0000000040080400 0x8 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(bootloader_start.o)
+ 0x1c (size before relaxing)
+ .literal.pycom_bootloader_common_ota_select_valid
+ 0x0000000040080408 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_bootloader.o)
+ 0x4 (size before relaxing)
+ .literal.pycom_bootloader_utility_get_selected_boot_partition
+ 0x0000000040080408 0x8 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_bootloader.o)
+ 0x2c (size before relaxing)
+ .literal.wait_while_blinking
+ 0x0000000040080410 0x10 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_bootmgr.o)
+ 0x1c (size before relaxing)
+ .literal.wait_for_safe_boot
+ 0x0000000040080420 0xc /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_bootmgr.o)
+ 0x38 (size before relaxing)
+ .literal.mperror_fatal_error
+ 0x000000004008042c 0x4 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_mperror.o)
+ 0x8 (size before relaxing)
+ .literal.mperror_heartbeat_switch_off
+ 0x0000000040080430 0x4 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_mperror.o)
+ 0x8 (size before relaxing)
+ .literal.mperror_init0
+ 0x0000000040080434 0x4 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_mperror.o)
+ 0x18 (size before relaxing)
+ .literal.gpio_pullup_en
+ 0x0000000040080438 0x4 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_gpio.o)
+ .literal.gpio_pullup_dis
+ 0x000000004008043c 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_gpio.o)
+ 0x4 (size before relaxing)
+ .literal.gpio_pulldown_en
+ 0x000000004008043c 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_gpio.o)
+ 0x4 (size before relaxing)
+ .literal.gpio_pulldown_dis
+ 0x000000004008043c 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_gpio.o)
+ 0x4 (size before relaxing)
+ .literal.gpio_set_intr_type
+ 0x000000004008043c 0x4 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_gpio.o)
+ 0x8 (size before relaxing)
+ .literal.gpio_intr_enable
+ 0x0000000040080440 0xc /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_gpio.o)
+ 0x14 (size before relaxing)
+ .literal.gpio_intr_disable
+ 0x000000004008044c 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_gpio.o)
+ 0xc (size before relaxing)
+ .literal.gpio_get_level
+ 0x000000004008044c 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_gpio.o)
+ 0x4 (size before relaxing)
+ .literal.gpio_config
+ 0x000000004008044c 0x4 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_gpio.o)
+ 0x30 (size before relaxing)
+ .literal.pycom_read_otadata
+ 0x0000000040080450 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(pycom_bootloader_support.o)
+ 0xc (size before relaxing)
+ .literal.pycom_bootloader_common_ota_select_crc
+ 0x0000000040080450 0x4 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(pycom_bootloader_support.o)
+ .literal.unlikely.abort
+ 0x0000000040080454 0x8 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_esp32.o)
+ 0x10 (size before relaxing)
+ .literal.bootloader_init
+ 0x000000004008045c 0xd0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_esp32.o)
+ 0x138 (size before relaxing)
+ .literal.execute_flash_command
+ 0x000000004008052c 0x38 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(flash_qio_mode.o)
+ 0x3c (size before relaxing)
+ .literal.write_status_8b_wrsr2
+ 0x0000000040080564 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(flash_qio_mode.o)
+ 0x4 (size before relaxing)
+ .literal.read_status_8b_rdsr2
+ 0x0000000040080564 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(flash_qio_mode.o)
+ 0x4 (size before relaxing)
+ .literal.write_status_16b_wrsr
+ 0x0000000040080564 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(flash_qio_mode.o)
+ 0x4 (size before relaxing)
+ .literal.read_status_16b_rdsr_rdsr2
+ 0x0000000040080564 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(flash_qio_mode.o)
+ 0x8 (size before relaxing)
+ .literal.write_status_8b_wrsr
+ 0x0000000040080564 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(flash_qio_mode.o)
+ 0x4 (size before relaxing)
+ .literal.read_status_8b_rdsr
+ 0x0000000040080564 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(flash_qio_mode.o)
+ 0x4 (size before relaxing)
+ .literal.write_status_8b_xmc25qu64a
+ 0x0000000040080564 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(flash_qio_mode.o)
+ 0x18 (size before relaxing)
+ .literal.read_status_8b_xmc25qu64a
+ 0x0000000040080564 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(flash_qio_mode.o)
+ 0x14 (size before relaxing)
+ .literal.bootloader_read_flash_id
+ 0x0000000040080564 0x8 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(flash_qio_mode.o)
+ 0xc (size before relaxing)
+ .literal.bootloader_enable_qio_mode
+ 0x000000004008056c 0x10 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(flash_qio_mode.o)
+ 0x28 (size before relaxing)
+ .literal.bootloader_clear_bss_section
+ 0x000000004008057c 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_init.o)
+ 0xc (size before relaxing)
+ .literal.bootloader_read_bootloader_header
+ 0x000000004008057c 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_init.o)
+ 0xc (size before relaxing)
+ .literal.bootloader_check_bootloader_validity
+ 0x000000004008057c 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_init.o)
+ 0xc (size before relaxing)
+ .literal.bootloader_config_wdt
+ 0x000000004008057c 0x10 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_init.o)
+ 0x30 (size before relaxing)
+ .literal.bootloader_enable_random
+ 0x000000004008058c 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_init.o)
+ 0x4 (size before relaxing)
+ .literal.bootloader_flash_update_id
+ 0x000000004008058c 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_flash_config_esp32.o)
+ 0x8 (size before relaxing)
+ .literal.rtc_vddsdio_get_config
+ 0x000000004008058c 0xc /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_init.o)
+ 0x10 (size before relaxing)
+ .literal.rtc_vddsdio_set_config
+ 0x0000000040080598 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_init.o)
+ 0x8 (size before relaxing)
+ .literal.rtc_clk_xtal_freq_estimate
+ 0x0000000040080598 0x10 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk_init.o)
+ 0x24 (size before relaxing)
+ .literal.rtc_clk_init
+ 0x00000000400805a8 0x3c /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk_init.o)
+ 0x84 (size before relaxing)
+ .literal.rtc_clk_cal_internal
+ 0x00000000400805e4 0x38 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_time.o)
+ 0x58 (size before relaxing)
+ .literal.rtc_clk_cal_ratio
+ 0x000000004008061c 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_time.o)
+ 0x8 (size before relaxing)
+ .literal.rtc_clk_wait_for_slow_cycle
+ 0x000000004008061c 0x8 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_time.o)
+ 0x1c (size before relaxing)
+ .text.call_start_cpu0
+ 0x0000000040080624 0x44 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(bootloader_start.o)
+ 0x50 (size before relaxing)
+ 0x0000000040080624 call_start_cpu0
+ .text.pycom_bootloader_common_ota_select_valid
+ 0x0000000040080668 0x1d /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_bootloader.o)
+ 0x21 (size before relaxing)
+ 0x0000000040080668 pycom_bootloader_common_ota_select_valid
+ *fill* 0x0000000040080685 0x3
+ .text.pycom_bootloader_utility_get_selected_boot_partition
+ 0x0000000040080688 0xd2 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_bootloader.o)
+ 0xea (size before relaxing)
+ 0x0000000040080688 pycom_bootloader_utility_get_selected_boot_partition
+ *fill* 0x000000004008075a 0x2
+ .text.wait_while_blinking
+ 0x000000004008075c 0x57 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_bootmgr.o)
+ 0x5e (size before relaxing)
+ *fill* 0x00000000400807b3 0x1
+ .text.wait_for_safe_boot
+ 0x00000000400807b4 0x84 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_bootmgr.o)
+ 0x98 (size before relaxing)
+ 0x00000000400807b4 wait_for_safe_boot
+ .text.mperror_fatal_error
+ 0x0000000040080838 0xc /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_mperror.o)
+ 0xf (size before relaxing)
+ 0x0000000040080838 mperror_fatal_error
+ *fill* 0x0000000040080844 0x0
+ .text.mperror_heartbeat_switch_off
+ 0x0000000040080844 0x16 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_mperror.o)
+ 0x1a (size before relaxing)
+ 0x0000000040080844 mperror_heartbeat_switch_off
+ *fill* 0x000000004008085a 0x2
+ .text.mperror_init0
+ 0x000000004008085c 0x2d /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_mperror.o)
+ 0x31 (size before relaxing)
+ 0x000000004008085c mperror_init0
+ *fill* 0x0000000040080889 0x3
+ .text.gpio_pullup_en
+ 0x000000004008088c 0x2e /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_gpio.o)
+ 0x000000004008088c gpio_pullup_en
+ *fill* 0x00000000400808ba 0x2
+ .text.gpio_pullup_dis
+ 0x00000000400808bc 0x2e /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_gpio.o)
+ 0x00000000400808bc gpio_pullup_dis
+ *fill* 0x00000000400808ea 0x2
+ .text.gpio_pulldown_en
+ 0x00000000400808ec 0x2e /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_gpio.o)
+ 0x00000000400808ec gpio_pulldown_en
+ *fill* 0x000000004008091a 0x2
+ .text.gpio_pulldown_dis
+ 0x000000004008091c 0x2e /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_gpio.o)
+ 0x000000004008091c gpio_pulldown_dis
+ *fill* 0x000000004008094a 0x2
+ .text.gpio_set_intr_type
+ 0x000000004008094c 0x56 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_gpio.o)
+ 0x000000004008094c gpio_set_intr_type
+ *fill* 0x00000000400809a2 0x2
+ .text.gpio_intr_enable
+ 0x00000000400809a4 0x5c /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_gpio.o)
+ 0x00000000400809a4 gpio_intr_enable
+ .text.gpio_intr_disable
+ 0x0000000040080a00 0x38 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_gpio.o)
+ 0x0000000040080a00 gpio_intr_disable
+ .text.gpio_get_level
+ 0x0000000040080a38 0x2e /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_gpio.o)
+ 0x0000000040080a38 gpio_get_level
+ *fill* 0x0000000040080a66 0x2
+ .text.gpio_config
+ 0x0000000040080a68 0x18b /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_gpio.o)
+ 0x19f (size before relaxing)
+ 0x0000000040080a68 gpio_config
+ *fill* 0x0000000040080bf3 0x1
+ .text.pycom_read_otadata
+ 0x0000000040080bf4 0x39 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(pycom_bootloader_support.o)
+ 0x3d (size before relaxing)
+ 0x0000000040080bf4 pycom_read_otadata
+ *fill* 0x0000000040080c2d 0x3
+ .text.pycom_bootloader_common_ota_select_crc
+ 0x0000000040080c30 0x14 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(pycom_bootloader_support.o)
+ 0x0000000040080c30 pycom_bootloader_common_ota_select_crc
+ .text.unlikely.abort
+ 0x0000000040080c44 0x2c /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_esp32.o)
+ 0x2f (size before relaxing)
+ 0x0000000040080c44 abort
+ *fill* 0x0000000040080c70 0x0
+ .text.bootloader_init
+ 0x0000000040080c70 0x2d8 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_esp32.o)
+ 0x308 (size before relaxing)
+ 0x0000000040080c70 bootloader_init
+ .text.execute_flash_command
+ 0x0000000040080f48 0x167 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(flash_qio_mode.o)
+ *fill* 0x00000000400810af 0x1
+ .text.write_status_8b_wrsr2
+ 0x00000000400810b0 0x13 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(flash_qio_mode.o)
+ *fill* 0x00000000400810c3 0x1
+ .text.read_status_8b_rdsr2
+ 0x00000000400810c4 0x15 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(flash_qio_mode.o)
+ *fill* 0x00000000400810d9 0x3
+ .text.write_status_16b_wrsr
+ 0x00000000400810dc 0x13 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(flash_qio_mode.o)
+ *fill* 0x00000000400810ef 0x1
+ .text.read_status_16b_rdsr_rdsr2
+ 0x00000000400810f0 0x25 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(flash_qio_mode.o)
+ 0x29 (size before relaxing)
+ *fill* 0x0000000040081115 0x3
+ .text.write_status_8b_wrsr
+ 0x0000000040081118 0x13 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(flash_qio_mode.o)
+ *fill* 0x000000004008112b 0x1
+ .text.read_status_8b_rdsr
+ 0x000000004008112c 0x15 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(flash_qio_mode.o)
+ *fill* 0x0000000040081141 0x3
+ .text.write_status_8b_xmc25qu64a
+ 0x0000000040081144 0x36 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(flash_qio_mode.o)
+ 0x42 (size before relaxing)
+ *fill* 0x000000004008117a 0x2
+ .text.read_status_8b_xmc25qu64a
+ 0x000000004008117c 0x2e /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(flash_qio_mode.o)
+ 0x3a (size before relaxing)
+ *fill* 0x00000000400811aa 0x2
+ .text.bootloader_read_flash_id
+ 0x00000000400811ac 0x2a /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(flash_qio_mode.o)
+ 0x2e (size before relaxing)
+ 0x00000000400811ac bootloader_read_flash_id
+ *fill* 0x00000000400811d6 0x2
+ .text.bootloader_enable_qio_mode
+ 0x00000000400811d8 0xfe /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(flash_qio_mode.o)
+ 0x10a (size before relaxing)
+ 0x00000000400811d8 bootloader_enable_qio_mode
+ *fill* 0x00000000400812d6 0x2
+ .text.bootloader_clear_bss_section
+ 0x00000000400812d8 0x16 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_init.o)
+ 0x00000000400812d8 bootloader_clear_bss_section
+ *fill* 0x00000000400812ee 0x2
+ .text.bootloader_read_bootloader_header
+ 0x00000000400812f0 0x1c /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_init.o)
+ 0x20 (size before relaxing)
+ 0x00000000400812f0 bootloader_read_bootloader_header
+ .text.bootloader_check_bootloader_validity
+ 0x000000004008130c 0x1c /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_init.o)
+ 0x20 (size before relaxing)
+ 0x000000004008130c bootloader_check_bootloader_validity
+ .text.bootloader_config_wdt
+ 0x0000000040081328 0x4c /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_init.o)
+ 0x68 (size before relaxing)
+ 0x0000000040081328 bootloader_config_wdt
+ .text.bootloader_enable_random
+ 0x0000000040081374 0x8 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_init.o)
+ 0xb (size before relaxing)
+ 0x0000000040081374 bootloader_enable_random
+ *fill* 0x000000004008137c 0x0
+ .text.bootloader_flash_update_id
+ 0x000000004008137c 0xd /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_flash_config_esp32.o)
+ 0x10 (size before relaxing)
+ 0x000000004008137c bootloader_flash_update_id
+ *fill* 0x0000000040081389 0x3
+ .text.rtc_vddsdio_get_config
+ 0x000000004008138c 0xa0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_init.o)
+ 0x000000004008138c rtc_vddsdio_get_config
+ .text.rtc_vddsdio_set_config
+ 0x000000004008142c 0x46 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_init.o)
+ 0x000000004008142c rtc_vddsdio_set_config
+ *fill* 0x0000000040081472 0x2
+ .text.rtc_clk_xtal_freq_estimate
+ 0x0000000040081474 0x60 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk_init.o)
+ 0x6c (size before relaxing)
+ .text.rtc_clk_init
+ 0x00000000400814d4 0x192 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk_init.o)
+ 0x1b2 (size before relaxing)
+ 0x00000000400814d4 rtc_clk_init
+ *fill* 0x0000000040081666 0x2
+ .text.rtc_clk_cal_internal
+ 0x0000000040081668 0x180 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_time.o)
+ 0x184 (size before relaxing)
+ .text.rtc_clk_cal_ratio
+ 0x00000000400817e8 0x20 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_time.o)
+ 0x24 (size before relaxing)
+ 0x00000000400817e8 rtc_clk_cal_ratio
+ .text.rtc_clk_wait_for_slow_cycle
+ 0x0000000040081808 0x68 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_time.o)
+ 0x0000000040081808 rtc_clk_wait_for_slow_cycle
+ *fill* 0x0000000040081870 0x0
+ *fill* 0x0000000040081870 0x0
+ *fill* 0x0000000040081870 0x0
+ *fill* 0x0000000040081870 0x0
+ *fill* 0x0000000040081870 0x0
+ *fill* 0x0000000040081870 0x0
+ *fill* 0x0000000040081870 0x0
+ *fill* 0x0000000040081870 0x0
+ *fill* 0x0000000040081870 0x0
+ *fill* 0x0000000040081870 0x0
+ *fill* 0x0000000040081870 0x0
+ *fill* 0x0000000040081870 0x0
+ *fill* 0x0000000040081870 0x0
+ *fill* 0x0000000040081870 0x0
+ *fill* 0x0000000040081870 0x0
+ *fill* 0x0000000040081870 0x0
+ *fill* 0x0000000040081870 0x0
+ *fill* 0x0000000040081870 0x0
+ *fill* 0x0000000040081870 0x0
+ *fill* 0x0000000040081870 0x0
+ *fill* 0x0000000040081870 0x0
+ *fill* 0x0000000040081870 0x0
+ *fill* 0x0000000040081870 0x0
+ *fill* 0x0000000040081870 0x0
+ *fill* 0x0000000040081870 0x0
+ *fill* 0x0000000040081870 0x0
+ *fill* 0x0000000040081870 0x0
+ *fill* 0x0000000040081870 0x0
+ .text.bootloader_print_banner
+ 0x0000000040081870 0x5 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_init.o)
+ 0x0000000040081870 bootloader_print_banner
+ *fill* 0x0000000040081875 0x3
+ .text.__assert_func
+ 0x0000000040081878 0x6 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_init.o)
+ 0x0000000040081878 __assert_func
+ *fill* 0x000000004008187e 0x0
+ *fill* 0x000000004008187e 0x0
+ *fill* 0x000000004008187e 0x0
+ *(.iram .iram.*)
+ *(.fini.literal)
+ *(.fini)
+ *(.gnu.version)
+ 0x000000004008187e _text_end = ABSOLUTE (.)
+ 0x000000004008187e _etext = .
+
+.dram0.bss 0x000000003fff0000 0x40
+ 0x000000003fff0000 . = ALIGN (0x8)
+ 0x000000003fff0000 _dram_start = ABSOLUTE (.)
+ 0x000000003fff0000 _bss_start = ABSOLUTE (.)
+ *(.dynsbss)
+ *(.sbss)
+ *(.sbss.*)
+ *(.gnu.linkonce.sb.*)
+ *(.scommon)
+ *(.sbss2)
+ *(.sbss2.*)
+ *(.gnu.linkonce.sb2.*)
+ *(.dynbss)
+ *(.bss)
+ *(.bss.*)
+ .bss.mperror_heart_beat
+ 0x000000003fff0000 0xc /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_mperror.o)
+ 0x000000003fff0000 mperror_heart_beat
+ .bss.ota_has_initial_contents
+ 0x000000003fff000c 0x1 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_utility.o)
+ *fill* 0x000000003fff000d 0x3
+ .bss.ram_obfs_value
+ 0x000000003fff0010 0x8 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(esp_image_format.o)
+ .bss.words_hashed
+ 0x000000003fff0018 0x4 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_sha.o)
+ .bss.mapped 0x000000003fff001c 0x1 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_flash.o)
+ *fill* 0x000000003fff001d 0x3
+ .bss.s_cur_pll_freq
+ 0x000000003fff0020 0x4 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk.o)
+ *(.gnu.linkonce.b.*)
+ *(COMMON)
+ COMMON 0x000000003fff0024 0x18 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_init.o)
+ 0x000000003fff0024 bootloader_image_hdr
+ 0x000000003fff0040 . = ALIGN (0x8)
+ *fill* 0x000000003fff003c 0x4
+ 0x000000003fff0040 _bss_end = ABSOLUTE (.)
+
+.dram0.data 0x000000003fff0040 0x8
+ 0x000000003fff0040 _data_start = ABSOLUTE (.)
+ *(.data)
+ *(.data.*)
+ .data.toggle$5291
+ 0x000000003fff0040 0x1 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_bootmgr.o)
+ *fill* 0x000000003fff0041 0x3
+ .data.current_read_mapping
+ 0x000000003fff0044 0x4 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_flash.o)
+ *(.gnu.linkonce.d.*)
+ *(.data1)
+ *(.sdata)
+ *(.sdata.*)
+ *(.gnu.linkonce.s.*)
+ *(.sdata2)
+ *(.sdata2.*)
+ *(.gnu.linkonce.s2.*)
+ *(.jcr)
+ 0x000000003fff0048 _data_end = ABSOLUTE (.)
+
+.dram0.rodata 0x000000003fff0048 0x6dc
+ 0x000000003fff0048 _rodata_start = ABSOLUTE (.)
+ *(.rodata)
+ .rodata 0x000000003fff0048 0x18 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_bootmgr.o)
+ .rodata 0x000000003fff0060 0x18 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_mperror.o)
+ .rodata 0x000000003fff0078 0x14 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_esp32.o)
+ .rodata 0x000000003fff008c 0x8 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_clock.o)
+ *(.rodata.*)
+ .rodata.pycom_bootloader_utility_get_selected_boot_partition.str1.1
+ 0x000000003fff0094 0x5c /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_bootloader.o)
+ .rodata.GPIO_PIN_MUX_REG
+ 0x000000003fff00f0 0xa0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_gpio.o)
+ 0x000000003fff00f0 GPIO_PIN_MUX_REG
+ .rodata.bootloader_debug_buffer.str1.1
+ 0x000000003fff0190 0x6d /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_utility.o)
+ .rodata.__func__$7281
+ 0x000000003fff01fd 0x18 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_utility.o)
+ .rodata.bootloader_util_regions_overlap.str1.1
+ 0x000000003fff0215 0x78 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(esp_image_format.o)
+ .rodata.verify_load_addresses.str1.1
+ 0x000000003fff028d 0x72 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(esp_image_format.o)
+ .rodata.image_load.str1.1
+ 0x000000003fff02ff 0x1e /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(esp_image_format.o)
+ .rodata.__func__$4343
+ 0x000000003fff031d 0x20 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(esp_image_format.o)
+ .rodata.__func__$4659
+ 0x000000003fff033d 0x16 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(esp_image_format.o)
+ .rodata.bootloader_fill_random.str1.1
+ 0x000000003fff0353 0x6d /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_random.o)
+ .rodata.__func__$5186
+ 0x000000003fff03c0 0x17 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_random.o)
+ .rodata.bootloader_sha256_data.str1.1
+ 0x000000003fff03d7 0x82 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_sha.o)
+ .rodata.bootloader_sha256_finish.str1.1
+ 0x000000003fff0459 0x45 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_sha.o)
+ .rodata.padding$4028
+ 0x000000003fff049e 0x40 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_sha.o)
+ .rodata.__func__$4024
+ 0x000000003fff04de 0x19 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_sha.o)
+ .rodata.__func__$4004
+ 0x000000003fff04f7 0x17 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_sha.o)
+ .rodata.abort.str1.1
+ 0x000000003fff050e 0x22 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_esp32.o)
+ .rodata.bootloader_init.str1.1
+ 0x000000003fff0530 0xba /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_esp32.o)
+ .rodata.CSWTCH$26
+ 0x000000003fff05ea 0x5 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_esp32.o)
+ .rodata.__func__$7198
+ 0x000000003fff05ef 0x10 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_esp32.o)
+ .rodata.CSWTCH$0
+ 0x000000003fff05ff 0x7 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_efuse_esp32.o)
+ .rodata.CSWTCH$26
+ 0x000000003fff0606 0x6 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_flash.o)
+ .rodata.str1.1
+ 0x000000003fff060c 0x1f /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(flash_qio_mode.o)
+ .rodata.chip_data
+ 0x000000003fff062b 0x6c /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(flash_qio_mode.o)
+ *fill* 0x000000003fff0697 0x1
+ .rodata.CSWTCH$29
+ 0x000000003fff0698 0x18 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/spi_flash/libspi_flash.a(spi_flash_rom_patch.o)
+ .rodata.rtc_clk_cal_internal.str1.1
+ 0x000000003fff06b0 0x5f /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_time.o)
+ .rodata.__func__$3908
+ 0x000000003fff070f 0x15 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_time.o)
+ *(.gnu.linkonce.r.*)
+ *(.rodata1)
+ 0x000000003fff0724 __XT_EXCEPTION_TABLE_ = ABSOLUTE (.)
+ *(.xt_except_table)
+ *(.gcc_except_table)
+ *(.gnu.linkonce.e.*)
+ *(.gnu.version_r)
+ *(.eh_frame)
+ 0x000000003fff0724 . = ((. + 0x3) & 0xfffffffffffffffc)
+ 0x000000003fff0724 __init_array_start = ABSOLUTE (.)
+ *crtbegin.*(.ctors)
+ *(EXCLUDE_FILE(*crtend.*) .ctors)
+ *(SORT_BY_NAME(.ctors.*))
+ *(.ctors)
+ 0x000000003fff0724 __init_array_end = ABSOLUTE (.)
+ *crtbegin.*(.dtors)
+ *(EXCLUDE_FILE(*crtend.*) .dtors)
+ *(SORT_BY_NAME(.dtors.*))
+ *(.dtors)
+ 0x000000003fff0724 __XT_EXCEPTION_DESCS_ = ABSOLUTE (.)
+ *(.xt_except_desc)
+ *(.gnu.linkonce.h.*)
+ 0x000000003fff0724 __XT_EXCEPTION_DESCS_END__ = ABSOLUTE (.)
+ *(.xt_except_desc_end)
+ *(.dynamic)
+ *(.gnu.version_d)
+ 0x000000003fff0724 _rodata_end = ABSOLUTE (.)
+ 0x000000003fff0724 _lit4_start = ABSOLUTE (.)
+ *(*.lit4)
+ *(.lit4.*)
+ *(.gnu.linkonce.lit4.*)
+ 0x000000003fff0724 _lit4_end = ABSOLUTE (.)
+ 0x000000003fff0724 . = ALIGN (0x4)
+ 0x000000003fff0724 _dram_end = ABSOLUTE (.)
+ 0x0000000040008550 PROVIDE (ets_update_cpu_frequency = 0x40008550)
+ 0x000000004005db1c PROVIDE (MD5Final = 0x4005db1c)
+ 0x000000004005da7c PROVIDE (MD5Init = 0x4005da7c)
+ 0x000000004005da9c PROVIDE (MD5Update = 0x4005da9c)
+ 0x000000004000c050 xthal_get_ccount = 0x4000c050
+ 0x000000004000c078 xthal_get_ccompare = 0x4000c078
+ 0x000000004000c058 xthal_set_ccompare = 0x4000c058
+ [!provide] PROVIDE (Add2SelfBigHex256 = 0x40015b7c)
+ [!provide] PROVIDE (AddBigHex256 = 0x40015b28)
+ [!provide] PROVIDE (AddBigHexModP256 = 0x40015c98)
+ [!provide] PROVIDE (AddP256 = 0x40015c74)
+ [!provide] PROVIDE (AddPdiv2_256 = 0x40015ce0)
+ [!provide] PROVIDE (app_gpio_arg = 0x3ffe003c)
+ [!provide] PROVIDE (app_gpio_handler = 0x3ffe0040)
+ [!provide] PROVIDE (BasePoint_x_256 = 0x3ff97488)
+ [!provide] PROVIDE (BasePoint_y_256 = 0x3ff97468)
+ [!provide] PROVIDE (bigHexInversion256 = 0x400168f0)
+ [!provide] PROVIDE (bigHexP256 = 0x3ff973bc)
+ [!provide] PROVIDE (btdm_r_ble_bt_handler_tab_p_get = 0x40019b0c)
+ [!provide] PROVIDE (btdm_r_btdm_option_data_p_get = 0x40010004)
+ [!provide] PROVIDE (btdm_r_btdm_rom_version_get = 0x40010078)
+ [!provide] PROVIDE (btdm_r_data_init = 0x4001002c)
+ [!provide] PROVIDE (btdm_r_import_rf_phy_func_p_get = 0x40054298)
+ [!provide] PROVIDE (btdm_r_ip_func_p_get = 0x40019af0)
+ [!provide] PROVIDE (btdm_r_ip_func_p_set = 0x40019afc)
+ [!provide] PROVIDE (btdm_r_modules_func_p_get = 0x4005427c)
+ [!provide] PROVIDE (btdm_r_modules_func_p_set = 0x40054270)
+ [!provide] PROVIDE (btdm_r_plf_func_p_set = 0x40054288)
+ [!provide] PROVIDE (bt_util_buf_env = 0x3ffb8bd4)
+ 0x00000000400095e0 PROVIDE (cache_flash_mmu_set_rom = 0x400095e0)
+ 0x0000000040009a14 PROVIDE (Cache_Flush_rom = 0x40009a14)
+ 0x0000000040009ab8 PROVIDE (Cache_Read_Disable_rom = 0x40009ab8)
+ 0x0000000040009a84 PROVIDE (Cache_Read_Enable_rom = 0x40009a84)
+ [!provide] PROVIDE (Cache_Read_Init_rom = 0x40009950)
+ [!provide] PROVIDE (cache_sram_mmu_set_rom = 0x400097f4)
+ [!provide] PROVIDE (calc_rtc_memory_crc = 0x40008170)
+ [!provide] PROVIDE (__clear_cache = 0x40063860)
+ [!provide] PROVIDE (co_default_bdaddr = 0x3ffae704)
+ [!provide] PROVIDE (co_null_bdaddr = 0x3ffb80e0)
+ [!provide] PROVIDE (co_sca2ppm = 0x3ff971e8)
+ [!provide] PROVIDE (crc16_be = 0x4005d09c)
+ [!provide] PROVIDE (crc16_le = 0x4005d05c)
+ [!provide] PROVIDE (crc32_be = 0x4005d024)
+ 0x000000004005cfec PROVIDE (crc32_le = 0x4005cfec)
+ [!provide] PROVIDE (crc8_be = 0x4005d114)
+ [!provide] PROVIDE (crc8_le = 0x4005d0e0)
+ [!provide] PROVIDE (_data_end_rom = 0x4000d5c8)
+ [!provide] PROVIDE (_data_end_btdm_rom = 0x4000d4f8)
+ [!provide] PROVIDE (_data_start_rom = 0x4000d4f8)
+ [!provide] PROVIDE (_data_start_btdm_rom = 0x4000d4f4)
+ [!provide] PROVIDE (_data_start_btdm = 0x3ffae6e0)
+ [!provide] PROVIDE (_data_end_btdm = 0x3ffaff10)
+ [!provide] PROVIDE (_bss_start_btdm = 0x3ffb8000)
+ [!provide] PROVIDE (_bss_end_btdm = 0x3ffbff70)
+ [!provide] PROVIDE (dbg_default_handler = 0x3ff97218)
+ [!provide] PROVIDE (dbg_default_state = 0x3ff97220)
+ [!provide] PROVIDE (dbg_state = 0x3ffb8d5d)
+ [!provide] PROVIDE (DebugE256PublicKey_x = 0x3ff97428)
+ [!provide] PROVIDE (DebugE256PublicKey_y = 0x3ff97408)
+ [!provide] PROVIDE (DebugE256SecretKey = 0x3ff973e8)
+ [!provide] PROVIDE (debug_timer = 0x3ffe042c)
+ [!provide] PROVIDE (debug_timerfn = 0x3ffe0430)
+ [!provide] PROVIDE (dh_group14_generator = 0x3ff9ac60)
+ [!provide] PROVIDE (dh_group14_prime = 0x3ff9ab60)
+ [!provide] PROVIDE (dh_group15_generator = 0x3ff9ab5f)
+ [!provide] PROVIDE (dh_group15_prime = 0x3ff9a9df)
+ [!provide] PROVIDE (dh_group16_generator = 0x3ff9a9de)
+ [!provide] PROVIDE (dh_group16_prime = 0x3ff9a7de)
+ [!provide] PROVIDE (dh_group17_generator = 0x3ff9a7dd)
+ [!provide] PROVIDE (dh_group17_prime = 0x3ff9a4dd)
+ [!provide] PROVIDE (dh_group18_generator = 0x3ff9a4dc)
+ [!provide] PROVIDE (dh_group18_prime = 0x3ff9a0dc)
+ [!provide] PROVIDE (dh_group1_generator = 0x3ff9ae03)
+ [!provide] PROVIDE (dh_group1_prime = 0x3ff9ada3)
+ [!provide] PROVIDE (dh_group2_generator = 0x3ff9ada2)
+ [!provide] PROVIDE (dh_group2_prime = 0x3ff9ad22)
+ [!provide] PROVIDE (dh_group5_generator = 0x3ff9ad21)
+ [!provide] PROVIDE (dh_group5_prime = 0x3ff9ac61)
+ 0x000000003ffae290 PROVIDE (g_rom_spiflash_dummy_len_plus = 0x3ffae290)
+ [!provide] PROVIDE (ecc_env = 0x3ffb8d60)
+ [!provide] PROVIDE (ecc_Jacobian_InfinityPoint256 = 0x3ff972e8)
+ [!provide] PROVIDE (em_buf_env = 0x3ffb8d74)
+ [!provide] PROVIDE (esp_crc8 = 0x4005d144)
+ [!provide] PROVIDE (_etext = 0x4000d66c)
+ [!provide] PROVIDE (ets_readySet_ = 0x3ffe01f0)
+ [!provide] PROVIDE (ets_startup_callback = 0x3ffe0404)
+ [!provide] PROVIDE (rwip_coex_cfg = 0x3ff9914c)
+ [!provide] PROVIDE (rwip_priority = 0x3ff99159)
+ [!provide] PROVIDE (exc_cause_table = 0x3ff991d0)
+ [!provide] PROVIDE (GF_Jacobian_Point_Addition256 = 0x400163a4)
+ [!provide] PROVIDE (GF_Jacobian_Point_Double256 = 0x40016260)
+ [!provide] PROVIDE (GF_Point_Jacobian_To_Affine256 = 0x40016b0c)
+ [!provide] PROVIDE (g_phyFuns_instance = 0x3ffae0c4)
+ 0x000000003ffae270 PROVIDE (g_rom_flashchip = 0x3ffae270)
+ [!provide] PROVIDE (gTxMsg = 0x3ffe0050)
+ [!provide] PROVIDE (hci_cmd_desc_root_tab = 0x3ff976d4)
+ [!provide] PROVIDE (hci_cmd_desc_tab_ctrl_bb = 0x3ff97b70)
+ [!provide] PROVIDE (hci_cmd_desc_tab_info_par = 0x3ff97b1c)
+ [!provide] PROVIDE (hci_cmd_desc_tab_le = 0x3ff97870)
+ [!provide] PROVIDE (hci_cmd_desc_tab_lk_ctrl = 0x3ff97fc0)
+ [!provide] PROVIDE (hci_cmd_desc_tab_lk_pol = 0x3ff97f3c)
+ [!provide] PROVIDE (hci_cmd_desc_tab_stat_par = 0x3ff97ac8)
+ [!provide] PROVIDE (hci_cmd_desc_tab_testing = 0x3ff97a98)
+ [!provide] PROVIDE (hci_cmd_desc_tab_vs = 0x3ff97714)
+ [!provide] PROVIDE (hci_command_handler = 0x4004c928)
+ [!provide] PROVIDE (hci_env = 0x3ffb9350)
+ [!provide] PROVIDE (rwip_env = 0x3ffb8bcc)
+ [!provide] PROVIDE (hci_evt_dbg_desc_tab = 0x3ff9750c)
+ [!provide] PROVIDE (hci_evt_desc_tab = 0x3ff9751c)
+ [!provide] PROVIDE (hci_evt_le_desc_tab = 0x3ff974b4)
+ [!provide] PROVIDE (hci_fc_env = 0x3ffb9340)
+ [!provide] PROVIDE (jd_decomp = 0x400613e8)
+ [!provide] PROVIDE (jd_prepare = 0x40060fa8)
+ [!provide] PROVIDE (ke_env = 0x3ffb93cc)
+ [!provide] PROVIDE (lb_default_handler = 0x3ff982b8)
+ [!provide] PROVIDE (lb_default_state_tab_p_get = 0x4001c198)
+ [!provide] PROVIDE (lb_env = 0x3ffb9424)
+ [!provide] PROVIDE (lb_hci_cmd_handler_tab_p_get = 0x4001c18c)
+ [!provide] PROVIDE (lb_state = 0x3ffb94e8)
+ [!provide] PROVIDE (lc_default_handler = 0x3ff98648)
+ [!provide] PROVIDE (lc_default_state_tab_p_get = 0x4002f494)
+ [!provide] PROVIDE (lc_env = 0x3ffb94ec)
+ [!provide] PROVIDE (lc_hci_cmd_handler_tab_p_get = 0x4002f488)
+ [!provide] PROVIDE (lc_state = 0x3ffb9508)
+ [!provide] PROVIDE (ld_acl_br_sizes = 0x3ff98a2a)
+ [!provide] PROVIDE (ld_acl_br_types = 0x3ff98a36)
+ [!provide] PROVIDE (ld_acl_edr_sizes = 0x3ff98a14)
+ [!provide] PROVIDE (ld_acl_edr_types = 0x3ff98a22)
+ [!provide] PROVIDE (ld_env = 0x3ffb9510)
+ [!provide] PROVIDE (ld_pcm_settings_dft = 0x3ff98a0c)
+ [!provide] PROVIDE (ld_sched_params = 0x3ffb96c0)
+ [!provide] PROVIDE (ld_sync_train_channels = 0x3ff98a3c)
+ [!provide] PROVIDE (llc_default_handler = 0x3ff98b3c)
+ [!provide] PROVIDE (llc_default_state_tab_p_get = 0x40046058)
+ [!provide] PROVIDE (llc_env = 0x3ffb96d0)
+ [!provide] PROVIDE (llc_hci_acl_data_tx_handler = 0x40042398)
+ [!provide] PROVIDE (llc_hci_cmd_handler_tab_p_get = 0x40042358)
+ [!provide] PROVIDE (llc_hci_command_handler = 0x40042360)
+ [!provide] PROVIDE (llcp_pdu_handler_tab_p_get = 0x40043f64)
+ [!provide] PROVIDE (llc_state = 0x3ffb96f8)
+ [!provide] PROVIDE (lldesc_build_chain = 0x4000a850)
+ [!provide] PROVIDE (lldesc_num2link = 0x4000a948)
+ [!provide] PROVIDE (lldesc_set_owner = 0x4000a974)
+ [!provide] PROVIDE (lld_evt_deferred_elt_push = 0x400466b4)
+ [!provide] PROVIDE (lld_evt_deferred_elt_pop = 0x400466dc)
+ [!provide] PROVIDE (lld_evt_winsize_change = 0x40046730)
+ [!provide] PROVIDE (lld_evt_rxwin_compute = 0x400467c8)
+ [!provide] PROVIDE (lld_evt_slave_time_compute = 0x40046818)
+ [!provide] PROVIDE (lld_evt_env = 0x3ffb9704)
+ [!provide] PROVIDE (lld_evt_elt_wait_get = 0x400468e4)
+ [!provide] PROVIDE (lld_evt_get_next_free_slot = 0x4004692c)
+ [!provide] PROVIDE (lld_pdu_adv_pk_desc_tab = 0x3ff98c70)
+ [!provide] PROVIDE (lld_pdu_llcp_pk_desc_tab = 0x3ff98b68)
+ [!provide] PROVIDE (lld_pdu_tx_flush_list = 0x4004a760)
+ [!provide] PROVIDE (lld_pdu_pack = 0x4004ab14)
+ [!provide] PROVIDE (LLM_AA_CT1 = 0x3ff98d8a)
+ [!provide] PROVIDE (LLM_AA_CT2 = 0x3ff98d88)
+ [!provide] PROVIDE (llm_default_handler = 0x3ff98d80)
+ [!provide] PROVIDE (llm_default_state_tab_p_get = 0x4004e718)
+ [!provide] PROVIDE (llm_hci_cmd_handler_tab_p_get = 0x4004c920)
+ [!provide] PROVIDE (llm_le_env = 0x3ffb976c)
+ [!provide] PROVIDE (llm_local_cmds = 0x3ff98d38)
+ [!provide] PROVIDE (llm_local_data_len_values = 0x3ff98d1c)
+ [!provide] PROVIDE (llm_local_le_feats = 0x3ff98d30)
+ [!provide] PROVIDE (llm_local_le_states = 0x3ff98d28)
+ [!provide] PROVIDE (llm_state = 0x3ffb985c)
+ [!provide] PROVIDE (lm_default_handler = 0x3ff990e0)
+ [!provide] PROVIDE (lm_default_state_tab_p_get = 0x40054268)
+ [!provide] PROVIDE (lm_env = 0x3ffb9860)
+ [!provide] PROVIDE (lm_hci_cmd_handler_tab_p_get = 0x4005425c)
+ [!provide] PROVIDE (lm_local_supp_feats = 0x3ff990ee)
+ [!provide] PROVIDE (lm_n_page_tab = 0x3ff990e8)
+ [!provide] PROVIDE (lmp_desc_tab = 0x3ff96e6c)
+ [!provide] PROVIDE (lmp_ext_desc_tab = 0x3ff96d9c)
+ [!provide] PROVIDE (lm_state = 0x3ffb9a1c)
+ [!provide] PROVIDE (maxSecretKey_256 = 0x3ff97448)
+ 0x00000000400095a4 PROVIDE (mmu_init = 0x400095a4)
+ [!provide] PROVIDE (MultiplyBigHexByUint32_256 = 0x40016214)
+ [!provide] PROVIDE (MultiplyBigHexModP256 = 0x400160b8)
+ [!provide] PROVIDE (MultiplyByU32ModP256 = 0x40015fdc)
+ [!provide] PROVIDE (multofup = 0x4000ab8c)
+ [!provide] PROVIDE (mz_adler32 = 0x4005edbc)
+ [!provide] PROVIDE (mz_crc32 = 0x4005ee88)
+ [!provide] PROVIDE (mz_free = 0x4005eed4)
+ [!provide] PROVIDE (notEqual256 = 0x40015b04)
+ [!provide] PROVIDE (one_bits = 0x3ff971f8)
+ [!provide] PROVIDE (phy_get_romfuncs = 0x40004100)
+ [!provide] PROVIDE (_Pri_4_HandlerAddress = 0x3ffe0648)
+ [!provide] PROVIDE (_Pri_5_HandlerAddress = 0x3ffe064c)
+ [!provide] PROVIDE (r_btdm_option_data = 0x3ffae6e0)
+ [!provide] PROVIDE (r_bt_util_buf_acl_rx_alloc = 0x40010218)
+ [!provide] PROVIDE (r_bt_util_buf_acl_rx_free = 0x40010234)
+ [!provide] PROVIDE (r_bt_util_buf_acl_tx_alloc = 0x40010268)
+ [!provide] PROVIDE (r_bt_util_buf_acl_tx_free = 0x40010280)
+ [!provide] PROVIDE (r_bt_util_buf_init = 0x400100e4)
+ [!provide] PROVIDE (r_bt_util_buf_lmp_tx_alloc = 0x400101d0)
+ [!provide] PROVIDE (r_bt_util_buf_lmp_tx_free = 0x400101ec)
+ [!provide] PROVIDE (r_bt_util_buf_sync_clear = 0x400103c8)
+ [!provide] PROVIDE (r_bt_util_buf_sync_init = 0x400102c4)
+ [!provide] PROVIDE (r_bt_util_buf_sync_rx_alloc = 0x40010468)
+ [!provide] PROVIDE (r_bt_util_buf_sync_rx_free = 0x4001049c)
+ [!provide] PROVIDE (r_bt_util_buf_sync_tx_alloc = 0x400103ec)
+ [!provide] PROVIDE (r_bt_util_buf_sync_tx_free = 0x40010428)
+ [!provide] PROVIDE (r_co_bdaddr_compare = 0x40014324)
+ [!provide] PROVIDE (r_co_bytes_to_string = 0x400142e4)
+ [!provide] PROVIDE (r_co_list_check_size_available = 0x400142c4)
+ [!provide] PROVIDE (r_co_list_extract = 0x4001404c)
+ [!provide] PROVIDE (r_co_list_extract_after = 0x40014118)
+ [!provide] PROVIDE (r_co_list_find = 0x4001419c)
+ [!provide] PROVIDE (r_co_list_init = 0x40013f14)
+ [!provide] PROVIDE (r_co_list_insert_after = 0x40014254)
+ [!provide] PROVIDE (r_co_list_insert_before = 0x40014200)
+ [!provide] PROVIDE (r_co_list_merge = 0x400141bc)
+ [!provide] PROVIDE (r_co_list_pool_init = 0x40013f30)
+ [!provide] PROVIDE (r_co_list_pop_front = 0x40014028)
+ [!provide] PROVIDE (r_co_list_push_back = 0x40013fb8)
+ [!provide] PROVIDE (r_co_list_push_front = 0x40013ff4)
+ [!provide] PROVIDE (r_co_list_size = 0x400142ac)
+ [!provide] PROVIDE (r_co_nb_good_channels = 0x40014360)
+ [!provide] PROVIDE (r_co_slot_to_duration = 0x40014348)
+ [!provide] PROVIDE (r_dbg_init = 0x40014394)
+ [!provide] PROVIDE (r_dbg_platform_reset_complete = 0x400143d0)
+ [!provide] PROVIDE (r_dbg_swdiag_init = 0x40014470)
+ [!provide] PROVIDE (r_dbg_swdiag_read = 0x400144a4)
+ [!provide] PROVIDE (r_dbg_swdiag_write = 0x400144d0)
+ [!provide] PROVIDE (r_E1 = 0x400108e8)
+ [!provide] PROVIDE (r_E21 = 0x40010968)
+ [!provide] PROVIDE (r_E22 = 0x400109b4)
+ [!provide] PROVIDE (r_E3 = 0x40010a58)
+ [!provide] PROVIDE (lm_n192_mod_mul = 0x40011dc0)
+ [!provide] PROVIDE (lm_n192_mod_add = 0x40011e9c)
+ [!provide] PROVIDE (lm_n192_mod_sub = 0x40011eec)
+ [!provide] PROVIDE (r_ea_alarm_clear = 0x40015ab4)
+ [!provide] PROVIDE (r_ea_alarm_set = 0x40015a10)
+ [!provide] PROVIDE (r_ea_elt_cancel = 0x400150d0)
+ [!provide] PROVIDE (r_ea_elt_create = 0x40015264)
+ [!provide] PROVIDE (r_ea_elt_insert = 0x400152a8)
+ [!provide] PROVIDE (r_ea_elt_remove = 0x400154f0)
+ [!provide] PROVIDE (r_ea_finetimer_isr = 0x400155d4)
+ [!provide] PROVIDE (r_ea_init = 0x40015228)
+ [!provide] PROVIDE (r_ea_interval_create = 0x4001555c)
+ [!provide] PROVIDE (r_ea_interval_delete = 0x400155a8)
+ [!provide] PROVIDE (r_ea_interval_duration_req = 0x4001597c)
+ [!provide] PROVIDE (r_ea_interval_insert = 0x4001557c)
+ [!provide] PROVIDE (r_ea_interval_remove = 0x40015590)
+ [!provide] PROVIDE (ea_conflict_check = 0x40014e9c)
+ [!provide] PROVIDE (ea_prog_timer = 0x40014f88)
+ [!provide] PROVIDE (r_ea_offset_req = 0x40015748)
+ [!provide] PROVIDE (r_ea_sleep_check = 0x40015928)
+ [!provide] PROVIDE (r_ea_sw_isr = 0x40015724)
+ [!provide] PROVIDE (r_ea_time_get_halfslot_rounded = 0x40015894)
+ [!provide] PROVIDE (r_ea_time_get_slot_rounded = 0x400158d4)
+ [!provide] PROVIDE (r_ecc_abort_key256_generation = 0x40017070)
+ [!provide] PROVIDE (r_ecc_generate_key256 = 0x40016e00)
+ [!provide] PROVIDE (r_ecc_gen_new_public_key = 0x400170c0)
+ [!provide] PROVIDE (r_ecc_gen_new_secret_key = 0x400170e4)
+ [!provide] PROVIDE (r_ecc_get_debug_Keys = 0x40017224)
+ [!provide] PROVIDE (r_ecc_init = 0x40016dbc)
+ [!provide] PROVIDE (ecc_point_multiplication_uint8_256 = 0x40016804)
+ [!provide] PROVIDE (RecvBuff = 0x3ffe009c)
+ [!provide] PROVIDE (r_em_buf_init = 0x4001729c)
+ [!provide] PROVIDE (r_em_buf_rx_buff_addr_get = 0x400173e8)
+ [!provide] PROVIDE (r_em_buf_rx_free = 0x400173c4)
+ [!provide] PROVIDE (r_em_buf_tx_buff_addr_get = 0x40017404)
+ [!provide] PROVIDE (r_em_buf_tx_free = 0x4001741c)
+ [!provide] PROVIDE (r_F1_256 = 0x400133e4)
+ [!provide] PROVIDE (r_F2_256 = 0x40013568)
+ [!provide] PROVIDE (r_F3_256 = 0x40013664)
+ [!provide] PROVIDE (RFPLL_ICP_TABLE = 0x3ffb8b7c)
+ [!provide] PROVIDE (r_G_256 = 0x40013470)
+ [!provide] PROVIDE (r_H3 = 0x40013760)
+ [!provide] PROVIDE (r_H4 = 0x40013830)
+ [!provide] PROVIDE (r_h4tl_init = 0x40017878)
+ [!provide] PROVIDE (r_h4tl_start = 0x40017924)
+ [!provide] PROVIDE (r_h4tl_stop = 0x40017934)
+ [!provide] PROVIDE (r_h4tl_write = 0x400178d0)
+ [!provide] PROVIDE (r_H5 = 0x400138dc)
+ [!provide] PROVIDE (r_hashConcat = 0x40013a38)
+ [!provide] PROVIDE (r_hci_acl_tx_data_alloc = 0x4001951c)
+ [!provide] PROVIDE (r_hci_acl_tx_data_received = 0x40019654)
+ [!provide] PROVIDE (r_hci_bt_acl_bdaddr_register = 0x40018900)
+ [!provide] PROVIDE (r_hci_bt_acl_bdaddr_unregister = 0x400189ac)
+ [!provide] PROVIDE (r_hci_bt_acl_conhdl_register = 0x4001895c)
+ [!provide] PROVIDE (r_hci_cmd_get_max_param_size = 0x400192d0)
+ [!provide] PROVIDE (r_hci_cmd_received = 0x400192f8)
+ [!provide] PROVIDE (r_hci_evt_filter_add = 0x40018a64)
+ [!provide] PROVIDE (r_hci_evt_mask_set = 0x400189e4)
+ [!provide] PROVIDE (r_hci_fc_acl_buf_size_set = 0x40017988)
+ [!provide] PROVIDE (r_hci_fc_acl_en = 0x400179d8)
+ [!provide] PROVIDE (r_hci_fc_acl_packet_sent = 0x40017a3c)
+ [!provide] PROVIDE (r_hci_fc_check_host_available_nb_acl_packets = 0x40017aa4)
+ [!provide] PROVIDE (r_hci_fc_check_host_available_nb_sync_packets = 0x40017ac8)
+ [!provide] PROVIDE (r_hci_fc_host_nb_acl_pkts_complete = 0x40017a6c)
+ [!provide] PROVIDE (r_hci_fc_host_nb_sync_pkts_complete = 0x40017a88)
+ [!provide] PROVIDE (r_hci_fc_init = 0x40017974)
+ [!provide] PROVIDE (r_hci_fc_sync_buf_size_set = 0x400179b0)
+ [!provide] PROVIDE (r_hci_fc_sync_en = 0x40017a30)
+ [!provide] PROVIDE (r_hci_fc_sync_packet_sent = 0x40017a54)
+ [!provide] PROVIDE (r_hci_init = 0x40018538)
+ [!provide] PROVIDE (r_hci_look_for_cmd_desc = 0x40018454)
+ [!provide] PROVIDE (r_hci_look_for_dbg_evt_desc = 0x400184c4)
+ [!provide] PROVIDE (r_hci_look_for_evt_desc = 0x400184a0)
+ [!provide] PROVIDE (r_hci_look_for_le_evt_desc = 0x400184e0)
+ [!provide] PROVIDE (r_hci_reset = 0x4001856c)
+ [!provide] PROVIDE (r_hci_send_2_host = 0x400185bc)
+ [!provide] PROVIDE (r_hci_sync_tx_data_alloc = 0x40019754)
+ [!provide] PROVIDE (r_hci_sync_tx_data_received = 0x400197c0)
+ [!provide] PROVIDE (r_hci_tl_init = 0x40019290)
+ [!provide] PROVIDE (r_hci_tl_send = 0x40019228)
+ [!provide] PROVIDE (r_hci_util_pack = 0x40019874)
+ [!provide] PROVIDE (r_hci_util_unpack = 0x40019998)
+ [!provide] PROVIDE (r_hci_voice_settings_get = 0x40018bdc)
+ [!provide] PROVIDE (r_hci_voice_settings_set = 0x40018be8)
+ [!provide] PROVIDE (r_HMAC = 0x40013968)
+ [!provide] PROVIDE (r_import_rf_phy_func = 0x3ffb8354)
+ [!provide] PROVIDE (r_import_rf_phy_func_p = 0x3ffafd64)
+ [!provide] PROVIDE (r_ip_funcs = 0x3ffae710)
+ [!provide] PROVIDE (r_ip_funcs_p = 0x3ffae70c)
+ [!provide] PROVIDE (r_ke_check_malloc = 0x40019de0)
+ [!provide] PROVIDE (r_ke_event_callback_set = 0x40019ba8)
+ [!provide] PROVIDE (r_ke_event_clear = 0x40019c2c)
+ [!provide] PROVIDE (r_ke_event_flush = 0x40019ccc)
+ [!provide] PROVIDE (r_ke_event_get = 0x40019c78)
+ [!provide] PROVIDE (r_ke_event_get_all = 0x40019cc0)
+ [!provide] PROVIDE (r_ke_event_init = 0x40019b90)
+ [!provide] PROVIDE (r_ke_event_schedule = 0x40019cdc)
+ [!provide] PROVIDE (r_ke_event_set = 0x40019be0)
+ [!provide] PROVIDE (r_ke_flush = 0x4001a374)
+ [!provide] PROVIDE (r_ke_free = 0x4001a014)
+ [!provide] PROVIDE (r_ke_get_max_mem_usage = 0x4001a1c8)
+ [!provide] PROVIDE (r_ke_get_mem_usage = 0x4001a1a0)
+ [!provide] PROVIDE (r_ke_init = 0x4001a318)
+ [!provide] PROVIDE (r_ke_is_free = 0x4001a184)
+ [!provide] PROVIDE (r_ke_malloc = 0x40019eb4)
+ [!provide] PROVIDE (r_ke_mem_init = 0x40019d3c)
+ [!provide] PROVIDE (r_ke_mem_is_empty = 0x40019d8c)
+ [!provide] PROVIDE (r_ke_msg_alloc = 0x4001a1e0)
+ [!provide] PROVIDE (r_ke_msg_dest_id_get = 0x4001a2e0)
+ [!provide] PROVIDE (r_ke_msg_discard = 0x4001a850)
+ [!provide] PROVIDE (r_ke_msg_forward = 0x4001a290)
+ [!provide] PROVIDE (r_ke_msg_forward_new_id = 0x4001a2ac)
+ [!provide] PROVIDE (r_ke_msg_free = 0x4001a2cc)
+ [!provide] PROVIDE (r_ke_msg_in_queue = 0x4001a2f8)
+ [!provide] PROVIDE (r_ke_msg_save = 0x4001a858)
+ [!provide] PROVIDE (r_ke_msg_send = 0x4001a234)
+ [!provide] PROVIDE (r_ke_msg_send_basic = 0x4001a26c)
+ [!provide] PROVIDE (r_ke_msg_src_id_get = 0x4001a2ec)
+ [!provide] PROVIDE (r_ke_queue_extract = 0x40055fd0)
+ [!provide] PROVIDE (r_ke_queue_insert = 0x40056020)
+ [!provide] PROVIDE (r_ke_sleep_check = 0x4001a3d8)
+ [!provide] PROVIDE (r_ke_state_get = 0x4001a7d8)
+ [!provide] PROVIDE (r_ke_state_set = 0x4001a6fc)
+ [!provide] PROVIDE (r_ke_stats_get = 0x4001a3f0)
+ [!provide] PROVIDE (r_ke_task_check = 0x4001a8a4)
+ [!provide] PROVIDE (r_ke_task_create = 0x4001a674)
+ [!provide] PROVIDE (r_ke_task_delete = 0x4001a6c0)
+ [!provide] PROVIDE (r_ke_task_init = 0x4001a650)
+ [!provide] PROVIDE (r_ke_task_msg_flush = 0x4001a860)
+ [!provide] PROVIDE (r_ke_timer_active = 0x4001ac08)
+ [!provide] PROVIDE (r_ke_timer_adjust_all = 0x4001ac30)
+ [!provide] PROVIDE (r_ke_timer_clear = 0x4001ab90)
+ [!provide] PROVIDE (r_ke_timer_init = 0x4001aa9c)
+ [!provide] PROVIDE (r_ke_timer_set = 0x4001aac0)
+ [!provide] PROVIDE (r_ke_timer_sleep_check = 0x4001ac50)
+ [!provide] PROVIDE (r_KPrimC = 0x40010ad4)
+ [!provide] PROVIDE (r_lb_clk_adj_activate = 0x4001ae70)
+ [!provide] PROVIDE (r_lb_clk_adj_id_get = 0x4001af14)
+ [!provide] PROVIDE (r_lb_clk_adj_period_update = 0x4001af20)
+ [!provide] PROVIDE (r_lb_init = 0x4001acd4)
+ [!provide] PROVIDE (r_lb_mst_key = 0x4001afc0)
+ [!provide] PROVIDE (r_lb_mst_key_cmp = 0x4001af74)
+ [!provide] PROVIDE (r_lb_mst_key_restart_enc = 0x4001b0d4)
+ [!provide] PROVIDE (r_lb_mst_start_act_bcst_enc = 0x4001b198)
+ [!provide] PROVIDE (r_lb_mst_stop_act_bcst_enc = 0x4001b24c)
+ [!provide] PROVIDE (r_lb_reset = 0x4001ad38)
+ [!provide] PROVIDE (r_lb_send_lmp = 0x4001adbc)
+ [!provide] PROVIDE (r_lb_send_pdu_clk_adj = 0x4001af3c)
+ [!provide] PROVIDE (r_lb_util_get_csb_mode = 0x4001ada4)
+ [!provide] PROVIDE (r_lb_util_get_nb_broadcast = 0x4001ad80)
+ [!provide] PROVIDE (r_lb_util_get_res_lt_addr = 0x4001ad98)
+ [!provide] PROVIDE (r_lb_util_set_nb_broadcast = 0x4001ad8c)
+ [!provide] PROVIDE (r_lc_afh_set = 0x4001cc74)
+ [!provide] PROVIDE (r_lc_afh_start = 0x4001d240)
+ [!provide] PROVIDE (r_lc_auth_cmp = 0x4001cd54)
+ [!provide] PROVIDE (r_lc_calc_link_key = 0x4001ce7c)
+ [!provide] PROVIDE (r_lc_chg_pkt_type_cmp = 0x4001d038)
+ [!provide] PROVIDE (r_lc_chg_pkt_type_cont = 0x4001cfbc)
+ [!provide] PROVIDE (r_lc_chg_pkt_type_retry = 0x4001d0ac)
+ [!provide] PROVIDE (r_lc_chk_to = 0x4001d2a8)
+ [!provide] PROVIDE (r_lc_cmd_stat_send = 0x4001c914)
+ [!provide] PROVIDE (r_lc_comb_key_svr = 0x4001d30c)
+ [!provide] PROVIDE (r_lc_con_cmp = 0x4001d44c)
+ [!provide] PROVIDE (r_lc_con_cmp_evt_send = 0x4001d4fc)
+ [!provide] PROVIDE (r_lc_conn_seq_done = 0x40021334)
+ [!provide] PROVIDE (r_lc_detach = 0x4002037c)
+ [!provide] PROVIDE (r_lc_dhkey = 0x4001d564)
+ [!provide] PROVIDE (r_lc_enc_cmp = 0x4001d8bc)
+ [!provide] PROVIDE (r_lc_enc_key_refresh = 0x4001d720)
+ [!provide] PROVIDE (r_lc_end_chk_colli = 0x4001d858)
+ [!provide] PROVIDE (r_lc_end_of_sniff_nego = 0x4001d9a4)
+ [!provide] PROVIDE (r_lc_enter_sniff_mode = 0x4001ddb8)
+ [!provide] PROVIDE (r_lc_epr_change_lk = 0x4001db38)
+ [!provide] PROVIDE (r_lc_epr_cmp = 0x4001da88)
+ [!provide] PROVIDE (r_lc_epr_resp = 0x4001e0b4)
+ [!provide] PROVIDE (r_lc_epr_rsw_cmp = 0x4001dd40)
+ [!provide] PROVIDE (r_lc_ext_feat = 0x40020d6c)
+ [!provide] PROVIDE (r_lc_feat = 0x40020984)
+ [!provide] PROVIDE (r_lc_hl_connect = 0x400209e8)
+ [!provide] PROVIDE (r_lc_init = 0x4001c948)
+ [!provide] PROVIDE (r_lc_init_calc_f3 = 0x4001deb0)
+ [!provide] PROVIDE (r_lc_initiator_epr = 0x4001e064)
+ [!provide] PROVIDE (r_lc_init_passkey_loop = 0x4001dfc0)
+ [!provide] PROVIDE (r_lc_init_start_mutual_auth = 0x4001df60)
+ [!provide] PROVIDE (r_lc_key_exch_end = 0x4001e140)
+ [!provide] PROVIDE (r_lc_legacy_pair = 0x4001e1c0)
+ [!provide] PROVIDE (r_lc_local_switch = 0x4001e22c)
+ [!provide] PROVIDE (r_lc_local_trans_mode = 0x4001e2e4)
+ [!provide] PROVIDE (r_lc_local_untrans_mode = 0x4001e3a0)
+ [!provide] PROVIDE (r_lc_loc_auth = 0x40020ecc)
+ [!provide] PROVIDE (r_lc_locepr_lkref = 0x4001d648)
+ [!provide] PROVIDE (r_lc_locepr_rsw = 0x4001d5d0)
+ [!provide] PROVIDE (r_lc_loc_sniff = 0x40020a6c)
+ [!provide] PROVIDE (r_lc_max_slot_mgt = 0x4001e410)
+ [!provide] PROVIDE (r_lc_mst_key = 0x4001e7c0)
+ [!provide] PROVIDE (r_lc_mst_qos_done = 0x4001ea80)
+ [!provide] PROVIDE (r_lc_mst_send_mst_key = 0x4001e8f4)
+ [!provide] PROVIDE (r_lc_mutual_auth_end = 0x4001e670)
+ [!provide] PROVIDE (r_lc_mutual_auth_end2 = 0x4001e4f4)
+ [!provide] PROVIDE (r_lc_packet_type = 0x40021038)
+ [!provide] PROVIDE (r_lc_pair = 0x40020ddc)
+ [!provide] PROVIDE (r_lc_pairing_cont = 0x4001eafc)
+ [!provide] PROVIDE (r_lc_passkey_comm = 0x4001ed20)
+ [!provide] PROVIDE (r_lc_prepare_all_links_for_clk_adj = 0x40021430)
+ [!provide] PROVIDE (r_lc_proc_rcv_dhkey = 0x4001edec)
+ [!provide] PROVIDE (r_lc_ptt = 0x4001ee2c)
+ [!provide] PROVIDE (r_lc_ptt_cmp = 0x4001eeec)
+ [!provide] PROVIDE (r_lc_qos_setup = 0x4001ef50)
+ [!provide] PROVIDE (r_lc_rd_rem_name = 0x4001efd0)
+ [!provide] PROVIDE (r_lc_release = 0x4001f8a8)
+ [!provide] PROVIDE (r_lc_rem_enc = 0x4001f124)
+ [!provide] PROVIDE (r_lc_rem_name_cont = 0x4001f290)
+ [!provide] PROVIDE (r_lc_rem_nego_trans_mode = 0x4001f1b4)
+ [!provide] PROVIDE (r_lc_rem_sniff = 0x40020ca4)
+ [!provide] PROVIDE (r_lc_rem_sniff_sub_rate = 0x40020b10)
+ [!provide] PROVIDE (r_lc_rem_switch = 0x4001f070)
+ [!provide] PROVIDE (r_lc_rem_trans_mode = 0x4001f314)
+ [!provide] PROVIDE (r_lc_rem_unsniff = 0x400207a0)
+ [!provide] PROVIDE (r_lc_rem_untrans_mode = 0x4001f36c)
+ [!provide] PROVIDE (r_lc_reset = 0x4001c99c)
+ [!provide] PROVIDE (r_lc_resp_auth = 0x4001f518)
+ [!provide] PROVIDE (r_lc_resp_calc_f3 = 0x4001f710)
+ [!provide] PROVIDE (r_lc_resp_num_comp = 0x40020074)
+ [!provide] PROVIDE (r_lc_resp_oob_nonce = 0x4001f694)
+ [!provide] PROVIDE (r_lc_resp_oob_wait_nonce = 0x4001f66c)
+ [!provide] PROVIDE (r_lc_resp_pair = 0x400208a4)
+ [!provide] PROVIDE (r_lc_resp_sec_auth = 0x4001f4a0)
+ [!provide] PROVIDE (r_lc_resp_wait_dhkey_cont = 0x4001f86c)
+ [!provide] PROVIDE (r_lc_restart_enc = 0x4001f8ec)
+ [!provide] PROVIDE (r_lc_restart_enc_cont = 0x4001f940)
+ [!provide] PROVIDE (r_lc_restore_afh_reporting = 0x4001f028)
+ [!provide] PROVIDE (r_lc_restore_to = 0x4001f9e0)
+ [!provide] PROVIDE (r_lc_ret_sniff_max_slot_chg = 0x4001fa30)
+ [!provide] PROVIDE (r_lc_rsw_clean_up = 0x4001dc70)
+ [!provide] PROVIDE (r_lc_rsw_done = 0x4001db94)
+ [!provide] PROVIDE (r_lc_sco_baseband_ack = 0x40022b00)
+ [!provide] PROVIDE (r_lc_sco_detach = 0x40021e40)
+ [!provide] PROVIDE (r_lc_sco_host_accept = 0x40022118)
+ [!provide] PROVIDE (r_lc_sco_host_reject = 0x400222b8)
+ [!provide] PROVIDE (r_lc_sco_host_request = 0x40021f4c)
+ [!provide] PROVIDE (r_lc_sco_host_request_disc = 0x4002235c)
+ [!provide] PROVIDE (r_lc_sco_init = 0x40021dc8)
+ [!provide] PROVIDE (r_lc_sco_peer_accept = 0x40022780)
+ [!provide] PROVIDE (r_lc_sco_peer_accept_disc = 0x40022a08)
+ [!provide] PROVIDE (r_lc_sco_peer_reject = 0x40022824)
+ [!provide] PROVIDE (r_lc_sco_peer_reject_disc = 0x40022a8c)
+ [!provide] PROVIDE (r_lc_sco_peer_request = 0x4002240c)
+ [!provide] PROVIDE (r_lc_sco_peer_request_disc = 0x400228ec)
+ [!provide] PROVIDE (r_lc_sco_release = 0x40021eec)
+ [!provide] PROVIDE (r_lc_sco_reset = 0x40021dfc)
+ [!provide] PROVIDE (r_lc_sco_timeout = 0x40022bd4)
+ [!provide] PROVIDE (r_lc_sec_auth_compute_sres = 0x4001f3ec)
+ [!provide] PROVIDE (r_lc_semi_key_cmp = 0x40020294)
+ [!provide] PROVIDE (r_lc_send_enc_chg_evt = 0x4002134c)
+ [!provide] PROVIDE (r_lc_send_enc_mode = 0x40020220)
+ [!provide] PROVIDE (r_lc_send_lmp = 0x4001c1a8)
+ [!provide] PROVIDE (r_lc_send_pdu_acc = 0x4001c21c)
+ [!provide] PROVIDE (r_lc_send_pdu_acc_ext4 = 0x4001c240)
+ [!provide] PROVIDE (r_lc_send_pdu_au_rand = 0x4001c308)
+ [!provide] PROVIDE (r_lc_send_pdu_auto_rate = 0x4001c5d0)
+ [!provide] PROVIDE (r_lc_send_pdu_clk_adj_ack = 0x4001c46c)
+ [!provide] PROVIDE (r_lc_send_pdu_clk_adj_req = 0x4001c494)
+ [!provide] PROVIDE (r_lc_send_pdu_comb_key = 0x4001c368)
+ [!provide] PROVIDE (r_lc_send_pdu_dhkey_chk = 0x4001c8e8)
+ [!provide] PROVIDE (r_lc_send_pdu_encaps_head = 0x4001c440)
+ [!provide] PROVIDE (r_lc_send_pdu_encaps_payl = 0x4001c410)
+ [!provide] PROVIDE (r_lc_send_pdu_enc_key_sz_req = 0x4001c670)
+ [!provide] PROVIDE (r_lc_send_pdu_esco_lk_rem_req = 0x4001c5a8)
+ [!provide] PROVIDE (r_lc_send_pdu_feats_ext_req = 0x4001c6ec)
+ [!provide] PROVIDE (r_lc_send_pdu_feats_res = 0x4001c694)
+ [!provide] PROVIDE (r_lc_send_pdu_in_rand = 0x4001c338)
+ [!provide] PROVIDE (r_lc_send_pdu_io_cap_res = 0x4001c72c)
+ [!provide] PROVIDE (r_lc_send_pdu_lsto = 0x4001c64c)
+ [!provide] PROVIDE (r_lc_send_pdu_max_slot = 0x4001c3c8)
+ [!provide] PROVIDE (r_lc_send_pdu_max_slot_req = 0x4001c3ec)
+ [!provide] PROVIDE (r_lc_send_pdu_not_acc = 0x4001c26c)
+ [!provide] PROVIDE (r_lc_send_pdu_not_acc_ext4 = 0x4001c294)
+ [!provide] PROVIDE (r_lc_send_pdu_num_comp_fail = 0x4001c770)
+ [!provide] PROVIDE (r_lc_send_pdu_pause_enc_aes_req = 0x4001c794)
+ [!provide] PROVIDE (r_lc_send_pdu_paus_enc_req = 0x4001c7c0)
+ [!provide] PROVIDE (r_lc_send_pdu_ptt_req = 0x4001c4c0)
+ [!provide] PROVIDE (r_lc_send_pdu_qos_req = 0x4001c82c)
+ [!provide] PROVIDE (r_lc_send_pdu_resu_enc_req = 0x4001c7e4)
+ [!provide] PROVIDE (r_lc_send_pdu_sco_lk_rem_req = 0x4001c580)
+ [!provide] PROVIDE (r_lc_send_pdu_set_afh = 0x4001c2c8)
+ [!provide] PROVIDE (r_lc_send_pdu_setup_cmp = 0x4001c808)
+ [!provide] PROVIDE (r_lc_send_pdu_slot_off = 0x4001c854)
+ [!provide] PROVIDE (r_lc_send_pdu_sniff_req = 0x4001c5f0)
+ [!provide] PROVIDE (r_lc_send_pdu_sp_cfm = 0x4001c518)
+ [!provide] PROVIDE (r_lc_send_pdu_sp_nb = 0x4001c4e8)
+ [!provide] PROVIDE (r_lc_send_pdu_sres = 0x4001c548)
+ [!provide] PROVIDE (r_lc_send_pdu_tim_acc = 0x4001c6cc)
+ [!provide] PROVIDE (r_lc_send_pdu_unit_key = 0x4001c398)
+ [!provide] PROVIDE (r_lc_send_pdu_unsniff_req = 0x4001c894)
+ [!provide] PROVIDE (r_lc_send_pdu_vers_req = 0x4001c8b4)
+ [!provide] PROVIDE (r_lc_skip_hl_oob_req = 0x400201bc)
+ [!provide] PROVIDE (r_lc_sniff_init = 0x40022cac)
+ [!provide] PROVIDE (r_lc_sniff_max_slot_chg = 0x40020590)
+ [!provide] PROVIDE (r_lc_sniff_reset = 0x40022cc8)
+ [!provide] PROVIDE (r_lc_sniff_slot_unchange = 0x40021100)
+ [!provide] PROVIDE (r_lc_sniff_sub_mode = 0x400204fc)
+ [!provide] PROVIDE (r_lc_sp_end = 0x400213a8)
+ [!provide] PROVIDE (r_lc_sp_fail = 0x40020470)
+ [!provide] PROVIDE (r_lc_sp_oob_tid_fail = 0x400204cc)
+ [!provide] PROVIDE (r_lc_ssr_nego = 0x4002125c)
+ [!provide] PROVIDE (r_lc_start = 0x4001ca28)
+ [!provide] PROVIDE (r_lc_start_enc = 0x4001fb28)
+ [!provide] PROVIDE (r_lc_start_enc_key_size = 0x4001fd9c)
+ [!provide] PROVIDE (r_lc_start_key_exch = 0x4001fe10)
+ [!provide] PROVIDE (r_lc_start_lmp_to = 0x4001fae8)
+ [!provide] PROVIDE (r_lc_start_oob = 0x4001fffc)
+ [!provide] PROVIDE (r_lc_start_passkey = 0x4001feac)
+ [!provide] PROVIDE (r_lc_start_passkey_loop = 0x4001ff88)
+ [!provide] PROVIDE (r_lc_stop_afh_report = 0x40020184)
+ [!provide] PROVIDE (r_lc_stop_enc = 0x40020110)
+ [!provide] PROVIDE (r_lc_switch_cmp = 0x40020448)
+ [!provide] PROVIDE (r_lc_unit_key_svr = 0x400206d8)
+ [!provide] PROVIDE (r_lc_unsniff = 0x40020c50)
+ [!provide] PROVIDE (r_lc_unsniff_cmp = 0x40020810)
+ [!provide] PROVIDE (r_lc_unsniff_cont = 0x40020750)
+ [!provide] PROVIDE (r_lc_upd_to = 0x4002065c)
+ [!provide] PROVIDE (r_lc_util_convert_pref_rate_to_packet_type = 0x4002f9b0)
+ [!provide] PROVIDE (r_lc_util_get_max_packet_size = 0x4002f4ac)
+ [!provide] PROVIDE (r_lc_util_get_offset_clke = 0x4002f538)
+ [!provide] PROVIDE (r_lc_util_get_offset_clkn = 0x4002f51c)
+ [!provide] PROVIDE (r_lc_util_set_loc_trans_coll = 0x4002f500)
+ [!provide] PROVIDE (r_lc_version = 0x40020a30)
+ [!provide] PROVIDE (lc_set_encap_pdu_data_p192 = 0x4002e4c8)
+ [!provide] PROVIDE (lc_set_encap_pdu_data_p256 = 0x4002e454)
+ [!provide] PROVIDE (lm_get_auth_method = 0x40023420)
+ [!provide] PROVIDE (lmp_accepted_ext_handler = 0x40027290)
+ [!provide] PROVIDE (lmp_not_accepted_ext_handler = 0x40029c54)
+ [!provide] PROVIDE (lmp_clk_adj_handler = 0x40027468)
+ [!provide] PROVIDE (lmp_clk_adj_ack_handler = 0x400274f4)
+ [!provide] PROVIDE (lm_get_auth_method = 0x40023420)
+ [!provide] PROVIDE (lmp_accepted_ext_handler = 0x40027290)
+ [!provide] PROVIDE (lmp_not_accepted_ext_handler = 0x40029c54)
+ [!provide] PROVIDE (lmp_clk_adj_handler = 0x40027468)
+ [!provide] PROVIDE (lmp_clk_adj_ack_handler = 0x400274f4)
+ [!provide] PROVIDE (lmp_clk_adj_req_handler = 0x4002751c)
+ [!provide] PROVIDE (lmp_feats_res_ext_handler = 0x4002cac4)
+ [!provide] PROVIDE (lmp_feats_req_ext_handler = 0x4002ccb0)
+ [!provide] PROVIDE (lmp_pkt_type_tbl_req_handler = 0x40027574)
+ [!provide] PROVIDE (lmp_esco_link_req_handler = 0x40027610)
+ [!provide] PROVIDE (lmp_rmv_esco_link_req_handler = 0x400276e8)
+ [!provide] PROVIDE (lmp_ch_class_req_handler = 0x40027730)
+ [!provide] PROVIDE (lmp_ch_class_handler = 0x4002ca18)
+ [!provide] PROVIDE (lmp_ssr_req_handler = 0x4002780c)
+ [!provide] PROVIDE (lmp_ssr_res_handler = 0x40027900)
+ [!provide] PROVIDE (lmp_pause_enc_aes_req_handler = 0x400279a4)
+ [!provide] PROVIDE (lmp_pause_enc_req_handler = 0x4002df90)
+ [!provide] PROVIDE (lmp_resume_enc_req_handler = 0x4002e084)
+ [!provide] PROVIDE (lmp_num_comparison_fail_handler = 0x40027a74)
+ [!provide] PROVIDE (lmp_passkey_fail_handler = 0x40027aec)
+ [!provide] PROVIDE (lmp_keypress_notif_handler = 0x4002c5c8)
+ [!provide] PROVIDE (lmp_pwr_ctrl_req_handler = 0x400263bc)
+ [!provide] PROVIDE (lmp_pwr_ctrl_res_handler = 0x40026480)
+ [!provide] PROVIDE (lmp_auto_rate_handler = 0x40026548)
+ [!provide] PROVIDE (lmp_pref_rate_handler = 0x4002657c)
+ [!provide] PROVIDE (lmp_name_req_handler = 0x40025050)
+ [!provide] PROVIDE (lmp_name_res_handler = 0x400250bc)
+ [!provide] PROVIDE (lmp_not_accepted_handler = 0x400251d0)
+ [!provide] PROVIDE (lmp_accepted_handler = 0x4002e894)
+ [!provide] PROVIDE (lmp_clk_off_req_handler = 0x40025a44)
+ [!provide] PROVIDE (lmp_clk_off_res_handler = 0x40025ab8)
+ [!provide] PROVIDE (lmp_detach_handler = 0x40025b74)
+ [!provide] PROVIDE (lmp_tempkey_handler = 0x4002b6b0)
+ [!provide] PROVIDE (lmp_temprand_handler = 0x4002b74c)
+ [!provide] PROVIDE (lmp_sres_handler = 0x4002b840)
+ [!provide] PROVIDE (lmp_aurand_handler = 0x4002bda0)
+ [!provide] PROVIDE (lmp_unitkey_handler = 0x4002c13c)
+ [!provide] PROVIDE (lmp_combkey_handler = 0x4002c234)
+ [!provide] PROVIDE (lmp_inrand_handler = 0x4002c414)
+ [!provide] PROVIDE (lmp_oob_fail_handler = 0x40027b84)
+ [!provide] PROVIDE (lmp_ping_req_handler = 0x40027c08)
+ [!provide] PROVIDE (lmp_ping_res_handler = 0x40027c5c)
+ [!provide] PROVIDE (lmp_enc_mode_req_handler = 0x40025c60)
+ [!provide] PROVIDE (lmp_enc_key_size_req_handler = 0x40025e54)
+ [!provide] PROVIDE (lmp_switch_req_handler = 0x40025f84)
+ [!provide] PROVIDE (lmp_start_enc_req_handler = 0x4002e124)
+ [!provide] PROVIDE (lmp_stop_enc_req_handler = 0x4002de30)
+ [!provide] PROVIDE (lmp_sniff_req_handler = 0x400260c8)
+ [!provide] PROVIDE (lmp_unsniff_req_handler = 0x400261e0)
+ [!provide] PROVIDE (lmp_incr_pwr_req_handler = 0x4002629c)
+ [!provide] PROVIDE (lmp_decr_pwr_req_handler = 0x400262f8)
+ [!provide] PROVIDE (lmp_max_pwr_handler = 0x40026354)
+ [!provide] PROVIDE (lmp_min_pwr_handler = 0x40026388)
+ [!provide] PROVIDE (lmp_ver_req_handler = 0x400265f0)
+ [!provide] PROVIDE (lmp_ver_res_handler = 0x40026670)
+ [!provide] PROVIDE (lmp_qos_handler = 0x40026790)
+ [!provide] PROVIDE (lmp_qos_req_handler = 0x40026844)
+ [!provide] PROVIDE (lmp_sco_link_req_handler = 0x40026930)
+ [!provide] PROVIDE (lmp_rmv_sco_link_req_handler = 0x40026a10)
+ [!provide] PROVIDE (lmp_max_slot_handler = 0x40026a54)
+ [!provide] PROVIDE (lmp_max_slot_req_handler = 0x40026aac)
+ [!provide] PROVIDE (lmp_timing_accu_req_handler = 0x40026b54)
+ [!provide] PROVIDE (lmp_timing_accu_res_handler = 0x40026bcc)
+ [!provide] PROVIDE (lmp_setup_cmp_handler = 0x40026c84)
+ [!provide] PROVIDE (lmp_feats_res_handler = 0x4002b548)
+ [!provide] PROVIDE (lmp_feats_req_handler = 0x4002b620)
+ [!provide] PROVIDE (lmp_host_con_req_handler = 0x4002b3d8)
+ [!provide] PROVIDE (lmp_use_semi_perm_key_handler = 0x4002b4c4)
+ [!provide] PROVIDE (lmp_slot_off_handler = 0x40026cc8)
+ [!provide] PROVIDE (lmp_page_mode_req_handler = 0x40026d0c)
+ [!provide] PROVIDE (lmp_page_scan_mode_req_handler = 0x40026d4c)
+ [!provide] PROVIDE (lmp_supv_to_handler = 0x40026d94)
+ [!provide] PROVIDE (lmp_test_activate_handler = 0x40026e7c)
+ [!provide] PROVIDE (lmp_test_ctrl_handler = 0x40026ee4)
+ [!provide] PROVIDE (lmp_enc_key_size_mask_req_handler = 0x40027038)
+ [!provide] PROVIDE (lmp_enc_key_size_mask_res_handler = 0x400270a4)
+ [!provide] PROVIDE (lmp_set_afh_handler = 0x4002b2e4)
+ [!provide] PROVIDE (lmp_encaps_hdr_handler = 0x40027120)
+ [!provide] PROVIDE (lmp_encaps_payl_handler = 0x4002e590)
+ [!provide] PROVIDE (lmp_sp_nb_handler = 0x4002acf0)
+ [!provide] PROVIDE (lmp_sp_cfm_handler = 0x4002b170)
+ [!provide] PROVIDE (lmp_dhkey_chk_handler = 0x4002ab48)
+ [!provide] PROVIDE (lmp_pause_enc_aes_req_handler = 0x400279a4)
+ [!provide] PROVIDE (lmp_io_cap_res_handler = 0x4002c670)
+ [!provide] PROVIDE (lmp_io_cap_req_handler = 0x4002c7a4)
+ [!provide] PROVIDE (lc_cmd_cmp_bd_addr_send = 0x4002cec4)
+ [!provide] PROVIDE (ld_acl_tx_packet_type_select = 0x4002fb40)
+ [!provide] PROVIDE (ld_acl_sched = 0x40033268)
+ [!provide] PROVIDE (ld_acl_sniff_sched = 0x4003340c)
+ [!provide] PROVIDE (ld_acl_rx = 0x4003274c)
+ [!provide] PROVIDE (ld_acl_tx = 0x4002ffdc)
+ [!provide] PROVIDE (ld_acl_rx_sync = 0x4002fbec)
+ [!provide] PROVIDE (ld_acl_rx_sync2 = 0x4002fd8c)
+ [!provide] PROVIDE (ld_acl_rx_no_sync = 0x4002fe78)
+ [!provide] PROVIDE (ld_acl_clk_isr = 0x40030cf8)
+ [!provide] PROVIDE (ld_acl_rsw_frm_cbk = 0x40033bb0)
+ [!provide] PROVIDE (ld_sco_modify = 0x40031778)
+ [!provide] PROVIDE (lm_cmd_cmp_send = 0x40051838)
+ [!provide] PROVIDE (ld_sco_frm_cbk = 0x400349dc)
+ [!provide] PROVIDE (ld_acl_sniff_frm_cbk = 0x4003482c)
+ [!provide] PROVIDE (ld_inq_end = 0x4003ab48)
+ [!provide] PROVIDE (ld_inq_sched = 0x4003aba4)
+ [!provide] PROVIDE (ld_inq_frm_cbk = 0x4003ae4c)
+ [!provide] PROVIDE (r_ld_acl_active_hop_types_get = 0x40036e10)
+ [!provide] PROVIDE (r_ld_acl_afh_confirm = 0x40036d40)
+ [!provide] PROVIDE (r_ld_acl_afh_prepare = 0x40036c84)
+ [!provide] PROVIDE (r_ld_acl_afh_set = 0x40036b60)
+ [!provide] PROVIDE (r_ld_acl_allowed_tx_packet_types_set = 0x40036810)
+ [!provide] PROVIDE (r_ld_acl_bcst_rx_dec = 0x40036394)
+ [!provide] PROVIDE (r_ld_acl_bit_off_get = 0x40036b18)
+ [!provide] PROVIDE (r_ld_acl_clk_adj_set = 0x40036a00)
+ [!provide] PROVIDE (r_ld_acl_clk_off_get = 0x40036b00)
+ [!provide] PROVIDE (r_ld_acl_clk_set = 0x40036950)
+ [!provide] PROVIDE (r_ld_acl_clock_offset_get = 0x400364c0)
+ [!provide] PROVIDE (r_ld_acl_current_tx_power_get = 0x400368f0)
+ [!provide] PROVIDE (r_ld_acl_data_flush = 0x400357bc)
+ [!provide] PROVIDE (r_ld_acl_data_tx = 0x4003544c)
+ [!provide] PROVIDE (r_ld_acl_edr_set = 0x4003678c)
+ [!provide] PROVIDE (r_ld_acl_enc_key_load = 0x40036404)
+ [!provide] PROVIDE (r_ld_acl_flow_off = 0x40035400)
+ [!provide] PROVIDE (r_ld_acl_flow_on = 0x4003541c)
+ [!provide] PROVIDE (r_ld_acl_flush_timeout_get = 0x40035f9c)
+ [!provide] PROVIDE (r_ld_acl_flush_timeout_set = 0x40035fe0)
+ [!provide] PROVIDE (r_ld_acl_init = 0x40034d08)
+ [!provide] PROVIDE (r_ld_acl_lmp_flush = 0x40035d80)
+ [!provide] PROVIDE (r_ld_acl_lmp_tx = 0x40035b34)
+ [!provide] PROVIDE (r_ld_acl_lsto_get = 0x400366b4)
+ [!provide] PROVIDE (r_ld_acl_lsto_set = 0x400366f8)
+ [!provide] PROVIDE (r_ld_acl_reset = 0x40034d24)
+ [!provide] PROVIDE (r_ld_acl_role_get = 0x40036b30)
+ [!provide] PROVIDE (r_ld_acl_rssi_delta_get = 0x40037028)
+ [!provide] PROVIDE (r_ld_acl_rsw_req = 0x40035e74)
+ [!provide] PROVIDE (r_ld_acl_rx_enc = 0x40036344)
+ [!provide] PROVIDE (r_ld_acl_rx_max_slot_get = 0x40036e58)
+ [!provide] PROVIDE (r_ld_acl_rx_max_slot_set = 0x40036ea0)
+ [!provide] PROVIDE (r_ld_acl_slot_offset_get = 0x4003653c)
+ [!provide] PROVIDE (r_ld_acl_slot_offset_set = 0x40036658)
+ [!provide] PROVIDE (r_ld_acl_sniff = 0x4003617c)
+ [!provide] PROVIDE (r_ld_acl_sniff_trans = 0x400360a8)
+ [!provide] PROVIDE (r_ld_acl_ssr_set = 0x40036274)
+ [!provide] PROVIDE (r_ld_acl_start = 0x40034ddc)
+ [!provide] PROVIDE (r_ld_acl_stop = 0x4003532c)
+ [!provide] PROVIDE (r_ld_acl_test_mode_set = 0x40036f24)
+ [!provide] PROVIDE (r_ld_acl_timing_accuracy_set = 0x4003673c)
+ [!provide] PROVIDE (r_ld_acl_t_poll_get = 0x40036024)
+ [!provide] PROVIDE (r_ld_acl_t_poll_set = 0x40036068)
+ [!provide] PROVIDE (r_ld_acl_tx_enc = 0x400362f8)
+ [!provide] PROVIDE (ld_acl_frm_cbk = 0x40034414)
+ [!provide] PROVIDE (ld_acl_rsw_end = 0x40032bc0)
+ [!provide] PROVIDE (ld_acl_end = 0x40033140)
+ [!provide] PROVIDE (ld_acl_resched = 0x40033814)
+ [!provide] PROVIDE (ld_acl_test_mode_update = 0x40032050)
+ [!provide] PROVIDE (r_ld_acl_unsniff = 0x400361e0)
+ [!provide] PROVIDE (r_ld_active_check = 0x4003cac4)
+ [!provide] PROVIDE (r_ld_afh_ch_assess_data_get = 0x4003caec)
+ [!provide] PROVIDE (r_ld_bcst_acl_data_tx = 0x40038d3c)
+ [!provide] PROVIDE (r_ld_bcst_acl_init = 0x40038bd0)
+ [!provide] PROVIDE (r_ld_bcst_acl_reset = 0x40038bdc)
+ [!provide] PROVIDE (r_ld_bcst_acl_start = 0x4003882c)
+ [!provide] PROVIDE (r_ld_bcst_afh_update = 0x40038f3c)
+ [!provide] PROVIDE (r_ld_bcst_enc_key_load = 0x4003906c)
+ [!provide] PROVIDE (r_ld_bcst_lmp_tx = 0x40038bf8)
+ [!provide] PROVIDE (r_ld_bcst_tx_enc = 0x40038ff8)
+ [!provide] PROVIDE (r_ld_bd_addr_get = 0x4003ca20)
+ [!provide] PROVIDE (r_ld_channel_assess = 0x4003c184)
+ [!provide] PROVIDE (r_ld_class_of_dev_get = 0x4003ca34)
+ [!provide] PROVIDE (r_ld_class_of_dev_set = 0x4003ca50)
+ [!provide] PROVIDE (r_ld_csb_rx_afh_update = 0x40039af4)
+ [!provide] PROVIDE (r_ld_csb_rx_init = 0x40039690)
+ [!provide] PROVIDE (r_ld_csb_rx_reset = 0x4003969c)
+ [!provide] PROVIDE (r_ld_csb_rx_start = 0x4003972c)
+ [!provide] PROVIDE (r_ld_csb_rx_stop = 0x40039bb8)
+ [!provide] PROVIDE (r_ld_csb_tx_afh_update = 0x4003a5fc)
+ [!provide] PROVIDE (r_ld_csb_tx_clr_data = 0x4003a71c)
+ [!provide] PROVIDE (r_ld_csb_tx_dis = 0x4003a5e8)
+ [!provide] PROVIDE (r_ld_csb_tx_en = 0x4003a1c0)
+ [!provide] PROVIDE (r_ld_csb_tx_init = 0x4003a0e8)
+ [!provide] PROVIDE (r_ld_csb_tx_reset = 0x4003a0f8)
+ [!provide] PROVIDE (r_ld_csb_tx_set_data = 0x4003a6c0)
+ [!provide] PROVIDE (r_ld_fm_clk_isr = 0x4003a7a8)
+ [!provide] PROVIDE (r_ld_fm_frame_isr = 0x4003a82c)
+ [!provide] PROVIDE (r_ld_fm_init = 0x4003a760)
+ [!provide] PROVIDE (r_ld_fm_prog_check = 0x4003ab28)
+ [!provide] PROVIDE (r_ld_fm_prog_disable = 0x4003a984)
+ [!provide] PROVIDE (r_ld_fm_prog_enable = 0x4003a944)
+ [!provide] PROVIDE (r_ld_fm_prog_push = 0x4003a9d4)
+ [!provide] PROVIDE (r_ld_fm_reset = 0x4003a794)
+ [!provide] PROVIDE (r_ld_fm_rx_isr = 0x4003a7f4)
+ [!provide] PROVIDE (r_ld_fm_sket_isr = 0x4003a8a4)
+ [!provide] PROVIDE (r_ld_init = 0x4003c294)
+ [!provide] PROVIDE (r_ld_inq_init = 0x4003b15c)
+ [!provide] PROVIDE (r_ld_inq_reset = 0x4003b168)
+ [!provide] PROVIDE (r_ld_inq_start = 0x4003b1f0)
+ [!provide] PROVIDE (r_ld_inq_stop = 0x4003b4f0)
+ [!provide] PROVIDE (r_ld_iscan_eir_get = 0x4003c118)
+ [!provide] PROVIDE (r_ld_iscan_eir_set = 0x4003bfa0)
+ [!provide] PROVIDE (r_ld_iscan_init = 0x4003b9f0)
+ [!provide] PROVIDE (r_ld_iscan_reset = 0x4003ba14)
+ [!provide] PROVIDE (r_ld_iscan_restart = 0x4003ba44)
+ [!provide] PROVIDE (r_ld_iscan_start = 0x4003bb28)
+ [!provide] PROVIDE (r_ld_iscan_stop = 0x4003bf1c)
+ [!provide] PROVIDE (r_ld_iscan_tx_pwr_get = 0x4003c138)
+ [!provide] PROVIDE (r_ld_page_init = 0x4003d808)
+ [!provide] PROVIDE (r_ld_page_reset = 0x4003d814)
+ [!provide] PROVIDE (r_ld_page_start = 0x4003d848)
+ [!provide] PROVIDE (r_ld_page_stop = 0x4003da54)
+ [!provide] PROVIDE (r_ld_pca_coarse_clock_adjust = 0x4003e324)
+ [!provide] PROVIDE (r_ld_pca_init = 0x4003deb4)
+ [!provide] PROVIDE (r_ld_pca_initiate_clock_dragging = 0x4003e4ac)
+ [!provide] PROVIDE (r_ld_pca_local_config = 0x4003df6c)
+ [!provide] PROVIDE (r_ld_pca_mws_frame_sync = 0x4003e104)
+ [!provide] PROVIDE (r_ld_pca_mws_moment_offset_gt = 0x4003e278)
+ [!provide] PROVIDE (r_ld_pca_mws_moment_offset_lt = 0x4003e280)
+ [!provide] PROVIDE (r_ld_pca_reporting_enable = 0x4003e018)
+ [!provide] PROVIDE (r_ld_pca_reset = 0x4003df0c)
+ [!provide] PROVIDE (r_ld_pca_update_target_offset = 0x4003e050)
+ [!provide] PROVIDE (r_ld_pscan_evt_handler = 0x4003f238)
+ [!provide] PROVIDE (r_ld_pscan_init = 0x4003f474)
+ [!provide] PROVIDE (r_ld_pscan_reset = 0x4003f498)
+ [!provide] PROVIDE (r_ld_pscan_restart = 0x4003f4b8)
+ [!provide] PROVIDE (r_ld_pscan_start = 0x4003f514)
+ [!provide] PROVIDE (r_ld_pscan_stop = 0x4003f618)
+ [!provide] PROVIDE (r_ld_read_clock = 0x4003c9e4)
+ [!provide] PROVIDE (r_ld_reset = 0x4003c714)
+ [!provide] PROVIDE (r_ld_sched_acl_add = 0x4003f978)
+ [!provide] PROVIDE (r_ld_sched_acl_remove = 0x4003f99c)
+ [!provide] PROVIDE (r_ld_sched_compute = 0x4003f6f8)
+ [!provide] PROVIDE (r_ld_sched_init = 0x4003f7ac)
+ [!provide] PROVIDE (r_ld_sched_inq_add = 0x4003f8a8)
+ [!provide] PROVIDE (r_ld_sched_inq_remove = 0x4003f8d0)
+ [!provide] PROVIDE (r_ld_sched_iscan_add = 0x4003f7e8)
+ [!provide] PROVIDE (r_ld_sched_iscan_remove = 0x4003f808)
+ [!provide] PROVIDE (r_ld_sched_page_add = 0x4003f910)
+ [!provide] PROVIDE (r_ld_sched_page_remove = 0x4003f938)
+ [!provide] PROVIDE (r_ld_sched_pscan_add = 0x4003f828)
+ [!provide] PROVIDE (r_ld_sched_pscan_remove = 0x4003f848)
+ [!provide] PROVIDE (r_ld_sched_reset = 0x4003f7d4)
+ [!provide] PROVIDE (r_ld_sched_sco_add = 0x4003fa4c)
+ [!provide] PROVIDE (r_ld_sched_sco_remove = 0x4003fa9c)
+ [!provide] PROVIDE (r_ld_sched_sniff_add = 0x4003f9c4)
+ [!provide] PROVIDE (r_ld_sched_sniff_remove = 0x4003fa0c)
+ [!provide] PROVIDE (r_ld_sched_sscan_add = 0x4003f868)
+ [!provide] PROVIDE (r_ld_sched_sscan_remove = 0x4003f888)
+ [!provide] PROVIDE (r_ld_sco_audio_isr = 0x40037cc8)
+ [!provide] PROVIDE (r_ld_sco_data_tx = 0x40037ee8)
+ [!provide] PROVIDE (r_ld_sco_start = 0x40037110)
+ [!provide] PROVIDE (r_ld_sco_stop = 0x40037c40)
+ [!provide] PROVIDE (r_ld_sco_update = 0x40037a74)
+ [!provide] PROVIDE (r_ld_sscan_activated = 0x4004031c)
+ [!provide] PROVIDE (r_ld_sscan_init = 0x400402f0)
+ [!provide] PROVIDE (r_ld_sscan_reset = 0x400402fc)
+ [!provide] PROVIDE (r_ld_sscan_start = 0x40040384)
+ [!provide] PROVIDE (r_ld_strain_init = 0x400409f4)
+ [!provide] PROVIDE (r_ld_strain_reset = 0x40040a00)
+ [!provide] PROVIDE (r_ld_strain_start = 0x40040a8c)
+ [!provide] PROVIDE (r_ld_strain_stop = 0x40040df0)
+ [!provide] PROVIDE (r_ld_timing_accuracy_get = 0x4003caac)
+ [!provide] PROVIDE (r_ld_util_active_master_afh_map_get = 0x4004131c)
+ [!provide] PROVIDE (r_ld_util_active_master_afh_map_set = 0x40041308)
+ [!provide] PROVIDE (r_ld_util_bch_create = 0x40040fcc)
+ [!provide] PROVIDE (r_ld_util_fhs_pk = 0x400411c8)
+ [!provide] PROVIDE (r_ld_util_fhs_unpk = 0x40040e54)
+ [!provide] PROVIDE (r_ld_util_stp_pk = 0x400413f4)
+ [!provide] PROVIDE (r_ld_util_stp_unpk = 0x40041324)
+ [!provide] PROVIDE (r_ld_version_get = 0x4003ca6c)
+ [!provide] PROVIDE (r_ld_wlcoex_set = 0x4003caf8)
+ [!provide] PROVIDE (r_llc_ch_assess_get_current_ch_map = 0x40041574)
+ [!provide] PROVIDE (r_llc_ch_assess_get_local_ch_map = 0x4004150c)
+ [!provide] PROVIDE (r_llc_ch_assess_local = 0x40041494)
+ [!provide] PROVIDE (r_llc_ch_assess_merge_ch = 0x40041588)
+ [!provide] PROVIDE (r_llc_ch_assess_reass_ch = 0x400415c0)
+ [!provide] PROVIDE (r_llc_common_cmd_complete_send = 0x40044eac)
+ [!provide] PROVIDE (r_llc_common_cmd_status_send = 0x40044ee0)
+ [!provide] PROVIDE (r_llc_common_enc_change_evt_send = 0x40044f6c)
+ [!provide] PROVIDE (r_llc_common_enc_key_ref_comp_evt_send = 0x40044f38)
+ [!provide] PROVIDE (r_llc_common_flush_occurred_send = 0x40044f0c)
+ [!provide] PROVIDE (r_llc_common_nb_of_pkt_comp_evt_send = 0x40045000)
+ [!provide] PROVIDE (r_llc_con_update_complete_send = 0x40044d68)
+ [!provide] PROVIDE (r_llc_con_update_finished = 0x4004518c)
+ [!provide] PROVIDE (r_llc_con_update_ind = 0x40045038)
+ [!provide] PROVIDE (r_llc_discon_event_complete_send = 0x40044a30)
+ [!provide] PROVIDE (r_llc_end_evt_defer = 0x40046330)
+ [!provide] PROVIDE (r_llc_feats_rd_event_send = 0x40044e0c)
+ [!provide] PROVIDE (r_llc_init = 0x40044778)
+ [!provide] PROVIDE (r_llc_le_con_cmp_evt_send = 0x40044a78)
+ [!provide] PROVIDE (r_llc_llcp_ch_map_update_pdu_send = 0x40043f94)
+ [!provide] PROVIDE (r_llc_llcp_con_param_req_pdu_send = 0x400442fc)
+ [!provide] PROVIDE (r_llc_llcp_con_param_rsp_pdu_send = 0x40044358)
+ [!provide] PROVIDE (r_llc_llcp_con_update_pdu_send = 0x400442c4)
+ [!provide] PROVIDE (r_llc_llcp_enc_req_pdu_send = 0x40044064)
+ [!provide] PROVIDE (r_llc_llcp_enc_rsp_pdu_send = 0x40044160)
+ [!provide] PROVIDE (r_llc_llcp_feats_req_pdu_send = 0x400443b4)
+ [!provide] PROVIDE (r_llc_llcp_feats_rsp_pdu_send = 0x400443f0)
+ [!provide] PROVIDE (r_llc_llcp_get_autorize = 0x4004475c)
+ [!provide] PROVIDE (r_llc_llcp_length_req_pdu_send = 0x40044574)
+ [!provide] PROVIDE (r_llc_llcp_length_rsp_pdu_send = 0x400445ac)
+ [!provide] PROVIDE (r_llc_llcp_pause_enc_req_pdu_send = 0x40043fd8)
+ [!provide] PROVIDE (r_llc_llcp_pause_enc_rsp_pdu_send = 0x40044010)
+ [!provide] PROVIDE (r_llc_llcp_ping_req_pdu_send = 0x4004454c)
+ [!provide] PROVIDE (r_llc_llcp_ping_rsp_pdu_send = 0x40044560)
+ [!provide] PROVIDE (r_llc_llcp_recv_handler = 0x40044678)
+ [!provide] PROVIDE (r_llc_llcp_reject_ind_pdu_send = 0x4004425c)
+ [!provide] PROVIDE (r_llc_llcp_start_enc_req_pdu_send = 0x4004441c)
+ [!provide] PROVIDE (r_llc_llcp_start_enc_rsp_pdu_send = 0x400441f8)
+ [!provide] PROVIDE (r_llc_llcp_terminate_ind_pdu_send = 0x400444b0)
+ [!provide] PROVIDE (r_llc_llcp_tester_send = 0x400445e4)
+ [!provide] PROVIDE (r_llc_llcp_unknown_rsp_send_pdu = 0x40044534)
+ [!provide] PROVIDE (r_llc_llcp_version_ind_pdu_send = 0x40043f6c)
+ [!provide] PROVIDE (r_llc_lsto_con_update = 0x40045098)
+ [!provide] PROVIDE (r_llc_ltk_req_send = 0x40044dc0)
+ [!provide] PROVIDE (r_llc_map_update_finished = 0x40045260)
+ [!provide] PROVIDE (r_llc_map_update_ind = 0x400450f0)
+ [!provide] PROVIDE (r_llc_pdu_acl_tx_ack_defer = 0x400464dc)
+ [!provide] PROVIDE (r_llc_pdu_defer = 0x40046528)
+ [!provide] PROVIDE (r_llc_pdu_llcp_tx_ack_defer = 0x400463ac)
+ [!provide] PROVIDE (r_llc_reset = 0x400447b8)
+ [!provide] PROVIDE (r_llc_start = 0x400447f4)
+ [!provide] PROVIDE (r_llc_stop = 0x400449ac)
+ [!provide] PROVIDE (r_llc_util_bw_mgt = 0x4004629c)
+ [!provide] PROVIDE (r_llc_util_clear_operation_ptr = 0x40046234)
+ [!provide] PROVIDE (r_llc_util_dicon_procedure = 0x40046130)
+ [!provide] PROVIDE (r_llc_util_get_free_conhdl = 0x400460c8)
+ [!provide] PROVIDE (r_llc_util_get_nb_active_link = 0x40046100)
+ [!provide] PROVIDE (r_llc_util_set_auth_payl_to_margin = 0x400461f4)
+ [!provide] PROVIDE (r_llc_util_set_llcp_discard_enable = 0x400461c8)
+ [!provide] PROVIDE (r_llc_util_update_channel_map = 0x400461ac)
+ [!provide] PROVIDE (r_llc_version_rd_event_send = 0x40044e60)
+ [!provide] PROVIDE (r_lld_adv_start = 0x40048b38)
+ [!provide] PROVIDE (r_lld_adv_stop = 0x40048ea0)
+ [!provide] PROVIDE (r_lld_ch_map_ind = 0x4004a2f4)
+ [!provide] PROVIDE (r_lld_con_param_req = 0x40049f0c)
+ [!provide] PROVIDE (r_lld_con_param_rsp = 0x40049e00)
+ [!provide] PROVIDE (r_lld_con_start = 0x400491f8)
+ [!provide] PROVIDE (r_lld_con_stop = 0x40049fdc)
+ [!provide] PROVIDE (r_lld_con_update_after_param_req = 0x40049bcc)
+ [!provide] PROVIDE (r_lld_con_update_ind = 0x4004a30c)
+ [!provide] PROVIDE (r_lld_con_update_req = 0x40049b60)
+ [!provide] PROVIDE (r_lld_core_reset = 0x40048a9c)
+ [!provide] PROVIDE (r_lld_crypt_isr = 0x4004a324)
+ [!provide] PROVIDE (r_lld_evt_adv_create = 0x400481f4)
+ [!provide] PROVIDE (r_lld_evt_canceled = 0x400485c8)
+ [!provide] PROVIDE (r_lld_evt_channel_next = 0x40046aac)
+ [!provide] PROVIDE (r_lld_evt_deffered_elt_handler = 0x400482bc)
+ [!provide] PROVIDE (r_lld_evt_delete_elt_handler = 0x40046974)
+ [!provide] PROVIDE (r_lld_evt_delete_elt_push = 0x40046a3c)
+ [!provide] PROVIDE (r_lld_evt_drift_compute = 0x40047670)
+ [!provide] PROVIDE (r_lld_evt_elt_delete = 0x40047538)
+ [!provide] PROVIDE (r_lld_evt_elt_insert = 0x400474c8)
+ [!provide] PROVIDE (r_lld_evt_end = 0x400483e8)
+ [!provide] PROVIDE (r_lld_evt_end_isr = 0x4004862c)
+ [!provide] PROVIDE (r_lld_evt_init = 0x40046b3c)
+ [!provide] PROVIDE (r_lld_evt_init_evt = 0x40046cd0)
+ [!provide] PROVIDE (r_lld_evt_move_to_master = 0x40047ba0)
+ [!provide] PROVIDE (r_lld_evt_move_to_slave = 0x40047e18)
+ [!provide] PROVIDE (r_lld_evt_prevent_stop = 0x40047adc)
+ [!provide] PROVIDE (r_lld_evt_restart = 0x40046d50)
+ [!provide] PROVIDE (r_lld_evt_rx = 0x40048578)
+ [!provide] PROVIDE (r_lld_evt_rx_isr = 0x40048678)
+ [!provide] PROVIDE (r_lld_evt_scan_create = 0x40047ae8)
+ [!provide] PROVIDE (r_lld_evt_schedule = 0x40047908)
+ [!provide] PROVIDE (r_lld_evt_schedule_next = 0x400477dc)
+ [!provide] PROVIDE (r_lld_evt_schedule_next_instant = 0x400476a8)
+ [!provide] PROVIDE (r_lld_evt_slave_update = 0x40048138)
+ [!provide] PROVIDE (r_lld_evt_update_create = 0x40047cd8)
+ [!provide] PROVIDE (r_lld_get_mode = 0x40049ff8)
+ [!provide] PROVIDE (r_lld_init = 0x4004873c)
+ [!provide] PROVIDE (r_lld_move_to_master = 0x400499e0)
+ [!provide] PROVIDE (r_lld_move_to_slave = 0x4004a024)
+ [!provide] PROVIDE (r_lld_pdu_adv_pack = 0x4004b488)
+ [!provide] PROVIDE (r_lld_pdu_check = 0x4004ac34)
+ [!provide] PROVIDE (r_lld_pdu_data_send = 0x4004b018)
+ [!provide] PROVIDE (r_lld_pdu_data_tx_push = 0x4004aecc)
+ [!provide] PROVIDE (r_lld_pdu_rx_handler = 0x4004b4d4)
+ [!provide] PROVIDE (r_lld_pdu_send_packet = 0x4004b774)
+ [!provide] PROVIDE (r_lld_pdu_tx_flush = 0x4004b414)
+ [!provide] PROVIDE (r_lld_pdu_tx_loop = 0x4004ae40)
+ [!provide] PROVIDE (r_lld_pdu_tx_prog = 0x4004b120)
+ [!provide] PROVIDE (r_lld_pdu_tx_push = 0x4004b080)
+ [!provide] PROVIDE (r_lld_ral_renew_req = 0x4004a73c)
+ [!provide] PROVIDE (r_lld_scan_start = 0x40048ee0)
+ [!provide] PROVIDE (r_lld_scan_stop = 0x40049190)
+ [!provide] PROVIDE (r_lld_test_mode_rx = 0x4004a540)
+ [!provide] PROVIDE (r_lld_test_mode_tx = 0x4004a350)
+ [!provide] PROVIDE (r_lld_test_stop = 0x4004a710)
+ [!provide] PROVIDE (r_lld_util_anchor_point_move = 0x4004bacc)
+ [!provide] PROVIDE (r_lld_util_compute_ce_max = 0x4004bc0c)
+ [!provide] PROVIDE (r_lld_util_connection_param_set = 0x4004ba40)
+ [!provide] PROVIDE (r_lld_util_dle_set_cs_fields = 0x4004ba90)
+ [!provide] PROVIDE (r_lld_util_eff_tx_time_set = 0x4004bd88)
+ [!provide] PROVIDE (r_lld_util_elt_programmed = 0x4004bce0)
+ [!provide] PROVIDE (r_lld_util_flush_list = 0x4004bbd8)
+ [!provide] PROVIDE (r_lld_util_freq2chnl = 0x4004b9e4)
+ [!provide] PROVIDE (r_lld_util_get_bd_address = 0x4004b8ac)
+ [!provide] PROVIDE (r_lld_util_get_local_offset = 0x4004ba10)
+ [!provide] PROVIDE (r_lld_util_get_peer_offset = 0x4004ba24)
+ [!provide] PROVIDE (r_lld_util_get_tx_pkt_cnt = 0x4004bd80)
+ [!provide] PROVIDE (r_lld_util_instant_get = 0x4004b890)
+ [!provide] PROVIDE (r_lld_util_instant_ongoing = 0x4004bbfc)
+ [!provide] PROVIDE (r_lld_util_priority_set = 0x4004bd10)
+ [!provide] PROVIDE (r_lld_util_priority_update = 0x4004bd78)
+ [!provide] PROVIDE (r_lld_util_ral_force_rpa_renew = 0x4004b980)
+ [!provide] PROVIDE (r_lld_util_set_bd_address = 0x4004b8f8)
+ [!provide] PROVIDE (r_lld_wlcoex_set = 0x4004bd98)
+ [!provide] PROVIDE (r_llm_ble_ready = 0x4004cc34)
+ [!provide] PROVIDE (r_llm_common_cmd_complete_send = 0x4004d288)
+ [!provide] PROVIDE (r_llm_common_cmd_status_send = 0x4004d2b4)
+ [!provide] PROVIDE (r_llm_con_req_ind = 0x4004cc54)
+ [!provide] PROVIDE (r_llm_con_req_tx_cfm = 0x4004d158)
+ [!provide] PROVIDE (r_llm_create_con = 0x4004de78)
+ [!provide] PROVIDE (r_llm_encryption_done = 0x4004dff8)
+ [!provide] PROVIDE (r_llm_encryption_start = 0x4004e128)
+ [!provide] PROVIDE (r_llm_end_evt_defer = 0x4004eb6c)
+ [!provide] PROVIDE (r_llm_init = 0x4004c9f8)
+ [!provide] PROVIDE (r_llm_le_adv_report_ind = 0x4004cdf4)
+ [!provide] PROVIDE (r_llm_pdu_defer = 0x4004ec48)
+ [!provide] PROVIDE (r_llm_ral_clear = 0x4004e1fc)
+ [!provide] PROVIDE (r_llm_ral_dev_add = 0x4004e23c)
+ [!provide] PROVIDE (r_llm_ral_dev_rm = 0x4004e3bc)
+ [!provide] PROVIDE (r_llm_ral_get_rpa = 0x4004e400)
+ [!provide] PROVIDE (r_llm_ral_set_timeout = 0x4004e4a0)
+ [!provide] PROVIDE (r_llm_ral_update = 0x4004e4f8)
+ [!provide] PROVIDE (r_llm_set_adv_data = 0x4004d960)
+ [!provide] PROVIDE (r_llm_set_adv_en = 0x4004d7ec)
+ [!provide] PROVIDE (r_llm_set_adv_param = 0x4004d5f4)
+ [!provide] PROVIDE (r_llm_set_scan_en = 0x4004db64)
+ [!provide] PROVIDE (r_llm_set_scan_param = 0x4004dac8)
+ [!provide] PROVIDE (r_llm_set_scan_rsp_data = 0x4004da14)
+ [!provide] PROVIDE (r_llm_test_mode_start_rx = 0x4004d534)
+ [!provide] PROVIDE (r_llm_test_mode_start_tx = 0x4004d2fc)
+ [!provide] PROVIDE (r_llm_util_adv_data_update = 0x4004e8fc)
+ [!provide] PROVIDE (r_llm_util_apply_bd_addr = 0x4004e868)
+ [!provide] PROVIDE (r_llm_util_bd_addr_in_ral = 0x4004eb08)
+ [!provide] PROVIDE (r_llm_util_bd_addr_in_wl = 0x4004e788)
+ [!provide] PROVIDE (r_llm_util_bd_addr_wl_position = 0x4004e720)
+ [!provide] PROVIDE (r_llm_util_bl_add = 0x4004e9ac)
+ [!provide] PROVIDE (r_llm_util_bl_check = 0x4004e930)
+ [!provide] PROVIDE (r_llm_util_bl_rem = 0x4004ea70)
+ [!provide] PROVIDE (r_llm_util_check_address_validity = 0x4004e7e4)
+ [!provide] PROVIDE (r_llm_util_check_evt_mask = 0x4004e8b0)
+ [!provide] PROVIDE (r_llm_util_check_map_validity = 0x4004e800)
+ [!provide] PROVIDE (r_llm_util_get_channel_map = 0x4004e8d4)
+ [!provide] PROVIDE (r_llm_util_get_supp_features = 0x4004e8e8)
+ [!provide] PROVIDE (r_llm_util_set_public_addr = 0x4004e89c)
+ [!provide] PROVIDE (r_llm_wl_clr = 0x4004dc54)
+ [!provide] PROVIDE (r_llm_wl_dev_add = 0x4004dcc0)
+ [!provide] PROVIDE (r_llm_wl_dev_add_hdl = 0x4004dd38)
+ [!provide] PROVIDE (r_llm_wl_dev_rem = 0x4004dcfc)
+ [!provide] PROVIDE (r_llm_wl_dev_rem_hdl = 0x4004dde0)
+ [!provide] PROVIDE (r_lm_acl_disc = 0x4004f148)
+ [!provide] PROVIDE (r_LM_AddSniff = 0x40022d20)
+ [!provide] PROVIDE (r_lm_add_sync = 0x40051358)
+ [!provide] PROVIDE (r_lm_afh_activate_timer = 0x4004f444)
+ [!provide] PROVIDE (r_lm_afh_ch_ass_en_get = 0x4004f3f8)
+ [!provide] PROVIDE (r_lm_afh_host_ch_class_get = 0x4004f410)
+ [!provide] PROVIDE (r_lm_afh_master_ch_map_get = 0x4004f43c)
+ [!provide] PROVIDE (r_lm_afh_peer_ch_class_set = 0x4004f418)
+ [!provide] PROVIDE (r_lm_check_active_sync = 0x40051334)
+ [!provide] PROVIDE (r_LM_CheckEdrFeatureRequest = 0x4002f90c)
+ [!provide] PROVIDE (r_LM_CheckSwitchInstant = 0x4002f8c0)
+ [!provide] PROVIDE (r_lm_check_sync_hl_rsp = 0x4005169c)
+ [!provide] PROVIDE (r_lm_clk_adj_ack_pending_clear = 0x4004f514)
+ [!provide] PROVIDE (r_lm_clk_adj_instant_pending_set = 0x4004f4d8)
+ [!provide] PROVIDE (r_LM_ComputePacketType = 0x4002f554)
+ [!provide] PROVIDE (r_LM_ComputeSniffSubRate = 0x400233ac)
+ [!provide] PROVIDE (r_lm_debug_key_compare_192 = 0x4004f3a8)
+ [!provide] PROVIDE (r_lm_debug_key_compare_256 = 0x4004f3d0)
+ [!provide] PROVIDE (r_lm_dhkey_calc_init = 0x40013234)
+ [!provide] PROVIDE (r_lm_dhkey_compare = 0x400132d8)
+ [!provide] PROVIDE (r_lm_dut_mode_en_get = 0x4004f3ec)
+ [!provide] PROVIDE (r_LM_ExtractMaxEncKeySize = 0x4001aca4)
+ [!provide] PROVIDE (r_lm_f1 = 0x40012bb8)
+ [!provide] PROVIDE (r_lm_f2 = 0x40012cfc)
+ [!provide] PROVIDE (r_lm_f3 = 0x40013050)
+ [!provide] PROVIDE (r_lm_g = 0x40012f90)
+ [!provide] PROVIDE (r_LM_GetAFHSwitchInstant = 0x4002f86c)
+ [!provide] PROVIDE (r_lm_get_auth_en = 0x4004f1ac)
+ [!provide] PROVIDE (r_lm_get_common_pkt_types = 0x4002fa1c)
+ [!provide] PROVIDE (r_LM_GetConnectionAcceptTimeout = 0x4004f1f4)
+ [!provide] PROVIDE (r_LM_GetFeature = 0x4002f924)
+ [!provide] PROVIDE (r_LM_GetLinkTimeout = 0x400233ec)
+ [!provide] PROVIDE (r_LM_GetLocalNameSeg = 0x4004f200)
+ [!provide] PROVIDE (r_lm_get_loopback_mode = 0x4004f248)
+ [!provide] PROVIDE (r_LM_GetMasterEncKeySize = 0x4001b29c)
+ [!provide] PROVIDE (r_LM_GetMasterEncRand = 0x4001b288)
+ [!provide] PROVIDE (r_LM_GetMasterKey = 0x4001b260)
+ [!provide] PROVIDE (r_LM_GetMasterKeyRand = 0x4001b274)
+ [!provide] PROVIDE (r_lm_get_min_sync_intv = 0x400517a8)
+ [!provide] PROVIDE (r_lm_get_nb_acl = 0x4004ef9c)
+ [!provide] PROVIDE (r_lm_get_nb_sync_link = 0x4005179c)
+ [!provide] PROVIDE (r_lm_get_nonce = 0x400131c4)
+ [!provide] PROVIDE (r_lm_get_oob_local_commit = 0x4004f374)
+ [!provide] PROVIDE (r_lm_get_oob_local_data_192 = 0x4004f2d4)
+ [!provide] PROVIDE (r_lm_get_oob_local_data_256 = 0x4004f318)
+ [!provide] PROVIDE (r_LM_GetPINType = 0x4004f1e8)
+ [!provide] PROVIDE (r_lm_get_priv_key_192 = 0x4004f278)
+ [!provide] PROVIDE (r_lm_get_priv_key_256 = 0x4004f2b8)
+ [!provide] PROVIDE (r_lm_get_pub_key_192 = 0x4004f258)
+ [!provide] PROVIDE (r_lm_get_pub_key_256 = 0x4004f298)
+ [!provide] PROVIDE (r_LM_GetQoSParam = 0x4002f6e0)
+ [!provide] PROVIDE (r_lm_get_sec_con_host_supp = 0x4004f1d4)
+ [!provide] PROVIDE (r_LM_GetSniffSubratingParam = 0x4002325c)
+ [!provide] PROVIDE (r_lm_get_sp_en = 0x4004f1c0)
+ [!provide] PROVIDE (r_LM_GetSwitchInstant = 0x4002f7f8)
+ [!provide] PROVIDE (r_lm_get_synchdl = 0x4005175c)
+ [!provide] PROVIDE (r_lm_get_sync_param = 0x400503b4)
+ [!provide] PROVIDE (r_lm_init = 0x4004ed34)
+ [!provide] PROVIDE (r_lm_init_sync = 0x400512d8)
+ [!provide] PROVIDE (r_lm_is_acl_con = 0x4004f47c)
+ [!provide] PROVIDE (r_lm_is_acl_con_role = 0x4004f49c)
+ [!provide] PROVIDE (r_lm_is_clk_adj_ack_pending = 0x4004f4e8)
+ [!provide] PROVIDE (r_lm_is_clk_adj_instant_pending = 0x4004f4c8)
+ [!provide] PROVIDE (r_lm_local_ext_fr_configured = 0x4004f540)
+ [!provide] PROVIDE (r_lm_look_for_stored_link_key = 0x4002f948)
+ [!provide] PROVIDE (r_lm_look_for_sync = 0x40051774)
+ [!provide] PROVIDE (r_lm_lt_addr_alloc = 0x4004ef1c)
+ [!provide] PROVIDE (r_lm_lt_addr_free = 0x4004ef74)
+ [!provide] PROVIDE (r_lm_lt_addr_reserve = 0x4004ef48)
+ [!provide] PROVIDE (r_LM_MakeCof = 0x4002f84c)
+ [!provide] PROVIDE (r_LM_MakeRandVec = 0x400112d8)
+ [!provide] PROVIDE (r_lm_master_clk_adj_req_handler = 0x40054180)
+ [!provide] PROVIDE (r_LM_MaxSlot = 0x4002f694)
+ [!provide] PROVIDE (r_lm_modif_sync = 0x40051578)
+ [!provide] PROVIDE (r_lm_n_is_zero = 0x40012170)
+ [!provide] PROVIDE (r_lm_num_clk_adj_ack_pending_set = 0x4004f500)
+ [!provide] PROVIDE (r_lm_oob_f1 = 0x40012e54)
+ [!provide] PROVIDE (r_lm_pca_sscan_link_get = 0x4004f560)
+ [!provide] PROVIDE (r_lm_pca_sscan_link_set = 0x4004f550)
+ [!provide] PROVIDE (nvds_null_read = 0x400542a0)
+ [!provide] PROVIDE (nvds_null_write = 0x400542a8)
+ [!provide] PROVIDE (nvds_null_erase = 0x400542b0)
+ [!provide] PROVIDE (nvds_read = 0x400542c4)
+ [!provide] PROVIDE (nvds_write = 0x400542fc)
+ [!provide] PROVIDE (nvds_erase = 0x40054334)
+ [!provide] PROVIDE (nvds_init_memory = 0x40054358)
+ [!provide] PROVIDE (r_lmp_pack = 0x4001135c)
+ [!provide] PROVIDE (r_lmp_unpack = 0x4001149c)
+ [!provide] PROVIDE (r_lm_read_features = 0x4004f0d8)
+ [!provide] PROVIDE (r_LM_RemoveSniff = 0x40023124)
+ [!provide] PROVIDE (r_LM_RemoveSniffSubrating = 0x400233c4)
+ [!provide] PROVIDE (r_lm_remove_sync = 0x400517c8)
+ [!provide] PROVIDE (r_lm_reset_sync = 0x40051304)
+ [!provide] PROVIDE (r_lm_role_switch_finished = 0x4004f028)
+ [!provide] PROVIDE (r_lm_role_switch_start = 0x4004efe0)
+ [!provide] PROVIDE (r_lm_sco_nego_end = 0x40051828)
+ [!provide] PROVIDE (r_LM_SniffSubrateNegoRequired = 0x40023334)
+ [!provide] PROVIDE (r_LM_SniffSubratingHlReq = 0x40023154)
+ [!provide] PROVIDE (r_LM_SniffSubratingPeerReq = 0x400231dc)
+ [!provide] PROVIDE (r_lm_sp_debug_mode_get = 0x4004f398)
+ [!provide] PROVIDE (r_lm_sp_n192_convert_wnaf = 0x400123c0)
+ [!provide] PROVIDE (r_lm_sp_n_one = 0x400123a4)
+ [!provide] PROVIDE (r_lm_sp_p192_add = 0x40012828)
+ [!provide] PROVIDE (r_lm_sp_p192_dbl = 0x4001268c)
+ [!provide] PROVIDE (r_lm_sp_p192_invert = 0x40012b6c)
+ [!provide] PROVIDE (r_lm_sp_p192_point_jacobian_to_affine = 0x40012468)
+ [!provide] PROVIDE (r_lm_sp_p192_points_jacobian_to_affine = 0x400124e4)
+ [!provide] PROVIDE (r_lm_sp_p192_point_to_inf = 0x40012458)
+ [!provide] PROVIDE (r_lm_sp_pre_compute_points = 0x40012640)
+ [!provide] PROVIDE (r_lm_sp_sha256_calculate = 0x400121a0)
+ [!provide] PROVIDE (r_LM_SuppressAclPacket = 0x4002f658)
+ [!provide] PROVIDE (r_lm_sync_flow_ctrl_en_get = 0x4004f404)
+ [!provide] PROVIDE (r_LM_UpdateAclEdrPacketType = 0x4002f5d8)
+ [!provide] PROVIDE (r_LM_UpdateAclPacketType = 0x4002f584)
+ [!provide] PROVIDE (r_modules_funcs = 0x3ffafd6c)
+ [!provide] PROVIDE (r_modules_funcs_p = 0x3ffafd68)
+ [!provide] PROVIDE (r_nvds_del = 0x400544c4)
+ [!provide] PROVIDE (r_nvds_get = 0x40054488)
+ [!provide] PROVIDE (r_nvds_init = 0x40054410)
+ [!provide] PROVIDE (r_nvds_lock = 0x400544fc)
+ [!provide] PROVIDE (r_nvds_put = 0x40054534)
+ [!provide] PROVIDE (rom_abs_temp = 0x400054f0)
+ [!provide] PROVIDE (rom_bb_bss_bw_40_en = 0x4000401c)
+ [!provide] PROVIDE (rom_bb_bss_cbw40_dig = 0x40003bac)
+ [!provide] PROVIDE (rom_bb_rx_ht20_cen_bcov_en = 0x40003734)
+ [!provide] PROVIDE (rom_bb_tx_ht20_cen = 0x40003760)
+ [!provide] PROVIDE (rom_bb_wdg_test_en = 0x40003b70)
+ [!provide] PROVIDE (rom_cbw2040_cfg = 0x400040b0)
+ [!provide] PROVIDE (rom_check_noise_floor = 0x40003c78)
+ [!provide] PROVIDE (rom_chip_i2c_readReg = 0x40004110)
+ [!provide] PROVIDE (rom_chip_i2c_writeReg = 0x40004168)
+ [!provide] PROVIDE (rom_chip_v7_bt_init = 0x40004d8c)
+ [!provide] PROVIDE (rom_chip_v7_rx_init = 0x40004cec)
+ [!provide] PROVIDE (rom_chip_v7_rx_rifs_en = 0x40003d90)
+ [!provide] PROVIDE (rom_chip_v7_tx_init = 0x40004d18)
+ [!provide] PROVIDE (rom_clk_force_on_vit = 0x40003710)
+ [!provide] PROVIDE (rom_correct_rf_ana_gain = 0x400062a8)
+ [!provide] PROVIDE (rom_dc_iq_est = 0x400055c8)
+ [!provide] PROVIDE (rom_disable_agc = 0x40002fa4)
+ [!provide] PROVIDE (rom_enable_agc = 0x40002fcc)
+ [!provide] PROVIDE (rom_en_pwdet = 0x4000506c)
+ [!provide] PROVIDE (rom_gen_rx_gain_table = 0x40003e3c)
+ [!provide] PROVIDE (rom_get_data_sat = 0x4000312c)
+ [!provide] PROVIDE (rom_get_fm_sar_dout = 0x40005204)
+ [!provide] PROVIDE (rom_get_power_db = 0x40005fc8)
+ [!provide] PROVIDE (rom_get_pwctrl_correct = 0x400065d4)
+ [!provide] PROVIDE (rom_get_rfcal_rxiq_data = 0x40005bbc)
+ [!provide] PROVIDE (rom_get_rf_gain_qdb = 0x40006290)
+ [!provide] PROVIDE (rom_get_sar_dout = 0x40006564)
+ [!provide] PROVIDE (rom_i2c_readReg = 0x40004148)
+ 0x00000000400041c0 PROVIDE (rom_i2c_readReg_Mask = 0x400041c0)
+ 0x00000000400041a4 PROVIDE (rom_i2c_writeReg = 0x400041a4)
+ 0x00000000400041fc PROVIDE (rom_i2c_writeReg_Mask = 0x400041fc)
+ [!provide] PROVIDE (rom_index_to_txbbgain = 0x40004df8)
+ [!provide] PROVIDE (rom_iq_est_disable = 0x40005590)
+ [!provide] PROVIDE (rom_iq_est_enable = 0x40005514)
+ [!provide] PROVIDE (rom_linear_to_db = 0x40005f64)
+ [!provide] PROVIDE (rom_loopback_mode_en = 0x400030f8)
+ [!provide] PROVIDE (rom_meas_tone_pwr_db = 0x40006004)
+ [!provide] PROVIDE (rom_mhz2ieee = 0x4000404c)
+ [!provide] PROVIDE (rom_noise_floor_auto_set = 0x40003bdc)
+ [!provide] PROVIDE (rom_pbus_debugmode = 0x40004458)
+ [!provide] PROVIDE (rom_pbus_force_mode = 0x40004270)
+ [!provide] PROVIDE (rom_pbus_force_test = 0x400043c0)
+ [!provide] PROVIDE (rom_pbus_rd = 0x40004414)
+ [!provide] PROVIDE (rom_pbus_rd_addr = 0x40004334)
+ [!provide] PROVIDE (rom_pbus_rd_shift = 0x40004374)
+ [!provide] PROVIDE (rom_pbus_rx_dco_cal = 0x40005620)
+ [!provide] PROVIDE (rom_pbus_set_dco = 0x40004638)
+ [!provide] PROVIDE (rom_pbus_set_rxgain = 0x40004480)
+ [!provide] PROVIDE (rom_pbus_workmode = 0x4000446c)
+ [!provide] PROVIDE (rom_pbus_xpd_rx_off = 0x40004508)
+ [!provide] PROVIDE (rom_pbus_xpd_rx_on = 0x4000453c)
+ [!provide] PROVIDE (rom_pbus_xpd_tx_off = 0x40004590)
+ [!provide] PROVIDE (rom_pbus_xpd_tx_on = 0x400045e0)
+ [!provide] PROVIDE (rom_phy_disable_agc = 0x40002f6c)
+ [!provide] PROVIDE (rom_phy_disable_cca = 0x40003000)
+ [!provide] PROVIDE (rom_phy_enable_agc = 0x40002f88)
+ [!provide] PROVIDE (rom_phy_enable_cca = 0x4000302c)
+ [!provide] PROVIDE (rom_phy_freq_correct = 0x40004b44)
+ [!provide] PROVIDE (rom_phyFuns = 0x3ffae0c0)
+ [!provide] PROVIDE (rom_phy_get_noisefloor = 0x40003c2c)
+ [!provide] PROVIDE (rom_phy_get_vdd33 = 0x4000642c)
+ [!provide] PROVIDE (rom_pow_usr = 0x40003044)
+ [!provide] PROVIDE (rom_read_sar_dout = 0x400051c0)
+ [!provide] PROVIDE (rom_restart_cal = 0x400046e0)
+ [!provide] PROVIDE (rom_rfcal_pwrctrl = 0x40006058)
+ [!provide] PROVIDE (rom_rfcal_rxiq = 0x40005b4c)
+ [!provide] PROVIDE (rom_rfcal_txcap = 0x40005dec)
+ [!provide] PROVIDE (rom_rfpll_reset = 0x40004680)
+ [!provide] PROVIDE (rom_rfpll_set_freq = 0x400047f8)
+ [!provide] PROVIDE (rom_rtc_mem_backup = 0x40003db4)
+ [!provide] PROVIDE (rom_rtc_mem_recovery = 0x40003df4)
+ [!provide] PROVIDE (rom_rx_gain_force = 0x4000351c)
+ [!provide] PROVIDE (rom_rxiq_cover_mg_mp = 0x40005a68)
+ [!provide] PROVIDE (rom_rxiq_get_mis = 0x400058e4)
+ [!provide] PROVIDE (rom_rxiq_set_reg = 0x40005a00)
+ [!provide] PROVIDE (rom_set_cal_rxdc = 0x400030b8)
+ [!provide] PROVIDE (rom_set_chan_cal_interp = 0x40005ce0)
+ [!provide] PROVIDE (rom_set_channel_freq = 0x40004880)
+ [!provide] PROVIDE (rom_set_loopback_gain = 0x40003060)
+ [!provide] PROVIDE (rom_set_noise_floor = 0x40003d48)
+ [!provide] PROVIDE (rom_set_pbus_mem = 0x400031a4)
+ [!provide] PROVIDE (rom_set_rf_freq_offset = 0x40004ca8)
+ [!provide] PROVIDE (rom_set_rxclk_en = 0x40003594)
+ [!provide] PROVIDE (rom_set_txcap_reg = 0x40005d50)
+ [!provide] PROVIDE (rom_set_txclk_en = 0x40003564)
+ [!provide] PROVIDE (rom_spur_coef_cfg = 0x40003ac8)
+ [!provide] PROVIDE (rom_spur_reg_write_one_tone = 0x400037f0)
+ [!provide] PROVIDE (rom_start_tx_tone = 0x400036b4)
+ [!provide] PROVIDE (rom_start_tx_tone_step = 0x400035d0)
+ [!provide] PROVIDE (rom_stop_tx_tone = 0x40003f98)
+ [!provide] PROVIDE (_rom_store = 0x4000d66c)
+ [!provide] PROVIDE (_rom_store_table = 0x4000d4f8)
+ [!provide] PROVIDE (rom_target_power_add_backoff = 0x40006268)
+ [!provide] PROVIDE (rom_tx_atten_set_interp = 0x400061cc)
+ [!provide] PROVIDE (rom_txbbgain_to_index = 0x40004dc0)
+ [!provide] PROVIDE (rom_txcal_work_mode = 0x4000510c)
+ [!provide] PROVIDE (rom_txdc_cal_init = 0x40004e10)
+ [!provide] PROVIDE (rom_txdc_cal_v70 = 0x40004ea4)
+ [!provide] PROVIDE (rom_txiq_cover = 0x4000538c)
+ [!provide] PROVIDE (rom_txiq_get_mis_pwr = 0x400052dc)
+ [!provide] PROVIDE (rom_txiq_set_reg = 0x40005154)
+ [!provide] PROVIDE (rom_tx_pwctrl_bg_init = 0x4000662c)
+ [!provide] PROVIDE (rom_txtone_linear_pwr = 0x40005290)
+ [!provide] PROVIDE (rom_wait_rfpll_cal_end = 0x400047a8)
+ [!provide] PROVIDE (rom_write_gain_mem = 0x4000348c)
+ [!provide] PROVIDE (rom_write_rfpll_sdm = 0x40004740)
+ [!provide] PROVIDE (roundup2 = 0x4000ab7c)
+ [!provide] PROVIDE (r_plf_funcs_p = 0x3ffb8360)
+ [!provide] PROVIDE (r_rf_rw_bt_init = 0x40054868)
+ [!provide] PROVIDE (r_rf_rw_init = 0x40054b0c)
+ [!provide] PROVIDE (r_rf_rw_le_init = 0x400549d0)
+ [!provide] PROVIDE (r_rwble_activity_ongoing_check = 0x40054d8c)
+ [!provide] PROVIDE (r_rwble_init = 0x40054bf4)
+ [!provide] PROVIDE (r_rwble_isr = 0x40054e08)
+ [!provide] PROVIDE (r_rwble_reset = 0x40054ce8)
+ [!provide] PROVIDE (r_rwble_sleep_check = 0x40054d78)
+ [!provide] PROVIDE (r_rwble_version = 0x40054dac)
+ [!provide] PROVIDE (r_rwbt_init = 0x40055160)
+ [!provide] PROVIDE (r_rwbt_isr = 0x40055248)
+ [!provide] PROVIDE (r_rwbt_reset = 0x400551bc)
+ [!provide] PROVIDE (r_rwbt_sleep_check = 0x4005577c)
+ [!provide] PROVIDE (r_rwbt_sleep_enter = 0x400557a4)
+ [!provide] PROVIDE (r_rwbt_sleep_wakeup = 0x400557fc)
+ [!provide] PROVIDE (r_rwbt_sleep_wakeup_end = 0x400558cc)
+ [!provide] PROVIDE (r_rwbt_version = 0x4005520c)
+ [!provide] PROVIDE (r_rwip_assert_err = 0x40055f88)
+ [!provide] PROVIDE (r_rwip_check_wakeup_boundary = 0x400558fc)
+ [!provide] PROVIDE (r_rwip_ext_wakeup_enable = 0x40055f3c)
+ [!provide] PROVIDE (r_rwip_init = 0x4005595c)
+ [!provide] PROVIDE (r_rwip_pca_clock_dragging_only = 0x40055f48)
+ [!provide] PROVIDE (r_rwip_prevent_sleep_clear = 0x40055ec8)
+ [!provide] PROVIDE (r_rwip_prevent_sleep_set = 0x40055e64)
+ [!provide] PROVIDE (r_rwip_reset = 0x40055ab8)
+ [!provide] PROVIDE (r_rwip_schedule = 0x40055b38)
+ [!provide] PROVIDE (r_rwip_sleep = 0x40055b5c)
+ [!provide] PROVIDE (r_rwip_sleep_enable = 0x40055f30)
+ [!provide] PROVIDE (r_rwip_version = 0x40055b20)
+ [!provide] PROVIDE (r_rwip_wakeup = 0x40055dc4)
+ [!provide] PROVIDE (r_rwip_wakeup_delay_set = 0x40055e4c)
+ [!provide] PROVIDE (r_rwip_wakeup_end = 0x40055e18)
+ [!provide] PROVIDE (r_rwip_wlcoex_set = 0x40055f60)
+ [!provide] PROVIDE (r_SHA_256 = 0x40013a90)
+ [!provide] PROVIDE (rwip_coex_cfg = 0x3ff9914c)
+ [!provide] PROVIDE (rwip_priority = 0x3ff99159)
+ [!provide] PROVIDE (rwip_rf = 0x3ffbdb28)
+ [!provide] PROVIDE (rwip_rf_p_get = 0x400558f4)
+ [!provide] PROVIDE (r_XorKey = 0x400112c0)
+ [!provide] PROVIDE (sha_blk_bits = 0x3ff99290)
+ [!provide] PROVIDE (sha_blk_bits_bytes = 0x3ff99288)
+ [!provide] PROVIDE (sha_blk_hash_bytes = 0x3ff9928c)
+ [!provide] PROVIDE (sig_matrix = 0x3ffae293)
+ [!provide] PROVIDE (sip_after_tx_complete = 0x4000b358)
+ [!provide] PROVIDE (sip_alloc_to_host_evt = 0x4000ab9c)
+ [!provide] PROVIDE (sip_get_ptr = 0x4000b34c)
+ [!provide] PROVIDE (sip_get_state = 0x4000ae2c)
+ [!provide] PROVIDE (sip_init_attach = 0x4000ae58)
+ [!provide] PROVIDE (sip_install_rx_ctrl_cb = 0x4000ae10)
+ [!provide] PROVIDE (sip_install_rx_data_cb = 0x4000ae20)
+ [!provide] PROVIDE (sip_is_active = 0x4000b3c0)
+ [!provide] PROVIDE (sip_post_init = 0x4000aed8)
+ [!provide] PROVIDE (sip_reclaim_from_host_cmd = 0x4000adbc)
+ [!provide] PROVIDE (sip_reclaim_tx_data_pkt = 0x4000ad5c)
+ [!provide] PROVIDE (sip_send = 0x4000af54)
+ [!provide] PROVIDE (sip_to_host_chain_append = 0x4000aef8)
+ [!provide] PROVIDE (sip_to_host_evt_send_done = 0x4000ac04)
+ [!provide] PROVIDE (slc_add_credits = 0x4000baf4)
+ [!provide] PROVIDE (slc_enable = 0x4000b64c)
+ [!provide] PROVIDE (slc_from_host_chain_fetch = 0x4000b7e8)
+ [!provide] PROVIDE (slc_from_host_chain_recycle = 0x4000bb10)
+ [!provide] PROVIDE (slc_has_pkt_to_host = 0x4000b5fc)
+ [!provide] PROVIDE (slc_init_attach = 0x4000b918)
+ [!provide] PROVIDE (slc_init_credit = 0x4000badc)
+ [!provide] PROVIDE (slc_reattach = 0x4000b62c)
+ [!provide] PROVIDE (slc_send_to_host_chain = 0x4000b6a0)
+ [!provide] PROVIDE (slc_set_host_io_max_window = 0x4000b89c)
+ [!provide] PROVIDE (slc_to_host_chain_recycle = 0x4000b758)
+ [!provide] PROVIDE (specialModP256 = 0x4001600c)
+ [!provide] PROVIDE (__stack = 0x3ffe3f20)
+ [!provide] PROVIDE (__stack_app = 0x3ffe7e30)
+ [!provide] PROVIDE (_stack_sentry = 0x3ffe1320)
+ [!provide] PROVIDE (_stack_sentry_app = 0x3ffe5230)
+ [!provide] PROVIDE (_start = 0x40000704)
+ [!provide] PROVIDE (start_tb_console = 0x4005a980)
+ [!provide] PROVIDE (_stat_r = 0x4000bcb4)
+ [!provide] PROVIDE (_stext = 0x40000560)
+ [!provide] PROVIDE (SubtractBigHex256 = 0x40015bcc)
+ [!provide] PROVIDE (SubtractBigHexMod256 = 0x40015e8c)
+ [!provide] PROVIDE (SubtractBigHexUint32_256 = 0x40015f8c)
+ [!provide] PROVIDE (SubtractFromSelfBigHex256 = 0x40015c20)
+ [!provide] PROVIDE (SubtractFromSelfBigHexSign256 = 0x40015dc8)
+ [!provide] PROVIDE (sw_to_hw = 0x3ffb8d40)
+ [!provide] PROVIDE (syscall_table_ptr_app = 0x3ffae020)
+ [!provide] PROVIDE (syscall_table_ptr_pro = 0x3ffae024)
+ [!provide] PROVIDE (tdefl_compress = 0x400600bc)
+ [!provide] PROVIDE (tdefl_compress_buffer = 0x400607f4)
+ [!provide] PROVIDE (tdefl_compress_mem_to_mem = 0x40060900)
+ [!provide] PROVIDE (tdefl_compress_mem_to_output = 0x400608e0)
+ [!provide] PROVIDE (tdefl_get_adler32 = 0x400608d8)
+ [!provide] PROVIDE (tdefl_get_prev_return_status = 0x400608d0)
+ [!provide] PROVIDE (tdefl_init = 0x40060810)
+ [!provide] PROVIDE (tdefl_write_image_to_png_file_in_memory = 0x4006091c)
+ [!provide] PROVIDE (tdefl_write_image_to_png_file_in_memory_ex = 0x40060910)
+ [!provide] PROVIDE (tinfl_decompress = 0x4005ef30)
+ [!provide] PROVIDE (tinfl_decompress_mem_to_callback = 0x40060090)
+ [!provide] PROVIDE (tinfl_decompress_mem_to_mem = 0x40060050)
+ [!provide] PROVIDE (UartDev = 0x3ffe019c)
+ [!provide] PROVIDE (user_code_start = 0x3ffe0400)
+ [!provide] PROVIDE (veryBigHexP256 = 0x3ff9736c)
+ [!provide] PROVIDE (xthal_bcopy = 0x4000c098)
+ [!provide] PROVIDE (xthal_copy123 = 0x4000c124)
+ [!provide] PROVIDE (xthal_get_ccompare = 0x4000c078)
+ [!provide] PROVIDE (xthal_get_ccount = 0x4000c050)
+ [!provide] PROVIDE (xthal_get_interrupt = 0x4000c1e4)
+ [!provide] PROVIDE (xthal_get_intread = 0x4000c1e4)
+ [!provide] PROVIDE (Xthal_intlevel = 0x3ff9c2b4)
+ [!provide] PROVIDE (xthal_memcpy = 0x4000c0bc)
+ [!provide] PROVIDE (xthal_set_ccompare = 0x4000c058)
+ [!provide] PROVIDE (xthal_set_intclear = 0x4000c1ec)
+ [!provide] PROVIDE (_xtos_set_intlevel = 0x4000bfdc)
+ 0x000000003ffe01e0 PROVIDE (g_ticks_per_us_pro = 0x3ffe01e0)
+ [!provide] PROVIDE (g_ticks_per_us_app = 0x3ffe40f0)
+ 0x0000000040063238 PROVIDE (esp_rom_spiflash_config_param = 0x40063238)
+ 0x00000000400621b0 PROVIDE (esp_rom_spiflash_read_user_cmd = 0x400621b0)
+ 0x0000000040062e60 PROVIDE (esp_rom_spiflash_write_encrypted_disable = 0x40062e60)
+ 0x0000000040062df4 PROVIDE (esp_rom_spiflash_write_encrypted_enable = 0x40062df4)
+ 0x0000000040062e1c PROVIDE (esp_rom_spiflash_prepare_encrypted_data = 0x40062e1c)
+ 0x0000000040061ddc PROVIDE (esp_rom_spiflash_select_qio_pins = 0x40061ddc)
+ [!provide] PROVIDE (esp_rom_spiflash_attach = 0x40062a6c)
+ 0x0000000040062bc8 PROVIDE (esp_rom_spiflash_config_clk = 0x40062bc8)
+ 0x000000003ffae270 PROVIDE (g_rom_spiflash_chip = 0x3ffae270)
+ [!provide] PROVIDE (hci_le_rd_rem_used_feats_cmd_handler = 0x400417b4)
+ [!provide] PROVIDE (llcp_length_req_handler = 0x40043808)
+ [!provide] PROVIDE (llcp_unknown_rsp_handler = 0x40043ba8)
+ [!provide] PROVIDE (FilePacketSendDeflatedReqMsgProc = 0x40008b24)
+ [!provide] PROVIDE (FilePacketSendReqMsgProc = 0x40008860)
+ [!provide] PROVIDE (FlashDwnLdDeflatedStartMsgProc = 0x40008ad8)
+ [!provide] PROVIDE (FlashDwnLdParamCfgMsgProc = 0x4000891c)
+ [!provide] PROVIDE (FlashDwnLdStartMsgProc = 0x40008820)
+ [!provide] PROVIDE (FlashDwnLdStopDeflatedReqMsgProc = 0x40008c18)
+ [!provide] PROVIDE (FlashDwnLdStopReqMsgProc = 0x400088ec)
+ [!provide] PROVIDE (MemDwnLdStartMsgProc = 0x40008948)
+ [!provide] PROVIDE (MemDwnLdStopReqMsgProc = 0x400089dc)
+ [!provide] PROVIDE (MemPacketSendReqMsgProc = 0x40008978)
+ [!provide] PROVIDE (uart_baudrate_detect = 0x40009034)
+ [!provide] PROVIDE (uart_buff_switch = 0x400093c0)
+ [!provide] PROVIDE (UartConnCheck = 0x40008738)
+ [!provide] PROVIDE (UartConnectProc = 0x40008a04)
+ [!provide] PROVIDE (UartDwnLdProc = 0x40008ce8)
+ [!provide] PROVIDE (UartRegReadProc = 0x40008a58)
+ [!provide] PROVIDE (UartRegWriteProc = 0x40008a14)
+ [!provide] PROVIDE (UartSetBaudProc = 0x40008aac)
+ [!provide] PROVIDE (UartSpiAttachProc = 0x40008a6c)
+ [!provide] PROVIDE (UartSpiReadProc = 0x40008a80)
+ [!provide] PROVIDE (VerifyFlashMd5Proc = 0x40008c44)
+ [!provide] PROVIDE (GetUartDevice = 0x40009598)
+ [!provide] PROVIDE (RcvMsg = 0x4000954c)
+ [!provide] PROVIDE (SendMsg = 0x40009384)
+ [!provide] PROVIDE (UartGetCmdLn = 0x40009564)
+ [!provide] PROVIDE (UartRxString = 0x400092fc)
+ [!provide] PROVIDE (Uart_Init = 0x40009120)
+ [!provide] PROVIDE (recv_packet = 0x40009424)
+ [!provide] PROVIDE (send_packet = 0x40009340)
+ 0x0000000040008fd0 PROVIDE (uartAttach = 0x40008fd0)
+ 0x00000000400090cc PROVIDE (uart_div_modify = 0x400090cc)
+ [!provide] PROVIDE (uart_rx_intr_handler = 0x40008f4c)
+ [!provide] PROVIDE (uart_rx_one_char = 0x400092d0)
+ [!provide] PROVIDE (uart_rx_one_char_block = 0x400092a4)
+ [!provide] PROVIDE (uart_rx_readbuff = 0x40009394)
+ 0x0000000040009258 PROVIDE (uart_tx_flush = 0x40009258)
+ [!provide] PROVIDE (uart_tx_one_char = 0x40009200)
+ [!provide] PROVIDE (uart_tx_one_char2 = 0x4000922c)
+ [!provide] PROVIDE (uart_tx_switch = 0x40009028)
+ [!provide] PROVIDE (gpio_output_set = 0x40009b24)
+ 0x0000000040009b5c PROVIDE (gpio_output_set_high = 0x40009b5c)
+ 0x0000000040009b88 PROVIDE (gpio_input_get = 0x40009b88)
+ 0x0000000040009b9c PROVIDE (gpio_input_get_high = 0x40009b9c)
+ 0x0000000040009edc PROVIDE (gpio_matrix_in = 0x40009edc)
+ 0x0000000040009f0c PROVIDE (gpio_matrix_out = 0x40009f0c)
+ 0x0000000040009fdc PROVIDE (gpio_pad_select_gpio = 0x40009fdc)
+ [!provide] PROVIDE (gpio_pad_set_drv = 0x4000a11c)
+ [!provide] PROVIDE (gpio_pad_pulldown = 0x4000a348)
+ 0x000000004000a22c PROVIDE (gpio_pad_pullup = 0x4000a22c)
+ [!provide] PROVIDE (gpio_pad_hold = 0x4000a734)
+ [!provide] PROVIDE (gpio_pad_unhold = 0x4000a484)
+ [!provide] PROVIDE (ets_aes_crypt = 0x4005c9b8)
+ [!provide] PROVIDE (ets_aes_disable = 0x4005c8f8)
+ [!provide] PROVIDE (ets_aes_enable = 0x4005c8cc)
+ [!provide] PROVIDE (ets_aes_set_endian = 0x4005c928)
+ [!provide] PROVIDE (ets_aes_setkey_dec = 0x4005c994)
+ [!provide] PROVIDE (ets_aes_setkey_enc = 0x4005c97c)
+ [!provide] PROVIDE (ets_bigint_disable = 0x4005c4e0)
+ [!provide] PROVIDE (ets_bigint_enable = 0x4005c498)
+ [!provide] PROVIDE (ets_bigint_mod_mult_getz = 0x4005c818)
+ [!provide] PROVIDE (ets_bigint_mod_mult_prepare = 0x4005c7b4)
+ [!provide] PROVIDE (ets_bigint_mod_power_getz = 0x4005c614)
+ [!provide] PROVIDE (ets_bigint_mod_power_prepare = 0x4005c54c)
+ [!provide] PROVIDE (ets_bigint_montgomery_mult_getz = 0x4005c7a4)
+ [!provide] PROVIDE (ets_bigint_montgomery_mult_prepare = 0x4005c6fc)
+ [!provide] PROVIDE (ets_bigint_mult_getz = 0x4005c6e8)
+ [!provide] PROVIDE (ets_bigint_mult_prepare = 0x4005c630)
+ [!provide] PROVIDE (ets_bigint_wait_finish = 0x4005c520)
+ [!provide] PROVIDE (ets_post = 0x4000673c)
+ [!provide] PROVIDE (ets_run = 0x400066bc)
+ [!provide] PROVIDE (ets_set_idle_cb = 0x40006674)
+ [!provide] PROVIDE (ets_task = 0x40006688)
+ [!provide] PROVIDE (ets_efuse_get_8M_clock = 0x40008710)
+ 0x0000000040008658 PROVIDE (ets_efuse_get_spiconfig = 0x40008658)
+ [!provide] PROVIDE (ets_efuse_program_op = 0x40008628)
+ [!provide] PROVIDE (ets_efuse_read_op = 0x40008600)
+ [!provide] PROVIDE (ets_intr_lock = 0x400067b0)
+ [!provide] PROVIDE (ets_intr_unlock = 0x400067c4)
+ [!provide] PROVIDE (ets_isr_attach = 0x400067ec)
+ [!provide] PROVIDE (ets_waiti0 = 0x400067d8)
+ [!provide] PROVIDE (intr_matrix_set = 0x4000681c)
+ [!provide] PROVIDE (check_pos = 0x400068b8)
+ [!provide] PROVIDE (ets_set_appcpu_boot_addr = 0x4000689c)
+ [!provide] PROVIDE (ets_set_startup_callback = 0x4000688c)
+ [!provide] PROVIDE (ets_set_user_start = 0x4000687c)
+ [!provide] PROVIDE (ets_unpack_flash_code = 0x40007018)
+ [!provide] PROVIDE (ets_unpack_flash_code_legacy = 0x4000694c)
+ [!provide] PROVIDE (rom_main = 0x400076c4)
+ [!provide] PROVIDE (ets_write_char_uart = 0x40007cf8)
+ [!provide] PROVIDE (ets_install_putc1 = 0x40007d18)
+ [!provide] PROVIDE (ets_install_putc2 = 0x40007d38)
+ 0x0000000040007d28 PROVIDE (ets_install_uart_printf = 0x40007d28)
+ 0x0000000040007d54 PROVIDE (ets_printf = 0x40007d54)
+ [!provide] PROVIDE (rtc_boot_control = 0x4000821c)
+ 0x00000000400081d4 PROVIDE (rtc_get_reset_reason = 0x400081d4)
+ [!provide] PROVIDE (rtc_get_wakeup_cause = 0x400081f4)
+ [!provide] PROVIDE (rtc_select_apb_bridge = 0x40008288)
+ [!provide] PROVIDE (set_rtc_memory_crc = 0x40008208)
+ [!provide] PROVIDE (software_reset = 0x4000824c)
+ [!provide] PROVIDE (software_reset_cpu = 0x40008264)
+ [!provide] PROVIDE (ets_secure_boot_check = 0x4005cb40)
+ [!provide] PROVIDE (ets_secure_boot_check_finish = 0x4005cc04)
+ [!provide] PROVIDE (ets_secure_boot_check_start = 0x4005cbcc)
+ [!provide] PROVIDE (ets_secure_boot_finish = 0x4005ca84)
+ [!provide] PROVIDE (ets_secure_boot_hash = 0x4005cad4)
+ [!provide] PROVIDE (ets_secure_boot_obtain = 0x4005cb14)
+ [!provide] PROVIDE (ets_secure_boot_rd_abstract = 0x4005cba8)
+ [!provide] PROVIDE (ets_secure_boot_rd_iv = 0x4005cb84)
+ [!provide] PROVIDE (ets_secure_boot_start = 0x4005ca34)
+ [!provide] PROVIDE (ets_sha_disable = 0x4005c0a8)
+ 0x000000004005c07c PROVIDE (ets_sha_enable = 0x4005c07c)
+ [!provide] PROVIDE (ets_sha_finish = 0x4005c104)
+ [!provide] PROVIDE (ets_sha_init = 0x4005c0d4)
+ [!provide] PROVIDE (ets_sha_update = 0x4005c2a0)
+ 0x0000000040008534 PROVIDE (ets_delay_us = 0x40008534)
+ [!provide] PROVIDE (ets_get_cpu_frequency = 0x4000855c)
+ [!provide] PROVIDE (ets_get_detected_xtal_freq = 0x40008588)
+ [!provide] PROVIDE (ets_get_xtal_scale = 0x4000856c)
+ [!provide] PROVIDE (ets_update_cpu_frequency_rom = 0x40008550)
+ [!provide] PROVIDE (hci_tl_env = 0x3ffb8154)
+ [!provide] PROVIDE (ld_acl_env = 0x3ffb8258)
+ [!provide] PROVIDE (ea_env = 0x3ffb80ec)
+ [!provide] PROVIDE (lc_sco_data_path_config = 0x3ffb81f8)
+ [!provide] PROVIDE (lc_sco_env = 0x3ffb81fc)
+ [!provide] PROVIDE (ld_active_ch_map = 0x3ffb8334)
+ [!provide] PROVIDE (ld_bcst_acl_env = 0x3ffb8274)
+ [!provide] PROVIDE (ld_csb_rx_env = 0x3ffb8278)
+ [!provide] PROVIDE (ld_csb_tx_env = 0x3ffb827c)
+ [!provide] PROVIDE (ld_env = 0x3ffb9510)
+ [!provide] PROVIDE (ld_fm_env = 0x3ffb8284)
+ [!provide] PROVIDE (ld_inq_env = 0x3ffb82e4)
+ [!provide] PROVIDE (ld_iscan_env = 0x3ffb82e8)
+ [!provide] PROVIDE (ld_page_env = 0x3ffb82f0)
+ [!provide] PROVIDE (ld_pca_env = 0x3ffb82f4)
+ [!provide] PROVIDE (ld_pscan_env = 0x3ffb8308)
+ [!provide] PROVIDE (ld_sched_env = 0x3ffb830c)
+ [!provide] PROVIDE (ld_sched_params = 0x3ffb96c0)
+ [!provide] PROVIDE (ld_sco_env = 0x3ffb824c)
+ [!provide] PROVIDE (ld_sscan_env = 0x3ffb832c)
+ [!provide] PROVIDE (ld_strain_env = 0x3ffb8330)
+ [!provide] PROVIDE (LM_Sniff = 0x3ffb8230)
+ [!provide] PROVIDE (LM_SniffSubRate = 0x3ffb8214)
+ [!provide] PROVIDE (prbs_64bytes = 0x3ff98992)
+ [!provide] PROVIDE (nvds_env = 0x3ffb8364)
+ [!provide] PROVIDE (nvds_magic_number = 0x3ff9912a)
+ [!provide] PROVIDE (TASK_DESC_LLD = 0x3ff98b58)
+ 0x0000000040056340 abs = 0x40056340
+ 0x0000000040058ef0 __ascii_wctomb = 0x40058ef0
+ 0x00000000400566c4 atoi = 0x400566c4
+ 0x00000000400566d4 _atoi_r = 0x400566d4
+ 0x00000000400566ec atol = 0x400566ec
+ 0x00000000400566fc _atol_r = 0x400566fc
+ 0x000000004000c1f4 bzero = 0x4000c1f4
+ 0x0000000040001df8 _cleanup = 0x40001df8
+ 0x0000000040001d48 _cleanup_r = 0x40001d48
+ 0x0000000040000e8c creat = 0x40000e8c
+ 0x0000000040056348 div = 0x40056348
+ 0x000000004000c728 __dummy_lock = 0x4000c728
+ 0x000000004000c730 __dummy_lock_try = 0x4000c730
+ 0x0000000040001fd4 __env_lock = 0x40001fd4
+ 0x0000000040001fe0 __env_unlock = 0x40001fe0
+ 0x00000000400020ac fclose = 0x400020ac
+ 0x0000000040001fec _fclose_r = 0x40001fec
+ 0x0000000040059394 fflush = 0x40059394
+ 0x0000000040059320 _fflush_r = 0x40059320
+ 0x0000000040001f44 _findenv_r = 0x40001f44
+ 0x0000000040001f1c __fp_lock_all = 0x40001f1c
+ 0x0000000040001f30 __fp_unlock_all = 0x40001f30
+ 0x0000000040058da0 __fputwc = 0x40058da0
+ 0x0000000040058ea8 fputwc = 0x40058ea8
+ 0x0000000040058e4c _fputwc_r = 0x40058e4c
+ 0x000000004000c738 _fwalk = 0x4000c738
+ 0x000000004000c770 _fwalk_reent = 0x4000c770
+ 0x0000000040001fbc _getenv_r = 0x40001fbc
+ 0x0000000040000f04 isalnum = 0x40000f04
+ 0x0000000040000f18 isalpha = 0x40000f18
+ 0x000000004000c20c isascii = 0x4000c20c
+ 0x0000000040000ea0 _isatty_r = 0x40000ea0
+ 0x0000000040000f2c isblank = 0x40000f2c
+ 0x0000000040000f50 iscntrl = 0x40000f50
+ 0x0000000040000f64 isdigit = 0x40000f64
+ 0x0000000040000f94 isgraph = 0x40000f94
+ 0x0000000040000f78 islower = 0x40000f78
+ 0x0000000040000fa8 isprint = 0x40000fa8
+ 0x0000000040000fc0 ispunct = 0x40000fc0
+ 0x0000000040000fd4 isspace = 0x40000fd4
+ 0x0000000040000fe8 isupper = 0x40000fe8
+ 0x0000000040056678 __itoa = 0x40056678
+ 0x00000000400566b4 itoa = 0x400566b4
+ 0x0000000040056370 labs = 0x40056370
+ 0x0000000040056378 ldiv = 0x40056378
+ 0x00000000400562cc longjmp = 0x400562cc
+ 0x000000004000c220 memccpy = 0x4000c220
+ 0x000000004000c244 memchr = 0x4000c244
+ 0x000000004000c260 memcmp = 0x4000c260
+ 0x000000004000c2c8 memcpy = 0x4000c2c8
+ 0x000000004000c3c0 memmove = 0x4000c3c0
+ 0x000000004000c400 memrchr = 0x4000c400
+ 0x000000004000c44c memset = 0x4000c44c
+ 0x0000000040056424 qsort = 0x40056424
+ 0x0000000040001058 rand = 0x40001058
+ 0x00000000400010d4 rand_r = 0x400010d4
+ 0x000000004000c498 __sccl = 0x4000c498
+ 0x00000000400011b8 __sclose = 0x400011b8
+ 0x0000000040001148 __seofread = 0x40001148
+ 0x0000000040056268 setjmp = 0x40056268
+ 0x00000000400591e0 __sflush_r = 0x400591e0
+ 0x0000000040001dc8 __sfmoreglue = 0x40001dc8
+ 0x0000000040001e90 __sfp = 0x40001e90
+ 0x0000000040001e08 __sfp_lock_acquire = 0x40001e08
+ 0x0000000040001e14 __sfp_lock_release = 0x40001e14
+ 0x000000004005893c __sfvwrite_r = 0x4005893c
+ 0x0000000040001e38 __sinit = 0x40001e38
+ 0x0000000040001e20 __sinit_lock_acquire = 0x40001e20
+ 0x0000000040001e2c __sinit_lock_release = 0x40001e2c
+ 0x0000000040059108 __smakebuf_r = 0x40059108
+ 0x0000000040001004 srand = 0x40001004
+ 0x0000000040001118 __sread = 0x40001118
+ 0x00000000400593d4 __srefill_r = 0x400593d4
+ 0x0000000040001184 __sseek = 0x40001184
+ 0x00000000400011cc strcasecmp = 0x400011cc
+ 0x0000000040001210 strcasestr = 0x40001210
+ 0x000000004000c518 strcat = 0x4000c518
+ 0x000000004000c53c strchr = 0x4000c53c
+ 0x0000000040001274 strcmp = 0x40001274
+ 0x0000000040001398 strcoll = 0x40001398
+ 0x00000000400013ac strcpy = 0x400013ac
+ 0x000000004000c558 strcspn = 0x4000c558
+ 0x000000004000143c strdup = 0x4000143c
+ 0x0000000040001450 _strdup_r = 0x40001450
+ 0x0000000040001470 strlcat = 0x40001470
+ 0x000000004000c584 strlcpy = 0x4000c584
+ 0x00000000400014c0 strlen = 0x400014c0
+ 0x0000000040001524 strlwr = 0x40001524
+ 0x0000000040001550 strncasecmp = 0x40001550
+ 0x000000004000c5c4 strncat = 0x4000c5c4
+ 0x000000004000c5f4 strncmp = 0x4000c5f4
+ 0x00000000400015d4 strncpy = 0x400015d4
+ 0x00000000400016b0 strndup = 0x400016b0
+ 0x00000000400016c4 _strndup_r = 0x400016c4
+ 0x000000004000c628 strnlen = 0x4000c628
+ 0x0000000040001708 strrchr = 0x40001708
+ 0x0000000040001734 strsep = 0x40001734
+ 0x000000004000c648 strspn = 0x4000c648
+ 0x000000004000c674 strstr = 0x4000c674
+ 0x000000004000c6a8 __strtok_r = 0x4000c6a8
+ 0x000000004000c70c strtok_r = 0x4000c70c
+ 0x000000004005681c strtol = 0x4005681c
+ 0x0000000040056714 _strtol_r = 0x40056714
+ 0x000000004005692c strtoul = 0x4005692c
+ 0x0000000040056834 _strtoul_r = 0x40056834
+ 0x000000004000174c strupr = 0x4000174c
+ 0x0000000040058f3c __submore = 0x40058f3c
+ 0x0000000040058cb4 __swbuf = 0x40058cb4
+ 0x0000000040058bec __swbuf_r = 0x40058bec
+ 0x0000000040001150 __swrite = 0x40001150
+ 0x0000000040058cc8 __swsetup_r = 0x40058cc8
+ 0x000000004000c720 toascii = 0x4000c720
+ 0x0000000040001868 tolower = 0x40001868
+ 0x0000000040001884 toupper = 0x40001884
+ 0x00000000400590f4 ungetc = 0x400590f4
+ 0x0000000040058fa0 _ungetc_r = 0x40058fa0
+ 0x00000000400561f0 __utoa = 0x400561f0
+ 0x0000000040056258 utoa = 0x40056258
+ 0x0000000040058920 wcrtomb = 0x40058920
+ 0x00000000400588d8 _wcrtomb_r = 0x400588d8
+ 0x0000000040058f14 _wctomb_r = 0x40058f14
+ [!provide] PROVIDE (UART0 = 0x3ff40000)
+ 0x000000003ff42000 PROVIDE (SPI1 = 0x3ff42000)
+ [!provide] PROVIDE (SPI0 = 0x3ff43000)
+ 0x000000003ff44000 PROVIDE (GPIO = 0x3ff44000)
+ [!provide] PROVIDE (SIGMADELTA = 0x3ff44f00)
+ [!provide] PROVIDE (RTCCNTL = 0x3ff48000)
+ [!provide] PROVIDE (RTCIO = 0x3ff48400)
+ [!provide] PROVIDE (SENS = 0x3ff48800)
+ [!provide] PROVIDE (HINF = 0x3ff4b000)
+ [!provide] PROVIDE (UHCI1 = 0x3ff4c000)
+ [!provide] PROVIDE (I2S0 = 0x3ff4f000)
+ [!provide] PROVIDE (UART1 = 0x3ff50000)
+ [!provide] PROVIDE (I2C0 = 0x3ff53000)
+ [!provide] PROVIDE (UHCI0 = 0x3ff54000)
+ [!provide] PROVIDE (HOST = 0x3ff55000)
+ [!provide] PROVIDE (RMT = 0x3ff56000)
+ [!provide] PROVIDE (RMTMEM = 0x3ff56800)
+ [!provide] PROVIDE (PCNT = 0x3ff57000)
+ [!provide] PROVIDE (SLC = 0x3ff58000)
+ [!provide] PROVIDE (LEDC = 0x3ff59000)
+ [!provide] PROVIDE (MCPWM0 = 0x3ff5e000)
+ 0x000000003ff5f000 PROVIDE (TIMERG0 = 0x3ff5f000)
+ [!provide] PROVIDE (TIMERG1 = 0x3ff60000)
+ [!provide] PROVIDE (SPI2 = 0x3ff64000)
+ [!provide] PROVIDE (SPI3 = 0x3ff65000)
+ [!provide] PROVIDE (SYSCON = 0x3ff66000)
+ [!provide] PROVIDE (I2C1 = 0x3ff67000)
+ [!provide] PROVIDE (SDMMC = 0x3ff68000)
+ [!provide] PROVIDE (EMAC_DMA = 0x3ff69000)
+ [!provide] PROVIDE (EMAC_EXT = 0x3ff69800)
+ [!provide] PROVIDE (EMAC_MAC = 0x3ff6a000)
+ [!provide] PROVIDE (CAN = 0x3ff6b000)
+ [!provide] PROVIDE (MCPWM1 = 0x3ff6c000)
+ [!provide] PROVIDE (I2S1 = 0x3ff6d000)
+ [!provide] PROVIDE (UART2 = 0x3ff6e000)
+OUTPUT(/home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader.elf elf32-xtensa-le)
+
+.debug_frame 0x0000000000000000 0x12b8
+ .debug_frame 0x0000000000000000 0x28 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(bootloader_start.o)
+ .debug_frame 0x0000000000000028 0x40 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_bootloader.o)
+ .debug_frame 0x0000000000000068 0x40 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_bootmgr.o)
+ .debug_frame 0x00000000000000a8 0xb8 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_mperror.o)
+ .debug_frame 0x0000000000000160 0x178 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_gpio.o)
+ .debug_frame 0x00000000000002d8 0x118 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_utility.o)
+ .debug_frame 0x00000000000003f0 0x148 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_common.o)
+ .debug_frame 0x0000000000000538 0x58 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(pycom_bootloader_support.o)
+ .debug_frame 0x0000000000000590 0x28 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(flash_partitions.o)
+ .debug_frame 0x00000000000005b8 0xe8 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(esp_image_format.o)
+ .debug_frame 0x00000000000006a0 0x58 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_random.o)
+ .debug_frame 0x00000000000006f8 0x58 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_sha.o)
+ .debug_frame 0x0000000000000750 0x58 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_esp32.o)
+ .debug_frame 0x00000000000007a8 0x40 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_efuse_esp32.o)
+ .debug_frame 0x00000000000007e8 0xb8 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_flash.o)
+ .debug_frame 0x00000000000008a0 0x118 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(flash_qio_mode.o)
+ .debug_frame 0x00000000000009b8 0xb8 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_init.o)
+ .debug_frame 0x0000000000000a70 0x40 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_clock.o)
+ .debug_frame 0x0000000000000ab0 0x88 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_flash_config_esp32.o)
+ .debug_frame 0x0000000000000b38 0x190 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/spi_flash/libspi_flash.a(spi_flash_rom_patch.o)
+ .debug_frame 0x0000000000000cc8 0x70 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(cpu_util.o)
+ .debug_frame 0x0000000000000d38 0x130 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_wdt.o)
+ .debug_frame 0x0000000000000e68 0x58 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_init.o)
+ .debug_frame 0x0000000000000ec0 0x40 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk_init.o)
+ .debug_frame 0x0000000000000f00 0x2b0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk.o)
+ .debug_frame 0x00000000000011b0 0xb8 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_time.o)
+ .debug_frame 0x0000000000001268 0x28 /home/element/xtensa-esp32-elf-2020r3/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/no-rtti/libgcc.a(_bswapsi2.o)
+ .debug_frame 0x0000000000001290 0x28 /home/element/xtensa-esp32-elf-2020r3/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/no-rtti/libgcc.a(_udivdi3.o)
+
+.debug_info 0x0000000000000000 0x69fda
+ .debug_info 0x0000000000000000 0xe3d /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(bootloader_start.o)
+ .debug_info 0x0000000000000e3d 0xf4e /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_bootloader.o)
+ .debug_info 0x0000000000001d8b 0x2582 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_bootmgr.o)
+ .debug_info 0x000000000000430d 0x2511 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_mperror.o)
+ .debug_info 0x000000000000681e 0x526d /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_gpio.o)
+ .debug_info 0x000000000000ba8b 0x26 /home/element/xtensa-esp32-elf-2020r3/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/no-rtti/libgcc.a(_lshrdi3.o)
+ .debug_info 0x000000000000bab1 0x82e0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_utility.o)
+ .debug_info 0x0000000000013d91 0x522c /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_common.o)
+ .debug_info 0x0000000000018fbd 0x15f7 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(pycom_bootloader_support.o)
+ .debug_info 0x000000000001a5b4 0xd37 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(flash_partitions.o)
+ .debug_info 0x000000000001b2eb 0x2d69 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(esp_image_format.o)
+ .debug_info 0x000000000001e054 0x791a /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_random.o)
+ .debug_info 0x000000000002596e 0x1430 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_sha.o)
+ .debug_info 0x0000000000026d9e 0x9bc3 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_esp32.o)
+ .debug_info 0x0000000000030961 0x9f7 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_efuse_esp32.o)
+ .debug_info 0x0000000000031358 0x1fb1 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_flash.o)
+ .debug_info 0x0000000000033309 0x363a /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(flash_qio_mode.o)
+ .debug_info 0x0000000000036943 0x5779 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_init.o)
+ .debug_info 0x000000000003c0bc 0x61f6 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_clock.o)
+ .debug_info 0x00000000000422b2 0x178e /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_flash_config_esp32.o)
+ .debug_info 0x0000000000043a40 0x3d83 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/spi_flash/libspi_flash.a(spi_flash_rom_patch.o)
+ .debug_info 0x00000000000477c3 0x3fb9 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(cpu_util.o)
+ .debug_info 0x000000000004b77c 0x445b /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_wdt.o)
+ .debug_info 0x000000000004fbd7 0x424f /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_init.o)
+ .debug_info 0x0000000000053e26 0x75af /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk_init.o)
+ .debug_info 0x000000000005b3d5 0x82b4 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk.o)
+ .debug_info 0x0000000000063689 0x4d52 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_time.o)
+ .debug_info 0x00000000000683db 0xb02 /home/element/xtensa-esp32-elf-2020r3/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/no-rtti/libgcc.a(_bswapsi2.o)
+ .debug_info 0x0000000000068edd 0x10fd /home/element/xtensa-esp32-elf-2020r3/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/no-rtti/libgcc.a(_udivdi3.o)
+
+.debug_abbrev 0x0000000000000000 0x66d7
+ .debug_abbrev 0x0000000000000000 0x2c3 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(bootloader_start.o)
+ .debug_abbrev 0x00000000000002c3 0x29a /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_bootloader.o)
+ .debug_abbrev 0x000000000000055d 0x3ba /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_bootmgr.o)
+ .debug_abbrev 0x0000000000000917 0x3dc /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_mperror.o)
+ .debug_abbrev 0x0000000000000cf3 0x4a3 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_gpio.o)
+ .debug_abbrev 0x0000000000001196 0x14 /home/element/xtensa-esp32-elf-2020r3/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/no-rtti/libgcc.a(_lshrdi3.o)
+ .debug_abbrev 0x00000000000011aa 0x64c /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_utility.o)
+ .debug_abbrev 0x00000000000017f6 0x4e2 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_common.o)
+ .debug_abbrev 0x0000000000001cd8 0x2d5 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(pycom_bootloader_support.o)
+ .debug_abbrev 0x0000000000001fad 0x270 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(flash_partitions.o)
+ .debug_abbrev 0x000000000000221d 0x544 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(esp_image_format.o)
+ .debug_abbrev 0x0000000000002761 0x35b /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_random.o)
+ .debug_abbrev 0x0000000000002abc 0x2b2 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_sha.o)
+ .debug_abbrev 0x0000000000002d6e 0x567 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_esp32.o)
+ .debug_abbrev 0x00000000000032d5 0x1d2 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_efuse_esp32.o)
+ .debug_abbrev 0x00000000000034a7 0x492 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_flash.o)
+ .debug_abbrev 0x0000000000003939 0x440 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(flash_qio_mode.o)
+ .debug_abbrev 0x0000000000003d79 0x3a6 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_init.o)
+ .debug_abbrev 0x000000000000411f 0x384 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_clock.o)
+ .debug_abbrev 0x00000000000044a3 0x2d8 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_flash_config_esp32.o)
+ .debug_abbrev 0x000000000000477b 0x4fb /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/spi_flash/libspi_flash.a(spi_flash_rom_patch.o)
+ .debug_abbrev 0x0000000000004c76 0x286 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(cpu_util.o)
+ .debug_abbrev 0x0000000000004efc 0x412 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_wdt.o)
+ .debug_abbrev 0x000000000000530e 0x2e4 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_init.o)
+ .debug_abbrev 0x00000000000055f2 0x3ea /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk_init.o)
+ .debug_abbrev 0x00000000000059dc 0x56a /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk.o)
+ .debug_abbrev 0x0000000000005f46 0x366 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_time.o)
+ .debug_abbrev 0x00000000000062ac 0x1b1 /home/element/xtensa-esp32-elf-2020r3/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/no-rtti/libgcc.a(_bswapsi2.o)
+ .debug_abbrev 0x000000000000645d 0x27a /home/element/xtensa-esp32-elf-2020r3/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/no-rtti/libgcc.a(_udivdi3.o)
+
+.debug_loc 0x0000000000000000 0x7fd1
+ .debug_loc 0x0000000000000000 0xce /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(bootloader_start.o)
+ .debug_loc 0x00000000000000ce 0x19e /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_bootloader.o)
+ .debug_loc 0x000000000000026c 0x17c /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_bootmgr.o)
+ .debug_loc 0x00000000000003e8 0xb3 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_mperror.o)
+ .debug_loc 0x000000000000049b 0x724 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_gpio.o)
+ .debug_loc 0x0000000000000bbf 0xf9e /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_utility.o)
+ .debug_loc 0x0000000000001b5d 0x70c /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_common.o)
+ .debug_loc 0x0000000000002269 0x112 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(pycom_bootloader_support.o)
+ .debug_loc 0x000000000000237b 0x182 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(flash_partitions.o)
+ .debug_loc 0x00000000000024fd 0x123f /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(esp_image_format.o)
+ .debug_loc 0x000000000000373c 0x105 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_random.o)
+ .debug_loc 0x0000000000003841 0x238 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_sha.o)
+ .debug_loc 0x0000000000003a79 0x6fc /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_esp32.o)
+ .debug_loc 0x0000000000004175 0x72 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_efuse_esp32.o)
+ .debug_loc 0x00000000000041e7 0x8d0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_flash.o)
+ .debug_loc 0x0000000000004ab7 0x23f /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(flash_qio_mode.o)
+ .debug_loc 0x0000000000004cf6 0x80 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_init.o)
+ .debug_loc 0x0000000000004d76 0x7e /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_clock.o)
+ .debug_loc 0x0000000000004df4 0x1ea /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_flash_config_esp32.o)
+ .debug_loc 0x0000000000004fde 0xa78 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/spi_flash/libspi_flash.a(spi_flash_rom_patch.o)
+ .debug_loc 0x0000000000005a56 0x3a /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(cpu_util.o)
+ .debug_loc 0x0000000000005a90 0x3fe /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_wdt.o)
+ .debug_loc 0x0000000000005e8e 0x653 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_init.o)
+ .debug_loc 0x00000000000064e1 0x262 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk_init.o)
+ .debug_loc 0x0000000000006743 0xaab /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk.o)
+ .debug_loc 0x00000000000071ee 0x334 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_time.o)
+ .debug_loc 0x0000000000007522 0x25 /home/element/xtensa-esp32-elf-2020r3/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/no-rtti/libgcc.a(_bswapsi2.o)
+ .debug_loc 0x0000000000007547 0xa8a /home/element/xtensa-esp32-elf-2020r3/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/no-rtti/libgcc.a(_udivdi3.o)
+
+.debug_aranges 0x0000000000000000 0x868
+ .debug_aranges
+ 0x0000000000000000 0x20 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(bootloader_start.o)
+ .debug_aranges
+ 0x0000000000000020 0x28 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_bootloader.o)
+ .debug_aranges
+ 0x0000000000000048 0x28 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_bootmgr.o)
+ .debug_aranges
+ 0x0000000000000070 0x50 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_mperror.o)
+ .debug_aranges
+ 0x00000000000000c0 0x90 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_gpio.o)
+ .debug_aranges
+ 0x0000000000000150 0x20 /home/element/xtensa-esp32-elf-2020r3/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/no-rtti/libgcc.a(_lshrdi3.o)
+ .debug_aranges
+ 0x0000000000000170 0x70 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_utility.o)
+ .debug_aranges
+ 0x00000000000001e0 0x80 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_common.o)
+ .debug_aranges
+ 0x0000000000000260 0x30 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(pycom_bootloader_support.o)
+ .debug_aranges
+ 0x0000000000000290 0x20 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(flash_partitions.o)
+ .debug_aranges
+ 0x00000000000002b0 0x60 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(esp_image_format.o)
+ .debug_aranges
+ 0x0000000000000310 0x30 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_random.o)
+ .debug_aranges
+ 0x0000000000000340 0x30 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_sha.o)
+ .debug_aranges
+ 0x0000000000000370 0x30 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_esp32.o)
+ .debug_aranges
+ 0x00000000000003a0 0x28 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_efuse_esp32.o)
+ .debug_aranges
+ 0x00000000000003c8 0x50 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_flash.o)
+ .debug_aranges
+ 0x0000000000000418 0x70 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(flash_qio_mode.o)
+ .debug_aranges
+ 0x0000000000000488 0x50 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_init.o)
+ .debug_aranges
+ 0x00000000000004d8 0x28 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_clock.o)
+ .debug_aranges
+ 0x0000000000000500 0x40 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_flash_config_esp32.o)
+ .debug_aranges
+ 0x0000000000000540 0x98 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/spi_flash/libspi_flash.a(spi_flash_rom_patch.o)
+ .debug_aranges
+ 0x00000000000005d8 0x38 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(cpu_util.o)
+ .debug_aranges
+ 0x0000000000000610 0x78 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_wdt.o)
+ .debug_aranges
+ 0x0000000000000688 0x30 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_init.o)
+ .debug_aranges
+ 0x00000000000006b8 0x28 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk_init.o)
+ .debug_aranges
+ 0x00000000000006e0 0xf8 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk.o)
+ .debug_aranges
+ 0x00000000000007d8 0x50 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_time.o)
+ .debug_aranges
+ 0x0000000000000828 0x20 /home/element/xtensa-esp32-elf-2020r3/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/no-rtti/libgcc.a(_bswapsi2.o)
+ .debug_aranges
+ 0x0000000000000848 0x20 /home/element/xtensa-esp32-elf-2020r3/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/no-rtti/libgcc.a(_udivdi3.o)
+
+.debug_ranges 0x0000000000000000 0x1218
+ .debug_ranges 0x0000000000000000 0x10 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(bootloader_start.o)
+ .debug_ranges 0x0000000000000010 0x18 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_bootloader.o)
+ .debug_ranges 0x0000000000000028 0x48 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_bootmgr.o)
+ .debug_ranges 0x0000000000000070 0x58 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_mperror.o)
+ .debug_ranges 0x00000000000000c8 0xb0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_gpio.o)
+ .debug_ranges 0x0000000000000178 0x298 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_utility.o)
+ .debug_ranges 0x0000000000000410 0x118 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_common.o)
+ .debug_ranges 0x0000000000000528 0x38 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(pycom_bootloader_support.o)
+ .debug_ranges 0x0000000000000560 0x30 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(flash_partitions.o)
+ .debug_ranges 0x0000000000000590 0x390 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(esp_image_format.o)
+ .debug_ranges 0x0000000000000920 0x80 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_random.o)
+ .debug_ranges 0x00000000000009a0 0x50 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_sha.o)
+ .debug_ranges 0x00000000000009f0 0xb0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_esp32.o)
+ .debug_ranges 0x0000000000000aa0 0x18 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_efuse_esp32.o)
+ .debug_ranges 0x0000000000000ab8 0x140 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_flash.o)
+ .debug_ranges 0x0000000000000bf8 0x80 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(flash_qio_mode.o)
+ .debug_ranges 0x0000000000000c78 0x70 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_init.o)
+ .debug_ranges 0x0000000000000ce8 0x30 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_clock.o)
+ .debug_ranges 0x0000000000000d18 0x30 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_flash_config_esp32.o)
+ .debug_ranges 0x0000000000000d48 0xe0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/spi_flash/libspi_flash.a(spi_flash_rom_patch.o)
+ .debug_ranges 0x0000000000000e28 0x28 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(cpu_util.o)
+ .debug_ranges 0x0000000000000e50 0xd0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_wdt.o)
+ .debug_ranges 0x0000000000000f20 0x50 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_init.o)
+ .debug_ranges 0x0000000000000f70 0x30 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk_init.o)
+ .debug_ranges 0x0000000000000fa0 0x198 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk.o)
+ .debug_ranges 0x0000000000001138 0x40 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_time.o)
+ .debug_ranges 0x0000000000001178 0xa0 /home/element/xtensa-esp32-elf-2020r3/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/no-rtti/libgcc.a(_udivdi3.o)
+
+.debug_line 0x0000000000000000 0x14f69
+ .debug_line 0x0000000000000000 0x4fa /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(bootloader_start.o)
+ .debug_line 0x00000000000004fa 0x86a /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_bootloader.o)
+ .debug_line 0x0000000000000d64 0x823 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_bootmgr.o)
+ .debug_line 0x0000000000001587 0xa0e /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_mperror.o)
+ .debug_line 0x0000000000001f95 0x13f7 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_gpio.o)
+ .debug_line 0x000000000000338c 0xbb /home/element/xtensa-esp32-elf-2020r3/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/no-rtti/libgcc.a(_lshrdi3.o)
+ .debug_line 0x0000000000003447 0x1d56 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_utility.o)
+ .debug_line 0x000000000000519d 0x10fc /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_common.o)
+ .debug_line 0x0000000000006299 0x7f3 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(pycom_bootloader_support.o)
+ .debug_line 0x0000000000006a8c 0x5dc /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(flash_partitions.o)
+ .debug_line 0x0000000000007068 0x1c90 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(esp_image_format.o)
+ .debug_line 0x0000000000008cf8 0x8cf /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_random.o)
+ .debug_line 0x00000000000095c7 0x7a1 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_sha.o)
+ .debug_line 0x0000000000009d68 0x15c4 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_esp32.o)
+ .debug_line 0x000000000000b32c 0x387 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_efuse_esp32.o)
+ .debug_line 0x000000000000b6b3 0xee7 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_flash.o)
+ .debug_line 0x000000000000c59a 0xb6c /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(flash_qio_mode.o)
+ .debug_line 0x000000000000d106 0x8d3 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_init.o)
+ .debug_line 0x000000000000d9d9 0x5f3 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_clock.o)
+ .debug_line 0x000000000000dfcc 0x840 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_flash_config_esp32.o)
+ .debug_line 0x000000000000e80c 0x1841 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/spi_flash/libspi_flash.a(spi_flash_rom_patch.o)
+ .debug_line 0x000000000001004d 0x3fa /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(cpu_util.o)
+ .debug_line 0x0000000000010447 0x963 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_wdt.o)
+ .debug_line 0x0000000000010daa 0x948 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_init.o)
+ .debug_line 0x00000000000116f2 0x921 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk_init.o)
+ .debug_line 0x0000000000012013 0x198a /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk.o)
+ .debug_line 0x000000000001399d 0x8b7 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_time.o)
+ .debug_line 0x0000000000014254 0x2e2 /home/element/xtensa-esp32-elf-2020r3/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/no-rtti/libgcc.a(_bswapsi2.o)
+ .debug_line 0x0000000000014536 0xa33 /home/element/xtensa-esp32-elf-2020r3/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/no-rtti/libgcc.a(_udivdi3.o)
+
+.debug_str 0x0000000000000000 0xab4a
+ .debug_str 0x0000000000000000 0x95d /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(bootloader_start.o)
+ 0xa38 (size before relaxing)
+ .debug_str 0x000000000000095d 0x242 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_bootloader.o)
+ 0x9fb (size before relaxing)
+ .debug_str 0x0000000000000b9f 0x13c1 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_bootmgr.o)
+ 0x1acd (size before relaxing)
+ .debug_str 0x0000000000001f60 0x121 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_mperror.o)
+ 0x1aec (size before relaxing)
+ .debug_str 0x0000000000002081 0x1b0d /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_gpio.o)
+ 0x320c (size before relaxing)
+ .debug_str 0x0000000000003b8e 0xd2 /home/element/xtensa-esp32-elf-2020r3/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/no-rtti/libgcc.a(_lshrdi3.o)
+ .debug_str 0x0000000000003c60 0x142b /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_utility.o)
+ 0x44e7 (size before relaxing)
+ .debug_str 0x000000000000508b 0x487 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_common.o)
+ 0x2c1f (size before relaxing)
+ .debug_str 0x0000000000005512 0x65 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(pycom_bootloader_support.o)
+ 0x14c8 (size before relaxing)
+ .debug_str 0x0000000000005577 0xb8 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(flash_partitions.o)
+ 0x803 (size before relaxing)
+ .debug_str 0x000000000000562f 0x6bb /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(esp_image_format.o)
+ 0x1df6 (size before relaxing)
+ .debug_str 0x0000000000005cea 0x16a2 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_random.o)
+ 0x4732 (size before relaxing)
+ .debug_str 0x000000000000738c 0x103 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_sha.o)
+ 0x128a (size before relaxing)
+ .debug_str 0x000000000000748f 0x18c0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_esp32.o)
+ 0x56a0 (size before relaxing)
+ .debug_str 0x0000000000008d4f 0x8c /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_efuse_esp32.o)
+ 0x697 (size before relaxing)
+ .debug_str 0x0000000000008ddb 0x221 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_flash.o)
+ 0x16f3 (size before relaxing)
+ .debug_str 0x0000000000008ffc 0x327 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(flash_qio_mode.o)
+ 0x2011 (size before relaxing)
+ .debug_str 0x0000000000009323 0x2cd /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_init.o)
+ 0x348b (size before relaxing)
+ .debug_str 0x00000000000095f0 0x268 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_clock.o)
+ 0x3996 (size before relaxing)
+ .debug_str 0x0000000000009858 0xce /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_flash_config_esp32.o)
+ 0xbe6 (size before relaxing)
+ .debug_str 0x0000000000009926 0x3ca /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/spi_flash/libspi_flash.a(spi_flash_rom_patch.o)
+ 0x25b8 (size before relaxing)
+ .debug_str 0x0000000000009cf0 0xcb /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(cpu_util.o)
+ 0x275c (size before relaxing)
+ .debug_str 0x0000000000009dbb 0x155 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_wdt.o)
+ 0x2389 (size before relaxing)
+ .debug_str 0x0000000000009f10 0xc7 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_init.o)
+ 0x2815 (size before relaxing)
+ .debug_str 0x0000000000009fd7 0x2dd /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk_init.o)
+ 0x46ae (size before relaxing)
+ .debug_str 0x000000000000a2b4 0x4c0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk.o)
+ 0x4a1e (size before relaxing)
+ .debug_str 0x000000000000a774 0x148 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_time.o)
+ 0x256b (size before relaxing)
+ .debug_str 0x000000000000a8bc 0x1b5 /home/element/xtensa-esp32-elf-2020r3/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/no-rtti/libgcc.a(_bswapsi2.o)
+ 0x6df (size before relaxing)
+ .debug_str 0x000000000000aa71 0xd9 /home/element/xtensa-esp32-elf-2020r3/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/no-rtti/libgcc.a(_udivdi3.o)
+ 0x759 (size before relaxing)
+
+.comment 0x0000000000000000 0x25
+ .comment 0x0000000000000000 0x25 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(bootloader_start.o)
+ 0x26 (size before relaxing)
+ .comment 0x0000000000000025 0x26 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_bootloader.o)
+ .comment 0x0000000000000025 0x26 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_bootmgr.o)
+ .comment 0x0000000000000025 0x26 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_mperror.o)
+ .comment 0x0000000000000025 0x26 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_gpio.o)
+ .comment 0x0000000000000025 0x26 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_utility.o)
+ .comment 0x0000000000000025 0x26 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_common.o)
+ .comment 0x0000000000000025 0x26 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(pycom_bootloader_support.o)
+ .comment 0x0000000000000025 0x26 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(flash_partitions.o)
+ .comment 0x0000000000000025 0x26 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(esp_image_format.o)
+ .comment 0x0000000000000025 0x26 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_random.o)
+ .comment 0x0000000000000025 0x26 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_sha.o)
+ .comment 0x0000000000000025 0x26 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_esp32.o)
+ .comment 0x0000000000000025 0x26 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_efuse_esp32.o)
+ .comment 0x0000000000000025 0x26 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_flash.o)
+ .comment 0x0000000000000025 0x26 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(flash_qio_mode.o)
+ .comment 0x0000000000000025 0x26 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_init.o)
+ .comment 0x0000000000000025 0x26 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_clock.o)
+ .comment 0x0000000000000025 0x26 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_flash_config_esp32.o)
+ .comment 0x0000000000000025 0x26 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/spi_flash/libspi_flash.a(spi_flash_rom_patch.o)
+ .comment 0x0000000000000025 0x26 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(cpu_util.o)
+ .comment 0x0000000000000025 0x26 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_wdt.o)
+ .comment 0x0000000000000025 0x26 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_init.o)
+ .comment 0x0000000000000025 0x26 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk_init.o)
+ .comment 0x0000000000000025 0x26 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk.o)
+ .comment 0x0000000000000025 0x26 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_time.o)
+ .comment 0x0000000000000025 0x26 /home/element/xtensa-esp32-elf-2020r3/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/no-rtti/libgcc.a(_bswapsi2.o)
+ .comment 0x0000000000000025 0x26 /home/element/xtensa-esp32-elf-2020r3/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/no-rtti/libgcc.a(_udivdi3.o)
+
+.xtensa.info 0x0000000000000000 0x38
+ .xtensa.info 0x0000000000000000 0x38 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(bootloader_start.o)
+ .xtensa.info 0x0000000000000038 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_bootloader.o)
+ .xtensa.info 0x0000000000000038 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_bootmgr.o)
+ .xtensa.info 0x0000000000000038 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_mperror.o)
+ .xtensa.info 0x0000000000000038 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/main/libmain.a(pycom_gpio.o)
+ .xtensa.info 0x0000000000000038 0x0 /home/element/xtensa-esp32-elf-2020r3/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/no-rtti/libgcc.a(_lshrdi3.o)
+ .xtensa.info 0x0000000000000038 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_utility.o)
+ .xtensa.info 0x0000000000000038 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_common.o)
+ .xtensa.info 0x0000000000000038 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(pycom_bootloader_support.o)
+ .xtensa.info 0x0000000000000038 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(flash_partitions.o)
+ .xtensa.info 0x0000000000000038 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(esp_image_format.o)
+ .xtensa.info 0x0000000000000038 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_random.o)
+ .xtensa.info 0x0000000000000038 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_sha.o)
+ .xtensa.info 0x0000000000000038 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_esp32.o)
+ .xtensa.info 0x0000000000000038 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_efuse_esp32.o)
+ .xtensa.info 0x0000000000000038 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_flash.o)
+ .xtensa.info 0x0000000000000038 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(flash_qio_mode.o)
+ .xtensa.info 0x0000000000000038 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_init.o)
+ .xtensa.info 0x0000000000000038 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_clock.o)
+ .xtensa.info 0x0000000000000038 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/bootloader_support/libbootloader_support.a(bootloader_flash_config_esp32.o)
+ .xtensa.info 0x0000000000000038 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/log/liblog.a(log_noos.o)
+ .xtensa.info 0x0000000000000038 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/spi_flash/libspi_flash.a(spi_flash_rom_patch.o)
+ .xtensa.info 0x0000000000000038 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(cpu_util.o)
+ .xtensa.info 0x0000000000000038 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_wdt.o)
+ .xtensa.info 0x0000000000000038 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_init.o)
+ .xtensa.info 0x0000000000000038 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk_init.o)
+ .xtensa.info 0x0000000000000038 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_clk.o)
+ .xtensa.info 0x0000000000000038 0x0 /home/element/Work/github/pycom-esp-idf/examples/wifi/scan/build/bootloader/soc/libsoc.a(rtc_time.o)
+ .xtensa.info 0x0000000000000038 0x0 /home/element/xtensa-esp32-elf-2020r3/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/no-rtti/libgcc.a(_bswapsi2.o)
+ .xtensa.info 0x0000000000000038 0x0 /home/element/xtensa-esp32-elf-2020r3/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/no-rtti/libgcc.a(_divdi3.o)
+ .xtensa.info 0x0000000000000038 0x0 /home/element/xtensa-esp32-elf-2020r3/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/no-rtti/libgcc.a(_udivdi3.o)
diff --git a/esp32/bootloader/lib/libbootloader_support.a b/esp32/bootloader/lib/libbootloader_support.a
index 7f15307e23..d976505458 100644
Binary files a/esp32/bootloader/lib/libbootloader_support.a and b/esp32/bootloader/lib/libbootloader_support.a differ
diff --git a/esp32/bootloader/lib/libefuse.a b/esp32/bootloader/lib/libefuse.a
index 173eeec9c4..3d2df033b0 100644
Binary files a/esp32/bootloader/lib/libefuse.a and b/esp32/bootloader/lib/libefuse.a differ
diff --git a/esp32/bootloader/lib/liblog.a b/esp32/bootloader/lib/liblog.a
index 78a2937b20..93c6e3e3c4 100644
Binary files a/esp32/bootloader/lib/liblog.a and b/esp32/bootloader/lib/liblog.a differ
diff --git a/esp32/bootloader/lib/libmain.a b/esp32/bootloader/lib/libmain.a
new file mode 100644
index 0000000000..e9f864e869
Binary files /dev/null and b/esp32/bootloader/lib/libmain.a differ
diff --git a/esp32/bootloader/lib/libmicro-ecc.a b/esp32/bootloader/lib/libmicro-ecc.a
index 0effdb6e3e..718d9a94db 100644
Binary files a/esp32/bootloader/lib/libmicro-ecc.a and b/esp32/bootloader/lib/libmicro-ecc.a differ
diff --git a/esp32/bootloader/lib/libsoc.a b/esp32/bootloader/lib/libsoc.a
index 4de815ae6e..5a759b7fbf 100644
Binary files a/esp32/bootloader/lib/libsoc.a and b/esp32/bootloader/lib/libsoc.a differ
diff --git a/esp32/bootloader/lib/libspi_flash.a b/esp32/bootloader/lib/libspi_flash.a
index cd2afbaa38..928669ca2a 100644
Binary files a/esp32/bootloader/lib/libspi_flash.a and b/esp32/bootloader/lib/libspi_flash.a differ
diff --git a/esp32/bootloader/mperror.c b/esp32/bootloader/mperror.c
deleted file mode 100644
index d11795cf6d..0000000000
--- a/esp32/bootloader/mperror.c
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * Copyright (c) 2020, Pycom Limited.
- *
- * This software is licensed under the GNU GPL version 3 or any
- * later version, with permitted additional terms. For more information
- * see the Pycom Licence v1.0 document supplied with this file, or
- * available at https://www.pycom.io/opensource/licensing
- */
-#ifndef RGB_LED_DISABLE
-#include
-#include
-#include
-#include
-
-#include "xtensa/xtruntime.h"
-#include "mpconfigboard.h"
-#include "mperror.h"
-
-#include "esp_heap_caps.h"
-#include "sdkconfig.h"
-#include "esp_system.h"
-#include "esp_spi_flash.h"
-#include "nvs_flash.h"
-
-#include "gpio.h"
-
-/******************************************************************************
- DEFINE CONSTANTS
- ******************************************************************************/
-#define MPERROR_TOOGLE_MS (50)
-#define MPERROR_SIGNAL_ERROR_MS (1200)
-#define MPERROR_HEARTBEAT_ON_MS (80)
-#define MPERROR_HEARTBEAT_OFF_MS (3920)
-
-#define MPERROR_HEARTBEAT_PRIORITY (5)
-
-/******************************************************************************
- DECLARE PRIVATE DATA
- ******************************************************************************/
-
-struct mperror_heart_beat {
- uint32_t off_time;
- uint32_t on_time;
- bool beating;
- bool enabled;
- bool do_disable;
-} mperror_heart_beat = {.off_time = 0, .on_time = 0, .beating = false, .enabled = false, .do_disable = false};
-
-void TASK_Heartbeat (void *pvParameters);
-
-/******************************************************************************
- DEFINE PUBLIC FUNCTIONS
- ******************************************************************************/
-
-void mperror_init0 (void) {
- gpio_config_t gpioconf = {.pin_bit_mask = 1ull << MICROPY_HW_HB_PIN_NUM,
- .mode = GPIO_MODE_OUTPUT,
- .pull_up_en = GPIO_PULLUP_DISABLE,
- .pull_down_en = GPIO_PULLDOWN_DISABLE,
- .intr_type = GPIO_INTR_DISABLE};
- gpio_config(&gpioconf);
-
- mperror_heart_beat.enabled = true;
- //delay introduced to separate last falling edge of signal and next color code
- ets_delay_us(300);
- mperror_heartbeat_switch_off();
-}
-
-__attribute__((noreturn)) void mperror_fatal_error (void) {
- // signal the crash with the system led
- mperror_set_rgb_color(MPERROR_FATAL_COLOR);
- for ( ; ; );
-}
-
-void mperror_heartbeat_switch_off (void) {
- if (mperror_heart_beat.enabled) {
- mperror_heart_beat.on_time = 0;
- mperror_heart_beat.off_time = 0;
- mperror_set_rgb_color(0);
- }
-}
-
-void mperror_enable_heartbeat (bool enable) {
- if (enable) {
- mperror_heart_beat.enabled = true;
- mperror_heart_beat.do_disable = false;
- mperror_heartbeat_switch_off();
- } else {
- mperror_heart_beat.do_disable = true;
- mperror_heart_beat.enabled = false;
- }
-}
-
-bool mperror_is_heartbeat_enabled (void) {
- return mperror_heart_beat.enabled;
-}
-
-#define BIT_1_HIGH_TIME_NS (950)
-#define BIT_1_LOW_TIME_NS (22)
-#define BIT_0_HIGH_TIME_NS (40)
-#define BIT_0_LOW_TIME_NS (500)
-#define RESET_TIME_US (52)
-
-#define NS_TO_COUNT(ns) (ns / 22)
-
-static inline uint32_t get_ccount(void) {
- uint32_t r;
- asm volatile ("rsr %0, ccount" : "=r"(r));
- return r;
-}
-
-static void IRAM_ATTR wait_for_count(uint32_t count) {
- uint32_t volatile register cr = get_ccount();
- uint32_t volatile register ct = cr + count;
- if (ct > cr) {
- while (get_ccount() < ct);
- } else {
- while (ct < get_ccount());
- }
-}
-
-#define DELAY_NS(ns) wait_for_count(NS_TO_COUNT(ns))
-#define GP0_PIN_NUMBER (0)
-
-void IRAM_ATTR mperror_set_rgb_color (uint32_t rgbcolor) {
- uint32_t volatile register grbcolor =
- ((rgbcolor << 8) & 0x00FF0000) | ((rgbcolor >> 8) & 0x0000FF00) | (rgbcolor & 0x000000FF);
-
- uint32_t volatile register ilevel = XTOS_DISABLE_ALL_INTERRUPTS;
-
- for (int volatile register i = 24; i != 0; --i) {
- if (grbcolor & 0x800000) {
- GPIO_REG_WRITE(GPIO_OUT_W1TS_REG, 1 << GP0_PIN_NUMBER);
- DELAY_NS(BIT_1_HIGH_TIME_NS);
- GPIO_REG_WRITE(GPIO_OUT_W1TC_REG, 1 << GP0_PIN_NUMBER);
- DELAY_NS(BIT_1_LOW_TIME_NS);
- } else {
- GPIO_REG_WRITE(GPIO_OUT_W1TS_REG, 1 << GP0_PIN_NUMBER);
-// DELAY_NS(BIT_0_HIGH_TIME_NS);
- GPIO_REG_WRITE(GPIO_OUT_W1TC_REG, 1 << GP0_PIN_NUMBER);
- DELAY_NS(BIT_0_LOW_TIME_NS);
- }
- // put the next bit in place
- grbcolor <<= 1;
- }
- XTOS_RESTORE_INTLEVEL(ilevel);
- ets_delay_us(RESET_TIME_US);
-}
-
-#else
-
-__attribute__((noreturn)) void mperror_fatal_error (void) {
- for ( ; ; );
-}
-
-#endif //RGB_LED_DISABLE
diff --git a/esp32/can/CAN.c b/esp32/can/CAN.c
index 07c9c57fe3..6d7ee682c7 100755
--- a/esp32/can/CAN.c
+++ b/esp32/can/CAN.c
@@ -32,7 +32,7 @@
#include "freertos/FreeRTOS.h"
#include "freertos/queue.h"
-#include "esp_intr.h"
+#include "esp_intr_alloc.h"
#include "soc/dport_reg.h"
#include
diff --git a/esp32/check_xtensa_version.py b/esp32/check_xtensa_version.py
new file mode 100644
index 0000000000..503201202b
--- /dev/null
+++ b/esp32/check_xtensa_version.py
@@ -0,0 +1,29 @@
+import argparse
+from subprocess import Popen, PIPE
+
+
+def main():
+ cmd_parser = argparse.ArgumentParser()
+ cmd_parser.add_argument('--VERSION', default=None)
+ cmd_args = cmd_parser.parse_args()
+ version = cmd_args.VERSION
+
+ process = Popen(["xtensa-esp32-elf-gcc", "--version", "."], stdout=PIPE)
+ (output, err) = process.communicate()
+ exit_code = process.wait()
+ if(exit_code == 0):
+ if version in str(output):
+ print("Xtensa version OK!")
+ exit(0)
+ else:
+ print("xtensa-esp32-elf-gcc version NOT OK. expected:" + version, "but I got:", output)
+ # Non zero exit code means error
+ exit(1)
+ else:
+ print("xtensa-esp32-elf-gcc dropped an error, its version cannot be checked!")
+ # Non zero exit code means error
+ exit(1)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/esp32/esp32.project.ld b/esp32/esp32.project.ld
index 15c9d87d00..9ebb5b30e2 100644
--- a/esp32/esp32.project.ld
+++ b/esp32/esp32.project.ld
@@ -1,6 +1,6 @@
/* Automatically generated file; DO NOT EDIT */
/* Espressif IoT Development Framework Linker Script */
-/* Generated from: /home/peter/docs/pycom-esp-idf/components/esp32/ld/esp32.project.ld.in */
+/* Generated from: /home/element/Work/github/pycom-esp-idf/components/esp32/ld/esp32.project.ld.in */
/* Default entry point: */
ENTRY(call_start_cpu0);
@@ -14,14 +14,15 @@ SECTIONS
{
. = ALIGN(4);
- *( .rtc.literal .rtc.text .rtc.text.*)
+ *(EXCLUDE_FILE(*libsoc.a:uart_hal_iram.*) .rtc.literal EXCLUDE_FILE(*libsoc.a:uart_hal_iram.*) .rtc.text EXCLUDE_FILE(*libsoc.a:uart_hal_iram.*) .rtc.text.*)
+ *libsoc.a:uart_hal_iram.*( .rtc.literal .rtc.text .rtc.text.*)
*rtc_wake_stub*.*(.literal .text .literal.* .text.*)
_rtc_text_end = ABSOLUTE(.);
} > rtc_iram_seg
-
+
/*
- This section is required to skip rtc.text area because rtc_iram_seg and
+ This section is required to skip rtc.text area because rtc_iram_seg and
rtc_data_seg are reflect the same address space on different buses.
*/
.rtc.dummy :
@@ -32,8 +33,8 @@ SECTIONS
_rtc_dummy_end = ABSOLUTE(.);
} > rtc_data_seg
- /* This section located in RTC FAST Memory area.
- It holds data marked with RTC_FAST_ATTR attribute.
+ /* This section located in RTC FAST Memory area.
+ It holds data marked with RTC_FAST_ATTR attribute.
See the file "esp_attr.h" for more information.
*/
.rtc.force_fast :
@@ -49,14 +50,15 @@ SECTIONS
data/rodata, including from any source file
named rtc_wake_stub*.c and the data marked with
RTC_DATA_ATTR, RTC_RODATA_ATTR attributes.
- The memory location of the data is dependent on
+ The memory location of the data is dependent on
CONFIG_ESP32_RTCDATA_IN_FAST_MEM option.
*/
.rtc.data :
{
_rtc_data_start = ABSOLUTE(.);
- *( .rtc.data .rtc.data.* .rtc.rodata .rtc.rodata.*)
+ *(EXCLUDE_FILE(*libsoc.a:uart_hal_iram.*) .rtc.data EXCLUDE_FILE(*libsoc.a:uart_hal_iram.*) .rtc.data.* EXCLUDE_FILE(*libsoc.a:uart_hal_iram.*) .rtc.rodata EXCLUDE_FILE(*libsoc.a:uart_hal_iram.*) .rtc.rodata.*)
+ *libsoc.a:uart_hal_iram.*( .rtc.data .rtc.data.* .rtc.rodata .rtc.rodata.*)
*rtc_wake_stub*.*(.data .rodata .data.* .rodata.* .bss .bss.*)
_rtc_data_end = ABSOLUTE(.);
@@ -69,16 +71,17 @@ SECTIONS
*rtc_wake_stub*.*(.bss .bss.*)
*rtc_wake_stub*.*(COMMON)
- *( .rtc.bss)
+ *(EXCLUDE_FILE(*libsoc.a:uart_hal_iram.*) .rtc.bss)
+ *libsoc.a:uart_hal_iram.*( .rtc.bss)
_rtc_bss_end = ABSOLUTE(.);
} > rtc_data_location
- /* This section holds data that should not be initialized at power up
+ /* This section holds data that should not be initialized at power up
and will be retained during deep sleep.
User data marked with RTC_NOINIT_ATTR will be placed
- into this section. See the file "esp_attr.h" for more information.
- The memory location of the data is dependent on
+ into this section. See the file "esp_attr.h" for more information.
+ The memory location of the data is dependent on
CONFIG_ESP32_RTCDATA_IN_FAST_MEM option.
*/
.rtc_noinit (NOLOAD):
@@ -90,8 +93,8 @@ SECTIONS
_rtc_noinit_end = ABSOLUTE(.);
} > rtc_data_location
- /* This section located in RTC SLOW Memory area.
- It holds data marked with RTC_SLOW_ATTR attribute.
+ /* This section located in RTC SLOW Memory area.
+ It holds data marked with RTC_SLOW_ATTR attribute.
See the file "esp_attr.h" for more information.
*/
.rtc.force_slow :
@@ -104,17 +107,17 @@ SECTIONS
} > rtc_slow_seg
/* Get size of rtc slow data based on rtc_data_location alias */
- _rtc_slow_length = (ORIGIN(rtc_slow_seg) == ORIGIN(rtc_data_location))
- ? (_rtc_force_slow_end - _rtc_data_start)
+ _rtc_slow_length = (ORIGIN(rtc_slow_seg) == ORIGIN(rtc_data_location))
+ ? (_rtc_force_slow_end - _rtc_data_start)
: (_rtc_force_slow_end - _rtc_force_slow_start);
- _rtc_fast_length = (ORIGIN(rtc_slow_seg) == ORIGIN(rtc_data_location))
- ? (_rtc_force_fast_end - _rtc_fast_start)
+ _rtc_fast_length = (ORIGIN(rtc_slow_seg) == ORIGIN(rtc_data_location))
+ ? (_rtc_force_fast_end - _rtc_fast_start)
: (_rtc_noinit_end - _rtc_fast_start);
-
+
ASSERT((_rtc_slow_length <= LENGTH(rtc_slow_seg)),
"RTC_SLOW segment data does not fit.")
-
+
ASSERT((_rtc_fast_length <= LENGTH(rtc_data_seg)),
"RTC_FAST segment data does not fit.")
@@ -162,165 +165,184 @@ SECTIONS
/* Code marked as runnning out of IRAM */
_iram_text_start = ABSOLUTE(.);
- *( .iram1 .iram1.*)
- *libspi_flash.a:spi_flash_rom_patch.*( .literal .literal.* .text .text.*)
+ *(EXCLUDE_FILE(*libsoc.a:uart_hal_iram.*) .iram1 EXCLUDE_FILE(*libsoc.a:uart_hal_iram.*) .iram1.*)
+ *libapp_trace.a:SEGGER_RTT_esp32.*( .literal .literal.* .text .text.*)
+ *libapp_trace.a:SEGGER_SYSVIEW.*( .literal .literal.* .text .text.*)
+ *libapp_trace.a:SEGGER_SYSVIEW_Config_FreeRTOS.*( .literal .literal.* .text .text.*)
+ *libapp_trace.a:SEGGER_SYSVIEW_FreeRTOS.*( .literal .literal.* .text .text.*)
+ *libapp_trace.a:app_trace.*( .literal .literal.* .text .text.*)
+ *libapp_trace.a:app_trace_util.*( .literal .literal.* .text .text.*)
+ *libc.a:creat.*( .literal .literal.* .text .text.*)
+ *libc.a:isatty.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-abs.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-asctime.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-asctime_r.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-atoi.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-atol.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-bzero.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-close.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-creat.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-ctime.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-ctime_r.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-ctype_.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-div.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-environ.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-envlock.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-fclose.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-fflush.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-findfp.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-fputwc.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-fvwrite.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-fwalk.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-getenv_r.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-gettzinfo.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-gmtime.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-gmtime_r.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-impure.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-isalnum.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-isalpha.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-isascii.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-isblank.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-iscntrl.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-isdigit.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-isgraph.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-islower.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-isprint.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-ispunct.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-isspace.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-isupper.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-itoa.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-labs.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-lcltime.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-lcltime_r.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-ldiv.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-longjmp.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-makebuf.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-memccpy.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-memchr.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-memcmp.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-memcpy.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-memmove.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-memrchr.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-memset.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-mktime.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-month_lengths.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-open.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-quorem.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-raise.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-rand.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-rand_r.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-read.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-refill.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-rshift.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-s_fpclassify.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-sbrk.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-sccl.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-setjmp.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-sf_nan.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-srand.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-stdio.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-strcasecmp.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-strcasestr.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-strcat.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-strchr.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-strcmp.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-strcoll.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-strcpy.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-strcspn.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-strdup.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-strdup_r.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-strftime.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-strlcat.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-strlcpy.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-strlen.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-strlwr.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-strncasecmp.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-strncat.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-strncmp.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-strncpy.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-strndup.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-strndup_r.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-strnlen.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-strptime.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-strrchr.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-strsep.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-strspn.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-strstr.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-strtok_r.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-strtol.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-strtoul.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-strupr.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-sysclose.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-sysopen.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-sysread.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-syssbrk.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-system.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-systimes.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-syswrite.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-time.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-timelocal.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-toascii.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-tolower.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-toupper.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-tzcalc_limits.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-tzlock.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-tzset.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-tzset_r.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-tzvars.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-ungetc.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-utoa.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-wbuf.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-wcrtomb.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-wctomb_r.*( .literal .literal.* .text .text.*)
+ *libc.a:lib_a-wsetup.*( .literal .literal.* .text .text.*)
+ *libc.a:lock.*( .literal .literal.* .text .text.*)
+ *libesp32.a:panic.*( .literal .literal.* .text .text.*)
+ *libesp_event.a:default_event_loop.*(.literal.esp_event_isr_post .text.esp_event_isr_post)
+ *libesp_event.a:esp_event.*(.literal.esp_event_isr_post_to .text.esp_event_isr_post_to)
*libesp_ringbuf.a:( .literal .literal.* .text .text.*)
+ *libfreertos.a:( .literal .literal.* .text .text.*)
+ *libgcc.a:_divsf3.*( .literal .literal.* .text .text.*)
+ *libgcc.a:lib2funcs.*( .literal .literal.* .text .text.*)
+ *libgcov.a:( .literal .literal.* .text .text.*)
*libhal.a:( .literal .literal.* .text .text.*)
- *libapp_trace.a:( .literal .literal.* .text .text.*)
- *libesp32.a:panic.*( .literal .literal.* .text .text.*)
- *libespcoredump.a:core_dump_port.*( .literal .literal.* .text .text.*)
- *libespcoredump.a:core_dump_flash.*( .literal .literal.* .text .text.*)
- *libespcoredump.a:core_dump_uart.*( .literal .literal.* .text .text.*)
- *libespcoredump.a:core_dump_common.*( .literal .literal.* .text .text.*)
+ *libheap.a:multi_heap.*( .literal .literal.* .text .text.*)
+ *libheap.a:multi_heap_poisoning.*( .literal .literal.* .text .text.*)
+ *liblog.a:log.*(.literal.esp_log_write .text.esp_log_write)
+ *liblog.a:log_freertos.*(.literal.esp_log_early_timestamp .text.esp_log_early_timestamp)
+ *liblog.a:log_freertos.*(.literal.esp_log_impl_lock .text.esp_log_impl_lock)
+ *liblog.a:log_freertos.*(.literal.esp_log_impl_lock_timeout .text.esp_log_impl_lock_timeout)
+ *liblog.a:log_freertos.*(.literal.esp_log_impl_unlock .text.esp_log_impl_unlock)
+ *liblog.a:log_freertos.*(.literal.esp_log_timestamp .text.esp_log_timestamp)
+ *libnewlib.a:heap.*( .literal .literal.* .text .text.*)
*librtc.a:( .literal .literal.* .text .text.*)
- *libgcc.a:lib2funcs.*( .literal .literal.* .text .text.*)
- *libsoc.a:rtc_time.*( .literal .literal.* .text .text.*)
*libsoc.a:cpu_util.*( .literal .literal.* .text .text.*)
- *libsoc.a:rtc_clk_init.*( .literal .literal.* .text .text.*)
+ *libsoc.a:i2c_hal_iram.*( .literal .literal.* .text .text.*)
+ *libsoc.a:ledc_hal_iram.*( .literal .literal.* .text .text.*)
+ *libsoc.a:lldesc.*( .literal .literal.* .text .text.*)
*libsoc.a:rtc_clk.*( .literal .literal.* .text .text.*)
+ *libsoc.a:rtc_clk_init.*( .literal .literal.* .text .text.*)
*libsoc.a:rtc_init.*( .literal .literal.* .text .text.*)
+ *libsoc.a:rtc_periph.*( .literal .literal.* .text .text.*)
*libsoc.a:rtc_pm.*( .literal .literal.* .text .text.*)
*libsoc.a:rtc_sleep.*( .literal .literal.* .text .text.*)
+ *libsoc.a:rtc_time.*( .literal .literal.* .text .text.*)
*libsoc.a:rtc_wdt.*( .literal .literal.* .text .text.*)
- *libsoc.a:rtc_periph.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-time.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-makebuf.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-strcasestr.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-tzlock.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-memset.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-strdup.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-environ.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-tzcalc_limits.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-labs.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-strlcat.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-strstr.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-lcltime_r.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-ungetc.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-strlen.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:isatty.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-tzset_r.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-asctime_r.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-tolower.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-memccpy.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-wctomb_r.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-strcspn.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-strcasecmp.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-iscntrl.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-strncasecmp.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-abs.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-sf_nan.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-asctime.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-strncmp.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-fvwrite.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-isblank.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-read.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-tzset.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-rand_r.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-ispunct.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-s_fpclassify.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-quorem.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-strspn.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-strrchr.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-strndup.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-gettzinfo.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-fclose.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-isalnum.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-strtol.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-creat.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-fwalk.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-memcmp.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-strcmp.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-rshift.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-toascii.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-isdigit.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-isalpha.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-wcrtomb.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-tzvars.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-strcoll.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-strndup_r.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-gmtime.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-gmtime_r.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-sccl.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-wbuf.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-mktime.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-ctime_r.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-isascii.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-memcpy.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:creat.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-sysclose.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-setjmp.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-srand.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-strcat.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-bzero.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-month_lengths.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-strncat.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-strftime.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-isupper.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-wsetup.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-close.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-islower.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-strncpy.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-raise.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-atol.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-ldiv.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-getenv_r.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-isspace.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-system.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-strchr.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-memchr.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-refill.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-atoi.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-envlock.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-strnlen.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-isgraph.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-syssbrk.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-sysread.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-longjmp.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-sbrk.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-timelocal.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-strlcpy.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-strdup_r.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-sysopen.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-toupper.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-strtoul.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-strsep.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-itoa.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-memrchr.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-open.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-utoa.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-strcpy.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-stdio.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-fputwc.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-strtok_r.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-memmove.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-isprint.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-syswrite.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-impure.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-rand.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-ctime.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-fflush.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-strupr.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-lcltime.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-strlwr.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-strptime.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-findfp.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-systimes.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-div.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lib_a-ctype_.*( .literal .literal.* .text .text.*)
- *libc-psram-workaround.a:lock.*( .literal .literal.* .text .text.*)
- *libfreertos.a:( .literal .literal.* .text .text.*)
- *libgcov.a:( .literal .literal.* .text .text.*)
- *libxtensa-debug-module.a:eri.*( .literal .literal.* .text .text.*)
- *libheap.a:multi_heap.*( .literal .literal.* .text .text.*)
- *libheap.a:multi_heap_poisoning.*( .literal .literal.* .text .text.*)
+ *libsoc.a:spi_flash_hal_gpspi.*( .literal .literal.* .text .text.*)
+ *libsoc.a:spi_flash_hal_iram.*( .literal .literal.* .text .text.*)
+ *libsoc.a:spi_hal_iram.*( .literal .literal.* .text .text.*)
+ *libsoc.a:spi_slave_hal_iram.*( .literal .literal.* .text .text.*)
+ *libsoc.a:uart_hal_iram.*( .iram1 .iram1.*)
+ *libspi_flash.a:memspi_host_driver.*( .literal .literal.* .text .text.*)
+ *libspi_flash.a:spi_flash_chip_gd.*( .literal .literal.* .text .text.*)
+ *libspi_flash.a:spi_flash_chip_generic.*( .literal .literal.* .text .text.*)
+ *libspi_flash.a:spi_flash_chip_issi.*( .literal .literal.* .text .text.*)
+ *libspi_flash.a:spi_flash_rom_patch.*( .literal .literal.* .text .text.*)
+ *libxtensa.a:eri.*( .literal .literal.* .text .text.*)
_iram_text_end = ABSOLUTE(.);
- _iram_end = ABSOLUTE(.);
} > iram0_0_seg
- ASSERT(((_iram_text_end - ORIGIN(iram0_0_seg)) <= LENGTH(iram0_0_seg)),
- "IRAM0 segment data does not fit.")
-
.dram0.data :
{
_data_start = ABSOLUTE(.);
@@ -332,6 +354,10 @@ SECTIONS
*libbtdm_app.a:(.data .data.*)
. = ALIGN (4);
_btdm_data_end = ABSOLUTE(.);
+ _nimble_data_start = ABSOLUTE(.);
+ *libnimble.a:(.data .data.*)
+ . = ALIGN (4);
+ _nimble_data_end = ABSOLUTE(.);
*(.gnu.linkonce.d.*)
*(.data1)
*(.sdata)
@@ -342,139 +368,163 @@ SECTIONS
*(.gnu.linkonce.s2.*)
*(.jcr)
- *( .data .data.* .dram1 .dram1.*)
- *libapp_trace.a:( .rodata .rodata.*)
+
+ *(EXCLUDE_FILE(*libsoc.a:uart_hal_iram.*) .data EXCLUDE_FILE(*libsoc.a:uart_hal_iram.*) .data.* EXCLUDE_FILE(*libsoc.a:uart_hal_iram.*) .dram1 EXCLUDE_FILE(*libsoc.a:uart_hal_iram.*) .dram1.*)
+ *libapp_trace.a:SEGGER_RTT_esp32.*( .rodata .rodata.*)
+ *libapp_trace.a:SEGGER_SYSVIEW.*( .rodata .rodata.*)
+ *libapp_trace.a:SEGGER_SYSVIEW_Config_FreeRTOS.*( .rodata .rodata.*)
+ *libapp_trace.a:SEGGER_SYSVIEW_FreeRTOS.*( .rodata .rodata.*)
+ *libapp_trace.a:app_trace.*( .rodata .rodata.*)
+ *libapp_trace.a:app_trace_util.*( .rodata .rodata.*)
+ *libc.a:creat.*( .rodata .rodata.*)
+ *libc.a:isatty.*( .rodata .rodata.*)
+ *libc.a:lib_a-abs.*( .rodata .rodata.*)
+ *libc.a:lib_a-asctime.*( .rodata .rodata.*)
+ *libc.a:lib_a-asctime_r.*( .rodata .rodata.*)
+ *libc.a:lib_a-atoi.*( .rodata .rodata.*)
+ *libc.a:lib_a-atol.*( .rodata .rodata.*)
+ *libc.a:lib_a-bzero.*( .rodata .rodata.*)
+ *libc.a:lib_a-close.*( .rodata .rodata.*)
+ *libc.a:lib_a-creat.*( .rodata .rodata.*)
+ *libc.a:lib_a-ctime.*( .rodata .rodata.*)
+ *libc.a:lib_a-ctime_r.*( .rodata .rodata.*)
+ *libc.a:lib_a-ctype_.*( .rodata .rodata.*)
+ *libc.a:lib_a-div.*( .rodata .rodata.*)
+ *libc.a:lib_a-environ.*( .rodata .rodata.*)
+ *libc.a:lib_a-envlock.*( .rodata .rodata.*)
+ *libc.a:lib_a-fclose.*( .rodata .rodata.*)
+ *libc.a:lib_a-fflush.*( .rodata .rodata.*)
+ *libc.a:lib_a-findfp.*( .rodata .rodata.*)
+ *libc.a:lib_a-fputwc.*( .rodata .rodata.*)
+ *libc.a:lib_a-fvwrite.*( .rodata .rodata.*)
+ *libc.a:lib_a-fwalk.*( .rodata .rodata.*)
+ *libc.a:lib_a-getenv_r.*( .rodata .rodata.*)
+ *libc.a:lib_a-gettzinfo.*( .rodata .rodata.*)
+ *libc.a:lib_a-gmtime.*( .rodata .rodata.*)
+ *libc.a:lib_a-gmtime_r.*( .rodata .rodata.*)
+ *libc.a:lib_a-impure.*( .rodata .rodata.*)
+ *libc.a:lib_a-isalnum.*( .rodata .rodata.*)
+ *libc.a:lib_a-isalpha.*( .rodata .rodata.*)
+ *libc.a:lib_a-isascii.*( .rodata .rodata.*)
+ *libc.a:lib_a-isblank.*( .rodata .rodata.*)
+ *libc.a:lib_a-iscntrl.*( .rodata .rodata.*)
+ *libc.a:lib_a-isdigit.*( .rodata .rodata.*)
+ *libc.a:lib_a-isgraph.*( .rodata .rodata.*)
+ *libc.a:lib_a-islower.*( .rodata .rodata.*)
+ *libc.a:lib_a-isprint.*( .rodata .rodata.*)
+ *libc.a:lib_a-ispunct.*( .rodata .rodata.*)
+ *libc.a:lib_a-isspace.*( .rodata .rodata.*)
+ *libc.a:lib_a-isupper.*( .rodata .rodata.*)
+ *libc.a:lib_a-itoa.*( .rodata .rodata.*)
+ *libc.a:lib_a-labs.*( .rodata .rodata.*)
+ *libc.a:lib_a-lcltime.*( .rodata .rodata.*)
+ *libc.a:lib_a-lcltime_r.*( .rodata .rodata.*)
+ *libc.a:lib_a-ldiv.*( .rodata .rodata.*)
+ *libc.a:lib_a-longjmp.*( .rodata .rodata.*)
+ *libc.a:lib_a-makebuf.*( .rodata .rodata.*)
+ *libc.a:lib_a-memccpy.*( .rodata .rodata.*)
+ *libc.a:lib_a-memchr.*( .rodata .rodata.*)
+ *libc.a:lib_a-memcmp.*( .rodata .rodata.*)
+ *libc.a:lib_a-memcpy.*( .rodata .rodata.*)
+ *libc.a:lib_a-memmove.*( .rodata .rodata.*)
+ *libc.a:lib_a-memrchr.*( .rodata .rodata.*)
+ *libc.a:lib_a-memset.*( .rodata .rodata.*)
+ *libc.a:lib_a-mktime.*( .rodata .rodata.*)
+ *libc.a:lib_a-month_lengths.*( .rodata .rodata.*)
+ *libc.a:lib_a-open.*( .rodata .rodata.*)
+ *libc.a:lib_a-quorem.*( .rodata .rodata.*)
+ *libc.a:lib_a-raise.*( .rodata .rodata.*)
+ *libc.a:lib_a-rand.*( .rodata .rodata.*)
+ *libc.a:lib_a-rand_r.*( .rodata .rodata.*)
+ *libc.a:lib_a-read.*( .rodata .rodata.*)
+ *libc.a:lib_a-refill.*( .rodata .rodata.*)
+ *libc.a:lib_a-rshift.*( .rodata .rodata.*)
+ *libc.a:lib_a-s_fpclassify.*( .rodata .rodata.*)
+ *libc.a:lib_a-sbrk.*( .rodata .rodata.*)
+ *libc.a:lib_a-sccl.*( .rodata .rodata.*)
+ *libc.a:lib_a-setjmp.*( .rodata .rodata.*)
+ *libc.a:lib_a-sf_nan.*( .rodata .rodata.*)
+ *libc.a:lib_a-srand.*( .rodata .rodata.*)
+ *libc.a:lib_a-stdio.*( .rodata .rodata.*)
+ *libc.a:lib_a-strcasecmp.*( .rodata .rodata.*)
+ *libc.a:lib_a-strcasestr.*( .rodata .rodata.*)
+ *libc.a:lib_a-strcat.*( .rodata .rodata.*)
+ *libc.a:lib_a-strchr.*( .rodata .rodata.*)
+ *libc.a:lib_a-strcmp.*( .rodata .rodata.*)
+ *libc.a:lib_a-strcoll.*( .rodata .rodata.*)
+ *libc.a:lib_a-strcpy.*( .rodata .rodata.*)
+ *libc.a:lib_a-strcspn.*( .rodata .rodata.*)
+ *libc.a:lib_a-strdup.*( .rodata .rodata.*)
+ *libc.a:lib_a-strdup_r.*( .rodata .rodata.*)
+ *libc.a:lib_a-strftime.*( .rodata .rodata.*)
+ *libc.a:lib_a-strlcat.*( .rodata .rodata.*)
+ *libc.a:lib_a-strlcpy.*( .rodata .rodata.*)
+ *libc.a:lib_a-strlen.*( .rodata .rodata.*)
+ *libc.a:lib_a-strlwr.*( .rodata .rodata.*)
+ *libc.a:lib_a-strncasecmp.*( .rodata .rodata.*)
+ *libc.a:lib_a-strncat.*( .rodata .rodata.*)
+ *libc.a:lib_a-strncmp.*( .rodata .rodata.*)
+ *libc.a:lib_a-strncpy.*( .rodata .rodata.*)
+ *libc.a:lib_a-strndup.*( .rodata .rodata.*)
+ *libc.a:lib_a-strndup_r.*( .rodata .rodata.*)
+ *libc.a:lib_a-strnlen.*( .rodata .rodata.*)
+ *libc.a:lib_a-strptime.*( .rodata .rodata.*)
+ *libc.a:lib_a-strrchr.*( .rodata .rodata.*)
+ *libc.a:lib_a-strsep.*( .rodata .rodata.*)
+ *libc.a:lib_a-strspn.*( .rodata .rodata.*)
+ *libc.a:lib_a-strstr.*( .rodata .rodata.*)
+ *libc.a:lib_a-strtok_r.*( .rodata .rodata.*)
+ *libc.a:lib_a-strtol.*( .rodata .rodata.*)
+ *libc.a:lib_a-strtoul.*( .rodata .rodata.*)
+ *libc.a:lib_a-strupr.*( .rodata .rodata.*)
+ *libc.a:lib_a-sysclose.*( .rodata .rodata.*)
+ *libc.a:lib_a-sysopen.*( .rodata .rodata.*)
+ *libc.a:lib_a-sysread.*( .rodata .rodata.*)
+ *libc.a:lib_a-syssbrk.*( .rodata .rodata.*)
+ *libc.a:lib_a-system.*( .rodata .rodata.*)
+ *libc.a:lib_a-systimes.*( .rodata .rodata.*)
+ *libc.a:lib_a-syswrite.*( .rodata .rodata.*)
+ *libc.a:lib_a-time.*( .rodata .rodata.*)
+ *libc.a:lib_a-timelocal.*( .rodata .rodata.*)
+ *libc.a:lib_a-toascii.*( .rodata .rodata.*)
+ *libc.a:lib_a-tolower.*( .rodata .rodata.*)
+ *libc.a:lib_a-toupper.*( .rodata .rodata.*)
+ *libc.a:lib_a-tzcalc_limits.*( .rodata .rodata.*)
+ *libc.a:lib_a-tzlock.*( .rodata .rodata.*)
+ *libc.a:lib_a-tzset.*( .rodata .rodata.*)
+ *libc.a:lib_a-tzset_r.*( .rodata .rodata.*)
+ *libc.a:lib_a-tzvars.*( .rodata .rodata.*)
+ *libc.a:lib_a-ungetc.*( .rodata .rodata.*)
+ *libc.a:lib_a-utoa.*( .rodata .rodata.*)
+ *libc.a:lib_a-wbuf.*( .rodata .rodata.*)
+ *libc.a:lib_a-wcrtomb.*( .rodata .rodata.*)
+ *libc.a:lib_a-wctomb_r.*( .rodata .rodata.*)
+ *libc.a:lib_a-wsetup.*( .rodata .rodata.*)
+ *libc.a:lock.*( .rodata .rodata.*)
*libesp32.a:panic.*( .rodata .rodata.*)
- *libphy.a:( .rodata .rodata.*)
- *libsoc.a:rtc_clk.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-time.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-makebuf.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-strcasestr.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-tzlock.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-memset.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-strdup.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-environ.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-tzcalc_limits.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-labs.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-strlcat.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-strstr.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-lcltime_r.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-ungetc.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-strlen.*( .rodata .rodata.*)
- *libc-psram-workaround.a:isatty.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-tzset_r.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-asctime_r.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-tolower.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-memccpy.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-wctomb_r.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-strcspn.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-strcasecmp.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-iscntrl.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-strncasecmp.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-abs.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-sf_nan.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-asctime.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-strncmp.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-fvwrite.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-isblank.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-read.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-tzset.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-rand_r.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-ispunct.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-s_fpclassify.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-quorem.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-strspn.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-strrchr.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-strndup.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-gettzinfo.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-fclose.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-isalnum.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-strtol.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-creat.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-fwalk.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-memcmp.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-strcmp.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-rshift.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-toascii.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-isdigit.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-isalpha.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-wcrtomb.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-tzvars.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-strcoll.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-strndup_r.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-gmtime.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-gmtime_r.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-sccl.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-wbuf.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-mktime.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-ctime_r.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-isascii.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-memcpy.*( .rodata .rodata.*)
- *libc-psram-workaround.a:creat.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-sysclose.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-setjmp.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-srand.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-strcat.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-bzero.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-month_lengths.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-strncat.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-strftime.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-isupper.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-wsetup.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-close.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-islower.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-strncpy.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-raise.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-atol.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-ldiv.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-getenv_r.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-isspace.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-system.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-strchr.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-memchr.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-refill.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-atoi.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-envlock.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-strnlen.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-isgraph.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-syssbrk.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-sysread.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-longjmp.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-sbrk.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-timelocal.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-strlcpy.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-strdup_r.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-sysopen.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-toupper.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-strtoul.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-strsep.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-itoa.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-memrchr.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-open.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-utoa.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-strcpy.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-stdio.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-fputwc.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-strtok_r.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-memmove.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-isprint.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-syswrite.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-impure.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-rand.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-ctime.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-fflush.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-strupr.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-lcltime.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-strlwr.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-strptime.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-findfp.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-systimes.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-div.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lib_a-ctype_.*( .rodata .rodata.*)
- *libc-psram-workaround.a:lock.*( .rodata .rodata.*)
+ *libesp_event.a:default_event_loop.*(.rodata.esp_event_isr_post)
+ *libesp_event.a:esp_event.*(.rodata.esp_event_isr_post_to)
+ *libgcc.a:_divsf3.*( .rodata .rodata.*)
*libgcov.a:( .rodata .rodata.*)
*libheap.a:multi_heap.*( .rodata .rodata.*)
*libheap.a:multi_heap_poisoning.*( .rodata .rodata.*)
+ *liblog.a:log.*(.rodata.esp_log_write)
+ *liblog.a:log_freertos.*(.rodata.esp_log_early_timestamp)
+ *liblog.a:log_freertos.*(.rodata.esp_log_impl_lock)
+ *liblog.a:log_freertos.*(.rodata.esp_log_impl_lock_timeout)
+ *liblog.a:log_freertos.*(.rodata.esp_log_impl_unlock)
+ *liblog.a:log_freertos.*(.rodata.esp_log_timestamp)
+ *libnewlib.a:heap.*( .rodata .rodata.*)
+ *libphy.a:( .rodata .rodata.*)
+ *libsoc.a:i2c_hal_iram.*( .rodata .rodata.*)
+ *libsoc.a:rtc_clk.*( .rodata .rodata.*)
+ *libsoc.a:spi_flash_hal_gpspi.*( .rodata .rodata.*)
+ *libsoc.a:spi_flash_hal_iram.*( .rodata .rodata.*)
+ *libsoc.a:uart_hal_iram.*( .data .data.* .dram1 .dram1.*)
+ *libspi_flash.a:memspi_host_driver.*( .rodata .rodata.*)
+ *libspi_flash.a:spi_flash_chip_gd.*( .rodata .rodata.*)
+ *libspi_flash.a:spi_flash_chip_generic.*( .rodata .rodata.*)
+ *libspi_flash.a:spi_flash_chip_issi.*( .rodata .rodata.*)
_data_end = ABSOLUTE(.);
. = ALIGN(4);
@@ -489,7 +539,7 @@ SECTIONS
{
. = ALIGN(4);
_noinit_start = ABSOLUTE(.);
- *(.noinit .noinit.*)
+ *(.noinit .noinit.*)
. = ALIGN(4) ;
_noinit_end = ABSOLUTE(.);
} > dram0_0_seg
@@ -508,8 +558,13 @@ SECTIONS
*libbtdm_app.a:(.bss .bss.* COMMON)
. = ALIGN (4);
_btdm_bss_end = ABSOLUTE(.);
+ _nimble_bss_start = ABSOLUTE(.);
+ *libnimble.a:(.bss .bss.* COMMON)
+ . = ALIGN (4);
+ _nimble_bss_end = ABSOLUTE(.);
- *( .bss .bss.* COMMON)
+ *(EXCLUDE_FILE(*libsoc.a:uart_hal_iram.*) .bss EXCLUDE_FILE(*libsoc.a:uart_hal_iram.*) .bss.* EXCLUDE_FILE(*libsoc.a:uart_hal_iram.*) COMMON)
+ *libsoc.a:uart_hal_iram.*( .bss .bss.* COMMON)
*(.dynsbss)
*(.sbss)
@@ -525,13 +580,11 @@ SECTIONS
. = ALIGN (8);
_bss_end = ABSOLUTE(.);
- /* The heap starts right after end of this section */
- _heap_start = ABSOLUTE(.);
} > dram0_0_seg
ASSERT(((_bss_end - ORIGIN(dram0_0_seg)) <= LENGTH(dram0_0_seg)),
"DRAM segment data does not fit.")
-
+
.flash.rodata :
{
_rodata_start = ABSOLUTE(.);
@@ -539,7 +592,12 @@ SECTIONS
*(.rodata_desc .rodata_desc.*) /* Should be the first. App version info. DO NOT PUT ANYTHING BEFORE IT! */
*(.rodata_custom_desc .rodata_custom_desc.*) /* Should be the second. Custom app version info. DO NOT PUT ANYTHING BEFORE IT! */
- *(EXCLUDE_FILE(*libapp_trace.a *libesp32.a:panic.* *libphy.a *libsoc.a:rtc_clk.* *libc-psram-workaround.a:lock.* *libc-psram-workaround.a:lib_a-ctype_.* *libc-psram-workaround.a:lib_a-div.* *libc-psram-workaround.a:lib_a-systimes.* *libc-psram-workaround.a:lib_a-findfp.* *libc-psram-workaround.a:lib_a-strptime.* *libc-psram-workaround.a:lib_a-strlwr.* *libc-psram-workaround.a:lib_a-lcltime.* *libc-psram-workaround.a:lib_a-strupr.* *libc-psram-workaround.a:lib_a-fflush.* *libc-psram-workaround.a:lib_a-ctime.* *libc-psram-workaround.a:lib_a-rand.* *libc-psram-workaround.a:lib_a-impure.* *libc-psram-workaround.a:lib_a-syswrite.* *libc-psram-workaround.a:lib_a-isprint.* *libc-psram-workaround.a:lib_a-memmove.* *libc-psram-workaround.a:lib_a-strtok_r.* *libc-psram-workaround.a:lib_a-fputwc.* *libc-psram-workaround.a:lib_a-stdio.* *libc-psram-workaround.a:lib_a-strcpy.* *libc-psram-workaround.a:lib_a-utoa.* *libc-psram-workaround.a:lib_a-open.* *libc-psram-workaround.a:lib_a-memrchr.* *libc-psram-workaround.a:lib_a-itoa.* *libc-psram-workaround.a:lib_a-strsep.* *libc-psram-workaround.a:lib_a-strtoul.* *libc-psram-workaround.a:lib_a-toupper.* *libc-psram-workaround.a:lib_a-sysopen.* *libc-psram-workaround.a:lib_a-strdup_r.* *libc-psram-workaround.a:lib_a-strlcpy.* *libc-psram-workaround.a:lib_a-timelocal.* *libc-psram-workaround.a:lib_a-sbrk.* *libc-psram-workaround.a:lib_a-longjmp.* *libc-psram-workaround.a:lib_a-sysread.* *libc-psram-workaround.a:lib_a-syssbrk.* *libc-psram-workaround.a:lib_a-isgraph.* *libc-psram-workaround.a:lib_a-strnlen.* *libc-psram-workaround.a:lib_a-envlock.* *libc-psram-workaround.a:lib_a-atoi.* *libc-psram-workaround.a:lib_a-refill.* *libc-psram-workaround.a:lib_a-memchr.* *libc-psram-workaround.a:lib_a-strchr.* *libc-psram-workaround.a:lib_a-system.* *libc-psram-workaround.a:lib_a-isspace.* *libc-psram-workaround.a:lib_a-getenv_r.* *libc-psram-workaround.a:lib_a-ldiv.* *libc-psram-workaround.a:lib_a-atol.* *libc-psram-workaround.a:lib_a-raise.* *libc-psram-workaround.a:lib_a-strncpy.* *libc-psram-workaround.a:lib_a-islower.* *libc-psram-workaround.a:lib_a-close.* *libc-psram-workaround.a:lib_a-wsetup.* *libc-psram-workaround.a:lib_a-isupper.* *libc-psram-workaround.a:lib_a-strftime.* *libc-psram-workaround.a:lib_a-strncat.* *libc-psram-workaround.a:lib_a-month_lengths.* *libc-psram-workaround.a:lib_a-bzero.* *libc-psram-workaround.a:lib_a-strcat.* *libc-psram-workaround.a:lib_a-srand.* *libc-psram-workaround.a:lib_a-setjmp.* *libc-psram-workaround.a:lib_a-sysclose.* *libc-psram-workaround.a:creat.* *libc-psram-workaround.a:lib_a-memcpy.* *libc-psram-workaround.a:lib_a-isascii.* *libc-psram-workaround.a:lib_a-ctime_r.* *libc-psram-workaround.a:lib_a-mktime.* *libc-psram-workaround.a:lib_a-wbuf.* *libc-psram-workaround.a:lib_a-sccl.* *libc-psram-workaround.a:lib_a-gmtime_r.* *libc-psram-workaround.a:lib_a-gmtime.* *libc-psram-workaround.a:lib_a-strndup_r.* *libc-psram-workaround.a:lib_a-strcoll.* *libc-psram-workaround.a:lib_a-tzvars.* *libc-psram-workaround.a:lib_a-wcrtomb.* *libc-psram-workaround.a:lib_a-isalpha.* *libc-psram-workaround.a:lib_a-isdigit.* *libc-psram-workaround.a:lib_a-toascii.* *libc-psram-workaround.a:lib_a-rshift.* *libc-psram-workaround.a:lib_a-strcmp.* *libc-psram-workaround.a:lib_a-memcmp.* *libc-psram-workaround.a:lib_a-fwalk.* *libc-psram-workaround.a:lib_a-creat.* *libc-psram-workaround.a:lib_a-strtol.* *libc-psram-workaround.a:lib_a-isalnum.* *libc-psram-workaround.a:lib_a-fclose.* *libc-psram-workaround.a:lib_a-gettzinfo.* *libc-psram-workaround.a:lib_a-strndup.* *libc-psram-workaround.a:lib_a-strrchr.* *libc-psram-workaround.a:lib_a-strspn.* *libc-psram-workaround.a:lib_a-quorem.* *libc-psram-workaround.a:lib_a-s_fpclassify.* *libc-psram-workaround.a:lib_a-ispunct.* *libc-psram-workaround.a:lib_a-rand_r.* *libc-psram-workaround.a:lib_a-tzset.* *libc-psram-workaround.a:lib_a-read.* *libc-psram-workaround.a:lib_a-isblank.* *libc-psram-workaround.a:lib_a-fvwrite.* *libc-psram-workaround.a:lib_a-strncmp.* *libc-psram-workaround.a:lib_a-asctime.* *libc-psram-workaround.a:lib_a-sf_nan.* *libc-psram-workaround.a:lib_a-abs.* *libc-psram-workaround.a:lib_a-strncasecmp.* *libc-psram-workaround.a:lib_a-iscntrl.* *libc-psram-workaround.a:lib_a-strcasecmp.* *libc-psram-workaround.a:lib_a-strcspn.* *libc-psram-workaround.a:lib_a-wctomb_r.* *libc-psram-workaround.a:lib_a-memccpy.* *libc-psram-workaround.a:lib_a-tolower.* *libc-psram-workaround.a:lib_a-asctime_r.* *libc-psram-workaround.a:lib_a-tzset_r.* *libc-psram-workaround.a:isatty.* *libc-psram-workaround.a:lib_a-strlen.* *libc-psram-workaround.a:lib_a-ungetc.* *libc-psram-workaround.a:lib_a-lcltime_r.* *libc-psram-workaround.a:lib_a-strstr.* *libc-psram-workaround.a:lib_a-strlcat.* *libc-psram-workaround.a:lib_a-labs.* *libc-psram-workaround.a:lib_a-tzcalc_limits.* *libc-psram-workaround.a:lib_a-environ.* *libc-psram-workaround.a:lib_a-strdup.* *libc-psram-workaround.a:lib_a-memset.* *libc-psram-workaround.a:lib_a-tzlock.* *libc-psram-workaround.a:lib_a-strcasestr.* *libc-psram-workaround.a:lib_a-makebuf.* *libc-psram-workaround.a:lib_a-time.* *libgcov.a *libheap.a:multi_heap_poisoning.* *libheap.a:multi_heap.*) .rodata EXCLUDE_FILE(*libapp_trace.a *libesp32.a:panic.* *libphy.a *libsoc.a:rtc_clk.* *libc-psram-workaround.a:lock.* *libc-psram-workaround.a:lib_a-ctype_.* *libc-psram-workaround.a:lib_a-div.* *libc-psram-workaround.a:lib_a-systimes.* *libc-psram-workaround.a:lib_a-findfp.* *libc-psram-workaround.a:lib_a-strptime.* *libc-psram-workaround.a:lib_a-strlwr.* *libc-psram-workaround.a:lib_a-lcltime.* *libc-psram-workaround.a:lib_a-strupr.* *libc-psram-workaround.a:lib_a-fflush.* *libc-psram-workaround.a:lib_a-ctime.* *libc-psram-workaround.a:lib_a-rand.* *libc-psram-workaround.a:lib_a-impure.* *libc-psram-workaround.a:lib_a-syswrite.* *libc-psram-workaround.a:lib_a-isprint.* *libc-psram-workaround.a:lib_a-memmove.* *libc-psram-workaround.a:lib_a-strtok_r.* *libc-psram-workaround.a:lib_a-fputwc.* *libc-psram-workaround.a:lib_a-stdio.* *libc-psram-workaround.a:lib_a-strcpy.* *libc-psram-workaround.a:lib_a-utoa.* *libc-psram-workaround.a:lib_a-open.* *libc-psram-workaround.a:lib_a-memrchr.* *libc-psram-workaround.a:lib_a-itoa.* *libc-psram-workaround.a:lib_a-strsep.* *libc-psram-workaround.a:lib_a-strtoul.* *libc-psram-workaround.a:lib_a-toupper.* *libc-psram-workaround.a:lib_a-sysopen.* *libc-psram-workaround.a:lib_a-strdup_r.* *libc-psram-workaround.a:lib_a-strlcpy.* *libc-psram-workaround.a:lib_a-timelocal.* *libc-psram-workaround.a:lib_a-sbrk.* *libc-psram-workaround.a:lib_a-longjmp.* *libc-psram-workaround.a:lib_a-sysread.* *libc-psram-workaround.a:lib_a-syssbrk.* *libc-psram-workaround.a:lib_a-isgraph.* *libc-psram-workaround.a:lib_a-strnlen.* *libc-psram-workaround.a:lib_a-envlock.* *libc-psram-workaround.a:lib_a-atoi.* *libc-psram-workaround.a:lib_a-refill.* *libc-psram-workaround.a:lib_a-memchr.* *libc-psram-workaround.a:lib_a-strchr.* *libc-psram-workaround.a:lib_a-system.* *libc-psram-workaround.a:lib_a-isspace.* *libc-psram-workaround.a:lib_a-getenv_r.* *libc-psram-workaround.a:lib_a-ldiv.* *libc-psram-workaround.a:lib_a-atol.* *libc-psram-workaround.a:lib_a-raise.* *libc-psram-workaround.a:lib_a-strncpy.* *libc-psram-workaround.a:lib_a-islower.* *libc-psram-workaround.a:lib_a-close.* *libc-psram-workaround.a:lib_a-wsetup.* *libc-psram-workaround.a:lib_a-isupper.* *libc-psram-workaround.a:lib_a-strftime.* *libc-psram-workaround.a:lib_a-strncat.* *libc-psram-workaround.a:lib_a-month_lengths.* *libc-psram-workaround.a:lib_a-bzero.* *libc-psram-workaround.a:lib_a-strcat.* *libc-psram-workaround.a:lib_a-srand.* *libc-psram-workaround.a:lib_a-setjmp.* *libc-psram-workaround.a:lib_a-sysclose.* *libc-psram-workaround.a:creat.* *libc-psram-workaround.a:lib_a-memcpy.* *libc-psram-workaround.a:lib_a-isascii.* *libc-psram-workaround.a:lib_a-ctime_r.* *libc-psram-workaround.a:lib_a-mktime.* *libc-psram-workaround.a:lib_a-wbuf.* *libc-psram-workaround.a:lib_a-sccl.* *libc-psram-workaround.a:lib_a-gmtime_r.* *libc-psram-workaround.a:lib_a-gmtime.* *libc-psram-workaround.a:lib_a-strndup_r.* *libc-psram-workaround.a:lib_a-strcoll.* *libc-psram-workaround.a:lib_a-tzvars.* *libc-psram-workaround.a:lib_a-wcrtomb.* *libc-psram-workaround.a:lib_a-isalpha.* *libc-psram-workaround.a:lib_a-isdigit.* *libc-psram-workaround.a:lib_a-toascii.* *libc-psram-workaround.a:lib_a-rshift.* *libc-psram-workaround.a:lib_a-strcmp.* *libc-psram-workaround.a:lib_a-memcmp.* *libc-psram-workaround.a:lib_a-fwalk.* *libc-psram-workaround.a:lib_a-creat.* *libc-psram-workaround.a:lib_a-strtol.* *libc-psram-workaround.a:lib_a-isalnum.* *libc-psram-workaround.a:lib_a-fclose.* *libc-psram-workaround.a:lib_a-gettzinfo.* *libc-psram-workaround.a:lib_a-strndup.* *libc-psram-workaround.a:lib_a-strrchr.* *libc-psram-workaround.a:lib_a-strspn.* *libc-psram-workaround.a:lib_a-quorem.* *libc-psram-workaround.a:lib_a-s_fpclassify.* *libc-psram-workaround.a:lib_a-ispunct.* *libc-psram-workaround.a:lib_a-rand_r.* *libc-psram-workaround.a:lib_a-tzset.* *libc-psram-workaround.a:lib_a-read.* *libc-psram-workaround.a:lib_a-isblank.* *libc-psram-workaround.a:lib_a-fvwrite.* *libc-psram-workaround.a:lib_a-strncmp.* *libc-psram-workaround.a:lib_a-asctime.* *libc-psram-workaround.a:lib_a-sf_nan.* *libc-psram-workaround.a:lib_a-abs.* *libc-psram-workaround.a:lib_a-strncasecmp.* *libc-psram-workaround.a:lib_a-iscntrl.* *libc-psram-workaround.a:lib_a-strcasecmp.* *libc-psram-workaround.a:lib_a-strcspn.* *libc-psram-workaround.a:lib_a-wctomb_r.* *libc-psram-workaround.a:lib_a-memccpy.* *libc-psram-workaround.a:lib_a-tolower.* *libc-psram-workaround.a:lib_a-asctime_r.* *libc-psram-workaround.a:lib_a-tzset_r.* *libc-psram-workaround.a:isatty.* *libc-psram-workaround.a:lib_a-strlen.* *libc-psram-workaround.a:lib_a-ungetc.* *libc-psram-workaround.a:lib_a-lcltime_r.* *libc-psram-workaround.a:lib_a-strstr.* *libc-psram-workaround.a:lib_a-strlcat.* *libc-psram-workaround.a:lib_a-labs.* *libc-psram-workaround.a:lib_a-tzcalc_limits.* *libc-psram-workaround.a:lib_a-environ.* *libc-psram-workaround.a:lib_a-strdup.* *libc-psram-workaround.a:lib_a-memset.* *libc-psram-workaround.a:lib_a-tzlock.* *libc-psram-workaround.a:lib_a-strcasestr.* *libc-psram-workaround.a:lib_a-makebuf.* *libc-psram-workaround.a:lib_a-time.* *libgcov.a *libheap.a:multi_heap_poisoning.* *libheap.a:multi_heap.*) .rodata.*)
+ *(EXCLUDE_FILE(*libgcov.a *libapp_trace.a:SEGGER_SYSVIEW_FreeRTOS.* *libapp_trace.a:SEGGER_RTT_esp32.* *libapp_trace.a:app_trace_util.* *libapp_trace.a:app_trace.* *libapp_trace.a:SEGGER_SYSVIEW.* *libapp_trace.a:SEGGER_SYSVIEW_Config_FreeRTOS.* *libgcc.a:_divsf3.* *libc.a:lib_a-strcat.* *libc.a:lib_a-toascii.* *libc.a:lib_a-strcoll.* *libc.a:lib_a-s_fpclassify.* *libc.a:lib_a-system.* *libc.a:lib_a-strtoul.* *libc.a:lib_a-strlen.* *libc.a:lib_a-utoa.* *libc.a:lib_a-lcltime.* *libc.a:lib_a-fvwrite.* *libc.a:lib_a-itoa.* *libc.a:lib_a-strndup_r.* *libc.a:lib_a-strtol.* *libc.a:lib_a-strdup_r.* *libc.a:lib_a-refill.* *libc.a:lib_a-fclose.* *libc.a:lib_a-gmtime.* *libc.a:lib_a-strcasestr.* *libc.a:lib_a-strlcat.* *libc.a:lib_a-asctime_r.* *libc.a:lib_a-tzset.* *libc.a:lib_a-tzset_r.* *libc.a:lib_a-fputwc.* *libc.a:lib_a-rand_r.* *libc.a:lib_a-strsep.* *libc.a:lib_a-strrchr.* *libc.a:lib_a-ctime_r.* *libc.a:lib_a-isalpha.* *libc.a:lib_a-memmove.* *libc.a:lib_a-sysopen.* *libc.a:lib_a-quorem.* *libc.a:lib_a-gmtime_r.* *libc.a:lib_a-isblank.* *libc.a:isatty.* *libc.a:lib_a-syssbrk.* *libc.a:lib_a-memcpy.* *libc.a:lib_a-memset.* *libc.a:lib_a-gettzinfo.* *libc.a:lib_a-strndup.* *libc.a:lib_a-strlwr.* *libc.a:lib_a-labs.* *libc.a:lib_a-strupr.* *libc.a:lib_a-ctime.* *libc.a:lib_a-wsetup.* *libc.a:lib_a-fflush.* *libc.a:lib_a-srand.* *libc.a:lib_a-wcrtomb.* *libc.a:lib_a-tzvars.* *libc.a:lib_a-strncat.* *libc.a:lib_a-setjmp.* *libc.a:lib_a-envlock.* *libc.a:lib_a-sysread.* *libc.a:lib_a-strcmp.* *libc.a:lib_a-ctype_.* *libc.a:lib_a-asctime.* *libc.a:lib_a-read.* *libc.a:lib_a-sbrk.* *libc.a:lib_a-abs.* *libc.a:lib_a-tzlock.* *libc.a:lib_a-strdup.* *libc.a:lib_a-strncasecmp.* *libc.a:lib_a-makebuf.* *libc.a:lib_a-strchr.* *libc.a:lock.* *libc.a:lib_a-syswrite.* *libc.a:lib_a-mktime.* *libc.a:lib_a-sysclose.* *libc.a:creat.* *libc.a:lib_a-ungetc.* *libc.a:lib_a-rshift.* *libc.a:lib_a-bzero.* *libc.a:lib_a-impure.* *libc.a:lib_a-fwalk.* *libc.a:lib_a-isupper.* *libc.a:lib_a-environ.* *libc.a:lib_a-strcasecmp.* *libc.a:lib_a-strcspn.* *libc.a:lib_a-rand.* *libc.a:lib_a-isgraph.* *libc.a:lib_a-systimes.* *libc.a:lib_a-strspn.* *libc.a:lib_a-getenv_r.* *libc.a:lib_a-ldiv.* *libc.a:lib_a-strlcpy.* *libc.a:lib_a-close.* *libc.a:lib_a-strncpy.* *libc.a:lib_a-sf_nan.* *libc.a:lib_a-isspace.* *libc.a:lib_a-isalnum.* *libc.a:lib_a-toupper.* *libc.a:lib_a-month_lengths.* *libc.a:lib_a-strftime.* *libc.a:lib_a-tzcalc_limits.* *libc.a:lib_a-iscntrl.* *libc.a:lib_a-strnlen.* *libc.a:lib_a-memcmp.* *libc.a:lib_a-div.* *libc.a:lib_a-lcltime_r.* *libc.a:lib_a-findfp.* *libc.a:lib_a-isdigit.* *libc.a:lib_a-strcpy.* *libc.a:lib_a-memrchr.* *libc.a:lib_a-islower.* *libc.a:lib_a-isascii.* *libc.a:lib_a-sccl.* *libc.a:lib_a-open.* *libc.a:lib_a-time.* *libc.a:lib_a-stdio.* *libc.a:lib_a-wbuf.* *libc.a:lib_a-tolower.* *libc.a:lib_a-memchr.* *libc.a:lib_a-ispunct.* *libc.a:lib_a-isprint.* *libc.a:lib_a-strtok_r.* *libc.a:lib_a-raise.* *libc.a:lib_a-longjmp.* *libc.a:lib_a-atol.* *libc.a:lib_a-atoi.* *libc.a:lib_a-creat.* *libc.a:lib_a-strncmp.* *libc.a:lib_a-wctomb_r.* *libc.a:lib_a-strptime.* *libc.a:lib_a-memccpy.* *libc.a:lib_a-timelocal.* *libc.a:lib_a-strstr.* *libheap.a:multi_heap.* *libheap.a:multi_heap_poisoning.* *libesp32.a:panic.* *libspi_flash.a:memspi_host_driver.* *libspi_flash.a:spi_flash_chip_generic.* *libspi_flash.a:spi_flash_chip_gd.* *libspi_flash.a:spi_flash_chip_issi.* *libsoc.a:i2c_hal_iram.* *libsoc.a:rtc_clk.* *libsoc.a:spi_flash_hal_iram.* *libsoc.a:uart_hal_iram.* *libsoc.a:spi_flash_hal_gpspi.* *libnewlib.a:heap.* *libphy.a) .rodata EXCLUDE_FILE(*libgcov.a *libapp_trace.a:SEGGER_SYSVIEW_FreeRTOS.* *libapp_trace.a:SEGGER_RTT_esp32.* *libapp_trace.a:app_trace_util.* *libapp_trace.a:app_trace.* *libapp_trace.a:SEGGER_SYSVIEW.* *libapp_trace.a:SEGGER_SYSVIEW_Config_FreeRTOS.* *liblog.a:log_freertos.* *liblog.a:log.* *libgcc.a:_divsf3.* *libesp_event.a:esp_event.* *libesp_event.a:default_event_loop.* *libc.a:lib_a-strcat.* *libc.a:lib_a-toascii.* *libc.a:lib_a-strcoll.* *libc.a:lib_a-s_fpclassify.* *libc.a:lib_a-system.* *libc.a:lib_a-strtoul.* *libc.a:lib_a-strlen.* *libc.a:lib_a-utoa.* *libc.a:lib_a-lcltime.* *libc.a:lib_a-fvwrite.* *libc.a:lib_a-itoa.* *libc.a:lib_a-strndup_r.* *libc.a:lib_a-strtol.* *libc.a:lib_a-strdup_r.* *libc.a:lib_a-refill.* *libc.a:lib_a-fclose.* *libc.a:lib_a-gmtime.* *libc.a:lib_a-strcasestr.* *libc.a:lib_a-strlcat.* *libc.a:lib_a-asctime_r.* *libc.a:lib_a-tzset.* *libc.a:lib_a-tzset_r.* *libc.a:lib_a-fputwc.* *libc.a:lib_a-rand_r.* *libc.a:lib_a-strsep.* *libc.a:lib_a-strrchr.* *libc.a:lib_a-ctime_r.* *libc.a:lib_a-isalpha.* *libc.a:lib_a-memmove.* *libc.a:lib_a-sysopen.* *libc.a:lib_a-quorem.* *libc.a:lib_a-gmtime_r.* *libc.a:lib_a-isblank.* *libc.a:isatty.* *libc.a:lib_a-syssbrk.* *libc.a:lib_a-memcpy.* *libc.a:lib_a-memset.* *libc.a:lib_a-gettzinfo.* *libc.a:lib_a-strndup.* *libc.a:lib_a-strlwr.* *libc.a:lib_a-labs.* *libc.a:lib_a-strupr.* *libc.a:lib_a-ctime.* *libc.a:lib_a-wsetup.* *libc.a:lib_a-fflush.* *libc.a:lib_a-srand.* *libc.a:lib_a-wcrtomb.* *libc.a:lib_a-tzvars.* *libc.a:lib_a-strncat.* *libc.a:lib_a-setjmp.* *libc.a:lib_a-envlock.* *libc.a:lib_a-sysread.* *libc.a:lib_a-strcmp.* *libc.a:lib_a-ctype_.* *libc.a:lib_a-asctime.* *libc.a:lib_a-read.* *libc.a:lib_a-sbrk.* *libc.a:lib_a-abs.* *libc.a:lib_a-tzlock.* *libc.a:lib_a-strdup.* *libc.a:lib_a-strncasecmp.* *libc.a:lib_a-makebuf.* *libc.a:lib_a-strchr.* *libc.a:lock.* *libc.a:lib_a-syswrite.* *libc.a:lib_a-mktime.* *libc.a:lib_a-sysclose.* *libc.a:creat.* *libc.a:lib_a-ungetc.* *libc.a:lib_a-rshift.* *libc.a:lib_a-bzero.* *libc.a:lib_a-impure.* *libc.a:lib_a-fwalk.* *libc.a:lib_a-isupper.* *libc.a:lib_a-environ.* *libc.a:lib_a-strcasecmp.* *libc.a:lib_a-strcspn.* *libc.a:lib_a-rand.* *libc.a:lib_a-isgraph.* *libc.a:lib_a-systimes.* *libc.a:lib_a-strspn.* *libc.a:lib_a-getenv_r.* *libc.a:lib_a-ldiv.* *libc.a:lib_a-strlcpy.* *libc.a:lib_a-close.* *libc.a:lib_a-strncpy.* *libc.a:lib_a-sf_nan.* *libc.a:lib_a-isspace.* *libc.a:lib_a-isalnum.* *libc.a:lib_a-toupper.* *libc.a:lib_a-month_lengths.* *libc.a:lib_a-strftime.* *libc.a:lib_a-tzcalc_limits.* *libc.a:lib_a-iscntrl.* *libc.a:lib_a-strnlen.* *libc.a:lib_a-memcmp.* *libc.a:lib_a-div.* *libc.a:lib_a-lcltime_r.* *libc.a:lib_a-findfp.* *libc.a:lib_a-isdigit.* *libc.a:lib_a-strcpy.* *libc.a:lib_a-memrchr.* *libc.a:lib_a-islower.* *libc.a:lib_a-isascii.* *libc.a:lib_a-sccl.* *libc.a:lib_a-open.* *libc.a:lib_a-time.* *libc.a:lib_a-stdio.* *libc.a:lib_a-wbuf.* *libc.a:lib_a-tolower.* *libc.a:lib_a-memchr.* *libc.a:lib_a-ispunct.* *libc.a:lib_a-isprint.* *libc.a:lib_a-strtok_r.* *libc.a:lib_a-raise.* *libc.a:lib_a-longjmp.* *libc.a:lib_a-atol.* *libc.a:lib_a-atoi.* *libc.a:lib_a-creat.* *libc.a:lib_a-strncmp.* *libc.a:lib_a-wctomb_r.* *libc.a:lib_a-strptime.* *libc.a:lib_a-memccpy.* *libc.a:lib_a-timelocal.* *libc.a:lib_a-strstr.* *libheap.a:multi_heap.* *libheap.a:multi_heap_poisoning.* *libesp32.a:panic.* *libspi_flash.a:memspi_host_driver.* *libspi_flash.a:spi_flash_chip_generic.* *libspi_flash.a:spi_flash_chip_gd.* *libspi_flash.a:spi_flash_chip_issi.* *libsoc.a:i2c_hal_iram.* *libsoc.a:rtc_clk.* *libsoc.a:spi_flash_hal_iram.* *libsoc.a:uart_hal_iram.* *libsoc.a:spi_flash_hal_gpspi.* *libnewlib.a:heap.* *libphy.a) .rodata.*)
+ *libesp_event.a:default_event_loop.*(.rodata.esp_event_loop_create_default.str1.1 .rodata.esp_event_send_to_default_loop)
+ *libesp_event.a:esp_event.*(.rodata.loop_node_add_handler.str1.1 .rodata.esp_event_loop_create.str1.1)
+ *liblog.a:log.*(.rodata.esp_log_level_set.str1.1)
+ *liblog.a:log_freertos.*(.rodata.esp_log_system_timestamp.str1.1)
+ *libsoc.a:uart_hal_iram.*( .rodata .rodata.*)
*(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */
*(.gnu.linkonce.r.*)
@@ -553,12 +611,12 @@ SECTIONS
__eh_frame = ABSOLUTE(.);
KEEP(*(.eh_frame))
. = (. + 7) & ~ 3;
- /* C++ constructor and destructor tables, properly ordered: */
+ /* C++ constructor and destructor tables
+
+ Make a point of not including anything from crtbegin.o or crtend.o, as IDF doesn't use toolchain crt
+ */
__init_array_start = ABSOLUTE(.);
- KEEP (*crtbegin.*(.ctors))
- KEEP (*(EXCLUDE_FILE (*crtend.*) .ctors))
- KEEP (*(SORT(.ctors.*)))
- KEEP (*(.ctors))
+ KEEP (*(EXCLUDE_FILE (*crtend.* *crtbegin.*) .ctors .ctors.*))
__init_array_end = ABSOLUTE(.);
KEEP (*crtbegin.*(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.*) .dtors))
@@ -592,14 +650,19 @@ SECTIONS
*(.tbss.*)
_thread_local_end = ABSOLUTE(.);
. = ALIGN(4);
- } >drom0_0_seg
+ } >default_rodata_seg
.flash.text :
{
_stext = .;
_text_start = ABSOLUTE(.);
- *(EXCLUDE_FILE(*libspi_flash.a:spi_flash_rom_patch.* *libesp_ringbuf.a *libhal.a *libapp_trace.a *libesp32.a:panic.* *libespcoredump.a:core_dump_common.* *libespcoredump.a:core_dump_uart.* *libespcoredump.a:core_dump_flash.* *libespcoredump.a:core_dump_port.* *librtc.a *libgcc.a:lib2funcs.* *libsoc.a:rtc_periph.* *libsoc.a:rtc_wdt.* *libsoc.a:rtc_sleep.* *libsoc.a:rtc_pm.* *libsoc.a:rtc_init.* *libsoc.a:rtc_clk.* *libsoc.a:rtc_clk_init.* *libsoc.a:cpu_util.* *libsoc.a:rtc_time.* *libc-psram-workaround.a:lock.* *libc-psram-workaround.a:lib_a-ctype_.* *libc-psram-workaround.a:lib_a-div.* *libc-psram-workaround.a:lib_a-systimes.* *libc-psram-workaround.a:lib_a-findfp.* *libc-psram-workaround.a:lib_a-strptime.* *libc-psram-workaround.a:lib_a-strlwr.* *libc-psram-workaround.a:lib_a-lcltime.* *libc-psram-workaround.a:lib_a-strupr.* *libc-psram-workaround.a:lib_a-fflush.* *libc-psram-workaround.a:lib_a-ctime.* *libc-psram-workaround.a:lib_a-rand.* *libc-psram-workaround.a:lib_a-impure.* *libc-psram-workaround.a:lib_a-syswrite.* *libc-psram-workaround.a:lib_a-isprint.* *libc-psram-workaround.a:lib_a-memmove.* *libc-psram-workaround.a:lib_a-strtok_r.* *libc-psram-workaround.a:lib_a-fputwc.* *libc-psram-workaround.a:lib_a-stdio.* *libc-psram-workaround.a:lib_a-strcpy.* *libc-psram-workaround.a:lib_a-utoa.* *libc-psram-workaround.a:lib_a-open.* *libc-psram-workaround.a:lib_a-memrchr.* *libc-psram-workaround.a:lib_a-itoa.* *libc-psram-workaround.a:lib_a-strsep.* *libc-psram-workaround.a:lib_a-strtoul.* *libc-psram-workaround.a:lib_a-toupper.* *libc-psram-workaround.a:lib_a-sysopen.* *libc-psram-workaround.a:lib_a-strdup_r.* *libc-psram-workaround.a:lib_a-strlcpy.* *libc-psram-workaround.a:lib_a-timelocal.* *libc-psram-workaround.a:lib_a-sbrk.* *libc-psram-workaround.a:lib_a-longjmp.* *libc-psram-workaround.a:lib_a-sysread.* *libc-psram-workaround.a:lib_a-syssbrk.* *libc-psram-workaround.a:lib_a-isgraph.* *libc-psram-workaround.a:lib_a-strnlen.* *libc-psram-workaround.a:lib_a-envlock.* *libc-psram-workaround.a:lib_a-atoi.* *libc-psram-workaround.a:lib_a-refill.* *libc-psram-workaround.a:lib_a-memchr.* *libc-psram-workaround.a:lib_a-strchr.* *libc-psram-workaround.a:lib_a-system.* *libc-psram-workaround.a:lib_a-isspace.* *libc-psram-workaround.a:lib_a-getenv_r.* *libc-psram-workaround.a:lib_a-ldiv.* *libc-psram-workaround.a:lib_a-atol.* *libc-psram-workaround.a:lib_a-raise.* *libc-psram-workaround.a:lib_a-strncpy.* *libc-psram-workaround.a:lib_a-islower.* *libc-psram-workaround.a:lib_a-close.* *libc-psram-workaround.a:lib_a-wsetup.* *libc-psram-workaround.a:lib_a-isupper.* *libc-psram-workaround.a:lib_a-strftime.* *libc-psram-workaround.a:lib_a-strncat.* *libc-psram-workaround.a:lib_a-month_lengths.* *libc-psram-workaround.a:lib_a-bzero.* *libc-psram-workaround.a:lib_a-strcat.* *libc-psram-workaround.a:lib_a-srand.* *libc-psram-workaround.a:lib_a-setjmp.* *libc-psram-workaround.a:lib_a-sysclose.* *libc-psram-workaround.a:creat.* *libc-psram-workaround.a:lib_a-memcpy.* *libc-psram-workaround.a:lib_a-isascii.* *libc-psram-workaround.a:lib_a-ctime_r.* *libc-psram-workaround.a:lib_a-mktime.* *libc-psram-workaround.a:lib_a-wbuf.* *libc-psram-workaround.a:lib_a-sccl.* *libc-psram-workaround.a:lib_a-gmtime_r.* *libc-psram-workaround.a:lib_a-gmtime.* *libc-psram-workaround.a:lib_a-strndup_r.* *libc-psram-workaround.a:lib_a-strcoll.* *libc-psram-workaround.a:lib_a-tzvars.* *libc-psram-workaround.a:lib_a-wcrtomb.* *libc-psram-workaround.a:lib_a-isalpha.* *libc-psram-workaround.a:lib_a-isdigit.* *libc-psram-workaround.a:lib_a-toascii.* *libc-psram-workaround.a:lib_a-rshift.* *libc-psram-workaround.a:lib_a-strcmp.* *libc-psram-workaround.a:lib_a-memcmp.* *libc-psram-workaround.a:lib_a-fwalk.* *libc-psram-workaround.a:lib_a-creat.* *libc-psram-workaround.a:lib_a-strtol.* *libc-psram-workaround.a:lib_a-isalnum.* *libc-psram-workaround.a:lib_a-fclose.* *libc-psram-workaround.a:lib_a-gettzinfo.* *libc-psram-workaround.a:lib_a-strndup.* *libc-psram-workaround.a:lib_a-strrchr.* *libc-psram-workaround.a:lib_a-strspn.* *libc-psram-workaround.a:lib_a-quorem.* *libc-psram-workaround.a:lib_a-s_fpclassify.* *libc-psram-workaround.a:lib_a-ispunct.* *libc-psram-workaround.a:lib_a-rand_r.* *libc-psram-workaround.a:lib_a-tzset.* *libc-psram-workaround.a:lib_a-read.* *libc-psram-workaround.a:lib_a-isblank.* *libc-psram-workaround.a:lib_a-fvwrite.* *libc-psram-workaround.a:lib_a-strncmp.* *libc-psram-workaround.a:lib_a-asctime.* *libc-psram-workaround.a:lib_a-sf_nan.* *libc-psram-workaround.a:lib_a-abs.* *libc-psram-workaround.a:lib_a-strncasecmp.* *libc-psram-workaround.a:lib_a-iscntrl.* *libc-psram-workaround.a:lib_a-strcasecmp.* *libc-psram-workaround.a:lib_a-strcspn.* *libc-psram-workaround.a:lib_a-wctomb_r.* *libc-psram-workaround.a:lib_a-memccpy.* *libc-psram-workaround.a:lib_a-tolower.* *libc-psram-workaround.a:lib_a-asctime_r.* *libc-psram-workaround.a:lib_a-tzset_r.* *libc-psram-workaround.a:isatty.* *libc-psram-workaround.a:lib_a-strlen.* *libc-psram-workaround.a:lib_a-ungetc.* *libc-psram-workaround.a:lib_a-lcltime_r.* *libc-psram-workaround.a:lib_a-strstr.* *libc-psram-workaround.a:lib_a-strlcat.* *libc-psram-workaround.a:lib_a-labs.* *libc-psram-workaround.a:lib_a-tzcalc_limits.* *libc-psram-workaround.a:lib_a-environ.* *libc-psram-workaround.a:lib_a-strdup.* *libc-psram-workaround.a:lib_a-memset.* *libc-psram-workaround.a:lib_a-tzlock.* *libc-psram-workaround.a:lib_a-strcasestr.* *libc-psram-workaround.a:lib_a-makebuf.* *libc-psram-workaround.a:lib_a-time.* *libfreertos.a *libgcov.a *libxtensa-debug-module.a:eri.* *libheap.a:multi_heap_poisoning.* *libheap.a:multi_heap.*) .literal EXCLUDE_FILE(*libspi_flash.a:spi_flash_rom_patch.* *libesp_ringbuf.a *libhal.a *libapp_trace.a *libesp32.a:panic.* *libespcoredump.a:core_dump_common.* *libespcoredump.a:core_dump_uart.* *libespcoredump.a:core_dump_flash.* *libespcoredump.a:core_dump_port.* *librtc.a *libgcc.a:lib2funcs.* *libsoc.a:rtc_periph.* *libsoc.a:rtc_wdt.* *libsoc.a:rtc_sleep.* *libsoc.a:rtc_pm.* *libsoc.a:rtc_init.* *libsoc.a:rtc_clk.* *libsoc.a:rtc_clk_init.* *libsoc.a:cpu_util.* *libsoc.a:rtc_time.* *libc-psram-workaround.a:lock.* *libc-psram-workaround.a:lib_a-ctype_.* *libc-psram-workaround.a:lib_a-div.* *libc-psram-workaround.a:lib_a-systimes.* *libc-psram-workaround.a:lib_a-findfp.* *libc-psram-workaround.a:lib_a-strptime.* *libc-psram-workaround.a:lib_a-strlwr.* *libc-psram-workaround.a:lib_a-lcltime.* *libc-psram-workaround.a:lib_a-strupr.* *libc-psram-workaround.a:lib_a-fflush.* *libc-psram-workaround.a:lib_a-ctime.* *libc-psram-workaround.a:lib_a-rand.* *libc-psram-workaround.a:lib_a-impure.* *libc-psram-workaround.a:lib_a-syswrite.* *libc-psram-workaround.a:lib_a-isprint.* *libc-psram-workaround.a:lib_a-memmove.* *libc-psram-workaround.a:lib_a-strtok_r.* *libc-psram-workaround.a:lib_a-fputwc.* *libc-psram-workaround.a:lib_a-stdio.* *libc-psram-workaround.a:lib_a-strcpy.* *libc-psram-workaround.a:lib_a-utoa.* *libc-psram-workaround.a:lib_a-open.* *libc-psram-workaround.a:lib_a-memrchr.* *libc-psram-workaround.a:lib_a-itoa.* *libc-psram-workaround.a:lib_a-strsep.* *libc-psram-workaround.a:lib_a-strtoul.* *libc-psram-workaround.a:lib_a-toupper.* *libc-psram-workaround.a:lib_a-sysopen.* *libc-psram-workaround.a:lib_a-strdup_r.* *libc-psram-workaround.a:lib_a-strlcpy.* *libc-psram-workaround.a:lib_a-timelocal.* *libc-psram-workaround.a:lib_a-sbrk.* *libc-psram-workaround.a:lib_a-longjmp.* *libc-psram-workaround.a:lib_a-sysread.* *libc-psram-workaround.a:lib_a-syssbrk.* *libc-psram-workaround.a:lib_a-isgraph.* *libc-psram-workaround.a:lib_a-strnlen.* *libc-psram-workaround.a:lib_a-envlock.* *libc-psram-workaround.a:lib_a-atoi.* *libc-psram-workaround.a:lib_a-refill.* *libc-psram-workaround.a:lib_a-memchr.* *libc-psram-workaround.a:lib_a-strchr.* *libc-psram-workaround.a:lib_a-system.* *libc-psram-workaround.a:lib_a-isspace.* *libc-psram-workaround.a:lib_a-getenv_r.* *libc-psram-workaround.a:lib_a-ldiv.* *libc-psram-workaround.a:lib_a-atol.* *libc-psram-workaround.a:lib_a-raise.* *libc-psram-workaround.a:lib_a-strncpy.* *libc-psram-workaround.a:lib_a-islower.* *libc-psram-workaround.a:lib_a-close.* *libc-psram-workaround.a:lib_a-wsetup.* *libc-psram-workaround.a:lib_a-isupper.* *libc-psram-workaround.a:lib_a-strftime.* *libc-psram-workaround.a:lib_a-strncat.* *libc-psram-workaround.a:lib_a-month_lengths.* *libc-psram-workaround.a:lib_a-bzero.* *libc-psram-workaround.a:lib_a-strcat.* *libc-psram-workaround.a:lib_a-srand.* *libc-psram-workaround.a:lib_a-setjmp.* *libc-psram-workaround.a:lib_a-sysclose.* *libc-psram-workaround.a:creat.* *libc-psram-workaround.a:lib_a-memcpy.* *libc-psram-workaround.a:lib_a-isascii.* *libc-psram-workaround.a:lib_a-ctime_r.* *libc-psram-workaround.a:lib_a-mktime.* *libc-psram-workaround.a:lib_a-wbuf.* *libc-psram-workaround.a:lib_a-sccl.* *libc-psram-workaround.a:lib_a-gmtime_r.* *libc-psram-workaround.a:lib_a-gmtime.* *libc-psram-workaround.a:lib_a-strndup_r.* *libc-psram-workaround.a:lib_a-strcoll.* *libc-psram-workaround.a:lib_a-tzvars.* *libc-psram-workaround.a:lib_a-wcrtomb.* *libc-psram-workaround.a:lib_a-isalpha.* *libc-psram-workaround.a:lib_a-isdigit.* *libc-psram-workaround.a:lib_a-toascii.* *libc-psram-workaround.a:lib_a-rshift.* *libc-psram-workaround.a:lib_a-strcmp.* *libc-psram-workaround.a:lib_a-memcmp.* *libc-psram-workaround.a:lib_a-fwalk.* *libc-psram-workaround.a:lib_a-creat.* *libc-psram-workaround.a:lib_a-strtol.* *libc-psram-workaround.a:lib_a-isalnum.* *libc-psram-workaround.a:lib_a-fclose.* *libc-psram-workaround.a:lib_a-gettzinfo.* *libc-psram-workaround.a:lib_a-strndup.* *libc-psram-workaround.a:lib_a-strrchr.* *libc-psram-workaround.a:lib_a-strspn.* *libc-psram-workaround.a:lib_a-quorem.* *libc-psram-workaround.a:lib_a-s_fpclassify.* *libc-psram-workaround.a:lib_a-ispunct.* *libc-psram-workaround.a:lib_a-rand_r.* *libc-psram-workaround.a:lib_a-tzset.* *libc-psram-workaround.a:lib_a-read.* *libc-psram-workaround.a:lib_a-isblank.* *libc-psram-workaround.a:lib_a-fvwrite.* *libc-psram-workaround.a:lib_a-strncmp.* *libc-psram-workaround.a:lib_a-asctime.* *libc-psram-workaround.a:lib_a-sf_nan.* *libc-psram-workaround.a:lib_a-abs.* *libc-psram-workaround.a:lib_a-strncasecmp.* *libc-psram-workaround.a:lib_a-iscntrl.* *libc-psram-workaround.a:lib_a-strcasecmp.* *libc-psram-workaround.a:lib_a-strcspn.* *libc-psram-workaround.a:lib_a-wctomb_r.* *libc-psram-workaround.a:lib_a-memccpy.* *libc-psram-workaround.a:lib_a-tolower.* *libc-psram-workaround.a:lib_a-asctime_r.* *libc-psram-workaround.a:lib_a-tzset_r.* *libc-psram-workaround.a:isatty.* *libc-psram-workaround.a:lib_a-strlen.* *libc-psram-workaround.a:lib_a-ungetc.* *libc-psram-workaround.a:lib_a-lcltime_r.* *libc-psram-workaround.a:lib_a-strstr.* *libc-psram-workaround.a:lib_a-strlcat.* *libc-psram-workaround.a:lib_a-labs.* *libc-psram-workaround.a:lib_a-tzcalc_limits.* *libc-psram-workaround.a:lib_a-environ.* *libc-psram-workaround.a:lib_a-strdup.* *libc-psram-workaround.a:lib_a-memset.* *libc-psram-workaround.a:lib_a-tzlock.* *libc-psram-workaround.a:lib_a-strcasestr.* *libc-psram-workaround.a:lib_a-makebuf.* *libc-psram-workaround.a:lib_a-time.* *libfreertos.a *libgcov.a *libxtensa-debug-module.a:eri.* *libheap.a:multi_heap_poisoning.* *libheap.a:multi_heap.*) .literal.* EXCLUDE_FILE(*libspi_flash.a:spi_flash_rom_patch.* *libesp_ringbuf.a *libhal.a *libapp_trace.a *libesp32.a:panic.* *libespcoredump.a:core_dump_common.* *libespcoredump.a:core_dump_uart.* *libespcoredump.a:core_dump_flash.* *libespcoredump.a:core_dump_port.* *librtc.a *libgcc.a:lib2funcs.* *libsoc.a:rtc_periph.* *libsoc.a:rtc_wdt.* *libsoc.a:rtc_sleep.* *libsoc.a:rtc_pm.* *libsoc.a:rtc_init.* *libsoc.a:rtc_clk.* *libsoc.a:rtc_clk_init.* *libsoc.a:cpu_util.* *libsoc.a:rtc_time.* *libc-psram-workaround.a:lock.* *libc-psram-workaround.a:lib_a-ctype_.* *libc-psram-workaround.a:lib_a-div.* *libc-psram-workaround.a:lib_a-systimes.* *libc-psram-workaround.a:lib_a-findfp.* *libc-psram-workaround.a:lib_a-strptime.* *libc-psram-workaround.a:lib_a-strlwr.* *libc-psram-workaround.a:lib_a-lcltime.* *libc-psram-workaround.a:lib_a-strupr.* *libc-psram-workaround.a:lib_a-fflush.* *libc-psram-workaround.a:lib_a-ctime.* *libc-psram-workaround.a:lib_a-rand.* *libc-psram-workaround.a:lib_a-impure.* *libc-psram-workaround.a:lib_a-syswrite.* *libc-psram-workaround.a:lib_a-isprint.* *libc-psram-workaround.a:lib_a-memmove.* *libc-psram-workaround.a:lib_a-strtok_r.* *libc-psram-workaround.a:lib_a-fputwc.* *libc-psram-workaround.a:lib_a-stdio.* *libc-psram-workaround.a:lib_a-strcpy.* *libc-psram-workaround.a:lib_a-utoa.* *libc-psram-workaround.a:lib_a-open.* *libc-psram-workaround.a:lib_a-memrchr.* *libc-psram-workaround.a:lib_a-itoa.* *libc-psram-workaround.a:lib_a-strsep.* *libc-psram-workaround.a:lib_a-strtoul.* *libc-psram-workaround.a:lib_a-toupper.* *libc-psram-workaround.a:lib_a-sysopen.* *libc-psram-workaround.a:lib_a-strdup_r.* *libc-psram-workaround.a:lib_a-strlcpy.* *libc-psram-workaround.a:lib_a-timelocal.* *libc-psram-workaround.a:lib_a-sbrk.* *libc-psram-workaround.a:lib_a-longjmp.* *libc-psram-workaround.a:lib_a-sysread.* *libc-psram-workaround.a:lib_a-syssbrk.* *libc-psram-workaround.a:lib_a-isgraph.* *libc-psram-workaround.a:lib_a-strnlen.* *libc-psram-workaround.a:lib_a-envlock.* *libc-psram-workaround.a:lib_a-atoi.* *libc-psram-workaround.a:lib_a-refill.* *libc-psram-workaround.a:lib_a-memchr.* *libc-psram-workaround.a:lib_a-strchr.* *libc-psram-workaround.a:lib_a-system.* *libc-psram-workaround.a:lib_a-isspace.* *libc-psram-workaround.a:lib_a-getenv_r.* *libc-psram-workaround.a:lib_a-ldiv.* *libc-psram-workaround.a:lib_a-atol.* *libc-psram-workaround.a:lib_a-raise.* *libc-psram-workaround.a:lib_a-strncpy.* *libc-psram-workaround.a:lib_a-islower.* *libc-psram-workaround.a:lib_a-close.* *libc-psram-workaround.a:lib_a-wsetup.* *libc-psram-workaround.a:lib_a-isupper.* *libc-psram-workaround.a:lib_a-strftime.* *libc-psram-workaround.a:lib_a-strncat.* *libc-psram-workaround.a:lib_a-month_lengths.* *libc-psram-workaround.a:lib_a-bzero.* *libc-psram-workaround.a:lib_a-strcat.* *libc-psram-workaround.a:lib_a-srand.* *libc-psram-workaround.a:lib_a-setjmp.* *libc-psram-workaround.a:lib_a-sysclose.* *libc-psram-workaround.a:creat.* *libc-psram-workaround.a:lib_a-memcpy.* *libc-psram-workaround.a:lib_a-isascii.* *libc-psram-workaround.a:lib_a-ctime_r.* *libc-psram-workaround.a:lib_a-mktime.* *libc-psram-workaround.a:lib_a-wbuf.* *libc-psram-workaround.a:lib_a-sccl.* *libc-psram-workaround.a:lib_a-gmtime_r.* *libc-psram-workaround.a:lib_a-gmtime.* *libc-psram-workaround.a:lib_a-strndup_r.* *libc-psram-workaround.a:lib_a-strcoll.* *libc-psram-workaround.a:lib_a-tzvars.* *libc-psram-workaround.a:lib_a-wcrtomb.* *libc-psram-workaround.a:lib_a-isalpha.* *libc-psram-workaround.a:lib_a-isdigit.* *libc-psram-workaround.a:lib_a-toascii.* *libc-psram-workaround.a:lib_a-rshift.* *libc-psram-workaround.a:lib_a-strcmp.* *libc-psram-workaround.a:lib_a-memcmp.* *libc-psram-workaround.a:lib_a-fwalk.* *libc-psram-workaround.a:lib_a-creat.* *libc-psram-workaround.a:lib_a-strtol.* *libc-psram-workaround.a:lib_a-isalnum.* *libc-psram-workaround.a:lib_a-fclose.* *libc-psram-workaround.a:lib_a-gettzinfo.* *libc-psram-workaround.a:lib_a-strndup.* *libc-psram-workaround.a:lib_a-strrchr.* *libc-psram-workaround.a:lib_a-strspn.* *libc-psram-workaround.a:lib_a-quorem.* *libc-psram-workaround.a:lib_a-s_fpclassify.* *libc-psram-workaround.a:lib_a-ispunct.* *libc-psram-workaround.a:lib_a-rand_r.* *libc-psram-workaround.a:lib_a-tzset.* *libc-psram-workaround.a:lib_a-read.* *libc-psram-workaround.a:lib_a-isblank.* *libc-psram-workaround.a:lib_a-fvwrite.* *libc-psram-workaround.a:lib_a-strncmp.* *libc-psram-workaround.a:lib_a-asctime.* *libc-psram-workaround.a:lib_a-sf_nan.* *libc-psram-workaround.a:lib_a-abs.* *libc-psram-workaround.a:lib_a-strncasecmp.* *libc-psram-workaround.a:lib_a-iscntrl.* *libc-psram-workaround.a:lib_a-strcasecmp.* *libc-psram-workaround.a:lib_a-strcspn.* *libc-psram-workaround.a:lib_a-wctomb_r.* *libc-psram-workaround.a:lib_a-memccpy.* *libc-psram-workaround.a:lib_a-tolower.* *libc-psram-workaround.a:lib_a-asctime_r.* *libc-psram-workaround.a:lib_a-tzset_r.* *libc-psram-workaround.a:isatty.* *libc-psram-workaround.a:lib_a-strlen.* *libc-psram-workaround.a:lib_a-ungetc.* *libc-psram-workaround.a:lib_a-lcltime_r.* *libc-psram-workaround.a:lib_a-strstr.* *libc-psram-workaround.a:lib_a-strlcat.* *libc-psram-workaround.a:lib_a-labs.* *libc-psram-workaround.a:lib_a-tzcalc_limits.* *libc-psram-workaround.a:lib_a-environ.* *libc-psram-workaround.a:lib_a-strdup.* *libc-psram-workaround.a:lib_a-memset.* *libc-psram-workaround.a:lib_a-tzlock.* *libc-psram-workaround.a:lib_a-strcasestr.* *libc-psram-workaround.a:lib_a-makebuf.* *libc-psram-workaround.a:lib_a-time.* *libfreertos.a *libgcov.a *libxtensa-debug-module.a:eri.* *libheap.a:multi_heap_poisoning.* *libheap.a:multi_heap.*) .text EXCLUDE_FILE(*libspi_flash.a:spi_flash_rom_patch.* *libesp_ringbuf.a *libhal.a *libapp_trace.a *libesp32.a:panic.* *libespcoredump.a:core_dump_common.* *libespcoredump.a:core_dump_uart.* *libespcoredump.a:core_dump_flash.* *libespcoredump.a:core_dump_port.* *librtc.a *libgcc.a:lib2funcs.* *libsoc.a:rtc_periph.* *libsoc.a:rtc_wdt.* *libsoc.a:rtc_sleep.* *libsoc.a:rtc_pm.* *libsoc.a:rtc_init.* *libsoc.a:rtc_clk.* *libsoc.a:rtc_clk_init.* *libsoc.a:cpu_util.* *libsoc.a:rtc_time.* *libc-psram-workaround.a:lock.* *libc-psram-workaround.a:lib_a-ctype_.* *libc-psram-workaround.a:lib_a-div.* *libc-psram-workaround.a:lib_a-systimes.* *libc-psram-workaround.a:lib_a-findfp.* *libc-psram-workaround.a:lib_a-strptime.* *libc-psram-workaround.a:lib_a-strlwr.* *libc-psram-workaround.a:lib_a-lcltime.* *libc-psram-workaround.a:lib_a-strupr.* *libc-psram-workaround.a:lib_a-fflush.* *libc-psram-workaround.a:lib_a-ctime.* *libc-psram-workaround.a:lib_a-rand.* *libc-psram-workaround.a:lib_a-impure.* *libc-psram-workaround.a:lib_a-syswrite.* *libc-psram-workaround.a:lib_a-isprint.* *libc-psram-workaround.a:lib_a-memmove.* *libc-psram-workaround.a:lib_a-strtok_r.* *libc-psram-workaround.a:lib_a-fputwc.* *libc-psram-workaround.a:lib_a-stdio.* *libc-psram-workaround.a:lib_a-strcpy.* *libc-psram-workaround.a:lib_a-utoa.* *libc-psram-workaround.a:lib_a-open.* *libc-psram-workaround.a:lib_a-memrchr.* *libc-psram-workaround.a:lib_a-itoa.* *libc-psram-workaround.a:lib_a-strsep.* *libc-psram-workaround.a:lib_a-strtoul.* *libc-psram-workaround.a:lib_a-toupper.* *libc-psram-workaround.a:lib_a-sysopen.* *libc-psram-workaround.a:lib_a-strdup_r.* *libc-psram-workaround.a:lib_a-strlcpy.* *libc-psram-workaround.a:lib_a-timelocal.* *libc-psram-workaround.a:lib_a-sbrk.* *libc-psram-workaround.a:lib_a-longjmp.* *libc-psram-workaround.a:lib_a-sysread.* *libc-psram-workaround.a:lib_a-syssbrk.* *libc-psram-workaround.a:lib_a-isgraph.* *libc-psram-workaround.a:lib_a-strnlen.* *libc-psram-workaround.a:lib_a-envlock.* *libc-psram-workaround.a:lib_a-atoi.* *libc-psram-workaround.a:lib_a-refill.* *libc-psram-workaround.a:lib_a-memchr.* *libc-psram-workaround.a:lib_a-strchr.* *libc-psram-workaround.a:lib_a-system.* *libc-psram-workaround.a:lib_a-isspace.* *libc-psram-workaround.a:lib_a-getenv_r.* *libc-psram-workaround.a:lib_a-ldiv.* *libc-psram-workaround.a:lib_a-atol.* *libc-psram-workaround.a:lib_a-raise.* *libc-psram-workaround.a:lib_a-strncpy.* *libc-psram-workaround.a:lib_a-islower.* *libc-psram-workaround.a:lib_a-close.* *libc-psram-workaround.a:lib_a-wsetup.* *libc-psram-workaround.a:lib_a-isupper.* *libc-psram-workaround.a:lib_a-strftime.* *libc-psram-workaround.a:lib_a-strncat.* *libc-psram-workaround.a:lib_a-month_lengths.* *libc-psram-workaround.a:lib_a-bzero.* *libc-psram-workaround.a:lib_a-strcat.* *libc-psram-workaround.a:lib_a-srand.* *libc-psram-workaround.a:lib_a-setjmp.* *libc-psram-workaround.a:lib_a-sysclose.* *libc-psram-workaround.a:creat.* *libc-psram-workaround.a:lib_a-memcpy.* *libc-psram-workaround.a:lib_a-isascii.* *libc-psram-workaround.a:lib_a-ctime_r.* *libc-psram-workaround.a:lib_a-mktime.* *libc-psram-workaround.a:lib_a-wbuf.* *libc-psram-workaround.a:lib_a-sccl.* *libc-psram-workaround.a:lib_a-gmtime_r.* *libc-psram-workaround.a:lib_a-gmtime.* *libc-psram-workaround.a:lib_a-strndup_r.* *libc-psram-workaround.a:lib_a-strcoll.* *libc-psram-workaround.a:lib_a-tzvars.* *libc-psram-workaround.a:lib_a-wcrtomb.* *libc-psram-workaround.a:lib_a-isalpha.* *libc-psram-workaround.a:lib_a-isdigit.* *libc-psram-workaround.a:lib_a-toascii.* *libc-psram-workaround.a:lib_a-rshift.* *libc-psram-workaround.a:lib_a-strcmp.* *libc-psram-workaround.a:lib_a-memcmp.* *libc-psram-workaround.a:lib_a-fwalk.* *libc-psram-workaround.a:lib_a-creat.* *libc-psram-workaround.a:lib_a-strtol.* *libc-psram-workaround.a:lib_a-isalnum.* *libc-psram-workaround.a:lib_a-fclose.* *libc-psram-workaround.a:lib_a-gettzinfo.* *libc-psram-workaround.a:lib_a-strndup.* *libc-psram-workaround.a:lib_a-strrchr.* *libc-psram-workaround.a:lib_a-strspn.* *libc-psram-workaround.a:lib_a-quorem.* *libc-psram-workaround.a:lib_a-s_fpclassify.* *libc-psram-workaround.a:lib_a-ispunct.* *libc-psram-workaround.a:lib_a-rand_r.* *libc-psram-workaround.a:lib_a-tzset.* *libc-psram-workaround.a:lib_a-read.* *libc-psram-workaround.a:lib_a-isblank.* *libc-psram-workaround.a:lib_a-fvwrite.* *libc-psram-workaround.a:lib_a-strncmp.* *libc-psram-workaround.a:lib_a-asctime.* *libc-psram-workaround.a:lib_a-sf_nan.* *libc-psram-workaround.a:lib_a-abs.* *libc-psram-workaround.a:lib_a-strncasecmp.* *libc-psram-workaround.a:lib_a-iscntrl.* *libc-psram-workaround.a:lib_a-strcasecmp.* *libc-psram-workaround.a:lib_a-strcspn.* *libc-psram-workaround.a:lib_a-wctomb_r.* *libc-psram-workaround.a:lib_a-memccpy.* *libc-psram-workaround.a:lib_a-tolower.* *libc-psram-workaround.a:lib_a-asctime_r.* *libc-psram-workaround.a:lib_a-tzset_r.* *libc-psram-workaround.a:isatty.* *libc-psram-workaround.a:lib_a-strlen.* *libc-psram-workaround.a:lib_a-ungetc.* *libc-psram-workaround.a:lib_a-lcltime_r.* *libc-psram-workaround.a:lib_a-strstr.* *libc-psram-workaround.a:lib_a-strlcat.* *libc-psram-workaround.a:lib_a-labs.* *libc-psram-workaround.a:lib_a-tzcalc_limits.* *libc-psram-workaround.a:lib_a-environ.* *libc-psram-workaround.a:lib_a-strdup.* *libc-psram-workaround.a:lib_a-memset.* *libc-psram-workaround.a:lib_a-tzlock.* *libc-psram-workaround.a:lib_a-strcasestr.* *libc-psram-workaround.a:lib_a-makebuf.* *libc-psram-workaround.a:lib_a-time.* *libfreertos.a *libgcov.a *libxtensa-debug-module.a:eri.* *libheap.a:multi_heap_poisoning.* *libheap.a:multi_heap.*) .text.* .wifi0iram .wifi0iram.*)
+ *(EXCLUDE_FILE(*libesp_ringbuf.a *libgcov.a *libapp_trace.a:SEGGER_SYSVIEW_FreeRTOS.* *libapp_trace.a:SEGGER_RTT_esp32.* *libapp_trace.a:app_trace_util.* *libapp_trace.a:app_trace.* *libapp_trace.a:SEGGER_SYSVIEW.* *libapp_trace.a:SEGGER_SYSVIEW_Config_FreeRTOS.* *libgcc.a:lib2funcs.* *libgcc.a:_divsf3.* *libc.a:lib_a-strcat.* *libc.a:lib_a-toascii.* *libc.a:lib_a-strcoll.* *libc.a:lib_a-s_fpclassify.* *libc.a:lib_a-system.* *libc.a:lib_a-strtoul.* *libc.a:lib_a-strlen.* *libc.a:lib_a-utoa.* *libc.a:lib_a-lcltime.* *libc.a:lib_a-fvwrite.* *libc.a:lib_a-itoa.* *libc.a:lib_a-strndup_r.* *libc.a:lib_a-strtol.* *libc.a:lib_a-strdup_r.* *libc.a:lib_a-refill.* *libc.a:lib_a-fclose.* *libc.a:lib_a-gmtime.* *libc.a:lib_a-strcasestr.* *libc.a:lib_a-strlcat.* *libc.a:lib_a-asctime_r.* *libc.a:lib_a-tzset.* *libc.a:lib_a-tzset_r.* *libc.a:lib_a-fputwc.* *libc.a:lib_a-rand_r.* *libc.a:lib_a-strsep.* *libc.a:lib_a-strrchr.* *libc.a:lib_a-ctime_r.* *libc.a:lib_a-isalpha.* *libc.a:lib_a-memmove.* *libc.a:lib_a-sysopen.* *libc.a:lib_a-quorem.* *libc.a:lib_a-gmtime_r.* *libc.a:lib_a-isblank.* *libc.a:isatty.* *libc.a:lib_a-syssbrk.* *libc.a:lib_a-memcpy.* *libc.a:lib_a-memset.* *libc.a:lib_a-gettzinfo.* *libc.a:lib_a-strndup.* *libc.a:lib_a-strlwr.* *libc.a:lib_a-labs.* *libc.a:lib_a-strupr.* *libc.a:lib_a-ctime.* *libc.a:lib_a-wsetup.* *libc.a:lib_a-fflush.* *libc.a:lib_a-srand.* *libc.a:lib_a-wcrtomb.* *libc.a:lib_a-tzvars.* *libc.a:lib_a-strncat.* *libc.a:lib_a-setjmp.* *libc.a:lib_a-envlock.* *libc.a:lib_a-sysread.* *libc.a:lib_a-strcmp.* *libc.a:lib_a-ctype_.* *libc.a:lib_a-asctime.* *libc.a:lib_a-read.* *libc.a:lib_a-sbrk.* *libc.a:lib_a-abs.* *libc.a:lib_a-tzlock.* *libc.a:lib_a-strdup.* *libc.a:lib_a-strncasecmp.* *libc.a:lib_a-makebuf.* *libc.a:lib_a-strchr.* *libc.a:lock.* *libc.a:lib_a-syswrite.* *libc.a:lib_a-mktime.* *libc.a:lib_a-sysclose.* *libc.a:creat.* *libc.a:lib_a-ungetc.* *libc.a:lib_a-rshift.* *libc.a:lib_a-bzero.* *libc.a:lib_a-impure.* *libc.a:lib_a-fwalk.* *libc.a:lib_a-isupper.* *libc.a:lib_a-environ.* *libc.a:lib_a-strcasecmp.* *libc.a:lib_a-strcspn.* *libc.a:lib_a-rand.* *libc.a:lib_a-isgraph.* *libc.a:lib_a-systimes.* *libc.a:lib_a-strspn.* *libc.a:lib_a-getenv_r.* *libc.a:lib_a-ldiv.* *libc.a:lib_a-strlcpy.* *libc.a:lib_a-close.* *libc.a:lib_a-strncpy.* *libc.a:lib_a-sf_nan.* *libc.a:lib_a-isspace.* *libc.a:lib_a-isalnum.* *libc.a:lib_a-toupper.* *libc.a:lib_a-month_lengths.* *libc.a:lib_a-strftime.* *libc.a:lib_a-tzcalc_limits.* *libc.a:lib_a-iscntrl.* *libc.a:lib_a-strnlen.* *libc.a:lib_a-memcmp.* *libc.a:lib_a-div.* *libc.a:lib_a-lcltime_r.* *libc.a:lib_a-findfp.* *libc.a:lib_a-isdigit.* *libc.a:lib_a-strcpy.* *libc.a:lib_a-memrchr.* *libc.a:lib_a-islower.* *libc.a:lib_a-isascii.* *libc.a:lib_a-sccl.* *libc.a:lib_a-open.* *libc.a:lib_a-time.* *libc.a:lib_a-stdio.* *libc.a:lib_a-wbuf.* *libc.a:lib_a-tolower.* *libc.a:lib_a-memchr.* *libc.a:lib_a-ispunct.* *libc.a:lib_a-isprint.* *libc.a:lib_a-strtok_r.* *libc.a:lib_a-raise.* *libc.a:lib_a-longjmp.* *libc.a:lib_a-atol.* *libc.a:lib_a-atoi.* *libc.a:lib_a-creat.* *libc.a:lib_a-strncmp.* *libc.a:lib_a-wctomb_r.* *libc.a:lib_a-strptime.* *libc.a:lib_a-memccpy.* *libc.a:lib_a-timelocal.* *libc.a:lib_a-strstr.* *libheap.a:multi_heap.* *libheap.a:multi_heap_poisoning.* *libesp32.a:panic.* *libspi_flash.a:memspi_host_driver.* *libspi_flash.a:spi_flash_chip_generic.* *libspi_flash.a:spi_flash_chip_gd.* *libspi_flash.a:spi_flash_chip_issi.* *libspi_flash.a:spi_flash_rom_patch.* *librtc.a *libsoc.a:i2c_hal_iram.* *libsoc.a:rtc_clk.* *libsoc.a:cpu_util.* *libsoc.a:rtc_sleep.* *libsoc.a:spi_hal_iram.* *libsoc.a:spi_flash_hal_iram.* *libsoc.a:uart_hal_iram.* *libsoc.a:rtc_clk_init.* *libsoc.a:rtc_pm.* *libsoc.a:rtc_periph.* *libsoc.a:lldesc.* *libsoc.a:spi_slave_hal_iram.* *libsoc.a:spi_flash_hal_gpspi.* *libsoc.a:rtc_wdt.* *libsoc.a:ledc_hal_iram.* *libsoc.a:rtc_time.* *libsoc.a:rtc_init.* *libxtensa.a:eri.* *libnewlib.a:heap.* *libhal.a *libfreertos.a) .literal EXCLUDE_FILE(*libesp_ringbuf.a *libgcov.a *libapp_trace.a:SEGGER_SYSVIEW_FreeRTOS.* *libapp_trace.a:SEGGER_RTT_esp32.* *libapp_trace.a:app_trace_util.* *libapp_trace.a:app_trace.* *libapp_trace.a:SEGGER_SYSVIEW.* *libapp_trace.a:SEGGER_SYSVIEW_Config_FreeRTOS.* *liblog.a:log.* *liblog.a:log_freertos.* *libgcc.a:lib2funcs.* *libgcc.a:_divsf3.* *libesp_event.a:default_event_loop.* *libesp_event.a:esp_event.* *libc.a:lib_a-strcat.* *libc.a:lib_a-toascii.* *libc.a:lib_a-strcoll.* *libc.a:lib_a-s_fpclassify.* *libc.a:lib_a-system.* *libc.a:lib_a-strtoul.* *libc.a:lib_a-strlen.* *libc.a:lib_a-utoa.* *libc.a:lib_a-lcltime.* *libc.a:lib_a-fvwrite.* *libc.a:lib_a-itoa.* *libc.a:lib_a-strndup_r.* *libc.a:lib_a-strtol.* *libc.a:lib_a-strdup_r.* *libc.a:lib_a-refill.* *libc.a:lib_a-fclose.* *libc.a:lib_a-gmtime.* *libc.a:lib_a-strcasestr.* *libc.a:lib_a-strlcat.* *libc.a:lib_a-asctime_r.* *libc.a:lib_a-tzset.* *libc.a:lib_a-tzset_r.* *libc.a:lib_a-fputwc.* *libc.a:lib_a-rand_r.* *libc.a:lib_a-strsep.* *libc.a:lib_a-strrchr.* *libc.a:lib_a-ctime_r.* *libc.a:lib_a-isalpha.* *libc.a:lib_a-memmove.* *libc.a:lib_a-sysopen.* *libc.a:lib_a-quorem.* *libc.a:lib_a-gmtime_r.* *libc.a:lib_a-isblank.* *libc.a:isatty.* *libc.a:lib_a-syssbrk.* *libc.a:lib_a-memcpy.* *libc.a:lib_a-memset.* *libc.a:lib_a-gettzinfo.* *libc.a:lib_a-strndup.* *libc.a:lib_a-strlwr.* *libc.a:lib_a-labs.* *libc.a:lib_a-strupr.* *libc.a:lib_a-ctime.* *libc.a:lib_a-wsetup.* *libc.a:lib_a-fflush.* *libc.a:lib_a-srand.* *libc.a:lib_a-wcrtomb.* *libc.a:lib_a-tzvars.* *libc.a:lib_a-strncat.* *libc.a:lib_a-setjmp.* *libc.a:lib_a-envlock.* *libc.a:lib_a-sysread.* *libc.a:lib_a-strcmp.* *libc.a:lib_a-ctype_.* *libc.a:lib_a-asctime.* *libc.a:lib_a-read.* *libc.a:lib_a-sbrk.* *libc.a:lib_a-abs.* *libc.a:lib_a-tzlock.* *libc.a:lib_a-strdup.* *libc.a:lib_a-strncasecmp.* *libc.a:lib_a-makebuf.* *libc.a:lib_a-strchr.* *libc.a:lock.* *libc.a:lib_a-syswrite.* *libc.a:lib_a-mktime.* *libc.a:lib_a-sysclose.* *libc.a:creat.* *libc.a:lib_a-ungetc.* *libc.a:lib_a-rshift.* *libc.a:lib_a-bzero.* *libc.a:lib_a-impure.* *libc.a:lib_a-fwalk.* *libc.a:lib_a-isupper.* *libc.a:lib_a-environ.* *libc.a:lib_a-strcasecmp.* *libc.a:lib_a-strcspn.* *libc.a:lib_a-rand.* *libc.a:lib_a-isgraph.* *libc.a:lib_a-systimes.* *libc.a:lib_a-strspn.* *libc.a:lib_a-getenv_r.* *libc.a:lib_a-ldiv.* *libc.a:lib_a-strlcpy.* *libc.a:lib_a-close.* *libc.a:lib_a-strncpy.* *libc.a:lib_a-sf_nan.* *libc.a:lib_a-isspace.* *libc.a:lib_a-isalnum.* *libc.a:lib_a-toupper.* *libc.a:lib_a-month_lengths.* *libc.a:lib_a-strftime.* *libc.a:lib_a-tzcalc_limits.* *libc.a:lib_a-iscntrl.* *libc.a:lib_a-strnlen.* *libc.a:lib_a-memcmp.* *libc.a:lib_a-div.* *libc.a:lib_a-lcltime_r.* *libc.a:lib_a-findfp.* *libc.a:lib_a-isdigit.* *libc.a:lib_a-strcpy.* *libc.a:lib_a-memrchr.* *libc.a:lib_a-islower.* *libc.a:lib_a-isascii.* *libc.a:lib_a-sccl.* *libc.a:lib_a-open.* *libc.a:lib_a-time.* *libc.a:lib_a-stdio.* *libc.a:lib_a-wbuf.* *libc.a:lib_a-tolower.* *libc.a:lib_a-memchr.* *libc.a:lib_a-ispunct.* *libc.a:lib_a-isprint.* *libc.a:lib_a-strtok_r.* *libc.a:lib_a-raise.* *libc.a:lib_a-longjmp.* *libc.a:lib_a-atol.* *libc.a:lib_a-atoi.* *libc.a:lib_a-creat.* *libc.a:lib_a-strncmp.* *libc.a:lib_a-wctomb_r.* *libc.a:lib_a-strptime.* *libc.a:lib_a-memccpy.* *libc.a:lib_a-timelocal.* *libc.a:lib_a-strstr.* *libheap.a:multi_heap.* *libheap.a:multi_heap_poisoning.* *libesp32.a:panic.* *libspi_flash.a:memspi_host_driver.* *libspi_flash.a:spi_flash_chip_generic.* *libspi_flash.a:spi_flash_chip_gd.* *libspi_flash.a:spi_flash_chip_issi.* *libspi_flash.a:spi_flash_rom_patch.* *librtc.a *libsoc.a:i2c_hal_iram.* *libsoc.a:rtc_clk.* *libsoc.a:cpu_util.* *libsoc.a:rtc_sleep.* *libsoc.a:spi_hal_iram.* *libsoc.a:spi_flash_hal_iram.* *libsoc.a:uart_hal_iram.* *libsoc.a:rtc_clk_init.* *libsoc.a:rtc_pm.* *libsoc.a:rtc_periph.* *libsoc.a:lldesc.* *libsoc.a:spi_slave_hal_iram.* *libsoc.a:spi_flash_hal_gpspi.* *libsoc.a:rtc_wdt.* *libsoc.a:ledc_hal_iram.* *libsoc.a:rtc_time.* *libsoc.a:rtc_init.* *libxtensa.a:eri.* *libnewlib.a:heap.* *libhal.a *libfreertos.a) .literal.* EXCLUDE_FILE(*libesp_ringbuf.a *libgcov.a *libapp_trace.a:SEGGER_SYSVIEW_FreeRTOS.* *libapp_trace.a:SEGGER_RTT_esp32.* *libapp_trace.a:app_trace_util.* *libapp_trace.a:app_trace.* *libapp_trace.a:SEGGER_SYSVIEW.* *libapp_trace.a:SEGGER_SYSVIEW_Config_FreeRTOS.* *libgcc.a:lib2funcs.* *libgcc.a:_divsf3.* *libc.a:lib_a-strcat.* *libc.a:lib_a-toascii.* *libc.a:lib_a-strcoll.* *libc.a:lib_a-s_fpclassify.* *libc.a:lib_a-system.* *libc.a:lib_a-strtoul.* *libc.a:lib_a-strlen.* *libc.a:lib_a-utoa.* *libc.a:lib_a-lcltime.* *libc.a:lib_a-fvwrite.* *libc.a:lib_a-itoa.* *libc.a:lib_a-strndup_r.* *libc.a:lib_a-strtol.* *libc.a:lib_a-strdup_r.* *libc.a:lib_a-refill.* *libc.a:lib_a-fclose.* *libc.a:lib_a-gmtime.* *libc.a:lib_a-strcasestr.* *libc.a:lib_a-strlcat.* *libc.a:lib_a-asctime_r.* *libc.a:lib_a-tzset.* *libc.a:lib_a-tzset_r.* *libc.a:lib_a-fputwc.* *libc.a:lib_a-rand_r.* *libc.a:lib_a-strsep.* *libc.a:lib_a-strrchr.* *libc.a:lib_a-ctime_r.* *libc.a:lib_a-isalpha.* *libc.a:lib_a-memmove.* *libc.a:lib_a-sysopen.* *libc.a:lib_a-quorem.* *libc.a:lib_a-gmtime_r.* *libc.a:lib_a-isblank.* *libc.a:isatty.* *libc.a:lib_a-syssbrk.* *libc.a:lib_a-memcpy.* *libc.a:lib_a-memset.* *libc.a:lib_a-gettzinfo.* *libc.a:lib_a-strndup.* *libc.a:lib_a-strlwr.* *libc.a:lib_a-labs.* *libc.a:lib_a-strupr.* *libc.a:lib_a-ctime.* *libc.a:lib_a-wsetup.* *libc.a:lib_a-fflush.* *libc.a:lib_a-srand.* *libc.a:lib_a-wcrtomb.* *libc.a:lib_a-tzvars.* *libc.a:lib_a-strncat.* *libc.a:lib_a-setjmp.* *libc.a:lib_a-envlock.* *libc.a:lib_a-sysread.* *libc.a:lib_a-strcmp.* *libc.a:lib_a-ctype_.* *libc.a:lib_a-asctime.* *libc.a:lib_a-read.* *libc.a:lib_a-sbrk.* *libc.a:lib_a-abs.* *libc.a:lib_a-tzlock.* *libc.a:lib_a-strdup.* *libc.a:lib_a-strncasecmp.* *libc.a:lib_a-makebuf.* *libc.a:lib_a-strchr.* *libc.a:lock.* *libc.a:lib_a-syswrite.* *libc.a:lib_a-mktime.* *libc.a:lib_a-sysclose.* *libc.a:creat.* *libc.a:lib_a-ungetc.* *libc.a:lib_a-rshift.* *libc.a:lib_a-bzero.* *libc.a:lib_a-impure.* *libc.a:lib_a-fwalk.* *libc.a:lib_a-isupper.* *libc.a:lib_a-environ.* *libc.a:lib_a-strcasecmp.* *libc.a:lib_a-strcspn.* *libc.a:lib_a-rand.* *libc.a:lib_a-isgraph.* *libc.a:lib_a-systimes.* *libc.a:lib_a-strspn.* *libc.a:lib_a-getenv_r.* *libc.a:lib_a-ldiv.* *libc.a:lib_a-strlcpy.* *libc.a:lib_a-close.* *libc.a:lib_a-strncpy.* *libc.a:lib_a-sf_nan.* *libc.a:lib_a-isspace.* *libc.a:lib_a-isalnum.* *libc.a:lib_a-toupper.* *libc.a:lib_a-month_lengths.* *libc.a:lib_a-strftime.* *libc.a:lib_a-tzcalc_limits.* *libc.a:lib_a-iscntrl.* *libc.a:lib_a-strnlen.* *libc.a:lib_a-memcmp.* *libc.a:lib_a-div.* *libc.a:lib_a-lcltime_r.* *libc.a:lib_a-findfp.* *libc.a:lib_a-isdigit.* *libc.a:lib_a-strcpy.* *libc.a:lib_a-memrchr.* *libc.a:lib_a-islower.* *libc.a:lib_a-isascii.* *libc.a:lib_a-sccl.* *libc.a:lib_a-open.* *libc.a:lib_a-time.* *libc.a:lib_a-stdio.* *libc.a:lib_a-wbuf.* *libc.a:lib_a-tolower.* *libc.a:lib_a-memchr.* *libc.a:lib_a-ispunct.* *libc.a:lib_a-isprint.* *libc.a:lib_a-strtok_r.* *libc.a:lib_a-raise.* *libc.a:lib_a-longjmp.* *libc.a:lib_a-atol.* *libc.a:lib_a-atoi.* *libc.a:lib_a-creat.* *libc.a:lib_a-strncmp.* *libc.a:lib_a-wctomb_r.* *libc.a:lib_a-strptime.* *libc.a:lib_a-memccpy.* *libc.a:lib_a-timelocal.* *libc.a:lib_a-strstr.* *libheap.a:multi_heap.* *libheap.a:multi_heap_poisoning.* *libesp32.a:panic.* *libspi_flash.a:memspi_host_driver.* *libspi_flash.a:spi_flash_chip_generic.* *libspi_flash.a:spi_flash_chip_gd.* *libspi_flash.a:spi_flash_chip_issi.* *libspi_flash.a:spi_flash_rom_patch.* *librtc.a *libsoc.a:i2c_hal_iram.* *libsoc.a:rtc_clk.* *libsoc.a:cpu_util.* *libsoc.a:rtc_sleep.* *libsoc.a:spi_hal_iram.* *libsoc.a:spi_flash_hal_iram.* *libsoc.a:uart_hal_iram.* *libsoc.a:rtc_clk_init.* *libsoc.a:rtc_pm.* *libsoc.a:rtc_periph.* *libsoc.a:lldesc.* *libsoc.a:spi_slave_hal_iram.* *libsoc.a:spi_flash_hal_gpspi.* *libsoc.a:rtc_wdt.* *libsoc.a:ledc_hal_iram.* *libsoc.a:rtc_time.* *libsoc.a:rtc_init.* *libxtensa.a:eri.* *libnewlib.a:heap.* *libhal.a *libfreertos.a) .text EXCLUDE_FILE(*libesp_ringbuf.a *libgcov.a *libapp_trace.a:SEGGER_SYSVIEW_FreeRTOS.* *libapp_trace.a:SEGGER_RTT_esp32.* *libapp_trace.a:app_trace_util.* *libapp_trace.a:app_trace.* *libapp_trace.a:SEGGER_SYSVIEW.* *libapp_trace.a:SEGGER_SYSVIEW_Config_FreeRTOS.* *liblog.a:log.* *liblog.a:log_freertos.* *libgcc.a:lib2funcs.* *libgcc.a:_divsf3.* *libesp_event.a:default_event_loop.* *libesp_event.a:esp_event.* *libc.a:lib_a-strcat.* *libc.a:lib_a-toascii.* *libc.a:lib_a-strcoll.* *libc.a:lib_a-s_fpclassify.* *libc.a:lib_a-system.* *libc.a:lib_a-strtoul.* *libc.a:lib_a-strlen.* *libc.a:lib_a-utoa.* *libc.a:lib_a-lcltime.* *libc.a:lib_a-fvwrite.* *libc.a:lib_a-itoa.* *libc.a:lib_a-strndup_r.* *libc.a:lib_a-strtol.* *libc.a:lib_a-strdup_r.* *libc.a:lib_a-refill.* *libc.a:lib_a-fclose.* *libc.a:lib_a-gmtime.* *libc.a:lib_a-strcasestr.* *libc.a:lib_a-strlcat.* *libc.a:lib_a-asctime_r.* *libc.a:lib_a-tzset.* *libc.a:lib_a-tzset_r.* *libc.a:lib_a-fputwc.* *libc.a:lib_a-rand_r.* *libc.a:lib_a-strsep.* *libc.a:lib_a-strrchr.* *libc.a:lib_a-ctime_r.* *libc.a:lib_a-isalpha.* *libc.a:lib_a-memmove.* *libc.a:lib_a-sysopen.* *libc.a:lib_a-quorem.* *libc.a:lib_a-gmtime_r.* *libc.a:lib_a-isblank.* *libc.a:isatty.* *libc.a:lib_a-syssbrk.* *libc.a:lib_a-memcpy.* *libc.a:lib_a-memset.* *libc.a:lib_a-gettzinfo.* *libc.a:lib_a-strndup.* *libc.a:lib_a-strlwr.* *libc.a:lib_a-labs.* *libc.a:lib_a-strupr.* *libc.a:lib_a-ctime.* *libc.a:lib_a-wsetup.* *libc.a:lib_a-fflush.* *libc.a:lib_a-srand.* *libc.a:lib_a-wcrtomb.* *libc.a:lib_a-tzvars.* *libc.a:lib_a-strncat.* *libc.a:lib_a-setjmp.* *libc.a:lib_a-envlock.* *libc.a:lib_a-sysread.* *libc.a:lib_a-strcmp.* *libc.a:lib_a-ctype_.* *libc.a:lib_a-asctime.* *libc.a:lib_a-read.* *libc.a:lib_a-sbrk.* *libc.a:lib_a-abs.* *libc.a:lib_a-tzlock.* *libc.a:lib_a-strdup.* *libc.a:lib_a-strncasecmp.* *libc.a:lib_a-makebuf.* *libc.a:lib_a-strchr.* *libc.a:lock.* *libc.a:lib_a-syswrite.* *libc.a:lib_a-mktime.* *libc.a:lib_a-sysclose.* *libc.a:creat.* *libc.a:lib_a-ungetc.* *libc.a:lib_a-rshift.* *libc.a:lib_a-bzero.* *libc.a:lib_a-impure.* *libc.a:lib_a-fwalk.* *libc.a:lib_a-isupper.* *libc.a:lib_a-environ.* *libc.a:lib_a-strcasecmp.* *libc.a:lib_a-strcspn.* *libc.a:lib_a-rand.* *libc.a:lib_a-isgraph.* *libc.a:lib_a-systimes.* *libc.a:lib_a-strspn.* *libc.a:lib_a-getenv_r.* *libc.a:lib_a-ldiv.* *libc.a:lib_a-strlcpy.* *libc.a:lib_a-close.* *libc.a:lib_a-strncpy.* *libc.a:lib_a-sf_nan.* *libc.a:lib_a-isspace.* *libc.a:lib_a-isalnum.* *libc.a:lib_a-toupper.* *libc.a:lib_a-month_lengths.* *libc.a:lib_a-strftime.* *libc.a:lib_a-tzcalc_limits.* *libc.a:lib_a-iscntrl.* *libc.a:lib_a-strnlen.* *libc.a:lib_a-memcmp.* *libc.a:lib_a-div.* *libc.a:lib_a-lcltime_r.* *libc.a:lib_a-findfp.* *libc.a:lib_a-isdigit.* *libc.a:lib_a-strcpy.* *libc.a:lib_a-memrchr.* *libc.a:lib_a-islower.* *libc.a:lib_a-isascii.* *libc.a:lib_a-sccl.* *libc.a:lib_a-open.* *libc.a:lib_a-time.* *libc.a:lib_a-stdio.* *libc.a:lib_a-wbuf.* *libc.a:lib_a-tolower.* *libc.a:lib_a-memchr.* *libc.a:lib_a-ispunct.* *libc.a:lib_a-isprint.* *libc.a:lib_a-strtok_r.* *libc.a:lib_a-raise.* *libc.a:lib_a-longjmp.* *libc.a:lib_a-atol.* *libc.a:lib_a-atoi.* *libc.a:lib_a-creat.* *libc.a:lib_a-strncmp.* *libc.a:lib_a-wctomb_r.* *libc.a:lib_a-strptime.* *libc.a:lib_a-memccpy.* *libc.a:lib_a-timelocal.* *libc.a:lib_a-strstr.* *libheap.a:multi_heap.* *libheap.a:multi_heap_poisoning.* *libesp32.a:panic.* *libspi_flash.a:memspi_host_driver.* *libspi_flash.a:spi_flash_chip_generic.* *libspi_flash.a:spi_flash_chip_gd.* *libspi_flash.a:spi_flash_chip_issi.* *libspi_flash.a:spi_flash_rom_patch.* *librtc.a *libsoc.a:i2c_hal_iram.* *libsoc.a:rtc_clk.* *libsoc.a:cpu_util.* *libsoc.a:rtc_sleep.* *libsoc.a:spi_hal_iram.* *libsoc.a:spi_flash_hal_iram.* *libsoc.a:uart_hal_iram.* *libsoc.a:rtc_clk_init.* *libsoc.a:rtc_pm.* *libsoc.a:rtc_periph.* *libsoc.a:lldesc.* *libsoc.a:spi_slave_hal_iram.* *libsoc.a:spi_flash_hal_gpspi.* *libsoc.a:rtc_wdt.* *libsoc.a:ledc_hal_iram.* *libsoc.a:rtc_time.* *libsoc.a:rtc_init.* *libxtensa.a:eri.* *libnewlib.a:heap.* *libhal.a *libfreertos.a) .text.* EXCLUDE_FILE(*libsoc.a:uart_hal_iram.*) .wifi0iram EXCLUDE_FILE(*libsoc.a:uart_hal_iram.*) .wifi0iram.* EXCLUDE_FILE(*libsoc.a:uart_hal_iram.*) .wifirxiram EXCLUDE_FILE(*libsoc.a:uart_hal_iram.*) .wifirxiram.*)
+ *libesp_event.a:default_event_loop.*(.literal.esp_event_handler_register .literal.esp_event_handler_unregister .literal.esp_event_post .literal.esp_event_loop_create_default .literal.esp_event_loop_delete_default .literal.esp_event_send_to_default_loop .text.esp_event_handler_register .text.esp_event_handler_unregister .text.esp_event_post .text.esp_event_loop_create_default .text.esp_event_loop_delete_default .text.esp_event_send_to_default_loop)
+ *libesp_event.a:esp_event.*(.literal.handler_instances_remove_all$isra$1 .literal.handler_instances_add$isra$2 .literal.base_node_add_handler .literal.loop_node_add_handler .literal.handler_instances_remove$isra$3 .literal.esp_event_loop_create .literal.esp_event_loop_run .literal.esp_event_loop_run_task .literal.esp_event_loop_delete .literal.esp_event_handler_register_with .literal.esp_event_handler_unregister_with .literal.esp_event_post_to .text.handler_instances_remove_all$isra$1 .text.handler_instances_add$isra$2 .text.base_node_add_handler .text.loop_node_add_handler .text.handler_instances_remove$isra$3 .text.esp_event_loop_create .text.esp_event_loop_run .text.esp_event_loop_run_task .text.esp_event_loop_delete .text.esp_event_handler_register_with .text.esp_event_handler_unregister_with .text.esp_event_post_to .text.esp_event_dump)
+ *liblog.a:log.*(.literal.heap_bubble_down .literal.esp_log_set_vprintf .literal.esp_log_level_set .literal.esp_log_writev .text.heap_bubble_down .text.esp_log_set_vprintf .text.esp_log_level_set .text.esp_log_writev)
+ *liblog.a:log_freertos.*(.literal.esp_log_system_timestamp .text.esp_log_system_timestamp)
+ *libsoc.a:uart_hal_iram.*( .literal .literal.* .text .text.* .wifi0iram .wifi0iram.* .wifirxiram .wifirxiram.*)
*(.stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
*(.irom0.text) /* catch stray ICACHE_RODATA_ATTR */
@@ -614,5 +677,25 @@ SECTIONS
the flash.text segment.
*/
_flash_cache_start = ABSOLUTE(0);
- } >iram0_2_seg
+ } >default_code_seg
+
+ /* Marks the end of IRAM code segment */
+ .iram0.text_end (NOLOAD) :
+ {
+ . = ALIGN (4);
+ _iram_end = ABSOLUTE(.);
+ } > iram0_0_seg
+
+ /* Marks the end of data, bss and possibly rodata */
+ .dram0.heap_start (NOLOAD) :
+ {
+ . = ALIGN (8);
+ _heap_start = ABSOLUTE(.);
+ } > dram0_0_seg
}
+
+ASSERT(((_iram_text_end - ORIGIN(iram0_0_seg)) <= LENGTH(iram0_0_seg)),
+ "IRAM0 segment data does not fit.")
+
+ASSERT(((_heap_start - ORIGIN(dram0_0_seg)) <= LENGTH(dram0_0_seg)),
+ "DRAM segment data does not fit.")
diff --git a/esp32/factory_fw/binary/factory_fw.bin b/esp32/factory_fw/binary/factory_fw.bin
new file mode 100644
index 0000000000..1dcf63cc07
Binary files /dev/null and b/esp32/factory_fw/binary/factory_fw.bin differ
diff --git a/esp32/frozen/Pybytes/_OTA.py b/esp32/frozen/Pybytes/_OTA.py
index a1391035c3..8c2986781f 100644
--- a/esp32/frozen/Pybytes/_OTA.py
+++ b/esp32/frozen/Pybytes/_OTA.py
@@ -64,7 +64,7 @@ def get_update_manifest(self, fwtype=None, token=None):
if fwtype == 'pymesh':
request_template = "manifest.json?current_ver={}&sysname={}&token={}&ota_slot={}&wmac={}&fwtype={}¤t_fwtype={}"
req = request_template.format(current_version, sysname, token, hex(pycom.ota_slot()), wmac.upper(), fwtype, 'pymesh' if hasattr(os.uname(),'pymesh') else 'pybytes')
- elif fwtype == 'pygate':
+ elif fwtype == 'pygate' or fwtype == 'factory':
request_template = "manifest.json?current_ver={}&sysname={}&ota_slot={}&wmac={}&fwtype={}¤t_fwtype={}"
req = request_template.format(current_version, sysname, hex(pycom.ota_slot()), wmac.upper(), fwtype, 'pygate' if hasattr(os.uname(),'pygate') else 'pybytes')
else:
@@ -79,7 +79,7 @@ def update(self, customManifest=None, fwtype=None, token=None):
try:
manifest = self.get_update_manifest(fwtype, token) if not customManifest else customManifest
except Exception as e:
- print('Error reading the manifest, aborting: {}'.format(e))
+ print('Error reading the manifest, aborting: {}, \nmanifest: {}'.format(e, manifest))
return 0
if manifest is None:
@@ -122,7 +122,29 @@ def update(self, customManifest=None, fwtype=None, token=None):
# Flash firmware
if "firmware" in manifest:
- self.write_firmware(manifest['firmware'])
+ if fwtype=='factory':
+ # In case of factory FW update, we do the update from the App FW
+ self.write_firmware(manifest['firmware'])
+ else:
+ # Since the firmware update is going to be done in the factory image,
+ # we will set the required configurations here and move on
+ if fwtype == 'pymesh':
+ pycom.pybytes_fwtype(pycom.FWTYPE_PYMESH)
+ else:
+ pycom.pybytes_fwtype(pycom.FWTYPE_PYBYTES)
+
+ print('Setting SW version: ', self.get_current_version())
+ pycom.sw_version(self.get_current_version())
+
+ print('Setting sysname: ', os.uname().sysname)
+ pycom.pybytes_sysname(os.uname().sysname)
+
+ # Setting the OTA Status to Pending
+ print('Setting OTA Status: OTA_STATUS_PENDING')
+ pycom.pybytes_ota_status(pycom.OTA_STATUS_PENDING)
+
+ # Updating bootinfo to boot from the factory image on the next boot
+ pycom.factory_img(True)
# Save version number
# try:
@@ -330,6 +352,9 @@ def update_network_config(self, letResp, fcota, config):
config['network_preferences'] = netConf['networkPreferences']
if 'wifi' in netConf:
config['wifi'] = netConf['wifi']
+ print('Wifi Credentials updated to SSID:{}, PWD:{}'.format(config['wifi']['wifi_ssid'], config['wifi']['wifi_pwd']))
+ pycom.wifi_ssid_sta(config['wifi']['wifi_ssid'])
+ pycom.wifi_pwd_sta(config['wifi']['wifi_pwd'])
elif 'wifi' in config:
del config['wifi']
diff --git a/esp32/ftp/ftp.c b/esp32/ftp/ftp.c
index 2ea6efbdbb..35ddaa14f4 100644
--- a/esp32/ftp/ftp.c
+++ b/esp32/ftp/ftp.c
@@ -51,6 +51,7 @@
#include "machrtc.h"
#include "mptask.h"
+#include "modwlan.h"
#include "esp32_mphal.h"
//#define MSG(fmt, ...) printf("[%u] ftp: " fmt, mp_hal_ticks_ms(), ##__VA_ARGS__)
@@ -870,29 +871,31 @@ static ftp_result_t ftp_wait_for_connection (int32_t l_sd, int32_t *n_sd, uint32
}
if (ip_addr) {
- tcpip_adapter_ip_info_t ip_info;
+ esp_netif_ip_info_t ip_info;
bool adapter_found = false;
#ifdef PYETH_ENABLED
if ( tcpip_adapter_is_netif_up(TCPIP_ADAPTER_IF_ETH) ) {
- tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_ETH, &ip_info);
+ tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_ETH, (tcpip_adapter_ip_info_t*)&ip_info);
adapter_found = true;
}
#endif
- if ( !adapter_found && tcpip_adapter_is_netif_up(TCPIP_ADAPTER_IF_AP) ){
- tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_AP, &ip_info);
+ if (!adapter_found && esp_netif_is_netif_up(wlan_obj.esp_netif_AP)){
+ esp_netif_get_ip_info(wlan_obj.esp_netif_AP, &ip_info);
adapter_found = true;
}
- if ( !adapter_found && tcpip_adapter_is_netif_up(TCPIP_ADAPTER_IF_STA) ){
- tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_STA, &ip_info);
+ if (!adapter_found && esp_netif_is_netif_up(wlan_obj.esp_netif_STA)){
+ esp_netif_get_ip_info(wlan_obj.esp_netif_STA, &ip_info);
adapter_found = true;
}
MSG("fwfc ip=%08x nm=%08x gw=%08x cl=%08x\n", ip_info.ip.addr, ip_info.netmask.addr, ip_info.gw.addr, sClientAddress.sin_addr.s_addr);
MSG("fwfc ip=" IPSTR " nm=" IPSTR " gw=" IPSTR "\n", IP2STR(&ip_info.ip), IP2STR(&ip_info.netmask), IP2STR(&ip_info.gw) );
*ip_addr = ip_info.ip.addr;
+
+
}
// add the new socket to the network administration
diff --git a/esp32/ftp/updater.c b/esp32/ftp/updater.c
index b106a2c562..581e404d33 100644
--- a/esp32/ftp/updater.c
+++ b/esp32/ftp/updater.c
@@ -13,14 +13,14 @@
#include "py/mpconfig.h"
#include "py/obj.h"
-#include "bootloader.h"
+#include "pycom_bootloader.h"
#include "updater.h"
#include "esp_spi_flash.h"
#include "esp_flash_encrypt.h"
#include "esp_image_format.h"
//#define LOG_LOCAL_LEVEL ESP_LOG_INFO
#include "esp_log.h"
-#include "rom/crc.h"
+#include "esp32/rom/crc.h"
#include "esp32chipinfo.h"
#ifdef DIFF_UPDATE_ENABLED
@@ -34,6 +34,16 @@
static const char *TAG = "updater";
#define UPDATER_IMG_PATH "/flash/sys/appimg.bin"
+#if(SMALL_FACTORY_FW_ENABLED == 1)
+#define IMG_SIZE_8MB (3004 * 1024)
+#define IMG_UPDATE1_OFFSET_8MB (1088 * 1024) // taken from the partitions table
+#else
+#define IMG_SIZE_8MB (1980 * 1024)
+#define IMG_UPDATE1_OFFSET_8MB (2112 * 1024) // taken from the partitions table
+#endif
+#define IMG_SIZE_4MB (2424 * 1024)
+#define IMG_UPDATE1_OFFSET_4MB (1088 * 1024) // taken from the partitions table
+
/* if flash is encrypted, it requires the flash_write operation to be done in 16 Bytes chunks */
#define ENCRYP_FLASH_MIN_CHUNK 16
@@ -565,7 +575,6 @@ bool updater_write_boot_info(boot_info_t *boot_info, uint32_t boot_info_offset)
spi_flash_read_encrypted(boot_info_offset + sizeof(boot_info_t),
(void *)(buff + sizeof(boot_info_t)),
len_aligned_16 - sizeof(boot_info_t) );
-
ret = spi_flash_write_encrypted(boot_info_offset, (void *)buff, len_aligned_16);
} else { // not-encrypted flash, just write directly boot_info
ret = spi_flash_write(boot_info_offset, (void *)boot_info, sizeof(boot_info_t));
diff --git a/esp32/ftp/updater.h b/esp32/ftp/updater.h
index 1cfa832a95..49c63dbd24 100644
--- a/esp32/ftp/updater.h
+++ b/esp32/ftp/updater.h
@@ -11,7 +11,7 @@
#ifndef UPDATER_H_
#define UPDATER_H_
-#include "bootloader.h"
+#include "pycom_bootloader.h"
/**
* @brief Checks the default path.
diff --git a/esp32/get_idf_libs.py b/esp32/get_idf_libs.py
index b7b62a788e..072c0995fc 100755
--- a/esp32/get_idf_libs.py
+++ b/esp32/get_idf_libs.py
@@ -7,6 +7,18 @@
import traceback
+def find_xtensa_path():
+ system_path = os.environ['PATH']
+ system_paths = system_path.split(os.pathsep)
+
+ for p in system_paths:
+ if "xtensa-esp32-elf" in p:
+ # Remove /bin from the end
+ return p[:-4]
+
+ print("Couldn't find xtensa-esp32-elf toolchain!")
+ traceback.print_exc()
+
def main():
src_def = os.environ['IDF_PATH']+'/examples/wifi/scan/build'
cmd_parser = argparse.ArgumentParser(description='Get the precompiled libs from the IDF')
@@ -19,29 +31,31 @@ def main():
dstbl = os.getcwd() + '/bootloader/lib'
dsttmpapp = os.getcwd() + '/lib/tmp'
dstapp = os.getcwd() + '/lib'
-
+
try:
# copy the bootloader libraries
-
+
os.mkdir(dsttmpbl)
os.mkdir(dsttmpapp)
-
- shutil.copy(src + '/bootloader/bootloader_support/libbootloader_support.a', dsttmpbl)
+
shutil.copy(src + '/bootloader/log/liblog.a', dsttmpbl)
- shutil.copy(src + '/bootloader/micro-ecc/libmicro-ecc.a', dsttmpbl)
shutil.copy(src + '/bootloader/soc/libsoc.a', dsttmpbl)
- shutil.copy(src + '/bootloader/spi_flash/libspi_flash.a', dsttmpbl)
+ shutil.copy(src + '/bootloader/main/libmain.a', dsttmpbl)
shutil.copy(src + '/bootloader/efuse/libefuse.a', dsttmpbl)
-
+ shutil.copy(src + '/bootloader/micro-ecc/libmicro-ecc.a', dsttmpbl)
+ shutil.copy(src + '/bootloader/spi_flash/libspi_flash.a', dsttmpbl)
+ shutil.copy(src + '/bootloader/bootloader_support/libbootloader_support.a', dsttmpbl)
+ # bootloader.map is needed since we build all the bootlader libraries (including Pycom's one) in esp-idf, here we will just link them together
+ shutil.copy(src + '/bootloader/bootloader.map', dsttmpbl)
+
# copy the application libraries
-
+
shutil.copy(src + '/bootloader_support/libbootloader_support.a', dsttmpapp)
shutil.copy(src + '/bt/libbt.a', dsttmpapp)
shutil.copy(src + '/cxx/libcxx.a', dsttmpapp)
shutil.copy(src + '/driver/libdriver.a', dsttmpapp)
shutil.copy(src + '/esp_adc_cal/libesp_adc_cal.a', dsttmpapp)
shutil.copy(src + '/esp32/libesp32.a', dsttmpapp)
- shutil.copy(src + '/smartconfig_ack/libsmartconfig_ack.a', dsttmpapp)
shutil.copy(src + '/expat/libexpat.a', dsttmpapp)
shutil.copy(src + '/freertos/libfreertos.a', dsttmpapp)
shutil.copy(src + '/heap/libheap.a', dsttmpapp)
@@ -50,7 +64,6 @@ def main():
shutil.copy(src + '/log/liblog.a', dsttmpapp)
shutil.copy(src + '/lwip/liblwip.a', dsttmpapp)
shutil.copy(src + '/mbedtls/libmbedtls.a', dsttmpapp)
- shutil.copy(src + '/micro-ecc/libmicro-ecc.a', dsttmpapp)
shutil.copy(src + '/newlib/libnewlib.a', dsttmpapp)
shutil.copy(src + '/nghttp/libnghttp.a', dsttmpapp)
shutil.copy(src + '/nvs_flash/libnvs_flash.a', dsttmpapp)
@@ -59,33 +72,51 @@ def main():
shutil.copy(src + '/sdmmc/libsdmmc.a', dsttmpapp)
shutil.copy(src + '/soc/libsoc.a', dsttmpapp)
shutil.copy(src + '/spi_flash/libspi_flash.a', dsttmpapp)
+ shutil.copy(src + '/esp_netif/libesp_netif.a', dsttmpapp)
shutil.copy(src + '/tcpip_adapter/libtcpip_adapter.a', dsttmpapp)
shutil.copy(src + '/vfs/libvfs.a', dsttmpapp)
shutil.copy(src + '/wpa_supplicant/libwpa_supplicant.a', dsttmpapp)
- shutil.copy(src + '/xtensa-debug-module/libxtensa-debug-module.a', dsttmpapp)
shutil.copy(src + '/esp_ringbuf/libesp_ringbuf.a', dsttmpapp)
shutil.copy(src + '/coap/libcoap.a', dsttmpapp)
shutil.copy(src + '/mdns/libmdns.a', dsttmpapp)
shutil.copy(src + '/efuse/libefuse.a', dsttmpapp)
shutil.copy(src + '/espcoredump/libespcoredump.a', dsttmpapp)
shutil.copy(src + '/app_update/libapp_update.a', dsttmpapp)
- shutil.copy(src + '/ethernet/libethernet.a', dsttmpapp)
+ # Added with esp-idf 4.x update
+ shutil.copy(src + '/esp_common/libesp_common.a', dsttmpapp)
+ shutil.copy(src + '/esp_event/libesp_event.a', dsttmpapp)
+ shutil.copy(src + '/esp_wifi/libesp_wifi.a', dsttmpapp)
+ shutil.copy(src + '/xtensa/libxtensa.a', dsttmpapp)
+ shutil.copy(src + '/esp_eth/libesp_eth.a', dsttmpapp)
+ shutil.copy(src + '/esp_netif/libesp_netif.a', dsttmpapp)
+ shutil.copy(os.environ['IDF_PATH'] + '/components/bt/controller/lib/libbtdm_app.a', dsttmpapp)
+ shutil.copy(os.environ['IDF_PATH'] + '/components/esp_wifi/lib/esp32/libphy.a', dsttmpapp)
+ shutil.copy(os.environ['IDF_PATH'] + '/components/esp_wifi/lib/esp32/librtc.a', dsttmpapp)
+ shutil.copy(os.environ['IDF_PATH'] + '/components/esp_wifi/lib/esp32/libnet80211.a', dsttmpapp)
+ shutil.copy(os.environ['IDF_PATH'] + '/components/esp_wifi/lib/esp32/libpp.a', dsttmpapp)
+ shutil.copy(os.environ['IDF_PATH'] + '/components/esp_wifi/lib/esp32/libcore.a', dsttmpapp)
+ shutil.copy(os.environ['IDF_PATH'] + '/components/esp_wifi/lib/esp32/libmesh.a', dsttmpapp)
+ shutil.copy(os.environ['IDF_PATH'] + '/components/esp_wifi/lib/esp32/libcoexist.a', dsttmpapp)
+ shutil.copy(os.environ['IDF_PATH'] + '/components/xtensa/esp32/libhal.a', dsttmpapp)
+ shutil.copy(os.environ['IDF_PATH'] + '/components/esp_wifi/lib/esp32/libsmartconfig.a', dsttmpapp)
+ # shutil.copy(src + '/tfmicro/libtfmicro.a', dsttmpapp)
+ shutil.copy(os.environ['IDF_PATH'] + '/components/esp_wifi/lib/esp32/libespnow.a', dsttmpapp)
except:
print("Couldn't Copy IDF libs defaulting to Local Lib Folders!")
traceback.print_exc()
shutil.rmtree(dsttmpbl)
shutil.rmtree(dsttmpapp)
- return
-
+ return False
+
for item in os.listdir(dsttmpbl):
shutil.copy(dsttmpbl+ '/' + item, dstbl + '/' + item)
-
+
for item in os.listdir(dsttmpapp):
shutil.copy(dsttmpapp + '/' + item, dstapp + '/' + item)
-
+
# copy the project's linker script
shutil.copy(src + '/esp32/esp32.project.ld', ".")
-
+
# copy the generated sdkconfig.h
with open(src + '/include/sdkconfig.h', 'r') as input:
content = input.read()
@@ -94,9 +125,13 @@ def main():
shutil.rmtree(dsttmpbl)
shutil.rmtree(dsttmpapp)
-
+
print("IDF Libs, linker script and sdkconfig.h copied successfully!")
-
+ return True
+
if __name__ == "__main__":
- main()
+ if main():
+ exit(0)
+ else:
+ exit(1)
diff --git a/esp32/get_sigfox_libs.py b/esp32/get_sigfox_libs.py
index 92ba7f0375..55aa84992f 100755
--- a/esp32/get_sigfox_libs.py
+++ b/esp32/get_sigfox_libs.py
@@ -11,7 +11,6 @@ def main():
try:
shutil.copy('./build/FIPY/release/sigfox/sigfox.a', './sigfox/modsigfox_FIPY.a')
shutil.copy('./build/LOPY4/release/sigfox/sigfox.a', './sigfox/modsigfox_LOPY4.a')
- shutil.copy('./build/SIPY/release/sigfox/sigfox.a', './sigfox/modsigfox_SIPY.a')
except:
print("Couldn't copy Sigfox libs!")
traceback.print_exc()
diff --git a/esp32/hal/esp32_mphal.c b/esp32/hal/esp32_mphal.c
index cdca99d8b5..d7f8c3a020 100644
--- a/esp32/hal/esp32_mphal.c
+++ b/esp32/hal/esp32_mphal.c
@@ -16,6 +16,7 @@
#include "py/runtime.h"
#include "py/objstr.h"
#include "py/mpstate.h"
+#include "py/stream.h"
#include "esp_heap_caps.h"
#include "sdkconfig.h"
@@ -32,7 +33,7 @@
#include "mpexception.h"
#include "modmachine.h"
#include "updater.h"
-#include "bootloader.h"
+#include "pycom_bootloader.h"
#include "modwlan.h"
#include "modbt.h"
#include "machtimer.h"
@@ -124,6 +125,17 @@ void mp_hal_delay_us(uint32_t us) {
}
}
+STATIC uint8_t stdin_ringbuf_array[256];
+ringbuf_t stdin_ringbuf = {stdin_ringbuf_array, sizeof(stdin_ringbuf_array)};
+
+uintptr_t mp_hal_stdio_poll(uintptr_t poll_flags) {
+ uintptr_t ret = 0;
+ if ((poll_flags & MP_STREAM_POLL_RD) && stdin_ringbuf.iget != stdin_ringbuf.iput) {
+ ret |= MP_STREAM_POLL_RD;
+ }
+ return ret;
+}
+
int mp_hal_stdin_rx_chr(void) {
for ( ; ; ) {
// read telnet first
diff --git a/esp32/hal/esp32_mphal.h b/esp32/hal/esp32_mphal.h
index 8958e391ed..53583559f9 100644
--- a/esp32/hal/esp32_mphal.h
+++ b/esp32/hal/esp32_mphal.h
@@ -10,6 +10,10 @@
#ifndef _INCLUDED_MPHAL_H_
#define _INCLUDED_MPHAL_H_
+#include "py/ringbuf.h"
+
+extern ringbuf_t stdin_ringbuf;
+
#if defined (LOPY) || defined(LOPY4) || defined(FIPY)
void HAL_set_tick_cb (void *cb);
#endif
diff --git a/esp32/lib/libapp_update.a b/esp32/lib/libapp_update.a
index c1276796da..6730aa648c 100644
Binary files a/esp32/lib/libapp_update.a and b/esp32/lib/libapp_update.a differ
diff --git a/esp32/lib/libbootloader_support.a b/esp32/lib/libbootloader_support.a
index 1594abbc85..a53e73d7c0 100644
Binary files a/esp32/lib/libbootloader_support.a and b/esp32/lib/libbootloader_support.a differ
diff --git a/esp32/lib/libbt.a b/esp32/lib/libbt.a
index eac7eba7b3..d78b7335a9 100644
Binary files a/esp32/lib/libbt.a and b/esp32/lib/libbt.a differ
diff --git a/esp32/lib/libbtdm_app.a b/esp32/lib/libbtdm_app.a
new file mode 100644
index 0000000000..930b3a91b0
Binary files /dev/null and b/esp32/lib/libbtdm_app.a differ
diff --git a/esp32/lib/libcoap.a b/esp32/lib/libcoap.a
index 7c995cea40..eb5417b017 100644
Binary files a/esp32/lib/libcoap.a and b/esp32/lib/libcoap.a differ
diff --git a/esp32/lib/libcoexist.a b/esp32/lib/libcoexist.a
new file mode 100644
index 0000000000..10438dcda3
Binary files /dev/null and b/esp32/lib/libcoexist.a differ
diff --git a/esp32/lib/libcore.a b/esp32/lib/libcore.a
new file mode 100644
index 0000000000..72585f6f13
Binary files /dev/null and b/esp32/lib/libcore.a differ
diff --git a/esp32/lib/libcxx.a b/esp32/lib/libcxx.a
index d29dc54e0b..f86ed3d7d5 100644
Binary files a/esp32/lib/libcxx.a and b/esp32/lib/libcxx.a differ
diff --git a/esp32/lib/libdriver.a b/esp32/lib/libdriver.a
index d4608c3a39..a93f7ab724 100644
Binary files a/esp32/lib/libdriver.a and b/esp32/lib/libdriver.a differ
diff --git a/esp32/lib/libefuse.a b/esp32/lib/libefuse.a
index 90fc08d324..4c57d384cc 100644
Binary files a/esp32/lib/libefuse.a and b/esp32/lib/libefuse.a differ
diff --git a/esp32/lib/libesp32.a b/esp32/lib/libesp32.a
index fd107af180..823ffc9646 100644
Binary files a/esp32/lib/libesp32.a and b/esp32/lib/libesp32.a differ
diff --git a/esp32/lib/libesp_adc_cal.a b/esp32/lib/libesp_adc_cal.a
index d3ceede222..2f5aa29215 100644
Binary files a/esp32/lib/libesp_adc_cal.a and b/esp32/lib/libesp_adc_cal.a differ
diff --git a/esp32/lib/libesp_common.a b/esp32/lib/libesp_common.a
new file mode 100644
index 0000000000..3463f4bcbf
Binary files /dev/null and b/esp32/lib/libesp_common.a differ
diff --git a/esp32/lib/libesp_eth.a b/esp32/lib/libesp_eth.a
new file mode 100644
index 0000000000..5074f28de1
Binary files /dev/null and b/esp32/lib/libesp_eth.a differ
diff --git a/esp32/lib/libesp_event.a b/esp32/lib/libesp_event.a
new file mode 100644
index 0000000000..677e303ddb
Binary files /dev/null and b/esp32/lib/libesp_event.a differ
diff --git a/esp32/lib/libesp_netif.a b/esp32/lib/libesp_netif.a
new file mode 100644
index 0000000000..5eb48ae7da
Binary files /dev/null and b/esp32/lib/libesp_netif.a differ
diff --git a/esp32/lib/libesp_ringbuf.a b/esp32/lib/libesp_ringbuf.a
index 77010891aa..162436b056 100644
Binary files a/esp32/lib/libesp_ringbuf.a and b/esp32/lib/libesp_ringbuf.a differ
diff --git a/esp32/lib/libesp_wifi.a b/esp32/lib/libesp_wifi.a
new file mode 100644
index 0000000000..366d1990b3
Binary files /dev/null and b/esp32/lib/libesp_wifi.a differ
diff --git a/esp32/lib/libespcoredump.a b/esp32/lib/libespcoredump.a
index 9647c581da..7aa2a60c34 100644
Binary files a/esp32/lib/libespcoredump.a and b/esp32/lib/libespcoredump.a differ
diff --git a/esp32/lib/libespnow.a b/esp32/lib/libespnow.a
new file mode 100644
index 0000000000..7cf6cdebcf
Binary files /dev/null and b/esp32/lib/libespnow.a differ
diff --git a/esp32/lib/libethernet.a b/esp32/lib/libethernet.a
deleted file mode 100644
index e71f92eb61..0000000000
Binary files a/esp32/lib/libethernet.a and /dev/null differ
diff --git a/esp32/lib/libexpat.a b/esp32/lib/libexpat.a
index 0b497bb02e..9403f6b98a 100644
Binary files a/esp32/lib/libexpat.a and b/esp32/lib/libexpat.a differ
diff --git a/esp32/lib/libfreertos.a b/esp32/lib/libfreertos.a
index cd9a3aba4b..409783a804 100644
Binary files a/esp32/lib/libfreertos.a and b/esp32/lib/libfreertos.a differ
diff --git a/esp32/lib/libhal.a b/esp32/lib/libhal.a
new file mode 100644
index 0000000000..382f4e0ab2
Binary files /dev/null and b/esp32/lib/libhal.a differ
diff --git a/esp32/lib/libheap.a b/esp32/lib/libheap.a
index 001383c764..04fe402856 100644
Binary files a/esp32/lib/libheap.a and b/esp32/lib/libheap.a differ
diff --git a/esp32/lib/libjsmn.a b/esp32/lib/libjsmn.a
index 68768c2cf0..4b32b198fe 100644
Binary files a/esp32/lib/libjsmn.a and b/esp32/lib/libjsmn.a differ
diff --git a/esp32/lib/libjson.a b/esp32/lib/libjson.a
index 37188d324e..d31fc1fabe 100644
Binary files a/esp32/lib/libjson.a and b/esp32/lib/libjson.a differ
diff --git a/esp32/lib/liblog.a b/esp32/lib/liblog.a
index 29326a63b5..b0d2a68394 100644
Binary files a/esp32/lib/liblog.a and b/esp32/lib/liblog.a differ
diff --git a/esp32/lib/liblwip.a b/esp32/lib/liblwip.a
index 47f7e1f34f..6517d4e775 100644
Binary files a/esp32/lib/liblwip.a and b/esp32/lib/liblwip.a differ
diff --git a/esp32/lib/libmbedtls.a b/esp32/lib/libmbedtls.a
index 3b21051436..6dec48dad8 100644
Binary files a/esp32/lib/libmbedtls.a and b/esp32/lib/libmbedtls.a differ
diff --git a/esp32/lib/libmdns.a b/esp32/lib/libmdns.a
index 0a90dd4cd2..cb905c922f 100644
Binary files a/esp32/lib/libmdns.a and b/esp32/lib/libmdns.a differ
diff --git a/esp32/lib/libmesh.a b/esp32/lib/libmesh.a
new file mode 100644
index 0000000000..a1531aa466
Binary files /dev/null and b/esp32/lib/libmesh.a differ
diff --git a/esp32/lib/libmicro-ecc.a b/esp32/lib/libmicro-ecc.a
deleted file mode 100644
index 2e025c3806..0000000000
Binary files a/esp32/lib/libmicro-ecc.a and /dev/null differ
diff --git a/esp32/lib/libnet80211.a b/esp32/lib/libnet80211.a
new file mode 100644
index 0000000000..f4ac5a9b1a
Binary files /dev/null and b/esp32/lib/libnet80211.a differ
diff --git a/esp32/lib/libnewlib.a b/esp32/lib/libnewlib.a
index 2d38cb67ff..1d76c49f0f 100644
Binary files a/esp32/lib/libnewlib.a and b/esp32/lib/libnewlib.a differ
diff --git a/esp32/lib/libnghttp.a b/esp32/lib/libnghttp.a
index c6f1c210f6..8c2873d2b7 100644
Binary files a/esp32/lib/libnghttp.a and b/esp32/lib/libnghttp.a differ
diff --git a/esp32/lib/libnvs_flash.a b/esp32/lib/libnvs_flash.a
index 85d5b40816..dd31e8d7fb 100644
Binary files a/esp32/lib/libnvs_flash.a and b/esp32/lib/libnvs_flash.a differ
diff --git a/esp32/lib/libopenssl.a b/esp32/lib/libopenssl.a
index 940b07af9d..94b1af4a28 100644
Binary files a/esp32/lib/libopenssl.a and b/esp32/lib/libopenssl.a differ
diff --git a/esp32/lib/libphy.a b/esp32/lib/libphy.a
new file mode 100644
index 0000000000..0ea80f8579
Binary files /dev/null and b/esp32/lib/libphy.a differ
diff --git a/esp32/lib/libpp.a b/esp32/lib/libpp.a
new file mode 100644
index 0000000000..9f2f72d864
Binary files /dev/null and b/esp32/lib/libpp.a differ
diff --git a/esp32/lib/libpthread.a b/esp32/lib/libpthread.a
index c03c03d409..23048fcf71 100644
Binary files a/esp32/lib/libpthread.a and b/esp32/lib/libpthread.a differ
diff --git a/esp32/lib/librtc.a b/esp32/lib/librtc.a
new file mode 100644
index 0000000000..f571485b8b
Binary files /dev/null and b/esp32/lib/librtc.a differ
diff --git a/esp32/lib/libsdmmc.a b/esp32/lib/libsdmmc.a
index 182f124efb..c6ae1e4f83 100644
Binary files a/esp32/lib/libsdmmc.a and b/esp32/lib/libsdmmc.a differ
diff --git a/esp32/lib/libsmartconfig.a b/esp32/lib/libsmartconfig.a
new file mode 100644
index 0000000000..3f97477de9
Binary files /dev/null and b/esp32/lib/libsmartconfig.a differ
diff --git a/esp32/lib/libsmartconfig_ack.a b/esp32/lib/libsmartconfig_ack.a
deleted file mode 100644
index e1741be7dc..0000000000
Binary files a/esp32/lib/libsmartconfig_ack.a and /dev/null differ
diff --git a/esp32/lib/libsoc.a b/esp32/lib/libsoc.a
index 6aec8764b3..92a6f88a50 100644
Binary files a/esp32/lib/libsoc.a and b/esp32/lib/libsoc.a differ
diff --git a/esp32/lib/libspi_flash.a b/esp32/lib/libspi_flash.a
index 11847b3b8b..7289716d76 100644
Binary files a/esp32/lib/libspi_flash.a and b/esp32/lib/libspi_flash.a differ
diff --git a/esp32/lib/libtcpip_adapter.a b/esp32/lib/libtcpip_adapter.a
index 763f3f2741..792589fa4e 100644
Binary files a/esp32/lib/libtcpip_adapter.a and b/esp32/lib/libtcpip_adapter.a differ
diff --git a/esp32/lib/libtfmicro.a b/esp32/lib/libtfmicro.a
new file mode 100644
index 0000000000..cb3b260ef5
Binary files /dev/null and b/esp32/lib/libtfmicro.a differ
diff --git a/esp32/lib/libvfs.a b/esp32/lib/libvfs.a
index 3e49b40f6f..c7612c8bfa 100644
Binary files a/esp32/lib/libvfs.a and b/esp32/lib/libvfs.a differ
diff --git a/esp32/lib/libwpa_supplicant.a b/esp32/lib/libwpa_supplicant.a
index 5539f6c461..12c495faac 100644
Binary files a/esp32/lib/libwpa_supplicant.a and b/esp32/lib/libwpa_supplicant.a differ
diff --git a/esp32/lib/libxtensa-debug-module.a b/esp32/lib/libxtensa-debug-module.a
deleted file mode 100644
index 74fde6323f..0000000000
Binary files a/esp32/lib/libxtensa-debug-module.a and /dev/null differ
diff --git a/esp32/lib/libxtensa.a b/esp32/lib/libxtensa.a
new file mode 100644
index 0000000000..a523ee6056
Binary files /dev/null and b/esp32/lib/libxtensa.a differ
diff --git a/esp32/lib/partitions_8MB.csv b/esp32/lib/partitions_8MB.csv
deleted file mode 100644
index e072ef126b..0000000000
--- a/esp32/lib/partitions_8MB.csv
+++ /dev/null
@@ -1,9 +0,0 @@
-# IMPORTANT: Changes need need to be checked against the constants PARTITIONS_COUNT
-# and OTA_DATA_INDEX defined in in bootloader.h
-
-# Name, Type, SubType, Offset, Size
-nvs, data, nvs, 0x9000, 0x7000
-factory, app, factory, 0x10000, 1980k, encrypted
-otadata, data, ota, , 4K, encrypted
-ota_0, app, ota_0, 0x210000, 1980K, encrypted
-config, data, 6, , 4K
diff --git a/esp32/lib/partitions_8MB_normal_factory_fw.csv b/esp32/lib/partitions_8MB_normal_factory_fw.csv
new file mode 100644
index 0000000000..2b6a91be8e
--- /dev/null
+++ b/esp32/lib/partitions_8MB_normal_factory_fw.csv
@@ -0,0 +1,9 @@
+# IMPORTANT: Changes need need to be checked against the constants PARTITIONS_COUNT
+# and OTA_DATA_INDEX defined in in bootloader.h
+
+# Name, Type, SubType, Offset, Size
+nvs, data, nvs, 0x9000, 0x7000
+factory, app, factory, 0x10000, 1980k, encrypted
+otadata, data, ota, , 4K, encrypted
+ota_0, app, ota_0, 0x210000, 1980k, encrypted
+config, data, 6, , 4K
diff --git a/esp32/lib/partitions_8MB_small_factory_fw.csv b/esp32/lib/partitions_8MB_small_factory_fw.csv
new file mode 100644
index 0000000000..9be85a805e
--- /dev/null
+++ b/esp32/lib/partitions_8MB_small_factory_fw.csv
@@ -0,0 +1,9 @@
+# IMPORTANT: Changes need need to be checked against the constants PARTITIONS_COUNT
+# and OTA_DATA_INDEX defined in in bootloader.h
+
+# Name, Type, SubType, Offset, Size
+nvs, data, nvs, 0x9000, 0x7000
+factory, app, factory, 0x10000, 1020k, encrypted
+otadata, data, ota, , 4K, encrypted
+ota_0, app, ota_0, 0x110000, 3004k, encrypted
+config, data, 6, , 4K
diff --git a/esp32/littlefs/sflash_diskio_littlefs.c b/esp32/littlefs/sflash_diskio_littlefs.c
index f386cf47f4..ea61ada52c 100644
--- a/esp32/littlefs/sflash_diskio_littlefs.c
+++ b/esp32/littlefs/sflash_diskio_littlefs.c
@@ -45,7 +45,7 @@ struct lfs_config lfscfg =
.prog_size = SFLASH_BLOCK_SIZE,
.block_size = SFLASH_BLOCK_SIZE,
.block_count = 0, // To be initialized according to the flash size of the chip
- .block_cycles = 0, // No block-level wear-leveling
+ .block_cycles = 100, // Enable block-level wear-leveling
/* Current implementation of littlefs_read/prog/erase/sync() functions only operates with
* full blocks, always the starting address of the block is passed to the driver.
* This helps on the Power-loss resilient behavior of LittleFS, with this approach the File System will not be corrupted by corruption of a single file/block
diff --git a/esp32/littlefs/vfs_littlefs_file.c b/esp32/littlefs/vfs_littlefs_file.c
index aa7a90edb5..84094d4fcc 100644
--- a/esp32/littlefs/vfs_littlefs_file.c
+++ b/esp32/littlefs/vfs_littlefs_file.c
@@ -3,6 +3,7 @@
#include
+#include "py/obj.h"
#include "py/runtime.h"
#include "py/stream.h"
#include "py/mperrno.h"
@@ -20,6 +21,7 @@ typedef struct _pyb_file_obj_t {
vfs_lfs_struct_t* littlefs;
struct lfs_file_config cfg; // Attributes of the file, e.g.: timestamp
bool timestamp_update; // For requesting timestamp update when closing the file
+ bool opened; // Indicate whether the file is opened
} pyb_file_obj_t;
STATIC void file_obj_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
@@ -31,6 +33,12 @@ STATIC mp_uint_t file_obj_read(mp_obj_t self_in, void *buf, mp_uint_t size, int
pyb_file_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ if (self->opened == false) {
+ // Return EINVAL just as FatFS if the file is not opened
+ *errcode = MP_EINVAL;
+ return MP_STREAM_ERROR;
+ }
+
xSemaphoreTake(self->littlefs->mutex, portMAX_DELAY);
lfs_ssize_t sz_out = lfs_file_read(&self->littlefs->lfs ,&self->fp, buf, size);
xSemaphoreGive(self->littlefs->mutex);
@@ -46,6 +54,12 @@ STATIC mp_uint_t file_obj_write(mp_obj_t self_in, const void *buf, mp_uint_t siz
pyb_file_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ if (self->opened == false) {
+ // Return EINVAL just as FatFS if the file is not opened
+ *errcode = MP_EINVAL;
+ return MP_STREAM_ERROR;
+ }
+
xSemaphoreTake(self->littlefs->mutex, portMAX_DELAY);
lfs_ssize_t sz_out = lfs_file_write(&self->littlefs->lfs, &self->fp, buf, size);
// Request timestamp update if file has been written successfully
@@ -89,6 +103,12 @@ STATIC mp_uint_t file_obj_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg,
} else if (request == MP_STREAM_FLUSH) {
+ if (self->opened == false) {
+ // Return EINVAL just as FatFS if the file is not opened
+ *errcode = MP_EINVAL;
+ return MP_STREAM_ERROR;
+ }
+
xSemaphoreTake(self->littlefs->mutex, portMAX_DELAY);
int res = lfs_file_sync(&self->littlefs->lfs, &self->fp);
xSemaphoreGive(self->littlefs->mutex);
@@ -101,16 +121,21 @@ STATIC mp_uint_t file_obj_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg,
} else if (request == MP_STREAM_CLOSE) {
+ if (self->opened == false) {
+ // Return 0 just as FatFs if the file is not opened
+ return 0;
+ }
+
xSemaphoreTake(self->littlefs->mutex, portMAX_DELAY);
int res = littlefs_close_common_helper(&self->littlefs->lfs, &self->fp, &self->cfg, &self->timestamp_update);
xSemaphoreGive(self->littlefs->mutex);
+
if (res < 0) {
*errcode = littleFsErrorToErrno(res);
return MP_STREAM_ERROR;
}
- // Free up the object so GC does not need to do that
- m_del_obj(pyb_file_obj_t, self);
+ self->opened = false; // indicate a closed file
return 0;
} else {
*errcode = MP_EINVAL;
@@ -121,9 +146,9 @@ STATIC mp_uint_t file_obj_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg,
// Note: encoding is ignored for now; it's also not a valid kwarg for CPython's FileIO,
// but by adding it here we can use one single mp_arg_t array for open() and FileIO's constructor
STATIC const mp_arg_t file_open_args[] = {
- { MP_QSTR_file, MP_ARG_OBJ | MP_ARG_REQUIRED, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} },
+ { MP_QSTR_file, MP_ARG_OBJ | MP_ARG_REQUIRED, {.u_obj = mp_const_none} },
{ MP_QSTR_mode, MP_ARG_OBJ, {.u_obj = MP_OBJ_NEW_QSTR(MP_QSTR_r)} },
- { MP_QSTR_encoding, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} },
+ { MP_QSTR_encoding, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = mp_const_none} },
};
#define FILE_OPEN_NUM_ARGS MP_ARRAY_SIZE(file_open_args)
@@ -165,6 +190,7 @@ STATIC mp_obj_t file_open(fs_user_mount_t *vfs, const mp_obj_type_t *type, mp_ar
pyb_file_obj_t *o = m_new_obj_with_finaliser(pyb_file_obj_t);
o->base.type = type;
o->timestamp_update = false;
+ o->opened = false;
xSemaphoreTake(vfs->fs.littlefs.mutex, portMAX_DELAY);
const char *fname = concat_with_cwd(&vfs->fs.littlefs, mp_obj_str_get_str(args[0].u_obj));
@@ -178,6 +204,7 @@ STATIC mp_obj_t file_open(fs_user_mount_t *vfs, const mp_obj_type_t *type, mp_ar
}
o->littlefs = &vfs->fs.littlefs;
+ o->opened = true; // File is opened successfully
return MP_OBJ_FROM_PTR(o);
}
diff --git a/esp32/lora/board.c b/esp32/lora/board.c
index 7a6c7f1bd9..470b9da6fa 100644
--- a/esp32/lora/board.c
+++ b/esp32/lora/board.c
@@ -30,6 +30,8 @@ Maintainer: Miguel Luis and Gregory Cristian
#include "board.h"
#include "random.h"
+#include "rtc-board.h"
+
/*!
* Flag to indicate if the MCU is Initialized
*/
@@ -53,7 +55,7 @@ void BoardInitMcu( void )
SX1276IoInit( );
#endif
- TimerHwInit( );
+ RtcInit( );
McuInitialized = true;
}
diff --git a/esp32/lora/board.h b/esp32/lora/board.h
index fc4829f8b5..8dd8bd6151 100644
--- a/esp32/lora/board.h
+++ b/esp32/lora/board.h
@@ -72,6 +72,19 @@ Maintainer: Miguel Luis and Gregory Cristian
#define RADIO_NSS micropy_lpwan_ncs_pin_index
#define RADIO_DIO micropy_lpwan_dio_pin_index
+
+#define LPWAN_NCS_PIN_NUMBER (18)
+#define LPWAN_NCS_PIN (&pin_GPIO18)
+#endif
+
+#if defined (WIPY)
+#define LPWAN_NCS_PIN_NUMBER (18)
+#define LPWAN_NCS_PIN (&pin_GPIO18)
+#endif
+
+#if defined (GPY)
+#define LPWAN_NCS_PIN_NUMBER (18)
+#define LPWAN_NCS_PIN (&pin_GPIO18)
#endif
void BoardInitPeriph( void );
diff --git a/esp32/lora/rtc-board.c b/esp32/lora/rtc-board.c
new file mode 100644
index 0000000000..8f1ef5ef5d
--- /dev/null
+++ b/esp32/lora/rtc-board.c
@@ -0,0 +1,262 @@
+/*
+ * This file is derived from the MicroPython project, http://micropython.org/
+ *
+ * Copyright (c) 2020, Pycom Limited and its licensors.
+ *
+ * This software is licensed under the GNU GPL version 3 or any later version,
+ * with permitted additional terms. For more information see the Pycom Licence
+ * v1.0 document supplied with this file, or available at:
+ * https://www.pycom.io/opensource/licensing
+ *
+ * This file contains code under the following copyright and licensing notices.
+ * The code has been changed but otherwise retained.
+ */
+
+/*!
+ * \file rtc-board.c
+ *
+ * \brief Target board RTC timer and low power modes management
+ *
+ * \copyright Revised BSD License, see section \ref LICENSE.
+ *
+ * \code
+ * ______ _
+ * / _____) _ | |
+ * ( (____ _____ ____ _| |_ _____ ____| |__
+ * \____ \| ___ | (_ _) ___ |/ ___) _ \
+ * _____) ) ____| | | || |_| ____( (___| | | |
+ * (______/|_____)_|_|_| \__)_____)\____)_| |_|
+ * (C)2013-2017 Semtech
+ *
+ * \endcode
+ *
+ * \author Miguel Luis ( Semtech )
+ *
+ * \author Gregory Cristian ( Semtech )
+ *
+ * \author Marten Lootsma(TWTG) on behalf of Microchip/Atmel (c)2017
+ */
+
+#include "lora/system/timer.h"
+#include "lora/system/systime.h"
+#include "gpio.h"
+#include "board.h"
+
+#include "rtc-board.h"
+
+#include "py/mphal.h"
+
+
+/*!
+ * Hardware Time base in ms
+ */
+#define HW_TIMER_TIME_BASE 1 // ms
+
+/*!
+ * Hardware Timer tick counter
+ */
+DRAM_ATTR volatile TimerTime_t RTCTimerTickCounter = 1;
+
+/*!
+ * Value trigging the IRQ
+ */
+DRAM_ATTR volatile TimerTime_t RTCTimeoutCntValue = 0;
+
+
+#define MIN_ALARM_DELAY 1 // in ticks
+
+/*!
+ * \brief Indicates if the RTC is already Initialized or not
+ */
+static bool RtcInitialized = false;
+
+typedef enum AlarmStates_e
+{
+ ALARM_STOPPED = 0,
+ ALARM_RUNNING = !ALARM_STOPPED
+} AlarmStates_t;
+
+/*!
+ * RTC timer context
+ */
+typedef struct
+{
+ uint32_t Time; // Reference time
+ uint32_t Delay; // Reference Timeout duration
+ uint32_t AlarmState;
+}RtcTimerContext_t;
+
+/*!
+ * Keep the value of the RTC timer when the RTC alarm is set
+ * Set with the \ref RtcSetTimerContext function
+ * Value is kept as a Reference to calculate alarm
+ */
+static RtcTimerContext_t RtcTimerContext;
+
+/*!
+ * Used to store the Seconds and SubSeconds.
+ *
+ * WARNING: Temporary fix fix. Should use MCU NVM internal
+ * registers
+ */
+uint32_t RtcBkupRegisters[] = { 0, 0 };
+
+/*!
+ * \brief Callback for the hw_timer when alarm expired
+ */
+static void RtcAlarmIrq( void );
+
+/*!
+ * \brief Callback for the hw_timer when counter overflows
+ */
+#define TIMEOUT_WINDOW (1000*60) //60sec
+static IRAM_ATTR void TimerTickCallback (void) {
+ RTCTimerTickCounter++;
+ if ((RtcTimerContext.AlarmState == ALARM_RUNNING) &&
+ (TIMEOUT_WINDOW > (RTCTimerTickCounter-RTCTimeoutCntValue))) {
+ RtcAlarmIrq();
+ }
+}
+
+IRAM_ATTR void TimerTickAdjust(uint32_t offset_ms) {
+ RTCTimerTickCounter += offset_ms;
+}
+
+void RtcInit( void )
+{
+ if( RtcInitialized == false )
+ {
+ // RTC timer
+ CRITICAL_SECTION_BEGIN( );
+ HAL_set_tick_cb(TimerTickCallback);
+ CRITICAL_SECTION_END( );
+
+ RtcTimerContext.AlarmState = ALARM_STOPPED;
+ RtcSetTimerContext( );
+ RtcInitialized = true;
+ }
+}
+
+IRAM_ATTR uint32_t RtcSetTimerContext( void )
+{
+ RtcTimerContext.Time = ( uint32_t )RTCTimerTickCounter;
+ return ( uint32_t )RtcTimerContext.Time;
+}
+
+IRAM_ATTR uint32_t RtcGetTimerContext( void )
+{
+ return RtcTimerContext.Time;
+}
+
+IRAM_ATTR uint32_t RtcGetMinimumTimeout( void )
+{
+ return( MIN_ALARM_DELAY );
+}
+
+IRAM_ATTR uint32_t RtcMs2Tick( TimerTime_t milliseconds )
+{
+ return ( uint32_t )( milliseconds );
+}
+
+TimerTime_t RtcTick2Ms( uint32_t tick )
+{
+ return ( TimerTime_t ) ( tick );
+}
+
+void RtcDelayMs( TimerTime_t milliseconds )
+{
+ vTaskDelay (milliseconds / portTICK_PERIOD_MS);
+}
+
+IRAM_ATTR void RtcSetAlarm( uint32_t timeout )
+{
+ RtcStartAlarm( timeout );
+}
+
+IRAM_ATTR void RtcStopAlarm( void )
+{
+ RtcTimerContext.AlarmState = ALARM_STOPPED;
+}
+
+IRAM_ATTR void RtcStartAlarm( uint32_t timeout )
+{
+ CRITICAL_SECTION_BEGIN( );
+
+ RtcStopAlarm( );
+
+ RtcTimerContext.Delay = timeout;
+ RtcTimerContext.Time = RTCTimerTickCounter;
+
+ if(timeout <= MIN_ALARM_DELAY) {
+ RTCTimeoutCntValue = RTCTimerTickCounter + MIN_ALARM_DELAY;
+ } else {
+ RTCTimeoutCntValue = RTCTimerTickCounter + timeout;
+ }
+
+ RtcTimerContext.AlarmState = ALARM_RUNNING;
+
+ CRITICAL_SECTION_END( );
+}
+
+uint32_t RtcGetTimerValue( void )
+{
+ return ( uint32_t )RTCTimerTickCounter;
+}
+
+IRAM_ATTR uint32_t RtcGetTimerElapsedTime( void )
+{
+ return ( uint32_t)( RTCTimerTickCounter - RtcTimerContext.Time );
+}
+
+uint32_t RtcGetCalendarTime( uint16_t *milliseconds )
+{
+ uint32_t calendarValue = mp_hal_ticks_ms();
+
+ uint32_t seconds = ( uint32_t )calendarValue / 1000;
+
+ *milliseconds = ( uint32_t ) ( calendarValue - seconds * 1000);
+
+ return seconds;
+}
+
+void RtcBkupWrite( uint32_t data0, uint32_t data1 )
+{
+ CRITICAL_SECTION_BEGIN( );
+ RtcBkupRegisters[0] = data0;
+ RtcBkupRegisters[1] = data1;
+ CRITICAL_SECTION_END( );
+}
+
+void RtcBkupRead( uint32_t* data0, uint32_t* data1 )
+{
+ CRITICAL_SECTION_BEGIN( );
+ *data0 = RtcBkupRegisters[0];
+ *data1 = RtcBkupRegisters[1];
+ CRITICAL_SECTION_END( );
+}
+
+void RtcProcess( void )
+{
+
+}
+
+TimerTime_t RtcTempCompensation( TimerTime_t period, float temperature )
+{
+ return period;
+}
+
+static IRAM_ATTR void RtcAlarmIrq( void )
+{
+ RtcTimerContext.AlarmState = ALARM_STOPPED;
+
+ // NOTE: The handler should take less then 1 ms otherwise the clock shifts
+ TimerIrqHandler( );
+}
+
+IRAM_ATTR uint32_t RtcRemaingMs(void)
+{
+ if (RtcTimerContext.AlarmState == ALARM_STOPPED) {
+ return 0xFFFFFFFF;
+ }
+ return RTCTimeoutCntValue-RTCTimerTickCounter;
+}
\ No newline at end of file
diff --git a/esp32/lora/rtc-board.h b/esp32/lora/rtc-board.h
new file mode 100644
index 0000000000..f7534e6a86
--- /dev/null
+++ b/esp32/lora/rtc-board.h
@@ -0,0 +1,195 @@
+/*!
+ * \file rtc-board.h
+ *
+ * \brief Target board RTC timer and low power modes management
+ *
+ * \copyright Revised BSD License, see section \ref LICENSE.
+ *
+ * \code
+ * ______ _
+ * / _____) _ | |
+ * ( (____ _____ ____ _| |_ _____ ____| |__
+ * \____ \| ___ | (_ _) ___ |/ ___) _ \
+ * _____) ) ____| | | || |_| ____( (___| | | |
+ * (______/|_____)_|_|_| \__)_____)\____)_| |_|
+ * (C)2013-2017 Semtech
+ *
+ * \endcode
+ *
+ * \author Miguel Luis ( Semtech )
+ *
+ * \author Gregory Cristian ( Semtech )
+ */
+#ifndef __RTC_BOARD_H__
+#define __RTC_BOARD_H__
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include
+#include
+#include "lora/system/timer.h"
+
+/*!
+ * \brief Initializes the RTC timer
+ *
+ * \remark The timer is based on the RTC
+ */
+void RtcInit( void );
+
+/*!
+ * \brief Returns the minimum timeout value
+ *
+ * \retval minTimeout Minimum timeout value in in ticks
+ */
+uint32_t RtcGetMinimumTimeout( void );
+
+/*!
+ * \brief converts time in ms to time in ticks
+ *
+ * \param[IN] milliseconds Time in milliseconds
+ * \retval returns time in timer ticks
+ */
+uint32_t RtcMs2Tick( TimerTime_t milliseconds );
+
+/*!
+ * \brief converts time in ticks to time in ms
+ *
+ * \param[IN] time in timer ticks
+ * \retval returns time in milliseconds
+ */
+TimerTime_t RtcTick2Ms( uint32_t tick );
+
+/*!
+ * \brief Performs a delay of milliseconds by polling RTC
+ *
+ * \param[IN] milliseconds Delay in ms
+ */
+void RtcDelayMs( TimerTime_t milliseconds );
+
+/*!
+ * \brief Calculates the wake up time between wake up and MCU start
+ *
+ * \note Resolution in RTC_ALARM_TIME_BASE
+ */
+void RtcSetMcuWakeUpTime( void );
+
+/*!
+ * \brief Returns the wake up time in ticks
+ *
+ * \retval wakeUpTime The WakeUpTime value in ticks
+ */
+int16_t RtcGetMcuWakeUpTime( void );
+
+/*!
+ * \brief Sets the alarm
+ *
+ * \note The alarm is set at now (read in this funtion) + timeout
+ *
+ * \param timeout [IN] Duration of the Timer ticks
+ */
+void RtcSetAlarm( uint32_t timeout );
+
+/*!
+ * \brief Stops the Alarm
+ */
+void RtcStopAlarm( void );
+
+/*!
+ * \brief Starts wake up alarm
+ *
+ * \note Alarm in RtcTimerContext.Time + timeout
+ *
+ * \param [IN] timeout Timeout value in ticks
+ */
+void RtcStartAlarm( uint32_t timeout );
+
+/*!
+ * \brief Sets the RTC timer reference
+ *
+ * \retval value Timer reference value in ticks
+ */
+uint32_t RtcSetTimerContext( void );
+
+/*!
+ * \brief Gets the RTC timer reference
+ *
+ * \retval value Timer value in ticks
+ */
+uint32_t RtcGetTimerContext( void );
+
+/*!
+ * \brief Gets the system time with the number of seconds elapsed since epoch
+ *
+ * \param [OUT] milliseconds Number of milliseconds elapsed since epoch
+ * \retval seconds Number of seconds elapsed since epoch
+ */
+uint32_t RtcGetCalendarTime( uint16_t *milliseconds );
+
+/*!
+ * \brief Get the RTC timer value
+ *
+ * \retval RTC Timer value
+ */
+uint32_t RtcGetTimerValue( void );
+
+/*!
+ * \brief Get the RTC timer elapsed time since the last Alarm was set
+ *
+ * \retval RTC Elapsed time since the last alarm in ticks.
+ */
+uint32_t RtcGetTimerElapsedTime( void );
+
+/*!
+ * \brief Writes data0 and data1 to the RTC backup registers
+ *
+ * \param [IN] data0 1st Data to be written
+ * \param [IN] data1 2nd Data to be written
+ */
+void RtcBkupWrite( uint32_t data0, uint32_t data1 );
+
+/*!
+ * \brief Reads data0 and data1 from the RTC backup registers
+ *
+ * \param [OUT] data0 1st Data to be read
+ * \param [OUT] data1 2nd Data to be read
+ */
+void RtcBkupRead( uint32_t* data0, uint32_t* data1 );
+
+/*!
+ * \brief Processes pending timer events
+ */
+void RtcProcess( void );
+
+/*!
+ * \brief Computes the temperature compensation for a period of time on a
+ * specific temperature.
+ *
+ * \param [IN] period Time period to compensate in milliseconds
+ * \param [IN] temperature Current temperature
+ *
+ * \retval Compensated time period
+ */
+TimerTime_t RtcTempCompensation( TimerTime_t period, float temperature );
+
+/*!
+ * \brief Compensate for the time spent sleeping
+ *
+ * \param [IN] offset_ms is the time in ms spent in sleep mode
+ */
+void TimerTickAdjust(uint32_t offset_ms);
+
+/*!
+ * \brief Returns the time remaining until next alarm
+ *
+ * \param [OUT] the time in ms or 0xFFFFFFFF if no alarm
+ */
+uint32_t RtcRemaingMs(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // __RTC_BOARD_H__
diff --git a/esp32/lora/spi-board.c b/esp32/lora/spi-board.c
index 27a7b6330a..2e2bd0ccc7 100644
--- a/esp32/lora/spi-board.c
+++ b/esp32/lora/spi-board.c
@@ -78,8 +78,8 @@ void SpiInit( Spi_t *obj, PinNames mosi, PinNames miso, PinNames sclk, PinNames
obj->Spi = (void *)SPIDEV;
// this is SpiNum_SPI3
- DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG,DPORT_SPI_CLK_EN_2);
- DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG,DPORT_SPI_RST_2);
+ DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG,DPORT_SPI3_CLK_EN);
+ DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG,DPORT_SPI3_RST);
#if defined (SIPY)
// configure the SPI port
@@ -87,7 +87,7 @@ void SpiInit( Spi_t *obj, PinNames mosi, PinNames miso, PinNames sclk, PinNames
.bitOrder = SpiBitOrder_MSBFirst, .halfMode = SpiWorkMode_Full};
#else
// configure the SPI port
- spi_attr_t spi_attr = {.mode = SpiMode_Master, .subMode = SpiSubMode_0, .speed = SpiSpeed_10MHz,
+ spi_attr_t spi_attr = {.mode = SpiMode_Master, .subMode = SpiSubMode_0, .speed = SpiSpeed_10MHz+1,
.bitOrder = SpiBitOrder_MSBFirst, .halfMode = SpiWorkMode_Full};
#endif
spi_init((uint32_t)obj->Spi, &spi_attr);
@@ -101,12 +101,18 @@ void SpiInit( Spi_t *obj, PinNames mosi, PinNames miso, PinNames sclk, PinNames
CLEAR_PERI_REG_MASK(SPI_USER_REG((uint32_t)obj->Spi), SPI_USR_ADDR);
SET_PERI_REG_BITS(SPI_USER1_REG((uint32_t)obj->Spi), SPI_USR_ADDR_BITLEN,0, SPI_USR_ADDR_BITLEN_S);
+ //clear CS HOLD
+ CLEAR_PERI_REG_MASK(SPI_USER_REG((uint32_t)obj->Spi), SPI_CS_HOLD);
+
+ // set no wait to nCS deassert - reserved
+ CLEAR_PERI_REG_MASK(SPI_CTRL1_REG((uint32_t)obj->Spi), 0xF0000000);
+
// enable MOSI
SET_PERI_REG_MASK(SPI_USER_REG((uint32_t)obj->Spi), SPI_USR_MOSI);
// set the data send buffer length. The max data length 64 bytes.
- SET_PERI_REG_BITS(SPI_MOSI_DLEN_REG((uint32_t)obj->Spi), SPI_USR_MOSI_DBITLEN, 7, SPI_USR_MOSI_DBITLEN_S);
- SET_PERI_REG_BITS(SPI_MISO_DLEN_REG((uint32_t)obj->Spi), SPI_USR_MISO_DBITLEN, 7, SPI_USR_MISO_DBITLEN_S);
+ SET_PERI_REG_BITS(SPI_MOSI_DLEN_REG((uint32_t)obj->Spi), SPI_USR_MOSI_DBITLEN, 15, SPI_USR_MOSI_DBITLEN_S);
+ SET_PERI_REG_BITS(SPI_MISO_DLEN_REG((uint32_t)obj->Spi), SPI_USR_MISO_DBITLEN, 15, SPI_USR_MISO_DBITLEN_S);
// assign the SPI pins to the GPIO matrix and configure the AF
pin_config(obj->Miso.pin_obj, VSPIQ_IN_IDX, -1, GPIO_MODE_INPUT, PIN_NO_PULL, 0);
@@ -165,7 +171,7 @@ void SpiFrequency( Spi_t *obj, uint32_t hz ) {
IRAM_ATTR uint16_t SpiInOut(Spi_t *obj, uint16_t outData) {
uint32_t spiNum = (uint32_t)obj->Spi;
-#if defined(FIPY) || defined(LOPY4)
+#if defined(FIPY) || defined(LOPY4) || defined(LOPY)
// set data send buffer length (1 byte)
SET_PERI_REG_BITS(SPI_MOSI_DLEN_REG(spiNum), SPI_USR_MOSI_DBITLEN, 7, SPI_USR_MOSI_DBITLEN_S);
SET_PERI_REG_BITS(SPI_MISO_DLEN_REG(spiNum), SPI_USR_MISO_DBITLEN, 7, SPI_USR_MISO_DBITLEN_S);
@@ -206,10 +212,6 @@ IRAM_ATTR uint8_t SpiInOut(uint32_t spiNum, uint32_t outData) {
* \retval void
*/
IRAM_ATTR void SpiOut(uint32_t spiNum, uint32_t outData) {
- // set data send buffer length (2 bytes)
- SET_PERI_REG_BITS(SPI_MOSI_DLEN_REG(spiNum), SPI_USR_MOSI_DBITLEN, 15, SPI_USR_MOSI_DBITLEN_S);
- SET_PERI_REG_BITS(SPI_MISO_DLEN_REG(spiNum), SPI_USR_MISO_DBITLEN, 15, SPI_USR_MISO_DBITLEN_S);
-
// load send buffer
WRITE_PERI_REG(SPI_W0_REG(spiNum), outData);
WRITE_PERI_REG(SPI_W0_REG(spiNum) + 4, outData >> 8); // the SPI FIFO is 4-byte wide
@@ -219,3 +221,129 @@ IRAM_ATTR void SpiOut(uint32_t spiNum, uint32_t outData) {
while (READ_PERI_REG(SPI_CMD_REG(spiNum)) & SPI_USR);
}
#endif
+
+IRAM_ATTR void SpiIn0Out16(Spi_t *obj, uint16_t outData) {
+ uint32_t spiNum = (uint32_t)obj->Spi;
+ // load the send buffer
+ WRITE_PERI_REG(SPI_W0_REG(spiNum), outData);
+ // start to send data
+ WRITE_PERI_REG(SPI_CMD_REG(spiNum), SPI_USR);
+ // wait transfer complete
+ while (READ_PERI_REG(SPI_CMD_REG(spiNum)) & SPI_USR);
+}
+
+IRAM_ATTR uint8_t SpiIn8Out16(Spi_t *obj, uint16_t outData) {
+ uint32_t spiNum = (uint32_t)obj->Spi;
+ // load the send buffer
+ WRITE_PERI_REG(SPI_W0_REG(spiNum), outData);
+ // start to send data
+ SET_PERI_REG_MASK(SPI_CMD_REG(spiNum), SPI_USR);
+ // wait transfer complete
+ while (READ_PERI_REG(SPI_CMD_REG(spiNum)) & SPI_USR);
+ // read data out
+ return (READ_PERI_REG(SPI_W0_REG(spiNum))>>8);
+}
+
+IRAM_ATTR void SpiInBuf(Spi_t *obj, uint8_t* pData, uint8_t len) {
+ uint8_t bytes;
+ uint32_t spiNum = (uint32_t)obj->Spi;
+
+ while(len&0xFC) {
+ if (len>64) {
+ bytes = 64;
+ }
+ else {
+ bytes = len&0xFC;
+ }
+ // set transfer size in bits
+ SET_PERI_REG_BITS(SPI_MOSI_DLEN_REG(spiNum), SPI_USR_MOSI_DBITLEN, 8*bytes-1, SPI_USR_MOSI_DBITLEN_S);
+ SET_PERI_REG_BITS(SPI_MISO_DLEN_REG(spiNum), SPI_USR_MISO_DBITLEN, 8*bytes-1, SPI_USR_MISO_DBITLEN_S);
+ // start to get data
+ SET_PERI_REG_MASK(SPI_CMD_REG(spiNum), SPI_USR);
+ // do side operations
+ len -= bytes;
+ // wait transfer complete
+ while (READ_PERI_REG(SPI_CMD_REG(spiNum)) & SPI_USR);
+ // read data out
+ if(1)
+ {
+ uint8_t index;
+ for (index = 0; index0) {
+ // set transfer size in bits
+ SET_PERI_REG_BITS(SPI_MOSI_DLEN_REG(spiNum), SPI_USR_MOSI_DBITLEN, 8*len-1, SPI_USR_MOSI_DBITLEN_S);
+ SET_PERI_REG_BITS(SPI_MISO_DLEN_REG(spiNum), SPI_USR_MISO_DBITLEN, 8*len-1, SPI_USR_MISO_DBITLEN_S);
+ // start to get data
+ SET_PERI_REG_MASK(SPI_CMD_REG(spiNum), SPI_USR);
+ // wait transfer complete
+ while (READ_PERI_REG(SPI_CMD_REG(spiNum)) & SPI_USR);
+ // read data out
+ if(1)
+ {
+ uint32_t data = READ_PERI_REG(SPI_W0_REG(spiNum));
+ while (len--) {
+ *pData = data&0xFF;
+ pData++;
+ data = data>>8;
+ }
+ }
+ }
+ // set data send buffer length to default (2 bytes)
+ SET_PERI_REG_BITS(SPI_MOSI_DLEN_REG(spiNum), SPI_USR_MOSI_DBITLEN, 15, SPI_USR_MOSI_DBITLEN_S);
+ SET_PERI_REG_BITS(SPI_MISO_DLEN_REG(spiNum), SPI_USR_MISO_DBITLEN, 15, SPI_USR_MISO_DBITLEN_S);
+}
+
+IRAM_ATTR void SpiOutBuf(Spi_t *obj, uint8_t* pData, uint8_t len) {
+ uint8_t bytes;
+ uint32_t spiNum = (uint32_t)obj->Spi;
+
+ bytes = len&0x03;
+ if (bytes>0) {
+ // set transfer size in bits
+ SET_PERI_REG_BITS(SPI_MOSI_DLEN_REG(spiNum), SPI_USR_MOSI_DBITLEN, 8*bytes-1, SPI_USR_MOSI_DBITLEN_S);
+ SET_PERI_REG_BITS(SPI_MISO_DLEN_REG(spiNum), SPI_USR_MISO_DBITLEN, 8*bytes-1, SPI_USR_MISO_DBITLEN_S);
+ // write data
+ WRITE_PERI_REG(SPI_W0_REG(spiNum), *(uint32_t*)pData);
+ // start to send data
+ SET_PERI_REG_MASK(SPI_CMD_REG(spiNum), SPI_USR);
+ // do side operations
+ len -= bytes;
+ pData += bytes;
+ // wait transfer complete
+ while (READ_PERI_REG(SPI_CMD_REG(spiNum)) & SPI_USR);
+ }
+ while(len) {
+ if (len>64) {
+ bytes = 64;
+ }
+ else {
+ bytes = len;
+ }
+ // set transfer size in bits
+ SET_PERI_REG_BITS(SPI_MOSI_DLEN_REG(spiNum), SPI_USR_MOSI_DBITLEN, 8*bytes-1, SPI_USR_MOSI_DBITLEN_S);
+ SET_PERI_REG_BITS(SPI_MISO_DLEN_REG(spiNum), SPI_USR_MISO_DBITLEN, 8*bytes-1, SPI_USR_MISO_DBITLEN_S);
+ // write data
+ if(1)
+ {
+ uint8_t index;
+ for (index = 0; index
+#include
+#include "sx1272/sx1272.h"
/*!
* \brief Radio hardware registers initialization definition
@@ -60,6 +77,21 @@ void SX1272IoIrqInit( DioIrqHandler **irqHandlers );
*/
void SX1272IoDeInit( void );
+/*!
+ * \brief Initializes the TCXO power pin.
+ */
+void SX1272IoTcxoInit( void );
+
+/*!
+ * \brief Initializes the radio debug pins.
+ */
+void SX1272IoDbgInit( void );
+
+/*!
+ * \brief Resets the radio
+ */
+void SX1272Reset( void );
+
/*!
* \brief Sets the radio output power.
*
@@ -68,12 +100,32 @@ void SX1272IoDeInit( void );
void SX1272SetRfTxPower( int8_t power );
/*!
- * \brief Gets the board PA selection configuration
+ * \brief Set the RF Switch I/Os pins in low power mode
*
- * \param [IN] channel Channel frequency in Hz
- * \retval PaSelect RegPaConfig PaSelect value
+ * \param [IN] status enable or disable
*/
-uint8_t SX1272GetPaSelect( uint32_t channel );
+void SX1272SetAntSwLowPower( bool status );
+
+/*!
+ * \brief Initializes the RF Switch I/Os pins interface
+ */
+void SX1272AntSwInit( void );
+
+/*!
+ * \brief De-initializes the RF Switch I/Os pins interface
+ *
+ * \remark Needed to decrease the power consumption in MCU low power modes
+ */
+void SX1272AntSwDeInit( void );
+
+/*!
+ * \brief Controls the antenna switch if necessary.
+ *
+ * \remark see errata note
+ *
+ * \param [IN] opMode Current radio operating mode
+ */
+void SX1272SetAntSw( uint8_t opMode );
/*!
* \brief Checks if the given RF frequency is supported by the hardware
@@ -83,9 +135,41 @@ uint8_t SX1272GetPaSelect( uint32_t channel );
*/
bool SX1272CheckRfFrequency( uint32_t frequency );
+/*!
+ * \brief Enables/disables the TCXO if available on board design.
+ *
+ * \param [IN] state TCXO enabled when true and disabled when false.
+ */
+void SX1272SetBoardTcxo( uint8_t state );
+
+/*!
+ * \brief Gets the Defines the time required for the TCXO to wakeup [ms].
+ *
+ * \retval time Board TCXO wakeup time in ms.
+ */
+uint32_t SX1272GetBoardTcxoWakeupTime( void );
+
+/*!
+ * \brief Writes new Tx debug pin state
+ *
+ * \param [IN] state Debug pin state
+ */
+void SX1272DbgPinTxWrite( uint8_t state );
+
+/*!
+ * \brief Writes new Rx debug pin state
+ *
+ * \param [IN] state Debug pin state
+ */
+void SX1272DbgPinRxWrite( uint8_t state );
+
/*!
* Radio hardware and global parameters
*/
extern SX1272_t SX1272;
-#endif // __SX1272_ARCH_H__
+#ifdef __cplusplus
+}
+#endif
+
+#endif // __SX1272_BOARD_H__
diff --git a/esp32/lora/sx1276-board.c b/esp32/lora/sx1276-board.c
index 9bee40d23a..d0fec4442b 100755
--- a/esp32/lora/sx1276-board.c
+++ b/esp32/lora/sx1276-board.c
@@ -22,6 +22,18 @@ Maintainer: Miguel Luis and Gregory Cristian
#include "sx1276/sx1276.h"
#include "sx1276-board.h"
+static uint8_t SX1276GetPaSelect( uint32_t channel )
+{
+ if( channel >= RF_MID_BAND_THRESH )
+ {
+ return RF_PACONFIG_PASELECT_PABOOST;
+ }
+ else
+ {
+ return RF_PACONFIG_PASELECT_RFO;
+ }
+}
+
/*!
* Radio driver structure initialization
*/
@@ -50,7 +62,12 @@ DRAM_ATTR const struct Radio_s Radio =
SX1276WriteBuffer,
SX1276ReadBuffer,
SX1276SetMaxPayloadLength,
- SX1276SetPublicNetwork
+ SX1276SetPublicNetwork,
+ SX1276Reset, // void ( *Reset )( void )
+ SX1276GetWakeupTime, // uint32_t ( *GetWakeupTime )( void )
+ NULL, // void ( *IrqProcess )( void )
+ NULL, // void ( *RxBoosted )( uint32_t timeout )
+ NULL // void ( *SetRxDutyCycle ) ( uint32_t rxTime, uint32_t sleepTime )
};
/*!
@@ -73,6 +90,35 @@ void SX1276IoDeInit( void )
GpioInit( &SX1276.DIO, RADIO_DIO, PIN_INPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 );
}
+void SX1276IoTcxoInit( void )
+{
+ // Not supported
+}
+
+void SX1276IoDbgInit( void )
+{
+ // Not supported
+}
+
+void SX1276Reset( void )
+{
+ if (micropy_lpwan_use_reset_pin) {
+ // Set RESET pin to 0
+ GpioInit( &SX1276.Reset, RADIO_RESET, PIN_OUTPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 );
+
+ // Wait 2 ms
+ DelayMs( 2 );
+
+ // Configure RESET as input
+ GpioInit( &SX1276.Reset, RADIO_RESET, PIN_INPUT, PIN_PUSH_PULL, PIN_NO_PULL, 1 );
+
+ // Wait 6 ms
+ DelayMs( 6 );
+ } else {
+ DelayMs( 2 );
+ }
+}
+
void SX1276SetRfTxPower( int8_t power )
{
uint8_t paConfig = 0;
@@ -135,16 +181,24 @@ void SX1276SetRfTxPower( int8_t power )
SX1276Write( REG_PADAC, paDac );
}
-uint8_t SX1276GetPaSelect( uint32_t channel )
+void SX1276SetAntSwLowPower( bool status )
{
- if( channel >= RF_MID_BAND_THRESH )
- {
- return RF_PACONFIG_PASELECT_PABOOST;
- }
- else
- {
- return RF_PACONFIG_PASELECT_RFO;
- }
+ // No antenna switch available.
+}
+
+void SX1276AntSwInit( void )
+{
+ // No antenna switch available.
+}
+
+void SX1276AntSwDeInit( void )
+{
+ // No antenna switch available.
+}
+
+void SX1276SetAntSw( uint8_t opMode )
+{
+ // No antenna switch available.
}
bool SX1276CheckRfFrequency( uint32_t frequency )
@@ -153,4 +207,24 @@ bool SX1276CheckRfFrequency( uint32_t frequency )
return true;
}
+void SX1276SetBoardTcxo( uint8_t state )
+{
+ // Not supported
+}
+
+uint32_t SX1276GetBoardTcxoWakeupTime( void )
+{
+ return 5; // TODO: Returning a random number for now
+}
+
+void SX1276DbgPinTxWrite( uint8_t state )
+{
+ // Not supported
+}
+
+void SX1276DbgPinRxWrite( uint8_t state )
+{
+ // Not supported
+}
+
#endif
diff --git a/esp32/lora/sx1276-board.h b/esp32/lora/sx1276-board.h
old mode 100755
new mode 100644
index cd82ad4bff..2386756204
--- a/esp32/lora/sx1276-board.h
+++ b/esp32/lora/sx1276-board.h
@@ -1,19 +1,36 @@
-/*
- / _____) _ | |
-( (____ _____ ____ _| |_ _____ ____| |__
- \____ \| ___ | (_ _) ___ |/ ___) _ \
- _____) ) ____| | | || |_| ____( (___| | | |
-(______/|_____)_|_|_| \__)_____)\____)_| |_|
- (C)2013 Semtech
-
-Description: SX1276 driver specific target board functions implementation
+/*!
+ * \file sx1276-board.h
+ *
+ * \brief Target board SX1276 driver implementation
+ *
+ * \copyright Revised BSD License, see section \ref LICENSE.
+ *
+ * \code
+ * ______ _
+ * / _____) _ | |
+ * ( (____ _____ ____ _| |_ _____ ____| |__
+ * \____ \| ___ | (_ _) ___ |/ ___) _ \
+ * _____) ) ____| | | || |_| ____( (___| | | |
+ * (______/|_____)_|_|_| \__)_____)\____)_| |_|
+ * (C)2013-2017 Semtech
+ *
+ * \endcode
+ *
+ * \author Miguel Luis ( Semtech )
+ *
+ * \author Gregory Cristian ( Semtech )
+ */
+#ifndef __SX1276_BOARD_H__
+#define __SX1276_BOARD_H__
-License: Revised BSD License, see LICENSE.TXT file include in the project
+#ifdef __cplusplus
+extern "C"
+{
+#endif
-Maintainer: Miguel Luis and Gregory Cristian
-*/
-#ifndef __SX1276_ARCH_H__
-#define __SX1276_ARCH_H__
+#include
+#include
+#include "sx1276/sx1276.h"
/*!
* \brief Radio hardware registers initialization definition
@@ -37,7 +54,6 @@ Maintainer: Miguel Luis and Gregory Cristian
{ MODEM_FSK , REG_IMAGECAL , 0x02 },\
{ MODEM_FSK , REG_DIOMAPPING1 , 0x00 },\
{ MODEM_FSK , REG_DIOMAPPING2 , 0x30 },\
- { MODEM_LORA, REG_LR_TCXO , 0x19 },\
{ MODEM_LORA, REG_LR_PAYLOADMAXLENGTH, 0x40 },\
} \
@@ -56,12 +72,27 @@ void SX1276IoInit( void );
void SX1276IoIrqInit( DioIrqHandler **irqHandlers );
/*!
- * \brief De-initializes the radio I/Os pins interface.
+ * \brief De-initializes the radio I/Os pins interface.
*
* \remark Useful when going in MCU low power modes
*/
void SX1276IoDeInit( void );
+/*!
+ * \brief Initializes the TCXO power pin.
+ */
+void SX1276IoTcxoInit( void );
+
+/*!
+ * \brief Initializes the radio debug pins.
+ */
+void SX1276IoDbgInit( void );
+
+/*!
+ * \brief Resets the radio
+ */
+void SX1276Reset( void );
+
/*!
* \brief Sets the radio output power.
*
@@ -70,12 +101,32 @@ void SX1276IoDeInit( void );
void SX1276SetRfTxPower( int8_t power );
/*!
- * \brief Gets the board PA selection configuration
+ * \brief Set the RF Switch I/Os pins in low power mode
*
- * \param [IN] channel Channel frequency in Hz
- * \retval PaSelect RegPaConfig PaSelect value
+ * \param [IN] status enable or disable
*/
-uint8_t SX1276GetPaSelect( uint32_t channel );
+void SX1276SetAntSwLowPower( bool status );
+
+/*!
+ * \brief Initializes the RF Switch I/Os pins interface
+ */
+void SX1276AntSwInit( void );
+
+/*!
+ * \brief De-initializes the RF Switch I/Os pins interface
+ *
+ * \remark Needed to decrease the power consumption in MCU low power modes
+ */
+void SX1276AntSwDeInit( void );
+
+/*!
+ * \brief Controls the antenna switch if necessary.
+ *
+ * \remark see errata note
+ *
+ * \param [IN] opMode Current radio operating mode
+ */
+void SX1276SetAntSw( uint8_t opMode );
/*!
* \brief Checks if the given RF frequency is supported by the hardware
@@ -85,9 +136,41 @@ uint8_t SX1276GetPaSelect( uint32_t channel );
*/
bool SX1276CheckRfFrequency( uint32_t frequency );
+/*!
+ * \brief Enables/disables the TCXO if available on board design.
+ *
+ * \param [IN] state TCXO enabled when true and disabled when false.
+ */
+void SX1276SetBoardTcxo( uint8_t state );
+
+/*!
+ * \brief Gets the Defines the time required for the TCXO to wakeup [ms].
+ *
+ * \retval time Board TCXO wakeup time in ms.
+ */
+uint32_t SX1276GetBoardTcxoWakeupTime( void );
+
+/*!
+ * \brief Writes new Tx debug pin state
+ *
+ * \param [IN] state Debug pin state
+ */
+void SX1276DbgPinTxWrite( uint8_t state );
+
+/*!
+ * \brief Writes new Rx debug pin state
+ *
+ * \param [IN] state Debug pin state
+ */
+void SX1276DbgPinRxWrite( uint8_t state );
+
/*!
* Radio hardware and global parameters
*/
extern SX1276_t SX1276;
-#endif // __SX1276_ARCH_H__
+#ifdef __cplusplus
+}
+#endif
+
+#endif // __SX1276_BOARD_H__
diff --git a/esp32/lora/utilities.c b/esp32/lora/utilities.c
index 230e0d6329..61ef3eb35c 100644
--- a/esp32/lora/utilities.c
+++ b/esp32/lora/utilities.c
@@ -83,3 +83,13 @@ int8_t Nibble2HexChar( uint8_t a )
return '?';
}
}
+
+IRAM_ATTR void BoardCriticalSectionBegin( uint32_t *mask )
+{
+ *mask = MICROPY_BEGIN_ATOMIC_SECTION();
+}
+
+IRAM_ATTR void BoardCriticalSectionEnd( uint32_t *mask )
+{
+ MICROPY_END_ATOMIC_SECTION(*mask);
+}
diff --git a/esp32/lora/utilities.h b/esp32/lora/utilities.h
index 1007ded630..29c9041f2c 100644
--- a/esp32/lora/utilities.h
+++ b/esp32/lora/utilities.h
@@ -1,22 +1,48 @@
-/*
- / _____) _ | |
-( (____ _____ ____ _| |_ _____ ____| |__
- \____ \| ___ | (_ _) ___ |/ ___) _ \
- _____) ) ____| | | || |_| ____( (___| | | |
-(______/|_____)_|_|_| \__)_____)\____)_| |_|
- (C)2013 Semtech
+/*!
+ * \file utilities.h
+ *
+ * \brief Helper functions implementation
+ *
+ * \copyright Revised BSD License, see section \ref LICENSE.
+ *
+ * \code
+ * ______ _
+ * / _____) _ | |
+ * ( (____ _____ ____ _| |_ _____ ____| |__
+ * \____ \| ___ | (_ _) ___ |/ ___) _ \
+ * _____) ) ____| | | || |_| ____( (___| | | |
+ * (______/|_____)_|_|_| \__)_____)\____)_| |_|
+ * (C)2013-2017 Semtech
+ *
+ * \endcode
+ *
+ * \author Miguel Luis ( Semtech )
+ *
+ * \author Gregory Cristian ( Semtech )
+ */
+#ifndef __UTILITIES_H__
+#define __UTILITIES_H__
-Description: Helper functions implementation
+#ifdef __cplusplus
+extern "C"
+{
+#endif
-License: Revised BSD License, see LICENSE.TXT file include in the project
+#include
-Maintainer: Miguel Luis and Gregory Cristian
-*/
-#ifndef __UTILITIES_H__
-#define __UTILITIES_H__
+/*!
+ * Generic definition
+ */
+// #ifndef SUCCESS
+// #define SUCCESS 1
+// #endif
+
+// #ifndef FAIL
+// #define FAIL 0
+// #endif
/*!
- * \brief Returns the minimum value betwen a and b
+ * \brief Returns the minimum value between a and b
*
* \param [IN] a 1st value
* \param [IN] b 2nd value
@@ -27,7 +53,7 @@ Maintainer: Miguel Luis and Gregory Cristian
#endif
/*!
- * \brief Returns the maximum value betwen a and b
+ * \brief Returns the maximum value between a and b
*
* \param [IN] a 1st value
* \param [IN] b 2nd value
@@ -46,9 +72,24 @@ Maintainer: Miguel Luis and Gregory Cristian
#define POW2( n ) ( 1 << n )
/*!
- * \brief Initializes the pseudo ramdom generator initial value
+ * Version
+ */
+typedef union Version_u
+{
+ struct Version_s
+ {
+ uint8_t Rfu;
+ uint8_t Revision;
+ uint8_t Minor;
+ uint8_t Major;
+ }Fields;
+ uint32_t Value;
+}Version_t;
+
+/*!
+ * \brief Initializes the pseudo random generator initial value
*
- * \param [IN] seed Pseudo ramdom generator initial value
+ * \param [IN] seed Pseudo random generator initial value
*/
void srand1( uint32_t seed );
@@ -63,7 +104,7 @@ int32_t randr( int32_t min, int32_t max );
/*!
* \brief Copies size elements of src array to dst array
- *
+ *
* \remark STM32 Standard memcpy function only works on pointers that are aligned
*
* \param [OUT] dst Destination array
@@ -82,8 +123,8 @@ void memcpy1( uint8_t *dst, const uint8_t *src, uint16_t size );
void memcpyr( uint8_t *dst, const uint8_t *src, uint16_t size );
/*!
- * \brief Set size elements of dst array with value
- *
+ * \brief Set size elements of dst array with value
+ *
* \remark STM32 Standard memset function only works on pointers that are aligned
*
* \param [OUT] dst Destination array
@@ -94,10 +135,44 @@ void memset1( uint8_t *dst, uint8_t value, uint16_t size );
/*!
* \brief Converts a nibble to an hexadecimal character
- *
+ *
* \param [IN] a Nibble to be converted
* \retval hexChar Converted hexadecimal character
*/
int8_t Nibble2HexChar( uint8_t a );
+/*!
+ * Begins critical section
+ */
+#define CRITICAL_SECTION_BEGIN( ) uint32_t mask; BoardCriticalSectionBegin( &mask )
+
+/*!
+ * Ends critical section
+ */
+#define CRITICAL_SECTION_END( ) BoardCriticalSectionEnd( &mask )
+
+/*
+ * ============================================================================
+ * Following functions must be implemented inside the specific platform
+ * board.c file.
+ * ============================================================================
+ */
+/*!
+ * Disable interrupts, begins critical section
+ *
+ * \param [IN] mask Pointer to a variable where to store the CPU IRQ mask
+ */
+void BoardCriticalSectionBegin( uint32_t *mask );
+
+/*!
+ * Ends critical section
+ *
+ * \param [IN] mask Pointer to a variable where the CPU IRQ mask was stored
+ */
+void BoardCriticalSectionEnd( uint32_t *mask );
+
+#ifdef __cplusplus
+}
+#endif
+
#endif // __UTILITIES_H__
diff --git a/esp32/lte/lteppp.c b/esp32/lte/lteppp.c
index 01035c1d74..562fc23fe8 100644
--- a/esp32/lte/lteppp.c
+++ b/esp32/lte/lteppp.c
@@ -16,8 +16,10 @@
#include "esp_log.h"
#include "driver/uart.h"
+#include "uart_struct.h"
+#include "uart_reg.h"
#include "driver/gpio.h"
-#include "tcpip_adapter.h"
+#include "esp_netif.h"
#include "netif/ppp/pppos.h"
#include "netif/ppp/ppp.h"
#include "netif/ppp/pppapi.h"
@@ -128,7 +130,8 @@ void connect_lte_uart (void) {
config.stop_bits = UART_STOP_BITS_1;
config.flow_ctrl = UART_HW_FLOWCTRL_CTS_RTS;
config.rx_flow_ctrl_thresh = 64;
- config.use_ref_tick = false;
+ // Use UART_SCLK_APB as originally use_ref_tick = false was used here
+ config.source_clk = UART_SCLK_APB;
uart_param_config(LTE_UART_ID, &config);
// configure the UART pins
@@ -830,8 +833,8 @@ static void lteppp_status_cb (ppp_pcb *pcb, int err_code, void *ctx) {
lte_ipv4addr = pppif->ip_addr.u_addr.ip4.addr;
if(lte_ipv4addr > 0)
{
- ltepp_dns_info[0] = dns_getserver(0);
- ltepp_dns_info[1] = dns_getserver(1);
+ ltepp_dns_info[0] = *(dns_getserver(0));
+ ltepp_dns_info[1] = *(dns_getserver(1));
}
MSG("ipaddr = %s\n", ipaddr_ntoa(&pppif->ip_addr));
MSG("gateway = %s\n", ipaddr_ntoa(&pppif->gw));
@@ -857,12 +860,12 @@ static void lteppp_status_cb (ppp_pcb *pcb, int err_code, void *ctx) {
case PPPERR_USER:
MSG("User interrupt (disconnected)\n");
lte_ipv4addr = 0;
- memset(lte_ipv6addr.addr, 0, sizeof(lte_ipv4addr));
+ memset(lte_ipv6addr.addr, 0, sizeof(lte_ipv6addr.addr));
break;
case PPPERR_CONNECT:
MSG("\n\n\nConnection lost\n");
lte_ipv4addr = 0;
- memset(lte_ipv6addr.addr, 0, sizeof(lte_ipv4addr));
+ memset(lte_ipv6addr.addr, 0, sizeof(lte_ipv6addr.addr));
break;
case PPPERR_AUTHFAIL:
MSG("Failed authentication challenge\n");
@@ -885,7 +888,7 @@ static void lteppp_status_cb (ppp_pcb *pcb, int err_code, void *ctx) {
default:
MSG("Unknown error code %d\n", err_code);
lte_ipv4addr = 0;
- memset(lte_ipv6addr.addr, 0, sizeof(lte_ipv4addr));
+ memset(lte_ipv6addr.addr, 0, sizeof(lte_ipv6addr.addr));
break;
}
}
diff --git a/esp32/main.c b/esp32/main.c
index 5f921cf8f5..4caf1744f0 100644
--- a/esp32/main.c
+++ b/esp32/main.c
@@ -36,8 +36,8 @@
#include "esp_system.h"
#include "esp_attr.h"
#include "esp_spi_flash.h"
-#include "rom/spi_flash.h"
-#include "rom/ets_sys.h"
+#include "esp32/rom/spi_flash.h"
+#include "esp32/rom/ets_sys.h"
#include "nvs_flash.h"
#include "soc/dport_reg.h"
#include "esp_log.h"
@@ -54,6 +54,8 @@
#include "esp_event_loop.h"
#include "app_sys_evt.h"
+#include "esp32/lora/board.h"
+
TaskHandle_t mpTaskHandle;
TaskHandle_t svTaskHandle;
@@ -134,8 +136,11 @@ void app_main(void) {
// remove all the logs from the IDF
esp_log_level_set("*", ESP_LOG_NONE);
+ // TODO: esp_event_loop_init is a legacy function and should be removed.
+ // TODO: Double check why app_sys_event_handler is needed to be registered. If not needed, then simply call esp_event_loop_create_default()
// Register sys event callback
ESP_ERROR_CHECK(esp_event_loop_init(app_sys_event_handler, NULL));
+ // ESP_ERROR_CHECK(esp_event_loop_create_default());
// setup the timer used as a reference in mphal
machtimer_preinit();
@@ -164,8 +169,8 @@ void app_main(void) {
micropy_hw_antenna_diversity_pin_num = MICROPY_SECOND_GEN_ANT_SELECT_PIN_NUM;
micropy_lpwan_ncs_pin_index = 1;
- micropy_lpwan_ncs_pin_num = 18;
- micropy_lpwan_ncs_pin = &pin_GPIO18;
+ micropy_lpwan_ncs_pin_num = LPWAN_NCS_PIN_NUMBER;
+ micropy_lpwan_ncs_pin = LPWAN_NCS_PIN;
micropy_lpwan_use_reset_pin = false;
diff --git a/esp32/mods/lwipsocket.c b/esp32/mods/lwipsocket.c
index ebe5e70859..fa22ad93e2 100644
--- a/esp32/mods/lwipsocket.c
+++ b/esp32/mods/lwipsocket.c
@@ -82,7 +82,7 @@ int lwipsocket_socket_socket(mod_network_socket_obj_t *s, int *_errno) {
// enable address reusing
uint32_t option = 1;
- lwip_setsockopt_r(sd, SOL_SOCKET, SO_REUSEADDR, &option, sizeof(option));
+ lwip_setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &option, sizeof(option));
s->sock_base.u.sd = sd;
return 0;
@@ -104,7 +104,7 @@ void lwipsocket_socket_close(mod_network_socket_obj_t *s) {
mbedtls_ctr_drbg_free(&ss->ctr_drbg);
mbedtls_entropy_free(&ss->entropy);
} else {
- lwip_close_r(s->sock_base.u.sd);
+ lwip_close(s->sock_base.u.sd);
}
modusocket_socket_delete(s->sock_base.u.sd);
s->sock_base.connected = false;
@@ -112,7 +112,7 @@ void lwipsocket_socket_close(mod_network_socket_obj_t *s) {
int lwipsocket_socket_bind(mod_network_socket_obj_t *s, byte *ip, mp_uint_t port, int *_errno) {
MAKE_SOCKADDR(addr, ip, port)
- int ret = lwip_bind_r(s->sock_base.u.sd, &addr, sizeof(addr));
+ int ret = lwip_bind(s->sock_base.u.sd, &addr, sizeof(addr));
if (ret != 0) {
*_errno = errno;
return -1;
@@ -121,7 +121,7 @@ int lwipsocket_socket_bind(mod_network_socket_obj_t *s, byte *ip, mp_uint_t port
}
int lwipsocket_socket_listen(mod_network_socket_obj_t *s, mp_int_t backlog, int *_errno) {
- int ret = lwip_listen_r(s->sock_base.u.sd, backlog);
+ int ret = lwip_listen(s->sock_base.u.sd, backlog);
if (ret != 0) {
*_errno = errno;
return -1;
@@ -135,7 +135,7 @@ int lwipsocket_socket_accept(mod_network_socket_obj_t *s, mod_network_socket_obj
struct sockaddr addr;
socklen_t addr_len = sizeof(addr);
- sd = lwip_accept_r(s->sock_base.u.sd, &addr, &addr_len);
+ sd = lwip_accept(s->sock_base.u.sd, &addr, &addr_len);
// save the socket descriptor
s2->sock_base.u.sd = sd;
if (sd < 0) {
@@ -152,7 +152,7 @@ int lwipsocket_socket_accept(mod_network_socket_obj_t *s, mod_network_socket_obj
int lwipsocket_socket_connect(mod_network_socket_obj_t *s, byte *ip, mp_uint_t port, int *_errno) {
MAKE_SOCKADDR(addr, ip, port)
- int ret = lwip_connect_r(s->sock_base.u.sd, &addr, sizeof(addr));
+ int ret = lwip_connect(s->sock_base.u.sd, &addr, sizeof(addr));
if (ret != 0) {
// printf("Connect returned -0x%x\n", -ret);
@@ -186,7 +186,7 @@ int lwipsocket_socket_send(mod_network_socket_obj_t *s, const byte *buf, mp_uint
}
}
} else {
- bytes = lwip_send_r(s->sock_base.u.sd, (const void *)buf, len, 0);
+ bytes = lwip_send(s->sock_base.u.sd, (const void *)buf, len, 0);
}
}
if (bytes <= 0) {
@@ -237,7 +237,7 @@ int lwipsocket_socket_recv(mod_network_socket_obj_t *s, byte *buf, mp_uint_t len
return -1;
}
} else {
- ret = lwip_recv_r(s->sock_base.u.sd, buf, MIN(len, WLAN_MAX_RX_SIZE), 0);
+ ret = lwip_recv(s->sock_base.u.sd, buf, MIN(len, WLAN_MAX_RX_SIZE), 0);
if (ret < 0) {
*_errno = errno;
return -1;
@@ -249,7 +249,7 @@ int lwipsocket_socket_recv(mod_network_socket_obj_t *s, byte *buf, mp_uint_t len
int lwipsocket_socket_sendto( mod_network_socket_obj_t *s, const byte *buf, mp_uint_t len, byte *ip, mp_uint_t port, int *_errno) {
if (len > 0) {
MAKE_SOCKADDR(addr, ip, port)
- int ret = lwip_sendto_r(s->sock_base.u.sd, (byte*)buf, len, 0, (struct sockaddr*)&addr, sizeof(addr));
+ int ret = lwip_sendto(s->sock_base.u.sd, (byte*)buf, len, 0, (struct sockaddr*)&addr, sizeof(addr));
if (ret < 0) {
*_errno = errno;
return -1;
@@ -262,7 +262,7 @@ int lwipsocket_socket_sendto( mod_network_socket_obj_t *s, const byte *buf, mp_u
int lwipsocket_socket_recvfrom(mod_network_socket_obj_t *s, byte *buf, mp_uint_t len, byte *ip, mp_uint_t *port, int *_errno) {
struct sockaddr addr;
socklen_t addr_len = sizeof(addr);
- mp_int_t ret = lwip_recvfrom_r(s->sock_base.u.sd, buf, MIN(len, WLAN_MAX_RX_SIZE), 0, &addr, &addr_len);
+ mp_int_t ret = lwip_recvfrom(s->sock_base.u.sd, buf, MIN(len, WLAN_MAX_RX_SIZE), 0, &addr, &addr_len);
if (ret < 0) {
*_errno = errno;
return -1;
@@ -272,7 +272,7 @@ int lwipsocket_socket_recvfrom(mod_network_socket_obj_t *s, byte *buf, mp_uint_t
}
int lwipsocket_socket_setsockopt(mod_network_socket_obj_t *s, mp_uint_t level, mp_uint_t opt, const void *optval, mp_uint_t optlen, int *_errno) {
- int ret = lwip_setsockopt_r(s->sock_base.u.sd, level, opt, optval, optlen);
+ int ret = lwip_setsockopt(s->sock_base.u.sd, level, opt, optval, optlen);
if (ret < 0) {
*_errno = errno;
return -1;
@@ -281,7 +281,7 @@ int lwipsocket_socket_setsockopt(mod_network_socket_obj_t *s, mp_uint_t level, m
}
int lwipsocket_socket_settimeout(mod_network_socket_obj_t *s, mp_int_t timeout_ms, int *_errno) {
- int ret;
+ int ret = 0;
if (s->sock_base.is_ssl) {
mp_obj_ssl_socket_t *ss = (mp_obj_ssl_socket_t *)s;
@@ -289,29 +289,39 @@ int lwipsocket_socket_settimeout(mod_network_socket_obj_t *s, mp_int_t timeout_m
mbedtls_ssl_conf_read_timeout(&ss->conf, timeout_ms);
}
else {
- uint32_t option = lwip_fcntl_r(s->sock_base.u.sd, F_GETFL, 0);
-
- if (timeout_ms <= 0) {
- if (timeout_ms == 0) {
- // set non-blocking mode
- option |= O_NONBLOCK;
- } else {
- // set blocking mode
- option &= ~O_NONBLOCK;
- timeout_ms = UINT32_MAX;
- }
- } else {
- // set blocking mode
+ struct timeval tv;
+ uint32_t option = lwip_fcntl(s->sock_base.u.sd, F_GETFL, 0);
+
+ // timeout_ms is in milliseconds
+ // 0 value means set the socket to non-blocking
+ if(timeout_ms == 0) {
+ // set non-blocking mode
+ option |= O_NONBLOCK;
+ // Timeout values does not really matter as the socket set to non-blocking
+ tv.tv_sec = 0;
+ tv.tv_usec = 0;
+ }
+ else {
+ // set the socket to blocking
option &= ~O_NONBLOCK;
+ // Set the timeout if given correctly
+ if(timeout_ms != -1) {
+ // set the timeout
+ tv.tv_sec = timeout_ms / 1000; // seconds
+ tv.tv_usec = (timeout_ms % 1000) * 1000; // microseconds
+ }
+ else {
+ // Clear the timeout values, the socket must wait forever
+ tv.tv_sec = 0;
+ tv.tv_usec = 0;
+ }
}
- // set the timeout
- struct timeval tv;
- tv.tv_sec = timeout_ms / 1000; // seconds
- tv.tv_usec = (timeout_ms % 1000) * 1000; // microseconds
- ret = lwip_setsockopt_r(s->sock_base.u.sd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
- ret |= lwip_setsockopt_r(s->sock_base.u.sd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
- ret |= lwip_fcntl_r(s->sock_base.u.sd, F_SETFL, option);
+ // Configure the correct timeout
+ ret = lwip_setsockopt(s->sock_base.u.sd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
+ ret |= lwip_setsockopt(s->sock_base.u.sd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
+ // Configure the socket as per its option: blocking or non blocking
+ ret |= lwip_fcntl(s->sock_base.u.sd, F_SETFL, option);
if (ret != 0) {
*_errno = errno;
diff --git a/esp32/mods/machine_i2c.c b/esp32/mods/machine_i2c.c
index a29c0492be..603cc92ac4 100644
--- a/esp32/mods/machine_i2c.c
+++ b/esp32/mods/machine_i2c.c
@@ -59,7 +59,7 @@
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
-#include "rom/ets_sys.h"
+#include "esp32/rom/ets_sys.h"
#include "driver/i2c.h"
#include "driver/gpio.h"
#include "driver/periph_ctrl.h"
diff --git a/esp32/mods/machpin.c b/esp32/mods/machpin.c
index ced3e65ef5..d1a4106de3 100644
--- a/esp32/mods/machpin.c
+++ b/esp32/mods/machpin.c
@@ -51,7 +51,7 @@
#include "esp_system.h"
#include "esp_spi_flash.h"
#include "nvs_flash.h"
-#include "esp_intr.h"
+#include "esp_intr_alloc.h"
#include "driver/rtc_io.h"
#include "gpio.h"
@@ -107,7 +107,7 @@ DECLARE PRIVATE DATA
DEFINE PUBLIC FUNCTIONS
******************************************************************************/
void pin_preinit(void) {
- gpio_isr_register(machpin_intr_process, NULL, ESP_INTR_FLAG_IRAM, NULL);
+ gpio_isr_register(machpin_intr_process, NULL, 0, NULL);
}
void pin_init0(void) {
diff --git a/esp32/mods/machpwm.c b/esp32/mods/machpwm.c
index 323deb4f46..bf69f26f00 100644
--- a/esp32/mods/machpwm.c
+++ b/esp32/mods/machpwm.c
@@ -213,11 +213,6 @@ STATIC mp_obj_t mach_pwm_init(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mach_pwm_init_obj, 1, mach_pwm_init);
-STATIC mp_obj_t mach_pwm_deinit(mp_obj_t self_in) {
- return mp_const_none;
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(mach_pwm_deinit_obj, mach_pwm_deinit);
-
STATIC const mp_map_elem_t mach_pwm_timer_locals_dict_table[] = {
// instance methods
{ MP_OBJ_NEW_QSTR(MP_QSTR_init), (mp_obj_t)&mach_pwm_init_obj },
diff --git a/esp32/mods/machrtc.c b/esp32/mods/machrtc.c
index f2a819b68b..355daf7fae 100644
--- a/esp32/mods/machrtc.c
+++ b/esp32/mods/machrtc.c
@@ -21,7 +21,7 @@
#include "mpexception.h"
#include "machrtc.h"
#include "soc/rtc.h"
-#include "esp_clk.h"
+#include "esp32/clk.h"
#include "esp_clk_internal.h"
@@ -177,7 +177,7 @@ STATIC mp_obj_t mach_rtc_make_new(const mp_obj_type_t *type, mp_uint_t n_args, m
rtc_clk_32k_bootstrap(5);
}
}
- rtc_clk_select_rtc_slow_clk(clk_src);
+ rtc_clk_select_rtc_slow_clk();
settimeofday(&now, NULL);
}
diff --git a/esp32/mods/machspi.c b/esp32/mods/machspi.c
index 6ac7f81df0..f9b279a111 100644
--- a/esp32/mods/machspi.c
+++ b/esp32/mods/machspi.c
@@ -51,7 +51,7 @@
#include "esp_types.h"
#include "esp_attr.h"
-#include "esp_intr.h"
+#include "esp_intr_alloc.h"
#include "soc/dport_reg.h"
#include "soc/gpio_sig_map.h"
@@ -106,11 +106,11 @@ static const uint32_t mach_spi_pin_af[1][3] = { {HSPICLK_OUT_IDX, HSPID_OUT_IDX,
// only master mode is available for the moment
STATIC void machspi_init (const mach_spi_obj_t *self) {
if (self->spi_num == SpiNum_SPI2) {
- DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI_CLK_EN);
- DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI_RST);
+ DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI2_CLK_EN);
+ DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI2_RST);
} else {
- DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI_CLK_EN_2);
- DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI_RST_2);
+ DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI3_CLK_EN);
+ DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI3_RST);
}
// configure the SPI port
diff --git a/esp32/mods/machtimer_alarm.c b/esp32/mods/machtimer_alarm.c
index 4bf444fcb4..0b81c0eabe 100644
--- a/esp32/mods/machtimer_alarm.c
+++ b/esp32/mods/machtimer_alarm.c
@@ -306,12 +306,107 @@ STATIC mp_obj_t alarm_delete(mp_obj_t self_in) {
}
MP_DEFINE_CONST_FUN_OBJ_1(alarm_delete_obj, alarm_delete);
+STATIC mp_obj_t alarm_freeze(void) {
+ uint32_t state = MICROPY_BEGIN_ATOMIC_SECTION();
+ uint16_t previous_state = TIMERG0.hw_timer[0].config.enable;
+ TIMERG0.hw_timer[0].config.enable = 0; // disable the counter of alarm system
+ MICROPY_END_ATOMIC_SECTION(state);
+ return mp_obj_new_int_from_uint(previous_state);
+}
+MP_DEFINE_CONST_FUN_OBJ_0(alarm_freeze_fun_obj, alarm_freeze);
+STATIC MP_DEFINE_CONST_STATICMETHOD_OBJ(alarm_freeze_obj, &alarm_freeze_fun_obj);
+
+STATIC mp_obj_t alarm_remaining(void) {
+
+ // TODO: review comments
+ // Atomic section is placed here due to the following reasons:
+ // 1. If user calls "cancel" function it might be interrupted by the ISR when reordering the list because
+ // in this case the alarm is an active alarm which means it is placed on the alarm_heap and its heap_index != -1.
+ // 2. When GC calls this function it is 100% percent sure that the heap_index is -1, because
+ // GC will only collect this object if it is not referred from the alarm_heap, which means it is not active thus
+ // its heap_index == -1.
+ uint64_t current_clocks;
+ uint64_t proxima_clocks;
+ uint64_t time_ms;
+
+ if (alarm_heap.count==0) {
+ return mp_obj_new_int(0);
+ }
+
+ uint32_t state = MICROPY_BEGIN_ATOMIC_SECTION();
+ TIMERG0.hw_timer[0].update = 1;
+ current_clocks = ((uint64_t) TIMERG0.hw_timer[0].cnt_high << 32)
+ | (TIMERG0.hw_timer[0].cnt_low);
+ proxima_clocks = alarm_heap.data[0]->when;
+ MICROPY_END_ATOMIC_SECTION(state);
+
+ time_ms = (proxima_clocks - current_clocks)*1000/CLK_FREQ;
+ if (time_ms >> 32) {
+ time_ms = 0xFFFFFFFF;
+ }
+
+ return mp_obj_new_int_from_uint((uint32_t)time_ms);
+}
+MP_DEFINE_CONST_FUN_OBJ_0(alarm_remaining_fun_obj, alarm_remaining);
+STATIC MP_DEFINE_CONST_STATICMETHOD_OBJ(alarm_remaining_obj, &alarm_remaining_fun_obj);
+
+#define ALARM_TIME_GUARD (4)
+STATIC mp_obj_t alarm_resume(mp_obj_t obj_offset_ms) {
+ if (!mp_obj_is_integer(obj_offset_ms)) {
+ mp_raise_ValueError("please provide a positive number for time offset in ms");
+ }
+ int64_t offset = mp_obj_int_get_checked(obj_offset_ms);
+ if (offset<0) {
+ mp_raise_ValueError("please provide a positive number for time offset in ms");
+ }
+ offset = offset*CLK_FREQ/1000;
+ uint32_t state = MICROPY_BEGIN_ATOMIC_SECTION();
+ if (TIMERG0.hw_timer[0].config.enable==1) {
+ MICROPY_END_ATOMIC_SECTION(state);
+ mp_raise_ValueError("alarm already running, time correction not applied");
+ }
+ uint32_t i = 0;
+ TIMERG0.hw_timer[0].update = 1;
+ uint64_t expired_event_when = ALARM_TIME_GUARD +
+ (((uint64_t) TIMERG0.hw_timer[0].cnt_high << 32) | (TIMERG0.hw_timer[0].cnt_low));
+ for (; iwhen-offset)<0x0FFFFFFFFFFFFFFF) { //beaware this is a limitation on distant events
+ break;
+ }
+ alarm_heap.data[i]->when = expired_event_when;
+ if (i==0) {
+
+ }
+ }
+ for (; iwhen -= offset;
+ if (alarm_heap.data[i]->whenwhen = ALARM_TIME_GUARD;
+ }
+ }
+ if (alarm_heap.count > 0) {
+ uint64_t when;
+ when = alarm_heap.data[0]->when;
+ TIMERG0.hw_timer[0].alarm_high = (uint32_t) (when >> 32);
+ TIMERG0.hw_timer[0].alarm_low = (uint32_t) when;
+ //TIMERG0.hw_timer[0].config.alarm_en = 1; // enable the alarm system
+ }
+ TIMERG0.hw_timer[0].config.enable = 1; //enable the counter of alarm system
+ MICROPY_END_ATOMIC_SECTION(state);
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(alarm_resume_fun_obj, alarm_resume);
+STATIC MP_DEFINE_CONST_STATICMETHOD_OBJ(alarm_resume_obj, &alarm_resume_fun_obj);
+
STATIC const mp_map_elem_t mach_timer_alarm_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_alarm) },
{ MP_OBJ_NEW_QSTR(MP_QSTR___del__), (mp_obj_t) &alarm_delete_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_callback), (mp_obj_t) &alarm_callback_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_cancel), (mp_obj_t) &alarm_delete_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_FreezeAll), (mp_obj_t) &alarm_freeze_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_Remaining), (mp_obj_t) &alarm_remaining_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_ResumeAll), (mp_obj_t) &alarm_resume_obj },
};
STATIC MP_DEFINE_CONST_DICT(mach_timer_alarm_dict, mach_timer_alarm_dict_table);
diff --git a/esp32/mods/machuart.c b/esp32/mods/machuart.c
index e92009c2a4..2309515c9a 100644
--- a/esp32/mods/machuart.c
+++ b/esp32/mods/machuart.c
@@ -28,9 +28,9 @@
#include "esp_types.h"
#include "esp_attr.h"
-#include "esp_intr.h"
+#include "esp_intr_alloc.h"
-#include "rom/ets_sys.h"
+#include "esp32/rom/ets_sys.h"
#include "soc/uart_struct.h"
#include "soc/dport_reg.h"
#include "soc/gpio_sig_map.h"
diff --git a/esp32/mods/machwdt.c b/esp32/mods/machwdt.c
index ad4e165958..d87e17b2bf 100644
--- a/esp32/mods/machwdt.c
+++ b/esp32/mods/machwdt.c
@@ -20,7 +20,6 @@
#include
#include "esp_err.h"
-#include "esp_intr.h"
#include "esp_intr_alloc.h"
#include "esp_attr.h"
#include "esp_freertos_hooks.h"
diff --git a/esp32/mods/modble_mesh.c b/esp32/mods/modble_mesh.c
new file mode 100644
index 0000000000..afff6406de
--- /dev/null
+++ b/esp32/mods/modble_mesh.c
@@ -0,0 +1,1737 @@
+/*
+ * Copyright (c) 2020, Pycom Limited.
+ *
+ * This software is licensed under the GNU GPL version 3 or any
+ * later version, with permitted additional terms. For more information
+ * see the Pycom Licence v1.0 document supplied with this file, or
+ * available at https://www.pycom.io/opensource/licensing
+ */
+
+#include "py/mpconfig.h"
+#include "py/obj.h"
+#include "py/runtime.h"
+#include "py/gc.h"
+#include
+#include
+#include
+
+#include "esp_bt_device.h"
+
+#include "esp_ble_mesh_defs.h"
+#include "esp_ble_mesh_common_api.h"
+#include "esp_ble_mesh_provisioning_api.h"
+#include "esp_ble_mesh_config_model_api.h"
+#include "esp_ble_mesh_generic_model_api.h"
+#include "esp_ble_mesh_sensor_model_api.h"
+#include "esp_ble_mesh_networking_api.h"
+
+#include "mpirq.h"
+
+static esp_ble_mesh_client_t sensor_client;
+
+/******************************************************************************
+ DEFINE CONSTANTS
+ ******************************************************************************/
+
+#define MOD_BLE_MESH_SERVER (0)
+#define MOD_BLE_MESH_CLIENT (1)
+
+#define MOD_BLE_MESH_PROV_ADV (1)
+#define MOD_BLE_MESH_PROV_GATT (2)
+#define MOD_BLE_MESH_PROV_NONE (4)
+
+#define MOD_BLE_MESH_NO_OOB (0)
+#define MOD_BLE_MESH_INPUT_OOB (1)
+#define MOD_BLE_MESH_OUTPUT_OOB (2)
+
+#define MOD_BLE_MESH_RELAY (1)
+#define MOD_BLE_MESH_GATT_PROXY (2)
+#define MOD_BLE_MESH_LOW_POWER (4)
+#define MOD_BLE_MESH_FRIEND (8)
+
+// For Configuration Model
+#define MOD_BLE_MESH_MODEL_NONE (4)
+
+// Model Groups
+#define MOD_BLE_MESH_GROUP_GENERIC (0)
+#define MOD_BLE_MESH_GROUP_SENSOR (1)
+#define MOD_BLE_MESH_GROUP_TIME (2)
+#define MOD_BLE_MESH_GROUP_LIGHTNING (3)
+
+// Model Sensor/Client
+#define MOD_BLE_MESH_SERVER (0)
+#define MOD_BLE_MESH_CLIENT (1)
+
+// Model Type
+#define MOD_BLE_MESH_MODEL_GEN_ONOFF (0)
+#define MOD_BLE_MESH_MODEL_GEN_LEVEL (1)
+#define MOD_BLE_MESH_MODEL_SENSOR (2)
+#define MOD_BLE_MESH_MODEL_SENSOR_SETUP (3)
+#define MOD_BLE_MESH_MODEL_CONFIGURATION (4)
+
+// States
+#define MOD_BLE_MESH_STATE_ONOFF (0)
+#define MOD_BLE_MESH_STATE_LEVEL (3)
+#define MOD_BLE_MESH_STATE_LEVEL_DELTA (7)
+#define MOD_BLE_MESH_STATE_LEVEL_MOVE (11)
+#define MOD_BLE_MESH_STATE_SEN_DESCRIPTOR (14)
+#define MOD_BLE_MESH_STATE_SEN (18)
+#define MOD_BLE_MESH_STATE_SEN_COLUMN (22)
+#define MOD_BLE_MESH_STATE_SEN_SERIES (26)
+#define MOD_BLE_MESH_STATE_SEN_SET_CADENCE (29)
+#define MOD_BLE_MESH_STATE_SEN_SET_SETTINGS (33)
+#define MOD_BLE_MESH_STATE_SEN_SET_SETTING (37)
+
+// Requests
+#define MOD_BLE_MESH_REQ_GET (0)
+#define MOD_BLE_MESH_REQ_SET (1)
+#define MOD_BLE_MESH_REQ_SET_UNACK (2)
+#define MOD_BLE_MESH_REQ_STATE (3)
+
+#define MOD_BLE_ADDR_ALL_NODES (0xFFFF)
+#define MOD_BLE_ADDR_PUBLISH (0x0000)
+
+#define MOD_BLE_MESH_DEFAULT_NAME "PYCOM-ESP-BLE-MESH"
+
+#define MOD_BLE_MESH_STATE_LOCATION_IN_SRV_T_TYPE (sizeof(esp_ble_mesh_model_t*) + sizeof(esp_ble_mesh_server_rsp_ctrl_t))
+
+// Define macros from latest ESP-IDF
+#define ESP_BLE_MESH_SENSOR_DATA_FORMAT_A_MPID(_len, _id) \
+ ((((_id) & BIT_MASK(11)) << 5) | (((_len) & BIT_MASK(4)) << 1) | ESP_BLE_MESH_SENSOR_DATA_FORMAT_A)
+
+#define ESP_BLE_MESH_SENSOR_DATA_FORMAT_B_MPID(_len, _id) \
+ (((_id) << 8) | (((_len) & BIT_MASK(7)) << 1) | ESP_BLE_MESH_SENSOR_DATA_FORMAT_B)
+
+#define ESP_BLE_MESH_GET_SENSOR_DATA_PROPERTY_ID(_data, _fmt) \
+ (((_fmt) == ESP_BLE_MESH_SENSOR_DATA_FORMAT_A) ? ((((_data)[1]) << 3) | (((_data)[0]) >> 5)) : ((((_data)[2]) << 8) | ((_data)[1])))
+
+#define ESP_BLE_MESH_GET_SENSOR_DATA_FORMAT(_data) (((_data)[0]) & BIT_MASK(1))
+
+#define ESP_BLE_MESH_GET_SENSOR_DATA_LENGTH(_data, _fmt) \
+ (((_fmt) == ESP_BLE_MESH_SENSOR_DATA_FORMAT_A) ? ((((_data)[0]) >> 1) & BIT_MASK(4)) : ((((_data)[0]) >> 1) & BIT_MASK(7)))
+
+/******************************************************************************
+ DEFINE PRIVATE TYPES
+ ******************************************************************************/
+
+// TYPE : SIZE table, can be addressed with (model_type + state + request).
+// int to eliminate compiler warnings
+static const int opcode_table[] = {
+ // GENERIC ONOFF ONOFF
+ ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_GET,
+ ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET,
+ ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET_UNACK,
+ ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_STATUS,
+ // GENERIC LEVEL LEVEL
+ ESP_BLE_MESH_MODEL_OP_GEN_LEVEL_GET,
+ ESP_BLE_MESH_MODEL_OP_GEN_LEVEL_SET,
+ ESP_BLE_MESH_MODEL_OP_GEN_LEVEL_SET_UNACK,
+ ESP_BLE_MESH_MODEL_OP_GEN_LEVEL_STATUS,
+ // GENERIC LEVEL DELTA
+ -1,
+ ESP_BLE_MESH_MODEL_OP_GEN_DELTA_SET,
+ ESP_BLE_MESH_MODEL_OP_GEN_DELTA_SET_UNACK,
+ -1,
+ // GENERIC LEVEL MOVE
+ -1,
+ ESP_BLE_MESH_MODEL_OP_GEN_MOVE_SET,
+ ESP_BLE_MESH_MODEL_OP_GEN_MOVE_SET_UNACK,
+ -1,
+ // SENSOR SENSOR_DESCRIPTOR
+ ESP_BLE_MESH_MODEL_OP_SENSOR_DESCRIPTOR_GET,
+ -1,
+ -1,
+ ESP_BLE_MESH_MODEL_OP_SENSOR_DESCRIPTOR_STATUS,
+ // SENSOR SENSOR
+ ESP_BLE_MESH_MODEL_OP_SENSOR_GET,
+ -1,
+ -1,
+ ESP_BLE_MESH_MODEL_OP_SENSOR_STATUS,
+ // SENSOR SENSOR_COLUMN
+ ESP_BLE_MESH_MODEL_OP_SENSOR_COLUMN_GET,
+ -1,
+ -1,
+ ESP_BLE_MESH_MODEL_OP_SENSOR_COLUMN_STATUS,
+ // SENSOR SENSOR_SERIES
+ ESP_BLE_MESH_MODEL_OP_SENSOR_SERIES_GET,
+ -1,
+ -1,
+ ESP_BLE_MESH_MODEL_OP_SENSOR_SERIES_STATUS,
+ // SENSOR_SETUP SENSOR_CADENCE
+ ESP_BLE_MESH_MODEL_OP_SENSOR_CADENCE_GET,
+ ESP_BLE_MESH_MODEL_OP_SENSOR_CADENCE_SET,
+ ESP_BLE_MESH_MODEL_OP_SENSOR_CADENCE_SET_UNACK,
+ ESP_BLE_MESH_MODEL_OP_SENSOR_CADENCE_STATUS,
+ // SENSOR SENSOR_COLUMN
+ ESP_BLE_MESH_MODEL_OP_SENSOR_SETTINGS_GET,
+ -1,
+ -1,
+ ESP_BLE_MESH_MODEL_OP_SENSOR_SETTINGS_STATUS,
+ // SENSOR SENSOR_SERIES
+ ESP_BLE_MESH_MODEL_OP_SENSOR_SETTING_GET,
+ ESP_BLE_MESH_MODEL_OP_SENSOR_SETTING_SET,
+ ESP_BLE_MESH_MODEL_OP_SENSOR_SETTING_SET_UNACK,
+ ESP_BLE_MESH_MODEL_OP_SENSOR_SETTING_STATUS,
+
+};
+
+// There is only one UUID, and it cannot be changed during runtime
+// TODO: why is this initialized with these 2 values ?
+static uint8_t dev_uuid[16] = { 0xdd, 0xdd };
+
+typedef union mod_ble_mesh_sensor_state_s {
+ float state_float;
+ uint8_t state_uint8[4];
+}mod_ble_mesh_sensor_state_t;
+
+// This is the same as esp_ble_mesh_elem_t just without const members
+typedef struct mod_ble_mesh_elem_s {
+ uint16_t element_addr;
+ uint16_t location;
+ uint8_t sig_model_count;
+ uint8_t vnd_model_count;
+ esp_ble_mesh_model_t *sig_models;
+ esp_ble_mesh_model_t *vnd_models;
+}mod_ble_mesh_elem_t;
+
+// This is the same as esp_ble_mesh_sensor_srv_t just without const members
+typedef struct mod_ble_mesh_sensor_srv_s {
+ esp_ble_mesh_model_t *model;
+ esp_ble_mesh_server_rsp_ctrl_t rsp_ctrl;
+ uint8_t state_count;
+ esp_ble_mesh_sensor_state_t *states;
+} mod_ble_mesh_sensor_srv_t;
+
+typedef struct mod_ble_mesh_element_class_s {
+ mp_obj_base_t base;
+ mod_ble_mesh_elem_t *element;
+}mod_ble_mesh_element_class_t;
+
+typedef struct mod_ble_mesh_sensor_state_class_s {
+ mp_obj_base_t base;
+ esp_ble_mesh_sensor_state_t *sensor_state;
+}mod_ble_mesh_sensor_state_class_t;
+
+typedef struct mod_ble_mesh_model_class_s {
+ mp_obj_base_t base;
+ struct mod_ble_mesh_model_class_s* next;
+ // Pointer to the element owns this model
+ mod_ble_mesh_element_class_t *element;
+ // Index in the esp ble context
+ uint8_t index;
+ // User defined MicroPython callback function
+ mp_obj_t callback;
+ // Value of the model to return to MicroPython
+ mp_obj_t value_mp_obj;
+ // Default Get Opcode
+ int32_t op_def_get;
+ // Default Set Opcode
+ int32_t op_def_set;
+ // Default Set_Unack Opcode
+ int32_t op_def_set_unack;
+ // Default Status Opcode
+ int32_t op_def_status;
+ // Store whether this is a Server or a Client Model
+ bool server_client;
+ // Store Model Type
+ uint8_t type;
+ // Store Model Group
+ uint8_t group;
+}mod_ble_mesh_model_class_t;
+
+typedef struct mod_ble_mesh_generic_server_callback_param_s {
+ esp_ble_mesh_generic_server_cb_event_t event;
+ esp_ble_mesh_generic_server_cb_param_t* param;
+}mod_ble_mesh_generic_server_callback_param_t;
+
+typedef struct mod_ble_mesh_generic_client_callback_param_s {
+ esp_ble_mesh_generic_client_cb_event_t event;
+ esp_ble_mesh_generic_client_cb_param_t* param;
+}mod_ble_mesh_generic_client_callback_param_t;
+
+typedef struct mod_ble_mesh_sensor_server_callback_param_s {
+ esp_ble_mesh_sensor_server_cb_event_t event;
+ esp_ble_mesh_sensor_server_cb_param_t* param;
+}mod_ble_mesh_sensor_server_callback_param_t;
+
+typedef struct mod_ble_mesh_sensor_client_callback_param_s {
+ esp_ble_mesh_sensor_client_cb_event_t event;
+ esp_ble_mesh_sensor_client_cb_param_t* param;
+}mod_ble_mesh_sensor_client_callback_param_t;
+
+typedef struct mod_ble_mesh_provision_callback_param_s {
+ mp_obj_t callback;
+ int8_t prov_event;
+ int8_t oob_key;
+}mod_ble_mesh_provision_callback_param_t;
+
+/******************************************************************************
+ DECLARE PRIVATE FUNCTIONS
+ ******************************************************************************/
+static mp_obj_t mod_ble_state_to_mp_obj(mod_ble_mesh_model_class_t* model, void* state_change);
+static esp_ble_mesh_generic_client_set_state_t mod_ble_mp_obj_to_state(mp_obj_t obj, mod_ble_mesh_model_class_t* model);
+static uint8_t get_sen_state_idx(mp_int_t prop_id);
+static uint16_t example_ble_mesh_get_sensor_data(esp_ble_mesh_sensor_state_t *state, uint8_t *data);
+
+/******************************************************************************
+ DEFINE PRIVATE VARIABLES
+ ******************************************************************************/
+
+static const mp_obj_type_t mod_ble_mesh_sensor_state_type;
+static const mp_obj_type_t mod_ble_mesh_model_type;
+// TODO: add support for more Elements
+static mod_ble_mesh_element_class_t mod_ble_mesh_element;
+// This is a list containing all the Models regardless their Elements
+static mod_ble_mesh_model_class_t *mod_ble_models_list = NULL;
+// Sensor Server
+static mod_ble_mesh_sensor_srv_t mod_ble_sensor_srv;
+
+static bool initialized = false;
+static esp_ble_mesh_prov_t *provision_ptr;
+static esp_ble_mesh_comp_t *composition_ptr;
+// TODO: double check whether this is needed
+static uint8_t msg_tid = 0x0;
+
+// TODO: This should be part of the primary element as provisioning is performed on it only
+mp_obj_t provision_callback;
+
+/******************************************************************************
+ DEFINE PRIVATE FUNCTIONS
+ ******************************************************************************/
+
+static mod_ble_mesh_model_class_t* mod_ble_add_model_to_list(mod_ble_mesh_element_class_t* ble_mesh_element,
+ uint8_t index,
+ mp_obj_t callback,
+ int32_t op_def_get,
+ int32_t op_def_set,
+ int32_t op_def_set_unack,
+ int32_t op_def_status,
+ mp_obj_t value_mp_obj,
+ bool server_client,
+ uint8_t type,
+ uint8_t group) {
+
+ mod_ble_mesh_model_class_t *model = mod_ble_models_list;
+ mod_ble_mesh_model_class_t *model_last = NULL; // Only needed as helper pointer for the case when the list is fully empty
+
+
+ // Find the last element of the list
+ while(model != NULL) {
+ // Save the last Model we checked
+ model_last = model;
+ // Jump to the next Model
+ model = model->next;
+ }
+
+ // Allocate memory for the new element
+ //TODO: check this allocation, it should be from GC controlled memory
+ model = (mod_ble_mesh_model_class_t*)heap_caps_malloc(sizeof(mod_ble_mesh_model_class_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
+ // Initialize the new Model
+ model->base.type = &mod_ble_mesh_model_type;
+ model->element = ble_mesh_element;
+ model->index = index;
+ model->callback = callback;
+ model->next = NULL;
+ model->op_def_get = op_def_get;
+ model->op_def_set = op_def_set;
+ model->op_def_set_unack = op_def_set_unack;
+ model->op_def_status = op_def_status;
+ model->value_mp_obj = value_mp_obj;
+ model->server_client = server_client;
+ model->type = type;
+ model->group = group;
+
+ // Add the new element to the list
+ if(model_last != NULL) {
+ model_last->next = model;
+ }
+ else {
+ // This means this new element is the very first one in the list
+ mod_ble_models_list = model;
+ }
+
+ return model;
+}
+
+static mod_ble_mesh_model_class_t* mod_ble_find_model(esp_ble_mesh_model_t *esp_ble_model) {
+
+ mod_ble_mesh_model_class_t *model = mod_ble_models_list;
+
+ // TODO: handle when we have more elements, first find the BLE Mesh Element using esp_ble_model->element reference
+
+ // The pointer to the Model directly cannot be used to match the incoming ESP BLE Model with MOD BLE Mesh model,
+ // because of some reasons the BLE Mesh library does not always use the same pointer what was saved into Element's model list, that's why the index must be used
+ // Iterate through on all the Models
+ while(model != NULL) {
+ if(model->index == esp_ble_model->model_idx) {
+ return model;
+ }
+ model = model->next;
+ }
+
+ return NULL;
+}
+
+static void mod_ble_mesh_generic_server_callback_handler(void* param_in) {
+
+ mod_ble_mesh_generic_server_callback_param_t* callback_param = (mod_ble_mesh_generic_server_callback_param_t*)param_in;
+ mod_ble_mesh_model_class_t* mod_ble_model = mod_ble_find_model(callback_param->param->model);
+
+ if(mod_ble_model != NULL) {
+
+ esp_ble_mesh_generic_server_cb_event_t event = callback_param->event;
+ esp_ble_mesh_generic_server_cb_param_t* param = callback_param->param;
+
+ switch (event) {
+ case ESP_BLE_MESH_GENERIC_SERVER_RECV_SET_MSG_EVT:
+ //printf("ESP_BLE_MESH_GENERIC_SERVER_RECV_SET_MSG_EVT\n");
+ // TODO: implement this case, for now let if falling through to STATE because
+ // ESP_BLE_MESH_SERVER_AUTO_RSP is set, so SET event will never come, only STATE
+ case ESP_BLE_MESH_GENERIC_SERVER_STATE_CHANGE_EVT:
+ //printf("ESP_BLE_MESH_GENERIC_SERVER_STATE_CHANGE_EVT\n");
+
+ // Publish that the State of this Server Model changed
+ if(mod_ble_model->callback != NULL) {
+ mp_obj_t args[4];
+ args[0] = mod_ble_state_to_mp_obj(mod_ble_model, &(param->value.state_change));
+ args[1] = mp_obj_new_int(param->ctx.addr);
+ args[2] = mp_obj_new_int(mod_ble_model->type);
+ args[3] = mp_const_none;
+ mp_call_function_n_kw(mod_ble_model->callback, 4, 0, args);
+ }
+ break;
+ case ESP_BLE_MESH_GENERIC_SERVER_RECV_GET_MSG_EVT:
+ //printf("ESP_BLE_MESH_GENERIC_SERVER_RECV_GET_MSG_EVT\n");
+ // TODO: double check this, should be automatically answered by the Mesh Library because ESP_BLE_MESH_SERVER_AUTO_RSP is set
+ break;
+ default:
+ // Handle it silently
+ break;
+ }
+ }
+}
+
+static void mod_ble_mesh_generic_client_callback_handler(void* param_in) {
+
+ mod_ble_mesh_generic_client_callback_param_t* callback_param = (mod_ble_mesh_generic_client_callback_param_t*)param_in;
+ mod_ble_mesh_model_class_t* mod_ble_model = mod_ble_find_model(callback_param->param->params->model);
+
+ if(mod_ble_model != NULL) {
+
+ esp_ble_mesh_generic_client_cb_event_t event = callback_param->event;
+ esp_ble_mesh_generic_client_cb_param_t* param = callback_param->param;
+
+ switch (event) {
+ case ESP_BLE_MESH_GENERIC_CLIENT_GET_STATE_EVT:
+ //printf("ESP_BLE_MESH_GENERIC_CLIENT_GET_STATE_EVT\n");
+ //TODO: figure out a generic way to handle this... it is not easy
+ break;
+ case ESP_BLE_MESH_GENERIC_CLIENT_SET_STATE_EVT:
+ //printf("ESP_BLE_MESH_GENERIC_CLIENT_SET_STATE_EVT\n");
+ break;
+ case ESP_BLE_MESH_GENERIC_CLIENT_PUBLISH_EVT:
+ //printf("ESP_BLE_MESH_GENERIC_CLIENT_PUBLISH_EVT\n");
+ //TODO: figure out a generic way to handle this... it is not easy
+ break;
+ case ESP_BLE_MESH_GENERIC_CLIENT_TIMEOUT_EVT:
+ //printf("ESP_BLE_MESH_GENERIC_CLIENT_TIMEOUT_EVT\n");
+ break;
+ default:
+ break;
+ }
+
+ if(mod_ble_model->callback != NULL) {
+ mp_obj_t args[4];
+ args[0] = mod_ble_state_to_mp_obj(mod_ble_model, (void*)&(param->status_cb));
+ args[1] = mp_obj_new_int(param->params->ctx.addr);
+ args[2] = mp_obj_new_int(mod_ble_model->type);
+ args[3] = mp_const_none;
+ mp_call_function_n_kw(mod_ble_model->callback, 4, 0, args);
+ }
+ }
+}
+
+static void mod_ble_mesh_sensor_server_callback_handler(void* param_in) {
+
+ mod_ble_mesh_sensor_server_callback_param_t* callback_param = (mod_ble_mesh_sensor_server_callback_param_t*)param_in;
+ mod_ble_mesh_model_class_t* mod_ble_model = mod_ble_find_model(callback_param->param->model);
+
+ if(mod_ble_model != NULL) {
+
+ esp_ble_mesh_sensor_server_cb_event_t event = callback_param->event;
+ esp_ble_mesh_sensor_server_cb_param_t* param = callback_param->param;
+
+ if (event == ESP_BLE_MESH_SENSOR_SERVER_RECV_GET_MSG_EVT) {
+ int8_t state_idx;
+ if(param->value.get.sensor_data.op_en) {
+ // Get Property ID from user
+ mp_int_t prop_id = param->value.get.sensor_data.property_id;
+ // Get Sensor State Index
+ state_idx = get_sen_state_idx(prop_id);
+ }
+ else {
+ state_idx = 0;
+ }
+
+ if(state_idx != -1) {
+ uint8_t *status = NULL;
+ uint16_t buf_size = 0;
+ uint16_t length = 0;
+
+ esp_ble_mesh_sensor_state_t *state = &mod_ble_sensor_srv.states[state_idx];
+
+ if (state->sensor_data.length == ESP_BLE_MESH_SENSOR_DATA_ZERO_LEN) {
+ buf_size += ESP_BLE_MESH_SENSOR_DATA_FORMAT_B_MPID_LEN;
+ } else {
+ // Use "state->sensor_data.length + 3" because sending 4 uint8
+ if (state->sensor_data.format == ESP_BLE_MESH_SENSOR_DATA_FORMAT_A) {
+ buf_size += ESP_BLE_MESH_SENSOR_DATA_FORMAT_A_MPID_LEN + state->sensor_data.length + 3;
+ } else {
+ buf_size += ESP_BLE_MESH_SENSOR_DATA_FORMAT_B_MPID_LEN + state->sensor_data.length + 3;
+ }
+ }
+
+ status = calloc(1, buf_size);
+ length = example_ble_mesh_get_sensor_data(&mod_ble_sensor_srv.states[state_idx], status);
+
+ esp_ble_mesh_server_model_send_msg((esp_ble_mesh_model_t*)¶m->ctx.model, ¶m->ctx, ESP_BLE_MESH_MODEL_OP_SENSOR_STATUS, length, status);
+ free(status);
+ }
+ }
+ }
+}
+
+static void mod_ble_mesh_sensor_client_callback_handler(void* param_in) {
+
+ mod_ble_mesh_sensor_client_callback_param_t* callback_param = (mod_ble_mesh_sensor_client_callback_param_t*)param_in;
+ mod_ble_mesh_model_class_t* mod_ble_model = mod_ble_find_model(callback_param->param->params->model);
+
+ if(mod_ble_model != NULL) {
+
+ esp_ble_mesh_sensor_client_cb_event_t event = callback_param->event;
+ esp_ble_mesh_sensor_client_cb_param_t* param = callback_param->param;
+
+ if (mod_ble_model->callback != NULL && event == ESP_BLE_MESH_SENSOR_CLIENT_PUBLISH_EVT && param->status_cb.sensor_status.marshalled_sensor_data->len) {
+ // Get Prop ID
+ uint8_t *data = param->status_cb.sensor_status.marshalled_sensor_data->__buf;
+ uint8_t fmt = ESP_BLE_MESH_GET_SENSOR_DATA_FORMAT(data);
+ uint16_t prop_id = ESP_BLE_MESH_GET_SENSOR_DATA_PROPERTY_ID(data, fmt);
+
+ mp_obj_t args[4];
+ args[0] = mod_ble_state_to_mp_obj(mod_ble_model, (void*)&(param->status_cb));
+ args[1] = mp_obj_new_int(param->params->ctx.addr);
+ args[2] = mp_obj_new_int(mod_ble_model->type);
+ args[3] = mp_obj_new_int(prop_id);
+
+ mp_call_function_n_kw(mod_ble_model->callback, 4, 0, args);
+ }
+ }
+}
+
+STATIC void mod_ble_mesh_provision_callback_call_mp_callback(void* param_in) {
+
+ mod_ble_mesh_provision_callback_param_t* callback_param = (mod_ble_mesh_provision_callback_param_t*)param_in;
+ mp_obj_t args[2];
+ // GET OOB Type
+ args[0] = mp_obj_new_int(callback_param->prov_event);
+
+ if(callback_param->prov_event == ESP_BLE_MESH_NODE_PROV_OUTPUT_NUMBER_EVT) {
+ //OOB Key
+ args[1] = mp_obj_new_int(callback_param->oob_key);
+ }
+ else {
+ //Invalid OOB Key
+ args[1] = mp_const_none;
+ }
+
+ // Call the user registered MicroPython function
+ mp_call_function_n_kw(callback_param->callback, 2, 0, args);
+
+ // Free callback_param
+ heap_caps_free(callback_param);
+}
+
+static void mod_ble_mesh_provision_callback(esp_ble_mesh_prov_cb_event_t event, esp_ble_mesh_prov_cb_param_t *param) {
+ mod_ble_mesh_provision_callback_param_t* callback_param_ptr = NULL;
+
+ if(provision_callback != NULL) {
+ callback_param_ptr = (mod_ble_mesh_provision_callback_param_t *)heap_caps_malloc(sizeof(mod_ble_mesh_provision_callback_param_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
+ callback_param_ptr->callback = provision_callback;
+ callback_param_ptr->prov_event = event;
+
+ if (event == ESP_BLE_MESH_NODE_PROV_OUTPUT_NUMBER_EVT) {
+ callback_param_ptr->oob_key = param->node_prov_output_num.number;
+ }
+
+ if(callback_param_ptr != NULL) {
+ // The user registered MicroPython callback will be called decoupled from the BLE Mesh context in the IRQ Task
+ mp_irq_queue_interrupt(mod_ble_mesh_provision_callback_call_mp_callback, (void *)callback_param_ptr);
+ }
+ }
+}
+
+static void mod_ble_mesh_generic_client_callback(esp_ble_mesh_generic_client_cb_event_t event, esp_ble_mesh_generic_client_cb_param_t *param) {
+
+ mod_ble_mesh_generic_client_callback_param_t* callback_param_ptr = (mod_ble_mesh_generic_client_callback_param_t *)heap_caps_malloc(sizeof(mod_ble_mesh_generic_server_callback_param_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
+ callback_param_ptr->param = (esp_ble_mesh_generic_client_cb_param_t *)heap_caps_malloc(sizeof(esp_ble_mesh_generic_client_cb_param_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
+ callback_param_ptr->param->params = (esp_ble_mesh_client_common_param_t *)heap_caps_malloc(sizeof(esp_ble_mesh_client_common_param_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
+
+ callback_param_ptr->event = event;
+ memcpy(callback_param_ptr->param, param, sizeof(esp_ble_mesh_generic_client_cb_param_t));
+ memcpy(callback_param_ptr->param->params, param->params, sizeof(esp_ble_mesh_client_common_param_t));
+
+ // The registered callback will be handled in context of TASK_Interrupts
+ mp_irq_queue_interrupt_non_ISR(mod_ble_mesh_generic_client_callback_handler, (void *)callback_param_ptr);
+}
+
+static void mod_ble_mesh_generic_server_callback(esp_ble_mesh_generic_server_cb_event_t event, esp_ble_mesh_generic_server_cb_param_t *param) {
+
+ mod_ble_mesh_generic_server_callback_param_t* callback_param_ptr = (mod_ble_mesh_generic_server_callback_param_t *)heap_caps_malloc(sizeof(mod_ble_mesh_generic_server_callback_param_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
+ callback_param_ptr->param = (esp_ble_mesh_generic_server_cb_param_t *)heap_caps_malloc(sizeof(esp_ble_mesh_generic_server_cb_param_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
+
+ callback_param_ptr->event = event;
+ memcpy(callback_param_ptr->param, param, sizeof(esp_ble_mesh_generic_server_cb_param_t));
+
+ // The registered callback will be handled in context of TASK_Interrupts
+ mp_irq_queue_interrupt_non_ISR(mod_ble_mesh_generic_server_callback_handler, (void *)callback_param_ptr);
+
+}
+
+static void mod_ble_mesh_sensor_server_callback(esp_ble_mesh_sensor_server_cb_event_t event,
+ esp_ble_mesh_sensor_server_cb_param_t *param) {
+
+ mod_ble_mesh_sensor_server_callback_param_t* callback_param_ptr = (mod_ble_mesh_sensor_server_callback_param_t *)heap_caps_malloc(sizeof(mod_ble_mesh_sensor_server_callback_param_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
+ callback_param_ptr->param = (esp_ble_mesh_sensor_server_cb_param_t *)heap_caps_malloc(sizeof(esp_ble_mesh_sensor_server_cb_param_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
+
+ callback_param_ptr->event = event;
+ memcpy(callback_param_ptr->param, param, sizeof(esp_ble_mesh_sensor_server_cb_param_t));
+
+ // The registered callback will be handled in context of TASK_Interrupts
+ mp_irq_queue_interrupt_non_ISR(mod_ble_mesh_sensor_server_callback_handler, (void *)callback_param_ptr);
+
+}
+
+static void mod_ble_mesh_sensor_client_callback(esp_ble_mesh_sensor_client_cb_event_t event,
+ esp_ble_mesh_sensor_client_cb_param_t *param) {
+
+ mod_ble_mesh_sensor_client_callback_param_t* callback_param_ptr = (mod_ble_mesh_sensor_client_callback_param_t *)heap_caps_malloc(sizeof(mod_ble_mesh_sensor_client_callback_param_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
+ callback_param_ptr->param = (esp_ble_mesh_sensor_client_cb_param_t *)heap_caps_malloc(sizeof(esp_ble_mesh_sensor_client_cb_param_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
+
+ callback_param_ptr->event = event;
+ memcpy(callback_param_ptr->param, param, sizeof(esp_ble_mesh_sensor_client_cb_param_t));
+
+ // The registered callback will be handled in context of TASK_Interrupts
+ mp_irq_queue_interrupt_non_ISR(mod_ble_mesh_sensor_client_callback_handler, (void *)callback_param_ptr);
+
+}
+
+static void mod_ble_mesh_config_server_callback(esp_ble_mesh_cfg_server_cb_event_t event, esp_ble_mesh_cfg_server_cb_param_t *param) {
+
+ // TODO: here the user registered MicroPython API should be called with correct parameters via the Interrupt Task
+
+ if (event == ESP_BLE_MESH_CFG_SERVER_STATE_CHANGE_EVT) {
+ switch (param->ctx.recv_op) {
+ case ESP_BLE_MESH_MODEL_OP_APP_KEY_ADD:
+ printf("ESP_BLE_MESH_MODEL_OP_APP_KEY_ADD\n");
+ printf("net_idx 0x%04x, app_idx 0x%04x\n",
+ param->value.state_change.appkey_add.net_idx,
+ param->value.state_change.appkey_add.app_idx);
+ break;
+ case ESP_BLE_MESH_MODEL_OP_MODEL_APP_BIND:
+ printf("ESP_BLE_MESH_MODEL_OP_MODEL_APP_BIND\n");
+ printf("elem_addr 0x%04x, app_idx 0x%04x, cid 0x%04x, mod_id 0x%04x\n",
+ param->value.state_change.mod_app_bind.element_addr,
+ param->value.state_change.mod_app_bind.app_idx,
+ param->value.state_change.mod_app_bind.company_id,
+ param->value.state_change.mod_app_bind.model_id);
+ break;
+ case ESP_BLE_MESH_MODEL_OP_MODEL_SUB_ADD:
+ printf("ESP_BLE_MESH_MODEL_OP_MODEL_SUB_ADD\n");
+ printf("elem_addr 0x%04x, sub_addr 0x%04x, cid 0x%04x, mod_id 0x%04x\n",
+ param->value.state_change.mod_sub_add.element_addr,
+ param->value.state_change.mod_sub_add.sub_addr,
+ param->value.state_change.mod_sub_add.company_id,
+ param->value.state_change.mod_sub_add.model_id);
+ break;
+ case ESP_BLE_MESH_MODEL_OP_MODEL_PUB_SET:
+ printf("ESP_BLE_MESH_MODEL_OP_MODEL_PUB_SET\n");
+ printf("elem_addr 0x%04x, pub_addr 0x%04x, pub_period %d, mod_id 0x%04x\n",
+ param->value.state_change.mod_pub_set.element_addr,
+ param->value.state_change.mod_pub_set.pub_addr,
+ param->value.state_change.mod_pub_set.pub_period,
+ param->value.state_change.mod_pub_set.model_id);
+ break;
+ default:
+ //TODO: we need to handle all types of event coming from Configuration Client (Provisioner) !
+ break;
+ }
+ }
+}
+
+// Returns MicroPython object from C structure
+static mp_obj_t mod_ble_state_to_mp_obj(mod_ble_mesh_model_class_t* model, void* state_change) {
+
+ mp_obj_t ret = mp_const_none;
+
+ if(model->server_client == MOD_BLE_MESH_SERVER) {
+ if(model->group == MOD_BLE_MESH_GROUP_GENERIC) {
+ esp_ble_mesh_generic_server_state_change_t* state_change_server;
+ state_change_server = (esp_ble_mesh_generic_server_state_change_t*) state_change;
+ if(model->type == MOD_BLE_MESH_MODEL_GEN_ONOFF) {
+ esp_ble_mesh_gen_onoff_srv_t *srv = model->element->element->sig_models[model->index].user_data;
+ if(state_change == NULL) {
+ ret = mp_obj_new_bool(srv->state.onoff);
+ } else {
+ ret = mp_obj_new_bool(state_change_server->onoff_set.onoff);
+ }
+ }
+ else if(model->type == MOD_BLE_MESH_MODEL_GEN_LEVEL) {
+ esp_ble_mesh_gen_level_srv_t *srv = model->element->element->sig_models[model->index].user_data;
+ if(state_change == NULL) {
+ ret = mp_obj_new_int(srv->state.level);
+ } else {
+ ret = mp_obj_new_int(state_change_server->level_set.level);
+ }
+ }
+ }
+ } else {
+ if(model->group == MOD_BLE_MESH_GROUP_GENERIC) {
+ esp_ble_mesh_gen_client_status_cb_t* state_change_client;
+ state_change_client = (esp_ble_mesh_gen_client_status_cb_t*) state_change;
+ if(model->type == MOD_BLE_MESH_MODEL_GEN_ONOFF) {
+ ret = mp_obj_new_bool(state_change_client->onoff_status.present_onoff);
+ }
+ else if(model->type == MOD_BLE_MESH_MODEL_GEN_LEVEL) {
+ ret = mp_obj_new_int(state_change_client->level_status.present_level);
+ }
+ }
+ else if(model->group == MOD_BLE_MESH_GROUP_SENSOR) {
+ esp_ble_mesh_sensor_client_status_cb_t* state_change_client;
+ state_change_client = (esp_ble_mesh_sensor_client_status_cb_t*) state_change;
+ if(model->type == MOD_BLE_MESH_MODEL_SENSOR) {
+ // GET the state of Sensor Server
+ uint8_t *data = state_change_client->sensor_status.marshalled_sensor_data->__buf;
+ uint8_t fmt = ESP_BLE_MESH_GET_SENSOR_DATA_FORMAT(data);
+ // Not used yet
+ //uint16_t prop_id = ESP_BLE_MESH_GET_SENSOR_DATA_PROPERTY_ID(data, fmt);
+ uint8_t mpid_len = (fmt == ESP_BLE_MESH_SENSOR_DATA_FORMAT_A ? ESP_BLE_MESH_SENSOR_DATA_FORMAT_A_MPID_LEN : ESP_BLE_MESH_SENSOR_DATA_FORMAT_B_MPID_LEN);
+
+ // GET the state of Sensor Server
+
+ mod_ble_mesh_sensor_state_t state;
+ state.state_uint8[0] = *(data + mpid_len);
+ state.state_uint8[1] = *(data + mpid_len + 1);
+ state.state_uint8[2] = *(data + mpid_len + 2);
+ state.state_uint8[3] = *(data + mpid_len + 3);
+
+ ret = mp_obj_new_float(state.state_float);
+ }
+ }
+ }
+ return ret;
+}
+
+// Sets Server Model state or returns Client set structure for Get request
+static esp_ble_mesh_generic_client_set_state_t mod_ble_mp_obj_to_state(mp_obj_t obj, mod_ble_mesh_model_class_t* model) {
+ esp_ble_mesh_generic_client_set_state_t set;
+
+ if(model->server_client == MOD_BLE_MESH_SERVER) {
+ // Server
+ if(model->type == MOD_BLE_MESH_MODEL_GEN_ONOFF) {
+ esp_ble_mesh_gen_onoff_srv_t *srv = model->element->element->sig_models[model->index].user_data;
+ srv->state.onoff = mp_obj_get_int(obj);
+ }
+ if(model->type == MOD_BLE_MESH_MODEL_GEN_LEVEL) {
+ esp_ble_mesh_gen_level_srv_t *srv = model->element->element->sig_models[model->index].user_data;
+ srv->state.level = mp_obj_get_int(obj);
+ }
+ } else {
+ // Client
+
+ if(model->type == MOD_BLE_MESH_MODEL_GEN_ONOFF) {
+ set.onoff_set.onoff = mp_obj_get_int(obj);
+ set.onoff_set.op_en = false;
+ set.onoff_set.tid = msg_tid++;
+ }
+ if(model->type == MOD_BLE_MESH_MODEL_GEN_LEVEL) {
+ set.level_set.level = mp_obj_get_int(obj);
+ set.level_set.op_en = false;
+ set.level_set.tid = msg_tid++;
+ }
+ }
+ return set;
+}
+
+// Get Sensor State Index defined by Property ID
+static uint8_t get_sen_state_idx(mp_int_t prop_id) {
+ // Invalidate State Index
+ int8_t state_idx = -1;
+
+ // Get First element if Property ID is not given
+ if(prop_id == -1) {
+ state_idx = 0;
+ }
+ else {
+ for(int8_t i=0; iserver_client == MOD_BLE_MESH_SERVER) {
+
+ if(self->group == MOD_BLE_MESH_GROUP_GENERIC) {
+ // GET the state of Generic Server
+ return mod_ble_state_to_mp_obj(self, NULL);
+ }
+ else if(self->group == MOD_BLE_MESH_GROUP_SENSOR) {
+ if(mod_ble_sensor_srv.state_count > 0) {
+ // Get Property ID from user
+ mp_int_t prop_id = args[4].u_int;
+ // Get Sensor State Index
+ int8_t state_idx = get_sen_state_idx(prop_id);
+
+ if(state_idx != -1) {
+ // GET the state of Sensor Server
+ mod_ble_mesh_sensor_state_t state;
+ state.state_uint8[0] = mod_ble_sensor_srv.states[state_idx].sensor_data.raw_value->data[0];
+ state.state_uint8[1] = mod_ble_sensor_srv.states[state_idx].sensor_data.raw_value->data[1];
+ state.state_uint8[2] = mod_ble_sensor_srv.states[state_idx].sensor_data.raw_value->data[2];
+ state.state_uint8[3] = mod_ble_sensor_srv.states[state_idx].sensor_data.raw_value->data[3];
+
+ return mp_obj_new_float(state.state_float);
+ }
+ else {
+ return mp_const_none;
+ }
+ }
+ else {
+ return mp_const_none;
+ }
+ }
+ else {
+ return mp_const_none;
+ }
+
+ } else {
+ // Fetch parameters
+ uint16_t addr = args[1].u_int;
+ uint16_t app_idx = args[2].u_int;
+ mp_obj_t state_type = args[3].u_obj;
+
+ // Fetch default opcode
+ int32_t opcode = self->op_def_get;
+
+ if(state_type != mp_const_none) {
+ // Get opcode if state is defined
+ opcode = opcode_table[self->type + mp_obj_get_int(state_type) + MOD_BLE_MESH_REQ_GET];
+ }
+
+ if(opcode == -1) {
+ // Error if Get request is not possible on state
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_RuntimeError, "Cannot Get this State!"));
+ }
+
+ // Setup CTX
+ esp_ble_mesh_msg_ctx_t ctx;
+ ctx.net_idx = 0;
+ ctx.app_idx = app_idx;
+ ctx.addr = addr;
+ ctx.send_ttl = 3;
+ ctx.send_rel = false;
+
+ if(self->group == MOD_BLE_MESH_GROUP_GENERIC) {
+ // GET the state of Generic Server
+ uint8_t* data = (uint8_t*)calloc(11, sizeof(uint8_t));
+ esp_ble_mesh_client_model_send_msg(&self->element->element->sig_models[self->index], &ctx, opcode, 11, data, 100, 0, ROLE_NODE);
+ }
+ else if(self->group == MOD_BLE_MESH_GROUP_SENSOR) {
+ // Get the state of Sensor Server
+ esp_ble_mesh_sensor_client_get_state_t get = {0};
+ esp_ble_mesh_client_common_param_t common = {0};
+
+ common.opcode = ESP_BLE_MESH_MODEL_OP_SENSOR_GET;
+ common.model = &self->element->element->sig_models[self->index];
+ common.ctx = ctx;
+ common.msg_timeout = 100;
+ common.msg_role = ROLE_NODE;
+
+ // Property ID
+ if(args[4].u_int == -1) {
+ get.sensor_get.op_en = false;
+ }
+ else {
+ get.sensor_get.op_en = true;
+ get.sensor_get.property_id = args[4].u_int;
+ }
+
+ /*if(args[4].u_int == -1) {
+ // Error if Set request is not possible on state
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_RuntimeError, "Property ID is not defined!"));
+ }
+ else {
+ get.sensor_get.property_id = args[4].u_int;
+ }*/
+
+
+ esp_ble_mesh_sensor_client_get_state(&common, &get);
+ }
+
+ return mp_const_none;
+ }
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mod_ble_mesh_model_get_state_obj, 1, mod_ble_mesh_model_get_state);
+
+// Sending out Set State message and updating the value of the Model
+STATIC mp_obj_t mod_ble_mesh_model_set_state(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+
+ STATIC const mp_arg_t mod_ble_mesh_model_set_state_args[] = {
+ { MP_QSTR_self_in, MP_ARG_OBJ, },
+ { MP_QSTR_value, MP_ARG_OBJ | MP_ARG_REQUIRED, },
+ { MP_QSTR_addr, MP_ARG_INT, {.u_int = MOD_BLE_ADDR_ALL_NODES} },
+ { MP_QSTR_app_idx, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 0} },
+ { MP_QSTR_state_type, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = mp_const_none} },
+ { MP_QSTR_prop_id, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = -1} },
+ };
+
+ mp_arg_val_t args[MP_ARRAY_SIZE(mod_ble_mesh_model_set_state_args)];
+ mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(args), mod_ble_mesh_model_set_state_args, args);
+
+ // Get Mod BLE Mesh Model
+ mod_ble_mesh_model_class_t* self = (mod_ble_mesh_model_class_t*)args[0].u_obj;
+
+ // Fetch parameters
+ mp_obj_t state_mp = args[1].u_obj;
+ uint16_t addr = args[2].u_int;
+ uint16_t app_idx = args[3].u_int;
+ mp_obj_t state_type = args[4].u_obj;
+
+ if(self->server_client == MOD_BLE_MESH_SERVER) {
+
+ if(self->group == MOD_BLE_MESH_GROUP_GENERIC) {
+ // SET the state of Generic Server
+ mod_ble_mp_obj_to_state(state_mp, self);
+
+ // Inform user through callback
+ if(self->callback != NULL) {
+ mp_obj_t args[4];
+ args[0] = mod_ble_state_to_mp_obj(self, NULL);
+ //TODO: Get address
+ args[1] = mp_const_none;
+ args[2] = mp_obj_new_int(self->type);
+ args[3] = mp_const_none;
+ mp_call_function_n_kw(self->callback, 4, 0, args);
+ }
+ }
+ else if(self->group == MOD_BLE_MESH_GROUP_SENSOR) {
+ // Get Property ID from user
+ mp_int_t prop_id = args[5].u_int;
+ // Get Sensor State Index
+ int8_t state_idx = get_sen_state_idx(prop_id);
+
+ if(state_idx != -1) {
+ // SET the state of Sensor Server as 4 uint8_t values
+ mod_ble_mesh_sensor_state_t state;
+ state.state_float = mp_obj_get_float(state_mp);
+
+ mod_ble_sensor_srv.states[state_idx].sensor_data.raw_value->data[0] = state.state_uint8[0];
+ mod_ble_sensor_srv.states[state_idx].sensor_data.raw_value->data[1] = state.state_uint8[1];
+ mod_ble_sensor_srv.states[state_idx].sensor_data.raw_value->data[2] = state.state_uint8[2];
+ mod_ble_sensor_srv.states[state_idx].sensor_data.raw_value->data[3] = state.state_uint8[3];
+
+ // Inform user through callback
+ if(self->callback != NULL) {
+ mp_obj_t args[4];
+ args[0] = mp_obj_new_float(state.state_float);
+ //TODO: Get address
+ args[1] = mp_const_none;
+ args[2] = mp_obj_new_int(self->type);
+ if(prop_id == -1) {
+ args[3] = mp_obj_new_int(mod_ble_sensor_srv.states[0].sensor_property_id);
+ }
+ else {
+ args[3] = mp_obj_new_int(prop_id);
+ }
+ mp_call_function_n_kw(self->callback, 4, 0, args);
+ }
+ }
+ }
+ } else {
+
+ // Fetch default opcode
+ int32_t opcode = self->op_def_set_unack;
+
+ if(state_type != mp_const_none) {
+ // Get opcode if state is defined
+ opcode = opcode_table[self->type + mp_obj_get_int(state_type) + MOD_BLE_MESH_REQ_SET_UNACK];
+ }
+
+ if(opcode == -1) {
+ // Error if Set request is not possible on state
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_RuntimeError, "Cannot Set this State!"));
+ }
+
+ if(self->group == MOD_BLE_MESH_GROUP_GENERIC) {
+
+ // Send a Set request from Client to Server
+ esp_ble_mesh_generic_client_set_state_t set = mod_ble_mp_obj_to_state(state_mp, self);
+ esp_ble_mesh_client_common_param_t common = {0};
+
+ // Set required options
+ common.opcode = opcode;
+ common.model = &self->element->element->sig_models[self->index];
+ common.ctx.net_idx = 0;
+ common.ctx.app_idx = app_idx;
+ common.ctx.addr = addr;
+ common.ctx.send_ttl = 3;
+ common.ctx.send_rel = false;
+ common.msg_timeout = 100;
+ common.msg_role = ROLE_NODE;
+
+ // Send set state
+ esp_ble_mesh_generic_client_set_state(&common, &set);
+ }
+ else if(self->group == MOD_BLE_MESH_GROUP_SENSOR) {
+ // TODO: Sensor SetState Features
+ }
+ }
+
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mod_ble_mesh_model_set_state_obj, 1, mod_ble_mesh_model_set_state);
+
+// Sending out Set State message and updating the value of the Model
+STATIC mp_obj_t mod_ble_mesh_model_status_state(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+
+ STATIC const mp_arg_t mod_ble_mesh_model_status_state_args[] = {
+ { MP_QSTR_self_in, MP_ARG_OBJ, },
+ { MP_QSTR_addr, MP_ARG_INT, {.u_int = MOD_BLE_ADDR_ALL_NODES} },
+ { MP_QSTR_app_idx, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 0} },
+ { MP_QSTR_state_type, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = mp_const_none} },
+ { MP_QSTR_prop_id, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = -1} },
+ };
+
+ mp_arg_val_t args[MP_ARRAY_SIZE(mod_ble_mesh_model_status_state_args)];
+ mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(args), mod_ble_mesh_model_status_state_args, args);
+
+ // Get Mod BLE Mesh Model
+ mod_ble_mesh_model_class_t* self = (mod_ble_mesh_model_class_t*)args[0].u_obj;
+
+ // Fetch parameters
+ uint16_t addr = args[1].u_int;
+ uint16_t app_idx = args[2].u_int;
+ mp_obj_t state_type = args[3].u_obj;
+
+ if(self->server_client == MOD_BLE_MESH_SERVER) {
+
+ // Fetch default opcode
+ int32_t opcode = self->op_def_status;
+
+ if(state_type != mp_const_none) {
+ // Get opcode if state is defined
+ opcode = opcode_table[self->type + mp_obj_get_int(state_type) + MOD_BLE_MESH_REQ_STATE];
+ }
+
+ if(opcode == -1) {
+ // Error if Status request is not possible on state
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_RuntimeError, "Cannot send Status of this State!"));
+ }
+
+ // Setup CTX
+ esp_ble_mesh_msg_ctx_t ctx;
+ ctx.net_idx = 0;
+ ctx.app_idx = app_idx;
+ ctx.addr = addr;
+ ctx.send_ttl = 3;
+ ctx.send_rel = false;
+
+ if(self->group == MOD_BLE_MESH_GROUP_GENERIC) {
+
+ if(self->type == MOD_BLE_MESH_MODEL_GEN_ONOFF) {
+ // Send Status of Generic OnOff Server State
+ esp_ble_mesh_gen_onoff_srv_t *srv = self->element->element->sig_models[self->index].user_data;
+ esp_ble_mesh_server_model_send_msg(&self->element->element->sig_models[self->index], &ctx, opcode, sizeof(srv->state.onoff), (uint8_t*)&srv->state.onoff);
+ }
+ else if(self->type == MOD_BLE_MESH_MODEL_GEN_LEVEL) {
+ // Send Status of Generic Level Server State
+ esp_ble_mesh_gen_level_srv_t *srv = self->element->element->sig_models[self->index].user_data;
+ esp_ble_mesh_server_model_send_msg(&self->element->element->sig_models[self->index], &ctx, opcode, sizeof(srv->state.level), (uint8_t*)&srv->state.level);
+ }
+ }
+ else if(self->group == MOD_BLE_MESH_GROUP_SENSOR) {
+
+ // Get Property ID from user
+ mp_int_t prop_id = args[4].u_int;
+ // Get Sensor State Index
+ int8_t state_idx = get_sen_state_idx(prop_id);
+
+ if(state_idx != -1) {
+ uint8_t *status = NULL;
+ uint16_t buf_size = 0;
+ uint16_t length = 0;
+
+ esp_ble_mesh_sensor_state_t *state = &mod_ble_sensor_srv.states[state_idx];
+
+ if (state->sensor_data.length == ESP_BLE_MESH_SENSOR_DATA_ZERO_LEN) {
+ buf_size += ESP_BLE_MESH_SENSOR_DATA_FORMAT_B_MPID_LEN;
+ } else {
+ // Use "state->sensor_data.length + 3" because sending 4 uint8
+ if (state->sensor_data.format == ESP_BLE_MESH_SENSOR_DATA_FORMAT_A) {
+ buf_size += ESP_BLE_MESH_SENSOR_DATA_FORMAT_A_MPID_LEN + state->sensor_data.length + 3;
+ } else {
+ buf_size += ESP_BLE_MESH_SENSOR_DATA_FORMAT_B_MPID_LEN + state->sensor_data.length + 3;
+ }
+ }
+
+ status = calloc(1, buf_size);
+ length = example_ble_mesh_get_sensor_data(&mod_ble_sensor_srv.states[state_idx], status);
+
+ esp_ble_mesh_server_model_send_msg(&self->element->element->sig_models[self->index], &ctx, ESP_BLE_MESH_MODEL_OP_SENSOR_STATUS, length, status);
+ free(status);
+ }
+ }
+
+ return mp_const_none;
+
+ } else {
+ // Error if State request is not possible on state
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_RuntimeError, "Cannot Send Status from Client!"));
+ }
+
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mod_ble_mesh_model_status_state_obj, 1, mod_ble_mesh_model_status_state);
+
+// Add Sensor
+STATIC mp_obj_t mod_ble_mesh_model_add_sensor(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+
+ STATIC const mp_arg_t mod_ble_mesh_model_add_sensor_args[] = {
+ { MP_QSTR_self_in, MP_ARG_OBJ, },
+ { MP_QSTR_prop_id, MP_ARG_INT, {.u_int = 0} },
+ };
+
+ mp_arg_val_t args[MP_ARRAY_SIZE(mod_ble_mesh_model_add_sensor_args)];
+ mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(args), mod_ble_mesh_model_add_sensor_args, args);
+
+ // Get Mod BLE Mesh Model
+ mod_ble_mesh_model_class_t* self = (mod_ble_mesh_model_class_t*)args[0].u_obj;
+ uint8_t prop_id = args[1].u_int;
+
+ if(self->group == MOD_BLE_MESH_GROUP_SENSOR && self->server_client == MOD_BLE_MESH_SERVER) {
+
+ for(int i=0; i__buf = net_buf_data;
+ buf->data = net_buf_data;
+ buf->len = 0;
+ buf->size = 4;
+
+ mod_ble_sensor_srv.states[mod_ble_sensor_srv.state_count].sensor_property_id = prop_id;
+ mod_ble_sensor_srv.states[mod_ble_sensor_srv.state_count].descriptor.positive_tolerance = ESP_BLE_MESH_SENSOR_UNSPECIFIED_POS_TOLERANCE;
+ mod_ble_sensor_srv.states[mod_ble_sensor_srv.state_count].descriptor.negative_tolerance = ESP_BLE_MESH_SENSOR_UNSPECIFIED_NEG_TOLERANCE;
+ mod_ble_sensor_srv.states[mod_ble_sensor_srv.state_count].descriptor.sampling_function = ESP_BLE_MESH_SAMPLE_FUNC_UNSPECIFIED;
+ mod_ble_sensor_srv.states[mod_ble_sensor_srv.state_count].descriptor.measure_period = ESP_BLE_MESH_SENSOR_NOT_APPL_MEASURE_PERIOD;
+ mod_ble_sensor_srv.states[mod_ble_sensor_srv.state_count].descriptor.update_interval = ESP_BLE_MESH_SENSOR_NOT_APPL_UPDATE_INTERVAL;
+ mod_ble_sensor_srv.states[mod_ble_sensor_srv.state_count].sensor_data.format = ESP_BLE_MESH_SENSOR_DATA_FORMAT_A;
+ mod_ble_sensor_srv.states[mod_ble_sensor_srv.state_count].sensor_data.length = 1;
+ mod_ble_sensor_srv.states[mod_ble_sensor_srv.state_count].sensor_data.raw_value = buf;
+
+ // Initialize the new Sensor Server State
+ mod_ble_mesh_sensor_state_class_t* sensor = (mod_ble_mesh_sensor_state_class_t*)heap_caps_malloc(sizeof(mod_ble_mesh_sensor_state_class_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
+ sensor->base.type = &mod_ble_mesh_sensor_state_type;
+ sensor->sensor_state = &mod_ble_sensor_srv.states[mod_ble_sensor_srv.state_count];
+
+ // Increase Number of States
+ mod_ble_sensor_srv.state_count = mod_ble_sensor_srv.state_count + 1;
+
+ return sensor;
+ }
+ else {
+ // Error if not Sensor Server Model
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_RuntimeError, "This operation is only allowed on Sensor Server Model!"));
+ }
+
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mod_ble_mesh_model_add_sensor_obj, 1, mod_ble_mesh_model_add_sensor);
+
+STATIC const mp_map_elem_t mod_ble_mesh_model_locals_dict_table[] = {
+ { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_BLE_Mesh_Model) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_get_state), (mp_obj_t)&mod_ble_mesh_model_get_state_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_set_state), (mp_obj_t)&mod_ble_mesh_model_set_state_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_status_state), (mp_obj_t)&mod_ble_mesh_model_status_state_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_add_sensor), (mp_obj_t)&mod_ble_mesh_model_add_sensor_obj },
+
+};
+STATIC MP_DEFINE_CONST_DICT(mod_ble_mesh_model_locals_dict, mod_ble_mesh_model_locals_dict_table);
+
+static const mp_obj_type_t mod_ble_mesh_model_type = {
+ { &mp_type_type },
+ .name = MP_QSTR_BLE_Mesh_Model,
+ .locals_dict = (mp_obj_t)&mod_ble_mesh_model_locals_dict,
+};
+/******************************************************************************
+ DEFINE BLE MESH ELEMENT FUNCTIONS
+ ******************************************************************************/
+
+static uint16_t example_ble_mesh_get_sensor_data(esp_ble_mesh_sensor_state_t *state, uint8_t *data)
+{
+ uint8_t mpid_len = 0, data_len = 0;
+ uint32_t mpid = 0;
+
+ if (state == NULL || data == NULL) {
+ printf("Invalid parameter\n");
+ return 0;
+ }
+
+ if (state->sensor_data.length == ESP_BLE_MESH_SENSOR_DATA_ZERO_LEN) {
+ /* For zero-length sensor data, the length is 0x7F, and the format is Format B. */
+ mpid = ESP_BLE_MESH_SENSOR_DATA_FORMAT_B_MPID(state->sensor_data.length, state->sensor_property_id);
+ mpid_len = ESP_BLE_MESH_SENSOR_DATA_FORMAT_B_MPID_LEN;
+ data_len = 0;
+ } else {
+ if (state->sensor_data.format == ESP_BLE_MESH_SENSOR_DATA_FORMAT_A) {
+ mpid = ESP_BLE_MESH_SENSOR_DATA_FORMAT_A_MPID(state->sensor_data.length, state->sensor_property_id);
+ mpid_len = ESP_BLE_MESH_SENSOR_DATA_FORMAT_A_MPID_LEN;
+ } else {
+ mpid = ESP_BLE_MESH_SENSOR_DATA_FORMAT_B_MPID(state->sensor_data.length, state->sensor_property_id);
+ mpid_len = ESP_BLE_MESH_SENSOR_DATA_FORMAT_B_MPID_LEN;
+ }
+ // Use "state->sensor_data.length + 3" because sending 4 uint8
+ data_len = state->sensor_data.length + 3;
+ }
+
+ memcpy(data, &mpid, mpid_len);
+ memcpy(data + mpid_len, state->sensor_data.raw_value->data, data_len);
+
+ return (mpid_len + data_len);
+}
+
+STATIC mp_obj_t mod_ble_mesh_element_add_model(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+
+ STATIC const mp_arg_t mod_ble_mesh_add_model_args[] = {
+ { MP_QSTR_self_in, MP_ARG_OBJ, },
+ { MP_QSTR_type, MP_ARG_INT, {.u_int = MOD_BLE_MESH_MODEL_GEN_ONOFF}},
+ { MP_QSTR_server_client, MP_ARG_INT, {.u_int = MOD_BLE_MESH_SERVER}},
+ { MP_QSTR_callback, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = MP_OBJ_NULL}},
+ { MP_QSTR_value, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = MP_OBJ_NULL}},
+ };
+
+ mp_arg_val_t args[MP_ARRAY_SIZE(mod_ble_mesh_add_model_args)];
+ mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(args), mod_ble_mesh_add_model_args, args);
+
+ mod_ble_mesh_element_class_t* ble_mesh_element = (mod_ble_mesh_element_class_t*)args[0].u_obj;
+ mp_int_t type = args[1].u_int;
+ // TODO: check the range, only SERVER or CLIENT is allowed
+ mp_int_t server_client = args[2].u_int;
+ mp_obj_t callback = args[3].u_obj;
+ mp_obj_t value_mp_obj = args[4].u_obj;
+
+ int16_t group = 0;
+
+ // Start preparing the Model
+ esp_ble_mesh_model_t tmp_model;
+ int32_t op_def_get = -1;
+ int32_t op_def_set = -1;
+ int32_t op_def_set_unack = -1;
+ int32_t op_def_status = -1;
+
+ esp_ble_mesh_model_pub_t* pub = (esp_ble_mesh_model_pub_t *)heap_caps_malloc(sizeof(esp_ble_mesh_model_pub_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
+ // Allocate 20 byte for the buffer, this size was taken from the examples
+ uint8_t* net_buf_data = (uint8_t *)heap_caps_malloc(20, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
+ struct net_buf_simple* net_buf_simple_ptr = (struct net_buf_simple *)heap_caps_malloc(sizeof(struct net_buf_simple), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
+ net_buf_simple_ptr->__buf = net_buf_data;
+ net_buf_simple_ptr->data = net_buf_data;
+ net_buf_simple_ptr->len = 0;
+ net_buf_simple_ptr->size = 20;
+ pub->update = 0;
+ pub->msg = net_buf_simple_ptr;
+ pub->dev_role = ROLE_NODE;
+
+ // Server Type
+ if(server_client == MOD_BLE_MESH_SERVER) {
+ if(type == MOD_BLE_MESH_MODEL_GEN_ONOFF) {
+ //TODO: check the validity of the value
+ // This will be saved into the Model's user_data field
+ esp_ble_mesh_gen_onoff_srv_t* onoff_server = (esp_ble_mesh_gen_onoff_srv_t *)heap_caps_malloc(sizeof(esp_ble_mesh_gen_onoff_srv_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
+ onoff_server->rsp_ctrl.get_auto_rsp = ESP_BLE_MESH_SERVER_AUTO_RSP;
+ onoff_server->rsp_ctrl.set_auto_rsp = ESP_BLE_MESH_SERVER_AUTO_RSP;
+
+ esp_ble_mesh_model_t gen_onoff_srv_mod = ESP_BLE_MESH_MODEL_GEN_ONOFF_SRV(pub, onoff_server);
+ memcpy(&tmp_model, &gen_onoff_srv_mod, sizeof(gen_onoff_srv_mod));
+
+ op_def_status = ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_STATUS;
+
+ group = MOD_BLE_MESH_GROUP_GENERIC;
+ }
+ else if(type == MOD_BLE_MESH_MODEL_GEN_LEVEL) {
+ //TODO: check the validity of the value
+ // This will be saved into the Model's user_data field
+ esp_ble_mesh_gen_level_srv_t* level_server = (esp_ble_mesh_gen_level_srv_t *)heap_caps_malloc(sizeof(esp_ble_mesh_gen_level_srv_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
+ level_server->rsp_ctrl.get_auto_rsp = ESP_BLE_MESH_SERVER_AUTO_RSP;
+ level_server->rsp_ctrl.set_auto_rsp = ESP_BLE_MESH_SERVER_AUTO_RSP;
+
+ esp_ble_mesh_model_t gen_level_srv_mod = ESP_BLE_MESH_MODEL_GEN_LEVEL_SRV(pub, level_server);
+ memcpy(&tmp_model, &gen_level_srv_mod, sizeof(gen_level_srv_mod));
+
+ op_def_status = ESP_BLE_MESH_MODEL_OP_GEN_LEVEL_STATUS;
+
+ group = MOD_BLE_MESH_GROUP_GENERIC;
+ }
+ else if(type == MOD_BLE_MESH_MODEL_SENSOR) {
+ ESP_BLE_MESH_MODEL_PUB_DEFINE(sensor_pub, 20, ROLE_NODE);
+
+ // 10 Number of Sensors is available
+ mod_ble_sensor_srv.rsp_ctrl.get_auto_rsp = ESP_BLE_MESH_SERVER_RSP_BY_APP;
+ mod_ble_sensor_srv.rsp_ctrl.set_auto_rsp = ESP_BLE_MESH_SERVER_RSP_BY_APP;
+ mod_ble_sensor_srv.state_count = 0;
+ mod_ble_sensor_srv.states = (esp_ble_mesh_sensor_state_t*)heap_caps_calloc(10, sizeof(esp_ble_mesh_sensor_state_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
+
+ esp_ble_mesh_model_t sen_srv_mod = ESP_BLE_MESH_MODEL_SENSOR_SRV(&sensor_pub, &mod_ble_sensor_srv);
+ memcpy(&tmp_model, &sen_srv_mod, sizeof(sen_srv_mod));
+
+ op_def_status = ESP_BLE_MESH_MODEL_OP_SENSOR_STATUS;
+
+ group = MOD_BLE_MESH_GROUP_SENSOR;
+ }
+ else {
+ //TODO: Add support for more functionality
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_RuntimeError, "Not supported Model type!!"));
+ }
+ }
+ else {
+ if(type == MOD_BLE_MESH_MODEL_GEN_ONOFF) {
+ // This will be saved into the Model's user_data field
+ esp_ble_mesh_client_t* onoff_client = (esp_ble_mesh_client_t *)heap_caps_calloc(1, sizeof(esp_ble_mesh_client_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
+ esp_ble_mesh_model_t gen_onoff_cli_mod = ESP_BLE_MESH_MODEL_GEN_ONOFF_CLI(pub, onoff_client);
+ memcpy(&tmp_model, &gen_onoff_cli_mod, sizeof(gen_onoff_cli_mod));
+
+ op_def_get = ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_GET;
+ op_def_set = ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET;
+ op_def_set_unack = ESP_BLE_MESH_MODEL_OP_GEN_ONOFF_SET_UNACK;
+
+ group = MOD_BLE_MESH_GROUP_GENERIC;
+ }
+ else if(type == MOD_BLE_MESH_MODEL_GEN_LEVEL) {
+ // This will be saved into the Model's user_data field
+ esp_ble_mesh_client_t* level_client = (esp_ble_mesh_client_t *)heap_caps_calloc(1, sizeof(esp_ble_mesh_client_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
+ esp_ble_mesh_model_t gen_level_cli_mod = ESP_BLE_MESH_MODEL_GEN_LEVEL_CLI(pub, level_client);
+ memcpy(&tmp_model, &gen_level_cli_mod, sizeof(gen_level_cli_mod));
+
+ op_def_get = ESP_BLE_MESH_MODEL_OP_GEN_LEVEL_GET;
+ op_def_set = ESP_BLE_MESH_MODEL_OP_GEN_LEVEL_SET;
+ op_def_set_unack = ESP_BLE_MESH_MODEL_OP_GEN_LEVEL_SET_UNACK;
+
+ group = MOD_BLE_MESH_GROUP_GENERIC;
+ }
+ else if(type == MOD_BLE_MESH_MODEL_SENSOR) {
+ //esp_ble_mesh_client_t* sensors_client = (esp_ble_mesh_client_t *)heap_caps_calloc(1, sizeof(esp_ble_mesh_client_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
+ esp_ble_mesh_model_t sen_cli_mod = ESP_BLE_MESH_MODEL_SENSOR_CLI(NULL, &sensor_client);
+ memcpy(&tmp_model, &sen_cli_mod, sizeof(sen_cli_mod));
+
+ op_def_get = ESP_BLE_MESH_MODEL_OP_SENSOR_GET;
+
+ group = MOD_BLE_MESH_GROUP_SENSOR;
+ }
+ else {
+ //TODO: Add support for more functionality
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_RuntimeError, "Not supported Model type!!"));
+ }
+ }
+
+ // Allocate memory for the new model, use realloc because the underlying BLE Mesh library expects the Models as an array, and not as a list
+ ble_mesh_element->element->sig_models = (esp_ble_mesh_model_t*)heap_caps_realloc(ble_mesh_element->element->sig_models, (ble_mesh_element->element->sig_model_count+1) * sizeof(esp_ble_mesh_model_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
+ memcpy(&ble_mesh_element->element->sig_models[ble_mesh_element->element->sig_model_count], &tmp_model, sizeof(tmp_model));
+
+ // Create the MicroPython Model
+ mod_ble_mesh_model_class_t* model = mod_ble_add_model_to_list(ble_mesh_element,
+ ble_mesh_element->element->sig_model_count,
+ callback,
+ op_def_get,
+ op_def_set,
+ op_def_set_unack,
+ op_def_status,
+ value_mp_obj,
+ server_client,
+ type,
+ group);
+
+ // Indicate we have a new element in the array
+ ble_mesh_element->element->sig_model_count++;
+
+ // Return with the MicroPtyhon Model object
+ return model;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mod_ble_mesh_element_add_model_obj, 1, mod_ble_mesh_element_add_model);
+
+STATIC const mp_map_elem_t mod_ble_mesh_element_locals_dict_table[] = {
+ { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_BLE_Mesh_Element) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_add_model), (mp_obj_t)&mod_ble_mesh_element_add_model_obj },
+
+};
+STATIC MP_DEFINE_CONST_DICT(mod_ble_mesh_element_locals_dict, mod_ble_mesh_element_locals_dict_table);
+
+static const mp_obj_type_t mod_ble_mesh_element_type = {
+ { &mp_type_type },
+ .name = MP_QSTR_BLE_Mesh_Element,
+ .locals_dict = (mp_obj_t)&mod_ble_mesh_element_locals_dict,
+};
+
+
+/******************************************************************************
+ DEFINE BLE MESH CLASS FUNCTIONS
+ ******************************************************************************/
+
+// TODO: add parameters
+// Initialize the module
+STATIC mp_obj_t mod_ble_mesh_init(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ STATIC const mp_arg_t mod_ble_mesh_init_args[] = {
+ { MP_QSTR_name, MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL}},
+ { MP_QSTR_auth, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 0}},
+ { MP_QSTR_callback, MP_ARG_OBJ | MP_ARG_KW_ONLY,{.u_obj = MP_OBJ_NULL}},
+ };
+
+ mp_arg_val_t args[MP_ARRAY_SIZE(mod_ble_mesh_init_args)];
+ mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(args), mod_ble_mesh_init_args, args);
+
+ // The BLE Mesh module should be initialized only once
+ if(initialized == false) {
+ esp_err_t err;
+
+ provision_ptr = (esp_ble_mesh_prov_t *)heap_caps_malloc(sizeof(esp_ble_mesh_prov_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
+ composition_ptr = (esp_ble_mesh_comp_t *)heap_caps_malloc(sizeof(esp_ble_mesh_comp_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
+
+ if(provision_ptr != NULL && composition_ptr != NULL) {
+
+ // Set UUID
+ memcpy(dev_uuid + 2, esp_bt_dev_get_address(), BD_ADDR_LEN);
+ provision_ptr->uuid = dev_uuid;
+
+ // Initiate parameters with NO OOB case
+ provision_ptr->input_size = 0;
+ provision_ptr->input_actions = ESP_BLE_MESH_NO_INPUT;
+
+ provision_ptr->output_size = 0;
+ provision_ptr->output_actions = ESP_BLE_MESH_NO_OUTPUT;
+
+ // GET auth information
+ int oob_type = args[1].u_int;
+
+ if(oob_type & MOD_BLE_MESH_INPUT_OOB) {
+ provision_ptr->input_size = 1;
+ provision_ptr->input_actions = ESP_BLE_MESH_PUSH;
+ }
+ if(oob_type & MOD_BLE_MESH_OUTPUT_OOB) {
+ provision_ptr->output_size = 1;
+ provision_ptr->output_actions = ESP_BLE_MESH_BLINK;
+ }
+
+ //TODO: initialize composition based on input parameters
+ composition_ptr->cid = 0x02C4; // CID_ESP=0x02C4
+ // TODO: add support for more Elements
+ composition_ptr->elements = (esp_ble_mesh_elem_t *)mod_ble_mesh_element.element;
+ composition_ptr->element_count = 1;
+
+ // Get MP callback
+ provision_callback = args[2].u_obj;
+
+ // Register Generic Callbacks
+ esp_ble_mesh_register_generic_client_callback(mod_ble_mesh_generic_client_callback);
+ esp_ble_mesh_register_generic_server_callback(mod_ble_mesh_generic_server_callback);
+
+ // Register Sensor Callbacks
+ esp_ble_mesh_register_sensor_server_callback(mod_ble_mesh_sensor_server_callback);
+ esp_ble_mesh_register_sensor_client_callback(mod_ble_mesh_sensor_client_callback);
+
+ // Register Config Server Callback
+ esp_ble_mesh_register_config_server_callback(mod_ble_mesh_config_server_callback);
+
+ // Register Provision Callback
+ esp_ble_mesh_register_prov_callback(mod_ble_mesh_provision_callback);
+
+ if(args[0].u_obj != MP_OBJ_NULL) {
+ err = esp_ble_mesh_set_unprovisioned_device_name(mp_obj_str_get_str(args[0].u_obj));
+ }
+ else {
+ err = esp_ble_mesh_set_unprovisioned_device_name(MOD_BLE_MESH_DEFAULT_NAME);
+ }
+
+ if(err != ESP_OK) {
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_RuntimeError, "BLE Mesh node name cannot be set, error code: %d!", err));
+ }
+
+ err = esp_ble_mesh_init(provision_ptr, composition_ptr);
+
+ if(err != ESP_OK) {
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_RuntimeError, "BLE Mesh module could not be initialized, error code: %d!", err));
+ }
+ else {
+ initialized = true;
+ }
+ }
+ else {
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_MemoryError, "BLE Mesh module could not be initialized!"));
+ }
+ }
+ else {
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_RuntimeError, "BLE Mesh module is already initialized!"));
+ }
+
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mod_ble_mesh_init_obj, 0, mod_ble_mesh_init);
+
+// Set node provisioning
+STATIC mp_obj_t mod_ble_mesh_set_node_prov(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+
+ STATIC const mp_arg_t mod_ble_mesh_set_node_prov_args[] = {
+ { MP_QSTR_bearer, MP_ARG_INT, {.u_int = 4}},
+ };
+
+ mp_arg_val_t args[MP_ARRAY_SIZE(mod_ble_mesh_set_node_prov_args)];
+ mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(args), mod_ble_mesh_set_node_prov_args, args);
+
+ // Get bearer type
+ int type = args[0].u_int;
+
+ // Disable node provision in prior
+ esp_ble_mesh_node_prov_disable(MOD_BLE_MESH_PROV_ADV|MOD_BLE_MESH_PROV_GATT);
+
+ // Check if provision mode is within valid range
+ if((type >= MOD_BLE_MESH_PROV_ADV) && (type <= (MOD_BLE_MESH_PROV_ADV|MOD_BLE_MESH_PROV_GATT))) {
+ esp_ble_mesh_node_prov_enable(type);
+ }
+ else if(type != MOD_BLE_MESH_PROV_NONE) {
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_RuntimeError, "Node provision mode is not valid!"));
+ }
+
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mod_ble_mesh_set_node_prov_obj, 0, mod_ble_mesh_set_node_prov);
+
+// Reset node provisioning information
+STATIC mp_obj_t mod_ble_mesh_reset_node_prov(void) {
+
+ // Delete and reset node provision information
+ esp_ble_mesh_node_local_reset();
+
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_ble_mesh_reset_node_prov_obj, mod_ble_mesh_reset_node_prov);
+
+// Set node provisioning
+STATIC mp_obj_t mod_ble_mesh_input_oob(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+
+ STATIC const mp_arg_t mod_ble_mesh_input_oob_args[] = {
+ { MP_QSTR_oob, MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL}},
+ };
+
+ mp_arg_val_t args[MP_ARRAY_SIZE(mod_ble_mesh_input_oob_args)];
+ mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(args), mod_ble_mesh_input_oob_args, args);
+
+ if(args[0].u_obj != MP_OBJ_NULL) {
+ if(mp_obj_is_int(args[0].u_obj)) {
+ esp_ble_mesh_node_input_number(mp_obj_get_int(args[0].u_obj));
+ }
+ else if(mp_obj_is_str(args[0].u_obj)) {
+ esp_ble_mesh_node_input_string(mp_obj_get_type_str(args[0].u_obj));
+ }
+ }
+
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mod_ble_mesh_input_oob_obj, 0, mod_ble_mesh_input_oob);
+
+// TODO: add parameters for configuring the Configuration Server Model
+STATIC mp_obj_t mod_ble_mesh_create_element(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+
+ STATIC const mp_arg_t mod_ble_mesh_create_element_args[] = {
+ { MP_QSTR_primary, MP_ARG_BOOL | MP_ARG_KW_ONLY | MP_ARG_REQUIRED },
+ { MP_QSTR_feature, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 0}},
+ { MP_QSTR_beacon, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = true}},
+ { MP_QSTR_ttl, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 7}},
+ };
+
+ mp_arg_val_t args[MP_ARRAY_SIZE(mod_ble_mesh_create_element_args)];
+ mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(args), mod_ble_mesh_create_element_args, args);
+
+ // Get primary bool
+ bool primary = args[0].u_bool;
+
+ if(primary) {
+ // TODO: check here if not other primary element exists
+ if(1) {
+ // Get Configuration Server Model parameters
+ int feature = args[1].u_int;
+ bool beacon = args[2].u_bool;
+ int ttl = args[3].u_int;
+
+ //TODO: add support for several more elements
+ mod_ble_mesh_element_class_t *ble_mesh_element = &mod_ble_mesh_element;
+
+ // Initiate an empty element
+ ble_mesh_element->base.type = &mod_ble_mesh_element_type;
+ ble_mesh_element->element = (mod_ble_mesh_elem_t *)heap_caps_calloc(1, sizeof(mod_ble_mesh_elem_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
+
+ // Add the mandatory Configuration Server Model
+ esp_ble_mesh_cfg_srv_t* configuration_server_model_ptr = (esp_ble_mesh_cfg_srv_t *)heap_caps_calloc(1, sizeof(esp_ble_mesh_cfg_srv_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
+
+ // Configure the Configuration Server Model
+ configuration_server_model_ptr->relay = ((feature & MOD_BLE_MESH_RELAY) > 0);
+ configuration_server_model_ptr->friend_state = ((feature & MOD_BLE_MESH_FRIEND) > 0);
+ configuration_server_model_ptr->gatt_proxy = ((feature & MOD_BLE_MESH_GATT_PROXY) > 0);
+
+ configuration_server_model_ptr->beacon = beacon;
+ configuration_server_model_ptr->default_ttl = ttl;
+
+ configuration_server_model_ptr->net_transmit = ESP_BLE_MESH_TRANSMIT(2, 20); /* 3 transmissions with 20ms interval */
+ configuration_server_model_ptr->relay_retransmit = ESP_BLE_MESH_TRANSMIT(2, 20);
+
+ // Prepare temp model
+ esp_ble_mesh_model_t tmp_model = ESP_BLE_MESH_MODEL_CFG_SRV(configuration_server_model_ptr);
+
+ // Allocate memory for the model
+ ble_mesh_element->element->sig_models = (esp_ble_mesh_model_t*)heap_caps_calloc(1, sizeof(esp_ble_mesh_model_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
+ // Copy the already prepared element to the new location
+ memcpy(ble_mesh_element->element->sig_models, &tmp_model, sizeof(esp_ble_mesh_model_t));
+
+ // Create the MicroPython Model
+ // TODO: add callback if the user configures it
+ (void)mod_ble_add_model_to_list(ble_mesh_element, 0, NULL, 0, 0, 0, 0, NULL, MOD_BLE_MESH_SERVER, MOD_BLE_MESH_MODEL_NONE, MOD_BLE_MESH_MODEL_CONFIGURATION);
+ // This is the first model
+ ble_mesh_element->element->sig_model_count = 1;
+
+ return ble_mesh_element;
+ }
+ else {
+ // TODO: add support for more elements
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_RuntimeError, "Only one Element can be created at this version!"));
+
+ return mp_const_none;
+ }
+ }
+ else {
+ // TODO: add secondary element
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_RuntimeError, "Only primary element is supported!"));
+ //Return none until not implemented scenario
+ return mp_const_none;
+ }
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mod_ble_mesh_create_element_obj, 0, mod_ble_mesh_create_element);
+
+
+STATIC const mp_map_elem_t mod_ble_mesh_globals_table[] = {
+ { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_BLE_Mesh) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_init), (mp_obj_t)&mod_ble_mesh_init_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_set_node_prov), (mp_obj_t)&mod_ble_mesh_set_node_prov_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_reset_node_prov), (mp_obj_t)&mod_ble_mesh_reset_node_prov_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_input_oob), (mp_obj_t)&mod_ble_mesh_input_oob_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_create_element), (mp_obj_t)&mod_ble_mesh_create_element_obj },
+
+ // Constants of Advertisement
+ { MP_OBJ_NEW_QSTR(MP_QSTR_PROV_ADV), MP_OBJ_NEW_SMALL_INT(MOD_BLE_MESH_PROV_ADV) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_PROV_GATT), MP_OBJ_NEW_SMALL_INT(MOD_BLE_MESH_PROV_GATT) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_PROV_NONE), MP_OBJ_NEW_SMALL_INT(MOD_BLE_MESH_PROV_NONE) },
+ // Constants of Node Features
+ { MP_OBJ_NEW_QSTR(MP_QSTR_RELAY), MP_OBJ_NEW_SMALL_INT(MOD_BLE_MESH_RELAY) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_LOW_POWER), MP_OBJ_NEW_SMALL_INT(MOD_BLE_MESH_LOW_POWER) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_GATT_PROXY), MP_OBJ_NEW_SMALL_INT(MOD_BLE_MESH_GATT_PROXY) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_FRIEND), MP_OBJ_NEW_SMALL_INT(MOD_BLE_MESH_FRIEND) },
+ // Constants of Authentication
+ { MP_OBJ_NEW_QSTR(MP_QSTR_OOB_INPUT), MP_OBJ_NEW_SMALL_INT(MOD_BLE_MESH_INPUT_OOB) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_OOB_OUTPUT), MP_OBJ_NEW_SMALL_INT(MOD_BLE_MESH_OUTPUT_OOB) },
+ // Constants of Node Addresses
+ { MP_OBJ_NEW_QSTR(MP_QSTR_ADDR_ALL_NODES), MP_OBJ_NEW_SMALL_INT(MOD_BLE_ADDR_ALL_NODES) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_ADDR_PUBLISH), MP_OBJ_NEW_SMALL_INT(MOD_BLE_ADDR_PUBLISH) },
+
+ // Constants of Server-Client
+ { MP_OBJ_NEW_QSTR(MP_QSTR_SERVER), MP_OBJ_NEW_SMALL_INT(MOD_BLE_MESH_SERVER) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_CLIENT), MP_OBJ_NEW_SMALL_INT(MOD_BLE_MESH_CLIENT) },
+
+ // Constants of States
+ { MP_OBJ_NEW_QSTR(MP_QSTR_STATE_ONOFF), MP_OBJ_NEW_SMALL_INT(MOD_BLE_MESH_STATE_ONOFF) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_STATE_LEVEL), MP_OBJ_NEW_SMALL_INT(MOD_BLE_MESH_STATE_LEVEL) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_STATE_LEVEL_DELTA), MP_OBJ_NEW_SMALL_INT(MOD_BLE_MESH_STATE_LEVEL_DELTA) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_STATE_LEVEL_MOVE), MP_OBJ_NEW_SMALL_INT(MOD_BLE_MESH_STATE_LEVEL_MOVE) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_STATE_SEN_DESCRIPTOR), MP_OBJ_NEW_SMALL_INT(MOD_BLE_MESH_STATE_SEN_DESCRIPTOR) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_STATE_SEN), MP_OBJ_NEW_SMALL_INT(MOD_BLE_MESH_STATE_SEN) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_STATE_SEN_COLUMN), MP_OBJ_NEW_SMALL_INT(MOD_BLE_MESH_STATE_SEN_COLUMN) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_STATE_SEN_SERIES), MP_OBJ_NEW_SMALL_INT(MOD_BLE_MESH_STATE_SEN_SERIES) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_STATE_SEN_SET_CADENCE), MP_OBJ_NEW_SMALL_INT(MOD_BLE_MESH_STATE_SEN_SET_CADENCE) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_STATE_SEN_SET_SETTINGS), MP_OBJ_NEW_SMALL_INT(MOD_BLE_MESH_STATE_SEN_SET_SETTINGS) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_STATE_SEN_SET_SETTING), MP_OBJ_NEW_SMALL_INT(MOD_BLE_MESH_STATE_SEN_SET_SETTING) },
+
+ // Models
+ { MP_OBJ_NEW_QSTR(MP_QSTR_GEN_ONOFF), MP_OBJ_NEW_SMALL_INT(MOD_BLE_MESH_MODEL_GEN_ONOFF) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_GEN_LEVEL), MP_OBJ_NEW_SMALL_INT(MOD_BLE_MESH_MODEL_GEN_LEVEL) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_SENSOR), MP_OBJ_NEW_SMALL_INT(MOD_BLE_MESH_MODEL_SENSOR) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_SENSOR_SETUP), MP_OBJ_NEW_SMALL_INT(MOD_BLE_MESH_MODEL_SENSOR_SETUP) },
+
+ // Provisioning Events
+ { MP_OBJ_NEW_QSTR(MP_QSTR_PROV_REGISTER_EVT), MP_OBJ_NEW_SMALL_INT(ESP_BLE_MESH_PROV_REGISTER_COMP_EVT) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_PROV_ENABLE_EVT), MP_OBJ_NEW_SMALL_INT(ESP_BLE_MESH_NODE_PROV_ENABLE_COMP_EVT) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_PROV_DISABLE_EVT), MP_OBJ_NEW_SMALL_INT(ESP_BLE_MESH_NODE_PROV_DISABLE_COMP_EVT) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_LINK_OPEN_EVT), MP_OBJ_NEW_SMALL_INT(ESP_BLE_MESH_NODE_PROV_LINK_OPEN_EVT) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_LINK_CLOSE_EVT), MP_OBJ_NEW_SMALL_INT(ESP_BLE_MESH_NODE_PROV_LINK_CLOSE_EVT) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_PROV_COMPLETE_EVT), MP_OBJ_NEW_SMALL_INT(ESP_BLE_MESH_NODE_PROV_COMPLETE_EVT) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_PROV_RESET_EVT), MP_OBJ_NEW_SMALL_INT(ESP_BLE_MESH_NODE_PROV_RESET_EVT) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_PROV_OUTPUT_OOB_REQ_EVT), MP_OBJ_NEW_SMALL_INT(ESP_BLE_MESH_NODE_PROV_OUTPUT_NUMBER_EVT) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_PROV_INPUT_OOB_REQ_EVT), MP_OBJ_NEW_SMALL_INT(ESP_BLE_MESH_NODE_PROV_INPUT_EVT) },
+
+};
+
+STATIC MP_DEFINE_CONST_DICT(mod_ble_mesh_globals, mod_ble_mesh_globals_table);
+
+// Sub-module of Bluetooth module (modbt.c)
+const mp_obj_module_t mod_ble_mesh = {
+ .base = { &mp_type_module },
+ .globals = (mp_obj_dict_t*)&mod_ble_mesh_globals,
+};
diff --git a/esp32/mods/modble_mesh.h b/esp32/mods/modble_mesh.h
new file mode 100644
index 0000000000..25f3b0d0fb
--- /dev/null
+++ b/esp32/mods/modble_mesh.h
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2020, Pycom Limited.
+ *
+ * This software is licensed under the GNU GPL version 3 or any
+ * later version, with permitted additional terms. For more information
+ * see the Pycom Licence v1.0 document supplied with this file, or
+ * available at https://www.pycom.io/opensource/licensing
+ */
+
+
+#ifndef ESP32_MODS_MODBLE_MESH_H_
+#define ESP32_MODS_MODBLE_MESH_H_
+
+extern const mp_obj_type_t mod_ble_mesh;
+
+#endif /* ESP32_MODS_MODBLE_MESH_H_ */
diff --git a/esp32/mods/modbt.c b/esp32/mods/modbt.c
index 529159630b..058fd73bde 100644
--- a/esp32/mods/modbt.c
+++ b/esp32/mods/modbt.c
@@ -31,7 +31,6 @@
#include "modbt.h"
#include "mpirq.h"
#include "antenna.h"
-
#include "esp_bt.h"
#include "common/bt_trace.h"
#include "stack/bt_types.h"
@@ -54,6 +53,7 @@
#include "lwip/def.h"
#include "mbedtls/sha1.h"
+#include "modble_mesh.h"
#include "nvs.h"
/******************************************************************************
@@ -61,7 +61,7 @@
******************************************************************************/
#define BT_SCAN_QUEUE_SIZE_MAX (16)
#define BT_GATTS_QUEUE_SIZE_MAX (2)
-#define BT_MTU_SIZE_MAX (200)
+#define BT_MTU_SIZE_MAX (ESP_GATT_MAX_MTU_SIZE)
#define BT_CHAR_VALUE_SIZE_MAX (BT_MTU_SIZE_MAX - 3)
#define MOD_BT_CLIENT_APP_ID (0)
@@ -346,6 +346,8 @@ void modbt_deinit(bool allow_reconnect)
connection_obj = ((bt_connection_obj_t *)(MP_STATE_PORT(btc_conn_list).items[i]));
//close connections
modbt_conn_disconnect(connection_obj);
+ // Wait for the disconnect event before initiating disconnect action on the next connection
+ xEventGroupWaitBits(bt_event_group, ESP_GATTC_DISCONNECT_EVT, true, true, 1000/portTICK_PERIOD_MS);
}
while ((MP_STATE_PORT(btc_conn_list).len > 0) && (timeout < 20) && !mod_bt_allow_resume_deinit)
{
@@ -791,6 +793,9 @@ static void gattc_events_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc
}
break;
}
+ case ESP_GATTC_DIS_SRVC_CMPL_EVT:
+ // Do nothing for now, might be useful in the future
+ break;
case ESP_GATTC_SEARCH_CMPL_EVT:
case ESP_GATTC_CANCEL_OPEN_EVT:
bt_obj.busy = false;
@@ -1474,7 +1479,8 @@ static mp_obj_t bt_connect_helper(mp_obj_t addr, TickType_t timeout, esp_ble_add
conn->addr_type = addr_type;
MP_THREAD_GIL_EXIT();
- uxBits = xEventGroupWaitBits(bt_event_group, MOD_BT_GATTC_MTU_EVT, true, true, 1000/portTICK_PERIOD_MS);
+ // Timeout time is increased compared to esp-idf 3.3 because as per the experience MOD_BT_GATTC_MTU_EVT arrives slower with esp-idf 4.1
+ uxBits = xEventGroupWaitBits(bt_event_group, MOD_BT_GATTC_MTU_EVT, true, true, 10000/portTICK_PERIOD_MS);
MP_THREAD_GIL_ENTER();
if(uxBits & MOD_BT_GATTC_MTU_EVT)
@@ -1661,7 +1667,7 @@ STATIC mp_obj_t bt_set_advertisement (mp_uint_t n_args, const mp_obj_t *pos_args
if (mp_obj_is_integer(args[3].u_obj)) {
uint32_t srv_uuid = mp_obj_get_int_truncated(args[3].u_obj);
uint8_t uuid_buf[16] = {0};
- memcpy(uuid_buf, (uint8_t *)&srv_uuid, sizeof(uuid_buf));
+ memcpy(uuid_buf, (uint8_t *)&srv_uuid, sizeof(srv_uuid));
adv_data.service_uuid_len = 16;
adv_data.p_service_uuid = (uint8_t *)&srv_uuid;
} else {
@@ -2200,6 +2206,8 @@ STATIC const mp_map_elem_t bt_locals_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_gatts_mtu), (mp_obj_t)&bt_gatts_get_mtu_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_nvram_erase), (mp_obj_t)&bt_nvram_erase_obj },
+ // BLE Mesh
+ { MP_OBJ_NEW_QSTR(MP_QSTR_BLE_Mesh), (mp_obj_t)&mod_ble_mesh },
// exceptions
{ MP_OBJ_NEW_QSTR(MP_QSTR_timeout), (mp_obj_t)&mp_type_TimeoutError },
diff --git a/esp32/mods/modcoap.c b/esp32/mods/modcoap.c
index ac8a98be41..92ae4d0540 100644
--- a/esp32/mods/modcoap.c
+++ b/esp32/mods/modcoap.c
@@ -13,51 +13,72 @@
#include "py/runtime.h"
#include "coap.h"
-#include "coap_list.h"
+#include "coap_hashkey.h"
#include "modcoap.h"
#include "modnetwork.h"
#include "modusocket.h"
#include "lwipsocket.h"
#include "netutils.h"
+#include "mpirq.h"
#include "freertos/semphr.h"
-
/******************************************************************************
DEFINE CONSTANTS
******************************************************************************/
-#define MODCOAP_DEFAULT_PORT (5683)
-#define MODCOAP_IP4_MULTICAST ("224.0.1.187")
-#define MODCOAP_REQUEST_GET (0x01)
-#define MODCOAP_REQUEST_PUT (0x02)
-#define MODCOAP_REQUEST_POST (0x04)
-#define MODCOAP_REQUEST_DELETE (0x08)
+#define MODCOAP_IP4_MULTICAST ("224.0.1.187")
+#define MODCOAP_REQUEST_GET (0x01)
+#define MODCOAP_REQUEST_PUT (0x02)
+#define MODCOAP_REQUEST_POST (0x04)
+#define MODCOAP_REQUEST_DELETE (0x08)
+#define MODCOAP_TASK_STACK_SIZE (5 * 1024)
+#define MODCOAP_TASK_PRIORITY (5)
/******************************************************************************
DEFINE PRIVATE TYPES
******************************************************************************/
+
+typedef struct mod_coap_response_handler_args_s {
+ uint8_t code;
+ uint16_t tid;
+ uint8_t type;
+ uint8_t* token;
+ uint8_t token_length;
+ uint8_t* data;
+ uint16_t data_length;
+}mod_coap_response_handler_args_t;
+
typedef struct mod_coap_resource_obj_s {
mp_obj_base_t base;
coap_resource_t* coap_resource;
struct mod_coap_resource_obj_s* next;
uint8_t* value;
- uint32_t max_age;
+ int32_t mediatype;
+ int32_t max_age;
uint16_t etag_value;
uint16_t value_len;
- uint8_t mediatype;
bool etag;
}mod_coap_resource_obj_t;
+typedef struct mod_coap_client_session_obj_s {
+ mp_obj_base_t base;
+ struct mod_coap_client_session_obj_s* next;
+ coap_session_t* session;
+ mp_obj_t ip_addr;
+ mp_obj_t port;
+ mp_obj_t protocol;
+}mod_coap_client_session_obj_t;
+
typedef struct mod_coap_obj_s {
mp_obj_base_t base;
coap_context_t* context;
- mod_network_socket_obj_t* socket;
mod_coap_resource_obj_t* resources;
+ mod_coap_client_session_obj_t* client_sessions;
SemaphoreHandle_t semphr;
- mp_obj_t callback;
- coap_list_t *optlist;
+ mp_obj_t callback_response;
+ mp_obj_t callback_new_resource;
}mod_coap_obj_t;
@@ -65,130 +86,231 @@ typedef struct mod_coap_obj_s {
/******************************************************************************
DECLARE PRIVATE FUNCTIONS
******************************************************************************/
-STATIC mod_coap_resource_obj_t* find_resource(coap_resource_t* resource);
-STATIC mod_coap_resource_obj_t* find_resource_by_key(coap_key_t key);
-STATIC mod_coap_resource_obj_t* add_resource(const char* uri, uint8_t mediatype, uint8_t max_age, mp_obj_t value, bool etag);
-STATIC void remove_resource_by_key(coap_key_t key);
+STATIC mod_coap_client_session_obj_t* new_client_session(mp_obj_t ip_addr_in, mp_obj_t port_in, mp_obj_t key_in, mp_obj_t identity_in);
+STATIC mod_coap_resource_obj_t* find_resource_by_uri(coap_str_const_t *uri_path);
+STATIC mod_coap_resource_obj_t* add_resource(const char* uri, int32_t mediatype, int32_t max_age, mp_obj_t value, bool etag);
+STATIC void remove_resource_by_uri(coap_str_const_t *uri_path);
STATIC void remove_resource(const char* uri);
STATIC void resource_update_value(mod_coap_resource_obj_t* resource, mp_obj_t new_value);
+STATIC void coap_response_new_resource_handler_micropython(void* arg);
+STATIC void TASK_MODCOAP (void *pvParameters);
+
+
STATIC void coap_resource_callback_get(coap_context_t * context,
struct coap_resource_t * resource,
- const coap_endpoint_t * endpoint,
- coap_address_t * address,
+ coap_session_t * session,
coap_pdu_t * request,
- str * token,
+ coap_binary_t * token,
+ coap_string_t * query_string,
coap_pdu_t * response);
STATIC void coap_resource_callback_put(coap_context_t * context,
struct coap_resource_t * resource,
- const coap_endpoint_t * endpoint,
- coap_address_t * address,
+ coap_session_t * session,
coap_pdu_t * request,
- str * token,
+ coap_binary_t * token,
+ coap_string_t * query_string,
coap_pdu_t * response);
STATIC void coap_resource_callback_post(coap_context_t * context,
struct coap_resource_t * resource,
- const coap_endpoint_t * endpoint,
- coap_address_t * address,
+ coap_session_t * session,
coap_pdu_t * request,
- str * token,
+ coap_binary_t * token,
+ coap_string_t * query_string,
coap_pdu_t * response);
STATIC void coap_resource_callback_delete(coap_context_t * context,
struct coap_resource_t * resource,
- const coap_endpoint_t * endpoint,
- coap_address_t * address,
+ coap_session_t * session,
coap_pdu_t * request,
- str * token,
+ coap_binary_t * token,
+ coap_string_t * query_string,
coap_pdu_t * response);
-STATIC void coap_response_handler(struct coap_context_t * context,
- const coap_endpoint_t *local_interface,
- const coap_address_t *remote,
- coap_pdu_t *sent,
- coap_pdu_t *received,
- const coap_tid_t id);
-
-STATIC void coap_response_handler(struct coap_context_t * context,
- const coap_endpoint_t *local_interface,
- const coap_address_t *remote,
- coap_pdu_t *sent,
- coap_pdu_t *received,
- const coap_tid_t id);
-
-STATIC int modcoap_order_opts(void *a, void *b);
+STATIC void coap_response_handler(struct coap_context_t *context,
+ coap_session_t *session,
+ coap_pdu_t *sent,
+ coap_pdu_t *received,
+ const coap_tid_t id);
+
STATIC coap_pdu_t * modcoap_new_request(coap_context_t *ctx,
+ coap_session_t* session,
unsigned int m,
- coap_list_t **options,
+ coap_optlist_t **options,
const char* token,
size_t token_length,
const char *data,
size_t length);
-STATIC coap_list_t * modcoap_new_option_node(unsigned short key, unsigned int length, unsigned char *data);
/******************************************************************************
DEFINE PRIVATE VARIABLES
******************************************************************************/
STATIC const mp_obj_type_t mod_coap_resource_type;
+STATIC const mp_obj_type_t mod_coap_client_session_type;
// Only 1 context is supported
STATIC mod_coap_obj_t* coap_obj_ptr;
STATIC bool initialized = false;
+STATIC TaskHandle_t ModCoapTaskHandle;
+
/******************************************************************************
DEFINE PRIVATE FUNCTIONS
******************************************************************************/
-// Get the resource if exists
-STATIC mod_coap_resource_obj_t* find_resource(coap_resource_t* resource) {
- if(coap_obj_ptr->resources != NULL) {
- mod_coap_resource_obj_t* current = coap_obj_ptr->resources;
+// This task handles the periodic and message reception functionality of the underlying esp-idf coap library
+STATIC void TASK_MODCOAP (void *pvParameters) {
+ while(1){
+ // This function returns when there is a new packet arrived or after 100ms
+ // Re-calling this function minimally after every 100ms is needed to perform periodic activities (e.g. retransmission of Confirmable packets)
+ coap_run_once(coap_obj_ptr->context, 100);
+ }
+}
+
+// Create a new client session in the scope of the only context
+STATIC mod_coap_client_session_obj_t* new_client_session(mp_obj_t ip_addr_in, mp_obj_t port_in, mp_obj_t key_in, mp_obj_t identity_in) {
+
+ // Currently only 1 context is supported
+ mod_coap_obj_t* context = coap_obj_ptr;
+
+ // Create a new Client Session object
+ mod_coap_client_session_obj_t* client_session = m_new_obj(mod_coap_client_session_obj_t);
+ client_session->base.type = &mod_coap_client_session_type;
+ client_session->ip_addr = ip_addr_in;
+ client_session->port = port_in;
+ client_session->protocol = key_in == mp_const_none ? mp_obj_new_int(COAP_PROTO_UDP) : mp_obj_new_int(COAP_PROTO_DTLS);
+
+ mp_obj_t address = mp_obj_new_list(0, NULL);
+
+ // Compose the list of IP address and port needed by netutils_parse_inet_addr
+ mp_obj_list_append(address, ip_addr_in);
+ mp_obj_list_append(address, port_in);
+
+ // Prepare the destination address where to send the request
+ coap_address_t dst_address;
+ coap_address_init(&dst_address);
+ dst_address.addr.sin.sin_family = AF_INET;
+ // The address will be in Big Endian order
+ uint16_t port = netutils_parse_inet_addr(address, (uint8_t*)&dst_address.addr.sin.sin_addr.s_addr, NETUTILS_BIG);
+ // The port will be in Big Endian order
+ dst_address.addr.sin.sin_port = htons(port);
+
+ // Create a new Client Session in the scope of esp-idf Coap module based on the protocol
+ mp_int_t protocol = mp_obj_get_int(client_session->protocol);
+ if(protocol == COAP_PROTO_UDP) {
+ client_session->session = coap_new_client_session(coap_obj_ptr->context, NULL, &dst_address, protocol);
+ }
+ else if(protocol == COAP_PROTO_DTLS) {
+ const char *identity = mp_obj_str_get_str(identity_in);
+ const uint8_t *key = (const uint8_t *)mp_obj_str_get_str(key_in);
+ unsigned key_len = strlen((const char*)key);
+ // PSK method is supported
+ client_session->session = coap_new_client_session_psk(coap_obj_ptr->context, NULL, &dst_address, protocol, identity, key, key_len);
+ }
+
+ if(client_session->session != NULL) {
+ // Add the Client Session to our context
+ if(context->client_sessions == NULL) {
+ // No resource exists, add as first element
+ context->client_sessions = client_session;
+ }
+ else {
+ mod_coap_client_session_obj_t* current = context->client_sessions;
+ // Find the last client session
+ for(; current->next != NULL; current = current->next) {}
+ // Append the new resource to the end of the list
+ current->next = client_session;
+ }
+
+ return client_session;
+ }
+ else {
+ m_del_obj(mod_coap_client_session_obj_t, client_session);
+ // Client Session cannot be created
+ return NULL;
+ }
+}
+
+// Remove the client session from the scope of the only context
+STATIC bool remove_client_session(const char* ip_addr_in, const uint16_t port_in, const uint8_t protocol_in) {
+
+ // Currently only 1 context is supported
+ mod_coap_obj_t* context = coap_obj_ptr;
+
+ if(context->client_sessions != NULL) {
+ mod_coap_client_session_obj_t* current = context->client_sessions;
+ mod_coap_client_session_obj_t* previous = context->client_sessions;
for(; current != NULL; current = current->next) {
- // The hash key is generated from Uri
- if(memcmp(current->coap_resource->key, resource->key, sizeof(current->coap_resource->key)) == 0) {
- return current;
+
+ const char* ip_addr = mp_obj_str_get_str(current->ip_addr);
+ const uint16_t port = mp_obj_get_int(current->port);
+ const uint8_t protocol = mp_obj_get_int(current->protocol);
+
+ // Find the one to be removed
+ if((port == port_in) && (protocol == protocol_in) && (strcmp(ip_addr, ip_addr_in) == 0)){
+ // Client session found, remove from the list
+ // Check if it is the first element in the list
+ if(context->client_sessions == current) {
+ // If no more element in the list then invalidate the list
+ if(current->next == NULL) {
+ context->client_sessions = NULL;
+ }
+ // Other elements are in the list
+ else {
+ context->client_sessions = current->next;
+ }
+ }
+ else {
+ // It is not the first element
+ previous->next = current->next;
+ }
+
+ // Close the session in esp-idf
+ coap_session_release(current->session);
+ // Free the client session itself
+ m_free(current);
+ // Invalidate the client session object
+ current = mp_const_none;
+
+ return true;
}
+ // Mark the current element as previous, needed when removing the actual current element from the list
+ previous = current;
}
}
- return NULL;
+
+ return false;
}
-// Get the resource if exists by its key
-STATIC mod_coap_resource_obj_t* find_resource_by_key(coap_key_t key) {
+// Get the resource if exists by its uri
+STATIC mod_coap_resource_obj_t* find_resource_by_uri(coap_str_const_t *uri_path) {
if(coap_obj_ptr->resources != NULL) {
mod_coap_resource_obj_t* current = coap_obj_ptr->resources;
for(; current != NULL; current = current->next) {
- // The hash key is generated from Uri
- if(memcmp(current->coap_resource->key, key, sizeof(current->coap_resource->key)) == 0) {
- return current;
+ if(current->coap_resource->uri_path->length == uri_path->length){
+ if(memcmp(current->coap_resource->uri_path->s, uri_path->s, uri_path->length) == 0) {
+ return current;
+ }
}
}
}
- return mp_const_none;
+ return NULL;
}
// Create a new resource in the scope of the only context
-STATIC mod_coap_resource_obj_t* add_resource(const char* uri, uint8_t mediatype, uint8_t max_age, mp_obj_t value, bool etag) {
+STATIC mod_coap_resource_obj_t* add_resource(const char* uri, int32_t mediatype, int32_t max_age, mp_obj_t value, bool etag) {
// Currently only 1 context is supported
mod_coap_obj_t* context = coap_obj_ptr;
- coap_key_t key;
- (void)coap_hash_path((const unsigned char*)uri, strlen(uri), key);
+ coap_str_const_t coap_str;
+ coap_str.s = (const uint8_t*)uri;
+ coap_str.length = strlen(uri);
- // Check if there is at least 1 resource
- if(context->resources != NULL) {
- mod_coap_resource_obj_t* current = context->resources;
- // Iterate through the resources and check whether the new one exists
- for(; current != NULL; current = current->next) {
- // The hash key is generated from Uri
- if(memcmp(key, current->coap_resource->key, sizeof(key)) == 0) {
- // Resource already exists
- return NULL;
- }
- }
+ if(NULL != find_resource_by_uri(&coap_str)) {
+ return NULL;
}
// Resource does not exist, create a new resource object
@@ -206,11 +328,7 @@ STATIC mod_coap_resource_obj_t* add_resource(const char* uri, uint8_t mediatype,
// No next elem
resource->next = NULL;
- // uri parameter pointer will be destroyed, pass a pointer to a permanent location
- unsigned char* uri_ptr = (unsigned char*)malloc(strlen(uri));
- memcpy(uri_ptr, uri, strlen(uri));
- // Pass COAP_RESOURCE_FLAGS_RELEASE_URI so Coap Library will free up the memory allocated to store the URI when the Resource is deleted
- resource->coap_resource = coap_resource_init(uri_ptr, strlen(uri), COAP_RESOURCE_FLAGS_RELEASE_URI);
+ resource->coap_resource = coap_resource_init(&coap_str, 0);
if(resource->coap_resource != NULL) {
// Add the resource to the Coap context
coap_add_resource(context->context, resource->coap_resource);
@@ -238,7 +356,6 @@ STATIC mod_coap_resource_obj_t* add_resource(const char* uri, uint8_t mediatype,
return resource;
}
else {
- free(uri_ptr);
m_del_obj(mod_coap_resource_obj_t, resource);
// Resource cannot be created
return NULL;
@@ -249,7 +366,7 @@ STATIC mod_coap_resource_obj_t* add_resource(const char* uri, uint8_t mediatype,
}
// Remove the resource in the scope of the only context by its key
-STATIC void remove_resource_by_key(coap_key_t key) {
+STATIC void remove_resource_by_uri(coap_str_const_t *uri_path) {
// Currently only 1 context is supported
mod_coap_obj_t* context = coap_obj_ptr;
@@ -259,35 +376,37 @@ STATIC void remove_resource_by_key(coap_key_t key) {
mod_coap_resource_obj_t* previous = context->resources;
for(; current != NULL; current = current->next) {
- // The hash key is generated from Uri
- if(memcmp(current->coap_resource->key, key, sizeof(coap_key_t)) == 0) {
- // Resource found, remove from the list
- // Check if it is the first element in the list
- if(context->resources == current) {
- // If no more element in the list then invalidate the list
- if(current->next == NULL) {
- context->resources = NULL;
+ if(current->coap_resource->uri_path->length == uri_path->length){
+ if(memcmp(current->coap_resource->uri_path->s, uri_path->s, uri_path->length) == 0) {
+ // Resource found, remove from the list
+ // Check if it is the first element in the list
+ if(context->resources == current) {
+ // If no more element in the list then invalidate the list
+ if(current->next == NULL) {
+ context->resources = NULL;
+ }
+ // Other elements are in the list
+ else {
+ context->resources = current->next;
+ }
}
- // Other elements are in the list
else {
- context->resources = current->next;
+ // It is not the first element
+ previous->next = current->next;
}
- }
- else {
- // It is not the first element
- previous->next = current->next;
- }
- // Free the resource in coap's scope
- coap_delete_resource(context->context, key);
- // Free the element in MP scope
- free(current->value);
- // Free the resource itself
- m_del_obj(mod_coap_resource_obj_t, current);
+ // Free the resource in coap's scope
+ coap_delete_resource(context->context, current->coap_resource);
+ // Free the element in MP scope
+ m_free(current->value);
+ // Free the resource itself
+ m_free(current);
+ // Invalidate the resource object
+ current = mp_const_none;
- return;
+ return;
+ }
}
-
// Mark the current element as previous, needed when removing the actual current element from the list
previous = current;
}
@@ -298,10 +417,11 @@ STATIC void remove_resource_by_key(coap_key_t key) {
// Remove the resource in the scope of the only context
STATIC void remove_resource(const char* uri) {
- coap_key_t key;
- (void)coap_hash_path((const unsigned char*)uri, strlen(uri), key);
+ coap_str_const_t coap_str;
+ coap_str.s = (const uint8_t *)uri;
+ coap_str.length = strlen(uri);
- remove_resource_by_key(key);
+ remove_resource_by_uri(&coap_str);
}
// Update the value of a resource
@@ -318,7 +438,7 @@ STATIC void resource_update_value(mod_coap_resource_obj_t* resource, mp_obj_t ne
// Invalidate current data first
resource->value_len = 0;
- free(resource->value);
+ m_free(resource->value);
if (mp_obj_is_integer(new_value)) {
@@ -332,7 +452,7 @@ STATIC void resource_update_value(mod_coap_resource_obj_t* resource, mp_obj_t ne
}
// Allocate memory for the new data
- resource->value = malloc(resource->value_len);
+ resource->value = m_malloc(resource->value_len);
memcpy(resource->value, &value, sizeof(value));
} else {
@@ -342,7 +462,7 @@ STATIC void resource_update_value(mod_coap_resource_obj_t* resource, mp_obj_t ne
resource->value_len = value_bufinfo.len;
// Allocate memory for the new data
- resource->value = malloc(resource->value_len);
+ resource->value = m_malloc(resource->value_len);
memcpy(resource->value, value_bufinfo.buf, resource->value_len);
}
}
@@ -351,14 +471,15 @@ STATIC void resource_update_value(mod_coap_resource_obj_t* resource, mp_obj_t ne
// Callback function when GET method is received
STATIC void coap_resource_callback_get(coap_context_t * context,
struct coap_resource_t * resource,
- const coap_endpoint_t * endpoint,
- coap_address_t * address,
+ coap_session_t * session,
coap_pdu_t * request,
- str * token,
+ coap_binary_t * token,
+ coap_string_t * query_string,
coap_pdu_t * response)
{
+ xSemaphoreTake(coap_obj_ptr->semphr, portMAX_DELAY);
- mod_coap_resource_obj_t* resource_obj = find_resource(resource);
+ mod_coap_resource_obj_t* resource_obj = find_resource_by_uri(resource->uri_path);
// Check if the resource exists. (e.g.: has not been removed in the background before we got the semaphore in mod_coap_read())
if(resource_obj != NULL) {
@@ -371,17 +492,17 @@ STATIC void coap_resource_callback_get(coap_context_t * context,
if(opt != NULL) {
unsigned short length = coap_opt_length(opt);
- unsigned int decoded = COAP_MEDIATYPE_TEXT_PLAIN;
+ int32_t decoded = COAP_MEDIATYPE_TEXT_PLAIN;
if(length != 0) { // 0 as length means the value is 0, which is MEDIATYPE TEXT PLAIN
- unsigned char* value = coap_opt_value(opt);
- decoded = coap_decode_var_bytes(value, length);
+ const uint8_t* value = coap_opt_value(opt);
+ decoded = (int32_t)coap_decode_var_bytes(value, length);
}
// If the accepted media type and stored one does not match respond with 4.06 Not Acceptable
if(decoded != resource_obj->mediatype) {
- response->hdr->code = COAP_RESPONSE_CODE(406);
- const char* error_message = coap_response_phrase(response->hdr->code);
+ response->code = COAP_RESPONSE_CODE(406);
+ const char* error_message = coap_response_phrase(response->code);
coap_add_data(response, strlen(error_message), (unsigned char *)error_message);
return;
}
@@ -389,7 +510,7 @@ STATIC void coap_resource_callback_get(coap_context_t * context,
}
// If no ETAG option is specified in the request than the response code will be 205
- response->hdr->code = COAP_RESPONSE_CODE(205);
+ response->code = COAP_RESPONSE_CODE(205);
// Check if ETAG value is maintained for the resource
if(resource_obj->etag == true) {
@@ -403,14 +524,14 @@ STATIC void coap_resource_callback_get(coap_context_t * context,
unsigned int decoded = 0;
if(length != 0) { // 0 as length means the value is 0
- unsigned char* value = coap_opt_value(opt);
+ const uint8_t* value = coap_opt_value(opt);
decoded = coap_decode_var_bytes(value, length);
}
if(decoded == resource_obj->etag_value) {
// If the resource has not been updated since the last request
// Response must include the E-Tag option in this case, this is ensured to be happened
- response->hdr->code = COAP_RESPONSE_CODE(203);
+ response->code = COAP_RESPONSE_CODE(203);
}
}
}
@@ -419,162 +540,238 @@ STATIC void coap_resource_callback_get(coap_context_t * context,
unsigned char buf[3];
if(resource_obj->etag == true) {
- coap_add_option(response, COAP_OPTION_ETAG, coap_encode_var_bytes(buf, resource_obj->etag_value), buf);
+ coap_add_option(response, COAP_OPTION_ETAG, coap_encode_var_safe(buf, sizeof(buf), resource_obj->etag_value), buf);
}
if(resource_obj->mediatype != -1) {
- coap_add_option(response, COAP_OPTION_CONTENT_TYPE, coap_encode_var_bytes(buf, resource_obj->mediatype), buf);
+ coap_add_option(response, COAP_OPTION_CONTENT_TYPE, coap_encode_var_safe(buf, sizeof(buf), resource_obj->mediatype), buf);
}
if(resource_obj->max_age != -1) {
- coap_add_option(response, COAP_OPTION_MAXAGE, coap_encode_var_bytes(buf, resource_obj->max_age), buf);
+ coap_add_option(response, COAP_OPTION_MAXAGE, coap_encode_var_safe(buf, sizeof(buf), resource_obj->max_age), buf);
}
// Add the data itself if updated
- if(response->hdr->code == COAP_RESPONSE_CODE(205)) {
+ if(response->code == COAP_RESPONSE_CODE(205)) {
coap_add_data(response, resource_obj->value_len, (unsigned char *)resource_obj->value);
}
}
else {
// 2.02 Deleted: The entry was deleted by another thread in the background
- response->hdr->code = COAP_RESPONSE_CODE(202);
- const char* error_message = coap_response_phrase(response->hdr->code);
+ response->code = COAP_RESPONSE_CODE(202);
+ const char* error_message = coap_response_phrase(response->code);
coap_add_data(response, strlen(error_message), (unsigned char *)error_message);
}
+
+ xSemaphoreGive(coap_obj_ptr->semphr);
+
}
// Callback function when PUT method is received
STATIC void coap_resource_callback_put(coap_context_t * context,
struct coap_resource_t * resource,
- const coap_endpoint_t * endpoint,
- coap_address_t * address,
+ coap_session_t * session,
coap_pdu_t * request,
- str * token,
+ coap_binary_t * token,
+ coap_string_t * query_string,
coap_pdu_t * response)
{
+ xSemaphoreTake(coap_obj_ptr->semphr, portMAX_DELAY);
- /* Due to limitation of libcoap, a previously not existed resource cannot be created with PUT
- * As a result the If-Non-Match option does not work as execution will not reach this function
- * if the object with the given URI does not exist
- * https://sourceforge.net/p/libcoap/mailman/message/36177974
- * https://github.com/obgm/libcoap/pull/225
- */
-
- mod_coap_resource_obj_t* resource_obj = find_resource(resource);
-
- // Check if the resource exists. (e.g.: has not been removed in the background before we got the semaphore in mod_coap_read())
- if(resource_obj != NULL) {
+ mod_coap_resource_obj_t* resource_obj = NULL;
+ coap_opt_t* opt;
+ coap_opt_iterator_t opt_it;
+ const uint8_t* mediatype_opt_ptr = NULL;
+ int32_t mediatype_opt_value = COAP_MEDIATYPE_TEXT_PLAIN;
+ size_t data_size;
+ unsigned char *data;
+
+ // Get CONTENT-FORMAT option if specified
+ opt = coap_check_option(request, COAP_OPTION_CONTENT_FORMAT, &opt_it);
+ if(opt != NULL) {
+ unsigned short length = coap_opt_length(opt);
+ if(length != 0) { // 0 as length means the value is 0
+ mediatype_opt_ptr = coap_opt_value(opt);
+ mediatype_opt_value = (int32_t)coap_decode_var_bytes(mediatype_opt_ptr, length);
+ }
+ else {
+ mediatype_opt_value = 0;
+ }
+ }
+ // If no CONTENT-FORMAT is specified set the media type to unknown
+ else {
+ mediatype_opt_value = -1;
+ }
- bool precondition = false;
- coap_opt_iterator_t opt_it;
+ // Get the Data
+ if(coap_get_data(request, &data_size, &data) == 0) {
+ // Indicate that an error occurred
+ data_size = -1;
+ }
- // Check for If-Match option, currently only 1 If-Match option is supported
- coap_opt_t *opt = coap_check_option(request, COAP_OPTION_IF_MATCH, &opt_it);
+ resource_obj = find_resource_by_uri(resource->uri_path);
+ // Check if the resource exists, if not then create it
+ if(resource_obj == NULL) {
+ // Get the URI-PATH from the message because in this case the libcoap does not provide it via resource->uri_path
+ coap_opt_t *opt = coap_check_option(request, COAP_OPTION_URI_PATH, &opt_it);
+ unsigned short uri_path_opt_length = 0;
if(opt != NULL) {
+ uri_path_opt_length = coap_opt_length(opt);
+ }
- unsigned short length = coap_opt_length(opt);
- if(length != 0) { // 0 as length means the value is 0
-
- // The value is an E-TAG
- unsigned char* value = coap_opt_value(opt);
- unsigned int etag = coap_decode_var_bytes(value, length);
+ if(uri_path_opt_length > 0) {
+ // The value is the URI-PATH
+ const uint8_t* uri_opt_ptr = coap_opt_value(opt);
+ // Transform it to a proper C String
+ char* uri = malloc(uri_path_opt_length + 1);
+ memcpy(uri, uri_opt_ptr, uri_path_opt_length);
+ uri[uri_path_opt_length] = '\0';
+
+ // Create new resource
+ mp_obj_t mp_data = mp_obj_new_int(0); // Default value is 0
+ if(data_size != -1) {
+ // If value is specified in the request, use that
+ mp_data = mp_obj_new_bytes(data, data_size);
+ }
- // If we maintain the E-TAG of the resource then check for equality
- if((resource_obj->etag == true) && (etag == resource_obj->etag_value)) {
- precondition = true;
+ /* Create new resource with the following parameters:
+ * - URI: the given URI from request
+ * - Mediatype: Mediatype from the request
+ * - Max-Age: not specified
+ * - Etag: no
+ * - Default value: value from the request, if not specified it is 0
+ */
+
+ resource_obj = add_resource((const char *)uri, mediatype_opt_value, -1, mp_data, false);
+ if(resource_obj) {
+ // Resource has been created
+ // Allow all methods
+ coap_register_handler(resource_obj->coap_resource, COAP_REQUEST_GET, coap_resource_callback_get);
+ coap_register_handler(resource_obj->coap_resource, COAP_REQUEST_PUT, coap_resource_callback_put);
+ coap_register_handler(resource_obj->coap_resource, COAP_REQUEST_POST, coap_resource_callback_post);
+ coap_register_handler(resource_obj->coap_resource, COAP_REQUEST_DELETE, coap_resource_callback_delete);
+
+ // 2.01 Created
+ response->code = COAP_RESPONSE_CODE(201);
+ const char* message = coap_response_phrase(response->code);
+ coap_add_data(response, strlen(message), (unsigned char *)message);
+
+ // Call new resource callback if configured
+ if(coap_obj_ptr->callback_new_resource != NULL) {
+ mp_irq_queue_interrupt_non_ISR(coap_response_new_resource_handler_micropython, (void *)resource_obj);
}
}
- // If no value is specified for If-Match option then update the resource anyway
- else
- {
- precondition = true;
+ else {
+ // Resource has not been created due to internal error
+ // 5.00 Internal Server error occurred
+ response->code = COAP_RESPONSE_CODE(500);
+ const char* error_message = coap_response_phrase(response->code);
+ coap_add_data(response, strlen(error_message), (unsigned char *)error_message);
}
+
+ // No longer needed as stored elsewhere
+ free(uri);
}
- // If no If-Match option given, update the value
else {
- precondition = true;
+ /* TODO: in this case we might generate the URI-PATH for the new resource but theoretically that should be done only in POST,
+ and in POST libcoap does not support this. */
+
+ // No URI-PATH is provided or it is empty, resource cannot be created
+ // 4.00 Bad request
+ response->code = COAP_RESPONSE_CODE(400);
+ const char* error_message = coap_response_phrase(response->code);
+ coap_add_data(response, strlen(error_message), (unsigned char *)error_message);
+ }
+ }
+ // Resource already exists
+ else {
+ const uint8_t* etag_opt_ptr = NULL;
+ unsigned int etag_opt_value = 0;
+ bool precondition_check = true;
+
+ // Check for If-Non-Match option, currently only 1 If-Non-Match option is supported
+ coap_opt_t* opt = coap_check_option(request, COAP_OPTION_IF_NONE_MATCH, &opt_it);
+ // If there is If-Non_match option added to the request (its value is always empty) then do not overwrite the resource
+ if(opt != NULL){
+ precondition_check = false;
}
- if(precondition == true) {
- // Need to check if CONTENT-FORMAT option is specified and update the stored media type accordingly
- coap_opt_t *opt = coap_check_option(request, COAP_OPTION_CONTENT_FORMAT, &opt_it);
+ if(precondition_check == true) {
+ // Check for If-Match option, currently only 1 If-Match option is supported
+ opt = coap_check_option(request, COAP_OPTION_IF_MATCH, &opt_it);
if(opt != NULL) {
-
unsigned short length = coap_opt_length(opt);
-
if(length != 0) { // 0 as length means the value is 0
- unsigned char* value = coap_opt_value(opt);
- resource_obj->mediatype = coap_decode_var_bytes(value, length);
- }
- else {
- resource_obj->mediatype = 0;
+ // The value is an E-TAG
+ etag_opt_ptr = coap_opt_value(opt);
+ etag_opt_value = coap_decode_var_bytes(etag_opt_ptr, length);
}
}
- // If no CONTENT-FORMAT is specified set the media type to unknown
- else {
- resource_obj->mediatype = -1;
+
+ // If we maintain the E-TAG of the resource then check for equality
+ if((resource_obj->etag == true) && (etag_opt_value != resource_obj->etag_value)) {
+ precondition_check = false;
}
+ }
+
+ if(precondition_check == true) {
- // Update the data and set response code and add E-Tag option if needed
- size_t size;
- unsigned char *data;
- int ret = coap_get_data(request, &size, &data);
- if(ret == 1) {
- mp_obj_t new_value = mp_obj_new_str((const char*)data, size);
+ if(data_size != -1) {
+ mp_obj_t new_value = mp_obj_new_bytes(data, data_size);
resource_update_value(resource_obj, new_value);
+ resource_obj->mediatype = mediatype_opt_value;
// Value is updated
- response->hdr->code = COAP_RESPONSE_CODE(204);
+ response->code = COAP_RESPONSE_CODE(204);
// Add E-Tag option if configured
unsigned char buf[3];
if(resource_obj->etag == true) {
- coap_add_option(response, COAP_OPTION_ETAG, coap_encode_var_bytes(buf, resource_obj->etag_value), buf);
+ coap_add_option(response, COAP_OPTION_ETAG, coap_encode_var_safe(buf, sizeof(3), resource_obj->etag_value), buf);
}
}
else {
+ // There was a problem fetching the data from the message
// 5.00 Internal Server error occurred
- response->hdr->code = COAP_RESPONSE_CODE(500);
- const char* error_message = coap_response_phrase(response->hdr->code);
+ response->code = COAP_RESPONSE_CODE(500);
+ const char* error_message = coap_response_phrase(response->code);
coap_add_data(response, strlen(error_message), (unsigned char *)error_message);
}
}
else {
+ // If-None-Match or If-Match precondition is not fulfilled
// 4.12 Precondition failed
- response->hdr->code = COAP_RESPONSE_CODE(412);
- const char* error_message = coap_response_phrase(response->hdr->code);
+ response->code = COAP_RESPONSE_CODE(412);
+ const char* error_message = coap_response_phrase(response->code);
coap_add_data(response, strlen(error_message), (unsigned char *)error_message);
}
}
- else {
- // 2.02 Deleted: The entry was deleted by another thread in the background
- response->hdr->code = COAP_RESPONSE_CODE(202);
- const char* error_message = coap_response_phrase(response->hdr->code);
- coap_add_data(response, strlen(error_message), (unsigned char *)error_message);
- }
+
+ xSemaphoreGive(coap_obj_ptr->semphr);
+
}
// Callback function when POST method is received
STATIC void coap_resource_callback_post(coap_context_t * context,
- struct coap_resource_t * resource,
- const coap_endpoint_t * endpoint,
- coap_address_t * address,
- coap_pdu_t * request,
- str * token,
- coap_pdu_t * response)
+ struct coap_resource_t * resource,
+ coap_session_t * session,
+ coap_pdu_t * request,
+ coap_binary_t * token,
+ coap_string_t * query_string,
+ coap_pdu_t * response)
{
+ xSemaphoreTake(coap_obj_ptr->semphr, portMAX_DELAY);
/* Post does not really make sense to use over PUT as the URI of the resource must be specified by the requester
- * Due to limitation of libcoap, a previously not existed resource cannot be created with POST
- * https://sourceforge.net/p/libcoap/mailman/message/36177974
- * https://github.com/obgm/libcoap/pull/225
+ * Due to limitation of libcoap, a previously not existed resource cannot be created with POST.
+ * Currently the PUT handler will be called for creating a not existing resource
*/
- mod_coap_resource_obj_t* resource_obj = find_resource(resource);
+ mod_coap_resource_obj_t* resource_obj = find_resource_by_uri(resource->uri_path);
// Check if the resource exists. (e.g.: has not been removed in the background before we got the semaphore in mod_coap_read())
if(resource_obj != NULL) {
@@ -588,7 +785,7 @@ STATIC void coap_resource_callback_post(coap_context_t * context,
unsigned short length = coap_opt_length(opt);
if(length != 0) { // 0 as length means the value is 0
- unsigned char* value = coap_opt_value(opt);
+ const uint8_t* value = coap_opt_value(opt);
resource_obj->mediatype = coap_decode_var_bytes(value, length);
}
else {
@@ -609,131 +806,143 @@ STATIC void coap_resource_callback_post(coap_context_t * context,
resource_update_value(resource_obj, new_value);
// Value is updated
- response->hdr->code = COAP_RESPONSE_CODE(204);
+ response->code = COAP_RESPONSE_CODE(204);
// Add E-Tag option if configured
unsigned char buf[3];
if(resource_obj->etag == true) {
- coap_add_option(response, COAP_OPTION_ETAG, coap_encode_var_bytes(buf, resource_obj->etag_value), buf);
+ coap_add_option(response, COAP_OPTION_ETAG, coap_encode_var_safe(buf, sizeof(buf), resource_obj->etag_value), buf);
}
}
else {
// 5.00 Internal Server error occurred
- response->hdr->code = COAP_RESPONSE_CODE(500);
- const char* error_message = coap_response_phrase(response->hdr->code);
+ response->code = COAP_RESPONSE_CODE(500);
+ const char* error_message = coap_response_phrase(response->code);
coap_add_data(response, strlen(error_message), (unsigned char *)error_message);
}
}
else {
// 2.02 Deleted: The entry was deleted by another thread in the background
- response->hdr->code = COAP_RESPONSE_CODE(202);
- const char* error_message = coap_response_phrase(response->hdr->code);
+ response->code = COAP_RESPONSE_CODE(202);
+ const char* error_message = coap_response_phrase(response->code);
coap_add_data(response, strlen(error_message), (unsigned char *)error_message);
}
+
+ xSemaphoreGive(coap_obj_ptr->semphr);
}
// Callback function when DELETE method is received
STATIC void coap_resource_callback_delete(coap_context_t * context,
- struct coap_resource_t * resource,
- const coap_endpoint_t * endpoint,
- coap_address_t * address,
- coap_pdu_t * request,
- str * token,
- coap_pdu_t * response)
+ struct coap_resource_t * resource,
+ coap_session_t * session,
+ coap_pdu_t * request,
+ coap_binary_t * token,
+ coap_string_t * query_string,
+ coap_pdu_t * response)
{
- mod_coap_resource_obj_t* resource_obj = find_resource(resource);
+ xSemaphoreTake(coap_obj_ptr->semphr, portMAX_DELAY);
+
+ mod_coap_resource_obj_t* resource_obj = find_resource_by_uri(resource->uri_path);
if(resource_obj != NULL) {
// Remove it if exists
- remove_resource_by_key(resource->key);
+ remove_resource_by_uri(resource->uri_path);
}
// Reply with DELETED response
- response->hdr->code = COAP_RESPONSE_CODE(202);
-}
+ response->code = COAP_RESPONSE_CODE(202);
+ xSemaphoreGive(coap_obj_ptr->semphr);
-// Callback function for responses of requests
-STATIC void coap_response_handler(struct coap_context_t * context,
- const coap_endpoint_t *local_interface,
- const coap_address_t *remote,
- coap_pdu_t *sent,
- coap_pdu_t *received,
- const coap_tid_t id)
-{
+}
- size_t len;
- unsigned char *databuf;
- int ret = coap_get_data(received, &len, &databuf);
+STATIC void coap_response_handler_micropython(void* arg) {
- if(ret == 1){
+ mod_coap_response_handler_args_t* params = (mod_coap_response_handler_args_t*)arg;
+ mp_obj_t args[5];
+ args[0] = mp_obj_new_int(params->code);
+ args[1] = mp_obj_new_int(params->tid);
+ args[2] = mp_obj_new_int(params->type);
+ args[3] = mp_obj_new_bytes(params->token, params->token_length);
+ args[4] = mp_obj_new_bytes(params->data, params->data_length);
- mp_obj_t args[5];
- args[0] = mp_obj_new_int(received->hdr->code);
- args[1] = mp_obj_new_int(received->hdr->id);
- args[2] = mp_obj_new_int(received->hdr->type);
- args[3] = mp_obj_new_bytes(received->hdr->token, received->hdr->token_length);
- args[4] = mp_obj_new_bytes(databuf, len);
+ // Objects in C no longer needed, they are all transformed to MicroPython objects
+ free(params->token);
+ free(params->data);
+ free(params);
- // Call the registered function, it must have 5 parameters:
- mp_call_function_n_kw(coap_obj_ptr->callback, 5, 0, args);
- }
+ // Call the registered function, it must have 5 parameters:
+ mp_call_function_n_kw(coap_obj_ptr->callback_response, 5, 0, args);
}
-// Helper function to order the options in a request as per delta encoding
-STATIC int modcoap_order_opts(void *a, void *b) {
+// Callback function for new resources created by PUT
+STATIC void coap_response_new_resource_handler_micropython(void* arg)
+{
+ // The only arg is the newly created resource object
+ mp_obj_t args[1] = {(mod_coap_resource_obj_t*)arg};
+ // Call the registered function, it must have 1 parameter:
+ mp_call_function_n_kw(coap_obj_ptr->callback_new_resource, 1, 0, args);
+}
- coap_option *o1, *o2;
- if (!a || !b) {
- return a < b ? -1 : 1;
- }
+// Callback function for responses of requests
+STATIC void coap_response_handler(struct coap_context_t *context,
+ coap_session_t *session,
+ coap_pdu_t *sent,
+ coap_pdu_t *received,
+ const coap_tid_t id)
+{
+ size_t len;
+ uint8_t *databuf;
+ int ret = coap_get_data(received, &len, &databuf);
- o1 = (coap_option *)(((coap_list_t *)a)->data);
- o2 = (coap_option *)(((coap_list_t *)b)->data);
+ if(ret == 1){
- return (COAP_OPTION_KEY(*o1) < COAP_OPTION_KEY(*o2)) ? -1 : (COAP_OPTION_KEY(*o1) != COAP_OPTION_KEY(*o2));
+ // This will be freed in coap_response_handler_micropython()
+ mod_coap_response_handler_args_t* params = malloc(sizeof(mod_coap_response_handler_args_t));
+ params->code = received->code;
+ params->tid = received->tid;
+ params->type = received->type;
+ params->token_length = received->token_length;
+ // This will be freed in coap_response_handler_micropython()
+ params->token = malloc(params->token_length);
+ memcpy(params->token, received->token, params->token_length);
+ params->data_length = len;
+ // This will be freed in coap_response_handler_micropython()
+ params->data = malloc(params->data_length);
+ memcpy(params->data, databuf, params->data_length);
+
+ mp_irq_queue_interrupt_non_ISR(coap_response_handler_micropython, (void *)params);
+ }
}
// Helper function to create a new request message
-STATIC coap_pdu_t * modcoap_new_request
-(
- coap_context_t *ctx,
- unsigned int method,
- coap_list_t **options,
- const char* token,
- size_t token_length,
- const char *data,
- size_t length
-)
+STATIC coap_pdu_t * modcoap_new_request(coap_context_t *ctx,
+ coap_session_t* session,
+ unsigned int method,
+ coap_optlist_t **options,
+ const char* token,
+ size_t token_length,
+ const char *data,
+ size_t length)
{
- coap_list_t *opt;
- // TODO: get the type of the PDU as a parameter
- // TODO: calculate somehow the proper length
- coap_pdu_t *pdu = coap_pdu_init(COAP_MESSAGE_CON, method, htons(++(ctx->message_id)), COAP_MAX_PDU_SIZE);
+ // TODO: get the type of the PDU as a parameter, currently only Confirmable message is supported
+ // TODO: calculate the proper size of the PDU
+ coap_pdu_t *pdu = coap_pdu_init(COAP_MESSAGE_CON, method, coap_new_message_id(session), coap_session_max_pdu_size(session));
if(pdu == NULL){
return NULL;
}
- pdu->hdr->token_length = token_length;
- if (0 == coap_add_token(pdu, token_length, (const unsigned char*)token)) {
+ pdu->token_length = token_length;
+ if (0 == coap_add_token(pdu, token_length, (const uint8_t*)token)) {
return NULL;
}
if (options) {
- /* sort options for delta encoding */
- LL_SORT((*options), modcoap_order_opts);
-
- LL_FOREACH((*options), opt) {
- coap_option *o = (coap_option *)(opt->data);
- coap_add_option(pdu,
- COAP_OPTION_KEY(*o),
- COAP_OPTION_LENGTH(*o),
- COAP_OPTION_DATA(*o));
- }
+ coap_add_optlist_pdu(pdu, options);
}
if (length) {
@@ -743,80 +952,277 @@ STATIC coap_pdu_t * modcoap_new_request
return pdu;
}
-// Helper function to create a new option for a request message
-STATIC coap_list_t * modcoap_new_option_node(unsigned short key, unsigned int length, unsigned char *data) {
-
- coap_list_t *node = malloc(sizeof(coap_list_t) + sizeof(coap_option) + length);
- if (node) {
- coap_option *option;
- option = (coap_option *)(node->data);
- COAP_OPTION_KEY(*option) = key;
- COAP_OPTION_LENGTH(*option) = length;
- memcpy(COAP_OPTION_DATA(*option), data, length);
- }
-
- return node;
-}
-
/******************************************************************************
- DEFINE COAP RESOURCE CLASS FUNCTIONS
+ DEFINE COAP CLIENT SESSION CLASS FUNCTIONS
******************************************************************************/
-// Add attribute to a resource
-STATIC mp_obj_t mod_coap_resource_add_attribute(mp_obj_t self_in, mp_obj_t name, mp_obj_t val) {
+STATIC const mp_arg_t mod_coap_client_session_send_request_args[] = {
+ { MP_QSTR_self, MP_ARG_REQUIRED | MP_ARG_OBJ, },
+ { MP_QSTR_method, MP_ARG_REQUIRED | MP_ARG_INT, },
+ { MP_QSTR_uri_path, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL}},
+ { MP_QSTR_content_format, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1}},
+ { MP_QSTR_payload, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL}},
+ { MP_QSTR_token, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL}},
+ { MP_QSTR_include_options, MP_ARG_KW_ONLY | MP_ARG_BOOL,{.u_bool = true}}
+};
- mod_coap_resource_obj_t* self = (mod_coap_resource_obj_t*)self_in;
- const char* name_string = mp_obj_str_get_str(name);
- const char* val_string = mp_obj_str_get_str(val);
+// Send a new request on the client session
+STATIC mp_obj_t mod_coap_client_session_send_request(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
- coap_attr_t * attribute = coap_add_attr(self->coap_resource,
- (const unsigned char*)name_string,
- strlen(name_string),
- (const unsigned char*)val_string,
- strlen(val_string),
- 0);
+ // The Coap module should have been already initialized
+ if(initialized == true) {
- if(attribute == NULL) {
- nlr_raise(mp_obj_new_exception_msg(&mp_type_MemoryError, "Attribute cannot be added"));
- }
+ mp_arg_val_t args[MP_ARRAY_SIZE(mod_coap_client_session_send_request_args)];
+ mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(args), mod_coap_client_session_send_request_args, args);
- return mp_const_none;
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_3(mod_coap_resource_add_attribute_obj, mod_coap_resource_add_attribute);
+ uint8_t* uri_path = NULL;
+ size_t uri_path_length = 0;
+ coap_optlist_t *optlist = NULL;
+ mod_coap_client_session_obj_t* self = args[0].u_obj;
-// Gets or sets the value of a resource
-STATIC mp_obj_t mod_coap_resource_value(mp_uint_t n_args, const mp_obj_t *args) {
+ // Get the method
+ mp_int_t method;
+ switch (args[1].u_int){
+ case MODCOAP_REQUEST_GET:
+ method = COAP_REQUEST_GET;
+ break;
+ case MODCOAP_REQUEST_PUT:
+ method = COAP_REQUEST_PUT;
+ break;
+ case MODCOAP_REQUEST_POST:
+ method = COAP_REQUEST_POST;
+ break;
+ case MODCOAP_REQUEST_DELETE:
+ method = COAP_REQUEST_DELETE;
+ break;
+ default:
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Invalid \"method\" parameter value!"));
+ }
- mod_coap_resource_obj_t* self = (mod_coap_resource_obj_t*)args[0];
- mp_obj_t ret = mp_const_none;
- xSemaphoreTake(coap_obj_ptr->semphr, portMAX_DELAY);
- // If the value exists, e.g.: not deleted from another task before we got the semaphore
- if(self->value != NULL) {
- if (n_args == 1) {
- // get
- ret = mp_obj_new_bytes(self->value, self->value_len);
- } else {
- // set
- resource_update_value(self, (mp_obj_t)args[1]);
+ // Get the path
+ if(args[2].u_obj != MP_OBJ_NULL) {
+ uri_path = (uint8_t*)mp_obj_str_get_data(args[2].u_obj, &uri_path_length);
}
- }
- xSemaphoreGive(coap_obj_ptr->semphr);
- return ret;
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_coap_resource_value_obj, 1, 2, mod_coap_resource_value);
+ // Get the content format
+ mp_int_t content_format = args[3].u_int;
+ switch (content_format){
+ case -1:
+ case COAP_MEDIATYPE_TEXT_PLAIN:
+ case COAP_MEDIATYPE_APPLICATION_CBOR:
+ case COAP_MEDIATYPE_APPLICATION_EXI:
+ case COAP_MEDIATYPE_APPLICATION_JSON:
+ case COAP_MEDIATYPE_APPLICATION_LINK_FORMAT:
+ case COAP_MEDIATYPE_APPLICATION_OCTET_STREAM:
+ case COAP_MEDIATYPE_APPLICATION_RDF_XML:
+ case COAP_MEDIATYPE_APPLICATION_XML:
+ break;
+ default:
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Invalid \"content_format\" parameter value!"));
+ }
+ // Get the payload
+ const char* payload = NULL;
+ size_t payload_length = 0;
+ if(args[4].u_obj != MP_OBJ_NULL) {
+ payload = mp_obj_str_get_data(args[4].u_obj, &payload_length);
+ }
-// Enable or disable a specific action on a resource
-STATIC mp_obj_t mod_coap_resource_callback_enable(mp_obj_t self_in, mp_obj_t request_type_in, mp_obj_t enable_in) {
+ // Get the token
+ const char* token = NULL;
+ size_t token_length = 0;
+ if(args[5].u_obj != MP_OBJ_NULL) {
+ token = mp_obj_str_get_data(args[5].u_obj, &token_length);
+ }
- mod_coap_resource_obj_t* self = (mod_coap_resource_obj_t*)self_in;
+ // Get the include_options parameter
+ bool include_options = args[6].u_bool;
+
+ // Take the context's semaphore to avoid concurrent access
+ xSemaphoreTake(coap_obj_ptr->semphr, portMAX_DELAY);
+
+ if(include_options == true) {
+
+ // Put the URI-HOST as an option
+ coap_insert_optlist(&optlist, coap_new_optlist(COAP_OPTION_URI_HOST, 4, (const uint8_t*)(&self->session->remote_addr.addr.sin.sin_addr.s_addr)));
+
+ // Put the URI-PORT as an option
+ // Already stored in Big Endian
+ uint8_t portbuf[2];
+ memcpy(portbuf, &self->session->remote_addr.addr.sin.sin_port, sizeof(portbuf));
+ coap_insert_optlist(&optlist, coap_new_optlist(COAP_OPTION_URI_PORT, sizeof(portbuf), portbuf));
+
+ // Split up the URI-PATH into more segments if needed
+ //TODO: allocate the proper length
+ size_t length = 300;
+ uint8_t* path = malloc(length);
+ uint8_t* path_start = path;
+ int segments = coap_split_path(uri_path, uri_path_length, path, &length);
+
+ // Insert the segments as separate URI-Path options
+ while (segments--) {
+ coap_insert_optlist(&optlist, coap_new_optlist(COAP_OPTION_URI_PATH, coap_opt_length(path), coap_opt_value(path)));
+ path += coap_opt_size(path);
+ }
+
+ // Free up the allocated space, at this point path does not point to the beginning
+ free(path_start);
+
+ // Put Content Format option if given
+ if(content_format != -1) {
+ uint8_t content_format_buf[2];
+ // Store it in Big Endian
+ content_format_buf[0] = (content_format >> 8) & 0xFF;
+ content_format_buf[1] = content_format & 0xFF;
+ coap_insert_optlist(&optlist, coap_new_optlist(COAP_OPTION_CONTENT_FORMAT, sizeof(content_format_buf), content_format_buf));
+ }
+ }
+
+ // Create new request
+ coap_pdu_t *pdu = modcoap_new_request(coap_obj_ptr->context, self->session, method, &optlist, token, token_length, payload, payload_length);
+
+ // Clean up optlist, they are already part of the PDU if it has been created
+ coap_delete_optlist(optlist);
+
+ if (pdu == NULL) {
+ xSemaphoreGive(coap_obj_ptr->semphr);
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Cannot create request"));
+ }
+
+ // Send out the request
+ // The session contains the destination address and port
+ coap_tid_t ret = coap_send(self->session, pdu);
+
+ // Sending the packet failed
+ if(ret == COAP_INVALID_TID) {
+ xSemaphoreGive(coap_obj_ptr->semphr);
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Sending message failed!"));
+ }
+
+ // Fetch the message ID to be used from MicroPython to match the request with response
+ mp_obj_t id = mp_obj_new_int(pdu->tid);
+
+ xSemaphoreGive(coap_obj_ptr->semphr);
+
+ return id;
+ }
+ else {
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_RuntimeError, "Coap module has not been initialized!"));
+ // Just to fulfill the compiler's needs
+ return mp_const_none;
+ }
+}
+
+STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mod_coap_client_session_send_request_obj, 2, mod_coap_client_session_send_request);
+
+// Get the details of this Client Session
+STATIC mp_obj_t mod_coap_client_session_get_details(mp_obj_t self_in) {
+
+ // The Coap module should have been already initialized
+ if(initialized == true) {
+
+ mp_obj_t list = mp_obj_new_list(0, NULL);
+
+ xSemaphoreTake(coap_obj_ptr->semphr, portMAX_DELAY);
+
+ mod_coap_client_session_obj_t* self = (mod_coap_client_session_obj_t*)self_in;
+
+ mp_obj_list_append(list, self->ip_addr);
+ mp_obj_list_append(list, self->port);
+ mp_obj_list_append(list, self->protocol);
+
+ xSemaphoreGive(coap_obj_ptr->semphr);
+
+ return list;
+
+ }
+ else {
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_RuntimeError, "Coap module has not been initialized!"));
+ // Just to fulfill the compiler's needs
+ return mp_const_none;
+ }
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_coap_client_session_get_details_obj, mod_coap_client_session_get_details);
+
+STATIC const mp_map_elem_t coap_client_session_locals_table[] = {
+ // instance methods
+ { MP_OBJ_NEW_QSTR(MP_QSTR_send_request), (mp_obj_t)&mod_coap_client_session_send_request_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_get_details), (mp_obj_t)&mod_coap_client_session_get_details_obj },
+};
+STATIC MP_DEFINE_CONST_DICT(coap_client_session_locals, coap_client_session_locals_table);
+
+STATIC const mp_obj_type_t mod_coap_client_session_type = {
+ { &mp_type_type },
+ .name = MP_QSTR_CoapClientSession,
+ .locals_dict = (mp_obj_t)&coap_client_session_locals,
+};
+
+
+/******************************************************************************
+ DEFINE COAP RESOURCE CLASS FUNCTIONS
+ ******************************************************************************/
+
+// Add attribute to a resource
+STATIC mp_obj_t mod_coap_resource_add_attribute(mp_obj_t self_in, mp_obj_t name, mp_obj_t val) {
+
+ mod_coap_resource_obj_t* self = (mod_coap_resource_obj_t*)self_in;
+
+ coap_str_const_t name_coap_str;
+ name_coap_str.s = (const uint8_t *)mp_obj_str_get_str(name);
+ name_coap_str.length = strlen((const char*)name_coap_str.s);
+
+ coap_str_const_t val_coap_str;
+ val_coap_str.s = (const uint8_t *)mp_obj_str_get_str(val);
+ val_coap_str.length = strlen((const char*)val_coap_str.s);
+
+ coap_attr_t * attribute = coap_add_attr(self->coap_resource,
+ &name_coap_str,
+ &val_coap_str,
+ 0);
+
+ if(attribute == NULL) {
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_MemoryError, "Attribute cannot be added"));
+ }
+
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_3(mod_coap_resource_add_attribute_obj, mod_coap_resource_add_attribute);
+
+
+// Gets or sets the value of a resource
+STATIC mp_obj_t mod_coap_resource_value(mp_uint_t n_args, const mp_obj_t *args) {
+
+ mod_coap_resource_obj_t* self = (mod_coap_resource_obj_t*)args[0];
+ mp_obj_t ret = mp_const_none;
+
+ xSemaphoreTake(coap_obj_ptr->semphr, portMAX_DELAY);
+ // If the value exists, e.g.: not deleted from another task before we got the semaphore
+ if(self->value != NULL) {
+ if (n_args == 1) {
+ // get
+ ret = mp_obj_new_bytes(self->value, self->value_len);
+ } else {
+ // set
+ resource_update_value(self, (mp_obj_t)args[1]);
+ }
+ }
+ xSemaphoreGive(coap_obj_ptr->semphr);
+
+ return ret;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_coap_resource_value_obj, 1, 2, mod_coap_resource_value);
+
+
+// Enable or disable a specific action on a resource
+STATIC mp_obj_t mod_coap_resource_callback_enable(mp_obj_t self_in, mp_obj_t request_type_in, mp_obj_t enable_in) {
+
+ mod_coap_resource_obj_t* self = (mod_coap_resource_obj_t*)self_in;
mp_int_t request_type = mp_obj_get_int(request_type_in);
- bool enable = mp_obj_get_int(request_type_in) == 0 ? false : true;
+ bool enable = mp_obj_get_int(enable_in) == 0 ? false : true;
if(request_type & MODCOAP_REQUEST_GET) {
if(enable) coap_register_handler(self->coap_resource, COAP_REQUEST_GET, coap_resource_callback_get);
@@ -844,11 +1250,75 @@ STATIC mp_obj_t mod_coap_resource_callback_enable(mp_obj_t self_in, mp_obj_t req
STATIC MP_DEFINE_CONST_FUN_OBJ_3(mod_coap_resource_callback_enable_obj, mod_coap_resource_callback_enable);
+// Get the details of this resource
+STATIC mp_obj_t mod_coap_resource_get_details(mp_obj_t self_in) {
+
+ mod_coap_resource_obj_t* self = (mod_coap_resource_obj_t*)self_in;
+ mp_obj_t list = mp_obj_new_list(0, NULL);
+
+
+ xSemaphoreTake(coap_obj_ptr->semphr, portMAX_DELAY);
+
+ mp_obj_list_append(list, mp_obj_new_str((const char*)self->coap_resource->uri_path->s, self->coap_resource->uri_path->length));
+ mp_obj_list_append(list, MP_OBJ_NEW_SMALL_INT(self->mediatype));
+ mp_obj_list_append(list, MP_OBJ_NEW_SMALL_INT(self->max_age));
+ mp_obj_list_append(list, MP_OBJ_NEW_SMALL_INT(self->etag));
+ mp_obj_list_append(list, MP_OBJ_NEW_SMALL_INT(self->etag_value));
+
+ xSemaphoreGive(coap_obj_ptr->semphr);
+
+ return list;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_coap_resource_get_details_obj, mod_coap_resource_get_details);
+
+STATIC const mp_arg_t mod_coap_resource_set_details_args[] = {
+ { MP_QSTR_self, MP_ARG_REQUIRED | MP_ARG_OBJ, },
+ { MP_QSTR_mediatype, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_obj = mp_const_none}},
+ { MP_QSTR_max_age, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_obj = mp_const_none}},
+ { MP_QSTR_etag, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_obj = mp_const_none}}
+};
+
+// Set the details of this resource
+STATIC mp_obj_t mod_coap_resource_set_details(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+
+ mp_arg_val_t args[MP_ARRAY_SIZE(mod_coap_resource_set_details_args)];
+ mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(args), mod_coap_resource_set_details_args, args);
+
+ mod_coap_resource_obj_t* self = (mod_coap_resource_obj_t*)args[0].u_obj;
+
+ xSemaphoreTake(coap_obj_ptr->semphr, portMAX_DELAY);
+
+ // Set mediatype if given
+ if(args[1].u_obj != mp_const_none) {
+ self->mediatype = args[1].u_int;
+ }
+
+ // Set max age if given
+ if(args[2].u_obj != mp_const_none) {
+ self->max_age = args[2].u_int;
+ }
+
+ // Set etag if given
+ if(args[3].u_obj != mp_const_none) {
+ self->etag = args[3].u_bool;
+ self->etag_value = self->etag ? 1 : 0;
+ }
+
+ xSemaphoreGive(coap_obj_ptr->semphr);
+
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mod_coap_resource_set_details_obj, 1, mod_coap_resource_set_details);
+
+
STATIC const mp_map_elem_t coap_resource_locals_table[] = {
// instance methods
{ MP_OBJ_NEW_QSTR(MP_QSTR_add_attribute), (mp_obj_t)&mod_coap_resource_add_attribute_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_value), (mp_obj_t)&mod_coap_resource_value_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_callback), (mp_obj_t)&mod_coap_resource_callback_enable_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_get_details), (mp_obj_t)&mod_coap_resource_get_details_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_set_details), (mp_obj_t)&mod_coap_resource_set_details_obj }
+
};
STATIC MP_DEFINE_CONST_DICT(coap_resource_locals, coap_resource_locals_table);
@@ -863,66 +1333,67 @@ STATIC const mp_obj_type_t mod_coap_resource_type = {
******************************************************************************/
-STATIC void mod_coap_init_helper(mp_obj_t address, bool service_discovery) {
+STATIC void mod_coap_init_helper(mp_obj_t address, bool service_discovery, bool dynamic_resources, mp_obj_t key_in, mp_obj_t hint_in) {
- coap_address_t server_address;
+ // Initialize Context without address, in Server mode address will be added
+ coap_obj_ptr->context = coap_new_context(NULL);
- // Create a new Coap context
- coap_address_init(&server_address);
- server_address.addr.sin.sin_family = AF_INET;
- // The address will be in Big Endian order
- uint16_t port = netutils_parse_inet_addr(address, (uint8_t*)&server_address.addr.sin.sin_addr.s_addr, NETUTILS_BIG);
- // Store the port in network byte order
- server_address.addr.sin.sin_port = htons(port);
-
- // Will create a new socket and bind it to the address and port
- coap_obj_ptr->context = coap_new_context(&server_address);
-
- // Create socket object
- coap_obj_ptr->socket = m_new_obj_with_finaliser(mod_network_socket_obj_t);
- coap_obj_ptr->socket->sock_base.nic_type = MP_OBJ_NULL;
- coap_obj_ptr->socket->base.type = (mp_obj_t)&socket_type;
- coap_obj_ptr->socket->sock_base.u.u_param.domain = AF_INET;
- // Coap protocol works on UDP
- coap_obj_ptr->socket->sock_base.u.u_param.type = SOCK_DGRAM;
- coap_obj_ptr->socket->sock_base.u.u_param.proto = IPPROTO_UDP;
- coap_obj_ptr->socket->sock_base.nic = MP_OBJ_NULL;
- coap_obj_ptr->socket->sock_base.nic_type = NULL;
- coap_obj_ptr->socket->sock_base.u.u_param.fileno = -1;
- coap_obj_ptr->socket->sock_base.timeout = 0;
- coap_obj_ptr->socket->sock_base.is_ssl = false;
- coap_obj_ptr->socket->sock_base.connected = false;
-
- // Find and register the NIC
- coap_obj_ptr->socket->sock_base.nic = mod_network_find_nic(coap_obj_ptr->socket, (const byte *)"");
- coap_obj_ptr->socket->sock_base.nic_type = (mod_network_nic_type_t*)mp_obj_get_type(coap_obj_ptr->socket->sock_base.nic);
- // Register the socket number
- coap_obj_ptr->socket->sock_base.u.sd = coap_obj_ptr->context->sockfd;
-
- // Add the socket to the list
- modusocket_socket_add(coap_obj_ptr->socket->sock_base.u.sd, true);
-
- // Listen on coap multicast ip address for service discovery if enabled
- if(service_discovery == true) {
- // Compose the address structure
- struct ip_mreq mreq;
- memcpy(&mreq.imr_interface, &server_address.addr.sin.sin_addr, sizeof(mreq.imr_interface));
- int _errno = 0;
- mp_obj_t list = mp_obj_new_list(0, NULL);
- mp_obj_list_append(list, mp_obj_new_str(MODCOAP_IP4_MULTICAST, strlen(MODCOAP_IP4_MULTICAST)));
- mp_obj_list_append(list, mp_obj_new_int(0)); // Port does not matter
- netutils_parse_inet_addr(list, (uint8_t*)&mreq.imr_multiaddr, NETUTILS_BIG);
+ // Configure Server mode
+ if(address != NULL) {
+ coap_address_t server_address;
- // Set socket option to join multicast group
- coap_obj_ptr->socket->sock_base.nic_type->n_setsockopt(coap_obj_ptr->socket, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq), &_errno);
- }
+ // Create a new Coap context
+ coap_address_init(&server_address);
+ server_address.addr.sin.sin_family = AF_INET;
+ // The address will be in Big Endian order
+ uint16_t port = netutils_parse_inet_addr(address, (uint8_t*)&server_address.addr.sin.sin_addr.s_addr, NETUTILS_BIG);
+ // Store the port in network byte order
+ server_address.addr.sin.sin_port = htons(port);
+
+ // Configure PSK if given
+ if(key_in != mp_const_none && hint_in != mp_const_none) {
+ const char *hint = mp_obj_str_get_str(hint_in);
+ const uint8_t *key = (const uint8_t *)mp_obj_str_get_str(key_in);
+ size_t key_len = strlen((const char*)key);
+ coap_context_set_psk(coap_obj_ptr->context, hint, key, key_len);
+ coap_new_endpoint(coap_obj_ptr->context, &server_address, COAP_PROTO_DTLS);
+ }
+ else {
+ coap_new_endpoint(coap_obj_ptr->context, &server_address, COAP_PROTO_UDP);
+ }
+ // Listen on coap multicast ip address for service discovery if enabled
+ if(service_discovery == true) {
+ // Compose the address structure
+ struct ip_mreq mreq;
+ memcpy(&mreq.imr_interface, &server_address.addr.sin.sin_addr, sizeof(mreq.imr_interface));
+ mp_obj_t list = mp_obj_new_list(0, NULL);
+ mp_obj_list_append(list, mp_obj_new_str(MODCOAP_IP4_MULTICAST, strlen(MODCOAP_IP4_MULTICAST)));
+ mp_obj_list_append(list, mp_obj_new_int(0)); // Port does not matter
+ netutils_parse_inet_addr(list, (uint8_t*)&mreq.imr_multiaddr, NETUTILS_BIG);
+
+ // Set socket option to join multicast group
+ lwip_setsockopt(coap_obj_ptr->context->endpoint->sock.fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq));
+ }
+
+ // These will be registered on demand by the user
+ coap_obj_ptr->callback_response = NULL;
+ coap_obj_ptr->callback_new_resource = NULL;
+ if(dynamic_resources == true) {
+ // Create a dummy resource to handle PUTs to unknown URIs
+ coap_resource_t* unknown_resource = coap_resource_unknown_init(coap_resource_callback_put);
+ coap_add_resource(coap_obj_ptr->context, unknown_resource);
+ }
+ }
}
STATIC const mp_arg_t mod_coap_init_args[] = {
- { MP_QSTR_address, MP_ARG_OBJ | MP_ARG_REQUIRED, },
- { MP_QSTR_port, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_int = MODCOAP_DEFAULT_PORT}},
+ { MP_QSTR_address, MP_ARG_OBJ , {.u_obj = NULL}},
+ { MP_QSTR_port, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_obj = mp_const_none}},
{ MP_QSTR_service_discovery, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = false}},
+ { MP_QSTR_dynamic_resources, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = false}},
+ { MP_QSTR_psk, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = mp_const_none}},
+ { MP_QSTR_hint, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = mp_const_none}},
};
// Initialize the module
@@ -932,55 +1403,73 @@ STATIC mp_obj_t mod_coap_init(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map
// Only 1 context is supported currently
if(initialized == false) {
- MP_STATE_PORT(coap_ptr) = m_new_obj(mod_coap_obj_t);
+ MP_STATE_PORT(coap_ptr) = m_malloc(sizeof(mod_coap_obj_t));
coap_obj_ptr = MP_STATE_PORT(coap_ptr);
coap_obj_ptr->context = NULL;
coap_obj_ptr->resources = NULL;
- coap_obj_ptr->socket = NULL;
+ coap_obj_ptr->client_sessions = NULL;
coap_obj_ptr->semphr = NULL;
mp_arg_val_t args[MP_ARRAY_SIZE(mod_coap_init_args)];
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(args), mod_coap_init_args, args);
- mp_obj_t list = mp_obj_new_list(0, NULL);
- // Get the address as a string
- mp_obj_list_append(list, args[0].u_obj);
- // Get the port as a number
- mp_obj_list_append(list, mp_obj_new_int(args[1].u_int));
- // Get whether service discovery is supported
- bool service_discovery = args[2].u_bool;
+ // The module is used in Coap Server and Client mode
+ if(args[0].u_obj != NULL) {
- mod_coap_init_helper(list, service_discovery);
+ // Check security parameters
+ mp_obj_t psk = args[4].u_obj;
+ mp_obj_t hint = args[5].u_obj;
- coap_obj_ptr->semphr = xSemaphoreCreateBinary();
- xSemaphoreGive(coap_obj_ptr->semphr);
+ // If neither PSK nor Hint is defined that means no security is enabled, otherwise security is used
+ if((psk == mp_const_none && hint != mp_const_none) || (psk != mp_const_none && hint == mp_const_none)) {
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Both PSK and Hint must be defined"));
+ }
- initialized = true;
- }
- else {
- nlr_raise(mp_obj_new_exception_msg(&mp_type_RuntimeError, "Coap module already initialized!"));
- }
+ // Get the address
+ mp_obj_t address = args[0].u_obj;
+ // Get the port
+ mp_obj_t port = args[1].u_obj;
+ // If no value is specified for the port then use default port value depending on whether security is enabled
+ if(port == mp_const_none) {
+ if(psk != mp_const_none && hint != mp_const_none) {
+ port = mp_obj_new_int(COAPS_DEFAULT_PORT);
+ }
+ else if((psk == mp_const_none && hint == mp_const_none)){
+ port = mp_obj_new_int(COAP_DEFAULT_PORT);
+ }
+ }
+ // Get whether service discovery is supported
+ bool service_discovery = args[2].u_bool;
+ // Get whether dynamic resource creation is allowed via PUT
+ bool dynamic_resources = args[3].u_bool;
- return mp_const_none;
-}
+ // Compose a list containing the address and the port
+ mp_obj_t list = mp_obj_new_list(0, NULL);
+ mp_obj_list_append(list, address);
+ mp_obj_list_append(list, port);
-STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mod_coap_init_obj, 1, mod_coap_init);
+ mod_coap_init_helper(list, service_discovery, dynamic_resources, psk, hint);
+ }
+ // The module is used in Coap Client only mode
+ else {
+ mod_coap_init_helper(NULL, false, false, mp_const_none, mp_const_none);
+ }
-// Get the socket of the Coap
-STATIC mp_obj_t mod_coap_socket(void) {
+ xTaskCreatePinnedToCore(TASK_MODCOAP, "Coap", MODCOAP_TASK_STACK_SIZE / sizeof(StackType_t), NULL, MODCOAP_TASK_PRIORITY, &ModCoapTaskHandle, 1);
- // The Coap module should have been already initialized
- if(initialized == true) {
- return coap_obj_ptr->socket;
+ coap_obj_ptr->semphr = xSemaphoreCreateBinary();
+ xSemaphoreGive(coap_obj_ptr->semphr);
+
+ initialized = true;
}
else {
- nlr_raise(mp_obj_new_exception_msg(&mp_type_RuntimeError, "Coap module has not been initialized!"));
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_RuntimeError, "Coap module already initialized!"));
}
return mp_const_none;
}
-STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_coap_socket_obj, mod_coap_socket);
+STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mod_coap_init_obj, 0, mod_coap_init);
STATIC const mp_arg_t mod_coap_add_resource_args[] = {
{ MP_QSTR_uri, MP_ARG_REQUIRED | MP_ARG_OBJ, },
@@ -1042,33 +1531,34 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_coap_remove_resource_obj, mod_coap_remove_r
// Get a resource from the context if exists
STATIC mp_obj_t mod_coap_get_resource(mp_obj_t uri_in) {
- mp_obj_t res = mp_const_none;
+ mp_obj_t res = NULL;
// The Coap module should have been already initialized
if(initialized == true) {
xSemaphoreTake(coap_obj_ptr->semphr, portMAX_DELAY);
- const char* uri = mp_obj_str_get_str(uri_in);
- coap_key_t key;
- (void)coap_hash_path((const unsigned char*)uri, strlen(uri), key);
- res = find_resource_by_key(key);
+ coap_str_const_t coap_str;
+ coap_str.s = (const uint8_t*)mp_obj_str_get_str(uri_in);
+ coap_str.length = strlen((const char*)coap_str.s);
+ res = find_resource_by_uri(&coap_str);
xSemaphoreGive(coap_obj_ptr->semphr);
}
else {
nlr_raise(mp_obj_new_exception_msg(&mp_type_RuntimeError, "Coap module has not been initialized!"));
}
- return res;
+ return res == NULL ? mp_const_none : res;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_coap_get_resource_obj, mod_coap_get_resource);
-
-// Call coap_read
-STATIC mp_obj_t mod_coap_read(void) {
+// Register the user's callback handler to be called when response is received to a request
+STATIC mp_obj_t mod_coap_register_response_handler(mp_obj_t callback) {
// The Coap module should have been already initialized
if(initialized == true) {
// Take the context's semaphore to avoid concurrent access, this will guard the handler functions too
xSemaphoreTake(coap_obj_ptr->semphr, portMAX_DELAY);
- coap_read(coap_obj_ptr->context);
+ // Register the user's callback handler
+ coap_obj_ptr->callback_response = callback;
+ coap_register_response_handler(coap_obj_ptr->context, coap_response_handler);
xSemaphoreGive(coap_obj_ptr->semphr);
}
else {
@@ -1077,18 +1567,17 @@ STATIC mp_obj_t mod_coap_read(void) {
return mp_const_none;
}
-STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_coap_read_obj, mod_coap_read);
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_coap_register_response_handler_obj, mod_coap_register_response_handler);
-// Register the user's callback handler
-STATIC mp_obj_t mod_coap_register_response_handler(mp_obj_t callback) {
+// Register the user's callback handler to be called when new resource is created via PUT
+STATIC mp_obj_t mod_coap_register_new_resource_handler(mp_obj_t callback) {
// The Coap module should have been already initialized
if(initialized == true) {
// Take the context's semaphore to avoid concurrent access, this will guard the handler functions too
xSemaphoreTake(coap_obj_ptr->semphr, portMAX_DELAY);
// Register the user's callback handler
- coap_obj_ptr->callback = callback;
- coap_register_response_handler(coap_obj_ptr->context, coap_response_handler);
+ coap_obj_ptr->callback_new_resource = callback;
xSemaphoreGive(coap_obj_ptr->semphr);
}
else {
@@ -1097,213 +1586,124 @@ STATIC mp_obj_t mod_coap_register_response_handler(mp_obj_t callback) {
return mp_const_none;
}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_coap_register_response_handler_obj, mod_coap_register_response_handler);
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_coap_register_new_resource_handler_obj, mod_coap_register_new_resource_handler);
-STATIC const mp_arg_t mod_coap_send_request_args[] = {
- { MP_QSTR_uri_host, MP_ARG_REQUIRED | MP_ARG_OBJ, },
- { MP_QSTR_method, MP_ARG_REQUIRED | MP_ARG_INT, },
- { MP_QSTR_uri_port, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = MODCOAP_DEFAULT_PORT}},
- { MP_QSTR_uri_path, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL}},
- { MP_QSTR_content_format, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1}},
- { MP_QSTR_payload, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL}},
- { MP_QSTR_token, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL}},
- { MP_QSTR_include_options, MP_ARG_KW_ONLY | MP_ARG_BOOL,{.u_bool = true}}
+STATIC const mp_arg_t mod_coap_new_client_session_args[] = {
+ { MP_QSTR_address, MP_ARG_OBJ , {.u_obj = NULL}},
+ { MP_QSTR_port, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_obj = mp_const_none}},
+ { MP_QSTR_psk, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = mp_const_none}},
+ { MP_QSTR_identity, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = mp_const_none}},
};
-
-
-// Call coap_read
-STATIC mp_obj_t mod_coap_send_request(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+// Create a new client session
+STATIC mp_obj_t mod_coap_new_client_session(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
// The Coap module should have been already initialized
if(initialized == true) {
- mp_arg_val_t args[MP_ARRAY_SIZE(mod_coap_send_request_args)];
- mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(args), mod_coap_send_request_args, args);
+ mp_arg_val_t args[MP_ARRAY_SIZE(mod_coap_new_client_session_args)];
+ mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(args), mod_coap_new_client_session_args, args);
- coap_uri_t coap_uri;
+ mp_obj_t ip_addr = args[0].u_obj;
+ mp_obj_t port = args[1].u_obj;
+ mp_obj_t psk = args[2].u_obj;
+ mp_obj_t identity = args[3].u_obj;
- // Get the destination address
- coap_uri.host.length = 0;
- coap_uri.host.s = (unsigned char*)mp_obj_str_get_data(args[0].u_obj, &coap_uri.host.length);
+ // If port not defined, select appropriate default port
+ if(port == mp_const_none) {
+ if(psk == mp_const_none) {
+ port = mp_obj_new_int(COAP_DEFAULT_PORT);
+ }
+ else {
+ port = mp_obj_new_int(COAPS_DEFAULT_PORT);
+ }
+ }
- // Get the method
- mp_int_t method;
- switch (args[1].u_int){
- case MODCOAP_REQUEST_GET:
- method = COAP_REQUEST_GET;
- break;
- case MODCOAP_REQUEST_PUT:
- method = COAP_REQUEST_PUT;
- break;
- case MODCOAP_REQUEST_POST:
- method = COAP_REQUEST_POST;
- break;
- case MODCOAP_REQUEST_DELETE:
- method = COAP_REQUEST_DELETE;
- break;
- default:
- nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Invalid \"method\" parameter value!"));
+ // If security is used then port must be different than 5683
+ if(psk != mp_const_none && mp_obj_get_int(port) == COAP_DEFAULT_PORT) {
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "If Security is configured port must not be 5683!"));
+ }
+ // If security is NOT used then port must be different than 5684
+ else if(psk == mp_const_none && mp_obj_get_int(port) == COAPS_DEFAULT_PORT) {
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "If Security is not configured port must not be 5684!"));
}
+ // Check if both PSK and Identity are configured
+ if((psk != mp_const_none && identity == mp_const_none) || (psk == mp_const_none && identity != mp_const_none)){
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "For Security both PSK and Identity must be configured!"));
+ }
- // Get the port
- coap_uri.port = args[2].u_int;
- // Get the path
- coap_uri.path.s = NULL;
- coap_uri.path.length = 0;
- if(args[3].u_obj != MP_OBJ_NULL) {
- coap_uri.path.s = (unsigned char*)mp_obj_str_get_data(args[3].u_obj, &coap_uri.path.length);
- }
+ xSemaphoreTake(coap_obj_ptr->semphr, portMAX_DELAY);
- // Get the content format
- mp_int_t content_format = args[4].u_int;
- switch (content_format){
- case -1:
- case COAP_MEDIATYPE_TEXT_PLAIN:
- case COAP_MEDIATYPE_APPLICATION_CBOR:
- case COAP_MEDIATYPE_APPLICATION_EXI:
- case COAP_MEDIATYPE_APPLICATION_JSON:
- case COAP_MEDIATYPE_APPLICATION_LINK_FORMAT:
- case COAP_MEDIATYPE_APPLICATION_OCTET_STREAM:
- case COAP_MEDIATYPE_APPLICATION_RDF_XML:
- case COAP_MEDIATYPE_APPLICATION_XML:
- break;
- default:
- nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Invalid \"content_format\" parameter value!"));
- }
+ mod_coap_client_session_obj_t* session = new_client_session(ip_addr, port, psk, identity);
- // Get the payload
- const char* payload = NULL;
- size_t payload_length = 0;
- if(args[5].u_obj != MP_OBJ_NULL) {
- payload = mp_obj_str_get_data(args[5].u_obj, &payload_length);
- }
+ xSemaphoreGive(coap_obj_ptr->semphr);
- // Get the token
- const char* token = NULL;
- size_t token_length = 0;
- if(args[6].u_obj != MP_OBJ_NULL) {
- token = mp_obj_str_get_data(args[6].u_obj, &token_length);
+ if(session == NULL) {
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_RuntimeError, "Client Session has not been created!"));
}
- // Get the include_options parameter
- bool include_options = args[7].u_bool;
+ return session;
+ }
+ else {
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_RuntimeError, "Coap module has not been initialized!"));
+ // Just to fulfill the compiler's needs
+ return mp_const_none;
+ }
+}
- mp_obj_t address = mp_obj_new_list(0, NULL);
- // Get the address as a string
- mp_obj_list_append(address, mp_obj_new_str((const char*)coap_uri.host.s, coap_uri.host.length));
+STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mod_coap_new_client_session_obj, 1, mod_coap_new_client_session);
- // Get the port as a number
- mp_obj_list_append(address, mp_obj_new_int(coap_uri.port));
+// Remove a client session
+STATIC mp_obj_t mod_coap_remove_client_session(mp_obj_t ip_addr_in, mp_obj_t port_in, mp_obj_t protocol_in) {
- // Prepare the destination address where to send the request
- coap_address_t dst_address;
- coap_address_init(&dst_address);
- dst_address.addr.sin.sin_family = AF_INET;
- // The address will be in Big Endian order
- uint16_t port = netutils_parse_inet_addr(address, (uint8_t*)&dst_address.addr.sin.sin_addr.s_addr, NETUTILS_BIG);
- dst_address.addr.sin.sin_port = htons(port);
+ // The Coap module should have been already initialized
+ if(initialized == true) {
- // Take the context's semaphore to avoid concurrent access
xSemaphoreTake(coap_obj_ptr->semphr, portMAX_DELAY);
- if(include_options == true) {
-
- // Put the URI-HOST as an option
- coap_list_t * node = modcoap_new_option_node(COAP_OPTION_URI_HOST, coap_uri.host.length, coap_uri.host.s);
- if(node != NULL) {
- LL_APPEND(coap_obj_ptr->optlist, node);
- }
+ const char* ip_addr = mp_obj_str_get_str(ip_addr_in);
+ const uint16_t port = mp_obj_get_int(port_in);
+ const uint8_t protocol = mp_obj_get_int(protocol_in);
- // Put the URI-PORT as an option
- unsigned char portbuf[2];
- // Store it in Big Endian
- portbuf[0] = (coap_uri.port >> 8) & 0xFF;
- portbuf[1] = coap_uri.port & 0xFF;
- node = modcoap_new_option_node(COAP_OPTION_URI_PORT, sizeof(portbuf), portbuf);
- if(node != NULL) {
- LL_APPEND(coap_obj_ptr->optlist, node);
- }
-
- // Split up the URI-PATH into more segments if needed
- //TODO: allocate the proper length
- size_t length = 300;
- unsigned char* path = malloc(length);
- // Need to use a different pointer because when the segments are composed the pointer itself is moved
- unsigned char* path_segment = path;
- int segments = coap_split_path(coap_uri.path.s, coap_uri.path.length, path_segment, &length);
-
- // Insert the segments as separate URI-Path options
- while (segments--) {
- node = modcoap_new_option_node(COAP_OPTION_URI_PATH, COAP_OPT_LENGTH(path_segment), COAP_OPT_VALUE(path_segment));
- if(node != NULL) {
- LL_APPEND(coap_obj_ptr->optlist, node);
- }
- // Move the path_segment pointer to the next segment
- path_segment += COAP_OPT_SIZE(path_segment);
- }
+ bool ret = remove_client_session(ip_addr, port, protocol);
- // Free up the memory using the pointer pointing to the beginning of the memory area
- free(path);
+ xSemaphoreGive(coap_obj_ptr->semphr);
- // Put Content Format option if given
- if(content_format != -1) {
- unsigned char content_format_buf[2];
- // Store it in Big Endian
- content_format_buf[0] = (content_format >> 8) & 0xFF;
- content_format_buf[1] = content_format & 0xFF;
- node = modcoap_new_option_node(COAP_OPTION_CONTENT_FORMAT, sizeof(content_format_buf), content_format_buf);
- if(node != NULL) {
- LL_APPEND(coap_obj_ptr->optlist, node);
- }
- }
+ if(ret == false) {
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_RuntimeError, "Client Session has not been removed"));
}
- // Create new request
- coap_pdu_t *pdu = modcoap_new_request(coap_obj_ptr->context, method, &coap_obj_ptr->optlist, token, token_length, payload, payload_length);
+ return mp_const_none;
+ }
+ else {
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_RuntimeError, "Coap module has not been initialized!"));
+ // Just to fulfill the compiler's needs
+ return mp_const_none;
+ }
+}
- // Clean up optlist, they are already part of the PDU if it has been created
- struct coap_list_t *next;
- while(coap_obj_ptr->optlist != NULL) {
- next = coap_obj_ptr->optlist->next;
- coap_obj_ptr->optlist->next = NULL;
- free(coap_obj_ptr->optlist);
- coap_obj_ptr->optlist = next;
- }
+STATIC MP_DEFINE_CONST_FUN_OBJ_3(mod_coap_remove_client_session_obj, mod_coap_remove_client_session);
- if (pdu == NULL) {
- xSemaphoreGive(coap_obj_ptr->semphr);
- nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Cannot create request"));
- }
+// Get all client sessions
+STATIC mp_obj_t mod_coap_get_client_sessions() {
- // Send out the request
- // TODO: currently always confirmed message is sent out
- coap_tid_t ret;
- if (pdu->hdr->type == COAP_MESSAGE_CON) {
- ret = coap_send_confirmed(coap_obj_ptr->context, coap_obj_ptr->context->endpoint, &dst_address, pdu);
- }
- else {
- ret = coap_send(coap_obj_ptr->context, coap_obj_ptr->context->endpoint, &dst_address, pdu);
- }
+ // The Coap module should have been already initialized
+ if(initialized == true) {
- // Sending the packet failed
- if(ret == COAP_INVALID_TID) {
- xSemaphoreGive(coap_obj_ptr->semphr);
- nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Sending message failed!"));
- }
+ mp_obj_t list = mp_obj_new_list(0, NULL);
- // Fetch the message ID to be used from MicroPython to match the request with response
- mp_obj_t id = mp_obj_new_int(pdu->hdr->id);
+ xSemaphoreTake(coap_obj_ptr->semphr, portMAX_DELAY);
- //TODO: check if this is needed once not-confirmed message support is added
-// if (pdu->hdr->type != COAP_MESSAGE_CON) {
-// coap_delete_pdu(pdu);
-// }
+ mod_coap_client_session_obj_t* client_session = coap_obj_ptr->client_sessions;
+ while(client_session != NULL) {
+ mp_obj_list_append(list, client_session);
+ client_session = client_session->next;
+ }
xSemaphoreGive(coap_obj_ptr->semphr);
- return id;
+ return list;
}
else {
nlr_raise(mp_obj_new_exception_msg(&mp_type_RuntimeError, "Coap module has not been initialized!"));
@@ -1312,19 +1712,21 @@ STATIC mp_obj_t mod_coap_send_request(mp_uint_t n_args, const mp_obj_t *pos_args
}
}
-STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mod_coap_send_request_obj, 2, mod_coap_send_request);
+STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_coap_get_client_sessions_obj, mod_coap_get_client_sessions);
STATIC const mp_map_elem_t mod_coap_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_coap) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_init), (mp_obj_t)&mod_coap_init_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_socket), (mp_obj_t)&mod_coap_socket_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_add_resource), (mp_obj_t)&mod_coap_add_resource_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_remove_resource), (mp_obj_t)&mod_coap_remove_resource_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_get_resource), (mp_obj_t)&mod_coap_get_resource_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_read), (mp_obj_t)&mod_coap_read_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_register_response_handler), (mp_obj_t)&mod_coap_register_response_handler_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_send_request), (mp_obj_t)&mod_coap_send_request_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_register_new_resource_handler), (mp_obj_t)&mod_coap_register_new_resource_handler_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_new_client_session), (mp_obj_t)&mod_coap_new_client_session_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_remove_client_session), (mp_obj_t)&mod_coap_remove_client_session_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_get_client_sessions), (mp_obj_t)&mod_coap_get_client_sessions_obj },
+
// class constants
{ MP_OBJ_NEW_QSTR(MP_QSTR_REQUEST_GET), MP_OBJ_NEW_SMALL_INT(MODCOAP_REQUEST_GET) },
@@ -1339,6 +1741,9 @@ STATIC const mp_map_elem_t mod_coap_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_MEDIATYPE_APP_EXI), MP_OBJ_NEW_SMALL_INT(COAP_MEDIATYPE_APPLICATION_EXI) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_MEDIATYPE_APP_JSON), MP_OBJ_NEW_SMALL_INT(COAP_MEDIATYPE_APPLICATION_JSON) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_MEDIATYPE_APP_CBOR), MP_OBJ_NEW_SMALL_INT(COAP_MEDIATYPE_APPLICATION_CBOR) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_PROTOCOL_UDP), MP_OBJ_NEW_SMALL_INT(COAP_PROTO_UDP) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_PROTOCOL_DTLS), MP_OBJ_NEW_SMALL_INT(COAP_PROTO_DTLS) },
+
};
STATIC MP_DEFINE_CONST_DICT(mod_coap_globals, mod_coap_globals_table);
diff --git a/esp32/mods/modespnow.c b/esp32/mods/modespnow.c
new file mode 100644
index 0000000000..f259b31ebe
--- /dev/null
+++ b/esp32/mods/modespnow.c
@@ -0,0 +1,590 @@
+/*
+ * This file is derived from the MicroPython project, http://micropython.org/
+ *
+ * Copyright (c) 2020, Pycom Limited and its licensors.
+ *
+ * This software is licensed under the GNU GPL version 3 or any later version,
+ * with permitted additional terms. For more information see the Pycom Licence
+ * v1.0 document supplied with this file, or available at:
+ * https://www.pycom.io/opensource/licensing
+ */
+
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2017 Nick Moore
+ * Copyright (c) 2018 shawwwn
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ *
+ */
+
+
+#include
+#include
+#include
+
+#include "esp_log.h"
+#include "esp_now.h"
+#include "esp_wifi.h"
+#include "esp_wifi_types.h"
+
+#include "py/runtime.h"
+#include "py/mphal.h"
+#include "py/nlr.h"
+#include "py/objlist.h"
+#include "py/runtime.h"
+#include "py/mphal.h"
+#include "py/mperrno.h"
+
+#include "modnetwork.h"
+#include "modespnow.h"
+#include "mpirq.h"
+#include "pycom_general_util.h"
+#include "modwlan.h"
+
+/******************************************************************************
+ DEFINE CONSTANTS
+ ******************************************************************************/
+/******************************************************************************
+ DEFINE PRIVATE TYPES
+ ******************************************************************************/
+typedef struct mod_espnow_peer_obj_s {
+ mp_obj_base_t base;
+ uint8_t peer_addr[ESP_NOW_ETH_ALEN];
+ uint8_t lmk[ESP_NOW_KEY_LEN];
+ bool encrypt;
+ struct mod_espnow_peer_obj_s* prev;
+ struct mod_espnow_peer_obj_s* next;
+}mod_espnow_peer_obj_t;
+/******************************************************************************
+ DECLARE PRIVATE FUNCTIONS
+ ******************************************************************************/
+STATIC void mod_esp_espnow_exceptions(esp_err_t e);
+STATIC void get_bytes(mp_obj_t str, size_t len, uint8_t *dst);
+STATIC void send_queue_handler(void *arg);
+STATIC void IRAM_ATTR send_cb(const uint8_t *macaddr, esp_now_send_status_t status);
+STATIC void recv_queue_handler(void *arg);
+STATIC void IRAM_ATTR recv_cb(const uint8_t *macaddr, const uint8_t *data, int len);
+STATIC esp_err_t mac_str_to_byte(const uint8_t* mac_string, const size_t length, uint8_t* output);
+STATIC void get_MAC_addr(mp_obj_t str, uint8_t *dst);
+STATIC void add_peer(mod_espnow_peer_obj_t* peer);
+STATIC void remove_peer(mod_espnow_peer_obj_t* peer);
+STATIC mod_espnow_peer_obj_t* get_peer(const uint8_t* peer_addr);
+
+/******************************************************************************
+ DEFINE PRIVATE VARIABLES
+ ******************************************************************************/
+STATIC const mp_obj_type_t mod_espnow_peer_type;
+STATIC bool initialized = false;
+STATIC mp_obj_t send_cb_obj = mp_const_none;
+STATIC mp_obj_t recv_cb_obj = mp_const_none;
+STATIC mod_espnow_peer_obj_t* peer_list = NULL;
+
+/******************************************************************************
+ DEFINE PRIVATE FUNCTIONS
+ ******************************************************************************/
+
+// Transform the incoming MAC Address from String format to Bytes
+STATIC esp_err_t mac_str_to_byte(const uint8_t* mac_string, const size_t length, uint8_t* output) {
+ if(length == 2*ESP_NOW_ETH_ALEN) {
+ for(int i = 0, j = 0; i < length; i = i+2) {
+ uint8_t lower_nibble = hex_from_char(mac_string[i+1]);
+ uint8_t upper_nibble = hex_from_char(mac_string[i]);
+
+ // Only HEX characters are allowed
+ if(lower_nibble == 16 || upper_nibble == 16) {
+ return ESP_FAIL;
+ }
+
+ output[j] = lower_nibble | (upper_nibble << 4);
+ j++;
+ }
+
+ return ESP_OK;
+ }
+ else {
+ return ESP_FAIL;
+ }
+}
+
+// Form MAC address from a MicroPython string or byte array
+STATIC void get_MAC_addr(mp_obj_t str, uint8_t *dst){
+
+ esp_err_t ret = ESP_OK;
+ size_t str_len;
+ const char *data = mp_obj_str_get_data(str, &str_len);
+ // Input parameter contains the MAC address in form of Byte Array
+ if(str_len == ESP_NOW_ETH_ALEN) {
+ memcpy(dst, data, str_len);
+ }
+ // Input parameter contains the MAC address in form of String
+ else if(str_len == 2*ESP_NOW_ETH_ALEN) {
+ ret = mac_str_to_byte((const uint8_t*)data, str_len, dst);
+ }
+ else {
+ ret = ESP_FAIL;
+ }
+
+ if(ret != ESP_OK) {
+ mp_raise_ValueError("Invalid MAC Address");
+ }
+}
+
+// Add peer to the linked-list of peers
+STATIC void add_peer(mod_espnow_peer_obj_t* peer) {
+ peer->next = NULL;
+
+ if(peer_list == NULL) {
+ peer->prev = NULL;
+ peer_list = peer;
+ }
+ else{
+ mod_espnow_peer_obj_t* peer_tmp = peer_list;
+ while(peer_tmp->next != NULL) {
+ peer_tmp = peer_tmp->next;
+ }
+ peer_tmp->next = peer;
+ peer->prev = peer_tmp;
+ }
+}
+
+// Remove a peer from the linked-list of peers
+STATIC void remove_peer(mod_espnow_peer_obj_t* peer) {
+
+ // If this is the only element in the list, then invalidate the list
+ if(peer->prev == NULL && peer->next == NULL) {
+ peer_list = NULL;
+ }
+ // If this is not the only element in the list then remove it correctly from the list
+ else {
+ // If this is the first element in the list, move start of the list to next element, it might be NULL, that means the list is empty
+ if(peer == peer_list) {
+ peer_list = peer->next;
+ }
+
+ // Chain together the previous and next element, if any
+ if(peer->prev != NULL) {
+ peer->prev->next = peer->next;
+ }
+ if(peer->next != NULL) {
+ peer->next->prev = peer->prev;
+ }
+ }
+ // Free up the memory
+ m_del_obj((mp_obj_t)&mod_espnow_peer_type, peer);
+}
+
+// Find a peer based on MAC address
+STATIC mod_espnow_peer_obj_t* get_peer(const uint8_t *peer_addr) {
+
+ mod_espnow_peer_obj_t* peer = peer_list;
+ while(peer != NULL) {
+ if(memcmp(peer_addr, peer->peer_addr, ESP_NOW_ETH_ALEN) == 0) {
+ return peer;
+ }
+ peer = peer->next;
+ }
+ return mp_const_none;
+}
+
+// Remove all peers from the linked-list
+STATIC void remove_all_peers() {
+
+ mod_espnow_peer_obj_t* peer = peer_list;
+ mod_espnow_peer_obj_t* peer_tmp = peer;
+ while(peer != NULL) {
+ peer_tmp = peer->next;
+ remove_peer(peer);
+ peer = peer_tmp;
+ }
+}
+
+STATIC void mod_esp_espnow_exceptions(esp_err_t e) {
+ switch (e) {
+ case ESP_OK:
+ break;
+ case ESP_ERR_ESPNOW_NOT_INIT:
+ mp_raise_msg(&mp_type_OSError, "ESP-Now Not Initialized");
+ break;
+ case ESP_ERR_ESPNOW_ARG:
+ mp_raise_msg(&mp_type_OSError, "ESP-Now Invalid Argument");
+ break;
+ case ESP_ERR_ESPNOW_NO_MEM:
+ mp_raise_msg(&mp_type_OSError, "ESP-Now Out Of Mem");
+ break;
+ case ESP_ERR_ESPNOW_FULL:
+ mp_raise_msg(&mp_type_OSError, "ESP-Now Peer List Full");
+ break;
+ case ESP_ERR_ESPNOW_NOT_FOUND:
+ mp_raise_msg(&mp_type_OSError, "ESP-Now Peer Not Found");
+ break;
+ case ESP_ERR_ESPNOW_INTERNAL:
+ mp_raise_msg(&mp_type_OSError, "ESP-Now Internal");
+ break;
+ case ESP_ERR_ESPNOW_EXIST:
+ mp_raise_msg(&mp_type_OSError, "ESP-Now Peer Exists");
+ break;
+ case ESP_ERR_ESPNOW_IF:
+ mp_raise_msg(&mp_type_OSError, "ESP-Now Wifi Interface error");
+ break;
+ default:
+ nlr_raise(mp_obj_new_exception_msg_varg(
+ &mp_type_RuntimeError, "ESP-Now Unknown Error 0x%04x", e
+ ));
+ break;
+ }
+}
+
+STATIC void get_bytes(mp_obj_t str, size_t len, uint8_t *dst) {
+ size_t str_len;
+ const char *data = mp_obj_str_get_data(str, &str_len);
+ if (str_len != len) mp_raise_ValueError("bad len");
+ memcpy(dst, data, len);
+}
+
+STATIC void send_queue_handler(void *arg) {
+ // this function will be called by the interrupt thread
+ mp_obj_tuple_t *msg = arg;
+ if (send_cb_obj != mp_const_none) {
+ mp_call_function_1(send_cb_obj, msg);
+ }
+}
+
+STATIC void IRAM_ATTR send_cb(const uint8_t *macaddr, esp_now_send_status_t status)
+{
+ if (send_cb_obj != mp_const_none) {
+ mp_obj_tuple_t *msg = mp_obj_new_tuple(2, NULL);
+ msg->items[0] = get_peer(macaddr);
+ msg->items[1] = (status == ESP_NOW_SEND_SUCCESS) ? mp_const_true : mp_const_false;
+ mp_irq_queue_interrupt(send_queue_handler, msg);
+ }
+}
+
+STATIC void recv_queue_handler(void *arg) {
+ // this function will be called by the interrupt thread
+ mp_obj_tuple_t *msg = arg;
+ if (recv_cb_obj != mp_const_none) {
+ mp_call_function_1(recv_cb_obj, msg);
+ }
+}
+
+STATIC void IRAM_ATTR recv_cb(const uint8_t *macaddr, const uint8_t *data, int len)
+{
+ if (recv_cb_obj != mp_const_none) {
+ mp_obj_tuple_t *msg = mp_obj_new_tuple(3, NULL);
+ msg->items[0] = mp_obj_new_str((const char *)macaddr, ESP_NOW_ETH_ALEN);
+ msg->items[1] = get_peer(macaddr);
+ msg->items[2] = mp_obj_new_bytes(data, len);
+ mp_irq_queue_interrupt(recv_queue_handler, msg);
+ }
+}
+
+/******************************************************************************
+ DEFINE ESP-NOW PEER CLASS FUNCTIONS
+ ******************************************************************************/
+
+STATIC mp_obj_t mod_espnow_peer_addr(mp_obj_t self_in) {
+
+ mod_espnow_peer_obj_t* self = (mod_espnow_peer_obj_t*)self_in;
+ return mp_obj_new_str((const char *)self->peer_addr, ESP_NOW_ETH_ALEN);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_espnow_peer_addr_obj, mod_espnow_peer_addr);
+
+STATIC mp_obj_t mod_espnow_peer_lmk(size_t n_args, const mp_obj_t *args) {
+
+ mod_espnow_peer_obj_t* self = (mod_espnow_peer_obj_t*)args[0];
+
+ if(n_args == 1) {
+ if(self->encrypt) {
+ return mp_obj_new_str((const char *)self->lmk, ESP_NOW_KEY_LEN);
+ }
+ }
+ else {
+ esp_now_peer_info_t peer;
+ mod_esp_espnow_exceptions(esp_now_get_peer(self->peer_addr, &peer));
+ if(args[1] == mp_const_none) {
+ peer.encrypt = false;
+ mod_esp_espnow_exceptions(esp_now_mod_peer(&peer));
+ self->encrypt = false;
+ }
+ else {
+ get_bytes(args[1], ESP_NOW_KEY_LEN, peer.lmk);
+ peer.encrypt = true;
+ mod_esp_espnow_exceptions(esp_now_mod_peer(&peer));
+ memcpy(self->lmk, peer.lmk, ESP_NOW_KEY_LEN);
+ self->encrypt = true;
+ }
+
+ }
+
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_espnow_peer_lmk_obj, 1, 2, mod_espnow_peer_lmk);
+
+
+STATIC mp_obj_t mod_espnow_peer_send(mp_obj_t self_in, mp_obj_t msg) {
+
+ if(msg != mp_const_none) {
+ mod_espnow_peer_obj_t* self = (mod_espnow_peer_obj_t*)self_in;
+ mp_uint_t msg_len;
+ const uint8_t *msg_buf = (const uint8_t *)mp_obj_str_get_data(msg, &msg_len);
+ if (msg_len > ESP_NOW_MAX_DATA_LEN) mp_raise_ValueError("Message is too long");
+
+ mod_esp_espnow_exceptions(esp_now_send(self->peer_addr, msg_buf, msg_len));
+ }
+ else {
+ mp_raise_ValueError("Message is invalid");
+ }
+
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_espnow_peer_send_obj, mod_espnow_peer_send);
+
+
+/******************************************************************************
+ DEFINE ESP-NOW MODULE FUNCTIONS
+ ******************************************************************************/
+
+STATIC mp_obj_t mod_espnow_init() {
+
+ if(wlan_obj.started == false) {
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_RuntimeError, "ESP-NOW module needs that WLAN is already initialized!"));
+ }
+ else if(initialized == false) {
+
+ mod_esp_espnow_exceptions(esp_now_init());
+ mod_esp_espnow_exceptions(esp_now_register_recv_cb(recv_cb));
+ mod_esp_espnow_exceptions(esp_now_register_send_cb(send_cb));
+
+ initialized = true;
+ }
+ else {
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_RuntimeError, "ESP-NOW module already initialized!"));
+ }
+
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_espnow_init_obj, mod_espnow_init);
+
+STATIC mp_obj_t mod_espnow_deinit() {
+ if(initialized == true) {
+ mod_esp_espnow_exceptions(esp_now_deinit());
+ remove_all_peers();
+ initialized = false;
+ }
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_espnow_deinit_obj, mod_espnow_deinit);
+
+STATIC mp_obj_t mod_espnow_on_send(size_t n_args, const mp_obj_t *args) {
+ if(initialized == true) {
+ if (n_args == 0) {
+ return send_cb_obj;
+ }
+ send_cb_obj = args[0];
+ }
+ else {
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_RuntimeError, "ESP-NOW module is not initialized!"));
+ }
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_espnow_on_send_obj, 0, 1, mod_espnow_on_send);
+
+STATIC mp_obj_t mod_espnow_on_recv(size_t n_args, const mp_obj_t *args) {
+
+ if(initialized == true) {
+ if (n_args == 0) {
+ return recv_cb_obj;
+ }
+ recv_cb_obj = args[0];
+ }
+ else {
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_RuntimeError, "ESP-NOW module is not initialized!"));
+ }
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_espnow_on_recv_obj, 0, 1, mod_espnow_on_recv);
+
+STATIC mp_obj_t mod_espnow_pmk(mp_obj_t key) {
+
+ if(initialized == true) {
+ uint8_t buf[ESP_NOW_KEY_LEN];
+ get_bytes(key, ESP_NOW_KEY_LEN, buf);
+ mod_esp_espnow_exceptions(esp_now_set_pmk(buf));
+ }
+ else {
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_RuntimeError, "ESP-NOW module is not initialized!"));
+ }
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_espnow_pmk_obj, mod_espnow_pmk);
+
+STATIC mp_obj_t mod_espnow_add_peer(size_t n_args, const mp_obj_t *args) {
+
+ if(initialized == true) {
+ esp_now_peer_info_t peer = {0};
+ get_MAC_addr(args[0], peer.peer_addr);
+ if (n_args > 1) {
+ get_bytes(args[1], ESP_NOW_KEY_LEN, peer.lmk);
+ peer.encrypt = true;
+ }
+ else {
+ peer.encrypt = false;
+ }
+
+ // Use the WIFI Station interface if configured otherwise use AP interface
+ if(wlan_obj.esp_netif_STA) {
+ peer.ifidx = ESP_IF_WIFI_STA;
+ }
+ else if(wlan_obj.esp_netif_AP) {
+ peer.ifidx = ESP_IF_WIFI_AP;
+ }
+
+ mod_esp_espnow_exceptions(esp_now_add_peer(&peer));
+
+ mod_espnow_peer_obj_t *peer_obj = m_new_obj(mod_espnow_peer_obj_t);
+ peer_obj->base.type = (mp_obj_t)&mod_espnow_peer_type;
+ memcpy(peer_obj->peer_addr, peer.peer_addr, sizeof(peer_obj->peer_addr));
+ if(peer.encrypt) {
+ memcpy(peer_obj->lmk, peer.lmk, ESP_NOW_KEY_LEN);
+ peer_obj->encrypt = true;
+ }
+ else {
+ peer_obj->encrypt = false;
+ }
+ add_peer(peer_obj);
+ return peer_obj;
+ }
+ else {
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_RuntimeError, "ESP-NOW module is not initialized!"));
+ }
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_espnow_add_peer_obj, 1, 2, mod_espnow_add_peer);
+
+STATIC mp_obj_t mod_espnow_del_peer(mp_obj_t peer_obj_in) {
+ if(initialized == true) {
+ mod_espnow_peer_obj_t* peer_obj = (mod_espnow_peer_obj_t*)peer_obj_in;
+ mod_esp_espnow_exceptions(esp_now_del_peer(peer_obj->peer_addr));
+ remove_peer(peer_obj);
+ }
+ else {
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_RuntimeError, "ESP-NOW module is not initialized!"));
+ }
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_espnow_del_peer_obj, mod_espnow_del_peer);
+
+STATIC mp_obj_t mod_espnow_send(mp_obj_t addr, mp_obj_t msg) {
+
+ if(initialized == true) {
+ mp_uint_t addr_len;
+ const uint8_t *addr_buf;
+ mp_uint_t msg_len;
+ const uint8_t *msg_buf = (const uint8_t *)mp_obj_str_get_data(msg, &msg_len);
+ if (msg_len > ESP_NOW_MAX_DATA_LEN) mp_raise_ValueError("msg too long");
+
+ if (addr == mp_const_none) {
+ // Send to all peers
+ mod_esp_espnow_exceptions(esp_now_send(NULL, msg_buf, msg_len));
+ } else {
+ // Send to the specified peer
+ addr_buf = (const uint8_t *)mp_obj_str_get_data(addr, &addr_len);
+ if (addr_len != ESP_NOW_ETH_ALEN) mp_raise_ValueError("addr invalid");
+ mod_esp_espnow_exceptions(esp_now_send(addr_buf, msg_buf, msg_len));
+ }
+ }
+ else {
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_RuntimeError, "ESP-NOW module is not initialized!"));
+ }
+
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_espnow_send_obj, mod_espnow_send);
+
+STATIC mp_obj_t mod_espnow_peer_count() {
+ if(initialized == true) {
+ esp_now_peer_num_t peer_num = {0};
+ mod_esp_espnow_exceptions(esp_now_get_peer_num(&peer_num));
+
+ mp_obj_t tuple[2];
+ tuple[0] = mp_obj_new_int(peer_num.total_num);
+ tuple[1] = mp_obj_new_int(peer_num.encrypt_num);
+ return mp_obj_new_tuple(2, tuple);
+ }
+ else {
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_RuntimeError, "ESP-NOW module is not initialized!"));
+ }
+
+ return mp_const_none;
+
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_espnow_peer_count_obj, mod_espnow_peer_count);
+
+STATIC mp_obj_t mod_espnow_version() {
+ if(initialized == true) {
+ uint32_t version;
+ mod_esp_espnow_exceptions(esp_now_get_version(&version));
+ return mp_obj_new_int(version);
+ }
+ else {
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_RuntimeError, "ESP-NOW module is not initialized!"));
+ }
+
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_espnow_version_obj, mod_espnow_version);
+
+STATIC const mp_map_elem_t mod_espnow_peer_locals_dict_table[] = {
+ { MP_OBJ_NEW_QSTR(MP_QSTR_addr), (mp_obj_t)&mod_espnow_peer_addr_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_lmk), (mp_obj_t)&mod_espnow_peer_lmk_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_send), (mp_obj_t)&mod_espnow_peer_send_obj },
+};
+STATIC MP_DEFINE_CONST_DICT(mod_espnow_peer_locals_dict, mod_espnow_peer_locals_dict_table);
+
+static const mp_obj_type_t mod_espnow_peer_type = {
+ { &mp_type_type },
+ .name = MP_QSTR_ESPNOW_Peer,
+ .locals_dict = (mp_obj_t)&mod_espnow_peer_locals_dict,
+};
+
+STATIC const mp_rom_map_elem_t mod_espnow_module_globals_table[] = {
+ { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_espnow) },
+ { MP_ROM_QSTR(MP_QSTR_init), (mp_obj_t)&mod_espnow_init_obj },
+ { MP_ROM_QSTR(MP_QSTR_deinit), (mp_obj_t)&mod_espnow_deinit_obj },
+ { MP_ROM_QSTR(MP_QSTR_pmk), (mp_obj_t)&mod_espnow_pmk_obj },
+ { MP_ROM_QSTR(MP_QSTR_add_peer), (mp_obj_t)&mod_espnow_add_peer_obj },
+ { MP_ROM_QSTR(MP_QSTR_del_peer), (mp_obj_t)&mod_espnow_del_peer_obj },
+ { MP_ROM_QSTR(MP_QSTR_send), (mp_obj_t)&mod_espnow_send_obj },
+ { MP_ROM_QSTR(MP_QSTR_on_send), (mp_obj_t)&mod_espnow_on_send_obj },
+ { MP_ROM_QSTR(MP_QSTR_on_recv), (mp_obj_t)&mod_espnow_on_recv_obj },
+ { MP_ROM_QSTR(MP_QSTR_peer_count), (mp_obj_t)&mod_espnow_peer_count_obj },
+ { MP_ROM_QSTR(MP_QSTR_version), (mp_obj_t)&mod_espnow_version_obj },
+};
+
+STATIC MP_DEFINE_CONST_DICT(mod_espnow_module_globals, mod_espnow_module_globals_table);
+
+const mp_obj_module_t mod_espnow = {
+ .base = { &mp_type_module },
+ .globals = (mp_obj_dict_t*)&mod_espnow_module_globals,
+};
diff --git a/esp32/mods/modespnow.h b/esp32/mods/modespnow.h
new file mode 100644
index 0000000000..17a66cc201
--- /dev/null
+++ b/esp32/mods/modespnow.h
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2020, Pycom Limited.
+ *
+ * This software is licensed under the GNU GPL version 3 or any
+ * later version, with permitted additional terms. For more information
+ * see the Pycom Licence v1.0 document supplied with this file, or
+ * available at https://www.pycom.io/opensource/licensing
+ */
+
+#ifndef MODESPNOW_H_
+#define MODESPNOW_H_
+
+
+extern const mp_obj_module_t mod_espnow;
+
+#endif // MODESPNOW_H_
diff --git a/esp32/mods/modeth.c b/esp32/mods/modeth.c
index 984fdfc220..94de865757 100644
--- a/esp32/mods/modeth.c
+++ b/esp32/mods/modeth.c
@@ -105,8 +105,9 @@ static DRAM_ATTR EventGroupHandle_t eth_event_group;
void eth_pre_init (void) {
// init tcpip stack
tcpip_adapter_init();
+ // TODO: commented out because this function does not exist in esp-idf 4.1
// init tcpip eth evt handlers to default
- esp_event_set_default_eth_handlers();
+ // esp_event_set_default_eth_handlers();
// register eth app evt handler
app_sys_register_evt_cb(APP_SYS_EVT_ETH, modeth_event_handler);
//Create cmd Queue
@@ -123,18 +124,18 @@ void modeth_get_mac(uint8_t *mac)
memcpy(mac, ethernet_mac, ETH_MAC_SIZE);
}
-eth_speed_mode_t get_eth_link_speed(void)
+eth_speed_t get_eth_link_speed(void)
{
portDISABLE_INTERRUPTS();
uint16_t speed = ksz8851_regrd(REG_PORT_STATUS);
portENABLE_INTERRUPTS();
if((speed & (PORT_STAT_SPEED_100MBIT)))
{
- return ETH_SPEED_MODE_100M;
+ return ETH_SPEED_100M;
}
else
{
- return ETH_SPEED_MODE_10M;
+ return ETH_SPEED_10M;
}
}
@@ -170,7 +171,7 @@ static esp_err_t modeth_event_handler(void *ctx, system_event_t *event)
#if defined(FIPY) || defined(GPY)
MSG("EH save DNS\n");
// Save DNS info for restoring if wifi inf is usable again after LTE disconnect
- tcpip_adapter_get_dns_info(TCPIP_ADAPTER_IF_ETH, TCPIP_ADAPTER_DNS_MAIN, ð_sta_inf_dns_info);
+ tcpip_adapter_get_dns_info(TCPIP_ADAPTER_IF_ETH, ESP_NETIF_DNS_MAIN, ð_sta_inf_dns_info);
#endif
mod_network_register_nic(ð_obj);
xEventGroupSetBits(eth_event_group, ETHERNET_EVT_CONNECTED);
@@ -188,7 +189,7 @@ static esp_err_t modeth_event_handler(void *ctx, system_event_t *event)
static void eth_set_default_inf(void)
{
#if defined(FIPY) || defined(GPY)
- tcpip_adapter_set_dns_info(TCPIP_ADAPTER_IF_ETH, TCPIP_ADAPTER_DNS_MAIN, ð_sta_inf_dns_info);
+ tcpip_adapter_set_dns_info(TCPIP_ADAPTER_IF_ETH, ESP_NETIF_DNS_MAIN, ð_sta_inf_dns_info);
tcpip_adapter_up(TCPIP_ADAPTER_IF_ETH);
#endif
}
@@ -624,7 +625,7 @@ STATIC mp_obj_t eth_ifconfig (mp_uint_t n_args, const mp_obj_t *pos_args, mp_map
if (args[0].u_obj == MP_OBJ_NULL) {
// get
tcpip_adapter_ip_info_t ip_info;
- tcpip_adapter_get_dns_info(TCPIP_ADAPTER_IF_ETH, TCPIP_ADAPTER_DNS_MAIN, &dns_info);
+ tcpip_adapter_get_dns_info(TCPIP_ADAPTER_IF_ETH, ESP_NETIF_DNS_MAIN, &dns_info);
if (ESP_OK == tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_ETH, &ip_info)) {
mp_obj_t ifconfig[4] = {
netutils_format_ipv4_addr((uint8_t *)&ip_info.ip.addr, NETUTILS_BIG),
@@ -650,7 +651,7 @@ STATIC mp_obj_t eth_ifconfig (mp_uint_t n_args, const mp_obj_t *pos_args, mp_map
tcpip_adapter_dhcpc_stop(TCPIP_ADAPTER_IF_ETH);
tcpip_adapter_set_ip_info(TCPIP_ADAPTER_IF_ETH, &ip_info);
- tcpip_adapter_set_dns_info(TCPIP_ADAPTER_IF_ETH, TCPIP_ADAPTER_DNS_MAIN, &dns_info);
+ tcpip_adapter_set_dns_info(TCPIP_ADAPTER_IF_ETH, ESP_NETIF_DNS_MAIN, &dns_info);
} else {
// check for the correct string
diff --git a/esp32/mods/modlora.c b/esp32/mods/modlora.c
index 94f742094d..76398a0d84 100644
--- a/esp32/mods/modlora.c
+++ b/esp32/mods/modlora.c
@@ -49,11 +49,13 @@
#include "lora/mac/region/RegionAS923.h"
#include "lora/mac/region/RegionAU915.h"
#include "lora/mac/region/RegionUS915.h"
-#include "lora/mac/region/RegionUS915-Hybrid.h"
+#include "lora/mac/region/RegionEU433.h"
#include "lora/mac/region/RegionEU868.h"
#include "lora/mac/region/RegionCN470.h"
+#include "lora/mac/region/RegionCN779.h"
#include "lora/mac/region/RegionIN865.h"
-#include "lora/mac/region/RegionEU433.h"
+#include "lora/mac/region/RegionKR920.h"
+#include "lora/mac/region/RegionRU864.h"
// openThread includes
#ifdef LORA_OPENTHREAD_ENABLED
@@ -116,6 +118,14 @@
#define MESH_CLI_OUTPUT_SIZE (1024)
+/*!
+ * When using ABP activation the MAC layer must know in advance to which server
+ * version it will be connected.
+ */
+#define ABP_ACTIVATION_LRWAN_VERSION_V10x 0x01000300 // 1.0.3.0
+
+#define ABP_ACTIVATION_LRWAN_VERSION ABP_ACTIVATION_LRWAN_VERSION_V10x
+
/******************************************************************************
DEFINE PRIVATE TYPES
******************************************************************************/
@@ -219,9 +229,9 @@ typedef struct {
uint8_t AppSKey[16];
} abp;
} u;
+ uint8_t McKeyE[16];
- bool txiq;
- bool rxiq;
+ bool inv_iq;
bool adr;
bool public;
bool joined;
@@ -258,11 +268,16 @@ static lora_rx_data_t rx_data_isr;
static TimerEvent_t TxNextActReqTimer;
static nvs_handle modlora_nvs_handle;
-static const char *modlora_nvs_data_key[E_LORA_NVS_NUM_KEYS] = { "JOINED", "UPLNK", "DWLNK", "DEVADDR",
- "NWSKEY", "APPSKEY", "NETID", "ADRACK",
- "MACPARAMS", "CHANNELS", "SRVACK", "MACNXTTX",
- "MACBUFIDX", "MACRPTIDX", "MACBUF", "MACRPTBUF",
- "REGION", "CHANMASK", "CHANMASKREM" };
+static const char *modlora_nvs_data_key[E_LORA_NVS_NUM_KEYS] = { "JOINED", "LORAMACCTX", "MACMCDCTX",
+ "REGION", "REGIONCTX", "SECELEMCTX" };
+
+/*!
+ * Indicates if LoRaMacProcess call is pending.
+ *
+ * \warning If variable is equal to 0 then the MCU can be set in low power mode
+ */
+static uint8_t IsMacProcessPending = 0;
+
/******************************************************************************
DECLARE PUBLIC DATA
******************************************************************************/
@@ -322,7 +337,7 @@ SemaphoreHandle_t xLoRaSigfoxSem;
void modlora_init0(void) {
xCmdQueue = xQueueCreate(LORA_CMD_QUEUE_SIZE_MAX, sizeof(lora_cmd_data_t));
xRxQueue = xQueueCreate(LORA_DATA_QUEUE_SIZE_MAX, sizeof(lora_rx_data_t));
- xCbQueue = xQueueCreate(LORA_CB_QUEUE_SIZE_MAX, sizeof(modlora_timerCallback));
+ xCbQueue = xQueueCreate(LORA_CB_QUEUE_SIZE_MAX, sizeof(modlora_timerCb_data_t));
LoRaEvents = xEventGroupCreate();
#if defined(FIPY) || defined(LOPY4)
xLoRaSigfoxSem = xSemaphoreCreateMutex();
@@ -392,13 +407,17 @@ bool modlora_is_module_sleep(void)
}
}
-IRAM_ATTR void modlora_set_timer_callback(modlora_timerCallback cb)
+IRAM_ATTR void modlora_set_timer_callback(modlora_timerCallback cb, void *cb_param)
{
if(cb != NULL)
{
+ modlora_timerCb_data_t cb_data;
+ cb_data.cb = cb;
+ cb_data.cb_param = cb_param;
+
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
- xQueueSendFromISR(xCbQueue, &cb, &xHigherPriorityTaskWoken);
+ xQueueSendFromISR(xCbQueue, &cb_data, &xHigherPriorityTaskWoken);
if( xHigherPriorityTaskWoken)
{
@@ -437,6 +456,22 @@ void lora_ot_send(const uint8_t *buf, uint16_t len) {
}
#endif // #ifdef LORA_OPENTHREAD_ENABLED
+bool modlora_lora_needs_processor_active (void)
+{
+ // returns true
+ if (!xQueueIsQueueEmptyFromISR(xCmdQueue)) {
+ return true;
+ }
+ if (
+ (lora_obj.state != E_LORA_STATE_RX) &&
+ (lora_obj.state != E_LORA_STATE_TX) &&
+ (lora_obj.state != E_LORA_STATE_IDLE) &&
+ (1)) {
+ return true;
+ }
+ return false;
+}
+
/******************************************************************************
DEFINE PRIVATE FUNCTIONS
******************************************************************************/
@@ -500,7 +535,6 @@ static int32_t lorawan_send (const byte *buf, uint32_t len, uint32_t timeout_ms,
pdTRUE, // clear on exit
pdFALSE, // do not wait for all bits
(TickType_t)portMAX_DELAY);
-
if (result & LORA_STATUS_MSG_SIZE) {
return -1;
} else if (result & LORA_STATUS_ERROR) {
@@ -519,7 +553,6 @@ static void McpsConfirm (McpsConfirm_t *McpsConfirm) {
lora_obj.tx_trials = McpsConfirm->NbRetries;
lora_obj.tx_time_on_air = McpsConfirm->TxTimeOnAir;
lora_obj.tx_power = McpsConfirm->TxPower;
- lora_obj.tx_frequency = McpsConfirm->UpLinkFrequency;
lora_obj.tx_counter = McpsConfirm->UpLinkCounter;
switch (McpsConfirm->McpsRequest) {
@@ -758,21 +791,21 @@ static void MlmeConfirm (MlmeConfirm_t *MlmeConfirm) {
#endif
}
-static void OnTxNextActReqTimerEvent(void) {
+static void OnTxNextActReqTimerEvent(void *context) {
MibRequestConfirm_t mibReq;
LoRaMacStatus_t status;
- mibReq.Type = MIB_NETWORK_JOINED;
+ mibReq.Type = MIB_NETWORK_ACTIVATION;
status = LoRaMacMibGetRequestConfirm(&mibReq);
if (status == LORAMAC_STATUS_OK) {
- if (mibReq.Param.IsNetworkJoined == true) {
+ if (mibReq.Param.NetworkActivation == ACTIVATION_TYPE_NONE) {
+ lora_obj.state = E_LORA_STATE_JOIN;
+ } else {
lora_obj.joined = true;
lora_obj.ComplianceTest.State = 1;
lora_obj.ComplianceTest.Running = false;
lora_obj.ComplianceTest.DownLinkCounter = 0;
- } else {
- lora_obj.state = E_LORA_STATE_JOIN;
}
}
}
@@ -783,8 +816,7 @@ static void MlmeIndication( MlmeIndication_t *mlmeIndication )
{
case MLME_SCHEDULE_UPLINK:
{// The MAC signals that we shall provide an uplink as soon as possible
- printf("Trying to send uplink\n");
- OnTxNextActReqTimerEvent( );
+ OnTxNextActReqTimerEvent( NULL );
break;
}
default:
@@ -792,10 +824,16 @@ static void MlmeIndication( MlmeIndication_t *mlmeIndication )
}
}
+static void OnMacProcessNotify( void )
+{
+ IsMacProcessPending = 1;
+}
+
static void TASK_LoRa (void *pvParameters) {
MibRequestConfirm_t mibReq;
MlmeReq_t mlmeReq;
McpsReq_t mcpsReq;
+ LoRaMacStatus_t ret;
bool isReset;
lora_obj.state = E_LORA_STATE_NOINIT;
@@ -810,6 +848,14 @@ static void TASK_LoRa (void *pvParameters) {
lora_obj.state = E_LORA_STATE_RESET;
lora_obj.reset = false;
}
+
+ // Process Radio IRQ
+ if (Radio.IrqProcess != NULL) {
+ Radio.IrqProcess();
+ }
+ // Processes the LoRaMac events
+ LoRaMacProcess();
+
switch (lora_obj.state) {
case E_LORA_STATE_NOINIT:
case E_LORA_STATE_IDLE:
@@ -829,7 +875,15 @@ static void TASK_LoRa (void *pvParameters) {
LoRaMacPrimitives.MacMlmeConfirm = MlmeConfirm;
LoRaMacPrimitives.MacMlmeIndication = MlmeIndication;
LoRaMacCallbacks.GetBatteryLevel = BoardGetBatteryLevel;
- LoRaMacInitialization(&LoRaMacPrimitives, &LoRaMacCallbacks, task_cmd_data.info.init.region);
+ LoRaMacCallbacks.GetTemperatureLevel = NULL;
+ LoRaMacCallbacks.NvmContextChange = NULL; // NULL for now
+ LoRaMacCallbacks.MacProcessNotify = OnMacProcessNotify;
+ ret = LoRaMacInitialization(&LoRaMacPrimitives, &LoRaMacCallbacks, task_cmd_data.info.init.region);
+ if(ret != LORAMAC_STATUS_OK)
+ {
+ printf("LoRaMac initiliazation failed. Error code: %d\n", (int)ret);
+ return;
+ }
TimerStop(&TxNextActReqTimer);
TimerInit(&TxNextActReqTimer, OnTxNextActReqTimerEvent);
@@ -847,98 +901,60 @@ static void TASK_LoRa (void *pvParameters) {
mibReq.Param.Class = task_cmd_data.info.init.device_class;
LoRaMacMibSetRequestConfirm(&mibReq);
+#if defined( REGION_EU868 ) || defined( REGION_RU864 ) || defined( REGION_CN779 ) || defined( REGION_EU433 )
LoRaMacTestSetDutyCycleOn(false);
+#endif
+ mibReq.Type = MIB_SYSTEM_MAX_RX_ERROR;
+ mibReq.Param.SystemMaxRxError = 20;
+ LoRaMacMibSetRequestConfirm( &mibReq );
// check if we have already joined the network
if (lora_obj.joined) {
- uint32_t length;
bool result = true;
- result &= modlora_nvs_get_uint(E_LORA_NVS_ELE_NET_ID, (uint32_t *)&lora_obj.net_id);
- result &= modlora_nvs_get_uint(E_LORA_NVS_ELE_DEVADDR, (uint32_t *)&lora_obj.u.abp.DevAddr);
- length = 16;
- result &= modlora_nvs_get_blob(E_LORA_NVS_ELE_NWSKEY, (void *)lora_obj.u.abp.NwkSKey, &length);
- length = 16;
- result &= modlora_nvs_get_blob(E_LORA_NVS_ELE_APPSKEY, (void *)lora_obj.u.abp.AppSKey, &length);
-
- uint32_t uplinks, downlinks;
- result &= modlora_nvs_get_uint(E_LORA_NVS_ELE_UPLINK, &uplinks);
- result &= modlora_nvs_get_uint(E_LORA_NVS_ELE_DWLINK, &downlinks);
- result &= modlora_nvs_get_uint(E_LORA_NVS_ELE_ADR_ACKS, LoRaMacGetAdrAckCounter());
+ uint32_t length;
+ MibRequestConfirm_t mibReq;
+ LoRaMacCtxs_t *NvmCtxts;
- if (result) {
- mibReq.Type = MIB_UPLINK_COUNTER;
- mibReq.Param.UpLinkCounter = uplinks;
- LoRaMacMibSetRequestConfirm( &mibReq );
-
- mibReq.Type = MIB_DOWNLINK_COUNTER;
- mibReq.Param.DownLinkCounter = downlinks;
- LoRaMacMibSetRequestConfirm( &mibReq );
-
- // write the MAC params directly from the NVRAM
- length = sizeof(LoRaMacParams_t);
- modlora_nvs_get_blob(E_LORA_NVS_ELE_MAC_PARAMS, (void *)LoRaMacGetMacParams(), &length);
-
- // write the channel list directly from the NVRAM
- ChannelParams_t *channels;
- LoRaMacGetChannelList(&channels, &length);
- modlora_nvs_get_blob(E_LORA_NVS_ELE_CHANNELS, channels, &length);
-
- // write the channel mask directly from the NVRAM
- uint16_t *channelmask;
- if (LoRaMacGetChannelsMask(&channelmask, &length)) {
- modlora_nvs_get_blob(E_LORA_NVS_ELE_CHANNELMASK, channelmask, &length);
- }
-
- // write the channel mask remaining directly from the NVRAM
- if (LoRaMacGetChannelsMaskRemaining(&channelmask, &length)) {
- modlora_nvs_get_blob(E_LORA_NVS_ELE_CHANNELMASK_REMAINING, channelmask, &length);
- }
-
- uint32_t srv_ack_req;
- modlora_nvs_get_uint(E_LORA_NVS_ELE_ACK_REQ, (uint32_t *)&srv_ack_req);
- bool *ack_req = LoRaMacGetSrvAckRequested();
- if (srv_ack_req) {
- *ack_req = true;
- } else {
- *ack_req = false;
- }
-
- uint32_t mac_cmd_next_tx;
- modlora_nvs_get_uint(E_LORA_NVS_MAC_NXT_TX, (uint32_t *)&mac_cmd_next_tx);
- bool *next_tx = LoRaMacGetMacCmdNextTx();
- if (mac_cmd_next_tx) {
- *next_tx = true;
- } else {
- *next_tx = false;
- }
-
- uint32_t mac_cmd_buffer_idx;
- modlora_nvs_get_uint(E_LORA_NVS_MAC_CMD_BUF_IDX, (uint32_t *)&mac_cmd_buffer_idx);
- uint8_t *buffer_idx = LoRaMacGetMacCmdBufferIndex();
- *buffer_idx = mac_cmd_buffer_idx;
-
- modlora_nvs_get_uint(E_LORA_NVS_MAC_CMD_BUF_RPT_IDX, (uint32_t *)&mac_cmd_buffer_idx);
- buffer_idx = LoRaMacGetMacCmdBufferRepeatIndex();
- *buffer_idx = mac_cmd_buffer_idx;
-
- // write the buffered MAC commads directly from NVRAM
- length = 128;
- modlora_nvs_get_blob(E_LORA_NVS_ELE_MAC_BUF, (void *)LoRaMacGetMacCmdBuffer(), &length);
-
- // write the buffered MAC commads to repeat directly from NVRAM
- length = 128;
- modlora_nvs_get_blob(E_LORA_NVS_ELE_MAC_RPT_BUF, (void *)LoRaMacGetMacCmdBufferRepeat(), &length);
+ mibReq.Type = MIB_NVM_CTXS;
+ LoRaMacMibGetRequestConfirm(&mibReq);
+ NvmCtxts = mibReq.Param.Contexts;
+
+ length = NvmCtxts->MacNvmCtxSize;
+ result &= modlora_nvs_get_blob(E_LORA_NVS_ELE_LORAMAC_CTX, NvmCtxts->MacNvmCtx, &length);
+
+ length = NvmCtxts->CommandsNvmCtxSize;
+ result &= modlora_nvs_get_blob(E_LORA_NVS_ELE_MAC_CMD_CTX, NvmCtxts->CommandsNvmCtx, &length);
+ length = NvmCtxts->SecureElementNvmCtxSize;
+ result &= modlora_nvs_get_blob(E_LORA_NVS_ELE_SEC_ELEM_CTX, NvmCtxts->SecureElementNvmCtx, &length);
+
+ length = NvmCtxts->RegionNvmCtxSize;
+ result &= modlora_nvs_get_blob(E_LORA_NVS_ELE_REGION_CTX, NvmCtxts->RegionNvmCtx, &length);
+
+ LoRaMacMibSetRequestConfirm(&mibReq);
+
+ mibReq.Type = MIB_NET_ID;
+ LoRaMacMibGetRequestConfirm(&mibReq);
+ lora_obj.net_id = mibReq.Param.NetID;
+
+ mibReq.Type = MIB_DEV_ADDR;
+ LoRaMacMibGetRequestConfirm(&mibReq);
+ lora_obj.u.abp.DevAddr = mibReq.Param.DevAddr;
+
+ if (result) {
lora_obj.activation = E_LORA_ACTIVATION_ABP;
lora_obj.state = E_LORA_STATE_JOIN;
+
// clear the joined flag until the nvram_save method is called again
modlora_nvs_set_uint(E_LORA_NVS_ELE_JOINED, (uint32_t)false);
} else {
+ printf("Reading LoRa parameters from NV failed.\n");
lora_obj.state = E_LORA_STATE_IDLE;
}
} else {
lora_obj.state = E_LORA_STATE_IDLE;
}
+ LoRaMacStart( );
} else {
// radio initialization
RadioEvents.TxDone = OnTxDone;
@@ -1048,15 +1064,19 @@ static void TASK_LoRa (void *pvParameters) {
#if defined(FIPY) || defined(LOPY4)
xSemaphoreTake(xLoRaSigfoxSem, portMAX_DELAY);
#endif
-
// set back the original datarate
if (!lora_obj.adr) {
mibReq.Param.ChannelsDatarate = mac_datarate;
- LoRaMacMibSetRequestConfirm( &mibReq );
+ ret = LoRaMacMibSetRequestConfirm( &mibReq );
+ if (ret != LORAMAC_STATUS_OK) {
+ printf("LoRaMacMibSetRequestConfirm returned error: %d\n", ret);
+ }
}
- if (LoRaMacMcpsRequest(&mcpsReq) != LORAMAC_STATUS_OK || empty_frame) {
- // the command has failed, send the response now
+ ret = LoRaMacMcpsRequest(&mcpsReq);
+
+ if (ret != LORAMAC_STATUS_OK || empty_frame) {
+ // the command has failed, send the response now
lora_obj.state = E_LORA_STATE_IDLE;
status |= LORA_STATUS_ERROR;
xEventGroupSetBits(LoRaEvents, status);
@@ -1094,6 +1114,7 @@ static void TASK_LoRa (void *pvParameters) {
}
break;
case E_LORA_STATE_JOIN:
+ ret = LORAMAC_STATUS_OK;
TimerStop( &TxNextActReqTimer );
if (!lora_obj.joined) {
if (lora_obj.activation == E_LORA_ACTIVATION_OTAA) {
@@ -1103,16 +1124,32 @@ static void TASK_LoRa (void *pvParameters) {
mibReq.Type = MIB_NETWORK_ACTIVATION;
mibReq.Param.NetworkActivation = ACTIVATION_TYPE_OTAA;
LoRaMacMibSetRequestConfirm( &mibReq );
-
+
+ mibReq.Type = MIB_DEV_EUI;
+ mibReq.Param.DevEui = (uint8_t *)lora_obj.u.otaa.DevEui;
+ LoRaMacMibSetRequestConfirm( &mibReq );
+
+ mibReq.Type = MIB_JOIN_EUI;
+ mibReq.Param.JoinEui = (uint8_t *)lora_obj.u.otaa.AppEui;
+ LoRaMacMibSetRequestConfirm( &mibReq );
+
+ mibReq.Type = MIB_GEN_APP_KEY;
+ mibReq.Param.GenAppKey = (uint8_t *)lora_obj.u.otaa.AppKey;
+ LoRaMacMibSetRequestConfirm( &mibReq );
+
+ mibReq.Type = MIB_NWK_KEY;
+ mibReq.Param.NwkKey = (uint8_t *)lora_obj.u.otaa.AppKey;
+ LoRaMacMibSetRequestConfirm( &mibReq );
+
TimerStart( &TxNextActReqTimer );
mlmeReq.Type = MLME_JOIN;
- mlmeReq.Req.Join.DevEui = (uint8_t *)lora_obj.u.otaa.DevEui;
- mlmeReq.Req.Join.AppEui = (uint8_t *)lora_obj.u.otaa.AppEui;
- mlmeReq.Req.Join.AppKey = (uint8_t *)lora_obj.u.otaa.AppKey;
- mlmeReq.Req.Join.NbTrials = 1;
- mlmeReq.Req.Join.DR = (uint8_t) lora_obj.otaa_dr;
- LoRaMacMlmeRequest( &mlmeReq );
+ mlmeReq.Req.Join.Datarate = (uint8_t) lora_obj.otaa_dr;
+ ret = LoRaMacMlmeRequest( &mlmeReq );
} else {
+ mibReq.Type = MIB_ABP_LORAWAN_VERSION;
+ mibReq.Param.AbpLrWanVersion.Value = ABP_ACTIVATION_LRWAN_VERSION;
+ LoRaMacMibSetRequestConfirm( &mibReq );
+
mibReq.Type = MIB_NETWORK_ACTIVATION;
mibReq.Param.NetworkActivation = ACTIVATION_TYPE_ABP;
LoRaMacMibSetRequestConfirm( &mibReq );
@@ -1125,22 +1162,32 @@ static void TASK_LoRa (void *pvParameters) {
mibReq.Param.DevAddr = (uint32_t)lora_obj.u.abp.DevAddr;
LoRaMacMibSetRequestConfirm( &mibReq );
- mibReq.Type = MIB_NWK_SKEY;
- mibReq.Param.NwkSKey = (uint8_t *)lora_obj.u.abp.NwkSKey;
+ mibReq.Type = MIB_F_NWK_S_INT_KEY;
+ mibReq.Param.FNwkSIntKey = (uint8_t *)lora_obj.u.abp.NwkSKey;
LoRaMacMibSetRequestConfirm( &mibReq );
- mibReq.Type = MIB_APP_SKEY;
- mibReq.Param.AppSKey = (uint8_t *)lora_obj.u.abp.AppSKey;
+ mibReq.Type = MIB_S_NWK_S_INT_KEY;
+ mibReq.Param.SNwkSIntKey = (uint8_t *)lora_obj.u.abp.NwkSKey;
+ LoRaMacMibSetRequestConfirm( &mibReq );
+
+ mibReq.Type = MIB_NWK_S_ENC_KEY;
+ mibReq.Param.NwkSEncKey = (uint8_t *)lora_obj.u.abp.NwkSKey;
LoRaMacMibSetRequestConfirm( &mibReq );
- mibReq.Type = MIB_NETWORK_JOINED;
- mibReq.Param.IsNetworkJoined = true;
+ mibReq.Type = MIB_APP_S_KEY;
+ mibReq.Param.AppSKey = (uint8_t *)lora_obj.u.abp.AppSKey;
LoRaMacMibSetRequestConfirm( &mibReq );
+
lora_obj.joined = true;
lora_obj.ComplianceTest.State = 1;
}
}
- xEventGroupSetBits(LoRaEvents, LORA_STATUS_COMPLETED);
+ if (ret == LORAMAC_STATUS_OK) {
+ xEventGroupSetBits(LoRaEvents, LORA_STATUS_COMPLETED);
+ } else {
+ printf("Failed to send MLME Join. Error: %d\n", ret);
+ xEventGroupSetBits(LoRaEvents, LORA_STATUS_ERROR);
+ }
lora_obj.state = E_LORA_STATE_IDLE;
break;
case E_LORA_STATE_LINK_CHECK:
@@ -1193,12 +1240,12 @@ static void TASK_LoRa_Timer (void *pvParameters) {
for(;;)
{
- modlora_timerCallback cb;
- while (pdTRUE == xQueueReceive(xCbQueue, &cb, portMAX_DELAY))
+ modlora_timerCb_data_t cb_data;
+ while (pdTRUE == xQueueReceive(xCbQueue, &cb_data, portMAX_DELAY))
{
- if(cb != NULL)
+ if(cb_data.cb != NULL)
{
- cb();
+ cb_data.cb(cb_data.cb_param);
}
}
}
@@ -1301,12 +1348,12 @@ static void lora_radio_setup (lora_init_cmd_data_t *init_data) {
Radio.SetTxConfig(MODEM_LORA, init_data->tx_power, 0, init_data->bandwidth,
init_data->sf, init_data->coding_rate,
init_data->preamble, LORA_FIX_LENGTH_PAYLOAD_OFF,
- true, 0, 0, init_data->txiq, LORA_TX_TIMEOUT_MAX);
+ true, 0, 0, init_data->inv_iq, LORA_TX_TIMEOUT_MAX);
Radio.SetRxConfig(MODEM_LORA, init_data->bandwidth, init_data->sf,
init_data->coding_rate, 0, init_data->preamble,
symbol_to, LORA_FIX_LENGTH_PAYLOAD_OFF,
- 0, true, 0, 0, init_data->rxiq, true);
+ 0, true, 0, 0, init_data->inv_iq, true);
Radio.SetMaxPayloadLength(MODEM_LORA, LORA_PAYLOAD_SIZE_MAX);
@@ -1338,16 +1385,6 @@ static void lora_validate_frequency (uint32_t frequency) {
goto freq_error;
}
break;
- case LORAMAC_REGION_US915:
- if (frequency < 902000000 || frequency > 928000000) {
- goto freq_error;
- }
- break;
- case LORAMAC_REGION_US915_HYBRID:
- if (frequency < 902000000 || frequency > 928000000) {
- goto freq_error;
- }
- break;
case LORAMAC_REGION_CN470:
#if defined(LOPY4)
if (frequency < 470000000 || frequency > 510000000) {
@@ -1357,14 +1394,14 @@ static void lora_validate_frequency (uint32_t frequency) {
goto freq_error;
#endif
break;
- case LORAMAC_REGION_IN865:
- if (frequency < 865000000 || frequency > 867000000) {
+ case LORAMAC_REGION_CN779:
+ if (frequency < 779500000 || frequency > 786500000 ) {
goto freq_error;
}
break;
case LORAMAC_REGION_EU433:
#if defined(LOPY4)
- if (frequency < 433000000 || frequency > 435000000) { // LoRa 433 - 434
+ if (frequency < 433175000 || frequency > 434665000 ) {
goto freq_error;
}
#else
@@ -1376,6 +1413,26 @@ static void lora_validate_frequency (uint32_t frequency) {
goto freq_error;
}
break;
+ case LORAMAC_REGION_KR920:
+ if (frequency < 920900000 || frequency > 923300000 ) {
+ goto freq_error;
+ }
+ break;
+ case LORAMAC_REGION_IN865:
+ if (frequency < 865000000 || frequency > 867000000) {
+ goto freq_error;
+ }
+ break;
+ case LORAMAC_REGION_US915:
+ if (frequency < 902000000 || frequency > 928000000) {
+ goto freq_error;
+ }
+ break;
+ case LORAMAC_REGION_RU864:
+ if (frequency < 864000000 || frequency > 870000000 ) {
+ goto freq_error;
+ }
+ break;
default:
break;
}
@@ -1397,13 +1454,18 @@ static void lora_validate_channel (uint32_t index) {
goto channel_error;
}
break;
- case LORAMAC_REGION_US915:
- if (index >= US915_MAX_NB_CHANNELS) {
+ case LORAMAC_REGION_CN470:
+ if (index >= CN470_MAX_NB_CHANNELS) {
+ goto channel_error;
+ }
+ break;
+ case LORAMAC_REGION_CN779:
+ if (index >= CN779_MAX_NB_CHANNELS) {
goto channel_error;
}
break;
- case LORAMAC_REGION_US915_HYBRID:
- if (index >= US915_HYBRID_MAX_NB_CHANNELS) {
+ case LORAMAC_REGION_EU433:
+ if (index >= EU433_MAX_NB_CHANNELS) {
goto channel_error;
}
break;
@@ -1412,8 +1474,8 @@ static void lora_validate_channel (uint32_t index) {
goto channel_error;
}
break;
- case LORAMAC_REGION_CN470:
- if (index >= CN470_MAX_NB_CHANNELS) {
+ case LORAMAC_REGION_KR920:
+ if (index >= KR920_MAX_NB_CHANNELS) {
goto channel_error;
}
break;
@@ -1422,6 +1484,16 @@ static void lora_validate_channel (uint32_t index) {
goto channel_error;
}
break;
+ case LORAMAC_REGION_US915:
+ if (index >= US915_MAX_NB_CHANNELS) {
+ goto channel_error;
+ }
+ break;
+ case LORAMAC_REGION_RU864:
+ if (index >= RU864_MAX_NB_CHANNELS) {
+ goto channel_error;
+ }
+ break;
default:
break;
}
@@ -1439,27 +1511,11 @@ static void lora_validate_power (uint8_t tx_power) {
static bool lora_validate_data_rate (uint32_t data_rate) {
- switch (lora_obj.region) {
- case LORAMAC_REGION_AS923:
- case LORAMAC_REGION_EU868:
- case LORAMAC_REGION_AU915:
- case LORAMAC_REGION_EU433:
- case LORAMAC_REGION_CN470:
- case LORAMAC_REGION_IN865:
- if (data_rate > DR_6) {
- return false;
- }
- break;
- case LORAMAC_REGION_US915:
- case LORAMAC_REGION_US915_HYBRID:
- if (data_rate > DR_4) {
- return false;
- }
- break;
- default:
- break;
- }
- return true;
+ VerifyParams_t verify;
+
+ verify.DatarateParams.Datarate = data_rate;
+
+ return RegionVerify( lora_obj.region, &verify, PHY_TX_DR );
}
static void lora_validate_bandwidth (uint8_t bandwidth) {
@@ -1494,26 +1550,18 @@ static void lora_validate_device_class (DeviceClass_t device_class) {
}
static void lora_validate_region (LoRaMacRegion_t region) {
- if (region != LORAMAC_REGION_AS923 && region != LORAMAC_REGION_AU915
- && region != LORAMAC_REGION_EU868 && region != LORAMAC_REGION_US915
- && region != LORAMAC_REGION_IN865
-#if defined(LOPY4)
- && region != LORAMAC_REGION_EU433 && region != LORAMAC_REGION_CN470
-#endif
- ) {
+ if (region < LORAMAC_REGION_AS923 || region > LORAMAC_REGION_RU864) {
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "invalid region %d", region));
}
}
-
static void lora_set_config (lora_cmd_data_t *cmd_data) {
lora_obj.stack_mode = cmd_data->info.init.stack_mode;
lora_obj.bandwidth = cmd_data->info.init.bandwidth;
lora_obj.coding_rate = cmd_data->info.init.coding_rate;
lora_obj.frequency = cmd_data->info.init.frequency;
lora_obj.preamble = cmd_data->info.init.preamble;
- lora_obj.rxiq = cmd_data->info.init.rxiq;
- lora_obj.txiq = cmd_data->info.init.txiq;
+ lora_obj.inv_iq = cmd_data->info.init.inv_iq;
lora_obj.sf = cmd_data->info.init.sf;
lora_obj.tx_power = cmd_data->info.init.tx_power;
lora_obj.pwr_mode = cmd_data->info.init.power_mode;
@@ -1530,8 +1578,7 @@ static void lora_get_config (lora_cmd_data_t *cmd_data) {
cmd_data->info.init.coding_rate = lora_obj.coding_rate;
cmd_data->info.init.frequency = lora_obj.frequency;
cmd_data->info.init.preamble = lora_obj.preamble;
- cmd_data->info.init.rxiq = lora_obj.rxiq;
- cmd_data->info.init.txiq = lora_obj.txiq;
+ cmd_data->info.init.inv_iq = lora_obj.inv_iq;
cmd_data->info.init.sf = lora_obj.sf;
cmd_data->info.init.tx_power = lora_obj.tx_power;
cmd_data->info.init.power_mode = lora_obj.pwr_mode;
@@ -1609,7 +1656,7 @@ static int32_t lora_send (const byte *buf, uint32_t len, uint32_t timeout_ms) {
}
static int32_t lora_recv (byte *buf, uint32_t len, int32_t timeout_ms, uint32_t *port) {
- lora_rx_data_t rx_data;
+ lora_rx_data_t rx_data = {{0}, 0, 0};
if (timeout_ms < 0) {
// blocking mode
@@ -1697,13 +1744,13 @@ static mp_obj_t lora_init_helper(lora_obj_t *self, const mp_arg_val_t *args) {
lora_validate_mode (cmd_data.info.init.stack_mode);
// we need to know the region first
- if (args[14].u_obj == MP_OBJ_NULL) {
+ if (args[13].u_obj == MP_OBJ_NULL) {
cmd_data.info.init.region = config_get_lora_region();
if (cmd_data.info.init.region == 0xff) {
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "no region specified and no default found in config block"));
}
} else {
- cmd_data.info.init.region = mp_obj_get_int(args[14].u_obj);
+ cmd_data.info.init.region = mp_obj_get_int(args[13].u_obj);
}
lora_validate_region(cmd_data.info.init.region);
// we need to do it here in advance for the rest of the validation to work
@@ -1716,19 +1763,29 @@ static mp_obj_t lora_init_helper(lora_obj_t *self, const mp_arg_val_t *args) {
break;
case LORAMAC_REGION_AU915:
case LORAMAC_REGION_US915:
- case LORAMAC_REGION_US915_HYBRID:
cmd_data.info.init.frequency = 915000000;
break;
- case LORAMAC_REGION_EU868:
- cmd_data.info.init.frequency = 868000000;
- break;
case LORAMAC_REGION_EU433:
cmd_data.info.init.frequency = 433175000;
break;
+ case LORAMAC_REGION_EU868:
+ cmd_data.info.init.frequency = 868000000;
+ break;
case LORAMAC_REGION_CN470:
cmd_data.info.init.frequency = 470000000;
+ break;
+ case LORAMAC_REGION_CN779:
+ cmd_data.info.init.frequency = 779500000;
+ break;
+ case LORAMAC_REGION_KR920:
+ cmd_data.info.init.frequency = 920900000;
+ break;
+ case LORAMAC_REGION_RU864:
+ cmd_data.info.init.frequency = 864000000;
+ break;
case LORAMAC_REGION_IN865:
cmd_data.info.init.frequency = 865000000;
+ break;
default:
break;
}
@@ -1743,16 +1800,16 @@ static mp_obj_t lora_init_helper(lora_obj_t *self, const mp_arg_val_t *args) {
case LORAMAC_REGION_AU915:
case LORAMAC_REGION_US915:
case LORAMAC_REGION_IN865:
- case LORAMAC_REGION_US915_HYBRID:
+ case LORAMAC_REGION_KR920:
+ case LORAMAC_REGION_RU864:
cmd_data.info.init.tx_power = 20;
break;
case LORAMAC_REGION_CN470:
+ case LORAMAC_REGION_CN779:
+ case LORAMAC_REGION_EU433:
case LORAMAC_REGION_EU868:
cmd_data.info.init.tx_power = 14;
break;
- case LORAMAC_REGION_EU433:
- cmd_data.info.init.tx_power = 12;
- break;
default:
break;
}
@@ -1775,14 +1832,13 @@ static mp_obj_t lora_init_helper(lora_obj_t *self, const mp_arg_val_t *args) {
cmd_data.info.init.power_mode = args[7].u_int;
lora_validate_power_mode (cmd_data.info.init.power_mode);
- cmd_data.info.init.txiq = args[8].u_bool;
- cmd_data.info.init.rxiq = args[9].u_bool;
+ cmd_data.info.init.inv_iq = args[8].u_bool;
- cmd_data.info.init.adr = args[10].u_bool;
- cmd_data.info.init.public = args[11].u_bool;
- cmd_data.info.init.tx_retries = args[12].u_int;
+ cmd_data.info.init.adr = args[9].u_bool;
+ cmd_data.info.init.public = args[10].u_bool;
+ cmd_data.info.init.tx_retries = args[11].u_int;
- cmd_data.info.init.device_class = args[13].u_int;
+ cmd_data.info.init.device_class = args[12].u_int;
lora_validate_device_class(cmd_data.info.init.device_class);
// send message to the lora task
@@ -1802,8 +1858,7 @@ STATIC const mp_arg_t lora_init_args[] = {
{ MP_QSTR_preamble, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} },
{ MP_QSTR_coding_rate, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = E_LORA_CODING_4_5} },
{ MP_QSTR_power_mode, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = E_LORA_MODE_ALWAYS_ON} },
- { MP_QSTR_tx_iq, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
- { MP_QSTR_rx_iq, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
+ { MP_QSTR_inv_iq, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
{ MP_QSTR_adr, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
{ MP_QSTR_public, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = true} },
{ MP_QSTR_tx_retries, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 2} },
@@ -1907,13 +1962,15 @@ STATIC mp_obj_t lora_join(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *
dr = DR_6;
break;
case LORAMAC_REGION_US915:
- case LORAMAC_REGION_US915_HYBRID:
dr = DR_4;
break;
case LORAMAC_REGION_CN470:
- case LORAMAC_REGION_EU868:
+ case LORAMAC_REGION_CN779:
case LORAMAC_REGION_EU433:
+ case LORAMAC_REGION_EU868:
case LORAMAC_REGION_IN865:
+ case LORAMAC_REGION_KR920:
+ case LORAMAC_REGION_RU864:
dr = DR_5;
break;
default:
@@ -1923,36 +1980,9 @@ STATIC mp_obj_t lora_join(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *
// get the data rate
if (args[2].u_obj != mp_const_none) {
dr = mp_obj_get_int(args[2].u_obj);
- switch (lora_obj.region) {
- case LORAMAC_REGION_AS923:
- if (dr != DR_2) {
- goto dr_error;
- }
- break;
- case LORAMAC_REGION_AU915:
- if (dr != DR_0 && dr != DR_6) {
- goto dr_error;
- }
- break;
- case LORAMAC_REGION_US915:
- if (dr != DR_0 && dr != DR_4) {
- goto dr_error;
- }
- break;
- case LORAMAC_REGION_US915_HYBRID:
- if (dr != DR_0 && dr != DR_4) {
- goto dr_error;
- }
- break;
- case LORAMAC_REGION_EU433:
- case LORAMAC_REGION_CN470:
- case LORAMAC_REGION_EU868:
- if (dr > DR_5) {
- goto dr_error;
- }
- break;
- default:
- break;
+
+ if (lora_validate_data_rate(dr) != true) {
+ goto dr_error;
}
}
cmd_data.info.join.otaa_dr = dr;
@@ -1986,39 +2016,59 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(lora_join_obj, 1, lora_join);
STATIC mp_obj_t lora_join_multicast_group (mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
static const mp_arg_t allowed_args[] = {
- { MP_QSTR_mcAddress, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = -1} },
- { MP_QSTR_mcNwkKey, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
- { MP_QSTR_mcAppKey, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
+ { MP_QSTR_mcAddress, MP_ARG_REQUIRED | MP_ARG_INT, },
+ { MP_QSTR_mcClass, MP_ARG_REQUIRED | MP_ARG_INT, },
+ { MP_QSTR_mcKeyE, MP_ARG_REQUIRED | MP_ARG_OBJ, },
+ { MP_QSTR_minMcFCount, MP_ARG_REQUIRED | MP_ARG_INT, },
+ { MP_QSTR_maxMcFCount, MP_ARG_REQUIRED | MP_ARG_INT, },
+ { MP_QSTR_groupId, MP_ARG_REQUIRED | MP_ARG_INT, },
+ { MP_QSTR_mcDatarate, MP_ARG_REQUIRED | MP_ARG_INT, },
+ { MP_QSTR_mcFrequency, MP_ARG_REQUIRED | MP_ARG_INT, },
+ { MP_QSTR_mcPeriodicity, MP_ARG_INT , {.u_int = 0} },
};
// parse args
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(args), allowed_args, args);
- mp_buffer_info_t bufinfo_0, bufinfo_1;
- mp_get_buffer_raise(args[1].u_obj, &bufinfo_0, MP_BUFFER_READ);
- mp_get_buffer_raise(args[2].u_obj, &bufinfo_1, MP_BUFFER_READ);
-
- MulticastParams_t *channelParam = m_new_obj(MulticastParams_t);
- channelParam->Next = NULL;
- channelParam->DownLinkCounter = 0;
- channelParam->Address = args[0].u_int;
- memcpy(channelParam->NwkSKey, bufinfo_0.buf, sizeof(channelParam->NwkSKey));
- memcpy(channelParam->AppSKey, bufinfo_1.buf, sizeof(channelParam->AppSKey));
-
- if (LoRaMacMulticastChannelLink(channelParam) == LORAMAC_STATUS_OK) {
+ mp_buffer_info_t bufinfo_0;
+ mp_get_buffer_raise(args[2].u_obj, &bufinfo_0, MP_BUFFER_READ);
+ memcpy(lora_obj.McKeyE, bufinfo_0.buf, sizeof(lora_obj.McKeyE));
+
+ McChannelParams_t *channelParams = m_new_obj(McChannelParams_t);
+
+ channelParams->Address = args[0].u_int;
+ channelParams->Class = args[1].u_int;
+ channelParams->FCountMin = args[3].u_int;
+ channelParams->FCountMax = args[4].u_int;
+ channelParams->GroupID = args[5].u_int;
+ channelParams->IsEnabled = true;
+ channelParams->McKeyE = lora_obj.McKeyE;
+
+ if(channelParams->Class == CLASS_B)
+ {
+ channelParams->RxParams.ClassB.Datarate = args[6].u_int;
+ channelParams->RxParams.ClassB.Frequency = args[7].u_int;
+ channelParams->RxParams.ClassB.Periodicity = args[8].u_int;
+ }
+ else
+ {
+ channelParams->RxParams.ClassC.Datarate = args[6].u_int;
+ channelParams->RxParams.ClassC.Frequency = args[7].u_int;
+ }
+
+ if (LoRaMacMcChannelSetup(channelParams) == LORAMAC_STATUS_OK) {
return mp_const_true;
}
-
+
return mp_const_false;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(lora_join_multicast_group_obj, 0, lora_join_multicast_group);
STATIC mp_obj_t lora_leave_multicast_group (mp_obj_t self_in, mp_obj_t multicast_addr_obj) {
uint32_t mcAddr = mp_obj_get_int(multicast_addr_obj);
- MulticastParams_t *channelParam = LoRaMacMulticastGetChannel(mcAddr);
- if (LoRaMacMulticastChannelUnlink(channelParam) == LORAMAC_STATUS_OK) {
- m_del_obj(MulticastParams_t, channelParam);
+
+ if (LoRaMacMcChannelDelete((AddressIdentifier_t)LoRaMacMcChannelGetGroupId(mcAddr)) == LORAMAC_STATUS_OK) {
return mp_const_true;
}
return mp_const_false;
@@ -2522,11 +2572,14 @@ STATIC const mp_map_elem_t lora_locals_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_AS923), MP_OBJ_NEW_SMALL_INT(LORAMAC_REGION_AS923) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_AU915), MP_OBJ_NEW_SMALL_INT(LORAMAC_REGION_AU915) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_EU433), MP_OBJ_NEW_SMALL_INT(LORAMAC_REGION_EU433) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_EU868), MP_OBJ_NEW_SMALL_INT(LORAMAC_REGION_EU868) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_US915), MP_OBJ_NEW_SMALL_INT(LORAMAC_REGION_US915) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_CN470), MP_OBJ_NEW_SMALL_INT(LORAMAC_REGION_CN470) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_CN779), MP_OBJ_NEW_SMALL_INT(LORAMAC_REGION_CN779) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_IN865), MP_OBJ_NEW_SMALL_INT(LORAMAC_REGION_IN865) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_EU433), MP_OBJ_NEW_SMALL_INT(LORAMAC_REGION_EU433) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_RU864), MP_OBJ_NEW_SMALL_INT(LORAMAC_REGION_RU864) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_KR920), MP_OBJ_NEW_SMALL_INT(LORAMAC_REGION_KR920) },
};
STATIC MP_DEFINE_CONST_DICT(lora_locals_dict, lora_locals_dict_table);
@@ -2572,13 +2625,16 @@ static int lora_socket_socket (mod_network_socket_obj_t *s, int *_errno) {
switch (lora_obj.region) {
case LORAMAC_REGION_AS923:
case LORAMAC_REGION_EU868:
- case LORAMAC_REGION_EU433:
case LORAMAC_REGION_CN470:
+ case LORAMAC_REGION_EU433:
+ case LORAMAC_REGION_CN779:
+ case LORAMAC_REGION_RU864:
+ case LORAMAC_REGION_IN865:
+ case LORAMAC_REGION_KR920:
dr = DR_5;
break;
case LORAMAC_REGION_AU915:
case LORAMAC_REGION_US915:
- case LORAMAC_REGION_US915_HYBRID:
dr = DR_4;
break;
default:
diff --git a/esp32/mods/modlora.h b/esp32/mods/modlora.h
index e2b7b0e4ac..915bcfb764 100644
--- a/esp32/mods/modlora.h
+++ b/esp32/mods/modlora.h
@@ -45,24 +45,11 @@ typedef enum {
typedef enum {
E_LORA_NVS_ELE_JOINED = 0,
- E_LORA_NVS_ELE_UPLINK,
- E_LORA_NVS_ELE_DWLINK,
- E_LORA_NVS_ELE_DEVADDR,
- E_LORA_NVS_ELE_NWSKEY,
- E_LORA_NVS_ELE_APPSKEY,
- E_LORA_NVS_ELE_NET_ID,
- E_LORA_NVS_ELE_ADR_ACKS,
- E_LORA_NVS_ELE_MAC_PARAMS,
- E_LORA_NVS_ELE_CHANNELS,
- E_LORA_NVS_ELE_ACK_REQ,
- E_LORA_NVS_MAC_NXT_TX,
- E_LORA_NVS_MAC_CMD_BUF_IDX,
- E_LORA_NVS_MAC_CMD_BUF_RPT_IDX,
- E_LORA_NVS_ELE_MAC_BUF,
- E_LORA_NVS_ELE_MAC_RPT_BUF,
+ E_LORA_NVS_ELE_LORAMAC_CTX,
+ E_LORA_NVS_ELE_MAC_CMD_CTX,
E_LORA_NVS_ELE_REGION,
- E_LORA_NVS_ELE_CHANNELMASK,
- E_LORA_NVS_ELE_CHANNELMASK_REMAINING,
+ E_LORA_NVS_ELE_REGION_CTX,
+ E_LORA_NVS_ELE_SEC_ELEM_CTX,
E_LORA_NVS_NUM_KEYS
} e_lora_nvs_key_t;
@@ -78,8 +65,7 @@ typedef struct {
uint8_t tx_power;
uint8_t power_mode;
uint8_t tx_retries;
- bool txiq;
- bool rxiq;
+ bool inv_iq;
bool adr;
bool public;
} lora_init_cmd_data_t;
@@ -140,7 +126,13 @@ typedef struct {
uint8_t port;
} lora_rx_data_t;
-typedef void ( *modlora_timerCallback )( void );
+typedef void ( *modlora_timerCallback )( void *context );
+
+typedef struct {
+ modlora_timerCallback cb;
+ void *cb_param;
+} modlora_timerCb_data_t;
+
/******************************************************************************
EXPORTED DATA
******************************************************************************/
@@ -155,9 +147,11 @@ extern bool modlora_nvs_get_uint(uint32_t key_idx, uint32_t *value);
extern bool modlora_nvs_get_blob(uint32_t key_idx, void *value, uint32_t *length);
extern void modlora_sleep_module(void);
extern bool modlora_is_module_sleep(void);
-IRAM_ATTR extern void modlora_set_timer_callback(modlora_timerCallback cb);
+IRAM_ATTR extern void modlora_set_timer_callback(modlora_timerCallback cb, void *cb_param);
extern int lora_ot_recv(uint8_t *buf, int8_t *rssi);
extern void lora_ot_send(const uint8_t *buf, uint16_t len);
+extern bool modlora_lora_needs_processor_active (void);
+
#endif // MODLORA_H_
diff --git a/esp32/mods/modlte.c b/esp32/mods/modlte.c
index b823883ef9..6a9fe98523 100644
--- a/esp32/mods/modlte.c
+++ b/esp32/mods/modlte.c
@@ -30,7 +30,7 @@
#include "esp_system.h"
#include "esp_spi_flash.h"
#include "nvs_flash.h"
-#include "esp_event_loop.h"
+#include "esp_event.h"
#include "ff.h"
#include "machpin.h"
@@ -62,6 +62,8 @@
#include "esp_log.h"
#include "driver/uart.h"
+#include "uart_struct.h"
+#include "uart_reg.h"
#include "driver/gpio.h"
#include "pycom_config.h"
@@ -592,10 +594,14 @@ STATIC mp_obj_t lte_psm(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw
pos++; // "
// get three digit TAU unit
+#ifdef DEBUG
char* oldpos = pos;
+#endif
tuple[2] = mp_obj_new_int_from_str_len( (const char**) &pos, 3, false, 2);
+#ifdef DEBUG
+ // assert() is empty when NDEBUG is defined (so DEBUG is not defined) and it causes compilation warning as "variable 'oldpos' set but not used"
assert( pos == oldpos + 3); // mp_obj_new_int_from_str_len is supposed to consume exactly 3 characters
-
+#endif
// get five digit TAU value
tuple[1] = mp_obj_new_int_from_str_len( (const char**) &pos, 5, false, 2);
@@ -605,10 +611,13 @@ STATIC mp_obj_t lte_psm(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw
pos++; // "
// get three digit ActiveTime unit
+#ifdef DEBUG
oldpos = pos;
+#endif
tuple[4] = mp_obj_new_int_from_str_len( (const char**) &pos, 3, false, 2);
+#ifdef DEBUG
assert( pos == oldpos + 3); // mp_obj_new_int_from_str_len is supposed to consume exactly 3 characters
-
+#endif
// get five digit ActiveTime value
tuple[3] = mp_obj_new_int_from_str_len( (const char**) &pos, 5, false, 2);
diff --git a/esp32/mods/modmachine.c b/esp32/mods/modmachine.c
index 28f4f4b9e0..403e59f1ae 100644
--- a/esp32/mods/modmachine.c
+++ b/esp32/mods/modmachine.c
@@ -88,10 +88,12 @@
#include "freertos/timers.h"
#include "freertos/xtensa_api.h"
-#include "rom/ets_sys.h"
+#include "esp32/rom/ets_sys.h"
#include "soc/rtc_cntl_reg.h"
#include "soc/sens_reg.h"
+#include "rtc-board.h"
+
#ifdef PYGATE_ENABLED
#include "cmd_manager.h"
#include "../pygate/concentrator/loragw_hal_esp.h"
@@ -400,6 +402,49 @@ STATIC mp_obj_t machine_idle(void) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_idle_obj, machine_idle);
+/**
+ * @brief machine_configure_wakeup_gpios enable gpios to wake up the core from light sleep
+ *
+ * param in: list of tuples of pin name and logic level
+ * machine.configure_wakeup_gpios([('P13',1), ('P14',0)])
+ * machine.configure_wakeup_gpios([('P13',machine.WAKEUP_HIGH), ('P14',machine.WAKEUP_LOW)])
+ */
+#define ESP_LIGHTSLEEP_WAKEUP_LOW 0
+#define ESP_LIGHTSLEEP_WAKEUP_HIGH 1
+STATIC mp_obj_t machine_configure_wakeup_gpios(mp_obj_t list_obj) {
+ if (!mp_obj_is_type(list_obj, &mp_type_list)) {
+ mp_raise_TypeError("list of tuples expected");
+ }
+ mp_obj_list_t* list = MP_OBJ_TO_PTR(list_obj);
+ for (uint32_t i=0; ilen; i++) {
+ if (!mp_obj_is_type(list->items[i], &mp_type_tuple)) {
+ mp_raise_TypeError("list of tuples expected");
+ }
+ mp_obj_tuple_t* tuple = MP_OBJ_TO_PTR(list->items[i]);
+ if (tuple->len!=2) {
+ mp_raise_TypeError("list of tuples expected");
+ }
+ volatile pin_obj_t* temp = pin_find(tuple->items[0]);
+ if (!mp_obj_is_int(tuple->items[1])) {
+ mp_raise_ValueError("wrong level");
+ }
+ uint32_t level = mp_obj_get_int(tuple->items[1]);
+ if ((level!=ESP_LIGHTSLEEP_WAKEUP_LOW) && (level!=ESP_LIGHTSLEEP_WAKEUP_HIGH)) {
+ mp_raise_ValueError("wrong level");
+ }
+ }
+
+ for (uint32_t i=0; ilen; i++) {
+ mp_obj_tuple_t* tuple = MP_OBJ_TO_PTR(list->items[i]);
+ pin_obj_t* gpio = pin_find(tuple->items[0]);
+ gpio_int_type_t level = mp_obj_get_int(tuple->items[1]);
+ gpio_wakeup_enable(gpio->pin_number, level+GPIO_INTR_LOW_LEVEL);
+ }
+ esp_sleep_enable_gpio_wakeup();
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_configure_wakeup_gpios_obj, machine_configure_wakeup_gpios);
+
STATIC mp_obj_t machine_sleep (uint n_args, const mp_obj_t *arg) {
bool reconnect = false;
@@ -483,6 +528,109 @@ STATIC mp_obj_t machine_deepsleep (uint n_args, const mp_obj_t *arg) {
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_deepsleep_obj, 0, 1, machine_deepsleep);
+#ifdef MOD_LORA_ENABLED
+#define MIN_SLEEP_TIME 150LL*1000 // us
+#define WAIT_SLEEP_TIME 5 // ms
+bool LoRaActionsWaiting (void);
+STATIC mp_obj_t machine_sleep_overlora (mp_obj_t duraton_ms, mp_obj_t reconnect_param) {
+ uint64_t sleep_time = (uint64_t)mp_obj_get_int_truncated(duraton_ms) * 1000;
+ bool reconnect = (bool)mp_obj_is_true(reconnect_param);
+ uint64_t alarm_duration;
+ struct timeval tv;
+ uint64_t ts_start;
+ uint64_t ts_stop;
+
+ if (sleep_timealarm_duration){
+ sleep_time = alarm_duration;
+ }
+ if (sleep_timepin_number, IRQ_HIGH_LEVEL);
+#endif
+#if defined(LOPY4)
+ gpio_wakeup_enable(SX1276.DIO.pin_obj->pin_number, IRQ_HIGH_LEVEL);
+#endif
+ esp_sleep_enable_gpio_wakeup();
+
+ {
+ gettimeofday(&tv, NULL);
+ ts_start = (uint64_t)(tv.tv_sec * 1000000ull) + tv.tv_usec;
+
+ if(ESP_OK != esp_light_sleep_start())
+ {
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "Wifi or BT not stopped before sleep"));
+ }
+
+ gettimeofday(&tv, NULL);
+ ts_stop = (uint64_t)(tv.tv_sec * 1000000ull) + tv.tv_usec;
+ TimerTickAdjust((ts_stop-ts_start)/1000);
+ }
+
+ /* restore setting for the lora int */
+#if defined(FIPY) || defined(LOPY)
+ gpio_set_intr_type(SX1272.DIO.pin_obj->pin_number, IRQ_RISING_EDGE);
+#endif
+#if defined(LOPY4)
+ gpio_set_intr_type(SX1276.DIO.pin_obj->pin_number, IRQ_RISING_EDGE);
+#endif
+
+ /* resume wlan */
+ wlan_resume(reconnect);
+ /* resume bt */
+ bt_resume(reconnect);
+
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(machine_sleep_overlora_obj, machine_sleep_overlora);
+#endif
+
STATIC mp_obj_t machine_remaining_sleep_time (void) {
return mp_obj_new_int_from_uint(mach_remaining_sleep_time);
}
@@ -612,7 +760,11 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_main), (mp_obj_t)(&machine_main_obj) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_rng), (mp_obj_t)(&machine_rng_get_obj) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_idle), (mp_obj_t)(&machine_idle_obj) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_configure_wakeup_gpios), (mp_obj_t)(&machine_configure_wakeup_gpios_obj) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_sleep), (mp_obj_t)(&machine_sleep_obj) },
+#ifdef MOD_LORA_ENABLED
+ { MP_OBJ_NEW_QSTR(MP_QSTR_sleep_overlora), (mp_obj_t)(&machine_sleep_overlora_obj) },
+#endif
{ MP_OBJ_NEW_QSTR(MP_QSTR_deepsleep), (mp_obj_t)(&machine_deepsleep_obj) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_remaining_sleep_time), (mp_obj_t)(&machine_remaining_sleep_time_obj) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_pin_sleep_wakeup), (mp_obj_t)(&machine_pin_sleep_wakeup_obj) },
@@ -669,6 +821,9 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_WAKEUP_ALL_LOW), MP_OBJ_NEW_SMALL_INT(ESP_EXT1_WAKEUP_ALL_LOW) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_WAKEUP_ANY_HIGH), MP_OBJ_NEW_SMALL_INT(ESP_EXT1_WAKEUP_ANY_HIGH) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_WAKEUP_LOW), MP_OBJ_NEW_SMALL_INT(ESP_LIGHTSLEEP_WAKEUP_LOW) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_WAKEUP_HIGH), MP_OBJ_NEW_SMALL_INT(ESP_LIGHTSLEEP_WAKEUP_HIGH) },
+
#ifdef PYGATE_ENABLED
{ MP_OBJ_NEW_QSTR(MP_QSTR_PYGATE_START_EVT), MP_OBJ_NEW_SMALL_INT(PYGATE_START_EVENT) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_PYGATE_STOP_EVT), MP_OBJ_NEW_SMALL_INT(PYGATE_STOP_EVENT) },
diff --git a/esp32/mods/modnetwork.c b/esp32/mods/modnetwork.c
index 26e52323b3..7c97cfa9da 100644
--- a/esp32/mods/modnetwork.c
+++ b/esp32/mods/modnetwork.c
@@ -52,11 +52,15 @@
#if defined(MOD_COAP_ENABLED)
#include "modcoap.h"
#endif
-
+#if defined(MOD_MDNS_ENABLED)
#include "modmdns.h"
+#endif
#ifdef PYETH_ENABLED
#include "modeth.h"
#endif
+#if defined(MOD_ESPNOW_ENABLED)
+#include "modespnow.h"
+#endif
#include "lwip/sockets.h"
@@ -387,7 +391,12 @@ STATIC const mp_map_elem_t mp_module_network_globals_table[] = {
#if defined(MOD_COAP_ENABLED)
{ MP_OBJ_NEW_QSTR(MP_QSTR_Coap), (mp_obj_t)&mod_coap },
#endif
+#if defined(MOD_MDNS_ENABLED)
{ MP_OBJ_NEW_QSTR(MP_QSTR_MDNS), (mp_obj_t)&mod_mdns },
+#endif
+#if defined(MOD_ESPNOW_ENABLED)
+ { MP_OBJ_NEW_QSTR(MP_QSTR_ESPNOW), (mp_obj_t)&mod_espnow },
+#endif
};
STATIC MP_DEFINE_CONST_DICT(mp_module_network_globals, mp_module_network_globals_table);
diff --git a/esp32/mods/modnetwork.h b/esp32/mods/modnetwork.h
index 97aee48580..fdb4b566ec 100644
--- a/esp32/mods/modnetwork.h
+++ b/esp32/mods/modnetwork.h
@@ -43,6 +43,7 @@
DEFINE CONSTANTS
******************************************************************************/
#define MOD_NETWORK_IPV4ADDR_BUF_SIZE (4)
+#define TCPIP_HOSTNAME_MAX_SIZE (32)
/******************************************************************************
DEFINE TYPES
diff --git a/esp32/mods/modpycom.c b/esp32/mods/modpycom.c
index 0e7f99ce0f..178075cb14 100644
--- a/esp32/mods/modpycom.c
+++ b/esp32/mods/modpycom.c
@@ -31,7 +31,7 @@
#include "antenna.h"
#include "py/mphal.h"
-#include "bootmgr.h"
+#include "pycom_bootloader.h"
#include "updater.h"
#include "mptask.h"
@@ -39,6 +39,8 @@
#include "modmachine.h"
#include "esp32chipinfo.h"
#include "modwlan.h"
+#include "pycom_general_util.h"
+
#include
@@ -66,16 +68,6 @@ void modpycom_init0(void) {
}
}
-static bool is_empty(uint8_t* value, uint8_t size) {
- bool ret_val = true;
- for (int i=0; i < size; i++) {
- if (value[i] != 0xFF) {
- ret_val = false;
- }
- }
- return ret_val;
-}
-
static void modpycom_bootmgr(uint8_t boot_partition, uint8_t fs_type, uint8_t safeboot, bool reset) {
bool update_part = false;
bool update_fstype = false;
@@ -224,6 +216,18 @@ STATIC mp_obj_t mod_pycom_diff_update_enabled (void) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_pycom_diff_update_enabled_obj, mod_pycom_diff_update_enabled);
+STATIC mp_obj_t mod_pycom_factory_img (mp_uint_t n_args, const mp_obj_t *args) {
+
+ if (n_args == 0) {
+ return mp_obj_new_bool(boot_info.ActiveImg == IMG_ACT_FACTORY);
+ } else {
+ boot_info.ActiveImg = IMG_ACT_FACTORY;
+ updater_write_boot_info(&boot_info, boot_info_offset);
+ return mp_const_none;
+ }
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_pycom_factory_img_obj, 0, 1, mod_pycom_factory_img);
+
STATIC mp_obj_t mod_pycom_pulses_get (mp_obj_t gpio, mp_obj_t timeout) {
rmt_config_t rmt_rx;
rmt_rx.channel = RMT_CHANNEL_0;
@@ -566,7 +570,9 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_pycom_wdt_on_boot_timeout_obj, 0,
STATIC mp_obj_t mod_pycom_heartbeat_on_boot (mp_uint_t n_args, const mp_obj_t *args) {
if (n_args) {
- config_set_heartbeat_on_boot (mp_obj_is_true(args[0]));
+ if (!config_set_heartbeat_on_boot (mp_obj_is_true(args[0]))) {
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "heartbeat set failed"));
+ }
} else {
return mp_obj_new_bool(config_get_heartbeat_on_boot());
}
@@ -574,6 +580,26 @@ STATIC mp_obj_t mod_pycom_heartbeat_on_boot (mp_uint_t n_args, const mp_obj_t *a
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_pycom_heartbeat_on_boot_obj, 0, 1, mod_pycom_heartbeat_on_boot);
+STATIC mp_obj_t mod_pycom_rgb_led_on_boot (mp_uint_t n_args, const mp_obj_t *args) {
+#ifndef CONFIG_PYCOM_RGB_LED_DISABLE
+ if (n_args) {
+ if (!mp_obj_is_int(args[0])) {
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "RGB Led color bad format"));
+ }
+ if (!config_set_rgb_led_on_boot(mp_obj_get_int(args[0]))) {
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "RGB Led set failed"));
+ }
+ } else {
+ return mp_obj_new_int(config_get_rgb_led_on_boot());
+ }
+#else
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "RGB Led Interface Disabled"));
+#endif
+
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_pycom_rgb_led_on_boot_obj, 0, 1, mod_pycom_rgb_led_on_boot);
+
STATIC mp_obj_t mod_pycom_lte_modem_on_boot (mp_uint_t n_args, const mp_obj_t *args) {
if (n_args) {
config_set_lte_modem_enable_on_boot (mp_obj_is_true(args[0]));
@@ -584,6 +610,8 @@ STATIC mp_obj_t mod_pycom_lte_modem_on_boot (mp_uint_t n_args, const mp_obj_t *a
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_pycom_lte_modem_on_boot_obj, 0, 1, mod_pycom_lte_modem_on_boot);
+#if (VARIANT == PYBYTES)
+
STATIC mp_obj_t mod_pycom_pybytes_on_boot (mp_uint_t n_args, const mp_obj_t *args) {
if (n_args) {
config_set_pybytes_autostart (mp_obj_is_true(args[0]));
@@ -594,7 +622,6 @@ STATIC mp_obj_t mod_pycom_pybytes_on_boot (mp_uint_t n_args, const mp_obj_t *arg
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_pycom_pybytes_on_boot_obj, 0, 1, mod_pycom_pybytes_on_boot);
-
STATIC mp_obj_t mod_pycom_pybytes_lte_config (size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_carrier, ARG_apn, ARG_cid, ARG_band, ARG_type, ARG_reset };
STATIC const mp_arg_t allowed_args[] = {
@@ -675,6 +702,8 @@ STATIC mp_obj_t mod_pycom_pybytes_lte_config (size_t n_args, const mp_obj_t *pos
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mod_pycom_pybytes_lte_config_obj, 0, mod_pycom_pybytes_lte_config);
+#endif
+
STATIC mp_obj_t mod_pycom_bootmgr (size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_boot_partition, ARG_fs_type, ARG_safeboot, ARG_status };
STATIC const mp_arg_t allowed_args[] = {
@@ -764,12 +793,97 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_pycom_get_free_heap_obj, mod_pycom_get_free
#if (VARIANT == PYBYTES)
-STATIC mp_obj_t mod_pycom_pybytes_device_token (void) {
- uint8_t pybytes_device_token[39];
- config_get_pybytes_device_token(pybytes_device_token);
- return mp_obj_new_str((const char*)pybytes_device_token,strlen((const char*)pybytes_device_token));
+STATIC mp_obj_t mod_pycom_pybytes_device_token(mp_uint_t n_args, const mp_obj_t *args) {
+
+ if (n_args) {
+ uint8_t *token_ptr;
+ token_ptr = (uint8_t *)mp_obj_str_get_str(args[0]);
+
+ if (!config_set_pybytes_device_token(token_ptr)) {
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Failed to write Device Token"));
+ }
+
+ return mp_const_none;
+ } else {
+ uint8_t pybytes_device_token[39];
+
+ config_get_pybytes_device_token(pybytes_device_token);
+ return mp_obj_new_str((const char *)pybytes_device_token, strlen((const char *)pybytes_device_token));
+ }
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_pycom_pybytes_device_token_obj, 0, 1, mod_pycom_pybytes_device_token);
+
+STATIC mp_obj_t mod_pycom_pybytes_ota_status (mp_uint_t n_args, const mp_obj_t *args) {
+
+ if (n_args) {
+ uint8_t status;
+ status = mp_obj_get_int(args[0]);
+
+ if (!config_set_pybytes_ota_status(status)) {
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Failed to write OTA Status"));
+ }
+ return mp_const_none;
+ } else {
+ return mp_obj_new_int(config_get_pybytes_ota_status());
+ }
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_pycom_pybytes_ota_status_obj, 0, 1, mod_pycom_pybytes_ota_status);
+
+STATIC mp_obj_t mod_pycom_pybytes_fwtype (mp_uint_t n_args, const mp_obj_t *args) {
+
+ if (n_args) {
+ uint8_t fwtype;
+ fwtype = mp_obj_get_int(args[0]);
+
+ if (!config_set_pybytes_fwtype(fwtype)) {
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Failed to write fwtype"));
+ }
+ return mp_const_none;
+ } else {
+ return mp_obj_new_int(config_get_pybytes_fwtype());
+ }
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_pycom_pybytes_fwtype_obj, 0, 1, mod_pycom_pybytes_fwtype);
+
+STATIC mp_obj_t mod_pycom_pybytes_sysname (mp_uint_t n_args, const mp_obj_t *args) {
+
+ if (n_args) {
+ uint8_t *sysname_ptr;
+ sysname_ptr = (uint8_t *)mp_obj_str_get_str(args[0]);
+
+ if (!config_set_pybytes_sysname(sysname_ptr)) {
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Failed to write sysname"));
+ }
+
+ return mp_const_none;
+ } else {
+ uint8_t sysname[6];
+
+ config_get_pybytes_sysname(sysname);
+ return mp_obj_new_str((const char *)sysname, strlen((const char *)sysname));
+ }
}
-STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_pycom_pybytes_device_token_obj, mod_pycom_pybytes_device_token);
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_pycom_pybytes_sysname_obj, 0, 1, mod_pycom_pybytes_sysname);
+
+STATIC mp_obj_t mod_pycom_sw_version (mp_uint_t n_args, const mp_obj_t *args) {
+
+ if (n_args) {
+ uint8_t *version;
+ version = (uint8_t *)mp_obj_str_get_str(args[0]);
+
+ if (!config_set_sw_version(version)) {
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Failed to write SW Version"));
+ }
+
+ return mp_const_none;
+ } else {
+ uint8_t sw_version[12];
+
+ config_get_sw_version(sw_version);
+ return mp_obj_new_str((const char *)sw_version, strlen((const char *)sw_version));
+ }
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_pycom_sw_version_obj, 0, 1, mod_pycom_sw_version);
STATIC mp_obj_t mod_pycom_pybytes_mqttServiceAddress (void) {
@@ -822,27 +936,18 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_pycom_smartConfig_obj, 0, 1, mod_
#endif //(VARIANT == PYBYTES)
+#if defined(FIPY) || defined(LOPY4) || defined(SIPY)
-// Helper function to return decimal value of a hexadecimal character coded in ASCII
-STATIC uint8_t hex_from_char(const char c) {
-
- if((uint8_t)c >= '0' && (uint8_t)c <= '9') {
- return c - '0';
- }
- else if((uint8_t)c >= 'A' && (uint8_t)c <= 'F') {
- return c - ('A' - 10);
- }
- else if((uint8_t)c >= 'a' && (uint8_t)c <= 'f') {
- return c - ('a' - 10);
- }
- else {
- // 16 is invalid, because in hexa allowed range is 0 - 15
- return 16;
+STATIC bool is_empty(uint8_t* value, uint8_t size) {
+ bool ret_val = true;
+ for (int i=0; i < size; i++) {
+ if (value[i] != 0xFF) {
+ ret_val = false;
+ }
}
-
+ return ret_val;
}
-
STATIC mp_obj_t mod_pycom_sigfox_info (size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_id, ARG_pac, ARG_public_key, ARG_private_key, ARG_force };
STATIC const mp_arg_t allowed_args[] = {
@@ -1013,6 +1118,64 @@ STATIC mp_obj_t mod_pycom_sigfox_info (size_t n_args, const mp_obj_t *pos_args,
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mod_pycom_sigfox_info_obj, 0, mod_pycom_sigfox_info);
+#endif // #if defined(FIPY) || defined(LOPY4) || defined(SIPY)
+
+#include "ml.h"
+
+STATIC mp_obj_t mod_pycom_ml_new_model (mp_obj_t model_definition) {
+
+ const char *model_definition_str = mp_obj_str_get_str(model_definition);
+
+ bool ret = new_model(model_definition_str);
+
+ return mp_obj_new_bool(ret);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_pycom_ml_new_model_obj, mod_pycom_ml_new_model);
+
+STATIC mp_obj_t mod_pycom_ml_run_model (mp_obj_t data) {
+
+ // Get input data.
+ mp_obj_t *list;
+ size_t listlen = 0;
+
+ mp_obj_list_get(data, &listlen, &list);
+
+ float *data_buf = (float *)malloc(listlen * sizeof(float));
+ for (int i = 0 ; i < listlen ; i++){
+ data_buf[i] = mp_obj_float_get(list[i]);
+ }
+
+ // Run inference.
+ List* results = run_model(data_buf, listlen);
+
+ free(data_buf);
+
+ // Dictionary to hold results.
+ mp_obj_dict_t *results_dct = mp_obj_new_dict(0);
+
+ // For each output block, add results.
+ l_for_each_entry(entry, results){
+
+ ReturnedData *rd = (ReturnedData *) entry->data;
+
+ mp_obj_t entry_l = mp_obj_new_list(0, NULL);
+
+ for(int i = 0; i < rd->data->buffer_size; i++){
+
+ mp_obj_list_append(entry_l, mp_obj_new_float(rd->data->buffer[i]));
+ }
+
+ // Add to dict.
+ mp_obj_dict_store (results_dct, mp_obj_new_str(rd->block_id, strlen(rd->block_id)), entry_l);
+ }
+
+ // Free memory.
+ l_delete_list(results);
+
+ return results_dct;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_pycom_ml_run_model_obj, mod_pycom_ml_run_model);
+
// This function creates a 128 bit long UUID stored in a byte array in Little Endian order from an input String
STATIC mp_obj_t create_128bit_le_uuid_from_string(mp_obj_t uuid_in) {
@@ -1070,6 +1233,7 @@ STATIC const mp_map_elem_t pycom_module_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_ota_verify), (mp_obj_t)&mod_pycom_ota_verify_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_ota_slot), (mp_obj_t)&mod_pycom_ota_slot_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_diff_update_enabled), (mp_obj_t)&mod_pycom_diff_update_enabled_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_factory_img), (mp_obj_t)&mod_pycom_factory_img_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_pulses_get), (mp_obj_t)&mod_pycom_pulses_get_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_nvs_set), (mp_obj_t)&mod_pycom_nvs_set_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_nvs_get), (mp_obj_t)&mod_pycom_nvs_get_obj },
@@ -1079,6 +1243,7 @@ STATIC const mp_map_elem_t pycom_module_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_wdt_on_boot), (mp_obj_t)&mod_pycom_wdt_on_boot_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_wdt_on_boot_timeout), (mp_obj_t)&mod_pycom_wdt_on_boot_timeout_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_heartbeat_on_boot), (mp_obj_t)&mod_pycom_heartbeat_on_boot_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_rgbled_on_boot), (mp_obj_t)&mod_pycom_rgb_led_on_boot_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_lte_modem_en_on_boot), (mp_obj_t)&mod_pycom_lte_modem_on_boot_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_get_free_heap), (mp_obj_t)&mod_pycom_get_free_heap_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_wifi_ssid_sta), (mp_obj_t)&mod_pycom_wifi_ssid_sta_obj },
@@ -1086,6 +1251,8 @@ STATIC const mp_map_elem_t pycom_module_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_wifi_pwd_sta), (mp_obj_t)&mod_pycom_wifi_pwd_sta_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_wifi_pwd_ap), (mp_obj_t)&mod_pycom_wifi_pwd_ap_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_wifi_mode_on_boot), (mp_obj_t)&mod_pycom_wifi_mode_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_ml_new_model), (mp_obj_t)&mod_pycom_ml_new_model_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_ml_run_model), (mp_obj_t)&mod_pycom_ml_run_model_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_create_128bit_le_uuid_from_string), (mp_obj_t)&create_128bit_le_uuid_from_string_obj },
@@ -1095,6 +1262,10 @@ STATIC const mp_map_elem_t pycom_module_globals_table[] = {
#if (VARIANT == PYBYTES)
{ MP_OBJ_NEW_QSTR(MP_QSTR_pybytes_device_token), (mp_obj_t)&mod_pycom_pybytes_device_token_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_pybytes_ota_status), (mp_obj_t)&mod_pycom_pybytes_ota_status_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_pybytes_fwtype), (mp_obj_t)&mod_pycom_pybytes_fwtype_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_pybytes_sysname), (mp_obj_t)&mod_pycom_pybytes_sysname_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_sw_version), (mp_obj_t)&mod_pycom_sw_version_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_pybytes_mqttServiceAddress), (mp_obj_t)&mod_pycom_pybytes_mqttServiceAddress_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_pybytes_userId), (mp_obj_t)&mod_pycom_pybytes_userId_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_pybytes_network_preferences), (mp_obj_t)&mod_pycom_pybytes_network_preferences_obj },
@@ -1110,8 +1281,13 @@ STATIC const mp_map_elem_t pycom_module_globals_table[] = {
// class constants
{ MP_OBJ_NEW_QSTR(MP_QSTR_FACTORY), MP_OBJ_NEW_SMALL_INT(0) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_OTA_0), MP_OBJ_NEW_SMALL_INT(1) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_FAT), MP_OBJ_NEW_SMALL_INT(0) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_FAT), MP_OBJ_NEW_SMALL_INT(0) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_LittleFS), MP_OBJ_NEW_SMALL_INT(1) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_OTA_STATUS_SUCCESS), MP_OBJ_NEW_SMALL_INT(OTA_STATUS_SUCCESS) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_OTA_STATUS_FAILURE), MP_OBJ_NEW_SMALL_INT(OTA_STATUS_FAILURE) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_OTA_STATUS_PENDING), MP_OBJ_NEW_SMALL_INT(OTA_STATUS_PENDING) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_FWTYPE_PYMESH), MP_OBJ_NEW_SMALL_INT(FW_TYPE_PYMESH) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_FWTYPE_PYBYTES), MP_OBJ_NEW_SMALL_INT(FW_TYPE_PYBYTES) }
};
diff --git a/esp32/mods/moducrypto.c b/esp32/mods/moducrypto.c
index f6340b8998..6e3bac4394 100644
--- a/esp32/mods/moducrypto.c
+++ b/esp32/mods/moducrypto.c
@@ -14,8 +14,8 @@
#include "py/nlr.h"
#include "py/runtime.h"
#include "esp_system.h"
-#include "hwcrypto/aes.h"
-#include "hwcrypto/sha.h"
+#include "esp32/aes.h"
+#include "esp32/sha.h"
#include "mpexception.h"
#include "mbedtls/entropy.h"
#include "mbedtls/pk.h"
diff --git a/esp32/mods/moduhashlib.c b/esp32/mods/moduhashlib.c
index 3652676181..3ce1c01f38 100644
--- a/esp32/mods/moduhashlib.c
+++ b/esp32/mods/moduhashlib.c
@@ -20,8 +20,8 @@
#include "sha1_alt.h"
#include "sha256_alt.h"
#include "sha512_alt.h"
-#include "rom/md5_hash.h"
-#include "hwcrypto/sha.h"
+#include "esp32/rom/md5_hash.h"
+#include "esp32/sha.h"
#include "mpexception.h"
#include "mbedtls/sha1.h"
#include "mbedtls/sha256.h"
diff --git a/esp32/mods/modusocket.c b/esp32/mods/modusocket.c
index cd660932b2..b9f4f4d87c 100644
--- a/esp32/mods/modusocket.c
+++ b/esp32/mods/modusocket.c
@@ -645,6 +645,7 @@ STATIC mp_obj_t socket_settimeout(mp_obj_t self_in, mp_obj_t timeout_in) {
if (timeout_in == mp_const_none) {
timeout = -1;
} else {
+ // Convert the timeout given in seconds to millisecond
timeout = 1000 * mp_obj_get_float(timeout_in);
}
int _errno;
@@ -950,7 +951,7 @@ STATIC mp_obj_t mod_usocket_dnsserver(size_t n_args, const mp_obj_t *args)
modusocket_check_numdns(args[0]);
uint8_t numdns = mp_obj_get_int(args[0]);
- ipaddr = dns_getserver(numdns);
+ ipaddr = *(dns_getserver(numdns));
if(ipaddr.type == 0)
{
tuple[0] = mp_obj_new_int(numdns);
@@ -982,7 +983,7 @@ STATIC mp_obj_t mod_usocket_dnsserver(size_t n_args, const mp_obj_t *args)
{
mp_obj_t tuple[MODUSOCKET_MAX_DNS_SERV];
for(int i=0; i < MODUSOCKET_MAX_DNS_SERV; i++) {
- ip_addr_t ipaddr = dns_getserver(i);
+ ip_addr_t ipaddr = *(dns_getserver(i));
tuple[i] = netutils_format_ipv4_addr((uint8_t *)&ipaddr.u_addr.ip4.addr, NETUTILS_BIG);
}
return mp_obj_new_tuple(MODUSOCKET_MAX_DNS_SERV, tuple);
diff --git a/esp32/mods/modussl.c b/esp32/mods/modussl.c
index 9e1dbe9a02..28423e19e7 100644
--- a/esp32/mods/modussl.c
+++ b/esp32/mods/modussl.c
@@ -13,7 +13,7 @@
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_wifi.h"
-#include "esp_event_loop.h"
+#include "esp_event.h"
#include "esp_log.h"
#include "esp_system.h"
#include "nvs_flash.h"
diff --git a/esp32/mods/modwlan.c b/esp32/mods/modwlan.c
index 55d5b793ea..f5dfac3440 100644
--- a/esp32/mods/modwlan.c
+++ b/esp32/mods/modwlan.c
@@ -28,12 +28,13 @@
#include "nvs_flash.h"
#include "esp_wifi.h"
#include "esp_wifi_types.h"
-#include "esp_event_loop.h"
+#include "esp_event.h"
#include "ff.h"
#include "lfs.h"
#include "vfs_littlefs.h"
#include "esp_wpa2.h"
#include "esp_smartconfig.h"
+#include "esp_netif_sta_list.h"
//#include "timeutils.h"
#include "netutils.h"
@@ -59,7 +60,6 @@
#include "mptask.h"
#include "pycom_config.h"
#include "pycom_general_util.h"
-#include "app_sys_evt.h"
/******************************************************************************
DEFINE TYPES
@@ -97,7 +97,9 @@ wlan_obj_t wlan_obj = {
.pwrsave = false,
.is_promiscuous = false,
.sta_conn_timeout = false,
- .country = NULL
+ .country = NULL,
+ .esp_netif_AP = NULL,
+ .esp_netif_STA = NULL
};
/* TODO: Maybe we can add possibility to create IRQs for wifi events */
@@ -129,7 +131,7 @@ static bool is_inf_up = false;
SemaphoreHandle_t timeout_mutex;
#if defined(FIPY) || defined(GPY)
// Variable saving DNS info
-static tcpip_adapter_dns_info_t wlan_sta_inf_dns_info;
+static esp_netif_dns_info_t wlan_sta_inf_dns_info;
#endif
SemaphoreHandle_t smartConfigTimeout_mutex;
@@ -153,14 +155,14 @@ STATIC bool wlan_set_bandwidth (wifi_bandwidth_t mode);
STATIC void wlan_validate_hostname (const char *hostname);
STATIC bool wlan_set_hostname (const char *hostname);
STATIC esp_err_t wlan_update_hostname ();
-STATIC void wlan_setup_ap (const char *ssid, uint32_t auth, const char *key, uint32_t channel, bool add_mac, bool hidden);
+STATIC void wlan_setup_ap (const char *ssid, wifi_auth_mode_t auth, const char *key, uint32_t channel, bool add_mac, bool hidden);
STATIC void wlan_validate_ssid_len (uint32_t len);
STATIC uint32_t wlan_set_ssid_internal (const char *ssid, uint8_t len, bool add_mac);
-STATIC void wlan_validate_security (uint8_t auth, const char *key);
-STATIC void wlan_set_security_internal (uint8_t auth, const char *key);
+STATIC void wlan_validate_security (wifi_auth_mode_t auth, const char *key);
+STATIC void wlan_set_security_internal (wifi_auth_mode_t auth, const char *key);
STATIC void wlan_validate_channel (uint8_t channel);
STATIC void wlan_set_antenna (uint8_t antenna);
-static esp_err_t wlan_event_handler(void *ctx, system_event_t *event);
+STATIC void wlan_event_handler(void* event_handler_arg, esp_event_base_t event_base, int32_t event_id, void* event_data);
STATIC void wlan_do_connect (const char* ssid, const char* bssid, const wifi_auth_mode_t auth, const char* key, int32_t timeout, const wlan_wpa2_ent_obj_t * const wpa2_ent, const char *hostname, uint8_t channel);
static void wlan_init_wlan_recover_params(void);
static void wlan_timer_callback( TimerHandle_t xTimer );
@@ -169,9 +171,11 @@ static void wlan_validate_country_policy(uint8_t policy);
STATIC void wlan_stop_sta_conn_timer();
STATIC void wlan_set_default_inf(void);
STATIC void wlan_stop_smartConfig_timer();
-static void smart_config_callback(smartconfig_status_t status, void *pdata);
+static void smart_config_callback(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data);
static void TASK_SMART_CONFIG (void *pvParameters);
STATIC void wlan_callback_handler(void* arg);
+static void wlan_setup_do_basic_init(wlan_internal_setup_t *config);
+
//*****************************************************************************
//
//! \brief The Function Handles WLAN Events
@@ -182,9 +186,7 @@ STATIC void wlan_callback_handler(void* arg);
//!
//*****************************************************************************
void wlan_pre_init (void) {
- tcpip_adapter_init();
wifi_event_group = xEventGroupCreate();
- app_sys_register_evt_cb(APP_SYS_EVT_WIFI, wlan_event_handler);
wlan_obj.base.type = (mp_obj_t)&mod_network_nic_type_wlan;
wlan_wpa2_ent.ca_certs_path = NULL;
wlan_wpa2_ent.client_cert_path = NULL;
@@ -203,6 +205,8 @@ void wlan_pre_init (void) {
wlan_obj.mutex = xSemaphoreCreateMutex();
timeout_mutex = xSemaphoreCreateMutex();
smartConfigTimeout_mutex = xSemaphoreCreateMutex();
+ wlan_obj.esp_netif_AP = NULL;
+ wlan_obj.esp_netif_STA = NULL;
// create Smart Config Task
xTaskCreatePinnedToCore(TASK_SMART_CONFIG, "SmartConfig", SMART_CONF_TASK_STACK_SIZE / sizeof(StackType_t), NULL, SMART_CONF_TASK_PRIORITY, &SmartConfTaskHandle, 1);
}
@@ -211,53 +215,69 @@ void wlan_resume (bool reconnect)
{
// Configure back WLAN as it was before if reconnect is TRUE
if(reconnect) {
+ // In wlan_setup the wlan_obj.country is overwritten with the value coming from setup_config, need to save it out
+ wifi_country_t country;
+ wifi_country_t* country_ptr = NULL;
+ if(wlan_obj.country != NULL) {
+ memcpy(&country, wlan_obj.country, sizeof(wifi_country_t));
+ country_ptr = &country;
+ }
+
+ wlan_internal_setup_t setup_config = {
+ wlan_obj.mode,
+ (const char *)(wlan_obj.ssid_o),
+ (const char *)(wlan_obj.key),
+ (const char *)(wlan_obj.ssid),
+ (const char *)(wlan_obj.key),
+ wlan_obj.auth,
+ wlan_obj.channel,
+ wlan_obj.antenna,
+ false,
+ wlan_conn_recover_hidden,
+ wlan_obj.bandwidth,
+ country_ptr,
+ &(wlan_obj.max_tx_pwr)
+ };
// If SmartConfig enabled then re-start it
if(wlan_smart_config_enabled) {
- // Do initial configuration as at this point the Wifi Driver is not initialized
- wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
- ESP_ERROR_CHECK(esp_wifi_init(&cfg));
- ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM));
- wlan_set_antenna(wlan_obj.antenna);
- wlan_set_mode(wlan_obj.mode);
- wlan_set_bandwidth(wlan_obj.bandwidth);
- if(wlan_obj.country != NULL) {
- esp_wifi_set_country(wlan_obj.country);
- }
+ // Do the basic initialization needed by SmartConfig
+ wlan_setup_do_basic_init(&setup_config);
xTaskNotifyGive(SmartConfTaskHandle);
}
// Otherwise set up WLAN with the same parameters as it was before
else {
- // In wlan_setup the wlan_obj.country is overwritten with the value coming from setup_config, need to save it out
- wifi_country_t country;
- wifi_country_t* country_ptr = NULL;
- if(wlan_obj.country != NULL) {
- memcpy(&country, wlan_obj.country, sizeof(wifi_country_t));
- country_ptr = &country;
- }
-
- wlan_internal_setup_t setup_config = {
- wlan_obj.mode,
- (const char *)(wlan_obj.ssid_o),
- (const char *)(wlan_obj.key),
- (const char *)(wlan_obj.ssid),
- (const char *)(wlan_obj.key),
- wlan_obj.auth,
- wlan_obj.channel,
- wlan_obj.antenna,
- false,
- wlan_conn_recover_hidden,
- wlan_obj.bandwidth,
- country_ptr,
- &(wlan_obj.max_tx_pwr)
- };
-
// Initialize & reconnect to the previous connection
wlan_setup(&setup_config);
}
}
}
-void wlan_setup (wlan_internal_setup_t *config) {
+static void wlan_setup_do_basic_init(wlan_internal_setup_t *config) {
+
+ /* Only initialize/create these if they have not been created/initialized before */
+ if(wlan_obj.started == false)
+ {
+ // Register the wlan_event_handler to the default event loop for all events with base event ID belonging to WIFI events
+ ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &wlan_event_handler, NULL));
+ // Register the wlan_event_handler to the default event loop for all events with base event ID belonging to IP events
+ ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &wlan_event_handler, NULL));
+ }
+
+ // Create the given esp_netif interface if it has not been already created
+ if(config->mode == WIFI_MODE_AP && wlan_obj.esp_netif_AP == NULL) {
+ wlan_obj.esp_netif_AP = esp_netif_create_default_wifi_ap();
+ }
+ else if(config->mode == WIFI_MODE_STA && wlan_obj.esp_netif_STA == NULL) {
+ wlan_obj.esp_netif_STA = esp_netif_create_default_wifi_sta();
+ }
+ else {
+ if(wlan_obj.esp_netif_AP == NULL) {
+ wlan_obj.esp_netif_AP = esp_netif_create_default_wifi_ap();
+ }
+ if(wlan_obj.esp_netif_STA == NULL) {
+ wlan_obj.esp_netif_STA = esp_netif_create_default_wifi_sta();
+ }
+ }
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
@@ -269,6 +289,11 @@ void wlan_setup (wlan_internal_setup_t *config) {
wlan_set_antenna(config->antenna);
wlan_set_mode(config->mode);
wlan_set_bandwidth(config->bandwidth);
+}
+
+void wlan_setup (wlan_internal_setup_t *config) {
+
+ wlan_setup_do_basic_init(config);
if (config->country != NULL) {
esp_err_t ret = esp_wifi_set_country(config->country);
@@ -292,12 +317,13 @@ void wlan_setup (wlan_internal_setup_t *config) {
}
}
}
+
switch(config->mode)
{
case WIFI_MODE_AP:
MP_THREAD_GIL_EXIT();
// wlan_setup_ap must be called only when GIL is not locked
- wlan_setup_ap (config->ssid_ap, config->auth, config->key_ap, config->channel, config->add_mac, config->hidden);
+ wlan_setup_ap(config->ssid_ap, config->auth, config->key_ap, config->channel, config->add_mac, config->hidden);
// Start Wifi
esp_wifi_start();
wlan_obj.started = true;
@@ -309,7 +335,7 @@ void wlan_setup (wlan_internal_setup_t *config) {
if(config->mode == WIFI_MODE_APSTA)
{
// wlan_setup_ap must be called only when GIL is not locked
- wlan_setup_ap (config->ssid_ap, config->auth, config->key_ap, config->channel, config->add_mac, config->hidden);
+ wlan_setup_ap(config->ssid_ap, config->auth, config->key_ap, config->channel, config->add_mac, config->hidden);
}
// Start Wifi
esp_wifi_start();
@@ -333,7 +359,7 @@ void wlan_setup (wlan_internal_setup_t *config) {
}
// connect to the requested access point
- wlan_do_connect (config->ssid_sta, NULL, config->auth, config->key_sta, 30000, &wlan_wpa2_ent, NULL, 0);
+ wlan_do_connect(config->ssid_sta, NULL, config->auth, config->key_sta, 30000, &wlan_wpa2_ent, NULL, 0);
}
MP_THREAD_GIL_ENTER();
@@ -364,102 +390,94 @@ STATIC bool wlan_is_inf_up(void)
return is_inf_up;
}
-STATIC esp_err_t wlan_event_handler(void *ctx, system_event_t *event) {
- switch(event->event_id) {
- case SYSTEM_EVENT_STA_START: /**< ESP32 station start */
- wlan_obj.sta_stopped = false;
- break;
- case SYSTEM_EVENT_STA_STOP: /**< ESP32 station stop */
- wlan_obj.sta_stopped = true;
- break;
- case SYSTEM_EVENT_STA_CONNECTED: /**< ESP32 station connected to AP */
- {
- system_event_sta_connected_t *_event = (system_event_sta_connected_t *)&event->event_info;
- memcpy(wlan_obj.bssid, _event->bssid, 6);
- memcpy(wlan_obj.ssid_o, _event->ssid, 32);
- wlan_obj.channel = _event->channel;
- wlan_obj.auth = _event->authmode;
- wlan_obj.disconnected = false;
- /* Stop Conn timeout counter*/
- wlan_stop_sta_conn_timer();
- }
- break;
- case SYSTEM_EVENT_STA_GOT_IP: /**< ESP32 station got IP from connected AP */
- xEventGroupSetBits(wifi_event_group, CONNECTED_BIT);
- mod_network_register_nic(&wlan_obj);
-#if defined(FIPY) || defined(GPY)
- // Save DNS info for restoring if wifi inf is usable again after LTE disconnect
- tcpip_adapter_get_dns_info(TCPIP_ADAPTER_IF_STA, TCPIP_ADAPTER_DNS_MAIN, &wlan_sta_inf_dns_info);
-#endif
- is_inf_up = true;
- break;
- case SYSTEM_EVENT_STA_DISCONNECTED: /**< ESP32 station disconnected from AP */
- xEventGroupClearBits(wifi_event_group, CONNECTED_BIT);
- system_event_sta_disconnected_t *disconn = &event->event_info.disconnected;
- is_inf_up = false;
- switch (disconn->reason) {
- case WIFI_REASON_AUTH_FAIL:
- case WIFI_REASON_ASSOC_LEAVE:
- wlan_obj.disconnected = true;
- mod_network_deregister_nic(&wlan_obj);
- break;
- default:
- // let other errors through and try to reconnect.
- break;
+STATIC void wlan_event_handler(void* event_handler_arg, esp_event_base_t event_base, int32_t event_id, void* event_data) {
+
+ if(WIFI_EVENT == event_base)
+ {
+ // Perform the specific action based on the event_id
+ switch(event_id) {
+ case WIFI_EVENT_STA_START: /**< ESP32 station start */
+ wlan_obj.sta_stopped = false;
+ break;
+ case WIFI_EVENT_STA_STOP: /**< ESP32 station stop */
+ wlan_obj.sta_stopped = true;
+ break;
+ case WIFI_EVENT_STA_CONNECTED: /**< ESP32 station connected to AP */
+ {
+ wifi_event_sta_connected_t *_event = (wifi_event_sta_connected_t *)event_data;
+ memcpy(wlan_obj.bssid, _event->bssid, 6);
+ memcpy(wlan_obj.ssid_o, _event->ssid, 32);
+ wlan_obj.channel = _event->channel;
+ wlan_obj.auth = _event->authmode;
+ wlan_obj.disconnected = false;
+ /* Stop Conn timeout counter*/
+ wlan_stop_sta_conn_timer();
}
- if (!wlan_obj.disconnected) {
- wifi_mode_t mode;
- if (esp_wifi_get_mode(&mode) == ESP_OK) {
- if (mode & WIFI_MODE_STA) {
- esp_wifi_connect();
+ break;
+ case WIFI_EVENT_STA_DISCONNECTED: /**< ESP32 station disconnected from AP */
+ xEventGroupClearBits(wifi_event_group, CONNECTED_BIT);
+ wifi_event_sta_disconnected_t *disconn = (wifi_event_sta_disconnected_t*)event_data;
+ is_inf_up = false;
+ switch (disconn->reason) {
+ case WIFI_REASON_AUTH_FAIL:
+ case WIFI_REASON_ASSOC_LEAVE:
+ wlan_obj.disconnected = true;
+ mod_network_deregister_nic(&wlan_obj);
+ break;
+ default:
+ // let other errors through and try to reconnect.
+ break;
+ }
+ if (!wlan_obj.disconnected) {
+ wifi_mode_t mode;
+ if (esp_wifi_get_mode(&mode) == ESP_OK) {
+ if (mode & WIFI_MODE_STA) {
+ esp_wifi_connect();
+ }
}
}
- }
- break;
+ break;
- case SYSTEM_EVENT_AP_START: /**< ESP32 soft-AP start */
- mod_wlan_ap_number_of_connections = 0;
- wlan_obj.soft_ap_stopped = false;
- break;
- case SYSTEM_EVENT_AP_STOP: /**< ESP32 soft-AP stop */
- xEventGroupClearBits(wifi_event_group, CONNECTED_BIT);
- wlan_obj.soft_ap_stopped = true;
- break;
- case SYSTEM_EVENT_AP_STACONNECTED: /**< a station connected to ESP32 soft-AP */
- mod_wlan_ap_number_of_connections++;
- xEventGroupSetBits(wifi_event_group, CONNECTED_BIT);
- break;
- case SYSTEM_EVENT_AP_STADISCONNECTED: /**< a station disconnected from ESP32 soft-AP */
- mod_wlan_ap_number_of_connections--;
- if(mod_wlan_ap_number_of_connections == 0) {
+ case WIFI_EVENT_AP_START: /**< ESP32 soft-AP start */
+ mod_wlan_ap_number_of_connections = 0;
+ wlan_obj.soft_ap_stopped = false;
+ break;
+ case WIFI_EVENT_AP_STOP: /**< ESP32 soft-AP stop */
xEventGroupClearBits(wifi_event_group, CONNECTED_BIT);
- }
- break;
- case SYSTEM_EVENT_WIFI_READY: /**< ESP32 WiFi ready */
- case SYSTEM_EVENT_SCAN_DONE: /**< ESP32 finish scanning AP */
- case SYSTEM_EVENT_STA_AUTHMODE_CHANGE: /**< the auth mode of AP connected by ESP32 station changed */
- case SYSTEM_EVENT_STA_LOST_IP: /**< ESP32 station lost IP and the IP is reset to 0 */
- case SYSTEM_EVENT_STA_WPS_ER_SUCCESS: /**< ESP32 station wps succeeds in enrollee mode */
- case SYSTEM_EVENT_STA_WPS_ER_FAILED: /**< ESP32 station wps fails in enrollee mode */
- case SYSTEM_EVENT_STA_WPS_ER_TIMEOUT: /**< ESP32 station wps timeout in enrollee mode */
- case SYSTEM_EVENT_STA_WPS_ER_PIN: /**< ESP32 station wps pin code in enrollee mode */
-
- case SYSTEM_EVENT_AP_STAIPASSIGNED: /**< ESP32 soft-AP assign an IP to a connected station */
- case SYSTEM_EVENT_AP_PROBEREQRECVED: /**< Receive probe request packet in soft-AP interface */
- case SYSTEM_EVENT_GOT_IP6: /**< ESP32 station or ap or ethernet interface v6IP addr is preferred */
- case SYSTEM_EVENT_ETH_START: /**< ESP32 ethernet start */
- case SYSTEM_EVENT_ETH_STOP: /**< ESP32 ethernet stop */
- case SYSTEM_EVENT_ETH_CONNECTED: /**< ESP32 ethernet phy link up */
- case SYSTEM_EVENT_ETH_DISCONNECTED: /**< ESP32 ethernet phy link down */
- case SYSTEM_EVENT_ETH_GOT_IP: /**< ESP32 ethernet got IP from connected AP */
-
- /* TODO: some of These events will be a good candidate for Diagnostics log send to Pybytes*/
-
- break;
- default:
- break;
+ wlan_obj.soft_ap_stopped = true;
+ break;
+ case WIFI_EVENT_AP_STACONNECTED: /**< a station connected to ESP32 soft-AP */
+ mod_wlan_ap_number_of_connections++;
+ xEventGroupSetBits(wifi_event_group, CONNECTED_BIT);
+ break;
+ case WIFI_EVENT_AP_STADISCONNECTED: /**< a station disconnected from ESP32 soft-AP */
+ mod_wlan_ap_number_of_connections--;
+ if(mod_wlan_ap_number_of_connections == 0) {
+ xEventGroupClearBits(wifi_event_group, CONNECTED_BIT);
+ }
+ break;
+ default:
+ /* TODO: some of these other events not handled now might be a good candidate for Diagnostics log send to Pybytes */
+ break;
+ }
+ }
+ else if(IP_EVENT == event_base)
+ {
+ // Perform the specific action based on the event_id
+ switch(event_id) {
+ case IP_EVENT_STA_GOT_IP: /*!< station got IP from connected AP */
+ xEventGroupSetBits(wifi_event_group, CONNECTED_BIT);
+ mod_network_register_nic(&wlan_obj);
+#if defined(FIPY) || defined(GPY)
+ // Save DNS info for restoring if wifi inf is usable again after LTE disconnect
+ esp_netif_get_dns_info(wlan_obj.esp_netif_STA, ESP_NETIF_DNS_MAIN, &wlan_sta_inf_dns_info);
+#endif
+ is_inf_up = true;
+ break;
+ default:
+ break;
+ }
}
- return ESP_OK;
}
STATIC void wlan_timer_callback( TimerHandle_t xTimer )
@@ -518,24 +536,24 @@ STATIC void wlan_stop_smartConfig_timer()
}
// Must be called only when GIL is not locked
-STATIC void wlan_setup_ap (const char *ssid, uint32_t auth, const char *key, uint32_t channel, bool add_mac, bool hidden) {
- uint32_t ssid_len = wlan_set_ssid_internal (ssid, strlen(ssid), add_mac);
+STATIC void wlan_setup_ap (const char *ssid, wifi_auth_mode_t auth, const char *key, uint32_t channel, bool add_mac, bool hidden) {
+ uint32_t ssid_len = wlan_set_ssid_internal(ssid, strlen(ssid), add_mac);
wlan_set_security_internal(auth, key);
-
// get the current config and then change it
wifi_config_t config;
- esp_wifi_get_config(WIFI_IF_AP, &config);
+ ESP_ERROR_CHECK(esp_wifi_get_config(ESP_IF_WIFI_AP, &config));
strcpy((char *)config.ap.ssid, (char *)wlan_obj.ssid);
config.ap.ssid_len = ssid_len;
- config.ap.authmode = wlan_obj.auth;
+ config.ap.authmode = auth;
strcpy((char *)config.ap.password, (char *)wlan_obj.key);
config.ap.channel = channel;
wlan_obj.channel = channel;
config.ap.max_connection = MAX_AP_CONNECTED_STA;
config.ap.ssid_hidden = (uint8_t)hidden;
- esp_wifi_set_config(WIFI_IF_AP, &config);
+ ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_AP, &config));
+
//get mac of AP
- esp_wifi_get_mac(WIFI_IF_AP, wlan_obj.mac_ap);
+ ESP_ERROR_CHECK(esp_wifi_get_mac(ESP_IF_WIFI_AP, wlan_obj.mac_ap));
// Need to take back the GIL as mod_network_register_nic() uses MicroPython API and wlan_setup_ap() is called when GIL is not locked
MP_THREAD_GIL_ENTER();
@@ -549,9 +567,9 @@ STATIC void wlan_validate_mode (uint mode) {
}
}
-STATIC void wlan_set_mode (uint mode) {
+STATIC void wlan_set_mode(wifi_mode_t mode) {
wlan_obj.mode = mode;
- esp_wifi_set_mode(mode);
+ ESP_ERROR_CHECK(esp_wifi_set_mode(mode));
wifi_ps_type_t wifi_ps_type;
if (mode != WIFI_MODE_STA || wlan_obj.pwrsave == false) {
wifi_ps_type = WIFI_PS_NONE;
@@ -598,11 +616,11 @@ STATIC void wlan_validate_hostname (const char *hostname) {
STATIC bool wlan_set_hostname (const char *hostname) {
if (wlan_obj.mode == WIFI_MODE_STA)
{
- if(tcpip_adapter_set_hostname(TCPIP_ADAPTER_IF_STA, hostname) != ESP_OK)
+ if(esp_netif_set_hostname(wlan_obj.esp_netif_STA, hostname) != ESP_OK)
return false;
} else
{
- if(tcpip_adapter_set_hostname(TCPIP_ADAPTER_IF_AP, hostname) != ESP_OK)
+ if(esp_netif_set_hostname(wlan_obj.esp_netif_AP, hostname) != ESP_OK)
return false;
}
@@ -612,9 +630,9 @@ STATIC bool wlan_set_hostname (const char *hostname) {
STATIC esp_err_t wlan_update_hostname () {
char* hostname = NULL;
- tcpip_adapter_if_t interface = wlan_obj.mode == WIFI_MODE_STA ? TCPIP_ADAPTER_IF_STA : TCPIP_ADAPTER_IF_AP;
+ esp_netif_t * interface = wlan_obj.mode == WIFI_MODE_STA ? wlan_obj.esp_netif_STA : wlan_obj.esp_netif_AP;
- esp_err_t err = tcpip_adapter_get_hostname(interface, (const char**)&hostname);
+ esp_err_t err = esp_netif_get_hostname(interface, (const char**)&hostname);
if(err != ESP_OK)
{
return err;
@@ -646,7 +664,7 @@ STATIC uint32_t wlan_set_ssid_internal (const char *ssid, uint8_t len, bool add_
return len;
}
-STATIC void wlan_validate_security (uint8_t auth, const char *key) {
+STATIC void wlan_validate_security (wifi_auth_mode_t auth, const char *key) {
if (auth < WIFI_AUTH_WEP && auth > WIFI_AUTH_WPA2_ENTERPRISE) {
goto invalid_args;
}
@@ -663,7 +681,7 @@ STATIC void wlan_validate_security (uint8_t auth, const char *key) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
}
-STATIC void wlan_set_security_internal (uint8_t auth, const char *key) {
+STATIC void wlan_set_security_internal (wifi_auth_mode_t auth, const char *key) {
wlan_obj.auth = auth;
// uint8_t wep_key[32];
if (key != NULL) {
@@ -697,7 +715,7 @@ STATIC void wlan_validate_certificates (wlan_wpa2_ent_obj_t *wpa2_ent) {
}
if (wpa2_ent->identity == NULL) {
- nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "indentiy required for WPA2_ENT authentication"));
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "identity required for WPA2_ENT authentication"));
} else if (strlen(wpa2_ent->identity) > 127) {
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "invalid identity length %d", strlen(wpa2_ent->identity)));
}
@@ -728,7 +746,6 @@ static void wlan_validate_country_policy(uint8_t policy)
STATIC void wlan_do_connect (const char* ssid, const char* bssid, const wifi_auth_mode_t auth, const char* key,
int32_t timeout, const wlan_wpa2_ent_obj_t * const wpa2_ent, const char* hostname, uint8_t channel) {
- esp_wpa2_config_t wpa2_config = WPA2_CONFIG_INIT_DEFAULT();
wifi_config_t wifi_config;
memset(&wifi_config, 0, sizeof(wifi_config));
@@ -799,7 +816,7 @@ STATIC void wlan_do_connect (const char* ssid, const char* bssid, const wifi_aut
}
}
- if (ESP_OK != esp_wifi_sta_wpa2_ent_enable(&wpa2_config)) {
+ if (ESP_OK != esp_wifi_sta_wpa2_ent_enable()) {
goto os_error;
}
}
@@ -948,23 +965,28 @@ STATIC void wlan_set_default_inf(void)
{
#if defined(FIPY) || defined(GPY)
if (wlan_obj.mode == WIFI_MODE_STA || wlan_obj.mode == WIFI_MODE_APSTA) {
- tcpip_adapter_set_dns_info(TCPIP_ADAPTER_IF_STA, TCPIP_ADAPTER_DNS_MAIN, &wlan_sta_inf_dns_info);
- tcpip_adapter_up(TCPIP_ADAPTER_IF_STA);
+ esp_netif_set_dns_info(wlan_obj.esp_netif_STA, ESP_NETIF_DNS_MAIN, &wlan_sta_inf_dns_info);
+ //TODO: this is a private function
+// esp_netif_up(wlan_obj.esp_netif_STA);
}
#endif
}
//STATIC void wlan_get_sl_mac (void) {
-// // Get the MAC address
-//// uint8_t macAddrLen = SL_MAC_ADDR_LEN;
-//// sl_NetCfgGet(SL_MAC_ADDRESS_GET, NULL, &macAddrLen, wlan_obj.mac);
+// Get the MAC address
+// uint8_t macAddrLen = SL_MAC_ADDR_LEN;
+// sl_NetCfgGet(SL_MAC_ADDRESS_GET, NULL, &macAddrLen, wlan_obj.mac);
//}
+
static void TASK_SMART_CONFIG (void *pvParameters) {
EventBits_t uxBits;
bool connected;
static uint32_t thread_notification;
+ // Register the SmartConfig event handler
+ esp_event_handler_register(SC_EVENT, ESP_EVENT_ANY_ID, &smart_config_callback, NULL);
+
smartConf_init:
connected = false;
// Block task till notification is received
@@ -981,13 +1003,15 @@ static void TASK_SMART_CONFIG (void *pvParameters) {
CHECK_ESP_ERR(esp_wifi_disconnect(), smartConf_init)
}
CHECK_ESP_ERR(esp_smartconfig_set_type(SC_TYPE_ESPTOUCH), smartConf_init)
- CHECK_ESP_ERR(esp_smartconfig_start(smart_config_callback), smartConf_init)
+ smartconfig_start_config_t cfg = SMARTCONFIG_START_CONFIG_DEFAULT();
+ CHECK_ESP_ERR(esp_smartconfig_start(&cfg), smartConf_init );
goto smartConf_start;
}
goto smartConf_init;
smartConf_start:
wlan_smart_config_enabled = true;
+ //mp_printf(&mp_plat_print, "\n-------SmartConfig Started-------\n");
/*create Timer */
wlan_smartConfig_timeout = xTimerCreate("smartConfig_Timer", 60000 / portTICK_PERIOD_MS, 0, 0, wlan_timer_callback);
/*start Timer */
@@ -1049,42 +1073,43 @@ static void TASK_SMART_CONFIG (void *pvParameters) {
}
-static void smart_config_callback(smartconfig_status_t status, void *pdata)
+static void smart_config_callback(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data)
{
- wifi_config_t *wifi_config;
+ if (event_base == SC_EVENT && event_id == SC_EVENT_SCAN_DONE) {
+ //mp_printf(&mp_plat_print, "Scan done\n");
+ } else if (event_base == SC_EVENT && event_id == SC_EVENT_FOUND_CHANNEL) {
+ //mp_printf(&mp_plat_print, "Found channel\n");
+ } else if (event_base == SC_EVENT && event_id == SC_EVENT_GOT_SSID_PSWD) {
+ //mp_printf(&mp_plat_print, "Got SSID and password\n");
- switch (status) {
- case SC_STATUS_WAIT:
- //mp_printf(&mp_plat_print, "SC_STATUS_WAIT\n");
- break;
- case SC_STATUS_FIND_CHANNEL:
- //mp_printf(&mp_plat_print, "SC_STATUS_FINDING_CHANNEL\n");
- break;
- case SC_STATUS_GETTING_SSID_PSWD:
- //mp_printf(&mp_plat_print, "SC_STATUS_GETTING_SSID_PSWD\n");
- break;
- case SC_STATUS_LINK:
- //mp_printf(&mp_plat_print, "SC_STATUS_LINK\n");
- wifi_config = pdata;
- //save password/ssid/auth
- memcpy(wlan_obj.key, wifi_config->sta.password, 64);
- memcpy(wlan_obj.ssid, wifi_config->sta.ssid, (MODWLAN_SSID_LEN_MAX));
- wlan_obj.auth = wifi_config->sta.threshold.authmode;
- esp_wifi_disconnect();
- esp_wifi_set_config(ESP_IF_WIFI_STA, wifi_config);
- esp_wifi_connect();
- break;
- case SC_STATUS_LINK_OVER:
- //mp_printf(&mp_plat_print, "SC_STATUS_LINK_OVER\n");
- if (pdata != NULL) {
- uint8_t phone_ip[4] = { 0 };
- memcpy(phone_ip, (uint8_t* )pdata, 4);
- //mp_printf(&mp_plat_print, "Phone ip: %d.%d.%d.%d\n", phone_ip[0], phone_ip[1], phone_ip[2], phone_ip[3]);
- }
- xEventGroupSetBits(wifi_event_group, ESPTOUCH_DONE_BIT);
- break;
- default:
- break;
+ smartconfig_event_got_ssid_pswd_t *evt = (smartconfig_event_got_ssid_pswd_t *)event_data;
+ wifi_config_t wifi_config;
+ bzero(&wifi_config, sizeof(wifi_config_t));
+ memcpy(wifi_config.sta.ssid, evt->ssid, sizeof(wifi_config.sta.ssid));
+ memcpy(wifi_config.sta.password, evt->password, sizeof(wifi_config.sta.password));
+ wifi_config.sta.bssid_set = evt->bssid_set;
+ if (wifi_config.sta.bssid_set == true) {
+ memcpy(wifi_config.sta.bssid, evt->bssid, sizeof(wifi_config.sta.bssid));
+ }
+
+ //save password/ssid/auth
+ memcpy(wlan_obj.key, wifi_config.sta.password, 64);
+ memcpy(wlan_obj.ssid, wifi_config.sta.ssid, (MODWLAN_SSID_LEN_MAX));
+ wlan_obj.auth = wifi_config.sta.threshold.authmode;
+
+ esp_wifi_disconnect();
+ esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config);
+ esp_wifi_connect();
+
+ } else if (event_base == SC_EVENT && event_id == SC_EVENT_SEND_ACK_DONE) {
+ //mp_printf(&mp_plat_print, "SC_EVENT_SEND_ACK_DONE event\n");
+ if (event_data != NULL) {
+ smartconfig_event_got_ssid_pswd_t *evt = (smartconfig_event_got_ssid_pswd_t *)event_data;
+ uint8_t phone_ip[4] = { 0 };
+ memcpy(phone_ip, evt->cellphone_ip, 4);
+ //mp_printf(&mp_plat_print, "Phone ip: %d.%d.%d.%d\n", phone_ip[0], phone_ip[1], phone_ip[2], phone_ip[3]);
+ }
+ xEventGroupSetBits(wifi_event_group, ESPTOUCH_DONE_BIT);
}
}
@@ -1271,7 +1296,7 @@ mp_obj_t wlan_deinit(mp_obj_t self_in) {
if(wlan_smart_config_enabled) {
// If the input parameter is not the object itself but a simple boolean, it is interpreted that
// wlan_deinit is called from machine_sleep()
- if(mp_obj_get_type(self_in) == &mp_type_bool) {
+ if(self_in != NULL && mp_obj_get_type(self_in) == &mp_type_bool) {
called_from_sleep = (bool)mp_obj_get_int(self_in);
if(called_from_sleep == true) {
// stop smart config with special event
@@ -1295,7 +1320,20 @@ mp_obj_t wlan_deinit(mp_obj_t self_in) {
vTaskDelay(1 / portTICK_PERIOD_MS);
}
- /* stop and free wifi resource */
+ // Destroy esp_netif interfaces
+ if(wlan_obj.esp_netif_AP != NULL) {
+ esp_netif_destroy(wlan_obj.esp_netif_AP);
+ wlan_obj.esp_netif_AP = NULL;
+ }
+ if(wlan_obj.esp_netif_STA != NULL) {
+ esp_netif_destroy(wlan_obj.esp_netif_STA);
+ wlan_obj.esp_netif_STA = NULL;
+ }
+ // Unregister event handler
+ esp_event_handler_unregister(IP_EVENT, IP_EVENT_STA_GOT_IP, wlan_event_handler);
+ esp_event_handler_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, wlan_event_handler);
+
+ // Deinitialize Wifi
esp_wifi_deinit();
// Only free up memory area of country information if this deinit is not called from machine.sleep()
if(called_from_sleep == false) {
@@ -1691,22 +1729,31 @@ STATIC mp_obj_t wlan_ifconfig (mp_uint_t n_args, const mp_obj_t *pos_args, mp_ma
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(args), wlan_ifconfig_args, args);
// check the interface id
- tcpip_adapter_if_t adapter_if;
+ esp_interface_t interface_id;
+ esp_netif_t * esp_netif_interface;
if (args[0].u_int > 1) {
- nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable));
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_AttributeError, "Invalid interface ID!"));
} else if (args[0].u_int == 0) {
- adapter_if = TCPIP_ADAPTER_IF_STA;
+ if(wlan_obj.esp_netif_STA == NULL) {
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_AttributeError, "The STA interface has not been initialized!"));
+ }
+ esp_netif_interface = wlan_obj.esp_netif_STA;
+ interface_id = ESP_IF_WIFI_STA;
} else {
- adapter_if = TCPIP_ADAPTER_IF_AP;
+ if(wlan_obj.esp_netif_AP == NULL) {
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_AttributeError, "The AP interface has not been initialized!"));
+ }
+ esp_netif_interface = wlan_obj.esp_netif_AP;
+ interface_id = ESP_IF_WIFI_AP;
}
- tcpip_adapter_dns_info_t dns_info;
+ esp_netif_dns_info_t dns_info;
// get the configuration
if (args[1].u_obj == MP_OBJ_NULL) {
// get
- tcpip_adapter_ip_info_t ip_info;
- tcpip_adapter_get_dns_info(adapter_if, TCPIP_ADAPTER_DNS_MAIN, &dns_info);
- if (ESP_OK == tcpip_adapter_get_ip_info(adapter_if, &ip_info)) {
+ esp_netif_ip_info_t ip_info;
+ esp_netif_get_dns_info(esp_netif_interface, ESP_NETIF_DNS_MAIN, &dns_info);
+ if (ESP_OK == esp_netif_get_ip_info(esp_netif_interface, &ip_info)) {
mp_obj_t ifconfig[4] = {
netutils_format_ipv4_addr((uint8_t *)&ip_info.ip.addr, NETUTILS_BIG),
netutils_format_ipv4_addr((uint8_t *)&ip_info.netmask.addr, NETUTILS_BIG),
@@ -1723,21 +1770,17 @@ STATIC mp_obj_t wlan_ifconfig (mp_uint_t n_args, const mp_obj_t *pos_args, mp_ma
mp_obj_t *items;
mp_obj_get_array_fixed_n(args[1].u_obj, 4, &items);
- tcpip_adapter_ip_info_t ip_info;
+ esp_netif_ip_info_t ip_info;
netutils_parse_ipv4_addr(items[0], (uint8_t *)&ip_info.ip.addr, NETUTILS_BIG);
netutils_parse_ipv4_addr(items[1], (uint8_t *)&ip_info.netmask.addr, NETUTILS_BIG);
netutils_parse_ipv4_addr(items[2], (uint8_t *)&ip_info.gw.addr, NETUTILS_BIG);
netutils_parse_ipv4_addr(items[3], (uint8_t *)&dns_info.ip, NETUTILS_BIG);
- if (adapter_if == TCPIP_ADAPTER_IF_STA) {
- tcpip_adapter_dhcpc_stop(TCPIP_ADAPTER_IF_STA);
- tcpip_adapter_set_ip_info(adapter_if, &ip_info);
- tcpip_adapter_set_dns_info(adapter_if, TCPIP_ADAPTER_DNS_MAIN, &dns_info);
- } else {
- tcpip_adapter_dhcps_stop(TCPIP_ADAPTER_IF_AP);
- tcpip_adapter_set_ip_info(adapter_if, &ip_info);
- tcpip_adapter_set_dns_info(adapter_if, TCPIP_ADAPTER_DNS_MAIN, &dns_info);
- tcpip_adapter_dhcps_start(TCPIP_ADAPTER_IF_AP);
+ esp_netif_dhcpc_stop(esp_netif_interface);
+ esp_netif_set_ip_info(esp_netif_interface, &ip_info);
+ esp_netif_set_dns_info(esp_netif_interface, ESP_NETIF_DNS_MAIN, &dns_info);
+ if (interface_id == ESP_IF_WIFI_AP) {
+ esp_netif_dhcps_start(esp_netif_interface);
}
} else {
// check for the correct string
@@ -1746,12 +1789,12 @@ STATIC mp_obj_t wlan_ifconfig (mp_uint_t n_args, const mp_obj_t *pos_args, mp_ma
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
}
- if (ESP_OK != tcpip_adapter_dhcpc_start(adapter_if)) {
+ if (ESP_OK != esp_netif_dhcpc_start(esp_netif_interface)) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_operation_failed));
}
}
- return mp_const_none;
}
+ return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(wlan_ifconfig_obj, 1, wlan_ifconfig);
@@ -1998,13 +2041,13 @@ STATIC mp_obj_t wlan_ap_tcpip_sta_list (mp_obj_t self_in) {
uint8_t index;
wifi_sta_list_t wifi_sta_list;
esp_wifi_ap_get_sta_list(&wifi_sta_list);
- tcpip_adapter_sta_list_t sta_list;
+ esp_netif_sta_list_t sta_list;
wlan_obj_t * self = self_in;
mp_obj_t sta_out_list = mp_obj_new_list(0, NULL);
/* Check if AP mode is enabled */
if (self->mode == WIFI_MODE_AP || self->mode == WIFI_MODE_APSTA) {
- tcpip_adapter_get_sta_list(&wifi_sta_list, &sta_list);
+ esp_netif_get_sta_list(&wifi_sta_list, &sta_list);
mp_obj_t tuple[2];
for(index = 0; index < MAX_AP_CONNECTED_STA && index < sta_list.num; index++)
@@ -2793,8 +2836,8 @@ const mod_network_nic_type_t mod_network_nic_type_wlan = {
.n_settimeout = lwipsocket_socket_settimeout,
.n_ioctl = lwipsocket_socket_ioctl,
.n_setupssl = lwipsocket_socket_setup_ssl,
- .inf_up = wlan_is_inf_up,
- .set_default_inf = wlan_set_default_inf
+ .inf_up = wlan_is_inf_up,
+ .set_default_inf = wlan_set_default_inf
};
//STATIC const mp_irq_methods_t wlan_irq_methods = {
diff --git a/esp32/mods/modwlan.h b/esp32/mods/modwlan.h
index 97f572b15f..747e48393f 100644
--- a/esp32/mods/modwlan.h
+++ b/esp32/mods/modwlan.h
@@ -10,7 +10,8 @@
#ifndef MODWLAN_H_
#define MODWLAN_H_
-#include
+#include "esp_netif.h"
+#include "modnetwork.h"
/******************************************************************************
DEFINE CONSTANTS
@@ -67,9 +68,9 @@ typedef struct _wlan_obj_t {
uint32_t ip;
- int8_t mode;
+ wifi_mode_t mode;
int8_t bandwidth;
- uint8_t auth;
+ wifi_auth_mode_t auth;
uint8_t channel;
uint8_t antenna;
int8_t max_tx_pwr;
@@ -100,6 +101,8 @@ typedef struct _wlan_obj_t {
mp_obj_t handler;
mp_obj_t handler_arg;
SemaphoreHandle_t mutex;
+ esp_netif_t * esp_netif_AP;
+ esp_netif_t * esp_netif_STA;
} wlan_obj_t;
typedef struct wlan_internal_prom_t
@@ -112,12 +115,12 @@ typedef struct wlan_internal_prom_t
#pragma pack(1)
typedef struct wlan_internal_setup_t
{
- int32_t mode;
+ wifi_mode_t mode;
const char * ssid_sta;
const char * key_sta;
const char * ssid_ap;
const char * key_ap;
- uint32_t auth;
+ wifi_auth_mode_t auth;
uint32_t channel;
uint32_t antenna;
bool add_mac;
diff --git a/esp32/mods/pybadc.c b/esp32/mods/pybadc.c
index 1f442fe2c9..37f7ab1750 100644
--- a/esp32/mods/pybadc.c
+++ b/esp32/mods/pybadc.c
@@ -22,7 +22,7 @@
#include "esp_types.h"
#include "esp_attr.h"
-#include "esp_intr.h"
+#include "esp_intr_alloc.h"
#include "soc/dport_reg.h"
#include "soc/gpio_sig_map.h"
diff --git a/esp32/mods/pybflash.c b/esp32/mods/pybflash.c
index 4ddecff888..9aa7c60b99 100644
--- a/esp32/mods/pybflash.c
+++ b/esp32/mods/pybflash.c
@@ -71,12 +71,12 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_3(pyb_flash_writeblocks_obj, pyb_flash_writeblock
STATIC mp_obj_t pyb_flash_ioctl(mp_obj_t self, mp_obj_t cmd_in, mp_obj_t arg_in) {
mp_int_t cmd = mp_obj_get_int(cmd_in);
switch (cmd) {
- case BP_IOCTL_INIT: return MP_OBJ_NEW_SMALL_INT(sflash_disk_init() != RES_OK);
- case BP_IOCTL_DEINIT: sflash_disk_flush(); return MP_OBJ_NEW_SMALL_INT(0);
- case BP_IOCTL_SYNC: sflash_disk_flush(); return MP_OBJ_NEW_SMALL_INT(0);
- case BP_IOCTL_SEC_COUNT:
+ case MP_BLOCKDEV_IOCTL_INIT: return MP_OBJ_NEW_SMALL_INT(sflash_disk_init() != RES_OK);
+ case MP_BLOCKDEV_IOCTL_DEINIT: sflash_disk_flush(); return MP_OBJ_NEW_SMALL_INT(0);
+ case MP_BLOCKDEV_IOCTL_SYNC: sflash_disk_flush(); return MP_OBJ_NEW_SMALL_INT(0);
+ case MP_BLOCKDEV_IOCTL_BLOCK_COUNT:
return (spi_flash_get_chip_size() > (4 * 1024 * 1024)) ? MP_OBJ_NEW_SMALL_INT(SFLASH_FS_SECTOR_COUNT_8MB) : MP_OBJ_NEW_SMALL_INT(SFLASH_FS_SECTOR_COUNT_4MB);
- case BP_IOCTL_SEC_SIZE: return MP_OBJ_NEW_SMALL_INT(SFLASH_FS_SECTOR_SIZE);
+ case MP_BLOCKDEV_IOCTL_BLOCK_SIZE: return MP_OBJ_NEW_SMALL_INT(SFLASH_FS_SECTOR_SIZE);
default: return mp_const_none;
}
}
@@ -99,16 +99,16 @@ const mp_obj_type_t pyb_flash_type = {
void pyb_flash_init_vfs(fs_user_mount_t *vfs) {
vfs->base.type = &mp_fat_vfs_type;
- vfs->flags |= FSUSER_NATIVE | FSUSER_HAVE_IOCTL;
+ vfs->blockdev.flags |= FSUSER_NATIVE | FSUSER_HAVE_IOCTL;
vfs->fs.fatfs.drv = vfs;
- vfs->readblocks[0] = (mp_obj_t)&pyb_flash_readblocks_obj;
- vfs->readblocks[1] = (mp_obj_t)&pyb_flash_obj;
- vfs->readblocks[2] = (mp_obj_t)sflash_disk_read; // native version
- vfs->writeblocks[0] = (mp_obj_t)&pyb_flash_writeblocks_obj;
- vfs->writeblocks[1] = (mp_obj_t)&pyb_flash_obj;
- vfs->writeblocks[2] = (mp_obj_t)sflash_disk_write; // native version
- vfs->u.ioctl[0] = (mp_obj_t)&pyb_flash_ioctl_obj;
- vfs->u.ioctl[1] = (mp_obj_t)&pyb_flash_obj;
+ vfs->blockdev.readblocks[0] = (mp_obj_t)&pyb_flash_readblocks_obj;
+ vfs->blockdev.readblocks[1] = (mp_obj_t)&pyb_flash_obj;
+ vfs->blockdev.readblocks[2] = (mp_obj_t)sflash_disk_read; // native version
+ vfs->blockdev.writeblocks[0] = (mp_obj_t)&pyb_flash_writeblocks_obj;
+ vfs->blockdev.writeblocks[1] = (mp_obj_t)&pyb_flash_obj;
+ vfs->blockdev.writeblocks[2] = (mp_obj_t)sflash_disk_write; // native version
+ vfs->blockdev.u.ioctl[0] = (mp_obj_t)&pyb_flash_ioctl_obj;
+ vfs->blockdev.u.ioctl[1] = (mp_obj_t)&pyb_flash_obj;
}
void pyb_flash_init_vfs_littlefs(fs_user_mount_t *vfs) {
diff --git a/esp32/mods/pybsd.c b/esp32/mods/pybsd.c
index c6b6c1bcf3..3f64c6bdc8 100644
--- a/esp32/mods/pybsd.c
+++ b/esp32/mods/pybsd.c
@@ -147,16 +147,16 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_3(pyb_sd_writeblocks_obj, pyb_sd_writeblocks);
STATIC mp_obj_t pyb_sd_ioctl(mp_obj_t self, mp_obj_t cmd_in, mp_obj_t arg_in) {
mp_int_t cmd = mp_obj_get_int(cmd_in);
switch (cmd) {
- case BP_IOCTL_INIT:
- case BP_IOCTL_DEINIT:
- case BP_IOCTL_SYNC:
+ case MP_BLOCKDEV_IOCTL_INIT:
+ case MP_BLOCKDEV_IOCTL_DEINIT:
+ case MP_BLOCKDEV_IOCTL_SYNC:
// nothing to do
return MP_OBJ_NEW_SMALL_INT(0); // success
- case BP_IOCTL_SEC_COUNT:
+ case MP_BLOCKDEV_IOCTL_BLOCK_COUNT:
return MP_OBJ_NEW_SMALL_INT(sdmmc_card_info.csd.capacity);
- case BP_IOCTL_SEC_SIZE:
+ case MP_BLOCKDEV_IOCTL_BLOCK_SIZE:
return MP_OBJ_NEW_SMALL_INT(sdmmc_card_info.csd.sector_size);
default: // unknown command
diff --git a/esp32/mptask.c b/esp32/mptask.c
index e5e89919d7..d664428b0b 100644
--- a/esp32/mptask.c
+++ b/esp32/mptask.c
@@ -19,7 +19,7 @@
#include "esp_err.h"
#include "esp_system.h"
#include "esp_wifi.h"
-#include "esp_event_loop.h"
+#include "esp_event.h"
#include "nvs_flash.h"
#include "esp_spi_flash.h"
#include "soc/cpu.h"
@@ -63,7 +63,7 @@
#endif
#include "random.h"
-#include "bootmgr.h"
+#include "pycom_bootloader.h"
#include "updater.h"
#include "pycom_config.h"
#include "mpsleep.h"
@@ -212,6 +212,9 @@ void TASK_Micropython (void *pvParameters) {
mach_timer_alarm_preinit();
pin_preinit();
+ //Init the esp_netif system
+ ESP_ERROR_CHECK(esp_netif_init());
+
soft_reset:
// thread init
@@ -422,7 +425,7 @@ STATIC void mptask_init_sflash_filesystem_fatfs(void) {
// Initialise the local flash filesystem.
// init the vfs object
fs_user_mount_t *vfs_fat = &sflash_vfs_flash;
- vfs_fat->flags = 0;
+ vfs_fat->blockdev.flags = 0;
pyb_flash_init_vfs(vfs_fat);
FILINFO fno;
@@ -677,7 +680,7 @@ STATIC void mptask_update_lpwan_mac_address (void) {
void mptask_config_wifi(bool force_start)
{
uint8_t mode = config_get_wifi_mode();
- uint8_t auth = config_get_wifi_auth();
+ wifi_auth_mode_t auth = (wifi_auth_mode_t)config_get_wifi_auth();
bool wifi_on_boot = config_get_wifi_on_boot();
bool antenna;
char ssid_station [33];
@@ -706,10 +709,13 @@ void mptask_config_wifi(bool force_start)
break;
}
- if(auth >= WIFI_AUTH_MAX)
+ // If "auth" is not configured, value 7 is returned because it is full of 1s
+ // Until WPA3 is not supported, using 3 bits in pycom_wifi_config_t for storing "auth" is okay
+ // If 4 bits will be used to store "auth", then (auth >= WIFI_AUTH_MAX) should be added back here
+ if(auth == 7)
{
- auth = (uint8_t)WIFI_AUTH_WPA2_PSK;
- config_set_wifi_auth(auth, true);
+ auth = WIFI_AUTH_WPA2_PSK;
+ config_set_wifi_auth((uint8_t)auth, true);
}
if(true == config_get_wifi_antenna())
{
@@ -753,7 +759,7 @@ void mptask_config_wifi(bool force_start)
pwd_sta,
ssid_ap,
pwd_ap,
- (uint32_t)auth,
+ auth,
0,
antenna,
true,
diff --git a/esp32/mpthreadport.c b/esp32/mpthreadport.c
index de383be612..c718a253a3 100644
--- a/esp32/mpthreadport.c
+++ b/esp32/mpthreadport.c
@@ -118,7 +118,7 @@ mp_state_thread_t *mp_thread_get_state(void) {
return pvTaskGetThreadLocalStoragePointer(NULL, 1);
}
-void mp_thread_set_state(void *state) {
+void mp_thread_set_state(mp_state_thread_t *state) {
vTaskSetThreadLocalStoragePointer(NULL, 1, state);
}
diff --git a/esp32/mpthreadport.h b/esp32/mpthreadport.h
index c54d0bc4a7..3f4c527223 100644
--- a/esp32/mpthreadport.h
+++ b/esp32/mpthreadport.h
@@ -39,7 +39,6 @@
#define __MICROPY_INCLUDED_ESP32_MPTHREADPORT_H__
#include "py/mpconfig.h"
-#include "py/mpstate.h"
#include "py/obj.h"
#include "freertos/FreeRTOS.h"
diff --git a/esp32/pycom_config.c b/esp32/pycom_config.c
index 74c75b5752..3eac4631ec 100644
--- a/esp32/pycom_config.c
+++ b/esp32/pycom_config.c
@@ -335,6 +335,11 @@ void config_get_pybytes_mqttServiceAddress (uint8_t *pybytes_mqttServiceAddress)
}
}
+bool config_set_pybytes_device_token (uint8_t *pybytes_device_token) {
+ memcpy( pycom_config_block.pybytes_config.device_token, pybytes_device_token, sizeof(pycom_config_block.pybytes_config.device_token));
+ return config_write();
+}
+
void config_get_pybytes_device_token (uint8_t *pybytes_device_token) {
memcpy( pybytes_device_token, pycom_config_block.pybytes_config.device_token, sizeof(pycom_config_block.pybytes_config.device_token));
if (pybytes_device_token[0]==0xff) {
@@ -355,6 +360,49 @@ void config_get_pybytes_extra_preferences (uint8_t *pybytes_extra_preferences) {
pybytes_extra_preferences[0]=0x0;
}
}
+
+bool config_set_pybytes_ota_status(uint8_t ota_status) {
+ pycom_config_block.pybytes_config.ota_status = ota_status;
+ return config_write();
+}
+
+uint8_t config_get_pybytes_ota_status(void) {
+ return pycom_config_block.pybytes_config.ota_status;
+}
+
+bool config_set_pybytes_sysname(uint8_t *sysname) {
+ memcpy(pycom_config_block.pybytes_config.sysname, sysname, sizeof(pycom_config_block.pybytes_config.sysname));
+ return config_write();
+}
+
+void config_get_pybytes_sysname(uint8_t *sysname) {
+ memcpy(sysname, pycom_config_block.pybytes_config.sysname, sizeof(pycom_config_block.pybytes_config.sysname));
+ if (sysname[0] == 0xff) {
+ sysname[0] = 0x0;
+ }
+}
+
+bool config_set_pybytes_fwtype(uint8_t fwtype) {
+ pycom_config_block.pybytes_config.fwtype = fwtype;
+ return config_write();
+}
+
+uint8_t config_get_pybytes_fwtype(void) {
+ return pycom_config_block.pybytes_config.fwtype;
+}
+
+bool config_set_sw_version (uint8_t *sw_version) {
+ memcpy(pycom_config_block.pycom_config.sw_version, sw_version, sizeof(pycom_config_block.pycom_config.sw_version));
+ return config_write();
+}
+
+void config_get_sw_version(uint8_t *sw_version) {
+ memcpy(sw_version, pycom_config_block.pycom_config.sw_version, sizeof(pycom_config_block.pycom_config.sw_version));
+ if (sw_version[0] == 0xff) {
+ sw_version[0] = 0x0;
+ }
+}
+
#endif
uint8_t config_get_boot_partition (void) {
@@ -413,3 +461,27 @@ static bool config_write (void) {
}
return false;
}
+
+bool config_set_rgb_led_on_boot (uint32_t new_color) {
+ uint32_t old_color =
+ (((pycom_config_block.rgbled_config.rgb_heartbeat_color[0]<<8) +
+ pycom_config_block.rgbled_config.rgb_heartbeat_color[1])<<8) +
+ pycom_config_block.rgbled_config.rgb_heartbeat_color[2];
+ if (old_color != new_color) {
+ pycom_config_block.rgbled_config.rgb_heartbeat_color[2] = new_color & 0xFF;
+ new_color >>= 8;
+ pycom_config_block.rgbled_config.rgb_heartbeat_color[1] = new_color & 0xFF;
+ new_color >>= 8;
+ pycom_config_block.rgbled_config.rgb_heartbeat_color[0] = new_color & 0xFF;
+ return config_write();
+ }
+ return true;
+}
+
+uint32_t config_get_rgb_led_on_boot (void) {
+ uint32_t old_color =
+ (((pycom_config_block.rgbled_config.rgb_heartbeat_color[0]<<8) +
+ pycom_config_block.rgbled_config.rgb_heartbeat_color[1])<<8) +
+ pycom_config_block.rgbled_config.rgb_heartbeat_color[2];
+ return old_color;
+}
diff --git a/esp32/pycom_config.h b/esp32/pycom_config.h
index 9c23f5ae17..e58da0dd39 100644
--- a/esp32/pycom_config.h
+++ b/esp32/pycom_config.h
@@ -25,6 +25,12 @@
/******************************************************************************
DEFINE CONSTANTS
******************************************************************************/
+#define OTA_STATUS_SUCCESS 0
+#define OTA_STATUS_FAILURE 1
+#define OTA_STATUS_PENDING 2
+
+#define FW_TYPE_PYBYTES 0
+#define FW_TYPE_PYMESH 1
/******************************************************************************
DEFINE TYPES
@@ -77,7 +83,10 @@ typedef struct {
uint8_t extra_preferences[100];
uint8_t force_update;
uint8_t auto_start;
- uint8_t reserved[11];
+ uint8_t ota_status; // Current status of OTA Update. Can be SUCCESS(0), FAILURE(1) or PENDING(2)
+ uint8_t sysname[6]; // sysname parameter used to request a new firmware e.g. LoPy4
+ uint8_t fwtype; // Type of the requested firmware. Should be 1 if pymesh firmware is to be requested
+ uint8_t reserved[3];
} pycom_pybytes_config_t;
_Static_assert(sizeof(pycom_pybytes_config_t) == 348, "pycom_pybytes_config_t should have a size of 348 bytes");
@@ -108,7 +117,7 @@ typedef struct {
uint8_t band;
uint8_t reset;
} pycom_pybytes_lte_config_t;
-// pycom_pybytes_lte_config_t is the last used member of pycom_config_block_t, so no _Static_assert(sizeof()) needed
+_Static_assert(sizeof(pycom_pybytes_lte_config_t) == 278, "pycom_pybytes_lte_config_t should have a size of 278 bytes");
typedef struct { // size
pycom_lpwan_config_t lpwan_config; // 53
@@ -185,7 +194,7 @@ bool config_set_wdt_on_boot_timeout (uint32_t wdt_on_boot_timeout);
uint32_t config_get_wdt_on_boot_timeout (void);
-bool config_set_heartbeat_on_boot(uint8_t wifi_on_boot);
+bool config_set_heartbeat_on_boot(uint8_t hb_on_boot);
bool config_get_heartbeat_on_boot(void);
@@ -209,6 +218,8 @@ bool config_set_lora_region (uint8_t lora_region);
uint8_t config_get_lora_region (void);
+bool config_set_pybytes_device_token (uint8_t *pybytes_device_token);
+
void config_get_pybytes_device_token (uint8_t *pybytes_device_token);
void config_get_pybytes_mqttServiceAddress (uint8_t *pybytes_mqttServiceAddress);
@@ -223,6 +234,23 @@ void config_get_pybytes_extra_preferences (uint8_t *pybytes_userId);
bool config_set_pybytes_force_update (uint8_t force_update);
bool config_get_pybytes_force_update (void);
+
+bool config_set_pybytes_ota_status (uint8_t ota_status);
+
+uint8_t config_get_pybytes_ota_status (void);
+
+bool config_set_pybytes_sysname(uint8_t *sysname);
+
+void config_get_pybytes_sysname(uint8_t *sysname);
+
+bool config_set_pybytes_fwtype(uint8_t fwtype);
+
+uint8_t config_get_pybytes_fwtype(void);
+
+bool config_set_sw_version (uint8_t *sw_version);
+
+void config_get_sw_version (uint8_t *sw_version);
+
#endif
uint8_t config_get_boot_fs_type (void);
@@ -245,4 +273,8 @@ bool config_set_pybytes_autostart (bool pybytes_autostart);
bool config_get_pybytes_autostart (void);
+bool config_set_rgb_led_on_boot (uint32_t new_color);
+
+uint32_t config_get_rgb_led_on_boot (void);
+
#endif /* PYCOM_CONFIG_H_ */
diff --git a/esp32/pycom_version.h b/esp32/pycom_version.h
index b85d758bb1..596de86ae5 100644
--- a/esp32/pycom_version.h
+++ b/esp32/pycom_version.h
@@ -10,7 +10,7 @@
#ifndef VERSION_H_
#define VERSION_H_
-#define SW_VERSION_NUMBER "1.20.2.r3"
+#define SW_VERSION_NUMBER "1.20.3.b3"
#define LORAWAN_VERSION_NUMBER "1.0.2"
diff --git a/esp32/sdkconfig.h b/esp32/sdkconfig.h
index 225893c051..53c3c88026 100644
--- a/esp32/sdkconfig.h
+++ b/esp32/sdkconfig.h
@@ -1,331 +1,539 @@
/*
- *
- * Automatically generated file; DO NOT EDIT.
- * Espressif IoT Development Framework Configuration
- *
+ * Automatically generated file. DO NOT EDIT.
+ * Espressif IoT Development Framework (ESP-IDF) Configuration Header
*/
-#define CONFIG_GATTC_ENABLE 1
-#define CONFIG_ESP32_PHY_MAX_TX_POWER 20
-#define CONFIG_TRACEMEM_RESERVE_DRAM 0x0
-#define CONFIG_FREERTOS_MAX_TASK_NAME_LEN 16
-#define CONFIG_SECURE_BOOT_SIGNING_KEY "secure_boot_signing_key.pem"
-#define CONFIG_BLE_SMP_ENABLE 1
-#define CONFIG_FATFS_LFN_NONE 1
-#define CONFIG_SPIRAM_TYPE_AUTO 1
-#define CONFIG_SMP_SLAVE_CON_PARAMS_UPD_ENABLE 1
-#define CONFIG_MB_SERIAL_TASK_PRIO 10
-#define CONFIG_TCP_RECVMBOX_SIZE 6
-#define CONFIG_FATFS_CODEPAGE_437 1
-#define CONFIG_LWIP_ETHARP_TRUST_IP_MAC 1
-#define CONFIG_BLE_SCAN_DUPLICATE 1
-#define CONFIG_TCP_WND_DEFAULT 5744
+#pragma once
+#define CONFIG_IDF_TARGET "esp32"
+#define CONFIG_IDF_TARGET_ESP32 1
+#define CONFIG_IDF_FIRMWARE_CHIP_ID 0x0000
+#define CONFIG_SDK_TOOLPREFIX "xtensa-esp32-elf-"
+#define CONFIG_SDK_PYTHON "python"
+#define CONFIG_SDK_MAKE_WARN_UNDEFINED_VARIABLES 1
+#define CONFIG_APP_BUILD_TYPE_APP_2NDBOOT 1
+#define CONFIG_APP_BUILD_GENERATE_BINARIES 1
+#define CONFIG_APP_BUILD_BOOTLOADER 1
+#define CONFIG_APP_BUILD_USE_FLASH_SECTIONS 1
+#define CONFIG_APP_COMPILE_TIME_DATE 1
+#define CONFIG_APP_EXCLUDE_PROJECT_VER_VAR 1
+#define CONFIG_APP_EXCLUDE_PROJECT_NAME_VAR 1
+#define CONFIG_APP_RETRIEVE_LEN_ELF_SHA 16
+#define CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE 1
+#define CONFIG_BOOTLOADER_LOG_LEVEL_NONE 1
+#define CONFIG_BOOTLOADER_LOG_LEVEL 0
+#define CONFIG_BOOTLOADER_SPI_WP_PIN 7
+#define CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_9V 1
+#define CONFIG_BOOTLOADER_WDT_ENABLE 1
+#define CONFIG_BOOTLOADER_WDT_TIME_MS 9000
+#define CONFIG_BOOTLOADER_RESERVE_RTC_SIZE 0x0
+#define CONFIG_ESPTOOLPY_PORT "/dev/ttyUSB0"
+#define CONFIG_ESPTOOLPY_BAUD_921600B 1
+#define CONFIG_ESPTOOLPY_BAUD_OTHER_VAL 115200
+#define CONFIG_ESPTOOLPY_BAUD 921600
+#define CONFIG_ESPTOOLPY_COMPRESSED 1
+#define CONFIG_ESPTOOLPY_FLASHMODE_QIO 1
+#define CONFIG_ESPTOOLPY_FLASHMODE "dio"
+#define CONFIG_ESPTOOLPY_FLASHFREQ_80M 1
+#define CONFIG_ESPTOOLPY_FLASHFREQ "80m"
+#define CONFIG_ESPTOOLPY_FLASHSIZE_4MB 1
+#define CONFIG_ESPTOOLPY_FLASHSIZE "4MB"
+#define CONFIG_ESPTOOLPY_FLASHSIZE_DETECT 1
#define CONFIG_ESPTOOLPY_BEFORE_NORESET 1
+#define CONFIG_ESPTOOLPY_BEFORE "no_reset"
+#define CONFIG_ESPTOOLPY_AFTER_NORESET 1
+#define CONFIG_ESPTOOLPY_AFTER "no_reset"
+#define CONFIG_ESPTOOLPY_MONITOR_BAUD_115200B 1
+#define CONFIG_ESPTOOLPY_MONITOR_BAUD_OTHER_VAL 115200
+#define CONFIG_ESPTOOLPY_MONITOR_BAUD 115200
+#define CONFIG_EXAMPLE_SCAN_LIST_SIZE 10
+#define CONFIG_PARTITION_TABLE_SINGLE_APP 1
+#define CONFIG_PARTITION_TABLE_CUSTOM_FILENAME "partitions.csv"
+#define CONFIG_PARTITION_TABLE_FILENAME "partitions_singleapp.csv"
#define CONFIG_PARTITION_TABLE_OFFSET 0x8000
-#define CONFIG_OPTIMIZATION_ASSERTIONS_SILENT 1
-#define CONFIG_SPIFFS_USE_MAGIC_LENGTH 1
-#define CONFIG_ESPTOOLPY_FLASHSIZE_4MB 1
-#define CONFIG_IPC_TASK_STACK_SIZE 1024
-#define CONFIG_WIFI_PROV_SCAN_MAX_ENTRIES 16
-#define CONFIG_FATFS_PER_FILE_CACHE 1
+#define CONFIG_COMPILER_OPTIMIZATION_SIZE 1
+#define CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT 1
+#define CONFIG_COMPILER_STACK_CHECK_MODE_NONE 1
+#define CONFIG_APPTRACE_DEST_NONE 1
+#define CONFIG_APPTRACE_LOCK_ENABLE 1
+#define CONFIG_BT_ENABLED 1
+#define CONFIG_BTDM_CTRL_MODE_BLE_ONLY 1
+#define CONFIG_BTDM_CTRL_BLE_MAX_CONN 3
+#define CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_EFF 0
+#define CONFIG_BTDM_CTRL_BLE_MAX_CONN_EFF 3
+#define CONFIG_BTDM_CTRL_BR_EDR_MAX_ACL_CONN_EFF 0
+#define CONFIG_BTDM_CTRL_BR_EDR_MAX_SYNC_CONN_EFF 0
+#define CONFIG_BTDM_CTRL_PINNED_TO_CORE_0 1
+#define CONFIG_BTDM_CTRL_PINNED_TO_CORE 0
+#define CONFIG_BTDM_CTRL_HCI_MODE_VHCI 1
+#define CONFIG_BTDM_MODEM_SLEEP 1
+#define CONFIG_BTDM_MODEM_SLEEP_MODE_ORIG 1
+#define CONFIG_BTDM_LPCLK_SEL_MAIN_XTAL 1
+#define CONFIG_BTDM_BLE_DEFAULT_SCA_250PPM 1
+#define CONFIG_BTDM_BLE_SLEEP_CLOCK_ACCURACY_INDEX_EFF 1
+#define CONFIG_BTDM_BLE_SCAN_DUPL 1
+#define CONFIG_BTDM_SCAN_DUPL_TYPE_DATA_DEVICE 1
+#define CONFIG_BTDM_SCAN_DUPL_TYPE 2
+#define CONFIG_BTDM_SCAN_DUPL_CACHE_SIZE 20
+#define CONFIG_BTDM_BLE_MESH_SCAN_DUPL_EN 1
+#define CONFIG_BTDM_MESH_DUPL_SCAN_CACHE_SIZE 200
+#define CONFIG_BTDM_CTRL_FULL_SCAN_SUPPORTED 1
+#define CONFIG_BTDM_BLE_ADV_REPORT_FLOW_CTRL_SUPP 1
+#define CONFIG_BTDM_BLE_ADV_REPORT_FLOW_CTRL_NUM 100
+#define CONFIG_BTDM_BLE_ADV_REPORT_DISCARD_THRSHOLD 20
+#define CONFIG_BT_BLUEDROID_ENABLED 1
+#define CONFIG_BT_BTC_TASK_STACK_SIZE 3328
+#define CONFIG_BT_BLUEDROID_PINNED_TO_CORE_0 1
+#define CONFIG_BT_BLUEDROID_PINNED_TO_CORE 0
+#define CONFIG_BT_BTU_TASK_STACK_SIZE 4512
+#define CONFIG_BT_BLE_ENABLED 1
+#define CONFIG_BT_GATTS_ENABLE 1
+#define CONFIG_BT_GATTS_SEND_SERVICE_CHANGE_MANUAL 1
+#define CONFIG_BT_GATTS_SEND_SERVICE_CHANGE_MODE 1
+#define CONFIG_BT_GATTC_ENABLE 1
+#define CONFIG_BT_BLE_SMP_ENABLE 1
+#define CONFIG_BT_SMP_SLAVE_CON_PARAMS_UPD_ENABLE 1
+#define CONFIG_BT_STACK_NO_LOG 1
+#define CONFIG_BT_ACL_CONNECTIONS 4
+#define CONFIG_BT_ALLOCATION_FROM_SPIRAM_FIRST 1
#define CONFIG_BT_BLE_DYNAMIC_ENV_MEMORY 1
-#define CONFIG_ESPTOOLPY_FLASHFREQ "80m"
-#define CONFIG_MBEDTLS_KEY_EXCHANGE_RSA 1
-#define CONFIG_UDP_RECVMBOX_SIZE 6
-#define CONFIG_FREERTOS_QUEUE_REGISTRY_SIZE 0
-#define CONFIG_MBEDTLS_AES_C 1
-#define CONFIG_MBEDTLS_ECP_DP_SECP521R1_ENABLED 1
-#define CONFIG_ESP32_WIFI_SOFTAP_BEACON_MAX_LEN 752
-#define CONFIG_MBEDTLS_GCM_C 1
-#define CONFIG_ESPTOOLPY_FLASHSIZE "4MB"
-#define CONFIG_HEAP_POISONING_DISABLED 1
-#define CONFIG_SPIFFS_CACHE_WR 1
+#define CONFIG_BT_BLE_HOST_QUEUE_CONG_CHECK 1
+#define CONFIG_BT_SMP_ENABLE 1
+#define CONFIG_BT_BLE_ACT_SCAN_REP_ADV_SCAN 1
+#define CONFIG_BT_BLE_ESTAB_LINK_CONN_TOUT 30
+#define CONFIG_BT_RESERVE_DRAM 0xdb5c
+#define CONFIG_BLE_MESH 1
+#define CONFIG_BLE_MESH_HCI_5_0 1
+#define CONFIG_BLE_MESH_USE_DUPLICATE_SCAN 1
+#define CONFIG_BLE_MESH_NODE 1
+#define CONFIG_BLE_MESH_PROV 1
+#define CONFIG_BLE_MESH_PB_ADV 1
+#define CONFIG_BLE_MESH_PB_GATT 1
+#define CONFIG_BLE_MESH_PROXY 1
+#define CONFIG_BLE_MESH_GATT_PROXY_SERVER 1
+#define CONFIG_BLE_MESH_NODE_ID_TIMEOUT 60
+#define CONFIG_BLE_MESH_PROXY_FILTER_SIZE 1
+#define CONFIG_BLE_MESH_NET_BUF_POOL_USAGE 1
+#define CONFIG_BLE_MESH_SUBNET_COUNT 3
+#define CONFIG_BLE_MESH_APP_KEY_COUNT 3
+#define CONFIG_BLE_MESH_MODEL_KEY_COUNT 3
+#define CONFIG_BLE_MESH_MODEL_GROUP_COUNT 3
+#define CONFIG_BLE_MESH_LABEL_COUNT 3
+#define CONFIG_BLE_MESH_CRPL 10
+#define CONFIG_BLE_MESH_MSG_CACHE_SIZE 10
+#define CONFIG_BLE_MESH_ADV_BUF_COUNT 60
+#define CONFIG_BLE_MESH_IVU_DIVIDER 4
+#define CONFIG_BLE_MESH_TX_SEG_MSG_COUNT 10
+#define CONFIG_BLE_MESH_RX_SEG_MSG_COUNT 10
+#define CONFIG_BLE_MESH_RX_SDU_MAX 384
+#define CONFIG_BLE_MESH_TX_SEG_MAX 20
+#define CONFIG_BLE_MESH_RELAY 1
+#define CONFIG_BLE_MESH_RELAY_ADV_BUF 1
+#define CONFIG_BLE_MESH_RELAY_ADV_BUF_COUNT 60
+#define CONFIG_BLE_MESH_NO_LOG 1
+#define CONFIG_BLE_MESH_CLIENT_MSG_TIMEOUT 4000
+#define CONFIG_BLE_MESH_CFG_CLI 1
+#define CONFIG_BLE_MESH_HEALTH_CLI 1
+#define CONFIG_BLE_MESH_GENERIC_ONOFF_CLI 1
+#define CONFIG_BLE_MESH_GENERIC_LEVEL_CLI 1
+#define CONFIG_BLE_MESH_SENSOR_CLI 1
+#define CONFIG_COAP_MBEDTLS_PSK 1
+#define CONFIG_COAP_LOG_DEFAULT_LEVEL 0
+#define CONFIG_ADC_DISABLE_DAC 1
+#define CONFIG_SPI_MASTER_ISR_IN_IRAM 1
+#define CONFIG_SPI_SLAVE_IN_IRAM 1
+#define CONFIG_SPI_SLAVE_ISR_IN_IRAM 1
+#define CONFIG_EFUSE_CODE_SCHEME_COMPAT_3_4 1
+#define CONFIG_EFUSE_MAX_BLK_LEN 192
+#define CONFIG_ESP_TLS_USING_MBEDTLS 1
+#define CONFIG_ESP32_REV_MIN_0 1
+#define CONFIG_ESP32_REV_MIN 0
+#define CONFIG_ESP32_DPORT_WORKAROUND 1
+#define CONFIG_ESP32_DEFAULT_CPU_FREQ_160 1
+#define CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ 160
+#define CONFIG_ESP32_SPIRAM_SUPPORT 1
+#define CONFIG_SPIRAM_TYPE_AUTO 1
+#define CONFIG_SPIRAM_SIZE -1
+#define CONFIG_SPIRAM_SPEED_40M 1
+#define CONFIG_SPIRAM 1
+#define CONFIG_SPIRAM_BOOT_INIT 1
+#define CONFIG_SPIRAM_USE_MALLOC 1
+#define CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL 16384
+#define CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP 1
+#define CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL 16384
+#define CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY 1
#define CONFIG_SPIRAM_CACHE_WORKAROUND 1
+#define CONFIG_SPIRAM_CACHE_WORKAROUND_STRATEGY_MEMW 1
+#define CONFIG_D0WD_PSRAM_CLK_IO 17
#define CONFIG_D0WD_PSRAM_CS_IO 16
-#define CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER 1
-#define CONFIG_EMAC_L2_TO_L3_RX_BUF_MODE 1
-#define CONFIG_BTDM_CONTROLLER_MODEM_SLEEP 1
-#define CONFIG_SPIFFS_CACHE 1
-#define CONFIG_BTDM_CONTROLLER_BLE_MAX_CONN 3
-
-#define CONFIG_MBEDTLS_SSL_PROTO_TLS1 1
-#define CONFIG_BT_STACK_NO_LOG 1
-#define CONFIG_MBEDTLS_ECDSA_C 1
-#define CONFIG_HTTPD_MAX_REQ_HDR_LEN 512
-#define CONFIG_BTDM_CONTROLLER_PINNED_TO_CORE 0
-#define CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS 2
-#define CONFIG_MBEDTLS_ECDH_C 1
-#define CONFIG_ESP32_ENABLE_COREDUMP_TO_UART 1
-#define CONFIG_MBEDTLS_KEY_EXCHANGE_ELLIPTIC_CURVE 1
-#define CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM 8
-#define CONFIG_MBEDTLS_SSL_ALPN 1
-#define CONFIG_MBEDTLS_PEM_WRITE_C 1
-#define CONFIG_BT_RESERVE_DRAM 0xdb5c
-#define CONFIG_APP_COMPILE_TIME_DATE 1
-#define CONFIG_SECURE_SIGNED_ON_BOOT 1
#define CONFIG_D2WD_PSRAM_CLK_IO 9
-#define CONFIG_FATFS_FS_LOCK 0
-#define CONFIG_IP_LOST_TIMER_INTERVAL 120
-#define CONFIG_SPIFFS_META_LENGTH 4
+#define CONFIG_D2WD_PSRAM_CS_IO 10
+#define CONFIG_PICO_PSRAM_CS_IO 16
+#define CONFIG_ESP32_TRACEMEM_RESERVE_DRAM 0x0
+#define CONFIG_ESP32_UNIVERSAL_MAC_ADDRESSES_FOUR 1
+#define CONFIG_ESP32_UNIVERSAL_MAC_ADDRESSES 4
+#define CONFIG_ESP32_ULP_COPROC_RESERVE_MEM 0
#define CONFIG_ESP32_PANIC_PRINT_REBOOT 1
-#define CONFIG_MB_CONTROLLER_NOTIFY_QUEUE_SIZE 0
-#define CONFIG_MBEDTLS_ECP_DP_BP384R1_ENABLED 1
-#define CONFIG_MBEDTLS_ECP_DP_SECP256K1_ENABLED 1
+#define CONFIG_ESP32_DEBUG_OCDAWARE 1
+#define CONFIG_ESP32_BROWNOUT_DET 1
+#define CONFIG_ESP32_BROWNOUT_DET_LVL_SEL_2 1
+#define CONFIG_ESP32_BROWNOUT_DET_LVL 2
+#define CONFIG_ESP32_REDUCE_PHY_TX_POWER 1
+#define CONFIG_ESP32_TIME_SYSCALL_USE_RTC_FRC1 1
+#define CONFIG_ESP32_RTC_CLK_SRC_INT_RC 1
+#define CONFIG_ESP32_RTC_CLK_CAL_CYCLES 1024
+#define CONFIG_ESP32_DEEP_SLEEP_WAKEUP_DELAY 2000
+#define CONFIG_ESP32_XTAL_FREQ_40 1
+#define CONFIG_ESP32_XTAL_FREQ 40
+#define CONFIG_ESP32_USE_FIXED_STATIC_RAM_SIZE 1
+#define CONFIG_ESP32_FIXED_STATIC_RAM_SIZE 0x2c200
#define CONFIG_ESP32_DPORT_DIS_INTERRUPT_LVL 5
-#define CONFIG_MB_SERIAL_BUF_SIZE 0
-#define CONFIG_CONSOLE_UART_BAUDRATE 115200
-#define CONFIG_SPIRAM_SUPPORT 1
-#define CONFIG_LWIP_MAX_SOCKETS 10
-#define CONFIG_LWIP_NETIF_LOOPBACK 1
-#define CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL 16384
-#define CONFIG_ESP32_PTHREAD_TASK_NAME_DEFAULT "pthread"
-#define CONFIG_EMAC_TASK_PRIORITY 20
-#define CONFIG_TIMER_TASK_STACK_DEPTH 2560
-#define CONFIG_TCP_MSS 1436
-#define CONFIG_MBEDTLS_ECP_DP_CURVE25519_ENABLED 1
-#define CONFIG_APP_EXCLUDE_PROJECT_NAME_VAR 1
-#define CONFIG_BTDM_CONTROLLER_BLE_MAX_CONN_EFF 3
-#define CONFIG_EFUSE_CODE_SCHEME_COMPAT_3_4 1
-#define CONFIG_TCPIP_TASK_AFFINITY_CPU0 1
-#define CONFIG_FATFS_CODEPAGE 437
-#define CONFIG_ESP32_DEFAULT_CPU_FREQ_160 1
-#define CONFIG_ULP_COPROC_RESERVE_MEM 0
-#define CONFIG_SECURE_SIGNED_APPS 1
-#define CONFIG_LWIP_MAX_UDP_PCBS 16
-#define CONFIG_ESPTOOLPY_BAUD 921600
+#define CONFIG_ESP32S2_TRACEMEM_RESERVE_DRAM 0x0
+#define CONFIG_ESP32S2_ULP_COPROC_RESERVE_MEM 0
+#define CONFIG_ESP32S2_DEBUG_OCDAWARE 1
+#define CONFIG_ESP32S2_BROWNOUT_DET 1
+#define CONFIG_ADC_CAL_EFUSE_TP_ENABLE 1
+#define CONFIG_ADC_CAL_EFUSE_VREF_ENABLE 1
#define CONFIG_ADC_CAL_LUT_ENABLE 1
-#define CONFIG_WIFI_FAST_SCAN 1
-#define CONFIG_LWIP_DHCPS_MAX_STATION_NUM 8
-#define CONFIG_TOOLPREFIX "xtensa-esp32-elf-"
-#define CONFIG_MBEDTLS_ECP_C 1
-#define CONFIG_FREERTOS_IDLE_TASK_STACKSIZE 1024
-#define CONFIG_MBEDTLS_RC4_DISABLED 1
-#define CONFIG_SPI_SLAVE_IN_IRAM 1
-#define CONFIG_CONSOLE_UART_NUM 0
-#define CONFIG_ESP32_APPTRACE_LOCK_ENABLE 1
-#define CONFIG_PTHREAD_STACK_MIN 768
-#define CONFIG_ESP32_RTC_CLOCK_SOURCE_INTERNAL_RC 1
-#define CONFIG_TCP_OVERSIZE_MSS 1
-#define CONFIG_FOUR_UNIVERSAL_MAC_ADDRESS 1
-#define CONFIG_CONSOLE_UART_DEFAULT 1
-#define CONFIG_MBEDTLS_SSL_MAX_CONTENT_LEN 16384
-#define CONFIG_NUMBER_OF_UNIVERSAL_MAC_ADDRESS 4
-#define CONFIG_ENABLE_STATIC_TASK_CLEAN_UP_HOOK 1
-#define CONFIG_ESPTOOLPY_FLASHSIZE_DETECT 1
-#define CONFIG_PPP_CHAP_SUPPORT 1
-#define CONFIG_TIMER_TASK_STACK_SIZE 2560
-#define CONFIG_MBEDTLS_X509_CRL_PARSE_C 1
-#define CONFIG_MBEDTLS_EXTERNAL_MEM_ALLOC 1
-#define CONFIG_FREERTOS_CHECK_MUTEX_GIVEN_BY_OWNER 1
+#define CONFIG_ESP_SYSTEM_EVENT_QUEUE_SIZE 32
+#define CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE 2560
+#define CONFIG_ESP_MAIN_TASK_STACK_SIZE 4096
+#define CONFIG_ESP_IPC_TASK_STACK_SIZE 1024
+#define CONFIG_ESP_IPC_USES_CALLERS_PRIORITY 1
+#define CONFIG_ESP_TIMER_TASK_STACK_SIZE 2560
+#define CONFIG_ESP_MINIMAL_SHARED_STACK_SIZE 2048
+#define CONFIG_ESP_CONSOLE_UART_DEFAULT 1
+#define CONFIG_ESP_CONSOLE_UART_NUM 0
+#define CONFIG_ESP_CONSOLE_UART_BAUDRATE 115200
+#define CONFIG_ESP_INT_WDT 1
+#define CONFIG_ESP_INT_WDT_TIMEOUT_MS 800
+#define CONFIG_ESP_INT_WDT_CHECK_CPU1 1
+#define CONFIG_ETH_ENABLED 1
+#define CONFIG_ETH_USE_ESP32_EMAC 1
+#define CONFIG_ETH_PHY_INTERFACE_RMII 1
+#define CONFIG_ETH_RMII_CLK_INPUT 1
+#define CONFIG_ETH_RMII_CLK_IN_GPIO 0
+#define CONFIG_ETH_DMA_BUFFER_SIZE 512
+#define CONFIG_ETH_DMA_RX_BUFFER_NUM 10
+#define CONFIG_ETH_DMA_TX_BUFFER_NUM 10
+#define CONFIG_ETH_USE_SPI_ETHERNET 1
+#define CONFIG_ETH_SPI_ETHERNET_DM9051 1
+#define CONFIG_ESP_EVENT_POST_FROM_ISR 1
+#define CONFIG_ESP_EVENT_POST_FROM_IRAM_ISR 1
+#define CONFIG_HTTPD_MAX_REQ_HDR_LEN 512
+#define CONFIG_HTTPD_MAX_URI_LEN 512
+#define CONFIG_HTTPD_ERR_RESP_NO_DELAY 1
#define CONFIG_HTTPD_PURGE_BUF_LEN 32
-#define CONFIG_SCAN_DUPLICATE_BY_DEVICE_ADDR 1
-#define CONFIG_MB_SERIAL_TASK_STACK_SIZE 768
-#define CONFIG_GATTS_SEND_SERVICE_CHANGE_AUTO 1
-#define CONFIG_LWIP_DHCPS_LEASE_UNIT 60
-#define CONFIG_EFUSE_MAX_BLK_LEN 192
-#define CONFIG_SPIFFS_USE_MAGIC 1
-#define CONFIG_TCPIP_TASK_STACK_SIZE 3072
-#define CONFIG_BLUEDROID_PINNED_TO_CORE_0 1
-#define CONFIG_MAIN_TASK_STACK_SIZE 4096
-#define CONFIG_SPIFFS_PAGE_CHECK 1
-#define CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_0 1
-#define CONFIG_LWIP_MAX_ACTIVE_TCP 16
-#define CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES 1
-#define CONFIG_ESPTOOLPY_FLASHMODE "dio"
-#define CONFIG_BTC_TASK_STACK_SIZE 3328
-#define CONFIG_BLUEDROID_ENABLED 1
-#define CONFIG_NEWLIB_STDIN_LINE_ENDING_CR 1
-#define CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_RSA 1
-#define CONFIG_ESPTOOLPY_BEFORE "no_reset"
-#define CONFIG_ADC2_DISABLE_DAC 1
-#define CONFIG_BLE_ADV_REPORT_FLOW_CONTROL_NUM 100
-#define CONFIG_ESP32_REV_MIN_0 1
-#define CONFIG_LOG_DEFAULT_LEVEL 0
-#define CONFIG_FREERTOS_ASSERT_ON_UNTESTED_FUNCTION 1
-#define CONFIG_TIMER_QUEUE_LENGTH 10
-#define CONFIG_ESP32_REV_MIN 0
-#define CONFIG_GATTS_SEND_SERVICE_CHANGE_MODE 0
-#define CONFIG_MAKE_WARN_UNDEFINED_VARIABLES 1
-#define CONFIG_FATFS_TIMEOUT_MS 10000
-#define CONFIG_BOOTLOADER_SPI_WP_PIN 7
+#define CONFIG_ESP_NETIF_IP_LOST_TIMER_INTERVAL 120
+#define CONFIG_ESP_NETIF_TCPIP_LWIP 1
+#define CONFIG_ESP_NETIF_TCPIP_ADAPTER_COMPATIBLE_LAYER 1
+#define CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM 8
#define CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM 16
-#define CONFIG_ESP_HTTP_CLIENT_ENABLE_HTTPS 1
-#define CONFIG_MBEDTLS_CCM_C 1
-#define CONFIG_SPI_MASTER_ISR_IN_IRAM 1
-#define CONFIG_ESP32_PHY_MAX_WIFI_TX_POWER 20
-#define CONFIG_ESP32_RTC_CLK_CAL_CYCLES 1024
+#define CONFIG_ESP32_WIFI_STATIC_TX_BUFFER 1
+#define CONFIG_ESP32_WIFI_TX_BUFFER_TYPE 0
+#define CONFIG_ESP32_WIFI_STATIC_TX_BUFFER_NUM 16
+#define CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED 1
#define CONFIG_ESP32_WIFI_TX_BA_WIN 6
+#define CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED 1
+#define CONFIG_ESP32_WIFI_RX_BA_WIN 16
#define CONFIG_ESP32_WIFI_NVS_ENABLED 1
-#define CONFIG_MDNS_MAX_SERVICES 10
-#define CONFIG_IDF_TARGET_ESP32 1
-#define CONFIG_EMAC_CHECK_LINK_PERIOD_MS 2000
-#define CONFIG_BTDM_LPCLK_SEL_MAIN_XTAL 1
-#define CONFIG_MBEDTLS_ECP_DP_SECP224R1_ENABLED 1
-#define CONFIG_LWIP_SNTP_UPDATE_DELAY 3600000
-#define CONFIG_LIBSODIUM_USE_MBEDTLS_SHA 1
-#define CONFIG_DMA_RX_BUF_NUM 10
-#define CONFIG_MBEDTLS_ECP_DP_SECP384R1_ENABLED 1
-#define CONFIG_ESP32_ENABLE_COREDUMP 1
-#define CONFIG_TCP_SYNMAXRTX 6
-#define CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA 1
-#define CONFIG_BTDM_CONTROLLER_BR_EDR_MAX_SYNC_CONN_EFF 0
-#define CONFIG_PYTHON "python"
-#define CONFIG_MBEDTLS_ECP_NIST_OPTIM 1
-#define CONFIG_ESP32_TIME_SYSCALL_USE_RTC_FRC1 1
-#define CONFIG_ESPTOOLPY_COMPRESSED 1
-#define CONFIG_PARTITION_TABLE_FILENAME "partitions_singleapp.csv"
-#define CONFIG_MB_CONTROLLER_STACK_SIZE 0
-#define CONFIG_TCP_SND_BUF_DEFAULT 5744
-#define CONFIG_LWIP_DHCP_MAX_NTP_SERVERS 2
-#define CONFIG_TCP_MSL 60000
-#define CONFIG_MBEDTLS_SSL_PROTO_TLS1_1 1
-#define CONFIG_LWIP_SO_REUSE_RXTOALL 1
-#define CONFIG_MB_CONTROLLER_NOTIFY_TIMEOUT 20
-#define CONFIG_WIFI_SSID "myssid"
+#define CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_0 1
+#define CONFIG_ESP32_WIFI_SOFTAP_BEACON_MAX_LEN 752
#define CONFIG_ESP32_WIFI_MGMT_SBUF_NUM 32
-#define CONFIG_PARTITION_TABLE_SINGLE_APP 1
-#define CONFIG_SPIRAM_USE_MALLOC 1
-#define CONFIG_ESP32_WIFI_RX_BA_WIN 16
-#define CONFIG_MBEDTLS_X509_CSR_PARSE_C 1
-#define CONFIG_SPIFFS_USE_MTIME 1
-#define CONFIG_LWIP_DHCP_RESTORE_LAST_IP 1
-#define CONFIG_FLASHMODE_QIO 1
-#define CONFIG_PICO_PSRAM_CS_IO 16
-#define CONFIG_EMAC_TASK_STACK_SIZE 2000
-#define CONFIG_GATTC_CACHE_NVS_FLASH 1
-#define CONFIG_MB_QUEUE_LENGTH 0
-#define CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_RSA 1
-#define CONFIG_LWIP_DHCP_DOES_ARP_CHECK 1
-#define CONFIG_ESPTOOLPY_FLASHFREQ_80M 1
-#define CONFIG_PPP_SUPPORT 1
-#define CONFIG_SPIRAM_SPEED_40M 1
-#define CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE 2560
-#define CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_9V 1
-#define CONFIG_ESP32_DEEP_SLEEP_WAKEUP_DELAY 2000
-#define CONFIG_MBEDTLS_PEM_PARSE_C 1
-#define CONFIG_SPIFFS_GC_MAX_RUNS 10
-#define CONFIG_ESP32_APPTRACE_DEST_NONE 1
-#define CONFIG_SECURE_BOOTLOADER_KEY_ENCODING_256BIT 1
-#define CONFIG_MBEDTLS_SSL_PROTO_TLS1_2 1
-#define CONFIG_MBEDTLS_KEY_EXCHANGE_DHE_RSA 1
-#define CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM 32
-#define CONFIG_HTTPD_MAX_URI_LEN 512
-#define CONFIG_MBEDTLS_ECP_DP_BP256R1_ENABLED 1
-#define CONFIG_MBEDTLS_ECP_DP_SECP224K1_ENABLED 1
-#define CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ 160
-#define CONFIG_MBEDTLS_HARDWARE_AES 1
-#define CONFIG_FREERTOS_HZ 1000
+#define CONFIG_ESP32_WIFI_ENABLE_WPA3_SAE 1
#define CONFIG_ESP32_PHY_CALIBRATION_AND_DATA_STORAGE 1
-#define CONFIG_STACK_CHECK_NONE 1
-#define CONFIG_ADC_CAL_EFUSE_TP_ENABLE 1
-#define CONFIG_FREERTOS_ASSERT_FAIL_ABORT 1
-#define CONFIG_ESP32_XTAL_FREQ 40
-#define CONFIG_MONITOR_BAUD_115200B 1
-#define CONFIG_LOG_BOOTLOADER_LEVEL 0
-#define CONFIG_D2WD_PSRAM_CS_IO 10
-#define CONFIG_MBEDTLS_TLS_ENABLED 1
-#define CONFIG_LWIP_MAX_RAW_PCBS 16
-#define CONFIG_SPIRAM_IGNORE_NOTFOUND 1
-#define CONFIG_BTU_TASK_STACK_SIZE 4096
-#define CONFIG_SMP_ENABLE 1
-#define CONFIG_SPIRAM_SIZE -1
-#define CONFIG_FAST_SCAN_MINIMUM_SIGNAL -127
-#define CONFIG_MBEDTLS_SSL_SESSION_TICKETS 1
-#define CONFIG_SPIFFS_MAX_PARTITIONS 3
+#define CONFIG_ESP32_PHY_MAX_WIFI_TX_POWER 20
+#define CONFIG_ESP32_PHY_MAX_TX_POWER 20
+#define CONFIG_ESP32_ENABLE_COREDUMP_TO_UART 1
+#define CONFIG_ESP32_COREDUMP_DATA_FORMAT_ELF 1
+#define CONFIG_ESP32_COREDUMP_CHECKSUM_CRC32 1
+#define CONFIG_ESP32_ENABLE_COREDUMP 1
#define CONFIG_ESP32_CORE_DUMP_MAX_TASKS_NUM 64
-#define CONFIG_BTDM_CONTROLLER_PINNED_TO_CORE_0 1
-#define CONFIG_BLE_HOST_QUEUE_CONGESTION_CHECK 1
-#define CONFIG_MBEDTLS_SSL_RENEGOTIATION 1
#define CONFIG_ESP32_CORE_DUMP_UART_DELAY 0
-#define CONFIG_MB_EVENT_QUEUE_TIMEOUT 20
-#define CONFIG_ESPTOOLPY_BAUD_OTHER_VAL 115200
-#define CONFIG_PPP_MPPE_SUPPORT 1
-#define CONFIG_FAST_SCAN_THRESHOLD 1
-#define CONFIG_SECURE_BOOTLOADER_REFLASHABLE 1
-#define CONFIG_SPIFFS_OBJ_NAME_LEN 32
-#define CONFIG_ESP32_PTHREAD_TASK_PRIO_DEFAULT 5
-#define CONFIG_BTDM_CONTROLLER_BR_EDR_MAX_ACL_CONN_EFF 0
-#define CONFIG_LOG_BOOTLOADER_LEVEL_NONE 1
-#define CONFIG_TCPIP_RECVMBOX_SIZE 32
-#define CONFIG_BT_ALLOCATION_FROM_SPIRAM_FIRST 1
-#define CONFIG_TCP_MAXRTX 12
-#define CONFIG_ESPTOOLPY_AFTER "no_reset"
-#define CONFIG_TCPIP_TASK_AFFINITY 0x0
-#define CONFIG_LWIP_SO_REUSE 1
-#define CONFIG_EXAMPLE_OPEN 1
-#define CONFIG_ESP32_XTAL_FREQ_40 1
-#define CONFIG_BTDM_CONTROLLER_MODE_BLE_ONLY 1
-#define CONFIG_DMA_TX_BUF_NUM 10
-#define CONFIG_LWIP_MAX_LISTENING_TCP 16
+#define CONFIG_ESP32_CORE_DUMP_STACK_SIZE 0
+#define CONFIG_FATFS_CODEPAGE_437 1
+#define CONFIG_FATFS_CODEPAGE 437
+#define CONFIG_FATFS_LFN_NONE 1
+#define CONFIG_FATFS_FS_LOCK 0
+#define CONFIG_FATFS_TIMEOUT_MS 10000
+#define CONFIG_FATFS_PER_FILE_CACHE 1
+#define CONFIG_FATFS_ALLOC_PREFER_EXTRAM 1
+#define CONFIG_FMB_COMM_MODE_RTU_EN 1
+#define CONFIG_FMB_COMM_MODE_ASCII_EN 1
+#define CONFIG_FMB_MASTER_TIMEOUT_MS_RESPOND 150
+#define CONFIG_FMB_MASTER_DELAY_MS_CONVERT 200
+#define CONFIG_FMB_QUEUE_LENGTH 0
+#define CONFIG_FMB_SERIAL_TASK_STACK_SIZE 768
+#define CONFIG_FMB_SERIAL_BUF_SIZE 0
+#define CONFIG_FMB_SERIAL_ASCII_BITS_PER_SYMB 8
+#define CONFIG_FMB_SERIAL_ASCII_TIMEOUT_RESPOND_MS 1000
+#define CONFIG_FMB_SERIAL_TASK_PRIO 10
+#define CONFIG_FMB_CONTROLLER_NOTIFY_TIMEOUT 20
+#define CONFIG_FMB_CONTROLLER_NOTIFY_QUEUE_SIZE 0
+#define CONFIG_FMB_CONTROLLER_STACK_SIZE 0
+#define CONFIG_FMB_EVENT_QUEUE_TIMEOUT 20
+#define CONFIG_FMB_TIMER_GROUP 0
+#define CONFIG_FMB_TIMER_INDEX 0
+#define CONFIG_FREERTOS_NO_AFFINITY 0x7FFFFFFF
+#define CONFIG_FREERTOS_CORETIMER_0 1
+#define CONFIG_FREERTOS_HZ 1000
+#define CONFIG_FREERTOS_ASSERT_ON_UNTESTED_FUNCTION 1
+#define CONFIG_FREERTOS_CHECK_STACKOVERFLOW_CANARY 1
#define CONFIG_FREERTOS_INTERRUPT_BACKTRACE 1
-#define CONFIG_WL_SECTOR_SIZE 4096
-#define CONFIG_ESP32_DEBUG_OCDAWARE 1
+#define CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS 2
+#define CONFIG_FREERTOS_ASSERT_FAIL_ABORT 1
+#define CONFIG_FREERTOS_IDLE_TASK_STACKSIZE 1024
+#define CONFIG_FREERTOS_ISR_STACKSIZE 2560
+#define CONFIG_FREERTOS_MAX_TASK_NAME_LEN 16
+#define CONFIG_FREERTOS_SUPPORT_STATIC_ALLOCATION 1
+#define CONFIG_FREERTOS_ENABLE_STATIC_TASK_CLEAN_UP 1
+#define CONFIG_FREERTOS_TIMER_TASK_PRIORITY 10
+#define CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH 2560
+#define CONFIG_FREERTOS_TIMER_QUEUE_LENGTH 10
+#define CONFIG_FREERTOS_QUEUE_REGISTRY_SIZE 0
+#define CONFIG_FREERTOS_CHECK_MUTEX_GIVEN_BY_OWNER 1
+#define CONFIG_FREERTOS_DEBUG_OCDAWARE 1
+#define CONFIG_HEAP_POISONING_DISABLED 1
+#define CONFIG_HEAP_TRACING_OFF 1
+#define CONFIG_LIBSODIUM_USE_MBEDTLS_SHA 1
#define CONFIG_LOG_DEFAULT_LEVEL_NONE 1
-#define CONFIG_TIMER_TASK_PRIORITY 10
-#define CONFIG_PPP_PAP_SUPPORT 1
-#define CONFIG_MBEDTLS_TLS_CLIENT 1
-#define CONFIG_BTDM_CONTROLLER_HCI_MODE_VHCI 1
-#define CONFIG_BT_ENABLED 1
-#define CONFIG_ESP32_DEFAULT_PTHREAD_CORE_NO_AFFINITY 1
-#define CONFIG_D0WD_PSRAM_CLK_IO 17
-#define CONFIG_MBEDTLS_ECP_DP_SECP256R1_ENABLED 1
-#define CONFIG_MONITOR_BAUD 115200
-#define CONFIG_ESP32_PTHREAD_TASK_CORE_DEFAULT -1
-#define CONFIG_BLE_ESTABLISH_LINK_CONNECTION_TIMEOUT 30
-#define CONFIG_TCPIP_LWIP 1
-#define CONFIG_ESP_TCP_KEEP_CONNECTION_WHEN_IP_CHANGES 1
-#define CONFIG_WIFI_LWIP_ALLOCATION_FROM_SPIRAM_FIRST 1
-#define CONFIG_FREERTOS_CORETIMER_0 1
-#define CONFIG_IDF_FIRMWARE_CHIP_ID 0x0000
-#define CONFIG_PARTITION_TABLE_CUSTOM_FILENAME "partitions.csv"
+#define CONFIG_LOG_DEFAULT_LEVEL 0
+#define CONFIG_LOG_TIMESTAMP_SOURCE_RTOS 1
+#define CONFIG_LWIP_LOCAL_HOSTNAME "espressif"
+#define CONFIG_LWIP_DNS_SUPPORT_MDNS_QUERIES 1
+#define CONFIG_LWIP_TIMERS_ONDEMAND 1
+#define CONFIG_LWIP_MAX_SOCKETS 10
+#define CONFIG_LWIP_SO_REUSE 1
+#define CONFIG_LWIP_SO_REUSE_RXTOALL 1
+#define CONFIG_LWIP_SO_RCVBUF 1
+#define CONFIG_LWIP_ETHARP_TRUST_IP_MAC 1
+#define CONFIG_LWIP_TCPIP_RECVMBOX_SIZE 32
+#define CONFIG_LWIP_DHCP_DOES_ARP_CHECK 1
+#define CONFIG_LWIP_DHCP_RESTORE_LAST_IP 1
+#define CONFIG_LWIP_DHCPS_LEASE_UNIT 60
+#define CONFIG_LWIP_DHCPS_MAX_STATION_NUM 8
+#define CONFIG_LWIP_NETIF_LOOPBACK 1
+#define CONFIG_LWIP_LOOPBACK_MAX_PBUFS 8
+#define CONFIG_LWIP_MAX_ACTIVE_TCP 16
+#define CONFIG_LWIP_MAX_LISTENING_TCP 16
+#define CONFIG_LWIP_TCP_MAXRTX 12
+#define CONFIG_LWIP_TCP_SYNMAXRTX 6
+#define CONFIG_LWIP_TCP_MSS 1436
+#define CONFIG_LWIP_TCP_TMR_INTERVAL 250
+#define CONFIG_LWIP_TCP_MSL 60000
+#define CONFIG_LWIP_TCP_SND_BUF_DEFAULT 5744
+#define CONFIG_LWIP_TCP_WND_DEFAULT 5744
+#define CONFIG_LWIP_TCP_RECVMBOX_SIZE 6
+#define CONFIG_LWIP_TCP_QUEUE_OOSEQ 1
+#define CONFIG_LWIP_TCP_KEEP_CONNECTION_WHEN_IP_CHANGES 1
+#define CONFIG_LWIP_TCP_OVERSIZE_MSS 1
+#define CONFIG_LWIP_MAX_UDP_PCBS 16
+#define CONFIG_LWIP_UDP_RECVMBOX_SIZE 6
+#define CONFIG_LWIP_TCPIP_TASK_STACK_SIZE 3072
+#define CONFIG_LWIP_TCPIP_TASK_AFFINITY_CPU0 1
+#define CONFIG_LWIP_TCPIP_TASK_AFFINITY 0x0
+#define CONFIG_LWIP_PPP_SUPPORT 1
+#define CONFIG_LWIP_PPP_ENABLE_IPV6 1
+#define CONFIG_LWIP_PPP_PAP_SUPPORT 1
+#define CONFIG_LWIP_PPP_CHAP_SUPPORT 1
+#define CONFIG_LWIP_PPP_MSCHAP_SUPPORT 1
+#define CONFIG_LWIP_PPP_MPPE_SUPPORT 1
+#define CONFIG_LWIP_MAX_RAW_PCBS 16
+#define CONFIG_LWIP_DHCP_MAX_NTP_SERVERS 2
+#define CONFIG_LWIP_SNTP_UPDATE_DELAY 3600000
+#define CONFIG_MBEDTLS_EXTERNAL_MEM_ALLOC 1
+#define CONFIG_MBEDTLS_SSL_MAX_CONTENT_LEN 16384
+#define CONFIG_MBEDTLS_HARDWARE_AES 1
#define CONFIG_MBEDTLS_HAVE_TIME 1
-#define CONFIG_FREERTOS_CHECK_STACKOVERFLOW_CANARY 1
-#define CONFIG_TCP_QUEUE_OOSEQ 1
-#define CONFIG_FATFS_ALLOC_PREFER_EXTRAM 1
-#define CONFIG_GATTS_ENABLE 1
-#define CONFIG_ADC_CAL_EFUSE_VREF_ENABLE 1
-#define CONFIG_MBEDTLS_TLS_SERVER 1
#define CONFIG_MBEDTLS_TLS_SERVER_AND_CLIENT 1
-#define CONFIG_APP_EXCLUDE_PROJECT_VER_VAR 1
-#define CONFIG_SPIRAM_BOOT_INIT 1
-#define CONFIG_ESPTOOLPY_AFTER_NORESET 1
-#define CONFIG_BLE_ADV_REPORT_FLOW_CONTROL_SUPPORTED 1
-#define CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL 16384
-#define CONFIG_FREERTOS_ISR_STACKSIZE 2560
-#define CONFIG_OPENSSL_ASSERT_DO_NOTHING 1
-#define CONFIG_IDF_TARGET "esp32"
-#define CONFIG_WL_SECTOR_SIZE_4096 1
-#define CONFIG_FREERTOS_NO_AFFINITY 0x7FFFFFFF
-#define CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED 1
-#define CONFIG_HTTPD_ERR_RESP_NO_DELAY 1
-#define CONFIG_SCAN_DUPLICATE_TYPE 0
+#define CONFIG_MBEDTLS_TLS_SERVER 1
+#define CONFIG_MBEDTLS_TLS_CLIENT 1
+#define CONFIG_MBEDTLS_TLS_ENABLED 1
+#define CONFIG_MBEDTLS_PSK_MODES 1
+#define CONFIG_MBEDTLS_KEY_EXCHANGE_PSK 1
+#define CONFIG_MBEDTLS_KEY_EXCHANGE_DHE_PSK 1
+#define CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_PSK 1
+#define CONFIG_MBEDTLS_KEY_EXCHANGE_RSA_PSK 1
+#define CONFIG_MBEDTLS_KEY_EXCHANGE_RSA 1
+#define CONFIG_MBEDTLS_KEY_EXCHANGE_DHE_RSA 1
+#define CONFIG_MBEDTLS_KEY_EXCHANGE_ELLIPTIC_CURVE 1
+#define CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_RSA 1
+#define CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA 1
+#define CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA 1
+#define CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_RSA 1
+#define CONFIG_MBEDTLS_SSL_RENEGOTIATION 1
+#define CONFIG_MBEDTLS_SSL_PROTO_TLS1 1
+#define CONFIG_MBEDTLS_SSL_PROTO_TLS1_1 1
+#define CONFIG_MBEDTLS_SSL_PROTO_TLS1_2 1
+#define CONFIG_MBEDTLS_SSL_PROTO_DTLS 1
+#define CONFIG_MBEDTLS_SSL_ALPN 1
+#define CONFIG_MBEDTLS_CLIENT_SSL_SESSION_TICKETS 1
+#define CONFIG_MBEDTLS_SERVER_SSL_SESSION_TICKETS 1
+#define CONFIG_MBEDTLS_AES_C 1
+#define CONFIG_MBEDTLS_RC4_DISABLED 1
+#define CONFIG_MBEDTLS_CCM_C 1
+#define CONFIG_MBEDTLS_GCM_C 1
+#define CONFIG_MBEDTLS_PEM_PARSE_C 1
+#define CONFIG_MBEDTLS_PEM_WRITE_C 1
+#define CONFIG_MBEDTLS_X509_CRL_PARSE_C 1
+#define CONFIG_MBEDTLS_X509_CSR_PARSE_C 1
+#define CONFIG_MBEDTLS_ECP_C 1
+#define CONFIG_MBEDTLS_ECDH_C 1
+#define CONFIG_MBEDTLS_ECDSA_C 1
#define CONFIG_MBEDTLS_ECP_DP_SECP192R1_ENABLED 1
+#define CONFIG_MBEDTLS_ECP_DP_SECP224R1_ENABLED 1
+#define CONFIG_MBEDTLS_ECP_DP_SECP256R1_ENABLED 1
+#define CONFIG_MBEDTLS_ECP_DP_SECP384R1_ENABLED 1
+#define CONFIG_MBEDTLS_ECP_DP_SECP521R1_ENABLED 1
+#define CONFIG_MBEDTLS_ECP_DP_SECP192K1_ENABLED 1
+#define CONFIG_MBEDTLS_ECP_DP_SECP224K1_ENABLED 1
+#define CONFIG_MBEDTLS_ECP_DP_SECP256K1_ENABLED 1
+#define CONFIG_MBEDTLS_ECP_DP_BP256R1_ENABLED 1
+#define CONFIG_MBEDTLS_ECP_DP_BP384R1_ENABLED 1
#define CONFIG_MBEDTLS_ECP_DP_BP512R1_ENABLED 1
-#define CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA 1
-#define CONFIG_SPI_SLAVE_ISR_IN_IRAM 1
-#define CONFIG_WIFI_CONNECT_AP_BY_SIGNAL 1
-#define CONFIG_WIFI_PASSWORD "mypassword"
-#define CONFIG_SYSTEM_EVENT_QUEUE_SIZE 32
-#define CONFIG_BT_ACL_CONNECTIONS 4
-#define CONFIG_ESP32_WIFI_TX_BUFFER_TYPE 1
-#define CONFIG_SUPPORT_STATIC_ALLOCATION 1
-#define CONFIG_ESPTOOLPY_BAUD_921600B 1
-#define CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED 1
-#define CONFIG_LWIP_LOOPBACK_MAX_PBUFS 8
+#define CONFIG_MBEDTLS_ECP_DP_CURVE25519_ENABLED 1
+#define CONFIG_MBEDTLS_ECP_NIST_OPTIM 1
+#define CONFIG_MDNS_MAX_SERVICES 10
+#define CONFIG_MDNS_TASK_PRIORITY 1
+#define CONFIG_MDNS_TASK_AFFINITY_CPU0 1
+#define CONFIG_MDNS_TASK_AFFINITY 0x0
+#define CONFIG_MDNS_SERVICE_ADD_TIMEOUT_MS 2000
+#define CONFIG_MDNS_TIMER_PERIOD_MS 100
+#define CONFIG_NEWLIB_STDOUT_LINE_ENDING_CRLF 1
+#define CONFIG_NEWLIB_STDIN_LINE_ENDING_CR 1
+#define CONFIG_OPENSSL_ASSERT_DO_NOTHING 1
+#define CONFIG_PTHREAD_TASK_PRIO_DEFAULT 5
+#define CONFIG_PTHREAD_TASK_STACK_SIZE_DEFAULT 2048
+#define CONFIG_PTHREAD_STACK_MIN 768
+#define CONFIG_PTHREAD_DEFAULT_CORE_NO_AFFINITY 1
+#define CONFIG_PTHREAD_TASK_CORE_DEFAULT -1
+#define CONFIG_PTHREAD_TASK_NAME_DEFAULT "pthread"
#define CONFIG_SPI_FLASH_ROM_DRIVER_PATCH 1
+#define CONFIG_SPI_FLASH_DANGEROUS_WRITE_ABORTS 1
+#define CONFIG_SPI_FLASH_USE_LEGACY_IMPL 1
+#define CONFIG_SPI_FLASH_YIELD_DURING_ERASE 1
+#define CONFIG_SPI_FLASH_ERASE_YIELD_DURATION_MS 20
+#define CONFIG_SPI_FLASH_ERASE_YIELD_TICKS 1
+#define CONFIG_SPI_FLASH_SUPPORT_ISSI_CHIP 1
+#define CONFIG_SPI_FLASH_SUPPORT_GD_CHIP 1
+#define CONFIG_SPIFFS_MAX_PARTITIONS 3
+#define CONFIG_SPIFFS_CACHE 1
+#define CONFIG_SPIFFS_CACHE_WR 1
+#define CONFIG_SPIFFS_PAGE_CHECK 1
+#define CONFIG_SPIFFS_GC_MAX_RUNS 10
#define CONFIG_SPIFFS_PAGE_SIZE 256
-#define CONFIG_SECURE_SIGNED_ON_UPDATE 1
-#define CONFIG_MBEDTLS_ECP_DP_SECP192K1_ENABLED 1
-#define CONFIG_ESP32_DPORT_WORKAROUND 1
-#define CONFIG_PPP_MSCHAP_SUPPORT 1
-#define CONFIG_ESP32_PTHREAD_TASK_STACK_SIZE_DEFAULT 2048
-#define CONFIG_LWIP_SO_RCVBUF 1
-#define CONFIG_DUPLICATE_SCAN_CACHE_SIZE 20
-#define CONFIG_MONITOR_BAUD_OTHER_VAL 115200
-#define CONFIG_NEWLIB_STDOUT_LINE_ENDING_CRLF 1
-#define CONFIG_ESPTOOLPY_PORT "/dev/ttyUSB0"
-#define CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ABORTS 1
-#define CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_EFF 0
-#define CONFIG_OPTIMIZATION_LEVEL_RELEASE 1
-#define CONFIG_BLE_ADV_REPORT_DISCARD_THRSHOLD 20
-#define CONFIG_BLUEDROID_PINNED_TO_CORE 0
-#define CONFIG_BTDM_MODEM_SLEEP_MODE_ORIG 1
+#define CONFIG_SPIFFS_OBJ_NAME_LEN 32
+#define CONFIG_SPIFFS_USE_MAGIC 1
+#define CONFIG_SPIFFS_USE_MAGIC_LENGTH 1
+#define CONFIG_SPIFFS_META_LENGTH 4
+#define CONFIG_SPIFFS_USE_MTIME 1
+#define CONFIG_UNITY_ENABLE_FLOAT 1
+#define CONFIG_UNITY_ENABLE_DOUBLE 1
+#define CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER 1
+#define CONFIG_SEMIHOSTFS_MAX_MOUNT_POINTS 1
+#define CONFIG_SEMIHOSTFS_HOST_PATH_MAX_LEN 128
+#define CONFIG_WL_SECTOR_SIZE_4096 1
+#define CONFIG_WL_SECTOR_SIZE 4096
+#define CONFIG_WIFI_PROV_SCAN_MAX_ENTRIES 16
+#define CONFIG_WIFI_PROV_AUTOSTOP_TIMEOUT 30
+#define CONFIG_WPA_MBEDTLS_CRYPTO 1
+#define CONFIG_PYCOM_RGB_LED_PIN 0
+
+/* List of deprecated options */
+#define CONFIG_ADC2_DISABLE_DAC CONFIG_ADC_DISABLE_DAC
+#define CONFIG_BLE_ACTIVE_SCAN_REPORT_ADV_SCAN_RSP_INDIVIDUALLY CONFIG_BT_BLE_ACT_SCAN_REP_ADV_SCAN
+#define CONFIG_BLE_ADV_REPORT_DISCARD_THRSHOLD CONFIG_BTDM_BLE_ADV_REPORT_DISCARD_THRSHOLD
+#define CONFIG_BLE_ADV_REPORT_FLOW_CONTROL_NUM CONFIG_BTDM_BLE_ADV_REPORT_FLOW_CTRL_NUM
+#define CONFIG_BLE_ADV_REPORT_FLOW_CONTROL_SUPPORTED CONFIG_BTDM_BLE_ADV_REPORT_FLOW_CTRL_SUPP
+#define CONFIG_BLE_ESTABLISH_LINK_CONNECTION_TIMEOUT CONFIG_BT_BLE_ESTAB_LINK_CONN_TOUT
+#define CONFIG_BLE_HOST_QUEUE_CONGESTION_CHECK CONFIG_BT_BLE_HOST_QUEUE_CONG_CHECK
+#define CONFIG_BLE_MESH_GATT_PROXY CONFIG_BLE_MESH_GATT_PROXY_SERVER
+#define CONFIG_BLE_MESH_SCAN_DUPLICATE_EN CONFIG_BTDM_BLE_MESH_SCAN_DUPL_EN
+#define CONFIG_BLE_SCAN_DUPLICATE CONFIG_BTDM_BLE_SCAN_DUPL
+#define CONFIG_BLE_SMP_ENABLE CONFIG_BT_BLE_SMP_ENABLE
+#define CONFIG_BLUEDROID_ENABLED CONFIG_BT_BLUEDROID_ENABLED
+#define CONFIG_BLUEDROID_PINNED_TO_CORE_0 CONFIG_BT_BLUEDROID_PINNED_TO_CORE_0
+#define CONFIG_BROWNOUT_DET CONFIG_ESP32_BROWNOUT_DET
+#define CONFIG_BROWNOUT_DET_LVL_SEL_2 CONFIG_ESP32_BROWNOUT_DET_LVL_SEL_2
+#define CONFIG_BTC_TASK_STACK_SIZE CONFIG_BT_BTC_TASK_STACK_SIZE
+#define CONFIG_BTDM_CONTROLLER_BLE_MAX_CONN CONFIG_BTDM_CTRL_BLE_MAX_CONN
+#define CONFIG_BTDM_CONTROLLER_FULL_SCAN_SUPPORTED CONFIG_BTDM_CTRL_FULL_SCAN_SUPPORTED
+#define CONFIG_BTDM_CONTROLLER_HCI_MODE_VHCI CONFIG_BTDM_CTRL_HCI_MODE_VHCI
+#define CONFIG_BTDM_CONTROLLER_MODEM_SLEEP CONFIG_BTDM_MODEM_SLEEP
+#define CONFIG_BTDM_CONTROLLER_MODE_BLE_ONLY CONFIG_BTDM_CTRL_MODE_BLE_ONLY
+#define CONFIG_BTU_TASK_STACK_SIZE CONFIG_BT_BTU_TASK_STACK_SIZE
+#define CONFIG_COMPILER_OPTIMIZATION_LEVEL_RELEASE CONFIG_COMPILER_OPTIMIZATION_SIZE
+#define CONFIG_CONSOLE_UART_BAUDRATE CONFIG_ESP_CONSOLE_UART_BAUDRATE
+#define CONFIG_CONSOLE_UART_DEFAULT CONFIG_ESP_CONSOLE_UART_DEFAULT
+#define CONFIG_DUPLICATE_SCAN_CACHE_SIZE CONFIG_BTDM_SCAN_DUPL_CACHE_SIZE
+#define CONFIG_ENABLE_STATIC_TASK_CLEAN_UP_HOOK CONFIG_FREERTOS_ENABLE_STATIC_TASK_CLEAN_UP
+#define CONFIG_ESP32_APPTRACE_DEST_NONE CONFIG_APPTRACE_DEST_NONE
+#define CONFIG_ESP32_DEFAULT_PTHREAD_CORE_NO_AFFINITY CONFIG_PTHREAD_DEFAULT_CORE_NO_AFFINITY
+#define CONFIG_ESP32_PTHREAD_STACK_MIN CONFIG_PTHREAD_STACK_MIN
+#define CONFIG_ESP32_PTHREAD_TASK_NAME_DEFAULT CONFIG_PTHREAD_TASK_NAME_DEFAULT
+#define CONFIG_ESP32_PTHREAD_TASK_PRIO_DEFAULT CONFIG_PTHREAD_TASK_PRIO_DEFAULT
+#define CONFIG_ESP32_PTHREAD_TASK_STACK_SIZE_DEFAULT CONFIG_PTHREAD_TASK_STACK_SIZE_DEFAULT
+#define CONFIG_ESP32_RTC_CLOCK_SOURCE_INTERNAL_RC CONFIG_ESP32_RTC_CLK_SRC_INT_RC
+#define CONFIG_ESP_TCP_KEEP_CONNECTION_WHEN_IP_CHANGES CONFIG_LWIP_TCP_KEEP_CONNECTION_WHEN_IP_CHANGES
+#define CONFIG_FLASHMODE_QIO CONFIG_ESPTOOLPY_FLASHMODE_QIO
+#define CONFIG_FOUR_UNIVERSAL_MAC_ADDRESS CONFIG_ESP32_UNIVERSAL_MAC_ADDRESSES_FOUR
+#define CONFIG_GATTC_ENABLE CONFIG_BT_GATTC_ENABLE
+#define CONFIG_GATTS_ENABLE CONFIG_BT_GATTS_ENABLE
+#define CONFIG_GATTS_SEND_SERVICE_CHANGE_MANUAL CONFIG_BT_GATTS_SEND_SERVICE_CHANGE_MANUAL
+#define CONFIG_INT_WDT CONFIG_ESP_INT_WDT
+#define CONFIG_INT_WDT_CHECK_CPU1 CONFIG_ESP_INT_WDT_CHECK_CPU1
+#define CONFIG_INT_WDT_TIMEOUT_MS CONFIG_ESP_INT_WDT_TIMEOUT_MS
+#define CONFIG_IPC_TASK_STACK_SIZE CONFIG_ESP_IPC_TASK_STACK_SIZE
+#define CONFIG_LOG_BOOTLOADER_LEVEL_NONE CONFIG_BOOTLOADER_LOG_LEVEL_NONE
+#define CONFIG_MAIN_TASK_STACK_SIZE CONFIG_ESP_MAIN_TASK_STACK_SIZE
+#define CONFIG_MAKE_WARN_UNDEFINED_VARIABLES CONFIG_SDK_MAKE_WARN_UNDEFINED_VARIABLES
+#define CONFIG_MB_CONTROLLER_NOTIFY_QUEUE_SIZE CONFIG_FMB_CONTROLLER_NOTIFY_QUEUE_SIZE
+#define CONFIG_MB_CONTROLLER_NOTIFY_TIMEOUT CONFIG_FMB_CONTROLLER_NOTIFY_TIMEOUT
+#define CONFIG_MB_CONTROLLER_STACK_SIZE CONFIG_FMB_CONTROLLER_STACK_SIZE
+#define CONFIG_MB_EVENT_QUEUE_TIMEOUT CONFIG_FMB_EVENT_QUEUE_TIMEOUT
+#define CONFIG_MB_MASTER_DELAY_MS_CONVERT CONFIG_FMB_MASTER_DELAY_MS_CONVERT
+#define CONFIG_MB_MASTER_TIMEOUT_MS_RESPOND CONFIG_FMB_MASTER_TIMEOUT_MS_RESPOND
+#define CONFIG_MB_QUEUE_LENGTH CONFIG_FMB_QUEUE_LENGTH
+#define CONFIG_MB_SERIAL_BUF_SIZE CONFIG_FMB_SERIAL_BUF_SIZE
+#define CONFIG_MB_SERIAL_TASK_PRIO CONFIG_FMB_SERIAL_TASK_PRIO
+#define CONFIG_MB_SERIAL_TASK_STACK_SIZE CONFIG_FMB_SERIAL_TASK_STACK_SIZE
+#define CONFIG_MB_TIMER_GROUP CONFIG_FMB_TIMER_GROUP
+#define CONFIG_MB_TIMER_INDEX CONFIG_FMB_TIMER_INDEX
+#define CONFIG_MESH_DUPLICATE_SCAN_CACHE_SIZE CONFIG_BTDM_MESH_DUPL_SCAN_CACHE_SIZE
+#define CONFIG_MONITOR_BAUD_115200B CONFIG_ESPTOOLPY_MONITOR_BAUD_115200B
+#define CONFIG_OPTIMIZATION_ASSERTIONS_SILENT CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT
+#define CONFIG_OPTIMIZATION_LEVEL_RELEASE CONFIG_COMPILER_OPTIMIZATION_SIZE
+#define CONFIG_POST_EVENTS_FROM_IRAM_ISR CONFIG_ESP_EVENT_POST_FROM_IRAM_ISR
+#define CONFIG_POST_EVENTS_FROM_ISR CONFIG_ESP_EVENT_POST_FROM_ISR
+#define CONFIG_PPP_CHAP_SUPPORT CONFIG_LWIP_PPP_CHAP_SUPPORT
+#define CONFIG_PPP_MPPE_SUPPORT CONFIG_LWIP_PPP_MPPE_SUPPORT
+#define CONFIG_PPP_MSCHAP_SUPPORT CONFIG_LWIP_PPP_MSCHAP_SUPPORT
+#define CONFIG_PPP_PAP_SUPPORT CONFIG_LWIP_PPP_PAP_SUPPORT
+#define CONFIG_PPP_SUPPORT CONFIG_LWIP_PPP_SUPPORT
+#define CONFIG_PYTHON CONFIG_SDK_PYTHON
+#define CONFIG_REDUCE_PHY_TX_POWER CONFIG_ESP32_REDUCE_PHY_TX_POWER
+#define CONFIG_SCAN_DUPLICATE_BY_ADV_DATA_AND_DEVICE_ADDR CONFIG_BTDM_SCAN_DUPL_TYPE_DATA_DEVICE
+#define CONFIG_SMP_SLAVE_CON_PARAMS_UPD_ENABLE CONFIG_BT_SMP_SLAVE_CON_PARAMS_UPD_ENABLE
+#define CONFIG_SPIRAM_SUPPORT CONFIG_ESP32_SPIRAM_SUPPORT
+#define CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ABORTS CONFIG_SPI_FLASH_DANGEROUS_WRITE_ABORTS
+#define CONFIG_STACK_CHECK_NONE CONFIG_COMPILER_STACK_CHECK_MODE_NONE
+#define CONFIG_SUPPORT_STATIC_ALLOCATION CONFIG_FREERTOS_SUPPORT_STATIC_ALLOCATION
+#define CONFIG_SYSTEM_EVENT_QUEUE_SIZE CONFIG_ESP_SYSTEM_EVENT_QUEUE_SIZE
+#define CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE
+#define CONFIG_TCPIP_RECVMBOX_SIZE CONFIG_LWIP_TCPIP_RECVMBOX_SIZE
+#define CONFIG_TCPIP_TASK_AFFINITY_CPU0 CONFIG_LWIP_TCPIP_TASK_AFFINITY_CPU0
+#define CONFIG_TCPIP_TASK_STACK_SIZE CONFIG_LWIP_TCPIP_TASK_STACK_SIZE
+#define CONFIG_TCP_MAXRTX CONFIG_LWIP_TCP_MAXRTX
+#define CONFIG_TCP_MSL CONFIG_LWIP_TCP_MSL
+#define CONFIG_TCP_MSS CONFIG_LWIP_TCP_MSS
+#define CONFIG_TCP_OVERSIZE_MSS CONFIG_LWIP_TCP_OVERSIZE_MSS
+#define CONFIG_TCP_QUEUE_OOSEQ CONFIG_LWIP_TCP_QUEUE_OOSEQ
+#define CONFIG_TCP_RECVMBOX_SIZE CONFIG_LWIP_TCP_RECVMBOX_SIZE
+#define CONFIG_TCP_SND_BUF_DEFAULT CONFIG_LWIP_TCP_SND_BUF_DEFAULT
+#define CONFIG_TCP_SYNMAXRTX CONFIG_LWIP_TCP_SYNMAXRTX
+#define CONFIG_TCP_WND_DEFAULT CONFIG_LWIP_TCP_WND_DEFAULT
+#define CONFIG_TIMER_QUEUE_LENGTH CONFIG_FREERTOS_TIMER_QUEUE_LENGTH
+#define CONFIG_TIMER_TASK_PRIORITY CONFIG_FREERTOS_TIMER_TASK_PRIORITY
+#define CONFIG_TIMER_TASK_STACK_DEPTH CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH
+#define CONFIG_TIMER_TASK_STACK_SIZE CONFIG_ESP_TIMER_TASK_STACK_SIZE
+#define CONFIG_TOOLPREFIX CONFIG_SDK_TOOLPREFIX
+#define CONFIG_UDP_RECVMBOX_SIZE CONFIG_LWIP_UDP_RECVMBOX_SIZE
+#define CONFIG_WIFI_LWIP_ALLOCATION_FROM_SPIRAM_FIRST CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP
diff --git a/esp32/sigfox/README b/esp32/sigfox/README
index 80418deb3d..932f00d7e7 100644
--- a/esp32/sigfox/README
+++ b/esp32/sigfox/README
@@ -1,16 +1,15 @@
This directory contains the sigfox support.
-There are three prebuilt libraries for SIPY, LOPY4, and FIPY.
+There are three prebuilt libraries for LOPY4 and FIPY.
@Pycom In order to build these libraries execute the following steps using the private pyupython repository:
-git clone -b sigfox git@github.com:pycom/pyupython.git src
+git clone -b sigfox_idf_4 git@github.com:pycom/pyupython.git src
cd src
-git checkout 9a5e7a9b
+git checkout 05d49f8f
cd ../..
make BOARD=LOPY4 TARGET=sigfox
make BOARD=FIPY TARGET=sigfox
-make BOARD=SIPY TARGET=sigfox
./get_sigfox_libs.py
Now you see the updated .a files with
diff --git a/esp32/sigfox/modsigfox_FIPY.a b/esp32/sigfox/modsigfox_FIPY.a
index d579f9a157..2ecb43fa95 100644
Binary files a/esp32/sigfox/modsigfox_FIPY.a and b/esp32/sigfox/modsigfox_FIPY.a differ
diff --git a/esp32/sigfox/modsigfox_LOPY4.a b/esp32/sigfox/modsigfox_LOPY4.a
index 34c56ab98e..1a4b6b282e 100644
Binary files a/esp32/sigfox/modsigfox_LOPY4.a and b/esp32/sigfox/modsigfox_LOPY4.a differ
diff --git a/esp32/telnet/telnet.c b/esp32/telnet/telnet.c
index 91972ecdfe..03fcf1f2f4 100644
--- a/esp32/telnet/telnet.c
+++ b/esp32/telnet/telnet.c
@@ -13,6 +13,7 @@
#include "py/mpconfig.h"
#include "py/obj.h"
#include "py/mphal.h"
+#include "py/runtime.h"
#include "readline.h"
#include "telnet.h"
#include "serverstask.h"
diff --git a/esp32/tools/fw_updater/esptool.py b/esp32/tools/fw_updater/esptool.py
index 7a462c99a4..39f8e24a19 100755
--- a/esp32/tools/fw_updater/esptool.py
+++ b/esp32/tools/fw_updater/esptool.py
@@ -187,6 +187,9 @@ def _set_port_baudrate(self, baud):
self._port.baudrate = baud
except IOError:
raise FatalError("Failed to set baud rate %d. The driver may not support this rate." % baud)
+
+ def disconnect(self):
+ self._port.close()
@staticmethod
def detect_chip(port=DEFAULT_PORT, baud=ESP_ROM_BAUD, connect_mode='default_reset'):
diff --git a/esp32/tools/fw_updater/updater.py b/esp32/tools/fw_updater/updater.py
old mode 100755
new mode 100644
index 401330c2cd..9aae306337
--- a/esp32/tools/fw_updater/updater.py
+++ b/esp32/tools/fw_updater/updater.py
@@ -7,26 +7,26 @@
# see the Pycom Licence v1.0 document supplied with this file, or
# available at https://www.pycom.io/opensource/licensing
-from __future__ import print_function
+
+
+from __future__ import print_function
+from esptool import ESP32ROM
+from io import BytesIO, StringIO
+from pypic import Pypic
+from traceback import print_exc
import argparse
import base64
import binascii
-from io import BytesIO, StringIO
+import esptool
import json
import os
import re
+import serial.tools.list_ports
import struct
import sys
import tarfile
import time
-from traceback import print_exc
-
-import serial.tools.list_ports
-
-from esptool import ESP32ROM
-import esptool
-from pypic import Pypic
try:
import humanfriendly
@@ -43,7 +43,7 @@
FAST_BAUD_RATE = 921600
MAXPICREAD_BAUD_RATE = 230400
-LORA_REGIONS = ["EU868", "US915", "AS923", "AU915", "IN865"]
+LORA_REGIONS = ["EU868", "US915", "AS923", "AU915", "IN865", "CN470", "EU433"]
PIC_BOARDS = ["04D8:F013", "04D8:F012", "04D8:EF98", "04D8:EF38", "04D8:ED14"]
@@ -537,7 +537,7 @@ def run_script(self, script, config_block=None, erase_fs=False, chip_id=None, ui
if erase_fs:
self.erase_fs(chip_id, ui_label=ui_label)
if erase_nvs:
- self.erase(int(PARTITIONS.get('nvs')[0], 16), int(PARTITIONS.get('nvs')[1], 16), ui_label=ui_label, updateList = True)
+ self.erase(int(PARTITIONS.get('nvs')[0], 16), int(PARTITIONS.get('nvs')[1], 16), ui_label=ui_label, updateList=True)
for instruction in script:
if instruction[0].split(':', 2)[0] == 'w' or instruction[0].split(':', 2)[0] == 'o':
@@ -747,10 +747,10 @@ def set_pycom_config(self, config_block, boot_fs_type=None):
if DEBUG:
self.print_cb(config_block)
if boot_fs_type is not None:
- if str(boot_fs_type) == 'LittleFS' or boot_fs_type == 1 or str(boot_fs_type) == '1':
- fs = b'\x01'
- else:
+ if str(boot_fs_type) == 'FatFS' or boot_fs_type == 1 or str(boot_fs_type) == '1':
fs = b'\x00'
+ else:
+ fs = b'\x01'
new_config_block = config_block[0:533] \
+fs \
@@ -758,7 +758,7 @@ def set_pycom_config(self, config_block, boot_fs_type=None):
if DEBUG:
self.print_cb(config_block)
if self.__resultUpdateList is not None:
- self.__resultUpdateList.append('File system type set to {}'.format('LittleFS' if (boot_fs_type == 'LittleFS' or boot_fs_type == 1 or boot_fs_type == '1') else 'FatFS'))
+ self.__resultUpdateList.append('File system type set to {}'.format('FatFS' if (boot_fs_type == 'FatFS' or boot_fs_type == 1 or boot_fs_type == '1') else 'LittleFS'))
return self.set_pybytes_config(new_config_block, force_update=True)
def print_cb(self, config_block):
@@ -871,28 +871,28 @@ def set_lpwan_config(self, config_block, lora_region=None):
def set_sigfox_config(self, config_block, sid=None, pac=None, pubkey=None, privkey=None):
config_block = config_block.ljust(int(PARTITIONS.get('config')[1], 16), b'\x00')
if sid is not None:
- if not len(sid)==8:
+ if not len(sid) == 8:
raise ValueError('ID must be 8 HEX characters')
sigid = bytearray.fromhex(sid).ljust(4, b'\x00')
else:
sigid = config_block[8:12]
if pac is not None:
- if not len(pac)==16:
+ if not len(pac) == 16:
raise ValueError('PAC must be 16 HEX characters')
spac = bytearray.fromhex(pac).ljust(8, b'\x00')
else:
spac = config_block[12:20]
if privkey is not None:
- if not len(privkey)==32:
+ if not len(privkey) == 32:
raise ValueError('private key must be 32 HEX characters')
sprivkey = bytearray.fromhex(privkey).ljust(16, b'\x00')
else:
sprivkey = config_block[20:36]
if pubkey is not None:
- if not len(pubkey)==32:
+ if not len(pubkey) == 32:
raise ValueError('public key must be 32 HEX characters')
spubkey = bytearray.fromhex(pubkey).ljust(16, b'\x00')
else:
@@ -901,12 +901,11 @@ def set_sigfox_config(self, config_block, sid=None, pac=None, pubkey=None, privk
new_config_block = config_block[0:8] \
+sigid \
+spac \
- + sprivkey \
- + spubkey \
+ +sprivkey \
+ +spubkey \
+config_block[52:]
return new_config_block
-
def read_mac(self):
# returns a tuple with (wifi_mac, bluetooth_mac)
return self.esp.read_mac()
@@ -921,7 +920,7 @@ def exit_pycom_programming_mode(self, reset=True):
if not self.__pypic:
self.esp.hard_reset()
time.sleep(.5)
- del self.esp
+ self.esp.disconnect()
if (self.__pypic):
pic = Pypic(self.esp_port)
if pic.isdetected():
@@ -1003,6 +1002,7 @@ def process_arguments():
cmd_parser_pycom = subparsers.add_parser('pycom', help='Check / Set pycom parameters')
cmd_parser_pycom.add_argument('--fs_type', default=None, help="Set the file system type ['FatFS' or 'LittleFS']")
+
cmd_parser_sigfox = subparsers.add_parser('sigfox', help='Show/Update sigfox details')
cmd_parser_sigfox.add_argument('--id', default=None, help='Update Sigfox id')
cmd_parser_sigfox.add_argument('--pac', default=None, help='Update Sigfox pac')
@@ -1039,7 +1039,7 @@ def process_arguments():
cmd_parser_wifi.add_argument('--ssid', default=None, help='Set Wifi SSID')
cmd_parser_wifi.add_argument('--pwd', default=None, help='Set Wifi PWD')
# This doesn't really work as we updated the field to a bitfield
- #cmd_parser_wifi.add_argument('--wob', type=str2bool, nargs='?', const=True, help='Set Wifi on boot')
+ # cmd_parser_wifi.add_argument('--wob', type=str2bool, nargs='?', const=True, help='Set Wifi on boot')
cmd_parser_pybytes = subparsers.add_parser('pybytes', help='Read/Write pybytes configuration')
cmd_parser_pybytes.add_argument('--token', default=None, help='Set Device Token')
@@ -1544,29 +1544,6 @@ def progress_fs(msg):
except:
print("WIFI_ON_BOOT=[not set]")
- elif args.command == 'pycom':
- config_block = nPy.read(int(PARTITIONS.get('config')[0], 16), int(PARTITIONS.get('config')[1], 16))
- nPy.print_cb(config_block)
- if (args.fs_type is not None):
- new_config_block = nPy.set_pycom_config(config_block, args.fs_type)
- nPy.print_cb(new_config_block)
- nPy.write(int(PARTITIONS.get('config')[0], 16), new_config_block)
- else:
- sys.stdout = old_stdout
- try:
- if sys.version_info[0] < 3:
- fs_type = config_block[533]
- else:
- fs_type = config_block[533].to_bytes(1, byteorder='little')
- if fs_type == (b'\x00'):
- print("fs_type=FatFS")
- if fs_type == (b'\x01'):
- print("fs_type=LittleFS")
- if fs_type == (b'\xff'):
- print("fs_type=[not set]")
- except:
- print("fs_type=[not set]")
-
elif args.command == 'pybytes':
config_block = nPy.read(int(PARTITIONS.get('config')[0], 16), int(PARTITIONS.get('config')[1], 16))
if (hasattr(args, "token") and args.token is not None) \
@@ -1612,6 +1589,29 @@ def progress_fs(msg):
print("EXTRAPREFS=%s" % pybytes_eprefs)
except:
print("EXTRAPREFS=[not set]")
+
+ elif args.command == 'pycom':
+ config_block = nPy.read(int(PARTITIONS.get('config')[0], 16), int(PARTITIONS.get('config')[1], 16))
+ nPy.print_cb(config_block)
+ if (args.fs_type is not None):
+ new_config_block = nPy.set_pycom_config(config_block, args.fs_type)
+ nPy.print_cb(new_config_block)
+ nPy.write(int(PARTITIONS.get('config')[0], 16), new_config_block)
+ else:
+ sys.stdout = old_stdout
+ try:
+ if sys.version_info[0] < 3:
+ fs_type = config_block[533]
+ else:
+ fs_type = config_block[533].to_bytes(1, byteorder='little')
+ if fs_type == (b'\x00'):
+ print("fs_type=FatFS")
+ if fs_type == (b'\x01'):
+ print("fs_type=LittleFS")
+ if fs_type == (b'\xff'):
+ print("fs_type=[not set]")
+ except:
+ print("fs_type=[not set]")
elif args.command == 'erase_fs':
diff --git a/esp32/tools/idfVerCheck.sh b/esp32/tools/idfVerCheck.sh
index 3323cb8e0e..8697583f79 100644
--- a/esp32/tools/idfVerCheck.sh
+++ b/esp32/tools/idfVerCheck.sh
@@ -26,7 +26,7 @@ You should probably update one (or multiple) of:
* IDF_PATH environment variable
* IDF_HASH variable in esp32/Makefile
* IDF commit, e.g.
-cd \$IDF_PATH && git checkout $IDF_HASH && git submodule sync && git submodule update --init --recursive && cd -
+cd \$IDF_PATH && git checkout $IDF_HASH && git submodule update --init --recursive && git clean -d -f -f && cd -
"
exit 1
diff --git a/esp32/tools/makepkg.sh b/esp32/tools/makepkg.sh
index b7f041f4c3..a9a1d35440 100755
--- a/esp32/tools/makepkg.sh
+++ b/esp32/tools/makepkg.sh
@@ -8,12 +8,22 @@ else
fi
BOARD=$(echo $1)
-if [ $4 ]; then
+FACTORY_BIN_DIR="$(pwd)/factory_fw/binary"
+
+if [ $4 -eq 1 ]; then
SCRIPT_NAME_4MB="script_4MB_enc"
- SCRIPT_NAME_8MB="script_8MB_enc"
+ if [ $5 -eq 1 ]; then
+ SCRIPT_NAME_8MB="script_8MB_small_factory_fw_enc"
+ else
+ SCRIPT_NAME_8MB='script_8MB_normal_factory_fw_enc'
+ fi
else
SCRIPT_NAME_4MB="script_4MB"
- SCRIPT_NAME_8MB="script_8MB"
+ if [ $5 -eq 1 ]; then
+ SCRIPT_NAME_8MB='script_8MB_small_factory_fw'
+ else
+ SCRIPT_NAME_8MB='script_8MB_normal_factory_fw'
+ fi
fi
if [ -z $1 ]; then echo >&2 "Invalid board name!"; exit 1; fi
if ! [ $0 = "tools/makepkg.sh" ]; then echo >&2 "Need to run as tools/makepkg.sh!"; exit 1; fi
@@ -23,13 +33,8 @@ if ! [ -r "pycom_version.h" ]; then echo >&2 "Cannot read pycom_version.h! Abort
if [ "${BOARD}" = "GPY" -o "${BOARD}" = "LOPY4" -o "${BOARD}" = "FIPY" ]; then
if ! [ -r "boards/$1/${SCRIPT_NAME_8MB}" ]; then echo >&2 "Cannot read boards/$1/${SCRIPT_NAME_8MB}! Aborting."; exit 1; fi
elif [ "${BOARD}" = "LOPY" -o "${BOARD}" = "WIPY" ]; then
- if ! [ -r "boards/$1/${SCRIPT_NAME_4MB}" ]; then echo >&2 "Cannot read boards/$1/${SCRIPT_NAME_4MB}! Aborting."; exit 1; fi
if ! [ -r "boards/$1/${SCRIPT_NAME_8MB}" ]; then echo >&2 "Cannot read boards/$1/${SCRIPT_NAME_8MB}! Aborting."; exit 1; fi
-else
- if ! [ -r "boards/$1/${SCRIPT_NAME_4MB}" ]; then echo >&2 "Cannot read boards/$1/${SCRIPT_NAME_4MB}! Aborting."; exit 1; fi
fi
-if ! [ -r "boards/$1/script" ]; then echo >&2 "Cannot read legacy boards/$1/script! Aborting."; exit 1; fi
-if ! [ -r "boards/$1/script2" ]; then echo >&2 "Cannot read legacy boards/$1/script2! Aborting."; exit 1; fi
if [ -z $2 ]; then
RELEASE_DIR="$(pwd)/${BUILD_DIR}"
@@ -52,64 +57,51 @@ VERSION=$(cat pycom_version.h |grep SW_VERSION_NUMBER | cut -d'"' -f2)
PKG_TMP_DIR="${BUILD_DIR}/firmware_package"
mkdir -p ${PKG_TMP_DIR}
-PART_FILE_4MB=''
PART_FILE_8MB=''
-SCRIPT_FILE_4MB=''
SCRIPT_FILE_8MB=''
-
-if [ $4 ]; then
+
+if [ $4 -eq 1 ]; then
BOOT_FILE='bootloader-reflash-digest.bin_enc'
APP_FILE="${BOARD_NAME_L}.bin_enc"
+ if [ $5 -eq 1 ]; then
+ FACTORY_FILE="factory_fw.bin"
+ fi
FILE_NAME="${BOARD_NAME}-${VERSION}_ENC.tar.gz"
else
BOOT_FILE='bootloader.bin'
APP_FILE="${BOARD_NAME_L}.bin"
+ if [ $5 -eq 1 ]; then
+ FACTORY_FILE="factory_fw.bin"
+ fi
FILE_NAME="$BOARD_NAME-$VERSION.tar.gz"
fi
cp ${BUILD_DIR}/bootloader/${BOOT_FILE} ${PKG_TMP_DIR}
cp ${BUILD_DIR}/${APP_FILE} ${PKG_TMP_DIR}
-if [ "${BOARD}" != "SIPY" ]; then
- if [ $4 ]; then
- PART_FILE_8MB='partitions_8MB.bin_enc'
- SCRIPT_FILE_8MB='script_8MB_enc'
+if [ $4 -eq 1 ]; then
+ SCRIPT_FILE_8MB='script_8MB_enc'
+ if [ $5 -eq 1 ]; then
+ PART_FILE_8MB='partitions_8MB_small_factory_fw.bin_enc'
else
- PART_FILE_8MB='partitions_8MB.bin'
- SCRIPT_FILE_8MB='script_8MB'
- fi
-
- cp ${BUILD_DIR}/lib/${PART_FILE_8MB} ${PKG_TMP_DIR}
- cat boards/$1/${SCRIPT_FILE_8MB} > ${PKG_TMP_DIR}/${SCRIPT_FILE_8MB} || { echo >&2 "Cannot create ${SCRIPT_FILE_8MB} file! Aborting."; exit 1; }
-
- if [ "${BOARD}" = "LOPY" -o "${BOARD}" = "WIPY" ]; then
- if [ $4 ]; then
- PART_FILE_4MB='partitions_4MB.bin_enc'
- SCRIPT_FILE_4MB='script_4MB_enc'
- else
- PART_FILE_4MB='partitions_4MB.bin'
- SCRIPT_FILE_4MB='script_4MB'
- fi
-
- cp ${BUILD_DIR}/lib/${PART_FILE_4MB} ${PKG_TMP_DIR}
- cat boards/$1/${SCRIPT_FILE_4MB} > ${PKG_TMP_DIR}/${SCRIPT_FILE_4MB} || { echo >&2 "Cannot create ${SCRIPT_FILE_4MB} file! Aborting."; exit 1; }
+ PART_FILE_8MB='partitions_8MB_normal_factory_fw.bin_enc'
fi
else
- if [ $4 ]; then
- PART_FILE_4MB='partitions_4MB.bin_enc'
- SCRIPT_FILE_4MB='script_4MB_enc'
+ SCRIPT_FILE_8MB='script_8MB'
+ if [ $5 -eq 1 ]; then
+ PART_FILE_8MB='partitions_8MB_small_factory_fw.bin'
else
- PART_FILE_4MB='partitions_4MB.bin'
- SCRIPT_FILE_4MB='script_4MB'
+ PART_FILE_8MB='partitions_8MB_normal_factory_fw.bin'
fi
-
- cp ${BUILD_DIR}/lib/${PART_FILE_4MB} ${PKG_TMP_DIR}
- cat boards/$1/${SCRIPT_FILE_4MB} > ${PKG_TMP_DIR}/${SCRIPT_FILE_4MB} || { echo >&2 "Cannot create ${SCRIPT_FILE_4MB} file! Aborting."; exit 1; }
+fi
+cp ${BUILD_DIR}/lib/${PART_FILE_8MB} ${PKG_TMP_DIR}
+if [ $5 -eq 1 ]; then
+ cp ${FACTORY_BIN_DIR}/${FACTORY_FILE} ${PKG_TMP_DIR}
fi
-cat boards/$1/script > ${PKG_TMP_DIR}/script || { echo >&2 "Cannot create legacy script file! Aborting."; exit 1; }
-cat boards/$1/script2 > ${PKG_TMP_DIR}/script2 || { echo >&2 "Cannot create legacy script2 file! Aborting."; exit 1; }
-tar -czf ${RELEASE_DIR}/${FILE_NAME} -C ${PKG_TMP_DIR} ${BOOT_FILE} ${PART_FILE_4MB} ${PART_FILE_8MB} ${APP_FILE} ${SCRIPT_FILE_4MB} ${SCRIPT_FILE_8MB} script script2 || { echo >&2 "Cannot create ${RELEASE_DIR}/${FILE_NAME}! Aborting."; exit 1; }
+cat boards/$1/${SCRIPT_NAME_8MB} > ${PKG_TMP_DIR}/${SCRIPT_FILE_8MB} || { echo >&2 "Cannot create ${SCRIPT_FILE_8MB} file! Aborting."; exit 1; }
+
+tar -czf ${RELEASE_DIR}/${FILE_NAME} -C ${PKG_TMP_DIR} ${BOOT_FILE} ${PART_FILE_8MB} ${APP_FILE} ${SCRIPT_FILE_8MB} ${FACTORY_FILE} || { echo >&2 "Cannot create ${RELEASE_DIR}/${FILE_NAME}! Aborting."; exit 1; }
echo "Release package ${FILE_NAME} created successfully."
rm -rf ${PKG_TMP_DIR}/
diff --git a/esp32/tools/size_check.sh b/esp32/tools/size_check.sh
index 9a9d7afca1..53fe5ac2bb 100644
--- a/esp32/tools/size_check.sh
+++ b/esp32/tools/size_check.sh
@@ -11,8 +11,14 @@ else
BUILD_DIR="build"
fi
-IMG_MAX_SIZE_8MB=2027520
-IMG_MAX_SIZE_4MB=1761280
+if [ $4 -eq 1 ]; then
+ IMG_MAX_SIZE_8MB=3076096
+else
+ IMG_MAX_SIZE_8MB=2027520
+fi
+# 4MB boards are deprecated
+# IMG_MAX_SIZE_4MB=1761280
+
OS="$(uname)"
#Script Has to be called from esp32 Dir
@@ -52,21 +58,11 @@ fi
total_size=$((${size_app} + ${size_boot}))
-IMG_MAX_SIZE=${IMG_MAX_SIZE_4MB}
-
-if [ "${BOARD}" = "LOPY4" -o "${BOARD}" = "GPY" -o "${BOARD}" = "FIPY" ] ; then
- IMG_MAX_SIZE=${IMG_MAX_SIZE_8MB}
-elif [ "${BOARD}" = "WIPY" -a "${VARIANT}" = "PYGATE" ] ; then
- # WiPy2.0 has a 4MB chip
- # WiPy3.0 has a 8MB chip
- # they are both supported by BOARD=WIPY
- # on the Pygate we support only the WiPy3.0, so for this combination we allow the 8MB limit
- IMG_MAX_SIZE=${IMG_MAX_SIZE_8MB}
-fi
+IMG_MAX_SIZE=${IMG_MAX_SIZE_8MB}
if [ ${total_size} -gt ${IMG_MAX_SIZE} ] ; then
- echo "${total_size} bytes => Firmware image size exceeds avialable space ${IMG_MAX_SIZE} on board!" >&2
+ echo "${total_size} bytes => Firmware image size is NOT ok. It exceeds the available space ${IMG_MAX_SIZE} by $[ $total_size - $IMG_MAX_SIZE ]!" >&2
exit 1
else
- echo "${total_size} bytes => Size OK" >&2
+ echo "${total_size} bytes => Firmware image size is OK. It does not exceed the available space ${IMG_MAX_SIZE}. Still $[ $IMG_MAX_SIZE - $total_size ] left" >&2
fi
diff --git a/esp32/util/mperror.c b/esp32/util/mperror.c
index b963b45a18..a86cfd08dd 100644
--- a/esp32/util/mperror.c
+++ b/esp32/util/mperror.c
@@ -52,7 +52,6 @@
DECLARE PRIVATE DATA
******************************************************************************/
#ifndef BOOTLOADER_BUILD
-STATIC const mp_obj_base_t pyb_heartbeat_obj = {&pyb_heartbeat_type};
static rmt_item32_t rmt_grb_items[COLOR_BITS];
@@ -110,7 +109,7 @@ void mperror_signal_error (void) {
}
disable_and_wait();
led_set_color(&led_info, false, false);
- toggle = ~toggle;
+ toggle = !toggle;
mp_hal_delay_ms(MPERROR_TOOGLE_MS);
}
}
@@ -131,16 +130,21 @@ bool mperror_heartbeat_signal (void) {
mperror_heart_beat.do_disable = false;
} else if (mperror_heart_beat.enabled) {
if (!mperror_heart_beat.beating) {
- if ((mperror_heart_beat.on_time = mp_hal_ticks_ms_non_blocking()) - mperror_heart_beat.off_time > MPERROR_HEARTBEAT_OFF_MS) {
- led_info.color.value = MPERROR_HEARTBEAT_COLOR;
- led_set_color(&led_info, false, false);
+ if (mp_hal_ticks_ms_non_blocking() > mperror_heart_beat.off_time) {
+ led_info.color.value = config_get_rgb_led_on_boot();
+ if (led_info.color.value==0) {
+ led_info.color.value = MPERROR_HEARTBEAT_COLOR;
+ }
+ led_set_color(&led_info, true, false);
mperror_heart_beat.beating = true;
+ mperror_heart_beat.on_time = mp_hal_ticks_ms_non_blocking() + MPERROR_HEARTBEAT_ON_MS;
}
} else {
- if ((mperror_heart_beat.off_time = mp_hal_ticks_ms_non_blocking()) - mperror_heart_beat.on_time > MPERROR_HEARTBEAT_ON_MS) {
+ if (mp_hal_ticks_ms_non_blocking() > mperror_heart_beat.on_time) {
led_info.color.value = 0;
- led_set_color(&led_info, false, false);
+ led_set_color(&led_info, true, false);
mperror_heart_beat.beating = false;
+ mperror_heart_beat.off_time = mp_hal_ticks_ms_non_blocking() + MPERROR_HEARTBEAT_OFF_MS;
}
}
}
@@ -189,7 +193,10 @@ void mperror_enable_heartbeat (bool enable) {
mperror_heart_beat.on_time = 0;
mperror_heart_beat.off_time = 0;
mperror_heart_beat.beating = false;
- led_info.color.value = MPERROR_HEARTBEAT_COLOR;
+ led_info.color.value = config_get_rgb_led_on_boot();
+ if (led_info.color.value==0) {
+ led_info.color.value = MPERROR_HEARTBEAT_COLOR;
+ }
pin_config(&pin_GPIO0, -1, -1, GPIO_MODE_OUTPUT, MACHPIN_PULL_NONE, 0);
led_init(&led_info);
led_set_color(&led_info, false, false);
diff --git a/esp32/util/mpsleep.c b/esp32/util/mpsleep.c
index e14e5d8da1..d9332d1ba3 100644
--- a/esp32/util/mpsleep.c
+++ b/esp32/util/mpsleep.c
@@ -15,7 +15,7 @@
#include "py/mphal.h"
#include "sdkconfig.h"
-#include "rom/rtc.h"
+#include "esp32/rom/rtc.h"
#include "esp_system.h"
#include "esp_sleep.h"
#include "mpsleep.h"
diff --git a/esp32/util/pycom_general_util.c b/esp32/util/pycom_general_util.c
index 38c891c038..72fdb79a9a 100644
--- a/esp32/util/pycom_general_util.c
+++ b/esp32/util/pycom_general_util.c
@@ -25,6 +25,25 @@
/******************************************************************************
DEFINE PUBLIC FUNCTIONS
******************************************************************************/
+
+// Helper function to return decimal value of a hexadecimal character coded in ASCII
+uint8_t hex_from_char(const char c) {
+
+ if((uint8_t)c >= '0' && (uint8_t)c <= '9') {
+ return c - '0';
+ }
+ else if((uint8_t)c >= 'A' && (uint8_t)c <= 'F') {
+ return c - ('A' - 10);
+ }
+ else if((uint8_t)c >= 'a' && (uint8_t)c <= 'f') {
+ return c - ('a' - 10);
+ }
+ else {
+ // 16 is invalid, because in hexa allowed range is 0 - 15
+ return 16;
+ }
+}
+
char *pycom_util_read_file (const char *file_path, vstr_t *vstr) {
vstr_init(vstr, FILE_READ_SIZE);
char *filebuf = vstr->buf;
diff --git a/esp32/util/pycom_general_util.h b/esp32/util/pycom_general_util.h
index 97cd1e3d14..f45dcf87f3 100644
--- a/esp32/util/pycom_general_util.h
+++ b/esp32/util/pycom_general_util.h
@@ -12,6 +12,7 @@
#include "py/obj.h"
+uint8_t hex_from_char(const char c);
char *pycom_util_read_file(const char *file_path, vstr_t *vstr);
#endif /* ESP32_UTIL_PYCOM_GENERAL_UTIL_H_ */
diff --git a/examples/SDdatalogger/boot.py b/examples/SDdatalogger/boot.py
index 4ac94bbaa4..bc42cef2e9 100644
--- a/examples/SDdatalogger/boot.py
+++ b/examples/SDdatalogger/boot.py
@@ -8,18 +8,18 @@
import pyb
-pyb.LED(3).on() # indicate we are waiting for switch press
-pyb.delay(2000) # wait for user to maybe press the switch
-switch_value = pyb.Switch()() # sample the switch at end of delay
-pyb.LED(3).off() # indicate that we finished waiting for the switch
+pyb.LED(3).on() # indicate we are waiting for switch press
+pyb.delay(2000) # wait for user to maybe press the switch
+switch_value = pyb.Switch()() # sample the switch at end of delay
+pyb.LED(3).off() # indicate that we finished waiting for the switch
-pyb.LED(4).on() # indicate that we are selecting the mode
+pyb.LED(4).on() # indicate that we are selecting the mode
if switch_value:
- pyb.usb_mode('VCP+MSC')
- pyb.main('cardreader.py') # if switch was pressed, run this
+ pyb.usb_mode("VCP+MSC")
+ pyb.main("cardreader.py") # if switch was pressed, run this
else:
- pyb.usb_mode('VCP+HID')
- pyb.main('datalogger.py') # if switch wasn't pressed, run this
+ pyb.usb_mode("VCP+HID")
+ pyb.main("datalogger.py") # if switch wasn't pressed, run this
-pyb.LED(4).off() # indicate that we finished selecting the mode
+pyb.LED(4).off() # indicate that we finished selecting the mode
diff --git a/examples/SDdatalogger/datalogger.py b/examples/SDdatalogger/datalogger.py
index 0690c20bb9..3d6f98b389 100644
--- a/examples/SDdatalogger/datalogger.py
+++ b/examples/SDdatalogger/datalogger.py
@@ -17,17 +17,17 @@
# start if switch is pressed
if switch():
- pyb.delay(200) # delay avoids detection of multiple presses
- blue.on() # blue LED indicates file open
- log = open('/sd/log.csv', 'w') # open file on SD (SD: '/sd/', flash: '/flash/)
+ pyb.delay(200) # delay avoids detection of multiple presses
+ blue.on() # blue LED indicates file open
+ log = open("/sd/log.csv", "w") # open file on SD (SD: '/sd/', flash: '/flash/)
# until switch is pressed again
while not switch():
- t = pyb.millis() # get time
- x, y, z = accel.filtered_xyz() # get acceleration data
- log.write('{},{},{},{}\n'.format(t,x,y,z)) # write data to file
+ t = pyb.millis() # get time
+ x, y, z = accel.filtered_xyz() # get acceleration data
+ log.write("{},{},{},{}\n".format(t, x, y, z)) # write data to file
# end after switch is pressed again
- log.close() # close file
- blue.off() # blue LED indicates file closed
- pyb.delay(200) # delay avoids detection of multiple presses
+ log.close() # close file
+ blue.off() # blue LED indicates file closed
+ pyb.delay(200) # delay avoids detection of multiple presses
diff --git a/examples/accel_i2c.py b/examples/accel_i2c.py
index d635e3ccc1..7229c22899 100644
--- a/examples/accel_i2c.py
+++ b/examples/accel_i2c.py
@@ -17,10 +17,10 @@
i2c = I2C(1, baudrate=100000)
addrs = i2c.scan()
print("Scanning devices:", [hex(x) for x in addrs])
-if 0x4c not in addrs:
+if 0x4C not in addrs:
print("Accelerometer is not detected")
-ACCEL_ADDR = 0x4c
+ACCEL_ADDR = 0x4C
ACCEL_AXIS_X_REG = 0
ACCEL_MODE_REG = 7
diff --git a/examples/accellog.py b/examples/accellog.py
index bb711b05fa..e8b5d101da 100644
--- a/examples/accellog.py
+++ b/examples/accellog.py
@@ -2,16 +2,19 @@
import pyb
-accel = pyb.Accel() # create object of accelerometer
-blue = pyb.LED(4) # create object of blue LED
+accel = pyb.Accel() # create object of accelerometer
+blue = pyb.LED(4) # create object of blue LED
-log = open('1:/log.csv', 'w') # open file to write data - 1:/ ist the SD-card, 0:/ the internal memory
-blue.on() # turn on blue LED
+# open file to write data - /sd/ is the SD-card, /flash/ the internal memory
+log = open("/sd/log.csv", "w")
-for i in range(100): # do 100 times (if the board is connected via USB, you can't write longer because the PC tries to open the filesystem which messes up your file.)
- t = pyb.millis() # get time since reset
- x, y, z = accel.filtered_xyz() # get acceleration data
- log.write('{},{},{},{}\n'.format(t,x,y,z)) # write data to file
+blue.on() # turn on blue LED
-log.close() # close file
-blue.off() # turn off LED
+# do 100 times (if the board is connected via USB, you can't write longer because the PC tries to open the filesystem which messes up your file.)
+for i in range(100):
+ t = pyb.millis() # get time since reset
+ x, y, z = accel.filtered_xyz() # get acceleration data
+ log.write("{},{},{},{}\n".format(t, x, y, z)) # write data to file
+
+log.close() # close file
+blue.off() # turn off LED
diff --git a/examples/asmled.py b/examples/asmled.py
index 917d9ba03c..09a06c184a 100644
--- a/examples/asmled.py
+++ b/examples/asmled.py
@@ -2,8 +2,8 @@
# this version is overly verbose and uses word stores
@micropython.asm_thumb
def flash_led(r0):
- movw(r1, (stm.GPIOA + stm.GPIO_BSRRL) & 0xffff)
- movt(r1, ((stm.GPIOA + stm.GPIO_BSRRL) >> 16) & 0x7fff)
+ movw(r1, (stm.GPIOA + stm.GPIO_BSRRL) & 0xFFFF)
+ movt(r1, ((stm.GPIOA + stm.GPIO_BSRRL) >> 16) & 0x7FFF)
movw(r2, 1 << 13)
movt(r2, 0)
movw(r3, 0)
@@ -17,8 +17,8 @@ def flash_led(r0):
str(r2, [r1, 0])
# delay for a bit
- movw(r4, 5599900 & 0xffff)
- movt(r4, (5599900 >> 16) & 0xffff)
+ movw(r4, 5599900 & 0xFFFF)
+ movt(r4, (5599900 >> 16) & 0xFFFF)
label(delay_on)
sub(r4, r4, 1)
cmp(r4, 0)
@@ -28,8 +28,8 @@ def flash_led(r0):
str(r3, [r1, 0])
# delay for a bit
- movw(r4, 5599900 & 0xffff)
- movt(r4, (5599900 >> 16) & 0xffff)
+ movw(r4, 5599900 & 0xFFFF)
+ movt(r4, (5599900 >> 16) & 0xFFFF)
label(delay_off)
sub(r4, r4, 1)
cmp(r4, 0)
@@ -41,6 +41,7 @@ def flash_led(r0):
cmp(r0, 0)
bgt(loop1)
+
# flash LED #2 using inline assembler
# this version uses half-word sortes, and the convenience assembler operation 'movwt'
@micropython.asm_thumb
@@ -81,5 +82,6 @@ def flash_led_v2(r0):
cmp(r0, 0)
bgt(loop1)
+
flash_led(5)
flash_led_v2(5)
diff --git a/examples/asmsum.py b/examples/asmsum.py
index 07e71c7384..f465b25afd 100644
--- a/examples/asmsum.py
+++ b/examples/asmsum.py
@@ -22,6 +22,7 @@ def asm_sum_words(r0, r1):
mov(r0, r2)
+
@micropython.asm_thumb
def asm_sum_bytes(r0, r1):
@@ -46,12 +47,13 @@ def asm_sum_bytes(r0, r1):
mov(r0, r2)
+
import array
-b = array.array('l', (100, 200, 300, 400))
+b = array.array("l", (100, 200, 300, 400))
n = asm_sum_words(len(b), b)
print(b, n)
-b = array.array('b', (10, 20, 30, 40, 50, 60, 70, 80))
+b = array.array("b", (10, 20, 30, 40, 50, 60, 70, 80))
n = asm_sum_bytes(len(b), b)
print(b, n)
diff --git a/examples/bluetooth/ble_advertising.py b/examples/bluetooth/ble_advertising.py
new file mode 100644
index 0000000000..eed527f55d
--- /dev/null
+++ b/examples/bluetooth/ble_advertising.py
@@ -0,0 +1,93 @@
+# Helpers for generating BLE advertising payloads.
+
+from micropython import const
+import struct
+import bluetooth
+
+# Advertising payloads are repeated packets of the following form:
+# 1 byte data length (N + 1)
+# 1 byte type (see constants below)
+# N bytes type-specific data
+
+_ADV_TYPE_FLAGS = const(0x01)
+_ADV_TYPE_NAME = const(0x09)
+_ADV_TYPE_UUID16_COMPLETE = const(0x3)
+_ADV_TYPE_UUID32_COMPLETE = const(0x5)
+_ADV_TYPE_UUID128_COMPLETE = const(0x7)
+_ADV_TYPE_UUID16_MORE = const(0x2)
+_ADV_TYPE_UUID32_MORE = const(0x4)
+_ADV_TYPE_UUID128_MORE = const(0x6)
+_ADV_TYPE_APPEARANCE = const(0x19)
+
+
+# Generate a payload to be passed to gap_advertise(adv_data=...).
+def advertising_payload(limited_disc=False, br_edr=False, name=None, services=None, appearance=0):
+ payload = bytearray()
+
+ def _append(adv_type, value):
+ nonlocal payload
+ payload += struct.pack("BB", len(value) + 1, adv_type) + value
+
+ _append(
+ _ADV_TYPE_FLAGS,
+ struct.pack("B", (0x01 if limited_disc else 0x02) + (0x18 if br_edr else 0x04)),
+ )
+
+ if name:
+ _append(_ADV_TYPE_NAME, name)
+
+ if services:
+ for uuid in services:
+ b = bytes(uuid)
+ if len(b) == 2:
+ _append(_ADV_TYPE_UUID16_COMPLETE, b)
+ elif len(b) == 4:
+ _append(_ADV_TYPE_UUID32_COMPLETE, b)
+ elif len(b) == 16:
+ _append(_ADV_TYPE_UUID128_COMPLETE, b)
+
+ # See org.bluetooth.characteristic.gap.appearance.xml
+ if appearance:
+ _append(_ADV_TYPE_APPEARANCE, struct.pack(" 0
+
+ def _advertise(self, interval_us=500000):
+ print("Starting advertising")
+ self._ble.gap_advertise(interval_us, adv_data=self._payload)
+
+ def on_write(self, callback):
+ self._write_callback = callback
+
+
+def demo():
+ ble = bluetooth.BLE()
+ p = BLESimplePeripheral(ble)
+
+ def on_rx(v):
+ print("RX", v)
+
+ p.on_write(on_rx)
+
+ i = 0
+ while True:
+ if p.is_connected():
+ # Short burst of queued notifications.
+ for _ in range(3):
+ data = str(i) + "_"
+ print("TX", data)
+ p.send(data)
+ i += 1
+ time.sleep_ms(100)
+
+
+if __name__ == "__main__":
+ demo()
diff --git a/examples/bluetooth/ble_temperature.py b/examples/bluetooth/ble_temperature.py
new file mode 100644
index 0000000000..001a26b114
--- /dev/null
+++ b/examples/bluetooth/ble_temperature.py
@@ -0,0 +1,93 @@
+# This example demonstrates a simple temperature sensor peripheral.
+#
+# The sensor's local value updates every second, and it will notify
+# any connected central every 10 seconds.
+
+import bluetooth
+import random
+import struct
+import time
+from ble_advertising import advertising_payload
+
+from micropython import const
+
+_IRQ_CENTRAL_CONNECT = const(1)
+_IRQ_CENTRAL_DISCONNECT = const(2)
+_IRQ_GATTS_INDICATE_DONE = const(20)
+
+# org.bluetooth.service.environmental_sensing
+_ENV_SENSE_UUID = bluetooth.UUID(0x181A)
+# org.bluetooth.characteristic.temperature
+_TEMP_CHAR = (
+ bluetooth.UUID(0x2A6E),
+ bluetooth.FLAG_READ | bluetooth.FLAG_NOTIFY | bluetooth.FLAG_INDICATE,
+)
+_ENV_SENSE_SERVICE = (
+ _ENV_SENSE_UUID,
+ (_TEMP_CHAR,),
+)
+
+# org.bluetooth.characteristic.gap.appearance.xml
+_ADV_APPEARANCE_GENERIC_THERMOMETER = const(768)
+
+
+class BLETemperature:
+ def __init__(self, ble, name="mpy-temp"):
+ self._ble = ble
+ self._ble.active(True)
+ self._ble.irq(handler=self._irq)
+ ((self._handle,),) = self._ble.gatts_register_services((_ENV_SENSE_SERVICE,))
+ self._connections = set()
+ self._payload = advertising_payload(
+ name=name, services=[_ENV_SENSE_UUID], appearance=_ADV_APPEARANCE_GENERIC_THERMOMETER
+ )
+ self._advertise()
+
+ def _irq(self, event, data):
+ # Track connections so we can send notifications.
+ if event == _IRQ_CENTRAL_CONNECT:
+ conn_handle, _, _ = data
+ self._connections.add(conn_handle)
+ elif event == _IRQ_CENTRAL_DISCONNECT:
+ conn_handle, _, _ = data
+ self._connections.remove(conn_handle)
+ # Start advertising again to allow a new connection.
+ self._advertise()
+ elif event == _IRQ_GATTS_INDICATE_DONE:
+ conn_handle, value_handle, status = data
+
+ def set_temperature(self, temp_deg_c, notify=False, indicate=False):
+ # Data is sint16 in degrees Celsius with a resolution of 0.01 degrees Celsius.
+ # Write the local value, ready for a central to read.
+ self._ble.gatts_write(self._handle, struct.pack("source_name, MP_EMIT_OPT_NONE, false);
+ mp_obj_t module_fun = mp_compile(&pt, src_name, false);
mp_call_function_0(module_fun);
nlr_pop();
return 0;
@@ -58,8 +60,7 @@ int main() {
mp_init();
const char str[] = "print('Hello world of easy embedding!')";
- mp_lexer_t *lex = mp_lexer_new_from_str_len(0/*MP_QSTR_*/, str, strlen(str), false);
- if (execute_from_lexer(lex)) {
+ if (execute_from_str(str)) {
printf("Error\n");
}
}
diff --git a/examples/embedding/mpconfigport.h b/examples/embedding/mpconfigport.h
deleted file mode 120000
index 142e5d6f43..0000000000
--- a/examples/embedding/mpconfigport.h
+++ /dev/null
@@ -1 +0,0 @@
-mpconfigport_minimal.h
\ No newline at end of file
diff --git a/examples/embedding/mpconfigport.h b/examples/embedding/mpconfigport.h
new file mode 100644
index 0000000000..89c180b2a8
--- /dev/null
+++ b/examples/embedding/mpconfigport.h
@@ -0,0 +1 @@
+#include "mpconfigport_minimal.h"
diff --git a/examples/embedding/mpconfigport_minimal.h b/examples/embedding/mpconfigport_minimal.h
index 90011b3f81..b5ffd376ae 100644
--- a/examples/embedding/mpconfigport_minimal.h
+++ b/examples/embedding/mpconfigport_minimal.h
@@ -1,5 +1,5 @@
/*
- * This file is part of the Micro Python project, http://micropython.org/
+ * This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
@@ -24,7 +24,7 @@
* THE SOFTWARE.
*/
-// options to control how Micro Python is built
+// options to control how MicroPython is built
#define MICROPY_ALLOC_PATH_MAX (PATH_MAX)
#define MICROPY_ENABLE_GC (1)
@@ -33,6 +33,8 @@
#define MICROPY_COMP_CONST (0)
#define MICROPY_MEM_STATS (0)
#define MICROPY_DEBUG_PRINTERS (0)
+#define MICROPY_READER_POSIX (1)
+#define MICROPY_KBD_EXCEPTION (1)
#define MICROPY_HELPER_REPL (1)
#define MICROPY_HELPER_LEXER_UNIX (1)
#define MICROPY_ENABLE_SOURCE_LINE (0)
@@ -87,23 +89,17 @@
extern const struct _mp_obj_module_t mp_module_os;
#define MICROPY_PORT_BUILTIN_MODULES \
- { MP_OBJ_NEW_QSTR(MP_QSTR_uos), (mp_obj_t)&mp_module_os }, \
+ { MP_ROM_QSTR(MP_QSTR_uos), MP_ROM_PTR(&mp_module_os) }, \
#define MICROPY_PORT_ROOT_POINTERS \
- mp_obj_t keyboard_interrupt_obj;
//////////////////////////////////////////
// Do not change anything beyond this line
//////////////////////////////////////////
-// Define to 1 to use undertested inefficient GC helper implementation
-// (if more efficient arch-specific one is not available).
-#ifndef MICROPY_GCREGS_SETJMP
- #ifdef __mips__
- #define MICROPY_GCREGS_SETJMP (1)
- #else
- #define MICROPY_GCREGS_SETJMP (0)
- #endif
+#if !(defined(MICROPY_GCREGS_SETJMP) || defined(__x86_64__) || defined(__i386__) || defined(__thumb2__) || defined(__thumb__) || defined(__arm__))
+// Fall back to setjmp() implementation for discovery of GC pointers in registers.
+#define MICROPY_GCREGS_SETJMP (1)
#endif
// type definitions for the specific machine
@@ -118,8 +114,6 @@ typedef int mp_int_t; // must be pointer size
typedef unsigned int mp_uint_t; // must be pointer size
#endif
-#define BYTES_PER_WORD sizeof(mp_int_t)
-
// Cannot include , as it may lead to symbol name clashes
#if _FILE_OFFSET_BITS == 64 && !defined(__LP64__)
typedef long long mp_off_t;
diff --git a/examples/hwapi/button_led.py b/examples/hwapi/button_led.py
new file mode 100644
index 0000000000..bd6fe01729
--- /dev/null
+++ b/examples/hwapi/button_led.py
@@ -0,0 +1,9 @@
+import utime
+from hwconfig import LED, BUTTON
+
+# Light LED when (and while) a BUTTON is pressed
+
+while 1:
+ LED.value(BUTTON.value())
+ # Don't burn CPU
+ utime.sleep_ms(10)
diff --git a/examples/hwapi/button_reaction.py b/examples/hwapi/button_reaction.py
new file mode 100644
index 0000000000..e5a139a575
--- /dev/null
+++ b/examples/hwapi/button_reaction.py
@@ -0,0 +1,21 @@
+import utime
+import machine
+from hwconfig import LED, BUTTON
+
+# machine.time_pulse_us() function demo
+
+print(
+ """\
+Let's play an interesting game:
+You click button as fast as you can, and I tell you how slow you are.
+Ready? Cliiiiick!
+"""
+)
+
+while 1:
+ delay = machine.time_pulse_us(BUTTON, 1, 10 * 1000 * 1000)
+ if delay < 0:
+ print("Well, you're *really* slow")
+ else:
+ print("You are as slow as %d microseconds!" % delay)
+ utime.sleep_ms(10)
diff --git a/examples/hwapi/hwconfig_console.py b/examples/hwapi/hwconfig_console.py
new file mode 100644
index 0000000000..1b49d52379
--- /dev/null
+++ b/examples/hwapi/hwconfig_console.py
@@ -0,0 +1,18 @@
+# This is hwconfig for "emulation" for cases when there's no real hardware.
+# It just prints information to console.
+class LEDClass:
+ def __init__(self, id):
+ self.id = "LED(%d):" % id
+
+ def value(self, v):
+ print(self.id, v)
+
+ def on(self):
+ self.value(1)
+
+ def off(self):
+ self.value(0)
+
+
+LED = LEDClass(1)
+LED2 = LEDClass(12)
diff --git a/examples/hwapi/hwconfig_dragonboard410c.py b/examples/hwapi/hwconfig_dragonboard410c.py
index 00f21a658f..eec3582039 100644
--- a/examples/hwapi/hwconfig_dragonboard410c.py
+++ b/examples/hwapi/hwconfig_dragonboard410c.py
@@ -1,12 +1,22 @@
-from machine import Pin
+from machine import Pin, Signal
# 96Boards/Qualcomm DragonBoard 410c
+#
# By default, on-board LEDs are controlled by kernel LED driver.
# To make corresponding pins be available as normal GPIO,
# corresponding driver needs to be unbound first (as root):
# echo -n "soc:leds" >/sys/class/leds/apq8016-sbc:green:user1/device/driver/unbind
# Note that application also either should be run as root, or
# /sys/class/gpio ownership needs to be changed.
+# Likewise, onboard buttons are controlled by gpio_keys driver.
+# To release corresponding GPIOs:
+# echo -n "gpio_keys" >/sys/class/input/input1/device/driver/unbind
# User LED 1 on gpio21
-LED = Pin(21, Pin.OUT)
+LED = Signal(Pin(21, Pin.OUT))
+
+# User LED 2 on gpio120
+LED2 = Signal(Pin(120, Pin.OUT))
+
+# Button S3 on gpio107
+BUTTON = Pin(107, Pin.IN)
diff --git a/examples/hwapi/hwconfig_esp8266_esp12.py b/examples/hwapi/hwconfig_esp8266_esp12.py
index e8cf2d12e1..2e855ee3d3 100644
--- a/examples/hwapi/hwconfig_esp8266_esp12.py
+++ b/examples/hwapi/hwconfig_esp8266_esp12.py
@@ -1,5 +1,5 @@
-from machine import Pin
+from machine import Pin, Signal
# ESP12 module as used by many boards
-# Blue LED on pin 2
-LED = Pin(2, Pin.OUT)
+# Blue LED on pin 2, active low (inverted)
+LED = Signal(2, Pin.OUT, invert=True)
diff --git a/examples/hwapi/hwconfig_pyboard.py b/examples/hwapi/hwconfig_pyboard.py
new file mode 100644
index 0000000000..a74a1ae151
--- /dev/null
+++ b/examples/hwapi/hwconfig_pyboard.py
@@ -0,0 +1,13 @@
+from machine import Pin, Signal
+
+# Red LED on pin LED_RED also kown as A13
+LED = Signal("LED_RED", Pin.OUT)
+
+# Green LED on pin LED_GREEN also known as A14
+LED2 = Signal("LED_GREEN", Pin.OUT)
+
+# Yellow LED on pin LED_YELLOW also known as A15
+LED3 = Signal("LED_YELLOW", Pin.OUT)
+
+# Blue LED on pin LED_BLUE also known as B4
+LED4 = Signal("LED_BLUE", Pin.OUT)
diff --git a/examples/hwapi/hwconfig_z_96b_carbon.py b/examples/hwapi/hwconfig_z_96b_carbon.py
new file mode 100644
index 0000000000..97fd57a07f
--- /dev/null
+++ b/examples/hwapi/hwconfig_z_96b_carbon.py
@@ -0,0 +1,9 @@
+from machine import Signal
+
+# 96Boards Carbon board
+# USR1 - User controlled led, connected to PD2
+# USR2 - User controlled led, connected to PA15
+# BT - Bluetooth indicator, connected to PB5.
+# Note - 96b_carbon uses (at the time of writing) non-standard
+# for Zephyr port device naming convention.
+LED = Signal(("GPIOA", 15), Pin.OUT)
diff --git a/examples/hwapi/hwconfig_z_frdm_k64f.py b/examples/hwapi/hwconfig_z_frdm_k64f.py
index c45e3e7567..377c638787 100644
--- a/examples/hwapi/hwconfig_z_frdm_k64f.py
+++ b/examples/hwapi/hwconfig_z_frdm_k64f.py
@@ -1,5 +1,5 @@
-from machine import Pin
+from machine import Pin, Signal
# Freescale/NXP FRDM-K64F board
# Blue LED on port B, pin 21
-LED = Pin(("GPIO_1", 21), Pin.OUT)
+LED = Signal(("GPIO_1", 21), Pin.OUT)
diff --git a/examples/hwapi/soft_pwm.py b/examples/hwapi/soft_pwm.py
index a9a5561717..72291b0ecd 100644
--- a/examples/hwapi/soft_pwm.py
+++ b/examples/hwapi/soft_pwm.py
@@ -14,10 +14,10 @@ def pwm_cycle(led, duty, cycles):
duty_off = 20 - duty
for i in range(cycles):
if duty:
- led.value(1)
+ led.on()
utime.sleep_ms(duty)
if duty_off:
- led.value(0)
+ led.off()
utime.sleep_ms(duty_off)
diff --git a/examples/hwapi/soft_pwm2_uasyncio.py b/examples/hwapi/soft_pwm2_uasyncio.py
new file mode 100644
index 0000000000..908ef2d8ac
--- /dev/null
+++ b/examples/hwapi/soft_pwm2_uasyncio.py
@@ -0,0 +1,31 @@
+# Like soft_pwm_uasyncio.py, but fading 2 LEDs with different phase.
+# Also see original soft_pwm.py.
+import uasyncio
+from hwconfig import LED, LED2
+
+
+async def pwm_cycle(led, duty, cycles):
+ duty_off = 20 - duty
+ for i in range(cycles):
+ if duty:
+ led.value(1)
+ await uasyncio.sleep_ms(duty)
+ if duty_off:
+ led.value(0)
+ await uasyncio.sleep_ms(duty_off)
+
+
+async def fade_in_out(LED):
+ while True:
+ # Fade in
+ for i in range(1, 21):
+ await pwm_cycle(LED, i, 2)
+ # Fade out
+ for i in range(20, 0, -1):
+ await pwm_cycle(LED, i, 2)
+
+
+loop = uasyncio.get_event_loop()
+loop.create_task(fade_in_out(LED))
+loop.call_later_ms(800, fade_in_out(LED2))
+loop.run_forever()
diff --git a/examples/hwapi/soft_pwm_uasyncio.py b/examples/hwapi/soft_pwm_uasyncio.py
new file mode 100644
index 0000000000..8d7ad8c9e0
--- /dev/null
+++ b/examples/hwapi/soft_pwm_uasyncio.py
@@ -0,0 +1,28 @@
+# See original soft_pwm.py for detailed comments.
+import uasyncio
+from hwconfig import LED
+
+
+async def pwm_cycle(led, duty, cycles):
+ duty_off = 20 - duty
+ for i in range(cycles):
+ if duty:
+ led.value(1)
+ await uasyncio.sleep_ms(duty)
+ if duty_off:
+ led.value(0)
+ await uasyncio.sleep_ms(duty_off)
+
+
+async def fade_in_out(LED):
+ while True:
+ # Fade in
+ for i in range(1, 21):
+ await pwm_cycle(LED, i, 2)
+ # Fade out
+ for i in range(20, 0, -1):
+ await pwm_cycle(LED, i, 2)
+
+
+loop = uasyncio.get_event_loop()
+loop.run_until_complete(fade_in_out(LED))
diff --git a/examples/ledangle.py b/examples/ledangle.py
index 8c8d9e99d9..3d47e8f72d 100644
--- a/examples/ledangle.py
+++ b/examples/ledangle.py
@@ -1,5 +1,6 @@
import pyb
+
def led_angle(seconds_to_run_for):
# make LED objects
l1 = pyb.LED(1)
diff --git a/examples/mandel.py b/examples/mandel.py
index bbb8086470..2f3d7da235 100644
--- a/examples/mandel.py
+++ b/examples/mandel.py
@@ -3,13 +3,14 @@
except:
pass
+
def mandelbrot():
# returns True if c, complex, is in the Mandelbrot set
- #@micropython.native
+ # @micropython.native
def in_set(c):
z = 0
for i in range(40):
- z = z*z + c
+ z = z * z + c
if abs(z) > 60:
return False
return True
@@ -21,7 +22,9 @@ def in_set(c):
lcd.set(u, v)
lcd.show()
+
# PC testing
import lcd
+
lcd = lcd.LCD(128, 32)
mandelbrot()
diff --git a/examples/micropython.py b/examples/micropython.py
index f91da94f41..5b87ba192e 100644
--- a/examples/micropython.py
+++ b/examples/micropython.py
@@ -2,7 +2,9 @@
# Dummy function decorators
+
def nodecor(x):
return x
+
bytecode = native = viper = nodecor
diff --git a/examples/natmod/.gitignore b/examples/natmod/.gitignore
new file mode 100644
index 0000000000..4815d20f06
--- /dev/null
+++ b/examples/natmod/.gitignore
@@ -0,0 +1 @@
+*.mpy
diff --git a/examples/natmod/btree/Makefile b/examples/natmod/btree/Makefile
new file mode 100644
index 0000000000..d795102b4a
--- /dev/null
+++ b/examples/natmod/btree/Makefile
@@ -0,0 +1,37 @@
+# Location of top-level MicroPython directory
+MPY_DIR = ../../..
+
+# Name of module (different to built-in btree so it can coexist)
+MOD = btree_$(ARCH)
+
+# Source files (.c or .py)
+SRC = btree_c.c btree_py.py
+
+# Architecture to build for (x86, x64, armv7m, xtensa, xtensawin)
+ARCH = x64
+
+BTREE_DIR = $(MPY_DIR)/lib/berkeley-db-1.xx
+BTREE_DEFS = -D__DBINTERFACE_PRIVATE=1 -Dmpool_error="(void)" -Dabort=abort_ "-Dvirt_fd_t=void*" $(BTREE_DEFS_EXTRA)
+CFLAGS += -I$(BTREE_DIR)/PORT/include
+CFLAGS += -Wno-old-style-definition -Wno-sign-compare -Wno-unused-parameter $(BTREE_DEFS)
+
+SRC += $(addprefix $(realpath $(BTREE_DIR))/,\
+ btree/bt_close.c \
+ btree/bt_conv.c \
+ btree/bt_delete.c \
+ btree/bt_get.c \
+ btree/bt_open.c \
+ btree/bt_overflow.c \
+ btree/bt_page.c \
+ btree/bt_put.c \
+ btree/bt_search.c \
+ btree/bt_seq.c \
+ btree/bt_split.c \
+ btree/bt_utils.c \
+ mpool/mpool.c \
+ )
+
+include $(MPY_DIR)/py/dynruntime.mk
+
+# btree needs gnu99 defined
+CFLAGS += -std=gnu99
diff --git a/examples/natmod/btree/btree_c.c b/examples/natmod/btree/btree_c.c
new file mode 100644
index 0000000000..5e8a34ac40
--- /dev/null
+++ b/examples/natmod/btree/btree_c.c
@@ -0,0 +1,147 @@
+#define MICROPY_PY_BTREE (1)
+
+#include "py/dynruntime.h"
+
+#include
+
+#if !defined(__linux__)
+void *memcpy(void *dst, const void *src, size_t n) {
+ return mp_fun_table.memmove_(dst, src, n);
+}
+void *memset(void *s, int c, size_t n) {
+ return mp_fun_table.memset_(s, c, n);
+}
+#endif
+
+void *memmove(void *dest, const void *src, size_t n) {
+ return mp_fun_table.memmove_(dest, src, n);
+}
+
+void *malloc(size_t n) {
+ void *ptr = m_malloc(n);
+ return ptr;
+}
+void *realloc(void *ptr, size_t n) {
+ mp_printf(&mp_plat_print, "UNDEF %d\n", __LINE__);
+ return NULL;
+}
+void *calloc(size_t n, size_t m) {
+ void *ptr = m_malloc(n * m);
+ // memory already cleared by conservative GC
+ return ptr;
+}
+
+void free(void *ptr) {
+ m_free(ptr);
+}
+
+void abort_(void) {
+ nlr_raise(mp_obj_new_exception(mp_load_global(MP_QSTR_RuntimeError)));
+}
+
+int native_errno;
+#if defined(__linux__)
+int *__errno_location (void)
+#else
+int *__errno (void)
+#endif
+{
+ return &native_errno;
+}
+
+ssize_t mp_stream_posix_write(void *stream, const void *buf, size_t len) {
+ mp_obj_base_t* o = stream;
+ const mp_stream_p_t *stream_p = o->type->protocol;
+ mp_uint_t out_sz = stream_p->write(MP_OBJ_FROM_PTR(stream), buf, len, &native_errno);
+ if (out_sz == MP_STREAM_ERROR) {
+ return -1;
+ } else {
+ return out_sz;
+ }
+}
+
+ssize_t mp_stream_posix_read(void *stream, void *buf, size_t len) {
+ mp_obj_base_t* o = stream;
+ const mp_stream_p_t *stream_p = o->type->protocol;
+ mp_uint_t out_sz = stream_p->read(MP_OBJ_FROM_PTR(stream), buf, len, &native_errno);
+ if (out_sz == MP_STREAM_ERROR) {
+ return -1;
+ } else {
+ return out_sz;
+ }
+}
+
+off_t mp_stream_posix_lseek(void *stream, off_t offset, int whence) {
+ const mp_obj_base_t* o = stream;
+ const mp_stream_p_t *stream_p = o->type->protocol;
+ struct mp_stream_seek_t seek_s;
+ seek_s.offset = offset;
+ seek_s.whence = whence;
+ mp_uint_t res = stream_p->ioctl(MP_OBJ_FROM_PTR(stream), MP_STREAM_SEEK, (mp_uint_t)(uintptr_t)&seek_s, &native_errno);
+ if (res == MP_STREAM_ERROR) {
+ return -1;
+ }
+ return seek_s.offset;
+}
+
+int mp_stream_posix_fsync(void *stream) {
+ mp_obj_base_t* o = stream;
+ const mp_stream_p_t *stream_p = o->type->protocol;
+ mp_uint_t res = stream_p->ioctl(MP_OBJ_FROM_PTR(stream), MP_STREAM_FLUSH, 0, &native_errno);
+ if (res == MP_STREAM_ERROR) {
+ return -1;
+ }
+ return res;
+}
+
+mp_obj_type_t btree_type;
+
+#include "extmod/modbtree.c"
+
+mp_map_elem_t btree_locals_dict_table[8];
+STATIC MP_DEFINE_CONST_DICT(btree_locals_dict, btree_locals_dict_table);
+
+STATIC mp_obj_t btree_open(size_t n_args, const mp_obj_t *args) {
+ // Make sure we got a stream object
+ mp_get_stream_raise(args[0], MP_STREAM_OP_READ | MP_STREAM_OP_WRITE | MP_STREAM_OP_IOCTL);
+
+ BTREEINFO openinfo = {0};
+ openinfo.flags = mp_obj_get_int(args[1]);
+ openinfo.cachesize = mp_obj_get_int(args[2]);
+ openinfo.psize = mp_obj_get_int(args[3]);
+ openinfo.minkeypage = mp_obj_get_int(args[4]);
+ DB *db = __bt_open(MP_OBJ_TO_PTR(args[0]), &btree_stream_fvtable, &openinfo, 0);
+ if (db == NULL) {
+ mp_raise_OSError(native_errno);
+ }
+
+ return MP_OBJ_FROM_PTR(btree_new(db, args[0]));
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(btree_open_obj, 5, 5, btree_open);
+
+mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) {
+ MP_DYNRUNTIME_INIT_ENTRY
+
+ btree_type.base.type = (void*)&mp_fun_table.type_type;
+ btree_type.name = MP_QSTR_btree;
+ btree_type.print = btree_print;
+ btree_type.getiter = btree_getiter;
+ btree_type.iternext = btree_iternext;
+ btree_type.binary_op = btree_binary_op;
+ btree_type.subscr = btree_subscr;
+ btree_locals_dict_table[0] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_close), MP_OBJ_FROM_PTR(&btree_close_obj) };
+ btree_locals_dict_table[1] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_flush), MP_OBJ_FROM_PTR(&btree_flush_obj) };
+ btree_locals_dict_table[2] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_get), MP_OBJ_FROM_PTR(&btree_get_obj) };
+ btree_locals_dict_table[3] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_put), MP_OBJ_FROM_PTR(&btree_put_obj) };
+ btree_locals_dict_table[4] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_seq), MP_OBJ_FROM_PTR(&btree_seq_obj) };
+ btree_locals_dict_table[5] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_keys), MP_OBJ_FROM_PTR(&btree_keys_obj) };
+ btree_locals_dict_table[6] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_values), MP_OBJ_FROM_PTR(&btree_values_obj) };
+ btree_locals_dict_table[7] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_items), MP_OBJ_FROM_PTR(&btree_items_obj) };
+ btree_type.locals_dict = (void*)&btree_locals_dict;
+
+ mp_store_global(MP_QSTR__open, MP_OBJ_FROM_PTR(&btree_open_obj));
+ mp_store_global(MP_QSTR_INCL, MP_OBJ_NEW_SMALL_INT(FLAG_END_KEY_INCL));
+ mp_store_global(MP_QSTR_DESC, MP_OBJ_NEW_SMALL_INT(FLAG_DESC));
+
+ MP_DYNRUNTIME_INIT_EXIT
+}
diff --git a/examples/natmod/btree/btree_py.py b/examples/natmod/btree/btree_py.py
new file mode 100644
index 0000000000..bd53c084a1
--- /dev/null
+++ b/examples/natmod/btree/btree_py.py
@@ -0,0 +1,3 @@
+# Implemented in Python to support keyword arguments
+def open(stream, *, flags=0, cachesize=0, pagesize=0, minkeypage=0):
+ return _open(stream, flags, cachesize, pagesize, minkeypage)
diff --git a/examples/natmod/features0/Makefile b/examples/natmod/features0/Makefile
new file mode 100644
index 0000000000..57490df90a
--- /dev/null
+++ b/examples/natmod/features0/Makefile
@@ -0,0 +1,14 @@
+# Location of top-level MicroPython directory
+MPY_DIR = ../../..
+
+# Name of module
+MOD = features0
+
+# Source files (.c or .py)
+SRC = features0.c
+
+# Architecture to build for (x86, x64, armv7m, xtensa, xtensawin)
+ARCH = x64
+
+# Include to get the rules for compiling and linking the module
+include $(MPY_DIR)/py/dynruntime.mk
diff --git a/examples/natmod/features0/features0.c b/examples/natmod/features0/features0.c
new file mode 100644
index 0000000000..1b1867a3bc
--- /dev/null
+++ b/examples/natmod/features0/features0.c
@@ -0,0 +1,40 @@
+/* This example demonstrates the following features in a native module:
+ - defining a simple function exposed to Python
+ - defining a local, helper C function
+ - getting and creating integer objects
+*/
+
+// Include the header file to get access to the MicroPython API
+#include "py/dynruntime.h"
+
+// Helper function to compute factorial
+STATIC mp_int_t factorial_helper(mp_int_t x) {
+ if (x == 0) {
+ return 1;
+ }
+ return x * factorial_helper(x - 1);
+}
+
+// This is the function which will be called from Python, as factorial(x)
+STATIC mp_obj_t factorial(mp_obj_t x_obj) {
+ // Extract the integer from the MicroPython input object
+ mp_int_t x = mp_obj_get_int(x_obj);
+ // Calculate the factorial
+ mp_int_t result = factorial_helper(x);
+ // Convert the result to a MicroPython integer object and return it
+ return mp_obj_new_int(result);
+}
+// Define a Python reference to the function above
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(factorial_obj, factorial);
+
+// This is the entry point and is called when the module is imported
+mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) {
+ // This must be first, it sets up the globals dict and other things
+ MP_DYNRUNTIME_INIT_ENTRY
+
+ // Make the function available in the module's namespace
+ mp_store_global(MP_QSTR_factorial, MP_OBJ_FROM_PTR(&factorial_obj));
+
+ // This must be last, it restores the globals dict
+ MP_DYNRUNTIME_INIT_EXIT
+}
diff --git a/examples/natmod/features1/Makefile b/examples/natmod/features1/Makefile
new file mode 100644
index 0000000000..010640daf9
--- /dev/null
+++ b/examples/natmod/features1/Makefile
@@ -0,0 +1,14 @@
+# Location of top-level MicroPython directory
+MPY_DIR = ../../..
+
+# Name of module
+MOD = features1
+
+# Source files (.c or .py)
+SRC = features1.c
+
+# Architecture to build for (x86, x64, armv7m, xtensa, xtensawin)
+ARCH = x64
+
+# Include to get the rules for compiling and linking the module
+include $(MPY_DIR)/py/dynruntime.mk
diff --git a/examples/natmod/features1/features1.c b/examples/natmod/features1/features1.c
new file mode 100644
index 0000000000..f865f1887c
--- /dev/null
+++ b/examples/natmod/features1/features1.c
@@ -0,0 +1,106 @@
+/* This example demonstrates the following features in a native module:
+ - defining simple functions exposed to Python
+ - defining local, helper C functions
+ - defining constant integers and strings exposed to Python
+ - getting and creating integer objects
+ - creating Python lists
+ - raising exceptions
+ - allocating memory
+ - BSS and constant data (rodata)
+ - relocated pointers in rodata
+*/
+
+// Include the header file to get access to the MicroPython API
+#include "py/dynruntime.h"
+
+// BSS (zero) data
+uint16_t data16[4];
+
+// Constant data (rodata)
+const uint8_t table8[] = { 0, 1, 1, 2, 3, 5, 8, 13 };
+const uint16_t table16[] = { 0x1000, 0x2000 };
+
+// Constant data pointing to BSS/constant data
+uint16_t *const table_ptr16a[] = { &data16[0], &data16[1], &data16[2], &data16[3] };
+const uint16_t *const table_ptr16b[] = { &table16[0], &table16[1] };
+
+// A simple function that adds its 2 arguments (must be integers)
+STATIC mp_obj_t add(mp_obj_t x_in, mp_obj_t y_in) {
+ mp_int_t x = mp_obj_get_int(x_in);
+ mp_int_t y = mp_obj_get_int(y_in);
+ return mp_obj_new_int(x + y);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(add_obj, add);
+
+// A local helper function (not exposed to Python)
+STATIC mp_int_t fibonacci_helper(mp_int_t x) {
+ if (x < MP_ARRAY_SIZE(table8)) {
+ return table8[x];
+ } else {
+ return fibonacci_helper(x - 1) + fibonacci_helper(x - 2);
+ }
+}
+
+// A function which computes Fibonacci numbers
+STATIC mp_obj_t fibonacci(mp_obj_t x_in) {
+ mp_int_t x = mp_obj_get_int(x_in);
+ if (x < 0) {
+ mp_raise_ValueError(MP_ERROR_TEXT("can't compute negative Fibonacci number"));
+ }
+ return mp_obj_new_int(fibonacci_helper(x));
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(fibonacci_obj, fibonacci);
+
+// A function that accesses the BSS data
+STATIC mp_obj_t access(size_t n_args, const mp_obj_t *args) {
+ if (n_args == 0) {
+ // Create a list holding all items from data16
+ mp_obj_list_t *lst = MP_OBJ_TO_PTR(mp_obj_new_list(MP_ARRAY_SIZE(data16), NULL));
+ for (int i = 0; i < MP_ARRAY_SIZE(data16); ++i) {
+ lst->items[i] = mp_obj_new_int(data16[i]);
+ }
+ return MP_OBJ_FROM_PTR(lst);
+ } else if (n_args == 1) {
+ // Get one item from data16
+ mp_int_t idx = mp_obj_get_int(args[0]) & 3;
+ return mp_obj_new_int(data16[idx]);
+ } else {
+ // Set one item in data16 (via table_ptr16a)
+ mp_int_t idx = mp_obj_get_int(args[0]) & 3;
+ *table_ptr16a[idx] = mp_obj_get_int(args[1]);
+ return mp_const_none;
+ }
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(access_obj, 0, 2, access);
+
+// A function that allocates memory and creates a bytearray
+STATIC mp_obj_t make_array(void) {
+ uint16_t *ptr = m_new(uint16_t, MP_ARRAY_SIZE(table_ptr16b));
+ for (int i = 0; i < MP_ARRAY_SIZE(table_ptr16b); ++i) {
+ ptr[i] = *table_ptr16b[i];
+ }
+ return mp_obj_new_bytearray_by_ref(sizeof(uint16_t) * MP_ARRAY_SIZE(table_ptr16b), ptr);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_0(make_array_obj, make_array);
+
+// This is the entry point and is called when the module is imported
+mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) {
+ // This must be first, it sets up the globals dict and other things
+ MP_DYNRUNTIME_INIT_ENTRY
+
+ // Messages can be printed as usualy
+ mp_printf(&mp_plat_print, "initialising module self=%p\n", self);
+
+ // Make the functions available in the module's namespace
+ mp_store_global(MP_QSTR_add, MP_OBJ_FROM_PTR(&add_obj));
+ mp_store_global(MP_QSTR_fibonacci, MP_OBJ_FROM_PTR(&fibonacci_obj));
+ mp_store_global(MP_QSTR_access, MP_OBJ_FROM_PTR(&access_obj));
+ mp_store_global(MP_QSTR_make_array, MP_OBJ_FROM_PTR(&make_array_obj));
+
+ // Add some constants to the module's namespace
+ mp_store_global(MP_QSTR_VAL, MP_OBJ_NEW_SMALL_INT(42));
+ mp_store_global(MP_QSTR_MSG, MP_OBJ_NEW_QSTR(MP_QSTR_HELLO_MICROPYTHON));
+
+ // This must be last, it restores the globals dict
+ MP_DYNRUNTIME_INIT_EXIT
+}
diff --git a/examples/natmod/features2/Makefile b/examples/natmod/features2/Makefile
new file mode 100644
index 0000000000..4fd23c6879
--- /dev/null
+++ b/examples/natmod/features2/Makefile
@@ -0,0 +1,14 @@
+# Location of top-level MicroPython directory
+MPY_DIR = ../../..
+
+# Name of module
+MOD = features2
+
+# Source files (.c or .py)
+SRC = main.c prod.c test.py
+
+# Architecture to build for (x86, x64, armv7m, xtensa, xtensawin)
+ARCH = x64
+
+# Include to get the rules for compiling and linking the module
+include $(MPY_DIR)/py/dynruntime.mk
diff --git a/examples/natmod/features2/main.c b/examples/natmod/features2/main.c
new file mode 100644
index 0000000000..1a39700dc4
--- /dev/null
+++ b/examples/natmod/features2/main.c
@@ -0,0 +1,83 @@
+/* This example demonstrates the following features in a native module:
+ - using floats
+ - defining additional code in Python (see test.py)
+ - have extra C code in a separate file (see prod.c)
+*/
+
+// Include the header file to get access to the MicroPython API
+#include "py/dynruntime.h"
+
+// Include the header for auxiliary C code for this module
+#include "prod.h"
+
+// Automatically detect if this module should include double-precision code.
+// If double precision is supported by the target architecture then it can
+// be used in native module regardless of what float setting the target
+// MicroPython runtime uses (being none, float or double).
+#if defined(__i386__) || defined(__x86_64__) || (defined(__ARM_FP) && (__ARM_FP & 8))
+#define USE_DOUBLE 1
+#else
+#define USE_DOUBLE 0
+#endif
+
+// A function that uses the default float type configured for the current target
+// This default can be overridden by specifying MICROPY_FLOAT_IMPL at the make level
+STATIC mp_obj_t add(mp_obj_t x, mp_obj_t y) {
+ return mp_obj_new_float(mp_obj_get_float(x) + mp_obj_get_float(y));
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(add_obj, add);
+
+// A function that explicitly uses single precision floats
+STATIC mp_obj_t add_f(mp_obj_t x, mp_obj_t y) {
+ return mp_obj_new_float_from_f(mp_obj_get_float_to_f(x) + mp_obj_get_float_to_f(y));
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(add_f_obj, add_f);
+
+#if USE_DOUBLE
+// A function that explicitly uses double precision floats
+STATIC mp_obj_t add_d(mp_obj_t x, mp_obj_t y) {
+ return mp_obj_new_float_from_d(mp_obj_get_float_to_d(x) + mp_obj_get_float_to_d(y));
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(add_d_obj, add_d);
+#endif
+
+// A function that computes the product of floats in an array.
+// This function uses the most general C argument interface, which is more difficult
+// to use but has access to the globals dict of the module via self->globals.
+STATIC mp_obj_t productf(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) {
+ // Check number of arguments is valid
+ mp_arg_check_num(n_args, n_kw, 1, 1, false);
+
+ // Extract buffer pointer and verify typecode
+ mp_buffer_info_t bufinfo;
+ mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_RW);
+ if (bufinfo.typecode != 'f') {
+ mp_raise_ValueError(MP_ERROR_TEXT("expecting float array"));
+ }
+
+ // Compute product, store result back in first element of array
+ float *ptr = bufinfo.buf;
+ float prod = prod_array(bufinfo.len / sizeof(*ptr), ptr);
+ ptr[0] = prod;
+
+ return mp_const_none;
+}
+
+// This is the entry point and is called when the module is imported
+mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) {
+ // This must be first, it sets up the globals dict and other things
+ MP_DYNRUNTIME_INIT_ENTRY
+
+ // Make the functions available in the module's namespace
+ mp_store_global(MP_QSTR_add, MP_OBJ_FROM_PTR(&add_obj));
+ mp_store_global(MP_QSTR_add_f, MP_OBJ_FROM_PTR(&add_f_obj));
+ #if USE_DOUBLE
+ mp_store_global(MP_QSTR_add_d, MP_OBJ_FROM_PTR(&add_d_obj));
+ #endif
+
+ // The productf function uses the most general C argument interface
+ mp_store_global(MP_QSTR_productf, MP_DYNRUNTIME_MAKE_FUNCTION(productf));
+
+ // This must be last, it restores the globals dict
+ MP_DYNRUNTIME_INIT_EXIT
+}
diff --git a/examples/natmod/features2/prod.c b/examples/natmod/features2/prod.c
new file mode 100644
index 0000000000..7791dcad1d
--- /dev/null
+++ b/examples/natmod/features2/prod.c
@@ -0,0 +1,9 @@
+#include "prod.h"
+
+float prod_array(int n, float *ar) {
+ float ans = 1;
+ for (int i = 0; i < n; ++i) {
+ ans *= ar[i];
+ }
+ return ans;
+}
diff --git a/examples/natmod/features2/prod.h b/examples/natmod/features2/prod.h
new file mode 100644
index 0000000000..f27dd8d033
--- /dev/null
+++ b/examples/natmod/features2/prod.h
@@ -0,0 +1 @@
+float prod_array(int n, float *ar);
diff --git a/examples/natmod/features2/test.py b/examples/natmod/features2/test.py
new file mode 100644
index 0000000000..5ac80120d7
--- /dev/null
+++ b/examples/natmod/features2/test.py
@@ -0,0 +1,29 @@
+# This Python code will be merged with the C code in main.c
+
+import array
+
+
+def isclose(a, b):
+ return abs(a - b) < 1e-3
+
+
+def test():
+ tests = [
+ isclose(add(0.1, 0.2), 0.3),
+ isclose(add_f(0.1, 0.2), 0.3),
+ ]
+
+ ar = array.array("f", [1, 2, 3.5])
+ productf(ar)
+ tests.append(isclose(ar[0], 7))
+
+ if "add_d" in globals():
+ tests.append(isclose(add_d(0.1, 0.2), 0.3))
+
+ print(tests)
+
+ if not all(tests):
+ raise SystemExit(1)
+
+
+test()
diff --git a/examples/natmod/framebuf/Makefile b/examples/natmod/framebuf/Makefile
new file mode 100644
index 0000000000..2e2b815975
--- /dev/null
+++ b/examples/natmod/framebuf/Makefile
@@ -0,0 +1,13 @@
+# Location of top-level MicroPython directory
+MPY_DIR = ../../..
+
+# Name of module (different to built-in framebuf so it can coexist)
+MOD = framebuf_$(ARCH)
+
+# Source files (.c or .py)
+SRC = framebuf.c
+
+# Architecture to build for (x86, x64, armv7m, xtensa, xtensawin)
+ARCH = x64
+
+include $(MPY_DIR)/py/dynruntime.mk
diff --git a/examples/natmod/framebuf/framebuf.c b/examples/natmod/framebuf/framebuf.c
new file mode 100644
index 0000000000..8d488cffd6
--- /dev/null
+++ b/examples/natmod/framebuf/framebuf.c
@@ -0,0 +1,49 @@
+#define MICROPY_PY_FRAMEBUF (1)
+
+#include "py/dynruntime.h"
+
+#if !defined(__linux__)
+void *memset(void *s, int c, size_t n) {
+ return mp_fun_table.memset_(s, c, n);
+}
+#endif
+
+mp_obj_type_t mp_type_framebuf;
+
+#include "extmod/modframebuf.c"
+
+mp_map_elem_t framebuf_locals_dict_table[10];
+STATIC MP_DEFINE_CONST_DICT(framebuf_locals_dict, framebuf_locals_dict_table);
+
+mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) {
+ MP_DYNRUNTIME_INIT_ENTRY
+
+ mp_type_framebuf.base.type = (void*)&mp_type_type;
+ mp_type_framebuf.name = MP_QSTR_FrameBuffer;
+ mp_type_framebuf.make_new = framebuf_make_new;
+ mp_type_framebuf.buffer_p.get_buffer = framebuf_get_buffer;
+ framebuf_locals_dict_table[0] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_fill), MP_OBJ_FROM_PTR(&framebuf_fill_obj) };
+ framebuf_locals_dict_table[1] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_fill_rect), MP_OBJ_FROM_PTR(&framebuf_fill_rect_obj) };
+ framebuf_locals_dict_table[2] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_pixel), MP_OBJ_FROM_PTR(&framebuf_pixel_obj) };
+ framebuf_locals_dict_table[3] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_hline), MP_OBJ_FROM_PTR(&framebuf_hline_obj) };
+ framebuf_locals_dict_table[4] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_vline), MP_OBJ_FROM_PTR(&framebuf_vline_obj) };
+ framebuf_locals_dict_table[5] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_rect), MP_OBJ_FROM_PTR(&framebuf_rect_obj) };
+ framebuf_locals_dict_table[6] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_line), MP_OBJ_FROM_PTR(&framebuf_line_obj) };
+ framebuf_locals_dict_table[7] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_blit), MP_OBJ_FROM_PTR(&framebuf_blit_obj) };
+ framebuf_locals_dict_table[8] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_scroll), MP_OBJ_FROM_PTR(&framebuf_scroll_obj) };
+ framebuf_locals_dict_table[9] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_text), MP_OBJ_FROM_PTR(&framebuf_text_obj) };
+ mp_type_framebuf.locals_dict = (void*)&framebuf_locals_dict;
+
+ mp_store_global(MP_QSTR_FrameBuffer, MP_OBJ_FROM_PTR(&mp_type_framebuf));
+ mp_store_global(MP_QSTR_FrameBuffer1, MP_OBJ_FROM_PTR(&legacy_framebuffer1_obj));
+ mp_store_global(MP_QSTR_MVLSB, MP_OBJ_NEW_SMALL_INT(FRAMEBUF_MVLSB));
+ mp_store_global(MP_QSTR_MONO_VLSB, MP_OBJ_NEW_SMALL_INT(FRAMEBUF_MVLSB));
+ mp_store_global(MP_QSTR_RGB565, MP_OBJ_NEW_SMALL_INT(FRAMEBUF_RGB565));
+ mp_store_global(MP_QSTR_GS2_HMSB, MP_OBJ_NEW_SMALL_INT(FRAMEBUF_GS2_HMSB));
+ mp_store_global(MP_QSTR_GS4_HMSB, MP_OBJ_NEW_SMALL_INT(FRAMEBUF_GS4_HMSB));
+ mp_store_global(MP_QSTR_GS8, MP_OBJ_NEW_SMALL_INT(FRAMEBUF_GS8));
+ mp_store_global(MP_QSTR_MONO_HLSB, MP_OBJ_NEW_SMALL_INT(FRAMEBUF_MHLSB));
+ mp_store_global(MP_QSTR_MONO_HMSB, MP_OBJ_NEW_SMALL_INT(FRAMEBUF_MHMSB));
+
+ MP_DYNRUNTIME_INIT_EXIT
+}
diff --git a/examples/natmod/uheapq/Makefile b/examples/natmod/uheapq/Makefile
new file mode 100644
index 0000000000..55de3cc081
--- /dev/null
+++ b/examples/natmod/uheapq/Makefile
@@ -0,0 +1,13 @@
+# Location of top-level MicroPython directory
+MPY_DIR = ../../..
+
+# Name of module (different to built-in uheapq so it can coexist)
+MOD = uheapq_$(ARCH)
+
+# Source files (.c or .py)
+SRC = uheapq.c
+
+# Architecture to build for (x86, x64, armv7m, xtensa, xtensawin)
+ARCH = x64
+
+include $(MPY_DIR)/py/dynruntime.mk
diff --git a/examples/natmod/uheapq/uheapq.c b/examples/natmod/uheapq/uheapq.c
new file mode 100644
index 0000000000..9da6bb4ada
--- /dev/null
+++ b/examples/natmod/uheapq/uheapq.c
@@ -0,0 +1,16 @@
+#define MICROPY_PY_UHEAPQ (1)
+
+#include "py/dynruntime.h"
+
+#include "extmod/moduheapq.c"
+
+mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) {
+ MP_DYNRUNTIME_INIT_ENTRY
+
+ mp_store_global(MP_QSTR___name__, MP_OBJ_NEW_QSTR(MP_QSTR_uheapq));
+ mp_store_global(MP_QSTR_heappush, MP_OBJ_FROM_PTR(&mod_uheapq_heappush_obj));
+ mp_store_global(MP_QSTR_heappop, MP_OBJ_FROM_PTR(&mod_uheapq_heappop_obj));
+ mp_store_global(MP_QSTR_heapify, MP_OBJ_FROM_PTR(&mod_uheapq_heapify_obj));
+
+ MP_DYNRUNTIME_INIT_EXIT
+}
diff --git a/examples/natmod/urandom/Makefile b/examples/natmod/urandom/Makefile
new file mode 100644
index 0000000000..3f018baaf7
--- /dev/null
+++ b/examples/natmod/urandom/Makefile
@@ -0,0 +1,13 @@
+# Location of top-level MicroPython directory
+MPY_DIR = ../../..
+
+# Name of module (different to built-in urandom so it can coexist)
+MOD = urandom_$(ARCH)
+
+# Source files (.c or .py)
+SRC = urandom.c
+
+# Architecture to build for (x86, x64, armv7m, xtensa, xtensawin)
+ARCH = x64
+
+include $(MPY_DIR)/py/dynruntime.mk
diff --git a/examples/natmod/urandom/urandom.c b/examples/natmod/urandom/urandom.c
new file mode 100644
index 0000000000..e1fed6a554
--- /dev/null
+++ b/examples/natmod/urandom/urandom.c
@@ -0,0 +1,33 @@
+#define MICROPY_PY_URANDOM (1)
+#define MICROPY_PY_URANDOM_EXTRA_FUNCS (1)
+
+#include "py/dynruntime.h"
+
+// Dynamic native modules don't support a data section so these must go in the BSS
+uint32_t yasmarang_pad, yasmarang_n, yasmarang_d;
+uint8_t yasmarang_dat;
+
+#include "extmod/modurandom.c"
+
+mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) {
+ MP_DYNRUNTIME_INIT_ENTRY
+
+ yasmarang_pad = 0xeda4baba;
+ yasmarang_n = 69;
+ yasmarang_d = 233;
+
+ mp_store_global(MP_QSTR___name__, MP_OBJ_NEW_QSTR(MP_QSTR_urandom));
+ mp_store_global(MP_QSTR_getrandbits, MP_OBJ_FROM_PTR(&mod_urandom_getrandbits_obj));
+ mp_store_global(MP_QSTR_seed, MP_OBJ_FROM_PTR(&mod_urandom_seed_obj));
+ #if MICROPY_PY_URANDOM_EXTRA_FUNCS
+ mp_store_global(MP_QSTR_randrange, MP_OBJ_FROM_PTR(&mod_urandom_randrange_obj));
+ mp_store_global(MP_QSTR_randint, MP_OBJ_FROM_PTR(&mod_urandom_randint_obj));
+ mp_store_global(MP_QSTR_choice, MP_OBJ_FROM_PTR(&mod_urandom_choice_obj));
+ #if MICROPY_PY_BUILTINS_FLOAT
+ mp_store_global(MP_QSTR_random, MP_OBJ_FROM_PTR(&mod_urandom_random_obj));
+ mp_store_global(MP_QSTR_uniform, MP_OBJ_FROM_PTR(&mod_urandom_uniform_obj));
+ #endif
+ #endif
+
+ MP_DYNRUNTIME_INIT_EXIT
+}
diff --git a/examples/natmod/ure/Makefile b/examples/natmod/ure/Makefile
new file mode 100644
index 0000000000..f5254298fd
--- /dev/null
+++ b/examples/natmod/ure/Makefile
@@ -0,0 +1,13 @@
+# Location of top-level MicroPython directory
+MPY_DIR = ../../..
+
+# Name of module (different to built-in ure so it can coexist)
+MOD = ure_$(ARCH)
+
+# Source files (.c or .py)
+SRC = ure.c
+
+# Architecture to build for (x86, x64, armv7m, xtensa, xtensawin)
+ARCH = x64
+
+include $(MPY_DIR)/py/dynruntime.mk
diff --git a/examples/natmod/ure/ure.c b/examples/natmod/ure/ure.c
new file mode 100644
index 0000000000..175b93e395
--- /dev/null
+++ b/examples/natmod/ure/ure.c
@@ -0,0 +1,78 @@
+#define MICROPY_STACK_CHECK (1)
+#define MICROPY_PY_URE (1)
+#define MICROPY_PY_URE_MATCH_GROUPS (1)
+#define MICROPY_PY_URE_MATCH_SPAN_START_END (1)
+#define MICROPY_PY_URE_SUB (0) // requires vstr interface
+
+#include
+#include "py/dynruntime.h"
+
+#define STACK_LIMIT (2048)
+
+const char *stack_top;
+
+void mp_stack_check(void) {
+ // Assumes descending stack on target
+ volatile char dummy;
+ if (stack_top - &dummy >= STACK_LIMIT) {
+ mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("maximum recursion depth exceeded"));
+ }
+}
+
+#if !defined(__linux__)
+void *memcpy(void *dst, const void *src, size_t n) {
+ return mp_fun_table.memmove_(dst, src, n);
+}
+void *memset(void *s, int c, size_t n) {
+ return mp_fun_table.memset_(s, c, n);
+}
+#endif
+
+void *memmove(void *dest, const void *src, size_t n) {
+ return mp_fun_table.memmove_(dest, src, n);
+}
+
+mp_obj_type_t match_type;
+mp_obj_type_t re_type;
+
+#include "extmod/modure.c"
+
+mp_map_elem_t match_locals_dict_table[5];
+STATIC MP_DEFINE_CONST_DICT(match_locals_dict, match_locals_dict_table);
+
+mp_map_elem_t re_locals_dict_table[3];
+STATIC MP_DEFINE_CONST_DICT(re_locals_dict, re_locals_dict_table);
+
+mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) {
+ MP_DYNRUNTIME_INIT_ENTRY
+
+ char dummy;
+ stack_top = &dummy;
+
+ // Because MP_QSTR_start/end/split are static, xtensa and xtensawin will make a small data section
+ // to copy in this key/value pair if they are specified as a struct, so assign them separately.
+
+ match_type.base.type = (void*)&mp_fun_table.type_type;
+ match_type.name = MP_QSTR_match;
+ match_type.print = match_print;
+ match_locals_dict_table[0] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_group), MP_OBJ_FROM_PTR(&match_group_obj) };
+ match_locals_dict_table[1] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_groups), MP_OBJ_FROM_PTR(&match_groups_obj) };
+ match_locals_dict_table[2] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_span), MP_OBJ_FROM_PTR(&match_span_obj) };
+ match_locals_dict_table[3] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_start), MP_OBJ_FROM_PTR(&match_start_obj) };
+ match_locals_dict_table[4] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_end), MP_OBJ_FROM_PTR(&match_end_obj) };
+ match_type.locals_dict = (void*)&match_locals_dict;
+
+ re_type.base.type = (void*)&mp_fun_table.type_type;
+ re_type.name = MP_QSTR_ure;
+ re_type.print = re_print;
+ re_locals_dict_table[0] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_match), MP_OBJ_FROM_PTR(&re_match_obj) };
+ re_locals_dict_table[1] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_search), MP_OBJ_FROM_PTR(&re_search_obj) };
+ re_locals_dict_table[2] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_split), MP_OBJ_FROM_PTR(&re_split_obj) };
+ re_type.locals_dict = (void*)&re_locals_dict;
+
+ mp_store_global(MP_QSTR_compile, MP_OBJ_FROM_PTR(&mod_re_compile_obj));
+ mp_store_global(MP_QSTR_match, MP_OBJ_FROM_PTR(&re_match_obj));
+ mp_store_global(MP_QSTR_search, MP_OBJ_FROM_PTR(&re_search_obj));
+
+ MP_DYNRUNTIME_INIT_EXIT
+}
diff --git a/examples/natmod/uzlib/Makefile b/examples/natmod/uzlib/Makefile
new file mode 100644
index 0000000000..8761caf2dd
--- /dev/null
+++ b/examples/natmod/uzlib/Makefile
@@ -0,0 +1,13 @@
+# Location of top-level MicroPython directory
+MPY_DIR = ../../..
+
+# Name of module (different to built-in uzlib so it can coexist)
+MOD = uzlib_$(ARCH)
+
+# Source files (.c or .py)
+SRC = uzlib.c
+
+# Architecture to build for (x86, x64, armv7m, xtensa, xtensawin)
+ARCH = x64
+
+include $(MPY_DIR)/py/dynruntime.mk
diff --git a/examples/natmod/uzlib/uzlib.c b/examples/natmod/uzlib/uzlib.c
new file mode 100644
index 0000000000..99b3691761
--- /dev/null
+++ b/examples/natmod/uzlib/uzlib.c
@@ -0,0 +1,35 @@
+#define MICROPY_PY_UZLIB (1)
+
+#include "py/dynruntime.h"
+
+#if !defined(__linux__)
+void *memset(void *s, int c, size_t n) {
+ return mp_fun_table.memset_(s, c, n);
+}
+#endif
+
+mp_obj_type_t decompio_type;
+
+#include "extmod/moduzlib.c"
+
+mp_map_elem_t decompio_locals_dict_table[3];
+STATIC MP_DEFINE_CONST_DICT(decompio_locals_dict, decompio_locals_dict_table);
+
+mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) {
+ MP_DYNRUNTIME_INIT_ENTRY
+
+ decompio_type.base.type = mp_fun_table.type_type;
+ decompio_type.name = MP_QSTR_DecompIO;
+ decompio_type.make_new = decompio_make_new;
+ decompio_type.protocol = &decompio_stream_p;
+ decompio_locals_dict_table[0] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_read), MP_OBJ_FROM_PTR(&mp_stream_read_obj) };
+ decompio_locals_dict_table[1] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_readinto), MP_OBJ_FROM_PTR(&mp_stream_readinto_obj) };
+ decompio_locals_dict_table[2] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_readline), MP_OBJ_FROM_PTR(&mp_stream_unbuffered_readline_obj) };
+ decompio_type.locals_dict = (void*)&decompio_locals_dict;
+
+ mp_store_global(MP_QSTR___name__, MP_OBJ_NEW_QSTR(MP_QSTR_uzlib));
+ mp_store_global(MP_QSTR_decompress, MP_OBJ_FROM_PTR(&mod_uzlib_decompress_obj));
+ mp_store_global(MP_QSTR_DecompIO, MP_OBJ_FROM_PTR(&decompio_type));
+
+ MP_DYNRUNTIME_INIT_EXIT
+}
diff --git a/examples/network/http_client.py b/examples/network/http_client.py
index b245a721ac..0791c8066b 100644
--- a/examples/network/http_client.py
+++ b/examples/network/http_client.py
@@ -19,7 +19,7 @@ def main(use_stream=False):
# directly, but the line below is needed for CPython.
s = s.makefile("rwb", 0)
s.write(b"GET / HTTP/1.0\r\n\r\n")
- print(s.readall())
+ print(s.read())
else:
s.send(b"GET / HTTP/1.0\r\n\r\n")
print(s.recv(4096))
diff --git a/examples/network/http_server.py b/examples/network/http_server.py
index e3a66e8283..76be3ab817 100644
--- a/examples/network/http_server.py
+++ b/examples/network/http_server.py
@@ -10,6 +10,7 @@
Hello #%d from MicroPython!
"""
+
def main(micropython_optimize=False):
s = socket.socket()
diff --git a/examples/network/http_server_simplistic.py b/examples/network/http_server_simplistic.py
index 67ecb1ad7a..71949419e6 100644
--- a/examples/network/http_server_simplistic.py
+++ b/examples/network/http_server_simplistic.py
@@ -12,6 +12,7 @@
Hello #%d from MicroPython!
"""
+
def main():
s = socket.socket()
ai = socket.getaddrinfo("0.0.0.0", 8080)
diff --git a/examples/network/http_server_simplistic_commented.py b/examples/network/http_server_simplistic_commented.py
index b58e9eeb60..da042c6c8a 100644
--- a/examples/network/http_server_simplistic_commented.py
+++ b/examples/network/http_server_simplistic_commented.py
@@ -20,6 +20,7 @@
Hello #%d from MicroPython!
"""
+
def main():
s = socket.socket()
diff --git a/examples/network/http_server_ssl.py b/examples/network/http_server_ssl.py
index 9a69ca9d41..1116c71e99 100644
--- a/examples/network/http_server_ssl.py
+++ b/examples/network/http_server_ssl.py
@@ -1,3 +1,5 @@
+import ubinascii as binascii
+
try:
import usocket as socket
except:
@@ -5,12 +7,44 @@
import ussl as ssl
+# This self-signed key/cert pair is randomly generated and to be used for
+# testing/demonstration only. You should always generate your own key/cert.
+key = binascii.unhexlify(
+ b"3082013b020100024100cc20643fd3d9c21a0acba4f48f61aadd675f52175a9dcf07fbef"
+ b"610a6a6ba14abb891745cd18a1d4c056580d8ff1a639460f867013c8391cdc9f2e573b0f"
+ b"872d0203010001024100bb17a54aeb3dd7ae4edec05e775ca9632cf02d29c2a089b563b0"
+ b"d05cdf95aeca507de674553f28b4eadaca82d5549a86058f9996b07768686a5b02cb240d"
+ b"d9f1022100f4a63f5549e817547dca97b5c658038e8593cb78c5aba3c4642cc4cd031d86"
+ b"8f022100d598d870ffe4a34df8de57047a50b97b71f4d23e323f527837c9edae88c79483"
+ b"02210098560c89a70385c36eb07fd7083235c4c1184e525d838aedf7128958bedfdbb102"
+ b"2051c0dab7057a8176ca966f3feb81123d4974a733df0f958525f547dfd1c271f9022044"
+ b"6c2cafad455a671a8cf398e642e1be3b18a3d3aec2e67a9478f83c964c4f1f"
+)
+cert = binascii.unhexlify(
+ b"308201d53082017f020203e8300d06092a864886f70d01010505003075310b3009060355"
+ b"0406130258583114301206035504080c0b54686550726f76696e63653110300e06035504"
+ b"070c075468654369747931133011060355040a0c0a436f6d70616e7958595a3113301106"
+ b"0355040b0c0a436f6d70616e7958595a3114301206035504030c0b546865486f73744e61"
+ b"6d65301e170d3139313231383033333935355a170d3239313231353033333935355a3075"
+ b"310b30090603550406130258583114301206035504080c0b54686550726f76696e636531"
+ b"10300e06035504070c075468654369747931133011060355040a0c0a436f6d70616e7958"
+ b"595a31133011060355040b0c0a436f6d70616e7958595a3114301206035504030c0b5468"
+ b"65486f73744e616d65305c300d06092a864886f70d0101010500034b003048024100cc20"
+ b"643fd3d9c21a0acba4f48f61aadd675f52175a9dcf07fbef610a6a6ba14abb891745cd18"
+ b"a1d4c056580d8ff1a639460f867013c8391cdc9f2e573b0f872d0203010001300d06092a"
+ b"864886f70d0101050500034100b0513fe2829e9ecbe55b6dd14c0ede7502bde5d46153c8"
+ b"e960ae3ebc247371b525caeb41bbcf34686015a44c50d226e66aef0a97a63874ca5944ef"
+ b"979b57f0b3"
+)
+
+
CONTENT = b"""\
HTTP/1.0 200 OK
Hello #%d from MicroPython!
"""
+
def main(use_stream=True):
s = socket.socket()
@@ -31,7 +65,8 @@ def main(use_stream=True):
client_addr = res[1]
print("Client address:", client_addr)
print("Client socket:", client_s)
- client_s = ssl.wrap_socket(client_s, server_side=True)
+ # CPython uses key keyfile/certfile arguments, but MicroPython uses key/cert
+ client_s = ssl.wrap_socket(client_s, server_side=True, key=key, cert=cert)
print(client_s)
print("Request:")
if use_stream:
diff --git a/examples/pins.py b/examples/pins.py
index ab359f6921..3a8472e8a6 100644
--- a/examples/pins.py
+++ b/examples/pins.py
@@ -1,9 +1,10 @@
# Print a nice list of pins, their current settings, and available afs.
-# Requires pins_af.py from stmhal/build-PYBV10/ directory.
+# Requires pins_af.py from ports/stm32/build-PYBV10/ directory.
import pyb
import pins_af
+
def af():
max_name_width = 0
max_af_width = 0
@@ -13,21 +14,22 @@ def af():
max_af_width = max(max_af_width, len(af_entry[1]))
for pin_entry in pins_af.PINS_AF:
pin_name = pin_entry[0]
- print('%-*s ' % (max_name_width, pin_name), end='')
+ print("%-*s " % (max_name_width, pin_name), end="")
for af_entry in pin_entry[1:]:
- print('%2d: %-*s ' % (af_entry[0], max_af_width, af_entry[1]), end='')
- print('')
+ print("%2d: %-*s " % (af_entry[0], max_af_width, af_entry[1]), end="")
+ print("")
+
def pins():
- mode_str = { pyb.Pin.IN : 'IN',
- pyb.Pin.OUT_PP : 'OUT_PP',
- pyb.Pin.OUT_OD : 'OUT_OD',
- pyb.Pin.AF_PP : 'AF_PP',
- pyb.Pin.AF_OD : 'AF_OD',
- pyb.Pin.ANALOG : 'ANALOG' }
- pull_str = { pyb.Pin.PULL_NONE : '',
- pyb.Pin.PULL_UP : 'PULL_UP',
- pyb.Pin.PULL_DOWN : 'PULL_DOWN' }
+ mode_str = {
+ pyb.Pin.IN: "IN",
+ pyb.Pin.OUT_PP: "OUT_PP",
+ pyb.Pin.OUT_OD: "OUT_OD",
+ pyb.Pin.AF_PP: "AF_PP",
+ pyb.Pin.AF_OD: "AF_OD",
+ pyb.Pin.ANALOG: "ANALOG",
+ }
+ pull_str = {pyb.Pin.PULL_NONE: "", pyb.Pin.PULL_UP: "PULL_UP", pyb.Pin.PULL_DOWN: "PULL_DOWN"}
width = [0, 0, 0, 0]
rows = []
for pin_entry in pins_af.PINS_AF:
@@ -42,17 +44,17 @@ def pins():
pin_af = pin.af()
for af_entry in pin_entry[1:]:
if pin_af == af_entry[0]:
- af_str = '%d: %s' % (pin_af, af_entry[1])
+ af_str = "%d: %s" % (pin_af, af_entry[1])
break
else:
- af_str = '%d' % pin_af
+ af_str = "%d" % pin_af
else:
- af_str = ''
+ af_str = ""
row.append(af_str)
for col in range(len(width)):
width[col] = max(width[col], len(row[col]))
rows.append(row)
for row in rows:
for col in range(len(width)):
- print('%-*s ' % (width[col], row[col]), end='')
- print('')
+ print("%-*s " % (width[col], row[col]), end="")
+ print("")
diff --git a/examples/pyb.py b/examples/pyb.py
index b303777e5a..67620e793a 100644
--- a/examples/pyb.py
+++ b/examples/pyb.py
@@ -1,17 +1,22 @@
# pyboard testing functions for CPython
import time
+
def delay(n):
- #time.sleep(float(n) / 1000)
+ # time.sleep(float(n) / 1000)
pass
+
rand_seed = 1
+
+
def rng():
global rand_seed
# for these choice of numbers, see P L'Ecuyer, "Tables of linear congruential generators of different sizes and good lattice structure"
rand_seed = (rand_seed * 653276) % 8388593
return rand_seed
+
# LCD testing object for PC
# uses double buffering
class LCD:
@@ -30,12 +35,12 @@ def fill(self, value):
self.buf1[y][x] = self.buf2[y][x] = value
def show(self):
- print('') # blank line to separate frames
+ print("") # blank line to separate frames
for y in range(self.height):
for x in range(self.width):
self.buf1[y][x] = self.buf2[y][x]
for y in range(self.height):
- row = ''.join(['*' if self.buf1[y][x] else ' ' for x in range(self.width)])
+ row = "".join(["*" if self.buf1[y][x] else " " for x in range(self.width)])
print(row)
def get(self, x, y):
diff --git a/examples/switch.py b/examples/switch.py
index 0efaf22675..c099a35298 100644
--- a/examples/switch.py
+++ b/examples/switch.py
@@ -24,6 +24,7 @@
blue_led = pyb.LED(4)
all_leds = (red_led, green_led, orange_led, blue_led)
+
def run_loop(leds=all_leds):
"""
Start the loop.
@@ -31,15 +32,16 @@ def run_loop(leds=all_leds):
:param `leds`: Which LEDs to light up upon switch press.
:type `leds`: sequence of LED objects
"""
- print('Loop started.\nPress Ctrl+C to break out of the loop.')
+ print("Loop started.\nPress Ctrl+C to break out of the loop.")
while 1:
try:
if switch():
[led.on() for led in leds]
else:
[led.off() for led in leds]
- except OSError: # VCPInterrupt # Ctrl+C in interpreter mode.
+ except OSError: # VCPInterrupt # Ctrl+C in interpreter mode.
break
-if __name__ == '__main__':
+
+if __name__ == "__main__":
run_loop()
diff --git a/examples/unix/ffi_example.py b/examples/unix/ffi_example.py
index f650e33708..a8f02c766e 100644
--- a/examples/unix/ffi_example.py
+++ b/examples/unix/ffi_example.py
@@ -1,4 +1,5 @@
import ffi
+import uctypes
libc = ffi.open("libc.so.6")
print("libc:", libc)
@@ -8,7 +9,7 @@
perror = libc.func("v", "perror", "s")
time = libc.func("i", "time", "p")
open = libc.func("i", "open", "si")
-qsort = libc.func("v", "qsort", "piip")
+qsort = libc.func("v", "qsort", "piiC")
# And one variable
errno = libc.var("i", "errno")
@@ -16,23 +17,25 @@
print("UNIX time is:", time(None))
print()
-perror("ffi before error")
+perror("perror before error")
open("somethingnonexistent__", 0)
print("errno object:", errno)
print("errno value:", errno.get())
-perror("ffi after error")
+perror("perror after error")
print()
+
def cmp(pa, pb):
- a = ffi.as_bytearray(pa, 1)
- b = ffi.as_bytearray(pb, 1)
+ a = uctypes.bytearray_at(pa, 1)
+ b = uctypes.bytearray_at(pb, 1)
print("cmp:", a, b)
return a[0] - b[0]
-cmp_c = ffi.callback("i", cmp, "pp")
-print("callback:", cmp_c)
+
+cmp_cb = ffi.callback("i", cmp, "PP")
+print("callback:", cmp_cb)
s = bytearray(b"foobar")
print("org string:", s)
-qsort(s, len(s), 1, cmp_c)
+qsort(s, len(s), 1, cmp_cb)
print("qsort'ed string:", s)
diff --git a/examples/unix/machine_bios.py b/examples/unix/machine_bios.py
index f62e4dbdb4..878f3fd8f3 100644
--- a/examples/unix/machine_bios.py
+++ b/examples/unix/machine_bios.py
@@ -6,4 +6,4 @@
import umachine as machine
-print(hex(machine.mem16[0xc0000]))
+print(hex(machine.mem16[0xC0000]))
diff --git a/extmod/btstack/btstack.mk b/extmod/btstack/btstack.mk
new file mode 100644
index 0000000000..dd96e63379
--- /dev/null
+++ b/extmod/btstack/btstack.mk
@@ -0,0 +1,57 @@
+# Makefile directives for BlueKitchen BTstack
+
+ifeq ($(MICROPY_BLUETOOTH_BTSTACK),1)
+
+MICROPY_BLUETOOTH_BTSTACK_USB ?= 0
+
+BTSTACK_EXTMOD_DIR = extmod/btstack
+
+EXTMOD_SRC_C += extmod/btstack/modbluetooth_btstack.c
+
+INC += -I$(TOP)/$(BTSTACK_EXTMOD_DIR)
+
+CFLAGS_MOD += -DMICROPY_BLUETOOTH_BTSTACK=1
+
+BTSTACK_DIR = $(TOP)/lib/btstack
+
+ifneq ($(wildcard $(BTSTACK_DIR)/src),)
+
+include $(BTSTACK_DIR)/src/Makefile.inc
+include $(BTSTACK_DIR)/src/ble/Makefile.inc
+
+INC += -I$(BTSTACK_DIR)/src
+INC += -I$(BTSTACK_DIR)/3rd-party/bluedroid/decoder/include
+INC += -I$(BTSTACK_DIR)/3rd-party/bluedroid/encoder/include
+INC += -I$(BTSTACK_DIR)/3rd-party/md5
+INC += -I$(BTSTACK_DIR)/3rd-party/yxml
+
+SRC_BTSTACK = \
+ $(addprefix lib/btstack/src/, $(SRC_FILES)) \
+ $(addprefix lib/btstack/src/ble/, $(filter-out %_tlv.c, $(SRC_BLE_FILES))) \
+ lib/btstack/platform/embedded/btstack_run_loop_embedded.c
+
+ifeq ($(MICROPY_BLUETOOTH_BTSTACK_USB),1)
+SRC_BTSTACK += \
+ lib/btstack/platform/libusb/hci_transport_h2_libusb.c
+
+CFLAGS += $(shell pkg-config libusb-1.0 --cflags)
+LDFLAGS += $(shell pkg-config libusb-1.0 --libs)
+endif
+
+ifeq ($(MICROPY_BLUETOOTH_BTSTACK_ENABLE_CLASSIC),1)
+include $(BTSTACK_DIR)/src/classic/Makefile.inc
+SRC_BTSTACK += \
+ $(addprefix lib/btstack/src/classic/, $(SRC_CLASSIC_FILES))
+endif
+
+LIB_SRC_C += $(SRC_BTSTACK)
+
+# Suppress some warnings.
+BTSTACK_WARNING_CFLAGS = -Wno-old-style-definition -Wno-unused-variable -Wno-unused-parameter
+ifneq ($(CC),clang)
+BTSTACK_WARNING_CFLAGS += -Wno-format
+endif
+$(BUILD)/lib/btstack/src/%.o: CFLAGS += $(BTSTACK_WARNING_CFLAGS)
+
+endif
+endif
diff --git a/extmod/btstack/btstack_config.h b/extmod/btstack/btstack_config.h
new file mode 100644
index 0000000000..f420f47a5b
--- /dev/null
+++ b/extmod/btstack/btstack_config.h
@@ -0,0 +1,47 @@
+#ifndef MICROPY_INCLUDED_EXTMOD_BTSTACK_BTSTACK_CONFIG_H
+#define MICROPY_INCLUDED_EXTMOD_BTSTACK_BTSTACK_CONFIG_H
+
+// BTstack features that can be enabled
+#define ENABLE_BLE
+#define ENABLE_LE_PERIPHERAL
+#define ENABLE_LE_CENTRAL
+// #define ENABLE_CLASSIC
+#define ENABLE_LE_DATA_CHANNELS
+// #define ENABLE_LOG_INFO
+#define ENABLE_LOG_ERROR
+
+// BTstack configuration. buffers, sizes, ...
+#define HCI_ACL_PAYLOAD_SIZE 1021
+#define MAX_NR_GATT_CLIENTS 1
+#define MAX_NR_HCI_CONNECTIONS 1
+#define MAX_NR_L2CAP_SERVICES 3
+#define MAX_NR_L2CAP_CHANNELS 3
+#define MAX_NR_RFCOMM_MULTIPLEXERS 1
+#define MAX_NR_RFCOMM_SERVICES 1
+#define MAX_NR_RFCOMM_CHANNELS 1
+#define MAX_NR_BTSTACK_LINK_KEY_DB_MEMORY_ENTRIES 2
+#define MAX_NR_BNEP_SERVICES 1
+#define MAX_NR_BNEP_CHANNELS 1
+#define MAX_NR_HFP_CONNECTIONS 1
+#define MAX_NR_WHITELIST_ENTRIES 1
+#define MAX_NR_SM_LOOKUP_ENTRIES 3
+#define MAX_NR_SERVICE_RECORD_ITEMS 1
+#define MAX_NR_AVDTP_STREAM_ENDPOINTS 1
+#define MAX_NR_AVDTP_CONNECTIONS 1
+#define MAX_NR_AVRCP_CONNECTIONS 1
+
+#define MAX_NR_LE_DEVICE_DB_ENTRIES 4
+
+// Link Key DB and LE Device DB using TLV on top of Flash Sector interface
+// #define NVM_NUM_DEVICE_DB_ENTRIES 16
+
+// We don't give btstack a malloc, so use a fixed-size ATT DB.
+#define MAX_ATT_DB_SIZE 512
+
+// BTstack HAL configuration
+#define HAVE_EMBEDDED_TIME_MS
+
+// Some USB dongles take longer to respond to HCI reset (e.g. BCM20702A).
+#define HCI_RESET_RESEND_TIMEOUT_MS 1000
+
+#endif // MICROPY_INCLUDED_EXTMOD_BTSTACK_BTSTACK_CONFIG_H
diff --git a/extmod/btstack/modbluetooth_btstack.c b/extmod/btstack/modbluetooth_btstack.c
new file mode 100644
index 0000000000..8f0c82974c
--- /dev/null
+++ b/extmod/btstack/modbluetooth_btstack.c
@@ -0,0 +1,1047 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2020 Damien P. George
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "py/runtime.h"
+#include "py/mperrno.h"
+#include "py/mphal.h"
+
+#if MICROPY_PY_BLUETOOTH && MICROPY_BLUETOOTH_BTSTACK
+
+#include "extmod/btstack/modbluetooth_btstack.h"
+#include "extmod/modbluetooth.h"
+
+#include "lib/btstack/src/btstack.h"
+
+#define DEBUG_EVENT_printf(...) // printf(__VA_ARGS__)
+
+#ifndef MICROPY_PY_BLUETOOTH_DEFAULT_GAP_NAME
+#define MICROPY_PY_BLUETOOTH_DEFAULT_GAP_NAME "MPY BTSTACK"
+#endif
+
+// How long to wait for a controller to init/deinit.
+// Some controllers can take up to 5-6 seconds in normal operation.
+STATIC const uint32_t BTSTACK_INIT_DEINIT_TIMEOUT_MS = 15000;
+
+// We need to know the attribute handle for the GAP device name (see GAP_DEVICE_NAME_UUID)
+// so it can be put into the gatts_db before registering the services, and accessed
+// efficiently when requesting an attribute in att_read_callback. Because this is the
+// first characteristic of the first service, it always has a handle value of 3.
+STATIC const uint16_t BTSTACK_GAP_DEVICE_NAME_HANDLE = 3;
+
+volatile int mp_bluetooth_btstack_state = MP_BLUETOOTH_BTSTACK_STATE_OFF;
+
+STATIC int btstack_error_to_errno(int err) {
+ DEBUG_EVENT_printf(" --> btstack error: %d\n", err);
+ if (err == ERROR_CODE_SUCCESS) {
+ return 0;
+ } else if (err == BTSTACK_ACL_BUFFERS_FULL || err == BTSTACK_MEMORY_ALLOC_FAILED) {
+ return MP_ENOMEM;
+ } else if (err == GATT_CLIENT_IN_WRONG_STATE) {
+ return MP_EALREADY;
+ } else if (err == GATT_CLIENT_BUSY) {
+ return MP_EBUSY;
+ } else if (err == GATT_CLIENT_NOT_CONNECTED) {
+ return MP_ENOTCONN;
+ } else {
+ return MP_EINVAL;
+ }
+}
+
+#if MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE
+STATIC mp_obj_bluetooth_uuid_t create_mp_uuid(uint16_t uuid16, const uint8_t *uuid128) {
+ mp_obj_bluetooth_uuid_t result;
+ if (uuid16 != 0) {
+ result.data[0] = uuid16 & 0xff;
+ result.data[1] = (uuid16 >> 8) & 0xff;
+ result.type = MP_BLUETOOTH_UUID_TYPE_16;
+ } else {
+ reverse_128(uuid128, result.data);
+ result.type = MP_BLUETOOTH_UUID_TYPE_128;
+ }
+ return result;
+}
+#endif
+
+// Notes on supporting background ops (e.g. an attempt to gatts_notify while
+// an existing notification is in progress):
+
+// GATTS Notify/Indicate (att_server_notify/indicate)
+// * When available, copies buffer immediately.
+// * Otherwise fails with BTSTACK_ACL_BUFFERS_FULL
+// * Use att_server_request_to_send_notification/indication to get callback
+// * Takes btstack_context_callback_registration_t (and takes ownership) and conn_handle.
+// * Callback is invoked with just the context member of the btstack_context_callback_registration_t
+
+// GATTC Write without response (gatt_client_write_value_of_characteristic_without_response)
+// * When available, copies buffer immediately.
+// * Otherwise, fails with GATT_CLIENT_BUSY.
+// * Use gatt_client_request_can_write_without_response_event to get callback
+// * Takes btstack_packet_handler_t (function pointer) and conn_handle
+// * Callback is invoked, use gatt_event_can_write_without_response_get_handle to get the conn_handle (no other context)
+// * There can only be one pending gatt_client_request_can_write_without_response_event (otherwise we fail with EALREADY).
+
+// GATTC Write with response (gatt_client_write_value_of_characteristic)
+// * When peripheral is available, takes ownership of buffer.
+// * Otherwise, fails with GATT_CLIENT_IN_WRONG_STATE (we fail the operation).
+// * Raises GATT_EVENT_QUERY_COMPLETE to the supplied packet handler.
+
+// For notify/indicate/write-without-response that proceed immediately, nothing extra required.
+// For all other cases, buffer needs to be copied and protected from GC.
+// For notify/indicate:
+// * btstack_context_callback_registration_t:
+// * needs to be malloc'ed
+// * needs to be protected from GC
+// * context arg needs to point back to the callback registration so it can be freed and un-protected
+// For write-without-response
+// * only the conn_handle is available in the callback
+// * so we need a queue of conn_handle->(value_handle, copied buffer)
+
+// Pending operation types.
+enum {
+ // Queued for sending when possible.
+ MP_BLUETOOTH_BTSTACK_PENDING_NOTIFY, // Waiting for context callback
+ MP_BLUETOOTH_BTSTACK_PENDING_INDICATE, // Waiting for context callback
+ MP_BLUETOOTH_BTSTACK_PENDING_WRITE_NO_RESPONSE, // Waiting for conn handle
+ // Hold buffer pointer until complete.
+ MP_BLUETOOTH_BTSTACK_PENDING_WRITE, // Waiting for write done event
+};
+
+// Pending operation:
+// - Holds a GC reference to the copied outgoing buffer.
+// - Provides enough information for the callback handler to execute the desired operation.
+struct _mp_btstack_pending_op_t {
+ btstack_linked_item_t *next; // Must be first field to match btstack_linked_item.
+
+ // See enum above.
+ uint16_t op_type;
+
+ // For all op types.
+ uint16_t conn_handle;
+ uint16_t value_handle;
+
+ // For notify/indicate only.
+ // context_registration.context will point back to this struct.
+ btstack_context_callback_registration_t context_registration;
+
+ // For notify/indicate/write-without-response, this is the actual buffer to send.
+ // For write-with-response, just holding onto the buffer for GC ref.
+ size_t len;
+ uint8_t buf[];
+};
+
+// Must hold MICROPY_PY_BLUETOOTH_ENTER.
+STATIC void btstack_remove_pending_operation(mp_btstack_pending_op_t *pending_op, bool del) {
+ bool removed = btstack_linked_list_remove(&MP_STATE_PORT(bluetooth_btstack_root_pointers)->pending_ops, (btstack_linked_item_t *)pending_op);
+ assert(removed);
+ (void)removed;
+ if (del) {
+ m_del_var(mp_btstack_pending_op_t, uint8_t, pending_op->len, pending_op);
+ }
+}
+
+// Called in response to a gatts_notify/indicate being unable to complete, which then calls
+// att_server_request_to_send_notification.
+// We now have an opportunity to re-try the operation with an empty ACL buffer.
+STATIC void btstack_notify_indicate_ready_handler(void *context) {
+ MICROPY_PY_BLUETOOTH_ENTER
+ mp_btstack_pending_op_t *pending_op = (mp_btstack_pending_op_t *)context;
+ DEBUG_EVENT_printf("btstack_notify_indicate_ready_handler op_type=%d conn_handle=%d value_handle=%d len=%lu\n", pending_op->op_type, pending_op->conn_handle, pending_op->value_handle, pending_op->len);
+ if (pending_op->op_type == MP_BLUETOOTH_BTSTACK_PENDING_NOTIFY) {
+ int err = att_server_notify(pending_op->conn_handle, pending_op->value_handle, pending_op->buf, pending_op->len);
+ DEBUG_EVENT_printf("btstack_notify_indicate_ready_handler: sending notification err=%d\n", err);
+ assert(err == ERROR_CODE_SUCCESS);
+ (void)err;
+ } else {
+ assert(pending_op->op_type == MP_BLUETOOTH_BTSTACK_PENDING_INDICATE);
+ int err = att_server_indicate(pending_op->conn_handle, pending_op->value_handle, NULL, 0);
+ DEBUG_EVENT_printf("btstack_notify_indicate_ready_handler: sending indication err=%d\n", err);
+ assert(err == ERROR_CODE_SUCCESS);
+ (void)err;
+ }
+ // Can't free the pending op as we're in IRQ context. Leave it for the GC.
+ btstack_remove_pending_operation(pending_op, false /* del */);
+ MICROPY_PY_BLUETOOTH_EXIT
+}
+
+// Register a pending background operation -- copies the buffer, and makes it known to the GC.
+STATIC mp_btstack_pending_op_t *btstack_enqueue_pending_operation(uint16_t op_type, uint16_t conn_handle, uint16_t value_handle, const uint8_t *buf, size_t len) {
+ DEBUG_EVENT_printf("btstack_enqueue_pending_operation op_type=%d conn_handle=%d value_handle=%d len=%lu\n", op_type, conn_handle, value_handle, len);
+ mp_btstack_pending_op_t *pending_op = m_new_obj_var(mp_btstack_pending_op_t, uint8_t, len);
+ pending_op->op_type = op_type;
+ pending_op->conn_handle = conn_handle;
+ pending_op->value_handle = value_handle;
+ pending_op->len = len;
+ memcpy(pending_op->buf, buf, len);
+
+ if (op_type == MP_BLUETOOTH_BTSTACK_PENDING_NOTIFY || op_type == MP_BLUETOOTH_BTSTACK_PENDING_INDICATE) {
+ pending_op->context_registration.callback = &btstack_notify_indicate_ready_handler;
+ pending_op->context_registration.context = pending_op;
+ }
+
+ MICROPY_PY_BLUETOOTH_ENTER
+ bool added = btstack_linked_list_add(&MP_STATE_PORT(bluetooth_btstack_root_pointers)->pending_ops, (btstack_linked_item_t *)pending_op);
+ assert(added);
+ (void)added;
+ MICROPY_PY_BLUETOOTH_EXIT
+
+ return pending_op;
+}
+
+#if MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE
+
+// Cleans up a pending op of the specified type for this conn_handle (and if specified, value_handle).
+// Used by MP_BLUETOOTH_BTSTACK_PENDING_WRITE and MP_BLUETOOTH_BTSTACK_PENDING_WRITE_NO_RESPONSE.
+// At the moment, both will set value_handle=0xffff as the events do not know their value_handle.
+// TODO: Can we make btstack give us the value_handle for regular write (with response) so that we
+// know for sure that we're using the correct entry.
+STATIC mp_btstack_pending_op_t *btstack_finish_pending_operation(uint16_t op_type, uint16_t conn_handle, uint16_t value_handle, bool del) {
+ MICROPY_PY_BLUETOOTH_ENTER
+ DEBUG_EVENT_printf("btstack_finish_pending_operation op_type=%d conn_handle=%d value_handle=%d\n", op_type, conn_handle, value_handle);
+ btstack_linked_list_iterator_t it;
+ btstack_linked_list_iterator_init(&it, &MP_STATE_PORT(bluetooth_btstack_root_pointers)->pending_ops);
+ while (btstack_linked_list_iterator_has_next(&it)) {
+ mp_btstack_pending_op_t *pending_op = (mp_btstack_pending_op_t *)btstack_linked_list_iterator_next(&it);
+
+ if (pending_op->op_type == op_type && pending_op->conn_handle == conn_handle && (value_handle == 0xffff || pending_op->value_handle == value_handle)) {
+ DEBUG_EVENT_printf("btstack_finish_pending_operation: found value_handle=%d len=%lu\n", pending_op->value_handle, pending_op->len);
+ btstack_remove_pending_operation(pending_op, del);
+ MICROPY_PY_BLUETOOTH_EXIT
+ return del ? NULL : pending_op;
+ }
+ }
+ DEBUG_EVENT_printf("btstack_finish_pending_operation: not found\n");
+ MICROPY_PY_BLUETOOTH_EXIT
+ return NULL;
+}
+#endif
+
+// This needs to be separate to btstack_packet_handler otherwise we get
+// dual-delivery of the HCI_EVENT_LE_META event.
+STATIC void btstack_packet_handler_att_server(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size) {
+ (void)channel;
+ (void)size;
+ DEBUG_EVENT_printf("btstack_packet_handler_att_server(packet_type=%u, packet=%p)\n", packet_type, packet);
+ if (packet_type != HCI_EVENT_PACKET) {
+ return;
+ }
+
+ uint8_t event_type = hci_event_packet_get_type(packet);
+
+ if (event_type == ATT_EVENT_CONNECTED) {
+ DEBUG_EVENT_printf(" --> att connected\n");
+ // The ATT_EVENT_*CONNECTED events are fired for both peripheral and central role, with no way to tell which.
+ // So we use the HCI_EVENT_LE_META event directly in the main packet handler.
+ } else if (event_type == ATT_EVENT_DISCONNECTED) {
+ DEBUG_EVENT_printf(" --> att disconnected\n");
+ } else if (event_type == ATT_EVENT_HANDLE_VALUE_INDICATION_COMPLETE) {
+ DEBUG_EVENT_printf(" --> att indication complete\n");
+ uint16_t conn_handle = att_event_handle_value_indication_complete_get_conn_handle(packet);
+ uint16_t value_handle = att_event_handle_value_indication_complete_get_attribute_handle(packet);
+ uint8_t status = att_event_handle_value_indication_complete_get_status(packet);
+ mp_bluetooth_gatts_on_indicate_complete(conn_handle, value_handle, status);
+ } else if (event_type == HCI_EVENT_LE_META || event_type == HCI_EVENT_DISCONNECTION_COMPLETE) {
+ // Ignore, duplicated by att_server.c.
+ } else {
+ DEBUG_EVENT_printf(" --> hci att server event type: unknown (0x%02x)\n", event_type);
+ }
+}
+
+STATIC void btstack_packet_handler(uint8_t packet_type, uint8_t *packet, uint8_t irq) {
+ DEBUG_EVENT_printf("btstack_packet_handler(packet_type=%u, packet=%p)\n", packet_type, packet);
+ if (packet_type != HCI_EVENT_PACKET) {
+ return;
+ }
+
+ uint8_t event_type = hci_event_packet_get_type(packet);
+
+ if (event_type == HCI_EVENT_LE_META) {
+ DEBUG_EVENT_printf(" --> hci le meta\n");
+ if (hci_event_le_meta_get_subevent_code(packet) == HCI_SUBEVENT_LE_CONNECTION_COMPLETE) {
+ uint16_t conn_handle = hci_subevent_le_connection_complete_get_connection_handle(packet);
+ uint8_t addr_type = hci_subevent_le_connection_complete_get_peer_address_type(packet);
+ bd_addr_t addr;
+ hci_subevent_le_connection_complete_get_peer_address(packet, addr);
+ uint16_t irq_event;
+ if (hci_subevent_le_connection_complete_get_role(packet) == 0) {
+ // Master role.
+ irq_event = MP_BLUETOOTH_IRQ_PERIPHERAL_CONNECT;
+ } else {
+ // Slave role.
+ irq_event = MP_BLUETOOTH_IRQ_CENTRAL_CONNECT;
+ }
+ mp_bluetooth_gap_on_connected_disconnected(irq_event, conn_handle, addr_type, addr);
+ }
+ } else if (event_type == BTSTACK_EVENT_STATE) {
+ uint8_t state = btstack_event_state_get_state(packet);
+ DEBUG_EVENT_printf(" --> btstack event state 0x%02x\n", state);
+ if (state == HCI_STATE_WORKING) {
+ // Signal that initialisation has completed.
+ mp_bluetooth_btstack_state = MP_BLUETOOTH_BTSTACK_STATE_ACTIVE;
+ } else if (state == HCI_STATE_OFF) {
+ // Signal that de-initialisation has completed.
+ mp_bluetooth_btstack_state = MP_BLUETOOTH_BTSTACK_STATE_OFF;
+ }
+ } else if (event_type == HCI_EVENT_TRANSPORT_PACKET_SENT) {
+ DEBUG_EVENT_printf(" --> hci transport packet sent\n");
+ } else if (event_type == HCI_EVENT_COMMAND_COMPLETE) {
+ DEBUG_EVENT_printf(" --> hci command complete\n");
+ } else if (event_type == HCI_EVENT_COMMAND_STATUS) {
+ DEBUG_EVENT_printf(" --> hci command status\n");
+ } else if (event_type == HCI_EVENT_NUMBER_OF_COMPLETED_PACKETS) {
+ DEBUG_EVENT_printf(" --> hci number of completed packets\n");
+ } else if (event_type == BTSTACK_EVENT_NR_CONNECTIONS_CHANGED) {
+ DEBUG_EVENT_printf(" --> btstack # conns changed\n");
+ } else if (event_type == HCI_EVENT_VENDOR_SPECIFIC) {
+ DEBUG_EVENT_printf(" --> hci vendor specific\n");
+ } else if (event_type == GATT_EVENT_MTU) {
+ DEBUG_EVENT_printf(" --> hci MTU\n");
+ } else if (event_type == HCI_EVENT_DISCONNECTION_COMPLETE) {
+ DEBUG_EVENT_printf(" --> hci disconnect complete\n");
+ uint16_t conn_handle = hci_event_disconnection_complete_get_connection_handle(packet);
+ const hci_connection_t *conn = hci_connection_for_handle(conn_handle);
+ uint16_t irq_event;
+ if (conn == NULL || conn->role == 0) {
+ // Master role.
+ irq_event = MP_BLUETOOTH_IRQ_PERIPHERAL_DISCONNECT;
+ } else {
+ // Slave role.
+ irq_event = MP_BLUETOOTH_IRQ_CENTRAL_DISCONNECT;
+ }
+ uint8_t addr[6] = {0};
+ mp_bluetooth_gap_on_connected_disconnected(irq_event, conn_handle, 0xff, addr);
+ #if MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE
+ } else if (event_type == GAP_EVENT_ADVERTISING_REPORT) {
+ DEBUG_EVENT_printf(" --> gap advertising report\n");
+ bd_addr_t address;
+ gap_event_advertising_report_get_address(packet, address);
+ uint8_t adv_event_type = gap_event_advertising_report_get_advertising_event_type(packet);
+ uint8_t address_type = gap_event_advertising_report_get_address_type(packet);
+ int8_t rssi = gap_event_advertising_report_get_rssi(packet);
+ uint8_t length = gap_event_advertising_report_get_data_length(packet);
+ const uint8_t *data = gap_event_advertising_report_get_data(packet);
+ mp_bluetooth_gap_on_scan_result(address_type, address, adv_event_type, rssi, data, length);
+ } else if (event_type == GATT_EVENT_QUERY_COMPLETE) {
+ uint16_t conn_handle = gatt_event_query_complete_get_handle(packet);
+ uint16_t status = gatt_event_query_complete_get_att_status(packet);
+ DEBUG_EVENT_printf(" --> gatt query complete irq=%d conn_handle=%d status=%d\n", irq, conn_handle, status);
+ if (irq == MP_BLUETOOTH_IRQ_GATTC_READ_DONE || irq == MP_BLUETOOTH_IRQ_GATTC_WRITE_DONE) {
+ // TODO there is no value_handle available to pass here.
+ // TODO try and get this implemented in btstack.
+ mp_bluetooth_gattc_on_read_write_status(irq, conn_handle, 0xffff, status);
+ // Unref the saved buffer for the write operation on this conn_handle.
+ if (irq == MP_BLUETOOTH_IRQ_GATTC_WRITE_DONE) {
+ btstack_finish_pending_operation(MP_BLUETOOTH_BTSTACK_PENDING_WRITE, conn_handle, 0xffff, false /* del */);
+ }
+ } else if (irq == MP_BLUETOOTH_IRQ_GATTC_SERVICE_DONE ||
+ irq == MP_BLUETOOTH_IRQ_GATTC_CHARACTERISTIC_DONE ||
+ irq == MP_BLUETOOTH_IRQ_GATTC_DESCRIPTOR_DONE) {
+ mp_bluetooth_gattc_on_discover_complete(irq, conn_handle, status);
+ }
+ } else if (event_type == GATT_EVENT_SERVICE_QUERY_RESULT) {
+ DEBUG_EVENT_printf(" --> gatt service query result\n");
+ uint16_t conn_handle = gatt_event_service_query_result_get_handle(packet);
+ gatt_client_service_t service;
+ gatt_event_service_query_result_get_service(packet, &service);
+ mp_obj_bluetooth_uuid_t service_uuid = create_mp_uuid(service.uuid16, service.uuid128);
+ mp_bluetooth_gattc_on_primary_service_result(conn_handle, service.start_group_handle, service.end_group_handle, &service_uuid);
+ } else if (event_type == GATT_EVENT_CHARACTERISTIC_QUERY_RESULT) {
+ DEBUG_EVENT_printf(" --> gatt characteristic query result\n");
+ uint16_t conn_handle = gatt_event_characteristic_query_result_get_handle(packet);
+ gatt_client_characteristic_t characteristic;
+ gatt_event_characteristic_query_result_get_characteristic(packet, &characteristic);
+ mp_obj_bluetooth_uuid_t characteristic_uuid = create_mp_uuid(characteristic.uuid16, characteristic.uuid128);
+ mp_bluetooth_gattc_on_characteristic_result(conn_handle, characteristic.start_handle, characteristic.value_handle, characteristic.properties, &characteristic_uuid);
+ } else if (event_type == GATT_EVENT_CHARACTERISTIC_DESCRIPTOR_QUERY_RESULT) {
+ DEBUG_EVENT_printf(" --> gatt descriptor query result\n");
+ uint16_t conn_handle = gatt_event_all_characteristic_descriptors_query_result_get_handle(packet);
+ gatt_client_characteristic_descriptor_t descriptor;
+ gatt_event_all_characteristic_descriptors_query_result_get_characteristic_descriptor(packet, &descriptor);
+ mp_obj_bluetooth_uuid_t descriptor_uuid = create_mp_uuid(descriptor.uuid16, descriptor.uuid128);
+ mp_bluetooth_gattc_on_descriptor_result(conn_handle, descriptor.handle, &descriptor_uuid);
+ } else if (event_type == GATT_EVENT_CHARACTERISTIC_VALUE_QUERY_RESULT) {
+ DEBUG_EVENT_printf(" --> gatt characteristic value query result\n");
+ uint16_t conn_handle = gatt_event_characteristic_value_query_result_get_handle(packet);
+ uint16_t value_handle = gatt_event_characteristic_value_query_result_get_value_handle(packet);
+ uint16_t len = gatt_event_characteristic_value_query_result_get_value_length(packet);
+ const uint8_t *data = gatt_event_characteristic_value_query_result_get_value(packet);
+ mp_uint_t atomic_state;
+ len = mp_bluetooth_gattc_on_data_available_start(MP_BLUETOOTH_IRQ_GATTC_READ_RESULT, conn_handle, value_handle, len, &atomic_state);
+ mp_bluetooth_gattc_on_data_available_chunk(data, len);
+ mp_bluetooth_gattc_on_data_available_end(atomic_state);
+ } else if (event_type == GATT_EVENT_NOTIFICATION) {
+ DEBUG_EVENT_printf(" --> gatt notification\n");
+ uint16_t conn_handle = gatt_event_notification_get_handle(packet);
+ uint16_t value_handle = gatt_event_notification_get_value_handle(packet);
+ uint16_t len = gatt_event_notification_get_value_length(packet);
+ const uint8_t *data = gatt_event_notification_get_value(packet);
+ mp_uint_t atomic_state;
+ len = mp_bluetooth_gattc_on_data_available_start(MP_BLUETOOTH_IRQ_GATTC_NOTIFY, conn_handle, value_handle, len, &atomic_state);
+ mp_bluetooth_gattc_on_data_available_chunk(data, len);
+ mp_bluetooth_gattc_on_data_available_end(atomic_state);
+ } else if (event_type == GATT_EVENT_INDICATION) {
+ DEBUG_EVENT_printf(" --> gatt indication\n");
+ uint16_t conn_handle = gatt_event_indication_get_handle(packet);
+ uint16_t value_handle = gatt_event_indication_get_value_handle(packet);
+ uint16_t len = gatt_event_indication_get_value_length(packet);
+ const uint8_t *data = gatt_event_indication_get_value(packet);
+ mp_uint_t atomic_state;
+ len = mp_bluetooth_gattc_on_data_available_start(MP_BLUETOOTH_IRQ_GATTC_INDICATE, conn_handle, value_handle, len, &atomic_state);
+ mp_bluetooth_gattc_on_data_available_chunk(data, len);
+ mp_bluetooth_gattc_on_data_available_end(atomic_state);
+ } else if (event_type == GATT_EVENT_CAN_WRITE_WITHOUT_RESPONSE) {
+ uint16_t conn_handle = gatt_event_can_write_without_response_get_handle(packet);
+ DEBUG_EVENT_printf(" --> gatt can write without response %d\n", conn_handle);
+ mp_btstack_pending_op_t *pending_op = btstack_finish_pending_operation(MP_BLUETOOTH_BTSTACK_PENDING_WRITE_NO_RESPONSE, conn_handle, 0xffff, false /* !del */);
+ if (pending_op) {
+ DEBUG_EVENT_printf(" --> ready for value_handle=%d len=%lu\n", pending_op->value_handle, pending_op->len);
+ gatt_client_write_value_of_characteristic_without_response(pending_op->conn_handle, pending_op->value_handle, pending_op->len, (uint8_t *)pending_op->buf);
+ // Note: Can't "del" the pending_op from IRQ context. Leave it for the GC.
+ }
+
+ #endif // MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE
+ } else {
+ DEBUG_EVENT_printf(" --> hci event type: unknown (0x%02x)\n", event_type);
+ }
+}
+
+// Because the packet handler callbacks don't support an argument, we use a specific
+// handler when we need to provide additional state to the handler (in the "irq" parameter).
+// This is the generic handler for when you don't need extra state.
+STATIC void btstack_packet_handler_generic(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size) {
+ (void)channel;
+ (void)size;
+ btstack_packet_handler(packet_type, packet, 0);
+}
+
+STATIC btstack_packet_callback_registration_t hci_event_callback_registration = {
+ .callback = &btstack_packet_handler_generic
+};
+
+#if MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE
+// For when the handler is being used for service discovery.
+STATIC void btstack_packet_handler_discover_services(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size) {
+ (void)channel;
+ (void)size;
+ btstack_packet_handler(packet_type, packet, MP_BLUETOOTH_IRQ_GATTC_SERVICE_DONE);
+}
+
+// For when the handler is being used for characteristic discovery.
+STATIC void btstack_packet_handler_discover_characteristics(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size) {
+ (void)channel;
+ (void)size;
+ btstack_packet_handler(packet_type, packet, MP_BLUETOOTH_IRQ_GATTC_CHARACTERISTIC_DONE);
+}
+
+// For when the handler is being used for descriptor discovery.
+STATIC void btstack_packet_handler_discover_descriptors(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size) {
+ (void)channel;
+ (void)size;
+ btstack_packet_handler(packet_type, packet, MP_BLUETOOTH_IRQ_GATTC_DESCRIPTOR_DONE);
+}
+
+// For when the handler is being used for a read query.
+STATIC void btstack_packet_handler_read(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size) {
+ (void)channel;
+ (void)size;
+ btstack_packet_handler(packet_type, packet, MP_BLUETOOTH_IRQ_GATTC_READ_DONE);
+}
+
+// For when the handler is being used for write-with-response.
+STATIC void btstack_packet_handler_write_with_response(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size) {
+ (void)channel;
+ (void)size;
+ btstack_packet_handler(packet_type, packet, MP_BLUETOOTH_IRQ_GATTC_WRITE_DONE);
+}
+#endif // MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE
+
+STATIC btstack_timer_source_t btstack_init_deinit_timeout;
+
+STATIC void btstack_init_deinit_timeout_handler(btstack_timer_source_t *ds) {
+ (void)ds;
+
+ // Stop waiting for initialisation.
+ // This signals both the loops in mp_bluetooth_init and mp_bluetooth_deinit,
+ // as well as ports that run a polling loop.
+ mp_bluetooth_btstack_state = MP_BLUETOOTH_BTSTACK_STATE_TIMEOUT;
+}
+
+int mp_bluetooth_init(void) {
+ DEBUG_EVENT_printf("mp_bluetooth_init\n");
+
+ if (mp_bluetooth_btstack_state == MP_BLUETOOTH_BTSTACK_STATE_ACTIVE) {
+ return 0;
+ }
+
+ // Clean up if necessary.
+ mp_bluetooth_deinit();
+
+ btstack_memory_init();
+
+ MP_STATE_PORT(bluetooth_btstack_root_pointers) = m_new0(mp_bluetooth_btstack_root_pointers_t, 1);
+ mp_bluetooth_gatts_db_create(&MP_STATE_PORT(bluetooth_btstack_root_pointers)->gatts_db);
+
+ // Set the default GAP device name.
+ const char *gap_name = MICROPY_PY_BLUETOOTH_DEFAULT_GAP_NAME;
+ size_t gap_len = strlen(gap_name);
+ mp_bluetooth_gatts_db_create_entry(MP_STATE_PORT(bluetooth_btstack_root_pointers)->gatts_db, BTSTACK_GAP_DEVICE_NAME_HANDLE, gap_len);
+ mp_bluetooth_gap_set_device_name((const uint8_t *)gap_name, gap_len);
+
+ mp_bluetooth_btstack_port_init();
+ mp_bluetooth_btstack_state = MP_BLUETOOTH_BTSTACK_STATE_STARTING;
+
+ l2cap_init();
+ le_device_db_init();
+ sm_init();
+
+ // Set blank ER/IR keys to suppress BTstack warning.
+ // TODO handle this correctly.
+ sm_key_t dummy_key;
+ memset(dummy_key, 0, sizeof(dummy_key));
+ sm_set_er(dummy_key);
+ sm_set_ir(dummy_key);
+
+ #if MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE
+ gatt_client_init();
+ #endif
+
+ // Register for HCI events.
+ hci_add_event_handler(&hci_event_callback_registration);
+
+ // Register for ATT server events.
+ att_server_register_packet_handler(&btstack_packet_handler_att_server);
+
+ // Set a timeout for HCI initialisation.
+ btstack_run_loop_set_timer(&btstack_init_deinit_timeout, BTSTACK_INIT_DEINIT_TIMEOUT_MS);
+ btstack_run_loop_set_timer_handler(&btstack_init_deinit_timeout, btstack_init_deinit_timeout_handler);
+ btstack_run_loop_add_timer(&btstack_init_deinit_timeout);
+
+ // Either the HCI event will set state to ACTIVE, or the timeout will set it to TIMEOUT.
+ mp_bluetooth_btstack_port_start();
+ while (mp_bluetooth_btstack_state == MP_BLUETOOTH_BTSTACK_STATE_STARTING) {
+ MICROPY_EVENT_POLL_HOOK
+ }
+ btstack_run_loop_remove_timer(&btstack_init_deinit_timeout);
+
+ // Check for timeout.
+ if (mp_bluetooth_btstack_state != MP_BLUETOOTH_BTSTACK_STATE_ACTIVE) {
+ // Required to stop the polling loop.
+ mp_bluetooth_btstack_state = MP_BLUETOOTH_BTSTACK_STATE_OFF;
+ // Attempt a shutdown (may not do anything).
+ mp_bluetooth_btstack_port_deinit();
+
+ // Clean up.
+ MP_STATE_PORT(bluetooth_btstack_root_pointers) = NULL;
+ return MP_ETIMEDOUT;
+ }
+
+ #if MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE
+ // Enable GATT_EVENT_NOTIFICATION/GATT_EVENT_INDICATION for all connections and handles.
+ gatt_client_listen_for_characteristic_value_updates(&MP_STATE_PORT(bluetooth_btstack_root_pointers)->notification, &btstack_packet_handler_generic, GATT_CLIENT_ANY_CONNECTION, NULL);
+ #endif
+
+ return 0;
+}
+
+void mp_bluetooth_deinit(void) {
+ DEBUG_EVENT_printf("mp_bluetooth_deinit\n");
+
+ // Nothing to do if not initialised.
+ if (!MP_STATE_PORT(bluetooth_btstack_root_pointers)) {
+ return;
+ }
+
+ mp_bluetooth_gap_advertise_stop();
+
+ #if MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE
+ // Remove our registration for notify/indicate.
+ gatt_client_stop_listening_for_characteristic_value_updates(&MP_STATE_PORT(bluetooth_btstack_root_pointers)->notification);
+ #endif
+
+ // Set a timer that will forcibly set the state to TIMEOUT, which will stop the loop below.
+ btstack_run_loop_set_timer(&btstack_init_deinit_timeout, BTSTACK_INIT_DEINIT_TIMEOUT_MS);
+ btstack_run_loop_add_timer(&btstack_init_deinit_timeout);
+
+ // This should result in a clean shutdown, which will set the state to OFF.
+ // On Unix this is blocking (it joins on the poll thread), on other ports the loop below will wait unil
+ // either timeout or clean shutdown.
+ mp_bluetooth_btstack_port_deinit();
+ while (mp_bluetooth_btstack_state == MP_BLUETOOTH_BTSTACK_STATE_ACTIVE) {
+ MICROPY_EVENT_POLL_HOOK
+ }
+ btstack_run_loop_remove_timer(&btstack_init_deinit_timeout);
+
+ mp_bluetooth_btstack_state = MP_BLUETOOTH_BTSTACK_STATE_OFF;
+ MP_STATE_PORT(bluetooth_btstack_root_pointers) = NULL;
+}
+
+bool mp_bluetooth_is_active(void) {
+ return mp_bluetooth_btstack_state == MP_BLUETOOTH_BTSTACK_STATE_ACTIVE;
+}
+
+void mp_bluetooth_get_device_addr(uint8_t *addr) {
+ mp_hal_get_mac(MP_HAL_MAC_BDADDR, addr);
+}
+
+size_t mp_bluetooth_gap_get_device_name(const uint8_t **buf) {
+ uint8_t *value = NULL;
+ size_t value_len = 0;
+ mp_bluetooth_gatts_db_read(MP_STATE_PORT(bluetooth_btstack_root_pointers)->gatts_db, BTSTACK_GAP_DEVICE_NAME_HANDLE, &value, &value_len);
+ *buf = value;
+ return value_len;
+}
+
+int mp_bluetooth_gap_set_device_name(const uint8_t *buf, size_t len) {
+ return mp_bluetooth_gatts_db_write(MP_STATE_PORT(bluetooth_btstack_root_pointers)->gatts_db, BTSTACK_GAP_DEVICE_NAME_HANDLE, buf, len);
+}
+
+int mp_bluetooth_gap_advertise_start(bool connectable, int32_t interval_us, const uint8_t *adv_data, size_t adv_data_len, const uint8_t *sr_data, size_t sr_data_len) {
+ DEBUG_EVENT_printf("mp_bluetooth_gap_advertise_start\n");
+ uint16_t adv_int_min = interval_us / 625;
+ uint16_t adv_int_max = interval_us / 625;
+ uint8_t adv_type = connectable ? 0 : 2;
+ bd_addr_t null_addr = {0};
+
+ uint8_t direct_address_type = 0;
+ uint8_t channel_map = 0x07; // Use all three broadcast channels.
+ uint8_t filter_policy = 0x00; // None.
+
+ gap_advertisements_set_params(adv_int_min, adv_int_max, adv_type, direct_address_type, null_addr, channel_map, filter_policy);
+
+ // Copy the adv_data and sr_data into a persistent buffer (which is findable via the btstack root pointers).
+ size_t total_bytes = adv_data_len + sr_data_len;
+ if (total_bytes > MP_STATE_PORT(bluetooth_btstack_root_pointers)->adv_data_alloc) {
+ // Resize if necessary.
+ MP_STATE_PORT(bluetooth_btstack_root_pointers)->adv_data = m_new(uint8_t, total_bytes);
+ MP_STATE_PORT(bluetooth_btstack_root_pointers)->adv_data_alloc = total_bytes;
+ }
+ uint8_t *data = MP_STATE_PORT(bluetooth_btstack_root_pointers)->adv_data;
+
+ if (adv_data) {
+ memcpy(data, (uint8_t *)adv_data, adv_data_len);
+ gap_advertisements_set_data(adv_data_len, data);
+ data += adv_data_len;
+ }
+ if (sr_data) {
+ memcpy(data, (uint8_t *)sr_data, sr_data_len);
+ gap_scan_response_set_data(sr_data_len, data);
+ }
+
+ gap_advertisements_enable(true);
+ return 0;
+}
+
+void mp_bluetooth_gap_advertise_stop(void) {
+ DEBUG_EVENT_printf("mp_bluetooth_gap_advertise_stop\n");
+ gap_advertisements_enable(false);
+ MP_STATE_PORT(bluetooth_btstack_root_pointers)->adv_data_alloc = 0;
+ MP_STATE_PORT(bluetooth_btstack_root_pointers)->adv_data = NULL;
+}
+
+int mp_bluetooth_gatts_register_service_begin(bool append) {
+ DEBUG_EVENT_printf("mp_bluetooth_gatts_register_service_begin\n");
+ if (!append) {
+ // This will reset the DB.
+ // Becase the DB is statically allocated, there's no problem with just re-initing it.
+ // Note this would be a memory leak if we enabled HAVE_MALLOC (there's no API to free the existing db).
+ att_db_util_init();
+
+ att_db_util_add_service_uuid16(GAP_SERVICE_UUID);
+ uint16_t handle = att_db_util_add_characteristic_uuid16(GAP_DEVICE_NAME_UUID, ATT_PROPERTY_READ | ATT_PROPERTY_DYNAMIC, ATT_SECURITY_NONE, ATT_SECURITY_NONE, NULL, 0);
+ assert(handle == BTSTACK_GAP_DEVICE_NAME_HANDLE);
+ (void)handle;
+
+ att_db_util_add_service_uuid16(0x1801);
+ att_db_util_add_characteristic_uuid16(0x2a05, ATT_PROPERTY_READ, ATT_SECURITY_NONE, ATT_SECURITY_NONE, NULL, 0);
+ }
+
+ return 0;
+}
+
+STATIC uint16_t att_read_callback(hci_con_handle_t connection_handle, uint16_t att_handle, uint16_t offset, uint8_t *buffer, uint16_t buffer_size) {
+ (void)connection_handle;
+ DEBUG_EVENT_printf("btstack: att_read_callback (handle: %u, offset: %u, buffer: %p, size: %u)\n", att_handle, offset, buffer, buffer_size);
+ mp_bluetooth_gatts_db_entry_t *entry = mp_bluetooth_gatts_db_lookup(MP_STATE_PORT(bluetooth_btstack_root_pointers)->gatts_db, att_handle);
+ if (!entry) {
+ DEBUG_EVENT_printf("btstack: att_read_callback handle not found\n");
+ return 0; // TODO: Find status code for not-found.
+ }
+
+ return att_read_callback_handle_blob(entry->data, entry->data_len, offset, buffer, buffer_size);
+}
+
+STATIC int att_write_callback(hci_con_handle_t connection_handle, uint16_t att_handle, uint16_t transaction_mode, uint16_t offset, uint8_t *buffer, uint16_t buffer_size) {
+ (void)offset;
+ (void)transaction_mode;
+ DEBUG_EVENT_printf("btstack: att_write_callback (handle: %u, mode: %u, offset: %u, buffer: %p, size: %u)\n", att_handle, transaction_mode, offset, buffer, buffer_size);
+ mp_bluetooth_gatts_db_entry_t *entry = mp_bluetooth_gatts_db_lookup(MP_STATE_PORT(bluetooth_btstack_root_pointers)->gatts_db, att_handle);
+ if (!entry) {
+ DEBUG_EVENT_printf("btstack: att_write_callback handle not found\n");
+ return 0; // TODO: Find status code for not-found.
+ }
+
+ // TODO: Use `offset` arg.
+ size_t append_offset = 0;
+ if (entry->append) {
+ append_offset = entry->data_len;
+ }
+ entry->data_len = MIN(entry->data_alloc, buffer_size + append_offset);
+ memcpy(entry->data + append_offset, buffer, entry->data_len - append_offset);
+
+ mp_bluetooth_gatts_on_write(connection_handle, att_handle);
+
+ return 0;
+}
+
+STATIC inline uint16_t get_uuid16(const mp_obj_bluetooth_uuid_t *uuid) {
+ return (uuid->data[1] << 8) | uuid->data[0];
+}
+
+int mp_bluetooth_gatts_register_service(mp_obj_bluetooth_uuid_t *service_uuid, mp_obj_bluetooth_uuid_t **characteristic_uuids, uint8_t *characteristic_flags, mp_obj_bluetooth_uuid_t **descriptor_uuids, uint8_t *descriptor_flags, uint8_t *num_descriptors, uint16_t *handles, size_t num_characteristics) {
+ DEBUG_EVENT_printf("mp_bluetooth_gatts_register_service\n");
+ // Note: btstack expects BE UUIDs (which it immediately convertes to LE).
+ // So we have to convert all our modbluetooth LE UUIDs to BE just for the att_db_util_add_* methods (using get_uuid16 above, and reverse_128 from btstackutil.h).
+
+ // TODO: btstack's att_db_util_add_* methods have no bounds checking or validation.
+ // Need some way to prevent additional services being added if we're out of space in the static buffer.
+
+ if (service_uuid->type == MP_BLUETOOTH_UUID_TYPE_16) {
+ att_db_util_add_service_uuid16(get_uuid16(service_uuid));
+ } else if (service_uuid->type == MP_BLUETOOTH_UUID_TYPE_128) {
+ uint8_t buffer[16];
+ reverse_128(service_uuid->data, buffer);
+ att_db_util_add_service_uuid128(buffer);
+ } else {
+ return MP_EINVAL;
+ }
+
+ size_t handle_index = 0;
+ size_t descriptor_index = 0;
+ static uint8_t cccb_buf[2] = {0};
+
+ for (size_t i = 0; i < num_characteristics; ++i) {
+ uint16_t props = characteristic_flags[i] | ATT_PROPERTY_DYNAMIC;
+ uint16_t read_permission = ATT_SECURITY_NONE;
+ uint16_t write_permission = ATT_SECURITY_NONE;
+ if (characteristic_uuids[i]->type == MP_BLUETOOTH_UUID_TYPE_16) {
+ handles[handle_index] = att_db_util_add_characteristic_uuid16(get_uuid16(characteristic_uuids[i]), props, read_permission, write_permission, NULL, 0);
+ } else if (characteristic_uuids[i]->type == MP_BLUETOOTH_UUID_TYPE_128) {
+ uint8_t buffer[16];
+ reverse_128(characteristic_uuids[i]->data, buffer);
+ handles[handle_index] = att_db_util_add_characteristic_uuid128(buffer, props, read_permission, write_permission, NULL, 0);
+ } else {
+ return MP_EINVAL;
+ }
+ mp_bluetooth_gatts_db_create_entry(MP_STATE_PORT(bluetooth_btstack_root_pointers)->gatts_db, handles[handle_index], MP_BLUETOOTH_DEFAULT_ATTR_LEN);
+ // If a NOTIFY or INDICATE characteristic is added, then we need to manage a value for the CCCB.
+ if (props & (ATT_PROPERTY_NOTIFY | ATT_PROPERTY_INDICATE)) {
+ // btstack creates the CCCB as the next handle.
+ mp_bluetooth_gatts_db_create_entry(MP_STATE_PORT(bluetooth_btstack_root_pointers)->gatts_db, handles[handle_index] + 1, MP_BLUETOOTH_CCCB_LEN);
+ int ret = mp_bluetooth_gatts_db_write(MP_STATE_PORT(bluetooth_btstack_root_pointers)->gatts_db, handles[handle_index] + 1, cccb_buf, sizeof(cccb_buf));
+ if (ret) {
+ return ret;
+ }
+ }
+ DEBUG_EVENT_printf("Registered char with handle %u\n", handles[handle_index]);
+ ++handle_index;
+
+ for (size_t j = 0; j < num_descriptors[i]; ++j) {
+ props = descriptor_flags[descriptor_index] | ATT_PROPERTY_DYNAMIC;
+ read_permission = ATT_SECURITY_NONE;
+ write_permission = ATT_SECURITY_NONE;
+
+ if (descriptor_uuids[descriptor_index]->type == MP_BLUETOOTH_UUID_TYPE_16) {
+ handles[handle_index] = att_db_util_add_descriptor_uuid16(get_uuid16(descriptor_uuids[descriptor_index]), props, read_permission, write_permission, NULL, 0);
+ } else if (descriptor_uuids[descriptor_index]->type == MP_BLUETOOTH_UUID_TYPE_128) {
+ uint8_t buffer[16];
+ reverse_128(descriptor_uuids[descriptor_index]->data, buffer);
+ handles[handle_index] = att_db_util_add_descriptor_uuid128(buffer, props, read_permission, write_permission, NULL, 0);
+ } else {
+ return MP_EINVAL;
+ }
+ mp_bluetooth_gatts_db_create_entry(MP_STATE_PORT(bluetooth_btstack_root_pointers)->gatts_db, handles[handle_index], MP_BLUETOOTH_DEFAULT_ATTR_LEN);
+ DEBUG_EVENT_printf("Registered desc with handle %u\n", handles[handle_index]);
+ ++descriptor_index;
+ ++handle_index;
+ }
+ }
+
+ return 0;
+}
+
+int mp_bluetooth_gatts_register_service_end(void) {
+ DEBUG_EVENT_printf("mp_bluetooth_gatts_register_service_end\n");
+ att_server_init(att_db_util_get_address(), &att_read_callback, &att_write_callback);
+ return 0;
+}
+
+int mp_bluetooth_gatts_read(uint16_t value_handle, uint8_t **value, size_t *value_len) {
+ DEBUG_EVENT_printf("mp_bluetooth_gatts_read\n");
+ return mp_bluetooth_gatts_db_read(MP_STATE_PORT(bluetooth_btstack_root_pointers)->gatts_db, value_handle, value, value_len);
+}
+
+int mp_bluetooth_gatts_write(uint16_t value_handle, const uint8_t *value, size_t value_len) {
+ DEBUG_EVENT_printf("mp_bluetooth_gatts_write\n");
+ return mp_bluetooth_gatts_db_write(MP_STATE_PORT(bluetooth_btstack_root_pointers)->gatts_db, value_handle, value, value_len);
+}
+
+int mp_bluetooth_gatts_notify(uint16_t conn_handle, uint16_t value_handle) {
+ DEBUG_EVENT_printf("mp_bluetooth_gatts_notify\n");
+ // Note: btstack doesn't appear to support sending a notification without a value, so include the stored value.
+ uint8_t *data = NULL;
+ size_t len = 0;
+ mp_bluetooth_gatts_db_read(MP_STATE_PORT(bluetooth_btstack_root_pointers)->gatts_db, value_handle, &data, &len);
+ return mp_bluetooth_gatts_notify_send(conn_handle, value_handle, data, len);
+}
+
+int mp_bluetooth_gatts_notify_send(uint16_t conn_handle, uint16_t value_handle, const uint8_t *value, size_t value_len) {
+ DEBUG_EVENT_printf("mp_bluetooth_gatts_notify_send\n");
+
+ // Attempt to send immediately. If it succeeds, btstack will copy the buffer.
+ MICROPY_PY_BLUETOOTH_ENTER
+ int err = att_server_notify(conn_handle, value_handle, value, value_len);
+ MICROPY_PY_BLUETOOTH_EXIT
+
+ if (err == BTSTACK_ACL_BUFFERS_FULL) {
+ DEBUG_EVENT_printf("mp_bluetooth_gatts_notify_send: ACL buffer full, scheduling callback\n");
+ // Schedule callback, making a copy of the buffer.
+ mp_btstack_pending_op_t *pending_op = btstack_enqueue_pending_operation(MP_BLUETOOTH_BTSTACK_PENDING_NOTIFY, conn_handle, value_handle, value, value_len);
+
+ err = att_server_request_to_send_notification(&pending_op->context_registration, conn_handle);
+
+ if (err != ERROR_CODE_SUCCESS) {
+ // Failure. Unref and free the pending operation.
+ btstack_remove_pending_operation(pending_op, true /* del */);
+ }
+
+ return 0;
+ } else {
+ return btstack_error_to_errno(err);
+ }
+}
+
+int mp_bluetooth_gatts_indicate(uint16_t conn_handle, uint16_t value_handle) {
+ DEBUG_EVENT_printf("mp_bluetooth_gatts_indicate\n");
+
+ uint8_t *data = NULL;
+ size_t len = 0;
+ mp_bluetooth_gatts_db_read(MP_STATE_PORT(bluetooth_btstack_root_pointers)->gatts_db, value_handle, &data, &len);
+
+ // Indicate will raise ATT_EVENT_HANDLE_VALUE_INDICATION_COMPLETE when
+ // acknowledged (or timeout/error).
+
+ // Attempt to send immediately, will copy buffer.
+ MICROPY_PY_BLUETOOTH_ENTER
+ int err = att_server_indicate(conn_handle, value_handle, data, len);
+ MICROPY_PY_BLUETOOTH_EXIT
+
+ if (err == BTSTACK_ACL_BUFFERS_FULL) {
+ DEBUG_EVENT_printf("mp_bluetooth_gatts_indicate: ACL buffer full, scheduling callback\n");
+ // Schedule callback, making a copy of the buffer.
+ mp_btstack_pending_op_t *pending_op = btstack_enqueue_pending_operation(MP_BLUETOOTH_BTSTACK_PENDING_INDICATE, conn_handle, value_handle, data, len);
+
+ err = att_server_request_to_send_indication(&pending_op->context_registration, conn_handle);
+
+ if (err != ERROR_CODE_SUCCESS) {
+ // Failure. Unref and free the pending operation.
+ btstack_remove_pending_operation(pending_op, true /* del */);
+ }
+
+ return 0;
+ } else {
+ return btstack_error_to_errno(err);
+ }
+}
+
+int mp_bluetooth_gatts_set_buffer(uint16_t value_handle, size_t len, bool append) {
+ DEBUG_EVENT_printf("mp_bluetooth_gatts_set_buffer\n");
+ return mp_bluetooth_gatts_db_resize(MP_STATE_PORT(bluetooth_btstack_root_pointers)->gatts_db, value_handle, len, append);
+}
+
+int mp_bluetooth_gap_disconnect(uint16_t conn_handle) {
+ DEBUG_EVENT_printf("mp_bluetooth_gap_disconnect\n");
+ gap_disconnect(conn_handle);
+ return 0;
+}
+
+#if MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE
+STATIC btstack_timer_source_t scan_duration_timeout;
+
+STATIC void scan_duration_timeout_handler(btstack_timer_source_t *ds) {
+ (void)ds;
+ mp_bluetooth_gap_scan_stop();
+}
+
+int mp_bluetooth_gap_scan_start(int32_t duration_ms, int32_t interval_us, int32_t window_us, bool active_scan) {
+ DEBUG_EVENT_printf("mp_bluetooth_gap_scan_start\n");
+
+ if (duration_ms > 0) {
+ btstack_run_loop_set_timer(&scan_duration_timeout, duration_ms);
+ btstack_run_loop_set_timer_handler(&scan_duration_timeout, scan_duration_timeout_handler);
+ btstack_run_loop_add_timer(&scan_duration_timeout);
+ }
+
+ gap_set_scan_parameters(active_scan ? 1 : 0, interval_us / 625, window_us / 625);
+ gap_start_scan();
+
+ return 0;
+}
+
+int mp_bluetooth_gap_scan_stop(void) {
+ DEBUG_EVENT_printf("mp_bluetooth_gap_scan_stop\n");
+ btstack_run_loop_remove_timer(&scan_duration_timeout);
+ gap_stop_scan();
+ mp_bluetooth_gap_on_scan_complete();
+ return 0;
+}
+
+int mp_bluetooth_gap_peripheral_connect(uint8_t addr_type, const uint8_t *addr, int32_t duration_ms) {
+ DEBUG_EVENT_printf("mp_bluetooth_gap_peripheral_connect\n");
+
+ uint16_t conn_scan_interval = 60000 / 625;
+ uint16_t conn_scan_window = 30000 / 625;
+ uint16_t conn_interval_min = 10000 / 1250;
+ uint16_t conn_interval_max = 30000 / 1250;
+ uint16_t conn_latency = 4;
+ uint16_t supervision_timeout = duration_ms / 10; // default = 720
+ uint16_t min_ce_length = 10000 / 625;
+ uint16_t max_ce_length = 30000 / 625;
+
+ gap_set_connection_parameters(conn_scan_interval, conn_scan_window, conn_interval_min, conn_interval_max, conn_latency, supervision_timeout, min_ce_length, max_ce_length);
+
+ bd_addr_t btstack_addr;
+ memcpy(btstack_addr, addr, BD_ADDR_LEN);
+ return btstack_error_to_errno(gap_connect(btstack_addr, addr_type));
+}
+
+int mp_bluetooth_gattc_discover_primary_services(uint16_t conn_handle, const mp_obj_bluetooth_uuid_t *uuid) {
+ DEBUG_EVENT_printf("mp_bluetooth_gattc_discover_primary_services\n");
+ uint8_t err;
+ if (uuid) {
+ if (uuid->type == MP_BLUETOOTH_UUID_TYPE_16) {
+ err = gatt_client_discover_primary_services_by_uuid16(&btstack_packet_handler_discover_services, conn_handle, get_uuid16(uuid));
+ } else if (uuid->type == MP_BLUETOOTH_UUID_TYPE_128) {
+ uint8_t buffer[16];
+ reverse_128(uuid->data, buffer);
+ err = gatt_client_discover_primary_services_by_uuid128(&btstack_packet_handler_discover_services, conn_handle, buffer);
+ } else {
+ DEBUG_EVENT_printf(" --> unknown UUID size\n");
+ return MP_EINVAL;
+ }
+ } else {
+ err = gatt_client_discover_primary_services(&btstack_packet_handler_discover_services, conn_handle);
+ }
+ return btstack_error_to_errno(err);
+}
+
+int mp_bluetooth_gattc_discover_characteristics(uint16_t conn_handle, uint16_t start_handle, uint16_t end_handle, const mp_obj_bluetooth_uuid_t *uuid) {
+ DEBUG_EVENT_printf("mp_bluetooth_gattc_discover_characteristics\n");
+ gatt_client_service_t service = {
+ // Only start/end handles needed for gatt_client_discover_characteristics_for_service.
+ .start_group_handle = start_handle,
+ .end_group_handle = end_handle,
+ .uuid16 = 0,
+ .uuid128 = {0},
+ };
+ uint8_t err;
+ if (uuid) {
+ if (uuid->type == MP_BLUETOOTH_UUID_TYPE_16) {
+ err = gatt_client_discover_characteristics_for_service_by_uuid16(&btstack_packet_handler_discover_characteristics, conn_handle, &service, get_uuid16(uuid));
+ } else if (uuid->type == MP_BLUETOOTH_UUID_TYPE_128) {
+ uint8_t buffer[16];
+ reverse_128(uuid->data, buffer);
+ err = gatt_client_discover_characteristics_for_service_by_uuid128(&btstack_packet_handler_discover_characteristics, conn_handle, &service, buffer);
+ } else {
+ DEBUG_EVENT_printf(" --> unknown UUID size\n");
+ return MP_EINVAL;
+ }
+ } else {
+ err = gatt_client_discover_characteristics_for_service(&btstack_packet_handler_discover_characteristics, conn_handle, &service);
+ }
+ return btstack_error_to_errno(err);
+}
+
+int mp_bluetooth_gattc_discover_descriptors(uint16_t conn_handle, uint16_t start_handle, uint16_t end_handle) {
+ DEBUG_EVENT_printf("mp_bluetooth_gattc_discover_descriptors\n");
+ gatt_client_characteristic_t characteristic = {
+ // Only start/end handles needed for gatt_client_discover_characteristic_descriptors.
+ .start_handle = start_handle,
+ .value_handle = 0,
+ .end_handle = end_handle,
+ .properties = 0,
+ .uuid16 = 0,
+ .uuid128 = {0},
+ };
+ return btstack_error_to_errno(gatt_client_discover_characteristic_descriptors(&btstack_packet_handler_discover_descriptors, conn_handle, &characteristic));
+}
+
+int mp_bluetooth_gattc_read(uint16_t conn_handle, uint16_t value_handle) {
+ DEBUG_EVENT_printf("mp_bluetooth_gattc_read\n");
+ return btstack_error_to_errno(gatt_client_read_value_of_characteristic_using_value_handle(&btstack_packet_handler_read, conn_handle, value_handle));
+}
+
+int mp_bluetooth_gattc_write(uint16_t conn_handle, uint16_t value_handle, const uint8_t *value, size_t *value_len, unsigned int mode) {
+ DEBUG_EVENT_printf("mp_bluetooth_gattc_write\n");
+
+ // We should be distinguishing between gatt_client_write_value_of_characteristic vs
+ // gatt_client_write_characteristic_descriptor_using_descriptor_handle.
+ // However both are implemented using send_gatt_write_attribute_value_request under the hood,
+ // and we get the exact same event to the packet handler.
+ // Same story for the "without response" version.
+
+ int err;
+ mp_btstack_pending_op_t *pending_op = NULL;
+
+ if (mode == MP_BLUETOOTH_WRITE_MODE_NO_RESPONSE) {
+ // If possible, this will send immediately, copying the buffer directly to the ACL buffer.
+ err = gatt_client_write_value_of_characteristic_without_response(conn_handle, value_handle, *value_len, (uint8_t *)value);
+ if (err == GATT_CLIENT_BUSY) {
+ DEBUG_EVENT_printf("mp_bluetooth_gattc_write: client busy\n");
+ // Can't send right now, need to take a copy of the buffer and add it to the queue.
+ pending_op = btstack_enqueue_pending_operation(MP_BLUETOOTH_BTSTACK_PENDING_WRITE_NO_RESPONSE, conn_handle, value_handle, value, *value_len);
+ // Notify when this conn_handle can write.
+ err = gatt_client_request_can_write_without_response_event(&btstack_packet_handler_generic, conn_handle);
+ } else {
+ DEBUG_EVENT_printf("mp_bluetooth_gattc_write: other failure: %d\n", err);
+ }
+ } else if (mode == MP_BLUETOOTH_WRITE_MODE_WITH_RESPONSE) {
+ // Pending operation copies the value buffer and keeps a GC reference
+ // until the response comes back (there is always a response).
+ pending_op = btstack_enqueue_pending_operation(MP_BLUETOOTH_BTSTACK_PENDING_WRITE, conn_handle, value_handle, value, *value_len);
+ err = gatt_client_write_value_of_characteristic(&btstack_packet_handler_write_with_response, conn_handle, value_handle, pending_op->len, pending_op->buf);
+ } else {
+ return MP_EINVAL;
+ }
+
+ if (pending_op && err != ERROR_CODE_SUCCESS) {
+ // Failure. Unref and free the pending operation.
+ btstack_remove_pending_operation(pending_op, true /* del */);
+ }
+
+ return btstack_error_to_errno(err);
+}
+#endif // MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE
+
+#endif // MICROPY_PY_BLUETOOTH && MICROPY_BLUETOOTH_BTSTACK
diff --git a/extmod/btstack/modbluetooth_btstack.h b/extmod/btstack/modbluetooth_btstack.h
new file mode 100644
index 0000000000..2fad86f226
--- /dev/null
+++ b/extmod/btstack/modbluetooth_btstack.h
@@ -0,0 +1,70 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2020 Damien P. George
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef MICROPY_INCLUDED_EXTMOD_BTSTACK_MODBLUETOOTH_BTSTACK_H
+#define MICROPY_INCLUDED_EXTMOD_BTSTACK_MODBLUETOOTH_BTSTACK_H
+
+#if MICROPY_PY_BLUETOOTH && MICROPY_BLUETOOTH_BTSTACK
+
+#include "extmod/modbluetooth.h"
+
+#include "lib/btstack/src/btstack.h"
+
+typedef struct _mp_btstack_pending_op_t mp_btstack_pending_op_t;
+
+typedef struct _mp_bluetooth_btstack_root_pointers_t {
+ // This stores both the advertising data and the scan response data, concatenated together.
+ uint8_t *adv_data;
+ // Total length of both.
+ size_t adv_data_alloc;
+
+ // Characteristic (and descriptor) value storage.
+ mp_gatts_db_t gatts_db;
+
+ btstack_linked_list_t pending_ops;
+
+ #if MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE
+ // Registration for notify/indicate events.
+ gatt_client_notification_t notification;
+ #endif
+} mp_bluetooth_btstack_root_pointers_t;
+
+enum {
+ MP_BLUETOOTH_BTSTACK_STATE_OFF,
+ MP_BLUETOOTH_BTSTACK_STATE_STARTING,
+ MP_BLUETOOTH_BTSTACK_STATE_ACTIVE,
+ MP_BLUETOOTH_BTSTACK_STATE_TIMEOUT,
+};
+
+extern volatile int mp_bluetooth_btstack_state;
+
+void mp_bluetooth_btstack_port_init(void);
+void mp_bluetooth_btstack_port_deinit(void);
+void mp_bluetooth_btstack_port_start(void);
+
+#endif // MICROPY_PY_BLUETOOTH && MICROPY_BLUETOOTH_BTSTACK
+
+#endif // MICROPY_INCLUDED_EXTMOD_BTSTACK_MODBLUETOOTH_BTSTACK_H
diff --git a/extmod/crypto-algorithms/sha256.c b/extmod/crypto-algorithms/sha256.c
index 276611cfd5..24e964749b 100644
--- a/extmod/crypto-algorithms/sha256.c
+++ b/extmod/crypto-algorithms/sha256.c
@@ -1,7 +1,8 @@
/*********************************************************************
+* Source: https://github.com/B-Con/crypto-algorithms
* Filename: sha256.c
* Author: Brad Conte (brad AT bradconte.com)
-* Copyright:
+* Copyright: This code is released into the public domain.
* Disclaimer: This code is presented "as is" without any guarantees.
* Details: Implementation of the SHA-256 hashing algorithm.
SHA-256 is one of the three algorithms in the SHA2
diff --git a/extmod/crypto-algorithms/sha256.h b/extmod/crypto-algorithms/sha256.h
index caa1f81020..9c19472ea2 100644
--- a/extmod/crypto-algorithms/sha256.h
+++ b/extmod/crypto-algorithms/sha256.h
@@ -1,7 +1,8 @@
/*********************************************************************
+* Source: https://github.com/B-Con/crypto-algorithms
* Filename: sha256.h
* Author: Brad Conte (brad AT bradconte.com)
-* Copyright:
+* Copyright: This code is released into the public domain.
* Disclaimer: This code is presented "as is" without any guarantees.
* Details: Defines the API for the corresponding SHA1 implementation.
*********************************************************************/
diff --git a/extmod/extmod.mk b/extmod/extmod.mk
new file mode 100644
index 0000000000..e312acba86
--- /dev/null
+++ b/extmod/extmod.mk
@@ -0,0 +1,229 @@
+# This makefile fragment provides rules to build 3rd-party components for extmod modules
+
+################################################################################
+# VFS FAT FS
+
+OOFATFS_DIR = lib/oofatfs
+
+# this sets the config file for FatFs
+CFLAGS_MOD += -DFFCONF_H=\"$(OOFATFS_DIR)/ffconf.h\"
+
+ifeq ($(MICROPY_VFS_FAT),1)
+CFLAGS_MOD += -DMICROPY_VFS_FAT=1
+SRC_MOD += $(addprefix $(OOFATFS_DIR)/,\
+ ff.c \
+ ffunicode.c \
+ )
+endif
+
+################################################################################
+# VFS littlefs
+
+LITTLEFS_DIR = lib/littlefs
+
+ifeq ($(MICROPY_VFS_LFS1),1)
+CFLAGS_MOD += -DMICROPY_VFS_LFS1=1
+CFLAGS_MOD += -DLFS1_NO_MALLOC -DLFS1_NO_DEBUG -DLFS1_NO_WARN -DLFS1_NO_ERROR -DLFS1_NO_ASSERT
+SRC_MOD += $(addprefix $(LITTLEFS_DIR)/,\
+ lfs1.c \
+ lfs1_util.c \
+ )
+endif
+
+ifeq ($(MICROPY_VFS_LFS2),1)
+CFLAGS_MOD += -DMICROPY_VFS_LFS2=1
+CFLAGS_MOD += -DLFS2_NO_MALLOC -DLFS2_NO_DEBUG -DLFS2_NO_WARN -DLFS2_NO_ERROR -DLFS2_NO_ASSERT
+SRC_MOD += $(addprefix $(LITTLEFS_DIR)/,\
+ lfs2.c \
+ lfs2_util.c \
+ )
+endif
+
+################################################################################
+# ussl
+
+ifeq ($(MICROPY_PY_USSL),1)
+CFLAGS_MOD += -DMICROPY_PY_USSL=1
+ifeq ($(MICROPY_SSL_AXTLS),1)
+CFLAGS_MOD += -DMICROPY_SSL_AXTLS=1 -I$(TOP)/lib/axtls/ssl -I$(TOP)/lib/axtls/crypto -I$(TOP)/extmod/axtls-include
+AXTLS_DIR = lib/axtls
+$(BUILD)/$(AXTLS_DIR)/%.o: CFLAGS += -Wno-all -Wno-unused-parameter -Wno-uninitialized -Wno-sign-compare -Wno-old-style-definition -Dmp_stream_errno=errno $(AXTLS_DEFS_EXTRA)
+SRC_MOD += $(addprefix $(AXTLS_DIR)/,\
+ ssl/asn1.c \
+ ssl/loader.c \
+ ssl/tls1.c \
+ ssl/tls1_svr.c \
+ ssl/tls1_clnt.c \
+ ssl/x509.c \
+ crypto/aes.c \
+ crypto/bigint.c \
+ crypto/crypto_misc.c \
+ crypto/hmac.c \
+ crypto/md5.c \
+ crypto/rsa.c \
+ crypto/sha1.c \
+ )
+else ifeq ($(MICROPY_SSL_MBEDTLS),1)
+MBEDTLS_DIR = lib/mbedtls
+CFLAGS_MOD += -DMICROPY_SSL_MBEDTLS=1 -I$(TOP)/$(MBEDTLS_DIR)/include
+SRC_MOD += $(addprefix $(MBEDTLS_DIR)/library/,\
+ aes.c \
+ aesni.c \
+ arc4.c \
+ asn1parse.c \
+ asn1write.c \
+ base64.c \
+ bignum.c \
+ blowfish.c \
+ camellia.c \
+ ccm.c \
+ certs.c \
+ chacha20.c \
+ chachapoly.c \
+ cipher.c \
+ cipher_wrap.c \
+ cmac.c \
+ ctr_drbg.c \
+ debug.c \
+ des.c \
+ dhm.c \
+ ecdh.c \
+ ecdsa.c \
+ ecjpake.c \
+ ecp.c \
+ ecp_curves.c \
+ entropy.c \
+ entropy_poll.c \
+ error.c \
+ gcm.c \
+ havege.c \
+ hmac_drbg.c \
+ md2.c \
+ md4.c \
+ md5.c \
+ md.c \
+ md_wrap.c \
+ oid.c \
+ padlock.c \
+ pem.c \
+ pk.c \
+ pkcs11.c \
+ pkcs12.c \
+ pkcs5.c \
+ pkparse.c \
+ pk_wrap.c \
+ pkwrite.c \
+ platform.c \
+ platform_util.c \
+ poly1305.c \
+ ripemd160.c \
+ rsa.c \
+ rsa_internal.c \
+ sha1.c \
+ sha256.c \
+ sha512.c \
+ ssl_cache.c \
+ ssl_ciphersuites.c \
+ ssl_cli.c \
+ ssl_cookie.c \
+ ssl_srv.c \
+ ssl_ticket.c \
+ ssl_tls.c \
+ timing.c \
+ x509.c \
+ x509_create.c \
+ x509_crl.c \
+ x509_crt.c \
+ x509_csr.c \
+ x509write_crt.c \
+ x509write_csr.c \
+ xtea.c \
+ )
+endif
+endif
+
+################################################################################
+# lwip
+
+ifeq ($(MICROPY_PY_LWIP),1)
+# A port should add an include path where lwipopts.h can be found (eg extmod/lwip-include)
+LWIP_DIR = lib/lwip/src
+INC += -I$(TOP)/$(LWIP_DIR)/include
+CFLAGS_MOD += -DMICROPY_PY_LWIP=1
+$(BUILD)/$(LWIP_DIR)/core/ipv4/dhcp.o: CFLAGS_MOD += -Wno-address
+SRC_MOD += extmod/modlwip.c lib/netutils/netutils.c
+SRC_MOD += $(addprefix $(LWIP_DIR)/,\
+ apps/mdns/mdns.c \
+ core/def.c \
+ core/dns.c \
+ core/inet_chksum.c \
+ core/init.c \
+ core/ip.c \
+ core/mem.c \
+ core/memp.c \
+ core/netif.c \
+ core/pbuf.c \
+ core/raw.c \
+ core/stats.c \
+ core/sys.c \
+ core/tcp.c \
+ core/tcp_in.c \
+ core/tcp_out.c \
+ core/timeouts.c \
+ core/udp.c \
+ core/ipv4/autoip.c \
+ core/ipv4/dhcp.c \
+ core/ipv4/etharp.c \
+ core/ipv4/icmp.c \
+ core/ipv4/igmp.c \
+ core/ipv4/ip4_addr.c \
+ core/ipv4/ip4.c \
+ core/ipv4/ip4_frag.c \
+ core/ipv6/dhcp6.c \
+ core/ipv6/ethip6.c \
+ core/ipv6/icmp6.c \
+ core/ipv6/inet6.c \
+ core/ipv6/ip6_addr.c \
+ core/ipv6/ip6.c \
+ core/ipv6/ip6_frag.c \
+ core/ipv6/mld6.c \
+ core/ipv6/nd6.c \
+ netif/ethernet.c \
+ )
+ifeq ($(MICROPY_PY_LWIP_SLIP),1)
+CFLAGS_MOD += -DMICROPY_PY_LWIP_SLIP=1
+SRC_MOD += $(LWIP_DIR)/netif/slipif.c
+endif
+endif
+
+################################################################################
+# btree
+
+ifeq ($(MICROPY_PY_BTREE),1)
+BTREE_DIR = lib/berkeley-db-1.xx
+BTREE_DEFS = -D__DBINTERFACE_PRIVATE=1 -Dmpool_error=printf -Dabort=abort_ "-Dvirt_fd_t=void*" $(BTREE_DEFS_EXTRA)
+INC += -I$(TOP)/$(BTREE_DIR)/PORT/include
+SRC_MOD += extmod/modbtree.c
+SRC_MOD += $(addprefix $(BTREE_DIR)/,\
+ btree/bt_close.c \
+ btree/bt_conv.c \
+ btree/bt_debug.c \
+ btree/bt_delete.c \
+ btree/bt_get.c \
+ btree/bt_open.c \
+ btree/bt_overflow.c \
+ btree/bt_page.c \
+ btree/bt_put.c \
+ btree/bt_search.c \
+ btree/bt_seq.c \
+ btree/bt_split.c \
+ btree/bt_utils.c \
+ mpool/mpool.c \
+ )
+CFLAGS_MOD += -DMICROPY_PY_BTREE=1
+# we need to suppress certain warnings to get berkeley-db to compile cleanly
+# and we have separate BTREE_DEFS so the definitions don't interfere with other source code
+$(BUILD)/$(BTREE_DIR)/%.o: CFLAGS += -Wno-old-style-definition -Wno-sign-compare -Wno-unused-parameter $(BTREE_DEFS)
+$(BUILD)/extmod/modbtree.o: CFLAGS += $(BTREE_DEFS)
+endif
+
diff --git a/extmod/machine_i2c.c b/extmod/machine_i2c.c
index 0687aa9d2d..c804cf5703 100644
--- a/extmod/machine_i2c.c
+++ b/extmod/machine_i2c.c
@@ -183,7 +183,7 @@ STATIC int mp_hal_i2c_read_byte(machine_i2c_obj_t *self, uint8_t *val, int nack)
// >=0 - success; for read it's 0, for write it's number of acks received
// <0 - error, with errno being the negative of the return value
int mp_machine_soft_i2c_transfer(mp_obj_base_t *self_in, uint16_t addr, size_t n, mp_machine_i2c_buf_t *bufs, unsigned int flags) {
- machine_i2c_obj_t *self = (machine_i2c_obj_t*)self_in;
+ machine_i2c_obj_t *self = (machine_i2c_obj_t *)self_in;
// start the I2C transaction
int ret = mp_hal_i2c_start(self);
@@ -267,7 +267,7 @@ int mp_machine_i2c_transfer_adaptor(mp_obj_base_t *self, uint16_t addr, size_t n
}
}
- mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t*)self->type->protocol;
+ mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t *)self->type->protocol;
int ret = i2c_p->transfer_single(self, addr, len, buf, flags);
if (n > 1) {
@@ -286,15 +286,15 @@ int mp_machine_i2c_transfer_adaptor(mp_obj_base_t *self, uint16_t addr, size_t n
}
STATIC int mp_machine_i2c_readfrom(mp_obj_base_t *self, uint16_t addr, uint8_t *dest, size_t len, bool stop) {
- mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t*)self->type->protocol;
+ mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t *)self->type->protocol;
mp_machine_i2c_buf_t buf = {.len = len, .buf = dest};
unsigned int flags = MP_MACHINE_I2C_FLAG_READ | (stop ? MP_MACHINE_I2C_FLAG_STOP : 0);
return i2c_p->transfer(self, addr, 1, &buf, flags);
}
STATIC int mp_machine_i2c_writeto(mp_obj_base_t *self, uint16_t addr, const uint8_t *src, size_t len, bool stop) {
- mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t*)self->type->protocol;
- mp_machine_i2c_buf_t buf = {.len = len, .buf = (uint8_t*)src};
+ mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t *)self->type->protocol;
+ mp_machine_i2c_buf_t buf = {.len = len, .buf = (uint8_t *)src};
unsigned int flags = stop ? MP_MACHINE_I2C_FLAG_STOP : 0;
return i2c_p->transfer(self, addr, 1, &buf, flags);
}
@@ -327,7 +327,7 @@ STATIC mp_obj_t machine_i2c_make_new(const mp_obj_type_t *type, size_t n_args, s
extern mp_obj_t MICROPY_PY_MACHINE_I2C_MAKE_NEW(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args);
return MICROPY_PY_MACHINE_I2C_MAKE_NEW(type, n_args, n_kw, args);
#else
- mp_raise_ValueError("invalid I2C peripheral");
+ mp_raise_ValueError(MP_ERROR_TEXT("invalid I2C peripheral"));
#endif
}
--n_args;
@@ -364,10 +364,10 @@ STATIC mp_obj_t machine_i2c_scan(mp_obj_t self_in) {
MP_DEFINE_CONST_FUN_OBJ_1(machine_i2c_scan_obj, machine_i2c_scan);
STATIC mp_obj_t machine_i2c_start(mp_obj_t self_in) {
- mp_obj_base_t *self = (mp_obj_base_t*)MP_OBJ_TO_PTR(self_in);
- mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t*)self->type->protocol;
+ mp_obj_base_t *self = (mp_obj_base_t *)MP_OBJ_TO_PTR(self_in);
+ mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t *)self->type->protocol;
if (i2c_p->start == NULL) {
- mp_raise_msg(&mp_type_OSError, "I2C operation not supported");
+ mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("I2C operation not supported"));
}
int ret = i2c_p->start(self);
if (ret != 0) {
@@ -378,10 +378,10 @@ STATIC mp_obj_t machine_i2c_start(mp_obj_t self_in) {
MP_DEFINE_CONST_FUN_OBJ_1(machine_i2c_start_obj, machine_i2c_start);
STATIC mp_obj_t machine_i2c_stop(mp_obj_t self_in) {
- mp_obj_base_t *self = (mp_obj_base_t*)MP_OBJ_TO_PTR(self_in);
- mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t*)self->type->protocol;
+ mp_obj_base_t *self = (mp_obj_base_t *)MP_OBJ_TO_PTR(self_in);
+ mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t *)self->type->protocol;
if (i2c_p->stop == NULL) {
- mp_raise_msg(&mp_type_OSError, "I2C operation not supported");
+ mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("I2C operation not supported"));
}
int ret = i2c_p->stop(self);
if (ret != 0) {
@@ -392,10 +392,10 @@ STATIC mp_obj_t machine_i2c_stop(mp_obj_t self_in) {
MP_DEFINE_CONST_FUN_OBJ_1(machine_i2c_stop_obj, machine_i2c_stop);
STATIC mp_obj_t machine_i2c_readinto(size_t n_args, const mp_obj_t *args) {
- mp_obj_base_t *self = (mp_obj_base_t*)MP_OBJ_TO_PTR(args[0]);
- mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t*)self->type->protocol;
+ mp_obj_base_t *self = (mp_obj_base_t *)MP_OBJ_TO_PTR(args[0]);
+ mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t *)self->type->protocol;
if (i2c_p->read == NULL) {
- mp_raise_msg(&mp_type_OSError, "I2C operation not supported");
+ mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("I2C operation not supported"));
}
// get the buffer to read into
@@ -416,10 +416,10 @@ STATIC mp_obj_t machine_i2c_readinto(size_t n_args, const mp_obj_t *args) {
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_i2c_readinto_obj, 2, 3, machine_i2c_readinto);
STATIC mp_obj_t machine_i2c_write(mp_obj_t self_in, mp_obj_t buf_in) {
- mp_obj_base_t *self = (mp_obj_base_t*)MP_OBJ_TO_PTR(self_in);
- mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t*)self->type->protocol;
+ mp_obj_base_t *self = (mp_obj_base_t *)MP_OBJ_TO_PTR(self_in);
+ mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t *)self->type->protocol;
if (i2c_p->write == NULL) {
- mp_raise_msg(&mp_type_OSError, "I2C operation not supported");
+ mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("I2C operation not supported"));
}
// get the buffer to write from
@@ -438,12 +438,12 @@ STATIC mp_obj_t machine_i2c_write(mp_obj_t self_in, mp_obj_t buf_in) {
MP_DEFINE_CONST_FUN_OBJ_2(machine_i2c_write_obj, machine_i2c_write);
STATIC mp_obj_t machine_i2c_readfrom(size_t n_args, const mp_obj_t *args) {
- mp_obj_base_t *self = (mp_obj_base_t*)MP_OBJ_TO_PTR(args[0]);
+ mp_obj_base_t *self = (mp_obj_base_t *)MP_OBJ_TO_PTR(args[0]);
mp_int_t addr = mp_obj_get_int(args[1]);
vstr_t vstr;
vstr_init_len(&vstr, mp_obj_get_int(args[2]));
bool stop = (n_args == 3) ? true : mp_obj_is_true(args[3]);
- int ret = mp_machine_i2c_readfrom(self, addr, (uint8_t*)vstr.buf, vstr.len, stop);
+ int ret = mp_machine_i2c_readfrom(self, addr, (uint8_t *)vstr.buf, vstr.len, stop);
if (ret < 0) {
mp_raise_OSError(-ret);
}
@@ -452,7 +452,7 @@ STATIC mp_obj_t machine_i2c_readfrom(size_t n_args, const mp_obj_t *args) {
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_i2c_readfrom_obj, 3, 4, machine_i2c_readfrom);
STATIC mp_obj_t machine_i2c_readfrom_into(size_t n_args, const mp_obj_t *args) {
- mp_obj_base_t *self = (mp_obj_base_t*)MP_OBJ_TO_PTR(args[0]);
+ mp_obj_base_t *self = (mp_obj_base_t *)MP_OBJ_TO_PTR(args[0]);
mp_int_t addr = mp_obj_get_int(args[1]);
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(args[2], &bufinfo, MP_BUFFER_WRITE);
@@ -466,7 +466,7 @@ STATIC mp_obj_t machine_i2c_readfrom_into(size_t n_args, const mp_obj_t *args) {
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_i2c_readfrom_into_obj, 3, 4, machine_i2c_readfrom_into);
STATIC mp_obj_t machine_i2c_writeto(size_t n_args, const mp_obj_t *args) {
- mp_obj_base_t *self = (mp_obj_base_t*)MP_OBJ_TO_PTR(args[0]);
+ mp_obj_base_t *self = (mp_obj_base_t *)MP_OBJ_TO_PTR(args[0]);
mp_int_t addr = mp_obj_get_int(args[1]);
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(args[2], &bufinfo, MP_BUFFER_READ);
@@ -481,13 +481,13 @@ STATIC mp_obj_t machine_i2c_writeto(size_t n_args, const mp_obj_t *args) {
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_i2c_writeto_obj, 3, 4, machine_i2c_writeto);
STATIC mp_obj_t machine_i2c_writevto(size_t n_args, const mp_obj_t *args) {
- mp_obj_base_t *self = (mp_obj_base_t*)MP_OBJ_TO_PTR(args[0]);
+ mp_obj_base_t *self = (mp_obj_base_t *)MP_OBJ_TO_PTR(args[0]);
mp_int_t addr = mp_obj_get_int(args[1]);
// Get the list of data buffer(s) to write
size_t nitems;
const mp_obj_t *items;
- mp_obj_get_array(args[2], &nitems, (mp_obj_t**)&items);
+ mp_obj_get_array(args[2], &nitems, (mp_obj_t **)&items);
// Get the stop argument
bool stop = (n_args == 3) ? true : mp_obj_is_true(args[3]);
@@ -513,7 +513,7 @@ STATIC mp_obj_t machine_i2c_writevto(size_t n_args, const mp_obj_t *args) {
}
// Do the I2C transfer
- mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t*)self->type->protocol;
+ mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t *)self->type->protocol;
int ret = i2c_p->transfer(self, addr, nbufs, bufs, stop ? MP_MACHINE_I2C_FLAG_STOP : 0);
mp_local_free(bufs);
@@ -526,13 +526,24 @@ STATIC mp_obj_t machine_i2c_writevto(size_t n_args, const mp_obj_t *args) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_i2c_writevto_obj, 3, 4, machine_i2c_writevto);
-STATIC int read_mem(mp_obj_t self_in, uint16_t addr, uint32_t memaddr, uint8_t addrsize, uint8_t *buf, size_t len) {
- mp_obj_base_t *self = (mp_obj_base_t*)MP_OBJ_TO_PTR(self_in);
- uint8_t memaddr_buf[4];
+STATIC size_t fill_memaddr_buf(uint8_t *memaddr_buf, uint32_t memaddr, uint8_t addrsize) {
size_t memaddr_len = 0;
+ if ((addrsize & 7) != 0 || addrsize > 32) {
+ mp_raise_ValueError(MP_ERROR_TEXT("invalid addrsize"));
+ }
for (int16_t i = addrsize - 8; i >= 0; i -= 8) {
memaddr_buf[memaddr_len++] = memaddr >> i;
}
+ return memaddr_len;
+}
+
+STATIC int read_mem(mp_obj_t self_in, uint16_t addr, uint32_t memaddr, uint8_t addrsize, uint8_t *buf, size_t len) {
+ mp_obj_base_t *self = (mp_obj_base_t *)MP_OBJ_TO_PTR(self_in);
+
+ // Create buffer with memory address
+ uint8_t memaddr_buf[4];
+ size_t memaddr_len = fill_memaddr_buf(&memaddr_buf[0], memaddr, addrsize);
+
int ret = mp_machine_i2c_writeto(self, addr, memaddr_buf, memaddr_len, false);
if (ret != memaddr_len) {
// must generate STOP
@@ -543,23 +554,20 @@ STATIC int read_mem(mp_obj_t self_in, uint16_t addr, uint32_t memaddr, uint8_t a
}
STATIC int write_mem(mp_obj_t self_in, uint16_t addr, uint32_t memaddr, uint8_t addrsize, const uint8_t *buf, size_t len) {
- mp_obj_base_t *self = (mp_obj_base_t*)MP_OBJ_TO_PTR(self_in);
+ mp_obj_base_t *self = (mp_obj_base_t *)MP_OBJ_TO_PTR(self_in);
// Create buffer with memory address
- size_t memaddr_len = 0;
uint8_t memaddr_buf[4];
- for (int16_t i = addrsize - 8; i >= 0; i -= 8) {
- memaddr_buf[memaddr_len++] = memaddr >> i;
- }
+ size_t memaddr_len = fill_memaddr_buf(&memaddr_buf[0], memaddr, addrsize);
// Create partial write buffers
mp_machine_i2c_buf_t bufs[2] = {
{.len = memaddr_len, .buf = memaddr_buf},
- {.len = len, .buf = (uint8_t*)buf},
+ {.len = len, .buf = (uint8_t *)buf},
};
// Do I2C transfer
- mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t*)self->type->protocol;
+ mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t *)self->type->protocol;
return i2c_p->transfer(self, addr, 2, bufs, MP_MACHINE_I2C_FLAG_STOP);
}
@@ -582,7 +590,7 @@ STATIC mp_obj_t machine_i2c_readfrom_mem(size_t n_args, const mp_obj_t *pos_args
// do the transfer
int ret = read_mem(pos_args[0], args[ARG_addr].u_int, args[ARG_memaddr].u_int,
- args[ARG_addrsize].u_int, (uint8_t*)vstr.buf, vstr.len);
+ args[ARG_addrsize].u_int, (uint8_t *)vstr.buf, vstr.len);
if (ret < 0) {
mp_raise_OSError(-ret);
}
@@ -658,7 +666,7 @@ STATIC const mp_rom_map_elem_t machine_i2c_locals_dict_table[] = {
MP_DEFINE_CONST_DICT(mp_machine_soft_i2c_locals_dict, machine_i2c_locals_dict_table);
int mp_machine_soft_i2c_read(mp_obj_base_t *self_in, uint8_t *dest, size_t len, bool nack) {
- machine_i2c_obj_t *self = (machine_i2c_obj_t*)self_in;
+ machine_i2c_obj_t *self = (machine_i2c_obj_t *)self_in;
while (len--) {
int ret = mp_hal_i2c_read_byte(self, dest++, nack && (len == 0));
if (ret != 0) {
@@ -669,7 +677,7 @@ int mp_machine_soft_i2c_read(mp_obj_base_t *self_in, uint8_t *dest, size_t len,
}
int mp_machine_soft_i2c_write(mp_obj_base_t *self_in, const uint8_t *src, size_t len) {
- machine_i2c_obj_t *self = (machine_i2c_obj_t*)self_in;
+ machine_i2c_obj_t *self = (machine_i2c_obj_t *)self_in;
int num_acks = 0;
while (len--) {
int ret = mp_hal_i2c_write_byte(self, *src++);
@@ -685,8 +693,8 @@ int mp_machine_soft_i2c_write(mp_obj_base_t *self_in, const uint8_t *src, size_t
}
STATIC const mp_machine_i2c_p_t mp_machine_soft_i2c_p = {
- .start = (int(*)(mp_obj_base_t*))mp_hal_i2c_start,
- .stop = (int(*)(mp_obj_base_t*))mp_hal_i2c_stop,
+ .start = (int (*)(mp_obj_base_t *))mp_hal_i2c_start,
+ .stop = (int (*)(mp_obj_base_t *))mp_hal_i2c_stop,
.read = mp_machine_soft_i2c_read,
.write = mp_machine_soft_i2c_write,
.transfer = mp_machine_soft_i2c_transfer,
@@ -697,7 +705,7 @@ const mp_obj_type_t machine_i2c_type = {
.name = MP_QSTR_I2C,
.make_new = machine_i2c_make_new,
.protocol = &mp_machine_soft_i2c_p,
- .locals_dict = (mp_obj_dict_t*)&mp_machine_soft_i2c_locals_dict,
+ .locals_dict = (mp_obj_dict_t *)&mp_machine_soft_i2c_locals_dict,
};
#endif // MICROPY_PY_MACHINE_I2C
diff --git a/extmod/machine_mem.c b/extmod/machine_mem.c
index b9f16507c4..a1494bd51a 100644
--- a/extmod/machine_mem.c
+++ b/extmod/machine_mem.c
@@ -42,7 +42,7 @@
STATIC uintptr_t machine_mem_get_addr(mp_obj_t addr_o, uint align) {
uintptr_t addr = mp_obj_int_get_truncated(addr_o);
if ((addr & (align - 1)) != 0) {
- nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "address %08x is not aligned to %d bytes", addr, align));
+ mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("address %08x is not aligned to %d bytes"), addr, align);
}
return addr;
}
@@ -71,9 +71,15 @@ STATIC mp_obj_t machine_mem_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t va
uintptr_t addr = MICROPY_MACHINE_MEM_GET_READ_ADDR(index, self->elem_size);
uint32_t val;
switch (self->elem_size) {
- case 1: val = (*(uint8_t*)addr); break;
- case 2: val = (*(uint16_t*)addr); break;
- default: val = (*(uint32_t*)addr); break;
+ case 1:
+ val = (*(uint8_t *)addr);
+ break;
+ case 2:
+ val = (*(uint16_t *)addr);
+ break;
+ default:
+ val = (*(uint32_t *)addr);
+ break;
}
return mp_obj_new_int(val);
} else {
@@ -81,9 +87,15 @@ STATIC mp_obj_t machine_mem_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t va
uintptr_t addr = MICROPY_MACHINE_MEM_GET_WRITE_ADDR(index, self->elem_size);
uint32_t val = mp_obj_get_int_truncated(value);
switch (self->elem_size) {
- case 1: (*(uint8_t*)addr) = val; break;
- case 2: (*(uint16_t*)addr) = val; break;
- default: (*(uint32_t*)addr) = val; break;
+ case 1:
+ (*(uint8_t *)addr) = val;
+ break;
+ case 2:
+ (*(uint16_t *)addr) = val;
+ break;
+ default:
+ (*(uint32_t *)addr) = val;
+ break;
}
return mp_const_none;
}
diff --git a/extmod/machine_pulse.c b/extmod/machine_pulse.c
index 5f837479dd..7178b22d79 100644
--- a/extmod/machine_pulse.c
+++ b/extmod/machine_pulse.c
@@ -30,7 +30,7 @@
#if MICROPY_PY_MACHINE_PULSE
-mp_uint_t machine_time_pulse_us(mp_hal_pin_obj_t pin, int pulse_level, mp_uint_t timeout_us) {
+MP_WEAK mp_uint_t machine_time_pulse_us(mp_hal_pin_obj_t pin, int pulse_level, mp_uint_t timeout_us) {
mp_uint_t start = mp_hal_ticks_us();
while (mp_hal_pin_read(pin) != pulse_level) {
if ((mp_uint_t)(mp_hal_ticks_us() - start) >= timeout_us) {
diff --git a/extmod/machine_signal.c b/extmod/machine_signal.c
index 8204ef174a..f112ddc57c 100644
--- a/extmod/machine_signal.c
+++ b/extmod/machine_signal.c
@@ -50,8 +50,8 @@ STATIC mp_obj_t signal_make_new(const mp_obj_type_t *type, size_t n_args, size_t
mp_pin_p_t *pin_p = NULL;
if (n_args > 0 && mp_obj_is_obj(args[0])) {
- mp_obj_base_t *pin_base = (mp_obj_base_t*)MP_OBJ_TO_PTR(args[0]);
- pin_p = (mp_pin_p_t*)pin_base->type->protocol;
+ mp_obj_base_t *pin_base = (mp_obj_base_t *)MP_OBJ_TO_PTR(args[0]);
+ pin_p = (mp_pin_p_t *)pin_base->type->protocol;
}
if (pin_p == NULL) {
@@ -90,8 +90,7 @@ STATIC mp_obj_t signal_make_new(const mp_obj_type_t *type, size_t n_args, size_t
pin = MICROPY_PY_MACHINE_PIN_MAKE_NEW(NULL, n_args, n_kw, pin_args);
mp_local_free(pin_args);
- }
- else
+ } else
#endif
// Otherwise there should be 1 or 2 args
{
@@ -180,7 +179,7 @@ const mp_obj_type_t machine_signal_type = {
.make_new = signal_make_new,
.call = signal_call,
.protocol = &signal_pin_p,
- .locals_dict = (void*)&signal_locals_dict,
+ .locals_dict = (void *)&signal_locals_dict,
};
#endif // MICROPY_PY_MACHINE
diff --git a/extmod/machine_spi.c b/extmod/machine_spi.c
index f0c4896c2e..a7f96573a7 100644
--- a/extmod/machine_spi.c
+++ b/extmod/machine_spi.c
@@ -52,7 +52,7 @@ mp_obj_t mp_machine_spi_make_new(const mp_obj_type_t *type, size_t n_args, size_
extern mp_obj_t MICROPY_PY_MACHINE_SPI_MAKE_NEW(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args);
return MICROPY_PY_MACHINE_SPI_MAKE_NEW(type, n_args, n_kw, args);
#else
- mp_raise_ValueError("invalid SPI peripheral");
+ mp_raise_ValueError(MP_ERROR_TEXT("invalid SPI peripheral"));
#endif
}
--n_args;
@@ -64,16 +64,16 @@ mp_obj_t mp_machine_spi_make_new(const mp_obj_type_t *type, size_t n_args, size_
}
STATIC mp_obj_t machine_spi_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
- mp_obj_base_t *s = (mp_obj_base_t*)MP_OBJ_TO_PTR(args[0]);
- mp_machine_spi_p_t *spi_p = (mp_machine_spi_p_t*)s->type->protocol;
+ mp_obj_base_t *s = (mp_obj_base_t *)MP_OBJ_TO_PTR(args[0]);
+ mp_machine_spi_p_t *spi_p = (mp_machine_spi_p_t *)s->type->protocol;
spi_p->init(s, n_args - 1, args + 1, kw_args);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_spi_init_obj, 1, machine_spi_init);
STATIC mp_obj_t machine_spi_deinit(mp_obj_t self) {
- mp_obj_base_t *s = (mp_obj_base_t*)MP_OBJ_TO_PTR(self);
- mp_machine_spi_p_t *spi_p = (mp_machine_spi_p_t*)s->type->protocol;
+ mp_obj_base_t *s = (mp_obj_base_t *)MP_OBJ_TO_PTR(self);
+ mp_machine_spi_p_t *spi_p = (mp_machine_spi_p_t *)s->type->protocol;
if (spi_p->deinit != NULL) {
spi_p->deinit(s);
}
@@ -82,8 +82,8 @@ STATIC mp_obj_t machine_spi_deinit(mp_obj_t self) {
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_spi_deinit_obj, machine_spi_deinit);
STATIC void mp_machine_spi_transfer(mp_obj_t self, size_t len, const void *src, void *dest) {
- mp_obj_base_t *s = (mp_obj_base_t*)MP_OBJ_TO_PTR(self);
- mp_machine_spi_p_t *spi_p = (mp_machine_spi_p_t*)s->type->protocol;
+ mp_obj_base_t *s = (mp_obj_base_t *)MP_OBJ_TO_PTR(self);
+ mp_machine_spi_p_t *spi_p = (mp_machine_spi_p_t *)s->type->protocol;
spi_p->transfer(s, len, src, dest);
}
@@ -108,7 +108,7 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_machine_spi_readinto_obj, 2, 3, mp_machin
STATIC mp_obj_t mp_machine_spi_write(mp_obj_t self, mp_obj_t wr_buf) {
mp_buffer_info_t src;
mp_get_buffer_raise(wr_buf, &src, MP_BUFFER_READ);
- mp_machine_spi_transfer(self, src.len, (const uint8_t*)src.buf, NULL);
+ mp_machine_spi_transfer(self, src.len, (const uint8_t *)src.buf, NULL);
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_2(mp_machine_spi_write_obj, mp_machine_spi_write);
@@ -119,7 +119,7 @@ STATIC mp_obj_t mp_machine_spi_write_readinto(mp_obj_t self, mp_obj_t wr_buf, mp
mp_buffer_info_t dest;
mp_get_buffer_raise(rd_buf, &dest, MP_BUFFER_WRITE);
if (src.len != dest.len) {
- mp_raise_ValueError("buffers must be the same length");
+ mp_raise_ValueError(MP_ERROR_TEXT("buffers must be the same length"));
}
mp_machine_spi_transfer(self, src.len, src.buf, dest.buf);
return mp_const_none;
@@ -202,15 +202,15 @@ STATIC mp_obj_t mp_machine_soft_spi_make_new(const mp_obj_type_t *type, size_t n
self->spi.polarity = args[ARG_polarity].u_int;
self->spi.phase = args[ARG_phase].u_int;
if (args[ARG_bits].u_int != 8) {
- mp_raise_ValueError("bits must be 8");
+ mp_raise_ValueError(MP_ERROR_TEXT("bits must be 8"));
}
if (args[ARG_firstbit].u_int != MICROPY_PY_MACHINE_SPI_MSB) {
- mp_raise_ValueError("firstbit must be MSB");
+ mp_raise_ValueError(MP_ERROR_TEXT("firstbit must be MSB"));
}
if (args[ARG_sck].u_obj == MP_OBJ_NULL
|| args[ARG_mosi].u_obj == MP_OBJ_NULL
|| args[ARG_miso].u_obj == MP_OBJ_NULL) {
- mp_raise_ValueError("must specify all of sck/mosi/miso");
+ mp_raise_ValueError(MP_ERROR_TEXT("must specify all of sck/mosi/miso"));
}
self->spi.sck = mp_hal_get_pin_obj(args[ARG_sck].u_obj);
self->spi.mosi = mp_hal_get_pin_obj(args[ARG_mosi].u_obj);
@@ -223,7 +223,7 @@ STATIC mp_obj_t mp_machine_soft_spi_make_new(const mp_obj_type_t *type, size_t n
}
STATIC void mp_machine_soft_spi_init(mp_obj_base_t *self_in, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
- mp_machine_soft_spi_obj_t *self = (mp_machine_soft_spi_obj_t*)self_in;
+ mp_machine_soft_spi_obj_t *self = (mp_machine_soft_spi_obj_t *)self_in;
enum { ARG_baudrate, ARG_polarity, ARG_phase, ARG_sck, ARG_mosi, ARG_miso };
static const mp_arg_t allowed_args[] = {
@@ -261,7 +261,7 @@ STATIC void mp_machine_soft_spi_init(mp_obj_base_t *self_in, size_t n_args, cons
}
STATIC void mp_machine_soft_spi_transfer(mp_obj_base_t *self_in, size_t len, const uint8_t *src, uint8_t *dest) {
- mp_machine_soft_spi_obj_t *self = (mp_machine_soft_spi_obj_t*)self_in;
+ mp_machine_soft_spi_obj_t *self = (mp_machine_soft_spi_obj_t *)self_in;
mp_soft_spi_transfer(&self->spi, len, src, dest);
}
@@ -277,7 +277,7 @@ const mp_obj_type_t mp_machine_soft_spi_type = {
.print = mp_machine_soft_spi_print,
.make_new = mp_machine_spi_make_new, // delegate to master constructor
.protocol = &mp_machine_soft_spi_p,
- .locals_dict = (mp_obj_dict_t*)&mp_machine_spi_locals_dict,
+ .locals_dict = (mp_obj_dict_t *)&mp_machine_spi_locals_dict,
};
#endif // MICROPY_PY_MACHINE_SPI
diff --git a/extmod/misc.h b/extmod/misc.h
index dae6bec4a1..40b091e5f7 100644
--- a/extmod/misc.h
+++ b/extmod/misc.h
@@ -36,6 +36,7 @@ MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_uos_dupterm_obj);
#if MICROPY_PY_OS_DUPTERM
bool mp_uos_dupterm_is_builtin_stream(mp_const_obj_t stream);
+uintptr_t mp_uos_dupterm_poll(uintptr_t poll_flags);
int mp_uos_dupterm_rx_chr(void);
void mp_uos_dupterm_tx_strn(const char *str, size_t len);
void mp_uos_deactivate(size_t dupterm_idx, const char *msg, mp_obj_t exc);
diff --git a/extmod/modbtree.c b/extmod/modbtree.c
index a2bff06d44..2dd3a89b89 100644
--- a/extmod/modbtree.c
+++ b/extmod/modbtree.c
@@ -39,6 +39,7 @@
typedef struct _mp_obj_btree_t {
mp_obj_base_t base;
+ mp_obj_t stream; // retain a reference to prevent GC from reclaiming it
DB *db;
mp_obj_t start_key;
mp_obj_t end_key;
@@ -52,20 +53,23 @@ typedef struct _mp_obj_btree_t {
byte next_flags;
} mp_obj_btree_t;
+#if !MICROPY_ENABLE_DYNRUNTIME
STATIC const mp_obj_type_t btree_type;
+#endif
#define CHECK_ERROR(res) \
- if (res == RET_ERROR) { \
- mp_raise_OSError(errno); \
- }
+ if (res == RET_ERROR) { \
+ mp_raise_OSError(errno); \
+ }
void __dbpanic(DB *db) {
- printf("__dbpanic(%p)\n", db);
+ mp_printf(&mp_plat_print, "__dbpanic(%p)\n", db);
}
-STATIC mp_obj_btree_t *btree_new(DB *db) {
+STATIC mp_obj_btree_t *btree_new(DB *db, mp_obj_t stream) {
mp_obj_btree_t *o = m_new_obj(mp_obj_btree_t);
o->base.type = &btree_type;
+ o->stream = stream;
o->db = db;
o->start_key = mp_const_none;
o->end_key = mp_const_none;
@@ -95,8 +99,8 @@ STATIC mp_obj_t btree_put(size_t n_args, const mp_obj_t *args) {
(void)n_args;
mp_obj_btree_t *self = MP_OBJ_TO_PTR(args[0]);
DBT key, val;
- key.data = (void*)mp_obj_str_get_data(args[1], &key.size);
- val.data = (void*)mp_obj_str_get_data(args[2], &val.size);
+ key.data = (void *)mp_obj_str_get_data(args[1], &key.size);
+ val.data = (void *)mp_obj_str_get_data(args[2], &val.size);
return MP_OBJ_NEW_SMALL_INT(__bt_put(self->db, &key, &val, 0));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(btree_put_obj, 3, 4, btree_put);
@@ -104,7 +108,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(btree_put_obj, 3, 4, btree_put);
STATIC mp_obj_t btree_get(size_t n_args, const mp_obj_t *args) {
mp_obj_btree_t *self = MP_OBJ_TO_PTR(args[0]);
DBT key, val;
- key.data = (void*)mp_obj_str_get_data(args[1], &key.size);
+ key.data = (void *)mp_obj_str_get_data(args[1], &key.size);
int res = __bt_get(self->db, &key, &val, 0);
if (res == RET_SPECIAL) {
if (n_args > 2) {
@@ -123,7 +127,7 @@ STATIC mp_obj_t btree_seq(size_t n_args, const mp_obj_t *args) {
int flags = MP_OBJ_SMALL_INT_VALUE(args[1]);
DBT key, val;
if (n_args > 2) {
- key.data = (void*)mp_obj_str_get_data(args[2], &key.size);
+ key.data = (void *)mp_obj_str_get_data(args[2], &key.size);
}
int res = __bt_seq(self->db, &key, &val, flags);
@@ -198,7 +202,7 @@ STATIC mp_obj_t btree_iternext(mp_obj_t self_in) {
if (self->start_key != MP_OBJ_NULL) {
int flags = R_FIRST;
if (self->start_key != mp_const_none) {
- key.data = (void*)mp_obj_str_get_data(self->start_key, &key.size);
+ key.data = (void *)mp_obj_str_get_data(self->start_key, &key.size);
flags = R_CURSOR;
} else if (desc) {
flags = R_LAST;
@@ -216,7 +220,7 @@ STATIC mp_obj_t btree_iternext(mp_obj_t self_in) {
if (self->end_key != mp_const_none) {
DBT end_key;
- end_key.data = (void*)mp_obj_str_get_data(self->end_key, &end_key.size);
+ end_key.data = (void *)mp_obj_str_get_data(self->end_key, &end_key.size);
BTREE *t = self->db->internal;
int cmp = t->bt_cmp(&key, &end_key);
if (desc) {
@@ -251,28 +255,28 @@ STATIC mp_obj_t btree_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
if (value == MP_OBJ_NULL) {
// delete
DBT key;
- key.data = (void*)mp_obj_str_get_data(index, &key.size);
+ key.data = (void *)mp_obj_str_get_data(index, &key.size);
int res = __bt_delete(self->db, &key, 0);
if (res == RET_SPECIAL) {
- nlr_raise(mp_obj_new_exception(&mp_type_KeyError));
+ mp_raise_type(&mp_type_KeyError);
}
CHECK_ERROR(res);
return mp_const_none;
} else if (value == MP_OBJ_SENTINEL) {
// load
DBT key, val;
- key.data = (void*)mp_obj_str_get_data(index, &key.size);
+ key.data = (void *)mp_obj_str_get_data(index, &key.size);
int res = __bt_get(self->db, &key, &val, 0);
if (res == RET_SPECIAL) {
- nlr_raise(mp_obj_new_exception(&mp_type_KeyError));
+ mp_raise_type(&mp_type_KeyError);
}
CHECK_ERROR(res);
return mp_obj_new_bytes(val.data, val.size);
} else {
// store
DBT key, val;
- key.data = (void*)mp_obj_str_get_data(index, &key.size);
- val.data = (void*)mp_obj_str_get_data(value, &val.size);
+ key.data = (void *)mp_obj_str_get_data(index, &key.size);
+ val.data = (void *)mp_obj_str_get_data(value, &val.size);
int res = __bt_put(self->db, &key, &val, 0);
CHECK_ERROR(res);
return mp_const_none;
@@ -284,7 +288,7 @@ STATIC mp_obj_t btree_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs
switch (op) {
case MP_BINARY_OP_CONTAINS: {
DBT key, val;
- key.data = (void*)mp_obj_str_get_data(rhs_in, &key.size);
+ key.data = (void *)mp_obj_str_get_data(rhs_in, &key.size);
int res = __bt_get(self->db, &key, &val, 0);
CHECK_ERROR(res);
return mp_obj_new_bool(res != RET_SPECIAL);
@@ -295,6 +299,7 @@ STATIC mp_obj_t btree_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs
}
}
+#if !MICROPY_ENABLE_DYNRUNTIME
STATIC const mp_rom_map_elem_t btree_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&btree_close_obj) },
{ MP_ROM_QSTR(MP_QSTR_flush), MP_ROM_PTR(&btree_flush_obj) },
@@ -317,16 +322,18 @@ STATIC const mp_obj_type_t btree_type = {
.iternext = btree_iternext,
.binary_op = btree_binary_op,
.subscr = btree_subscr,
- .locals_dict = (void*)&btree_locals_dict,
+ .locals_dict = (void *)&btree_locals_dict,
};
+#endif
-STATIC FILEVTABLE btree_stream_fvtable = {
+STATIC const FILEVTABLE btree_stream_fvtable = {
mp_stream_posix_read,
mp_stream_posix_write,
mp_stream_posix_lseek,
mp_stream_posix_fsync
};
+#if !MICROPY_ENABLE_DYNRUNTIME
STATIC mp_obj_t mod_btree_open(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_flags, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
@@ -345,18 +352,18 @@ STATIC mp_obj_t mod_btree_open(size_t n_args, const mp_obj_t *pos_args, mp_map_t
mp_arg_val_t minkeypage;
} args;
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args,
- MP_ARRAY_SIZE(allowed_args), allowed_args, (mp_arg_val_t*)&args);
+ MP_ARRAY_SIZE(allowed_args), allowed_args, (mp_arg_val_t *)&args);
BTREEINFO openinfo = {0};
openinfo.flags = args.flags.u_int;
openinfo.cachesize = args.cachesize.u_int;
openinfo.psize = args.pagesize.u_int;
openinfo.minkeypage = args.minkeypage.u_int;
- DB *db = __bt_open(MP_OBJ_TO_PTR(pos_args[0]), &btree_stream_fvtable, &openinfo, /*dflags*/0);
+ DB *db = __bt_open(MP_OBJ_TO_PTR(pos_args[0]), &btree_stream_fvtable, &openinfo, /*dflags*/ 0);
if (db == NULL) {
mp_raise_OSError(errno);
}
- return MP_OBJ_FROM_PTR(btree_new(db));
+ return MP_OBJ_FROM_PTR(btree_new(db, pos_args[0]));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mod_btree_open_obj, 1, mod_btree_open);
@@ -371,7 +378,8 @@ STATIC MP_DEFINE_CONST_DICT(mp_module_btree_globals, mp_module_btree_globals_tab
const mp_obj_module_t mp_module_btree = {
.base = { &mp_type_module },
- .globals = (mp_obj_dict_t*)&mp_module_btree_globals,
+ .globals = (mp_obj_dict_t *)&mp_module_btree_globals,
};
+#endif
#endif // MICROPY_PY_BTREE
diff --git a/extmod/modframebuf.c b/extmod/modframebuf.c
index a7f6ba905f..2753acc271 100644
--- a/extmod/modframebuf.c
+++ b/extmod/modframebuf.c
@@ -41,8 +41,12 @@ typedef struct _mp_obj_framebuf_t {
uint8_t format;
} mp_obj_framebuf_t;
-typedef void (*setpixel_t)(const mp_obj_framebuf_t*, int, int, uint32_t);
-typedef uint32_t (*getpixel_t)(const mp_obj_framebuf_t*, int, int);
+#if !MICROPY_ENABLE_DYNRUNTIME
+STATIC const mp_obj_type_t mp_type_framebuf;
+#endif
+
+typedef void (*setpixel_t)(const mp_obj_framebuf_t *, int, int, uint32_t);
+typedef uint32_t (*getpixel_t)(const mp_obj_framebuf_t *, int, int);
typedef void (*fill_rect_t)(const mp_obj_framebuf_t *, int, int, int, int, uint32_t);
typedef struct _mp_framebuf_p_t {
@@ -65,20 +69,20 @@ typedef struct _mp_framebuf_p_t {
STATIC void mono_horiz_setpixel(const mp_obj_framebuf_t *fb, int x, int y, uint32_t col) {
size_t index = (x + y * fb->stride) >> 3;
int offset = fb->format == FRAMEBUF_MHMSB ? x & 0x07 : 7 - (x & 0x07);
- ((uint8_t*)fb->buf)[index] = (((uint8_t*)fb->buf)[index] & ~(0x01 << offset)) | ((col != 0) << offset);
+ ((uint8_t *)fb->buf)[index] = (((uint8_t *)fb->buf)[index] & ~(0x01 << offset)) | ((col != 0) << offset);
}
STATIC uint32_t mono_horiz_getpixel(const mp_obj_framebuf_t *fb, int x, int y) {
size_t index = (x + y * fb->stride) >> 3;
int offset = fb->format == FRAMEBUF_MHMSB ? x & 0x07 : 7 - (x & 0x07);
- return (((uint8_t*)fb->buf)[index] >> (offset)) & 0x01;
+ return (((uint8_t *)fb->buf)[index] >> (offset)) & 0x01;
}
STATIC void mono_horiz_fill_rect(const mp_obj_framebuf_t *fb, int x, int y, int w, int h, uint32_t col) {
int reverse = fb->format == FRAMEBUF_MHMSB;
int advance = fb->stride >> 3;
while (w--) {
- uint8_t *b = &((uint8_t*)fb->buf)[(x >> 3) + y * advance];
+ uint8_t *b = &((uint8_t *)fb->buf)[(x >> 3) + y * advance];
int offset = reverse ? x & 7 : 7 - (x & 7);
for (int hh = h; hh; --hh) {
*b = (*b & ~(0x01 << offset)) | ((col != 0) << offset);
@@ -93,16 +97,16 @@ STATIC void mono_horiz_fill_rect(const mp_obj_framebuf_t *fb, int x, int y, int
STATIC void mvlsb_setpixel(const mp_obj_framebuf_t *fb, int x, int y, uint32_t col) {
size_t index = (y >> 3) * fb->stride + x;
uint8_t offset = y & 0x07;
- ((uint8_t*)fb->buf)[index] = (((uint8_t*)fb->buf)[index] & ~(0x01 << offset)) | ((col != 0) << offset);
+ ((uint8_t *)fb->buf)[index] = (((uint8_t *)fb->buf)[index] & ~(0x01 << offset)) | ((col != 0) << offset);
}
STATIC uint32_t mvlsb_getpixel(const mp_obj_framebuf_t *fb, int x, int y) {
- return (((uint8_t*)fb->buf)[(y >> 3) * fb->stride + x] >> (y & 0x07)) & 0x01;
+ return (((uint8_t *)fb->buf)[(y >> 3) * fb->stride + x] >> (y & 0x07)) & 0x01;
}
STATIC void mvlsb_fill_rect(const mp_obj_framebuf_t *fb, int x, int y, int w, int h, uint32_t col) {
while (h--) {
- uint8_t *b = &((uint8_t*)fb->buf)[(y >> 3) * fb->stride + x];
+ uint8_t *b = &((uint8_t *)fb->buf)[(y >> 3) * fb->stride + x];
uint8_t offset = y & 0x07;
for (int ww = w; ww; --ww) {
*b = (*b & ~(0x01 << offset)) | ((col != 0) << offset);
@@ -115,15 +119,15 @@ STATIC void mvlsb_fill_rect(const mp_obj_framebuf_t *fb, int x, int y, int w, in
// Functions for RGB565 format
STATIC void rgb565_setpixel(const mp_obj_framebuf_t *fb, int x, int y, uint32_t col) {
- ((uint16_t*)fb->buf)[x + y * fb->stride] = col;
+ ((uint16_t *)fb->buf)[x + y * fb->stride] = col;
}
STATIC uint32_t rgb565_getpixel(const mp_obj_framebuf_t *fb, int x, int y) {
- return ((uint16_t*)fb->buf)[x + y * fb->stride];
+ return ((uint16_t *)fb->buf)[x + y * fb->stride];
}
STATIC void rgb565_fill_rect(const mp_obj_framebuf_t *fb, int x, int y, int w, int h, uint32_t col) {
- uint16_t *b = &((uint16_t*)fb->buf)[x + y * fb->stride];
+ uint16_t *b = &((uint16_t *)fb->buf)[x + y * fb->stride];
while (h--) {
for (int ww = w; ww; --ww) {
*b++ = col;
@@ -135,7 +139,7 @@ STATIC void rgb565_fill_rect(const mp_obj_framebuf_t *fb, int x, int y, int w, i
// Functions for GS2_HMSB format
STATIC void gs2_hmsb_setpixel(const mp_obj_framebuf_t *fb, int x, int y, uint32_t col) {
- uint8_t *pixel = &((uint8_t*)fb->buf)[(x + y * fb->stride) >> 2];
+ uint8_t *pixel = &((uint8_t *)fb->buf)[(x + y * fb->stride) >> 2];
uint8_t shift = (x & 0x3) << 1;
uint8_t mask = 0x3 << shift;
uint8_t color = (col & 0x3) << shift;
@@ -143,14 +147,14 @@ STATIC void gs2_hmsb_setpixel(const mp_obj_framebuf_t *fb, int x, int y, uint32_
}
STATIC uint32_t gs2_hmsb_getpixel(const mp_obj_framebuf_t *fb, int x, int y) {
- uint8_t pixel = ((uint8_t*)fb->buf)[(x + y * fb->stride) >> 2];
+ uint8_t pixel = ((uint8_t *)fb->buf)[(x + y * fb->stride) >> 2];
uint8_t shift = (x & 0x3) << 1;
return (pixel >> shift) & 0x3;
}
STATIC void gs2_hmsb_fill_rect(const mp_obj_framebuf_t *fb, int x, int y, int w, int h, uint32_t col) {
- for (int xx=x; xx < x+w; xx++) {
- for (int yy=y; yy < y+h; yy++) {
+ for (int xx = x; xx < x + w; xx++) {
+ for (int yy = y; yy < y + h; yy++) {
gs2_hmsb_setpixel(fb, xx, yy, col);
}
}
@@ -159,7 +163,7 @@ STATIC void gs2_hmsb_fill_rect(const mp_obj_framebuf_t *fb, int x, int y, int w,
// Functions for GS4_HMSB format
STATIC void gs4_hmsb_setpixel(const mp_obj_framebuf_t *fb, int x, int y, uint32_t col) {
- uint8_t *pixel = &((uint8_t*)fb->buf)[(x + y * fb->stride) >> 1];
+ uint8_t *pixel = &((uint8_t *)fb->buf)[(x + y * fb->stride) >> 1];
if (x % 2) {
*pixel = ((uint8_t)col & 0x0f) | (*pixel & 0xf0);
@@ -170,15 +174,15 @@ STATIC void gs4_hmsb_setpixel(const mp_obj_framebuf_t *fb, int x, int y, uint32_
STATIC uint32_t gs4_hmsb_getpixel(const mp_obj_framebuf_t *fb, int x, int y) {
if (x % 2) {
- return ((uint8_t*)fb->buf)[(x + y * fb->stride) >> 1] & 0x0f;
+ return ((uint8_t *)fb->buf)[(x + y * fb->stride) >> 1] & 0x0f;
}
- return ((uint8_t*)fb->buf)[(x + y * fb->stride) >> 1] >> 4;
+ return ((uint8_t *)fb->buf)[(x + y * fb->stride) >> 1] >> 4;
}
STATIC void gs4_hmsb_fill_rect(const mp_obj_framebuf_t *fb, int x, int y, int w, int h, uint32_t col) {
col &= 0x0f;
- uint8_t *pixel_pair = &((uint8_t*)fb->buf)[(x + y * fb->stride) >> 1];
+ uint8_t *pixel_pair = &((uint8_t *)fb->buf)[(x + y * fb->stride) >> 1];
uint8_t col_shifted_left = col << 4;
uint8_t col_pixel_pair = col_shifted_left | col;
int pixel_count_till_next_line = (fb->stride - w) >> 1;
@@ -210,16 +214,16 @@ STATIC void gs4_hmsb_fill_rect(const mp_obj_framebuf_t *fb, int x, int y, int w,
// Functions for GS8 format
STATIC void gs8_setpixel(const mp_obj_framebuf_t *fb, int x, int y, uint32_t col) {
- uint8_t *pixel = &((uint8_t*)fb->buf)[(x + y * fb->stride)];
+ uint8_t *pixel = &((uint8_t *)fb->buf)[(x + y * fb->stride)];
*pixel = col & 0xff;
}
STATIC uint32_t gs8_getpixel(const mp_obj_framebuf_t *fb, int x, int y) {
- return ((uint8_t*)fb->buf)[(x + y * fb->stride)];
+ return ((uint8_t *)fb->buf)[(x + y * fb->stride)];
}
STATIC void gs8_fill_rect(const mp_obj_framebuf_t *fb, int x, int y, int w, int h, uint32_t col) {
- uint8_t *pixel = &((uint8_t*)fb->buf)[(x + y * fb->stride)];
+ uint8_t *pixel = &((uint8_t *)fb->buf)[(x + y * fb->stride)];
while (h--) {
memset(pixel, col, w);
pixel += fb->stride;
@@ -296,7 +300,7 @@ STATIC mp_obj_t framebuf_make_new(const mp_obj_type_t *type, size_t n_args, size
case FRAMEBUF_GS8:
break;
default:
- mp_raise_ValueError("invalid format");
+ mp_raise_ValueError(MP_ERROR_TEXT("invalid format"));
}
return MP_OBJ_FROM_PTR(o);
@@ -393,9 +397,9 @@ STATIC mp_obj_t framebuf_rect(size_t n_args, const mp_obj_t *args) {
mp_int_t col = mp_obj_get_int(args[5]);
fill_rect(self, x, y, w, 1, col);
- fill_rect(self, x, y + h- 1, w, 1, col);
+ fill_rect(self, x, y + h - 1, w, 1, col);
fill_rect(self, x, y, 1, h, col);
- fill_rect(self, x + w- 1, y, 1, h, col);
+ fill_rect(self, x + w - 1, y, 1, h, col);
return mp_const_none;
}
@@ -432,9 +436,15 @@ STATIC mp_obj_t framebuf_line(size_t n_args, const mp_obj_t *args) {
bool steep;
if (dy > dx) {
mp_int_t temp;
- temp = x1; x1 = y1; y1 = temp;
- temp = dx; dx = dy; dy = temp;
- temp = sx; sx = sy; sy = temp;
+ temp = x1;
+ x1 = y1;
+ y1 = temp;
+ temp = dx;
+ dx = dy;
+ dy = temp;
+ temp = sx;
+ sx = sy;
+ sy = temp;
steep = true;
} else {
steep = false;
@@ -469,7 +479,12 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_line_obj, 6, 6, framebuf_lin
STATIC mp_obj_t framebuf_blit(size_t n_args, const mp_obj_t *args) {
mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args[0]);
- mp_obj_framebuf_t *source = MP_OBJ_TO_PTR(args[1]);
+ mp_obj_t source_in = mp_obj_cast_to_native_base(args[1], MP_OBJ_FROM_PTR(&mp_type_framebuf));
+ if (source_in == MP_OBJ_NULL) {
+ mp_raise_TypeError(NULL);
+ }
+ mp_obj_framebuf_t *source = MP_OBJ_TO_PTR(source_in);
+
mp_int_t x = mp_obj_get_int(args[2]);
mp_int_t y = mp_obj_get_int(args[3]);
mp_int_t key = -1;
@@ -482,7 +497,7 @@ STATIC mp_obj_t framebuf_blit(size_t n_args, const mp_obj_t *args) {
(y >= self->height) ||
(-x >= source->width) ||
(-y >= source->height)
- ) {
+ ) {
// Out of bounds, no-op.
return mp_const_none;
}
@@ -556,7 +571,7 @@ STATIC mp_obj_t framebuf_text(size_t n_args, const mp_obj_t *args) {
// loop over chars
for (; *str; ++str) {
// get char and make sure its in range of font
- int chr = *(uint8_t*)str;
+ int chr = *(uint8_t *)str;
if (chr < 32 || chr > 127) {
chr = 127;
}
@@ -580,6 +595,7 @@ STATIC mp_obj_t framebuf_text(size_t n_args, const mp_obj_t *args) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_text_obj, 4, 5, framebuf_text);
+#if !MICROPY_ENABLE_DYNRUNTIME
STATIC const mp_rom_map_elem_t framebuf_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_fill), MP_ROM_PTR(&framebuf_fill_obj) },
{ MP_ROM_QSTR(MP_QSTR_fill_rect), MP_ROM_PTR(&framebuf_fill_rect_obj) },
@@ -599,8 +615,9 @@ STATIC const mp_obj_type_t mp_type_framebuf = {
.name = MP_QSTR_FrameBuffer,
.make_new = framebuf_make_new,
.buffer_p = { .get_buffer = framebuf_get_buffer },
- .locals_dict = (mp_obj_dict_t*)&framebuf_locals_dict,
+ .locals_dict = (mp_obj_dict_t *)&framebuf_locals_dict,
};
+#endif
// this factory function is provided for backwards compatibility with old FrameBuffer1 class
STATIC mp_obj_t legacy_framebuffer1(size_t n_args, const mp_obj_t *args) {
@@ -624,6 +641,7 @@ STATIC mp_obj_t legacy_framebuffer1(size_t n_args, const mp_obj_t *args) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(legacy_framebuffer1_obj, 3, 4, legacy_framebuffer1);
+#if !MICROPY_ENABLE_DYNRUNTIME
STATIC const mp_rom_map_elem_t framebuf_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_framebuf) },
{ MP_ROM_QSTR(MP_QSTR_FrameBuffer), MP_ROM_PTR(&mp_type_framebuf) },
@@ -642,7 +660,8 @@ STATIC MP_DEFINE_CONST_DICT(framebuf_module_globals, framebuf_module_globals_tab
const mp_obj_module_t mp_module_framebuf = {
.base = { &mp_type_module },
- .globals = (mp_obj_dict_t*)&framebuf_module_globals,
+ .globals = (mp_obj_dict_t *)&framebuf_module_globals,
};
+#endif
#endif // MICROPY_PY_FRAMEBUF
diff --git a/extmod/modlwip.c b/extmod/modlwip.c
index 4127d21add..1d557a6a84 100644
--- a/extmod/modlwip.c
+++ b/extmod/modlwip.c
@@ -40,7 +40,7 @@
#include "lwip/init.h"
#include "lwip/tcp.h"
#include "lwip/udp.h"
-//#include "lwip/raw.h"
+#include "lwip/raw.h"
#include "lwip/dns.h"
#include "lwip/igmp.h"
#if LWIP_VERSION_MAJOR < 2
@@ -103,7 +103,7 @@ void mod_lwip_register_poll(void (*poll)(void *arg), void *poll_arg);
void mod_lwip_deregister_poll(void (*poll)(void *arg), void *poll_arg);
STATIC void slip_lwip_poll(void *netif) {
- slipif_poll((struct netif*)netif);
+ slipif_poll((struct netif *)netif);
}
STATIC const mp_obj_type_t lwip_slip_type;
@@ -144,15 +144,15 @@ STATIC mp_obj_t lwip_slip_make_new(mp_obj_t type_in, size_t n_args, size_t n_kw,
ip_addr_t iplocal, ipremote;
if (!ipaddr_aton(mp_obj_str_get_str(args[1]), &iplocal)) {
- mp_raise_ValueError("not a valid local IP");
+ mp_raise_ValueError(MP_ERROR_TEXT("not a valid local IP"));
}
if (!ipaddr_aton(mp_obj_str_get_str(args[2]), &ipremote)) {
- mp_raise_ValueError("not a valid remote IP");
+ mp_raise_ValueError(MP_ERROR_TEXT("not a valid remote IP"));
}
struct netif *n = &lwip_slip_obj.lwip_netif;
if (netif_add(n, &iplocal, IP_ADDR_BROADCAST, &ipremote, NULL, slipif_init, ip_input) == NULL) {
- mp_raise_ValueError("out of memory");
+ mp_raise_ValueError(MP_ERROR_TEXT("out of memory"));
}
netif_set_up(n);
netif_set_default(n);
@@ -178,7 +178,7 @@ STATIC const mp_obj_type_t lwip_slip_type = {
{ &mp_type_type },
.name = MP_QSTR_slip,
.make_new = lwip_slip_make_new,
- .locals_dict = (mp_obj_dict_t*)&lwip_slip_locals_dict,
+ .locals_dict = (mp_obj_dict_t *)&lwip_slip_locals_dict,
};
#endif // MICROPY_PY_LWIP_SLIP
@@ -190,7 +190,7 @@ STATIC const mp_obj_type_t lwip_slip_type = {
// lwIP 2 changed LWIP_VERSION and it can no longer be used in macros,
// so we define our own equivalent version that can.
#define LWIP_VERSION_MACRO (LWIP_VERSION_MAJOR << 24 | LWIP_VERSION_MINOR << 16 \
- | LWIP_VERSION_REVISION << 8 | LWIP_VERSION_RC)
+ | LWIP_VERSION_REVISION << 8 | LWIP_VERSION_RC)
// Extension to lwIP error codes
#define _ERR_BADF -16
@@ -280,6 +280,7 @@ typedef struct _lwip_socket_obj_t {
volatile union {
struct tcp_pcb *tcp;
struct udp_pcb *udp;
+ struct raw_pcb *raw;
} pcb;
volatile union {
struct pbuf *pbuf;
@@ -307,16 +308,17 @@ typedef struct _lwip_socket_obj_t {
#define STATE_CONNECTING 2
#define STATE_CONNECTED 3
#define STATE_PEER_CLOSED 4
+ #define STATE_ACTIVE_UDP 5
// Negative value is lwIP error
int8_t state;
} lwip_socket_obj_t;
static inline void poll_sockets(void) {
-#ifdef MICROPY_EVENT_POLL_HOOK
+ #ifdef MICROPY_EVENT_POLL_HOOK
MICROPY_EVENT_POLL_HOOK;
-#else
+ #else
mp_hal_delay_ms(1);
-#endif
+ #endif
}
STATIC struct tcp_pcb *volatile *lwip_socket_incoming_array(lwip_socket_obj_t *socket) {
@@ -356,9 +358,30 @@ STATIC void lwip_socket_free_incoming(lwip_socket_obj_t *socket) {
static inline void exec_user_callback(lwip_socket_obj_t *socket) {
if (socket->callback != MP_OBJ_NULL) {
- mp_call_function_1_protected(socket->callback, MP_OBJ_FROM_PTR(socket));
+ // Schedule the user callback to execute outside the lwIP context
+ mp_sched_schedule(socket->callback, MP_OBJ_FROM_PTR(socket));
+ }
+}
+
+#if MICROPY_PY_LWIP_SOCK_RAW
+// Callback for incoming raw packets.
+#if LWIP_VERSION_MAJOR < 2
+STATIC u8_t _lwip_raw_incoming(void *arg, struct raw_pcb *pcb, struct pbuf *p, ip_addr_t *addr)
+#else
+STATIC u8_t _lwip_raw_incoming(void *arg, struct raw_pcb *pcb, struct pbuf *p, const ip_addr_t *addr)
+#endif
+{
+ lwip_socket_obj_t *socket = (lwip_socket_obj_t *)arg;
+
+ if (socket->incoming.pbuf != NULL) {
+ pbuf_free(p);
+ } else {
+ socket->incoming.pbuf = p;
+ memcpy(&socket->peer, addr, sizeof(socket->peer));
}
+ return 1; // we ate the packet
}
+#endif
// Callback for incoming UDP packets. We simply stash the packet and the source address,
// in case we need it for recvfrom.
@@ -368,7 +391,7 @@ STATIC void _lwip_udp_incoming(void *arg, struct udp_pcb *upcb, struct pbuf *p,
STATIC void _lwip_udp_incoming(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port)
#endif
{
- lwip_socket_obj_t *socket = (lwip_socket_obj_t*)arg;
+ lwip_socket_obj_t *socket = (lwip_socket_obj_t *)arg;
if (socket->incoming.pbuf != NULL) {
// That's why they call it "unreliable". No room in the inn, drop the packet.
@@ -382,7 +405,7 @@ STATIC void _lwip_udp_incoming(void *arg, struct udp_pcb *upcb, struct pbuf *p,
// Callback for general tcp errors.
STATIC void _lwip_tcp_error(void *arg, err_t err) {
- lwip_socket_obj_t *socket = (lwip_socket_obj_t*)arg;
+ lwip_socket_obj_t *socket = (lwip_socket_obj_t *)arg;
// Free any incoming buffers or connections that are stored
lwip_socket_free_incoming(socket);
@@ -394,7 +417,7 @@ STATIC void _lwip_tcp_error(void *arg, err_t err) {
// Callback for tcp connection requests. Error code err is unused. (See tcp.h)
STATIC err_t _lwip_tcp_connected(void *arg, struct tcp_pcb *tpcb, err_t err) {
- lwip_socket_obj_t *socket = (lwip_socket_obj_t*)arg;
+ lwip_socket_obj_t *socket = (lwip_socket_obj_t *)arg;
socket->state = STATE_CONNECTED;
return ERR_OK;
@@ -403,15 +426,15 @@ STATIC err_t _lwip_tcp_connected(void *arg, struct tcp_pcb *tpcb, err_t err) {
// Handle errors (eg connection aborted) on TCP PCBs that have been put on the
// accept queue but are not yet actually accepted.
STATIC void _lwip_tcp_err_unaccepted(void *arg, err_t err) {
- struct tcp_pcb *pcb = (struct tcp_pcb*)arg;
+ struct tcp_pcb *pcb = (struct tcp_pcb *)arg;
// The ->connected entry is repurposed to store the parent socket; this is safe
// because it's only ever used by lwIP if tcp_connect is called on the TCP PCB.
- lwip_socket_obj_t *socket = (lwip_socket_obj_t*)pcb->connected;
+ lwip_socket_obj_t *socket = (lwip_socket_obj_t *)pcb->connected;
// Array is not volatile because thiss callback is executed within the lwIP context
uint8_t alloc = socket->incoming.connection.alloc;
- struct tcp_pcb **tcp_array = (struct tcp_pcb**)lwip_socket_incoming_array(socket);
+ struct tcp_pcb **tcp_array = (struct tcp_pcb **)lwip_socket_incoming_array(socket);
// Search for PCB on the accept queue of the parent socket
struct tcp_pcb **shift_down = NULL;
@@ -446,18 +469,6 @@ STATIC err_t _lwip_tcp_recv_unaccepted(void *arg, struct tcp_pcb *pcb, struct pb
return ERR_BUF;
}
-// "Poll" (idle) callback to be called ASAP after accept callback
-// to execute Python callback function, as it can't be executed
-// from accept callback itself.
-STATIC err_t _lwip_tcp_accept_finished(void *arg, struct tcp_pcb *pcb)
-{
- // The ->connected entry of the pcb holds the listening socket of the accept
- lwip_socket_obj_t *socket = (lwip_socket_obj_t*)pcb->connected;
- tcp_poll(pcb, NULL, 0);
- exec_user_callback(socket);
- return ERR_OK;
-}
-
// Callback for incoming tcp connections.
STATIC err_t _lwip_tcp_accept(void *arg, struct tcp_pcb *newpcb, err_t err) {
// err can be ERR_MEM to notify us that there was no memory for an incoming connection
@@ -465,7 +476,7 @@ STATIC err_t _lwip_tcp_accept(void *arg, struct tcp_pcb *newpcb, err_t err) {
return ERR_OK;
}
- lwip_socket_obj_t *socket = (lwip_socket_obj_t*)arg;
+ lwip_socket_obj_t *socket = (lwip_socket_obj_t *)arg;
tcp_recv(newpcb, _lwip_tcp_recv_unaccepted);
// Search for an empty slot to store the new connection
@@ -476,18 +487,15 @@ STATIC err_t _lwip_tcp_accept(void *arg, struct tcp_pcb *newpcb, err_t err) {
if (++socket->incoming.connection.iput >= socket->incoming.connection.alloc) {
socket->incoming.connection.iput = 0;
}
- if (socket->callback != MP_OBJ_NULL) {
- // Schedule accept callback to be called when lwIP is done
- // with processing this incoming connection on its side and
- // is idle.
- tcp_poll(newpcb, _lwip_tcp_accept_finished, 1);
- }
+
+ // Schedule user accept callback
+ exec_user_callback(socket);
// Set the error callback to handle the case of a dropped connection before we
// have a chance to take it off the accept queue.
// The ->connected entry is repurposed to store the parent socket; this is safe
// because it's only ever used by lwIP if tcp_connect is called on the TCP PCB.
- newpcb->connected = (void*)socket;
+ newpcb->connected = (void *)socket;
tcp_arg(newpcb, newpcb);
tcp_err(newpcb, _lwip_tcp_err_unaccepted);
@@ -500,7 +508,7 @@ STATIC err_t _lwip_tcp_accept(void *arg, struct tcp_pcb *newpcb, err_t err) {
// Callback for inbound tcp packets.
STATIC err_t _lwip_tcp_recv(void *arg, struct tcp_pcb *tcpb, struct pbuf *p, err_t err) {
- lwip_socket_obj_t *socket = (lwip_socket_obj_t*)arg;
+ lwip_socket_obj_t *socket = (lwip_socket_obj_t *)arg;
if (p == NULL) {
// Other side has closed connection.
@@ -529,8 +537,8 @@ STATIC err_t _lwip_tcp_recv(void *arg, struct tcp_pcb *tcpb, struct pbuf *p, err
// Functions for socket send/receive operations. Socket send/recv and friends call
// these to do the work.
-// Helper function for send/sendto to handle UDP packets.
-STATIC mp_uint_t lwip_udp_send(lwip_socket_obj_t *socket, const byte *buf, mp_uint_t len, byte *ip, mp_uint_t port, int *_errno) {
+// Helper function for send/sendto to handle raw/UDP packets.
+STATIC mp_uint_t lwip_raw_udp_send(lwip_socket_obj_t *socket, const byte *buf, mp_uint_t len, byte *ip, mp_uint_t port, int *_errno) {
if (len > 0xffff) {
// Any packet that big is probably going to fail the pbuf_alloc anyway, but may as well try
len = 0xffff;
@@ -550,11 +558,25 @@ STATIC mp_uint_t lwip_udp_send(lwip_socket_obj_t *socket, const byte *buf, mp_ui
err_t err;
if (ip == NULL) {
- err = udp_send(socket->pcb.udp, p);
+ #if MICROPY_PY_LWIP_SOCK_RAW
+ if (socket->type == MOD_NETWORK_SOCK_RAW) {
+ err = raw_send(socket->pcb.raw, p);
+ } else
+ #endif
+ {
+ err = udp_send(socket->pcb.udp, p);
+ }
} else {
ip_addr_t dest;
IP4_ADDR(&dest, ip[0], ip[1], ip[2], ip[3]);
- err = udp_sendto(socket->pcb.udp, p, &dest, port);
+ #if MICROPY_PY_LWIP_SOCK_RAW
+ if (socket->type == MOD_NETWORK_SOCK_RAW) {
+ err = raw_sendto(socket->pcb.raw, p, &dest);
+ } else
+ #endif
+ {
+ err = udp_sendto(socket->pcb.udp, p, &dest, port);
+ }
}
pbuf_free(p);
@@ -572,23 +594,24 @@ STATIC mp_uint_t lwip_udp_send(lwip_socket_obj_t *socket, const byte *buf, mp_ui
return len;
}
-// Helper function for recv/recvfrom to handle UDP packets
-STATIC mp_uint_t lwip_udp_receive(lwip_socket_obj_t *socket, byte *buf, mp_uint_t len, byte *ip, mp_uint_t *port, int *_errno) {
+// Helper function for recv/recvfrom to handle raw/UDP packets
+STATIC mp_uint_t lwip_raw_udp_receive(lwip_socket_obj_t *socket, byte *buf, mp_uint_t len, byte *ip, mp_uint_t *port, int *_errno) {
if (socket->incoming.pbuf == NULL) {
- if (socket->timeout != -1) {
- for (mp_uint_t retries = socket->timeout / 100; retries--;) {
- mp_hal_delay_ms(100);
- if (socket->incoming.pbuf != NULL) break;
- }
- if (socket->incoming.pbuf == NULL) {
+ if (socket->timeout == 0) {
+ // Non-blocking socket.
+ *_errno = MP_EAGAIN;
+ return -1;
+ }
+
+ // Wait for data to arrive on UDP socket.
+ mp_uint_t start = mp_hal_ticks_ms();
+ while (socket->incoming.pbuf == NULL) {
+ if (socket->timeout != -1 && mp_hal_ticks_ms() - start > socket->timeout) {
*_errno = MP_ETIMEDOUT;
return -1;
}
- } else {
- while (socket->incoming.pbuf == NULL) {
- poll_sockets();
- }
+ poll_sockets();
}
}
@@ -607,25 +630,25 @@ STATIC mp_uint_t lwip_udp_receive(lwip_socket_obj_t *socket, byte *buf, mp_uint_
MICROPY_PY_LWIP_EXIT
- return (mp_uint_t) result;
+ return (mp_uint_t)result;
}
// For use in stream virtual methods
#define STREAM_ERROR_CHECK(socket) \
- if (socket->state < 0) { \
- *_errno = error_lookup_table[-socket->state]; \
- return MP_STREAM_ERROR; \
- } \
- assert(socket->pcb.tcp);
+ if (socket->state < 0) { \
+ *_errno = error_lookup_table[-socket->state]; \
+ return MP_STREAM_ERROR; \
+ } \
+ assert(socket->pcb.tcp);
// Version of above for use when lock is held
#define STREAM_ERROR_CHECK_WITH_LOCK(socket) \
- if (socket->state < 0) { \
- *_errno = error_lookup_table[-socket->state]; \
- MICROPY_PY_LWIP_EXIT \
- return MP_STREAM_ERROR; \
- } \
- assert(socket->pcb.tcp);
+ if (socket->state < 0) { \
+ *_errno = error_lookup_table[-socket->state]; \
+ MICROPY_PY_LWIP_EXIT \
+ return MP_STREAM_ERROR; \
+ } \
+ assert(socket->pcb.tcp);
// Helper function for send/sendto to handle TCP packets
@@ -668,7 +691,25 @@ STATIC mp_uint_t lwip_tcp_send(lwip_socket_obj_t *socket, const byte *buf, mp_ui
u16_t write_len = MIN(available, len);
- err_t err = tcp_write(socket->pcb.tcp, buf, write_len, TCP_WRITE_FLAG_COPY);
+ // If tcp_write returns ERR_MEM then there's currently not enough memory to
+ // queue the write, so wait and keep trying until it succeeds (with 10s limit).
+ // Note: if the socket is non-blocking then this code will actually block until
+ // there's enough memory to do the write, but by this stage we have already
+ // committed to being able to write the data.
+ err_t err;
+ for (int i = 0; i < 200; ++i) {
+ err = tcp_write(socket->pcb.tcp, buf, write_len, TCP_WRITE_FLAG_COPY);
+ if (err != ERR_MEM) {
+ break;
+ }
+ err = tcp_output(socket->pcb.tcp);
+ if (err != ERR_OK) {
+ break;
+ }
+ MICROPY_PY_LWIP_EXIT
+ mp_hal_delay_ms(50);
+ MICROPY_PY_LWIP_REENTER
+ }
// If the output buffer is getting full then send the data to the lower layers
if (err == ERR_OK && tcp_sndbuf(socket->pcb.tcp) < TCP_SND_BUF / 4) {
@@ -716,8 +757,11 @@ STATIC mp_uint_t lwip_tcp_receive(lwip_socket_obj_t *socket, byte *buf, mp_uint_
return 0;
}
} else if (socket->state != STATE_CONNECTED) {
- assert(socket->state < 0);
- *_errno = error_lookup_table[-socket->state];
+ if (socket->state >= STATE_NEW) {
+ *_errno = MP_ENOTCONN;
+ } else {
+ *_errno = error_lookup_table[-socket->state];
+ }
return -1;
}
}
@@ -733,7 +777,7 @@ STATIC mp_uint_t lwip_tcp_receive(lwip_socket_obj_t *socket, byte *buf, mp_uint_
len = remaining;
}
- memcpy(buf, (byte*)p->payload + socket->recv_offset, len);
+ memcpy(buf, (byte *)p->payload + socket->recv_offset, len);
remaining -= len;
if (remaining == 0) {
@@ -771,9 +815,13 @@ STATIC mp_obj_t lwip_socket_make_new(const mp_obj_type_t *type, size_t n_args, s
lwip_socket_obj_t *socket = m_new_obj_with_finaliser(lwip_socket_obj_t);
socket->base.type = &lwip_socket_type;
+ socket->timeout = -1;
+ socket->recv_offset = 0;
socket->domain = MOD_NETWORK_AF_INET;
socket->type = MOD_NETWORK_SOCK_STREAM;
socket->callback = MP_OBJ_NULL;
+ socket->state = STATE_NEW;
+
if (n_args >= 1) {
socket->domain = mp_obj_get_int(args[0]);
if (n_args >= 2) {
@@ -791,8 +839,15 @@ STATIC mp_obj_t lwip_socket_make_new(const mp_obj_type_t *type, size_t n_args, s
socket->pcb.udp = udp_new();
socket->incoming.pbuf = NULL;
break;
- //case MOD_NETWORK_SOCK_RAW: socket->pcb.raw = raw_new(); break;
- default: mp_raise_OSError(MP_EINVAL);
+ #if MICROPY_PY_LWIP_SOCK_RAW
+ case MOD_NETWORK_SOCK_RAW: {
+ mp_int_t proto = n_args <= 2 ? 0 : mp_obj_get_int(args[2]);
+ socket->pcb.raw = raw_new(proto);
+ break;
+ }
+ #endif
+ default:
+ mp_raise_OSError(MP_EINVAL);
}
if (socket->pcb.tcp == NULL) {
@@ -802,22 +857,28 @@ STATIC mp_obj_t lwip_socket_make_new(const mp_obj_type_t *type, size_t n_args, s
switch (socket->type) {
case MOD_NETWORK_SOCK_STREAM: {
// Register the socket object as our callback argument.
- tcp_arg(socket->pcb.tcp, (void*)socket);
+ tcp_arg(socket->pcb.tcp, (void *)socket);
// Register our error callback.
tcp_err(socket->pcb.tcp, _lwip_tcp_error);
break;
}
case MOD_NETWORK_SOCK_DGRAM: {
+ socket->state = STATE_ACTIVE_UDP;
// Register our receive callback now. Since UDP sockets don't require binding or connection
// before use, there's no other good time to do it.
- udp_recv(socket->pcb.udp, _lwip_udp_incoming, (void*)socket);
+ udp_recv(socket->pcb.udp, _lwip_udp_incoming, (void *)socket);
+ break;
+ }
+ #if MICROPY_PY_LWIP_SOCK_RAW
+ case MOD_NETWORK_SOCK_RAW: {
+ // Register our receive callback now. Since raw sockets don't require binding or connection
+ // before use, there's no other good time to do it.
+ raw_recv(socket->pcb.raw, _lwip_raw_incoming, (void *)socket);
break;
}
+ #endif
}
- socket->timeout = -1;
- socket->state = STATE_NEW;
- socket->recv_offset = 0;
return MP_OBJ_FROM_PTR(socket);
}
@@ -873,7 +934,7 @@ STATIC mp_obj_t lwip_socket_listen(mp_obj_t self_in, mp_obj_t backlog_in) {
socket->incoming.connection.tcp.item = NULL;
} else {
socket->incoming.connection.alloc = backlog;
- socket->incoming.connection.tcp.array = m_new0(struct tcp_pcb*, backlog);
+ socket->incoming.connection.tcp.array = m_new0(struct tcp_pcb *, backlog);
}
socket->incoming.connection.iget = 0;
socket->incoming.connection.iput = 0;
@@ -957,7 +1018,7 @@ STATIC mp_obj_t lwip_socket_accept(mp_obj_t self_in) {
socket2->state = STATE_CONNECTED;
socket2->recv_offset = 0;
socket2->callback = MP_OBJ_NULL;
- tcp_arg(socket2->pcb.tcp, (void*)socket2);
+ tcp_arg(socket2->pcb.tcp, (void *)socket2);
tcp_err(socket2->pcb.tcp, _lwip_tcp_error);
tcp_recv(socket2->pcb.tcp, _lwip_tcp_recv);
@@ -1020,7 +1081,9 @@ STATIC mp_obj_t lwip_socket_connect(mp_obj_t self_in, mp_obj_t addr_in) {
if (socket->timeout != -1) {
for (mp_uint_t retries = socket->timeout / 100; retries--;) {
mp_hal_delay_ms(100);
- if (socket->state != STATE_CONNECTING) break;
+ if (socket->state != STATE_CONNECTING) {
+ break;
+ }
}
if (socket->state == STATE_CONNECTING) {
mp_raise_OSError(MP_EINPROGRESS);
@@ -1031,9 +1094,9 @@ STATIC mp_obj_t lwip_socket_connect(mp_obj_t self_in, mp_obj_t addr_in) {
}
}
if (socket->state == STATE_CONNECTED) {
- err = ERR_OK;
+ err = ERR_OK;
} else {
- err = socket->state;
+ err = socket->state;
}
break;
}
@@ -1041,6 +1104,12 @@ STATIC mp_obj_t lwip_socket_connect(mp_obj_t self_in, mp_obj_t addr_in) {
err = udp_connect(socket->pcb.udp, &dest, port);
break;
}
+ #if MICROPY_PY_LWIP_SOCK_RAW
+ case MOD_NETWORK_SOCK_RAW: {
+ err = raw_connect(socket->pcb.raw, &dest);
+ break;
+ }
+ #endif
}
if (err != ERR_OK) {
@@ -1075,10 +1144,12 @@ STATIC mp_obj_t lwip_socket_send(mp_obj_t self_in, mp_obj_t buf_in) {
ret = lwip_tcp_send(socket, bufinfo.buf, bufinfo.len, &_errno);
break;
}
- case MOD_NETWORK_SOCK_DGRAM: {
- ret = lwip_udp_send(socket, bufinfo.buf, bufinfo.len, NULL, 0, &_errno);
+ case MOD_NETWORK_SOCK_DGRAM:
+ #if MICROPY_PY_LWIP_SOCK_RAW
+ case MOD_NETWORK_SOCK_RAW:
+ #endif
+ ret = lwip_raw_udp_send(socket, bufinfo.buf, bufinfo.len, NULL, 0, &_errno);
break;
- }
}
if (ret == -1) {
mp_raise_OSError(_errno);
@@ -1101,13 +1172,15 @@ STATIC mp_obj_t lwip_socket_recv(mp_obj_t self_in, mp_obj_t len_in) {
mp_uint_t ret = 0;
switch (socket->type) {
case MOD_NETWORK_SOCK_STREAM: {
- ret = lwip_tcp_receive(socket, (byte*)vstr.buf, len, &_errno);
+ ret = lwip_tcp_receive(socket, (byte *)vstr.buf, len, &_errno);
break;
}
- case MOD_NETWORK_SOCK_DGRAM: {
- ret = lwip_udp_receive(socket, (byte*)vstr.buf, len, NULL, NULL, &_errno);
+ case MOD_NETWORK_SOCK_DGRAM:
+ #if MICROPY_PY_LWIP_SOCK_RAW
+ case MOD_NETWORK_SOCK_RAW:
+ #endif
+ ret = lwip_raw_udp_receive(socket, (byte *)vstr.buf, len, NULL, NULL, &_errno);
break;
- }
}
if (ret == -1) {
mp_raise_OSError(_errno);
@@ -1139,10 +1212,12 @@ STATIC mp_obj_t lwip_socket_sendto(mp_obj_t self_in, mp_obj_t data_in, mp_obj_t
ret = lwip_tcp_send(socket, bufinfo.buf, bufinfo.len, &_errno);
break;
}
- case MOD_NETWORK_SOCK_DGRAM: {
- ret = lwip_udp_send(socket, bufinfo.buf, bufinfo.len, ip, port, &_errno);
+ case MOD_NETWORK_SOCK_DGRAM:
+ #if MICROPY_PY_LWIP_SOCK_RAW
+ case MOD_NETWORK_SOCK_RAW:
+ #endif
+ ret = lwip_raw_udp_send(socket, bufinfo.buf, bufinfo.len, ip, port, &_errno);
break;
- }
}
if (ret == -1) {
mp_raise_OSError(_errno);
@@ -1168,14 +1243,16 @@ STATIC mp_obj_t lwip_socket_recvfrom(mp_obj_t self_in, mp_obj_t len_in) {
switch (socket->type) {
case MOD_NETWORK_SOCK_STREAM: {
memcpy(ip, &socket->peer, sizeof(socket->peer));
- port = (mp_uint_t) socket->peer_port;
- ret = lwip_tcp_receive(socket, (byte*)vstr.buf, len, &_errno);
+ port = (mp_uint_t)socket->peer_port;
+ ret = lwip_tcp_receive(socket, (byte *)vstr.buf, len, &_errno);
break;
}
- case MOD_NETWORK_SOCK_DGRAM: {
- ret = lwip_udp_receive(socket, (byte*)vstr.buf, len, ip, &port, &_errno);
+ case MOD_NETWORK_SOCK_DGRAM:
+ #if MICROPY_PY_LWIP_SOCK_RAW
+ case MOD_NETWORK_SOCK_RAW:
+ #endif
+ ret = lwip_raw_udp_receive(socket, (byte *)vstr.buf, len, ip, &port, &_errno);
break;
- }
}
if (ret == -1) {
mp_raise_OSError(_errno);
@@ -1222,7 +1299,7 @@ STATIC mp_obj_t lwip_socket_sendall(mp_obj_t self_in, mp_obj_t buf_in) {
mp_raise_OSError(_errno);
}
bufinfo.len -= ret;
- bufinfo.buf = (char*)bufinfo.buf + ret;
+ bufinfo.buf = (char *)bufinfo.buf + ret;
}
break;
}
@@ -1242,7 +1319,7 @@ STATIC mp_obj_t lwip_socket_settimeout(mp_obj_t self_in, mp_obj_t timeout_in) {
timeout = -1;
} else {
#if MICROPY_PY_BUILTINS_FLOAT
- timeout = 1000 * mp_obj_get_float(timeout_in);
+ timeout = (mp_uint_t)(MICROPY_FLOAT_CONST(1000.0) * mp_obj_get_float(timeout_in));
#else
timeout = 1000 * mp_obj_get_int(timeout_in);
#endif
@@ -1300,7 +1377,7 @@ STATIC mp_obj_t lwip_socket_setsockopt(size_t n_args, const mp_obj_t *args) {
}
// POSIX setsockopt has order: group addr, if addr, lwIP has it vice-versa
- err_t err = igmp_joingroup((ip_addr_t*)bufinfo.buf + 1, bufinfo.buf);
+ err_t err = igmp_joingroup((ip_addr_t *)bufinfo.buf + 1, bufinfo.buf);
if (err != ERR_OK) {
mp_raise_OSError(error_lookup_table[-err]);
}
@@ -1327,7 +1404,10 @@ STATIC mp_uint_t lwip_socket_read(mp_obj_t self_in, void *buf, mp_uint_t size, i
case MOD_NETWORK_SOCK_STREAM:
return lwip_tcp_receive(socket, buf, size, errcode);
case MOD_NETWORK_SOCK_DGRAM:
- return lwip_udp_receive(socket, buf, size, NULL, NULL, errcode);
+ #if MICROPY_PY_LWIP_SOCK_RAW
+ case MOD_NETWORK_SOCK_RAW:
+ #endif
+ return lwip_raw_udp_receive(socket, buf, size, NULL, NULL, errcode);
}
// Unreachable
return MP_STREAM_ERROR;
@@ -1340,7 +1420,10 @@ STATIC mp_uint_t lwip_socket_write(mp_obj_t self_in, const void *buf, mp_uint_t
case MOD_NETWORK_SOCK_STREAM:
return lwip_tcp_send(socket, buf, size, errcode);
case MOD_NETWORK_SOCK_DGRAM:
- return lwip_udp_send(socket, buf, size, NULL, 0, errcode);
+ #if MICROPY_PY_LWIP_SOCK_RAW
+ case MOD_NETWORK_SOCK_RAW:
+ #endif
+ return lwip_raw_udp_send(socket, buf, size, NULL, 0, errcode);
}
// Unreachable
return MP_STREAM_ERROR;
@@ -1381,6 +1464,11 @@ STATIC mp_uint_t lwip_socket_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_
if (socket->type == MOD_NETWORK_SOCK_DGRAM && socket->pcb.udp != NULL) {
// UDP socket is writable
ret |= MP_STREAM_POLL_WR;
+ #if MICROPY_PY_LWIP_SOCK_RAW
+ } else if (socket->type == MOD_NETWORK_SOCK_RAW && socket->pcb.raw != NULL) {
+ // raw socket is writable
+ ret |= MP_STREAM_POLL_WR;
+ #endif
} else if (socket->pcb.tcp != NULL && tcp_sndbuf(socket->pcb.tcp) > 0) {
// TCP socket is writable
// Note: pcb.tcp==NULL if state<0, and in this case we can't call tcp_sndbuf
@@ -1390,7 +1478,7 @@ STATIC mp_uint_t lwip_socket_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_
if (socket->state == STATE_NEW) {
// New sockets are not connected so set HUP
- ret |= flags & MP_STREAM_POLL_HUP;
+ ret |= MP_STREAM_POLL_HUP;
} else if (socket->state == STATE_PEER_CLOSED) {
// Peer-closed socket is both readable and writable: read will
// return EOF, write - error. Without this poll will hang on a
@@ -1398,11 +1486,14 @@ STATIC mp_uint_t lwip_socket_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_
ret |= flags & (MP_STREAM_POLL_RD | MP_STREAM_POLL_WR);
} else if (socket->state == ERR_RST) {
// Socket was reset by peer, a write will return an error
- ret |= flags & (MP_STREAM_POLL_WR | MP_STREAM_POLL_HUP);
+ ret |= flags & MP_STREAM_POLL_WR;
+ ret |= MP_STREAM_POLL_HUP;
+ } else if (socket->state == _ERR_BADF) {
+ ret |= MP_STREAM_POLL_NVAL;
} else if (socket->state < 0) {
// Socket in some other error state, use catch-all ERR flag
// TODO: may need to set other return flags here
- ret |= flags & MP_STREAM_POLL_ERR;
+ ret |= MP_STREAM_POLL_ERR;
}
} else if (request == MP_STREAM_CLOSE) {
@@ -1433,8 +1524,14 @@ STATIC mp_uint_t lwip_socket_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_
}
break;
}
- case MOD_NETWORK_SOCK_DGRAM: udp_remove(socket->pcb.udp); break;
- //case MOD_NETWORK_SOCK_RAW: raw_remove(socket->pcb.raw); break;
+ case MOD_NETWORK_SOCK_DGRAM:
+ udp_remove(socket->pcb.udp);
+ break;
+ #if MICROPY_PY_LWIP_SOCK_RAW
+ case MOD_NETWORK_SOCK_RAW:
+ raw_remove(socket->pcb.raw);
+ break;
+ #endif
}
socket->pcb.tcp = NULL;
@@ -1487,7 +1584,7 @@ STATIC const mp_obj_type_t lwip_socket_type = {
.print = lwip_socket_print,
.make_new = lwip_socket_make_new,
.protocol = &lwip_socket_stream_p,
- .locals_dict = (mp_obj_dict_t*)&lwip_socket_locals_dict,
+ .locals_dict = (mp_obj_dict_t *)&lwip_socket_locals_dict,
};
/******************************************************************************/
@@ -1507,18 +1604,18 @@ void sys_arch_unprotect(sys_prot_t state) {
// itself a "list" but isn't; we only support a single interface.
typedef struct nic_poll {
- void (* poll)(void *arg);
+ void (*poll)(void *arg);
void *poll_arg;
} nic_poll_t;
STATIC nic_poll_t lwip_poll_list;
-void mod_lwip_register_poll(void (* poll)(void *arg), void *poll_arg) {
+void mod_lwip_register_poll(void (*poll)(void *arg), void *poll_arg) {
lwip_poll_list.poll = poll;
lwip_poll_list.poll_arg = poll_arg;
}
-void mod_lwip_deregister_poll(void (* poll)(void *arg), void *poll_arg) {
+void mod_lwip_deregister_poll(void (*poll)(void *arg), void *poll_arg) {
lwip_poll_list.poll = NULL;
}
@@ -1585,9 +1682,9 @@ STATIC mp_obj_t lwip_getaddrinfo(size_t n_args, const mp_obj_t *args) {
}
}
if (!((family == 0 || family == MOD_NETWORK_AF_INET)
- && (type == 0 || type == MOD_NETWORK_SOCK_STREAM)
- && proto == 0
- && flags == 0)) {
+ && (type == 0 || type == MOD_NETWORK_SOCK_STREAM)
+ && proto == 0
+ && flags == 0)) {
mp_warning(MP_WARN_CAT(RuntimeWarning), "unsupported getaddrinfo constraints");
}
}
@@ -1596,7 +1693,7 @@ STATIC mp_obj_t lwip_getaddrinfo(size_t n_args, const mp_obj_t *args) {
state.status = 0;
MICROPY_PY_LWIP_ENTER
- err_t ret = dns_gethostbyname(host, (ip_addr_t*)&state.ipaddr, lwip_getaddrinfo_cb, &state);
+ err_t ret = dns_gethostbyname(host, (ip_addr_t *)&state.ipaddr, lwip_getaddrinfo_cb, &state);
MICROPY_PY_LWIP_EXIT
switch (ret) {
@@ -1624,8 +1721,8 @@ STATIC mp_obj_t lwip_getaddrinfo(size_t n_args, const mp_obj_t *args) {
tuple->items[1] = MP_OBJ_NEW_SMALL_INT(MOD_NETWORK_SOCK_STREAM);
tuple->items[2] = MP_OBJ_NEW_SMALL_INT(0);
tuple->items[3] = MP_OBJ_NEW_QSTR(MP_QSTR_);
- tuple->items[4] = netutils_format_inet_addr((uint8_t*)&state.ipaddr, port, NETUTILS_BIG);
- return mp_obj_new_list(1, (mp_obj_t*)&tuple);
+ tuple->items[4] = netutils_format_inet_addr((uint8_t *)&state.ipaddr, port, NETUTILS_BIG);
+ return mp_obj_new_list(1, (mp_obj_t *)&tuple);
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(lwip_getaddrinfo_obj, 2, 6, lwip_getaddrinfo);
@@ -1647,16 +1744,18 @@ STATIC const mp_rom_map_elem_t mp_module_lwip_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_print_pcbs), MP_ROM_PTR(&lwip_print_pcbs_obj) },
// objects
{ MP_ROM_QSTR(MP_QSTR_socket), MP_ROM_PTR(&lwip_socket_type) },
-#ifdef MICROPY_PY_LWIP_SLIP
+ #ifdef MICROPY_PY_LWIP_SLIP
{ MP_ROM_QSTR(MP_QSTR_slip), MP_ROM_PTR(&lwip_slip_type) },
-#endif
+ #endif
// class constants
{ MP_ROM_QSTR(MP_QSTR_AF_INET), MP_ROM_INT(MOD_NETWORK_AF_INET) },
{ MP_ROM_QSTR(MP_QSTR_AF_INET6), MP_ROM_INT(MOD_NETWORK_AF_INET6) },
{ MP_ROM_QSTR(MP_QSTR_SOCK_STREAM), MP_ROM_INT(MOD_NETWORK_SOCK_STREAM) },
{ MP_ROM_QSTR(MP_QSTR_SOCK_DGRAM), MP_ROM_INT(MOD_NETWORK_SOCK_DGRAM) },
+ #if MICROPY_PY_LWIP_SOCK_RAW
{ MP_ROM_QSTR(MP_QSTR_SOCK_RAW), MP_ROM_INT(MOD_NETWORK_SOCK_RAW) },
+ #endif
{ MP_ROM_QSTR(MP_QSTR_SOL_SOCKET), MP_ROM_INT(1) },
{ MP_ROM_QSTR(MP_QSTR_SO_REUSEADDR), MP_ROM_INT(SOF_REUSEADDR) },
@@ -1669,7 +1768,7 @@ STATIC MP_DEFINE_CONST_DICT(mp_module_lwip_globals, mp_module_lwip_globals_table
const mp_obj_module_t mp_module_lwip = {
.base = { &mp_type_module },
- .globals = (mp_obj_dict_t*)&mp_module_lwip_globals,
+ .globals = (mp_obj_dict_t *)&mp_module_lwip_globals,
};
#endif // MICROPY_PY_LWIP
diff --git a/extmod/modonewire.c b/extmod/modonewire.c
index 7ef4c3bce8..210bee366e 100644
--- a/extmod/modonewire.c
+++ b/extmod/modonewire.c
@@ -126,7 +126,7 @@ STATIC mp_obj_t onewire_crc8(mp_obj_t data) {
mp_get_buffer_raise(data, &bufinfo, MP_BUFFER_READ);
uint8_t crc = 0;
for (size_t i = 0; i < bufinfo.len; ++i) {
- uint8_t byte = ((uint8_t*)bufinfo.buf)[i];
+ uint8_t byte = ((uint8_t *)bufinfo.buf)[i];
for (int b = 0; b < 8; ++b) {
uint8_t fb_bit = (crc ^ byte) & 0x01;
if (fb_bit == 0x01) {
@@ -158,5 +158,5 @@ STATIC MP_DEFINE_CONST_DICT(onewire_module_globals, onewire_module_globals_table
const mp_obj_module_t mp_module_onewire = {
.base = { &mp_type_module },
- .globals = (mp_obj_dict_t*)&onewire_module_globals,
+ .globals = (mp_obj_dict_t *)&onewire_module_globals,
};
diff --git a/extmod/moduasyncio.c b/extmod/moduasyncio.c
new file mode 100644
index 0000000000..0b15c9e079
--- /dev/null
+++ b/extmod/moduasyncio.c
@@ -0,0 +1,294 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2020 Damien P. George
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "py/runtime.h"
+#include "py/smallint.h"
+#include "py/pairheap.h"
+#include "py/mphal.h"
+
+#if MICROPY_PY_UASYNCIO
+
+typedef struct _mp_obj_task_t {
+ mp_pairheap_t pairheap;
+ mp_obj_t coro;
+ mp_obj_t data;
+ mp_obj_t waiting;
+
+ mp_obj_t ph_key;
+} mp_obj_task_t;
+
+typedef struct _mp_obj_task_queue_t {
+ mp_obj_base_t base;
+ mp_obj_task_t *heap;
+} mp_obj_task_queue_t;
+
+STATIC const mp_obj_type_t task_queue_type;
+STATIC const mp_obj_type_t task_type;
+
+STATIC mp_obj_t task_queue_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args);
+
+/******************************************************************************/
+// Ticks for task ordering in pairing heap
+
+STATIC mp_obj_t ticks(void) {
+ return MP_OBJ_NEW_SMALL_INT(mp_hal_ticks_ms() & (MICROPY_PY_UTIME_TICKS_PERIOD - 1));
+}
+
+STATIC mp_int_t ticks_diff(mp_obj_t t1_in, mp_obj_t t0_in) {
+ mp_uint_t t0 = MP_OBJ_SMALL_INT_VALUE(t0_in);
+ mp_uint_t t1 = MP_OBJ_SMALL_INT_VALUE(t1_in);
+ mp_int_t diff = ((t1 - t0 + MICROPY_PY_UTIME_TICKS_PERIOD / 2) & (MICROPY_PY_UTIME_TICKS_PERIOD - 1))
+ - MICROPY_PY_UTIME_TICKS_PERIOD / 2;
+ return diff;
+}
+
+STATIC int task_lt(mp_pairheap_t *n1, mp_pairheap_t *n2) {
+ mp_obj_task_t *t1 = (mp_obj_task_t *)n1;
+ mp_obj_task_t *t2 = (mp_obj_task_t *)n2;
+ return MP_OBJ_SMALL_INT_VALUE(ticks_diff(t1->ph_key, t2->ph_key)) < 0;
+}
+
+/******************************************************************************/
+// TaskQueue class
+
+STATIC mp_obj_t task_queue_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
+ (void)args;
+ mp_arg_check_num(n_args, n_kw, 0, 0, false);
+ mp_obj_task_queue_t *self = m_new_obj(mp_obj_task_queue_t);
+ self->base.type = type;
+ self->heap = (mp_obj_task_t *)mp_pairheap_new(task_lt);
+ return MP_OBJ_FROM_PTR(self);
+}
+
+STATIC mp_obj_t task_queue_peek(mp_obj_t self_in) {
+ mp_obj_task_queue_t *self = MP_OBJ_TO_PTR(self_in);
+ if (self->heap == NULL) {
+ return mp_const_none;
+ } else {
+ return MP_OBJ_FROM_PTR(self->heap);
+ }
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(task_queue_peek_obj, task_queue_peek);
+
+STATIC mp_obj_t task_queue_push_sorted(size_t n_args, const mp_obj_t *args) {
+ mp_obj_task_queue_t *self = MP_OBJ_TO_PTR(args[0]);
+ mp_obj_task_t *task = MP_OBJ_TO_PTR(args[1]);
+ task->data = mp_const_none;
+ if (n_args == 2) {
+ task->ph_key = ticks();
+ } else {
+ assert(mp_obj_is_small_int(args[2]));
+ task->ph_key = args[2];
+ }
+ self->heap = (mp_obj_task_t *)mp_pairheap_push(task_lt, &self->heap->pairheap, &task->pairheap);
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(task_queue_push_sorted_obj, 2, 3, task_queue_push_sorted);
+
+STATIC mp_obj_t task_queue_pop_head(mp_obj_t self_in) {
+ mp_obj_task_queue_t *self = MP_OBJ_TO_PTR(self_in);
+ mp_obj_task_t *head = (mp_obj_task_t *)mp_pairheap_peek(task_lt, &self->heap->pairheap);
+ if (head == NULL) {
+ mp_raise_msg(&mp_type_IndexError, MP_ERROR_TEXT("empty heap"));
+ }
+ self->heap = (mp_obj_task_t *)mp_pairheap_pop(task_lt, &self->heap->pairheap);
+ return MP_OBJ_FROM_PTR(head);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(task_queue_pop_head_obj, task_queue_pop_head);
+
+STATIC mp_obj_t task_queue_remove(mp_obj_t self_in, mp_obj_t task_in) {
+ mp_obj_task_queue_t *self = MP_OBJ_TO_PTR(self_in);
+ mp_obj_task_t *task = MP_OBJ_TO_PTR(task_in);
+ self->heap = (mp_obj_task_t *)mp_pairheap_delete(task_lt, &self->heap->pairheap, &task->pairheap);
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(task_queue_remove_obj, task_queue_remove);
+
+STATIC const mp_rom_map_elem_t task_queue_locals_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_peek), MP_ROM_PTR(&task_queue_peek_obj) },
+ { MP_ROM_QSTR(MP_QSTR_push_sorted), MP_ROM_PTR(&task_queue_push_sorted_obj) },
+ { MP_ROM_QSTR(MP_QSTR_push_head), MP_ROM_PTR(&task_queue_push_sorted_obj) },
+ { MP_ROM_QSTR(MP_QSTR_pop_head), MP_ROM_PTR(&task_queue_pop_head_obj) },
+ { MP_ROM_QSTR(MP_QSTR_remove), MP_ROM_PTR(&task_queue_remove_obj) },
+};
+STATIC MP_DEFINE_CONST_DICT(task_queue_locals_dict, task_queue_locals_dict_table);
+
+STATIC const mp_obj_type_t task_queue_type = {
+ { &mp_type_type },
+ .name = MP_QSTR_TaskQueue,
+ .make_new = task_queue_make_new,
+ .locals_dict = (mp_obj_dict_t *)&task_queue_locals_dict,
+};
+
+/******************************************************************************/
+// Task class
+
+// This is the core uasyncio context with cur_task, _task_queue and CancelledError.
+STATIC mp_obj_t uasyncio_context = MP_OBJ_NULL;
+
+STATIC mp_obj_t task_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
+ mp_arg_check_num(n_args, n_kw, 1, 2, false);
+ mp_obj_task_t *self = m_new_obj(mp_obj_task_t);
+ self->pairheap.base.type = type;
+ mp_pairheap_init_node(task_lt, &self->pairheap);
+ self->coro = args[0];
+ self->data = mp_const_none;
+ self->waiting = mp_const_none;
+ self->ph_key = MP_OBJ_NEW_SMALL_INT(0);
+ if (n_args == 2) {
+ uasyncio_context = args[1];
+ }
+ return MP_OBJ_FROM_PTR(self);
+}
+
+STATIC mp_obj_t task_cancel(mp_obj_t self_in) {
+ mp_obj_task_t *self = MP_OBJ_TO_PTR(self_in);
+ // Check if task is already finished.
+ if (self->coro == mp_const_none) {
+ return mp_const_false;
+ }
+ // Can't cancel self (not supported yet).
+ mp_obj_t cur_task = mp_obj_dict_get(uasyncio_context, MP_OBJ_NEW_QSTR(MP_QSTR_cur_task));
+ if (self_in == cur_task) {
+ mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("can't cancel self"));
+ }
+ // If Task waits on another task then forward the cancel to the one it's waiting on.
+ while (mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(mp_obj_get_type(self->data)), MP_OBJ_FROM_PTR(&task_type))) {
+ self = MP_OBJ_TO_PTR(self->data);
+ }
+
+ mp_obj_t _task_queue = mp_obj_dict_get(uasyncio_context, MP_OBJ_NEW_QSTR(MP_QSTR__task_queue));
+
+ // Reschedule Task as a cancelled task.
+ mp_obj_t dest[3];
+ mp_load_method_maybe(self->data, MP_QSTR_remove, dest);
+ if (dest[0] != MP_OBJ_NULL) {
+ // Not on the main running queue, remove the task from the queue it's on.
+ dest[2] = MP_OBJ_FROM_PTR(self);
+ mp_call_method_n_kw(1, 0, dest);
+ // _task_queue.push_head(self)
+ dest[0] = _task_queue;
+ dest[1] = MP_OBJ_FROM_PTR(self);
+ task_queue_push_sorted(2, dest);
+ } else if (ticks_diff(self->ph_key, ticks()) > 0) {
+ // On the main running queue but scheduled in the future, so bring it forward to now.
+ // _task_queue.remove(self)
+ task_queue_remove(_task_queue, MP_OBJ_FROM_PTR(self));
+ // _task_queue.push_head(self)
+ dest[0] = _task_queue;
+ dest[1] = MP_OBJ_FROM_PTR(self);
+ task_queue_push_sorted(2, dest);
+ }
+
+ self->data = mp_obj_dict_get(uasyncio_context, MP_OBJ_NEW_QSTR(MP_QSTR_CancelledError));
+
+ return mp_const_true;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(task_cancel_obj, task_cancel);
+
+STATIC void task_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
+ mp_obj_task_t *self = MP_OBJ_TO_PTR(self_in);
+ if (dest[0] == MP_OBJ_NULL) {
+ // Load
+ if (attr == MP_QSTR_coro) {
+ dest[0] = self->coro;
+ } else if (attr == MP_QSTR_data) {
+ dest[0] = self->data;
+ } else if (attr == MP_QSTR_waiting) {
+ if (self->waiting != mp_const_none) {
+ dest[0] = self->waiting;
+ }
+ } else if (attr == MP_QSTR_cancel) {
+ dest[0] = MP_OBJ_FROM_PTR(&task_cancel_obj);
+ dest[1] = self_in;
+ } else if (attr == MP_QSTR_ph_key) {
+ dest[0] = self->ph_key;
+ }
+ } else if (dest[1] != MP_OBJ_NULL) {
+ // Store
+ if (attr == MP_QSTR_coro) {
+ self->coro = dest[1];
+ dest[0] = MP_OBJ_NULL;
+ } else if (attr == MP_QSTR_data) {
+ self->data = dest[1];
+ dest[0] = MP_OBJ_NULL;
+ } else if (attr == MP_QSTR_waiting) {
+ self->waiting = dest[1];
+ dest[0] = MP_OBJ_NULL;
+ }
+ }
+}
+
+STATIC mp_obj_t task_getiter(mp_obj_t self_in, mp_obj_iter_buf_t *iter_buf) {
+ (void)iter_buf;
+ mp_obj_task_t *self = MP_OBJ_TO_PTR(self_in);
+ if (self->waiting == mp_const_none) {
+ self->waiting = task_queue_make_new(&task_queue_type, 0, 0, NULL);
+ }
+ return self_in;
+}
+
+STATIC mp_obj_t task_iternext(mp_obj_t self_in) {
+ mp_obj_task_t *self = MP_OBJ_TO_PTR(self_in);
+ if (self->coro == mp_const_none) {
+ // Task finished, raise return value to caller so it can continue.
+ nlr_raise(self->data);
+ } else {
+ // Put calling task on waiting queue.
+ mp_obj_t cur_task = mp_obj_dict_get(uasyncio_context, MP_OBJ_NEW_QSTR(MP_QSTR_cur_task));
+ mp_obj_t args[2] = { self->waiting, cur_task };
+ task_queue_push_sorted(2, args);
+ // Set calling task's data to this task that it waits on, to double-link it.
+ ((mp_obj_task_t *)MP_OBJ_TO_PTR(cur_task))->data = self_in;
+ }
+ return mp_const_none;
+}
+
+STATIC const mp_obj_type_t task_type = {
+ { &mp_type_type },
+ .name = MP_QSTR_Task,
+ .make_new = task_make_new,
+ .attr = task_attr,
+ .getiter = task_getiter,
+ .iternext = task_iternext,
+};
+
+/******************************************************************************/
+// C-level uasyncio module
+
+STATIC const mp_rom_map_elem_t mp_module_uasyncio_globals_table[] = {
+ { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR__uasyncio) },
+ { MP_ROM_QSTR(MP_QSTR_TaskQueue), MP_ROM_PTR(&task_queue_type) },
+ { MP_ROM_QSTR(MP_QSTR_Task), MP_ROM_PTR(&task_type) },
+};
+STATIC MP_DEFINE_CONST_DICT(mp_module_uasyncio_globals, mp_module_uasyncio_globals_table);
+
+const mp_obj_module_t mp_module_uasyncio = {
+ .base = { &mp_type_module },
+ .globals = (mp_obj_dict_t *)&mp_module_uasyncio_globals,
+};
+
+#endif // MICROPY_PY_UASYNCIO
diff --git a/extmod/modubinascii.c b/extmod/modubinascii.c
index 8256a50cf2..1d4c72b24b 100644
--- a/extmod/modubinascii.c
+++ b/extmod/modubinascii.c
@@ -30,9 +30,10 @@
#include "py/runtime.h"
#include "py/binary.h"
-#include "extmod/modubinascii.h"
-mp_obj_t mod_binascii_hexlify(size_t n_args, const mp_obj_t *args) {
+#if MICROPY_PY_UBINASCII
+
+STATIC mp_obj_t mod_binascii_hexlify(size_t n_args, const mp_obj_t *args) {
// Second argument is for an extension to allow a separator to be used
// between values.
const char *sep = NULL;
@@ -53,7 +54,7 @@ mp_obj_t mod_binascii_hexlify(size_t n_args, const mp_obj_t *args) {
sep = mp_obj_str_get_str(args[1]);
}
vstr_init_len(&vstr, out_len);
- byte *in = bufinfo.buf, *out = (byte*)vstr.buf;
+ byte *in = bufinfo.buf, *out = (byte *)vstr.buf;
for (mp_uint_t i = bufinfo.len; i--;) {
byte d = (*in >> 4);
if (d > 9) {
@@ -71,25 +72,25 @@ mp_obj_t mod_binascii_hexlify(size_t n_args, const mp_obj_t *args) {
}
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
}
-MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_binascii_hexlify_obj, 1, 2, mod_binascii_hexlify);
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_binascii_hexlify_obj, 1, 2, mod_binascii_hexlify);
-mp_obj_t mod_binascii_unhexlify(mp_obj_t data) {
+STATIC mp_obj_t mod_binascii_unhexlify(mp_obj_t data) {
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(data, &bufinfo, MP_BUFFER_READ);
if ((bufinfo.len & 1) != 0) {
- mp_raise_ValueError("odd-length string");
+ mp_raise_ValueError(MP_ERROR_TEXT("odd-length string"));
}
vstr_t vstr;
vstr_init_len(&vstr, bufinfo.len / 2);
- byte *in = bufinfo.buf, *out = (byte*)vstr.buf;
+ byte *in = bufinfo.buf, *out = (byte *)vstr.buf;
byte hex_byte = 0;
for (mp_uint_t i = bufinfo.len; i--;) {
byte hex_ch = *in++;
if (unichar_isxdigit(hex_ch)) {
hex_byte += unichar_xdigit_value(hex_ch);
} else {
- mp_raise_ValueError("non-hex digit found");
+ mp_raise_ValueError(MP_ERROR_TEXT("non-hex digit found"));
}
if (i & 1) {
hex_byte <<= 4;
@@ -100,7 +101,7 @@ mp_obj_t mod_binascii_unhexlify(mp_obj_t data) {
}
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
}
-MP_DEFINE_CONST_FUN_OBJ_1(mod_binascii_unhexlify_obj, mod_binascii_unhexlify);
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_binascii_unhexlify_obj, mod_binascii_unhexlify);
// If ch is a character in the base64 alphabet, and is not a pad character, then
// the corresponding integer between 0 and 63, inclusively, is returned.
@@ -121,7 +122,7 @@ static int mod_binascii_sextet(byte ch) {
}
}
-mp_obj_t mod_binascii_a2b_base64(mp_obj_t data) {
+STATIC mp_obj_t mod_binascii_a2b_base64(mp_obj_t data) {
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(data, &bufinfo, MP_BUFFER_READ);
byte *in = bufinfo.buf;
@@ -157,14 +158,14 @@ mp_obj_t mod_binascii_a2b_base64(mp_obj_t data) {
}
if (nbits) {
- mp_raise_ValueError("incorrect padding");
+ mp_raise_ValueError(MP_ERROR_TEXT("incorrect padding"));
}
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
}
-MP_DEFINE_CONST_FUN_OBJ_1(mod_binascii_a2b_base64_obj, mod_binascii_a2b_base64);
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_binascii_a2b_base64_obj, mod_binascii_a2b_base64);
-mp_obj_t mod_binascii_b2a_base64(mp_obj_t data) {
+STATIC mp_obj_t mod_binascii_b2a_base64(mp_obj_t data) {
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(data, &bufinfo, MP_BUFFER_READ);
@@ -172,7 +173,7 @@ mp_obj_t mod_binascii_b2a_base64(mp_obj_t data) {
vstr_init_len(&vstr, ((bufinfo.len != 0) ? (((bufinfo.len - 1) / 3) + 1) * 4 : 0) + 1);
// First pass, we convert input buffer to numeric base 64 values
- byte *in = bufinfo.buf, *out = (byte*)vstr.buf;
+ byte *in = bufinfo.buf, *out = (byte *)vstr.buf;
mp_uint_t i;
for (i = bufinfo.len; i >= 3; i -= 3) {
*out++ = (in[0] & 0xFC) >> 2;
@@ -186,8 +187,7 @@ mp_obj_t mod_binascii_b2a_base64(mp_obj_t data) {
if (i == 2) {
*out++ = (in[0] & 0x03) << 4 | (in[1] & 0xF0) >> 4;
*out++ = (in[1] & 0x0F) << 2;
- }
- else {
+ } else {
*out++ = (in[0] & 0x03) << 4;
*out++ = 64;
}
@@ -195,7 +195,7 @@ mp_obj_t mod_binascii_b2a_base64(mp_obj_t data) {
}
// Second pass, we convert number base 64 values to actual base64 ascii encoding
- out = (byte*)vstr.buf;
+ out = (byte *)vstr.buf;
for (mp_uint_t j = vstr.len - 1; j--;) {
if (*out < 26) {
*out += 'A';
@@ -204,7 +204,7 @@ mp_obj_t mod_binascii_b2a_base64(mp_obj_t data) {
} else if (*out < 62) {
*out += '0' - 52;
} else if (*out == 62) {
- *out ='+';
+ *out = '+';
} else if (*out == 63) {
*out = '/';
} else {
@@ -215,23 +215,21 @@ mp_obj_t mod_binascii_b2a_base64(mp_obj_t data) {
*out = '\n';
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
}
-MP_DEFINE_CONST_FUN_OBJ_1(mod_binascii_b2a_base64_obj, mod_binascii_b2a_base64);
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_binascii_b2a_base64_obj, mod_binascii_b2a_base64);
#if MICROPY_PY_UBINASCII_CRC32
#include "uzlib/tinf.h"
-mp_obj_t mod_binascii_crc32(size_t n_args, const mp_obj_t *args) {
+STATIC mp_obj_t mod_binascii_crc32(size_t n_args, const mp_obj_t *args) {
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_READ);
uint32_t crc = (n_args > 1) ? mp_obj_get_int_truncated(args[1]) : 0;
crc = uzlib_crc32(bufinfo.buf, bufinfo.len, crc ^ 0xffffffff);
return mp_obj_new_int_from_uint(crc ^ 0xffffffff);
}
-MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_binascii_crc32_obj, 1, 2, mod_binascii_crc32);
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_binascii_crc32_obj, 1, 2, mod_binascii_crc32);
#endif
-#if MICROPY_PY_UBINASCII
-
STATIC const mp_rom_map_elem_t mp_module_binascii_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_ubinascii) },
{ MP_ROM_QSTR(MP_QSTR_hexlify), MP_ROM_PTR(&mod_binascii_hexlify_obj) },
@@ -247,7 +245,7 @@ STATIC MP_DEFINE_CONST_DICT(mp_module_binascii_globals, mp_module_binascii_globa
const mp_obj_module_t mp_module_ubinascii = {
.base = { &mp_type_module },
- .globals = (mp_obj_dict_t*)&mp_module_binascii_globals,
+ .globals = (mp_obj_dict_t *)&mp_module_binascii_globals,
};
-#endif //MICROPY_PY_UBINASCII
+#endif // MICROPY_PY_UBINASCII
diff --git a/extmod/modubinascii.h b/extmod/modubinascii.h
deleted file mode 100644
index fb31692678..0000000000
--- a/extmod/modubinascii.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * This file is part of the MicroPython project, http://micropython.org/
- *
- * The MIT License (MIT)
- *
- * Copyright (c) 2014 Paul Sokolovsky
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-#ifndef MICROPY_INCLUDED_EXTMOD_MODUBINASCII_H
-#define MICROPY_INCLUDED_EXTMOD_MODUBINASCII_H
-
-extern mp_obj_t mod_binascii_hexlify(size_t n_args, const mp_obj_t *args);
-extern mp_obj_t mod_binascii_unhexlify(mp_obj_t data);
-extern mp_obj_t mod_binascii_a2b_base64(mp_obj_t data);
-extern mp_obj_t mod_binascii_b2a_base64(mp_obj_t data);
-extern mp_obj_t mod_binascii_crc32(size_t n_args, const mp_obj_t *args);
-
-MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mod_binascii_hexlify_obj);
-MP_DECLARE_CONST_FUN_OBJ_1(mod_binascii_unhexlify_obj);
-MP_DECLARE_CONST_FUN_OBJ_1(mod_binascii_a2b_base64_obj);
-MP_DECLARE_CONST_FUN_OBJ_1(mod_binascii_b2a_base64_obj);
-MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mod_binascii_crc32_obj);
-
-#endif // MICROPY_INCLUDED_EXTMOD_MODUBINASCII_H
diff --git a/extmod/moducryptolib.c b/extmod/moducryptolib.c
index 15cd4535f8..6c89d6d9fe 100644
--- a/extmod/moducryptolib.c
+++ b/extmod/moducryptolib.c
@@ -82,14 +82,14 @@ struct mbedtls_aes_ctx_with_key {
typedef struct _mp_obj_aes_t {
mp_obj_base_t base;
AES_CTX_IMPL ctx;
- uint8_t block_mode: 6;
+ uint8_t block_mode : 6;
#define AES_KEYTYPE_NONE 0
#define AES_KEYTYPE_ENC 1
#define AES_KEYTYPE_DEC 2
- uint8_t key_type: 2;
+ uint8_t key_type : 2;
} mp_obj_aes_t;
-STATIC inline bool is_ctr_mode(int block_mode) {
+static inline bool is_ctr_mode(int block_mode) {
#if MICROPY_PY_UCRYPTOLIB_CTR
return block_mode == UCRYPTOLIB_MODE_CTR;
#else
@@ -97,9 +97,9 @@ STATIC inline bool is_ctr_mode(int block_mode) {
#endif
}
-STATIC inline struct ctr_params *ctr_params_from_aes(mp_obj_aes_t *o) {
+static inline struct ctr_params *ctr_params_from_aes(mp_obj_aes_t *o) {
// ctr_params follows aes object struct
- return (struct ctr_params*)&o[1];
+ return (struct ctr_params *)&o[1];
}
#if MICROPY_SSL_AXTLS
@@ -117,7 +117,7 @@ STATIC void aes_final_set_key_impl(AES_CTX_IMPL *ctx, bool encrypt) {
STATIC void aes_process_ecb_impl(AES_CTX_IMPL *ctx, const uint8_t in[16], uint8_t out[16], bool encrypt) {
memcpy(out, in, 16);
// We assume that out (vstr.buf or given output buffer) is uint32_t aligned
- uint32_t *p = (uint32_t*)out;
+ uint32_t *p = (uint32_t *)out;
// axTLS likes it weird and complicated with byteswaps
for (int i = 0; i < 4; i++) {
p[i] = MP_HTOBE32(p[i]);
@@ -225,7 +225,7 @@ STATIC mp_obj_t ucryptolib_aes_make_new(const mp_obj_type_t *type, size_t n_args
break;
default:
- mp_raise_ValueError("mode");
+ mp_raise_ValueError(MP_ERROR_TEXT("mode"));
}
mp_obj_aes_t *o = m_new_obj_var(mp_obj_aes_t, struct ctr_params, !!is_ctr_mode(block_mode));
@@ -237,7 +237,7 @@ STATIC mp_obj_t ucryptolib_aes_make_new(const mp_obj_type_t *type, size_t n_args
mp_buffer_info_t keyinfo;
mp_get_buffer_raise(args[0], &keyinfo, MP_BUFFER_READ);
if (32 != keyinfo.len && 16 != keyinfo.len) {
- mp_raise_ValueError("key");
+ mp_raise_ValueError(MP_ERROR_TEXT("key"));
}
mp_buffer_info_t ivinfo;
@@ -246,10 +246,10 @@ STATIC mp_obj_t ucryptolib_aes_make_new(const mp_obj_type_t *type, size_t n_args
mp_get_buffer_raise(args[2], &ivinfo, MP_BUFFER_READ);
if (16 != ivinfo.len) {
- mp_raise_ValueError("IV");
+ mp_raise_ValueError(MP_ERROR_TEXT("IV"));
}
} else if (o->block_mode == UCRYPTOLIB_MODE_CBC || is_ctr_mode(o->block_mode)) {
- mp_raise_ValueError("IV");
+ mp_raise_ValueError(MP_ERROR_TEXT("IV"));
}
if (is_ctr_mode(block_mode)) {
@@ -274,7 +274,7 @@ STATIC mp_obj_t aes_process(size_t n_args, const mp_obj_t *args, bool encrypt) {
mp_get_buffer_raise(in_buf, &in_bufinfo, MP_BUFFER_READ);
if (!is_ctr_mode(self->block_mode) && in_bufinfo.len % 16 != 0) {
- mp_raise_ValueError("blksize % 16");
+ mp_raise_ValueError(MP_ERROR_TEXT("blksize % 16"));
}
vstr_t vstr;
@@ -284,12 +284,12 @@ STATIC mp_obj_t aes_process(size_t n_args, const mp_obj_t *args, bool encrypt) {
if (out_buf != MP_OBJ_NULL) {
mp_get_buffer_raise(out_buf, &out_bufinfo, MP_BUFFER_WRITE);
if (out_bufinfo.len < in_bufinfo.len) {
- mp_raise_ValueError("output too small");
+ mp_raise_ValueError(MP_ERROR_TEXT("output too small"));
}
out_buf_ptr = out_bufinfo.buf;
} else {
vstr_init_len(&vstr, in_bufinfo.len);
- out_buf_ptr = (uint8_t*)vstr.buf;
+ out_buf_ptr = (uint8_t *)vstr.buf;
}
if (AES_KEYTYPE_NONE == self->key_type) {
@@ -301,7 +301,7 @@ STATIC mp_obj_t aes_process(size_t n_args, const mp_obj_t *args, bool encrypt) {
if ((encrypt && self->key_type == AES_KEYTYPE_DEC) ||
(!encrypt && self->key_type == AES_KEYTYPE_ENC)) {
- mp_raise_ValueError("can't encrypt & decrypt");
+ mp_raise_ValueError(MP_ERROR_TEXT("can't encrypt & decrypt"));
}
}
@@ -353,26 +353,26 @@ STATIC const mp_obj_type_t ucryptolib_aes_type = {
{ &mp_type_type },
.name = MP_QSTR_aes,
.make_new = ucryptolib_aes_make_new,
- .locals_dict = (void*)&ucryptolib_aes_locals_dict,
+ .locals_dict = (void *)&ucryptolib_aes_locals_dict,
};
STATIC const mp_rom_map_elem_t mp_module_ucryptolib_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_ucryptolib) },
{ MP_ROM_QSTR(MP_QSTR_aes), MP_ROM_PTR(&ucryptolib_aes_type) },
-#if MICROPY_PY_UCRYPTOLIB_CONSTS
+ #if MICROPY_PY_UCRYPTOLIB_CONSTS
{ MP_ROM_QSTR(MP_QSTR_MODE_ECB), MP_ROM_INT(UCRYPTOLIB_MODE_ECB) },
{ MP_ROM_QSTR(MP_QSTR_MODE_CBC), MP_ROM_INT(UCRYPTOLIB_MODE_CBC) },
#if MICROPY_PY_UCRYPTOLIB_CTR
{ MP_ROM_QSTR(MP_QSTR_MODE_CTR), MP_ROM_INT(UCRYPTOLIB_MODE_CTR) },
#endif
-#endif
+ #endif
};
STATIC MP_DEFINE_CONST_DICT(mp_module_ucryptolib_globals, mp_module_ucryptolib_globals_table);
const mp_obj_module_t mp_module_ucryptolib = {
.base = { &mp_type_module },
- .globals = (mp_obj_dict_t*)&mp_module_ucryptolib_globals,
+ .globals = (mp_obj_dict_t *)&mp_module_ucryptolib_globals,
};
-#endif //MICROPY_PY_UCRYPTOLIB
+#endif // MICROPY_PY_UCRYPTOLIB
diff --git a/extmod/moductypes.c b/extmod/moductypes.c
index 9b46371f36..811258424a 100644
--- a/extmod/moductypes.c
+++ b/extmod/moductypes.c
@@ -117,14 +117,14 @@ typedef struct _mp_obj_uctypes_struct_t {
} mp_obj_uctypes_struct_t;
STATIC NORETURN void syntax_error(void) {
- mp_raise_TypeError("syntax error in uctypes descriptor");
+ mp_raise_TypeError(MP_ERROR_TEXT("syntax error in uctypes descriptor"));
}
STATIC mp_obj_t uctypes_struct_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
mp_arg_check_num(n_args, n_kw, 2, 3, false);
mp_obj_uctypes_struct_t *o = m_new_obj(mp_obj_uctypes_struct_t);
o->base.type = type;
- o->addr = (void*)(uintptr_t)mp_obj_int_get_truncated(args[0]);
+ o->addr = (void *)(uintptr_t)mp_obj_int_get_truncated(args[0]);
o->desc = args[1];
o->flags = LAYOUT_NATIVE;
if (n_args == 3) {
@@ -137,19 +137,19 @@ STATIC void uctypes_struct_print(const mp_print_t *print, mp_obj_t self_in, mp_p
(void)kind;
mp_obj_uctypes_struct_t *self = MP_OBJ_TO_PTR(self_in);
const char *typen = "unk";
- if (mp_obj_is_type(self->desc, &mp_type_dict)
- #if MICROPY_PY_COLLECTIONS_ORDEREDDICT
- || mp_obj_is_type(self->desc, &mp_type_ordereddict)
- #endif
- ) {
+ if (mp_obj_is_dict_or_ordereddict(self->desc)) {
typen = "STRUCT";
} else if (mp_obj_is_type(self->desc, &mp_type_tuple)) {
mp_obj_tuple_t *t = MP_OBJ_TO_PTR(self->desc);
mp_int_t offset = MP_OBJ_SMALL_INT_VALUE(t->items[0]);
uint agg_type = GET_TYPE(offset, AGG_TYPE_BITS);
switch (agg_type) {
- case PTR: typen = "PTR"; break;
- case ARRAY: typen = "ARRAY"; break;
+ case PTR:
+ typen = "PTR";
+ break;
+ case ARRAY:
+ typen = "ARRAY";
+ break;
}
} else {
typen = "ERROR";
@@ -180,10 +180,10 @@ STATIC mp_uint_t uctypes_struct_agg_size(mp_obj_tuple_t *t, int layout_type, mp_
case STRUCT:
return uctypes_struct_size(t->items[1], layout_type, max_field_size);
case PTR:
- if (sizeof(void*) > *max_field_size) {
- *max_field_size = sizeof(void*);
+ if (sizeof(void *) > *max_field_size) {
+ *max_field_size = sizeof(void *);
}
- return sizeof(void*);
+ return sizeof(void *);
case ARRAY: {
mp_int_t arr_sz = MP_OBJ_SMALL_INT_VALUE(t->items[1]);
uint val_type = GET_TYPE(arr_sz, VAL_TYPE_BITS);
@@ -210,19 +210,15 @@ STATIC mp_uint_t uctypes_struct_agg_size(mp_obj_tuple_t *t, int layout_type, mp_
}
STATIC mp_uint_t uctypes_struct_size(mp_obj_t desc_in, int layout_type, mp_uint_t *max_field_size) {
- if (!mp_obj_is_type(desc_in, &mp_type_dict)
- #if MICROPY_PY_COLLECTIONS_ORDEREDDICT
- && !mp_obj_is_type(desc_in, &mp_type_ordereddict)
- #endif
- ) {
+ if (!mp_obj_is_dict_or_ordereddict(desc_in)) {
if (mp_obj_is_type(desc_in, &mp_type_tuple)) {
- return uctypes_struct_agg_size((mp_obj_tuple_t*)MP_OBJ_TO_PTR(desc_in), layout_type, max_field_size);
+ return uctypes_struct_agg_size((mp_obj_tuple_t *)MP_OBJ_TO_PTR(desc_in), layout_type, max_field_size);
} else if (mp_obj_is_small_int(desc_in)) {
// We allow sizeof on both type definitions and structures/structure fields,
// but scalar structure field is lowered into native Python int, so all
// type info is lost. So, we cannot say if it's scalar type description,
// or such lowered scalar.
- mp_raise_TypeError("Cannot unambiguously get sizeof scalar");
+ mp_raise_TypeError(MP_ERROR_TEXT("can't unambiguously get sizeof scalar"));
}
syntax_error();
}
@@ -299,23 +295,23 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(uctypes_struct_sizeof_obj, 1, 2, ucty
static inline mp_obj_t get_unaligned(uint val_type, byte *p, int big_endian) {
char struct_type = big_endian ? '>' : '<';
static const char type2char[16] = "BbHhIiQq------fd";
- return mp_binary_get_val(struct_type, type2char[val_type], &p);
+ return mp_binary_get_val(struct_type, type2char[val_type], p, &p);
}
static inline void set_unaligned(uint val_type, byte *p, int big_endian, mp_obj_t val) {
char struct_type = big_endian ? '>' : '<';
static const char type2char[16] = "BbHhIiQq------fd";
- mp_binary_set_val(struct_type, type2char[val_type], val, &p);
+ mp_binary_set_val(struct_type, type2char[val_type], val, p, &p);
}
static inline mp_uint_t get_aligned_basic(uint val_type, void *p) {
switch (val_type) {
case UINT8:
- return *(uint8_t*)p;
+ return *(uint8_t *)p;
case UINT16:
- return *(uint16_t*)p;
+ return *(uint16_t *)p;
case UINT32:
- return *(uint32_t*)p;
+ return *(uint32_t *)p;
}
assert(0);
return 0;
@@ -324,11 +320,14 @@ static inline mp_uint_t get_aligned_basic(uint val_type, void *p) {
static inline void set_aligned_basic(uint val_type, void *p, mp_uint_t v) {
switch (val_type) {
case UINT8:
- *(uint8_t*)p = (uint8_t)v; return;
+ *(uint8_t *)p = (uint8_t)v;
+ return;
case UINT16:
- *(uint16_t*)p = (uint16_t)v; return;
+ *(uint16_t *)p = (uint16_t)v;
+ return;
case UINT32:
- *(uint32_t*)p = (uint32_t)v; return;
+ *(uint32_t *)p = (uint32_t)v;
+ return;
}
assert(0);
}
@@ -336,26 +335,26 @@ static inline void set_aligned_basic(uint val_type, void *p, mp_uint_t v) {
STATIC mp_obj_t get_aligned(uint val_type, void *p, mp_int_t index) {
switch (val_type) {
case UINT8:
- return MP_OBJ_NEW_SMALL_INT(((uint8_t*)p)[index]);
+ return MP_OBJ_NEW_SMALL_INT(((uint8_t *)p)[index]);
case INT8:
- return MP_OBJ_NEW_SMALL_INT(((int8_t*)p)[index]);
+ return MP_OBJ_NEW_SMALL_INT(((int8_t *)p)[index]);
case UINT16:
- return MP_OBJ_NEW_SMALL_INT(((uint16_t*)p)[index]);
+ return MP_OBJ_NEW_SMALL_INT(((uint16_t *)p)[index]);
case INT16:
- return MP_OBJ_NEW_SMALL_INT(((int16_t*)p)[index]);
+ return MP_OBJ_NEW_SMALL_INT(((int16_t *)p)[index]);
case UINT32:
- return mp_obj_new_int_from_uint(((uint32_t*)p)[index]);
+ return mp_obj_new_int_from_uint(((uint32_t *)p)[index]);
case INT32:
- return mp_obj_new_int(((int32_t*)p)[index]);
+ return mp_obj_new_int(((int32_t *)p)[index]);
case UINT64:
- return mp_obj_new_int_from_ull(((uint64_t*)p)[index]);
+ return mp_obj_new_int_from_ull(((uint64_t *)p)[index]);
case INT64:
- return mp_obj_new_int_from_ll(((int64_t*)p)[index]);
+ return mp_obj_new_int_from_ll(((int64_t *)p)[index]);
#if MICROPY_PY_BUILTINS_FLOAT
case FLOAT32:
- return mp_obj_new_float(((float*)p)[index]);
+ return mp_obj_new_float_from_f(((float *)p)[index]);
case FLOAT64:
- return mp_obj_new_float(((double*)p)[index]);
+ return mp_obj_new_float_from_d(((double *)p)[index]);
#endif
default:
assert(0);
@@ -366,11 +365,10 @@ STATIC mp_obj_t get_aligned(uint val_type, void *p, mp_int_t index) {
STATIC void set_aligned(uint val_type, void *p, mp_int_t index, mp_obj_t val) {
#if MICROPY_PY_BUILTINS_FLOAT
if (val_type == FLOAT32 || val_type == FLOAT64) {
- mp_float_t v = mp_obj_get_float(val);
if (val_type == FLOAT32) {
- ((float*)p)[index] = v;
+ ((float *)p)[index] = mp_obj_get_float_to_f(val);
} else {
- ((double*)p)[index] = v;
+ ((double *)p)[index] = mp_obj_get_float_to_d(val);
}
return;
}
@@ -378,21 +376,27 @@ STATIC void set_aligned(uint val_type, void *p, mp_int_t index, mp_obj_t val) {
mp_int_t v = mp_obj_get_int_truncated(val);
switch (val_type) {
case UINT8:
- ((uint8_t*)p)[index] = (uint8_t)v; return;
+ ((uint8_t *)p)[index] = (uint8_t)v;
+ return;
case INT8:
- ((int8_t*)p)[index] = (int8_t)v; return;
+ ((int8_t *)p)[index] = (int8_t)v;
+ return;
case UINT16:
- ((uint16_t*)p)[index] = (uint16_t)v; return;
+ ((uint16_t *)p)[index] = (uint16_t)v;
+ return;
case INT16:
- ((int16_t*)p)[index] = (int16_t)v; return;
+ ((int16_t *)p)[index] = (int16_t)v;
+ return;
case UINT32:
- ((uint32_t*)p)[index] = (uint32_t)v; return;
+ ((uint32_t *)p)[index] = (uint32_t)v;
+ return;
case INT32:
- ((int32_t*)p)[index] = (int32_t)v; return;
+ ((int32_t *)p)[index] = (int32_t)v;
+ return;
case INT64:
case UINT64:
if (sizeof(mp_int_t) == 8) {
- ((uint64_t*)p)[index] = (uint64_t)v;
+ ((uint64_t *)p)[index] = (uint64_t)v;
} else {
// TODO: Doesn't offer atomic store semantics, but should at least try
set_unaligned(val_type, p, MP_ENDIANNESS_BIG, val);
@@ -406,12 +410,8 @@ STATIC void set_aligned(uint val_type, void *p, mp_int_t index, mp_obj_t val) {
STATIC mp_obj_t uctypes_struct_attr_op(mp_obj_t self_in, qstr attr, mp_obj_t set_val) {
mp_obj_uctypes_struct_t *self = MP_OBJ_TO_PTR(self_in);
- if (!mp_obj_is_type(self->desc, &mp_type_dict)
- #if MICROPY_PY_COLLECTIONS_ORDEREDDICT
- && !mp_obj_is_type(self->desc, &mp_type_ordereddict)
- #endif
- ) {
- mp_raise_TypeError("struct: no fields");
+ if (!mp_obj_is_dict_or_ordereddict(self->desc)) {
+ mp_raise_TypeError(MP_ERROR_TEXT("struct: no fields"));
}
mp_obj_t deref = mp_obj_dict_get(self->desc, MP_OBJ_NEW_QSTR(attr));
@@ -419,7 +419,7 @@ STATIC mp_obj_t uctypes_struct_attr_op(mp_obj_t self_in, qstr attr, mp_obj_t set
mp_int_t offset = MP_OBJ_SMALL_INT_VALUE(deref);
mp_uint_t val_type = GET_TYPE(offset, VAL_TYPE_BITS);
offset &= VALUE_MASK(VAL_TYPE_BITS);
-//printf("scalar type=%d offset=%x\n", val_type, offset);
+// printf("scalar type=%d offset=%x\n", val_type, offset);
if (val_type <= INT64 || val_type == FLOAT32 || val_type == FLOAT64) {
// printf("size=%d\n", GET_SCALAR_SIZE(val_type));
@@ -489,7 +489,7 @@ STATIC mp_obj_t uctypes_struct_attr_op(mp_obj_t self_in, qstr attr, mp_obj_t set
mp_int_t offset = MP_OBJ_SMALL_INT_VALUE(sub->items[0]);
mp_uint_t agg_type = GET_TYPE(offset, AGG_TYPE_BITS);
offset &= VALUE_MASK(AGG_TYPE_BITS);
-//printf("agg type=%d offset=%x\n", agg_type, offset);
+// printf("agg type=%d offset=%x\n", agg_type, offset);
switch (agg_type) {
case STRUCT: {
@@ -513,7 +513,7 @@ STATIC mp_obj_t uctypes_struct_attr_op(mp_obj_t self_in, qstr attr, mp_obj_t set
o->desc = MP_OBJ_FROM_PTR(sub);
o->addr = self->addr + offset;
o->flags = self->flags;
-//printf("PTR/ARR base addr=%p\n", o->addr);
+// printf("PTR/ARR base addr=%p\n", o->addr);
return MP_OBJ_FROM_PTR(o);
}
}
@@ -544,7 +544,7 @@ STATIC mp_obj_t uctypes_struct_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_ob
} else {
// load / store
if (!mp_obj_is_type(self->desc, &mp_type_tuple)) {
- mp_raise_TypeError("struct: cannot index");
+ mp_raise_TypeError(MP_ERROR_TEXT("struct: can't index"));
}
mp_obj_tuple_t *t = MP_OBJ_TO_PTR(self->desc);
@@ -558,7 +558,7 @@ STATIC mp_obj_t uctypes_struct_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_ob
uint val_type = GET_TYPE(arr_sz, VAL_TYPE_BITS);
arr_sz &= VALUE_MASK(VAL_TYPE_BITS);
if (index >= arr_sz) {
- nlr_raise(mp_obj_new_exception_msg(&mp_type_IndexError, "struct: index out of range"));
+ mp_raise_msg(&mp_type_IndexError, MP_ERROR_TEXT("struct: index out of range"));
}
if (t->len == 2) {
@@ -593,7 +593,7 @@ STATIC mp_obj_t uctypes_struct_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_ob
}
} else if (agg_type == PTR) {
- byte *p = *(void**)self->addr;
+ byte *p = *(void **)self->addr;
if (mp_obj_is_small_int(t->items[1])) {
uint val_type = GET_TYPE(MP_OBJ_SMALL_INT_VALUE(t->items[1]), VAL_TYPE_BITS);
return get_aligned(val_type, p, index);
@@ -623,13 +623,14 @@ STATIC mp_obj_t uctypes_struct_unary_op(mp_unary_op_t op, mp_obj_t self_in) {
mp_int_t offset = MP_OBJ_SMALL_INT_VALUE(t->items[0]);
uint agg_type = GET_TYPE(offset, AGG_TYPE_BITS);
if (agg_type == PTR) {
- byte *p = *(void**)self->addr;
+ byte *p = *(void **)self->addr;
return mp_obj_new_int((mp_int_t)(uintptr_t)p);
}
}
- /* fallthru */
+ /* fallthru */
- default: return MP_OBJ_NULL; // op not supported
+ default:
+ return MP_OBJ_NULL; // op not supported
}
}
@@ -660,7 +661,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(uctypes_struct_addressof_obj, uctypes_struct_addressof
/// captured by reference (and thus memory pointed by bytearray may change
/// or become invalid at later time). Use bytes_at() to capture by value.
STATIC mp_obj_t uctypes_struct_bytearray_at(mp_obj_t ptr, mp_obj_t size) {
- return mp_obj_new_bytearray_by_ref(mp_obj_int_get_truncated(size), (void*)(uintptr_t)mp_obj_int_get_truncated(ptr));
+ return mp_obj_new_bytearray_by_ref(mp_obj_int_get_truncated(size), (void *)(uintptr_t)mp_obj_int_get_truncated(ptr));
}
MP_DEFINE_CONST_FUN_OBJ_2(uctypes_struct_bytearray_at_obj, uctypes_struct_bytearray_at);
@@ -669,7 +670,7 @@ MP_DEFINE_CONST_FUN_OBJ_2(uctypes_struct_bytearray_at_obj, uctypes_struct_bytear
/// captured by value, i.e. copied. Use bytearray_at() to capture by reference
/// ("zero copy").
STATIC mp_obj_t uctypes_struct_bytes_at(mp_obj_t ptr, mp_obj_t size) {
- return mp_obj_new_bytes((void*)(uintptr_t)mp_obj_int_get_truncated(ptr), mp_obj_int_get_truncated(size));
+ return mp_obj_new_bytes((void *)(uintptr_t)mp_obj_int_get_truncated(ptr), mp_obj_int_get_truncated(size));
}
MP_DEFINE_CONST_FUN_OBJ_2(uctypes_struct_bytes_at_obj, uctypes_struct_bytes_at);
@@ -772,7 +773,7 @@ STATIC MP_DEFINE_CONST_DICT(mp_module_uctypes_globals, mp_module_uctypes_globals
const mp_obj_module_t mp_module_uctypes = {
.base = { &mp_type_module },
- .globals = (mp_obj_dict_t*)&mp_module_uctypes_globals,
+ .globals = (mp_obj_dict_t *)&mp_module_uctypes_globals,
};
#endif
diff --git a/extmod/moduhashlib.c b/extmod/moduhashlib.c
index 603cdb44a4..195a24334b 100644
--- a/extmod/moduhashlib.c
+++ b/extmod/moduhashlib.c
@@ -78,8 +78,8 @@ STATIC mp_obj_t uhashlib_sha256_make_new(const mp_obj_type_t *type, size_t n_arg
mp_arg_check_num(n_args, n_kw, 0, 1, false);
mp_obj_hash_t *o = m_new_obj_var(mp_obj_hash_t, char, sizeof(mbedtls_sha256_context));
o->base.type = type;
- mbedtls_sha256_init((mbedtls_sha256_context*)&o->state);
- mbedtls_sha256_starts_ret((mbedtls_sha256_context*)&o->state, 0);
+ mbedtls_sha256_init((mbedtls_sha256_context *)&o->state);
+ mbedtls_sha256_starts_ret((mbedtls_sha256_context *)&o->state, 0);
if (n_args == 1) {
uhashlib_sha256_update(MP_OBJ_FROM_PTR(o), args[0]);
}
@@ -90,7 +90,7 @@ STATIC mp_obj_t uhashlib_sha256_update(mp_obj_t self_in, mp_obj_t arg) {
mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in);
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(arg, &bufinfo, MP_BUFFER_READ);
- mbedtls_sha256_update_ret((mbedtls_sha256_context*)&self->state, bufinfo.buf, bufinfo.len);
+ mbedtls_sha256_update_ret((mbedtls_sha256_context *)&self->state, bufinfo.buf, bufinfo.len);
return mp_const_none;
}
@@ -98,7 +98,7 @@ STATIC mp_obj_t uhashlib_sha256_digest(mp_obj_t self_in) {
mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in);
vstr_t vstr;
vstr_init_len(&vstr, 32);
- mbedtls_sha256_finish_ret((mbedtls_sha256_context*)&self->state, (unsigned char *)vstr.buf);
+ mbedtls_sha256_finish_ret((mbedtls_sha256_context *)&self->state, (unsigned char *)vstr.buf);
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
}
@@ -110,7 +110,7 @@ STATIC mp_obj_t uhashlib_sha256_make_new(const mp_obj_type_t *type, size_t n_arg
mp_arg_check_num(n_args, n_kw, 0, 1, false);
mp_obj_hash_t *o = m_new_obj_var(mp_obj_hash_t, char, sizeof(CRYAL_SHA256_CTX));
o->base.type = type;
- sha256_init((CRYAL_SHA256_CTX*)o->state);
+ sha256_init((CRYAL_SHA256_CTX *)o->state);
if (n_args == 1) {
uhashlib_sha256_update(MP_OBJ_FROM_PTR(o), args[0]);
}
@@ -121,7 +121,7 @@ STATIC mp_obj_t uhashlib_sha256_update(mp_obj_t self_in, mp_obj_t arg) {
mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in);
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(arg, &bufinfo, MP_BUFFER_READ);
- sha256_update((CRYAL_SHA256_CTX*)self->state, bufinfo.buf, bufinfo.len);
+ sha256_update((CRYAL_SHA256_CTX *)self->state, bufinfo.buf, bufinfo.len);
return mp_const_none;
}
@@ -129,7 +129,7 @@ STATIC mp_obj_t uhashlib_sha256_digest(mp_obj_t self_in) {
mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in);
vstr_t vstr;
vstr_init_len(&vstr, SHA256_BLOCK_SIZE);
- sha256_final((CRYAL_SHA256_CTX*)self->state, (byte*)vstr.buf);
+ sha256_final((CRYAL_SHA256_CTX *)self->state, (byte *)vstr.buf);
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
}
#endif
@@ -148,7 +148,7 @@ STATIC const mp_obj_type_t uhashlib_sha256_type = {
{ &mp_type_type },
.name = MP_QSTR_sha256,
.make_new = uhashlib_sha256_make_new,
- .locals_dict = (void*)&uhashlib_sha256_locals_dict,
+ .locals_dict = (void *)&uhashlib_sha256_locals_dict,
};
#endif
@@ -160,7 +160,7 @@ STATIC mp_obj_t uhashlib_sha1_make_new(const mp_obj_type_t *type, size_t n_args,
mp_arg_check_num(n_args, n_kw, 0, 1, false);
mp_obj_hash_t *o = m_new_obj_var(mp_obj_hash_t, char, sizeof(SHA1_CTX));
o->base.type = type;
- SHA1_Init((SHA1_CTX*)o->state);
+ SHA1_Init((SHA1_CTX *)o->state);
if (n_args == 1) {
uhashlib_sha1_update(MP_OBJ_FROM_PTR(o), args[0]);
}
@@ -171,7 +171,7 @@ STATIC mp_obj_t uhashlib_sha1_update(mp_obj_t self_in, mp_obj_t arg) {
mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in);
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(arg, &bufinfo, MP_BUFFER_READ);
- SHA1_Update((SHA1_CTX*)self->state, bufinfo.buf, bufinfo.len);
+ SHA1_Update((SHA1_CTX *)self->state, bufinfo.buf, bufinfo.len);
return mp_const_none;
}
@@ -179,7 +179,7 @@ STATIC mp_obj_t uhashlib_sha1_digest(mp_obj_t self_in) {
mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in);
vstr_t vstr;
vstr_init_len(&vstr, SHA1_SIZE);
- SHA1_Final((byte*)vstr.buf, (SHA1_CTX*)self->state);
+ SHA1_Final((byte *)vstr.buf, (SHA1_CTX *)self->state);
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
}
#endif
@@ -196,8 +196,8 @@ STATIC mp_obj_t uhashlib_sha1_make_new(const mp_obj_type_t *type, size_t n_args,
mp_arg_check_num(n_args, n_kw, 0, 1, false);
mp_obj_hash_t *o = m_new_obj_var(mp_obj_hash_t, char, sizeof(mbedtls_sha1_context));
o->base.type = type;
- mbedtls_sha1_init((mbedtls_sha1_context*)o->state);
- mbedtls_sha1_starts_ret((mbedtls_sha1_context*)o->state);
+ mbedtls_sha1_init((mbedtls_sha1_context *)o->state);
+ mbedtls_sha1_starts_ret((mbedtls_sha1_context *)o->state);
if (n_args == 1) {
uhashlib_sha1_update(MP_OBJ_FROM_PTR(o), args[0]);
}
@@ -208,7 +208,7 @@ STATIC mp_obj_t uhashlib_sha1_update(mp_obj_t self_in, mp_obj_t arg) {
mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in);
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(arg, &bufinfo, MP_BUFFER_READ);
- mbedtls_sha1_update_ret((mbedtls_sha1_context*)self->state, bufinfo.buf, bufinfo.len);
+ mbedtls_sha1_update_ret((mbedtls_sha1_context *)self->state, bufinfo.buf, bufinfo.len);
return mp_const_none;
}
@@ -216,8 +216,8 @@ STATIC mp_obj_t uhashlib_sha1_digest(mp_obj_t self_in) {
mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in);
vstr_t vstr;
vstr_init_len(&vstr, 20);
- mbedtls_sha1_finish_ret((mbedtls_sha1_context*)self->state, (byte*)vstr.buf);
- mbedtls_sha1_free((mbedtls_sha1_context*)self->state);
+ mbedtls_sha1_finish_ret((mbedtls_sha1_context *)self->state, (byte *)vstr.buf);
+ mbedtls_sha1_free((mbedtls_sha1_context *)self->state);
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
}
#endif
@@ -235,7 +235,7 @@ STATIC const mp_obj_type_t uhashlib_sha1_type = {
{ &mp_type_type },
.name = MP_QSTR_sha1,
.make_new = uhashlib_sha1_make_new,
- .locals_dict = (void*)&uhashlib_sha1_locals_dict,
+ .locals_dict = (void *)&uhashlib_sha1_locals_dict,
};
#endif
@@ -247,7 +247,7 @@ STATIC mp_obj_t uhashlib_md5_make_new(const mp_obj_type_t *type, size_t n_args,
mp_arg_check_num(n_args, n_kw, 0, 1, false);
mp_obj_hash_t *o = m_new_obj_var(mp_obj_hash_t, char, sizeof(MD5_CTX));
o->base.type = type;
- MD5_Init((MD5_CTX*)o->state);
+ MD5_Init((MD5_CTX *)o->state);
if (n_args == 1) {
uhashlib_md5_update(MP_OBJ_FROM_PTR(o), args[0]);
}
@@ -258,7 +258,7 @@ STATIC mp_obj_t uhashlib_md5_update(mp_obj_t self_in, mp_obj_t arg) {
mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in);
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(arg, &bufinfo, MP_BUFFER_READ);
- MD5_Update((MD5_CTX*)self->state, bufinfo.buf, bufinfo.len);
+ MD5_Update((MD5_CTX *)self->state, bufinfo.buf, bufinfo.len);
return mp_const_none;
}
@@ -266,7 +266,7 @@ STATIC mp_obj_t uhashlib_md5_digest(mp_obj_t self_in) {
mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in);
vstr_t vstr;
vstr_init_len(&vstr, MD5_SIZE);
- MD5_Final((byte*)vstr.buf, (MD5_CTX*)self->state);
+ MD5_Final((byte *)vstr.buf, (MD5_CTX *)self->state);
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
}
#endif // MICROPY_SSL_AXTLS
@@ -283,8 +283,8 @@ STATIC mp_obj_t uhashlib_md5_make_new(const mp_obj_type_t *type, size_t n_args,
mp_arg_check_num(n_args, n_kw, 0, 1, false);
mp_obj_hash_t *o = m_new_obj_var(mp_obj_hash_t, char, sizeof(mbedtls_md5_context));
o->base.type = type;
- mbedtls_md5_init((mbedtls_md5_context*)o->state);
- mbedtls_md5_starts_ret((mbedtls_md5_context*)o->state);
+ mbedtls_md5_init((mbedtls_md5_context *)o->state);
+ mbedtls_md5_starts_ret((mbedtls_md5_context *)o->state);
if (n_args == 1) {
uhashlib_md5_update(MP_OBJ_FROM_PTR(o), args[0]);
}
@@ -295,7 +295,7 @@ STATIC mp_obj_t uhashlib_md5_update(mp_obj_t self_in, mp_obj_t arg) {
mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in);
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(arg, &bufinfo, MP_BUFFER_READ);
- mbedtls_md5_update_ret((mbedtls_md5_context*)self->state, bufinfo.buf, bufinfo.len);
+ mbedtls_md5_update_ret((mbedtls_md5_context *)self->state, bufinfo.buf, bufinfo.len);
return mp_const_none;
}
@@ -303,8 +303,8 @@ STATIC mp_obj_t uhashlib_md5_digest(mp_obj_t self_in) {
mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in);
vstr_t vstr;
vstr_init_len(&vstr, 16);
- mbedtls_md5_finish_ret((mbedtls_md5_context*)self->state, (byte*)vstr.buf);
- mbedtls_md5_free((mbedtls_md5_context*)self->state);
+ mbedtls_md5_finish_ret((mbedtls_md5_context *)self->state, (byte *)vstr.buf);
+ mbedtls_md5_free((mbedtls_md5_context *)self->state);
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
}
#endif // MICROPY_SSL_MBEDTLS
@@ -322,7 +322,7 @@ STATIC const mp_obj_type_t uhashlib_md5_type = {
{ &mp_type_type },
.name = MP_QSTR_md5,
.make_new = uhashlib_md5_make_new,
- .locals_dict = (void*)&uhashlib_md5_locals_dict,
+ .locals_dict = (void *)&uhashlib_md5_locals_dict,
};
#endif // MICROPY_PY_UHASHLIB_MD5
@@ -343,7 +343,7 @@ STATIC MP_DEFINE_CONST_DICT(mp_module_uhashlib_globals, mp_module_uhashlib_globa
const mp_obj_module_t mp_module_uhashlib = {
.base = { &mp_type_module },
- .globals = (mp_obj_dict_t*)&mp_module_uhashlib_globals,
+ .globals = (mp_obj_dict_t *)&mp_module_uhashlib_globals,
};
-#endif //MICROPY_PY_UHASHLIB
+#endif // MICROPY_PY_UHASHLIB
diff --git a/extmod/moduheapq.c b/extmod/moduheapq.c
index bdaf191e94..073ce516b9 100644
--- a/extmod/moduheapq.c
+++ b/extmod/moduheapq.c
@@ -31,14 +31,14 @@
// the algorithm here is modelled on CPython's heapq.py
-STATIC mp_obj_list_t *get_heap(mp_obj_t heap_in) {
+STATIC mp_obj_list_t *uheapq_get_heap(mp_obj_t heap_in) {
if (!mp_obj_is_type(heap_in, &mp_type_list)) {
- mp_raise_TypeError("heap must be a list");
+ mp_raise_TypeError(MP_ERROR_TEXT("heap must be a list"));
}
return MP_OBJ_TO_PTR(heap_in);
}
-STATIC void heap_siftdown(mp_obj_list_t *heap, mp_uint_t start_pos, mp_uint_t pos) {
+STATIC void uheapq_heap_siftdown(mp_obj_list_t *heap, mp_uint_t start_pos, mp_uint_t pos) {
mp_obj_t item = heap->items[pos];
while (pos > start_pos) {
mp_uint_t parent_pos = (pos - 1) >> 1;
@@ -53,7 +53,7 @@ STATIC void heap_siftdown(mp_obj_list_t *heap, mp_uint_t start_pos, mp_uint_t po
heap->items[pos] = item;
}
-STATIC void heap_siftup(mp_obj_list_t *heap, mp_uint_t pos) {
+STATIC void uheapq_heap_siftup(mp_obj_list_t *heap, mp_uint_t pos) {
mp_uint_t start_pos = pos;
mp_uint_t end_pos = heap->len;
mp_obj_t item = heap->items[pos];
@@ -67,42 +67,43 @@ STATIC void heap_siftup(mp_obj_list_t *heap, mp_uint_t pos) {
pos = child_pos;
}
heap->items[pos] = item;
- heap_siftdown(heap, start_pos, pos);
+ uheapq_heap_siftdown(heap, start_pos, pos);
}
STATIC mp_obj_t mod_uheapq_heappush(mp_obj_t heap_in, mp_obj_t item) {
- mp_obj_list_t *heap = get_heap(heap_in);
+ mp_obj_list_t *heap = uheapq_get_heap(heap_in);
mp_obj_list_append(heap_in, item);
- heap_siftdown(heap, 0, heap->len - 1);
+ uheapq_heap_siftdown(heap, 0, heap->len - 1);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_uheapq_heappush_obj, mod_uheapq_heappush);
STATIC mp_obj_t mod_uheapq_heappop(mp_obj_t heap_in) {
- mp_obj_list_t *heap = get_heap(heap_in);
+ mp_obj_list_t *heap = uheapq_get_heap(heap_in);
if (heap->len == 0) {
- nlr_raise(mp_obj_new_exception_msg(&mp_type_IndexError, "empty heap"));
+ mp_raise_msg(&mp_type_IndexError, MP_ERROR_TEXT("empty heap"));
}
mp_obj_t item = heap->items[0];
heap->len -= 1;
heap->items[0] = heap->items[heap->len];
heap->items[heap->len] = MP_OBJ_NULL; // so we don't retain a pointer
if (heap->len) {
- heap_siftup(heap, 0);
+ uheapq_heap_siftup(heap, 0);
}
return item;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_uheapq_heappop_obj, mod_uheapq_heappop);
STATIC mp_obj_t mod_uheapq_heapify(mp_obj_t heap_in) {
- mp_obj_list_t *heap = get_heap(heap_in);
+ mp_obj_list_t *heap = uheapq_get_heap(heap_in);
for (mp_uint_t i = heap->len / 2; i > 0;) {
- heap_siftup(heap, --i);
+ uheapq_heap_siftup(heap, --i);
}
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_uheapq_heapify_obj, mod_uheapq_heapify);
+#if !MICROPY_ENABLE_DYNRUNTIME
STATIC const mp_rom_map_elem_t mp_module_uheapq_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uheapq) },
{ MP_ROM_QSTR(MP_QSTR_heappush), MP_ROM_PTR(&mod_uheapq_heappush_obj) },
@@ -114,7 +115,8 @@ STATIC MP_DEFINE_CONST_DICT(mp_module_uheapq_globals, mp_module_uheapq_globals_t
const mp_obj_module_t mp_module_uheapq = {
.base = { &mp_type_module },
- .globals = (mp_obj_dict_t*)&mp_module_uheapq_globals,
+ .globals = (mp_obj_dict_t *)&mp_module_uheapq_globals,
};
+#endif
-#endif //MICROPY_PY_UHEAPQ
+#endif // MICROPY_PY_UHEAPQ
diff --git a/extmod/modujson.c b/extmod/modujson.c
index f5c6428ef9..8dff673580 100644
--- a/extmod/modujson.c
+++ b/extmod/modujson.c
@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2014-2016 Damien P. George
+ * Copyright (c) 2014-2019 Damien P. George
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -96,11 +96,11 @@ STATIC mp_obj_t mod_ujson_load(mp_obj_t stream_obj) {
stack.len = 0;
stack.items = NULL;
mp_obj_t stack_top = MP_OBJ_NULL;
- mp_obj_type_t *stack_top_type = NULL;
+ const mp_obj_type_t *stack_top_type = NULL;
mp_obj_t stack_key = MP_OBJ_NULL;
S_NEXT(s);
for (;;) {
- cont:
+ cont:
if (S_END(s)) {
break;
}
@@ -147,11 +147,21 @@ STATIC mp_obj_t mod_ujson_load(mp_obj_t stream_obj) {
if (c == '\\') {
c = S_NEXT(s);
switch (c) {
- case 'b': c = 0x08; break;
- case 'f': c = 0x0c; break;
- case 'n': c = 0x0a; break;
- case 'r': c = 0x0d; break;
- case 't': c = 0x09; break;
+ case 'b':
+ c = 0x08;
+ break;
+ case 'f':
+ c = 0x0c;
+ break;
+ case 'n':
+ c = 0x0a;
+ break;
+ case 'r':
+ c = 0x0d;
+ break;
+ case 't':
+ c = 0x09;
+ break;
case 'u': {
mp_uint_t num = 0;
for (int i = 0; i < 4; i++) {
@@ -177,7 +187,16 @@ STATIC mp_obj_t mod_ujson_load(mp_obj_t stream_obj) {
next = mp_obj_new_str(vstr.buf, vstr.len);
break;
case '-':
- case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9': {
bool flt = false;
vstr_reset(&vstr);
for (;;) {
@@ -259,7 +278,7 @@ STATIC mp_obj_t mod_ujson_load(mp_obj_t stream_obj) {
}
}
}
- success:
+success:
// eat trailing whitespace
while (unichar_isspace(S_CUR(s))) {
S_NEXT(s);
@@ -275,15 +294,15 @@ STATIC mp_obj_t mod_ujson_load(mp_obj_t stream_obj) {
vstr_clear(&vstr);
return stack_top;
- fail:
- mp_raise_ValueError("syntax error in JSON");
+fail:
+ mp_raise_ValueError(MP_ERROR_TEXT("syntax error in JSON"));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_ujson_load_obj, mod_ujson_load);
STATIC mp_obj_t mod_ujson_loads(mp_obj_t obj) {
- size_t len;
- const char *buf = mp_obj_str_get_data(obj, &len);
- vstr_t vstr = {len, len, (char*)buf, true};
+ mp_buffer_info_t bufinfo;
+ mp_get_buffer_raise(obj, &bufinfo, MP_BUFFER_READ);
+ vstr_t vstr = {bufinfo.len, bufinfo.len, (char *)bufinfo.buf, true};
mp_obj_stringio_t sio = {{&mp_type_stringio}, &vstr, 0, MP_OBJ_NULL};
return mod_ujson_load(MP_OBJ_FROM_PTR(&sio));
}
@@ -301,7 +320,7 @@ STATIC MP_DEFINE_CONST_DICT(mp_module_ujson_globals, mp_module_ujson_globals_tab
const mp_obj_module_t mp_module_ujson = {
.base = { &mp_type_module },
- .globals = (mp_obj_dict_t*)&mp_module_ujson_globals,
+ .globals = (mp_obj_dict_t *)&mp_module_ujson_globals,
};
-#endif //MICROPY_PY_UJSON
+#endif // MICROPY_PY_UJSON
diff --git a/extmod/modurandom.c b/extmod/modurandom.c
index 2e667570d6..ab83b0f701 100644
--- a/extmod/modurandom.c
+++ b/extmod/modurandom.c
@@ -36,18 +36,19 @@
// http://www.literatecode.com/yasmarang
// Public Domain
+#if !MICROPY_ENABLE_DYNRUNTIME
STATIC uint32_t yasmarang_pad = 0xeda4baba, yasmarang_n = 69, yasmarang_d = 233;
STATIC uint8_t yasmarang_dat = 0;
+#endif
-STATIC uint32_t yasmarang(void)
-{
- yasmarang_pad += yasmarang_dat + yasmarang_d * yasmarang_n;
- yasmarang_pad = (yasmarang_pad<<3) + (yasmarang_pad>>29);
- yasmarang_n = yasmarang_pad | 2;
- yasmarang_d ^= (yasmarang_pad<<31) + (yasmarang_pad>>1);
- yasmarang_dat ^= (char) yasmarang_pad ^ (yasmarang_d>>8) ^ 1;
+STATIC uint32_t yasmarang(void) {
+ yasmarang_pad += yasmarang_dat + yasmarang_d * yasmarang_n;
+ yasmarang_pad = (yasmarang_pad << 3) + (yasmarang_pad >> 29);
+ yasmarang_n = yasmarang_pad | 2;
+ yasmarang_d ^= (yasmarang_pad << 31) + (yasmarang_pad >> 1);
+ yasmarang_dat ^= (char)yasmarang_pad ^ (yasmarang_d >> 8) ^ 1;
- return (yasmarang_pad^(yasmarang_d<<5)^(yasmarang_pad>>18)^(yasmarang_dat<<1));
+ return yasmarang_pad ^ (yasmarang_d << 5) ^ (yasmarang_pad >> 18) ^ (yasmarang_dat << 1);
} /* yasmarang */
// End of Yasmarang
@@ -152,7 +153,7 @@ STATIC mp_obj_t mod_urandom_choice(mp_obj_t seq) {
if (len > 0) {
return mp_obj_subscr(seq, mp_obj_new_int(yasmarang_randbelow(len)), MP_OBJ_SENTINEL);
} else {
- nlr_raise(mp_obj_new_exception(&mp_type_IndexError));
+ mp_raise_type(&mp_type_IndexError);
}
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_urandom_choice_obj, mod_urandom_choice);
@@ -161,19 +162,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_urandom_choice_obj, mod_urandom_choice);
// returns a number in the range [0..1) using Yasmarang to fill in the fraction bits
STATIC mp_float_t yasmarang_float(void) {
- #if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE
- typedef uint64_t mp_float_int_t;
- #elif MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT
- typedef uint32_t mp_float_int_t;
- #endif
- union {
- mp_float_t f;
- #if MP_ENDIANNESS_LITTLE
- struct { mp_float_int_t frc:MP_FLOAT_FRAC_BITS, exp:MP_FLOAT_EXP_BITS, sgn:1; } p;
- #else
- struct { mp_float_int_t sgn:1, exp:MP_FLOAT_EXP_BITS, frc:MP_FLOAT_FRAC_BITS; } p;
- #endif
- } u;
+ mp_float_union_t u;
u.p.sgn = 0;
u.p.exp = (1 << (MP_FLOAT_EXP_BITS - 1)) - 1;
if (MP_FLOAT_FRAC_BITS <= 32) {
@@ -208,6 +197,7 @@ STATIC mp_obj_t mod_urandom___init__() {
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_urandom___init___obj, mod_urandom___init__);
#endif
+#if !MICROPY_ENABLE_DYNRUNTIME
STATIC const mp_rom_map_elem_t mp_module_urandom_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_urandom) },
#ifdef MICROPY_PY_URANDOM_SEED_INIT_FUNC
@@ -230,7 +220,8 @@ STATIC MP_DEFINE_CONST_DICT(mp_module_urandom_globals, mp_module_urandom_globals
const mp_obj_module_t mp_module_urandom = {
.base = { &mp_type_module },
- .globals = (mp_obj_dict_t*)&mp_module_urandom_globals,
+ .globals = (mp_obj_dict_t *)&mp_module_urandom_globals,
};
+#endif
-#endif //MICROPY_PY_URANDOM
+#endif // MICROPY_PY_URANDOM
diff --git a/extmod/modure.c b/extmod/modure.c
index 0d5330cb54..328c897d88 100644
--- a/extmod/modure.c
+++ b/extmod/modure.c
@@ -53,6 +53,10 @@ typedef struct _mp_obj_match_t {
const char *caps[0];
} mp_obj_match_t;
+STATIC mp_obj_t mod_re_compile(size_t n_args, const mp_obj_t *args);
+#if !MICROPY_ENABLE_DYNRUNTIME
+STATIC const mp_obj_type_t re_type;
+#endif
STATIC void match_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
(void)kind;
@@ -73,7 +77,7 @@ STATIC mp_obj_t match_group(mp_obj_t self_in, mp_obj_t no_in) {
return mp_const_none;
}
return mp_obj_new_str_of_type(mp_obj_get_type(self->str),
- (const byte*)start, self->caps[no * 2 + 1] - start);
+ (const byte *)start, self->caps[no * 2 + 1] - start);
}
MP_DEFINE_CONST_FUN_OBJ_2(match_group_obj, match_group);
@@ -144,6 +148,7 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(match_end_obj, 1, 2, match_end);
#endif
+#if !MICROPY_ENABLE_DYNRUNTIME
STATIC const mp_rom_map_elem_t match_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_group), MP_ROM_PTR(&match_group_obj) },
#if MICROPY_PY_URE_MATCH_GROUPS
@@ -162,8 +167,9 @@ STATIC const mp_obj_type_t match_type = {
{ &mp_type_type },
.name = MP_QSTR_match,
.print = match_print,
- .locals_dict = (void*)&match_locals_dict,
+ .locals_dict = (void *)&match_locals_dict,
};
+#endif
STATIC void re_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
(void)kind;
@@ -173,18 +179,23 @@ STATIC void re_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t
STATIC mp_obj_t ure_exec(bool is_anchored, uint n_args, const mp_obj_t *args) {
(void)n_args;
- mp_obj_re_t *self = MP_OBJ_TO_PTR(args[0]);
+ mp_obj_re_t *self;
+ if (mp_obj_is_type(args[0], &re_type)) {
+ self = MP_OBJ_TO_PTR(args[0]);
+ } else {
+ self = MP_OBJ_TO_PTR(mod_re_compile(1, args));
+ }
Subject subj;
size_t len;
subj.begin = mp_obj_str_get_data(args[1], &len);
subj.end = subj.begin + len;
int caps_num = (self->re.sub + 1) * 2;
- mp_obj_match_t *match = m_new_obj_var(mp_obj_match_t, char*, caps_num);
+ mp_obj_match_t *match = m_new_obj_var(mp_obj_match_t, char *, caps_num);
// cast is a workaround for a bug in msvc: it treats const char** as a const pointer instead of a pointer to pointer to const char
- memset((char*)match->caps, 0, caps_num * sizeof(char*));
+ memset((char *)match->caps, 0, caps_num * sizeof(char *));
int res = re1_5_recursiveloopprog(&self->re, &subj, match->caps, caps_num, is_anchored);
if (res == 0) {
- m_del_var(mp_obj_match_t, char*, caps_num, match);
+ m_del_var(mp_obj_match_t, char *, caps_num, match);
return mp_const_none;
}
@@ -219,10 +230,10 @@ STATIC mp_obj_t re_split(size_t n_args, const mp_obj_t *args) {
}
mp_obj_t retval = mp_obj_new_list(0, NULL);
- const char **caps = mp_local_alloc(caps_num * sizeof(char*));
+ const char **caps = mp_local_alloc(caps_num * sizeof(char *));
while (true) {
// cast is a workaround for a bug in msvc: it treats const char** as a const pointer instead of a pointer to pointer to const char
- memset((char**)caps, 0, caps_num * sizeof(char*));
+ memset((char **)caps, 0, caps_num * sizeof(char *));
int res = re1_5_recursiveloopprog(&self->re, &subj, caps, caps_num, false);
// if we didn't have a match, or had an empty match, it's time to stop
@@ -230,10 +241,10 @@ STATIC mp_obj_t re_split(size_t n_args, const mp_obj_t *args) {
break;
}
- mp_obj_t s = mp_obj_new_str_of_type(str_type, (const byte*)subj.begin, caps[0] - subj.begin);
+ mp_obj_t s = mp_obj_new_str_of_type(str_type, (const byte *)subj.begin, caps[0] - subj.begin);
mp_obj_list_append(retval, s);
if (self->re.sub > 0) {
- mp_raise_NotImplementedError("Splitting with sub-captures");
+ mp_raise_NotImplementedError(MP_ERROR_TEXT("splitting with sub-captures"));
}
subj.begin = caps[1];
if (maxsplit > 0 && --maxsplit == 0) {
@@ -241,9 +252,9 @@ STATIC mp_obj_t re_split(size_t n_args, const mp_obj_t *args) {
}
}
// cast is a workaround for a bug in msvc (see above)
- mp_local_free((char**)caps);
+ mp_local_free((char **)caps);
- mp_obj_t s = mp_obj_new_str_of_type(str_type, (const byte*)subj.begin, subj.end - subj.begin);
+ mp_obj_t s = mp_obj_new_str_of_type(str_type, (const byte *)subj.begin, subj.end - subj.begin);
mp_obj_list_append(retval, s);
return retval;
}
@@ -251,8 +262,13 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(re_split_obj, 2, 3, re_split);
#if MICROPY_PY_URE_SUB
-STATIC mp_obj_t re_sub_helper(mp_obj_t self_in, size_t n_args, const mp_obj_t *args) {
- mp_obj_re_t *self = MP_OBJ_TO_PTR(self_in);
+STATIC mp_obj_t re_sub_helper(size_t n_args, const mp_obj_t *args) {
+ mp_obj_re_t *self;
+ if (mp_obj_is_type(args[0], &re_type)) {
+ self = MP_OBJ_TO_PTR(args[0]);
+ } else {
+ self = MP_OBJ_TO_PTR(mod_re_compile(1, args));
+ }
mp_obj_t replace = args[1];
mp_obj_t where = args[2];
mp_int_t count = 0;
@@ -270,14 +286,14 @@ STATIC mp_obj_t re_sub_helper(mp_obj_t self_in, size_t n_args, const mp_obj_t *a
vstr_t vstr_return;
vstr_return.buf = NULL; // We'll init the vstr after the first match
- mp_obj_match_t *match = mp_local_alloc(sizeof(mp_obj_match_t) + caps_num * sizeof(char*));
+ mp_obj_match_t *match = mp_local_alloc(sizeof(mp_obj_match_t) + caps_num * sizeof(char *));
match->base.type = &match_type;
match->num_matches = caps_num / 2; // caps_num counts start and end pointers
match->str = where;
for (;;) {
// cast is a workaround for a bug in msvc: it treats const char** as a const pointer instead of a pointer to pointer to const char
- memset((char*)match->caps, 0, caps_num * sizeof(char*));
+ memset((char *)match->caps, 0, caps_num * sizeof(char *));
int res = re1_5_recursiveloopprog(&self->re, &subj, match->caps, caps_num, false);
// If we didn't have a match, or had an empty match, it's time to stop
@@ -294,7 +310,7 @@ STATIC mp_obj_t re_sub_helper(mp_obj_t self_in, size_t n_args, const mp_obj_t *a
vstr_add_strn(&vstr_return, subj.begin, match->caps[0] - subj.begin);
// Get replacement string
- const char* repl = mp_obj_str_get_str((mp_obj_is_callable(replace) ? mp_call_function_1(replace, MP_OBJ_FROM_PTR(match)) : replace));
+ const char *repl = mp_obj_str_get_str((mp_obj_is_callable(replace) ? mp_call_function_1(replace, MP_OBJ_FROM_PTR(match)) : replace));
// Append replacement string to result, substituting any regex groups
while (*repl != '\0') {
@@ -356,13 +372,11 @@ STATIC mp_obj_t re_sub_helper(mp_obj_t self_in, size_t n_args, const mp_obj_t *a
return mp_obj_new_str_from_vstr(mp_obj_get_type(where), &vstr_return);
}
-STATIC mp_obj_t re_sub(size_t n_args, const mp_obj_t *args) {
- return re_sub_helper(args[0], n_args, args);
-}
-MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(re_sub_obj, 3, 5, re_sub);
+MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(re_sub_obj, 3, 5, re_sub_helper);
#endif
+#if !MICROPY_ENABLE_DYNRUNTIME
STATIC const mp_rom_map_elem_t re_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_match), MP_ROM_PTR(&re_match_obj) },
{ MP_ROM_QSTR(MP_QSTR_search), MP_ROM_PTR(&re_search_obj) },
@@ -378,10 +392,12 @@ STATIC const mp_obj_type_t re_type = {
{ &mp_type_type },
.name = MP_QSTR_ure,
.print = re_print,
- .locals_dict = (void*)&re_locals_dict,
+ .locals_dict = (void *)&re_locals_dict,
};
+#endif
STATIC mp_obj_t mod_re_compile(size_t n_args, const mp_obj_t *args) {
+ (void)n_args;
const char *re_str = mp_obj_str_get_str(args[0]);
int size = re1_5_sizecode(re_str);
if (size == -1) {
@@ -389,74 +405,57 @@ STATIC mp_obj_t mod_re_compile(size_t n_args, const mp_obj_t *args) {
}
mp_obj_re_t *o = m_new_obj_var(mp_obj_re_t, char, size);
o->base.type = &re_type;
+ #if MICROPY_PY_URE_DEBUG
int flags = 0;
if (n_args > 1) {
flags = mp_obj_get_int(args[1]);
}
+ #endif
int error = re1_5_compilecode(&o->re, re_str);
if (error != 0) {
-error:
- mp_raise_ValueError("Error in regex");
+ error:
+ mp_raise_ValueError(MP_ERROR_TEXT("error in regex"));
}
+ #if MICROPY_PY_URE_DEBUG
if (flags & FLAG_DEBUG) {
re1_5_dumpcode(&o->re);
}
+ #endif
return MP_OBJ_FROM_PTR(o);
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_re_compile_obj, 1, 2, mod_re_compile);
-STATIC mp_obj_t mod_re_exec(bool is_anchored, uint n_args, const mp_obj_t *args) {
- (void)n_args;
- mp_obj_t self = mod_re_compile(1, args);
-
- const mp_obj_t args2[] = {self, args[1]};
- mp_obj_t match = ure_exec(is_anchored, 2, args2);
- return match;
-}
-
-STATIC mp_obj_t mod_re_match(size_t n_args, const mp_obj_t *args) {
- return mod_re_exec(true, n_args, args);
-}
-MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_re_match_obj, 2, 4, mod_re_match);
-
-STATIC mp_obj_t mod_re_search(size_t n_args, const mp_obj_t *args) {
- return mod_re_exec(false, n_args, args);
-}
-MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_re_search_obj, 2, 4, mod_re_search);
-
-#if MICROPY_PY_URE_SUB
-STATIC mp_obj_t mod_re_sub(size_t n_args, const mp_obj_t *args) {
- mp_obj_t self = mod_re_compile(1, args);
- return re_sub_helper(self, n_args, args);
-}
-MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_re_sub_obj, 3, 5, mod_re_sub);
-#endif
-
+#if !MICROPY_ENABLE_DYNRUNTIME
STATIC const mp_rom_map_elem_t mp_module_re_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_ure) },
{ MP_ROM_QSTR(MP_QSTR_compile), MP_ROM_PTR(&mod_re_compile_obj) },
- { MP_ROM_QSTR(MP_QSTR_match), MP_ROM_PTR(&mod_re_match_obj) },
- { MP_ROM_QSTR(MP_QSTR_search), MP_ROM_PTR(&mod_re_search_obj) },
+ { MP_ROM_QSTR(MP_QSTR_match), MP_ROM_PTR(&re_match_obj) },
+ { MP_ROM_QSTR(MP_QSTR_search), MP_ROM_PTR(&re_search_obj) },
#if MICROPY_PY_URE_SUB
- { MP_ROM_QSTR(MP_QSTR_sub), MP_ROM_PTR(&mod_re_sub_obj) },
+ { MP_ROM_QSTR(MP_QSTR_sub), MP_ROM_PTR(&re_sub_obj) },
#endif
+ #if MICROPY_PY_URE_DEBUG
{ MP_ROM_QSTR(MP_QSTR_DEBUG), MP_ROM_INT(FLAG_DEBUG) },
+ #endif
};
STATIC MP_DEFINE_CONST_DICT(mp_module_re_globals, mp_module_re_globals_table);
const mp_obj_module_t mp_module_ure = {
.base = { &mp_type_module },
- .globals = (mp_obj_dict_t*)&mp_module_re_globals,
+ .globals = (mp_obj_dict_t *)&mp_module_re_globals,
};
+#endif
// Source files #include'd here to make sure they're compiled in
// only if module is enabled by config setting.
#define re1_5_fatal(x) assert(!x)
#include "re1.5/compilecode.c"
+#if MICROPY_PY_URE_DEBUG
#include "re1.5/dumpcode.c"
+#endif
#include "re1.5/recursiveloop.c"
#include "re1.5/charclass.c"
-#endif //MICROPY_PY_URE
+#endif // MICROPY_PY_URE
diff --git a/extmod/moduselect.c b/extmod/moduselect.c
index 4963b4d5c6..80beb8e09b 100644
--- a/extmod/moduselect.c
+++ b/extmod/moduselect.c
@@ -66,9 +66,9 @@ STATIC void poll_map_add(mp_map_t *poll_map, const mp_obj_t *obj, mp_uint_t obj_
} else {
// object exists; update its flags
if (or_flags) {
- ((poll_obj_t*)MP_OBJ_TO_PTR(elem->value))->flags |= flags;
+ ((poll_obj_t *)MP_OBJ_TO_PTR(elem->value))->flags |= flags;
} else {
- ((poll_obj_t*)MP_OBJ_TO_PTR(elem->value))->flags = flags;
+ ((poll_obj_t *)MP_OBJ_TO_PTR(elem->value))->flags = flags;
}
}
}
@@ -125,7 +125,7 @@ STATIC mp_obj_t select_select(size_t n_args, const mp_obj_t *args) {
if (n_args == 4) {
if (args[3] != mp_const_none) {
#if MICROPY_PY_BUILTINS_FLOAT
- float timeout_f = mp_obj_get_float(args[3]);
+ float timeout_f = mp_obj_get_float_to_f(args[3]);
if (timeout_f >= 0) {
timeout = (mp_uint_t)(timeout_f * 1000);
}
@@ -161,13 +161,13 @@ STATIC mp_obj_t select_select(size_t n_args, const mp_obj_t *args) {
}
poll_obj_t *poll_obj = MP_OBJ_TO_PTR(poll_map.table[i].value);
if (poll_obj->flags_ret & MP_STREAM_POLL_RD) {
- ((mp_obj_list_t*)MP_OBJ_TO_PTR(list_array[0]))->items[rwx_len[0]++] = poll_obj->obj;
+ ((mp_obj_list_t *)MP_OBJ_TO_PTR(list_array[0]))->items[rwx_len[0]++] = poll_obj->obj;
}
if (poll_obj->flags_ret & MP_STREAM_POLL_WR) {
- ((mp_obj_list_t*)MP_OBJ_TO_PTR(list_array[1]))->items[rwx_len[1]++] = poll_obj->obj;
+ ((mp_obj_list_t *)MP_OBJ_TO_PTR(list_array[1]))->items[rwx_len[1]++] = poll_obj->obj;
}
if ((poll_obj->flags_ret & ~(MP_STREAM_POLL_RD | MP_STREAM_POLL_WR)) != 0) {
- ((mp_obj_list_t*)MP_OBJ_TO_PTR(list_array[2]))->items[rwx_len[2]++] = poll_obj->obj;
+ ((mp_obj_list_t *)MP_OBJ_TO_PTR(list_array[2]))->items[rwx_len[2]++] = poll_obj->obj;
}
}
mp_map_deinit(&poll_map);
@@ -220,7 +220,7 @@ STATIC mp_obj_t poll_modify(mp_obj_t self_in, mp_obj_t obj_in, mp_obj_t eventmas
if (elem == NULL) {
mp_raise_OSError(MP_ENOENT);
}
- ((poll_obj_t*)MP_OBJ_TO_PTR(elem->value))->flags = mp_obj_get_int(eventmask_in);
+ ((poll_obj_t *)MP_OBJ_TO_PTR(elem->value))->flags = mp_obj_get_int(eventmask_in);
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_3(poll_modify_obj, poll_modify);
@@ -345,7 +345,7 @@ STATIC const mp_obj_type_t mp_type_poll = {
.name = MP_QSTR_poll,
.getiter = mp_identity_getiter,
.iternext = poll_iternext,
- .locals_dict = (void*)&poll_locals_dict,
+ .locals_dict = (void *)&poll_locals_dict,
};
/// \function poll()
@@ -373,7 +373,7 @@ STATIC MP_DEFINE_CONST_DICT(mp_module_select_globals, mp_module_select_globals_t
const mp_obj_module_t mp_module_uselect = {
.base = { &mp_type_module },
- .globals = (mp_obj_dict_t*)&mp_module_select_globals,
+ .globals = (mp_obj_dict_t *)&mp_module_select_globals,
};
#endif // MICROPY_PY_USELECT
diff --git a/extmod/modussl_axtls.c b/extmod/modussl_axtls.c
index b559b13580..0b0ce35fc8 100644
--- a/extmod/modussl_axtls.c
+++ b/extmod/modussl_axtls.c
@@ -29,6 +29,7 @@
#include "py/runtime.h"
#include "py/stream.h"
+#include "py/objstr.h"
#if MICROPY_PY_USSL && MICROPY_SSL_AXTLS
@@ -54,12 +55,62 @@ struct ssl_args {
STATIC const mp_obj_type_t ussl_socket_type;
-STATIC mp_obj_ssl_socket_t *socket_new(mp_obj_t sock, struct ssl_args *args) {
-#if MICROPY_PY_USSL_FINALISER
+// Table of errors
+struct ssl_errs {
+ int16_t errnum;
+ const char *errstr;
+};
+STATIC const struct ssl_errs ssl_error_tab[] = {
+ { SSL_NOT_OK, "NOT_OK" },
+ { SSL_ERROR_DEAD, "DEAD" },
+ { SSL_CLOSE_NOTIFY, "CLOSE_NOTIFY" },
+ { SSL_EAGAIN, "EAGAIN" },
+ { SSL_ERROR_CONN_LOST, "CONN_LOST" },
+ { SSL_ERROR_RECORD_OVERFLOW, "RECORD_OVERFLOW" },
+ { SSL_ERROR_SOCK_SETUP_FAILURE, "SOCK_SETUP_FAILURE" },
+ { SSL_ERROR_INVALID_HANDSHAKE, "INVALID_HANDSHAKE" },
+ { SSL_ERROR_INVALID_PROT_MSG, "INVALID_PROT_MSG" },
+ { SSL_ERROR_INVALID_HMAC, "INVALID_HMAC" },
+ { SSL_ERROR_INVALID_VERSION, "INVALID_VERSION" },
+ { SSL_ERROR_UNSUPPORTED_EXTENSION, "UNSUPPORTED_EXTENSION" },
+ { SSL_ERROR_INVALID_SESSION, "INVALID_SESSION" },
+ { SSL_ERROR_NO_CIPHER, "NO_CIPHER" },
+ { SSL_ERROR_INVALID_CERT_HASH_ALG, "INVALID_CERT_HASH_ALG" },
+ { SSL_ERROR_BAD_CERTIFICATE, "BAD_CERTIFICATE" },
+ { SSL_ERROR_INVALID_KEY, "INVALID_KEY" },
+ { SSL_ERROR_FINISHED_INVALID, "FINISHED_INVALID" },
+ { SSL_ERROR_NO_CERT_DEFINED, "NO_CERT_DEFINED" },
+ { SSL_ERROR_NO_CLIENT_RENOG, "NO_CLIENT_RENOG" },
+ { SSL_ERROR_NOT_SUPPORTED, "NOT_SUPPORTED" },
+};
+
+STATIC NORETURN void ussl_raise_error(int err) {
+ for (size_t i = 0; i < MP_ARRAY_SIZE(ssl_error_tab); i++) {
+ if (ssl_error_tab[i].errnum == err) {
+ // construct string object
+ mp_obj_str_t *o_str = m_new_obj_maybe(mp_obj_str_t);
+ if (o_str == NULL) {
+ break;
+ }
+ o_str->base.type = &mp_type_str;
+ o_str->data = (const byte *)ssl_error_tab[i].errstr;
+ o_str->len = strlen((char *)o_str->data);
+ o_str->hash = qstr_compute_hash(o_str->data, o_str->len);
+ // raise
+ mp_obj_t args[2] = { MP_OBJ_NEW_SMALL_INT(err), MP_OBJ_FROM_PTR(o_str)};
+ nlr_raise(mp_obj_exception_make_new(&mp_type_OSError, 2, 0, args));
+ }
+ }
+ mp_raise_OSError(err);
+}
+
+
+STATIC mp_obj_ssl_socket_t *ussl_socket_new(mp_obj_t sock, struct ssl_args *args) {
+ #if MICROPY_PY_USSL_FINALISER
mp_obj_ssl_socket_t *o = m_new_obj_with_finaliser(mp_obj_ssl_socket_t);
-#else
+ #else
mp_obj_ssl_socket_t *o = m_new_obj(mp_obj_ssl_socket_t);
-#endif
+ #endif
o->base.type = &ussl_socket_type;
o->buf = NULL;
o->bytes_left = 0;
@@ -79,16 +130,16 @@ STATIC mp_obj_ssl_socket_t *socket_new(mp_obj_t sock, struct ssl_args *args) {
if (args->key.u_obj != mp_const_none) {
size_t len;
- const byte *data = (const byte*)mp_obj_str_get_data(args->key.u_obj, &len);
+ const byte *data = (const byte *)mp_obj_str_get_data(args->key.u_obj, &len);
int res = ssl_obj_memory_load(o->ssl_ctx, SSL_OBJ_RSA_KEY, data, len, NULL);
if (res != SSL_OK) {
- mp_raise_ValueError("invalid key");
+ mp_raise_ValueError(MP_ERROR_TEXT("invalid key"));
}
- data = (const byte*)mp_obj_str_get_data(args->cert.u_obj, &len);
+ data = (const byte *)mp_obj_str_get_data(args->cert.u_obj, &len);
res = ssl_obj_memory_load(o->ssl_ctx, SSL_OBJ_X509_CERT, data, len, NULL);
if (res != SSL_OK) {
- mp_raise_ValueError("invalid cert");
+ mp_raise_ValueError(MP_ERROR_TEXT("invalid cert"));
}
}
@@ -98,7 +149,7 @@ STATIC mp_obj_ssl_socket_t *socket_new(mp_obj_t sock, struct ssl_args *args) {
SSL_EXTENSIONS *ext = ssl_ext_new();
if (args->server_hostname.u_obj != mp_const_none) {
- ext->host_name = (char*)mp_obj_str_get_str(args->server_hostname.u_obj);
+ ext->host_name = (char *)mp_obj_str_get_str(args->server_hostname.u_obj);
}
o->ssl_sock = ssl_client_new(o->ssl_ctx, (long)sock, NULL, 0, ext);
@@ -107,9 +158,7 @@ STATIC mp_obj_ssl_socket_t *socket_new(mp_obj_t sock, struct ssl_args *args) {
int res = ssl_handshake_status(o->ssl_sock);
if (res != SSL_OK) {
- printf("ssl_handshake_status: %d\n", res);
- ssl_display_error(res);
- mp_raise_OSError(MP_EIO);
+ ussl_raise_error(res);
}
}
@@ -118,13 +167,13 @@ STATIC mp_obj_ssl_socket_t *socket_new(mp_obj_t sock, struct ssl_args *args) {
return o;
}
-STATIC void socket_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
+STATIC void ussl_socket_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
(void)kind;
mp_obj_ssl_socket_t *self = MP_OBJ_TO_PTR(self_in);
mp_printf(print, "<_SSLSocket %p>", self->ssl_sock);
}
-STATIC mp_uint_t socket_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) {
+STATIC mp_uint_t ussl_socket_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) {
mp_obj_ssl_socket_t *o = MP_OBJ_TO_PTR(o_in);
if (o->ssl_sock == NULL) {
@@ -155,7 +204,7 @@ STATIC mp_uint_t socket_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errc
return 0;
}
if (r == SSL_EAGAIN) {
-eagain:
+ eagain:
r = MP_EAGAIN;
}
*errcode = r;
@@ -173,7 +222,7 @@ STATIC mp_uint_t socket_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errc
return size;
}
-STATIC mp_uint_t socket_write(mp_obj_t o_in, const void *buf, mp_uint_t size, int *errcode) {
+STATIC mp_uint_t ussl_socket_write(mp_obj_t o_in, const void *buf, mp_uint_t size, int *errcode) {
mp_obj_ssl_socket_t *o = MP_OBJ_TO_PTR(o_in);
if (o->ssl_sock == NULL) {
@@ -189,7 +238,7 @@ STATIC mp_uint_t socket_write(mp_obj_t o_in, const void *buf, mp_uint_t size, in
return r;
}
-STATIC mp_uint_t socket_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg, int *errcode) {
+STATIC mp_uint_t ussl_socket_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg, int *errcode) {
mp_obj_ssl_socket_t *self = MP_OBJ_TO_PTR(o_in);
if (request == MP_STREAM_CLOSE && self->ssl_sock != NULL) {
ssl_free(self->ssl_sock);
@@ -200,7 +249,7 @@ STATIC mp_uint_t socket_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg, i
return mp_get_stream(self->sock)->ioctl(self->sock, request, arg, errcode);
}
-STATIC mp_obj_t socket_setblocking(mp_obj_t self_in, mp_obj_t flag_in) {
+STATIC mp_obj_t ussl_socket_setblocking(mp_obj_t self_in, mp_obj_t flag_in) {
mp_obj_ssl_socket_t *o = MP_OBJ_TO_PTR(self_in);
mp_obj_t sock = o->sock;
mp_obj_t dest[3];
@@ -210,46 +259,46 @@ STATIC mp_obj_t socket_setblocking(mp_obj_t self_in, mp_obj_t flag_in) {
o->blocking = mp_obj_is_true(flag_in);
return res;
}
-STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_setblocking_obj, socket_setblocking);
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(ussl_socket_setblocking_obj, ussl_socket_setblocking);
STATIC const mp_rom_map_elem_t ussl_socket_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) },
{ MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) },
{ MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) },
{ MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) },
- { MP_ROM_QSTR(MP_QSTR_setblocking), MP_ROM_PTR(&socket_setblocking_obj) },
+ { MP_ROM_QSTR(MP_QSTR_setblocking), MP_ROM_PTR(&ussl_socket_setblocking_obj) },
{ MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&mp_stream_close_obj) },
-#if MICROPY_PY_USSL_FINALISER
+ #if MICROPY_PY_USSL_FINALISER
{ MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mp_stream_close_obj) },
-#endif
+ #endif
};
STATIC MP_DEFINE_CONST_DICT(ussl_socket_locals_dict, ussl_socket_locals_dict_table);
STATIC const mp_stream_p_t ussl_socket_stream_p = {
- .read = socket_read,
- .write = socket_write,
- .ioctl = socket_ioctl,
+ .read = ussl_socket_read,
+ .write = ussl_socket_write,
+ .ioctl = ussl_socket_ioctl,
};
STATIC const mp_obj_type_t ussl_socket_type = {
{ &mp_type_type },
// Save on qstr's, reuse same as for module
.name = MP_QSTR_ussl,
- .print = socket_print,
+ .print = ussl_socket_print,
.getiter = NULL,
.iternext = NULL,
.protocol = &ussl_socket_stream_p,
- .locals_dict = (void*)&ussl_socket_locals_dict,
+ .locals_dict = (void *)&ussl_socket_locals_dict,
};
STATIC mp_obj_t mod_ssl_wrap_socket(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
// TODO: Implement more args
static const mp_arg_t allowed_args[] = {
- { MP_QSTR_key, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} },
- { MP_QSTR_cert, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} },
+ { MP_QSTR_key, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
+ { MP_QSTR_cert, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
{ MP_QSTR_server_side, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
- { MP_QSTR_server_hostname, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} },
+ { MP_QSTR_server_hostname, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
{ MP_QSTR_do_handshake, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = true} },
};
@@ -258,9 +307,9 @@ STATIC mp_obj_t mod_ssl_wrap_socket(size_t n_args, const mp_obj_t *pos_args, mp_
struct ssl_args args;
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args,
- MP_ARRAY_SIZE(allowed_args), allowed_args, (mp_arg_val_t*)&args);
+ MP_ARRAY_SIZE(allowed_args), allowed_args, (mp_arg_val_t *)&args);
- return MP_OBJ_FROM_PTR(socket_new(sock, &args));
+ return MP_OBJ_FROM_PTR(ussl_socket_new(sock, &args));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mod_ssl_wrap_socket_obj, 1, mod_ssl_wrap_socket);
@@ -273,7 +322,7 @@ STATIC MP_DEFINE_CONST_DICT(mp_module_ssl_globals, mp_module_ssl_globals_table);
const mp_obj_module_t mp_module_ussl = {
.base = { &mp_type_module },
- .globals = (mp_obj_dict_t*)&mp_module_ssl_globals,
+ .globals = (mp_obj_dict_t *)&mp_module_ssl_globals,
};
#endif // MICROPY_PY_USSL
diff --git a/extmod/modussl_mbedtls.c b/extmod/modussl_mbedtls.c
index 94863be57a..1677dc6e1c 100644
--- a/extmod/modussl_mbedtls.c
+++ b/extmod/modussl_mbedtls.c
@@ -34,6 +34,7 @@
#include "py/runtime.h"
#include "py/stream.h"
+#include "py/objstr.h"
// mbedtls_time_t
#include "mbedtls/platform.h"
@@ -43,6 +44,7 @@
#include "mbedtls/entropy.h"
#include "mbedtls/ctr_drbg.h"
#include "mbedtls/debug.h"
+#include "mbedtls/error.h"
typedef struct _mp_obj_ssl_socket_t {
mp_obj_base_t base;
@@ -74,8 +76,48 @@ STATIC void mbedtls_debug(void *ctx, int level, const char *file, int line, cons
}
#endif
+STATIC NORETURN void mbedtls_raise_error(int err) {
+ // _mbedtls_ssl_send and _mbedtls_ssl_recv (below) turn positive error codes from the
+ // underlying socket into negative codes to pass them through mbedtls. Here we turn them
+ // positive again so they get interpreted as the OSError they really are. The
+ // cut-off of -256 is a bit hacky, sigh.
+ if (err < 0 && err > -256) {
+ mp_raise_OSError(-err);
+ }
+
+ #if defined(MBEDTLS_ERROR_C)
+ // Including mbedtls_strerror takes about 1.5KB due to the error strings.
+ // MBEDTLS_ERROR_C is the define used by mbedtls to conditionally include mbedtls_strerror.
+ // It is set/unset in the MBEDTLS_CONFIG_FILE which is defined in the Makefile.
+
+ // Try to allocate memory for the message
+ #define ERR_STR_MAX 80 // mbedtls_strerror truncates if it doesn't fit
+ mp_obj_str_t *o_str = m_new_obj_maybe(mp_obj_str_t);
+ byte *o_str_buf = m_new_maybe(byte, ERR_STR_MAX);
+ if (o_str == NULL || o_str_buf == NULL) {
+ mp_raise_OSError(err);
+ }
+
+ // print the error message into the allocated buffer
+ mbedtls_strerror(err, (char *)o_str_buf, ERR_STR_MAX);
+ size_t len = strlen((char *)o_str_buf);
+
+ // Put the exception object together
+ o_str->base.type = &mp_type_str;
+ o_str->data = o_str_buf;
+ o_str->len = len;
+ o_str->hash = qstr_compute_hash(o_str->data, o_str->len);
+ // raise
+ mp_obj_t args[2] = { MP_OBJ_NEW_SMALL_INT(err), MP_OBJ_FROM_PTR(o_str)};
+ nlr_raise(mp_obj_exception_make_new(&mp_type_OSError, 2, 0, args));
+ #else
+ // mbedtls is compiled without error strings so we simply return the err number
+ mp_raise_OSError(err); // err is typically a large negative number
+ #endif
+}
+
STATIC int _mbedtls_ssl_send(void *ctx, const byte *buf, size_t len) {
- mp_obj_t sock = *(mp_obj_t*)ctx;
+ mp_obj_t sock = *(mp_obj_t *)ctx;
const mp_stream_p_t *sock_stream = mp_get_stream(sock);
int err;
@@ -85,14 +127,14 @@ STATIC int _mbedtls_ssl_send(void *ctx, const byte *buf, size_t len) {
if (mp_is_nonblocking_error(err)) {
return MBEDTLS_ERR_SSL_WANT_WRITE;
}
- return -err;
+ return -err; // convert an MP_ERRNO to something mbedtls passes through as error
} else {
return out_sz;
}
}
STATIC int _mbedtls_ssl_recv(void *ctx, byte *buf, size_t len) {
- mp_obj_t sock = *(mp_obj_t*)ctx;
+ mp_obj_t sock = *(mp_obj_t *)ctx;
const mp_stream_p_t *sock_stream = mp_get_stream(sock);
int err;
@@ -113,11 +155,11 @@ STATIC mp_obj_ssl_socket_t *socket_new(mp_obj_t sock, struct ssl_args *args) {
// Verify the socket object has the full stream protocol
mp_get_stream_raise(sock, MP_STREAM_OP_READ | MP_STREAM_OP_WRITE | MP_STREAM_OP_IOCTL);
-#if MICROPY_PY_USSL_FINALISER
+ #if MICROPY_PY_USSL_FINALISER
mp_obj_ssl_socket_t *o = m_new_obj_with_finaliser(mp_obj_ssl_socket_t);
-#else
+ #else
mp_obj_ssl_socket_t *o = m_new_obj(mp_obj_ssl_socket_t);
-#endif
+ #endif
o->base.type = &ussl_socket_type;
o->sock = sock;
@@ -141,9 +183,9 @@ STATIC mp_obj_ssl_socket_t *socket_new(mp_obj_t sock, struct ssl_args *args) {
}
ret = mbedtls_ssl_config_defaults(&o->conf,
- args->server_side.u_bool ? MBEDTLS_SSL_IS_SERVER : MBEDTLS_SSL_IS_CLIENT,
- MBEDTLS_SSL_TRANSPORT_STREAM,
- MBEDTLS_SSL_PRESET_DEFAULT);
+ args->server_side.u_bool ? MBEDTLS_SSL_IS_SERVER : MBEDTLS_SSL_IS_CLIENT,
+ MBEDTLS_SSL_TRANSPORT_STREAM,
+ MBEDTLS_SSL_PRESET_DEFAULT);
if (ret != 0) {
goto cleanup;
}
@@ -169,27 +211,34 @@ STATIC mp_obj_ssl_socket_t *socket_new(mp_obj_t sock, struct ssl_args *args) {
mbedtls_ssl_set_bio(&o->ssl, &o->sock, _mbedtls_ssl_send, _mbedtls_ssl_recv, NULL);
- if (args->key.u_obj != MP_OBJ_NULL) {
+ if (args->key.u_obj != mp_const_none) {
size_t key_len;
- const byte *key = (const byte*)mp_obj_str_get_data(args->key.u_obj, &key_len);
+ const byte *key = (const byte *)mp_obj_str_get_data(args->key.u_obj, &key_len);
// len should include terminating null
ret = mbedtls_pk_parse_key(&o->pkey, key, key_len + 1, NULL, 0);
- assert(ret == 0);
+ if (ret != 0) {
+ ret = MBEDTLS_ERR_PK_BAD_INPUT_DATA; // use general error for all key errors
+ goto cleanup;
+ }
size_t cert_len;
- const byte *cert = (const byte*)mp_obj_str_get_data(args->cert.u_obj, &cert_len);
+ const byte *cert = (const byte *)mp_obj_str_get_data(args->cert.u_obj, &cert_len);
// len should include terminating null
ret = mbedtls_x509_crt_parse(&o->cert, cert, cert_len + 1);
- assert(ret == 0);
+ if (ret != 0) {
+ ret = MBEDTLS_ERR_X509_BAD_INPUT_DATA; // use general error for all cert errors
+ goto cleanup;
+ }
ret = mbedtls_ssl_conf_own_cert(&o->conf, &o->cert, &o->pkey);
- assert(ret == 0);
+ if (ret != 0) {
+ goto cleanup;
+ }
}
if (args->do_handshake.u_bool) {
while ((ret = mbedtls_ssl_handshake(&o->ssl)) != 0) {
if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) {
- printf("mbedtls_ssl_handshake error: -%x\n", -ret);
goto cleanup;
}
}
@@ -208,8 +257,12 @@ STATIC mp_obj_ssl_socket_t *socket_new(mp_obj_t sock, struct ssl_args *args) {
if (ret == MBEDTLS_ERR_SSL_ALLOC_FAILED) {
mp_raise_OSError(MP_ENOMEM);
+ } else if (ret == MBEDTLS_ERR_PK_BAD_INPUT_DATA) {
+ mp_raise_ValueError(MP_ERROR_TEXT("invalid key"));
+ } else if (ret == MBEDTLS_ERR_X509_BAD_INPUT_DATA) {
+ mp_raise_ValueError(MP_ERROR_TEXT("invalid cert"));
} else {
- mp_raise_OSError(MP_EIO);
+ mbedtls_raise_error(ret);
}
}
@@ -218,7 +271,10 @@ STATIC mp_obj_t mod_ssl_getpeercert(mp_obj_t o_in, mp_obj_t binary_form) {
if (!mp_obj_is_true(binary_form)) {
mp_raise_NotImplementedError(NULL);
}
- const mbedtls_x509_crt* peer_cert = mbedtls_ssl_get_peer_cert(&o->ssl);
+ const mbedtls_x509_crt *peer_cert = mbedtls_ssl_get_peer_cert(&o->ssl);
+ if (peer_cert == NULL) {
+ return mp_const_none;
+ }
return mp_obj_new_bytes(peer_cert->raw.p, peer_cert->raw.len);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_ssl_getpeercert_obj, mod_ssl_getpeercert);
@@ -303,9 +359,9 @@ STATIC const mp_rom_map_elem_t ussl_socket_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) },
{ MP_ROM_QSTR(MP_QSTR_setblocking), MP_ROM_PTR(&socket_setblocking_obj) },
{ MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&mp_stream_close_obj) },
-#if MICROPY_PY_USSL_FINALISER
+ #if MICROPY_PY_USSL_FINALISER
{ MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mp_stream_close_obj) },
-#endif
+ #endif
{ MP_ROM_QSTR(MP_QSTR_getpeercert), MP_ROM_PTR(&mod_ssl_getpeercert_obj) },
};
@@ -325,16 +381,16 @@ STATIC const mp_obj_type_t ussl_socket_type = {
.getiter = NULL,
.iternext = NULL,
.protocol = &ussl_socket_stream_p,
- .locals_dict = (void*)&ussl_socket_locals_dict,
+ .locals_dict = (void *)&ussl_socket_locals_dict,
};
STATIC mp_obj_t mod_ssl_wrap_socket(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
// TODO: Implement more args
static const mp_arg_t allowed_args[] = {
- { MP_QSTR_key, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
- { MP_QSTR_cert, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
+ { MP_QSTR_key, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
+ { MP_QSTR_cert, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
{ MP_QSTR_server_side, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
- { MP_QSTR_server_hostname, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
+ { MP_QSTR_server_hostname, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
{ MP_QSTR_do_handshake, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = true} },
};
@@ -343,7 +399,7 @@ STATIC mp_obj_t mod_ssl_wrap_socket(size_t n_args, const mp_obj_t *pos_args, mp_
struct ssl_args args;
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args,
- MP_ARRAY_SIZE(allowed_args), allowed_args, (mp_arg_val_t*)&args);
+ MP_ARRAY_SIZE(allowed_args), allowed_args, (mp_arg_val_t *)&args);
return MP_OBJ_FROM_PTR(socket_new(sock, &args));
}
@@ -358,7 +414,7 @@ STATIC MP_DEFINE_CONST_DICT(mp_module_ssl_globals, mp_module_ssl_globals_table);
const mp_obj_module_t mp_module_ussl = {
.base = { &mp_type_module },
- .globals = (mp_obj_dict_t*)&mp_module_ssl_globals,
+ .globals = (mp_obj_dict_t *)&mp_module_ssl_globals,
};
#endif // MICROPY_PY_USSL
diff --git a/extmod/modutimeq.c b/extmod/modutimeq.c
index e28d42c244..74c0a8942a 100644
--- a/extmod/modutimeq.c
+++ b/extmod/modutimeq.c
@@ -55,7 +55,7 @@ typedef struct _mp_obj_utimeq_t {
STATIC mp_uint_t utimeq_id;
-STATIC mp_obj_utimeq_t *get_heap(mp_obj_t heap_in) {
+STATIC mp_obj_utimeq_t *utimeq_get_heap(mp_obj_t heap_in) {
return MP_OBJ_TO_PTR(heap_in);
}
@@ -85,7 +85,7 @@ STATIC mp_obj_t utimeq_make_new(const mp_obj_type_t *type, size_t n_args, size_t
return MP_OBJ_FROM_PTR(o);
}
-STATIC void heap_siftdown(mp_obj_utimeq_t *heap, mp_uint_t start_pos, mp_uint_t pos) {
+STATIC void utimeq_heap_siftdown(mp_obj_utimeq_t *heap, mp_uint_t start_pos, mp_uint_t pos) {
struct qentry item = heap->items[pos];
while (pos > start_pos) {
mp_uint_t parent_pos = (pos - 1) >> 1;
@@ -101,7 +101,7 @@ STATIC void heap_siftdown(mp_obj_utimeq_t *heap, mp_uint_t start_pos, mp_uint_t
heap->items[pos] = item;
}
-STATIC void heap_siftup(mp_obj_utimeq_t *heap, mp_uint_t pos) {
+STATIC void utimeq_heap_siftup(mp_obj_utimeq_t *heap, mp_uint_t pos) {
mp_uint_t start_pos = pos;
mp_uint_t end_pos = heap->len;
struct qentry item = heap->items[pos];
@@ -118,34 +118,34 @@ STATIC void heap_siftup(mp_obj_utimeq_t *heap, mp_uint_t pos) {
pos = child_pos;
}
heap->items[pos] = item;
- heap_siftdown(heap, start_pos, pos);
+ utimeq_heap_siftdown(heap, start_pos, pos);
}
STATIC mp_obj_t mod_utimeq_heappush(size_t n_args, const mp_obj_t *args) {
(void)n_args;
mp_obj_t heap_in = args[0];
- mp_obj_utimeq_t *heap = get_heap(heap_in);
+ mp_obj_utimeq_t *heap = utimeq_get_heap(heap_in);
if (heap->len == heap->alloc) {
- mp_raise_msg(&mp_type_IndexError, "queue overflow");
+ mp_raise_msg(&mp_type_IndexError, MP_ERROR_TEXT("queue overflow"));
}
mp_uint_t l = heap->len;
heap->items[l].time = MP_OBJ_SMALL_INT_VALUE(args[1]);
heap->items[l].id = utimeq_id++;
heap->items[l].callback = args[2];
heap->items[l].args = args[3];
- heap_siftdown(heap, 0, heap->len);
+ utimeq_heap_siftdown(heap, 0, heap->len);
heap->len++;
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_utimeq_heappush_obj, 4, 4, mod_utimeq_heappush);
STATIC mp_obj_t mod_utimeq_heappop(mp_obj_t heap_in, mp_obj_t list_ref) {
- mp_obj_utimeq_t *heap = get_heap(heap_in);
+ mp_obj_utimeq_t *heap = utimeq_get_heap(heap_in);
if (heap->len == 0) {
- nlr_raise(mp_obj_new_exception_msg(&mp_type_IndexError, "empty heap"));
+ mp_raise_msg(&mp_type_IndexError, MP_ERROR_TEXT("empty heap"));
}
mp_obj_list_t *ret = MP_OBJ_TO_PTR(list_ref);
- if (!MP_OBJ_IS_TYPE(list_ref, &mp_type_list) || ret->len < 3) {
+ if (!mp_obj_is_type(list_ref, &mp_type_list) || ret->len < 3) {
mp_raise_TypeError("Not a list or length is less than 3!");
}
@@ -158,16 +158,16 @@ STATIC mp_obj_t mod_utimeq_heappop(mp_obj_t heap_in, mp_obj_t list_ref) {
heap->items[heap->len].callback = MP_OBJ_NULL; // so we don't retain a pointer
heap->items[heap->len].args = MP_OBJ_NULL;
if (heap->len) {
- heap_siftup(heap, 0);
+ utimeq_heap_siftup(heap, 0);
}
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_utimeq_heappop_obj, mod_utimeq_heappop);
STATIC mp_obj_t mod_utimeq_peektime(mp_obj_t heap_in) {
- mp_obj_utimeq_t *heap = get_heap(heap_in);
+ mp_obj_utimeq_t *heap = utimeq_get_heap(heap_in);
if (heap->len == 0) {
- nlr_raise(mp_obj_new_exception_msg(&mp_type_IndexError, "empty heap"));
+ mp_raise_msg(&mp_type_IndexError, MP_ERROR_TEXT("empty heap"));
}
struct qentry *item = &heap->items[0];
@@ -177,7 +177,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_utimeq_peektime_obj, mod_utimeq_peektime);
#if DEBUG
STATIC mp_obj_t mod_utimeq_dump(mp_obj_t heap_in) {
- mp_obj_utimeq_t *heap = get_heap(heap_in);
+ mp_obj_utimeq_t *heap = utimeq_get_heap(heap_in);
for (int i = 0; i < heap->len; i++) {
printf(UINT_FMT "\t%p\t%p\n", heap->items[i].time,
MP_OBJ_TO_PTR(heap->items[i].callback), MP_OBJ_TO_PTR(heap->items[i].args));
@@ -190,9 +190,12 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_utimeq_dump_obj, mod_utimeq_dump);
STATIC mp_obj_t utimeq_unary_op(mp_unary_op_t op, mp_obj_t self_in) {
mp_obj_utimeq_t *self = MP_OBJ_TO_PTR(self_in);
switch (op) {
- case MP_UNARY_OP_BOOL: return mp_obj_new_bool(self->len != 0);
- case MP_UNARY_OP_LEN: return MP_OBJ_NEW_SMALL_INT(self->len);
- default: return MP_OBJ_NULL; // op not supported
+ case MP_UNARY_OP_BOOL:
+ return mp_obj_new_bool(self->len != 0);
+ case MP_UNARY_OP_LEN:
+ return MP_OBJ_NEW_SMALL_INT(self->len);
+ default:
+ return MP_OBJ_NULL; // op not supported
}
}
@@ -212,7 +215,7 @@ STATIC const mp_obj_type_t utimeq_type = {
.name = MP_QSTR_utimeq,
.make_new = utimeq_make_new,
.unary_op = utimeq_unary_op,
- .locals_dict = (void*)&utimeq_locals_dict,
+ .locals_dict = (void *)&utimeq_locals_dict,
};
STATIC const mp_rom_map_elem_t mp_module_utimeq_globals_table[] = {
@@ -224,7 +227,7 @@ STATIC MP_DEFINE_CONST_DICT(mp_module_utimeq_globals, mp_module_utimeq_globals_t
const mp_obj_module_t mp_module_utimeq = {
.base = { &mp_type_module },
- .globals = (mp_obj_dict_t*)&mp_module_utimeq_globals,
+ .globals = (mp_obj_dict_t *)&mp_module_utimeq_globals,
};
-#endif //MICROPY_PY_UTIMEQ
+#endif // MICROPY_PY_UTIMEQ
diff --git a/extmod/moduwebsocket.c b/extmod/moduwebsocket.c
index eb5e20c6e3..34b520f337 100644
--- a/extmod/moduwebsocket.c
+++ b/extmod/moduwebsocket.c
@@ -71,11 +71,11 @@ STATIC mp_obj_t websocket_make_new(const mp_obj_type_t *type, size_t n_args, siz
if (n_args > 1 && args[1] == mp_const_true) {
o->opts |= BLOCKING_WRITE;
}
- return MP_OBJ_FROM_PTR(o);
+ return MP_OBJ_FROM_PTR(o);
}
STATIC mp_uint_t websocket_read(mp_obj_t self_in, void *buf, mp_uint_t size, int *errcode) {
- mp_obj_websocket_t *self = MP_OBJ_TO_PTR(self_in);
+ mp_obj_websocket_t *self = MP_OBJ_TO_PTR(self_in);
const mp_stream_p_t *stream_p = mp_get_stream(self->sock);
while (1) {
if (self->to_recv != 0) {
@@ -183,7 +183,7 @@ STATIC mp_uint_t websocket_read(mp_obj_t self_in, void *buf, mp_uint_t size, int
self->msg_sz -= out_sz;
if (self->msg_sz == 0) {
byte last_state;
-no_payload:
+ no_payload:
last_state = self->state;
self->state = FRAME_HEADER;
self->to_recv = 2;
@@ -194,13 +194,13 @@ STATIC mp_uint_t websocket_read(mp_obj_t self_in, void *buf, mp_uint_t size, int
if (last_state == CONTROL) {
byte frame_type = self->last_flags & FRAME_OPCODE_MASK;
if (frame_type == FRAME_CLOSE) {
- static char close_resp[2] = {0x88, 0};
+ static const char close_resp[2] = {0x88, 0};
int err;
websocket_write(self_in, close_resp, sizeof(close_resp), &err);
return 0;
}
- //DEBUG_printf("Finished receiving ctrl message %x, ignoring\n", self->last_flags);
+ // DEBUG_printf("Finished receiving ctrl message %x, ignoring\n", self->last_flags);
continue;
}
}
@@ -217,7 +217,7 @@ STATIC mp_uint_t websocket_read(mp_obj_t self_in, void *buf, mp_uint_t size, int
}
STATIC mp_uint_t websocket_write(mp_obj_t self_in, const void *buf, mp_uint_t size, int *errcode) {
- mp_obj_websocket_t *self = MP_OBJ_TO_PTR(self_in);
+ mp_obj_websocket_t *self = MP_OBJ_TO_PTR(self_in);
assert(size < 0x10000);
byte header[4] = {0x80 | (self->opts & FRAME_OPCODE_MASK)};
int hdr_sz;
@@ -296,7 +296,7 @@ STATIC const mp_obj_type_t websocket_type = {
.name = MP_QSTR_websocket,
.make_new = websocket_make_new,
.protocol = &websocket_stream_p,
- .locals_dict = (void*)&websocket_locals_dict,
+ .locals_dict = (void *)&websocket_locals_dict,
};
STATIC const mp_rom_map_elem_t uwebsocket_module_globals_table[] = {
@@ -308,7 +308,7 @@ STATIC MP_DEFINE_CONST_DICT(uwebsocket_module_globals, uwebsocket_module_globals
const mp_obj_module_t mp_module_uwebsocket = {
.base = { &mp_type_module },
- .globals = (mp_obj_dict_t*)&uwebsocket_module_globals,
+ .globals = (mp_obj_dict_t *)&uwebsocket_module_globals,
};
#endif // MICROPY_PY_UWEBSOCKET
diff --git a/extmod/moduzlib.c b/extmod/moduzlib.c
index f8452c72b9..ab70d67479 100644
--- a/extmod/moduzlib.c
+++ b/extmod/moduzlib.c
@@ -49,9 +49,9 @@ typedef struct _mp_obj_decompio_t {
} mp_obj_decompio_t;
STATIC int read_src_stream(TINF_DATA *data) {
- byte *p = (void*)data;
+ byte *p = (void *)data;
p -= offsetof(mp_obj_decompio_t, decomp);
- mp_obj_decompio_t *self = (mp_obj_decompio_t*)p;
+ mp_obj_decompio_t *self = (mp_obj_decompio_t *)p;
const mp_stream_p_t *stream = mp_get_stream(self->src_stream);
int err;
@@ -61,7 +61,7 @@ STATIC int read_src_stream(TINF_DATA *data) {
mp_raise_OSError(err);
}
if (out_sz == 0) {
- nlr_raise(mp_obj_new_exception(&mp_type_EOFError));
+ mp_raise_type(&mp_type_EOFError);
}
return c;
}
@@ -91,8 +91,8 @@ STATIC mp_obj_t decompio_make_new(const mp_obj_type_t *type, size_t n_args, size
} else if (dict_opt >= 0) {
dict_opt = uzlib_zlib_parse_header(&o->decomp);
if (dict_opt < 0) {
-header_error:
- mp_raise_ValueError("compression header");
+ header_error:
+ mp_raise_ValueError(MP_ERROR_TEXT("compression header"));
}
dict_sz = 1 << dict_opt;
} else {
@@ -110,7 +110,7 @@ STATIC mp_uint_t decompio_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *er
}
o->decomp.dest = buf;
- o->decomp.dest_limit = (byte*)buf + size;
+ o->decomp.dest_limit = (byte *)buf + size;
int st = uzlib_uncompress_chksum(&o->decomp);
if (st == TINF_DONE) {
o->eof = true;
@@ -119,9 +119,10 @@ STATIC mp_uint_t decompio_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *er
*errcode = MP_EINVAL;
return MP_STREAM_ERROR;
}
- return o->decomp.dest - (byte*)buf;
+ return o->decomp.dest - (byte *)buf;
}
+#if !MICROPY_ENABLE_DYNRUNTIME
STATIC const mp_rom_map_elem_t decompio_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) },
{ MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) },
@@ -129,18 +130,21 @@ STATIC const mp_rom_map_elem_t decompio_locals_dict_table[] = {
};
STATIC MP_DEFINE_CONST_DICT(decompio_locals_dict, decompio_locals_dict_table);
+#endif
STATIC const mp_stream_p_t decompio_stream_p = {
.read = decompio_read,
};
+#if !MICROPY_ENABLE_DYNRUNTIME
STATIC const mp_obj_type_t decompio_type = {
{ &mp_type_type },
.name = MP_QSTR_DecompIO,
.make_new = decompio_make_new,
.protocol = &decompio_stream_p,
- .locals_dict = (void*)&decompio_locals_dict,
+ .locals_dict = (void *)&decompio_locals_dict,
};
+#endif
STATIC mp_obj_t mod_uzlib_decompress(size_t n_args, const mp_obj_t *args) {
mp_obj_t data = args[0];
@@ -158,7 +162,7 @@ STATIC mp_obj_t mod_uzlib_decompress(size_t n_args, const mp_obj_t *args) {
decomp->dest_limit = dest_buf + dest_buf_size;
DEBUG_printf("uzlib: Initial out buffer: " UINT_FMT " bytes\n", dest_buf_size);
decomp->source = bufinfo.buf;
- decomp->source_limit = (byte*)bufinfo.buf + bufinfo.len;
+ decomp->source_limit = (byte *)bufinfo.buf + bufinfo.len;
int st;
bool is_zlib = true;
@@ -191,16 +195,17 @@ STATIC mp_obj_t mod_uzlib_decompress(size_t n_args, const mp_obj_t *args) {
mp_uint_t final_sz = decomp->dest - dest_buf;
DEBUG_printf("uzlib: Resizing from " UINT_FMT " to final size: " UINT_FMT " bytes\n", dest_buf_size, final_sz);
- dest_buf = (byte*)m_renew(byte, dest_buf, dest_buf_size, final_sz);
+ dest_buf = (byte *)m_renew(byte, dest_buf, dest_buf_size, final_sz);
mp_obj_t res = mp_obj_new_bytearray_by_ref(final_sz, dest_buf);
m_del_obj(TINF_DATA, decomp);
return res;
error:
- nlr_raise(mp_obj_new_exception_arg1(&mp_type_ValueError, MP_OBJ_NEW_SMALL_INT(st)));
+ nlr_raise(mp_obj_new_exception_arg1(&mp_type_ValueError, MP_OBJ_NEW_SMALL_INT(st)));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_uzlib_decompress_obj, 1, 3, mod_uzlib_decompress);
+#if !MICROPY_ENABLE_DYNRUNTIME
STATIC const mp_rom_map_elem_t mp_module_uzlib_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uzlib) },
{ MP_ROM_QSTR(MP_QSTR_decompress), MP_ROM_PTR(&mod_uzlib_decompress_obj) },
@@ -211,8 +216,9 @@ STATIC MP_DEFINE_CONST_DICT(mp_module_uzlib_globals, mp_module_uzlib_globals_tab
const mp_obj_module_t mp_module_uzlib = {
.base = { &mp_type_module },
- .globals = (mp_obj_dict_t*)&mp_module_uzlib_globals,
+ .globals = (mp_obj_dict_t *)&mp_module_uzlib_globals,
};
+#endif
// Source files #include'd here to make sure they're compiled in
// only if module is enabled by config setting.
diff --git a/extmod/modwebrepl.c b/extmod/modwebrepl.c
index c9ef774340..a8430bafb3 100644
--- a/extmod/modwebrepl.c
+++ b/extmod/modwebrepl.c
@@ -67,10 +67,9 @@ typedef struct _mp_obj_webrepl_t {
mp_obj_t cur_file;
} mp_obj_webrepl_t;
-// These get passed to functions which aren't force-l32, so can't be const
-STATIC char passwd_prompt[] = "Password: ";
-STATIC char connected_prompt[] = "\r\nWebREPL connected\r\n>>> ";
-STATIC char denied_prompt[] = "\r\nAccess denied\r\n";
+STATIC const char passwd_prompt[] = "Password: ";
+STATIC const char connected_prompt[] = "\r\nWebREPL connected\r\n>>> ";
+STATIC const char denied_prompt[] = "\r\nAccess denied\r\n";
STATIC char webrepl_passwd[10];
@@ -105,7 +104,7 @@ STATIC mp_obj_t webrepl_make_new(const mp_obj_type_t *type, size_t n_args, size_
o->data_to_recv = 0;
o->state = STATE_PASSWD;
write_webrepl_str(args[0], SSTR(passwd_prompt));
- return o;
+ return MP_OBJ_FROM_PTR(o);
}
STATIC void check_file_op_finished(mp_obj_webrepl_t *self) {
@@ -138,7 +137,7 @@ STATIC void handle_op(mp_obj_webrepl_t *self) {
switch (self->hdr.type) {
case GET_VER: {
- static char ver[] = {MICROPY_VERSION_MAJOR, MICROPY_VERSION_MINOR, MICROPY_VERSION_MICRO};
+ static const char ver[] = {MICROPY_VERSION_MAJOR, MICROPY_VERSION_MINOR, MICROPY_VERSION_MICRO};
write_webrepl(self->sock, ver, sizeof(ver));
self->hdr_to_recv = sizeof(struct webrepl_file);
return;
@@ -156,7 +155,7 @@ STATIC void handle_op(mp_obj_webrepl_t *self) {
open_args[1] = MP_OBJ_NEW_QSTR(MP_QSTR_wb);
}
- self->cur_file = mp_builtin_open(2, open_args, (mp_map_t*)&mp_const_empty_map);
+ self->cur_file = mp_builtin_open(2, open_args, (mp_map_t *)&mp_const_empty_map);
#if 0
struct mp_stream_seek_t seek = { .offset = self->hdr.offset, .whence = 0 };
@@ -188,16 +187,16 @@ STATIC mp_uint_t webrepl_read(mp_obj_t self_in, void *buf, mp_uint_t size, int *
STATIC mp_uint_t _webrepl_read(mp_obj_t self_in, void *buf, mp_uint_t size, int *errcode) {
// We know that os.dupterm always calls with size = 1
assert(size == 1);
- mp_obj_webrepl_t *self = self_in;
+ mp_obj_webrepl_t *self = MP_OBJ_TO_PTR(self_in);
const mp_stream_p_t *sock_stream = mp_get_stream(self->sock);
mp_uint_t out_sz = sock_stream->read(self->sock, buf, size, errcode);
- //DEBUG_printf("webrepl: Read %d initial bytes from websocket\n", out_sz);
+ // DEBUG_printf("webrepl: Read %d initial bytes from websocket\n", out_sz);
if (out_sz == 0 || out_sz == MP_STREAM_ERROR) {
return out_sz;
}
if (self->state == STATE_PASSWD) {
- char c = *(char*)buf;
+ char c = *(char *)buf;
if (c == '\r' || c == '\n') {
self->hdr.fname[self->data_to_recv] = 0;
DEBUG_printf("webrepl: entered password: %s\n", self->hdr.fname);
@@ -225,8 +224,8 @@ STATIC mp_uint_t _webrepl_read(mp_obj_t self_in, void *buf, mp_uint_t size, int
DEBUG_printf("webrepl: received bin data, hdr_to_recv: %d, data_to_recv=%d\n", self->hdr_to_recv, self->data_to_recv);
if (self->hdr_to_recv != 0) {
- char *p = (char*)&self->hdr + sizeof(self->hdr) - self->hdr_to_recv;
- *p++ = *(char*)buf;
+ char *p = (char *)&self->hdr + sizeof(self->hdr) - self->hdr_to_recv;
+ *p++ = *(char *)buf;
if (--self->hdr_to_recv != 0) {
mp_uint_t hdr_sz = sock_stream->read(self->sock, p, self->hdr_to_recv, errcode);
if (hdr_sz == MP_STREAM_ERROR) {
@@ -246,8 +245,12 @@ STATIC mp_uint_t _webrepl_read(mp_obj_t self_in, void *buf, mp_uint_t size, int
}
if (self->data_to_recv != 0) {
- static byte filebuf[512];
- filebuf[0] = *(byte*)buf;
+ // Ports that don't have much available stack can make this filebuf static
+ #if MICROPY_PY_WEBREPL_STATIC_FILEBUF
+ static
+ #endif
+ byte filebuf[512];
+ filebuf[0] = *(byte *)buf;
mp_uint_t buf_sz = 1;
if (--self->data_to_recv != 0) {
size_t to_read = MIN(sizeof(filebuf) - 1, self->data_to_recv);
@@ -291,7 +294,7 @@ STATIC mp_uint_t _webrepl_read(mp_obj_t self_in, void *buf, mp_uint_t size, int
}
STATIC mp_uint_t webrepl_write(mp_obj_t self_in, const void *buf, mp_uint_t size, int *errcode) {
- mp_obj_webrepl_t *self = self_in;
+ mp_obj_webrepl_t *self = MP_OBJ_TO_PTR(self_in);
if (self->state == STATE_PASSWD) {
// Don't forward output until passwd is entered
return size;
@@ -345,7 +348,7 @@ STATIC const mp_obj_type_t webrepl_type = {
.name = MP_QSTR__webrepl,
.make_new = webrepl_make_new,
.protocol = &webrepl_stream_p,
- .locals_dict = (mp_obj_dict_t*)&webrepl_locals_dict,
+ .locals_dict = (mp_obj_dict_t *)&webrepl_locals_dict,
};
STATIC const mp_rom_map_elem_t webrepl_module_globals_table[] = {
@@ -358,7 +361,7 @@ STATIC MP_DEFINE_CONST_DICT(webrepl_module_globals, webrepl_module_globals_table
const mp_obj_module_t mp_module_webrepl = {
.base = { &mp_type_module },
- .globals = (mp_obj_dict_t*)&webrepl_module_globals,
+ .globals = (mp_obj_dict_t *)&webrepl_module_globals,
};
#endif // MICROPY_PY_WEBREPL
diff --git a/extmod/network_cyw43.c b/extmod/network_cyw43.c
new file mode 100644
index 0000000000..adbe427b1d
--- /dev/null
+++ b/extmod/network_cyw43.c
@@ -0,0 +1,460 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018-2019 Damien P. George
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include
+#include
+#include "py/runtime.h"
+#include "py/objstr.h"
+#include "py/mphal.h"
+
+#if MICROPY_PY_NETWORK_CYW43
+
+#include "lwip/netif.h"
+#include "drivers/cyw43/cyw43.h"
+#include "extmod/network_cyw43.h"
+#include "modnetwork.h"
+
+typedef struct _network_cyw43_obj_t {
+ mp_obj_base_t base;
+ cyw43_t *cyw;
+ int itf;
+} network_cyw43_obj_t;
+
+STATIC const network_cyw43_obj_t network_cyw43_wl0 = { { &mp_network_cyw43_type }, &cyw43_state, 0 };
+STATIC const network_cyw43_obj_t network_cyw43_wl1 = { { &mp_network_cyw43_type }, &cyw43_state, 1 };
+
+STATIC void network_cyw43_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
+ network_cyw43_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ struct netif *netif = &self->cyw->netif[self->itf];
+ int status = cyw43_tcpip_link_status(self->cyw, self->itf);
+ const char *status_str;
+ if (status == CYW43_LINK_DOWN) {
+ status_str = "down";
+ } else if (status == CYW43_LINK_JOIN || status == CYW43_LINK_NOIP) {
+ status_str = "join";
+ } else if (status == CYW43_LINK_UP) {
+ status_str = "up";
+ } else if (status == CYW43_LINK_NONET) {
+ status_str = "nonet";
+ } else if (status == CYW43_LINK_BADAUTH) {
+ status_str = "badauth";
+ } else {
+ status_str = "fail";
+ }
+ mp_printf(print, "",
+ self->itf == 0 ? "STA" : "AP",
+ status_str,
+ netif->ip_addr.addr & 0xff,
+ netif->ip_addr.addr >> 8 & 0xff,
+ netif->ip_addr.addr >> 16 & 0xff,
+ netif->ip_addr.addr >> 24
+ );
+}
+
+STATIC mp_obj_t network_cyw43_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
+ mp_arg_check_num(n_args, n_kw, 0, 1, false);
+ if (n_args == 0 || mp_obj_get_int(args[0]) == 0) {
+ return MP_OBJ_FROM_PTR(&network_cyw43_wl0);
+ } else {
+ return MP_OBJ_FROM_PTR(&network_cyw43_wl1);
+ }
+}
+
+STATIC mp_obj_t network_cyw43_send_ethernet(mp_obj_t self_in, mp_obj_t buf_in) {
+ network_cyw43_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ mp_buffer_info_t buf;
+ mp_get_buffer_raise(buf_in, &buf, MP_BUFFER_READ);
+ int ret = cyw43_send_ethernet(self->cyw, self->itf, buf.len, buf.buf, false);
+ if (ret) {
+ mp_raise_OSError(-ret);
+ }
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(network_cyw43_send_ethernet_obj, network_cyw43_send_ethernet);
+
+STATIC mp_obj_t network_cyw43_ioctl(mp_obj_t self_in, mp_obj_t cmd_in, mp_obj_t buf_in) {
+ network_cyw43_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ mp_buffer_info_t buf;
+ mp_get_buffer_raise(buf_in, &buf, MP_BUFFER_READ | MP_BUFFER_WRITE);
+ cyw43_ioctl(self->cyw, mp_obj_get_int(cmd_in), buf.len, buf.buf, self->itf);
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_3(network_cyw43_ioctl_obj, network_cyw43_ioctl);
+
+/*******************************************************************************/
+// network API
+
+STATIC mp_obj_t network_cyw43_deinit(mp_obj_t self_in) {
+ network_cyw43_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ cyw43_deinit(self->cyw);
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_cyw43_deinit_obj, network_cyw43_deinit);
+
+STATIC mp_obj_t network_cyw43_active(size_t n_args, const mp_obj_t *args) {
+ network_cyw43_obj_t *self = MP_OBJ_TO_PTR(args[0]);
+ if (n_args == 1) {
+ return mp_obj_new_bool(cyw43_tcpip_link_status(self->cyw, self->itf));
+ } else {
+ cyw43_wifi_set_up(self->cyw, self->itf, mp_obj_is_true(args[1]));
+ return mp_const_none;
+ }
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(network_cyw43_active_obj, 1, 2, network_cyw43_active);
+
+STATIC int network_cyw43_scan_cb(void *env, const cyw43_ev_scan_result_t *res) {
+ mp_obj_t list = MP_OBJ_FROM_PTR(env);
+
+ // Search for existing BSSID to remove duplicates
+ bool found = false;
+ size_t len;
+ mp_obj_t *items;
+ mp_obj_get_array(list, &len, &items);
+ for (size_t i = 0; i < len; ++i) {
+ mp_obj_tuple_t *t = MP_OBJ_TO_PTR(items[i]);
+ if (memcmp(res->bssid, ((mp_obj_str_t *)MP_OBJ_TO_PTR(t->items[1]))->data, sizeof(res->bssid)) == 0) {
+ if (res->rssi > MP_OBJ_SMALL_INT_VALUE(t->items[3])) {
+ t->items[3] = MP_OBJ_NEW_SMALL_INT(res->rssi);
+ }
+ t->items[5] = MP_OBJ_NEW_SMALL_INT(MP_OBJ_SMALL_INT_VALUE(t->items[5]) + 1);
+ found = true;
+ break;
+ }
+ }
+
+ // Add to list of results if wanted
+ if (!found) {
+ mp_obj_t tuple[6] = {
+ mp_obj_new_bytes(res->ssid, res->ssid_len),
+ mp_obj_new_bytes(res->bssid, sizeof(res->bssid)),
+ MP_OBJ_NEW_SMALL_INT(res->channel),
+ MP_OBJ_NEW_SMALL_INT(res->rssi),
+ MP_OBJ_NEW_SMALL_INT(res->auth_mode),
+ // mp_const_false, // hidden
+ MP_OBJ_NEW_SMALL_INT(1), // N
+ };
+ mp_obj_list_append(list, mp_obj_new_tuple(6, tuple));
+ }
+
+ return 0; // continue scan
+}
+
+STATIC mp_obj_t network_cyw43_scan(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ enum { ARG_passive, ARG_essid, ARG_bssid };
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_passive, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
+ { MP_QSTR_essid, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
+ { MP_QSTR_bssid, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
+ };
+
+ network_cyw43_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
+ mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
+ mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
+
+ cyw43_wifi_scan_options_t opts;
+ opts.scan_type = args[ARG_passive].u_bool ? 1 : 0;
+ if (args[ARG_essid].u_obj == mp_const_none) {
+ opts.ssid_len = 0;
+ } else {
+ mp_buffer_info_t ssid;
+ mp_get_buffer_raise(args[ARG_essid].u_obj, &ssid, MP_BUFFER_READ);
+ opts.ssid_len = MIN(ssid.len, sizeof(opts.ssid));
+ memcpy(opts.ssid, ssid.buf, opts.ssid_len);
+ }
+ if (args[ARG_bssid].u_obj == mp_const_none) {
+ memset(opts.bssid, 0xff, sizeof(opts.bssid));
+ } else {
+ mp_buffer_info_t bssid;
+ mp_get_buffer_raise(args[ARG_bssid].u_obj, &bssid, MP_BUFFER_READ);
+ memcpy(opts.bssid, bssid.buf, sizeof(opts.bssid));
+ }
+
+ mp_obj_t res = mp_obj_new_list(0, NULL);
+ int scan_res = cyw43_wifi_scan(self->cyw, &opts, MP_OBJ_TO_PTR(res), network_cyw43_scan_cb);
+
+ if (scan_res < 0) {
+ mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("STA must be active"));
+ }
+
+ // Wait for scan to finish, with a 10s timeout
+ uint32_t start = mp_hal_ticks_ms();
+ while (cyw43_wifi_scan_active(self->cyw) && mp_hal_ticks_ms() - start < 10000) {
+ MICROPY_EVENT_POLL_HOOK
+ }
+
+ return res;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_KW(network_cyw43_scan_obj, 1, network_cyw43_scan);
+
+STATIC mp_obj_t network_cyw43_connect(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ enum { ARG_essid, ARG_key, ARG_auth, ARG_bssid, ARG_channel };
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_essid, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
+ { MP_QSTR_key, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
+ { MP_QSTR_auth, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
+ { MP_QSTR_bssid, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
+ { MP_QSTR_channel, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
+ };
+
+ network_cyw43_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
+ mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
+ mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
+
+ mp_buffer_info_t ssid;
+ mp_get_buffer_raise(args[ARG_essid].u_obj, &ssid, MP_BUFFER_READ);
+ mp_buffer_info_t key;
+ key.buf = NULL;
+ if (args[ARG_key].u_obj != mp_const_none) {
+ mp_get_buffer_raise(args[ARG_key].u_obj, &key, MP_BUFFER_READ);
+ }
+ mp_buffer_info_t bssid;
+ bssid.buf = NULL;
+ if (args[ARG_bssid].u_obj != mp_const_none) {
+ mp_get_buffer_raise(args[ARG_bssid].u_obj, &bssid, MP_BUFFER_READ);
+ if (bssid.len != 6) {
+ mp_raise_ValueError(NULL);
+ }
+ }
+ int ret = cyw43_wifi_join(self->cyw, ssid.len, ssid.buf, key.len, key.buf, args[ARG_auth].u_int, bssid.buf, args[ARG_channel].u_int);
+ if (ret != 0) {
+ mp_raise_OSError(ret);
+ }
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_KW(network_cyw43_connect_obj, 1, network_cyw43_connect);
+
+STATIC mp_obj_t network_cyw43_disconnect(mp_obj_t self_in) {
+ network_cyw43_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ cyw43_wifi_leave(self->cyw, self->itf);
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_cyw43_disconnect_obj, network_cyw43_disconnect);
+
+STATIC mp_obj_t network_cyw43_isconnected(mp_obj_t self_in) {
+ network_cyw43_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ return mp_obj_new_bool(cyw43_tcpip_link_status(self->cyw, self->itf) == 3);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_cyw43_isconnected_obj, network_cyw43_isconnected);
+
+STATIC mp_obj_t network_cyw43_ifconfig(size_t n_args, const mp_obj_t *args) {
+ network_cyw43_obj_t *self = MP_OBJ_TO_PTR(args[0]);
+ return mod_network_nic_ifconfig(&self->cyw->netif[self->itf], n_args - 1, args + 1);
+}
+MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(network_cyw43_ifconfig_obj, 1, 2, network_cyw43_ifconfig);
+
+STATIC mp_obj_t network_cyw43_status(size_t n_args, const mp_obj_t *args) {
+ network_cyw43_obj_t *self = MP_OBJ_TO_PTR(args[0]);
+ (void)self;
+
+ if (n_args == 1) {
+ // no arguments: return link status
+ return MP_OBJ_NEW_SMALL_INT(cyw43_tcpip_link_status(self->cyw, self->itf));
+ }
+
+ // one argument: return status based on query parameter
+ switch (mp_obj_str_get_qstr(args[1])) {
+ case MP_QSTR_stations: {
+ // return list of connected stations
+ if (self->itf != CYW43_ITF_AP) {
+ mp_raise_ValueError(MP_ERROR_TEXT("AP required"));
+ }
+ int num_stas;
+ uint8_t macs[32 * 6];
+ cyw43_wifi_ap_get_stas(self->cyw, &num_stas, macs);
+ mp_obj_t list = mp_obj_new_list(num_stas, NULL);
+ for (int i = 0; i < num_stas; ++i) {
+ mp_obj_t tuple[1] = {
+ mp_obj_new_bytes(&macs[i * 6], 6),
+ };
+ ((mp_obj_list_t *)MP_OBJ_TO_PTR(list))->items[i] = mp_obj_new_tuple(1, tuple);
+ }
+ return list;
+ }
+ }
+
+ mp_raise_ValueError(MP_ERROR_TEXT("unknown status param"));
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(network_cyw43_status_obj, 1, 2, network_cyw43_status);
+
+static inline uint32_t nw_get_le32(const uint8_t *buf) {
+ return buf[0] | buf[1] << 8 | buf[2] << 16 | buf[3] << 24;
+}
+
+static inline void nw_put_le32(uint8_t *buf, uint32_t x) {
+ buf[0] = x;
+ buf[1] = x >> 8;
+ buf[2] = x >> 16;
+ buf[3] = x >> 24;
+}
+
+STATIC mp_obj_t network_cyw43_config(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) {
+ network_cyw43_obj_t *self = MP_OBJ_TO_PTR(args[0]);
+
+ if (kwargs->used == 0) {
+ // Get config value
+ if (n_args != 2) {
+ mp_raise_TypeError(MP_ERROR_TEXT("must query one param"));
+ }
+
+ switch (mp_obj_str_get_qstr(args[1])) {
+ case MP_QSTR_antenna: {
+ uint8_t buf[4];
+ cyw43_ioctl(self->cyw, CYW43_IOCTL_GET_ANTDIV, 4, buf, self->itf);
+ return MP_OBJ_NEW_SMALL_INT(nw_get_le32(buf));
+ }
+ case MP_QSTR_channel: {
+ uint8_t buf[4];
+ cyw43_ioctl(self->cyw, CYW43_IOCTL_GET_CHANNEL, 4, buf, self->itf);
+ return MP_OBJ_NEW_SMALL_INT(nw_get_le32(buf));
+ }
+ case MP_QSTR_essid: {
+ if (self->itf == CYW43_ITF_STA) {
+ uint8_t buf[36];
+ cyw43_ioctl(self->cyw, CYW43_IOCTL_GET_SSID, 36, buf, self->itf);
+ return mp_obj_new_str((const char *)buf + 4, nw_get_le32(buf));
+ } else {
+ size_t len;
+ const uint8_t *buf;
+ cyw43_wifi_ap_get_ssid(self->cyw, &len, &buf);
+ return mp_obj_new_str((const char *)buf, len);
+ }
+ }
+ case MP_QSTR_mac: {
+ uint8_t buf[6];
+ cyw43_wifi_get_mac(self->cyw, self->itf, buf);
+ return mp_obj_new_bytes(buf, 6);
+ }
+ case MP_QSTR_txpower: {
+ uint8_t buf[13];
+ memcpy(buf, "qtxpower\x00\x00\x00\x00\x00", 13);
+ cyw43_ioctl(self->cyw, CYW43_IOCTL_GET_VAR, 13, buf, self->itf);
+ return MP_OBJ_NEW_SMALL_INT(nw_get_le32(buf) / 4);
+ }
+ default:
+ mp_raise_ValueError(MP_ERROR_TEXT("unknown config param"));
+ }
+ } else {
+ // Set config value(s)
+ if (n_args != 1) {
+ mp_raise_TypeError(MP_ERROR_TEXT("can't specify pos and kw args"));
+ }
+
+ for (size_t i = 0; i < kwargs->alloc; ++i) {
+ if (MP_MAP_SLOT_IS_FILLED(kwargs, i)) {
+ mp_map_elem_t *e = &kwargs->table[i];
+ switch (mp_obj_str_get_qstr(e->key)) {
+ case MP_QSTR_antenna: {
+ uint8_t buf[4];
+ nw_put_le32(buf, mp_obj_get_int(e->value));
+ cyw43_ioctl(self->cyw, CYW43_IOCTL_SET_ANTDIV, 4, buf, self->itf);
+ break;
+ }
+ case MP_QSTR_channel: {
+ cyw43_wifi_ap_set_channel(self->cyw, mp_obj_get_int(e->value));
+ break;
+ }
+ case MP_QSTR_essid: {
+ size_t len;
+ const char *str = mp_obj_str_get_data(e->value, &len);
+ cyw43_wifi_ap_set_ssid(self->cyw, len, (const uint8_t *)str);
+ break;
+ }
+ case MP_QSTR_monitor: {
+ mp_int_t value = mp_obj_get_int(e->value);
+ uint8_t buf[9 + 4];
+ memcpy(buf, "allmulti\x00", 9);
+ nw_put_le32(buf + 9, value);
+ cyw43_ioctl(self->cyw, CYW43_IOCTL_SET_VAR, 9 + 4, buf, self->itf);
+ nw_put_le32(buf, value);
+ cyw43_ioctl(self->cyw, CYW43_IOCTL_SET_MONITOR, 4, buf, self->itf);
+ if (value) {
+ self->cyw->trace_flags |= CYW43_TRACE_MAC;
+ } else {
+ self->cyw->trace_flags &= ~CYW43_TRACE_MAC;
+ }
+ break;
+ }
+ case MP_QSTR_password: {
+ size_t len;
+ const char *str = mp_obj_str_get_data(e->value, &len);
+ cyw43_wifi_ap_set_password(self->cyw, len, (const uint8_t *)str);
+ break;
+ }
+ case MP_QSTR_pm: {
+ cyw43_wifi_pm(self->cyw, mp_obj_get_int(e->value));
+ break;
+ }
+ case MP_QSTR_trace: {
+ self->cyw->trace_flags = mp_obj_get_int(e->value);
+ break;
+ }
+ case MP_QSTR_txpower: {
+ mp_int_t dbm = mp_obj_get_int(e->value);
+ uint8_t buf[9 + 4];
+ memcpy(buf, "qtxpower\x00", 9);
+ nw_put_le32(buf + 9, dbm * 4);
+ cyw43_ioctl(self->cyw, CYW43_IOCTL_SET_VAR, 9 + 4, buf, self->itf);
+ break;
+ }
+ default:
+ mp_raise_ValueError(MP_ERROR_TEXT("unknown config param"));
+ }
+ }
+ }
+
+ return mp_const_none;
+ }
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_KW(network_cyw43_config_obj, 1, network_cyw43_config);
+
+/*******************************************************************************/
+// class bindings
+
+STATIC const mp_rom_map_elem_t network_cyw43_locals_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_send_ethernet), MP_ROM_PTR(&network_cyw43_send_ethernet_obj) },
+ { MP_ROM_QSTR(MP_QSTR_ioctl), MP_ROM_PTR(&network_cyw43_ioctl_obj) },
+
+ { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&network_cyw43_deinit_obj) },
+ { MP_ROM_QSTR(MP_QSTR_active), MP_ROM_PTR(&network_cyw43_active_obj) },
+ { MP_ROM_QSTR(MP_QSTR_scan), MP_ROM_PTR(&network_cyw43_scan_obj) },
+ { MP_ROM_QSTR(MP_QSTR_connect), MP_ROM_PTR(&network_cyw43_connect_obj) },
+ { MP_ROM_QSTR(MP_QSTR_disconnect), MP_ROM_PTR(&network_cyw43_disconnect_obj) },
+ { MP_ROM_QSTR(MP_QSTR_isconnected), MP_ROM_PTR(&network_cyw43_isconnected_obj) },
+ { MP_ROM_QSTR(MP_QSTR_ifconfig), MP_ROM_PTR(&network_cyw43_ifconfig_obj) },
+ { MP_ROM_QSTR(MP_QSTR_status), MP_ROM_PTR(&network_cyw43_status_obj) },
+ { MP_ROM_QSTR(MP_QSTR_config), MP_ROM_PTR(&network_cyw43_config_obj) },
+};
+STATIC MP_DEFINE_CONST_DICT(network_cyw43_locals_dict, network_cyw43_locals_dict_table);
+
+const mp_obj_type_t mp_network_cyw43_type = {
+ { &mp_type_type },
+ .name = MP_QSTR_CYW43,
+ .print = network_cyw43_print,
+ .make_new = network_cyw43_make_new,
+ .locals_dict = (mp_obj_dict_t *)&network_cyw43_locals_dict,
+};
+
+#endif // MICROPY_PY_NETWORK_CYW43
diff --git a/extmod/network_cyw43.h b/extmod/network_cyw43.h
new file mode 100644
index 0000000000..4228bf6e8f
--- /dev/null
+++ b/extmod/network_cyw43.h
@@ -0,0 +1,31 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Damien P. George
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#ifndef MICROPY_INCLUDED_EXTMOD_NETWORK_CYW43_H
+#define MICROPY_INCLUDED_EXTMOD_NETWORK_CYW43_H
+
+extern const mp_obj_type_t mp_network_cyw43_type;
+
+#endif // MICROPY_INCLUDED_EXTMOD_NETWORK_CYW43_H
diff --git a/extmod/nimble/bsp/bsp.h b/extmod/nimble/bsp/bsp.h
new file mode 100644
index 0000000000..8b1a393741
--- /dev/null
+++ b/extmod/nimble/bsp/bsp.h
@@ -0,0 +1 @@
+// empty
diff --git a/extmod/nimble/hal/hal_gpio.h b/extmod/nimble/hal/hal_gpio.h
new file mode 100644
index 0000000000..8b1a393741
--- /dev/null
+++ b/extmod/nimble/hal/hal_gpio.h
@@ -0,0 +1 @@
+// empty
diff --git a/extmod/nimble/hal/hal_uart.c b/extmod/nimble/hal/hal_uart.c
new file mode 100644
index 0000000000..fba82b8304
--- /dev/null
+++ b/extmod/nimble/hal/hal_uart.c
@@ -0,0 +1,85 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018-2019 Damien P. George
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "py/runtime.h"
+#include "py/mphal.h"
+#include "pin_static_af.h"
+#include "nimble/ble.h"
+#include "extmod/nimble/hal/hal_uart.h"
+#include "extmod/modbluetooth_hci.h"
+#include "extmod/nimble/nimble/nimble_hci_uart.h"
+
+#if MICROPY_PY_BLUETOOTH && MICROPY_BLUETOOTH_NIMBLE
+
+static hal_uart_tx_cb_t hal_uart_tx_cb;
+static void *hal_uart_tx_arg;
+static hal_uart_rx_cb_t hal_uart_rx_cb;
+static void *hal_uart_rx_arg;
+
+int hal_uart_init_cbs(uint32_t port, hal_uart_tx_cb_t tx_cb, void *tx_arg, hal_uart_rx_cb_t rx_cb, void *rx_arg) {
+ hal_uart_tx_cb = tx_cb;
+ hal_uart_tx_arg = tx_arg;
+ hal_uart_rx_cb = rx_cb;
+ hal_uart_rx_arg = rx_arg;
+ return 0; // success
+}
+
+int hal_uart_config(uint32_t port, uint32_t baudrate, uint32_t bits, uint32_t stop, uint32_t parity, uint32_t flow) {
+ mp_bluetooth_hci_uart_init(port);
+ mp_bluetooth_hci_uart_set_baudrate(baudrate);
+ return mp_bluetooth_hci_uart_activate();
+}
+
+void hal_uart_start_tx(uint32_t port) {
+ size_t len = 0;
+ for (;;) {
+ int data = hal_uart_tx_cb(hal_uart_tx_arg);
+ if (data == -1) {
+ break;
+ }
+ mp_bluetooth_hci_cmd_buf[len++] = data;
+ }
+
+ #if 0
+ printf("[% 8d] BTUTX: %02x", mp_hal_ticks_ms(), hci_cmd_buf[0]);
+ for (int i = 1; i < len; ++i) {
+ printf(":%02x", hci_cmd_buf[i]);
+ }
+ printf("\n");
+ #endif
+
+ mp_bluetooth_nimble_hci_uart_tx_strn((void*)mp_bluetooth_hci_cmd_buf, len);
+}
+
+int hal_uart_close(uint32_t port) {
+ return 0; // success
+}
+
+void mp_bluetooth_nimble_hci_uart_process(void) {
+ mp_bluetooth_nimble_hci_uart_rx(hal_uart_rx_cb, hal_uart_rx_arg);
+}
+
+#endif // MICROPY_PY_BLUETOOTH && MICROPY_BLUETOOTH_NIMBLE
diff --git a/extmod/nimble/hal/hal_uart.h b/extmod/nimble/hal/hal_uart.h
new file mode 100644
index 0000000000..0ef04bc81e
--- /dev/null
+++ b/extmod/nimble/hal/hal_uart.h
@@ -0,0 +1,19 @@
+#ifndef MICROPY_INCLUDED_EXTMOD_NIMBLE_HAL_HAL_UART_H
+#define MICROPY_INCLUDED_EXTMOD_NIMBLE_HAL_HAL_UART_H
+
+#include
+
+#define SYSINIT_PANIC_ASSERT_MSG(cond, msg)
+
+#define HAL_UART_PARITY_NONE (0)
+
+typedef int (*hal_uart_tx_cb_t)(void *arg);
+typedef int (*hal_uart_rx_cb_t)(void *arg, uint8_t data);
+
+// Called by NimBLE, implemented in hal_uart.c.
+int hal_uart_init_cbs(uint32_t port, hal_uart_tx_cb_t tx_cb, void *tx_arg, hal_uart_rx_cb_t rx_cb, void *rx_arg);
+int hal_uart_config(uint32_t port, uint32_t baud, uint32_t bits, uint32_t stop, uint32_t parity, uint32_t flow);
+void hal_uart_start_tx(uint32_t port);
+int hal_uart_close(uint32_t port);
+
+#endif // MICROPY_INCLUDED_EXTMOD_NIMBLE_HAL_HAL_UART_H
diff --git a/extmod/nimble/modbluetooth_nimble.c b/extmod/nimble/modbluetooth_nimble.c
new file mode 100644
index 0000000000..e51f2747ec
--- /dev/null
+++ b/extmod/nimble/modbluetooth_nimble.c
@@ -0,0 +1,900 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Damien P. George
+ * Copyright (c) 2019-2020 Jim Mussared
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "py/runtime.h"
+#include "py/mperrno.h"
+#include "py/mphal.h"
+
+#if MICROPY_PY_BLUETOOTH && MICROPY_BLUETOOTH_NIMBLE
+
+#include "extmod/nimble/modbluetooth_nimble.h"
+#include "extmod/modbluetooth.h"
+
+#include "host/ble_hs.h"
+#include "host/util/util.h"
+#include "nimble/ble.h"
+#include "nimble/nimble_port.h"
+#include "services/gap/ble_svc_gap.h"
+#include "services/gatt/ble_svc_gatt.h"
+
+#ifndef MICROPY_PY_BLUETOOTH_DEFAULT_GAP_NAME
+#define MICROPY_PY_BLUETOOTH_DEFAULT_GAP_NAME "MPY NIMBLE"
+#endif
+
+#define DEBUG_EVENT_printf(...) // printf(__VA_ARGS__)
+
+#define ERRNO_BLUETOOTH_NOT_ACTIVE MP_ENODEV
+
+// Any BLE_HS_xxx code not in this table will default to MP_EIO.
+STATIC int8_t ble_hs_err_to_errno_table[] = {
+ [BLE_HS_EAGAIN] = MP_EAGAIN,
+ [BLE_HS_EALREADY] = MP_EALREADY,
+ [BLE_HS_EINVAL] = MP_EINVAL,
+ [BLE_HS_ENOENT] = MP_ENOENT,
+ [BLE_HS_ENOMEM] = MP_ENOMEM,
+ [BLE_HS_ENOTCONN] = MP_ENOTCONN,
+ [BLE_HS_ENOTSUP] = MP_EOPNOTSUPP,
+ [BLE_HS_ETIMEOUT] = MP_ETIMEDOUT,
+ [BLE_HS_EDONE] = MP_EIO, // TODO: Maybe should be MP_EISCONN (connect uses this for "already connected").
+ [BLE_HS_EBUSY] = MP_EBUSY,
+};
+
+STATIC int ble_hs_err_to_errno(int err) {
+ if (!err) {
+ return 0;
+ }
+ if (0 <= err && err < MP_ARRAY_SIZE(ble_hs_err_to_errno_table) && ble_hs_err_to_errno_table[err]) {
+ return ble_hs_err_to_errno_table[err];
+ } else {
+ return MP_EIO;
+ }
+}
+
+// Note: modbluetooth UUIDs store their data in LE.
+STATIC ble_uuid_t *create_nimble_uuid(const mp_obj_bluetooth_uuid_t *uuid, ble_uuid_any_t *storage) {
+ if (uuid->type == MP_BLUETOOTH_UUID_TYPE_16) {
+ ble_uuid16_t *result = storage ? &storage->u16 : m_new(ble_uuid16_t, 1);
+ result->u.type = BLE_UUID_TYPE_16;
+ result->value = (uuid->data[1] << 8) | uuid->data[0];
+ return (ble_uuid_t *)result;
+ } else if (uuid->type == MP_BLUETOOTH_UUID_TYPE_32) {
+ ble_uuid32_t *result = storage ? &storage->u32 : m_new(ble_uuid32_t, 1);
+ result->u.type = BLE_UUID_TYPE_32;
+ result->value = (uuid->data[1] << 24) | (uuid->data[1] << 16) | (uuid->data[1] << 8) | uuid->data[0];
+ return (ble_uuid_t *)result;
+ } else if (uuid->type == MP_BLUETOOTH_UUID_TYPE_128) {
+ ble_uuid128_t *result = storage ? &storage->u128 : m_new(ble_uuid128_t, 1);
+ result->u.type = BLE_UUID_TYPE_128;
+ memcpy(result->value, uuid->data, 16);
+ return (ble_uuid_t *)result;
+ } else {
+ return NULL;
+ }
+}
+
+// modbluetooth (and the layers above it) work in BE for addresses, Nimble works in LE.
+STATIC void reverse_addr_byte_order(uint8_t *addr_out, const uint8_t *addr_in) {
+ for (int i = 0; i < 6; ++i) {
+ addr_out[i] = addr_in[5 - i];
+ }
+}
+
+#if MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE
+
+STATIC mp_obj_bluetooth_uuid_t create_mp_uuid(const ble_uuid_any_t *uuid) {
+ mp_obj_bluetooth_uuid_t result;
+ switch (uuid->u.type) {
+ case BLE_UUID_TYPE_16:
+ result.type = MP_BLUETOOTH_UUID_TYPE_16;
+ result.data[0] = uuid->u16.value & 0xff;
+ result.data[1] = (uuid->u16.value >> 8) & 0xff;
+ break;
+ case BLE_UUID_TYPE_32:
+ result.type = MP_BLUETOOTH_UUID_TYPE_32;
+ result.data[0] = uuid->u32.value & 0xff;
+ result.data[1] = (uuid->u32.value >> 8) & 0xff;
+ result.data[2] = (uuid->u32.value >> 16) & 0xff;
+ result.data[3] = (uuid->u32.value >> 24) & 0xff;
+ break;
+ case BLE_UUID_TYPE_128:
+ result.type = MP_BLUETOOTH_UUID_TYPE_128;
+ memcpy(result.data, uuid->u128.value, 16);
+ break;
+ default:
+ assert(false);
+ }
+ return result;
+}
+
+STATIC ble_addr_t create_nimble_addr(uint8_t addr_type, const uint8_t *addr) {
+ ble_addr_t addr_nimble;
+ addr_nimble.type = addr_type;
+ // Incoming addr is from modbluetooth (BE), so copy and convert to LE for Nimble.
+ reverse_addr_byte_order(addr_nimble.val, addr);
+ return addr_nimble;
+}
+
+#endif // MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE
+
+volatile int mp_bluetooth_nimble_ble_state = MP_BLUETOOTH_NIMBLE_BLE_STATE_OFF;
+
+STATIC void reset_cb(int reason) {
+ (void)reason;
+}
+
+STATIC void sync_cb(void) {
+ int rc;
+ ble_addr_t addr;
+
+ rc = ble_hs_util_ensure_addr(0); // prefer public address
+ if (rc != 0) {
+ // https://mynewt.apache.org/latest/tutorials/ble/eddystone.html#configure-the-nimble-stack-with-an-address
+ #if MICROPY_PY_BLUETOOTH_RANDOM_ADDR
+ rc = ble_hs_id_gen_rnd(1, &addr);
+ assert(rc == 0);
+ rc = ble_hs_id_set_rnd(addr.val);
+ assert(rc == 0);
+ #else
+ uint8_t addr_be[6];
+ mp_hal_get_mac(MP_HAL_MAC_BDADDR, addr_be);
+ reverse_addr_byte_order(addr.val, addr_be);
+ // ble_hs_id_set_pub(addr.val);
+ rc = ble_hs_id_set_rnd(addr.val);
+ assert(rc == 0);
+ #endif
+
+ rc = ble_hs_util_ensure_addr(0); // prefer public address
+ assert(rc == 0);
+ }
+
+ if (MP_BLUETOOTH_DEFAULT_ATTR_LEN > 20) {
+ rc = ble_att_set_preferred_mtu(MP_BLUETOOTH_DEFAULT_ATTR_LEN + 3);
+ assert(rc == 0);
+ }
+
+ ble_svc_gap_device_name_set(MICROPY_PY_BLUETOOTH_DEFAULT_GAP_NAME);
+
+ mp_bluetooth_nimble_ble_state = MP_BLUETOOTH_NIMBLE_BLE_STATE_ACTIVE;
+}
+
+STATIC void gatts_register_cb(struct ble_gatt_register_ctxt *ctxt, void *arg) {
+ if (!mp_bluetooth_is_active()) {
+ return;
+ }
+ switch (ctxt->op) {
+ case BLE_GATT_REGISTER_OP_SVC:
+ // Called when a service is successfully registered.
+ DEBUG_EVENT_printf("gatts_register_cb: svc uuid=%p handle=%d\n", &ctxt->svc.svc_def->uuid, ctxt->svc.handle);
+ break;
+
+ case BLE_GATT_REGISTER_OP_CHR:
+ // Called when a characteristic is successfully registered.
+ DEBUG_EVENT_printf("gatts_register_cb: chr uuid=%p def_handle=%d val_handle=%d\n", &ctxt->chr.chr_def->uuid, ctxt->chr.def_handle, ctxt->chr.val_handle);
+
+ // Note: We will get this event for the default GAP Service, meaning that we allocate storage for the
+ // "device name" and "appearance" characteristics, even though we never see the reads for them.
+ // TODO: Possibly check if the service UUID is 0x1801 and ignore?
+
+ // Allocate the gatts_db storage for this characteristic.
+ // Although this function is a callback, it's called synchronously from ble_hs_sched_start/ble_gatts_start, so safe to allocate.
+ mp_bluetooth_gatts_db_create_entry(MP_STATE_PORT(bluetooth_nimble_root_pointers)->gatts_db, ctxt->chr.val_handle, MP_BLUETOOTH_DEFAULT_ATTR_LEN);
+ break;
+
+ case BLE_GATT_REGISTER_OP_DSC:
+ // Called when a descriptor is successfully registered.
+ // Note: This is event is not called for the CCCD.
+ DEBUG_EVENT_printf("gatts_register_cb: dsc uuid=%p handle=%d\n", &ctxt->dsc.dsc_def->uuid, ctxt->dsc.handle);
+
+ // See above, safe to alloc.
+ mp_bluetooth_gatts_db_create_entry(MP_STATE_PORT(bluetooth_nimble_root_pointers)->gatts_db, ctxt->dsc.handle, MP_BLUETOOTH_DEFAULT_ATTR_LEN);
+
+ // Unlike characteristics, we have to manually provide a way to get the handle back to the register method.
+ *((uint16_t *)ctxt->dsc.dsc_def->arg) = ctxt->dsc.handle;
+ break;
+
+ default:
+ DEBUG_EVENT_printf("gatts_register_cb: unknown op %d\n", ctxt->op);
+ break;
+ }
+}
+
+STATIC int gap_event_cb(struct ble_gap_event *event, void *arg) {
+ DEBUG_EVENT_printf("gap_event_cb: type=%d\n", event->type);
+ if (!mp_bluetooth_is_active()) {
+ return 0;
+ }
+ struct ble_gap_conn_desc desc;
+ uint8_t addr[6] = {0};
+
+ switch (event->type) {
+ case BLE_GAP_EVENT_CONNECT:
+ if (event->connect.status == 0) {
+ // Connection established.
+ ble_gap_conn_find(event->connect.conn_handle, &desc);
+ reverse_addr_byte_order(addr, desc.peer_id_addr.val);
+ mp_bluetooth_gap_on_connected_disconnected(MP_BLUETOOTH_IRQ_CENTRAL_CONNECT, event->connect.conn_handle, desc.peer_id_addr.type, addr);
+ } else {
+ // Connection failed.
+ mp_bluetooth_gap_on_connected_disconnected(MP_BLUETOOTH_IRQ_CENTRAL_DISCONNECT, event->connect.conn_handle, 0xff, addr);
+ }
+ break;
+
+ case BLE_GAP_EVENT_DISCONNECT:
+ // Disconnect.
+ reverse_addr_byte_order(addr, event->disconnect.conn.peer_id_addr.val);
+ mp_bluetooth_gap_on_connected_disconnected(MP_BLUETOOTH_IRQ_CENTRAL_DISCONNECT, event->disconnect.conn.conn_handle, event->disconnect.conn.peer_id_addr.type, addr);
+ break;
+
+ case BLE_GAP_EVENT_NOTIFY_TX: {
+ DEBUG_EVENT_printf("gap_event_cb: notify_tx: %d %d\n", event->notify_tx.indication, event->notify_tx.status);
+ // This event corresponds to either a sent notify/indicate (status == 0), or an indication confirmation (status != 0).
+ if (event->notify_tx.indication && event->notify_tx.status != 0) {
+ // Map "done/ack" to 0, otherwise pass the status directly.
+ mp_bluetooth_gatts_on_indicate_complete(event->notify_tx.conn_handle, event->notify_tx.attr_handle, event->notify_tx.status == BLE_HS_EDONE ? 0 : event->notify_tx.status);
+ }
+ }
+ }
+
+ return 0;
+}
+
+int mp_bluetooth_init(void) {
+ DEBUG_EVENT_printf("mp_bluetooth_init\n");
+ // Clean up if necessary.
+ mp_bluetooth_deinit();
+
+ ble_hs_cfg.reset_cb = reset_cb;
+ ble_hs_cfg.sync_cb = sync_cb;
+ ble_hs_cfg.gatts_register_cb = gatts_register_cb;
+ ble_hs_cfg.store_status_cb = ble_store_util_status_rr;
+
+ MP_STATE_PORT(bluetooth_nimble_root_pointers) = m_new0(mp_bluetooth_nimble_root_pointers_t, 1);
+ mp_bluetooth_gatts_db_create(&MP_STATE_PORT(bluetooth_nimble_root_pointers)->gatts_db);
+
+ mp_bluetooth_nimble_ble_state = MP_BLUETOOTH_NIMBLE_BLE_STATE_STARTING;
+
+ mp_bluetooth_nimble_port_preinit();
+ nimble_port_init();
+ mp_bluetooth_nimble_port_postinit();
+
+ // By default, just register the default gap/gatt service.
+ ble_svc_gap_init();
+ ble_svc_gatt_init();
+
+ mp_bluetooth_nimble_port_start();
+
+ // Wait for sync callback
+ while (mp_bluetooth_nimble_ble_state != MP_BLUETOOTH_NIMBLE_BLE_STATE_ACTIVE) {
+ MICROPY_EVENT_POLL_HOOK
+ }
+ DEBUG_EVENT_printf("mp_bluetooth_init: ready\n");
+
+ return 0;
+}
+
+// Called when the host stop procedure has completed.
+STATIC void ble_hs_shutdown_stop_cb(int status, void *arg) {
+ mp_bluetooth_nimble_ble_state = MP_BLUETOOTH_NIMBLE_BLE_STATE_OFF;
+}
+
+STATIC struct ble_hs_stop_listener ble_hs_shutdown_stop_listener;
+
+void mp_bluetooth_deinit(void) {
+ DEBUG_EVENT_printf("mp_bluetooth_deinit\n");
+ if (mp_bluetooth_nimble_ble_state == MP_BLUETOOTH_NIMBLE_BLE_STATE_OFF) {
+ return;
+ }
+
+ mp_bluetooth_gap_advertise_stop();
+ #if MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE
+ mp_bluetooth_gap_scan_stop();
+ #endif
+
+ mp_bluetooth_nimble_ble_state = MP_BLUETOOTH_NIMBLE_BLE_STATE_STOPPING;
+
+ ble_hs_stop(&ble_hs_shutdown_stop_listener, ble_hs_shutdown_stop_cb, NULL);
+
+ while (mp_bluetooth_nimble_ble_state != MP_BLUETOOTH_NIMBLE_BLE_STATE_OFF) {
+ MICROPY_EVENT_POLL_HOOK
+ }
+
+ mp_bluetooth_nimble_port_deinit();
+
+ MP_STATE_PORT(bluetooth_nimble_root_pointers) = NULL;
+ DEBUG_EVENT_printf("mp_bluetooth_deinit: shut down\n");
+}
+
+bool mp_bluetooth_is_active(void) {
+ return mp_bluetooth_nimble_ble_state == MP_BLUETOOTH_NIMBLE_BLE_STATE_ACTIVE;
+}
+
+void mp_bluetooth_get_device_addr(uint8_t *addr) {
+ #if MICROPY_PY_BLUETOOTH_RANDOM_ADDR
+ uint8_t addr_le[6];
+ int rc = ble_hs_id_copy_addr(BLE_ADDR_RANDOM, addr_le, NULL);
+ if (rc != 0) {
+ // Even with MICROPY_PY_BLUETOOTH_RANDOM_ADDR enabled the public address may
+ // be used instead, in which case there is no random address.
+ ble_hs_id_copy_addr(BLE_ADDR_PUBLIC, addr_le, NULL);
+ }
+ reverse_addr_byte_order(addr, addr_le);
+ #else
+ mp_hal_get_mac(MP_HAL_MAC_BDADDR, addr);
+ #endif
+}
+
+size_t mp_bluetooth_gap_get_device_name(const uint8_t **buf) {
+ const char *name = ble_svc_gap_device_name();
+ *buf = (const uint8_t *)name;
+ return strlen(name);
+}
+
+int mp_bluetooth_gap_set_device_name(const uint8_t *buf, size_t len) {
+ char tmp_buf[MYNEWT_VAL(BLE_SVC_GAP_DEVICE_NAME_MAX_LENGTH) + 1];
+ if (len + 1 > sizeof(tmp_buf)) {
+ return MP_EINVAL;
+ }
+ memcpy(tmp_buf, buf, len);
+ tmp_buf[len] = '\0';
+ return ble_hs_err_to_errno(ble_svc_gap_device_name_set(tmp_buf));
+}
+
+int mp_bluetooth_gap_advertise_start(bool connectable, int32_t interval_us, const uint8_t *adv_data, size_t adv_data_len, const uint8_t *sr_data, size_t sr_data_len) {
+ if (!mp_bluetooth_is_active()) {
+ return ERRNO_BLUETOOTH_NOT_ACTIVE;
+ }
+
+ mp_bluetooth_gap_advertise_stop();
+
+ int ret;
+ if (adv_data) {
+ ret = ble_gap_adv_set_data(adv_data, adv_data_len);
+ if (ret != 0) {
+ return ble_hs_err_to_errno(ret);
+ }
+ }
+
+ if (sr_data) {
+ ret = ble_gap_adv_rsp_set_data(sr_data, sr_data_len);
+ if (ret != 0) {
+ return ble_hs_err_to_errno(ret);
+ }
+ }
+
+ struct ble_gap_adv_params adv_params = {
+ .conn_mode = connectable ? BLE_GAP_CONN_MODE_UND : BLE_GAP_CONN_MODE_NON,
+ .disc_mode = BLE_GAP_DISC_MODE_GEN,
+ .itvl_min = interval_us / BLE_HCI_ADV_ITVL, // convert to 625us units.
+ .itvl_max = interval_us / BLE_HCI_ADV_ITVL,
+ .channel_map = 7, // all 3 channels.
+ };
+
+ ret = ble_gap_adv_start(BLE_OWN_ADDR_PUBLIC, NULL, BLE_HS_FOREVER, &adv_params, gap_event_cb, NULL);
+ if (ret == 0) {
+ return 0;
+ }
+ ret = ble_gap_adv_start(BLE_OWN_ADDR_RPA_PUBLIC_DEFAULT, NULL, BLE_HS_FOREVER, &adv_params, gap_event_cb, NULL);
+ if (ret == 0) {
+ return 0;
+ }
+ ret = ble_gap_adv_start(BLE_OWN_ADDR_RPA_RANDOM_DEFAULT, NULL, BLE_HS_FOREVER, &adv_params, gap_event_cb, NULL);
+ if (ret == 0) {
+ return 0;
+ }
+ ret = ble_gap_adv_start(BLE_OWN_ADDR_RANDOM, NULL, BLE_HS_FOREVER, &adv_params, gap_event_cb, NULL);
+ if (ret == 0) {
+ return 0;
+ }
+ DEBUG_EVENT_printf("ble_gap_adv_start: %d\n", ret);
+
+ return ble_hs_err_to_errno(ret);
+}
+
+void mp_bluetooth_gap_advertise_stop(void) {
+ if (ble_gap_adv_active()) {
+ ble_gap_adv_stop();
+ }
+}
+
+static int characteristic_access_cb(uint16_t conn_handle, uint16_t value_handle, struct ble_gatt_access_ctxt *ctxt, void *arg) {
+ DEBUG_EVENT_printf("characteristic_access_cb: conn_handle=%u value_handle=%u op=%u\n", conn_handle, value_handle, ctxt->op);
+ if (!mp_bluetooth_is_active()) {
+ return 0;
+ }
+ mp_bluetooth_gatts_db_entry_t *entry;
+ switch (ctxt->op) {
+ case BLE_GATT_ACCESS_OP_READ_CHR:
+ case BLE_GATT_ACCESS_OP_READ_DSC:
+ #if MICROPY_PY_BLUETOOTH_GATTS_ON_READ_CALLBACK
+ // Allow Python code to override (by using gatts_write), or deny (by returning false) the read.
+ if (!mp_bluetooth_gatts_on_read_request(conn_handle, value_handle)) {
+ return BLE_ATT_ERR_READ_NOT_PERMITTED;
+ }
+ #endif
+
+ entry = mp_bluetooth_gatts_db_lookup(MP_STATE_PORT(bluetooth_nimble_root_pointers)->gatts_db, value_handle);
+ if (!entry) {
+ return BLE_ATT_ERR_ATTR_NOT_FOUND;
+ }
+
+ os_mbuf_append(ctxt->om, entry->data, entry->data_len);
+
+ return 0;
+ case BLE_GATT_ACCESS_OP_WRITE_CHR:
+ case BLE_GATT_ACCESS_OP_WRITE_DSC:
+ entry = mp_bluetooth_gatts_db_lookup(MP_STATE_PORT(bluetooth_nimble_root_pointers)->gatts_db, value_handle);
+ if (!entry) {
+ return BLE_ATT_ERR_ATTR_NOT_FOUND;
+ }
+
+ size_t offset = 0;
+ if (entry->append) {
+ offset = entry->data_len;
+ }
+ entry->data_len = MIN(entry->data_alloc, OS_MBUF_PKTLEN(ctxt->om) + offset);
+ os_mbuf_copydata(ctxt->om, 0, entry->data_len - offset, entry->data + offset);
+
+ mp_bluetooth_gatts_on_write(conn_handle, value_handle);
+
+ return 0;
+ }
+ return BLE_ATT_ERR_UNLIKELY;
+}
+
+int mp_bluetooth_gatts_register_service_begin(bool append) {
+ if (!mp_bluetooth_is_active()) {
+ return ERRNO_BLUETOOTH_NOT_ACTIVE;
+ }
+ int ret = ble_gatts_reset();
+ if (ret != 0) {
+ return ble_hs_err_to_errno(ret);
+ }
+
+ // Reset the gatt characteristic value db.
+ mp_bluetooth_gatts_db_reset(MP_STATE_PORT(bluetooth_nimble_root_pointers)->gatts_db);
+
+ // By default, just register the default gap/gatt service.
+ ble_svc_gap_init();
+ ble_svc_gatt_init();
+
+ if (!append) {
+ // Unref any previous service definitions.
+ for (int i = 0; i < MP_STATE_PORT(bluetooth_nimble_root_pointers)->n_services; ++i) {
+ MP_STATE_PORT(bluetooth_nimble_root_pointers)->services[i] = NULL;
+ }
+ MP_STATE_PORT(bluetooth_nimble_root_pointers)->n_services = 0;
+ }
+
+ return 0;
+}
+
+int mp_bluetooth_gatts_register_service_end() {
+ int ret = ble_gatts_start();
+ if (ret != 0) {
+ return ble_hs_err_to_errno(ret);
+ }
+
+ return 0;
+}
+
+int mp_bluetooth_gatts_register_service(mp_obj_bluetooth_uuid_t *service_uuid, mp_obj_bluetooth_uuid_t **characteristic_uuids, uint8_t *characteristic_flags, mp_obj_bluetooth_uuid_t **descriptor_uuids, uint8_t *descriptor_flags, uint8_t *num_descriptors, uint16_t *handles, size_t num_characteristics) {
+ if (MP_STATE_PORT(bluetooth_nimble_root_pointers)->n_services == MP_BLUETOOTH_NIMBLE_MAX_SERVICES) {
+ return MP_E2BIG;
+ }
+ size_t handle_index = 0;
+ size_t descriptor_index = 0;
+
+ struct ble_gatt_chr_def *characteristics = m_new(struct ble_gatt_chr_def, num_characteristics + 1);
+ for (size_t i = 0; i < num_characteristics; ++i) {
+ characteristics[i].uuid = create_nimble_uuid(characteristic_uuids[i], NULL);
+ characteristics[i].access_cb = characteristic_access_cb;
+ characteristics[i].arg = NULL;
+ characteristics[i].flags = characteristic_flags[i];
+ characteristics[i].min_key_size = 0;
+ characteristics[i].val_handle = &handles[handle_index];
+ ++handle_index;
+
+ if (num_descriptors[i] == 0) {
+ characteristics[i].descriptors = NULL;
+ } else {
+ struct ble_gatt_dsc_def *descriptors = m_new(struct ble_gatt_dsc_def, num_descriptors[i] + 1);
+
+ for (size_t j = 0; j < num_descriptors[i]; ++j) {
+ descriptors[j].uuid = create_nimble_uuid(descriptor_uuids[descriptor_index], NULL);
+ descriptors[j].access_cb = characteristic_access_cb;
+ descriptors[j].att_flags = descriptor_flags[descriptor_index];
+ descriptors[j].min_key_size = 0;
+ // Unlike characteristic, Nimble doesn't provide an automatic way to remember the handle, so use the arg.
+ descriptors[j].arg = &handles[handle_index];
+ ++descriptor_index;
+ ++handle_index;
+ }
+ descriptors[num_descriptors[i]].uuid = NULL; // no more descriptors
+
+ characteristics[i].descriptors = descriptors;
+ }
+ }
+ characteristics[num_characteristics].uuid = NULL; // no more characteristics
+
+ struct ble_gatt_svc_def *service = m_new(struct ble_gatt_svc_def, 2);
+ service[0].type = BLE_GATT_SVC_TYPE_PRIMARY;
+ service[0].uuid = create_nimble_uuid(service_uuid, NULL);
+ service[0].includes = NULL;
+ service[0].characteristics = characteristics;
+ service[1].type = 0; // no more services
+
+ MP_STATE_PORT(bluetooth_nimble_root_pointers)->services[MP_STATE_PORT(bluetooth_nimble_root_pointers)->n_services++] = service;
+
+ // Note: advertising must be stopped for gatts registration to work
+
+ int ret = ble_gatts_count_cfg(service);
+ if (ret != 0) {
+ return ble_hs_err_to_errno(ret);
+ }
+
+ ret = ble_gatts_add_svcs(service);
+ if (ret != 0) {
+ return ble_hs_err_to_errno(ret);
+ }
+
+ return 0;
+}
+
+int mp_bluetooth_gap_disconnect(uint16_t conn_handle) {
+ if (!mp_bluetooth_is_active()) {
+ return ERRNO_BLUETOOTH_NOT_ACTIVE;
+ }
+ return ble_hs_err_to_errno(ble_gap_terminate(conn_handle, BLE_ERR_REM_USER_CONN_TERM));
+}
+
+int mp_bluetooth_gatts_read(uint16_t value_handle, uint8_t **value, size_t *value_len) {
+ if (!mp_bluetooth_is_active()) {
+ return ERRNO_BLUETOOTH_NOT_ACTIVE;
+ }
+ return mp_bluetooth_gatts_db_read(MP_STATE_PORT(bluetooth_nimble_root_pointers)->gatts_db, value_handle, value, value_len);
+}
+
+int mp_bluetooth_gatts_write(uint16_t value_handle, const uint8_t *value, size_t value_len) {
+ if (!mp_bluetooth_is_active()) {
+ return ERRNO_BLUETOOTH_NOT_ACTIVE;
+ }
+ return mp_bluetooth_gatts_db_write(MP_STATE_PORT(bluetooth_nimble_root_pointers)->gatts_db, value_handle, value, value_len);
+}
+
+// TODO: Could use ble_gatts_chr_updated to send to all subscribed centrals.
+
+int mp_bluetooth_gatts_notify(uint16_t conn_handle, uint16_t value_handle) {
+ if (!mp_bluetooth_is_active()) {
+ return ERRNO_BLUETOOTH_NOT_ACTIVE;
+ }
+ // Confusingly, notify/notify_custom/indicate are "gattc" function (even though they're used by peripherals (i.e. gatt servers)).
+ // See https://www.mail-archive.com/dev@mynewt.apache.org/msg01293.html
+ return ble_hs_err_to_errno(ble_gattc_notify(conn_handle, value_handle));
+}
+
+int mp_bluetooth_gatts_notify_send(uint16_t conn_handle, uint16_t value_handle, const uint8_t *value, size_t value_len) {
+ if (!mp_bluetooth_is_active()) {
+ return ERRNO_BLUETOOTH_NOT_ACTIVE;
+ }
+ struct os_mbuf *om = ble_hs_mbuf_from_flat(value, value_len);
+ if (om == NULL) {
+ return MP_ENOMEM;
+ }
+ // TODO: check that notify_custom takes ownership of om, if not os_mbuf_free_chain(om).
+ return ble_hs_err_to_errno(ble_gattc_notify_custom(conn_handle, value_handle, om));
+}
+
+int mp_bluetooth_gatts_indicate(uint16_t conn_handle, uint16_t value_handle) {
+ if (!mp_bluetooth_is_active()) {
+ return ERRNO_BLUETOOTH_NOT_ACTIVE;
+ }
+ // This will raise BLE_GAP_EVENT_NOTIFY_TX with a status when it is
+ // acknowledged (or timeout/error).
+ return ble_hs_err_to_errno(ble_gattc_indicate(conn_handle, value_handle));
+}
+
+int mp_bluetooth_gatts_set_buffer(uint16_t value_handle, size_t len, bool append) {
+ if (!mp_bluetooth_is_active()) {
+ return ERRNO_BLUETOOTH_NOT_ACTIVE;
+ }
+ return mp_bluetooth_gatts_db_resize(MP_STATE_PORT(bluetooth_nimble_root_pointers)->gatts_db, value_handle, len, append);
+}
+
+#if MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE
+
+STATIC void gattc_on_data_available(uint8_t event, uint16_t conn_handle, uint16_t value_handle, const struct os_mbuf *om) {
+ size_t len = OS_MBUF_PKTLEN(om);
+ mp_uint_t atomic_state;
+ len = mp_bluetooth_gattc_on_data_available_start(event, conn_handle, value_handle, len, &atomic_state);
+ while (len > 0 && om != NULL) {
+ size_t n = MIN(om->om_len, len);
+ mp_bluetooth_gattc_on_data_available_chunk(OS_MBUF_DATA(om, const uint8_t *), n);
+ len -= n;
+ om = SLIST_NEXT(om, om_next);
+ }
+ mp_bluetooth_gattc_on_data_available_end(atomic_state);
+}
+
+STATIC int gap_scan_cb(struct ble_gap_event *event, void *arg) {
+ DEBUG_EVENT_printf("gap_scan_cb: event=%d type=%d\n", event->type, event->type == BLE_GAP_EVENT_DISC ? event->disc.event_type : -1);
+ if (!mp_bluetooth_is_active()) {
+ return 0;
+ }
+
+ if (event->type == BLE_GAP_EVENT_DISC_COMPLETE) {
+ mp_bluetooth_gap_on_scan_complete();
+ return 0;
+ }
+
+ if (event->type != BLE_GAP_EVENT_DISC) {
+ return 0;
+ }
+
+ uint8_t addr[6];
+ reverse_addr_byte_order(addr, event->disc.addr.val);
+ mp_bluetooth_gap_on_scan_result(event->disc.addr.type, addr, event->disc.event_type, event->disc.rssi, event->disc.data, event->disc.length_data);
+
+ return 0;
+}
+
+int mp_bluetooth_gap_scan_start(int32_t duration_ms, int32_t interval_us, int32_t window_us, bool active_scan) {
+ if (!mp_bluetooth_is_active()) {
+ return ERRNO_BLUETOOTH_NOT_ACTIVE;
+ }
+ if (duration_ms == 0) {
+ duration_ms = BLE_HS_FOREVER;
+ }
+ struct ble_gap_disc_params discover_params = {
+ .itvl = MAX(BLE_HCI_SCAN_ITVL_MIN, MIN(BLE_HCI_SCAN_ITVL_MAX, interval_us / BLE_HCI_SCAN_ITVL)),
+ .window = MAX(BLE_HCI_SCAN_WINDOW_MIN, MIN(BLE_HCI_SCAN_WINDOW_MAX, window_us / BLE_HCI_SCAN_ITVL)),
+ .filter_policy = BLE_HCI_CONN_FILT_NO_WL,
+ .limited = 0,
+ .passive = active_scan ? 0 : 1,
+ .filter_duplicates = 0,
+ };
+ int err = ble_gap_disc(BLE_OWN_ADDR_PUBLIC, duration_ms, &discover_params, gap_scan_cb, NULL);
+ return ble_hs_err_to_errno(err);
+}
+
+int mp_bluetooth_gap_scan_stop(void) {
+ if (!mp_bluetooth_is_active()) {
+ return ERRNO_BLUETOOTH_NOT_ACTIVE;
+ }
+ if (!ble_gap_disc_active()) {
+ return 0;
+ }
+ int err = ble_gap_disc_cancel();
+ if (err == 0) {
+ mp_bluetooth_gap_on_scan_complete();
+ return 0;
+ }
+ return ble_hs_err_to_errno(err);
+}
+
+// Central role: GAP events for a connected peripheral.
+STATIC int peripheral_gap_event_cb(struct ble_gap_event *event, void *arg) {
+ DEBUG_EVENT_printf("peripheral_gap_event_cb: event=%d\n", event->type);
+ if (!mp_bluetooth_is_active()) {
+ return 0;
+ }
+ struct ble_gap_conn_desc desc;
+ uint8_t addr[6] = {0};
+
+ switch (event->type) {
+ case BLE_GAP_EVENT_CONNECT:
+ if (event->connect.status == 0) {
+ // Connection established.
+ ble_gap_conn_find(event->connect.conn_handle, &desc);
+ reverse_addr_byte_order(addr, desc.peer_id_addr.val);
+ mp_bluetooth_gap_on_connected_disconnected(MP_BLUETOOTH_IRQ_PERIPHERAL_CONNECT, event->connect.conn_handle, desc.peer_id_addr.type, addr);
+ } else {
+ // Connection failed.
+ mp_bluetooth_gap_on_connected_disconnected(MP_BLUETOOTH_IRQ_PERIPHERAL_DISCONNECT, event->connect.conn_handle, 0xff, addr);
+ }
+ break;
+
+ case BLE_GAP_EVENT_DISCONNECT:
+ // Disconnect.
+ reverse_addr_byte_order(addr, event->disconnect.conn.peer_id_addr.val);
+ mp_bluetooth_gap_on_connected_disconnected(MP_BLUETOOTH_IRQ_PERIPHERAL_DISCONNECT, event->disconnect.conn.conn_handle, event->disconnect.conn.peer_id_addr.type, addr);
+
+ break;
+
+ case BLE_GAP_EVENT_NOTIFY_RX: {
+ uint16_t ev = event->notify_rx.indication == 0 ? MP_BLUETOOTH_IRQ_GATTC_NOTIFY : MP_BLUETOOTH_IRQ_GATTC_INDICATE;
+ gattc_on_data_available(ev, event->notify_rx.conn_handle, event->notify_rx.attr_handle, event->notify_rx.om);
+ break;
+ }
+
+ case BLE_GAP_EVENT_CONN_UPDATE:
+ // TODO
+ break;
+
+ case BLE_GAP_EVENT_CONN_UPDATE_REQ:
+ // TODO
+ break;
+
+ default:
+ break;
+ }
+ return 0;
+}
+
+int mp_bluetooth_gap_peripheral_connect(uint8_t addr_type, const uint8_t *addr, int32_t duration_ms) {
+ if (!mp_bluetooth_is_active()) {
+ return ERRNO_BLUETOOTH_NOT_ACTIVE;
+ }
+ if (ble_gap_disc_active()) {
+ mp_bluetooth_gap_scan_stop();
+ }
+
+ // TODO: This is the same as ble_gap_conn_params_dflt (i.e. passing NULL).
+ STATIC const struct ble_gap_conn_params params = {
+ .scan_itvl = 0x0010,
+ .scan_window = 0x0010,
+ .itvl_min = BLE_GAP_INITIAL_CONN_ITVL_MIN,
+ .itvl_max = BLE_GAP_INITIAL_CONN_ITVL_MAX,
+ .latency = BLE_GAP_INITIAL_CONN_LATENCY,
+ .supervision_timeout = BLE_GAP_INITIAL_SUPERVISION_TIMEOUT,
+ .min_ce_len = BLE_GAP_INITIAL_CONN_MIN_CE_LEN,
+ .max_ce_len = BLE_GAP_INITIAL_CONN_MAX_CE_LEN,
+ };
+
+ ble_addr_t addr_nimble = create_nimble_addr(addr_type, addr);
+ int err = ble_gap_connect(BLE_OWN_ADDR_PUBLIC, &addr_nimble, duration_ms, ¶ms, &peripheral_gap_event_cb, NULL);
+ return ble_hs_err_to_errno(err);
+}
+
+STATIC int peripheral_discover_service_cb(uint16_t conn_handle, const struct ble_gatt_error *error, const struct ble_gatt_svc *service, void *arg) {
+ DEBUG_EVENT_printf("peripheral_discover_service_cb: conn_handle=%d status=%d start_handle=%d\n", conn_handle, error->status, service ? service->start_handle : -1);
+ if (!mp_bluetooth_is_active()) {
+ return 0;
+ }
+ if (error->status == 0) {
+ mp_obj_bluetooth_uuid_t service_uuid = create_mp_uuid(&service->uuid);
+ mp_bluetooth_gattc_on_primary_service_result(conn_handle, service->start_handle, service->end_handle, &service_uuid);
+ } else {
+ mp_bluetooth_gattc_on_discover_complete(MP_BLUETOOTH_IRQ_GATTC_SERVICE_DONE, conn_handle, error->status == BLE_HS_EDONE ? 0 : error->status);
+ }
+ return 0;
+}
+
+int mp_bluetooth_gattc_discover_primary_services(uint16_t conn_handle, const mp_obj_bluetooth_uuid_t *uuid) {
+ if (!mp_bluetooth_is_active()) {
+ return ERRNO_BLUETOOTH_NOT_ACTIVE;
+ }
+ int err;
+ if (uuid) {
+ ble_uuid_any_t nimble_uuid;
+ create_nimble_uuid(uuid, &nimble_uuid);
+ err = ble_gattc_disc_svc_by_uuid(conn_handle, &nimble_uuid.u, &peripheral_discover_service_cb, NULL);
+ } else {
+ err = ble_gattc_disc_all_svcs(conn_handle, &peripheral_discover_service_cb, NULL);
+ }
+ return ble_hs_err_to_errno(err);
+}
+
+STATIC int ble_gatt_characteristic_cb(uint16_t conn_handle, const struct ble_gatt_error *error, const struct ble_gatt_chr *characteristic, void *arg) {
+ DEBUG_EVENT_printf("ble_gatt_characteristic_cb: conn_handle=%d status=%d def_handle=%d val_handle=%d\n", conn_handle, error->status, characteristic ? characteristic->def_handle : -1, characteristic ? characteristic->val_handle : -1);
+ if (!mp_bluetooth_is_active()) {
+ return 0;
+ }
+ if (error->status == 0) {
+ mp_obj_bluetooth_uuid_t characteristic_uuid = create_mp_uuid(&characteristic->uuid);
+ mp_bluetooth_gattc_on_characteristic_result(conn_handle, characteristic->def_handle, characteristic->val_handle, characteristic->properties, &characteristic_uuid);
+ } else {
+ mp_bluetooth_gattc_on_discover_complete(MP_BLUETOOTH_IRQ_GATTC_CHARACTERISTIC_DONE, conn_handle, error->status == BLE_HS_EDONE ? 0 : error->status);
+ }
+ return 0;
+}
+
+int mp_bluetooth_gattc_discover_characteristics(uint16_t conn_handle, uint16_t start_handle, uint16_t end_handle, const mp_obj_bluetooth_uuid_t *uuid) {
+ if (!mp_bluetooth_is_active()) {
+ return ERRNO_BLUETOOTH_NOT_ACTIVE;
+ }
+ int err;
+ if (uuid) {
+ ble_uuid_any_t nimble_uuid;
+ create_nimble_uuid(uuid, &nimble_uuid);
+ err = ble_gattc_disc_chrs_by_uuid(conn_handle, start_handle, end_handle, &nimble_uuid.u, &ble_gatt_characteristic_cb, NULL);
+ } else {
+ err = ble_gattc_disc_all_chrs(conn_handle, start_handle, end_handle, &ble_gatt_characteristic_cb, NULL);
+ }
+ return ble_hs_err_to_errno(err);
+}
+
+STATIC int ble_gatt_descriptor_cb(uint16_t conn_handle, const struct ble_gatt_error *error, uint16_t characteristic_val_handle, const struct ble_gatt_dsc *descriptor, void *arg) {
+ DEBUG_EVENT_printf("ble_gatt_descriptor_cb: conn_handle=%d status=%d chr_handle=%d dsc_handle=%d\n", conn_handle, error->status, characteristic_val_handle, descriptor ? descriptor->handle : -1);
+ if (!mp_bluetooth_is_active()) {
+ return 0;
+ }
+ if (error->status == 0) {
+ mp_obj_bluetooth_uuid_t descriptor_uuid = create_mp_uuid(&descriptor->uuid);
+ mp_bluetooth_gattc_on_descriptor_result(conn_handle, descriptor->handle, &descriptor_uuid);
+ } else {
+ mp_bluetooth_gattc_on_discover_complete(MP_BLUETOOTH_IRQ_GATTC_DESCRIPTOR_DONE, conn_handle, error->status == BLE_HS_EDONE ? 0 : error->status);
+ }
+ return 0;
+}
+
+int mp_bluetooth_gattc_discover_descriptors(uint16_t conn_handle, uint16_t start_handle, uint16_t end_handle) {
+ if (!mp_bluetooth_is_active()) {
+ return ERRNO_BLUETOOTH_NOT_ACTIVE;
+ }
+ int err = ble_gattc_disc_all_dscs(conn_handle, start_handle, end_handle, &ble_gatt_descriptor_cb, NULL);
+ return ble_hs_err_to_errno(err);
+}
+
+STATIC int ble_gatt_attr_read_cb(uint16_t conn_handle, const struct ble_gatt_error *error, struct ble_gatt_attr *attr, void *arg) {
+ DEBUG_EVENT_printf("ble_gatt_attr_read_cb: conn_handle=%d status=%d handle=%d\n", conn_handle, error->status, attr ? attr->handle : -1);
+ if (!mp_bluetooth_is_active()) {
+ return 0;
+ }
+ if (error->status == 0) {
+ gattc_on_data_available(MP_BLUETOOTH_IRQ_GATTC_READ_RESULT, conn_handle, attr->handle, attr->om);
+ }
+ mp_bluetooth_gattc_on_read_write_status(MP_BLUETOOTH_IRQ_GATTC_READ_DONE, conn_handle, attr ? attr->handle : -1, error->status);
+ return 0;
+}
+
+// Initiate read of a value from the remote peripheral.
+int mp_bluetooth_gattc_read(uint16_t conn_handle, uint16_t value_handle) {
+ if (!mp_bluetooth_is_active()) {
+ return ERRNO_BLUETOOTH_NOT_ACTIVE;
+ }
+ int err = ble_gattc_read(conn_handle, value_handle, &ble_gatt_attr_read_cb, NULL);
+ return ble_hs_err_to_errno(err);
+}
+
+STATIC int ble_gatt_attr_write_cb(uint16_t conn_handle, const struct ble_gatt_error *error, struct ble_gatt_attr *attr, void *arg) {
+ DEBUG_EVENT_printf("ble_gatt_attr_write_cb: conn_handle=%d status=%d handle=%d\n", conn_handle, error->status, attr ? attr->handle : -1);
+ if (!mp_bluetooth_is_active()) {
+ return 0;
+ }
+ mp_bluetooth_gattc_on_read_write_status(MP_BLUETOOTH_IRQ_GATTC_WRITE_DONE, conn_handle, attr->handle, error->status);
+ return 0;
+}
+
+// Write the value to the remote peripheral.
+int mp_bluetooth_gattc_write(uint16_t conn_handle, uint16_t value_handle, const uint8_t *value, size_t *value_len, unsigned int mode) {
+ if (!mp_bluetooth_is_active()) {
+ return ERRNO_BLUETOOTH_NOT_ACTIVE;
+ }
+ int err;
+ if (mode == MP_BLUETOOTH_WRITE_MODE_NO_RESPONSE) {
+ err = ble_gattc_write_no_rsp_flat(conn_handle, value_handle, value, *value_len);
+ } else if (mode == MP_BLUETOOTH_WRITE_MODE_WITH_RESPONSE) {
+ err = ble_gattc_write_flat(conn_handle, value_handle, value, *value_len, &ble_gatt_attr_write_cb, NULL);
+ } else {
+ err = BLE_HS_EINVAL;
+ }
+ return ble_hs_err_to_errno(err);
+}
+
+#endif // MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE
+
+#endif // MICROPY_PY_BLUETOOTH && MICROPY_BLUETOOTH_NIMBLE
diff --git a/extmod/nimble/modbluetooth_nimble.h b/extmod/nimble/modbluetooth_nimble.h
new file mode 100644
index 0000000000..f44e1d69dc
--- /dev/null
+++ b/extmod/nimble/modbluetooth_nimble.h
@@ -0,0 +1,57 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Jim Mussared
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef MICROPY_INCLUDED_EXTMOD_NIMBLE_MODBLUETOOTH_NIMBLE_H
+#define MICROPY_INCLUDED_EXTMOD_NIMBLE_MODBLUETOOTH_NIMBLE_H
+
+#include "extmod/modbluetooth.h"
+
+#define MP_BLUETOOTH_NIMBLE_MAX_SERVICES (8)
+
+typedef struct _mp_bluetooth_nimble_root_pointers_t {
+ // Characteristic (and descriptor) value storage.
+ mp_gatts_db_t gatts_db;
+
+ // Pending service definitions.
+ size_t n_services;
+ struct ble_gatt_svc_def *services[MP_BLUETOOTH_NIMBLE_MAX_SERVICES];
+} mp_bluetooth_nimble_root_pointers_t;
+
+enum {
+ MP_BLUETOOTH_NIMBLE_BLE_STATE_OFF,
+ MP_BLUETOOTH_NIMBLE_BLE_STATE_STARTING,
+ MP_BLUETOOTH_NIMBLE_BLE_STATE_ACTIVE,
+ MP_BLUETOOTH_NIMBLE_BLE_STATE_STOPPING,
+};
+
+extern volatile int mp_bluetooth_nimble_ble_state;
+
+void mp_bluetooth_nimble_port_preinit(void);
+void mp_bluetooth_nimble_port_postinit(void);
+void mp_bluetooth_nimble_port_deinit(void);
+void mp_bluetooth_nimble_port_start(void);
+
+#endif // MICROPY_INCLUDED_EXTMOD_NIMBLE_MODBLUETOOTH_NIMBLE_H
diff --git a/extmod/nimble/nimble.mk b/extmod/nimble/nimble.mk
new file mode 100644
index 0000000000..4e1642c98a
--- /dev/null
+++ b/extmod/nimble/nimble.mk
@@ -0,0 +1,105 @@
+# Makefile directives for Apache Mynewt NimBLE component
+
+ifeq ($(MICROPY_BLUETOOTH_NIMBLE),1)
+
+EXTMOD_SRC_C += extmod/nimble/modbluetooth_nimble.c
+
+CFLAGS_MOD += -DMICROPY_BLUETOOTH_NIMBLE=1
+
+NIMBLE_EXTMOD_DIR = extmod/nimble
+
+# Use NimBLE from the submodule in lib/mynewt-nimble by default,
+# allowing a port to use their own system version (e.g. ESP32).
+MICROPY_BLUETOOTH_NIMBLE_BINDINGS_ONLY ?= 0
+
+ifeq ($(MICROPY_BLUETOOTH_NIMBLE_BINDINGS_ONLY),0)
+
+NIMBLE_LIB_DIR = lib/mynewt-nimble
+
+LIB_SRC_C += $(addprefix $(NIMBLE_LIB_DIR)/, \
+ $(addprefix ext/tinycrypt/src/, \
+ aes_encrypt.c \
+ cmac_mode.c \
+ ecc.c \
+ ecc_dh.c \
+ utils.c \
+ ) \
+ nimble/host/services/gap/src/ble_svc_gap.c \
+ nimble/host/services/gatt/src/ble_svc_gatt.c \
+ $(addprefix nimble/host/src/, \
+ ble_att.c \
+ ble_att_clt.c \
+ ble_att_cmd.c \
+ ble_att_svr.c \
+ ble_eddystone.c \
+ ble_gap.c \
+ ble_gattc.c \
+ ble_gatts.c \
+ ble_hs_adv.c \
+ ble_hs_atomic.c \
+ ble_hs.c \
+ ble_hs_cfg.c \
+ ble_hs_conn.c \
+ ble_hs_flow.c \
+ ble_hs_hci.c \
+ ble_hs_hci_cmd.c \
+ ble_hs_hci_evt.c \
+ ble_hs_hci_util.c \
+ ble_hs_id.c \
+ ble_hs_log.c \
+ ble_hs_mbuf.c \
+ ble_hs_misc.c \
+ ble_hs_mqueue.c \
+ ble_hs_pvcy.c \
+ ble_hs_startup.c \
+ ble_hs_stop.c \
+ ble_ibeacon.c \
+ ble_l2cap.c \
+ ble_l2cap_coc.c \
+ ble_l2cap_sig.c \
+ ble_l2cap_sig_cmd.c \
+ ble_monitor.c \
+ ble_sm_alg.c \
+ ble_sm.c \
+ ble_sm_cmd.c \
+ ble_sm_lgcy.c \
+ ble_sm_sc.c \
+ ble_store.c \
+ ble_store_util.c \
+ ble_uuid.c \
+ ) \
+ nimble/host/store/ram/src/ble_store_ram.c \
+ nimble/host/util/src/addr.c \
+ nimble/transport/uart/src/ble_hci_uart.c \
+ $(addprefix porting/nimble/src/, \
+ endian.c \
+ mem.c \
+ nimble_port.c \
+ os_mbuf.c \
+ os_mempool.c \
+ os_msys_init.c \
+ ) \
+ )
+
+EXTMOD_SRC_C += $(addprefix $(NIMBLE_EXTMOD_DIR)/, \
+ nimble/npl_os.c \
+ hal/hal_uart.c \
+ )
+
+INC += -I$(TOP)/$(NIMBLE_EXTMOD_DIR)
+INC += -I$(TOP)/$(NIMBLE_LIB_DIR)
+INC += -I$(TOP)/$(NIMBLE_LIB_DIR)/ext/tinycrypt/include
+INC += -I$(TOP)/$(NIMBLE_LIB_DIR)/nimble/host/include
+INC += -I$(TOP)/$(NIMBLE_LIB_DIR)/nimble/host/services/gap/include
+INC += -I$(TOP)/$(NIMBLE_LIB_DIR)/nimble/host/services/gatt/include
+INC += -I$(TOP)/$(NIMBLE_LIB_DIR)/nimble/host/store/ram/include
+INC += -I$(TOP)/$(NIMBLE_LIB_DIR)/nimble/host/util/include
+INC += -I$(TOP)/$(NIMBLE_LIB_DIR)/nimble/include
+INC += -I$(TOP)/$(NIMBLE_LIB_DIR)/nimble/transport/uart/include
+INC += -I$(TOP)/$(NIMBLE_LIB_DIR)/porting/nimble/include
+
+$(BUILD)/$(NIMBLE_LIB_DIR)/%.o: CFLAGS += -Wno-maybe-uninitialized -Wno-pointer-arith -Wno-unused-but-set-variable -Wno-format
+
+endif
+
+endif
diff --git a/extmod/nimble/nimble/nimble_hci_uart.h b/extmod/nimble/nimble/nimble_hci_uart.h
new file mode 100644
index 0000000000..646a12dac1
--- /dev/null
+++ b/extmod/nimble/nimble/nimble_hci_uart.h
@@ -0,0 +1,40 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Damien P. George
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#ifndef MICROPY_INCLUDED_EXTMOD_NIMBLE_NIMBLE_NIMBLE_HCI_UART_H
+#define MICROPY_INCLUDED_EXTMOD_NIMBLE_NIMBLE_NIMBLE_HCI_UART_H
+
+// Extensions to extmod/modbluetooth_hci.h specific to NimBLE.
+
+#include "extmod/nimble/hal/hal_uart.h"
+
+// Helpers called from ports.
+void mp_bluetooth_nimble_hci_uart_process(void);
+
+// Must be provided by the port.
+void mp_bluetooth_nimble_hci_uart_rx(hal_uart_rx_cb_t rx_cb, void *rx_arg);
+void mp_bluetooth_nimble_hci_uart_tx_strn(const char *str, uint len);
+
+#endif // MICROPY_INCLUDED_EXTMOD_NIMBLE_NIMBLE_NIMBLE_HCI_UART_H
diff --git a/extmod/nimble/nimble/nimble_npl_os.h b/extmod/nimble/nimble/nimble_npl_os.h
new file mode 100644
index 0000000000..3d886fedb5
--- /dev/null
+++ b/extmod/nimble/nimble/nimble_npl_os.h
@@ -0,0 +1,66 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018-2019 Damien P. George
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef MICROPY_INCLUDED_STM32_NIMBLE_NIMBLE_NPL_OS_H
+#define MICROPY_INCLUDED_STM32_NIMBLE_NIMBLE_NPL_OS_H
+
+#include
+
+#define BLE_NPL_OS_ALIGNMENT (4)
+#define BLE_NPL_TIME_FOREVER (0xffffffff)
+
+typedef uint32_t ble_npl_time_t;
+typedef int32_t ble_npl_stime_t;
+
+struct ble_npl_event {
+ ble_npl_event_fn *fn;
+ void *arg;
+ struct ble_npl_event *prev;
+ struct ble_npl_event *next;
+};
+
+struct ble_npl_eventq {
+ struct ble_npl_event *head;
+ struct ble_npl_eventq *nextq;
+};
+
+struct ble_npl_callout {
+ bool active;
+ uint32_t ticks;
+ struct ble_npl_eventq *evq;
+ struct ble_npl_event ev;
+ struct ble_npl_callout *nextc;
+};
+
+struct ble_npl_mutex {
+ volatile uint8_t locked;
+};
+
+struct ble_npl_sem {
+ volatile uint16_t count;
+};
+
+#endif // MICROPY_INCLUDED_STM32_NIMBLE_NIMBLE_NPL_OS_H
diff --git a/extmod/nimble/nimble/npl_os.c b/extmod/nimble/nimble/npl_os.c
new file mode 100644
index 0000000000..20c2604054
--- /dev/null
+++ b/extmod/nimble/nimble/npl_os.c
@@ -0,0 +1,397 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018-2019 Damien P. George
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include
+#include "py/mphal.h"
+#include "py/runtime.h"
+#include "nimble/ble.h"
+#include "nimble/nimble_npl.h"
+#include "nimble/nimble_hci_uart.h"
+
+#define DEBUG_OS_printf(...) //printf(__VA_ARGS__)
+#define DEBUG_MALLOC_printf(...) //printf(__VA_ARGS__)
+#define DEBUG_EVENT_printf(...) //printf(__VA_ARGS__)
+#define DEBUG_MUTEX_printf(...) //printf(__VA_ARGS__)
+#define DEBUG_SEM_printf(...) //printf(__VA_ARGS__)
+#define DEBUG_CALLOUT_printf(...) //printf(__VA_ARGS__)
+#define DEBUG_TIME_printf(...) //printf(__VA_ARGS__)
+#define DEBUG_CRIT_printf(...) //printf(__VA_ARGS__)
+
+bool ble_npl_os_started(void) {
+ DEBUG_OS_printf("ble_npl_os_started\n");
+ return true;
+}
+
+void *ble_npl_get_current_task_id(void) {
+ DEBUG_OS_printf("ble_npl_get_current_task_id\n");
+ return NULL;
+}
+
+/******************************************************************************/
+// malloc
+
+// Maintain a linked list of heap memory that we've passed to Nimble,
+// discoverable via the bluetooth_nimble_memory root pointer.
+
+// MP_STATE_PORT(bluetooth_nimble_memory) is a pointer to [next, prev, data...].
+
+// TODO: This is duplicated from mbedtls. Perhaps make this a generic feature?
+void *m_malloc_bluetooth(size_t size) {
+ void **ptr = m_malloc0(size + 2 * sizeof(uintptr_t));
+ if (MP_STATE_PORT(bluetooth_nimble_memory) != NULL) {
+ MP_STATE_PORT(bluetooth_nimble_memory)[0] = ptr;
+ }
+ ptr[0] = NULL;
+ ptr[1] = MP_STATE_PORT(bluetooth_nimble_memory);
+ MP_STATE_PORT(bluetooth_nimble_memory) = ptr;
+ return &ptr[2];
+}
+
+void m_free_bluetooth(void *ptr_in) {
+ void **ptr = &((void**)ptr_in)[-2];
+ if (ptr[1] != NULL) {
+ ((void**)ptr[1])[0] = ptr[0];
+ }
+ if (ptr[0] != NULL) {
+ ((void**)ptr[0])[1] = ptr[1];
+ } else {
+ MP_STATE_PORT(bluetooth_nimble_memory) = ptr[1];
+ }
+ m_free(ptr);
+}
+
+// Check if a nimble ptr is tracked.
+// If it isn't, that means that it's from a previous soft-reset cycle.
+STATIC bool is_valid_nimble_malloc(void *ptr) {
+ DEBUG_MALLOC_printf("NIMBLE is_valid_nimble_malloc(%p)\n", ptr);
+ void** search = MP_STATE_PORT(bluetooth_nimble_memory);
+ while (search) {
+ if (&search[2] == ptr) {
+ return true;
+ }
+
+ search = (void**)search[1];
+ }
+ return false;
+}
+
+void *nimble_malloc(size_t size) {
+ DEBUG_MALLOC_printf("NIMBLE malloc(%u)\n", (uint)size);
+ void* ptr = m_malloc_bluetooth(size);
+ DEBUG_MALLOC_printf(" --> %p\n", ptr);
+ return ptr;
+}
+
+// Only free if it's still a valid pointer.
+void nimble_free(void *ptr) {
+ DEBUG_MALLOC_printf("NIMBLE free(%p)\n", ptr);
+ if (ptr && is_valid_nimble_malloc(ptr)) {
+ m_free_bluetooth(ptr);
+ }
+}
+
+// Only realloc if it's still a valid pointer. Otherwise just malloc.
+void *nimble_realloc(void *ptr, size_t size) {
+ // This is only used by ble_gatts.c to grow the queue of pending services to be registered.
+ DEBUG_MALLOC_printf("NIMBLE realloc(%p, %u)\n", ptr, (uint)size);
+ void *ptr2 = nimble_malloc(size);
+ if (ptr && is_valid_nimble_malloc(ptr)) {
+ // If it's a realloc and we still have the old data, then copy it.
+ // This will happen as we add services.
+ memcpy(ptr2, ptr, size);
+ m_free_bluetooth(ptr);
+ }
+ return ptr2;
+}
+
+// No-op implementation (only used by NimBLE logging).
+int nimble_sprintf(char *str, const char *fmt, ...) {
+ str[0] = 0;
+ return 0;
+}
+
+/******************************************************************************/
+// EVENTQ
+
+struct ble_npl_eventq *global_eventq = NULL;
+
+void os_eventq_run_all(void) {
+ for (struct ble_npl_eventq *evq = global_eventq; evq != NULL; evq = evq->nextq) {
+ while (evq->head != NULL) {
+ struct ble_npl_event *ev = evq->head;
+ evq->head = ev->next;
+ if (ev->next) {
+ ev->next->prev = NULL;
+ ev->next = NULL;
+ }
+ ev->prev = NULL;
+ DEBUG_EVENT_printf("event_run(%p)\n", ev);
+ ev->fn(ev);
+ DEBUG_EVENT_printf("event_run(%p) done\n", ev);
+ }
+ }
+}
+
+void ble_npl_eventq_init(struct ble_npl_eventq *evq) {
+ DEBUG_EVENT_printf("ble_npl_eventq_init(%p)\n", evq);
+ evq->head = NULL;
+ struct ble_npl_eventq **evq2;
+ for (evq2 = &global_eventq; *evq2 != NULL; evq2 = &(*evq2)->nextq) {
+ }
+ *evq2 = evq;
+ evq->nextq = NULL;
+}
+
+void ble_npl_eventq_put(struct ble_npl_eventq *evq, struct ble_npl_event *ev) {
+ DEBUG_EVENT_printf("ble_npl_eventq_put(%p, %p (%p, %p))\n", evq, ev, ev->fn, ev->arg);
+ ev->next = NULL;
+ if (evq->head == NULL) {
+ evq->head = ev;
+ ev->prev = NULL;
+ } else {
+ struct ble_npl_event *ev2 = evq->head;
+ while (true) {
+ if (ev2 == ev) {
+ DEBUG_EVENT_printf(" --> already in queue\n");
+ return;
+ }
+ if (ev2->next == NULL) {
+ break;
+ }
+ DEBUG_EVENT_printf(" --> %p\n", ev2->next);
+ ev2 = ev2->next;
+ }
+ ev2->next = ev;
+ ev->prev = ev2;
+ }
+}
+
+void ble_npl_event_init(struct ble_npl_event *ev, ble_npl_event_fn *fn, void *arg) {
+ DEBUG_EVENT_printf("ble_npl_event_init(%p, %p, %p)\n", ev, fn, arg);
+ ev->fn = fn;
+ ev->arg = arg;
+ ev->next = NULL;
+}
+
+void *ble_npl_event_get_arg(struct ble_npl_event *ev) {
+ DEBUG_EVENT_printf("ble_npl_event_get_arg(%p) -> %p\n", ev, ev->arg);
+ return ev->arg;
+}
+
+void ble_npl_event_set_arg(struct ble_npl_event *ev, void *arg) {
+ DEBUG_EVENT_printf("ble_npl_event_set_arg(%p, %p)\n", ev, arg);
+ ev->arg = arg;
+}
+
+/******************************************************************************/
+// MUTEX
+
+ble_npl_error_t ble_npl_mutex_init(struct ble_npl_mutex *mu) {
+ DEBUG_MUTEX_printf("ble_npl_mutex_init(%p)\n", mu);
+ mu->locked = 0;
+ return BLE_NPL_OK;
+}
+
+ble_npl_error_t ble_npl_mutex_pend(struct ble_npl_mutex *mu, ble_npl_time_t timeout) {
+ DEBUG_MUTEX_printf("ble_npl_mutex_pend(%p, %u) locked=%u\n", mu, (uint)timeout, (uint)mu->locked);
+ mu->locked = 1;
+ return BLE_NPL_OK;
+}
+
+ble_npl_error_t ble_npl_mutex_release(struct ble_npl_mutex *mu) {
+ DEBUG_MUTEX_printf("ble_npl_mutex_release(%p) locked=%u\n", mu, (uint)mu->locked);
+ mu->locked = 0;
+ return BLE_NPL_OK;
+}
+
+/******************************************************************************/
+// SEM
+
+ble_npl_error_t ble_npl_sem_init(struct ble_npl_sem *sem, uint16_t tokens) {
+ DEBUG_SEM_printf("ble_npl_sem_init(%p, %u)\n", sem, (uint)tokens);
+ sem->count = tokens;
+ return BLE_NPL_OK;
+}
+
+ble_npl_error_t ble_npl_sem_pend(struct ble_npl_sem *sem, ble_npl_time_t timeout) {
+ DEBUG_SEM_printf("ble_npl_sem_pend(%p, %u) count=%u\n", sem, (uint)timeout, (uint)sem->count);
+ if (sem->count == 0) {
+ uint32_t t0 = mp_hal_ticks_ms();
+ while (sem->count == 0 && mp_hal_ticks_ms() - t0 < timeout) {
+ // This function may be called at thread-level, so execute
+ // mp_bluetooth_nimble_hci_uart_process at raised priority.
+ MICROPY_PY_BLUETOOTH_ENTER
+ mp_bluetooth_nimble_hci_uart_process();
+ MICROPY_PY_BLUETOOTH_EXIT
+ if (sem->count != 0) {
+ break;
+ }
+ __WFI();
+ }
+ if (sem->count == 0) {
+ printf("timeout\n");
+ return BLE_NPL_TIMEOUT;
+ }
+ DEBUG_SEM_printf("got response in %u ms\n", (int)(mp_hal_ticks_ms() - t0));
+ }
+ sem->count -= 1;
+ return BLE_NPL_OK;
+}
+
+ble_npl_error_t ble_npl_sem_release(struct ble_npl_sem *sem) {
+ DEBUG_SEM_printf("ble_npl_sem_release(%p)\n", sem);
+ sem->count += 1;
+ return BLE_NPL_OK;
+}
+
+uint16_t ble_npl_sem_get_count(struct ble_npl_sem *sem) {
+ DEBUG_SEM_printf("ble_npl_sem_get_count(%p)\n", sem);
+ return sem->count;
+}
+
+/******************************************************************************/
+// CALLOUT
+
+static struct ble_npl_callout *global_callout = NULL;
+
+void os_callout_process(void) {
+ uint32_t tnow = mp_hal_ticks_ms();
+ for (struct ble_npl_callout *c = global_callout; c != NULL; c = c->nextc) {
+ if (!c->active) {
+ continue;
+ }
+ if ((int32_t)(tnow - c->ticks) >= 0) {
+ DEBUG_CALLOUT_printf("callout_run(%p) tnow=%u ticks=%u evq=%p\n", c, (uint)tnow, (uint)c->ticks, c->evq);
+ c->active = false;
+ if (c->evq) {
+ ble_npl_eventq_put(c->evq, &c->ev);
+ } else {
+ c->ev.fn(&c->ev);
+ }
+ DEBUG_CALLOUT_printf("callout_run(%p) done\n", c);
+ }
+ }
+}
+
+void ble_npl_callout_init(struct ble_npl_callout *c, struct ble_npl_eventq *evq, ble_npl_event_fn *ev_cb, void *ev_arg) {
+ DEBUG_CALLOUT_printf("ble_npl_callout_init(%p, %p, %p, %p)\n", c, evq, ev_cb, ev_arg);
+ c->active = false;
+ c->ticks = 0;
+ c->evq = evq;
+ ble_npl_event_init(&c->ev, ev_cb, ev_arg);
+
+ struct ble_npl_callout **c2;
+ for (c2 = &global_callout; *c2 != NULL; c2 = &(*c2)->nextc) {
+ if (c == *c2) {
+ // callout already in linked list so don't link it in again
+ return;
+ }
+ }
+ *c2 = c;
+ c->nextc = NULL;
+}
+
+ble_npl_error_t ble_npl_callout_reset(struct ble_npl_callout *c, ble_npl_time_t ticks) {
+ DEBUG_CALLOUT_printf("ble_npl_callout_reset(%p, %u) tnow=%u\n", c, (uint)ticks, (uint)mp_hal_ticks_ms());
+ c->active = true;
+ c->ticks = ble_npl_time_get() + ticks;
+ return BLE_NPL_OK;
+}
+
+void ble_npl_callout_stop(struct ble_npl_callout *c) {
+ DEBUG_CALLOUT_printf("ble_npl_callout_stop(%p)\n", c);
+ c->active = false;
+}
+
+bool ble_npl_callout_is_active(struct ble_npl_callout *c) {
+ DEBUG_CALLOUT_printf("ble_npl_callout_is_active(%p)\n", c);
+ return c->active;
+}
+
+ble_npl_time_t ble_npl_callout_get_ticks(struct ble_npl_callout *c) {
+ DEBUG_CALLOUT_printf("ble_npl_callout_get_ticks(%p)\n", c);
+ return c->ticks;
+}
+
+ble_npl_time_t ble_npl_callout_remaining_ticks(struct ble_npl_callout *c, ble_npl_time_t now) {
+ DEBUG_CALLOUT_printf("ble_npl_callout_remaining_ticks(%p, %u)\n", c, (uint)now);
+ if (c->ticks > now) {
+ return c->ticks - now;
+ } else {
+ return 0;
+ }
+}
+
+void *ble_npl_callout_get_arg(struct ble_npl_callout *c) {
+ DEBUG_CALLOUT_printf("ble_npl_callout_get_arg(%p)\n", c);
+ return ble_npl_event_get_arg(&c->ev);
+}
+
+void ble_npl_callout_set_arg(struct ble_npl_callout *c, void *arg) {
+ DEBUG_CALLOUT_printf("ble_npl_callout_set_arg(%p, %p)\n", c, arg);
+ ble_npl_event_set_arg(&c->ev, arg);
+}
+
+/******************************************************************************/
+// TIME
+
+uint32_t ble_npl_time_get(void) {
+ DEBUG_TIME_printf("ble_npl_time_get -> %u\n", (uint)mp_hal_ticks_ms());
+ return mp_hal_ticks_ms();
+}
+
+ble_npl_error_t ble_npl_time_ms_to_ticks(uint32_t ms, ble_npl_time_t *out_ticks) {
+ DEBUG_TIME_printf("ble_npl_time_ms_to_ticks(%u)\n", (uint)ms);
+ *out_ticks = ms;
+ return BLE_NPL_OK;
+}
+
+ble_npl_time_t ble_npl_time_ms_to_ticks32(uint32_t ms) {
+ DEBUG_TIME_printf("ble_npl_time_ms_to_ticks32(%u)\n", (uint)ms);
+ return ms;
+}
+
+uint32_t ble_npl_time_ticks_to_ms32(ble_npl_time_t ticks) {
+ DEBUG_TIME_printf("ble_npl_time_ticks_to_ms32(%u)\n", (uint)ticks);
+ return ticks;
+}
+
+void ble_npl_time_delay(ble_npl_time_t ticks) {
+ mp_hal_delay_ms(ticks + 1);
+}
+
+/******************************************************************************/
+// CRITICAL
+
+uint32_t ble_npl_hw_enter_critical(void) {
+ DEBUG_CRIT_printf("ble_npl_hw_enter_critical()\n");
+ return raise_irq_pri(15);
+}
+
+void ble_npl_hw_exit_critical(uint32_t ctx) {
+ DEBUG_CRIT_printf("ble_npl_hw_exit_critical(%u)\n", (uint)ctx);
+ restore_irq_pri(ctx);
+}
diff --git a/extmod/nimble/syscfg/syscfg.h b/extmod/nimble/syscfg/syscfg.h
new file mode 100644
index 0000000000..6ac420f35e
--- /dev/null
+++ b/extmod/nimble/syscfg/syscfg.h
@@ -0,0 +1,164 @@
+#ifndef MICROPY_INCLUDED_EXTMOD_NIMBLE_SYSCFG_H
+#define MICROPY_INCLUDED_EXTMOD_NIMBLE_SYSCFG_H
+
+#include "py/mphal.h"
+#include "uart.h"
+
+void *nimble_malloc(size_t size);
+void nimble_free(void *ptr);
+void *nimble_realloc(void *ptr, size_t size);
+
+#define malloc(size) nimble_malloc(size)
+#define free(ptr) nimble_free(ptr)
+#define realloc(ptr, size) nimble_realloc(ptr, size)
+
+int nimble_sprintf(char *str, const char *fmt, ...);
+#define sprintf(str, fmt, ...) nimble_sprintf(str, fmt, __VA_ARGS__)
+
+#define MYNEWT_VAL(x) MYNEWT_VAL_ ## x
+
+#define MYNEWT_VAL_LOG_LEVEL (255)
+
+/*** compiler/arm-none-eabi-m4 */
+#define MYNEWT_VAL_HARDFLOAT (1)
+
+/*** kernel/os */
+#define MYNEWT_VAL_FLOAT_USER (0)
+#define MYNEWT_VAL_MSYS_1_BLOCK_COUNT (12)
+#define MYNEWT_VAL_MSYS_1_BLOCK_SIZE (292)
+#define MYNEWT_VAL_MSYS_2_BLOCK_COUNT (0)
+#define MYNEWT_VAL_MSYS_2_BLOCK_SIZE (0)
+#define MYNEWT_VAL_OS_CPUTIME_FREQ (1000000)
+#define MYNEWT_VAL_OS_CPUTIME_TIMER_NUM (0)
+#define MYNEWT_VAL_OS_CTX_SW_STACK_CHECK (0)
+#define MYNEWT_VAL_OS_CTX_SW_STACK_GUARD (4)
+#define MYNEWT_VAL_OS_MAIN_STACK_SIZE (1024)
+#define MYNEWT_VAL_OS_MAIN_TASK_PRIO (127)
+#define MYNEWT_VAL_OS_MEMPOOL_CHECK (0)
+#define MYNEWT_VAL_OS_MEMPOOL_POISON (0)
+
+/*** nimble */
+#define MYNEWT_VAL_BLE_EXT_ADV (0)
+#define MYNEWT_VAL_BLE_EXT_ADV_MAX_SIZE (31)
+#define MYNEWT_VAL_BLE_MAX_CONNECTIONS (4)
+#define MYNEWT_VAL_BLE_MULTI_ADV_INSTANCES (0)
+#define MYNEWT_VAL_BLE_ROLE_BROADCASTER (1)
+#define MYNEWT_VAL_BLE_ROLE_CENTRAL (1)
+#define MYNEWT_VAL_BLE_ROLE_OBSERVER (1)
+#define MYNEWT_VAL_BLE_ROLE_PERIPHERAL (1)
+#define MYNEWT_VAL_BLE_WHITELIST (1)
+
+/*** nimble/host */
+#define MYNEWT_VAL_BLE_ATT_PREFERRED_MTU (256)
+#define MYNEWT_VAL_BLE_ATT_SVR_FIND_INFO (1)
+#define MYNEWT_VAL_BLE_ATT_SVR_FIND_TYPE (1)
+#define MYNEWT_VAL_BLE_ATT_SVR_INDICATE (1)
+#define MYNEWT_VAL_BLE_ATT_SVR_MAX_PREP_ENTRIES (64)
+#define MYNEWT_VAL_BLE_ATT_SVR_NOTIFY (1)
+#define MYNEWT_VAL_BLE_ATT_SVR_QUEUED_WRITE (1)
+#define MYNEWT_VAL_BLE_ATT_SVR_QUEUED_WRITE_TMO (30000)
+#define MYNEWT_VAL_BLE_ATT_SVR_READ (1)
+#define MYNEWT_VAL_BLE_ATT_SVR_READ_BLOB (1)
+#define MYNEWT_VAL_BLE_ATT_SVR_READ_GROUP_TYPE (1)
+#define MYNEWT_VAL_BLE_ATT_SVR_READ_MULT (1)
+#define MYNEWT_VAL_BLE_ATT_SVR_READ_TYPE (1)
+#define MYNEWT_VAL_BLE_ATT_SVR_SIGNED_WRITE (1)
+#define MYNEWT_VAL_BLE_ATT_SVR_WRITE (1)
+#define MYNEWT_VAL_BLE_ATT_SVR_WRITE_NO_RSP (1)
+#define MYNEWT_VAL_BLE_GAP_MAX_PENDING_CONN_PARAM_UPDATE (1)
+#define MYNEWT_VAL_BLE_GATT_DISC_ALL_CHRS (MYNEWT_VAL_BLE_ROLE_CENTRAL)
+#define MYNEWT_VAL_BLE_GATT_DISC_ALL_DSCS (MYNEWT_VAL_BLE_ROLE_CENTRAL)
+#define MYNEWT_VAL_BLE_GATT_DISC_ALL_SVCS (MYNEWT_VAL_BLE_ROLE_CENTRAL)
+#define MYNEWT_VAL_BLE_GATT_DISC_CHR_UUID (MYNEWT_VAL_BLE_ROLE_CENTRAL)
+#define MYNEWT_VAL_BLE_GATT_DISC_SVC_UUID (MYNEWT_VAL_BLE_ROLE_CENTRAL)
+#define MYNEWT_VAL_BLE_GATT_FIND_INC_SVCS (MYNEWT_VAL_BLE_ROLE_CENTRAL)
+#define MYNEWT_VAL_BLE_GATT_INDICATE (1)
+#define MYNEWT_VAL_BLE_GATT_MAX_PROCS (4)
+#define MYNEWT_VAL_BLE_GATT_NOTIFY (1)
+#define MYNEWT_VAL_BLE_GATT_READ (MYNEWT_VAL_BLE_ROLE_CENTRAL)
+#define MYNEWT_VAL_BLE_GATT_READ_LONG (MYNEWT_VAL_BLE_ROLE_CENTRAL)
+#define MYNEWT_VAL_BLE_GATT_READ_MAX_ATTRS (8)
+#define MYNEWT_VAL_BLE_GATT_READ_MULT (MYNEWT_VAL_BLE_ROLE_CENTRAL)
+#define MYNEWT_VAL_BLE_GATT_READ_UUID (MYNEWT_VAL_BLE_ROLE_CENTRAL)
+#define MYNEWT_VAL_BLE_GATT_RESUME_RATE (1000)
+#define MYNEWT_VAL_BLE_GATT_SIGNED_WRITE (MYNEWT_VAL_BLE_ROLE_CENTRAL)
+#define MYNEWT_VAL_BLE_GATT_WRITE (MYNEWT_VAL_BLE_ROLE_CENTRAL)
+#define MYNEWT_VAL_BLE_GATT_WRITE_LONG (MYNEWT_VAL_BLE_ROLE_CENTRAL)
+#define MYNEWT_VAL_BLE_GATT_WRITE_MAX_ATTRS (4)
+#define MYNEWT_VAL_BLE_GATT_WRITE_NO_RSP (MYNEWT_VAL_BLE_ROLE_CENTRAL)
+#define MYNEWT_VAL_BLE_GATT_WRITE_RELIABLE (MYNEWT_VAL_BLE_ROLE_CENTRAL)
+#define MYNEWT_VAL_BLE_HOST (1)
+#define MYNEWT_VAL_BLE_HS_DEBUG (0)
+#define MYNEWT_VAL_BLE_HS_FLOW_CTRL (0)
+#define MYNEWT_VAL_BLE_HS_FLOW_CTRL_ITVL (1000)
+#define MYNEWT_VAL_BLE_HS_FLOW_CTRL_THRESH (2)
+#define MYNEWT_VAL_BLE_HS_FLOW_CTRL_TX_ON_DISCONNECT (0)
+#define MYNEWT_VAL_BLE_HS_PHONY_HCI_ACKS (0)
+#define MYNEWT_VAL_BLE_HS_REQUIRE_OS (1)
+#define MYNEWT_VAL_BLE_HS_STOP_ON_SHUTDOWN_TIMEOUT (2000)
+#define MYNEWT_VAL_BLE_L2CAP_COC_MAX_NUM (0)
+#define MYNEWT_VAL_BLE_L2CAP_JOIN_RX_FRAGS (1)
+#define MYNEWT_VAL_BLE_L2CAP_MAX_CHANS (3*MYNEWT_VAL_BLE_MAX_CONNECTIONS)
+#define MYNEWT_VAL_BLE_L2CAP_RX_FRAG_TIMEOUT (30000)
+#define MYNEWT_VAL_BLE_L2CAP_SIG_MAX_PROCS (1)
+#define MYNEWT_VAL_BLE_MONITOR_CONSOLE_BUFFER_SIZE (128)
+#define MYNEWT_VAL_BLE_MONITOR_RTT (0)
+#define MYNEWT_VAL_BLE_MONITOR_RTT_BUFFERED (1)
+#define MYNEWT_VAL_BLE_MONITOR_RTT_BUFFER_NAME ("monitor")
+#define MYNEWT_VAL_BLE_MONITOR_RTT_BUFFER_SIZE (256)
+#define MYNEWT_VAL_BLE_MONITOR_UART (0)
+#define MYNEWT_VAL_BLE_MONITOR_UART_BAUDRATE (1000000)
+#define MYNEWT_VAL_BLE_MONITOR_UART_BUFFER_SIZE (64)
+#define MYNEWT_VAL_BLE_MONITOR_UART_DEV ("uart0")
+#define MYNEWT_VAL_BLE_RPA_TIMEOUT (300)
+#define MYNEWT_VAL_BLE_SM_BONDING (0)
+#define MYNEWT_VAL_BLE_SM_IO_CAP (BLE_HS_IO_NO_INPUT_OUTPUT)
+#define MYNEWT_VAL_BLE_SM_KEYPRESS (0)
+#define MYNEWT_VAL_BLE_SM_LEGACY (1)
+#define MYNEWT_VAL_BLE_SM_MAX_PROCS (1)
+#define MYNEWT_VAL_BLE_SM_MITM (0)
+#define MYNEWT_VAL_BLE_SM_OOB_DATA_FLAG (0)
+#define MYNEWT_VAL_BLE_SM_OUR_KEY_DIST (0)
+#define MYNEWT_VAL_BLE_SM_SC (1)
+#define MYNEWT_VAL_BLE_SM_THEIR_KEY_DIST (0)
+#define MYNEWT_VAL_BLE_STORE_MAX_BONDS (3)
+#define MYNEWT_VAL_BLE_STORE_MAX_CCCDS (8)
+
+/*** nimble/host/services/gap */
+#define MYNEWT_VAL_BLE_SVC_GAP_APPEARANCE (0)
+#define MYNEWT_VAL_BLE_SVC_GAP_APPEARANCE_WRITE_PERM (-1)
+#define MYNEWT_VAL_BLE_SVC_GAP_CENTRAL_ADDRESS_RESOLUTION (-1)
+#define MYNEWT_VAL_BLE_SVC_GAP_DEVICE_NAME ("pybd")
+#define MYNEWT_VAL_BLE_SVC_GAP_DEVICE_NAME_MAX_LENGTH (31)
+#define MYNEWT_VAL_BLE_SVC_GAP_DEVICE_NAME_WRITE_PERM (-1)
+#define MYNEWT_VAL_BLE_SVC_GAP_PPCP_MAX_CONN_INTERVAL (0)
+#define MYNEWT_VAL_BLE_SVC_GAP_PPCP_MIN_CONN_INTERVAL (0)
+#define MYNEWT_VAL_BLE_SVC_GAP_PPCP_SLAVE_LATENCY (0)
+#define MYNEWT_VAL_BLE_SVC_GAP_PPCP_SUPERVISION_TMO (0)
+
+/* Overridden by targets/porting-nimble (defined by nimble/transport) */
+#define MYNEWT_VAL_BLE_HCI_TRANSPORT_NIMBLE_BUILTIN (0)
+#define MYNEWT_VAL_BLE_HCI_TRANSPORT_RAM (0)
+#define MYNEWT_VAL_BLE_HCI_TRANSPORT_SOCKET (0)
+#define MYNEWT_VAL_BLE_HCI_TRANSPORT_UART (1)
+
+/*** nimble/transport/uart */
+#define MYNEWT_VAL_BLE_ACL_BUF_COUNT (12)
+#define MYNEWT_VAL_BLE_ACL_BUF_SIZE (255)
+#define MYNEWT_VAL_BLE_HCI_ACL_OUT_COUNT (12)
+#define MYNEWT_VAL_BLE_HCI_EVT_BUF_SIZE (70)
+#define MYNEWT_VAL_BLE_HCI_EVT_HI_BUF_COUNT (8)
+#define MYNEWT_VAL_BLE_HCI_EVT_LO_BUF_COUNT (8)
+
+/* Overridden by targets/porting-nimble (defined by nimble/transport/uart) */
+#define MYNEWT_VAL_BLE_HCI_UART_BAUD (MICROPY_HW_BLE_UART_BAUDRATE)
+#define MYNEWT_VAL_BLE_HCI_UART_DATA_BITS (8)
+#define MYNEWT_VAL_BLE_HCI_UART_FLOW_CTRL (1)
+#define MYNEWT_VAL_BLE_HCI_UART_PARITY (HAL_UART_PARITY_NONE)
+#define MYNEWT_VAL_BLE_HCI_UART_PORT (MICROPY_HW_BLE_UART_ID)
+#define MYNEWT_VAL_BLE_HCI_UART_STOP_BITS (1)
+
+/* Required for code that uses BLE_HS_LOG */
+#define MYNEWT_VAL_NEWT_FEATURE_LOGCFG (1)
+
+#endif // MICROPY_INCLUDED_EXTMOD_NIMBLE_SYSCFG_H
diff --git a/extmod/re1.5/compilecode.c b/extmod/re1.5/compilecode.c
index a685a508a0..3f54b3993f 100644
--- a/extmod/re1.5/compilecode.c
+++ b/extmod/re1.5/compilecode.c
@@ -53,6 +53,9 @@ static const char *_compilecode(const char *re, ByteProg *prog, int sizecode)
PC++; // Skip # of pair byte
prog->len++;
for (cnt = 0; *re != ']'; re++, cnt++) {
+ if (*re == '\\') {
+ ++re;
+ }
if (!*re) return NULL;
EMIT(PC++, *re);
if (re[1] == '-' && re[2] != ']') {
diff --git a/extmod/uasyncio/__init__.py b/extmod/uasyncio/__init__.py
new file mode 100644
index 0000000000..08f924cf29
--- /dev/null
+++ b/extmod/uasyncio/__init__.py
@@ -0,0 +1,29 @@
+# MicroPython uasyncio module
+# MIT license; Copyright (c) 2019 Damien P. George
+
+from .core import *
+
+__version__ = (3, 0, 0)
+
+_attrs = {
+ "wait_for": "funcs",
+ "wait_for_ms": "funcs",
+ "gather": "funcs",
+ "Event": "event",
+ "Lock": "lock",
+ "open_connection": "stream",
+ "start_server": "stream",
+ "StreamReader": "stream",
+ "StreamWriter": "stream",
+}
+
+# Lazy loader, effectively does:
+# global attr
+# from .mod import attr
+def __getattr__(attr):
+ mod = _attrs.get(attr, None)
+ if mod is None:
+ raise AttributeError(attr)
+ value = getattr(__import__(mod, None, None, True, 1), attr)
+ globals()[attr] = value
+ return value
diff --git a/extmod/uasyncio/core.py b/extmod/uasyncio/core.py
new file mode 100644
index 0000000000..045b4cd139
--- /dev/null
+++ b/extmod/uasyncio/core.py
@@ -0,0 +1,277 @@
+# MicroPython uasyncio module
+# MIT license; Copyright (c) 2019 Damien P. George
+
+from time import ticks_ms as ticks, ticks_diff, ticks_add
+import sys, select
+
+# Import TaskQueue and Task, preferring built-in C code over Python code
+try:
+ from _uasyncio import TaskQueue, Task
+except:
+ from .task import TaskQueue, Task
+
+
+################################################################################
+# Exceptions
+
+
+class CancelledError(BaseException):
+ pass
+
+
+class TimeoutError(Exception):
+ pass
+
+
+# Used when calling Loop.call_exception_handler
+_exc_context = {"message": "Task exception wasn't retrieved", "exception": None, "future": None}
+
+
+################################################################################
+# Sleep functions
+
+# "Yield" once, then raise StopIteration
+class SingletonGenerator:
+ def __init__(self):
+ self.state = None
+ self.exc = StopIteration()
+
+ def __iter__(self):
+ return self
+
+ def __next__(self):
+ if self.state is not None:
+ _task_queue.push_sorted(cur_task, self.state)
+ self.state = None
+ return None
+ else:
+ self.exc.__traceback__ = None
+ raise self.exc
+
+
+# Pause task execution for the given time (integer in milliseconds, uPy extension)
+# Use a SingletonGenerator to do it without allocating on the heap
+def sleep_ms(t, sgen=SingletonGenerator()):
+ assert sgen.state is None
+ sgen.state = ticks_add(ticks(), max(0, t))
+ return sgen
+
+
+# Pause task execution for the given time (in seconds)
+def sleep(t):
+ return sleep_ms(int(t * 1000))
+
+
+################################################################################
+# Queue and poller for stream IO
+
+
+class IOQueue:
+ def __init__(self):
+ self.poller = select.poll()
+ self.map = {} # maps id(stream) to [task_waiting_read, task_waiting_write, stream]
+
+ def _enqueue(self, s, idx):
+ if id(s) not in self.map:
+ entry = [None, None, s]
+ entry[idx] = cur_task
+ self.map[id(s)] = entry
+ self.poller.register(s, select.POLLIN if idx == 0 else select.POLLOUT)
+ else:
+ sm = self.map[id(s)]
+ assert sm[idx] is None
+ assert sm[1 - idx] is not None
+ sm[idx] = cur_task
+ self.poller.modify(s, select.POLLIN | select.POLLOUT)
+ # Link task to this IOQueue so it can be removed if needed
+ cur_task.data = self
+
+ def _dequeue(self, s):
+ del self.map[id(s)]
+ self.poller.unregister(s)
+
+ def queue_read(self, s):
+ self._enqueue(s, 0)
+
+ def queue_write(self, s):
+ self._enqueue(s, 1)
+
+ def remove(self, task):
+ while True:
+ del_s = None
+ for k in self.map: # Iterate without allocating on the heap
+ q0, q1, s = self.map[k]
+ if q0 is task or q1 is task:
+ del_s = s
+ break
+ if del_s is not None:
+ self._dequeue(s)
+ else:
+ break
+
+ def wait_io_event(self, dt):
+ for s, ev in self.poller.ipoll(dt):
+ sm = self.map[id(s)]
+ # print('poll', s, sm, ev)
+ if ev & ~select.POLLOUT and sm[0] is not None:
+ # POLLIN or error
+ _task_queue.push_head(sm[0])
+ sm[0] = None
+ if ev & ~select.POLLIN and sm[1] is not None:
+ # POLLOUT or error
+ _task_queue.push_head(sm[1])
+ sm[1] = None
+ if sm[0] is None and sm[1] is None:
+ self._dequeue(s)
+ elif sm[0] is None:
+ self.poller.modify(s, select.POLLOUT)
+ else:
+ self.poller.modify(s, select.POLLIN)
+
+
+################################################################################
+# Main run loop
+
+# Ensure the awaitable is a task
+def _promote_to_task(aw):
+ return aw if isinstance(aw, Task) else create_task(aw)
+
+
+# Create and schedule a new task from a coroutine
+def create_task(coro):
+ if not hasattr(coro, "send"):
+ raise TypeError("coroutine expected")
+ t = Task(coro, globals())
+ _task_queue.push_head(t)
+ return t
+
+
+# Keep scheduling tasks until there are none left to schedule
+def run_until_complete(main_task=None):
+ global cur_task
+ excs_all = (CancelledError, Exception) # To prevent heap allocation in loop
+ excs_stop = (CancelledError, StopIteration) # To prevent heap allocation in loop
+ while True:
+ # Wait until the head of _task_queue is ready to run
+ dt = 1
+ while dt > 0:
+ dt = -1
+ t = _task_queue.peek()
+ if t:
+ # A task waiting on _task_queue; "ph_key" is time to schedule task at
+ dt = max(0, ticks_diff(t.ph_key, ticks()))
+ elif not _io_queue.map:
+ # No tasks can be woken so finished running
+ return
+ # print('(poll {})'.format(dt), len(_io_queue.map))
+ _io_queue.wait_io_event(dt)
+
+ # Get next task to run and continue it
+ t = _task_queue.pop_head()
+ cur_task = t
+ try:
+ # Continue running the coroutine, it's responsible for rescheduling itself
+ exc = t.data
+ if not exc:
+ t.coro.send(None)
+ else:
+ t.data = None
+ t.coro.throw(exc)
+ except excs_all as er:
+ # Check the task is not on any event queue
+ assert t.data is None
+ # This task is done, check if it's the main task and then loop should stop
+ if t is main_task:
+ if isinstance(er, StopIteration):
+ return er.value
+ raise er
+ # Save return value of coro to pass up to caller
+ t.data = er
+ # Schedule any other tasks waiting on the completion of this task
+ waiting = False
+ if hasattr(t, "waiting"):
+ while t.waiting.peek():
+ _task_queue.push_head(t.waiting.pop_head())
+ waiting = True
+ t.waiting = None # Free waiting queue head
+ # Print out exception for detached tasks
+ if not waiting and not isinstance(er, excs_stop):
+ _exc_context["exception"] = er
+ _exc_context["future"] = t
+ Loop.call_exception_handler(_exc_context)
+ # Indicate task is done
+ t.coro = None
+
+
+# Create a new task from a coroutine and run it until it finishes
+def run(coro):
+ return run_until_complete(create_task(coro))
+
+
+################################################################################
+# Event loop wrapper
+
+
+async def _stopper():
+ pass
+
+
+_stop_task = None
+
+
+class Loop:
+ _exc_handler = None
+
+ def create_task(coro):
+ return create_task(coro)
+
+ def run_forever():
+ global _stop_task
+ _stop_task = Task(_stopper(), globals())
+ run_until_complete(_stop_task)
+ # TODO should keep running until .stop() is called, even if there're no tasks left
+
+ def run_until_complete(aw):
+ return run_until_complete(_promote_to_task(aw))
+
+ def stop():
+ global _stop_task
+ if _stop_task is not None:
+ _task_queue.push_head(_stop_task)
+ # If stop() is called again, do nothing
+ _stop_task = None
+
+ def close():
+ pass
+
+ def set_exception_handler(handler):
+ Loop._exc_handler = handler
+
+ def get_exception_handler():
+ return Loop._exc_handler
+
+ def default_exception_handler(loop, context):
+ print(context["message"])
+ print("future:", context["future"], "coro=", context["future"].coro)
+ sys.print_exception(context["exception"])
+
+ def call_exception_handler(context):
+ (Loop._exc_handler or Loop.default_exception_handler)(Loop, context)
+
+
+# The runq_len and waitq_len arguments are for legacy uasyncio compatibility
+def get_event_loop(runq_len=0, waitq_len=0):
+ return Loop
+
+
+def new_event_loop():
+ global _task_queue, _io_queue
+ # TaskQueue of Task instances
+ _task_queue = TaskQueue()
+ # Task queue and poller for stream IO
+ _io_queue = IOQueue()
+ return Loop
+
+
+# Initialise default event loop
+new_event_loop()
diff --git a/extmod/uasyncio/event.py b/extmod/uasyncio/event.py
new file mode 100644
index 0000000000..31cb00e055
--- /dev/null
+++ b/extmod/uasyncio/event.py
@@ -0,0 +1,31 @@
+# MicroPython uasyncio module
+# MIT license; Copyright (c) 2019-2020 Damien P. George
+
+from . import core
+
+# Event class for primitive events that can be waited on, set, and cleared
+class Event:
+ def __init__(self):
+ self.state = False # False=unset; True=set
+ self.waiting = core.TaskQueue() # Queue of Tasks waiting on completion of this event
+
+ def is_set(self):
+ return self.state
+
+ def set(self):
+ # Event becomes set, schedule any tasks waiting on it
+ while self.waiting.peek():
+ core._task_queue.push_head(self.waiting.pop_head())
+ self.state = True
+
+ def clear(self):
+ self.state = False
+
+ async def wait(self):
+ if not self.state:
+ # Event not set, put the calling task on the event's waiting queue
+ self.waiting.push_head(core.cur_task)
+ # Set calling task's data to the event's queue so it can be removed if needed
+ core.cur_task.data = self.waiting
+ yield
+ return True
diff --git a/extmod/uasyncio/funcs.py b/extmod/uasyncio/funcs.py
new file mode 100644
index 0000000000..6e1305c94f
--- /dev/null
+++ b/extmod/uasyncio/funcs.py
@@ -0,0 +1,54 @@
+# MicroPython uasyncio module
+# MIT license; Copyright (c) 2019-2020 Damien P. George
+
+from . import core
+
+
+async def wait_for(aw, timeout, sleep=core.sleep):
+ aw = core._promote_to_task(aw)
+ if timeout is None:
+ return await aw
+
+ def cancel(aw, timeout, sleep):
+ await sleep(timeout)
+ aw.cancel()
+
+ cancel_task = core.create_task(cancel(aw, timeout, sleep))
+ try:
+ ret = await aw
+ except core.CancelledError:
+ # Ignore CancelledError from aw, it's probably due to timeout
+ pass
+ finally:
+ # Cancel the "cancel" task if it's still active (optimisation instead of cancel_task.cancel())
+ if cancel_task.coro is not None:
+ core._task_queue.remove(cancel_task)
+ if cancel_task.coro is None:
+ # Cancel task ran to completion, ie there was a timeout
+ raise core.TimeoutError
+ return ret
+
+
+def wait_for_ms(aw, timeout):
+ return wait_for(aw, timeout, core.sleep_ms)
+
+
+async def gather(*aws, return_exceptions=False):
+ ts = [core._promote_to_task(aw) for aw in aws]
+ for i in range(len(ts)):
+ try:
+ # TODO handle cancel of gather itself
+ # if ts[i].coro:
+ # iter(ts[i]).waiting.push_head(cur_task)
+ # try:
+ # yield
+ # except CancelledError as er:
+ # # cancel all waiting tasks
+ # raise er
+ ts[i] = await ts[i]
+ except Exception as er:
+ if return_exceptions:
+ ts[i] = er
+ else:
+ raise er
+ return ts
diff --git a/extmod/uasyncio/lock.py b/extmod/uasyncio/lock.py
new file mode 100644
index 0000000000..bddca295b6
--- /dev/null
+++ b/extmod/uasyncio/lock.py
@@ -0,0 +1,53 @@
+# MicroPython uasyncio module
+# MIT license; Copyright (c) 2019-2020 Damien P. George
+
+from . import core
+
+# Lock class for primitive mutex capability
+class Lock:
+ def __init__(self):
+ # The state can take the following values:
+ # - 0: unlocked
+ # - 1: locked
+ # - : unlocked but this task has been scheduled to acquire the lock next
+ self.state = 0
+ # Queue of Tasks waiting to acquire this Lock
+ self.waiting = core.TaskQueue()
+
+ def locked(self):
+ return self.state == 1
+
+ def release(self):
+ if self.state != 1:
+ raise RuntimeError("Lock not acquired")
+ if self.waiting.peek():
+ # Task(s) waiting on lock, schedule next Task
+ self.state = self.waiting.pop_head()
+ core._task_queue.push_head(self.state)
+ else:
+ # No Task waiting so unlock
+ self.state = 0
+
+ async def acquire(self):
+ if self.state != 0:
+ # Lock unavailable, put the calling Task on the waiting queue
+ self.waiting.push_head(core.cur_task)
+ # Set calling task's data to the lock's queue so it can be removed if needed
+ core.cur_task.data = self.waiting
+ try:
+ yield
+ except core.CancelledError as er:
+ if self.state == core.cur_task:
+ # Cancelled while pending on resume, schedule next waiting Task
+ self.state = 1
+ self.release()
+ raise er
+ # Lock available, set it as locked
+ self.state = 1
+ return True
+
+ async def __aenter__(self):
+ return await self.acquire()
+
+ async def __aexit__(self, exc_type, exc, tb):
+ return self.release()
diff --git a/extmod/uasyncio/manifest.py b/extmod/uasyncio/manifest.py
new file mode 100644
index 0000000000..f5fa27bfca
--- /dev/null
+++ b/extmod/uasyncio/manifest.py
@@ -0,0 +1,13 @@
+# This list of frozen files doesn't include task.py because that's provided by the C module.
+freeze(
+ "..",
+ (
+ "uasyncio/__init__.py",
+ "uasyncio/core.py",
+ "uasyncio/event.py",
+ "uasyncio/funcs.py",
+ "uasyncio/lock.py",
+ "uasyncio/stream.py",
+ ),
+ opt=3,
+)
diff --git a/extmod/uasyncio/stream.py b/extmod/uasyncio/stream.py
new file mode 100644
index 0000000000..b6d787e4f0
--- /dev/null
+++ b/extmod/uasyncio/stream.py
@@ -0,0 +1,158 @@
+# MicroPython uasyncio module
+# MIT license; Copyright (c) 2019-2020 Damien P. George
+
+from . import core
+
+
+class Stream:
+ def __init__(self, s, e={}):
+ self.s = s
+ self.e = e
+ self.out_buf = b""
+
+ def get_extra_info(self, v):
+ return self.e[v]
+
+ async def __aenter__(self):
+ return self
+
+ async def __aexit__(self, exc_type, exc, tb):
+ await self.close()
+
+ def close(self):
+ pass
+
+ async def wait_closed(self):
+ # TODO yield?
+ self.s.close()
+
+ async def read(self, n):
+ yield core._io_queue.queue_read(self.s)
+ return self.s.read(n)
+
+ async def readexactly(self, n):
+ r = b""
+ while n:
+ yield core._io_queue.queue_read(self.s)
+ r2 = self.s.read(n)
+ if r2 is not None:
+ if not len(r2):
+ raise EOFError
+ r += r2
+ n -= len(r2)
+ return r
+
+ async def readline(self):
+ l = b""
+ while True:
+ yield core._io_queue.queue_read(self.s)
+ l2 = self.s.readline() # may do multiple reads but won't block
+ l += l2
+ if not l2 or l[-1] == 10: # \n (check l in case l2 is str)
+ return l
+
+ def write(self, buf):
+ self.out_buf += buf
+
+ async def drain(self):
+ mv = memoryview(self.out_buf)
+ off = 0
+ while off < len(mv):
+ yield core._io_queue.queue_write(self.s)
+ ret = self.s.write(mv[off:])
+ if ret is not None:
+ off += ret
+ self.out_buf = b""
+
+
+# Stream can be used for both reading and writing to save code size
+StreamReader = Stream
+StreamWriter = Stream
+
+
+# Create a TCP stream connection to a remote host
+async def open_connection(host, port):
+ from uerrno import EINPROGRESS
+ import usocket as socket
+
+ ai = socket.getaddrinfo(host, port)[0] # TODO this is blocking!
+ s = socket.socket()
+ s.setblocking(False)
+ ss = Stream(s)
+ try:
+ s.connect(ai[-1])
+ except OSError as er:
+ if er.args[0] != EINPROGRESS:
+ raise er
+ yield core._io_queue.queue_write(s)
+ return ss, ss
+
+
+# Class representing a TCP stream server, can be closed and used in "async with"
+class Server:
+ async def __aenter__(self):
+ return self
+
+ async def __aexit__(self, exc_type, exc, tb):
+ self.close()
+ await self.wait_closed()
+
+ def close(self):
+ self.task.cancel()
+
+ async def wait_closed(self):
+ await self.task
+
+ async def _serve(self, cb, host, port, backlog):
+ import usocket as socket
+
+ ai = socket.getaddrinfo(host, port)[0] # TODO this is blocking!
+ s = socket.socket()
+ s.setblocking(False)
+ s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+ s.bind(ai[-1])
+ s.listen(backlog)
+ self.task = core.cur_task
+ # Accept incoming connections
+ while True:
+ try:
+ yield core._io_queue.queue_read(s)
+ except core.CancelledError:
+ # Shutdown server
+ s.close()
+ return
+ try:
+ s2, addr = s.accept()
+ except:
+ # Ignore a failed accept
+ continue
+ s2.setblocking(False)
+ s2s = Stream(s2, {"peername": addr})
+ core.create_task(cb(s2s, s2s))
+
+
+# Helper function to start a TCP stream server, running as a new task
+# TODO could use an accept-callback on socket read activity instead of creating a task
+async def start_server(cb, host, port, backlog=5):
+ s = Server()
+ core.create_task(s._serve(cb, host, port, backlog))
+ return s
+
+
+################################################################################
+# Legacy uasyncio compatibility
+
+
+async def stream_awrite(self, buf, off=0, sz=-1):
+ if off != 0 or sz != -1:
+ buf = memoryview(buf)
+ if sz == -1:
+ sz = len(buf)
+ buf = buf[off : off + sz]
+ self.write(buf)
+ await self.drain()
+
+
+Stream.aclose = Stream.wait_closed
+Stream.awrite = stream_awrite
+Stream.awritestr = stream_awrite # TODO explicitly convert to bytes?
diff --git a/extmod/uasyncio/task.py b/extmod/uasyncio/task.py
new file mode 100644
index 0000000000..1788cf0ed0
--- /dev/null
+++ b/extmod/uasyncio/task.py
@@ -0,0 +1,168 @@
+# MicroPython uasyncio module
+# MIT license; Copyright (c) 2019-2020 Damien P. George
+
+# This file contains the core TaskQueue based on a pairing heap, and the core Task class.
+# They can optionally be replaced by C implementations.
+
+from . import core
+
+
+# pairing-heap meld of 2 heaps; O(1)
+def ph_meld(h1, h2):
+ if h1 is None:
+ return h2
+ if h2 is None:
+ return h1
+ lt = core.ticks_diff(h1.ph_key, h2.ph_key) < 0
+ if lt:
+ if h1.ph_child is None:
+ h1.ph_child = h2
+ else:
+ h1.ph_child_last.ph_next = h2
+ h1.ph_child_last = h2
+ h2.ph_next = None
+ h2.ph_rightmost_parent = h1
+ return h1
+ else:
+ h1.ph_next = h2.ph_child
+ h2.ph_child = h1
+ if h1.ph_next is None:
+ h2.ph_child_last = h1
+ h1.ph_rightmost_parent = h2
+ return h2
+
+
+# pairing-heap pairing operation; amortised O(log N)
+def ph_pairing(child):
+ heap = None
+ while child is not None:
+ n1 = child
+ child = child.ph_next
+ n1.ph_next = None
+ if child is not None:
+ n2 = child
+ child = child.ph_next
+ n2.ph_next = None
+ n1 = ph_meld(n1, n2)
+ heap = ph_meld(heap, n1)
+ return heap
+
+
+# pairing-heap delete of a node; stable, amortised O(log N)
+def ph_delete(heap, node):
+ if node is heap:
+ child = heap.ph_child
+ node.ph_child = None
+ return ph_pairing(child)
+ # Find parent of node
+ parent = node
+ while parent.ph_next is not None:
+ parent = parent.ph_next
+ parent = parent.ph_rightmost_parent
+ # Replace node with pairing of its children
+ if node is parent.ph_child and node.ph_child is None:
+ parent.ph_child = node.ph_next
+ node.ph_next = None
+ return heap
+ elif node is parent.ph_child:
+ child = node.ph_child
+ next = node.ph_next
+ node.ph_child = None
+ node.ph_next = None
+ node = ph_pairing(child)
+ parent.ph_child = node
+ else:
+ n = parent.ph_child
+ while node is not n.ph_next:
+ n = n.ph_next
+ child = node.ph_child
+ next = node.ph_next
+ node.ph_child = None
+ node.ph_next = None
+ node = ph_pairing(child)
+ if node is None:
+ node = n
+ else:
+ n.ph_next = node
+ node.ph_next = next
+ if next is None:
+ node.ph_rightmost_parent = parent
+ parent.ph_child_last = node
+ return heap
+
+
+# TaskQueue class based on the above pairing-heap functions.
+class TaskQueue:
+ def __init__(self):
+ self.heap = None
+
+ def peek(self):
+ return self.heap
+
+ def push_sorted(self, v, key):
+ v.data = None
+ v.ph_key = key
+ v.ph_child = None
+ v.ph_next = None
+ self.heap = ph_meld(v, self.heap)
+
+ def push_head(self, v):
+ self.push_sorted(v, core.ticks())
+
+ def pop_head(self):
+ v = self.heap
+ self.heap = ph_pairing(self.heap.ph_child)
+ return v
+
+ def remove(self, v):
+ self.heap = ph_delete(self.heap, v)
+
+
+# Task class representing a coroutine, can be waited on and cancelled.
+class Task:
+ def __init__(self, coro, globals=None):
+ self.coro = coro # Coroutine of this Task
+ self.data = None # General data for queue it is waiting on
+ self.ph_key = 0 # Pairing heap
+ self.ph_child = None # Paring heap
+ self.ph_child_last = None # Paring heap
+ self.ph_next = None # Paring heap
+ self.ph_rightmost_parent = None # Paring heap
+
+ def __iter__(self):
+ if not hasattr(self, "waiting"):
+ # Lazily allocated head of linked list of Tasks waiting on completion of this task.
+ self.waiting = TaskQueue()
+ return self
+
+ def __next__(self):
+ if not self.coro:
+ # Task finished, raise return value to caller so it can continue.
+ raise self.data
+ else:
+ # Put calling task on waiting queue.
+ self.waiting.push_head(core.cur_task)
+ # Set calling task's data to this task that it waits on, to double-link it.
+ core.cur_task.data = self
+
+ def cancel(self):
+ # Check if task is already finished.
+ if self.coro is None:
+ return False
+ # Can't cancel self (not supported yet).
+ if self is core.cur_task:
+ raise RuntimeError("can't cancel self")
+ # If Task waits on another task then forward the cancel to the one it's waiting on.
+ while isinstance(self.data, Task):
+ self = self.data
+ # Reschedule Task as a cancelled task.
+ if hasattr(self.data, "remove"):
+ # Not on the main running queue, remove the task from the queue it's on.
+ self.data.remove(self)
+ core._task_queue.push_head(self)
+ elif core.ticks_diff(self.ph_key, core.ticks()) > 0:
+ # On the main running queue but scheduled in the future, so bring it forward to now.
+ core._task_queue.remove(self)
+ core._task_queue.push_head(self)
+ self.data = core.CancelledError
+ return True
diff --git a/extmod/uos_dupterm.c b/extmod/uos_dupterm.c
index 42cb21444b..ad706d5246 100644
--- a/extmod/uos_dupterm.c
+++ b/extmod/uos_dupterm.c
@@ -4,7 +4,7 @@
* The MIT License (MIT)
*
* Copyright (c) 2016 Paul Sokolovsky
- * Copyright (c) 2017 Damien P. George
+ * Copyright (c) 2017-2019 Damien P. George
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -53,6 +53,45 @@ void mp_uos_deactivate(size_t dupterm_idx, const char *msg, mp_obj_t exc) {
}
}
+uintptr_t mp_uos_dupterm_poll(uintptr_t poll_flags) {
+ uintptr_t poll_flags_out = 0;
+
+ for (size_t idx = 0; idx < MICROPY_PY_OS_DUPTERM; ++idx) {
+ mp_obj_t s = MP_STATE_VM(dupterm_objs[idx]);
+ if (s == MP_OBJ_NULL) {
+ continue;
+ }
+
+ int errcode = 0;
+ mp_uint_t ret = 0;
+ const mp_stream_p_t *stream_p = mp_get_stream(s);
+ #if MICROPY_PY_UOS_DUPTERM_BUILTIN_STREAM
+ if (mp_uos_dupterm_is_builtin_stream(s)) {
+ ret = stream_p->ioctl(s, MP_STREAM_POLL, poll_flags, &errcode);
+ } else
+ #endif
+ {
+ nlr_buf_t nlr;
+ if (nlr_push(&nlr) == 0) {
+ ret = stream_p->ioctl(s, MP_STREAM_POLL, poll_flags, &errcode);
+ nlr_pop();
+ } else {
+ // Ignore error with ioctl
+ }
+ }
+
+ if (ret != MP_STREAM_ERROR) {
+ poll_flags_out |= ret;
+ if (poll_flags_out == poll_flags) {
+ // Finish early if all requested flags are set
+ break;
+ }
+ }
+ }
+
+ return poll_flags_out;
+}
+
int mp_uos_dupterm_rx_chr(void) {
for (size_t idx = 0; idx < MICROPY_PY_OS_DUPTERM; ++idx) {
if (MP_STATE_VM(dupterm_objs[idx]) == MP_OBJ_NULL) {
@@ -67,9 +106,9 @@ int mp_uos_dupterm_rx_chr(void) {
mp_uint_t out_sz = stream_p->read(MP_STATE_VM(dupterm_objs[idx]), buf, 1, &errcode);
if (errcode == 0 && out_sz != 0) {
return buf[0];
- } else {
+ } else {
continue;
- }
+ }
}
#endif
@@ -140,7 +179,7 @@ STATIC mp_obj_t mp_uos_dupterm(size_t n_args, const mp_obj_t *args) {
}
if (idx < 0 || idx >= MICROPY_PY_OS_DUPTERM) {
- mp_raise_ValueError("invalid dupterm index");
+ mp_raise_ValueError(MP_ERROR_TEXT("invalid dupterm index"));
}
mp_obj_t previous_obj = MP_STATE_VM(dupterm_objs[idx]);
diff --git a/extmod/utime_mphal.c b/extmod/utime_mphal.c
index 0fe3a3ba1d..6aff2cac72 100644
--- a/extmod/utime_mphal.c
+++ b/extmod/utime_mphal.c
@@ -86,7 +86,7 @@ STATIC mp_obj_t time_ticks_diff(mp_obj_t end_in, mp_obj_t start_in) {
// Optimized formula avoiding if conditions. We adjust difference "forward",
// wrap it around and adjust back.
mp_int_t diff = ((end - start + MICROPY_PY_UTIME_TICKS_PERIOD / 2) & (MICROPY_PY_UTIME_TICKS_PERIOD - 1))
- - MICROPY_PY_UTIME_TICKS_PERIOD / 2;
+ - MICROPY_PY_UTIME_TICKS_PERIOD / 2;
return MP_OBJ_NEW_SMALL_INT(diff);
}
MP_DEFINE_CONST_FUN_OBJ_2(mp_utime_ticks_diff_obj, time_ticks_diff);
diff --git a/extmod/uzlib/tinflate.c b/extmod/uzlib/tinflate.c
index b93bc1fa36..045952c755 100644
--- a/extmod/uzlib/tinflate.c
+++ b/extmod/uzlib/tinflate.c
@@ -464,7 +464,7 @@ static int tinf_inflate_block_data(TINF_DATA *d, TINF_TREE *lt, TINF_TREE *dt)
}
} else {
/* catch trying to point before the start of dest buffer */
- if (offs > d->dest - d->destStart) {
+ if (offs > (unsigned int)(d->dest - d->destStart)) {
return TINF_DATA_ERROR;
}
d->lzOff = -offs;
diff --git a/extmod/vfs.c b/extmod/vfs.c
index e94a9abadb..25e495e436 100644
--- a/extmod/vfs.c
+++ b/extmod/vfs.c
@@ -119,7 +119,7 @@ STATIC mp_vfs_mount_t *lookup_path(mp_obj_t path_in, mp_obj_t *path_out) {
mp_vfs_mount_t *vfs = mp_vfs_lookup_path(path, &p_out);
if (vfs != MP_VFS_NONE && vfs != MP_VFS_ROOT) {
*path_out = mp_obj_new_str_of_type(mp_obj_get_type(path_in),
- (const byte*)p_out, strlen(p_out));
+ (const byte *)p_out, strlen(p_out));
}
return vfs;
}
@@ -179,8 +179,8 @@ mp_import_stat_t mp_vfs_import_stat(const char *path) {
mp_obj_t mp_vfs_mount(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_readonly, ARG_mkfs };
static const mp_arg_t allowed_args[] = {
- { MP_QSTR_readonly, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_false_obj)} },
- { MP_QSTR_mkfs, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_false_obj)} },
+ { MP_QSTR_readonly, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_FALSE} },
+ { MP_QSTR_mkfs, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_FALSE} },
};
// parse args
@@ -212,7 +212,7 @@ mp_obj_t mp_vfs_mount(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args
vfs->next = NULL;
// call the underlying object to do any mounting operation
- mp_vfs_proxy_call(vfs, MP_QSTR_mount, 2, (mp_obj_t*)&args);
+ mp_vfs_proxy_call(vfs, MP_QSTR_mount, 2, (mp_obj_t *)&args);
// check that the destination mount point is unused
const char *path_out;
@@ -278,10 +278,10 @@ MP_DEFINE_CONST_FUN_OBJ_1(mp_vfs_umount_obj, mp_vfs_umount);
mp_obj_t mp_vfs_open(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_file, ARG_mode, ARG_encoding };
static const mp_arg_t allowed_args[] = {
- { MP_QSTR_file, MP_ARG_OBJ | MP_ARG_REQUIRED, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} },
+ { MP_QSTR_file, MP_ARG_OBJ | MP_ARG_REQUIRED, {.u_rom_obj = MP_ROM_NONE} },
{ MP_QSTR_mode, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_QSTR(MP_QSTR_r)} },
{ MP_QSTR_buffering, MP_ARG_INT, {.u_int = -1} },
- { MP_QSTR_encoding, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} },
+ { MP_QSTR_encoding, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
};
// parse args
@@ -296,14 +296,13 @@ mp_obj_t mp_vfs_open(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args)
#endif
mp_vfs_mount_t *vfs = lookup_path(args[ARG_file].u_obj, &args[ARG_file].u_obj);
- return mp_vfs_proxy_call(vfs, MP_QSTR_open, 2, (mp_obj_t*)&args);
+ return mp_vfs_proxy_call(vfs, MP_QSTR_open, 2, (mp_obj_t *)&args);
}
MP_DEFINE_CONST_FUN_OBJ_KW(mp_vfs_open_obj, 0, mp_vfs_open);
mp_obj_t mp_vfs_chdir(mp_obj_t path_in) {
mp_obj_t path_out;
mp_vfs_mount_t *vfs = lookup_path(path_in, &path_out);
- MP_STATE_VM(vfs_cur) = vfs;
if (vfs == MP_VFS_ROOT) {
// If we change to the root dir and a VFS is mounted at the root then
// we must change that VFS's current dir to the root dir so that any
@@ -315,9 +314,11 @@ mp_obj_t mp_vfs_chdir(mp_obj_t path_in) {
break;
}
}
+ vfs = MP_VFS_ROOT;
} else {
mp_vfs_proxy_call(vfs, MP_QSTR_chdir, 1, &path_out);
}
+ MP_STATE_VM(vfs_cur) = vfs;
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_1(mp_vfs_chdir_obj, mp_vfs_chdir);
@@ -376,7 +377,7 @@ STATIC mp_obj_t mp_vfs_ilistdir_it_iternext(mp_obj_t self_in) {
mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(3, NULL));
t->items[0] = mp_obj_new_str_of_type(
self->is_str ? &mp_type_str : &mp_type_bytes,
- (const byte*)vfs->str + 1, vfs->len - 1);
+ (const byte *)vfs->str + 1, vfs->len - 1);
t->items[1] = MP_OBJ_NEW_SMALL_INT(MP_S_IFDIR);
t->items[2] = MP_OBJ_NEW_SMALL_INT(0); // no inode number
return MP_OBJ_FROM_PTR(t);
@@ -527,41 +528,62 @@ MP_DEFINE_CONST_FUN_OBJ_1(mp_vfs_getfree_obj, mp_vfs_getfree);
mp_obj_t mp_vfs_fsformat(mp_obj_t path_in)
{
- if (path_in != NULL)
- {
- if (MP_OBJ_IS_STR_OR_BYTES(path_in))
- {
- const char *path = mp_obj_str_get_str(path_in);
-
- int len = strlen(path);
- if(*path == '\0' || path[0] != '/')
- {
- nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "%s is not an absolute or invalid path", path));
- }
- else if (len == 1 && path[0] == '/')
- {
- nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "Cannot format root dir"));
- }
- else
- {
- for (mp_vfs_mount_t *vfs = MP_STATE_VM(vfs_mount_table); vfs != NULL; vfs = vfs->next)
- {
- if(!strcmp(vfs->str, path))
- {
- return mp_vfs_proxy_call(vfs, MP_QSTR_fsformat, 0, NULL);
- }
- }
- mp_raise_OSError(MP_ENODEV);
- }
- }
- else
- {
- nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "please specify correct fs mount path"));
- }
- }
-
- return MP_VFS_NONE;
+ if (path_in != NULL)
+ {
+ if (MP_OBJ_IS_STR_OR_BYTES(path_in))
+ {
+ const char *path = mp_obj_str_get_str(path_in);
+
+ int len = strlen(path);
+ if(*path == '\0' || path[0] != '/')
+ {
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "%s is not an absolute or invalid path", path));
+ }
+ else if (len == 1 && path[0] == '/')
+ {
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "Cannot format root dir"));
+ }
+ else
+ {
+ for (mp_vfs_mount_t *vfs = MP_STATE_VM(vfs_mount_table); vfs != NULL; vfs = vfs->next)
+ {
+ if(!strcmp(vfs->str, path))
+ {
+ return mp_vfs_proxy_call(vfs, MP_QSTR_fsformat, 0, NULL);
+ }
+ }
+ mp_raise_OSError(MP_ENODEV);
+ }
+ }
+ else
+ {
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "please specify correct fs mount path"));
+ }
+ }
+
+ return MP_VFS_NONE;
}
MP_DEFINE_CONST_FUN_OBJ_1(mp_vfs_fsformat_obj, mp_vfs_fsformat);
+// This is a C-level helper function for ports to use if needed.
+int mp_vfs_mount_and_chdir_protected(mp_obj_t bdev, mp_obj_t mount_point) {
+ nlr_buf_t nlr;
+ mp_int_t ret = -MP_EIO;
+ if (nlr_push(&nlr) == 0) {
+ mp_obj_t args[] = { bdev, mount_point };
+ mp_vfs_mount(2, args, (mp_map_t *)&mp_const_empty_map);
+ mp_vfs_chdir(mount_point);
+ ret = 0; // success
+ nlr_pop();
+ } else {
+ mp_obj_base_t *exc = nlr.ret_val;
+ if (mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(exc->type), MP_OBJ_FROM_PTR(&mp_type_OSError))) {
+ mp_obj_t v = mp_obj_exception_get_value(MP_OBJ_FROM_PTR(exc));
+ mp_obj_get_int_maybe(v, &ret); // get errno value
+ ret = -ret;
+ }
+ }
+ return ret;
+}
+
#endif // MICROPY_VFS
diff --git a/extmod/vfs.h b/extmod/vfs.h
index 9b748b53fa..3188496380 100644
--- a/extmod/vfs.h
+++ b/extmod/vfs.h
@@ -33,25 +33,37 @@
// return values of mp_vfs_lookup_path
// ROOT is 0 so that the default current directory is the root directory
-#define MP_VFS_NONE ((mp_vfs_mount_t*)1)
-#define MP_VFS_ROOT ((mp_vfs_mount_t*)0)
+#define MP_VFS_NONE ((mp_vfs_mount_t *)1)
+#define MP_VFS_ROOT ((mp_vfs_mount_t *)0)
// MicroPython's port-standardized versions of stat constants
#define MP_S_IFDIR (0x4000)
#define MP_S_IFREG (0x8000)
+// these are the values for mp_vfs_blockdev_t.flags
+#define MP_BLOCKDEV_FLAG_NATIVE (0x0001) // readblocks[2]/writeblocks[2] contain native func
+#define MP_BLOCKDEV_FLAG_FREE_OBJ (0x0002) // fs_user_mount_t obj should be freed on umount
+#define MP_BLOCKDEV_FLAG_HAVE_IOCTL (0x0004) // new protocol with ioctl
+#define MP_BLOCKDEV_FLAG_NO_FILESYSTEM (0x0008) // the block device has no filesystem on it
+
// constants for block protocol ioctl
-#define BP_IOCTL_INIT (1)
-#define BP_IOCTL_DEINIT (2)
-#define BP_IOCTL_SYNC (3)
-#define BP_IOCTL_SEC_COUNT (4)
-#define BP_IOCTL_SEC_SIZE (5)
+#define MP_BLOCKDEV_IOCTL_INIT (1)
+#define MP_BLOCKDEV_IOCTL_DEINIT (2)
+#define MP_BLOCKDEV_IOCTL_SYNC (3)
+#define MP_BLOCKDEV_IOCTL_BLOCK_COUNT (4)
+#define MP_BLOCKDEV_IOCTL_BLOCK_SIZE (5)
+#define MP_BLOCKDEV_IOCTL_BLOCK_ERASE (6)
-typedef struct _fs_user_mount_t {
- mp_obj_base_t base;
+// At the moment the VFS protocol just has import_stat, but could be extended to other methods
+typedef struct _mp_vfs_proto_t {
+ mp_import_stat_t (*import_stat)(void *self, const char *path);
+} mp_vfs_proto_t;
+
+typedef struct _mp_vfs_blockdev_t {
uint16_t flags;
- mp_obj_t readblocks[4];
- mp_obj_t writeblocks[4];
+ size_t block_size;
+ mp_obj_t readblocks[5];
+ mp_obj_t writeblocks[5];
// new protocol uses just ioctl, old uses sync (optional) and count
union {
mp_obj_t ioctl[4];
@@ -60,17 +72,18 @@ typedef struct _fs_user_mount_t {
mp_obj_t count[2];
} old;
} u;
- //Block device underlying this filesystem
+} mp_vfs_blockdev_t;
+
+typedef struct _fs_user_mount_t {
+ mp_obj_base_t base;
+ mp_vfs_blockdev_t blockdev;
+ // File System on this blockdevice
union {
FATFS fatfs;
vfs_lfs_struct_t littlefs;
} fs;
} fs_user_mount_t;
-typedef struct _mp_vfs_proto_t {
- mp_import_stat_t (*import_stat)(void *self, const char *path);
-} mp_vfs_proto_t;
-
typedef struct _mp_vfs_mount_t {
const char *str; // mount point with leading /
size_t len;
@@ -82,6 +95,13 @@ extern FATFS *lookup_path_fatfs(const TCHAR *path, const TCHAR **path_out);
extern vfs_lfs_struct_t *lookup_path_littlefs(const TCHAR *path, const TCHAR **path_out);
extern mp_import_stat_t littleFS_vfs_import_stat(fs_user_mount_t *vfs, const char *path);
+void mp_vfs_blockdev_init(mp_vfs_blockdev_t *self, mp_obj_t bdev);
+int mp_vfs_blockdev_read(mp_vfs_blockdev_t *self, size_t block_num, size_t num_blocks, uint8_t *buf);
+int mp_vfs_blockdev_read_ext(mp_vfs_blockdev_t *self, size_t block_num, size_t block_off, size_t len, uint8_t *buf);
+int mp_vfs_blockdev_write(mp_vfs_blockdev_t *self, size_t block_num, size_t num_blocks, const uint8_t *buf);
+int mp_vfs_blockdev_write_ext(mp_vfs_blockdev_t *self, size_t block_num, size_t block_off, size_t len, const uint8_t *buf);
+mp_obj_t mp_vfs_blockdev_ioctl(mp_vfs_blockdev_t *self, uintptr_t cmd, uintptr_t arg);
+
mp_vfs_mount_t *mp_vfs_lookup_path(const char *path, const char **path_out);
mp_import_stat_t mp_vfs_import_stat(const char *path);
mp_obj_t mp_vfs_mount(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
@@ -100,6 +120,8 @@ mp_obj_t mp_vfs_statvfs(mp_obj_t path_in);
mp_obj_t mp_vfs_getfree(mp_obj_t path_in);
mp_obj_t mp_vfs_fsformat(mp_obj_t path_in);
+int mp_vfs_mount_and_chdir_protected(mp_obj_t bdev, mp_obj_t mount_point);
+
MP_DECLARE_CONST_FUN_OBJ_KW(mp_vfs_mount_obj);
MP_DECLARE_CONST_FUN_OBJ_1(mp_vfs_umount_obj);
MP_DECLARE_CONST_FUN_OBJ_KW(mp_vfs_open_obj);
diff --git a/extmod/vfs_blockdev.c b/extmod/vfs_blockdev.c
new file mode 100644
index 0000000000..57c83b4289
--- /dev/null
+++ b/extmod/vfs_blockdev.c
@@ -0,0 +1,143 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2013-2019 Damien P. George
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "py/runtime.h"
+#include "py/binary.h"
+#include "py/objarray.h"
+#include "py/mperrno.h"
+#include "extmod/vfs.h"
+
+#if MICROPY_VFS
+
+void mp_vfs_blockdev_init(mp_vfs_blockdev_t *self, mp_obj_t bdev) {
+ mp_load_method(bdev, MP_QSTR_readblocks, self->readblocks);
+ mp_load_method_maybe(bdev, MP_QSTR_writeblocks, self->writeblocks);
+ mp_load_method_maybe(bdev, MP_QSTR_ioctl, self->u.ioctl);
+ if (self->u.ioctl[0] != MP_OBJ_NULL) {
+ // Device supports new block protocol, so indicate it
+ self->flags |= MP_BLOCKDEV_FLAG_HAVE_IOCTL;
+ } else {
+ // No ioctl method, so assume the device uses the old block protocol
+ mp_load_method_maybe(bdev, MP_QSTR_sync, self->u.old.sync);
+ mp_load_method(bdev, MP_QSTR_count, self->u.old.count);
+ }
+}
+
+int mp_vfs_blockdev_read(mp_vfs_blockdev_t *self, size_t block_num, size_t num_blocks, uint8_t *buf) {
+ if (self->flags & MP_BLOCKDEV_FLAG_NATIVE) {
+ mp_uint_t (*f)(uint8_t *, uint32_t, uint32_t) = (void *)(uintptr_t)self->readblocks[2];
+ return f(buf, block_num, num_blocks);
+ } else {
+ mp_obj_array_t ar = {{&mp_type_bytearray}, BYTEARRAY_TYPECODE, 0, num_blocks *self->block_size, buf};
+ self->readblocks[2] = MP_OBJ_NEW_SMALL_INT(block_num);
+ self->readblocks[3] = MP_OBJ_FROM_PTR(&ar);
+ mp_call_method_n_kw(2, 0, self->readblocks);
+ // TODO handle error return
+ return 0;
+ }
+}
+
+int mp_vfs_blockdev_read_ext(mp_vfs_blockdev_t *self, size_t block_num, size_t block_off, size_t len, uint8_t *buf) {
+ mp_obj_array_t ar = {{&mp_type_bytearray}, BYTEARRAY_TYPECODE, 0, len, buf};
+ self->readblocks[2] = MP_OBJ_NEW_SMALL_INT(block_num);
+ self->readblocks[3] = MP_OBJ_FROM_PTR(&ar);
+ self->readblocks[4] = MP_OBJ_NEW_SMALL_INT(block_off);
+ mp_obj_t ret = mp_call_method_n_kw(3, 0, self->readblocks);
+ if (ret == mp_const_none) {
+ return 0;
+ } else {
+ return MP_OBJ_SMALL_INT_VALUE(ret);
+ }
+}
+
+int mp_vfs_blockdev_write(mp_vfs_blockdev_t *self, size_t block_num, size_t num_blocks, const uint8_t *buf) {
+ if (self->writeblocks[0] == MP_OBJ_NULL) {
+ // read-only block device
+ return -MP_EROFS;
+ }
+
+ if (self->flags & MP_BLOCKDEV_FLAG_NATIVE) {
+ mp_uint_t (*f)(const uint8_t *, uint32_t, uint32_t) = (void *)(uintptr_t)self->writeblocks[2];
+ return f(buf, block_num, num_blocks);
+ } else {
+ mp_obj_array_t ar = {{&mp_type_bytearray}, BYTEARRAY_TYPECODE, 0, num_blocks *self->block_size, (void *)buf};
+ self->writeblocks[2] = MP_OBJ_NEW_SMALL_INT(block_num);
+ self->writeblocks[3] = MP_OBJ_FROM_PTR(&ar);
+ mp_call_method_n_kw(2, 0, self->writeblocks);
+ // TODO handle error return
+ return 0;
+ }
+}
+
+int mp_vfs_blockdev_write_ext(mp_vfs_blockdev_t *self, size_t block_num, size_t block_off, size_t len, const uint8_t *buf) {
+ if (self->writeblocks[0] == MP_OBJ_NULL) {
+ // read-only block device
+ return -MP_EROFS;
+ }
+
+ mp_obj_array_t ar = {{&mp_type_bytearray}, BYTEARRAY_TYPECODE, 0, len, (void *)buf};
+ self->writeblocks[2] = MP_OBJ_NEW_SMALL_INT(block_num);
+ self->writeblocks[3] = MP_OBJ_FROM_PTR(&ar);
+ self->writeblocks[4] = MP_OBJ_NEW_SMALL_INT(block_off);
+ mp_obj_t ret = mp_call_method_n_kw(3, 0, self->writeblocks);
+ if (ret == mp_const_none) {
+ return 0;
+ } else {
+ return MP_OBJ_SMALL_INT_VALUE(ret);
+ }
+}
+
+mp_obj_t mp_vfs_blockdev_ioctl(mp_vfs_blockdev_t *self, uintptr_t cmd, uintptr_t arg) {
+ if (self->flags & MP_BLOCKDEV_FLAG_HAVE_IOCTL) {
+ // New protocol with ioctl
+ self->u.ioctl[2] = MP_OBJ_NEW_SMALL_INT(cmd);
+ self->u.ioctl[3] = MP_OBJ_NEW_SMALL_INT(arg);
+ return mp_call_method_n_kw(2, 0, self->u.ioctl);
+ } else {
+ // Old protocol with sync and count
+ switch (cmd) {
+ case MP_BLOCKDEV_IOCTL_SYNC:
+ if (self->u.old.sync[0] != MP_OBJ_NULL) {
+ mp_call_method_n_kw(0, 0, self->u.old.sync);
+ }
+ break;
+
+ case MP_BLOCKDEV_IOCTL_BLOCK_COUNT:
+ return mp_call_method_n_kw(0, 0, self->u.old.count);
+
+ case MP_BLOCKDEV_IOCTL_BLOCK_SIZE:
+ // Old protocol has fixed sector size of 512 bytes
+ break;
+
+ case MP_BLOCKDEV_IOCTL_INIT:
+ // Old protocol doesn't have init
+ break;
+ }
+ return mp_const_none;
+ }
+}
+
+#endif // MICROPY_VFS
diff --git a/extmod/vfs_fat.c b/extmod/vfs_fat.c
index f7cb095cbd..e3ff11af80 100644
--- a/extmod/vfs_fat.c
+++ b/extmod/vfs_fat.c
@@ -70,27 +70,27 @@ STATIC mp_obj_t fat_vfs_make_new(const mp_obj_type_t *type, size_t n_args, size_
// create new object
fs_user_mount_t *vfs = m_new_obj(fs_user_mount_t);
vfs->base.type = type;
- vfs->flags = FSUSER_FREE_OBJ;
+ vfs->blockdev.flags = FSUSER_FREE_OBJ;
vfs->fs.fatfs.drv = vfs;
// load block protocol methods
- mp_load_method(args[0], MP_QSTR_readblocks, vfs->readblocks);
- mp_load_method_maybe(args[0], MP_QSTR_writeblocks, vfs->writeblocks);
- mp_load_method_maybe(args[0], MP_QSTR_ioctl, vfs->u.ioctl);
- if (vfs->u.ioctl[0] != MP_OBJ_NULL) {
+ mp_load_method(args[0], MP_QSTR_readblocks, vfs->blockdev.readblocks);
+ mp_load_method_maybe(args[0], MP_QSTR_writeblocks, vfs->blockdev.writeblocks);
+ mp_load_method_maybe(args[0], MP_QSTR_ioctl, vfs->blockdev.u.ioctl);
+ if (vfs->blockdev.u.ioctl[0] != MP_OBJ_NULL) {
// device supports new block protocol, so indicate it
- vfs->flags |= FSUSER_HAVE_IOCTL;
+ vfs->blockdev.flags |= FSUSER_HAVE_IOCTL;
} else {
// no ioctl method, so assume the device uses the old block protocol
- mp_load_method_maybe(args[0], MP_QSTR_sync, vfs->u.old.sync);
- mp_load_method(args[0], MP_QSTR_count, vfs->u.old.count);
+ mp_load_method_maybe(args[0], MP_QSTR_sync, vfs->blockdev.u.old.sync);
+ mp_load_method(args[0], MP_QSTR_count, vfs->blockdev.u.old.count);
}
// mount the block device so the VFS methods can be used
FRESULT res = f_mount(&vfs->fs.fatfs);
if (res == FR_NO_FILESYSTEM) {
// don't error out if no filesystem, to let mkfs()/mount() create one if wanted
- vfs->flags |= FSUSER_NO_FILESYSTEM;
+ vfs->blockdev.flags |= FSUSER_NO_FILESYSTEM;
} else if (res != FR_OK) {
mp_raise_OSError(fresult_to_errno_table[res]);
}
@@ -110,14 +110,14 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(fat_vfs_del_obj, fat_vfs_del);
STATIC mp_obj_t fat_vfs_mkfs(mp_obj_t bdev_in) {
// create new object
- fs_user_mount_t* vfs = MP_OBJ_TO_PTR(fat_vfs_make_new(&mp_fat_vfs_type, 1, 0, &bdev_in));
- FRESULT res = fat_format(vfs);
+ fs_user_mount_t* vfs = MP_OBJ_TO_PTR(fat_vfs_make_new(&mp_fat_vfs_type, 1, 0, &bdev_in));
+ FRESULT res = fat_format(vfs);
- if (FR_OK != res)
- {
- mp_raise_OSError(fresult_to_errno_table[res]);
- }
- vfs->flags &= ~FSUSER_NO_FILESYSTEM;
+ if (FR_OK != res)
+ {
+ mp_raise_OSError(fresult_to_errno_table[res]);
+ }
+ vfs->blockdev.flags &= ~FSUSER_NO_FILESYSTEM;
return mp_const_none;
}
@@ -130,29 +130,29 @@ STATIC FRESULT fat_format(fs_user_mount_t* vfs)
uint8_t options = FM_FAT;
uint8_t working_buf[FF_MAX_SS];
- if ((vfs->flags & FSUSER_HAVE_IOCTL))
+ if ((vfs->blockdev.flags & FSUSER_HAVE_IOCTL))
{
// device supports new block protocol, so indicate it
- vfs->u.ioctl[2] = MP_OBJ_NEW_SMALL_INT(BP_IOCTL_SEC_COUNT);
- vfs->u.ioctl[3] = MP_OBJ_NEW_SMALL_INT(0); // unused
- blockcount = mp_obj_get_int(mp_call_method_n_kw(2, 0, vfs->u.ioctl));
+ vfs->blockdev.u.ioctl[2] = MP_OBJ_NEW_SMALL_INT(MP_BLOCKDEV_IOCTL_BLOCK_COUNT);
+ vfs->blockdev.u.ioctl[3] = MP_OBJ_NEW_SMALL_INT(0); // unused
+ blockcount = mp_obj_get_int(mp_call_method_n_kw(2, 0, vfs->blockdev.u.ioctl));
}
else
{
// no ioctl method, so assume the device uses the old block protocol
- blockcount = mp_obj_get_int(mp_call_method_n_kw(0, 0, vfs->u.old.count));
+ blockcount = mp_obj_get_int(mp_call_method_n_kw(0, 0, vfs->blockdev.u.old.count));
}
- if (blockcount < 32768)
- {
- options |= FM_SFD;
- }
- else
- {
- options = FM_FAT32;
- }
- // make the filesystem
- return f_mkfs(&vfs->fs.fatfs, options, 0, working_buf, sizeof(working_buf));
+ if (blockcount < 32768)
+ {
+ options |= FM_SFD;
+ }
+ else
+ {
+ options = FM_FAT32;
+ }
+ // make the filesystem
+ return f_mkfs(&vfs->fs.fatfs, options, 0, working_buf, sizeof(working_buf));
}
typedef struct _mp_vfs_fat_ilistdir_it_t {
@@ -181,7 +181,7 @@ STATIC mp_obj_t mp_vfs_fat_ilistdir_it_iternext(mp_obj_t self_in) {
if (self->is_str) {
t->items[0] = mp_obj_new_str(fn, strlen(fn));
} else {
- t->items[0] = mp_obj_new_bytes((const byte*)fn, strlen(fn));
+ t->items[0] = mp_obj_new_bytes((const byte *)fn, strlen(fn));
}
if (fno.fattrib & AM_DIR) {
// dir
@@ -357,7 +357,10 @@ STATIC mp_obj_t fat_vfs_stat(mp_obj_t vfs_in, mp_obj_t path_in) {
(fno.ftime >> 11) & 0x1f,
(fno.ftime >> 5) & 0x3f,
2 * (fno.ftime & 0x1f)
- );
+ );
+ #if MICROPY_EPOCH_IS_1970
+ seconds += TIMEUTILS_SECONDS_1970_TO_2000;
+ #endif
t->items[0] = MP_OBJ_NEW_SMALL_INT(mode); // st_mode
t->items[1] = MP_OBJ_NEW_SMALL_INT(0); // st_ino
t->items[2] = MP_OBJ_NEW_SMALL_INT(0); // st_dev
@@ -426,6 +429,7 @@ STATIC mp_obj_t fat_vfs_getfree(mp_obj_t vfs_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(fat_vfs_getfree_obj, fat_vfs_getfree);
+
STATIC mp_obj_t vfs_fat_mount(mp_obj_t self_in, mp_obj_t readonly, mp_obj_t mkfs) {
fs_user_mount_t *self = MP_OBJ_TO_PTR(self_in);
@@ -434,20 +438,20 @@ STATIC mp_obj_t vfs_fat_mount(mp_obj_t self_in, mp_obj_t readonly, mp_obj_t mkfs
// 1. readonly=True keyword argument
// 2. nonexistent writeblocks method (then writeblocks[0] == MP_OBJ_NULL already)
if (mp_obj_is_true(readonly)) {
- self->writeblocks[0] = MP_OBJ_NULL;
+ self->blockdev.writeblocks[0] = MP_OBJ_NULL;
}
// check if we need to make the filesystem
- FRESULT res = (self->flags & FSUSER_NO_FILESYSTEM) ? FR_NO_FILESYSTEM : FR_OK;
+ FRESULT res = (self->blockdev.flags & FSUSER_NO_FILESYSTEM) ? FR_NO_FILESYSTEM : FR_OK;
if (res == FR_NO_FILESYSTEM && mp_obj_is_true(mkfs))
{
- res = fat_format(self);
- if (FR_OK != res)
- {
- mp_raise_OSError(fresult_to_errno_table[res]);
- }
+ res = fat_format(self);
+ if (FR_OK != res)
+ {
+ mp_raise_OSError(fresult_to_errno_table[res]);
+ }
}
- self->flags &= ~FSUSER_NO_FILESYSTEM;
+ self->blockdev.flags &= ~FSUSER_NO_FILESYSTEM;
return mp_const_none;
}
@@ -462,16 +466,16 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(fat_vfs_umount_obj, vfs_fat_umount);
STATIC mp_obj_t fat_vfs_fsformat(mp_obj_t vfs_in)
{
- fs_user_mount_t * vfs = MP_OBJ_TO_PTR(vfs_in);
- FRESULT res = fat_format(vfs);
- if (FR_OK != res)
- {
- mp_raise_OSError(fresult_to_errno_table[res]);
- }
+ fs_user_mount_t * vfs = MP_OBJ_TO_PTR(vfs_in);
+ FRESULT res = fat_format(vfs);
+ if (FR_OK != res)
+ {
+ mp_raise_OSError(fresult_to_errno_table[res]);
+ }
- vfs->flags &= ~FSUSER_NO_FILESYSTEM;
+ vfs->blockdev.flags &= ~FSUSER_NO_FILESYSTEM;
- return mp_const_none;
+ return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(fat_vfs_fsformat_obj, fat_vfs_fsformat);
@@ -493,7 +497,7 @@ STATIC const mp_rom_map_elem_t fat_vfs_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_getfree), MP_ROM_PTR(&fat_vfs_getfree_obj) },
{ MP_ROM_QSTR(MP_QSTR_mount), MP_ROM_PTR(&vfs_fat_mount_obj) },
{ MP_ROM_QSTR(MP_QSTR_umount), MP_ROM_PTR(&fat_vfs_umount_obj) },
- { MP_ROM_QSTR(MP_QSTR_fsformat), MP_ROM_PTR(&fat_vfs_fsformat_obj) },
+ { MP_ROM_QSTR(MP_QSTR_fsformat), MP_ROM_PTR(&fat_vfs_fsformat_obj) },
};
STATIC MP_DEFINE_CONST_DICT(fat_vfs_locals_dict, fat_vfs_locals_dict_table);
@@ -506,7 +510,7 @@ const mp_obj_type_t mp_fat_vfs_type = {
.name = MP_QSTR_VfsFat,
.make_new = fat_vfs_make_new,
.protocol = &fat_vfs_proto,
- .locals_dict = (mp_obj_dict_t*)&fat_vfs_locals_dict,
+ .locals_dict = (mp_obj_dict_t *)&fat_vfs_locals_dict,
};
diff --git a/extmod/vfs_fat_diskio.c b/extmod/vfs_fat_diskio.c
index e80d612411..08cd70de8c 100644
--- a/extmod/vfs_fat_diskio.c
+++ b/extmod/vfs_fat_diskio.c
@@ -50,35 +50,34 @@
typedef void *bdev_t;
STATIC fs_user_mount_t *disk_get_device(void *bdev) {
- return (fs_user_mount_t*)bdev;
+ return (fs_user_mount_t *)bdev;
}
/*-----------------------------------------------------------------------*/
/* Read Sector(s) */
/*-----------------------------------------------------------------------*/
-DRESULT disk_read (
+DRESULT disk_read(
bdev_t pdrv, /* Physical drive nmuber (0..) */
BYTE *buff, /* Data buffer to store read data */
DWORD sector, /* Sector address (LBA) */
UINT count /* Number of sectors to read (1..128) */
-)
-{
+ ){
fs_user_mount_t *vfs = disk_get_device(pdrv);
if (vfs == NULL) {
return RES_PARERR;
}
- if (vfs->flags & FSUSER_NATIVE) {
- mp_uint_t (*f)(uint8_t*, uint32_t, uint32_t) = (void*)(uintptr_t)vfs->readblocks[2];
+ if (vfs->blockdev.flags & FSUSER_NATIVE) {
+ mp_uint_t (*f)(uint8_t*, uint32_t, uint32_t) = (void*)(uintptr_t)vfs->blockdev.readblocks[2];
if (f(buff, sector, count) != 0) {
return RES_ERROR;
}
} else {
mp_obj_array_t ar = {{&mp_type_bytearray}, BYTEARRAY_TYPECODE, 0, count * SECSIZE(&vfs->fatfs), buff};
- vfs->readblocks[2] = MP_OBJ_NEW_SMALL_INT(sector);
- vfs->readblocks[3] = MP_OBJ_FROM_PTR(&ar);
- mp_call_method_n_kw(2, 0, vfs->readblocks);
+ vfs->blockdev.readblocks[2] = MP_OBJ_NEW_SMALL_INT(sector);
+ vfs->blockdev.readblocks[3] = MP_OBJ_FROM_PTR(&ar);
+ mp_call_method_n_kw(2, 0, vfs->blockdev.readblocks);
// TODO handle error return
}
@@ -89,33 +88,32 @@ DRESULT disk_read (
/* Write Sector(s) */
/*-----------------------------------------------------------------------*/
-DRESULT disk_write (
+DRESULT disk_write(
bdev_t pdrv, /* Physical drive nmuber (0..) */
const BYTE *buff, /* Data to be written */
DWORD sector, /* Sector address (LBA) */
UINT count /* Number of sectors to write (1..128) */
-)
-{
+ ) {
fs_user_mount_t *vfs = disk_get_device(pdrv);
if (vfs == NULL) {
return RES_PARERR;
}
- if (vfs->writeblocks[0] == MP_OBJ_NULL) {
+ if (vfs->blockdev.writeblocks[0] == MP_OBJ_NULL) {
// read-only block device
return RES_WRPRT;
}
- if (vfs->flags & FSUSER_NATIVE) {
- mp_uint_t (*f)(const uint8_t*, uint32_t, uint32_t) = (void*)(uintptr_t)vfs->writeblocks[2];
+ if (vfs->blockdev.flags & FSUSER_NATIVE) {
+ mp_uint_t (*f)(const uint8_t*, uint32_t, uint32_t) = (void*)(uintptr_t)vfs->blockdev.writeblocks[2];
if (f(buff, sector, count) != 0) {
return RES_ERROR;
}
} else {
mp_obj_array_t ar = {{&mp_type_bytearray}, BYTEARRAY_TYPECODE, 0, count * SECSIZE(&vfs->fatfs), (void*)buff};
- vfs->writeblocks[2] = MP_OBJ_NEW_SMALL_INT(sector);
- vfs->writeblocks[3] = MP_OBJ_FROM_PTR(&ar);
- mp_call_method_n_kw(2, 0, vfs->writeblocks);
+ vfs->blockdev.writeblocks[2] = MP_OBJ_NEW_SMALL_INT(sector);
+ vfs->blockdev.writeblocks[3] = MP_OBJ_FROM_PTR(&ar);
+ mp_call_method_n_kw(2, 0, vfs->blockdev.writeblocks);
// TODO handle error return
}
@@ -127,12 +125,11 @@ DRESULT disk_write (
/* Miscellaneous Functions */
/*-----------------------------------------------------------------------*/
-DRESULT disk_ioctl (
+DRESULT disk_ioctl(
bdev_t pdrv, /* Physical drive nmuber (0..) */
BYTE cmd, /* Control code */
void *buff /* Buffer to send/receive control data */
-)
-{
+ ) {
fs_user_mount_t *vfs = disk_get_device(pdrv);
if (vfs == NULL) {
return RES_PARERR;
@@ -140,31 +137,31 @@ DRESULT disk_ioctl (
// First part: call the relevant method of the underlying block device
mp_obj_t ret = mp_const_none;
- if (vfs->flags & FSUSER_HAVE_IOCTL) {
+ if (vfs->blockdev.flags & FSUSER_HAVE_IOCTL) {
// new protocol with ioctl
static const uint8_t op_map[8] = {
- [CTRL_SYNC] = BP_IOCTL_SYNC,
- [GET_SECTOR_COUNT] = BP_IOCTL_SEC_COUNT,
- [GET_SECTOR_SIZE] = BP_IOCTL_SEC_SIZE,
- [IOCTL_INIT] = BP_IOCTL_INIT,
+ [CTRL_SYNC] = MP_BLOCKDEV_IOCTL_SYNC,
+ [GET_SECTOR_COUNT] = MP_BLOCKDEV_IOCTL_BLOCK_COUNT,
+ [GET_SECTOR_SIZE] = MP_BLOCKDEV_IOCTL_BLOCK_SIZE,
+ [IOCTL_INIT] = MP_BLOCKDEV_IOCTL_INIT,
};
uint8_t bp_op = op_map[cmd & 7];
if (bp_op != 0) {
- vfs->u.ioctl[2] = MP_OBJ_NEW_SMALL_INT(bp_op);
- vfs->u.ioctl[3] = MP_OBJ_NEW_SMALL_INT(0); // unused
- ret = mp_call_method_n_kw(2, 0, vfs->u.ioctl);
+ vfs->blockdev.u.ioctl[2] = MP_OBJ_NEW_SMALL_INT(bp_op);
+ vfs->blockdev.u.ioctl[3] = MP_OBJ_NEW_SMALL_INT(0); // unused
+ ret = mp_call_method_n_kw(2, 0, vfs->blockdev.u.ioctl);
}
} else {
// old protocol with sync and count
switch (cmd) {
case CTRL_SYNC:
- if (vfs->u.old.sync[0] != MP_OBJ_NULL) {
- mp_call_method_n_kw(0, 0, vfs->u.old.sync);
+ if (vfs->blockdev.u.old.sync[0] != MP_OBJ_NULL) {
+ mp_call_method_n_kw(0, 0, vfs->blockdev.u.old.sync);
}
break;
case GET_SECTOR_COUNT:
- ret = mp_call_method_n_kw(0, 0, vfs->u.old.count);
+ ret = mp_call_method_n_kw(0, 0, vfs->blockdev.u.old.count);
break;
case GET_SECTOR_SIZE:
@@ -183,26 +180,27 @@ DRESULT disk_ioctl (
return RES_OK;
case GET_SECTOR_COUNT: {
- *((DWORD*)buff) = mp_obj_get_int(ret);
+ *((DWORD *)buff) = mp_obj_get_int(ret);
return RES_OK;
}
case GET_SECTOR_SIZE: {
if (ret == mp_const_none) {
// Default sector size
- *((WORD*)buff) = 512;
+ *((WORD *)buff) = 512;
} else {
- *((WORD*)buff) = mp_obj_get_int(ret);
+ *((WORD *)buff) = mp_obj_get_int(ret);
}
#if FF_MAX_SS != FF_MIN_SS
// need to store ssize because we use it in disk_read/disk_write
+ vfs->blockdev.block_size = *((WORD *)buff);
vfs->fatfs.ssize = *((WORD*)buff);
#endif
return RES_OK;
}
case GET_BLOCK_SIZE:
- *((DWORD*)buff) = 1; // erase block size in units of sector size
+ *((DWORD *)buff) = 1; // erase block size in units of sector size
return RES_OK;
case IOCTL_INIT:
@@ -211,12 +209,12 @@ DRESULT disk_ioctl (
if (ret != mp_const_none && MP_OBJ_SMALL_INT_VALUE(ret) != 0) {
// error initialising
stat = STA_NOINIT;
- } else if (vfs->writeblocks[0] == MP_OBJ_NULL) {
+ } else if (vfs->blockdev.writeblocks[0] == MP_OBJ_NULL) {
stat = STA_PROTECT;
} else {
stat = 0;
}
- *((DSTATUS*)buff) = stat;
+ *((DSTATUS *)buff) = stat;
return RES_OK;
}
diff --git a/extmod/vfs_fat_file.c b/extmod/vfs_fat_file.c
index 3b02cd8f17..defbc7e6a8 100644
--- a/extmod/vfs_fat_file.c
+++ b/extmod/vfs_fat_file.c
@@ -107,7 +107,7 @@ STATIC mp_uint_t file_obj_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg,
pyb_file_obj_t *self = MP_OBJ_TO_PTR(o_in);
if (request == MP_STREAM_SEEK) {
- struct mp_stream_seek_t *s = (struct mp_stream_seek_t*)(uintptr_t)arg;
+ struct mp_stream_seek_t *s = (struct mp_stream_seek_t *)(uintptr_t)arg;
switch (s->whence) {
case 0: // SEEK_SET
@@ -154,9 +154,9 @@ STATIC mp_uint_t file_obj_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg,
// Note: encoding is ignored for now; it's also not a valid kwarg for CPython's FileIO,
// but by adding it here we can use one single mp_arg_t array for open() and FileIO's constructor
STATIC const mp_arg_t file_open_args[] = {
- { MP_QSTR_file, MP_ARG_OBJ | MP_ARG_REQUIRED, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} },
+ { MP_QSTR_file, MP_ARG_OBJ | MP_ARG_REQUIRED, {.u_rom_obj = MP_ROM_NONE} },
{ MP_QSTR_mode, MP_ARG_OBJ, {.u_obj = MP_OBJ_NEW_QSTR(MP_QSTR_r)} },
- { MP_QSTR_encoding, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} },
+ { MP_QSTR_encoding, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_rom_obj = MP_ROM_NONE} },
};
#define FILE_OPEN_NUM_ARGS MP_ARRAY_SIZE(file_open_args)
@@ -219,7 +219,7 @@ STATIC mp_obj_t file_obj_make_new(const mp_obj_type_t *type, size_t n_args, size
// TODO gc hook to close the file if not already closed
-STATIC const mp_rom_map_elem_t rawfile_locals_dict_table[] = {
+STATIC const mp_rom_map_elem_t vfs_fat_rawfile_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) },
{ MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) },
{ MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) },
@@ -234,10 +234,10 @@ STATIC const mp_rom_map_elem_t rawfile_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&file_obj___exit___obj) },
};
-STATIC MP_DEFINE_CONST_DICT(rawfile_locals_dict, rawfile_locals_dict_table);
+STATIC MP_DEFINE_CONST_DICT(vfs_fat_rawfile_locals_dict, vfs_fat_rawfile_locals_dict_table);
#if MICROPY_PY_IO_FILEIO
-STATIC const mp_stream_p_t fileio_stream_p = {
+STATIC const mp_stream_p_t vfs_fat_fileio_stream_p = {
.read = file_obj_read,
.write = file_obj_write,
.ioctl = file_obj_ioctl,
@@ -250,12 +250,12 @@ const mp_obj_type_t mp_type_vfs_fat_fileio = {
.make_new = file_obj_make_new,
.getiter = mp_identity_getiter,
.iternext = mp_stream_unbuffered_iter,
- .protocol = &fileio_stream_p,
- .locals_dict = (mp_obj_dict_t*)&rawfile_locals_dict,
+ .protocol = &vfs_fat_fileio_stream_p,
+ .locals_dict = (mp_obj_dict_t *)&vfs_fat_rawfile_locals_dict,
};
#endif
-STATIC const mp_stream_p_t textio_stream_p = {
+STATIC const mp_stream_p_t vfs_fat_textio_stream_p = {
.read = file_obj_read,
.write = file_obj_write,
.ioctl = file_obj_ioctl,
@@ -269,8 +269,8 @@ const mp_obj_type_t mp_type_vfs_fat_textio = {
.make_new = file_obj_make_new,
.getiter = mp_identity_getiter,
.iternext = mp_stream_unbuffered_iter,
- .protocol = &textio_stream_p,
- .locals_dict = (mp_obj_dict_t*)&rawfile_locals_dict,
+ .protocol = &vfs_fat_textio_stream_p,
+ .locals_dict = (mp_obj_dict_t *)&vfs_fat_rawfile_locals_dict,
};
// Factory function for I/O stream classes
diff --git a/extmod/vfs_posix.c b/extmod/vfs_posix.c
index 4ef761956c..719afe28fe 100644
--- a/extmod/vfs_posix.c
+++ b/extmod/vfs_posix.c
@@ -26,11 +26,14 @@
#include "py/runtime.h"
#include "py/mperrno.h"
+#include "py/mphal.h"
+#include "py/mpthread.h"
#include "extmod/vfs.h"
#include "extmod/vfs_posix.h"
#if MICROPY_VFS_POSIX
+#include
#include
#include
#include
@@ -62,7 +65,7 @@ STATIC mp_obj_t vfs_posix_get_path_obj(mp_obj_vfs_posix_t *self, mp_obj_t path)
}
}
-STATIC mp_obj_t vfs_posix_fun1_helper(mp_obj_t self_in, mp_obj_t path_in, int (*f)(const char*)) {
+STATIC mp_obj_t vfs_posix_fun1_helper(mp_obj_t self_in, mp_obj_t path_in, int (*f)(const char *)) {
mp_obj_vfs_posix_t *self = MP_OBJ_TO_PTR(self_in);
int ret = f(vfs_posix_get_path_str(self, path_in));
if (ret != 0) {
@@ -169,12 +172,15 @@ STATIC mp_obj_t vfs_posix_ilistdir_it_iternext(mp_obj_t self_in) {
}
for (;;) {
+ MP_THREAD_GIL_EXIT();
struct dirent *dirent = readdir(self->dir);
if (dirent == NULL) {
closedir(self->dir);
+ MP_THREAD_GIL_ENTER();
self->dir = NULL;
return MP_OBJ_STOP_ITERATION;
}
+ MP_THREAD_GIL_ENTER();
const char *fn = dirent->d_name;
if (fn[0] == '.' && (fn[1] == 0 || fn[1] == '.')) {
@@ -188,7 +194,7 @@ STATIC mp_obj_t vfs_posix_ilistdir_it_iternext(mp_obj_t self_in) {
if (self->is_str) {
t->items[0] = mp_obj_new_str(fn, strlen(fn));
} else {
- t->items[0] = mp_obj_new_bytes((const byte*)fn, strlen(fn));
+ t->items[0] = mp_obj_new_bytes((const byte *)fn, strlen(fn));
}
#ifdef _DIRENT_HAVE_D_TYPE
@@ -228,7 +234,9 @@ STATIC mp_obj_t vfs_posix_ilistdir(mp_obj_t self_in, mp_obj_t path_in) {
if (path[0] == '\0') {
path = ".";
}
+ MP_THREAD_GIL_EXIT();
iter->dir = opendir(path);
+ MP_THREAD_GIL_ENTER();
if (iter->dir == NULL) {
mp_raise_OSError(errno);
}
@@ -244,7 +252,10 @@ typedef struct _mp_obj_listdir_t {
STATIC mp_obj_t vfs_posix_mkdir(mp_obj_t self_in, mp_obj_t path_in) {
mp_obj_vfs_posix_t *self = MP_OBJ_TO_PTR(self_in);
- int ret = mkdir(vfs_posix_get_path_str(self, path_in), 0777);
+ const char *path = vfs_posix_get_path_str(self, path_in);
+ MP_THREAD_GIL_EXIT();
+ int ret = mkdir(path, 0777);
+ MP_THREAD_GIL_ENTER();
if (ret != 0) {
mp_raise_OSError(errno);
}
@@ -261,7 +272,9 @@ STATIC mp_obj_t vfs_posix_rename(mp_obj_t self_in, mp_obj_t old_path_in, mp_obj_
mp_obj_vfs_posix_t *self = MP_OBJ_TO_PTR(self_in);
const char *old_path = vfs_posix_get_path_str(self, old_path_in);
const char *new_path = vfs_posix_get_path_str(self, new_path_in);
+ MP_THREAD_GIL_EXIT();
int ret = rename(old_path, new_path);
+ MP_THREAD_GIL_ENTER();
if (ret != 0) {
mp_raise_OSError(errno);
}
@@ -277,21 +290,20 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(vfs_posix_rmdir_obj, vfs_posix_rmdir);
STATIC mp_obj_t vfs_posix_stat(mp_obj_t self_in, mp_obj_t path_in) {
mp_obj_vfs_posix_t *self = MP_OBJ_TO_PTR(self_in);
struct stat sb;
- int ret = stat(vfs_posix_get_path_str(self, path_in), &sb);
- if (ret != 0) {
- mp_raise_OSError(errno);
- }
+ const char *path = vfs_posix_get_path_str(self, path_in);
+ int ret;
+ MP_HAL_RETRY_SYSCALL(ret, stat(path, &sb), mp_raise_OSError(err));
mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(10, NULL));
t->items[0] = MP_OBJ_NEW_SMALL_INT(sb.st_mode);
- t->items[1] = MP_OBJ_NEW_SMALL_INT(sb.st_ino);
- t->items[2] = MP_OBJ_NEW_SMALL_INT(sb.st_dev);
- t->items[3] = MP_OBJ_NEW_SMALL_INT(sb.st_nlink);
- t->items[4] = MP_OBJ_NEW_SMALL_INT(sb.st_uid);
- t->items[5] = MP_OBJ_NEW_SMALL_INT(sb.st_gid);
- t->items[6] = MP_OBJ_NEW_SMALL_INT(sb.st_size);
- t->items[7] = MP_OBJ_NEW_SMALL_INT(sb.st_atime);
- t->items[8] = MP_OBJ_NEW_SMALL_INT(sb.st_mtime);
- t->items[9] = MP_OBJ_NEW_SMALL_INT(sb.st_ctime);
+ t->items[1] = mp_obj_new_int_from_uint(sb.st_ino);
+ t->items[2] = mp_obj_new_int_from_uint(sb.st_dev);
+ t->items[3] = mp_obj_new_int_from_uint(sb.st_nlink);
+ t->items[4] = mp_obj_new_int_from_uint(sb.st_uid);
+ t->items[5] = mp_obj_new_int_from_uint(sb.st_gid);
+ t->items[6] = mp_obj_new_int_from_uint(sb.st_size);
+ t->items[7] = mp_obj_new_int_from_uint(sb.st_atime);
+ t->items[8] = mp_obj_new_int_from_uint(sb.st_mtime);
+ t->items[9] = mp_obj_new_int_from_uint(sb.st_ctime);
return MP_OBJ_FROM_PTR(t);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(vfs_posix_stat_obj, vfs_posix_stat);
@@ -320,10 +332,8 @@ STATIC mp_obj_t vfs_posix_statvfs(mp_obj_t self_in, mp_obj_t path_in) {
mp_obj_vfs_posix_t *self = MP_OBJ_TO_PTR(self_in);
STRUCT_STATVFS sb;
const char *path = vfs_posix_get_path_str(self, path_in);
- int ret = STATVFS(path, &sb);
- if (ret != 0) {
- mp_raise_OSError(errno);
- }
+ int ret;
+ MP_HAL_RETRY_SYSCALL(ret, STATVFS(path, &sb), mp_raise_OSError(err));
mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(10, NULL));
t->items[0] = MP_OBJ_NEW_SMALL_INT(sb.f_bsize);
t->items[1] = MP_OBJ_NEW_SMALL_INT(sb.f_frsize);
@@ -365,7 +375,7 @@ const mp_obj_type_t mp_type_vfs_posix = {
.name = MP_QSTR_VfsPosix,
.make_new = vfs_posix_make_new,
.protocol = &vfs_posix_proto,
- .locals_dict = (mp_obj_dict_t*)&vfs_posix_locals_dict,
+ .locals_dict = (mp_obj_dict_t *)&vfs_posix_locals_dict,
};
#endif // MICROPY_VFS_POSIX
diff --git a/extmod/vfs_posix_file.c b/extmod/vfs_posix_file.c
index 44cb85dcc7..264764b4ee 100644
--- a/extmod/vfs_posix_file.c
+++ b/extmod/vfs_posix_file.c
@@ -24,13 +24,16 @@
* THE SOFTWARE.
*/
+#include "py/mphal.h"
+#include "py/mpthread.h"
#include "py/runtime.h"
#include "py/stream.h"
#include "extmod/vfs_posix.h"
-#if MICROPY_VFS_POSIX
+#if MICROPY_VFS_POSIX || MICROPY_VFS_POSIX_FILE
#include
+#include
#ifdef _WIN32
#define fsync _commit
@@ -44,7 +47,7 @@ typedef struct _mp_obj_vfs_posix_file_t {
#ifdef MICROPY_CPYTHON_COMPAT
STATIC void check_fd_is_open(const mp_obj_vfs_posix_file_t *o) {
if (o->fd < 0) {
- nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "I/O operation on closed file"));
+ mp_raise_ValueError(MP_ERROR_TEXT("I/O operation on closed file"));
}
}
#else
@@ -78,7 +81,7 @@ mp_obj_t mp_vfs_posix_file_open(const mp_obj_type_t *type, mp_obj_t file_in, mp_
case '+':
mode_rw = O_RDWR;
break;
- #if MICROPY_PY_IO_FILEIO
+ #if MICROPY_PY_IO_FILEIO
// If we don't have io.FileIO, then files are in text mode implicitly
case 'b':
type = &mp_type_vfs_posix_fileio;
@@ -86,7 +89,7 @@ mp_obj_t mp_vfs_posix_file_open(const mp_obj_type_t *type, mp_obj_t file_in, mp_
case 't':
type = &mp_type_vfs_posix_textio;
break;
- #endif
+ #endif
}
}
@@ -100,17 +103,15 @@ mp_obj_t mp_vfs_posix_file_open(const mp_obj_type_t *type, mp_obj_t file_in, mp_
}
const char *fname = mp_obj_str_get_str(fid);
- int fd = open(fname, mode_x | mode_rw, 0644);
- if (fd == -1) {
- mp_raise_OSError(errno);
- }
+ int fd;
+ MP_HAL_RETRY_SYSCALL(fd, open(fname, mode_x | mode_rw, 0644), mp_raise_OSError(err));
o->fd = fd;
return MP_OBJ_FROM_PTR(o);
}
STATIC mp_obj_t vfs_posix_file_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
static const mp_arg_t allowed_args[] = {
- { MP_QSTR_file, MP_ARG_OBJ | MP_ARG_REQUIRED, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} },
+ { MP_QSTR_file, MP_ARG_OBJ | MP_ARG_REQUIRED, {.u_rom_obj = MP_ROM_NONE} },
{ MP_QSTR_mode, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_QSTR(MP_QSTR_r)} },
};
@@ -135,12 +136,12 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(vfs_posix_file___exit___obj, 4, 4, vf
STATIC mp_uint_t vfs_posix_file_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) {
mp_obj_vfs_posix_file_t *o = MP_OBJ_TO_PTR(o_in);
check_fd_is_open(o);
- mp_int_t r = read(o->fd, buf, size);
- if (r == -1) {
- *errcode = errno;
+ ssize_t r;
+ MP_HAL_RETRY_SYSCALL(r, read(o->fd, buf, size), {
+ *errcode = err;
return MP_STREAM_ERROR;
- }
- return r;
+ });
+ return (mp_uint_t)r;
}
STATIC mp_uint_t vfs_posix_file_write(mp_obj_t o_in, const void *buf, mp_uint_t size, int *errcode) {
@@ -152,35 +153,38 @@ STATIC mp_uint_t vfs_posix_file_write(mp_obj_t o_in, const void *buf, mp_uint_t
return size;
}
#endif
- mp_int_t r = write(o->fd, buf, size);
- while (r == -1 && errno == EINTR) {
- if (MP_STATE_VM(mp_pending_exception) != MP_OBJ_NULL) {
- mp_obj_t obj = MP_STATE_VM(mp_pending_exception);
- MP_STATE_VM(mp_pending_exception) = MP_OBJ_NULL;
- nlr_raise(obj);
- }
- r = write(o->fd, buf, size);
- }
- if (r == -1) {
- *errcode = errno;
+ ssize_t r;
+ MP_HAL_RETRY_SYSCALL(r, write(o->fd, buf, size), {
+ *errcode = err;
return MP_STREAM_ERROR;
- }
- return r;
+ });
+ return (mp_uint_t)r;
}
STATIC mp_uint_t vfs_posix_file_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg, int *errcode) {
mp_obj_vfs_posix_file_t *o = MP_OBJ_TO_PTR(o_in);
check_fd_is_open(o);
switch (request) {
- case MP_STREAM_FLUSH:
- if (fsync(o->fd) < 0) {
- *errcode = errno;
+ case MP_STREAM_FLUSH: {
+ int ret;
+ MP_HAL_RETRY_SYSCALL(ret, fsync(o->fd), {
+ if (err == EINVAL
+ && (o->fd == STDIN_FILENO || o->fd == STDOUT_FILENO || o->fd == STDERR_FILENO)) {
+ // fsync(stdin/stdout/stderr) may fail with EINVAL, but don't propagate that
+ // error out. Because data is not buffered by us, and stdin/out/err.flush()
+ // should just be a no-op.
+ return 0;
+ }
+ *errcode = err;
return MP_STREAM_ERROR;
- }
+ });
return 0;
+ }
case MP_STREAM_SEEK: {
- struct mp_stream_seek_t *s = (struct mp_stream_seek_t*)arg;
+ struct mp_stream_seek_t *s = (struct mp_stream_seek_t *)arg;
+ MP_THREAD_GIL_EXIT();
off_t off = lseek(o->fd, s->offset, s->whence);
+ MP_THREAD_GIL_ENTER();
if (off == (off_t)-1) {
*errcode = errno;
return MP_STREAM_ERROR;
@@ -189,18 +193,22 @@ STATIC mp_uint_t vfs_posix_file_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_
return 0;
}
case MP_STREAM_CLOSE:
+ MP_THREAD_GIL_EXIT();
close(o->fd);
+ MP_THREAD_GIL_ENTER();
#ifdef MICROPY_CPYTHON_COMPAT
o->fd = -1;
#endif
return 0;
+ case MP_STREAM_GET_FILENO:
+ return o->fd;
default:
*errcode = EINVAL;
return MP_STREAM_ERROR;
}
}
-STATIC const mp_rom_map_elem_t rawfile_locals_dict_table[] = {
+STATIC const mp_rom_map_elem_t vfs_posix_rawfile_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_fileno), MP_ROM_PTR(&vfs_posix_file_fileno_obj) },
{ MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) },
{ MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) },
@@ -215,10 +223,10 @@ STATIC const mp_rom_map_elem_t rawfile_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&vfs_posix_file___exit___obj) },
};
-STATIC MP_DEFINE_CONST_DICT(rawfile_locals_dict, rawfile_locals_dict_table);
+STATIC MP_DEFINE_CONST_DICT(vfs_posix_rawfile_locals_dict, vfs_posix_rawfile_locals_dict_table);
#if MICROPY_PY_IO_FILEIO
-STATIC const mp_stream_p_t fileio_stream_p = {
+STATIC const mp_stream_p_t vfs_posix_fileio_stream_p = {
.read = vfs_posix_file_read,
.write = vfs_posix_file_write,
.ioctl = vfs_posix_file_ioctl,
@@ -231,12 +239,12 @@ const mp_obj_type_t mp_type_vfs_posix_fileio = {
.make_new = vfs_posix_file_make_new,
.getiter = mp_identity_getiter,
.iternext = mp_stream_unbuffered_iter,
- .protocol = &fileio_stream_p,
- .locals_dict = (mp_obj_dict_t*)&rawfile_locals_dict,
+ .protocol = &vfs_posix_fileio_stream_p,
+ .locals_dict = (mp_obj_dict_t *)&vfs_posix_rawfile_locals_dict,
};
#endif
-STATIC const mp_stream_p_t textio_stream_p = {
+STATIC const mp_stream_p_t vfs_posix_textio_stream_p = {
.read = vfs_posix_file_read,
.write = vfs_posix_file_write,
.ioctl = vfs_posix_file_ioctl,
@@ -250,12 +258,12 @@ const mp_obj_type_t mp_type_vfs_posix_textio = {
.make_new = vfs_posix_file_make_new,
.getiter = mp_identity_getiter,
.iternext = mp_stream_unbuffered_iter,
- .protocol = &textio_stream_p,
- .locals_dict = (mp_obj_dict_t*)&rawfile_locals_dict,
+ .protocol = &vfs_posix_textio_stream_p,
+ .locals_dict = (mp_obj_dict_t *)&vfs_posix_rawfile_locals_dict,
};
-const mp_obj_vfs_posix_file_t mp_sys_stdin_obj = {{&mp_type_textio}, STDIN_FILENO};
+const mp_obj_vfs_posix_file_t mp_sys_stdin_obj = {{&mp_type_textio}, STDIN_FILENO};
const mp_obj_vfs_posix_file_t mp_sys_stdout_obj = {{&mp_type_textio}, STDOUT_FILENO};
const mp_obj_vfs_posix_file_t mp_sys_stderr_obj = {{&mp_type_textio}, STDERR_FILENO};
-#endif // MICROPY_VFS_POSIX
+#endif // MICROPY_VFS_POSIX || MICROPY_VFS_POSIX_FILE
diff --git a/extmod/vfs_reader.c b/extmod/vfs_reader.c
index e1ee45a3c7..d3904c5c50 100644
--- a/extmod/vfs_reader.c
+++ b/extmod/vfs_reader.c
@@ -42,7 +42,7 @@ typedef struct _mp_reader_vfs_t {
} mp_reader_vfs_t;
STATIC mp_uint_t mp_reader_vfs_readbyte(void *data) {
- mp_reader_vfs_t *reader = (mp_reader_vfs_t*)data;
+ mp_reader_vfs_t *reader = (mp_reader_vfs_t *)data;
if (reader->pos >= reader->len) {
if (reader->len < sizeof(reader->buf)) {
return MP_READER_EOF;
@@ -64,15 +64,18 @@ STATIC mp_uint_t mp_reader_vfs_readbyte(void *data) {
}
STATIC void mp_reader_vfs_close(void *data) {
- mp_reader_vfs_t *reader = (mp_reader_vfs_t*)data;
+ mp_reader_vfs_t *reader = (mp_reader_vfs_t *)data;
mp_stream_close(reader->file);
m_del_obj(mp_reader_vfs_t, reader);
}
void mp_reader_new_file(mp_reader_t *reader, const char *filename) {
mp_reader_vfs_t *rf = m_new_obj(mp_reader_vfs_t);
- mp_obj_t arg = mp_obj_new_str(filename, strlen(filename));
- rf->file = mp_vfs_open(1, &arg, (mp_map_t*)&mp_const_empty_map);
+ mp_obj_t args[2] = {
+ mp_obj_new_str(filename, strlen(filename)),
+ MP_OBJ_NEW_QSTR(MP_QSTR_rb),
+ };
+ rf->file = mp_vfs_open(MP_ARRAY_SIZE(args), &args[0], (mp_map_t *)&mp_const_empty_map);
int errcode;
rf->len = mp_stream_rw(rf->file, rf->buf, sizeof(rf->buf), &errcode, MP_STREAM_RW_READ | MP_STREAM_RW_ONCE);
if (errcode != 0) {
diff --git a/extmod/virtpin.c b/extmod/virtpin.c
index dbfa21d669..71a11232d4 100644
--- a/extmod/virtpin.c
+++ b/extmod/virtpin.c
@@ -27,13 +27,13 @@
#include "extmod/virtpin.h"
int mp_virtual_pin_read(mp_obj_t pin) {
- mp_obj_base_t* s = (mp_obj_base_t*)MP_OBJ_TO_PTR(pin);
- mp_pin_p_t *pin_p = (mp_pin_p_t*)s->type->protocol;
+ mp_obj_base_t *s = (mp_obj_base_t *)MP_OBJ_TO_PTR(pin);
+ mp_pin_p_t *pin_p = (mp_pin_p_t *)s->type->protocol;
return pin_p->ioctl(pin, MP_PIN_READ, 0, NULL);
}
void mp_virtual_pin_write(mp_obj_t pin, int value) {
- mp_obj_base_t* s = (mp_obj_base_t*)MP_OBJ_TO_PTR(pin);
- mp_pin_p_t *pin_p = (mp_pin_p_t*)s->type->protocol;
+ mp_obj_base_t *s = (mp_obj_base_t *)MP_OBJ_TO_PTR(pin);
+ mp_pin_p_t *pin_p = (mp_pin_p_t *)s->type->protocol;
pin_p->ioctl(pin, MP_PIN_WRITE, value, NULL);
}
diff --git a/extmod/webrepl/manifest.py b/extmod/webrepl/manifest.py
new file mode 100644
index 0000000000..6eceb3eeb6
--- /dev/null
+++ b/extmod/webrepl/manifest.py
@@ -0,0 +1 @@
+freeze(".", ("webrepl.py", "webrepl_setup.py", "websocket_helper.py"))
diff --git a/ports/esp8266/modules/webrepl.py b/extmod/webrepl/webrepl.py
similarity index 89%
rename from ports/esp8266/modules/webrepl.py
rename to extmod/webrepl/webrepl.py
index aa156d1487..8ddf56143f 100644
--- a/ports/esp8266/modules/webrepl.py
+++ b/extmod/webrepl/webrepl.py
@@ -2,13 +2,14 @@
import socket
import uos
import network
-import websocket
+import uwebsocket
import websocket_helper
import _webrepl
listen_s = None
client_s = None
+
def setup_conn(port, accept_handler):
global listen_s
listen_s = socket.socket()
@@ -40,11 +41,12 @@ def accept_conn(listen_sock):
print("\nWebREPL connection from:", remote_addr)
client_s = cl
websocket_helper.server_handshake(cl)
- ws = websocket.websocket(cl, True)
+ ws = uwebsocket.websocket(cl, True)
ws = _webrepl._webrepl(ws)
cl.setblocking(False)
- # notify REPL on socket incoming data
- cl.setsockopt(socket.SOL_SOCKET, 20, uos.dupterm_notify)
+ # notify REPL on socket incoming data (ESP32/ESP8266-only)
+ if hasattr(uos, "dupterm_notify"):
+ cl.setsockopt(socket.SOL_SOCKET, 20, uos.dupterm_notify)
uos.dupterm(ws)
@@ -62,6 +64,7 @@ def start(port=8266, password=None):
if password is None:
try:
import webrepl_cfg
+
_webrepl.password(webrepl_cfg.PASS)
setup_conn(port, accept_conn)
print("Started webrepl in normal mode")
diff --git a/ports/esp8266/modules/webrepl_setup.py b/extmod/webrepl/webrepl_setup.py
similarity index 94%
rename from ports/esp8266/modules/webrepl_setup.py
rename to extmod/webrepl/webrepl_setup.py
index 129313a21c..ffc9c77fc0 100644
--- a/ports/esp8266/modules/webrepl_setup.py
+++ b/extmod/webrepl/webrepl_setup.py
@@ -1,20 +1,24 @@
import sys
-#import uos as os
+
+# import uos as os
import os
import machine
RC = "./boot.py"
CONFIG = "./webrepl_cfg.py"
+
def input_choice(prompt, choices):
while 1:
resp = input(prompt)
if resp in choices:
return resp
+
def getpass(prompt):
return input(prompt)
+
def input_pass():
while 1:
passwd1 = getpass("New password (4-9 chars): ")
@@ -77,7 +81,9 @@ def main():
if resp == "E":
if exists(CONFIG):
- resp2 = input_choice("Would you like to change WebREPL password? (y/n) ", ("y", "n", ""))
+ resp2 = input_choice(
+ "Would you like to change WebREPL password? (y/n) ", ("y", "n", "")
+ )
else:
print("To enable WebREPL, you must set password for it")
resp2 = "y"
@@ -87,7 +93,6 @@ def main():
with open(CONFIG, "w") as f:
f.write("PASS = %r\n" % passwd)
-
if resp not in ("D", "E") or (resp == "D" and not status) or (resp == "E" and status):
print("No further action required")
sys.exit()
@@ -99,4 +104,5 @@ def main():
if resp == "y":
machine.reset()
+
main()
diff --git a/ports/esp8266/modules/websocket_helper.py b/extmod/webrepl/websocket_helper.py
similarity index 86%
rename from ports/esp8266/modules/websocket_helper.py
rename to extmod/webrepl/websocket_helper.py
index 9c06db5023..5ca80534eb 100644
--- a/ports/esp8266/modules/websocket_helper.py
+++ b/extmod/webrepl/websocket_helper.py
@@ -1,4 +1,5 @@
import sys
+
try:
import ubinascii as binascii
except:
@@ -10,10 +11,11 @@
DEBUG = 0
+
def server_handshake(sock):
clr = sock.makefile("rwb", 0)
l = clr.readline()
- #sys.stdout.write(repr(l))
+ # sys.stdout.write(repr(l))
webkey = None
@@ -23,11 +25,11 @@ def server_handshake(sock):
raise OSError("EOF in headers")
if l == b"\r\n":
break
- # sys.stdout.write(l)
+ # sys.stdout.write(l)
h, v = [x.strip() for x in l.split(b":", 1)]
if DEBUG:
print((h, v))
- if h == b'Sec-WebSocket-Key':
+ if h == b"Sec-WebSocket-Key":
webkey = v
if not webkey:
@@ -43,11 +45,13 @@ def server_handshake(sock):
if DEBUG:
print("respkey:", respkey)
- sock.send(b"""\
+ sock.send(
+ b"""\
HTTP/1.1 101 Switching Protocols\r
Upgrade: websocket\r
Connection: Upgrade\r
-Sec-WebSocket-Accept: """)
+Sec-WebSocket-Accept: """
+ )
sock.send(respkey)
sock.send("\r\n\r\n")
@@ -57,18 +61,22 @@ def server_handshake(sock):
# servers.
def client_handshake(sock):
cl = sock.makefile("rwb", 0)
- cl.write(b"""\
+ cl.write(
+ b"""\
GET / HTTP/1.1\r
Host: echo.websocket.org\r
Connection: Upgrade\r
Upgrade: websocket\r
Sec-WebSocket-Key: foo\r
\r
-""")
+"""
+ )
l = cl.readline()
-# print(l)
+ # print(l)
while 1:
l = cl.readline()
if l == b"\r\n":
break
+
+
# sys.stdout.write(l)
diff --git a/lib/asf4 b/lib/asf4
new file mode 160000
index 0000000000..d270f79aa1
--- /dev/null
+++ b/lib/asf4
@@ -0,0 +1 @@
+Subproject commit d270f79aa16dd8fd4ae3b6c14544283dcb992e9c
diff --git a/lib/btstack b/lib/btstack
new file mode 160000
index 0000000000..c8b9823f68
--- /dev/null
+++ b/lib/btstack
@@ -0,0 +1 @@
+Subproject commit c8b9823f68c6af0fa52e2c4e009aba4dbf257232
diff --git a/lib/cmsis/inc/cmsis_armcc.h b/lib/cmsis/inc/cmsis_armcc.h
index 74c49c67de..174d744033 100644
--- a/lib/cmsis/inc/cmsis_armcc.h
+++ b/lib/cmsis/inc/cmsis_armcc.h
@@ -1,43 +1,108 @@
/**************************************************************************//**
* @file cmsis_armcc.h
- * @brief CMSIS Cortex-M Core Function/Instruction Header File
- * @version V4.30
- * @date 20. October 2015
+ * @brief CMSIS compiler ARMCC (Arm Compiler 5) header file
+ * @version V5.0.5
+ * @date 14. December 2018
******************************************************************************/
-/* Copyright (c) 2009 - 2015 ARM LIMITED
-
- All rights reserved.
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are met:
- - Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- - Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
- - Neither the name of ARM nor the names of its contributors may be used
- to endorse or promote products derived from this software without
- specific prior written permission.
- *
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE
- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- POSSIBILITY OF SUCH DAMAGE.
- ---------------------------------------------------------------------------*/
-
+/*
+ * Copyright (c) 2009-2018 Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
#ifndef __CMSIS_ARMCC_H
#define __CMSIS_ARMCC_H
#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 400677)
- #error "Please use ARM Compiler Toolchain V4.0.677 or later!"
+ #error "Please use Arm Compiler Toolchain V4.0.677 or later!"
+#endif
+
+/* CMSIS compiler control architecture macros */
+#if ((defined (__TARGET_ARCH_6_M ) && (__TARGET_ARCH_6_M == 1)) || \
+ (defined (__TARGET_ARCH_6S_M ) && (__TARGET_ARCH_6S_M == 1)) )
+ #define __ARM_ARCH_6M__ 1
+#endif
+
+#if (defined (__TARGET_ARCH_7_M ) && (__TARGET_ARCH_7_M == 1))
+ #define __ARM_ARCH_7M__ 1
+#endif
+
+#if (defined (__TARGET_ARCH_7E_M) && (__TARGET_ARCH_7E_M == 1))
+ #define __ARM_ARCH_7EM__ 1
+#endif
+
+ /* __ARM_ARCH_8M_BASE__ not applicable */
+ /* __ARM_ARCH_8M_MAIN__ not applicable */
+
+/* CMSIS compiler control DSP macros */
+#if ((defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) )
+ #define __ARM_FEATURE_DSP 1
+#endif
+
+/* CMSIS compiler specific defines */
+#ifndef __ASM
+ #define __ASM __asm
+#endif
+#ifndef __INLINE
+ #define __INLINE __inline
+#endif
+#ifndef __STATIC_INLINE
+ #define __STATIC_INLINE static __inline
+#endif
+#ifndef __STATIC_FORCEINLINE
+ #define __STATIC_FORCEINLINE static __forceinline
+#endif
+#ifndef __NO_RETURN
+ #define __NO_RETURN __declspec(noreturn)
+#endif
+#ifndef __USED
+ #define __USED __attribute__((used))
+#endif
+#ifndef __WEAK
+ #define __WEAK __attribute__((weak))
+#endif
+#ifndef __PACKED
+ #define __PACKED __attribute__((packed))
+#endif
+#ifndef __PACKED_STRUCT
+ #define __PACKED_STRUCT __packed struct
+#endif
+#ifndef __PACKED_UNION
+ #define __PACKED_UNION __packed union
+#endif
+#ifndef __UNALIGNED_UINT32 /* deprecated */
+ #define __UNALIGNED_UINT32(x) (*((__packed uint32_t *)(x)))
+#endif
+#ifndef __UNALIGNED_UINT16_WRITE
+ #define __UNALIGNED_UINT16_WRITE(addr, val) ((*((__packed uint16_t *)(addr))) = (val))
+#endif
+#ifndef __UNALIGNED_UINT16_READ
+ #define __UNALIGNED_UINT16_READ(addr) (*((const __packed uint16_t *)(addr)))
+#endif
+#ifndef __UNALIGNED_UINT32_WRITE
+ #define __UNALIGNED_UINT32_WRITE(addr, val) ((*((__packed uint32_t *)(addr))) = (val))
+#endif
+#ifndef __UNALIGNED_UINT32_READ
+ #define __UNALIGNED_UINT32_READ(addr) (*((const __packed uint32_t *)(addr)))
+#endif
+#ifndef __ALIGNED
+ #define __ALIGNED(x) __attribute__((aligned(x)))
+#endif
+#ifndef __RESTRICT
+ #define __RESTRICT __restrict
#endif
/* ########################### Core Function Access ########################### */
@@ -46,7 +111,19 @@
@{
*/
+/**
+ \brief Enable IRQ Interrupts
+ \details Enables IRQ interrupts by clearing the I-bit in the CPSR.
+ Can only be executed in Privileged modes.
+ */
/* intrinsic void __enable_irq(); */
+
+
+/**
+ \brief Disable IRQ Interrupts
+ \details Disables IRQ interrupts by setting the I-bit in the CPSR.
+ Can only be executed in Privileged modes.
+ */
/* intrinsic void __disable_irq(); */
/**
@@ -181,7 +258,8 @@ __STATIC_INLINE void __set_PRIMASK(uint32_t priMask)
}
-#if (__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U)
+#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \
+ (defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) )
/**
\brief Enable FIQ
@@ -256,13 +334,12 @@ __STATIC_INLINE uint32_t __get_FAULTMASK(void)
__STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask)
{
register uint32_t __regFaultMask __ASM("faultmask");
- __regFaultMask = (faultMask & (uint32_t)1);
+ __regFaultMask = (faultMask & (uint32_t)1U);
}
-#endif /* (__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U) */
-
+#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \
+ (defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) */
-#if (__CORTEX_M == 0x04U) || (__CORTEX_M == 0x07U)
/**
\brief Get FPSCR
@@ -271,7 +348,8 @@ __STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask)
*/
__STATIC_INLINE uint32_t __get_FPSCR(void)
{
-#if (__FPU_PRESENT == 1U) && (__FPU_USED == 1U)
+#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \
+ (defined (__FPU_USED ) && (__FPU_USED == 1U)) )
register uint32_t __regfpscr __ASM("fpscr");
return(__regfpscr);
#else
@@ -287,15 +365,15 @@ __STATIC_INLINE uint32_t __get_FPSCR(void)
*/
__STATIC_INLINE void __set_FPSCR(uint32_t fpscr)
{
-#if (__FPU_PRESENT == 1U) && (__FPU_USED == 1U)
+#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \
+ (defined (__FPU_USED ) && (__FPU_USED == 1U)) )
register uint32_t __regfpscr __ASM("fpscr");
__regfpscr = (fpscr);
+#else
+ (void)fpscr;
#endif
}
-#endif /* (__CORTEX_M == 0x04U) || (__CORTEX_M == 0x07U) */
-
-
/*@} end of CMSIS_Core_RegAccFunctions */
@@ -369,9 +447,10 @@ __STATIC_INLINE void __set_FPSCR(uint32_t fpscr)
__schedule_barrier();\
} while (0U)
+
/**
\brief Reverse byte order (32 bit)
- \details Reverses the byte order in integer value.
+ \details Reverses the byte order in unsigned integer value. For example, 0x12345678 becomes 0x78563412.
\param [in] value Value to reverse
\return Reversed value
*/
@@ -380,7 +459,7 @@ __STATIC_INLINE void __set_FPSCR(uint32_t fpscr)
/**
\brief Reverse byte order (16 bit)
- \details Reverses the byte order in two unsigned short values.
+ \details Reverses the byte order within each halfword of a word. For example, 0x12345678 becomes 0x34127856.
\param [in] value Value to reverse
\return Reversed value
*/
@@ -392,14 +471,15 @@ __attribute__((section(".rev16_text"))) __STATIC_INLINE __ASM uint32_t __REV16(u
}
#endif
+
/**
- \brief Reverse byte order in signed short value
- \details Reverses the byte order in a signed short value with sign extension to integer.
+ \brief Reverse byte order (16 bit)
+ \details Reverses the byte order in a 16-bit value and returns the signed 16-bit result. For example, 0x0080 becomes 0x8000.
\param [in] value Value to reverse
\return Reversed value
*/
#ifndef __NO_EMBEDDED_ASM
-__attribute__((section(".revsh_text"))) __STATIC_INLINE __ASM int32_t __REVSH(int32_t value)
+__attribute__((section(".revsh_text"))) __STATIC_INLINE __ASM int16_t __REVSH(int16_t value)
{
revsh r0, r0
bx lr
@@ -410,8 +490,8 @@ __attribute__((section(".revsh_text"))) __STATIC_INLINE __ASM int32_t __REVSH(in
/**
\brief Rotate Right in unsigned value (32 bit)
\details Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits.
- \param [in] value Value to rotate
- \param [in] value Number of Bits to rotate
+ \param [in] op1 Value to rotate
+ \param [in] op2 Number of Bits to rotate
\return Rotated value
*/
#define __ROR __ror
@@ -433,23 +513,24 @@ __attribute__((section(".revsh_text"))) __STATIC_INLINE __ASM int32_t __REVSH(in
\param [in] value Value to reverse
\return Reversed value
*/
-#if (__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U)
+#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \
+ (defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) )
#define __RBIT __rbit
#else
__attribute__((always_inline)) __STATIC_INLINE uint32_t __RBIT(uint32_t value)
{
uint32_t result;
- int32_t s = 4 /*sizeof(v)*/ * 8 - 1; /* extra shift needed at end */
+ uint32_t s = (4U /*sizeof(v)*/ * 8U) - 1U; /* extra shift needed at end */
result = value; /* r will be reversed bits of v; first get LSB of v */
- for (value >>= 1U; value; value >>= 1U)
+ for (value >>= 1U; value != 0U; value >>= 1U)
{
result <<= 1U;
result |= value & 1U;
s--;
}
result <<= s; /* shift when v's highest bits are zero */
- return(result);
+ return result;
}
#endif
@@ -463,7 +544,8 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __RBIT(uint32_t value)
#define __CLZ __clz
-#if (__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U)
+#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \
+ (defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) )
/**
\brief LDR Exclusive (8 bit)
@@ -645,7 +727,60 @@ __attribute__((section(".rrx_text"))) __STATIC_INLINE __ASM uint32_t __RRX(uint3
*/
#define __STRT(value, ptr) __strt(value, ptr)
-#endif /* (__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U) */
+#else /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \
+ (defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) */
+
+/**
+ \brief Signed Saturate
+ \details Saturates a signed value.
+ \param [in] value Value to be saturated
+ \param [in] sat Bit position to saturate to (1..32)
+ \return Saturated value
+ */
+__attribute__((always_inline)) __STATIC_INLINE int32_t __SSAT(int32_t val, uint32_t sat)
+{
+ if ((sat >= 1U) && (sat <= 32U))
+ {
+ const int32_t max = (int32_t)((1U << (sat - 1U)) - 1U);
+ const int32_t min = -1 - max ;
+ if (val > max)
+ {
+ return max;
+ }
+ else if (val < min)
+ {
+ return min;
+ }
+ }
+ return val;
+}
+
+/**
+ \brief Unsigned Saturate
+ \details Saturates an unsigned value.
+ \param [in] value Value to be saturated
+ \param [in] sat Bit position to saturate to (0..31)
+ \return Saturated value
+ */
+__attribute__((always_inline)) __STATIC_INLINE uint32_t __USAT(int32_t val, uint32_t sat)
+{
+ if (sat <= 31U)
+ {
+ const uint32_t max = ((1U << sat) - 1U);
+ if (val > (int32_t)max)
+ {
+ return max;
+ }
+ else if (val < 0)
+ {
+ return 0U;
+ }
+ }
+ return (uint32_t)val;
+}
+
+#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \
+ (defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) */
/*@}*/ /* end of group CMSIS_Core_InstructionInterface */
@@ -656,7 +791,7 @@ __attribute__((section(".rrx_text"))) __STATIC_INLINE __ASM uint32_t __RRX(uint3
@{
*/
-#if (__CORTEX_M >= 0x04U) /* only for Cortex-M4 and above */
+#if ((defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) )
#define __SADD8 __sadd8
#define __QADD8 __qadd8
@@ -727,7 +862,7 @@ __attribute__((section(".rrx_text"))) __STATIC_INLINE __ASM uint32_t __RRX(uint3
#define __SMMLA(ARG1,ARG2,ARG3) ( (int32_t)((((int64_t)(ARG1) * (ARG2)) + \
((int64_t)(ARG3) << 32U) ) >> 32U))
-#endif /* (__CORTEX_M >= 0x04) */
+#endif /* ((defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) */
/*@} end of group CMSIS_SIMD_intrinsics */
diff --git a/lib/cmsis/inc/cmsis_armcc_V6.h b/lib/cmsis/inc/cmsis_armcc_V6.h
deleted file mode 100644
index cd13240ce3..0000000000
--- a/lib/cmsis/inc/cmsis_armcc_V6.h
+++ /dev/null
@@ -1,1800 +0,0 @@
-/**************************************************************************//**
- * @file cmsis_armcc_V6.h
- * @brief CMSIS Cortex-M Core Function/Instruction Header File
- * @version V4.30
- * @date 20. October 2015
- ******************************************************************************/
-/* Copyright (c) 2009 - 2015 ARM LIMITED
-
- All rights reserved.
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are met:
- - Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- - Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
- - Neither the name of ARM nor the names of its contributors may be used
- to endorse or promote products derived from this software without
- specific prior written permission.
- *
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE
- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- POSSIBILITY OF SUCH DAMAGE.
- ---------------------------------------------------------------------------*/
-
-
-#ifndef __CMSIS_ARMCC_V6_H
-#define __CMSIS_ARMCC_V6_H
-
-
-/* ########################### Core Function Access ########################### */
-/** \ingroup CMSIS_Core_FunctionInterface
- \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions
- @{
- */
-
-/**
- \brief Enable IRQ Interrupts
- \details Enables IRQ interrupts by clearing the I-bit in the CPSR.
- Can only be executed in Privileged modes.
- */
-__attribute__((always_inline)) __STATIC_INLINE void __enable_irq(void)
-{
- __ASM volatile ("cpsie i" : : : "memory");
-}
-
-
-/**
- \brief Disable IRQ Interrupts
- \details Disables IRQ interrupts by setting the I-bit in the CPSR.
- Can only be executed in Privileged modes.
- */
-__attribute__((always_inline)) __STATIC_INLINE void __disable_irq(void)
-{
- __ASM volatile ("cpsid i" : : : "memory");
-}
-
-
-/**
- \brief Get Control Register
- \details Returns the content of the Control Register.
- \return Control Register value
- */
-__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_CONTROL(void)
-{
- uint32_t result;
-
- __ASM volatile ("MRS %0, control" : "=r" (result) );
- return(result);
-}
-
-
-#if (__ARM_FEATURE_CMSE == 3U)
-/**
- \brief Get Control Register (non-secure)
- \details Returns the content of the non-secure Control Register when in secure mode.
- \return non-secure Control Register value
- */
-__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_CONTROL_NS(void)
-{
- uint32_t result;
-
- __ASM volatile ("MRS %0, control_ns" : "=r" (result) );
- return(result);
-}
-#endif
-
-
-/**
- \brief Set Control Register
- \details Writes the given value to the Control Register.
- \param [in] control Control Register value to set
- */
-__attribute__((always_inline)) __STATIC_INLINE void __set_CONTROL(uint32_t control)
-{
- __ASM volatile ("MSR control, %0" : : "r" (control) : "memory");
-}
-
-
-#if (__ARM_FEATURE_CMSE == 3U)
-/**
- \brief Set Control Register (non-secure)
- \details Writes the given value to the non-secure Control Register when in secure state.
- \param [in] control Control Register value to set
- */
-__attribute__((always_inline)) __STATIC_INLINE void __TZ_set_CONTROL_NS(uint32_t control)
-{
- __ASM volatile ("MSR control_ns, %0" : : "r" (control) : "memory");
-}
-#endif
-
-
-/**
- \brief Get IPSR Register
- \details Returns the content of the IPSR Register.
- \return IPSR Register value
- */
-__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_IPSR(void)
-{
- uint32_t result;
-
- __ASM volatile ("MRS %0, ipsr" : "=r" (result) );
- return(result);
-}
-
-
-#if (__ARM_FEATURE_CMSE == 3U)
-/**
- \brief Get IPSR Register (non-secure)
- \details Returns the content of the non-secure IPSR Register when in secure state.
- \return IPSR Register value
- */
-__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_IPSR_NS(void)
-{
- uint32_t result;
-
- __ASM volatile ("MRS %0, ipsr_ns" : "=r" (result) );
- return(result);
-}
-#endif
-
-
-/**
- \brief Get APSR Register
- \details Returns the content of the APSR Register.
- \return APSR Register value
- */
-__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_APSR(void)
-{
- uint32_t result;
-
- __ASM volatile ("MRS %0, apsr" : "=r" (result) );
- return(result);
-}
-
-
-#if (__ARM_FEATURE_CMSE == 3U)
-/**
- \brief Get APSR Register (non-secure)
- \details Returns the content of the non-secure APSR Register when in secure state.
- \return APSR Register value
- */
-__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_APSR_NS(void)
-{
- uint32_t result;
-
- __ASM volatile ("MRS %0, apsr_ns" : "=r" (result) );
- return(result);
-}
-#endif
-
-
-/**
- \brief Get xPSR Register
- \details Returns the content of the xPSR Register.
- \return xPSR Register value
- */
-__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_xPSR(void)
-{
- uint32_t result;
-
- __ASM volatile ("MRS %0, xpsr" : "=r" (result) );
- return(result);
-}
-
-
-#if (__ARM_FEATURE_CMSE == 3U)
-/**
- \brief Get xPSR Register (non-secure)
- \details Returns the content of the non-secure xPSR Register when in secure state.
- \return xPSR Register value
- */
-__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_xPSR_NS(void)
-{
- uint32_t result;
-
- __ASM volatile ("MRS %0, xpsr_ns" : "=r" (result) );
- return(result);
-}
-#endif
-
-
-/**
- \brief Get Process Stack Pointer
- \details Returns the current value of the Process Stack Pointer (PSP).
- \return PSP Register value
- */
-__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_PSP(void)
-{
- register uint32_t result;
-
- __ASM volatile ("MRS %0, psp" : "=r" (result) );
- return(result);
-}
-
-
-#if (__ARM_FEATURE_CMSE == 3U)
-/**
- \brief Get Process Stack Pointer (non-secure)
- \details Returns the current value of the non-secure Process Stack Pointer (PSP) when in secure state.
- \return PSP Register value
- */
-__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_PSP_NS(void)
-{
- register uint32_t result;
-
- __ASM volatile ("MRS %0, psp_ns" : "=r" (result) );
- return(result);
-}
-#endif
-
-
-/**
- \brief Set Process Stack Pointer
- \details Assigns the given value to the Process Stack Pointer (PSP).
- \param [in] topOfProcStack Process Stack Pointer value to set
- */
-__attribute__((always_inline)) __STATIC_INLINE void __set_PSP(uint32_t topOfProcStack)
-{
- __ASM volatile ("MSR psp, %0" : : "r" (topOfProcStack) : "sp");
-}
-
-
-#if (__ARM_FEATURE_CMSE == 3U)
-/**
- \brief Set Process Stack Pointer (non-secure)
- \details Assigns the given value to the non-secure Process Stack Pointer (PSP) when in secure state.
- \param [in] topOfProcStack Process Stack Pointer value to set
- */
-__attribute__((always_inline)) __STATIC_INLINE void __TZ_set_PSP_NS(uint32_t topOfProcStack)
-{
- __ASM volatile ("MSR psp_ns, %0" : : "r" (topOfProcStack) : "sp");
-}
-#endif
-
-
-/**
- \brief Get Main Stack Pointer
- \details Returns the current value of the Main Stack Pointer (MSP).
- \return MSP Register value
- */
-__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_MSP(void)
-{
- register uint32_t result;
-
- __ASM volatile ("MRS %0, msp" : "=r" (result) );
- return(result);
-}
-
-
-#if (__ARM_FEATURE_CMSE == 3U)
-/**
- \brief Get Main Stack Pointer (non-secure)
- \details Returns the current value of the non-secure Main Stack Pointer (MSP) when in secure state.
- \return MSP Register value
- */
-__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_MSP_NS(void)
-{
- register uint32_t result;
-
- __ASM volatile ("MRS %0, msp_ns" : "=r" (result) );
- return(result);
-}
-#endif
-
-
-/**
- \brief Set Main Stack Pointer
- \details Assigns the given value to the Main Stack Pointer (MSP).
- \param [in] topOfMainStack Main Stack Pointer value to set
- */
-__attribute__((always_inline)) __STATIC_INLINE void __set_MSP(uint32_t topOfMainStack)
-{
- __ASM volatile ("MSR msp, %0" : : "r" (topOfMainStack) : "sp");
-}
-
-
-#if (__ARM_FEATURE_CMSE == 3U)
-/**
- \brief Set Main Stack Pointer (non-secure)
- \details Assigns the given value to the non-secure Main Stack Pointer (MSP) when in secure state.
- \param [in] topOfMainStack Main Stack Pointer value to set
- */
-__attribute__((always_inline)) __STATIC_INLINE void __TZ_set_MSP_NS(uint32_t topOfMainStack)
-{
- __ASM volatile ("MSR msp_ns, %0" : : "r" (topOfMainStack) : "sp");
-}
-#endif
-
-
-/**
- \brief Get Priority Mask
- \details Returns the current state of the priority mask bit from the Priority Mask Register.
- \return Priority Mask value
- */
-__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_PRIMASK(void)
-{
- uint32_t result;
-
- __ASM volatile ("MRS %0, primask" : "=r" (result) );
- return(result);
-}
-
-
-#if (__ARM_FEATURE_CMSE == 3U)
-/**
- \brief Get Priority Mask (non-secure)
- \details Returns the current state of the non-secure priority mask bit from the Priority Mask Register when in secure state.
- \return Priority Mask value
- */
-__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_PRIMASK_NS(void)
-{
- uint32_t result;
-
- __ASM volatile ("MRS %0, primask_ns" : "=r" (result) );
- return(result);
-}
-#endif
-
-
-/**
- \brief Set Priority Mask
- \details Assigns the given value to the Priority Mask Register.
- \param [in] priMask Priority Mask
- */
-__attribute__((always_inline)) __STATIC_INLINE void __set_PRIMASK(uint32_t priMask)
-{
- __ASM volatile ("MSR primask, %0" : : "r" (priMask) : "memory");
-}
-
-
-#if (__ARM_FEATURE_CMSE == 3U)
-/**
- \brief Set Priority Mask (non-secure)
- \details Assigns the given value to the non-secure Priority Mask Register when in secure state.
- \param [in] priMask Priority Mask
- */
-__attribute__((always_inline)) __STATIC_INLINE void __TZ_set_PRIMASK_NS(uint32_t priMask)
-{
- __ASM volatile ("MSR primask_ns, %0" : : "r" (priMask) : "memory");
-}
-#endif
-
-
-#if ((__ARM_ARCH_7M__ == 1U) || (__ARM_ARCH_7EM__ == 1U) || (__ARM_ARCH_8M__ == 1U)) /* ToDo: ARMCC_V6: check if this is ok for cortex >=3 */
-
-/**
- \brief Enable FIQ
- \details Enables FIQ interrupts by clearing the F-bit in the CPSR.
- Can only be executed in Privileged modes.
- */
-__attribute__((always_inline)) __STATIC_INLINE void __enable_fault_irq(void)
-{
- __ASM volatile ("cpsie f" : : : "memory");
-}
-
-
-/**
- \brief Disable FIQ
- \details Disables FIQ interrupts by setting the F-bit in the CPSR.
- Can only be executed in Privileged modes.
- */
-__attribute__((always_inline)) __STATIC_INLINE void __disable_fault_irq(void)
-{
- __ASM volatile ("cpsid f" : : : "memory");
-}
-
-
-/**
- \brief Get Base Priority
- \details Returns the current value of the Base Priority register.
- \return Base Priority register value
- */
-__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_BASEPRI(void)
-{
- uint32_t result;
-
- __ASM volatile ("MRS %0, basepri" : "=r" (result) );
- return(result);
-}
-
-
-#if (__ARM_FEATURE_CMSE == 3U)
-/**
- \brief Get Base Priority (non-secure)
- \details Returns the current value of the non-secure Base Priority register when in secure state.
- \return Base Priority register value
- */
-__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_BASEPRI_NS(void)
-{
- uint32_t result;
-
- __ASM volatile ("MRS %0, basepri_ns" : "=r" (result) );
- return(result);
-}
-#endif
-
-
-/**
- \brief Set Base Priority
- \details Assigns the given value to the Base Priority register.
- \param [in] basePri Base Priority value to set
- */
-__attribute__((always_inline)) __STATIC_INLINE void __set_BASEPRI(uint32_t value)
-{
- __ASM volatile ("MSR basepri, %0" : : "r" (value) : "memory");
-}
-
-
-#if (__ARM_FEATURE_CMSE == 3U)
-/**
- \brief Set Base Priority (non-secure)
- \details Assigns the given value to the non-secure Base Priority register when in secure state.
- \param [in] basePri Base Priority value to set
- */
-__attribute__((always_inline)) __STATIC_INLINE void __TZ_set_BASEPRI_NS(uint32_t value)
-{
- __ASM volatile ("MSR basepri_ns, %0" : : "r" (value) : "memory");
-}
-#endif
-
-
-/**
- \brief Set Base Priority with condition
- \details Assigns the given value to the Base Priority register only if BASEPRI masking is disabled,
- or the new value increases the BASEPRI priority level.
- \param [in] basePri Base Priority value to set
- */
-__attribute__((always_inline)) __STATIC_INLINE void __set_BASEPRI_MAX(uint32_t value)
-{
- __ASM volatile ("MSR basepri_max, %0" : : "r" (value) : "memory");
-}
-
-
-#if (__ARM_FEATURE_CMSE == 3U)
-/**
- \brief Set Base Priority with condition (non_secure)
- \details Assigns the given value to the non-secure Base Priority register when in secure state only if BASEPRI masking is disabled,
- or the new value increases the BASEPRI priority level.
- \param [in] basePri Base Priority value to set
- */
-__attribute__((always_inline)) __STATIC_INLINE void __TZ_set_BASEPRI_MAX_NS(uint32_t value)
-{
- __ASM volatile ("MSR basepri_max_ns, %0" : : "r" (value) : "memory");
-}
-#endif
-
-
-/**
- \brief Get Fault Mask
- \details Returns the current value of the Fault Mask register.
- \return Fault Mask register value
- */
-__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_FAULTMASK(void)
-{
- uint32_t result;
-
- __ASM volatile ("MRS %0, faultmask" : "=r" (result) );
- return(result);
-}
-
-
-#if (__ARM_FEATURE_CMSE == 3U)
-/**
- \brief Get Fault Mask (non-secure)
- \details Returns the current value of the non-secure Fault Mask register when in secure state.
- \return Fault Mask register value
- */
-__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_FAULTMASK_NS(void)
-{
- uint32_t result;
-
- __ASM volatile ("MRS %0, faultmask_ns" : "=r" (result) );
- return(result);
-}
-#endif
-
-
-/**
- \brief Set Fault Mask
- \details Assigns the given value to the Fault Mask register.
- \param [in] faultMask Fault Mask value to set
- */
-__attribute__((always_inline)) __STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask)
-{
- __ASM volatile ("MSR faultmask, %0" : : "r" (faultMask) : "memory");
-}
-
-
-#if (__ARM_FEATURE_CMSE == 3U)
-/**
- \brief Set Fault Mask (non-secure)
- \details Assigns the given value to the non-secure Fault Mask register when in secure state.
- \param [in] faultMask Fault Mask value to set
- */
-__attribute__((always_inline)) __STATIC_INLINE void __TZ_set_FAULTMASK_NS(uint32_t faultMask)
-{
- __ASM volatile ("MSR faultmask_ns, %0" : : "r" (faultMask) : "memory");
-}
-#endif
-
-
-#endif /* ((__ARM_ARCH_7M__ == 1U) || (__ARM_ARCH_8M__ == 1U)) */
-
-
-#if (__ARM_ARCH_8M__ == 1U)
-
-/**
- \brief Get Process Stack Pointer Limit
- \details Returns the current value of the Process Stack Pointer Limit (PSPLIM).
- \return PSPLIM Register value
- */
-__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_PSPLIM(void)
-{
- register uint32_t result;
-
- __ASM volatile ("MRS %0, psplim" : "=r" (result) );
- return(result);
-}
-
-
-#if (__ARM_FEATURE_CMSE == 3U) && (__ARM_ARCH_PROFILE == 'M') /* ToDo: ARMCC_V6: check predefined macro for mainline */
-/**
- \brief Get Process Stack Pointer Limit (non-secure)
- \details Returns the current value of the non-secure Process Stack Pointer Limit (PSPLIM) when in secure state.
- \return PSPLIM Register value
- */
-__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_PSPLIM_NS(void)
-{
- register uint32_t result;
-
- __ASM volatile ("MRS %0, psplim_ns" : "=r" (result) );
- return(result);
-}
-#endif
-
-
-/**
- \brief Set Process Stack Pointer Limit
- \details Assigns the given value to the Process Stack Pointer Limit (PSPLIM).
- \param [in] ProcStackPtrLimit Process Stack Pointer Limit value to set
- */
-__attribute__((always_inline)) __STATIC_INLINE void __set_PSPLIM(uint32_t ProcStackPtrLimit)
-{
- __ASM volatile ("MSR psplim, %0" : : "r" (ProcStackPtrLimit));
-}
-
-
-#if (__ARM_FEATURE_CMSE == 3U) && (__ARM_ARCH_PROFILE == 'M') /* ToDo: ARMCC_V6: check predefined macro for mainline */
-/**
- \brief Set Process Stack Pointer (non-secure)
- \details Assigns the given value to the non-secure Process Stack Pointer Limit (PSPLIM) when in secure state.
- \param [in] ProcStackPtrLimit Process Stack Pointer Limit value to set
- */
-__attribute__((always_inline)) __STATIC_INLINE void __TZ_set_PSPLIM_NS(uint32_t ProcStackPtrLimit)
-{
- __ASM volatile ("MSR psplim_ns, %0\n" : : "r" (ProcStackPtrLimit));
-}
-#endif
-
-
-/**
- \brief Get Main Stack Pointer Limit
- \details Returns the current value of the Main Stack Pointer Limit (MSPLIM).
- \return MSPLIM Register value
- */
-__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_MSPLIM(void)
-{
- register uint32_t result;
-
- __ASM volatile ("MRS %0, msplim" : "=r" (result) );
-
- return(result);
-}
-
-
-#if (__ARM_FEATURE_CMSE == 3U) && (__ARM_ARCH_PROFILE == 'M') /* ToDo: ARMCC_V6: check predefined macro for mainline */
-/**
- \brief Get Main Stack Pointer Limit (non-secure)
- \details Returns the current value of the non-secure Main Stack Pointer Limit(MSPLIM) when in secure state.
- \return MSPLIM Register value
- */
-__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_MSPLIM_NS(void)
-{
- register uint32_t result;
-
- __ASM volatile ("MRS %0, msplim_ns" : "=r" (result) );
- return(result);
-}
-#endif
-
-
-/**
- \brief Set Main Stack Pointer Limit
- \details Assigns the given value to the Main Stack Pointer Limit (MSPLIM).
- \param [in] MainStackPtrLimit Main Stack Pointer Limit value to set
- */
-__attribute__((always_inline)) __STATIC_INLINE void __set_MSPLIM(uint32_t MainStackPtrLimit)
-{
- __ASM volatile ("MSR msplim, %0" : : "r" (MainStackPtrLimit));
-}
-
-
-#if (__ARM_FEATURE_CMSE == 3U) && (__ARM_ARCH_PROFILE == 'M') /* ToDo: ARMCC_V6: check predefined macro for mainline */
-/**
- \brief Set Main Stack Pointer Limit (non-secure)
- \details Assigns the given value to the non-secure Main Stack Pointer Limit (MSPLIM) when in secure state.
- \param [in] MainStackPtrLimit Main Stack Pointer value to set
- */
-__attribute__((always_inline)) __STATIC_INLINE void __TZ_set_MSPLIM_NS(uint32_t MainStackPtrLimit)
-{
- __ASM volatile ("MSR msplim_ns, %0" : : "r" (MainStackPtrLimit));
-}
-#endif
-
-#endif /* (__ARM_ARCH_8M__ == 1U) */
-
-
-#if ((__ARM_ARCH_7EM__ == 1U) || (__ARM_ARCH_8M__ == 1U)) /* ToDo: ARMCC_V6: check if this is ok for cortex >=4 */
-
-/**
- \brief Get FPSCR
- \details eturns the current value of the Floating Point Status/Control register.
- \return Floating Point Status/Control register value
- */
-#define __get_FPSCR __builtin_arm_get_fpscr
-#if 0
-__attribute__((always_inline)) __STATIC_INLINE uint32_t __get_FPSCR(void)
-{
-#if (__FPU_PRESENT == 1U) && (__FPU_USED == 1U)
- uint32_t result;
-
- __ASM volatile (""); /* Empty asm statement works as a scheduling barrier */
- __ASM volatile ("VMRS %0, fpscr" : "=r" (result) );
- __ASM volatile ("");
- return(result);
-#else
- return(0);
-#endif
-}
-#endif
-
-#if (__ARM_FEATURE_CMSE == 3U)
-/**
- \brief Get FPSCR (non-secure)
- \details Returns the current value of the non-secure Floating Point Status/Control register when in secure state.
- \return Floating Point Status/Control register value
- */
-__attribute__((always_inline)) __STATIC_INLINE uint32_t __TZ_get_FPSCR_NS(void)
-{
-#if (__FPU_PRESENT == 1U) && (__FPU_USED == 1U)
- uint32_t result;
-
- __ASM volatile (""); /* Empty asm statement works as a scheduling barrier */
- __ASM volatile ("VMRS %0, fpscr_ns" : "=r" (result) );
- __ASM volatile ("");
- return(result);
-#else
- return(0);
-#endif
-}
-#endif
-
-
-/**
- \brief Set FPSCR
- \details Assigns the given value to the Floating Point Status/Control register.
- \param [in] fpscr Floating Point Status/Control value to set
- */
-#define __set_FPSCR __builtin_arm_set_fpscr
-#if 0
-__attribute__((always_inline)) __STATIC_INLINE void __set_FPSCR(uint32_t fpscr)
-{
-#if (__FPU_PRESENT == 1U) && (__FPU_USED == 1U)
- __ASM volatile (""); /* Empty asm statement works as a scheduling barrier */
- __ASM volatile ("VMSR fpscr, %0" : : "r" (fpscr) : "vfpcc");
- __ASM volatile ("");
-#endif
-}
-#endif
-
-#if (__ARM_FEATURE_CMSE == 3U)
-/**
- \brief Set FPSCR (non-secure)
- \details Assigns the given value to the non-secure Floating Point Status/Control register when in secure state.
- \param [in] fpscr Floating Point Status/Control value to set
- */
-__attribute__((always_inline)) __STATIC_INLINE void __TZ_set_FPSCR_NS(uint32_t fpscr)
-{
-#if (__FPU_PRESENT == 1U) && (__FPU_USED == 1U)
- __ASM volatile (""); /* Empty asm statement works as a scheduling barrier */
- __ASM volatile ("VMSR fpscr_ns, %0" : : "r" (fpscr) : "vfpcc");
- __ASM volatile ("");
-#endif
-}
-#endif
-
-#endif /* ((__ARM_ARCH_7EM__ == 1U) || (__ARM_ARCH_8M__ == 1U)) */
-
-
-
-/*@} end of CMSIS_Core_RegAccFunctions */
-
-
-/* ########################## Core Instruction Access ######################### */
-/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface
- Access to dedicated instructions
- @{
-*/
-
-/* Define macros for porting to both thumb1 and thumb2.
- * For thumb1, use low register (r0-r7), specified by constraint "l"
- * Otherwise, use general registers, specified by constraint "r" */
-#if defined (__thumb__) && !defined (__thumb2__)
-#define __CMSIS_GCC_OUT_REG(r) "=l" (r)
-#define __CMSIS_GCC_USE_REG(r) "l" (r)
-#else
-#define __CMSIS_GCC_OUT_REG(r) "=r" (r)
-#define __CMSIS_GCC_USE_REG(r) "r" (r)
-#endif
-
-/**
- \brief No Operation
- \details No Operation does nothing. This instruction can be used for code alignment purposes.
- */
-#define __NOP __builtin_arm_nop
-
-/**
- \brief Wait For Interrupt
- \details Wait For Interrupt is a hint instruction that suspends execution until one of a number of events occurs.
- */
-#define __WFI __builtin_arm_wfi
-
-
-/**
- \brief Wait For Event
- \details Wait For Event is a hint instruction that permits the processor to enter
- a low-power state until one of a number of events occurs.
- */
-#define __WFE __builtin_arm_wfe
-
-
-/**
- \brief Send Event
- \details Send Event is a hint instruction. It causes an event to be signaled to the CPU.
- */
-#define __SEV __builtin_arm_sev
-
-
-/**
- \brief Instruction Synchronization Barrier
- \details Instruction Synchronization Barrier flushes the pipeline in the processor,
- so that all instructions following the ISB are fetched from cache or memory,
- after the instruction has been completed.
- */
-#define __ISB() __builtin_arm_isb(0xF);
-
-/**
- \brief Data Synchronization Barrier
- \details Acts as a special kind of Data Memory Barrier.
- It completes when all explicit memory accesses before this instruction complete.
- */
-#define __DSB() __builtin_arm_dsb(0xF);
-
-
-/**
- \brief Data Memory Barrier
- \details Ensures the apparent order of the explicit memory operations before
- and after the instruction, without ensuring their completion.
- */
-#define __DMB() __builtin_arm_dmb(0xF);
-
-
-/**
- \brief Reverse byte order (32 bit)
- \details Reverses the byte order in integer value.
- \param [in] value Value to reverse
- \return Reversed value
- */
-#define __REV __builtin_bswap32
-
-
-/**
- \brief Reverse byte order (16 bit)
- \details Reverses the byte order in two unsigned short values.
- \param [in] value Value to reverse
- \return Reversed value
- */
-#define __REV16 __builtin_bswap16 /* ToDo: ARMCC_V6: check if __builtin_bswap16 could be used */
-#if 0
-__attribute__((always_inline)) __STATIC_INLINE uint32_t __REV16(uint32_t value)
-{
- uint32_t result;
-
- __ASM volatile ("rev16 %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) );
- return(result);
-}
-#endif
-
-
-/**
- \brief Reverse byte order in signed short value
- \details Reverses the byte order in a signed short value with sign extension to integer.
- \param [in] value Value to reverse
- \return Reversed value
- */
- /* ToDo: ARMCC_V6: check if __builtin_bswap16 could be used */
-__attribute__((always_inline)) __STATIC_INLINE int32_t __REVSH(int32_t value)
-{
- int32_t result;
-
- __ASM volatile ("revsh %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) );
- return(result);
-}
-
-
-/**
- \brief Rotate Right in unsigned value (32 bit)
- \details Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits.
- \param [in] op1 Value to rotate
- \param [in] op2 Number of Bits to rotate
- \return Rotated value
- */
-__attribute__((always_inline)) __STATIC_INLINE uint32_t __ROR(uint32_t op1, uint32_t op2)
-{
- return (op1 >> op2) | (op1 << (32U - op2));
-}
-
-
-/**
- \brief Breakpoint
- \details Causes the processor to enter Debug state.
- Debug tools can use this to investigate system state when the instruction at a particular address is reached.
- \param [in] value is ignored by the processor.
- If required, a debugger can use it to store additional information about the breakpoint.
- */
-#define __BKPT(value) __ASM volatile ("bkpt "#value)
-
-
-/**
- \brief Reverse bit order of value
- \details Reverses the bit order of the given value.
- \param [in] value Value to reverse
- \return Reversed value
- */
- /* ToDo: ARMCC_V6: check if __builtin_arm_rbit is supported */
-__attribute__((always_inline)) __STATIC_INLINE uint32_t __RBIT(uint32_t value)
-{
- uint32_t result;
-
-#if ((__ARM_ARCH_7M__ == 1U) || (__ARM_ARCH_7EM__ == 1U) || (__ARM_ARCH_8M__ == 1U)) /* ToDo: ARMCC_V6: check if this is ok for cortex >=3 */
- __ASM volatile ("rbit %0, %1" : "=r" (result) : "r" (value) );
-#else
- int32_t s = 4 /*sizeof(v)*/ * 8 - 1; /* extra shift needed at end */
-
- result = value; /* r will be reversed bits of v; first get LSB of v */
- for (value >>= 1U; value; value >>= 1U)
- {
- result <<= 1U;
- result |= value & 1U;
- s--;
- }
- result <<= s; /* shift when v's highest bits are zero */
-#endif
- return(result);
-}
-
-
-/**
- \brief Count leading zeros
- \details Counts the number of leading zeros of a data value.
- \param [in] value Value to count the leading zeros
- \return number of leading zeros in value
- */
-#define __CLZ __builtin_clz
-
-
-#if ((__ARM_ARCH_7M__ == 1U) || (__ARM_ARCH_7EM__ == 1U) || (__ARM_ARCH_8M__ == 1U)) /* ToDo: ARMCC_V6: check if this is ok for cortex >=3 */
-
-/**
- \brief LDR Exclusive (8 bit)
- \details Executes a exclusive LDR instruction for 8 bit value.
- \param [in] ptr Pointer to data
- \return value of type uint8_t at (*ptr)
- */
-#define __LDREXB (uint8_t)__builtin_arm_ldrex
-
-
-/**
- \brief LDR Exclusive (16 bit)
- \details Executes a exclusive LDR instruction for 16 bit values.
- \param [in] ptr Pointer to data
- \return value of type uint16_t at (*ptr)
- */
-#define __LDREXH (uint16_t)__builtin_arm_ldrex
-
-
-/**
- \brief LDR Exclusive (32 bit)
- \details Executes a exclusive LDR instruction for 32 bit values.
- \param [in] ptr Pointer to data
- \return value of type uint32_t at (*ptr)
- */
-#define __LDREXW (uint32_t)__builtin_arm_ldrex
-
-
-/**
- \brief STR Exclusive (8 bit)
- \details Executes a exclusive STR instruction for 8 bit values.
- \param [in] value Value to store
- \param [in] ptr Pointer to location
- \return 0 Function succeeded
- \return 1 Function failed
- */
-#define __STREXB (uint32_t)__builtin_arm_strex
-
-
-/**
- \brief STR Exclusive (16 bit)
- \details Executes a exclusive STR instruction for 16 bit values.
- \param [in] value Value to store
- \param [in] ptr Pointer to location
- \return 0 Function succeeded
- \return 1 Function failed
- */
-#define __STREXH (uint32_t)__builtin_arm_strex
-
-
-/**
- \brief STR Exclusive (32 bit)
- \details Executes a exclusive STR instruction for 32 bit values.
- \param [in] value Value to store
- \param [in] ptr Pointer to location
- \return 0 Function succeeded
- \return 1 Function failed
- */
-#define __STREXW (uint32_t)__builtin_arm_strex
-
-
-/**
- \brief Remove the exclusive lock
- \details Removes the exclusive lock which is created by LDREX.
- */
-#define __CLREX __builtin_arm_clrex
-
-
-/**
- \brief Signed Saturate
- \details Saturates a signed value.
- \param [in] value Value to be saturated
- \param [in] sat Bit position to saturate to (1..32)
- \return Saturated value
- */
-/*#define __SSAT __builtin_arm_ssat*/
-#define __SSAT(ARG1,ARG2) \
-({ \
- int32_t __RES, __ARG1 = (ARG1); \
- __ASM ("ssat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \
- __RES; \
- })
-
-
-/**
- \brief Unsigned Saturate
- \details Saturates an unsigned value.
- \param [in] value Value to be saturated
- \param [in] sat Bit position to saturate to (0..31)
- \return Saturated value
- */
-#define __USAT __builtin_arm_usat
-#if 0
-#define __USAT(ARG1,ARG2) \
-({ \
- uint32_t __RES, __ARG1 = (ARG1); \
- __ASM ("usat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \
- __RES; \
- })
-#endif
-
-
-/**
- \brief Rotate Right with Extend (32 bit)
- \details Moves each bit of a bitstring right by one bit.
- The carry input is shifted in at the left end of the bitstring.
- \param [in] value Value to rotate
- \return Rotated value
- */
-__attribute__((always_inline)) __STATIC_INLINE uint32_t __RRX(uint32_t value)
-{
- uint32_t result;
-
- __ASM volatile ("rrx %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) );
- return(result);
-}
-
-
-/**
- \brief LDRT Unprivileged (8 bit)
- \details Executes a Unprivileged LDRT instruction for 8 bit value.
- \param [in] ptr Pointer to data
- \return value of type uint8_t at (*ptr)
- */
-__attribute__((always_inline)) __STATIC_INLINE uint8_t __LDRBT(volatile uint8_t *ptr)
-{
- uint32_t result;
-
- __ASM volatile ("ldrbt %0, %1" : "=r" (result) : "Q" (*ptr) );
- return ((uint8_t) result); /* Add explicit type cast here */
-}
-
-
-/**
- \brief LDRT Unprivileged (16 bit)
- \details Executes a Unprivileged LDRT instruction for 16 bit values.
- \param [in] ptr Pointer to data
- \return value of type uint16_t at (*ptr)
- */
-__attribute__((always_inline)) __STATIC_INLINE uint16_t __LDRHT(volatile uint16_t *ptr)
-{
- uint32_t result;
-
- __ASM volatile ("ldrht %0, %1" : "=r" (result) : "Q" (*ptr) );
- return ((uint16_t) result); /* Add explicit type cast here */
-}
-
-
-/**
- \brief LDRT Unprivileged (32 bit)
- \details Executes a Unprivileged LDRT instruction for 32 bit values.
- \param [in] ptr Pointer to data
- \return value of type uint32_t at (*ptr)
- */
-__attribute__((always_inline)) __STATIC_INLINE uint32_t __LDRT(volatile uint32_t *ptr)
-{
- uint32_t result;
-
- __ASM volatile ("ldrt %0, %1" : "=r" (result) : "Q" (*ptr) );
- return(result);
-}
-
-
-/**
- \brief STRT Unprivileged (8 bit)
- \details Executes a Unprivileged STRT instruction for 8 bit values.
- \param [in] value Value to store
- \param [in] ptr Pointer to location
- */
-__attribute__((always_inline)) __STATIC_INLINE void __STRBT(uint8_t value, volatile uint8_t *ptr)
-{
- __ASM volatile ("strbt %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) );
-}
-
-
-/**
- \brief STRT Unprivileged (16 bit)
- \details Executes a Unprivileged STRT instruction for 16 bit values.
- \param [in] value Value to store
- \param [in] ptr Pointer to location
- */
-__attribute__((always_inline)) __STATIC_INLINE void __STRHT(uint16_t value, volatile uint16_t *ptr)
-{
- __ASM volatile ("strht %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) );
-}
-
-
-/**
- \brief STRT Unprivileged (32 bit)
- \details Executes a Unprivileged STRT instruction for 32 bit values.
- \param [in] value Value to store
- \param [in] ptr Pointer to location
- */
-__attribute__((always_inline)) __STATIC_INLINE void __STRT(uint32_t value, volatile uint32_t *ptr)
-{
- __ASM volatile ("strt %1, %0" : "=Q" (*ptr) : "r" (value) );
-}
-
-#endif /* ((__ARM_ARCH_7M__ == 1U) || (__ARM_ARCH_7EM__ == 1U) || (__ARM_ARCH_8M__ == 1U)) */
-
-
-#if (__ARM_ARCH_8M__ == 1U)
-
-/**
- \brief Load-Acquire (8 bit)
- \details Executes a LDAB instruction for 8 bit value.
- \param [in] ptr Pointer to data
- \return value of type uint8_t at (*ptr)
- */
-__attribute__((always_inline)) __STATIC_INLINE uint8_t __LDAB(volatile uint8_t *ptr)
-{
- uint32_t result;
-
- __ASM volatile ("ldab %0, %1" : "=r" (result) : "Q" (*ptr) );
- return ((uint8_t) result);
-}
-
-
-/**
- \brief Load-Acquire (16 bit)
- \details Executes a LDAH instruction for 16 bit values.
- \param [in] ptr Pointer to data
- \return value of type uint16_t at (*ptr)
- */
-__attribute__((always_inline)) __STATIC_INLINE uint16_t __LDAH(volatile uint16_t *ptr)
-{
- uint32_t result;
-
- __ASM volatile ("ldah %0, %1" : "=r" (result) : "Q" (*ptr) );
- return ((uint16_t) result);
-}
-
-
-/**
- \brief Load-Acquire (32 bit)
- \details Executes a LDA instruction for 32 bit values.
- \param [in] ptr Pointer to data
- \return value of type uint32_t at (*ptr)
- */
-__attribute__((always_inline)) __STATIC_INLINE uint32_t __LDA(volatile uint32_t *ptr)
-{
- uint32_t result;
-
- __ASM volatile ("lda %0, %1" : "=r" (result) : "Q" (*ptr) );
- return(result);
-}
-
-
-/**
- \brief Store-Release (8 bit)
- \details Executes a STLB instruction for 8 bit values.
- \param [in] value Value to store
- \param [in] ptr Pointer to location
- */
-__attribute__((always_inline)) __STATIC_INLINE void __STLB(uint8_t value, volatile uint8_t *ptr)
-{
- __ASM volatile ("stlb %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) );
-}
-
-
-/**
- \brief Store-Release (16 bit)
- \details Executes a STLH instruction for 16 bit values.
- \param [in] value Value to store
- \param [in] ptr Pointer to location
- */
-__attribute__((always_inline)) __STATIC_INLINE void __STLH(uint16_t value, volatile uint16_t *ptr)
-{
- __ASM volatile ("stlh %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) );
-}
-
-
-/**
- \brief Store-Release (32 bit)
- \details Executes a STL instruction for 32 bit values.
- \param [in] value Value to store
- \param [in] ptr Pointer to location
- */
-__attribute__((always_inline)) __STATIC_INLINE void __STL(uint32_t value, volatile uint32_t *ptr)
-{
- __ASM volatile ("stl %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) );
-}
-
-
-/**
- \brief Load-Acquire Exclusive (8 bit)
- \details Executes a LDAB exclusive instruction for 8 bit value.
- \param [in] ptr Pointer to data
- \return value of type uint8_t at (*ptr)
- */
-#define __LDAEXB (uint8_t)__builtin_arm_ldaex
-
-
-/**
- \brief Load-Acquire Exclusive (16 bit)
- \details Executes a LDAH exclusive instruction for 16 bit values.
- \param [in] ptr Pointer to data
- \return value of type uint16_t at (*ptr)
- */
-#define __LDAEXH (uint16_t)__builtin_arm_ldaex
-
-
-/**
- \brief Load-Acquire Exclusive (32 bit)
- \details Executes a LDA exclusive instruction for 32 bit values.
- \param [in] ptr Pointer to data
- \return value of type uint32_t at (*ptr)
- */
-#define __LDAEX (uint32_t)__builtin_arm_ldaex
-
-
-/**
- \brief Store-Release Exclusive (8 bit)
- \details Executes a STLB exclusive instruction for 8 bit values.
- \param [in] value Value to store
- \param [in] ptr Pointer to location
- \return 0 Function succeeded
- \return 1 Function failed
- */
-#define __STLEXB (uint32_t)__builtin_arm_stlex
-
-
-/**
- \brief Store-Release Exclusive (16 bit)
- \details Executes a STLH exclusive instruction for 16 bit values.
- \param [in] value Value to store
- \param [in] ptr Pointer to location
- \return 0 Function succeeded
- \return 1 Function failed
- */
-#define __STLEXH (uint32_t)__builtin_arm_stlex
-
-
-/**
- \brief Store-Release Exclusive (32 bit)
- \details Executes a STL exclusive instruction for 32 bit values.
- \param [in] value Value to store
- \param [in] ptr Pointer to location
- \return 0 Function succeeded
- \return 1 Function failed
- */
-#define __STLEX (uint32_t)__builtin_arm_stlex
-
-#endif /* (__ARM_ARCH_8M__ == 1U) */
-
-/*@}*/ /* end of group CMSIS_Core_InstructionInterface */
-
-
-/* ################### Compiler specific Intrinsics ########################### */
-/** \defgroup CMSIS_SIMD_intrinsics CMSIS SIMD Intrinsics
- Access to dedicated SIMD instructions
- @{
-*/
-
-#if (__ARM_FEATURE_DSP == 1U) /* ToDo: ARMCC_V6: This should be ARCH >= ARMv7-M + SIMD */
-
-__attribute__((always_inline)) __STATIC_INLINE uint32_t __SADD8(uint32_t op1, uint32_t op2)
-{
- uint32_t result;
-
- __ASM volatile ("sadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
- return(result);
-}
-
-__attribute__((always_inline)) __STATIC_INLINE uint32_t __QADD8(uint32_t op1, uint32_t op2)
-{
- uint32_t result;
-
- __ASM volatile ("qadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
- return(result);
-}
-
-__attribute__((always_inline)) __STATIC_INLINE uint32_t __SHADD8(uint32_t op1, uint32_t op2)
-{
- uint32_t result;
-
- __ASM volatile ("shadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
- return(result);
-}
-
-__attribute__((always_inline)) __STATIC_INLINE uint32_t __UADD8(uint32_t op1, uint32_t op2)
-{
- uint32_t result;
-
- __ASM volatile ("uadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
- return(result);
-}
-
-__attribute__((always_inline)) __STATIC_INLINE uint32_t __UQADD8(uint32_t op1, uint32_t op2)
-{
- uint32_t result;
-
- __ASM volatile ("uqadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
- return(result);
-}
-
-__attribute__((always_inline)) __STATIC_INLINE uint32_t __UHADD8(uint32_t op1, uint32_t op2)
-{
- uint32_t result;
-
- __ASM volatile ("uhadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
- return(result);
-}
-
-
-__attribute__((always_inline)) __STATIC_INLINE uint32_t __SSUB8(uint32_t op1, uint32_t op2)
-{
- uint32_t result;
-
- __ASM volatile ("ssub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
- return(result);
-}
-
-__attribute__((always_inline)) __STATIC_INLINE uint32_t __QSUB8(uint32_t op1, uint32_t op2)
-{
- uint32_t result;
-
- __ASM volatile ("qsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
- return(result);
-}
-
-__attribute__((always_inline)) __STATIC_INLINE uint32_t __SHSUB8(uint32_t op1, uint32_t op2)
-{
- uint32_t result;
-
- __ASM volatile ("shsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
- return(result);
-}
-
-__attribute__((always_inline)) __STATIC_INLINE uint32_t __USUB8(uint32_t op1, uint32_t op2)
-{
- uint32_t result;
-
- __ASM volatile ("usub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
- return(result);
-}
-
-__attribute__((always_inline)) __STATIC_INLINE uint32_t __UQSUB8(uint32_t op1, uint32_t op2)
-{
- uint32_t result;
-
- __ASM volatile ("uqsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
- return(result);
-}
-
-__attribute__((always_inline)) __STATIC_INLINE uint32_t __UHSUB8(uint32_t op1, uint32_t op2)
-{
- uint32_t result;
-
- __ASM volatile ("uhsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
- return(result);
-}
-
-
-__attribute__((always_inline)) __STATIC_INLINE uint32_t __SADD16(uint32_t op1, uint32_t op2)
-{
- uint32_t result;
-
- __ASM volatile ("sadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
- return(result);
-}
-
-__attribute__((always_inline)) __STATIC_INLINE uint32_t __QADD16(uint32_t op1, uint32_t op2)
-{
- uint32_t result;
-
- __ASM volatile ("qadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
- return(result);
-}
-
-__attribute__((always_inline)) __STATIC_INLINE uint32_t __SHADD16(uint32_t op1, uint32_t op2)
-{
- uint32_t result;
-
- __ASM volatile ("shadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
- return(result);
-}
-
-__attribute__((always_inline)) __STATIC_INLINE uint32_t __UADD16(uint32_t op1, uint32_t op2)
-{
- uint32_t result;
-
- __ASM volatile ("uadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
- return(result);
-}
-
-__attribute__((always_inline)) __STATIC_INLINE uint32_t __UQADD16(uint32_t op1, uint32_t op2)
-{
- uint32_t result;
-
- __ASM volatile ("uqadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
- return(result);
-}
-
-__attribute__((always_inline)) __STATIC_INLINE uint32_t __UHADD16(uint32_t op1, uint32_t op2)
-{
- uint32_t result;
-
- __ASM volatile ("uhadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
- return(result);
-}
-
-__attribute__((always_inline)) __STATIC_INLINE uint32_t __SSUB16(uint32_t op1, uint32_t op2)
-{
- uint32_t result;
-
- __ASM volatile ("ssub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
- return(result);
-}
-
-__attribute__((always_inline)) __STATIC_INLINE uint32_t __QSUB16(uint32_t op1, uint32_t op2)
-{
- uint32_t result;
-
- __ASM volatile ("qsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
- return(result);
-}
-
-__attribute__((always_inline)) __STATIC_INLINE uint32_t __SHSUB16(uint32_t op1, uint32_t op2)
-{
- uint32_t result;
-
- __ASM volatile ("shsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
- return(result);
-}
-
-__attribute__((always_inline)) __STATIC_INLINE uint32_t __USUB16(uint32_t op1, uint32_t op2)
-{
- uint32_t result;
-
- __ASM volatile ("usub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
- return(result);
-}
-
-__attribute__((always_inline)) __STATIC_INLINE uint32_t __UQSUB16(uint32_t op1, uint32_t op2)
-{
- uint32_t result;
-
- __ASM volatile ("uqsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
- return(result);
-}
-
-__attribute__((always_inline)) __STATIC_INLINE uint32_t __UHSUB16(uint32_t op1, uint32_t op2)
-{
- uint32_t result;
-
- __ASM volatile ("uhsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
- return(result);
-}
-
-__attribute__((always_inline)) __STATIC_INLINE uint32_t __SASX(uint32_t op1, uint32_t op2)
-{
- uint32_t result;
-
- __ASM volatile ("sasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
- return(result);
-}
-
-__attribute__((always_inline)) __STATIC_INLINE uint32_t __QASX(uint32_t op1, uint32_t op2)
-{
- uint32_t result;
-
- __ASM volatile ("qasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
- return(result);
-}
-
-__attribute__((always_inline)) __STATIC_INLINE uint32_t __SHASX(uint32_t op1, uint32_t op2)
-{
- uint32_t result;
-
- __ASM volatile ("shasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
- return(result);
-}
-
-__attribute__((always_inline)) __STATIC_INLINE uint32_t __UASX(uint32_t op1, uint32_t op2)
-{
- uint32_t result;
-
- __ASM volatile ("uasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
- return(result);
-}
-
-__attribute__((always_inline)) __STATIC_INLINE uint32_t __UQASX(uint32_t op1, uint32_t op2)
-{
- uint32_t result;
-
- __ASM volatile ("uqasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
- return(result);
-}
-
-__attribute__((always_inline)) __STATIC_INLINE uint32_t __UHASX(uint32_t op1, uint32_t op2)
-{
- uint32_t result;
-
- __ASM volatile ("uhasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
- return(result);
-}
-
-__attribute__((always_inline)) __STATIC_INLINE uint32_t __SSAX(uint32_t op1, uint32_t op2)
-{
- uint32_t result;
-
- __ASM volatile ("ssax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
- return(result);
-}
-
-__attribute__((always_inline)) __STATIC_INLINE uint32_t __QSAX(uint32_t op1, uint32_t op2)
-{
- uint32_t result;
-
- __ASM volatile ("qsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
- return(result);
-}
-
-__attribute__((always_inline)) __STATIC_INLINE uint32_t __SHSAX(uint32_t op1, uint32_t op2)
-{
- uint32_t result;
-
- __ASM volatile ("shsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
- return(result);
-}
-
-__attribute__((always_inline)) __STATIC_INLINE uint32_t __USAX(uint32_t op1, uint32_t op2)
-{
- uint32_t result;
-
- __ASM volatile ("usax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
- return(result);
-}
-
-__attribute__((always_inline)) __STATIC_INLINE uint32_t __UQSAX(uint32_t op1, uint32_t op2)
-{
- uint32_t result;
-
- __ASM volatile ("uqsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
- return(result);
-}
-
-__attribute__((always_inline)) __STATIC_INLINE uint32_t __UHSAX(uint32_t op1, uint32_t op2)
-{
- uint32_t result;
-
- __ASM volatile ("uhsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
- return(result);
-}
-
-__attribute__((always_inline)) __STATIC_INLINE uint32_t __USAD8(uint32_t op1, uint32_t op2)
-{
- uint32_t result;
-
- __ASM volatile ("usad8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
- return(result);
-}
-
-__attribute__((always_inline)) __STATIC_INLINE uint32_t __USADA8(uint32_t op1, uint32_t op2, uint32_t op3)
-{
- uint32_t result;
-
- __ASM volatile ("usada8 %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) );
- return(result);
-}
-
-#define __SSAT16(ARG1,ARG2) \
-({ \
- uint32_t __RES, __ARG1 = (ARG1); \
- __ASM ("ssat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \
- __RES; \
- })
-
-#define __USAT16(ARG1,ARG2) \
-({ \
- uint32_t __RES, __ARG1 = (ARG1); \
- __ASM ("usat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \
- __RES; \
- })
-
-__attribute__((always_inline)) __STATIC_INLINE uint32_t __UXTB16(uint32_t op1)
-{
- uint32_t result;
-
- __ASM volatile ("uxtb16 %0, %1" : "=r" (result) : "r" (op1));
- return(result);
-}
-
-__attribute__((always_inline)) __STATIC_INLINE uint32_t __UXTAB16(uint32_t op1, uint32_t op2)
-{
- uint32_t result;
-
- __ASM volatile ("uxtab16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
- return(result);
-}
-
-__attribute__((always_inline)) __STATIC_INLINE uint32_t __SXTB16(uint32_t op1)
-{
- uint32_t result;
-
- __ASM volatile ("sxtb16 %0, %1" : "=r" (result) : "r" (op1));
- return(result);
-}
-
-__attribute__((always_inline)) __STATIC_INLINE uint32_t __SXTAB16(uint32_t op1, uint32_t op2)
-{
- uint32_t result;
-
- __ASM volatile ("sxtab16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
- return(result);
-}
-
-__attribute__((always_inline)) __STATIC_INLINE uint32_t __SMUAD (uint32_t op1, uint32_t op2)
-{
- uint32_t result;
-
- __ASM volatile ("smuad %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
- return(result);
-}
-
-__attribute__((always_inline)) __STATIC_INLINE uint32_t __SMUADX (uint32_t op1, uint32_t op2)
-{
- uint32_t result;
-
- __ASM volatile ("smuadx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
- return(result);
-}
-
-__attribute__((always_inline)) __STATIC_INLINE uint32_t __SMLAD (uint32_t op1, uint32_t op2, uint32_t op3)
-{
- uint32_t result;
-
- __ASM volatile ("smlad %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) );
- return(result);
-}
-
-__attribute__((always_inline)) __STATIC_INLINE uint32_t __SMLADX (uint32_t op1, uint32_t op2, uint32_t op3)
-{
- uint32_t result;
-
- __ASM volatile ("smladx %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) );
- return(result);
-}
-
-__attribute__((always_inline)) __STATIC_INLINE uint64_t __SMLALD (uint32_t op1, uint32_t op2, uint64_t acc)
-{
- union llreg_u{
- uint32_t w32[2];
- uint64_t w64;
- } llr;
- llr.w64 = acc;
-
-#ifndef __ARMEB__ /* Little endian */
- __ASM volatile ("smlald %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) );
-#else /* Big endian */
- __ASM volatile ("smlald %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) );
-#endif
-
- return(llr.w64);
-}
-
-__attribute__((always_inline)) __STATIC_INLINE uint64_t __SMLALDX (uint32_t op1, uint32_t op2, uint64_t acc)
-{
- union llreg_u{
- uint32_t w32[2];
- uint64_t w64;
- } llr;
- llr.w64 = acc;
-
-#ifndef __ARMEB__ /* Little endian */
- __ASM volatile ("smlaldx %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) );
-#else /* Big endian */
- __ASM volatile ("smlaldx %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) );
-#endif
-
- return(llr.w64);
-}
-
-__attribute__((always_inline)) __STATIC_INLINE uint32_t __SMUSD (uint32_t op1, uint32_t op2)
-{
- uint32_t result;
-
- __ASM volatile ("smusd %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
- return(result);
-}
-
-__attribute__((always_inline)) __STATIC_INLINE uint32_t __SMUSDX (uint32_t op1, uint32_t op2)
-{
- uint32_t result;
-
- __ASM volatile ("smusdx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
- return(result);
-}
-
-__attribute__((always_inline)) __STATIC_INLINE uint32_t __SMLSD (uint32_t op1, uint32_t op2, uint32_t op3)
-{
- uint32_t result;
-
- __ASM volatile ("smlsd %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) );
- return(result);
-}
-
-__attribute__((always_inline)) __STATIC_INLINE uint32_t __SMLSDX (uint32_t op1, uint32_t op2, uint32_t op3)
-{
- uint32_t result;
-
- __ASM volatile ("smlsdx %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) );
- return(result);
-}
-
-__attribute__((always_inline)) __STATIC_INLINE uint64_t __SMLSLD (uint32_t op1, uint32_t op2, uint64_t acc)
-{
- union llreg_u{
- uint32_t w32[2];
- uint64_t w64;
- } llr;
- llr.w64 = acc;
-
-#ifndef __ARMEB__ /* Little endian */
- __ASM volatile ("smlsld %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) );
-#else /* Big endian */
- __ASM volatile ("smlsld %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) );
-#endif
-
- return(llr.w64);
-}
-
-__attribute__((always_inline)) __STATIC_INLINE uint64_t __SMLSLDX (uint32_t op1, uint32_t op2, uint64_t acc)
-{
- union llreg_u{
- uint32_t w32[2];
- uint64_t w64;
- } llr;
- llr.w64 = acc;
-
-#ifndef __ARMEB__ /* Little endian */
- __ASM volatile ("smlsldx %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) );
-#else /* Big endian */
- __ASM volatile ("smlsldx %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) );
-#endif
-
- return(llr.w64);
-}
-
-__attribute__((always_inline)) __STATIC_INLINE uint32_t __SEL (uint32_t op1, uint32_t op2)
-{
- uint32_t result;
-
- __ASM volatile ("sel %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
- return(result);
-}
-
-__attribute__((always_inline)) __STATIC_INLINE int32_t __QADD( int32_t op1, int32_t op2)
-{
- int32_t result;
-
- __ASM volatile ("qadd %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
- return(result);
-}
-
-__attribute__((always_inline)) __STATIC_INLINE int32_t __QSUB( int32_t op1, int32_t op2)
-{
- int32_t result;
-
- __ASM volatile ("qsub %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
- return(result);
-}
-
-#define __PKHBT(ARG1,ARG2,ARG3) \
-({ \
- uint32_t __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \
- __ASM ("pkhbt %0, %1, %2, lsl %3" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2), "I" (ARG3) ); \
- __RES; \
- })
-
-#define __PKHTB(ARG1,ARG2,ARG3) \
-({ \
- uint32_t __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \
- if (ARG3 == 0) \
- __ASM ("pkhtb %0, %1, %2" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2) ); \
- else \
- __ASM ("pkhtb %0, %1, %2, asr %3" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2), "I" (ARG3) ); \
- __RES; \
- })
-
-__attribute__((always_inline)) __STATIC_INLINE uint32_t __SMMLA (int32_t op1, int32_t op2, int32_t op3)
-{
- int32_t result;
-
- __ASM volatile ("smmla %0, %1, %2, %3" : "=r" (result): "r" (op1), "r" (op2), "r" (op3) );
- return(result);
-}
-
-#endif /* (__ARM_FEATURE_DSP == 1U) */
-/*@} end of group CMSIS_SIMD_intrinsics */
-
-
-#endif /* __CMSIS_ARMCC_V6_H */
diff --git a/lib/cmsis/inc/cmsis_armclang.h b/lib/cmsis/inc/cmsis_armclang.h
new file mode 100644
index 0000000000..6a8867d574
--- /dev/null
+++ b/lib/cmsis/inc/cmsis_armclang.h
@@ -0,0 +1,1420 @@
+/**************************************************************************//**
+ * @file cmsis_armclang.h
+ * @brief CMSIS compiler armclang (Arm Compiler 6) header file
+ * @version V5.1.0
+ * @date 14. March 2019
+ ******************************************************************************/
+/*
+ * Copyright (c) 2009-2019 Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*lint -esym(9058, IRQn)*/ /* disable MISRA 2012 Rule 2.4 for IRQn */
+
+#ifndef __CMSIS_ARMCLANG_H
+#define __CMSIS_ARMCLANG_H
+
+#pragma clang system_header /* treat file as system include file */
+
+#ifndef __ARM_COMPAT_H
+#include /* Compatibility header for Arm Compiler 5 intrinsics */
+#endif
+
+/* CMSIS compiler specific defines */
+#ifndef __ASM
+ #define __ASM __asm
+#endif
+#ifndef __INLINE
+ #define __INLINE __inline
+#endif
+#ifndef __STATIC_INLINE
+ #define __STATIC_INLINE static __inline
+#endif
+#ifndef __STATIC_FORCEINLINE
+ #define __STATIC_FORCEINLINE __attribute__((always_inline)) static __inline
+#endif
+#ifndef __NO_RETURN
+ #define __NO_RETURN __attribute__((__noreturn__))
+#endif
+#ifndef __USED
+ #define __USED __attribute__((used))
+#endif
+#ifndef __WEAK
+ #define __WEAK __attribute__((weak))
+#endif
+#ifndef __PACKED
+ #define __PACKED __attribute__((packed, aligned(1)))
+#endif
+#ifndef __PACKED_STRUCT
+ #define __PACKED_STRUCT struct __attribute__((packed, aligned(1)))
+#endif
+#ifndef __PACKED_UNION
+ #define __PACKED_UNION union __attribute__((packed, aligned(1)))
+#endif
+#ifndef __UNALIGNED_UINT32 /* deprecated */
+ #pragma clang diagnostic push
+ #pragma clang diagnostic ignored "-Wpacked"
+/*lint -esym(9058, T_UINT32)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT32 */
+ struct __attribute__((packed)) T_UINT32 { uint32_t v; };
+ #pragma clang diagnostic pop
+ #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v)
+#endif
+#ifndef __UNALIGNED_UINT16_WRITE
+ #pragma clang diagnostic push
+ #pragma clang diagnostic ignored "-Wpacked"
+/*lint -esym(9058, T_UINT16_WRITE)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT16_WRITE */
+ __PACKED_STRUCT T_UINT16_WRITE { uint16_t v; };
+ #pragma clang diagnostic pop
+ #define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val))
+#endif
+#ifndef __UNALIGNED_UINT16_READ
+ #pragma clang diagnostic push
+ #pragma clang diagnostic ignored "-Wpacked"
+/*lint -esym(9058, T_UINT16_READ)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT16_READ */
+ __PACKED_STRUCT T_UINT16_READ { uint16_t v; };
+ #pragma clang diagnostic pop
+ #define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v)
+#endif
+#ifndef __UNALIGNED_UINT32_WRITE
+ #pragma clang diagnostic push
+ #pragma clang diagnostic ignored "-Wpacked"
+/*lint -esym(9058, T_UINT32_WRITE)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT32_WRITE */
+ __PACKED_STRUCT T_UINT32_WRITE { uint32_t v; };
+ #pragma clang diagnostic pop
+ #define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val))
+#endif
+#ifndef __UNALIGNED_UINT32_READ
+ #pragma clang diagnostic push
+ #pragma clang diagnostic ignored "-Wpacked"
+/*lint -esym(9058, T_UINT32_READ)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT32_READ */
+ __PACKED_STRUCT T_UINT32_READ { uint32_t v; };
+ #pragma clang diagnostic pop
+ #define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v)
+#endif
+#ifndef __ALIGNED
+ #define __ALIGNED(x) __attribute__((aligned(x)))
+#endif
+#ifndef __RESTRICT
+ #define __RESTRICT __restrict
+#endif
+
+
+/* ########################### Core Function Access ########################### */
+/** \ingroup CMSIS_Core_FunctionInterface
+ \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions
+ @{
+ */
+
+/**
+ \brief Enable IRQ Interrupts
+ \details Enables IRQ interrupts by clearing the I-bit in the CPSR.
+ Can only be executed in Privileged modes.
+ */
+/* intrinsic void __enable_irq(); see arm_compat.h */
+
+
+/**
+ \brief Disable IRQ Interrupts
+ \details Disables IRQ interrupts by setting the I-bit in the CPSR.
+ Can only be executed in Privileged modes.
+ */
+/* intrinsic void __disable_irq(); see arm_compat.h */
+
+
+/**
+ \brief Get Control Register
+ \details Returns the content of the Control Register.
+ \return Control Register value
+ */
+__STATIC_FORCEINLINE uint32_t __get_CONTROL(void)
+{
+ uint32_t result;
+
+ __ASM volatile ("MRS %0, control" : "=r" (result) );
+ return(result);
+}
+
+
+#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3))
+/**
+ \brief Get Control Register (non-secure)
+ \details Returns the content of the non-secure Control Register when in secure mode.
+ \return non-secure Control Register value
+ */
+__STATIC_FORCEINLINE uint32_t __TZ_get_CONTROL_NS(void)
+{
+ uint32_t result;
+
+ __ASM volatile ("MRS %0, control_ns" : "=r" (result) );
+ return(result);
+}
+#endif
+
+
+/**
+ \brief Set Control Register
+ \details Writes the given value to the Control Register.
+ \param [in] control Control Register value to set
+ */
+__STATIC_FORCEINLINE void __set_CONTROL(uint32_t control)
+{
+ __ASM volatile ("MSR control, %0" : : "r" (control) : "memory");
+}
+
+
+#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3))
+/**
+ \brief Set Control Register (non-secure)
+ \details Writes the given value to the non-secure Control Register when in secure state.
+ \param [in] control Control Register value to set
+ */
+__STATIC_FORCEINLINE void __TZ_set_CONTROL_NS(uint32_t control)
+{
+ __ASM volatile ("MSR control_ns, %0" : : "r" (control) : "memory");
+}
+#endif
+
+
+/**
+ \brief Get IPSR Register
+ \details Returns the content of the IPSR Register.
+ \return IPSR Register value
+ */
+__STATIC_FORCEINLINE uint32_t __get_IPSR(void)
+{
+ uint32_t result;
+
+ __ASM volatile ("MRS %0, ipsr" : "=r" (result) );
+ return(result);
+}
+
+
+/**
+ \brief Get APSR Register
+ \details Returns the content of the APSR Register.
+ \return APSR Register value
+ */
+__STATIC_FORCEINLINE uint32_t __get_APSR(void)
+{
+ uint32_t result;
+
+ __ASM volatile ("MRS %0, apsr" : "=r" (result) );
+ return(result);
+}
+
+
+/**
+ \brief Get xPSR Register
+ \details Returns the content of the xPSR Register.
+ \return xPSR Register value
+ */
+__STATIC_FORCEINLINE uint32_t __get_xPSR(void)
+{
+ uint32_t result;
+
+ __ASM volatile ("MRS %0, xpsr" : "=r" (result) );
+ return(result);
+}
+
+
+/**
+ \brief Get Process Stack Pointer
+ \details Returns the current value of the Process Stack Pointer (PSP).
+ \return PSP Register value
+ */
+__STATIC_FORCEINLINE uint32_t __get_PSP(void)
+{
+ uint32_t result;
+
+ __ASM volatile ("MRS %0, psp" : "=r" (result) );
+ return(result);
+}
+
+
+#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3))
+/**
+ \brief Get Process Stack Pointer (non-secure)
+ \details Returns the current value of the non-secure Process Stack Pointer (PSP) when in secure state.
+ \return PSP Register value
+ */
+__STATIC_FORCEINLINE uint32_t __TZ_get_PSP_NS(void)
+{
+ uint32_t result;
+
+ __ASM volatile ("MRS %0, psp_ns" : "=r" (result) );
+ return(result);
+}
+#endif
+
+
+/**
+ \brief Set Process Stack Pointer
+ \details Assigns the given value to the Process Stack Pointer (PSP).
+ \param [in] topOfProcStack Process Stack Pointer value to set
+ */
+__STATIC_FORCEINLINE void __set_PSP(uint32_t topOfProcStack)
+{
+ __ASM volatile ("MSR psp, %0" : : "r" (topOfProcStack) : );
+}
+
+
+#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3))
+/**
+ \brief Set Process Stack Pointer (non-secure)
+ \details Assigns the given value to the non-secure Process Stack Pointer (PSP) when in secure state.
+ \param [in] topOfProcStack Process Stack Pointer value to set
+ */
+__STATIC_FORCEINLINE void __TZ_set_PSP_NS(uint32_t topOfProcStack)
+{
+ __ASM volatile ("MSR psp_ns, %0" : : "r" (topOfProcStack) : );
+}
+#endif
+
+
+/**
+ \brief Get Main Stack Pointer
+ \details Returns the current value of the Main Stack Pointer (MSP).
+ \return MSP Register value
+ */
+__STATIC_FORCEINLINE uint32_t __get_MSP(void)
+{
+ uint32_t result;
+
+ __ASM volatile ("MRS %0, msp" : "=r" (result) );
+ return(result);
+}
+
+
+#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3))
+/**
+ \brief Get Main Stack Pointer (non-secure)
+ \details Returns the current value of the non-secure Main Stack Pointer (MSP) when in secure state.
+ \return MSP Register value
+ */
+__STATIC_FORCEINLINE uint32_t __TZ_get_MSP_NS(void)
+{
+ uint32_t result;
+
+ __ASM volatile ("MRS %0, msp_ns" : "=r" (result) );
+ return(result);
+}
+#endif
+
+
+/**
+ \brief Set Main Stack Pointer
+ \details Assigns the given value to the Main Stack Pointer (MSP).
+ \param [in] topOfMainStack Main Stack Pointer value to set
+ */
+__STATIC_FORCEINLINE void __set_MSP(uint32_t topOfMainStack)
+{
+ __ASM volatile ("MSR msp, %0" : : "r" (topOfMainStack) : );
+}
+
+
+#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3))
+/**
+ \brief Set Main Stack Pointer (non-secure)
+ \details Assigns the given value to the non-secure Main Stack Pointer (MSP) when in secure state.
+ \param [in] topOfMainStack Main Stack Pointer value to set
+ */
+__STATIC_FORCEINLINE void __TZ_set_MSP_NS(uint32_t topOfMainStack)
+{
+ __ASM volatile ("MSR msp_ns, %0" : : "r" (topOfMainStack) : );
+}
+#endif
+
+
+#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3))
+/**
+ \brief Get Stack Pointer (non-secure)
+ \details Returns the current value of the non-secure Stack Pointer (SP) when in secure state.
+ \return SP Register value
+ */
+__STATIC_FORCEINLINE uint32_t __TZ_get_SP_NS(void)
+{
+ uint32_t result;
+
+ __ASM volatile ("MRS %0, sp_ns" : "=r" (result) );
+ return(result);
+}
+
+
+/**
+ \brief Set Stack Pointer (non-secure)
+ \details Assigns the given value to the non-secure Stack Pointer (SP) when in secure state.
+ \param [in] topOfStack Stack Pointer value to set
+ */
+__STATIC_FORCEINLINE void __TZ_set_SP_NS(uint32_t topOfStack)
+{
+ __ASM volatile ("MSR sp_ns, %0" : : "r" (topOfStack) : );
+}
+#endif
+
+
+/**
+ \brief Get Priority Mask
+ \details Returns the current state of the priority mask bit from the Priority Mask Register.
+ \return Priority Mask value
+ */
+__STATIC_FORCEINLINE uint32_t __get_PRIMASK(void)
+{
+ uint32_t result;
+
+ __ASM volatile ("MRS %0, primask" : "=r" (result) );
+ return(result);
+}
+
+
+#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3))
+/**
+ \brief Get Priority Mask (non-secure)
+ \details Returns the current state of the non-secure priority mask bit from the Priority Mask Register when in secure state.
+ \return Priority Mask value
+ */
+__STATIC_FORCEINLINE uint32_t __TZ_get_PRIMASK_NS(void)
+{
+ uint32_t result;
+
+ __ASM volatile ("MRS %0, primask_ns" : "=r" (result) );
+ return(result);
+}
+#endif
+
+
+/**
+ \brief Set Priority Mask
+ \details Assigns the given value to the Priority Mask Register.
+ \param [in] priMask Priority Mask
+ */
+__STATIC_FORCEINLINE void __set_PRIMASK(uint32_t priMask)
+{
+ __ASM volatile ("MSR primask, %0" : : "r" (priMask) : "memory");
+}
+
+
+#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3))
+/**
+ \brief Set Priority Mask (non-secure)
+ \details Assigns the given value to the non-secure Priority Mask Register when in secure state.
+ \param [in] priMask Priority Mask
+ */
+__STATIC_FORCEINLINE void __TZ_set_PRIMASK_NS(uint32_t priMask)
+{
+ __ASM volatile ("MSR primask_ns, %0" : : "r" (priMask) : "memory");
+}
+#endif
+
+
+#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \
+ (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \
+ (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) )
+/**
+ \brief Enable FIQ
+ \details Enables FIQ interrupts by clearing the F-bit in the CPSR.
+ Can only be executed in Privileged modes.
+ */
+#define __enable_fault_irq __enable_fiq /* see arm_compat.h */
+
+
+/**
+ \brief Disable FIQ
+ \details Disables FIQ interrupts by setting the F-bit in the CPSR.
+ Can only be executed in Privileged modes.
+ */
+#define __disable_fault_irq __disable_fiq /* see arm_compat.h */
+
+
+/**
+ \brief Get Base Priority
+ \details Returns the current value of the Base Priority register.
+ \return Base Priority register value
+ */
+__STATIC_FORCEINLINE uint32_t __get_BASEPRI(void)
+{
+ uint32_t result;
+
+ __ASM volatile ("MRS %0, basepri" : "=r" (result) );
+ return(result);
+}
+
+
+#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3))
+/**
+ \brief Get Base Priority (non-secure)
+ \details Returns the current value of the non-secure Base Priority register when in secure state.
+ \return Base Priority register value
+ */
+__STATIC_FORCEINLINE uint32_t __TZ_get_BASEPRI_NS(void)
+{
+ uint32_t result;
+
+ __ASM volatile ("MRS %0, basepri_ns" : "=r" (result) );
+ return(result);
+}
+#endif
+
+
+/**
+ \brief Set Base Priority
+ \details Assigns the given value to the Base Priority register.
+ \param [in] basePri Base Priority value to set
+ */
+__STATIC_FORCEINLINE void __set_BASEPRI(uint32_t basePri)
+{
+ __ASM volatile ("MSR basepri, %0" : : "r" (basePri) : "memory");
+}
+
+
+#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3))
+/**
+ \brief Set Base Priority (non-secure)
+ \details Assigns the given value to the non-secure Base Priority register when in secure state.
+ \param [in] basePri Base Priority value to set
+ */
+__STATIC_FORCEINLINE void __TZ_set_BASEPRI_NS(uint32_t basePri)
+{
+ __ASM volatile ("MSR basepri_ns, %0" : : "r" (basePri) : "memory");
+}
+#endif
+
+
+/**
+ \brief Set Base Priority with condition
+ \details Assigns the given value to the Base Priority register only if BASEPRI masking is disabled,
+ or the new value increases the BASEPRI priority level.
+ \param [in] basePri Base Priority value to set
+ */
+__STATIC_FORCEINLINE void __set_BASEPRI_MAX(uint32_t basePri)
+{
+ __ASM volatile ("MSR basepri_max, %0" : : "r" (basePri) : "memory");
+}
+
+
+/**
+ \brief Get Fault Mask
+ \details Returns the current value of the Fault Mask register.
+ \return Fault Mask register value
+ */
+__STATIC_FORCEINLINE uint32_t __get_FAULTMASK(void)
+{
+ uint32_t result;
+
+ __ASM volatile ("MRS %0, faultmask" : "=r" (result) );
+ return(result);
+}
+
+
+#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3))
+/**
+ \brief Get Fault Mask (non-secure)
+ \details Returns the current value of the non-secure Fault Mask register when in secure state.
+ \return Fault Mask register value
+ */
+__STATIC_FORCEINLINE uint32_t __TZ_get_FAULTMASK_NS(void)
+{
+ uint32_t result;
+
+ __ASM volatile ("MRS %0, faultmask_ns" : "=r" (result) );
+ return(result);
+}
+#endif
+
+
+/**
+ \brief Set Fault Mask
+ \details Assigns the given value to the Fault Mask register.
+ \param [in] faultMask Fault Mask value to set
+ */
+__STATIC_FORCEINLINE void __set_FAULTMASK(uint32_t faultMask)
+{
+ __ASM volatile ("MSR faultmask, %0" : : "r" (faultMask) : "memory");
+}
+
+
+#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3))
+/**
+ \brief Set Fault Mask (non-secure)
+ \details Assigns the given value to the non-secure Fault Mask register when in secure state.
+ \param [in] faultMask Fault Mask value to set
+ */
+__STATIC_FORCEINLINE void __TZ_set_FAULTMASK_NS(uint32_t faultMask)
+{
+ __ASM volatile ("MSR faultmask_ns, %0" : : "r" (faultMask) : "memory");
+}
+#endif
+
+#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \
+ (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \
+ (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) */
+
+
+#if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \
+ (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) )
+
+/**
+ \brief Get Process Stack Pointer Limit
+ Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure
+ Stack Pointer Limit register hence zero is returned always in non-secure
+ mode.
+
+ \details Returns the current value of the Process Stack Pointer Limit (PSPLIM).
+ \return PSPLIM Register value
+ */
+__STATIC_FORCEINLINE uint32_t __get_PSPLIM(void)
+{
+#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \
+ (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3)))
+ // without main extensions, the non-secure PSPLIM is RAZ/WI
+ return 0U;
+#else
+ uint32_t result;
+ __ASM volatile ("MRS %0, psplim" : "=r" (result) );
+ return result;
+#endif
+}
+
+#if (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3))
+/**
+ \brief Get Process Stack Pointer Limit (non-secure)
+ Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure
+ Stack Pointer Limit register hence zero is returned always in non-secure
+ mode.
+
+ \details Returns the current value of the non-secure Process Stack Pointer Limit (PSPLIM) when in secure state.
+ \return PSPLIM Register value
+ */
+__STATIC_FORCEINLINE uint32_t __TZ_get_PSPLIM_NS(void)
+{
+#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)))
+ // without main extensions, the non-secure PSPLIM is RAZ/WI
+ return 0U;
+#else
+ uint32_t result;
+ __ASM volatile ("MRS %0, psplim_ns" : "=r" (result) );
+ return result;
+#endif
+}
+#endif
+
+
+/**
+ \brief Set Process Stack Pointer Limit
+ Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure
+ Stack Pointer Limit register hence the write is silently ignored in non-secure
+ mode.
+
+ \details Assigns the given value to the Process Stack Pointer Limit (PSPLIM).
+ \param [in] ProcStackPtrLimit Process Stack Pointer Limit value to set
+ */
+__STATIC_FORCEINLINE void __set_PSPLIM(uint32_t ProcStackPtrLimit)
+{
+#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \
+ (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3)))
+ // without main extensions, the non-secure PSPLIM is RAZ/WI
+ (void)ProcStackPtrLimit;
+#else
+ __ASM volatile ("MSR psplim, %0" : : "r" (ProcStackPtrLimit));
+#endif
+}
+
+
+#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3))
+/**
+ \brief Set Process Stack Pointer (non-secure)
+ Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure
+ Stack Pointer Limit register hence the write is silently ignored in non-secure
+ mode.
+
+ \details Assigns the given value to the non-secure Process Stack Pointer Limit (PSPLIM) when in secure state.
+ \param [in] ProcStackPtrLimit Process Stack Pointer Limit value to set
+ */
+__STATIC_FORCEINLINE void __TZ_set_PSPLIM_NS(uint32_t ProcStackPtrLimit)
+{
+#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)))
+ // without main extensions, the non-secure PSPLIM is RAZ/WI
+ (void)ProcStackPtrLimit;
+#else
+ __ASM volatile ("MSR psplim_ns, %0\n" : : "r" (ProcStackPtrLimit));
+#endif
+}
+#endif
+
+
+/**
+ \brief Get Main Stack Pointer Limit
+ Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure
+ Stack Pointer Limit register hence zero is returned always.
+
+ \details Returns the current value of the Main Stack Pointer Limit (MSPLIM).
+ \return MSPLIM Register value
+ */
+__STATIC_FORCEINLINE uint32_t __get_MSPLIM(void)
+{
+#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \
+ (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3)))
+ // without main extensions, the non-secure MSPLIM is RAZ/WI
+ return 0U;
+#else
+ uint32_t result;
+ __ASM volatile ("MRS %0, msplim" : "=r" (result) );
+ return result;
+#endif
+}
+
+
+#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3))
+/**
+ \brief Get Main Stack Pointer Limit (non-secure)
+ Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure
+ Stack Pointer Limit register hence zero is returned always.
+
+ \details Returns the current value of the non-secure Main Stack Pointer Limit(MSPLIM) when in secure state.
+ \return MSPLIM Register value
+ */
+__STATIC_FORCEINLINE uint32_t __TZ_get_MSPLIM_NS(void)
+{
+#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)))
+ // without main extensions, the non-secure MSPLIM is RAZ/WI
+ return 0U;
+#else
+ uint32_t result;
+ __ASM volatile ("MRS %0, msplim_ns" : "=r" (result) );
+ return result;
+#endif
+}
+#endif
+
+
+/**
+ \brief Set Main Stack Pointer Limit
+ Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure
+ Stack Pointer Limit register hence the write is silently ignored.
+
+ \details Assigns the given value to the Main Stack Pointer Limit (MSPLIM).
+ \param [in] MainStackPtrLimit Main Stack Pointer Limit value to set
+ */
+__STATIC_FORCEINLINE void __set_MSPLIM(uint32_t MainStackPtrLimit)
+{
+#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \
+ (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3)))
+ // without main extensions, the non-secure MSPLIM is RAZ/WI
+ (void)MainStackPtrLimit;
+#else
+ __ASM volatile ("MSR msplim, %0" : : "r" (MainStackPtrLimit));
+#endif
+}
+
+
+#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3))
+/**
+ \brief Set Main Stack Pointer Limit (non-secure)
+ Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure
+ Stack Pointer Limit register hence the write is silently ignored.
+
+ \details Assigns the given value to the non-secure Main Stack Pointer Limit (MSPLIM) when in secure state.
+ \param [in] MainStackPtrLimit Main Stack Pointer value to set
+ */
+__STATIC_FORCEINLINE void __TZ_set_MSPLIM_NS(uint32_t MainStackPtrLimit)
+{
+#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)))
+ // without main extensions, the non-secure MSPLIM is RAZ/WI
+ (void)MainStackPtrLimit;
+#else
+ __ASM volatile ("MSR msplim_ns, %0" : : "r" (MainStackPtrLimit));
+#endif
+}
+#endif
+
+#endif /* ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \
+ (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) */
+
+/**
+ \brief Get FPSCR
+ \details Returns the current value of the Floating Point Status/Control register.
+ \return Floating Point Status/Control register value
+ */
+#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \
+ (defined (__FPU_USED ) && (__FPU_USED == 1U)) )
+#define __get_FPSCR (uint32_t)__builtin_arm_get_fpscr
+#else
+#define __get_FPSCR() ((uint32_t)0U)
+#endif
+
+/**
+ \brief Set FPSCR
+ \details Assigns the given value to the Floating Point Status/Control register.
+ \param [in] fpscr Floating Point Status/Control value to set
+ */
+#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \
+ (defined (__FPU_USED ) && (__FPU_USED == 1U)) )
+#define __set_FPSCR __builtin_arm_set_fpscr
+#else
+#define __set_FPSCR(x) ((void)(x))
+#endif
+
+
+/*@} end of CMSIS_Core_RegAccFunctions */
+
+
+/* ########################## Core Instruction Access ######################### */
+/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface
+ Access to dedicated instructions
+ @{
+*/
+
+/* Define macros for porting to both thumb1 and thumb2.
+ * For thumb1, use low register (r0-r7), specified by constraint "l"
+ * Otherwise, use general registers, specified by constraint "r" */
+#if defined (__thumb__) && !defined (__thumb2__)
+#define __CMSIS_GCC_OUT_REG(r) "=l" (r)
+#define __CMSIS_GCC_RW_REG(r) "+l" (r)
+#define __CMSIS_GCC_USE_REG(r) "l" (r)
+#else
+#define __CMSIS_GCC_OUT_REG(r) "=r" (r)
+#define __CMSIS_GCC_RW_REG(r) "+r" (r)
+#define __CMSIS_GCC_USE_REG(r) "r" (r)
+#endif
+
+/**
+ \brief No Operation
+ \details No Operation does nothing. This instruction can be used for code alignment purposes.
+ */
+#define __NOP __builtin_arm_nop
+
+/**
+ \brief Wait For Interrupt
+ \details Wait For Interrupt is a hint instruction that suspends execution until one of a number of events occurs.
+ */
+#define __WFI __builtin_arm_wfi
+
+
+/**
+ \brief Wait For Event
+ \details Wait For Event is a hint instruction that permits the processor to enter
+ a low-power state until one of a number of events occurs.
+ */
+#define __WFE __builtin_arm_wfe
+
+
+/**
+ \brief Send Event
+ \details Send Event is a hint instruction. It causes an event to be signaled to the CPU.
+ */
+#define __SEV __builtin_arm_sev
+
+
+/**
+ \brief Instruction Synchronization Barrier
+ \details Instruction Synchronization Barrier flushes the pipeline in the processor,
+ so that all instructions following the ISB are fetched from cache or memory,
+ after the instruction has been completed.
+ */
+#define __ISB() __builtin_arm_isb(0xF)
+
+/**
+ \brief Data Synchronization Barrier
+ \details Acts as a special kind of Data Memory Barrier.
+ It completes when all explicit memory accesses before this instruction complete.
+ */
+#define __DSB() __builtin_arm_dsb(0xF)
+
+
+/**
+ \brief Data Memory Barrier
+ \details Ensures the apparent order of the explicit memory operations before
+ and after the instruction, without ensuring their completion.
+ */
+#define __DMB() __builtin_arm_dmb(0xF)
+
+
+/**
+ \brief Reverse byte order (32 bit)
+ \details Reverses the byte order in unsigned integer value. For example, 0x12345678 becomes 0x78563412.
+ \param [in] value Value to reverse
+ \return Reversed value
+ */
+#define __REV(value) __builtin_bswap32(value)
+
+
+/**
+ \brief Reverse byte order (16 bit)
+ \details Reverses the byte order within each halfword of a word. For example, 0x12345678 becomes 0x34127856.
+ \param [in] value Value to reverse
+ \return Reversed value
+ */
+#define __REV16(value) __ROR(__REV(value), 16)
+
+
+/**
+ \brief Reverse byte order (16 bit)
+ \details Reverses the byte order in a 16-bit value and returns the signed 16-bit result. For example, 0x0080 becomes 0x8000.
+ \param [in] value Value to reverse
+ \return Reversed value
+ */
+#define __REVSH(value) (int16_t)__builtin_bswap16(value)
+
+
+/**
+ \brief Rotate Right in unsigned value (32 bit)
+ \details Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits.
+ \param [in] op1 Value to rotate
+ \param [in] op2 Number of Bits to rotate
+ \return Rotated value
+ */
+__STATIC_FORCEINLINE uint32_t __ROR(uint32_t op1, uint32_t op2)
+{
+ op2 %= 32U;
+ if (op2 == 0U)
+ {
+ return op1;
+ }
+ return (op1 >> op2) | (op1 << (32U - op2));
+}
+
+
+/**
+ \brief Breakpoint
+ \details Causes the processor to enter Debug state.
+ Debug tools can use this to investigate system state when the instruction at a particular address is reached.
+ \param [in] value is ignored by the processor.
+ If required, a debugger can use it to store additional information about the breakpoint.
+ */
+#define __BKPT(value) __ASM volatile ("bkpt "#value)
+
+
+/**
+ \brief Reverse bit order of value
+ \details Reverses the bit order of the given value.
+ \param [in] value Value to reverse
+ \return Reversed value
+ */
+#define __RBIT __builtin_arm_rbit
+
+/**
+ \brief Count leading zeros
+ \details Counts the number of leading zeros of a data value.
+ \param [in] value Value to count the leading zeros
+ \return number of leading zeros in value
+ */
+__STATIC_FORCEINLINE uint8_t __CLZ(uint32_t value)
+{
+ /* Even though __builtin_clz produces a CLZ instruction on ARM, formally
+ __builtin_clz(0) is undefined behaviour, so handle this case specially.
+ This guarantees ARM-compatible results if happening to compile on a non-ARM
+ target, and ensures the compiler doesn't decide to activate any
+ optimisations using the logic "value was passed to __builtin_clz, so it
+ is non-zero".
+ ARM Compiler 6.10 and possibly earlier will optimise this test away, leaving a
+ single CLZ instruction.
+ */
+ if (value == 0U)
+ {
+ return 32U;
+ }
+ return __builtin_clz(value);
+}
+
+
+#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \
+ (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \
+ (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \
+ (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) )
+/**
+ \brief LDR Exclusive (8 bit)
+ \details Executes a exclusive LDR instruction for 8 bit value.
+ \param [in] ptr Pointer to data
+ \return value of type uint8_t at (*ptr)
+ */
+#define __LDREXB (uint8_t)__builtin_arm_ldrex
+
+
+/**
+ \brief LDR Exclusive (16 bit)
+ \details Executes a exclusive LDR instruction for 16 bit values.
+ \param [in] ptr Pointer to data
+ \return value of type uint16_t at (*ptr)
+ */
+#define __LDREXH (uint16_t)__builtin_arm_ldrex
+
+
+/**
+ \brief LDR Exclusive (32 bit)
+ \details Executes a exclusive LDR instruction for 32 bit values.
+ \param [in] ptr Pointer to data
+ \return value of type uint32_t at (*ptr)
+ */
+#define __LDREXW (uint32_t)__builtin_arm_ldrex
+
+
+/**
+ \brief STR Exclusive (8 bit)
+ \details Executes a exclusive STR instruction for 8 bit values.
+ \param [in] value Value to store
+ \param [in] ptr Pointer to location
+ \return 0 Function succeeded
+ \return 1 Function failed
+ */
+#define __STREXB (uint32_t)__builtin_arm_strex
+
+
+/**
+ \brief STR Exclusive (16 bit)
+ \details Executes a exclusive STR instruction for 16 bit values.
+ \param [in] value Value to store
+ \param [in] ptr Pointer to location
+ \return 0 Function succeeded
+ \return 1 Function failed
+ */
+#define __STREXH (uint32_t)__builtin_arm_strex
+
+
+/**
+ \brief STR Exclusive (32 bit)
+ \details Executes a exclusive STR instruction for 32 bit values.
+ \param [in] value Value to store
+ \param [in] ptr Pointer to location
+ \return 0 Function succeeded
+ \return 1 Function failed
+ */
+#define __STREXW (uint32_t)__builtin_arm_strex
+
+
+/**
+ \brief Remove the exclusive lock
+ \details Removes the exclusive lock which is created by LDREX.
+ */
+#define __CLREX __builtin_arm_clrex
+
+#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \
+ (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \
+ (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \
+ (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) */
+
+
+#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \
+ (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \
+ (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) )
+
+/**
+ \brief Signed Saturate
+ \details Saturates a signed value.
+ \param [in] value Value to be saturated
+ \param [in] sat Bit position to saturate to (1..32)
+ \return Saturated value
+ */
+#define __SSAT __builtin_arm_ssat
+
+
+/**
+ \brief Unsigned Saturate
+ \details Saturates an unsigned value.
+ \param [in] value Value to be saturated
+ \param [in] sat Bit position to saturate to (0..31)
+ \return Saturated value
+ */
+#define __USAT __builtin_arm_usat
+
+
+/**
+ \brief Rotate Right with Extend (32 bit)
+ \details Moves each bit of a bitstring right by one bit.
+ The carry input is shifted in at the left end of the bitstring.
+ \param [in] value Value to rotate
+ \return Rotated value
+ */
+__STATIC_FORCEINLINE uint32_t __RRX(uint32_t value)
+{
+ uint32_t result;
+
+ __ASM volatile ("rrx %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) );
+ return(result);
+}
+
+
+/**
+ \brief LDRT Unprivileged (8 bit)
+ \details Executes a Unprivileged LDRT instruction for 8 bit value.
+ \param [in] ptr Pointer to data
+ \return value of type uint8_t at (*ptr)
+ */
+__STATIC_FORCEINLINE uint8_t __LDRBT(volatile uint8_t *ptr)
+{
+ uint32_t result;
+
+ __ASM volatile ("ldrbt %0, %1" : "=r" (result) : "Q" (*ptr) );
+ return ((uint8_t) result); /* Add explicit type cast here */
+}
+
+
+/**
+ \brief LDRT Unprivileged (16 bit)
+ \details Executes a Unprivileged LDRT instruction for 16 bit values.
+ \param [in] ptr Pointer to data
+ \return value of type uint16_t at (*ptr)
+ */
+__STATIC_FORCEINLINE uint16_t __LDRHT(volatile uint16_t *ptr)
+{
+ uint32_t result;
+
+ __ASM volatile ("ldrht %0, %1" : "=r" (result) : "Q" (*ptr) );
+ return ((uint16_t) result); /* Add explicit type cast here */
+}
+
+
+/**
+ \brief LDRT Unprivileged (32 bit)
+ \details Executes a Unprivileged LDRT instruction for 32 bit values.
+ \param [in] ptr Pointer to data
+ \return value of type uint32_t at (*ptr)
+ */
+__STATIC_FORCEINLINE uint32_t __LDRT(volatile uint32_t *ptr)
+{
+ uint32_t result;
+
+ __ASM volatile ("ldrt %0, %1" : "=r" (result) : "Q" (*ptr) );
+ return(result);
+}
+
+
+/**
+ \brief STRT Unprivileged (8 bit)
+ \details Executes a Unprivileged STRT instruction for 8 bit values.
+ \param [in] value Value to store
+ \param [in] ptr Pointer to location
+ */
+__STATIC_FORCEINLINE void __STRBT(uint8_t value, volatile uint8_t *ptr)
+{
+ __ASM volatile ("strbt %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) );
+}
+
+
+/**
+ \brief STRT Unprivileged (16 bit)
+ \details Executes a Unprivileged STRT instruction for 16 bit values.
+ \param [in] value Value to store
+ \param [in] ptr Pointer to location
+ */
+__STATIC_FORCEINLINE void __STRHT(uint16_t value, volatile uint16_t *ptr)
+{
+ __ASM volatile ("strht %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) );
+}
+
+
+/**
+ \brief STRT Unprivileged (32 bit)
+ \details Executes a Unprivileged STRT instruction for 32 bit values.
+ \param [in] value Value to store
+ \param [in] ptr Pointer to location
+ */
+__STATIC_FORCEINLINE void __STRT(uint32_t value, volatile uint32_t *ptr)
+{
+ __ASM volatile ("strt %1, %0" : "=Q" (*ptr) : "r" (value) );
+}
+
+#else /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \
+ (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \
+ (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) */
+
+/**
+ \brief Signed Saturate
+ \details Saturates a signed value.
+ \param [in] value Value to be saturated
+ \param [in] sat Bit position to saturate to (1..32)
+ \return Saturated value
+ */
+__STATIC_FORCEINLINE int32_t __SSAT(int32_t val, uint32_t sat)
+{
+ if ((sat >= 1U) && (sat <= 32U))
+ {
+ const int32_t max = (int32_t)((1U << (sat - 1U)) - 1U);
+ const int32_t min = -1 - max ;
+ if (val > max)
+ {
+ return max;
+ }
+ else if (val < min)
+ {
+ return min;
+ }
+ }
+ return val;
+}
+
+/**
+ \brief Unsigned Saturate
+ \details Saturates an unsigned value.
+ \param [in] value Value to be saturated
+ \param [in] sat Bit position to saturate to (0..31)
+ \return Saturated value
+ */
+__STATIC_FORCEINLINE uint32_t __USAT(int32_t val, uint32_t sat)
+{
+ if (sat <= 31U)
+ {
+ const uint32_t max = ((1U << sat) - 1U);
+ if (val > (int32_t)max)
+ {
+ return max;
+ }
+ else if (val < 0)
+ {
+ return 0U;
+ }
+ }
+ return (uint32_t)val;
+}
+
+#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \
+ (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \
+ (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) */
+
+
+#if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \
+ (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) )
+/**
+ \brief Load-Acquire (8 bit)
+ \details Executes a LDAB instruction for 8 bit value.
+ \param [in] ptr Pointer to data
+ \return value of type uint8_t at (*ptr)
+ */
+__STATIC_FORCEINLINE uint8_t __LDAB(volatile uint8_t *ptr)
+{
+ uint32_t result;
+
+ __ASM volatile ("ldab %0, %1" : "=r" (result) : "Q" (*ptr) );
+ return ((uint8_t) result);
+}
+
+
+/**
+ \brief Load-Acquire (16 bit)
+ \details Executes a LDAH instruction for 16 bit values.
+ \param [in] ptr Pointer to data
+ \return value of type uint16_t at (*ptr)
+ */
+__STATIC_FORCEINLINE uint16_t __LDAH(volatile uint16_t *ptr)
+{
+ uint32_t result;
+
+ __ASM volatile ("ldah %0, %1" : "=r" (result) : "Q" (*ptr) );
+ return ((uint16_t) result);
+}
+
+
+/**
+ \brief Load-Acquire (32 bit)
+ \details Executes a LDA instruction for 32 bit values.
+ \param [in] ptr Pointer to data
+ \return value of type uint32_t at (*ptr)
+ */
+__STATIC_FORCEINLINE uint32_t __LDA(volatile uint32_t *ptr)
+{
+ uint32_t result;
+
+ __ASM volatile ("lda %0, %1" : "=r" (result) : "Q" (*ptr) );
+ return(result);
+}
+
+
+/**
+ \brief Store-Release (8 bit)
+ \details Executes a STLB instruction for 8 bit values.
+ \param [in] value Value to store
+ \param [in] ptr Pointer to location
+ */
+__STATIC_FORCEINLINE void __STLB(uint8_t value, volatile uint8_t *ptr)
+{
+ __ASM volatile ("stlb %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) );
+}
+
+
+/**
+ \brief Store-Release (16 bit)
+ \details Executes a STLH instruction for 16 bit values.
+ \param [in] value Value to store
+ \param [in] ptr Pointer to location
+ */
+__STATIC_FORCEINLINE void __STLH(uint16_t value, volatile uint16_t *ptr)
+{
+ __ASM volatile ("stlh %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) );
+}
+
+
+/**
+ \brief Store-Release (32 bit)
+ \details Executes a STL instruction for 32 bit values.
+ \param [in] value Value to store
+ \param [in] ptr Pointer to location
+ */
+__STATIC_FORCEINLINE void __STL(uint32_t value, volatile uint32_t *ptr)
+{
+ __ASM volatile ("stl %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) );
+}
+
+
+/**
+ \brief Load-Acquire Exclusive (8 bit)
+ \details Executes a LDAB exclusive instruction for 8 bit value.
+ \param [in] ptr Pointer to data
+ \return value of type uint8_t at (*ptr)
+ */
+#define __LDAEXB (uint8_t)__builtin_arm_ldaex
+
+
+/**
+ \brief Load-Acquire Exclusive (16 bit)
+ \details Executes a LDAH exclusive instruction for 16 bit values.
+ \param [in] ptr Pointer to data
+ \return value of type uint16_t at (*ptr)
+ */
+#define __LDAEXH (uint16_t)__builtin_arm_ldaex
+
+
+/**
+ \brief Load-Acquire Exclusive (32 bit)
+ \details Executes a LDA exclusive instruction for 32 bit values.
+ \param [in] ptr Pointer to data
+ \return value of type uint32_t at (*ptr)
+ */
+#define __LDAEX (uint32_t)__builtin_arm_ldaex
+
+
+/**
+ \brief Store-Release Exclusive (8 bit)
+ \details Executes a STLB exclusive instruction for 8 bit values.
+ \param [in] value Value to store
+ \param [in] ptr Pointer to location
+ \return 0 Function succeeded
+ \return 1 Function failed
+ */
+#define __STLEXB (uint32_t)__builtin_arm_stlex
+
+
+/**
+ \brief Store-Release Exclusive (16 bit)
+ \details Executes a STLH exclusive instruction for 16 bit values.
+ \param [in] value Value to store
+ \param [in] ptr Pointer to location
+ \return 0 Function succeeded
+ \return 1 Function failed
+ */
+#define __STLEXH (uint32_t)__builtin_arm_stlex
+
+
+/**
+ \brief Store-Release Exclusive (32 bit)
+ \details Executes a STL exclusive instruction for 32 bit values.
+ \param [in] value Value to store
+ \param [in] ptr Pointer to location
+ \return 0 Function succeeded
+ \return 1 Function failed
+ */
+#define __STLEX (uint32_t)__builtin_arm_stlex
+
+#endif /* ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \
+ (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) */
+
+/*@}*/ /* end of group CMSIS_Core_InstructionInterface */
+
+
+/* ################### Compiler specific Intrinsics ########################### */
+/** \defgroup CMSIS_SIMD_intrinsics CMSIS SIMD Intrinsics
+ Access to dedicated SIMD instructions
+ @{
+*/
+
+#if (defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1))
+
+#define __SADD8 __builtin_arm_sadd8
+#define __QADD8 __builtin_arm_qadd8
+#define __SHADD8 __builtin_arm_shadd8
+#define __UADD8 __builtin_arm_uadd8
+#define __UQADD8 __builtin_arm_uqadd8
+#define __UHADD8 __builtin_arm_uhadd8
+#define __SSUB8 __builtin_arm_ssub8
+#define __QSUB8 __builtin_arm_qsub8
+#define __SHSUB8 __builtin_arm_shsub8
+#define __USUB8 __builtin_arm_usub8
+#define __UQSUB8 __builtin_arm_uqsub8
+#define __UHSUB8 __builtin_arm_uhsub8
+#define __SADD16 __builtin_arm_sadd16
+#define __QADD16 __builtin_arm_qadd16
+#define __SHADD16 __builtin_arm_shadd16
+#define __UADD16 __builtin_arm_uadd16
+#define __UQADD16 __builtin_arm_uqadd16
+#define __UHADD16 __builtin_arm_uhadd16
+#define __SSUB16 __builtin_arm_ssub16
+#define __QSUB16 __builtin_arm_qsub16
+#define __SHSUB16 __builtin_arm_shsub16
+#define __USUB16 __builtin_arm_usub16
+#define __UQSUB16 __builtin_arm_uqsub16
+#define __UHSUB16 __builtin_arm_uhsub16
+#define __SASX __builtin_arm_sasx
+#define __QASX __builtin_arm_qasx
+#define __SHASX __builtin_arm_shasx
+#define __UASX __builtin_arm_uasx
+#define __UQASX __builtin_arm_uqasx
+#define __UHASX __builtin_arm_uhasx
+#define __SSAX __builtin_arm_ssax
+#define __QSAX __builtin_arm_qsax
+#define __SHSAX __builtin_arm_shsax
+#define __USAX __builtin_arm_usax
+#define __UQSAX __builtin_arm_uqsax
+#define __UHSAX __builtin_arm_uhsax
+#define __USAD8 __builtin_arm_usad8
+#define __USADA8 __builtin_arm_usada8
+#define __SSAT16 __builtin_arm_ssat16
+#define __USAT16 __builtin_arm_usat16
+#define __UXTB16 __builtin_arm_uxtb16
+#define __UXTAB16 __builtin_arm_uxtab16
+#define __SXTB16 __builtin_arm_sxtb16
+#define __SXTAB16 __builtin_arm_sxtab16
+#define __SMUAD __builtin_arm_smuad
+#define __SMUADX __builtin_arm_smuadx
+#define __SMLAD __builtin_arm_smlad
+#define __SMLADX __builtin_arm_smladx
+#define __SMLALD __builtin_arm_smlald
+#define __SMLALDX __builtin_arm_smlaldx
+#define __SMUSD __builtin_arm_smusd
+#define __SMUSDX __builtin_arm_smusdx
+#define __SMLSD __builtin_arm_smlsd
+#define __SMLSDX __builtin_arm_smlsdx
+#define __SMLSLD __builtin_arm_smlsld
+#define __SMLSLDX __builtin_arm_smlsldx
+#define __SEL __builtin_arm_sel
+#define __QADD __builtin_arm_qadd
+#define __QSUB __builtin_arm_qsub
+
+#define __PKHBT(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0x0000FFFFUL) | \
+ ((((uint32_t)(ARG2)) << (ARG3)) & 0xFFFF0000UL) )
+
+#define __PKHTB(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0xFFFF0000UL) | \
+ ((((uint32_t)(ARG2)) >> (ARG3)) & 0x0000FFFFUL) )
+
+__STATIC_FORCEINLINE int32_t __SMMLA (int32_t op1, int32_t op2, int32_t op3)
+{
+ int32_t result;
+
+ __ASM volatile ("smmla %0, %1, %2, %3" : "=r" (result): "r" (op1), "r" (op2), "r" (op3) );
+ return(result);
+}
+
+#endif /* (__ARM_FEATURE_DSP == 1) */
+/*@} end of group CMSIS_SIMD_intrinsics */
+
+
+#endif /* __CMSIS_ARMCLANG_H */
diff --git a/lib/cmsis/inc/cmsis_armclang_ltm.h b/lib/cmsis/inc/cmsis_armclang_ltm.h
new file mode 100644
index 0000000000..e4002a3fc4
--- /dev/null
+++ b/lib/cmsis/inc/cmsis_armclang_ltm.h
@@ -0,0 +1,1866 @@
+/**************************************************************************//**
+ * @file cmsis_armclang_ltm.h
+ * @brief CMSIS compiler armclang (Arm Compiler 6) header file
+ * @version V1.0.1
+ * @date 19. March 2019
+ ******************************************************************************/
+/*
+ * Copyright (c) 2018-2019 Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*lint -esym(9058, IRQn)*/ /* disable MISRA 2012 Rule 2.4 for IRQn */
+
+#ifndef __CMSIS_ARMCLANG_H
+#define __CMSIS_ARMCLANG_H
+
+#pragma clang system_header /* treat file as system include file */
+
+#ifndef __ARM_COMPAT_H
+#include /* Compatibility header for Arm Compiler 5 intrinsics */
+#endif
+
+/* CMSIS compiler specific defines */
+#ifndef __ASM
+ #define __ASM __asm
+#endif
+#ifndef __INLINE
+ #define __INLINE __inline
+#endif
+#ifndef __STATIC_INLINE
+ #define __STATIC_INLINE static __inline
+#endif
+#ifndef __STATIC_FORCEINLINE
+ #define __STATIC_FORCEINLINE __attribute__((always_inline)) static __inline
+#endif
+#ifndef __NO_RETURN
+ #define __NO_RETURN __attribute__((__noreturn__))
+#endif
+#ifndef __USED
+ #define __USED __attribute__((used))
+#endif
+#ifndef __WEAK
+ #define __WEAK __attribute__((weak))
+#endif
+#ifndef __PACKED
+ #define __PACKED __attribute__((packed, aligned(1)))
+#endif
+#ifndef __PACKED_STRUCT
+ #define __PACKED_STRUCT struct __attribute__((packed, aligned(1)))
+#endif
+#ifndef __PACKED_UNION
+ #define __PACKED_UNION union __attribute__((packed, aligned(1)))
+#endif
+#ifndef __UNALIGNED_UINT32 /* deprecated */
+ #pragma clang diagnostic push
+ #pragma clang diagnostic ignored "-Wpacked"
+/*lint -esym(9058, T_UINT32)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT32 */
+ struct __attribute__((packed)) T_UINT32 { uint32_t v; };
+ #pragma clang diagnostic pop
+ #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v)
+#endif
+#ifndef __UNALIGNED_UINT16_WRITE
+ #pragma clang diagnostic push
+ #pragma clang diagnostic ignored "-Wpacked"
+/*lint -esym(9058, T_UINT16_WRITE)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT16_WRITE */
+ __PACKED_STRUCT T_UINT16_WRITE { uint16_t v; };
+ #pragma clang diagnostic pop
+ #define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val))
+#endif
+#ifndef __UNALIGNED_UINT16_READ
+ #pragma clang diagnostic push
+ #pragma clang diagnostic ignored "-Wpacked"
+/*lint -esym(9058, T_UINT16_READ)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT16_READ */
+ __PACKED_STRUCT T_UINT16_READ { uint16_t v; };
+ #pragma clang diagnostic pop
+ #define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v)
+#endif
+#ifndef __UNALIGNED_UINT32_WRITE
+ #pragma clang diagnostic push
+ #pragma clang diagnostic ignored "-Wpacked"
+/*lint -esym(9058, T_UINT32_WRITE)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT32_WRITE */
+ __PACKED_STRUCT T_UINT32_WRITE { uint32_t v; };
+ #pragma clang diagnostic pop
+ #define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val))
+#endif
+#ifndef __UNALIGNED_UINT32_READ
+ #pragma clang diagnostic push
+ #pragma clang diagnostic ignored "-Wpacked"
+/*lint -esym(9058, T_UINT32_READ)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT32_READ */
+ __PACKED_STRUCT T_UINT32_READ { uint32_t v; };
+ #pragma clang diagnostic pop
+ #define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v)
+#endif
+#ifndef __ALIGNED
+ #define __ALIGNED(x) __attribute__((aligned(x)))
+#endif
+#ifndef __RESTRICT
+ #define __RESTRICT __restrict
+#endif
+
+
+/* ########################### Core Function Access ########################### */
+/** \ingroup CMSIS_Core_FunctionInterface
+ \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions
+ @{
+ */
+
+/**
+ \brief Enable IRQ Interrupts
+ \details Enables IRQ interrupts by clearing the I-bit in the CPSR.
+ Can only be executed in Privileged modes.
+ */
+/* intrinsic void __enable_irq(); see arm_compat.h */
+
+
+/**
+ \brief Disable IRQ Interrupts
+ \details Disables IRQ interrupts by setting the I-bit in the CPSR.
+ Can only be executed in Privileged modes.
+ */
+/* intrinsic void __disable_irq(); see arm_compat.h */
+
+
+/**
+ \brief Get Control Register
+ \details Returns the content of the Control Register.
+ \return Control Register value
+ */
+__STATIC_FORCEINLINE uint32_t __get_CONTROL(void)
+{
+ uint32_t result;
+
+ __ASM volatile ("MRS %0, control" : "=r" (result) );
+ return(result);
+}
+
+
+#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3))
+/**
+ \brief Get Control Register (non-secure)
+ \details Returns the content of the non-secure Control Register when in secure mode.
+ \return non-secure Control Register value
+ */
+__STATIC_FORCEINLINE uint32_t __TZ_get_CONTROL_NS(void)
+{
+ uint32_t result;
+
+ __ASM volatile ("MRS %0, control_ns" : "=r" (result) );
+ return(result);
+}
+#endif
+
+
+/**
+ \brief Set Control Register
+ \details Writes the given value to the Control Register.
+ \param [in] control Control Register value to set
+ */
+__STATIC_FORCEINLINE void __set_CONTROL(uint32_t control)
+{
+ __ASM volatile ("MSR control, %0" : : "r" (control) : "memory");
+}
+
+
+#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3))
+/**
+ \brief Set Control Register (non-secure)
+ \details Writes the given value to the non-secure Control Register when in secure state.
+ \param [in] control Control Register value to set
+ */
+__STATIC_FORCEINLINE void __TZ_set_CONTROL_NS(uint32_t control)
+{
+ __ASM volatile ("MSR control_ns, %0" : : "r" (control) : "memory");
+}
+#endif
+
+
+/**
+ \brief Get IPSR Register
+ \details Returns the content of the IPSR Register.
+ \return IPSR Register value
+ */
+__STATIC_FORCEINLINE uint32_t __get_IPSR(void)
+{
+ uint32_t result;
+
+ __ASM volatile ("MRS %0, ipsr" : "=r" (result) );
+ return(result);
+}
+
+
+/**
+ \brief Get APSR Register
+ \details Returns the content of the APSR Register.
+ \return APSR Register value
+ */
+__STATIC_FORCEINLINE uint32_t __get_APSR(void)
+{
+ uint32_t result;
+
+ __ASM volatile ("MRS %0, apsr" : "=r" (result) );
+ return(result);
+}
+
+
+/**
+ \brief Get xPSR Register
+ \details Returns the content of the xPSR Register.
+ \return xPSR Register value
+ */
+__STATIC_FORCEINLINE uint32_t __get_xPSR(void)
+{
+ uint32_t result;
+
+ __ASM volatile ("MRS %0, xpsr" : "=r" (result) );
+ return(result);
+}
+
+
+/**
+ \brief Get Process Stack Pointer
+ \details Returns the current value of the Process Stack Pointer (PSP).
+ \return PSP Register value
+ */
+__STATIC_FORCEINLINE uint32_t __get_PSP(void)
+{
+ uint32_t result;
+
+ __ASM volatile ("MRS %0, psp" : "=r" (result) );
+ return(result);
+}
+
+
+#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3))
+/**
+ \brief Get Process Stack Pointer (non-secure)
+ \details Returns the current value of the non-secure Process Stack Pointer (PSP) when in secure state.
+ \return PSP Register value
+ */
+__STATIC_FORCEINLINE uint32_t __TZ_get_PSP_NS(void)
+{
+ uint32_t result;
+
+ __ASM volatile ("MRS %0, psp_ns" : "=r" (result) );
+ return(result);
+}
+#endif
+
+
+/**
+ \brief Set Process Stack Pointer
+ \details Assigns the given value to the Process Stack Pointer (PSP).
+ \param [in] topOfProcStack Process Stack Pointer value to set
+ */
+__STATIC_FORCEINLINE void __set_PSP(uint32_t topOfProcStack)
+{
+ __ASM volatile ("MSR psp, %0" : : "r" (topOfProcStack) : );
+}
+
+
+#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3))
+/**
+ \brief Set Process Stack Pointer (non-secure)
+ \details Assigns the given value to the non-secure Process Stack Pointer (PSP) when in secure state.
+ \param [in] topOfProcStack Process Stack Pointer value to set
+ */
+__STATIC_FORCEINLINE void __TZ_set_PSP_NS(uint32_t topOfProcStack)
+{
+ __ASM volatile ("MSR psp_ns, %0" : : "r" (topOfProcStack) : );
+}
+#endif
+
+
+/**
+ \brief Get Main Stack Pointer
+ \details Returns the current value of the Main Stack Pointer (MSP).
+ \return MSP Register value
+ */
+__STATIC_FORCEINLINE uint32_t __get_MSP(void)
+{
+ uint32_t result;
+
+ __ASM volatile ("MRS %0, msp" : "=r" (result) );
+ return(result);
+}
+
+
+#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3))
+/**
+ \brief Get Main Stack Pointer (non-secure)
+ \details Returns the current value of the non-secure Main Stack Pointer (MSP) when in secure state.
+ \return MSP Register value
+ */
+__STATIC_FORCEINLINE uint32_t __TZ_get_MSP_NS(void)
+{
+ uint32_t result;
+
+ __ASM volatile ("MRS %0, msp_ns" : "=r" (result) );
+ return(result);
+}
+#endif
+
+
+/**
+ \brief Set Main Stack Pointer
+ \details Assigns the given value to the Main Stack Pointer (MSP).
+ \param [in] topOfMainStack Main Stack Pointer value to set
+ */
+__STATIC_FORCEINLINE void __set_MSP(uint32_t topOfMainStack)
+{
+ __ASM volatile ("MSR msp, %0" : : "r" (topOfMainStack) : );
+}
+
+
+#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3))
+/**
+ \brief Set Main Stack Pointer (non-secure)
+ \details Assigns the given value to the non-secure Main Stack Pointer (MSP) when in secure state.
+ \param [in] topOfMainStack Main Stack Pointer value to set
+ */
+__STATIC_FORCEINLINE void __TZ_set_MSP_NS(uint32_t topOfMainStack)
+{
+ __ASM volatile ("MSR msp_ns, %0" : : "r" (topOfMainStack) : );
+}
+#endif
+
+
+#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3))
+/**
+ \brief Get Stack Pointer (non-secure)
+ \details Returns the current value of the non-secure Stack Pointer (SP) when in secure state.
+ \return SP Register value
+ */
+__STATIC_FORCEINLINE uint32_t __TZ_get_SP_NS(void)
+{
+ uint32_t result;
+
+ __ASM volatile ("MRS %0, sp_ns" : "=r" (result) );
+ return(result);
+}
+
+
+/**
+ \brief Set Stack Pointer (non-secure)
+ \details Assigns the given value to the non-secure Stack Pointer (SP) when in secure state.
+ \param [in] topOfStack Stack Pointer value to set
+ */
+__STATIC_FORCEINLINE void __TZ_set_SP_NS(uint32_t topOfStack)
+{
+ __ASM volatile ("MSR sp_ns, %0" : : "r" (topOfStack) : );
+}
+#endif
+
+
+/**
+ \brief Get Priority Mask
+ \details Returns the current state of the priority mask bit from the Priority Mask Register.
+ \return Priority Mask value
+ */
+__STATIC_FORCEINLINE uint32_t __get_PRIMASK(void)
+{
+ uint32_t result;
+
+ __ASM volatile ("MRS %0, primask" : "=r" (result) );
+ return(result);
+}
+
+
+#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3))
+/**
+ \brief Get Priority Mask (non-secure)
+ \details Returns the current state of the non-secure priority mask bit from the Priority Mask Register when in secure state.
+ \return Priority Mask value
+ */
+__STATIC_FORCEINLINE uint32_t __TZ_get_PRIMASK_NS(void)
+{
+ uint32_t result;
+
+ __ASM volatile ("MRS %0, primask_ns" : "=r" (result) );
+ return(result);
+}
+#endif
+
+
+/**
+ \brief Set Priority Mask
+ \details Assigns the given value to the Priority Mask Register.
+ \param [in] priMask Priority Mask
+ */
+__STATIC_FORCEINLINE void __set_PRIMASK(uint32_t priMask)
+{
+ __ASM volatile ("MSR primask, %0" : : "r" (priMask) : "memory");
+}
+
+
+#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3))
+/**
+ \brief Set Priority Mask (non-secure)
+ \details Assigns the given value to the non-secure Priority Mask Register when in secure state.
+ \param [in] priMask Priority Mask
+ */
+__STATIC_FORCEINLINE void __TZ_set_PRIMASK_NS(uint32_t priMask)
+{
+ __ASM volatile ("MSR primask_ns, %0" : : "r" (priMask) : "memory");
+}
+#endif
+
+
+#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \
+ (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \
+ (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) )
+/**
+ \brief Enable FIQ
+ \details Enables FIQ interrupts by clearing the F-bit in the CPSR.
+ Can only be executed in Privileged modes.
+ */
+#define __enable_fault_irq __enable_fiq /* see arm_compat.h */
+
+
+/**
+ \brief Disable FIQ
+ \details Disables FIQ interrupts by setting the F-bit in the CPSR.
+ Can only be executed in Privileged modes.
+ */
+#define __disable_fault_irq __disable_fiq /* see arm_compat.h */
+
+
+/**
+ \brief Get Base Priority
+ \details Returns the current value of the Base Priority register.
+ \return Base Priority register value
+ */
+__STATIC_FORCEINLINE uint32_t __get_BASEPRI(void)
+{
+ uint32_t result;
+
+ __ASM volatile ("MRS %0, basepri" : "=r" (result) );
+ return(result);
+}
+
+
+#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3))
+/**
+ \brief Get Base Priority (non-secure)
+ \details Returns the current value of the non-secure Base Priority register when in secure state.
+ \return Base Priority register value
+ */
+__STATIC_FORCEINLINE uint32_t __TZ_get_BASEPRI_NS(void)
+{
+ uint32_t result;
+
+ __ASM volatile ("MRS %0, basepri_ns" : "=r" (result) );
+ return(result);
+}
+#endif
+
+
+/**
+ \brief Set Base Priority
+ \details Assigns the given value to the Base Priority register.
+ \param [in] basePri Base Priority value to set
+ */
+__STATIC_FORCEINLINE void __set_BASEPRI(uint32_t basePri)
+{
+ __ASM volatile ("MSR basepri, %0" : : "r" (basePri) : "memory");
+}
+
+
+#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3))
+/**
+ \brief Set Base Priority (non-secure)
+ \details Assigns the given value to the non-secure Base Priority register when in secure state.
+ \param [in] basePri Base Priority value to set
+ */
+__STATIC_FORCEINLINE void __TZ_set_BASEPRI_NS(uint32_t basePri)
+{
+ __ASM volatile ("MSR basepri_ns, %0" : : "r" (basePri) : "memory");
+}
+#endif
+
+
+/**
+ \brief Set Base Priority with condition
+ \details Assigns the given value to the Base Priority register only if BASEPRI masking is disabled,
+ or the new value increases the BASEPRI priority level.
+ \param [in] basePri Base Priority value to set
+ */
+__STATIC_FORCEINLINE void __set_BASEPRI_MAX(uint32_t basePri)
+{
+ __ASM volatile ("MSR basepri_max, %0" : : "r" (basePri) : "memory");
+}
+
+
+/**
+ \brief Get Fault Mask
+ \details Returns the current value of the Fault Mask register.
+ \return Fault Mask register value
+ */
+__STATIC_FORCEINLINE uint32_t __get_FAULTMASK(void)
+{
+ uint32_t result;
+
+ __ASM volatile ("MRS %0, faultmask" : "=r" (result) );
+ return(result);
+}
+
+
+#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3))
+/**
+ \brief Get Fault Mask (non-secure)
+ \details Returns the current value of the non-secure Fault Mask register when in secure state.
+ \return Fault Mask register value
+ */
+__STATIC_FORCEINLINE uint32_t __TZ_get_FAULTMASK_NS(void)
+{
+ uint32_t result;
+
+ __ASM volatile ("MRS %0, faultmask_ns" : "=r" (result) );
+ return(result);
+}
+#endif
+
+
+/**
+ \brief Set Fault Mask
+ \details Assigns the given value to the Fault Mask register.
+ \param [in] faultMask Fault Mask value to set
+ */
+__STATIC_FORCEINLINE void __set_FAULTMASK(uint32_t faultMask)
+{
+ __ASM volatile ("MSR faultmask, %0" : : "r" (faultMask) : "memory");
+}
+
+
+#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3))
+/**
+ \brief Set Fault Mask (non-secure)
+ \details Assigns the given value to the non-secure Fault Mask register when in secure state.
+ \param [in] faultMask Fault Mask value to set
+ */
+__STATIC_FORCEINLINE void __TZ_set_FAULTMASK_NS(uint32_t faultMask)
+{
+ __ASM volatile ("MSR faultmask_ns, %0" : : "r" (faultMask) : "memory");
+}
+#endif
+
+#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \
+ (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \
+ (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) */
+
+
+#if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \
+ (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) )
+
+/**
+ \brief Get Process Stack Pointer Limit
+ Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure
+ Stack Pointer Limit register hence zero is returned always in non-secure
+ mode.
+
+ \details Returns the current value of the Process Stack Pointer Limit (PSPLIM).
+ \return PSPLIM Register value
+ */
+__STATIC_FORCEINLINE uint32_t __get_PSPLIM(void)
+{
+#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \
+ (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3)))
+ // without main extensions, the non-secure PSPLIM is RAZ/WI
+ return 0U;
+#else
+ uint32_t result;
+ __ASM volatile ("MRS %0, psplim" : "=r" (result) );
+ return result;
+#endif
+}
+
+#if (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3))
+/**
+ \brief Get Process Stack Pointer Limit (non-secure)
+ Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure
+ Stack Pointer Limit register hence zero is returned always in non-secure
+ mode.
+
+ \details Returns the current value of the non-secure Process Stack Pointer Limit (PSPLIM) when in secure state.
+ \return PSPLIM Register value
+ */
+__STATIC_FORCEINLINE uint32_t __TZ_get_PSPLIM_NS(void)
+{
+#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)))
+ // without main extensions, the non-secure PSPLIM is RAZ/WI
+ return 0U;
+#else
+ uint32_t result;
+ __ASM volatile ("MRS %0, psplim_ns" : "=r" (result) );
+ return result;
+#endif
+}
+#endif
+
+
+/**
+ \brief Set Process Stack Pointer Limit
+ Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure
+ Stack Pointer Limit register hence the write is silently ignored in non-secure
+ mode.
+
+ \details Assigns the given value to the Process Stack Pointer Limit (PSPLIM).
+ \param [in] ProcStackPtrLimit Process Stack Pointer Limit value to set
+ */
+__STATIC_FORCEINLINE void __set_PSPLIM(uint32_t ProcStackPtrLimit)
+{
+#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \
+ (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3)))
+ // without main extensions, the non-secure PSPLIM is RAZ/WI
+ (void)ProcStackPtrLimit;
+#else
+ __ASM volatile ("MSR psplim, %0" : : "r" (ProcStackPtrLimit));
+#endif
+}
+
+
+#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3))
+/**
+ \brief Set Process Stack Pointer (non-secure)
+ Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure
+ Stack Pointer Limit register hence the write is silently ignored in non-secure
+ mode.
+
+ \details Assigns the given value to the non-secure Process Stack Pointer Limit (PSPLIM) when in secure state.
+ \param [in] ProcStackPtrLimit Process Stack Pointer Limit value to set
+ */
+__STATIC_FORCEINLINE void __TZ_set_PSPLIM_NS(uint32_t ProcStackPtrLimit)
+{
+#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)))
+ // without main extensions, the non-secure PSPLIM is RAZ/WI
+ (void)ProcStackPtrLimit;
+#else
+ __ASM volatile ("MSR psplim_ns, %0\n" : : "r" (ProcStackPtrLimit));
+#endif
+}
+#endif
+
+
+/**
+ \brief Get Main Stack Pointer Limit
+ Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure
+ Stack Pointer Limit register hence zero is returned always.
+
+ \details Returns the current value of the Main Stack Pointer Limit (MSPLIM).
+ \return MSPLIM Register value
+ */
+__STATIC_FORCEINLINE uint32_t __get_MSPLIM(void)
+{
+#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \
+ (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3)))
+ // without main extensions, the non-secure MSPLIM is RAZ/WI
+ return 0U;
+#else
+ uint32_t result;
+ __ASM volatile ("MRS %0, msplim" : "=r" (result) );
+ return result;
+#endif
+}
+
+
+#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3))
+/**
+ \brief Get Main Stack Pointer Limit (non-secure)
+ Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure
+ Stack Pointer Limit register hence zero is returned always.
+
+ \details Returns the current value of the non-secure Main Stack Pointer Limit(MSPLIM) when in secure state.
+ \return MSPLIM Register value
+ */
+__STATIC_FORCEINLINE uint32_t __TZ_get_MSPLIM_NS(void)
+{
+#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)))
+ // without main extensions, the non-secure MSPLIM is RAZ/WI
+ return 0U;
+#else
+ uint32_t result;
+ __ASM volatile ("MRS %0, msplim_ns" : "=r" (result) );
+ return result;
+#endif
+}
+#endif
+
+
+/**
+ \brief Set Main Stack Pointer Limit
+ Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure
+ Stack Pointer Limit register hence the write is silently ignored.
+
+ \details Assigns the given value to the Main Stack Pointer Limit (MSPLIM).
+ \param [in] MainStackPtrLimit Main Stack Pointer Limit value to set
+ */
+__STATIC_FORCEINLINE void __set_MSPLIM(uint32_t MainStackPtrLimit)
+{
+#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \
+ (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3)))
+ // without main extensions, the non-secure MSPLIM is RAZ/WI
+ (void)MainStackPtrLimit;
+#else
+ __ASM volatile ("MSR msplim, %0" : : "r" (MainStackPtrLimit));
+#endif
+}
+
+
+#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3))
+/**
+ \brief Set Main Stack Pointer Limit (non-secure)
+ Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure
+ Stack Pointer Limit register hence the write is silently ignored.
+
+ \details Assigns the given value to the non-secure Main Stack Pointer Limit (MSPLIM) when in secure state.
+ \param [in] MainStackPtrLimit Main Stack Pointer value to set
+ */
+__STATIC_FORCEINLINE void __TZ_set_MSPLIM_NS(uint32_t MainStackPtrLimit)
+{
+#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)))
+ // without main extensions, the non-secure MSPLIM is RAZ/WI
+ (void)MainStackPtrLimit;
+#else
+ __ASM volatile ("MSR msplim_ns, %0" : : "r" (MainStackPtrLimit));
+#endif
+}
+#endif
+
+#endif /* ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \
+ (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) */
+
+/**
+ \brief Get FPSCR
+ \details Returns the current value of the Floating Point Status/Control register.
+ \return Floating Point Status/Control register value
+ */
+#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \
+ (defined (__FPU_USED ) && (__FPU_USED == 1U)) )
+#define __get_FPSCR (uint32_t)__builtin_arm_get_fpscr
+#else
+#define __get_FPSCR() ((uint32_t)0U)
+#endif
+
+/**
+ \brief Set FPSCR
+ \details Assigns the given value to the Floating Point Status/Control register.
+ \param [in] fpscr Floating Point Status/Control value to set
+ */
+#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \
+ (defined (__FPU_USED ) && (__FPU_USED == 1U)) )
+#define __set_FPSCR __builtin_arm_set_fpscr
+#else
+#define __set_FPSCR(x) ((void)(x))
+#endif
+
+
+/*@} end of CMSIS_Core_RegAccFunctions */
+
+
+/* ########################## Core Instruction Access ######################### */
+/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface
+ Access to dedicated instructions
+ @{
+*/
+
+/* Define macros for porting to both thumb1 and thumb2.
+ * For thumb1, use low register (r0-r7), specified by constraint "l"
+ * Otherwise, use general registers, specified by constraint "r" */
+#if defined (__thumb__) && !defined (__thumb2__)
+#define __CMSIS_GCC_OUT_REG(r) "=l" (r)
+#define __CMSIS_GCC_USE_REG(r) "l" (r)
+#else
+#define __CMSIS_GCC_OUT_REG(r) "=r" (r)
+#define __CMSIS_GCC_USE_REG(r) "r" (r)
+#endif
+
+/**
+ \brief No Operation
+ \details No Operation does nothing. This instruction can be used for code alignment purposes.
+ */
+#define __NOP __builtin_arm_nop
+
+/**
+ \brief Wait For Interrupt
+ \details Wait For Interrupt is a hint instruction that suspends execution until one of a number of events occurs.
+ */
+#define __WFI __builtin_arm_wfi
+
+
+/**
+ \brief Wait For Event
+ \details Wait For Event is a hint instruction that permits the processor to enter
+ a low-power state until one of a number of events occurs.
+ */
+#define __WFE __builtin_arm_wfe
+
+
+/**
+ \brief Send Event
+ \details Send Event is a hint instruction. It causes an event to be signaled to the CPU.
+ */
+#define __SEV __builtin_arm_sev
+
+
+/**
+ \brief Instruction Synchronization Barrier
+ \details Instruction Synchronization Barrier flushes the pipeline in the processor,
+ so that all instructions following the ISB are fetched from cache or memory,
+ after the instruction has been completed.
+ */
+#define __ISB() __builtin_arm_isb(0xF)
+
+/**
+ \brief Data Synchronization Barrier
+ \details Acts as a special kind of Data Memory Barrier.
+ It completes when all explicit memory accesses before this instruction complete.
+ */
+#define __DSB() __builtin_arm_dsb(0xF)
+
+
+/**
+ \brief Data Memory Barrier
+ \details Ensures the apparent order of the explicit memory operations before
+ and after the instruction, without ensuring their completion.
+ */
+#define __DMB() __builtin_arm_dmb(0xF)
+
+
+/**
+ \brief Reverse byte order (32 bit)
+ \details Reverses the byte order in unsigned integer value. For example, 0x12345678 becomes 0x78563412.
+ \param [in] value Value to reverse
+ \return Reversed value
+ */
+#define __REV(value) __builtin_bswap32(value)
+
+
+/**
+ \brief Reverse byte order (16 bit)
+ \details Reverses the byte order within each halfword of a word. For example, 0x12345678 becomes 0x34127856.
+ \param [in] value Value to reverse
+ \return Reversed value
+ */
+#define __REV16(value) __ROR(__REV(value), 16)
+
+
+/**
+ \brief Reverse byte order (16 bit)
+ \details Reverses the byte order in a 16-bit value and returns the signed 16-bit result. For example, 0x0080 becomes 0x8000.
+ \param [in] value Value to reverse
+ \return Reversed value
+ */
+#define __REVSH(value) (int16_t)__builtin_bswap16(value)
+
+
+/**
+ \brief Rotate Right in unsigned value (32 bit)
+ \details Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits.
+ \param [in] op1 Value to rotate
+ \param [in] op2 Number of Bits to rotate
+ \return Rotated value
+ */
+__STATIC_FORCEINLINE uint32_t __ROR(uint32_t op1, uint32_t op2)
+{
+ op2 %= 32U;
+ if (op2 == 0U)
+ {
+ return op1;
+ }
+ return (op1 >> op2) | (op1 << (32U - op2));
+}
+
+
+/**
+ \brief Breakpoint
+ \details Causes the processor to enter Debug state.
+ Debug tools can use this to investigate system state when the instruction at a particular address is reached.
+ \param [in] value is ignored by the processor.
+ If required, a debugger can use it to store additional information about the breakpoint.
+ */
+#define __BKPT(value) __ASM volatile ("bkpt "#value)
+
+
+/**
+ \brief Reverse bit order of value
+ \details Reverses the bit order of the given value.
+ \param [in] value Value to reverse
+ \return Reversed value
+ */
+#define __RBIT __builtin_arm_rbit
+
+/**
+ \brief Count leading zeros
+ \details Counts the number of leading zeros of a data value.
+ \param [in] value Value to count the leading zeros
+ \return number of leading zeros in value
+ */
+__STATIC_FORCEINLINE uint8_t __CLZ(uint32_t value)
+{
+ /* Even though __builtin_clz produces a CLZ instruction on ARM, formally
+ __builtin_clz(0) is undefined behaviour, so handle this case specially.
+ This guarantees ARM-compatible results if happening to compile on a non-ARM
+ target, and ensures the compiler doesn't decide to activate any
+ optimisations using the logic "value was passed to __builtin_clz, so it
+ is non-zero".
+ ARM Compiler 6.10 and possibly earlier will optimise this test away, leaving a
+ single CLZ instruction.
+ */
+ if (value == 0U)
+ {
+ return 32U;
+ }
+ return __builtin_clz(value);
+}
+
+
+#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \
+ (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \
+ (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \
+ (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) )
+/**
+ \brief LDR Exclusive (8 bit)
+ \details Executes a exclusive LDR instruction for 8 bit value.
+ \param [in] ptr Pointer to data
+ \return value of type uint8_t at (*ptr)
+ */
+#define __LDREXB (uint8_t)__builtin_arm_ldrex
+
+
+/**
+ \brief LDR Exclusive (16 bit)
+ \details Executes a exclusive LDR instruction for 16 bit values.
+ \param [in] ptr Pointer to data
+ \return value of type uint16_t at (*ptr)
+ */
+#define __LDREXH (uint16_t)__builtin_arm_ldrex
+
+
+/**
+ \brief LDR Exclusive (32 bit)
+ \details Executes a exclusive LDR instruction for 32 bit values.
+ \param [in] ptr Pointer to data
+ \return value of type uint32_t at (*ptr)
+ */
+#define __LDREXW (uint32_t)__builtin_arm_ldrex
+
+
+/**
+ \brief STR Exclusive (8 bit)
+ \details Executes a exclusive STR instruction for 8 bit values.
+ \param [in] value Value to store
+ \param [in] ptr Pointer to location
+ \return 0 Function succeeded
+ \return 1 Function failed
+ */
+#define __STREXB (uint32_t)__builtin_arm_strex
+
+
+/**
+ \brief STR Exclusive (16 bit)
+ \details Executes a exclusive STR instruction for 16 bit values.
+ \param [in] value Value to store
+ \param [in] ptr Pointer to location
+ \return 0 Function succeeded
+ \return 1 Function failed
+ */
+#define __STREXH (uint32_t)__builtin_arm_strex
+
+
+/**
+ \brief STR Exclusive (32 bit)
+ \details Executes a exclusive STR instruction for 32 bit values.
+ \param [in] value Value to store
+ \param [in] ptr Pointer to location
+ \return 0 Function succeeded
+ \return 1 Function failed
+ */
+#define __STREXW (uint32_t)__builtin_arm_strex
+
+
+/**
+ \brief Remove the exclusive lock
+ \details Removes the exclusive lock which is created by LDREX.
+ */
+#define __CLREX __builtin_arm_clrex
+
+#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \
+ (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \
+ (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \
+ (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) */
+
+
+#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \
+ (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \
+ (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) )
+
+/**
+ \brief Signed Saturate
+ \details Saturates a signed value.
+ \param [in] value Value to be saturated
+ \param [in] sat Bit position to saturate to (1..32)
+ \return Saturated value
+ */
+#define __SSAT __builtin_arm_ssat
+
+
+/**
+ \brief Unsigned Saturate
+ \details Saturates an unsigned value.
+ \param [in] value Value to be saturated
+ \param [in] sat Bit position to saturate to (0..31)
+ \return Saturated value
+ */
+#define __USAT __builtin_arm_usat
+
+
+/**
+ \brief Rotate Right with Extend (32 bit)
+ \details Moves each bit of a bitstring right by one bit.
+ The carry input is shifted in at the left end of the bitstring.
+ \param [in] value Value to rotate
+ \return Rotated value
+ */
+__STATIC_FORCEINLINE uint32_t __RRX(uint32_t value)
+{
+ uint32_t result;
+
+ __ASM volatile ("rrx %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) );
+ return(result);
+}
+
+
+/**
+ \brief LDRT Unprivileged (8 bit)
+ \details Executes a Unprivileged LDRT instruction for 8 bit value.
+ \param [in] ptr Pointer to data
+ \return value of type uint8_t at (*ptr)
+ */
+__STATIC_FORCEINLINE uint8_t __LDRBT(volatile uint8_t *ptr)
+{
+ uint32_t result;
+
+ __ASM volatile ("ldrbt %0, %1" : "=r" (result) : "Q" (*ptr) );
+ return ((uint8_t) result); /* Add explicit type cast here */
+}
+
+
+/**
+ \brief LDRT Unprivileged (16 bit)
+ \details Executes a Unprivileged LDRT instruction for 16 bit values.
+ \param [in] ptr Pointer to data
+ \return value of type uint16_t at (*ptr)
+ */
+__STATIC_FORCEINLINE uint16_t __LDRHT(volatile uint16_t *ptr)
+{
+ uint32_t result;
+
+ __ASM volatile ("ldrht %0, %1" : "=r" (result) : "Q" (*ptr) );
+ return ((uint16_t) result); /* Add explicit type cast here */
+}
+
+
+/**
+ \brief LDRT Unprivileged (32 bit)
+ \details Executes a Unprivileged LDRT instruction for 32 bit values.
+ \param [in] ptr Pointer to data
+ \return value of type uint32_t at (*ptr)
+ */
+__STATIC_FORCEINLINE uint32_t __LDRT(volatile uint32_t *ptr)
+{
+ uint32_t result;
+
+ __ASM volatile ("ldrt %0, %1" : "=r" (result) : "Q" (*ptr) );
+ return(result);
+}
+
+
+/**
+ \brief STRT Unprivileged (8 bit)
+ \details Executes a Unprivileged STRT instruction for 8 bit values.
+ \param [in] value Value to store
+ \param [in] ptr Pointer to location
+ */
+__STATIC_FORCEINLINE void __STRBT(uint8_t value, volatile uint8_t *ptr)
+{
+ __ASM volatile ("strbt %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) );
+}
+
+
+/**
+ \brief STRT Unprivileged (16 bit)
+ \details Executes a Unprivileged STRT instruction for 16 bit values.
+ \param [in] value Value to store
+ \param [in] ptr Pointer to location
+ */
+__STATIC_FORCEINLINE void __STRHT(uint16_t value, volatile uint16_t *ptr)
+{
+ __ASM volatile ("strht %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) );
+}
+
+
+/**
+ \brief STRT Unprivileged (32 bit)
+ \details Executes a Unprivileged STRT instruction for 32 bit values.
+ \param [in] value Value to store
+ \param [in] ptr Pointer to location
+ */
+__STATIC_FORCEINLINE void __STRT(uint32_t value, volatile uint32_t *ptr)
+{
+ __ASM volatile ("strt %1, %0" : "=Q" (*ptr) : "r" (value) );
+}
+
+#else /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \
+ (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \
+ (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) */
+
+/**
+ \brief Signed Saturate
+ \details Saturates a signed value.
+ \param [in] value Value to be saturated
+ \param [in] sat Bit position to saturate to (1..32)
+ \return Saturated value
+ */
+__STATIC_FORCEINLINE int32_t __SSAT(int32_t val, uint32_t sat)
+{
+ if ((sat >= 1U) && (sat <= 32U))
+ {
+ const int32_t max = (int32_t)((1U << (sat - 1U)) - 1U);
+ const int32_t min = -1 - max ;
+ if (val > max)
+ {
+ return max;
+ }
+ else if (val < min)
+ {
+ return min;
+ }
+ }
+ return val;
+}
+
+/**
+ \brief Unsigned Saturate
+ \details Saturates an unsigned value.
+ \param [in] value Value to be saturated
+ \param [in] sat Bit position to saturate to (0..31)
+ \return Saturated value
+ */
+__STATIC_FORCEINLINE uint32_t __USAT(int32_t val, uint32_t sat)
+{
+ if (sat <= 31U)
+ {
+ const uint32_t max = ((1U << sat) - 1U);
+ if (val > (int32_t)max)
+ {
+ return max;
+ }
+ else if (val < 0)
+ {
+ return 0U;
+ }
+ }
+ return (uint32_t)val;
+}
+
+#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \
+ (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \
+ (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) */
+
+
+#if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \
+ (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) )
+/**
+ \brief Load-Acquire (8 bit)
+ \details Executes a LDAB instruction for 8 bit value.
+ \param [in] ptr Pointer to data
+ \return value of type uint8_t at (*ptr)
+ */
+__STATIC_FORCEINLINE uint8_t __LDAB(volatile uint8_t *ptr)
+{
+ uint32_t result;
+
+ __ASM volatile ("ldab %0, %1" : "=r" (result) : "Q" (*ptr) );
+ return ((uint8_t) result);
+}
+
+
+/**
+ \brief Load-Acquire (16 bit)
+ \details Executes a LDAH instruction for 16 bit values.
+ \param [in] ptr Pointer to data
+ \return value of type uint16_t at (*ptr)
+ */
+__STATIC_FORCEINLINE uint16_t __LDAH(volatile uint16_t *ptr)
+{
+ uint32_t result;
+
+ __ASM volatile ("ldah %0, %1" : "=r" (result) : "Q" (*ptr) );
+ return ((uint16_t) result);
+}
+
+
+/**
+ \brief Load-Acquire (32 bit)
+ \details Executes a LDA instruction for 32 bit values.
+ \param [in] ptr Pointer to data
+ \return value of type uint32_t at (*ptr)
+ */
+__STATIC_FORCEINLINE uint32_t __LDA(volatile uint32_t *ptr)
+{
+ uint32_t result;
+
+ __ASM volatile ("lda %0, %1" : "=r" (result) : "Q" (*ptr) );
+ return(result);
+}
+
+
+/**
+ \brief Store-Release (8 bit)
+ \details Executes a STLB instruction for 8 bit values.
+ \param [in] value Value to store
+ \param [in] ptr Pointer to location
+ */
+__STATIC_FORCEINLINE void __STLB(uint8_t value, volatile uint8_t *ptr)
+{
+ __ASM volatile ("stlb %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) );
+}
+
+
+/**
+ \brief Store-Release (16 bit)
+ \details Executes a STLH instruction for 16 bit values.
+ \param [in] value Value to store
+ \param [in] ptr Pointer to location
+ */
+__STATIC_FORCEINLINE void __STLH(uint16_t value, volatile uint16_t *ptr)
+{
+ __ASM volatile ("stlh %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) );
+}
+
+
+/**
+ \brief Store-Release (32 bit)
+ \details Executes a STL instruction for 32 bit values.
+ \param [in] value Value to store
+ \param [in] ptr Pointer to location
+ */
+__STATIC_FORCEINLINE void __STL(uint32_t value, volatile uint32_t *ptr)
+{
+ __ASM volatile ("stl %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) );
+}
+
+
+/**
+ \brief Load-Acquire Exclusive (8 bit)
+ \details Executes a LDAB exclusive instruction for 8 bit value.
+ \param [in] ptr Pointer to data
+ \return value of type uint8_t at (*ptr)
+ */
+#define __LDAEXB (uint8_t)__builtin_arm_ldaex
+
+
+/**
+ \brief Load-Acquire Exclusive (16 bit)
+ \details Executes a LDAH exclusive instruction for 16 bit values.
+ \param [in] ptr Pointer to data
+ \return value of type uint16_t at (*ptr)
+ */
+#define __LDAEXH (uint16_t)__builtin_arm_ldaex
+
+
+/**
+ \brief Load-Acquire Exclusive (32 bit)
+ \details Executes a LDA exclusive instruction for 32 bit values.
+ \param [in] ptr Pointer to data
+ \return value of type uint32_t at (*ptr)
+ */
+#define __LDAEX (uint32_t)__builtin_arm_ldaex
+
+
+/**
+ \brief Store-Release Exclusive (8 bit)
+ \details Executes a STLB exclusive instruction for 8 bit values.
+ \param [in] value Value to store
+ \param [in] ptr Pointer to location
+ \return 0 Function succeeded
+ \return 1 Function failed
+ */
+#define __STLEXB (uint32_t)__builtin_arm_stlex
+
+
+/**
+ \brief Store-Release Exclusive (16 bit)
+ \details Executes a STLH exclusive instruction for 16 bit values.
+ \param [in] value Value to store
+ \param [in] ptr Pointer to location
+ \return 0 Function succeeded
+ \return 1 Function failed
+ */
+#define __STLEXH (uint32_t)__builtin_arm_stlex
+
+
+/**
+ \brief Store-Release Exclusive (32 bit)
+ \details Executes a STL exclusive instruction for 32 bit values.
+ \param [in] value Value to store
+ \param [in] ptr Pointer to location
+ \return 0 Function succeeded
+ \return 1 Function failed
+ */
+#define __STLEX (uint32_t)__builtin_arm_stlex
+
+#endif /* ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \
+ (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) */
+
+/*@}*/ /* end of group CMSIS_Core_InstructionInterface */
+
+
+/* ################### Compiler specific Intrinsics ########################### */
+/** \defgroup CMSIS_SIMD_intrinsics CMSIS SIMD Intrinsics
+ Access to dedicated SIMD instructions
+ @{
+*/
+
+#if (defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1))
+
+__STATIC_FORCEINLINE uint32_t __SADD8(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("sadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __QADD8(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("qadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __SHADD8(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("shadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __UADD8(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("uadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __UQADD8(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("uqadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __UHADD8(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("uhadd8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+
+__STATIC_FORCEINLINE uint32_t __SSUB8(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("ssub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __QSUB8(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("qsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __SHSUB8(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("shsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __USUB8(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("usub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __UQSUB8(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("uqsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __UHSUB8(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("uhsub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+
+__STATIC_FORCEINLINE uint32_t __SADD16(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("sadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __QADD16(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("qadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __SHADD16(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("shadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __UADD16(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("uadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __UQADD16(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("uqadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __UHADD16(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("uhadd16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __SSUB16(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("ssub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __QSUB16(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("qsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __SHSUB16(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("shsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __USUB16(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("usub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __UQSUB16(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("uqsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __UHSUB16(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("uhsub16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __SASX(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("sasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __QASX(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("qasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __SHASX(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("shasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __UASX(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("uasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __UQASX(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("uqasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __UHASX(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("uhasx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __SSAX(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("ssax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __QSAX(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("qsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __SHSAX(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("shsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __USAX(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("usax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __UQSAX(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("uqsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __UHSAX(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("uhsax %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __USAD8(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("usad8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __USADA8(uint32_t op1, uint32_t op2, uint32_t op3)
+{
+ uint32_t result;
+
+ __ASM volatile ("usada8 %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) );
+ return(result);
+}
+
+#define __SSAT16(ARG1,ARG2) \
+({ \
+ int32_t __RES, __ARG1 = (ARG1); \
+ __ASM ("ssat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \
+ __RES; \
+ })
+
+#define __USAT16(ARG1,ARG2) \
+({ \
+ uint32_t __RES, __ARG1 = (ARG1); \
+ __ASM ("usat16 %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \
+ __RES; \
+ })
+
+__STATIC_FORCEINLINE uint32_t __UXTB16(uint32_t op1)
+{
+ uint32_t result;
+
+ __ASM volatile ("uxtb16 %0, %1" : "=r" (result) : "r" (op1));
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __UXTAB16(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("uxtab16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __SXTB16(uint32_t op1)
+{
+ uint32_t result;
+
+ __ASM volatile ("sxtb16 %0, %1" : "=r" (result) : "r" (op1));
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __SXTAB16(uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("sxtab16 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __SMUAD (uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("smuad %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __SMUADX (uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("smuadx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __SMLAD (uint32_t op1, uint32_t op2, uint32_t op3)
+{
+ uint32_t result;
+
+ __ASM volatile ("smlad %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __SMLADX (uint32_t op1, uint32_t op2, uint32_t op3)
+{
+ uint32_t result;
+
+ __ASM volatile ("smladx %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint64_t __SMLALD (uint32_t op1, uint32_t op2, uint64_t acc)
+{
+ union llreg_u{
+ uint32_t w32[2];
+ uint64_t w64;
+ } llr;
+ llr.w64 = acc;
+
+#ifndef __ARMEB__ /* Little endian */
+ __ASM volatile ("smlald %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) );
+#else /* Big endian */
+ __ASM volatile ("smlald %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) );
+#endif
+
+ return(llr.w64);
+}
+
+__STATIC_FORCEINLINE uint64_t __SMLALDX (uint32_t op1, uint32_t op2, uint64_t acc)
+{
+ union llreg_u{
+ uint32_t w32[2];
+ uint64_t w64;
+ } llr;
+ llr.w64 = acc;
+
+#ifndef __ARMEB__ /* Little endian */
+ __ASM volatile ("smlaldx %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) );
+#else /* Big endian */
+ __ASM volatile ("smlaldx %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) );
+#endif
+
+ return(llr.w64);
+}
+
+__STATIC_FORCEINLINE uint32_t __SMUSD (uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("smusd %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __SMUSDX (uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("smusdx %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __SMLSD (uint32_t op1, uint32_t op2, uint32_t op3)
+{
+ uint32_t result;
+
+ __ASM volatile ("smlsd %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint32_t __SMLSDX (uint32_t op1, uint32_t op2, uint32_t op3)
+{
+ uint32_t result;
+
+ __ASM volatile ("smlsdx %0, %1, %2, %3" : "=r" (result) : "r" (op1), "r" (op2), "r" (op3) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE uint64_t __SMLSLD (uint32_t op1, uint32_t op2, uint64_t acc)
+{
+ union llreg_u{
+ uint32_t w32[2];
+ uint64_t w64;
+ } llr;
+ llr.w64 = acc;
+
+#ifndef __ARMEB__ /* Little endian */
+ __ASM volatile ("smlsld %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) );
+#else /* Big endian */
+ __ASM volatile ("smlsld %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) );
+#endif
+
+ return(llr.w64);
+}
+
+__STATIC_FORCEINLINE uint64_t __SMLSLDX (uint32_t op1, uint32_t op2, uint64_t acc)
+{
+ union llreg_u{
+ uint32_t w32[2];
+ uint64_t w64;
+ } llr;
+ llr.w64 = acc;
+
+#ifndef __ARMEB__ /* Little endian */
+ __ASM volatile ("smlsldx %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) );
+#else /* Big endian */
+ __ASM volatile ("smlsldx %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) );
+#endif
+
+ return(llr.w64);
+}
+
+__STATIC_FORCEINLINE uint32_t __SEL (uint32_t op1, uint32_t op2)
+{
+ uint32_t result;
+
+ __ASM volatile ("sel %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE int32_t __QADD( int32_t op1, int32_t op2)
+{
+ int32_t result;
+
+ __ASM volatile ("qadd %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+__STATIC_FORCEINLINE int32_t __QSUB( int32_t op1, int32_t op2)
+{
+ int32_t result;
+
+ __ASM volatile ("qsub %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) );
+ return(result);
+}
+
+#define __PKHBT(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0x0000FFFFUL) | \
+ ((((uint32_t)(ARG2)) << (ARG3)) & 0xFFFF0000UL) )
+
+#define __PKHTB(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0xFFFF0000UL) | \
+ ((((uint32_t)(ARG2)) >> (ARG3)) & 0x0000FFFFUL) )
+
+__STATIC_FORCEINLINE int32_t __SMMLA (int32_t op1, int32_t op2, int32_t op3)
+{
+ int32_t result;
+
+ __ASM volatile ("smmla %0, %1, %2, %3" : "=r" (result): "r" (op1), "r" (op2), "r" (op3) );
+ return(result);
+}
+
+#endif /* (__ARM_FEATURE_DSP == 1) */
+/*@} end of group CMSIS_SIMD_intrinsics */
+
+
+#endif /* __CMSIS_ARMCLANG_H */
diff --git a/lib/cmsis/inc/cmsis_compiler.h b/lib/cmsis/inc/cmsis_compiler.h
new file mode 100644
index 0000000000..fdb1a971c6
--- /dev/null
+++ b/lib/cmsis/inc/cmsis_compiler.h
@@ -0,0 +1,271 @@
+/**************************************************************************//**
+ * @file cmsis_compiler.h
+ * @brief CMSIS compiler generic header file
+ * @version V5.1.0
+ * @date 09. October 2018
+ ******************************************************************************/
+/*
+ * Copyright (c) 2009-2018 Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __CMSIS_COMPILER_H
+#define __CMSIS_COMPILER_H
+
+#include
+
+/*
+ * Arm Compiler 4/5
+ */
+#if defined ( __CC_ARM )
+ #include "cmsis_armcc.h"
+
+
+/*
+ * Arm Compiler 6.6 LTM (armclang)
+ */
+#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) && (__ARMCC_VERSION < 6100100)
+ #include "cmsis_armclang_ltm.h"
+
+ /*
+ * Arm Compiler above 6.10.1 (armclang)
+ */
+#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6100100)
+ #include "cmsis_armclang.h"
+
+
+/*
+ * GNU Compiler
+ */
+#elif defined ( __GNUC__ )
+ #include "cmsis_gcc.h"
+
+
+/*
+ * IAR Compiler
+ */
+#elif defined ( __ICCARM__ )
+ #include
+
+
+/*
+ * TI Arm Compiler
+ */
+#elif defined ( __TI_ARM__ )
+ #include
+
+ #ifndef __ASM
+ #define __ASM __asm
+ #endif
+ #ifndef __INLINE
+ #define __INLINE inline
+ #endif
+ #ifndef __STATIC_INLINE
+ #define __STATIC_INLINE static inline
+ #endif
+ #ifndef __STATIC_FORCEINLINE
+ #define __STATIC_FORCEINLINE __STATIC_INLINE
+ #endif
+ #ifndef __NO_RETURN
+ #define __NO_RETURN __attribute__((noreturn))
+ #endif
+ #ifndef __USED
+ #define __USED __attribute__((used))
+ #endif
+ #ifndef __WEAK
+ #define __WEAK __attribute__((weak))
+ #endif
+ #ifndef __PACKED
+ #define __PACKED __attribute__((packed))
+ #endif
+ #ifndef __PACKED_STRUCT
+ #define __PACKED_STRUCT struct __attribute__((packed))
+ #endif
+ #ifndef __PACKED_UNION
+ #define __PACKED_UNION union __attribute__((packed))
+ #endif
+ #ifndef __UNALIGNED_UINT32 /* deprecated */
+ struct __attribute__((packed)) T_UINT32 { uint32_t v; };
+ #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v)
+ #endif
+ #ifndef __UNALIGNED_UINT16_WRITE
+ __PACKED_STRUCT T_UINT16_WRITE { uint16_t v; };
+ #define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void*)(addr))->v) = (val))
+ #endif
+ #ifndef __UNALIGNED_UINT16_READ
+ __PACKED_STRUCT T_UINT16_READ { uint16_t v; };
+ #define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v)
+ #endif
+ #ifndef __UNALIGNED_UINT32_WRITE
+ __PACKED_STRUCT T_UINT32_WRITE { uint32_t v; };
+ #define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val))
+ #endif
+ #ifndef __UNALIGNED_UINT32_READ
+ __PACKED_STRUCT T_UINT32_READ { uint32_t v; };
+ #define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v)
+ #endif
+ #ifndef __ALIGNED
+ #define __ALIGNED(x) __attribute__((aligned(x)))
+ #endif
+ #ifndef __RESTRICT
+ #define __RESTRICT __restrict
+ #endif
+
+
+/*
+ * TASKING Compiler
+ */
+#elif defined ( __TASKING__ )
+ /*
+ * The CMSIS functions have been implemented as intrinsics in the compiler.
+ * Please use "carm -?i" to get an up to date list of all intrinsics,
+ * Including the CMSIS ones.
+ */
+
+ #ifndef __ASM
+ #define __ASM __asm
+ #endif
+ #ifndef __INLINE
+ #define __INLINE inline
+ #endif
+ #ifndef __STATIC_INLINE
+ #define __STATIC_INLINE static inline
+ #endif
+ #ifndef __STATIC_FORCEINLINE
+ #define __STATIC_FORCEINLINE __STATIC_INLINE
+ #endif
+ #ifndef __NO_RETURN
+ #define __NO_RETURN __attribute__((noreturn))
+ #endif
+ #ifndef __USED
+ #define __USED __attribute__((used))
+ #endif
+ #ifndef __WEAK
+ #define __WEAK __attribute__((weak))
+ #endif
+ #ifndef __PACKED
+ #define __PACKED __packed__
+ #endif
+ #ifndef __PACKED_STRUCT
+ #define __PACKED_STRUCT struct __packed__
+ #endif
+ #ifndef __PACKED_UNION
+ #define __PACKED_UNION union __packed__
+ #endif
+ #ifndef __UNALIGNED_UINT32 /* deprecated */
+ struct __packed__ T_UINT32 { uint32_t v; };
+ #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v)
+ #endif
+ #ifndef __UNALIGNED_UINT16_WRITE
+ __PACKED_STRUCT T_UINT16_WRITE { uint16_t v; };
+ #define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val))
+ #endif
+ #ifndef __UNALIGNED_UINT16_READ
+ __PACKED_STRUCT T_UINT16_READ { uint16_t v; };
+ #define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v)
+ #endif
+ #ifndef __UNALIGNED_UINT32_WRITE
+ __PACKED_STRUCT T_UINT32_WRITE { uint32_t v; };
+ #define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val))
+ #endif
+ #ifndef __UNALIGNED_UINT32_READ
+ __PACKED_STRUCT T_UINT32_READ { uint32_t v; };
+ #define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v)
+ #endif
+ #ifndef __ALIGNED
+ #define __ALIGNED(x) __align(x)
+ #endif
+ #ifndef __RESTRICT
+ #warning No compiler specific solution for __RESTRICT. __RESTRICT is ignored.
+ #define __RESTRICT
+ #endif
+
+
+/*
+ * COSMIC Compiler
+ */
+#elif defined ( __CSMC__ )
+ #include
+
+ #ifndef __ASM
+ #define __ASM _asm
+ #endif
+ #ifndef __INLINE
+ #define __INLINE inline
+ #endif
+ #ifndef __STATIC_INLINE
+ #define __STATIC_INLINE static inline
+ #endif
+ #ifndef __STATIC_FORCEINLINE
+ #define __STATIC_FORCEINLINE __STATIC_INLINE
+ #endif
+ #ifndef __NO_RETURN
+ // NO RETURN is automatically detected hence no warning here
+ #define __NO_RETURN
+ #endif
+ #ifndef __USED
+ #warning No compiler specific solution for __USED. __USED is ignored.
+ #define __USED
+ #endif
+ #ifndef __WEAK
+ #define __WEAK __weak
+ #endif
+ #ifndef __PACKED
+ #define __PACKED @packed
+ #endif
+ #ifndef __PACKED_STRUCT
+ #define __PACKED_STRUCT @packed struct
+ #endif
+ #ifndef __PACKED_UNION
+ #define __PACKED_UNION @packed union
+ #endif
+ #ifndef __UNALIGNED_UINT32 /* deprecated */
+ @packed struct T_UINT32 { uint32_t v; };
+ #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v)
+ #endif
+ #ifndef __UNALIGNED_UINT16_WRITE
+ __PACKED_STRUCT T_UINT16_WRITE { uint16_t v; };
+ #define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val))
+ #endif
+ #ifndef __UNALIGNED_UINT16_READ
+ __PACKED_STRUCT T_UINT16_READ { uint16_t v; };
+ #define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v)
+ #endif
+ #ifndef __UNALIGNED_UINT32_WRITE
+ __PACKED_STRUCT T_UINT32_WRITE { uint32_t v; };
+ #define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val))
+ #endif
+ #ifndef __UNALIGNED_UINT32_READ
+ __PACKED_STRUCT T_UINT32_READ { uint32_t v; };
+ #define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v)
+ #endif
+ #ifndef __ALIGNED
+ #warning No compiler specific solution for __ALIGNED. __ALIGNED is ignored.
+ #define __ALIGNED(x)
+ #endif
+ #ifndef __RESTRICT
+ #warning No compiler specific solution for __RESTRICT. __RESTRICT is ignored.
+ #define __RESTRICT
+ #endif
+
+
+#else
+ #error Unknown compiler.
+#endif
+
+
+#endif /* __CMSIS_COMPILER_H */
+
diff --git a/lib/cmsis/inc/cmsis_gcc.h b/lib/cmsis/inc/cmsis_gcc.h
index bb89fbba9e..d86b0a2d5a 100644
--- a/lib/cmsis/inc/cmsis_gcc.h
+++ b/lib/cmsis/inc/cmsis_gcc.h
@@ -1,46 +1,117 @@
/**************************************************************************//**
* @file cmsis_gcc.h
- * @brief CMSIS Cortex-M Core Function/Instruction Header File
- * @version V4.30
- * @date 20. October 2015
+ * @brief CMSIS compiler GCC header file
+ * @version V5.1.0
+ * @date 20. December 2018
******************************************************************************/
-/* Copyright (c) 2009 - 2015 ARM LIMITED
-
- All rights reserved.
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are met:
- - Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- - Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
- - Neither the name of ARM nor the names of its contributors may be used
- to endorse or promote products derived from this software without
- specific prior written permission.
- *
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE
- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- POSSIBILITY OF SUCH DAMAGE.
- ---------------------------------------------------------------------------*/
-
+/*
+ * Copyright (c) 2009-2018 Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
#ifndef __CMSIS_GCC_H
#define __CMSIS_GCC_H
/* ignore some GCC warnings */
-#if defined ( __GNUC__ )
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wsign-conversion"
#pragma GCC diagnostic ignored "-Wconversion"
#pragma GCC diagnostic ignored "-Wunused-parameter"
+
+/* Fallback for __has_builtin */
+#ifndef __has_builtin
+ #define __has_builtin(x) (0)
+#endif
+
+/* CMSIS compiler specific defines */
+#ifndef __ASM
+ #define __ASM __asm
+#endif
+#ifndef __INLINE
+ #define __INLINE inline
+#endif
+#ifndef __STATIC_INLINE
+ #define __STATIC_INLINE static inline
+#endif
+#ifndef __STATIC_FORCEINLINE
+ #define __STATIC_FORCEINLINE __attribute__((always_inline)) static inline
+#endif
+#ifndef __NO_RETURN
+ #define __NO_RETURN __attribute__((__noreturn__))
+#endif
+#ifndef __USED
+ #define __USED __attribute__((used))
+#endif
+#ifndef __WEAK
+ #define __WEAK __attribute__((weak))
+#endif
+#ifndef __PACKED
+ #define __PACKED __attribute__((packed, aligned(1)))
+#endif
+#ifndef __PACKED_STRUCT
+ #define __PACKED_STRUCT struct __attribute__((packed, aligned(1)))
+#endif
+#ifndef __PACKED_UNION
+ #define __PACKED_UNION union __attribute__((packed, aligned(1)))
+#endif
+#ifndef __UNALIGNED_UINT32 /* deprecated */
+ #pragma GCC diagnostic push
+ #pragma GCC diagnostic ignored "-Wpacked"
+ #pragma GCC diagnostic ignored "-Wattributes"
+ struct __attribute__((packed)) T_UINT32 { uint32_t v; };
+ #pragma GCC diagnostic pop
+ #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v)
+#endif
+#ifndef __UNALIGNED_UINT16_WRITE
+ #pragma GCC diagnostic push
+ #pragma GCC diagnostic ignored "-Wpacked"
+ #pragma GCC diagnostic ignored "-Wattributes"
+ __PACKED_STRUCT T_UINT16_WRITE { uint16_t v; };
+ #pragma GCC diagnostic pop
+ #define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val))
+#endif
+#ifndef __UNALIGNED_UINT16_READ
+ #pragma GCC diagnostic push
+ #pragma GCC diagnostic ignored "-Wpacked"
+ #pragma GCC diagnostic ignored "-Wattributes"
+ __PACKED_STRUCT T_UINT16_READ { uint16_t v; };
+ #pragma GCC diagnostic pop
+ #define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v)
+#endif
+#ifndef __UNALIGNED_UINT32_WRITE
+ #pragma GCC diagnostic push
+ #pragma GCC diagnostic ignored "-Wpacked"
+ #pragma GCC diagnostic ignored "-Wattributes"
+ __PACKED_STRUCT T_UINT32_WRITE { uint32_t v; };
+ #pragma GCC diagnostic pop
+ #define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val))
+#endif
+#ifndef __UNALIGNED_UINT32_READ
+ #pragma GCC diagnostic push
+ #pragma GCC diagnostic ignored "-Wpacked"
+ #pragma GCC diagnostic ignored "-Wattributes"
+ __PACKED_STRUCT T_UINT32_READ { uint32_t v; };
+ #pragma GCC diagnostic pop
+ #define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v)
+#endif
+#ifndef __ALIGNED
+ #define __ALIGNED(x) __attribute__((aligned(x)))
+#endif
+#ifndef __RESTRICT
+ #define __RESTRICT __restrict
#endif
@@ -55,7 +126,7 @@
\details Enables IRQ interrupts by clearing the I-bit in the CPSR.
Can only be executed in Privileged modes.
*/
-__attribute__( ( always_inline ) ) __STATIC_INLINE void __enable_irq(void)
+__STATIC_FORCEINLINE void __enable_irq(void)
{
__ASM volatile ("cpsie i" : : : "memory");
}
@@ -64,9 +135,9 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE void __enable_irq(void)
/**
\brief Disable IRQ Interrupts
\details Disables IRQ interrupts by setting the I-bit in the CPSR.
- Can only be executed in Privileged modes.
+ Can only be executed in Privileged modes.
*/
-__attribute__( ( always_inline ) ) __STATIC_INLINE void __disable_irq(void)
+__STATIC_FORCEINLINE void __disable_irq(void)
{
__ASM volatile ("cpsid i" : : : "memory");
}
@@ -77,7 +148,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE void __disable_irq(void)
\details Returns the content of the Control Register.
\return Control Register value
*/
-__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_CONTROL(void)
+__STATIC_FORCEINLINE uint32_t __get_CONTROL(void)
{
uint32_t result;
@@ -86,23 +157,52 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_CONTROL(void)
}
+#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3))
+/**
+ \brief Get Control Register (non-secure)
+ \details Returns the content of the non-secure Control Register when in secure mode.
+ \return non-secure Control Register value
+ */
+__STATIC_FORCEINLINE uint32_t __TZ_get_CONTROL_NS(void)
+{
+ uint32_t result;
+
+ __ASM volatile ("MRS %0, control_ns" : "=r" (result) );
+ return(result);
+}
+#endif
+
+
/**
\brief Set Control Register
\details Writes the given value to the Control Register.
\param [in] control Control Register value to set
*/
-__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_CONTROL(uint32_t control)
+__STATIC_FORCEINLINE void __set_CONTROL(uint32_t control)
{
__ASM volatile ("MSR control, %0" : : "r" (control) : "memory");
}
+#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3))
+/**
+ \brief Set Control Register (non-secure)
+ \details Writes the given value to the non-secure Control Register when in secure state.
+ \param [in] control Control Register value to set
+ */
+__STATIC_FORCEINLINE void __TZ_set_CONTROL_NS(uint32_t control)
+{
+ __ASM volatile ("MSR control_ns, %0" : : "r" (control) : "memory");
+}
+#endif
+
+
/**
\brief Get IPSR Register
\details Returns the content of the IPSR Register.
\return IPSR Register value
*/
-__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_IPSR(void)
+__STATIC_FORCEINLINE uint32_t __get_IPSR(void)
{
uint32_t result;
@@ -116,7 +216,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_IPSR(void)
\details Returns the content of the APSR Register.
\return APSR Register value
*/
-__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_APSR(void)
+__STATIC_FORCEINLINE uint32_t __get_APSR(void)
{
uint32_t result;
@@ -128,10 +228,9 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_APSR(void)
/**
\brief Get xPSR Register
\details Returns the content of the xPSR Register.
-
- \return xPSR Register value
+ \return xPSR Register value
*/
-__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_xPSR(void)
+__STATIC_FORCEINLINE uint32_t __get_xPSR(void)
{
uint32_t result;
@@ -145,24 +244,53 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_xPSR(void)
\details Returns the current value of the Process Stack Pointer (PSP).
\return PSP Register value
*/
-__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_PSP(void)
+__STATIC_FORCEINLINE uint32_t __get_PSP(void)
{
- register uint32_t result;
+ uint32_t result;
- __ASM volatile ("MRS %0, psp\n" : "=r" (result) );
+ __ASM volatile ("MRS %0, psp" : "=r" (result) );
return(result);
}
+#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3))
+/**
+ \brief Get Process Stack Pointer (non-secure)
+ \details Returns the current value of the non-secure Process Stack Pointer (PSP) when in secure state.
+ \return PSP Register value
+ */
+__STATIC_FORCEINLINE uint32_t __TZ_get_PSP_NS(void)
+{
+ uint32_t result;
+
+ __ASM volatile ("MRS %0, psp_ns" : "=r" (result) );
+ return(result);
+}
+#endif
+
+
/**
\brief Set Process Stack Pointer
\details Assigns the given value to the Process Stack Pointer (PSP).
\param [in] topOfProcStack Process Stack Pointer value to set
*/
-__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_PSP(uint32_t topOfProcStack)
+__STATIC_FORCEINLINE void __set_PSP(uint32_t topOfProcStack)
+{
+ __ASM volatile ("MSR psp, %0" : : "r" (topOfProcStack) : );
+}
+
+
+#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3))
+/**
+ \brief Set Process Stack Pointer (non-secure)
+ \details Assigns the given value to the non-secure Process Stack Pointer (PSP) when in secure state.
+ \param [in] topOfProcStack Process Stack Pointer value to set
+ */
+__STATIC_FORCEINLINE void __TZ_set_PSP_NS(uint32_t topOfProcStack)
{
- __ASM volatile ("MSR psp, %0\n" : : "r" (topOfProcStack) : "sp");
+ __ASM volatile ("MSR psp_ns, %0" : : "r" (topOfProcStack) : );
}
+#endif
/**
@@ -170,25 +298,80 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE void __set_PSP(uint32_t topOf
\details Returns the current value of the Main Stack Pointer (MSP).
\return MSP Register value
*/
-__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_MSP(void)
+__STATIC_FORCEINLINE uint32_t __get_MSP(void)
{
- register uint32_t result;
+ uint32_t result;
- __ASM volatile ("MRS %0, msp\n" : "=r" (result) );
+ __ASM volatile ("MRS %0, msp" : "=r" (result) );
return(result);
}
+#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3))
+/**
+ \brief Get Main Stack Pointer (non-secure)
+ \details Returns the current value of the non-secure Main Stack Pointer (MSP) when in secure state.
+ \return MSP Register value
+ */
+__STATIC_FORCEINLINE uint32_t __TZ_get_MSP_NS(void)
+{
+ uint32_t result;
+
+ __ASM volatile ("MRS %0, msp_ns" : "=r" (result) );
+ return(result);
+}
+#endif
+
+
/**
\brief Set Main Stack Pointer
\details Assigns the given value to the Main Stack Pointer (MSP).
+ \param [in] topOfMainStack Main Stack Pointer value to set
+ */
+__STATIC_FORCEINLINE void __set_MSP(uint32_t topOfMainStack)
+{
+ __ASM volatile ("MSR msp, %0" : : "r" (topOfMainStack) : );
+}
+
- \param [in] topOfMainStack Main Stack Pointer value to set
+#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3))
+/**
+ \brief Set Main Stack Pointer (non-secure)
+ \details Assigns the given value to the non-secure Main Stack Pointer (MSP) when in secure state.
+ \param [in] topOfMainStack Main Stack Pointer value to set
*/
-__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_MSP(uint32_t topOfMainStack)
+__STATIC_FORCEINLINE void __TZ_set_MSP_NS(uint32_t topOfMainStack)
{
- __ASM volatile ("MSR msp, %0\n" : : "r" (topOfMainStack) : "sp");
+ __ASM volatile ("MSR msp_ns, %0" : : "r" (topOfMainStack) : );
}
+#endif
+
+
+#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3))
+/**
+ \brief Get Stack Pointer (non-secure)
+ \details Returns the current value of the non-secure Stack Pointer (SP) when in secure state.
+ \return SP Register value
+ */
+__STATIC_FORCEINLINE uint32_t __TZ_get_SP_NS(void)
+{
+ uint32_t result;
+
+ __ASM volatile ("MRS %0, sp_ns" : "=r" (result) );
+ return(result);
+}
+
+
+/**
+ \brief Set Stack Pointer (non-secure)
+ \details Assigns the given value to the non-secure Stack Pointer (SP) when in secure state.
+ \param [in] topOfStack Stack Pointer value to set
+ */
+__STATIC_FORCEINLINE void __TZ_set_SP_NS(uint32_t topOfStack)
+{
+ __ASM volatile ("MSR sp_ns, %0" : : "r" (topOfStack) : );
+}
+#endif
/**
@@ -196,34 +379,64 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE void __set_MSP(uint32_t topOf
\details Returns the current state of the priority mask bit from the Priority Mask Register.
\return Priority Mask value
*/
-__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_PRIMASK(void)
+__STATIC_FORCEINLINE uint32_t __get_PRIMASK(void)
{
uint32_t result;
- __ASM volatile ("MRS %0, primask" : "=r" (result) );
+ __ASM volatile ("MRS %0, primask" : "=r" (result) :: "memory");
return(result);
}
+#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3))
+/**
+ \brief Get Priority Mask (non-secure)
+ \details Returns the current state of the non-secure priority mask bit from the Priority Mask Register when in secure state.
+ \return Priority Mask value
+ */
+__STATIC_FORCEINLINE uint32_t __TZ_get_PRIMASK_NS(void)
+{
+ uint32_t result;
+
+ __ASM volatile ("MRS %0, primask_ns" : "=r" (result) :: "memory");
+ return(result);
+}
+#endif
+
+
/**
\brief Set Priority Mask
\details Assigns the given value to the Priority Mask Register.
\param [in] priMask Priority Mask
*/
-__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_PRIMASK(uint32_t priMask)
+__STATIC_FORCEINLINE void __set_PRIMASK(uint32_t priMask)
{
__ASM volatile ("MSR primask, %0" : : "r" (priMask) : "memory");
}
-#if (__CORTEX_M >= 0x03U)
+#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3))
+/**
+ \brief Set Priority Mask (non-secure)
+ \details Assigns the given value to the non-secure Priority Mask Register when in secure state.
+ \param [in] priMask Priority Mask
+ */
+__STATIC_FORCEINLINE void __TZ_set_PRIMASK_NS(uint32_t priMask)
+{
+ __ASM volatile ("MSR primask_ns, %0" : : "r" (priMask) : "memory");
+}
+#endif
+
+#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \
+ (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \
+ (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) )
/**
\brief Enable FIQ
\details Enables FIQ interrupts by clearing the F-bit in the CPSR.
Can only be executed in Privileged modes.
*/
-__attribute__( ( always_inline ) ) __STATIC_INLINE void __enable_fault_irq(void)
+__STATIC_FORCEINLINE void __enable_fault_irq(void)
{
__ASM volatile ("cpsie f" : : : "memory");
}
@@ -234,7 +447,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE void __enable_fault_irq(void)
\details Disables FIQ interrupts by setting the F-bit in the CPSR.
Can only be executed in Privileged modes.
*/
-__attribute__( ( always_inline ) ) __STATIC_INLINE void __disable_fault_irq(void)
+__STATIC_FORCEINLINE void __disable_fault_irq(void)
{
__ASM volatile ("cpsid f" : : : "memory");
}
@@ -245,7 +458,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE void __disable_fault_irq(void
\details Returns the current value of the Base Priority register.
\return Base Priority register value
*/
-__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_BASEPRI(void)
+__STATIC_FORCEINLINE uint32_t __get_BASEPRI(void)
{
uint32_t result;
@@ -254,26 +467,55 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_BASEPRI(void)
}
+#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3))
+/**
+ \brief Get Base Priority (non-secure)
+ \details Returns the current value of the non-secure Base Priority register when in secure state.
+ \return Base Priority register value
+ */
+__STATIC_FORCEINLINE uint32_t __TZ_get_BASEPRI_NS(void)
+{
+ uint32_t result;
+
+ __ASM volatile ("MRS %0, basepri_ns" : "=r" (result) );
+ return(result);
+}
+#endif
+
+
/**
\brief Set Base Priority
\details Assigns the given value to the Base Priority register.
\param [in] basePri Base Priority value to set
*/
-__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_BASEPRI(uint32_t value)
+__STATIC_FORCEINLINE void __set_BASEPRI(uint32_t basePri)
{
- __ASM volatile ("MSR basepri, %0" : : "r" (value) : "memory");
+ __ASM volatile ("MSR basepri, %0" : : "r" (basePri) : "memory");
}
+#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3))
+/**
+ \brief Set Base Priority (non-secure)
+ \details Assigns the given value to the non-secure Base Priority register when in secure state.
+ \param [in] basePri Base Priority value to set
+ */
+__STATIC_FORCEINLINE void __TZ_set_BASEPRI_NS(uint32_t basePri)
+{
+ __ASM volatile ("MSR basepri_ns, %0" : : "r" (basePri) : "memory");
+}
+#endif
+
+
/**
\brief Set Base Priority with condition
\details Assigns the given value to the Base Priority register only if BASEPRI masking is disabled,
or the new value increases the BASEPRI priority level.
\param [in] basePri Base Priority value to set
*/
-__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_BASEPRI_MAX(uint32_t value)
+__STATIC_FORCEINLINE void __set_BASEPRI_MAX(uint32_t basePri)
{
- __ASM volatile ("MSR basepri_max, %0" : : "r" (value) : "memory");
+ __ASM volatile ("MSR basepri_max, %0" : : "r" (basePri) : "memory");
}
@@ -282,7 +524,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE void __set_BASEPRI_MAX(uint32
\details Returns the current value of the Fault Mask register.
\return Fault Mask register value
*/
-__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_FAULTMASK(void)
+__STATIC_FORCEINLINE uint32_t __get_FAULTMASK(void)
{
uint32_t result;
@@ -291,38 +533,253 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_FAULTMASK(void
}
+#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3))
+/**
+ \brief Get Fault Mask (non-secure)
+ \details Returns the current value of the non-secure Fault Mask register when in secure state.
+ \return Fault Mask register value
+ */
+__STATIC_FORCEINLINE uint32_t __TZ_get_FAULTMASK_NS(void)
+{
+ uint32_t result;
+
+ __ASM volatile ("MRS %0, faultmask_ns" : "=r" (result) );
+ return(result);
+}
+#endif
+
+
/**
\brief Set Fault Mask
\details Assigns the given value to the Fault Mask register.
\param [in] faultMask Fault Mask value to set
*/
-__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask)
+__STATIC_FORCEINLINE void __set_FAULTMASK(uint32_t faultMask)
{
__ASM volatile ("MSR faultmask, %0" : : "r" (faultMask) : "memory");
}
-#endif /* (__CORTEX_M >= 0x03U) */
+
+#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3))
+/**
+ \brief Set Fault Mask (non-secure)
+ \details Assigns the given value to the non-secure Fault Mask register when in secure state.
+ \param [in] faultMask Fault Mask value to set
+ */
+__STATIC_FORCEINLINE void __TZ_set_FAULTMASK_NS(uint32_t faultMask)
+{
+ __ASM volatile ("MSR faultmask_ns, %0" : : "r" (faultMask) : "memory");
+}
+#endif
+
+#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \
+ (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \
+ (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) */
-#if (__CORTEX_M == 0x04U) || (__CORTEX_M == 0x07U)
+#if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \
+ (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) )
+
+/**
+ \brief Get Process Stack Pointer Limit
+ Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure
+ Stack Pointer Limit register hence zero is returned always in non-secure
+ mode.
+
+ \details Returns the current value of the Process Stack Pointer Limit (PSPLIM).
+ \return PSPLIM Register value
+ */
+__STATIC_FORCEINLINE uint32_t __get_PSPLIM(void)
+{
+#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \
+ (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3)))
+ // without main extensions, the non-secure PSPLIM is RAZ/WI
+ return 0U;
+#else
+ uint32_t result;
+ __ASM volatile ("MRS %0, psplim" : "=r" (result) );
+ return result;
+#endif
+}
+
+#if (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3))
+/**
+ \brief Get Process Stack Pointer Limit (non-secure)
+ Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure
+ Stack Pointer Limit register hence zero is returned always.
+
+ \details Returns the current value of the non-secure Process Stack Pointer Limit (PSPLIM) when in secure state.
+ \return PSPLIM Register value
+ */
+__STATIC_FORCEINLINE uint32_t __TZ_get_PSPLIM_NS(void)
+{
+#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)))
+ // without main extensions, the non-secure PSPLIM is RAZ/WI
+ return 0U;
+#else
+ uint32_t result;
+ __ASM volatile ("MRS %0, psplim_ns" : "=r" (result) );
+ return result;
+#endif
+}
+#endif
+
+
+/**
+ \brief Set Process Stack Pointer Limit
+ Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure
+ Stack Pointer Limit register hence the write is silently ignored in non-secure
+ mode.
+
+ \details Assigns the given value to the Process Stack Pointer Limit (PSPLIM).
+ \param [in] ProcStackPtrLimit Process Stack Pointer Limit value to set
+ */
+__STATIC_FORCEINLINE void __set_PSPLIM(uint32_t ProcStackPtrLimit)
+{
+#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \
+ (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3)))
+ // without main extensions, the non-secure PSPLIM is RAZ/WI
+ (void)ProcStackPtrLimit;
+#else
+ __ASM volatile ("MSR psplim, %0" : : "r" (ProcStackPtrLimit));
+#endif
+}
+
+
+#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3))
+/**
+ \brief Set Process Stack Pointer (non-secure)
+ Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure
+ Stack Pointer Limit register hence the write is silently ignored.
+
+ \details Assigns the given value to the non-secure Process Stack Pointer Limit (PSPLIM) when in secure state.
+ \param [in] ProcStackPtrLimit Process Stack Pointer Limit value to set
+ */
+__STATIC_FORCEINLINE void __TZ_set_PSPLIM_NS(uint32_t ProcStackPtrLimit)
+{
+#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)))
+ // without main extensions, the non-secure PSPLIM is RAZ/WI
+ (void)ProcStackPtrLimit;
+#else
+ __ASM volatile ("MSR psplim_ns, %0\n" : : "r" (ProcStackPtrLimit));
+#endif
+}
+#endif
+
+
+/**
+ \brief Get Main Stack Pointer Limit
+ Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure
+ Stack Pointer Limit register hence zero is returned always in non-secure
+ mode.
+
+ \details Returns the current value of the Main Stack Pointer Limit (MSPLIM).
+ \return MSPLIM Register value
+ */
+__STATIC_FORCEINLINE uint32_t __get_MSPLIM(void)
+{
+#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \
+ (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3)))
+ // without main extensions, the non-secure MSPLIM is RAZ/WI
+ return 0U;
+#else
+ uint32_t result;
+ __ASM volatile ("MRS %0, msplim" : "=r" (result) );
+ return result;
+#endif
+}
+
+
+#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3))
+/**
+ \brief Get Main Stack Pointer Limit (non-secure)
+ Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure
+ Stack Pointer Limit register hence zero is returned always.
+
+ \details Returns the current value of the non-secure Main Stack Pointer Limit(MSPLIM) when in secure state.
+ \return MSPLIM Register value
+ */
+__STATIC_FORCEINLINE uint32_t __TZ_get_MSPLIM_NS(void)
+{
+#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)))
+ // without main extensions, the non-secure MSPLIM is RAZ/WI
+ return 0U;
+#else
+ uint32_t result;
+ __ASM volatile ("MRS %0, msplim_ns" : "=r" (result) );
+ return result;
+#endif
+}
+#endif
+
+
+/**
+ \brief Set Main Stack Pointer Limit
+ Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure
+ Stack Pointer Limit register hence the write is silently ignored in non-secure
+ mode.
+
+ \details Assigns the given value to the Main Stack Pointer Limit (MSPLIM).
+ \param [in] MainStackPtrLimit Main Stack Pointer Limit value to set
+ */
+__STATIC_FORCEINLINE void __set_MSPLIM(uint32_t MainStackPtrLimit)
+{
+#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \
+ (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3)))
+ // without main extensions, the non-secure MSPLIM is RAZ/WI
+ (void)MainStackPtrLimit;
+#else
+ __ASM volatile ("MSR msplim, %0" : : "r" (MainStackPtrLimit));
+#endif
+}
+
+
+#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3))
+/**
+ \brief Set Main Stack Pointer Limit (non-secure)
+ Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure
+ Stack Pointer Limit register hence the write is silently ignored.
+
+ \details Assigns the given value to the non-secure Main Stack Pointer Limit (MSPLIM) when in secure state.
+ \param [in] MainStackPtrLimit Main Stack Pointer value to set
+ */
+__STATIC_FORCEINLINE void __TZ_set_MSPLIM_NS(uint32_t MainStackPtrLimit)
+{
+#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)))
+ // without main extensions, the non-secure MSPLIM is RAZ/WI
+ (void)MainStackPtrLimit;
+#else
+ __ASM volatile ("MSR msplim_ns, %0" : : "r" (MainStackPtrLimit));
+#endif
+}
+#endif
+
+#endif /* ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \
+ (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) */
+
/**
\brief Get FPSCR
\details Returns the current value of the Floating Point Status/Control register.
\return Floating Point Status/Control register value
*/
-__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_FPSCR(void)
-{
-#if (__FPU_PRESENT == 1U) && (__FPU_USED == 1U)
+__STATIC_FORCEINLINE uint32_t __get_FPSCR(void)
+{
+#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \
+ (defined (__FPU_USED ) && (__FPU_USED == 1U)) )
+#if __has_builtin(__builtin_arm_get_fpscr)
+// Re-enable using built-in when GCC has been fixed
+// || (__GNUC__ > 7) || (__GNUC__ == 7 && __GNUC_MINOR__ >= 2)
+ /* see https://gcc.gnu.org/ml/gcc-patches/2017-04/msg00443.html */
+ return __builtin_arm_get_fpscr();
+#else
uint32_t result;
- /* Empty asm statement works as a scheduling barrier */
- __ASM volatile ("");
__ASM volatile ("VMRS %0, fpscr" : "=r" (result) );
- __ASM volatile ("");
return(result);
+#endif
#else
- return(0);
+ return(0U);
#endif
}
@@ -332,19 +789,23 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_FPSCR(void)
\details Assigns the given value to the Floating Point Status/Control register.
\param [in] fpscr Floating Point Status/Control value to set
*/
-__attribute__( ( always_inline ) ) __STATIC_INLINE void __set_FPSCR(uint32_t fpscr)
-{
-#if (__FPU_PRESENT == 1U) && (__FPU_USED == 1U)
- /* Empty asm statement works as a scheduling barrier */
- __ASM volatile ("");
- __ASM volatile ("VMSR fpscr, %0" : : "r" (fpscr) : "vfpcc");
- __ASM volatile ("");
+__STATIC_FORCEINLINE void __set_FPSCR(uint32_t fpscr)
+{
+#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \
+ (defined (__FPU_USED ) && (__FPU_USED == 1U)) )
+#if __has_builtin(__builtin_arm_set_fpscr)
+// Re-enable using built-in when GCC has been fixed
+// || (__GNUC__ > 7) || (__GNUC__ == 7 && __GNUC_MINOR__ >= 2)
+ /* see https://gcc.gnu.org/ml/gcc-patches/2017-04/msg00443.html */
+ __builtin_arm_set_fpscr(fpscr);
+#else
+ __ASM volatile ("VMSR fpscr, %0" : : "r" (fpscr) : "vfpcc", "memory");
+#endif
+#else
+ (void)fpscr;
#endif
}
-#endif /* (__CORTEX_M == 0x04U) || (__CORTEX_M == 0x07U) */
-
-
/*@} end of CMSIS_Core_RegAccFunctions */
@@ -360,9 +821,11 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE void __set_FPSCR(uint32_t fps
* Otherwise, use general registers, specified by constraint "r" */
#if defined (__thumb__) && !defined (__thumb2__)
#define __CMSIS_GCC_OUT_REG(r) "=l" (r)
+#define __CMSIS_GCC_RW_REG(r) "+l" (r)
#define __CMSIS_GCC_USE_REG(r) "l" (r)
#else
#define __CMSIS_GCC_OUT_REG(r) "=r" (r)
+#define __CMSIS_GCC_RW_REG(r) "+r" (r)
#define __CMSIS_GCC_USE_REG(r) "r" (r)
#endif
@@ -370,41 +833,28 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE void __set_FPSCR(uint32_t fps
\brief No Operation
\details No Operation does nothing. This instruction can be used for code alignment purposes.
*/
-__attribute__((always_inline)) __STATIC_INLINE void __NOP(void)
-{
- __ASM volatile ("nop");
-}
-
+#define __NOP() __ASM volatile ("nop")
/**
\brief Wait For Interrupt
\details Wait For Interrupt is a hint instruction that suspends execution until one of a number of events occurs.
*/
-__attribute__((always_inline)) __STATIC_INLINE void __WFI(void)
-{
- __ASM volatile ("wfi");
-}
+#define __WFI() __ASM volatile ("wfi")
/**
\brief Wait For Event
\details Wait For Event is a hint instruction that permits the processor to enter
- a low-power state until one of a number of events occurs.
+ a low-power state until one of a number of events occurs.
*/
-__attribute__((always_inline)) __STATIC_INLINE void __WFE(void)
-{
- __ASM volatile ("wfe");
-}
+#define __WFE() __ASM volatile ("wfe")
/**
\brief Send Event
\details Send Event is a hint instruction. It causes an event to be signaled to the CPU.
*/
-__attribute__((always_inline)) __STATIC_INLINE void __SEV(void)
-{
- __ASM volatile ("sev");
-}
+#define __SEV() __ASM volatile ("sev")
/**
@@ -413,7 +863,7 @@ __attribute__((always_inline)) __STATIC_INLINE void __SEV(void)
so that all instructions following the ISB are fetched from cache or memory,
after the instruction has been completed.
*/
-__attribute__((always_inline)) __STATIC_INLINE void __ISB(void)
+__STATIC_FORCEINLINE void __ISB(void)
{
__ASM volatile ("isb 0xF":::"memory");
}
@@ -424,7 +874,7 @@ __attribute__((always_inline)) __STATIC_INLINE void __ISB(void)
\details Acts as a special kind of Data Memory Barrier.
It completes when all explicit memory accesses before this instruction complete.
*/
-__attribute__((always_inline)) __STATIC_INLINE void __DSB(void)
+__STATIC_FORCEINLINE void __DSB(void)
{
__ASM volatile ("dsb 0xF":::"memory");
}
@@ -435,7 +885,7 @@ __attribute__((always_inline)) __STATIC_INLINE void __DSB(void)
\details Ensures the apparent order of the explicit memory operations before
and after the instruction, without ensuring their completion.
*/
-__attribute__((always_inline)) __STATIC_INLINE void __DMB(void)
+__STATIC_FORCEINLINE void __DMB(void)
{
__ASM volatile ("dmb 0xF":::"memory");
}
@@ -443,11 +893,11 @@ __attribute__((always_inline)) __STATIC_INLINE void __DMB(void)
/**
\brief Reverse byte order (32 bit)
- \details Reverses the byte order in integer value.
+ \details Reverses the byte order in unsigned integer value. For example, 0x12345678 becomes 0x78563412.
\param [in] value Value to reverse
\return Reversed value
*/
-__attribute__((always_inline)) __STATIC_INLINE uint32_t __REV(uint32_t value)
+__STATIC_FORCEINLINE uint32_t __REV(uint32_t value)
{
#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)
return __builtin_bswap32(value);
@@ -455,41 +905,41 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __REV(uint32_t value)
uint32_t result;
__ASM volatile ("rev %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) );
- return(result);
+ return result;
#endif
}
/**
\brief Reverse byte order (16 bit)
- \details Reverses the byte order in two unsigned short values.
+ \details Reverses the byte order within each halfword of a word. For example, 0x12345678 becomes 0x34127856.
\param [in] value Value to reverse
\return Reversed value
*/
-__attribute__((always_inline)) __STATIC_INLINE uint32_t __REV16(uint32_t value)
+__STATIC_FORCEINLINE uint32_t __REV16(uint32_t value)
{
uint32_t result;
__ASM volatile ("rev16 %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) );
- return(result);
+ return result;
}
/**
- \brief Reverse byte order in signed short value
- \details Reverses the byte order in a signed short value with sign extension to integer.
+ \brief Reverse byte order (16 bit)
+ \details Reverses the byte order in a 16-bit value and returns the signed 16-bit result. For example, 0x0080 becomes 0x8000.
\param [in] value Value to reverse
\return Reversed value
*/
-__attribute__((always_inline)) __STATIC_INLINE int32_t __REVSH(int32_t value)
+__STATIC_FORCEINLINE int16_t __REVSH(int16_t value)
{
#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)
- return (short)__builtin_bswap16(value);
+ return (int16_t)__builtin_bswap16(value);
#else
- int32_t result;
+ int16_t result;
__ASM volatile ("revsh %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) );
- return(result);
+ return result;
#endif
}
@@ -497,12 +947,17 @@ __attribute__((always_inline)) __STATIC_INLINE int32_t __REVSH(int32_t value)
/**
\brief Rotate Right in unsigned value (32 bit)
\details Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits.
- \param [in] value Value to rotate
- \param [in] value Number of Bits to rotate
+ \param [in] op1 Value to rotate
+ \param [in] op2 Number of Bits to rotate
\return Rotated value
*/
-__attribute__((always_inline)) __STATIC_INLINE uint32_t __ROR(uint32_t op1, uint32_t op2)
+__STATIC_FORCEINLINE uint32_t __ROR(uint32_t op1, uint32_t op2)
{
+ op2 %= 32U;
+ if (op2 == 0U)
+ {
+ return op1;
+ }
return (op1 >> op2) | (op1 << (32U - op2));
}
@@ -523,17 +978,19 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __ROR(uint32_t op1, uint
\param [in] value Value to reverse
\return Reversed value
*/
-__attribute__((always_inline)) __STATIC_INLINE uint32_t __RBIT(uint32_t value)
+__STATIC_FORCEINLINE uint32_t __RBIT(uint32_t value)
{
uint32_t result;
-#if (__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U)
+#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \
+ (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \
+ (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) )
__ASM volatile ("rbit %0, %1" : "=r" (result) : "r" (value) );
#else
- int32_t s = 4 /*sizeof(v)*/ * 8 - 1; /* extra shift needed at end */
+ uint32_t s = (4U /*sizeof(v)*/ * 8U) - 1U; /* extra shift needed at end */
result = value; /* r will be reversed bits of v; first get LSB of v */
- for (value >>= 1U; value; value >>= 1U)
+ for (value >>= 1U; value != 0U; value >>= 1U)
{
result <<= 1U;
result |= value & 1U;
@@ -541,7 +998,7 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __RBIT(uint32_t value)
}
result <<= s; /* shift when v's highest bits are zero */
#endif
- return(result);
+ return result;
}
@@ -551,18 +1008,36 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __RBIT(uint32_t value)
\param [in] value Value to count the leading zeros
\return number of leading zeros in value
*/
-#define __CLZ __builtin_clz
-
+__STATIC_FORCEINLINE uint8_t __CLZ(uint32_t value)
+{
+ /* Even though __builtin_clz produces a CLZ instruction on ARM, formally
+ __builtin_clz(0) is undefined behaviour, so handle this case specially.
+ This guarantees ARM-compatible results if happening to compile on a non-ARM
+ target, and ensures the compiler doesn't decide to activate any
+ optimisations using the logic "value was passed to __builtin_clz, so it
+ is non-zero".
+ ARM GCC 7.3 and possibly earlier will optimise this test away, leaving a
+ single CLZ instruction.
+ */
+ if (value == 0U)
+ {
+ return 32U;
+ }
+ return __builtin_clz(value);
+}
-#if (__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U)
+#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \
+ (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \
+ (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \
+ (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) )
/**
\brief LDR Exclusive (8 bit)
\details Executes a exclusive LDR instruction for 8 bit value.
\param [in] ptr Pointer to data
\return value of type uint8_t at (*ptr)
*/
-__attribute__((always_inline)) __STATIC_INLINE uint8_t __LDREXB(volatile uint8_t *addr)
+__STATIC_FORCEINLINE uint8_t __LDREXB(volatile uint8_t *addr)
{
uint32_t result;
@@ -584,7 +1059,7 @@ __attribute__((always_inline)) __STATIC_INLINE uint8_t __LDREXB(volatile uint8_t
\param [in] ptr Pointer to data
\return value of type uint16_t at (*ptr)
*/
-__attribute__((always_inline)) __STATIC_INLINE uint16_t __LDREXH(volatile uint16_t *addr)
+__STATIC_FORCEINLINE uint16_t __LDREXH(volatile uint16_t *addr)
{
uint32_t result;
@@ -606,7 +1081,7 @@ __attribute__((always_inline)) __STATIC_INLINE uint16_t __LDREXH(volatile uint16
\param [in] ptr Pointer to data
\return value of type uint32_t at (*ptr)
*/
-__attribute__((always_inline)) __STATIC_INLINE uint32_t __LDREXW(volatile uint32_t *addr)
+__STATIC_FORCEINLINE uint32_t __LDREXW(volatile uint32_t *addr)
{
uint32_t result;
@@ -623,7 +1098,7 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __LDREXW(volatile uint32
\return 0 Function succeeded
\return 1 Function failed
*/
-__attribute__((always_inline)) __STATIC_INLINE uint32_t __STREXB(uint8_t value, volatile uint8_t *addr)
+__STATIC_FORCEINLINE uint32_t __STREXB(uint8_t value, volatile uint8_t *addr)
{
uint32_t result;
@@ -640,7 +1115,7 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __STREXB(uint8_t value,
\return 0 Function succeeded
\return 1 Function failed
*/
-__attribute__((always_inline)) __STATIC_INLINE uint32_t __STREXH(uint16_t value, volatile uint16_t *addr)
+__STATIC_FORCEINLINE uint32_t __STREXH(uint16_t value, volatile uint16_t *addr)
{
uint32_t result;
@@ -657,7 +1132,7 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __STREXH(uint16_t value,
\return 0 Function succeeded
\return 1 Function failed
*/
-__attribute__((always_inline)) __STATIC_INLINE uint32_t __STREXW(uint32_t value, volatile uint32_t *addr)
+__STATIC_FORCEINLINE uint32_t __STREXW(uint32_t value, volatile uint32_t *addr)
{
uint32_t result;
@@ -670,22 +1145,31 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __STREXW(uint32_t value,
\brief Remove the exclusive lock
\details Removes the exclusive lock which is created by LDREX.
*/
-__attribute__((always_inline)) __STATIC_INLINE void __CLREX(void)
+__STATIC_FORCEINLINE void __CLREX(void)
{
__ASM volatile ("clrex" ::: "memory");
}
+#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \
+ (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \
+ (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \
+ (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) */
+
+#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \
+ (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \
+ (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) )
/**
\brief Signed Saturate
\details Saturates a signed value.
- \param [in] value Value to be saturated
- \param [in] sat Bit position to saturate to (1..32)
+ \param [in] ARG1 Value to be saturated
+ \param [in] ARG2 Bit position to saturate to (1..32)
\return Saturated value
*/
#define __SSAT(ARG1,ARG2) \
+__extension__ \
({ \
- uint32_t __RES, __ARG1 = (ARG1); \
+ int32_t __RES, __ARG1 = (ARG1); \
__ASM ("ssat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \
__RES; \
})
@@ -694,11 +1178,12 @@ __attribute__((always_inline)) __STATIC_INLINE void __CLREX(void)
/**
\brief Unsigned Saturate
\details Saturates an unsigned value.
- \param [in] value Value to be saturated
- \param [in] sat Bit position to saturate to (0..31)
+ \param [in] ARG1 Value to be saturated
+ \param [in] ARG2 Bit position to saturate to (0..31)
\return Saturated value
*/
#define __USAT(ARG1,ARG2) \
+ __extension__ \
({ \
uint32_t __RES, __ARG1 = (ARG1); \
__ASM ("usat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \
@@ -713,7 +1198,7 @@ __attribute__((always_inline)) __STATIC_INLINE void __CLREX(void)
\param [in] value Value to rotate
\return Rotated value
*/
-__attribute__((always_inline)) __STATIC_INLINE uint32_t __RRX(uint32_t value)
+__STATIC_FORCEINLINE uint32_t __RRX(uint32_t value)
{
uint32_t result;
@@ -728,17 +1213,17 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __RRX(uint32_t value)
\param [in] ptr Pointer to data
\return value of type uint8_t at (*ptr)
*/
-__attribute__((always_inline)) __STATIC_INLINE uint8_t __LDRBT(volatile uint8_t *addr)
+__STATIC_FORCEINLINE uint8_t __LDRBT(volatile uint8_t *ptr)
{
uint32_t result;
#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)
- __ASM volatile ("ldrbt %0, %1" : "=r" (result) : "Q" (*addr) );
+ __ASM volatile ("ldrbt %0, %1" : "=r" (result) : "Q" (*ptr) );
#else
/* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not
accepted by assembler. So has to use following less efficient pattern.
*/
- __ASM volatile ("ldrbt %0, [%1]" : "=r" (result) : "r" (addr) : "memory" );
+ __ASM volatile ("ldrbt %0, [%1]" : "=r" (result) : "r" (ptr) : "memory" );
#endif
return ((uint8_t) result); /* Add explicit type cast here */
}
@@ -750,17 +1235,17 @@ __attribute__((always_inline)) __STATIC_INLINE uint8_t __LDRBT(volatile uint8_t
\param [in] ptr Pointer to data
\return value of type uint16_t at (*ptr)
*/
-__attribute__((always_inline)) __STATIC_INLINE uint16_t __LDRHT(volatile uint16_t *addr)
+__STATIC_FORCEINLINE uint16_t __LDRHT(volatile uint16_t *ptr)
{
uint32_t result;
#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)
- __ASM volatile ("ldrht %0, %1" : "=r" (result) : "Q" (*addr) );
+ __ASM volatile ("ldrht %0, %1" : "=r" (result) : "Q" (*ptr) );
#else
/* Prior to GCC 4.8, "Q" will be expanded to [rx, #0] which is not
accepted by assembler. So has to use following less efficient pattern.
*/
- __ASM volatile ("ldrht %0, [%1]" : "=r" (result) : "r" (addr) : "memory" );
+ __ASM volatile ("ldrht %0, [%1]" : "=r" (result) : "r" (ptr) : "memory" );
#endif
return ((uint16_t) result); /* Add explicit type cast here */
}
@@ -772,11 +1257,11 @@ __attribute__((always_inline)) __STATIC_INLINE uint16_t __LDRHT(volatile uint16_
\param [in] ptr Pointer to data
\return value of type uint32_t at (*ptr)
*/
-__attribute__((always_inline)) __STATIC_INLINE uint32_t __LDRT(volatile uint32_t *addr)
+__STATIC_FORCEINLINE uint32_t __LDRT(volatile uint32_t *ptr)
{
uint32_t result;
- __ASM volatile ("ldrt %0, %1" : "=r" (result) : "Q" (*addr) );
+ __ASM volatile ("ldrt %0, %1" : "=r" (result) : "Q" (*ptr) );
return(result);
}
@@ -787,9 +1272,9 @@ __attribute__((always_inline)) __STATIC_INLINE uint32_t __LDRT(volatile uint32_t
\param [in] value Value to store
\param [in] ptr Pointer to location
*/
-__attribute__((always_inline)) __STATIC_INLINE void __STRBT(uint8_t value, volatile uint8_t *addr)
+__STATIC_FORCEINLINE void __STRBT(uint8_t value, volatile uint8_t *ptr)
{
- __ASM volatile ("strbt %1, %0" : "=Q" (*addr) : "r" ((uint32_t)value) );
+ __ASM volatile ("strbt %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) );
}
@@ -799,9 +1284,9 @@ __attribute__((always_inline)) __STATIC_INLINE void __STRBT(uint8_t value, volat
\param [in] value Value to store
\param [in] ptr Pointer to location
*/
-__attribute__((always_inline)) __STATIC_INLINE void __STRHT(uint16_t value, volatile uint16_t *addr)
+__STATIC_FORCEINLINE void __STRHT(uint16_t value, volatile uint16_t *ptr)
{
- __ASM volatile ("strht %1, %0" : "=Q" (*addr) : "r" ((uint32_t)value) );
+ __ASM volatile ("strht %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) );
}
@@ -811,12 +1296,249 @@ __attribute__((always_inline)) __STATIC_INLINE void __STRHT(uint16_t value, vola
\param [in] value Value to store
\param [in] ptr Pointer to location
*/
-__attribute__((always_inline)) __STATIC_INLINE void __STRT(uint32_t value, volatile uint32_t *addr)
+__STATIC_FORCEINLINE void __STRT(uint32_t value, volatile uint32_t *ptr)
+{
+ __ASM volatile ("strt %1, %0" : "=Q" (*ptr) : "r" (value) );
+}
+
+#else /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \
+ (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \
+ (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) */
+
+/**
+ \brief Signed Saturate
+ \details Saturates a signed value.
+ \param [in] value Value to be saturated
+ \param [in] sat Bit position to saturate to (1..32)
+ \return Saturated value
+ */
+__STATIC_FORCEINLINE int32_t __SSAT(int32_t val, uint32_t sat)
+{
+ if ((sat >= 1U) && (sat <= 32U))
+ {
+ const int32_t max = (int32_t)((1U << (sat - 1U)) - 1U);
+ const int32_t min = -1 - max ;
+ if (val > max)
+ {
+ return max;
+ }
+ else if (val < min)
+ {
+ return min;
+ }
+ }
+ return val;
+}
+
+/**
+ \brief Unsigned Saturate
+ \details Saturates an unsigned value.
+ \param [in] value Value to be saturated
+ \param [in] sat Bit position to saturate to (0..31)
+ \return Saturated value
+ */
+__STATIC_FORCEINLINE uint32_t __USAT(int32_t val, uint32_t sat)
+{
+ if (sat <= 31U)
+ {
+ const uint32_t max = ((1U << sat) - 1U);
+ if (val > (int32_t)max)
+ {
+ return max;
+ }
+ else if (val < 0)
+ {
+ return 0U;
+ }
+ }
+ return (uint32_t)val;
+}
+
+#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \
+ (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \
+ (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) ) */
+
+
+#if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \
+ (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) )
+/**
+ \brief Load-Acquire (8 bit)
+ \details Executes a LDAB instruction for 8 bit value.
+ \param [in] ptr Pointer to data
+ \return value of type uint8_t at (*ptr)
+ */
+__STATIC_FORCEINLINE uint8_t __LDAB(volatile uint8_t *ptr)
+{
+ uint32_t result;
+
+ __ASM volatile ("ldab %0, %1" : "=r" (result) : "Q" (*ptr) );
+ return ((uint8_t) result);
+}
+
+
+/**
+ \brief Load-Acquire (16 bit)
+ \details Executes a LDAH instruction for 16 bit values.
+ \param [in] ptr Pointer to data
+ \return value of type uint16_t at (*ptr)
+ */
+__STATIC_FORCEINLINE uint16_t __LDAH(volatile uint16_t *ptr)
+{
+ uint32_t result;
+
+ __ASM volatile ("ldah %0, %1" : "=r" (result) : "Q" (*ptr) );
+ return ((uint16_t) result);
+}
+
+
+/**
+ \brief Load-Acquire (32 bit)
+ \details Executes a LDA instruction for 32 bit values.
+ \param [in] ptr Pointer to data
+ \return value of type uint32_t at (*ptr)
+ */
+__STATIC_FORCEINLINE uint32_t __LDA(volatile uint32_t *ptr)
+{
+ uint32_t result;
+
+ __ASM volatile ("lda %0, %1" : "=r" (result) : "Q" (*ptr) );
+ return(result);
+}
+
+
+/**
+ \brief Store-Release (8 bit)
+ \details Executes a STLB instruction for 8 bit values.
+ \param [in] value Value to store
+ \param [in] ptr Pointer to location
+ */
+__STATIC_FORCEINLINE void __STLB(uint8_t value, volatile uint8_t *ptr)
{
- __ASM volatile ("strt %1, %0" : "=Q" (*addr) : "r" (value) );
+ __ASM volatile ("stlb %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) );
}
-#endif /* (__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U) */
+
+/**
+ \brief Store-Release (16 bit)
+ \details Executes a STLH instruction for 16 bit values.
+ \param [in] value Value to store
+ \param [in] ptr Pointer to location
+ */
+__STATIC_FORCEINLINE void __STLH(uint16_t value, volatile uint16_t *ptr)
+{
+ __ASM volatile ("stlh %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) );
+}
+
+
+/**
+ \brief Store-Release (32 bit)
+ \details Executes a STL instruction for 32 bit values.
+ \param [in] value Value to store
+ \param [in] ptr Pointer to location
+ */
+__STATIC_FORCEINLINE void __STL(uint32_t value, volatile uint32_t *ptr)
+{
+ __ASM volatile ("stl %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) );
+}
+
+
+/**
+ \brief Load-Acquire Exclusive (8 bit)
+ \details Executes a LDAB exclusive instruction for 8 bit value.
+ \param [in] ptr Pointer to data
+ \return value of type uint8_t at (*ptr)
+ */
+__STATIC_FORCEINLINE uint8_t __LDAEXB(volatile uint8_t *ptr)
+{
+ uint32_t result;
+
+ __ASM volatile ("ldaexb %0, %1" : "=r" (result) : "Q" (*ptr) );
+ return ((uint8_t) result);
+}
+
+
+/**
+ \brief Load-Acquire Exclusive (16 bit)
+ \details Executes a LDAH exclusive instruction for 16 bit values.
+ \param [in] ptr Pointer to data
+ \return value of type uint16_t at (*ptr)
+ */
+__STATIC_FORCEINLINE uint16_t __LDAEXH(volatile uint16_t *ptr)
+{
+ uint32_t result;
+
+ __ASM volatile ("ldaexh %0, %1" : "=r" (result) : "Q" (*ptr) );
+ return ((uint16_t) result);
+}
+
+
+/**
+ \brief Load-Acquire Exclusive (32 bit)
+ \details Executes a LDA exclusive instruction for 32 bit values.
+ \param [in] ptr Pointer to data
+ \return value of type uint32_t at (*ptr)
+ */
+__STATIC_FORCEINLINE uint32_t __LDAEX(volatile uint32_t *ptr)
+{
+ uint32_t result;
+
+ __ASM volatile ("ldaex %0, %1" : "=r" (result) : "Q" (*ptr) );
+ return(result);
+}
+
+
+/**
+ \brief Store-Release Exclusive (8 bit)
+ \details Executes a STLB exclusive instruction for 8 bit values.
+ \param [in] value Value to store
+ \param [in] ptr Pointer to location
+ \return 0 Function succeeded
+ \return 1 Function failed
+ */
+__STATIC_FORCEINLINE uint32_t __STLEXB(uint8_t value, volatile uint8_t *ptr)
+{
+ uint32_t result;
+
+ __ASM volatile ("stlexb %0, %2, %1" : "=&r" (result), "=Q" (*ptr) : "r" ((uint32_t)value) );
+ return(result);
+}
+
+
+/**
+ \brief Store-Release Exclusive (16 bit)
+ \details Executes a STLH exclusive instruction for 16 bit values.
+ \param [in] value Value to store
+ \param [in] ptr Pointer to location
+ \return 0 Function succeeded
+ \return 1 Function failed
+ */
+__STATIC_FORCEINLINE uint32_t __STLEXH(uint16_t value, volatile uint16_t *ptr)
+{
+ uint32_t result;
+
+ __ASM volatile ("stlexh %0, %2, %1" : "=&r" (result), "=Q" (*ptr) : "r" ((uint32_t)value) );
+ return(result);
+}
+
+
+/**
+ \brief Store-Release Exclusive (32 bit)
+ \details Executes a STL exclusive instruction for 32 bit values.
+ \param [in] value Value to store
+ \param [in] ptr Pointer to location
+ \return 0 Function succeeded
+ \return 1 Function failed
+ */
+__STATIC_FORCEINLINE uint32_t __STLEX(uint32_t value, volatile uint32_t *ptr)
+{
+ uint32_t result;
+
+ __ASM volatile ("stlex %0, %2, %1" : "=&r" (result), "=Q" (*ptr) : "r" ((uint32_t)value) );
+ return(result);
+}
+
+#endif /* ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \
+ (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) ) */
/*@}*/ /* end of group CMSIS_Core_InstructionInterface */
@@ -827,9 +1549,9 @@ __attribute__((always_inline)) __STATIC_INLINE void __STRT(uint32_t value, volat
@{
*/
-#if (__CORTEX_M >= 0x04U) /* only for Cortex-M4 and above */
+#if (defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1))
-__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SADD8(uint32_t op1, uint32_t op2)
+__STATIC_FORCEINLINE uint32_t __SADD8(uint32_t op1, uint32_t op2)
{
uint32_t result;
@@ -837,7 +1559,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SADD8(uint32_t op1
return(result);
}
-__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QADD8(uint32_t op1, uint32_t op2)
+__STATIC_FORCEINLINE uint32_t __QADD8(uint32_t op1, uint32_t op2)
{
uint32_t result;
@@ -845,7 +1567,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QADD8(uint32_t op1
return(result);
}
-__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHADD8(uint32_t op1, uint32_t op2)
+__STATIC_FORCEINLINE uint32_t __SHADD8(uint32_t op1, uint32_t op2)
{
uint32_t result;
@@ -853,7 +1575,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHADD8(uint32_t op
return(result);
}
-__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UADD8(uint32_t op1, uint32_t op2)
+__STATIC_FORCEINLINE uint32_t __UADD8(uint32_t op1, uint32_t op2)
{
uint32_t result;
@@ -861,7 +1583,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UADD8(uint32_t op1
return(result);
}
-__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQADD8(uint32_t op1, uint32_t op2)
+__STATIC_FORCEINLINE uint32_t __UQADD8(uint32_t op1, uint32_t op2)
{
uint32_t result;
@@ -869,7 +1591,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQADD8(uint32_t op
return(result);
}
-__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHADD8(uint32_t op1, uint32_t op2)
+__STATIC_FORCEINLINE uint32_t __UHADD8(uint32_t op1, uint32_t op2)
{
uint32_t result;
@@ -878,7 +1600,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHADD8(uint32_t op
}
-__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SSUB8(uint32_t op1, uint32_t op2)
+__STATIC_FORCEINLINE uint32_t __SSUB8(uint32_t op1, uint32_t op2)
{
uint32_t result;
@@ -886,7 +1608,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SSUB8(uint32_t op1
return(result);
}
-__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QSUB8(uint32_t op1, uint32_t op2)
+__STATIC_FORCEINLINE uint32_t __QSUB8(uint32_t op1, uint32_t op2)
{
uint32_t result;
@@ -894,7 +1616,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QSUB8(uint32_t op1
return(result);
}
-__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHSUB8(uint32_t op1, uint32_t op2)
+__STATIC_FORCEINLINE uint32_t __SHSUB8(uint32_t op1, uint32_t op2)
{
uint32_t result;
@@ -902,7 +1624,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHSUB8(uint32_t op
return(result);
}
-__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USUB8(uint32_t op1, uint32_t op2)
+__STATIC_FORCEINLINE uint32_t __USUB8(uint32_t op1, uint32_t op2)
{
uint32_t result;
@@ -910,7 +1632,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USUB8(uint32_t op1
return(result);
}
-__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQSUB8(uint32_t op1, uint32_t op2)
+__STATIC_FORCEINLINE uint32_t __UQSUB8(uint32_t op1, uint32_t op2)
{
uint32_t result;
@@ -918,7 +1640,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQSUB8(uint32_t op
return(result);
}
-__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHSUB8(uint32_t op1, uint32_t op2)
+__STATIC_FORCEINLINE uint32_t __UHSUB8(uint32_t op1, uint32_t op2)
{
uint32_t result;
@@ -927,7 +1649,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHSUB8(uint32_t op
}
-__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SADD16(uint32_t op1, uint32_t op2)
+__STATIC_FORCEINLINE uint32_t __SADD16(uint32_t op1, uint32_t op2)
{
uint32_t result;
@@ -935,7 +1657,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SADD16(uint32_t op
return(result);
}
-__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QADD16(uint32_t op1, uint32_t op2)
+__STATIC_FORCEINLINE uint32_t __QADD16(uint32_t op1, uint32_t op2)
{
uint32_t result;
@@ -943,7 +1665,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QADD16(uint32_t op
return(result);
}
-__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHADD16(uint32_t op1, uint32_t op2)
+__STATIC_FORCEINLINE uint32_t __SHADD16(uint32_t op1, uint32_t op2)
{
uint32_t result;
@@ -951,7 +1673,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHADD16(uint32_t o
return(result);
}
-__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UADD16(uint32_t op1, uint32_t op2)
+__STATIC_FORCEINLINE uint32_t __UADD16(uint32_t op1, uint32_t op2)
{
uint32_t result;
@@ -959,7 +1681,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UADD16(uint32_t op
return(result);
}
-__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQADD16(uint32_t op1, uint32_t op2)
+__STATIC_FORCEINLINE uint32_t __UQADD16(uint32_t op1, uint32_t op2)
{
uint32_t result;
@@ -967,7 +1689,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQADD16(uint32_t o
return(result);
}
-__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHADD16(uint32_t op1, uint32_t op2)
+__STATIC_FORCEINLINE uint32_t __UHADD16(uint32_t op1, uint32_t op2)
{
uint32_t result;
@@ -975,7 +1697,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHADD16(uint32_t o
return(result);
}
-__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SSUB16(uint32_t op1, uint32_t op2)
+__STATIC_FORCEINLINE uint32_t __SSUB16(uint32_t op1, uint32_t op2)
{
uint32_t result;
@@ -983,7 +1705,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SSUB16(uint32_t op
return(result);
}
-__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QSUB16(uint32_t op1, uint32_t op2)
+__STATIC_FORCEINLINE uint32_t __QSUB16(uint32_t op1, uint32_t op2)
{
uint32_t result;
@@ -991,7 +1713,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QSUB16(uint32_t op
return(result);
}
-__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHSUB16(uint32_t op1, uint32_t op2)
+__STATIC_FORCEINLINE uint32_t __SHSUB16(uint32_t op1, uint32_t op2)
{
uint32_t result;
@@ -999,7 +1721,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHSUB16(uint32_t o
return(result);
}
-__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USUB16(uint32_t op1, uint32_t op2)
+__STATIC_FORCEINLINE uint32_t __USUB16(uint32_t op1, uint32_t op2)
{
uint32_t result;
@@ -1007,7 +1729,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USUB16(uint32_t op
return(result);
}
-__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQSUB16(uint32_t op1, uint32_t op2)
+__STATIC_FORCEINLINE uint32_t __UQSUB16(uint32_t op1, uint32_t op2)
{
uint32_t result;
@@ -1015,7 +1737,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQSUB16(uint32_t o
return(result);
}
-__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHSUB16(uint32_t op1, uint32_t op2)
+__STATIC_FORCEINLINE uint32_t __UHSUB16(uint32_t op1, uint32_t op2)
{
uint32_t result;
@@ -1023,7 +1745,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHSUB16(uint32_t o
return(result);
}
-__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SASX(uint32_t op1, uint32_t op2)
+__STATIC_FORCEINLINE uint32_t __SASX(uint32_t op1, uint32_t op2)
{
uint32_t result;
@@ -1031,7 +1753,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SASX(uint32_t op1,
return(result);
}
-__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QASX(uint32_t op1, uint32_t op2)
+__STATIC_FORCEINLINE uint32_t __QASX(uint32_t op1, uint32_t op2)
{
uint32_t result;
@@ -1039,7 +1761,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QASX(uint32_t op1,
return(result);
}
-__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHASX(uint32_t op1, uint32_t op2)
+__STATIC_FORCEINLINE uint32_t __SHASX(uint32_t op1, uint32_t op2)
{
uint32_t result;
@@ -1047,7 +1769,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHASX(uint32_t op1
return(result);
}
-__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UASX(uint32_t op1, uint32_t op2)
+__STATIC_FORCEINLINE uint32_t __UASX(uint32_t op1, uint32_t op2)
{
uint32_t result;
@@ -1055,7 +1777,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UASX(uint32_t op1,
return(result);
}
-__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQASX(uint32_t op1, uint32_t op2)
+__STATIC_FORCEINLINE uint32_t __UQASX(uint32_t op1, uint32_t op2)
{
uint32_t result;
@@ -1063,7 +1785,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQASX(uint32_t op1
return(result);
}
-__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHASX(uint32_t op1, uint32_t op2)
+__STATIC_FORCEINLINE uint32_t __UHASX(uint32_t op1, uint32_t op2)
{
uint32_t result;
@@ -1071,7 +1793,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHASX(uint32_t op1
return(result);
}
-__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SSAX(uint32_t op1, uint32_t op2)
+__STATIC_FORCEINLINE uint32_t __SSAX(uint32_t op1, uint32_t op2)
{
uint32_t result;
@@ -1079,7 +1801,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SSAX(uint32_t op1,
return(result);
}
-__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QSAX(uint32_t op1, uint32_t op2)
+__STATIC_FORCEINLINE uint32_t __QSAX(uint32_t op1, uint32_t op2)
{
uint32_t result;
@@ -1087,7 +1809,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __QSAX(uint32_t op1,
return(result);
}
-__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHSAX(uint32_t op1, uint32_t op2)
+__STATIC_FORCEINLINE uint32_t __SHSAX(uint32_t op1, uint32_t op2)
{
uint32_t result;
@@ -1095,7 +1817,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SHSAX(uint32_t op1
return(result);
}
-__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USAX(uint32_t op1, uint32_t op2)
+__STATIC_FORCEINLINE uint32_t __USAX(uint32_t op1, uint32_t op2)
{
uint32_t result;
@@ -1103,7 +1825,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USAX(uint32_t op1,
return(result);
}
-__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQSAX(uint32_t op1, uint32_t op2)
+__STATIC_FORCEINLINE uint32_t __UQSAX(uint32_t op1, uint32_t op2)
{
uint32_t result;
@@ -1111,7 +1833,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UQSAX(uint32_t op1
return(result);
}
-__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHSAX(uint32_t op1, uint32_t op2)
+__STATIC_FORCEINLINE uint32_t __UHSAX(uint32_t op1, uint32_t op2)
{
uint32_t result;
@@ -1119,7 +1841,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UHSAX(uint32_t op1
return(result);
}
-__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USAD8(uint32_t op1, uint32_t op2)
+__STATIC_FORCEINLINE uint32_t __USAD8(uint32_t op1, uint32_t op2)
{
uint32_t result;
@@ -1127,7 +1849,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USAD8(uint32_t op1
return(result);
}
-__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USADA8(uint32_t op1, uint32_t op2, uint32_t op3)
+__STATIC_FORCEINLINE uint32_t __USADA8(uint32_t op1, uint32_t op2, uint32_t op3)
{
uint32_t result;
@@ -1149,7 +1871,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __USADA8(uint32_t op
__RES; \
})
-__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UXTB16(uint32_t op1)
+__STATIC_FORCEINLINE uint32_t __UXTB16(uint32_t op1)
{
uint32_t result;
@@ -1157,7 +1879,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UXTB16(uint32_t op
return(result);
}
-__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UXTAB16(uint32_t op1, uint32_t op2)
+__STATIC_FORCEINLINE uint32_t __UXTAB16(uint32_t op1, uint32_t op2)
{
uint32_t result;
@@ -1165,7 +1887,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __UXTAB16(uint32_t o
return(result);
}
-__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SXTB16(uint32_t op1)
+__STATIC_FORCEINLINE uint32_t __SXTB16(uint32_t op1)
{
uint32_t result;
@@ -1173,7 +1895,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SXTB16(uint32_t op
return(result);
}
-__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SXTAB16(uint32_t op1, uint32_t op2)
+__STATIC_FORCEINLINE uint32_t __SXTAB16(uint32_t op1, uint32_t op2)
{
uint32_t result;
@@ -1181,7 +1903,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SXTAB16(uint32_t o
return(result);
}
-__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMUAD (uint32_t op1, uint32_t op2)
+__STATIC_FORCEINLINE uint32_t __SMUAD (uint32_t op1, uint32_t op2)
{
uint32_t result;
@@ -1189,7 +1911,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMUAD (uint32_t o
return(result);
}
-__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMUADX (uint32_t op1, uint32_t op2)
+__STATIC_FORCEINLINE uint32_t __SMUADX (uint32_t op1, uint32_t op2)
{
uint32_t result;
@@ -1197,7 +1919,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMUADX (uint32_t o
return(result);
}
-__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMLAD (uint32_t op1, uint32_t op2, uint32_t op3)
+__STATIC_FORCEINLINE uint32_t __SMLAD (uint32_t op1, uint32_t op2, uint32_t op3)
{
uint32_t result;
@@ -1205,7 +1927,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMLAD (uint32_t op
return(result);
}
-__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMLADX (uint32_t op1, uint32_t op2, uint32_t op3)
+__STATIC_FORCEINLINE uint32_t __SMLADX (uint32_t op1, uint32_t op2, uint32_t op3)
{
uint32_t result;
@@ -1213,7 +1935,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMLADX (uint32_t o
return(result);
}
-__attribute__( ( always_inline ) ) __STATIC_INLINE uint64_t __SMLALD (uint32_t op1, uint32_t op2, uint64_t acc)
+__STATIC_FORCEINLINE uint64_t __SMLALD (uint32_t op1, uint32_t op2, uint64_t acc)
{
union llreg_u{
uint32_t w32[2];
@@ -1230,7 +1952,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint64_t __SMLALD (uint32_t o
return(llr.w64);
}
-__attribute__( ( always_inline ) ) __STATIC_INLINE uint64_t __SMLALDX (uint32_t op1, uint32_t op2, uint64_t acc)
+__STATIC_FORCEINLINE uint64_t __SMLALDX (uint32_t op1, uint32_t op2, uint64_t acc)
{
union llreg_u{
uint32_t w32[2];
@@ -1247,7 +1969,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint64_t __SMLALDX (uint32_t
return(llr.w64);
}
-__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMUSD (uint32_t op1, uint32_t op2)
+__STATIC_FORCEINLINE uint32_t __SMUSD (uint32_t op1, uint32_t op2)
{
uint32_t result;
@@ -1255,7 +1977,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMUSD (uint32_t o
return(result);
}
-__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMUSDX (uint32_t op1, uint32_t op2)
+__STATIC_FORCEINLINE uint32_t __SMUSDX (uint32_t op1, uint32_t op2)
{
uint32_t result;
@@ -1263,7 +1985,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMUSDX (uint32_t o
return(result);
}
-__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMLSD (uint32_t op1, uint32_t op2, uint32_t op3)
+__STATIC_FORCEINLINE uint32_t __SMLSD (uint32_t op1, uint32_t op2, uint32_t op3)
{
uint32_t result;
@@ -1271,7 +1993,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMLSD (uint32_t op
return(result);
}
-__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMLSDX (uint32_t op1, uint32_t op2, uint32_t op3)
+__STATIC_FORCEINLINE uint32_t __SMLSDX (uint32_t op1, uint32_t op2, uint32_t op3)
{
uint32_t result;
@@ -1279,7 +2001,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMLSDX (uint32_t o
return(result);
}
-__attribute__( ( always_inline ) ) __STATIC_INLINE uint64_t __SMLSLD (uint32_t op1, uint32_t op2, uint64_t acc)
+__STATIC_FORCEINLINE uint64_t __SMLSLD (uint32_t op1, uint32_t op2, uint64_t acc)
{
union llreg_u{
uint32_t w32[2];
@@ -1296,7 +2018,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint64_t __SMLSLD (uint32_t o
return(llr.w64);
}
-__attribute__( ( always_inline ) ) __STATIC_INLINE uint64_t __SMLSLDX (uint32_t op1, uint32_t op2, uint64_t acc)
+__STATIC_FORCEINLINE uint64_t __SMLSLDX (uint32_t op1, uint32_t op2, uint64_t acc)
{
union llreg_u{
uint32_t w32[2];
@@ -1313,7 +2035,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint64_t __SMLSLDX (uint32_t
return(llr.w64);
}
-__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SEL (uint32_t op1, uint32_t op2)
+__STATIC_FORCEINLINE uint32_t __SEL (uint32_t op1, uint32_t op2)
{
uint32_t result;
@@ -1321,7 +2043,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SEL (uint32_t op1
return(result);
}
-__attribute__( ( always_inline ) ) __STATIC_INLINE int32_t __QADD( int32_t op1, int32_t op2)
+__STATIC_FORCEINLINE int32_t __QADD( int32_t op1, int32_t op2)
{
int32_t result;
@@ -1329,7 +2051,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE int32_t __QADD( int32_t op1,
return(result);
}
-__attribute__( ( always_inline ) ) __STATIC_INLINE int32_t __QSUB( int32_t op1, int32_t op2)
+__STATIC_FORCEINLINE int32_t __QSUB( int32_t op1, int32_t op2)
{
int32_t result;
@@ -1337,6 +2059,7 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE int32_t __QSUB( int32_t op1,
return(result);
}
+#if 0
#define __PKHBT(ARG1,ARG2,ARG3) \
({ \
uint32_t __RES, __ARG1 = (ARG1), __ARG2 = (ARG2); \
@@ -1353,8 +2076,15 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE int32_t __QSUB( int32_t op1,
__ASM ("pkhtb %0, %1, %2, asr %3" : "=r" (__RES) : "r" (__ARG1), "r" (__ARG2), "I" (ARG3) ); \
__RES; \
})
+#endif
-__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMMLA (int32_t op1, int32_t op2, int32_t op3)
+#define __PKHBT(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0x0000FFFFUL) | \
+ ((((uint32_t)(ARG2)) << (ARG3)) & 0xFFFF0000UL) )
+
+#define __PKHTB(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0xFFFF0000UL) | \
+ ((((uint32_t)(ARG2)) >> (ARG3)) & 0x0000FFFFUL) )
+
+__STATIC_FORCEINLINE int32_t __SMMLA (int32_t op1, int32_t op2, int32_t op3)
{
int32_t result;
@@ -1362,12 +2092,10 @@ __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __SMMLA (int32_t op1
return(result);
}
-#endif /* (__CORTEX_M >= 0x04) */
+#endif /* (__ARM_FEATURE_DSP == 1) */
/*@} end of group CMSIS_SIMD_intrinsics */
-#if defined ( __GNUC__ )
#pragma GCC diagnostic pop
-#endif
#endif /* __CMSIS_GCC_H */
diff --git a/lib/cmsis/inc/cmsis_iccarm.h b/lib/cmsis/inc/cmsis_iccarm.h
new file mode 100644
index 0000000000..20b50ce380
--- /dev/null
+++ b/lib/cmsis/inc/cmsis_iccarm.h
@@ -0,0 +1,940 @@
+/**************************************************************************//**
+ * @file cmsis_iccarm.h
+ * @brief CMSIS compiler ICCARM (IAR Compiler for Arm) header file
+ * @version V5.0.8
+ * @date 04. September 2018
+ ******************************************************************************/
+
+//------------------------------------------------------------------------------
+//
+// Copyright (c) 2017-2018 IAR Systems
+//
+// Licensed under the Apache License, Version 2.0 (the "License")
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//------------------------------------------------------------------------------
+
+
+#ifndef __CMSIS_ICCARM_H__
+#define __CMSIS_ICCARM_H__
+
+#ifndef __ICCARM__
+ #error This file should only be compiled by ICCARM
+#endif
+
+#pragma system_include
+
+#define __IAR_FT _Pragma("inline=forced") __intrinsic
+
+#if (__VER__ >= 8000000)
+ #define __ICCARM_V8 1
+#else
+ #define __ICCARM_V8 0
+#endif
+
+#ifndef __ALIGNED
+ #if __ICCARM_V8
+ #define __ALIGNED(x) __attribute__((aligned(x)))
+ #elif (__VER__ >= 7080000)
+ /* Needs IAR language extensions */
+ #define __ALIGNED(x) __attribute__((aligned(x)))
+ #else
+ #warning No compiler specific solution for __ALIGNED.__ALIGNED is ignored.
+ #define __ALIGNED(x)
+ #endif
+#endif
+
+
+/* Define compiler macros for CPU architecture, used in CMSIS 5.
+ */
+#if __ARM_ARCH_6M__ || __ARM_ARCH_7M__ || __ARM_ARCH_7EM__ || __ARM_ARCH_8M_BASE__ || __ARM_ARCH_8M_MAIN__
+/* Macros already defined */
+#else
+ #if defined(__ARM8M_MAINLINE__) || defined(__ARM8EM_MAINLINE__)
+ #define __ARM_ARCH_8M_MAIN__ 1
+ #elif defined(__ARM8M_BASELINE__)
+ #define __ARM_ARCH_8M_BASE__ 1
+ #elif defined(__ARM_ARCH_PROFILE) && __ARM_ARCH_PROFILE == 'M'
+ #if __ARM_ARCH == 6
+ #define __ARM_ARCH_6M__ 1
+ #elif __ARM_ARCH == 7
+ #if __ARM_FEATURE_DSP
+ #define __ARM_ARCH_7EM__ 1
+ #else
+ #define __ARM_ARCH_7M__ 1
+ #endif
+ #endif /* __ARM_ARCH */
+ #endif /* __ARM_ARCH_PROFILE == 'M' */
+#endif
+
+/* Alternativ core deduction for older ICCARM's */
+#if !defined(__ARM_ARCH_6M__) && !defined(__ARM_ARCH_7M__) && !defined(__ARM_ARCH_7EM__) && \
+ !defined(__ARM_ARCH_8M_BASE__) && !defined(__ARM_ARCH_8M_MAIN__)
+ #if defined(__ARM6M__) && (__CORE__ == __ARM6M__)
+ #define __ARM_ARCH_6M__ 1
+ #elif defined(__ARM7M__) && (__CORE__ == __ARM7M__)
+ #define __ARM_ARCH_7M__ 1
+ #elif defined(__ARM7EM__) && (__CORE__ == __ARM7EM__)
+ #define __ARM_ARCH_7EM__ 1
+ #elif defined(__ARM8M_BASELINE__) && (__CORE == __ARM8M_BASELINE__)
+ #define __ARM_ARCH_8M_BASE__ 1
+ #elif defined(__ARM8M_MAINLINE__) && (__CORE == __ARM8M_MAINLINE__)
+ #define __ARM_ARCH_8M_MAIN__ 1
+ #elif defined(__ARM8EM_MAINLINE__) && (__CORE == __ARM8EM_MAINLINE__)
+ #define __ARM_ARCH_8M_MAIN__ 1
+ #else
+ #error "Unknown target."
+ #endif
+#endif
+
+
+
+#if defined(__ARM_ARCH_6M__) && __ARM_ARCH_6M__==1
+ #define __IAR_M0_FAMILY 1
+#elif defined(__ARM_ARCH_8M_BASE__) && __ARM_ARCH_8M_BASE__==1
+ #define __IAR_M0_FAMILY 1
+#else
+ #define __IAR_M0_FAMILY 0
+#endif
+
+
+#ifndef __ASM
+ #define __ASM __asm
+#endif
+
+#ifndef __INLINE
+ #define __INLINE inline
+#endif
+
+#ifndef __NO_RETURN
+ #if __ICCARM_V8
+ #define __NO_RETURN __attribute__((__noreturn__))
+ #else
+ #define __NO_RETURN _Pragma("object_attribute=__noreturn")
+ #endif
+#endif
+
+#ifndef __PACKED
+ #if __ICCARM_V8
+ #define __PACKED __attribute__((packed, aligned(1)))
+ #else
+ /* Needs IAR language extensions */
+ #define __PACKED __packed
+ #endif
+#endif
+
+#ifndef __PACKED_STRUCT
+ #if __ICCARM_V8
+ #define __PACKED_STRUCT struct __attribute__((packed, aligned(1)))
+ #else
+ /* Needs IAR language extensions */
+ #define __PACKED_STRUCT __packed struct
+ #endif
+#endif
+
+#ifndef __PACKED_UNION
+ #if __ICCARM_V8
+ #define __PACKED_UNION union __attribute__((packed, aligned(1)))
+ #else
+ /* Needs IAR language extensions */
+ #define __PACKED_UNION __packed union
+ #endif
+#endif
+
+#ifndef __RESTRICT
+ #if __ICCARM_V8
+ #define __RESTRICT __restrict
+ #else
+ /* Needs IAR language extensions */
+ #define __RESTRICT restrict
+ #endif
+#endif
+
+#ifndef __STATIC_INLINE
+ #define __STATIC_INLINE static inline
+#endif
+
+#ifndef __FORCEINLINE
+ #define __FORCEINLINE _Pragma("inline=forced")
+#endif
+
+#ifndef __STATIC_FORCEINLINE
+ #define __STATIC_FORCEINLINE __FORCEINLINE __STATIC_INLINE
+#endif
+
+#ifndef __UNALIGNED_UINT16_READ
+#pragma language=save
+#pragma language=extended
+__IAR_FT uint16_t __iar_uint16_read(void const *ptr)
+{
+ return *(__packed uint16_t*)(ptr);
+}
+#pragma language=restore
+#define __UNALIGNED_UINT16_READ(PTR) __iar_uint16_read(PTR)
+#endif
+
+
+#ifndef __UNALIGNED_UINT16_WRITE
+#pragma language=save
+#pragma language=extended
+__IAR_FT void __iar_uint16_write(void const *ptr, uint16_t val)
+{
+ *(__packed uint16_t*)(ptr) = val;;
+}
+#pragma language=restore
+#define __UNALIGNED_UINT16_WRITE(PTR,VAL) __iar_uint16_write(PTR,VAL)
+#endif
+
+#ifndef __UNALIGNED_UINT32_READ
+#pragma language=save
+#pragma language=extended
+__IAR_FT uint32_t __iar_uint32_read(void const *ptr)
+{
+ return *(__packed uint32_t*)(ptr);
+}
+#pragma language=restore
+#define __UNALIGNED_UINT32_READ(PTR) __iar_uint32_read(PTR)
+#endif
+
+#ifndef __UNALIGNED_UINT32_WRITE
+#pragma language=save
+#pragma language=extended
+__IAR_FT void __iar_uint32_write(void const *ptr, uint32_t val)
+{
+ *(__packed uint32_t*)(ptr) = val;;
+}
+#pragma language=restore
+#define __UNALIGNED_UINT32_WRITE(PTR,VAL) __iar_uint32_write(PTR,VAL)
+#endif
+
+#ifndef __UNALIGNED_UINT32 /* deprecated */
+#pragma language=save
+#pragma language=extended
+__packed struct __iar_u32 { uint32_t v; };
+#pragma language=restore
+#define __UNALIGNED_UINT32(PTR) (((struct __iar_u32 *)(PTR))->v)
+#endif
+
+#ifndef __USED
+ #if __ICCARM_V8
+ #define __USED __attribute__((used))
+ #else
+ #define __USED _Pragma("__root")
+ #endif
+#endif
+
+#ifndef __WEAK
+ #if __ICCARM_V8
+ #define __WEAK __attribute__((weak))
+ #else
+ #define __WEAK _Pragma("__weak")
+ #endif
+#endif
+
+
+#ifndef __ICCARM_INTRINSICS_VERSION__
+ #define __ICCARM_INTRINSICS_VERSION__ 0
+#endif
+
+#if __ICCARM_INTRINSICS_VERSION__ == 2
+
+ #if defined(__CLZ)
+ #undef __CLZ
+ #endif
+ #if defined(__REVSH)
+ #undef __REVSH
+ #endif
+ #if defined(__RBIT)
+ #undef __RBIT
+ #endif
+ #if defined(__SSAT)
+ #undef __SSAT
+ #endif
+ #if defined(__USAT)
+ #undef __USAT
+ #endif
+
+ #include "iccarm_builtin.h"
+
+ #define __disable_fault_irq __iar_builtin_disable_fiq
+ #define __disable_irq __iar_builtin_disable_interrupt
+ #define __enable_fault_irq __iar_builtin_enable_fiq
+ #define __enable_irq __iar_builtin_enable_interrupt
+ #define __arm_rsr __iar_builtin_rsr
+ #define __arm_wsr __iar_builtin_wsr
+
+
+ #define __get_APSR() (__arm_rsr("APSR"))
+ #define __get_BASEPRI() (__arm_rsr("BASEPRI"))
+ #define __get_CONTROL() (__arm_rsr("CONTROL"))
+ #define __get_FAULTMASK() (__arm_rsr("FAULTMASK"))
+
+ #if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \
+ (defined (__FPU_USED ) && (__FPU_USED == 1U)) )
+ #define __get_FPSCR() (__arm_rsr("FPSCR"))
+ #define __set_FPSCR(VALUE) (__arm_wsr("FPSCR", (VALUE)))
+ #else
+ #define __get_FPSCR() ( 0 )
+ #define __set_FPSCR(VALUE) ((void)VALUE)
+ #endif
+
+ #define __get_IPSR() (__arm_rsr("IPSR"))
+ #define __get_MSP() (__arm_rsr("MSP"))
+ #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \
+ (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3)))
+ // without main extensions, the non-secure MSPLIM is RAZ/WI
+ #define __get_MSPLIM() (0U)
+ #else
+ #define __get_MSPLIM() (__arm_rsr("MSPLIM"))
+ #endif
+ #define __get_PRIMASK() (__arm_rsr("PRIMASK"))
+ #define __get_PSP() (__arm_rsr("PSP"))
+
+ #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \
+ (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3)))
+ // without main extensions, the non-secure PSPLIM is RAZ/WI
+ #define __get_PSPLIM() (0U)
+ #else
+ #define __get_PSPLIM() (__arm_rsr("PSPLIM"))
+ #endif
+
+ #define __get_xPSR() (__arm_rsr("xPSR"))
+
+ #define __set_BASEPRI(VALUE) (__arm_wsr("BASEPRI", (VALUE)))
+ #define __set_BASEPRI_MAX(VALUE) (__arm_wsr("BASEPRI_MAX", (VALUE)))
+ #define __set_CONTROL(VALUE) (__arm_wsr("CONTROL", (VALUE)))
+ #define __set_FAULTMASK(VALUE) (__arm_wsr("FAULTMASK", (VALUE)))
+ #define __set_MSP(VALUE) (__arm_wsr("MSP", (VALUE)))
+
+ #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \
+ (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3)))
+ // without main extensions, the non-secure MSPLIM is RAZ/WI
+ #define __set_MSPLIM(VALUE) ((void)(VALUE))
+ #else
+ #define __set_MSPLIM(VALUE) (__arm_wsr("MSPLIM", (VALUE)))
+ #endif
+ #define __set_PRIMASK(VALUE) (__arm_wsr("PRIMASK", (VALUE)))
+ #define __set_PSP(VALUE) (__arm_wsr("PSP", (VALUE)))
+ #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \
+ (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3)))
+ // without main extensions, the non-secure PSPLIM is RAZ/WI
+ #define __set_PSPLIM(VALUE) ((void)(VALUE))
+ #else
+ #define __set_PSPLIM(VALUE) (__arm_wsr("PSPLIM", (VALUE)))
+ #endif
+
+ #define __TZ_get_CONTROL_NS() (__arm_rsr("CONTROL_NS"))
+ #define __TZ_set_CONTROL_NS(VALUE) (__arm_wsr("CONTROL_NS", (VALUE)))
+ #define __TZ_get_PSP_NS() (__arm_rsr("PSP_NS"))
+ #define __TZ_set_PSP_NS(VALUE) (__arm_wsr("PSP_NS", (VALUE)))
+ #define __TZ_get_MSP_NS() (__arm_rsr("MSP_NS"))
+ #define __TZ_set_MSP_NS(VALUE) (__arm_wsr("MSP_NS", (VALUE)))
+ #define __TZ_get_SP_NS() (__arm_rsr("SP_NS"))
+ #define __TZ_set_SP_NS(VALUE) (__arm_wsr("SP_NS", (VALUE)))
+ #define __TZ_get_PRIMASK_NS() (__arm_rsr("PRIMASK_NS"))
+ #define __TZ_set_PRIMASK_NS(VALUE) (__arm_wsr("PRIMASK_NS", (VALUE)))
+ #define __TZ_get_BASEPRI_NS() (__arm_rsr("BASEPRI_NS"))
+ #define __TZ_set_BASEPRI_NS(VALUE) (__arm_wsr("BASEPRI_NS", (VALUE)))
+ #define __TZ_get_FAULTMASK_NS() (__arm_rsr("FAULTMASK_NS"))
+ #define __TZ_set_FAULTMASK_NS(VALUE)(__arm_wsr("FAULTMASK_NS", (VALUE)))
+
+ #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \
+ (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3)))
+ // without main extensions, the non-secure PSPLIM is RAZ/WI
+ #define __TZ_get_PSPLIM_NS() (0U)
+ #define __TZ_set_PSPLIM_NS(VALUE) ((void)(VALUE))
+ #else
+ #define __TZ_get_PSPLIM_NS() (__arm_rsr("PSPLIM_NS"))
+ #define __TZ_set_PSPLIM_NS(VALUE) (__arm_wsr("PSPLIM_NS", (VALUE)))
+ #endif
+
+ #define __TZ_get_MSPLIM_NS() (__arm_rsr("MSPLIM_NS"))
+ #define __TZ_set_MSPLIM_NS(VALUE) (__arm_wsr("MSPLIM_NS", (VALUE)))
+
+ #define __NOP __iar_builtin_no_operation
+
+ #define __CLZ __iar_builtin_CLZ
+ #define __CLREX __iar_builtin_CLREX
+
+ #define __DMB __iar_builtin_DMB
+ #define __DSB __iar_builtin_DSB
+ #define __ISB __iar_builtin_ISB
+
+ #define __LDREXB __iar_builtin_LDREXB
+ #define __LDREXH __iar_builtin_LDREXH
+ #define __LDREXW __iar_builtin_LDREX
+
+ #define __RBIT __iar_builtin_RBIT
+ #define __REV __iar_builtin_REV
+ #define __REV16 __iar_builtin_REV16
+
+ __IAR_FT int16_t __REVSH(int16_t val)
+ {
+ return (int16_t) __iar_builtin_REVSH(val);
+ }
+
+ #define __ROR __iar_builtin_ROR
+ #define __RRX __iar_builtin_RRX
+
+ #define __SEV __iar_builtin_SEV
+
+ #if !__IAR_M0_FAMILY
+ #define __SSAT __iar_builtin_SSAT
+ #endif
+
+ #define __STREXB __iar_builtin_STREXB
+ #define __STREXH __iar_builtin_STREXH
+ #define __STREXW __iar_builtin_STREX
+
+ #if !__IAR_M0_FAMILY
+ #define __USAT __iar_builtin_USAT
+ #endif
+
+ #define __WFE __iar_builtin_WFE
+ #define __WFI __iar_builtin_WFI
+
+ #if __ARM_MEDIA__
+ #define __SADD8 __iar_builtin_SADD8
+ #define __QADD8 __iar_builtin_QADD8
+ #define __SHADD8 __iar_builtin_SHADD8
+ #define __UADD8 __iar_builtin_UADD8
+ #define __UQADD8 __iar_builtin_UQADD8
+ #define __UHADD8 __iar_builtin_UHADD8
+ #define __SSUB8 __iar_builtin_SSUB8
+ #define __QSUB8 __iar_builtin_QSUB8
+ #define __SHSUB8 __iar_builtin_SHSUB8
+ #define __USUB8 __iar_builtin_USUB8
+ #define __UQSUB8 __iar_builtin_UQSUB8
+ #define __UHSUB8 __iar_builtin_UHSUB8
+ #define __SADD16 __iar_builtin_SADD16
+ #define __QADD16 __iar_builtin_QADD16
+ #define __SHADD16 __iar_builtin_SHADD16
+ #define __UADD16 __iar_builtin_UADD16
+ #define __UQADD16 __iar_builtin_UQADD16
+ #define __UHADD16 __iar_builtin_UHADD16
+ #define __SSUB16 __iar_builtin_SSUB16
+ #define __QSUB16 __iar_builtin_QSUB16
+ #define __SHSUB16 __iar_builtin_SHSUB16
+ #define __USUB16 __iar_builtin_USUB16
+ #define __UQSUB16 __iar_builtin_UQSUB16
+ #define __UHSUB16 __iar_builtin_UHSUB16
+ #define __SASX __iar_builtin_SASX
+ #define __QASX __iar_builtin_QASX
+ #define __SHASX __iar_builtin_SHASX
+ #define __UASX __iar_builtin_UASX
+ #define __UQASX __iar_builtin_UQASX
+ #define __UHASX __iar_builtin_UHASX
+ #define __SSAX __iar_builtin_SSAX
+ #define __QSAX __iar_builtin_QSAX
+ #define __SHSAX __iar_builtin_SHSAX
+ #define __USAX __iar_builtin_USAX
+ #define __UQSAX __iar_builtin_UQSAX
+ #define __UHSAX __iar_builtin_UHSAX
+ #define __USAD8 __iar_builtin_USAD8
+ #define __USADA8 __iar_builtin_USADA8
+ #define __SSAT16 __iar_builtin_SSAT16
+ #define __USAT16 __iar_builtin_USAT16
+ #define __UXTB16 __iar_builtin_UXTB16
+ #define __UXTAB16 __iar_builtin_UXTAB16
+ #define __SXTB16 __iar_builtin_SXTB16
+ #define __SXTAB16 __iar_builtin_SXTAB16
+ #define __SMUAD __iar_builtin_SMUAD
+ #define __SMUADX __iar_builtin_SMUADX
+ #define __SMMLA __iar_builtin_SMMLA
+ #define __SMLAD __iar_builtin_SMLAD
+ #define __SMLADX __iar_builtin_SMLADX
+ #define __SMLALD __iar_builtin_SMLALD
+ #define __SMLALDX __iar_builtin_SMLALDX
+ #define __SMUSD __iar_builtin_SMUSD
+ #define __SMUSDX __iar_builtin_SMUSDX
+ #define __SMLSD __iar_builtin_SMLSD
+ #define __SMLSDX __iar_builtin_SMLSDX
+ #define __SMLSLD __iar_builtin_SMLSLD
+ #define __SMLSLDX __iar_builtin_SMLSLDX
+ #define __SEL __iar_builtin_SEL
+ #define __QADD __iar_builtin_QADD
+ #define __QSUB __iar_builtin_QSUB
+ #define __PKHBT __iar_builtin_PKHBT
+ #define __PKHTB __iar_builtin_PKHTB
+ #endif
+
+#else /* __ICCARM_INTRINSICS_VERSION__ == 2 */
+
+ #if __IAR_M0_FAMILY
+ /* Avoid clash between intrinsics.h and arm_math.h when compiling for Cortex-M0. */
+ #define __CLZ __cmsis_iar_clz_not_active
+ #define __SSAT __cmsis_iar_ssat_not_active
+ #define __USAT __cmsis_iar_usat_not_active
+ #define __RBIT __cmsis_iar_rbit_not_active
+ #define __get_APSR __cmsis_iar_get_APSR_not_active
+ #endif
+
+
+ #if (!((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \
+ (defined (__FPU_USED ) && (__FPU_USED == 1U)) ))
+ #define __get_FPSCR __cmsis_iar_get_FPSR_not_active
+ #define __set_FPSCR __cmsis_iar_set_FPSR_not_active
+ #endif
+
+ #ifdef __INTRINSICS_INCLUDED
+ #error intrinsics.h is already included previously!
+ #endif
+
+ #include
+
+ #if __IAR_M0_FAMILY
+ /* Avoid clash between intrinsics.h and arm_math.h when compiling for Cortex-M0. */
+ #undef __CLZ
+ #undef __SSAT
+ #undef __USAT
+ #undef __RBIT
+ #undef __get_APSR
+
+ __STATIC_INLINE uint8_t __CLZ(uint32_t data)
+ {
+ if (data == 0U) { return 32U; }
+
+ uint32_t count = 0U;
+ uint32_t mask = 0x80000000U;
+
+ while ((data & mask) == 0U)
+ {
+ count += 1U;
+ mask = mask >> 1U;
+ }
+ return count;
+ }
+
+ __STATIC_INLINE uint32_t __RBIT(uint32_t v)
+ {
+ uint8_t sc = 31U;
+ uint32_t r = v;
+ for (v >>= 1U; v; v >>= 1U)
+ {
+ r <<= 1U;
+ r |= v & 1U;
+ sc--;
+ }
+ return (r << sc);
+ }
+
+ __STATIC_INLINE uint32_t __get_APSR(void)
+ {
+ uint32_t res;
+ __asm("MRS %0,APSR" : "=r" (res));
+ return res;
+ }
+
+ #endif
+
+ #if (!((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \
+ (defined (__FPU_USED ) && (__FPU_USED == 1U)) ))
+ #undef __get_FPSCR
+ #undef __set_FPSCR
+ #define __get_FPSCR() (0)
+ #define __set_FPSCR(VALUE) ((void)VALUE)
+ #endif
+
+ #pragma diag_suppress=Pe940
+ #pragma diag_suppress=Pe177
+
+ #define __enable_irq __enable_interrupt
+ #define __disable_irq __disable_interrupt
+ #define __NOP __no_operation
+
+ #define __get_xPSR __get_PSR
+
+ #if (!defined(__ARM_ARCH_6M__) || __ARM_ARCH_6M__==0)
+
+ __IAR_FT uint32_t __LDREXW(uint32_t volatile *ptr)
+ {
+ return __LDREX((unsigned long *)ptr);
+ }
+
+ __IAR_FT uint32_t __STREXW(uint32_t value, uint32_t volatile *ptr)
+ {
+ return __STREX(value, (unsigned long *)ptr);
+ }
+ #endif
+
+
+ /* __CORTEX_M is defined in core_cm0.h, core_cm3.h and core_cm4.h. */
+ #if (__CORTEX_M >= 0x03)
+
+ __IAR_FT uint32_t __RRX(uint32_t value)
+ {
+ uint32_t result;
+ __ASM("RRX %0, %1" : "=r"(result) : "r" (value) : "cc");
+ return(result);
+ }
+
+ __IAR_FT void __set_BASEPRI_MAX(uint32_t value)
+ {
+ __asm volatile("MSR BASEPRI_MAX,%0"::"r" (value));
+ }
+
+
+ #define __enable_fault_irq __enable_fiq
+ #define __disable_fault_irq __disable_fiq
+
+
+ #endif /* (__CORTEX_M >= 0x03) */
+
+ __IAR_FT uint32_t __ROR(uint32_t op1, uint32_t op2)
+ {
+ return (op1 >> op2) | (op1 << ((sizeof(op1)*8)-op2));
+ }
+
+ #if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \
+ (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) )
+
+ __IAR_FT uint32_t __get_MSPLIM(void)
+ {
+ uint32_t res;
+ #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \
+ (!defined (__ARM_FEATURE_CMSE ) || (__ARM_FEATURE_CMSE < 3)))
+ // without main extensions, the non-secure MSPLIM is RAZ/WI
+ res = 0U;
+ #else
+ __asm volatile("MRS %0,MSPLIM" : "=r" (res));
+ #endif
+ return res;
+ }
+
+ __IAR_FT void __set_MSPLIM(uint32_t value)
+ {
+ #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \
+ (!defined (__ARM_FEATURE_CMSE ) || (__ARM_FEATURE_CMSE < 3)))
+ // without main extensions, the non-secure MSPLIM is RAZ/WI
+ (void)value;
+ #else
+ __asm volatile("MSR MSPLIM,%0" :: "r" (value));
+ #endif
+ }
+
+ __IAR_FT uint32_t __get_PSPLIM(void)
+ {
+ uint32_t res;
+ #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \
+ (!defined (__ARM_FEATURE_CMSE ) || (__ARM_FEATURE_CMSE < 3)))
+ // without main extensions, the non-secure PSPLIM is RAZ/WI
+ res = 0U;
+ #else
+ __asm volatile("MRS %0,PSPLIM" : "=r" (res));
+ #endif
+ return res;
+ }
+
+ __IAR_FT void __set_PSPLIM(uint32_t value)
+ {
+ #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \
+ (!defined (__ARM_FEATURE_CMSE ) || (__ARM_FEATURE_CMSE < 3)))
+ // without main extensions, the non-secure PSPLIM is RAZ/WI
+ (void)value;
+ #else
+ __asm volatile("MSR PSPLIM,%0" :: "r" (value));
+ #endif
+ }
+
+ __IAR_FT uint32_t __TZ_get_CONTROL_NS(void)
+ {
+ uint32_t res;
+ __asm volatile("MRS %0,CONTROL_NS" : "=r" (res));
+ return res;
+ }
+
+ __IAR_FT void __TZ_set_CONTROL_NS(uint32_t value)
+ {
+ __asm volatile("MSR CONTROL_NS,%0" :: "r" (value));
+ }
+
+ __IAR_FT uint32_t __TZ_get_PSP_NS(void)
+ {
+ uint32_t res;
+ __asm volatile("MRS %0,PSP_NS" : "=r" (res));
+ return res;
+ }
+
+ __IAR_FT void __TZ_set_PSP_NS(uint32_t value)
+ {
+ __asm volatile("MSR PSP_NS,%0" :: "r" (value));
+ }
+
+ __IAR_FT uint32_t __TZ_get_MSP_NS(void)
+ {
+ uint32_t res;
+ __asm volatile("MRS %0,MSP_NS" : "=r" (res));
+ return res;
+ }
+
+ __IAR_FT void __TZ_set_MSP_NS(uint32_t value)
+ {
+ __asm volatile("MSR MSP_NS,%0" :: "r" (value));
+ }
+
+ __IAR_FT uint32_t __TZ_get_SP_NS(void)
+ {
+ uint32_t res;
+ __asm volatile("MRS %0,SP_NS" : "=r" (res));
+ return res;
+ }
+ __IAR_FT void __TZ_set_SP_NS(uint32_t value)
+ {
+ __asm volatile("MSR SP_NS,%0" :: "r" (value));
+ }
+
+ __IAR_FT uint32_t __TZ_get_PRIMASK_NS(void)
+ {
+ uint32_t res;
+ __asm volatile("MRS %0,PRIMASK_NS" : "=r" (res));
+ return res;
+ }
+
+ __IAR_FT void __TZ_set_PRIMASK_NS(uint32_t value)
+ {
+ __asm volatile("MSR PRIMASK_NS,%0" :: "r" (value));
+ }
+
+ __IAR_FT uint32_t __TZ_get_BASEPRI_NS(void)
+ {
+ uint32_t res;
+ __asm volatile("MRS %0,BASEPRI_NS" : "=r" (res));
+ return res;
+ }
+
+ __IAR_FT void __TZ_set_BASEPRI_NS(uint32_t value)
+ {
+ __asm volatile("MSR BASEPRI_NS,%0" :: "r" (value));
+ }
+
+ __IAR_FT uint32_t __TZ_get_FAULTMASK_NS(void)
+ {
+ uint32_t res;
+ __asm volatile("MRS %0,FAULTMASK_NS" : "=r" (res));
+ return res;
+ }
+
+ __IAR_FT void __TZ_set_FAULTMASK_NS(uint32_t value)
+ {
+ __asm volatile("MSR FAULTMASK_NS,%0" :: "r" (value));
+ }
+
+ __IAR_FT uint32_t __TZ_get_PSPLIM_NS(void)
+ {
+ uint32_t res;
+ #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \
+ (!defined (__ARM_FEATURE_CMSE ) || (__ARM_FEATURE_CMSE < 3)))
+ // without main extensions, the non-secure PSPLIM is RAZ/WI
+ res = 0U;
+ #else
+ __asm volatile("MRS %0,PSPLIM_NS" : "=r" (res));
+ #endif
+ return res;
+ }
+
+ __IAR_FT void __TZ_set_PSPLIM_NS(uint32_t value)
+ {
+ #if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \
+ (!defined (__ARM_FEATURE_CMSE ) || (__ARM_FEATURE_CMSE < 3)))
+ // without main extensions, the non-secure PSPLIM is RAZ/WI
+ (void)value;
+ #else
+ __asm volatile("MSR PSPLIM_NS,%0" :: "r" (value));
+ #endif
+ }
+
+ __IAR_FT uint32_t __TZ_get_MSPLIM_NS(void)
+ {
+ uint32_t res;
+ __asm volatile("MRS %0,MSPLIM_NS" : "=r" (res));
+ return res;
+ }
+
+ __IAR_FT void __TZ_set_MSPLIM_NS(uint32_t value)
+ {
+ __asm volatile("MSR MSPLIM_NS,%0" :: "r" (value));
+ }
+
+ #endif /* __ARM_ARCH_8M_MAIN__ or __ARM_ARCH_8M_BASE__ */
+
+#endif /* __ICCARM_INTRINSICS_VERSION__ == 2 */
+
+#define __BKPT(value) __asm volatile ("BKPT %0" : : "i"(value))
+
+#if __IAR_M0_FAMILY
+ __STATIC_INLINE int32_t __SSAT(int32_t val, uint32_t sat)
+ {
+ if ((sat >= 1U) && (sat <= 32U))
+ {
+ const int32_t max = (int32_t)((1U << (sat - 1U)) - 1U);
+ const int32_t min = -1 - max ;
+ if (val > max)
+ {
+ return max;
+ }
+ else if (val < min)
+ {
+ return min;
+ }
+ }
+ return val;
+ }
+
+ __STATIC_INLINE uint32_t __USAT(int32_t val, uint32_t sat)
+ {
+ if (sat <= 31U)
+ {
+ const uint32_t max = ((1U << sat) - 1U);
+ if (val > (int32_t)max)
+ {
+ return max;
+ }
+ else if (val < 0)
+ {
+ return 0U;
+ }
+ }
+ return (uint32_t)val;
+ }
+#endif
+
+#if (__CORTEX_M >= 0x03) /* __CORTEX_M is defined in core_cm0.h, core_cm3.h and core_cm4.h. */
+
+ __IAR_FT uint8_t __LDRBT(volatile uint8_t *addr)
+ {
+ uint32_t res;
+ __ASM("LDRBT %0, [%1]" : "=r" (res) : "r" (addr) : "memory");
+ return ((uint8_t)res);
+ }
+
+ __IAR_FT uint16_t __LDRHT(volatile uint16_t *addr)
+ {
+ uint32_t res;
+ __ASM("LDRHT %0, [%1]" : "=r" (res) : "r" (addr) : "memory");
+ return ((uint16_t)res);
+ }
+
+ __IAR_FT uint32_t __LDRT(volatile uint32_t *addr)
+ {
+ uint32_t res;
+ __ASM("LDRT %0, [%1]" : "=r" (res) : "r" (addr) : "memory");
+ return res;
+ }
+
+ __IAR_FT void __STRBT(uint8_t value, volatile uint8_t *addr)
+ {
+ __ASM("STRBT %1, [%0]" : : "r" (addr), "r" ((uint32_t)value) : "memory");
+ }
+
+ __IAR_FT void __STRHT(uint16_t value, volatile uint16_t *addr)
+ {
+ __ASM("STRHT %1, [%0]" : : "r" (addr), "r" ((uint32_t)value) : "memory");
+ }
+
+ __IAR_FT void __STRT(uint32_t value, volatile uint32_t *addr)
+ {
+ __ASM("STRT %1, [%0]" : : "r" (addr), "r" (value) : "memory");
+ }
+
+#endif /* (__CORTEX_M >= 0x03) */
+
+#if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \
+ (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) )
+
+
+ __IAR_FT uint8_t __LDAB(volatile uint8_t *ptr)
+ {
+ uint32_t res;
+ __ASM volatile ("LDAB %0, [%1]" : "=r" (res) : "r" (ptr) : "memory");
+ return ((uint8_t)res);
+ }
+
+ __IAR_FT uint16_t __LDAH(volatile uint16_t *ptr)
+ {
+ uint32_t res;
+ __ASM volatile ("LDAH %0, [%1]" : "=r" (res) : "r" (ptr) : "memory");
+ return ((uint16_t)res);
+ }
+
+ __IAR_FT uint32_t __LDA(volatile uint32_t *ptr)
+ {
+ uint32_t res;
+ __ASM volatile ("LDA %0, [%1]" : "=r" (res) : "r" (ptr) : "memory");
+ return res;
+ }
+
+ __IAR_FT void __STLB(uint8_t value, volatile uint8_t *ptr)
+ {
+ __ASM volatile ("STLB %1, [%0]" :: "r" (ptr), "r" (value) : "memory");
+ }
+
+ __IAR_FT void __STLH(uint16_t value, volatile uint16_t *ptr)
+ {
+ __ASM volatile ("STLH %1, [%0]" :: "r" (ptr), "r" (value) : "memory");
+ }
+
+ __IAR_FT void __STL(uint32_t value, volatile uint32_t *ptr)
+ {
+ __ASM volatile ("STL %1, [%0]" :: "r" (ptr), "r" (value) : "memory");
+ }
+
+ __IAR_FT uint8_t __LDAEXB(volatile uint8_t *ptr)
+ {
+ uint32_t res;
+ __ASM volatile ("LDAEXB %0, [%1]" : "=r" (res) : "r" (ptr) : "memory");
+ return ((uint8_t)res);
+ }
+
+ __IAR_FT uint16_t __LDAEXH(volatile uint16_t *ptr)
+ {
+ uint32_t res;
+ __ASM volatile ("LDAEXH %0, [%1]" : "=r" (res) : "r" (ptr) : "memory");
+ return ((uint16_t)res);
+ }
+
+ __IAR_FT uint32_t __LDAEX(volatile uint32_t *ptr)
+ {
+ uint32_t res;
+ __ASM volatile ("LDAEX %0, [%1]" : "=r" (res) : "r" (ptr) : "memory");
+ return res;
+ }
+
+ __IAR_FT uint32_t __STLEXB(uint8_t value, volatile uint8_t *ptr)
+ {
+ uint32_t res;
+ __ASM volatile ("STLEXB %0, %2, [%1]" : "=r" (res) : "r" (ptr), "r" (value) : "memory");
+ return res;
+ }
+
+ __IAR_FT uint32_t __STLEXH(uint16_t value, volatile uint16_t *ptr)
+ {
+ uint32_t res;
+ __ASM volatile ("STLEXH %0, %2, [%1]" : "=r" (res) : "r" (ptr), "r" (value) : "memory");
+ return res;
+ }
+
+ __IAR_FT uint32_t __STLEX(uint32_t value, volatile uint32_t *ptr)
+ {
+ uint32_t res;
+ __ASM volatile ("STLEX %0, %2, [%1]" : "=r" (res) : "r" (ptr), "r" (value) : "memory");
+ return res;
+ }
+
+#endif /* __ARM_ARCH_8M_MAIN__ or __ARM_ARCH_8M_BASE__ */
+
+#undef __IAR_FT
+#undef __IAR_M0_FAMILY
+#undef __ICCARM_V8
+
+#pragma diag_default=Pe940
+#pragma diag_default=Pe177
+
+#endif /* __CMSIS_ICCARM_H__ */
diff --git a/lib/cmsis/inc/cmsis_version.h b/lib/cmsis/inc/cmsis_version.h
new file mode 100644
index 0000000000..660f612aa3
--- /dev/null
+++ b/lib/cmsis/inc/cmsis_version.h
@@ -0,0 +1,39 @@
+/**************************************************************************//**
+ * @file cmsis_version.h
+ * @brief CMSIS Core(M) Version definitions
+ * @version V5.0.2
+ * @date 19. April 2017
+ ******************************************************************************/
+/*
+ * Copyright (c) 2009-2017 ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#if defined ( __ICCARM__ )
+ #pragma system_include /* treat file as system include file for MISRA check */
+#elif defined (__clang__)
+ #pragma clang system_header /* treat file as system include file */
+#endif
+
+#ifndef __CMSIS_VERSION_H
+#define __CMSIS_VERSION_H
+
+/* CMSIS Version definitions */
+#define __CM_CMSIS_VERSION_MAIN ( 5U) /*!< [31:16] CMSIS Core(M) main version */
+#define __CM_CMSIS_VERSION_SUB ( 1U) /*!< [15:0] CMSIS Core(M) sub version */
+#define __CM_CMSIS_VERSION ((__CM_CMSIS_VERSION_MAIN << 16U) | \
+ __CM_CMSIS_VERSION_SUB ) /*!< CMSIS Core(M) version number */
+#endif
diff --git a/lib/cmsis/inc/core_armv81mml.h b/lib/cmsis/inc/core_armv81mml.h
new file mode 100644
index 0000000000..db6d9f2363
--- /dev/null
+++ b/lib/cmsis/inc/core_armv81mml.h
@@ -0,0 +1,2967 @@
+/**************************************************************************//**
+ * @file core_armv81mml.h
+ * @brief CMSIS Armv8.1-M Mainline Core Peripheral Access Layer Header File
+ * @version V1.0.0
+ * @date 15. March 2019
+ ******************************************************************************/
+/*
+ * Copyright (c) 2018-2019 Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#if defined ( __ICCARM__ )
+ #pragma system_include /* treat file as system include file for MISRA check */
+#elif defined (__clang__)
+ #pragma clang system_header /* treat file as system include file */
+#endif
+
+#ifndef __CORE_ARMV81MML_H_GENERIC
+#define __CORE_ARMV81MML_H_GENERIC
+
+#include
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/**
+ \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions
+ CMSIS violates the following MISRA-C:2004 rules:
+
+ \li Required Rule 8.5, object/function definition in header file.
+ Function definitions in header files are used to allow 'inlining'.
+
+ \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
+ Unions are used for effective representation of core registers.
+
+ \li Advisory Rule 19.7, Function-like macro defined.
+ Function-like macros are used to allow more efficient code.
+ */
+
+
+/*******************************************************************************
+ * CMSIS definitions
+ ******************************************************************************/
+/**
+ \ingroup Cortex_ARMV81MML
+ @{
+ */
+
+#include "cmsis_version.h"
+
+#define __ARM_ARCH_8M_MAIN__ 1 // patching for now
+/* CMSIS ARMV81MML definitions */
+#define __ARMv81MML_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */
+#define __ARMv81MML_CMSIS_VERSION_SUB (__CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */
+#define __ARMv81MML_CMSIS_VERSION ((__ARMv81MML_CMSIS_VERSION_MAIN << 16U) | \
+ __ARMv81MML_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */
+
+#define __CORTEX_M (81U) /*!< Cortex-M Core */
+
+/** __FPU_USED indicates whether an FPU is used or not.
+ For this, __FPU_PRESENT has to be checked prior to making use of FPU specific registers and functions.
+*/
+#if defined ( __CC_ARM )
+ #if defined __TARGET_FPU_VFP
+ #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)
+ #define __FPU_USED 1U
+ #else
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #define __FPU_USED 0U
+ #endif
+ #else
+ #define __FPU_USED 0U
+ #endif
+
+ #if defined(__ARM_FEATURE_DSP)
+ #if defined(__DSP_PRESENT) && (__DSP_PRESENT == 1U)
+ #define __DSP_USED 1U
+ #else
+ #error "Compiler generates DSP (SIMD) instructions for a devices without DSP extensions (check __DSP_PRESENT)"
+ #define __DSP_USED 0U
+ #endif
+ #else
+ #define __DSP_USED 0U
+ #endif
+
+#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
+ #if defined __ARM_FP
+ #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)
+ #define __FPU_USED 1U
+ #else
+ #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #define __FPU_USED 0U
+ #endif
+ #else
+ #define __FPU_USED 0U
+ #endif
+
+ #if defined(__ARM_FEATURE_DSP)
+ #if defined(__DSP_PRESENT) && (__DSP_PRESENT == 1U)
+ #define __DSP_USED 1U
+ #else
+ #error "Compiler generates DSP (SIMD) instructions for a devices without DSP extensions (check __DSP_PRESENT)"
+ #define __DSP_USED 0U
+ #endif
+ #else
+ #define __DSP_USED 0U
+ #endif
+
+#elif defined ( __GNUC__ )
+ #if defined (__VFP_FP__) && !defined(__SOFTFP__)
+ #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)
+ #define __FPU_USED 1U
+ #else
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #define __FPU_USED 0U
+ #endif
+ #else
+ #define __FPU_USED 0U
+ #endif
+
+ #if defined(__ARM_FEATURE_DSP)
+ #if defined(__DSP_PRESENT) && (__DSP_PRESENT == 1U)
+ #define __DSP_USED 1U
+ #else
+ #error "Compiler generates DSP (SIMD) instructions for a devices without DSP extensions (check __DSP_PRESENT)"
+ #define __DSP_USED 0U
+ #endif
+ #else
+ #define __DSP_USED 0U
+ #endif
+
+#elif defined ( __ICCARM__ )
+ #if defined __ARMVFP__
+ #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)
+ #define __FPU_USED 1U
+ #else
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #define __FPU_USED 0U
+ #endif
+ #else
+ #define __FPU_USED 0U
+ #endif
+
+ #if defined(__ARM_FEATURE_DSP)
+ #if defined(__DSP_PRESENT) && (__DSP_PRESENT == 1U)
+ #define __DSP_USED 1U
+ #else
+ #error "Compiler generates DSP (SIMD) instructions for a devices without DSP extensions (check __DSP_PRESENT)"
+ #define __DSP_USED 0U
+ #endif
+ #else
+ #define __DSP_USED 0U
+ #endif
+
+#elif defined ( __TI_ARM__ )
+ #if defined __TI_VFP_SUPPORT__
+ #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)
+ #define __FPU_USED 1U
+ #else
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #define __FPU_USED 0U
+ #endif
+ #else
+ #define __FPU_USED 0U
+ #endif
+
+#elif defined ( __TASKING__ )
+ #if defined __FPU_VFP__
+ #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)
+ #define __FPU_USED 1U
+ #else
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #define __FPU_USED 0U
+ #endif
+ #else
+ #define __FPU_USED 0U
+ #endif
+
+#elif defined ( __CSMC__ )
+ #if ( __CSMC__ & 0x400U)
+ #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)
+ #define __FPU_USED 1U
+ #else
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #define __FPU_USED 0U
+ #endif
+ #else
+ #define __FPU_USED 0U
+ #endif
+
+#endif
+
+#include "cmsis_compiler.h" /* CMSIS compiler specific defines */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CORE_ARMV81MML_H_GENERIC */
+
+#ifndef __CMSIS_GENERIC
+
+#ifndef __CORE_ARMV81MML_H_DEPENDANT
+#define __CORE_ARMV81MML_H_DEPENDANT
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/* check device defines and use defaults */
+#if defined __CHECK_DEVICE_DEFINES
+ #ifndef __ARMv81MML_REV
+ #define __ARMv81MML_REV 0x0000U
+ #warning "__ARMv81MML_REV not defined in device header file; using default!"
+ #endif
+
+ #ifndef __FPU_PRESENT
+ #define __FPU_PRESENT 0U
+ #warning "__FPU_PRESENT not defined in device header file; using default!"
+ #endif
+
+ #ifndef __MPU_PRESENT
+ #define __MPU_PRESENT 0U
+ #warning "__MPU_PRESENT not defined in device header file; using default!"
+ #endif
+
+ #ifndef __SAUREGION_PRESENT
+ #define __SAUREGION_PRESENT 0U
+ #warning "__SAUREGION_PRESENT not defined in device header file; using default!"
+ #endif
+
+ #ifndef __DSP_PRESENT
+ #define __DSP_PRESENT 0U
+ #warning "__DSP_PRESENT not defined in device header file; using default!"
+ #endif
+
+ #ifndef __NVIC_PRIO_BITS
+ #define __NVIC_PRIO_BITS 3U
+ #warning "__NVIC_PRIO_BITS not defined in device header file; using default!"
+ #endif
+
+ #ifndef __Vendor_SysTickConfig
+ #define __Vendor_SysTickConfig 0U
+ #warning "__Vendor_SysTickConfig not defined in device header file; using default!"
+ #endif
+#endif
+
+/* IO definitions (access restrictions to peripheral registers) */
+/**
+ \defgroup CMSIS_glob_defs CMSIS Global Defines
+
+ IO Type Qualifiers are used
+ \li to specify the access to peripheral variables.
+ \li for automatic generation of peripheral register debug information.
+*/
+#ifdef __cplusplus
+ #define __I volatile /*!< Defines 'read only' permissions */
+#else
+ #define __I volatile const /*!< Defines 'read only' permissions */
+#endif
+#define __O volatile /*!< Defines 'write only' permissions */
+#define __IO volatile /*!< Defines 'read / write' permissions */
+
+/* following defines should be used for structure members */
+#define __IM volatile const /*! Defines 'read only' structure member permissions */
+#define __OM volatile /*! Defines 'write only' structure member permissions */
+#define __IOM volatile /*! Defines 'read / write' structure member permissions */
+
+/*@} end of group ARMv81MML */
+
+
+
+/*******************************************************************************
+ * Register Abstraction
+ Core Register contain:
+ - Core Register
+ - Core NVIC Register
+ - Core SCB Register
+ - Core SysTick Register
+ - Core Debug Register
+ - Core MPU Register
+ - Core SAU Register
+ - Core FPU Register
+ ******************************************************************************/
+/**
+ \defgroup CMSIS_core_register Defines and Type Definitions
+ \brief Type definitions and defines for Cortex-M processor based devices.
+*/
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_CORE Status and Control Registers
+ \brief Core Register type definitions.
+ @{
+ */
+
+/**
+ \brief Union type to access the Application Program Status Register (APSR).
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t _reserved0:16; /*!< bit: 0..15 Reserved */
+ uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */
+ uint32_t _reserved1:7; /*!< bit: 20..26 Reserved */
+ uint32_t Q:1; /*!< bit: 27 Saturation condition flag */
+ uint32_t V:1; /*!< bit: 28 Overflow condition code flag */
+ uint32_t C:1; /*!< bit: 29 Carry condition code flag */
+ uint32_t Z:1; /*!< bit: 30 Zero condition code flag */
+ uint32_t N:1; /*!< bit: 31 Negative condition code flag */
+ } b; /*!< Structure used for bit access */
+ uint32_t w; /*!< Type used for word access */
+} APSR_Type;
+
+/* APSR Register Definitions */
+#define APSR_N_Pos 31U /*!< APSR: N Position */
+#define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */
+
+#define APSR_Z_Pos 30U /*!< APSR: Z Position */
+#define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */
+
+#define APSR_C_Pos 29U /*!< APSR: C Position */
+#define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */
+
+#define APSR_V_Pos 28U /*!< APSR: V Position */
+#define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */
+
+#define APSR_Q_Pos 27U /*!< APSR: Q Position */
+#define APSR_Q_Msk (1UL << APSR_Q_Pos) /*!< APSR: Q Mask */
+
+#define APSR_GE_Pos 16U /*!< APSR: GE Position */
+#define APSR_GE_Msk (0xFUL << APSR_GE_Pos) /*!< APSR: GE Mask */
+
+
+/**
+ \brief Union type to access the Interrupt Program Status Register (IPSR).
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */
+ uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */
+ } b; /*!< Structure used for bit access */
+ uint32_t w; /*!< Type used for word access */
+} IPSR_Type;
+
+/* IPSR Register Definitions */
+#define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */
+#define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */
+
+
+/**
+ \brief Union type to access the Special-Purpose Program Status Registers (xPSR).
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */
+ uint32_t _reserved0:7; /*!< bit: 9..15 Reserved */
+ uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */
+ uint32_t _reserved1:4; /*!< bit: 20..23 Reserved */
+ uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */
+ uint32_t IT:2; /*!< bit: 25..26 saved IT state (read 0) */
+ uint32_t Q:1; /*!< bit: 27 Saturation condition flag */
+ uint32_t V:1; /*!< bit: 28 Overflow condition code flag */
+ uint32_t C:1; /*!< bit: 29 Carry condition code flag */
+ uint32_t Z:1; /*!< bit: 30 Zero condition code flag */
+ uint32_t N:1; /*!< bit: 31 Negative condition code flag */
+ } b; /*!< Structure used for bit access */
+ uint32_t w; /*!< Type used for word access */
+} xPSR_Type;
+
+/* xPSR Register Definitions */
+#define xPSR_N_Pos 31U /*!< xPSR: N Position */
+#define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */
+
+#define xPSR_Z_Pos 30U /*!< xPSR: Z Position */
+#define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */
+
+#define xPSR_C_Pos 29U /*!< xPSR: C Position */
+#define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */
+
+#define xPSR_V_Pos 28U /*!< xPSR: V Position */
+#define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */
+
+#define xPSR_Q_Pos 27U /*!< xPSR: Q Position */
+#define xPSR_Q_Msk (1UL << xPSR_Q_Pos) /*!< xPSR: Q Mask */
+
+#define xPSR_IT_Pos 25U /*!< xPSR: IT Position */
+#define xPSR_IT_Msk (3UL << xPSR_IT_Pos) /*!< xPSR: IT Mask */
+
+#define xPSR_T_Pos 24U /*!< xPSR: T Position */
+#define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */
+
+#define xPSR_GE_Pos 16U /*!< xPSR: GE Position */
+#define xPSR_GE_Msk (0xFUL << xPSR_GE_Pos) /*!< xPSR: GE Mask */
+
+#define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */
+#define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */
+
+
+/**
+ \brief Union type to access the Control Registers (CONTROL).
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */
+ uint32_t SPSEL:1; /*!< bit: 1 Stack-pointer select */
+ uint32_t FPCA:1; /*!< bit: 2 Floating-point context active */
+ uint32_t SFPA:1; /*!< bit: 3 Secure floating-point active */
+ uint32_t _reserved1:28; /*!< bit: 4..31 Reserved */
+ } b; /*!< Structure used for bit access */
+ uint32_t w; /*!< Type used for word access */
+} CONTROL_Type;
+
+/* CONTROL Register Definitions */
+#define CONTROL_SFPA_Pos 3U /*!< CONTROL: SFPA Position */
+#define CONTROL_SFPA_Msk (1UL << CONTROL_SFPA_Pos) /*!< CONTROL: SFPA Mask */
+
+#define CONTROL_FPCA_Pos 2U /*!< CONTROL: FPCA Position */
+#define CONTROL_FPCA_Msk (1UL << CONTROL_FPCA_Pos) /*!< CONTROL: FPCA Mask */
+
+#define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */
+#define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */
+
+#define CONTROL_nPRIV_Pos 0U /*!< CONTROL: nPRIV Position */
+#define CONTROL_nPRIV_Msk (1UL /*<< CONTROL_nPRIV_Pos*/) /*!< CONTROL: nPRIV Mask */
+
+/*@} end of group CMSIS_CORE */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC)
+ \brief Type definitions for the NVIC Registers
+ @{
+ */
+
+/**
+ \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC).
+ */
+typedef struct
+{
+ __IOM uint32_t ISER[16U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */
+ uint32_t RESERVED0[16U];
+ __IOM uint32_t ICER[16U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */
+ uint32_t RSERVED1[16U];
+ __IOM uint32_t ISPR[16U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */
+ uint32_t RESERVED2[16U];
+ __IOM uint32_t ICPR[16U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */
+ uint32_t RESERVED3[16U];
+ __IOM uint32_t IABR[16U]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */
+ uint32_t RESERVED4[16U];
+ __IOM uint32_t ITNS[16U]; /*!< Offset: 0x280 (R/W) Interrupt Non-Secure State Register */
+ uint32_t RESERVED5[16U];
+ __IOM uint8_t IPR[496U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register (8Bit wide) */
+ uint32_t RESERVED6[580U];
+ __OM uint32_t STIR; /*!< Offset: 0xE00 ( /W) Software Trigger Interrupt Register */
+} NVIC_Type;
+
+/* Software Triggered Interrupt Register Definitions */
+#define NVIC_STIR_INTID_Pos 0U /*!< STIR: INTLINESNUM Position */
+#define NVIC_STIR_INTID_Msk (0x1FFUL /*<< NVIC_STIR_INTID_Pos*/) /*!< STIR: INTLINESNUM Mask */
+
+/*@} end of group CMSIS_NVIC */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_SCB System Control Block (SCB)
+ \brief Type definitions for the System Control Block Registers
+ @{
+ */
+
+/**
+ \brief Structure type to access the System Control Block (SCB).
+ */
+typedef struct
+{
+ __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */
+ __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */
+ __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */
+ __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */
+ __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */
+ __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */
+ __IOM uint8_t SHPR[12U]; /*!< Offset: 0x018 (R/W) System Handlers Priority Registers (4-7, 8-11, 12-15) */
+ __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */
+ __IOM uint32_t CFSR; /*!< Offset: 0x028 (R/W) Configurable Fault Status Register */
+ __IOM uint32_t HFSR; /*!< Offset: 0x02C (R/W) HardFault Status Register */
+ __IOM uint32_t DFSR; /*!< Offset: 0x030 (R/W) Debug Fault Status Register */
+ __IOM uint32_t MMFAR; /*!< Offset: 0x034 (R/W) MemManage Fault Address Register */
+ __IOM uint32_t BFAR; /*!< Offset: 0x038 (R/W) BusFault Address Register */
+ __IOM uint32_t AFSR; /*!< Offset: 0x03C (R/W) Auxiliary Fault Status Register */
+ __IM uint32_t ID_PFR[2U]; /*!< Offset: 0x040 (R/ ) Processor Feature Register */
+ __IM uint32_t ID_DFR; /*!< Offset: 0x048 (R/ ) Debug Feature Register */
+ __IM uint32_t ID_ADR; /*!< Offset: 0x04C (R/ ) Auxiliary Feature Register */
+ __IM uint32_t ID_MMFR[4U]; /*!< Offset: 0x050 (R/ ) Memory Model Feature Register */
+ __IM uint32_t ID_ISAR[6U]; /*!< Offset: 0x060 (R/ ) Instruction Set Attributes Register */
+ __IM uint32_t CLIDR; /*!< Offset: 0x078 (R/ ) Cache Level ID register */
+ __IM uint32_t CTR; /*!< Offset: 0x07C (R/ ) Cache Type register */
+ __IM uint32_t CCSIDR; /*!< Offset: 0x080 (R/ ) Cache Size ID Register */
+ __IOM uint32_t CSSELR; /*!< Offset: 0x084 (R/W) Cache Size Selection Register */
+ __IOM uint32_t CPACR; /*!< Offset: 0x088 (R/W) Coprocessor Access Control Register */
+ __IOM uint32_t NSACR; /*!< Offset: 0x08C (R/W) Non-Secure Access Control Register */
+ uint32_t RESERVED3[92U];
+ __OM uint32_t STIR; /*!< Offset: 0x200 ( /W) Software Triggered Interrupt Register */
+ uint32_t RESERVED4[15U];
+ __IM uint32_t MVFR0; /*!< Offset: 0x240 (R/ ) Media and VFP Feature Register 0 */
+ __IM uint32_t MVFR1; /*!< Offset: 0x244 (R/ ) Media and VFP Feature Register 1 */
+ __IM uint32_t MVFR2; /*!< Offset: 0x248 (R/ ) Media and VFP Feature Register 2 */
+ uint32_t RESERVED5[1U];
+ __OM uint32_t ICIALLU; /*!< Offset: 0x250 ( /W) I-Cache Invalidate All to PoU */
+ uint32_t RESERVED6[1U];
+ __OM uint32_t ICIMVAU; /*!< Offset: 0x258 ( /W) I-Cache Invalidate by MVA to PoU */
+ __OM uint32_t DCIMVAC; /*!< Offset: 0x25C ( /W) D-Cache Invalidate by MVA to PoC */
+ __OM uint32_t DCISW; /*!< Offset: 0x260 ( /W) D-Cache Invalidate by Set-way */
+ __OM uint32_t DCCMVAU; /*!< Offset: 0x264 ( /W) D-Cache Clean by MVA to PoU */
+ __OM uint32_t DCCMVAC; /*!< Offset: 0x268 ( /W) D-Cache Clean by MVA to PoC */
+ __OM uint32_t DCCSW; /*!< Offset: 0x26C ( /W) D-Cache Clean by Set-way */
+ __OM uint32_t DCCIMVAC; /*!< Offset: 0x270 ( /W) D-Cache Clean and Invalidate by MVA to PoC */
+ __OM uint32_t DCCISW; /*!< Offset: 0x274 ( /W) D-Cache Clean and Invalidate by Set-way */
+ uint32_t RESERVED7[6U];
+ __IOM uint32_t ITCMCR; /*!< Offset: 0x290 (R/W) Instruction Tightly-Coupled Memory Control Register */
+ __IOM uint32_t DTCMCR; /*!< Offset: 0x294 (R/W) Data Tightly-Coupled Memory Control Registers */
+ __IOM uint32_t AHBPCR; /*!< Offset: 0x298 (R/W) AHBP Control Register */
+ __IOM uint32_t CACR; /*!< Offset: 0x29C (R/W) L1 Cache Control Register */
+ __IOM uint32_t AHBSCR; /*!< Offset: 0x2A0 (R/W) AHB Slave Control Register */
+ uint32_t RESERVED8[1U];
+ __IOM uint32_t ABFSR; /*!< Offset: 0x2A8 (R/W) Auxiliary Bus Fault Status Register */
+} SCB_Type;
+
+/* SCB CPUID Register Definitions */
+#define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */
+#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */
+
+#define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */
+#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */
+
+#define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */
+#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */
+
+#define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */
+#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */
+
+#define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */
+#define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */
+
+/* SCB Interrupt Control State Register Definitions */
+#define SCB_ICSR_PENDNMISET_Pos 31U /*!< SCB ICSR: PENDNMISET Position */
+#define SCB_ICSR_PENDNMISET_Msk (1UL << SCB_ICSR_PENDNMISET_Pos) /*!< SCB ICSR: PENDNMISET Mask */
+
+#define SCB_ICSR_NMIPENDSET_Pos SCB_ICSR_PENDNMISET_Pos /*!< SCB ICSR: NMIPENDSET Position, backward compatibility */
+#define SCB_ICSR_NMIPENDSET_Msk SCB_ICSR_PENDNMISET_Msk /*!< SCB ICSR: NMIPENDSET Mask, backward compatibility */
+
+#define SCB_ICSR_PENDNMICLR_Pos 30U /*!< SCB ICSR: PENDNMICLR Position */
+#define SCB_ICSR_PENDNMICLR_Msk (1UL << SCB_ICSR_PENDNMICLR_Pos) /*!< SCB ICSR: PENDNMICLR Mask */
+
+#define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */
+#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */
+
+#define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */
+#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */
+
+#define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */
+#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */
+
+#define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */
+#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */
+
+#define SCB_ICSR_STTNS_Pos 24U /*!< SCB ICSR: STTNS Position (Security Extension) */
+#define SCB_ICSR_STTNS_Msk (1UL << SCB_ICSR_STTNS_Pos) /*!< SCB ICSR: STTNS Mask (Security Extension) */
+
+#define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */
+#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */
+
+#define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */
+#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */
+
+#define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */
+#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */
+
+#define SCB_ICSR_RETTOBASE_Pos 11U /*!< SCB ICSR: RETTOBASE Position */
+#define SCB_ICSR_RETTOBASE_Msk (1UL << SCB_ICSR_RETTOBASE_Pos) /*!< SCB ICSR: RETTOBASE Mask */
+
+#define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */
+#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */
+
+/* SCB Vector Table Offset Register Definitions */
+#define SCB_VTOR_TBLOFF_Pos 7U /*!< SCB VTOR: TBLOFF Position */
+#define SCB_VTOR_TBLOFF_Msk (0x1FFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */
+
+/* SCB Application Interrupt and Reset Control Register Definitions */
+#define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */
+#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */
+
+#define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */
+#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */
+
+#define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */
+#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */
+
+#define SCB_AIRCR_PRIS_Pos 14U /*!< SCB AIRCR: PRIS Position */
+#define SCB_AIRCR_PRIS_Msk (1UL << SCB_AIRCR_PRIS_Pos) /*!< SCB AIRCR: PRIS Mask */
+
+#define SCB_AIRCR_BFHFNMINS_Pos 13U /*!< SCB AIRCR: BFHFNMINS Position */
+#define SCB_AIRCR_BFHFNMINS_Msk (1UL << SCB_AIRCR_BFHFNMINS_Pos) /*!< SCB AIRCR: BFHFNMINS Mask */
+
+#define SCB_AIRCR_PRIGROUP_Pos 8U /*!< SCB AIRCR: PRIGROUP Position */
+#define SCB_AIRCR_PRIGROUP_Msk (7UL << SCB_AIRCR_PRIGROUP_Pos) /*!< SCB AIRCR: PRIGROUP Mask */
+
+#define SCB_AIRCR_SYSRESETREQS_Pos 3U /*!< SCB AIRCR: SYSRESETREQS Position */
+#define SCB_AIRCR_SYSRESETREQS_Msk (1UL << SCB_AIRCR_SYSRESETREQS_Pos) /*!< SCB AIRCR: SYSRESETREQS Mask */
+
+#define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */
+#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */
+
+#define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */
+#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */
+
+/* SCB System Control Register Definitions */
+#define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */
+#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */
+
+#define SCB_SCR_SLEEPDEEPS_Pos 3U /*!< SCB SCR: SLEEPDEEPS Position */
+#define SCB_SCR_SLEEPDEEPS_Msk (1UL << SCB_SCR_SLEEPDEEPS_Pos) /*!< SCB SCR: SLEEPDEEPS Mask */
+
+#define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */
+#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */
+
+#define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */
+#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */
+
+/* SCB Configuration Control Register Definitions */
+#define SCB_CCR_BP_Pos 18U /*!< SCB CCR: BP Position */
+#define SCB_CCR_BP_Msk (1UL << SCB_CCR_BP_Pos) /*!< SCB CCR: BP Mask */
+
+#define SCB_CCR_IC_Pos 17U /*!< SCB CCR: IC Position */
+#define SCB_CCR_IC_Msk (1UL << SCB_CCR_IC_Pos) /*!< SCB CCR: IC Mask */
+
+#define SCB_CCR_DC_Pos 16U /*!< SCB CCR: DC Position */
+#define SCB_CCR_DC_Msk (1UL << SCB_CCR_DC_Pos) /*!< SCB CCR: DC Mask */
+
+#define SCB_CCR_STKOFHFNMIGN_Pos 10U /*!< SCB CCR: STKOFHFNMIGN Position */
+#define SCB_CCR_STKOFHFNMIGN_Msk (1UL << SCB_CCR_STKOFHFNMIGN_Pos) /*!< SCB CCR: STKOFHFNMIGN Mask */
+
+#define SCB_CCR_BFHFNMIGN_Pos 8U /*!< SCB CCR: BFHFNMIGN Position */
+#define SCB_CCR_BFHFNMIGN_Msk (1UL << SCB_CCR_BFHFNMIGN_Pos) /*!< SCB CCR: BFHFNMIGN Mask */
+
+#define SCB_CCR_DIV_0_TRP_Pos 4U /*!< SCB CCR: DIV_0_TRP Position */
+#define SCB_CCR_DIV_0_TRP_Msk (1UL << SCB_CCR_DIV_0_TRP_Pos) /*!< SCB CCR: DIV_0_TRP Mask */
+
+#define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */
+#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */
+
+#define SCB_CCR_USERSETMPEND_Pos 1U /*!< SCB CCR: USERSETMPEND Position */
+#define SCB_CCR_USERSETMPEND_Msk (1UL << SCB_CCR_USERSETMPEND_Pos) /*!< SCB CCR: USERSETMPEND Mask */
+
+/* SCB System Handler Control and State Register Definitions */
+#define SCB_SHCSR_HARDFAULTPENDED_Pos 21U /*!< SCB SHCSR: HARDFAULTPENDED Position */
+#define SCB_SHCSR_HARDFAULTPENDED_Msk (1UL << SCB_SHCSR_HARDFAULTPENDED_Pos) /*!< SCB SHCSR: HARDFAULTPENDED Mask */
+
+#define SCB_SHCSR_SECUREFAULTPENDED_Pos 20U /*!< SCB SHCSR: SECUREFAULTPENDED Position */
+#define SCB_SHCSR_SECUREFAULTPENDED_Msk (1UL << SCB_SHCSR_SECUREFAULTPENDED_Pos) /*!< SCB SHCSR: SECUREFAULTPENDED Mask */
+
+#define SCB_SHCSR_SECUREFAULTENA_Pos 19U /*!< SCB SHCSR: SECUREFAULTENA Position */
+#define SCB_SHCSR_SECUREFAULTENA_Msk (1UL << SCB_SHCSR_SECUREFAULTENA_Pos) /*!< SCB SHCSR: SECUREFAULTENA Mask */
+
+#define SCB_SHCSR_USGFAULTENA_Pos 18U /*!< SCB SHCSR: USGFAULTENA Position */
+#define SCB_SHCSR_USGFAULTENA_Msk (1UL << SCB_SHCSR_USGFAULTENA_Pos) /*!< SCB SHCSR: USGFAULTENA Mask */
+
+#define SCB_SHCSR_BUSFAULTENA_Pos 17U /*!< SCB SHCSR: BUSFAULTENA Position */
+#define SCB_SHCSR_BUSFAULTENA_Msk (1UL << SCB_SHCSR_BUSFAULTENA_Pos) /*!< SCB SHCSR: BUSFAULTENA Mask */
+
+#define SCB_SHCSR_MEMFAULTENA_Pos 16U /*!< SCB SHCSR: MEMFAULTENA Position */
+#define SCB_SHCSR_MEMFAULTENA_Msk (1UL << SCB_SHCSR_MEMFAULTENA_Pos) /*!< SCB SHCSR: MEMFAULTENA Mask */
+
+#define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */
+#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */
+
+#define SCB_SHCSR_BUSFAULTPENDED_Pos 14U /*!< SCB SHCSR: BUSFAULTPENDED Position */
+#define SCB_SHCSR_BUSFAULTPENDED_Msk (1UL << SCB_SHCSR_BUSFAULTPENDED_Pos) /*!< SCB SHCSR: BUSFAULTPENDED Mask */
+
+#define SCB_SHCSR_MEMFAULTPENDED_Pos 13U /*!< SCB SHCSR: MEMFAULTPENDED Position */
+#define SCB_SHCSR_MEMFAULTPENDED_Msk (1UL << SCB_SHCSR_MEMFAULTPENDED_Pos) /*!< SCB SHCSR: MEMFAULTPENDED Mask */
+
+#define SCB_SHCSR_USGFAULTPENDED_Pos 12U /*!< SCB SHCSR: USGFAULTPENDED Position */
+#define SCB_SHCSR_USGFAULTPENDED_Msk (1UL << SCB_SHCSR_USGFAULTPENDED_Pos) /*!< SCB SHCSR: USGFAULTPENDED Mask */
+
+#define SCB_SHCSR_SYSTICKACT_Pos 11U /*!< SCB SHCSR: SYSTICKACT Position */
+#define SCB_SHCSR_SYSTICKACT_Msk (1UL << SCB_SHCSR_SYSTICKACT_Pos) /*!< SCB SHCSR: SYSTICKACT Mask */
+
+#define SCB_SHCSR_PENDSVACT_Pos 10U /*!< SCB SHCSR: PENDSVACT Position */
+#define SCB_SHCSR_PENDSVACT_Msk (1UL << SCB_SHCSR_PENDSVACT_Pos) /*!< SCB SHCSR: PENDSVACT Mask */
+
+#define SCB_SHCSR_MONITORACT_Pos 8U /*!< SCB SHCSR: MONITORACT Position */
+#define SCB_SHCSR_MONITORACT_Msk (1UL << SCB_SHCSR_MONITORACT_Pos) /*!< SCB SHCSR: MONITORACT Mask */
+
+#define SCB_SHCSR_SVCALLACT_Pos 7U /*!< SCB SHCSR: SVCALLACT Position */
+#define SCB_SHCSR_SVCALLACT_Msk (1UL << SCB_SHCSR_SVCALLACT_Pos) /*!< SCB SHCSR: SVCALLACT Mask */
+
+#define SCB_SHCSR_NMIACT_Pos 5U /*!< SCB SHCSR: NMIACT Position */
+#define SCB_SHCSR_NMIACT_Msk (1UL << SCB_SHCSR_NMIACT_Pos) /*!< SCB SHCSR: NMIACT Mask */
+
+#define SCB_SHCSR_SECUREFAULTACT_Pos 4U /*!< SCB SHCSR: SECUREFAULTACT Position */
+#define SCB_SHCSR_SECUREFAULTACT_Msk (1UL << SCB_SHCSR_SECUREFAULTACT_Pos) /*!< SCB SHCSR: SECUREFAULTACT Mask */
+
+#define SCB_SHCSR_USGFAULTACT_Pos 3U /*!< SCB SHCSR: USGFAULTACT Position */
+#define SCB_SHCSR_USGFAULTACT_Msk (1UL << SCB_SHCSR_USGFAULTACT_Pos) /*!< SCB SHCSR: USGFAULTACT Mask */
+
+#define SCB_SHCSR_HARDFAULTACT_Pos 2U /*!< SCB SHCSR: HARDFAULTACT Position */
+#define SCB_SHCSR_HARDFAULTACT_Msk (1UL << SCB_SHCSR_HARDFAULTACT_Pos) /*!< SCB SHCSR: HARDFAULTACT Mask */
+
+#define SCB_SHCSR_BUSFAULTACT_Pos 1U /*!< SCB SHCSR: BUSFAULTACT Position */
+#define SCB_SHCSR_BUSFAULTACT_Msk (1UL << SCB_SHCSR_BUSFAULTACT_Pos) /*!< SCB SHCSR: BUSFAULTACT Mask */
+
+#define SCB_SHCSR_MEMFAULTACT_Pos 0U /*!< SCB SHCSR: MEMFAULTACT Position */
+#define SCB_SHCSR_MEMFAULTACT_Msk (1UL /*<< SCB_SHCSR_MEMFAULTACT_Pos*/) /*!< SCB SHCSR: MEMFAULTACT Mask */
+
+/* SCB Configurable Fault Status Register Definitions */
+#define SCB_CFSR_USGFAULTSR_Pos 16U /*!< SCB CFSR: Usage Fault Status Register Position */
+#define SCB_CFSR_USGFAULTSR_Msk (0xFFFFUL << SCB_CFSR_USGFAULTSR_Pos) /*!< SCB CFSR: Usage Fault Status Register Mask */
+
+#define SCB_CFSR_BUSFAULTSR_Pos 8U /*!< SCB CFSR: Bus Fault Status Register Position */
+#define SCB_CFSR_BUSFAULTSR_Msk (0xFFUL << SCB_CFSR_BUSFAULTSR_Pos) /*!< SCB CFSR: Bus Fault Status Register Mask */
+
+#define SCB_CFSR_MEMFAULTSR_Pos 0U /*!< SCB CFSR: Memory Manage Fault Status Register Position */
+#define SCB_CFSR_MEMFAULTSR_Msk (0xFFUL /*<< SCB_CFSR_MEMFAULTSR_Pos*/) /*!< SCB CFSR: Memory Manage Fault Status Register Mask */
+
+/* MemManage Fault Status Register (part of SCB Configurable Fault Status Register) */
+#define SCB_CFSR_MMARVALID_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 7U) /*!< SCB CFSR (MMFSR): MMARVALID Position */
+#define SCB_CFSR_MMARVALID_Msk (1UL << SCB_CFSR_MMARVALID_Pos) /*!< SCB CFSR (MMFSR): MMARVALID Mask */
+
+#define SCB_CFSR_MLSPERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 5U) /*!< SCB CFSR (MMFSR): MLSPERR Position */
+#define SCB_CFSR_MLSPERR_Msk (1UL << SCB_CFSR_MLSPERR_Pos) /*!< SCB CFSR (MMFSR): MLSPERR Mask */
+
+#define SCB_CFSR_MSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 4U) /*!< SCB CFSR (MMFSR): MSTKERR Position */
+#define SCB_CFSR_MSTKERR_Msk (1UL << SCB_CFSR_MSTKERR_Pos) /*!< SCB CFSR (MMFSR): MSTKERR Mask */
+
+#define SCB_CFSR_MUNSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 3U) /*!< SCB CFSR (MMFSR): MUNSTKERR Position */
+#define SCB_CFSR_MUNSTKERR_Msk (1UL << SCB_CFSR_MUNSTKERR_Pos) /*!< SCB CFSR (MMFSR): MUNSTKERR Mask */
+
+#define SCB_CFSR_DACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 1U) /*!< SCB CFSR (MMFSR): DACCVIOL Position */
+#define SCB_CFSR_DACCVIOL_Msk (1UL << SCB_CFSR_DACCVIOL_Pos) /*!< SCB CFSR (MMFSR): DACCVIOL Mask */
+
+#define SCB_CFSR_IACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 0U) /*!< SCB CFSR (MMFSR): IACCVIOL Position */
+#define SCB_CFSR_IACCVIOL_Msk (1UL /*<< SCB_CFSR_IACCVIOL_Pos*/) /*!< SCB CFSR (MMFSR): IACCVIOL Mask */
+
+/* BusFault Status Register (part of SCB Configurable Fault Status Register) */
+#define SCB_CFSR_BFARVALID_Pos (SCB_CFSR_BUSFAULTSR_Pos + 7U) /*!< SCB CFSR (BFSR): BFARVALID Position */
+#define SCB_CFSR_BFARVALID_Msk (1UL << SCB_CFSR_BFARVALID_Pos) /*!< SCB CFSR (BFSR): BFARVALID Mask */
+
+#define SCB_CFSR_LSPERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 5U) /*!< SCB CFSR (BFSR): LSPERR Position */
+#define SCB_CFSR_LSPERR_Msk (1UL << SCB_CFSR_LSPERR_Pos) /*!< SCB CFSR (BFSR): LSPERR Mask */
+
+#define SCB_CFSR_STKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 4U) /*!< SCB CFSR (BFSR): STKERR Position */
+#define SCB_CFSR_STKERR_Msk (1UL << SCB_CFSR_STKERR_Pos) /*!< SCB CFSR (BFSR): STKERR Mask */
+
+#define SCB_CFSR_UNSTKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 3U) /*!< SCB CFSR (BFSR): UNSTKERR Position */
+#define SCB_CFSR_UNSTKERR_Msk (1UL << SCB_CFSR_UNSTKERR_Pos) /*!< SCB CFSR (BFSR): UNSTKERR Mask */
+
+#define SCB_CFSR_IMPRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 2U) /*!< SCB CFSR (BFSR): IMPRECISERR Position */
+#define SCB_CFSR_IMPRECISERR_Msk (1UL << SCB_CFSR_IMPRECISERR_Pos) /*!< SCB CFSR (BFSR): IMPRECISERR Mask */
+
+#define SCB_CFSR_PRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 1U) /*!< SCB CFSR (BFSR): PRECISERR Position */
+#define SCB_CFSR_PRECISERR_Msk (1UL << SCB_CFSR_PRECISERR_Pos) /*!< SCB CFSR (BFSR): PRECISERR Mask */
+
+#define SCB_CFSR_IBUSERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 0U) /*!< SCB CFSR (BFSR): IBUSERR Position */
+#define SCB_CFSR_IBUSERR_Msk (1UL << SCB_CFSR_IBUSERR_Pos) /*!< SCB CFSR (BFSR): IBUSERR Mask */
+
+/* UsageFault Status Register (part of SCB Configurable Fault Status Register) */
+#define SCB_CFSR_DIVBYZERO_Pos (SCB_CFSR_USGFAULTSR_Pos + 9U) /*!< SCB CFSR (UFSR): DIVBYZERO Position */
+#define SCB_CFSR_DIVBYZERO_Msk (1UL << SCB_CFSR_DIVBYZERO_Pos) /*!< SCB CFSR (UFSR): DIVBYZERO Mask */
+
+#define SCB_CFSR_UNALIGNED_Pos (SCB_CFSR_USGFAULTSR_Pos + 8U) /*!< SCB CFSR (UFSR): UNALIGNED Position */
+#define SCB_CFSR_UNALIGNED_Msk (1UL << SCB_CFSR_UNALIGNED_Pos) /*!< SCB CFSR (UFSR): UNALIGNED Mask */
+
+#define SCB_CFSR_STKOF_Pos (SCB_CFSR_USGFAULTSR_Pos + 4U) /*!< SCB CFSR (UFSR): STKOF Position */
+#define SCB_CFSR_STKOF_Msk (1UL << SCB_CFSR_STKOF_Pos) /*!< SCB CFSR (UFSR): STKOF Mask */
+
+#define SCB_CFSR_NOCP_Pos (SCB_CFSR_USGFAULTSR_Pos + 3U) /*!< SCB CFSR (UFSR): NOCP Position */
+#define SCB_CFSR_NOCP_Msk (1UL << SCB_CFSR_NOCP_Pos) /*!< SCB CFSR (UFSR): NOCP Mask */
+
+#define SCB_CFSR_INVPC_Pos (SCB_CFSR_USGFAULTSR_Pos + 2U) /*!< SCB CFSR (UFSR): INVPC Position */
+#define SCB_CFSR_INVPC_Msk (1UL << SCB_CFSR_INVPC_Pos) /*!< SCB CFSR (UFSR): INVPC Mask */
+
+#define SCB_CFSR_INVSTATE_Pos (SCB_CFSR_USGFAULTSR_Pos + 1U) /*!< SCB CFSR (UFSR): INVSTATE Position */
+#define SCB_CFSR_INVSTATE_Msk (1UL << SCB_CFSR_INVSTATE_Pos) /*!< SCB CFSR (UFSR): INVSTATE Mask */
+
+#define SCB_CFSR_UNDEFINSTR_Pos (SCB_CFSR_USGFAULTSR_Pos + 0U) /*!< SCB CFSR (UFSR): UNDEFINSTR Position */
+#define SCB_CFSR_UNDEFINSTR_Msk (1UL << SCB_CFSR_UNDEFINSTR_Pos) /*!< SCB CFSR (UFSR): UNDEFINSTR Mask */
+
+/* SCB Hard Fault Status Register Definitions */
+#define SCB_HFSR_DEBUGEVT_Pos 31U /*!< SCB HFSR: DEBUGEVT Position */
+#define SCB_HFSR_DEBUGEVT_Msk (1UL << SCB_HFSR_DEBUGEVT_Pos) /*!< SCB HFSR: DEBUGEVT Mask */
+
+#define SCB_HFSR_FORCED_Pos 30U /*!< SCB HFSR: FORCED Position */
+#define SCB_HFSR_FORCED_Msk (1UL << SCB_HFSR_FORCED_Pos) /*!< SCB HFSR: FORCED Mask */
+
+#define SCB_HFSR_VECTTBL_Pos 1U /*!< SCB HFSR: VECTTBL Position */
+#define SCB_HFSR_VECTTBL_Msk (1UL << SCB_HFSR_VECTTBL_Pos) /*!< SCB HFSR: VECTTBL Mask */
+
+/* SCB Debug Fault Status Register Definitions */
+#define SCB_DFSR_EXTERNAL_Pos 4U /*!< SCB DFSR: EXTERNAL Position */
+#define SCB_DFSR_EXTERNAL_Msk (1UL << SCB_DFSR_EXTERNAL_Pos) /*!< SCB DFSR: EXTERNAL Mask */
+
+#define SCB_DFSR_VCATCH_Pos 3U /*!< SCB DFSR: VCATCH Position */
+#define SCB_DFSR_VCATCH_Msk (1UL << SCB_DFSR_VCATCH_Pos) /*!< SCB DFSR: VCATCH Mask */
+
+#define SCB_DFSR_DWTTRAP_Pos 2U /*!< SCB DFSR: DWTTRAP Position */
+#define SCB_DFSR_DWTTRAP_Msk (1UL << SCB_DFSR_DWTTRAP_Pos) /*!< SCB DFSR: DWTTRAP Mask */
+
+#define SCB_DFSR_BKPT_Pos 1U /*!< SCB DFSR: BKPT Position */
+#define SCB_DFSR_BKPT_Msk (1UL << SCB_DFSR_BKPT_Pos) /*!< SCB DFSR: BKPT Mask */
+
+#define SCB_DFSR_HALTED_Pos 0U /*!< SCB DFSR: HALTED Position */
+#define SCB_DFSR_HALTED_Msk (1UL /*<< SCB_DFSR_HALTED_Pos*/) /*!< SCB DFSR: HALTED Mask */
+
+/* SCB Non-Secure Access Control Register Definitions */
+#define SCB_NSACR_CP11_Pos 11U /*!< SCB NSACR: CP11 Position */
+#define SCB_NSACR_CP11_Msk (1UL << SCB_NSACR_CP11_Pos) /*!< SCB NSACR: CP11 Mask */
+
+#define SCB_NSACR_CP10_Pos 10U /*!< SCB NSACR: CP10 Position */
+#define SCB_NSACR_CP10_Msk (1UL << SCB_NSACR_CP10_Pos) /*!< SCB NSACR: CP10 Mask */
+
+#define SCB_NSACR_CPn_Pos 0U /*!< SCB NSACR: CPn Position */
+#define SCB_NSACR_CPn_Msk (1UL /*<< SCB_NSACR_CPn_Pos*/) /*!< SCB NSACR: CPn Mask */
+
+/* SCB Cache Level ID Register Definitions */
+#define SCB_CLIDR_LOUU_Pos 27U /*!< SCB CLIDR: LoUU Position */
+#define SCB_CLIDR_LOUU_Msk (7UL << SCB_CLIDR_LOUU_Pos) /*!< SCB CLIDR: LoUU Mask */
+
+#define SCB_CLIDR_LOC_Pos 24U /*!< SCB CLIDR: LoC Position */
+#define SCB_CLIDR_LOC_Msk (7UL << SCB_CLIDR_LOC_Pos) /*!< SCB CLIDR: LoC Mask */
+
+/* SCB Cache Type Register Definitions */
+#define SCB_CTR_FORMAT_Pos 29U /*!< SCB CTR: Format Position */
+#define SCB_CTR_FORMAT_Msk (7UL << SCB_CTR_FORMAT_Pos) /*!< SCB CTR: Format Mask */
+
+#define SCB_CTR_CWG_Pos 24U /*!< SCB CTR: CWG Position */
+#define SCB_CTR_CWG_Msk (0xFUL << SCB_CTR_CWG_Pos) /*!< SCB CTR: CWG Mask */
+
+#define SCB_CTR_ERG_Pos 20U /*!< SCB CTR: ERG Position */
+#define SCB_CTR_ERG_Msk (0xFUL << SCB_CTR_ERG_Pos) /*!< SCB CTR: ERG Mask */
+
+#define SCB_CTR_DMINLINE_Pos 16U /*!< SCB CTR: DminLine Position */
+#define SCB_CTR_DMINLINE_Msk (0xFUL << SCB_CTR_DMINLINE_Pos) /*!< SCB CTR: DminLine Mask */
+
+#define SCB_CTR_IMINLINE_Pos 0U /*!< SCB CTR: ImInLine Position */
+#define SCB_CTR_IMINLINE_Msk (0xFUL /*<< SCB_CTR_IMINLINE_Pos*/) /*!< SCB CTR: ImInLine Mask */
+
+/* SCB Cache Size ID Register Definitions */
+#define SCB_CCSIDR_WT_Pos 31U /*!< SCB CCSIDR: WT Position */
+#define SCB_CCSIDR_WT_Msk (1UL << SCB_CCSIDR_WT_Pos) /*!< SCB CCSIDR: WT Mask */
+
+#define SCB_CCSIDR_WB_Pos 30U /*!< SCB CCSIDR: WB Position */
+#define SCB_CCSIDR_WB_Msk (1UL << SCB_CCSIDR_WB_Pos) /*!< SCB CCSIDR: WB Mask */
+
+#define SCB_CCSIDR_RA_Pos 29U /*!< SCB CCSIDR: RA Position */
+#define SCB_CCSIDR_RA_Msk (1UL << SCB_CCSIDR_RA_Pos) /*!< SCB CCSIDR: RA Mask */
+
+#define SCB_CCSIDR_WA_Pos 28U /*!< SCB CCSIDR: WA Position */
+#define SCB_CCSIDR_WA_Msk (1UL << SCB_CCSIDR_WA_Pos) /*!< SCB CCSIDR: WA Mask */
+
+#define SCB_CCSIDR_NUMSETS_Pos 13U /*!< SCB CCSIDR: NumSets Position */
+#define SCB_CCSIDR_NUMSETS_Msk (0x7FFFUL << SCB_CCSIDR_NUMSETS_Pos) /*!< SCB CCSIDR: NumSets Mask */
+
+#define SCB_CCSIDR_ASSOCIATIVITY_Pos 3U /*!< SCB CCSIDR: Associativity Position */
+#define SCB_CCSIDR_ASSOCIATIVITY_Msk (0x3FFUL << SCB_CCSIDR_ASSOCIATIVITY_Pos) /*!< SCB CCSIDR: Associativity Mask */
+
+#define SCB_CCSIDR_LINESIZE_Pos 0U /*!< SCB CCSIDR: LineSize Position */
+#define SCB_CCSIDR_LINESIZE_Msk (7UL /*<< SCB_CCSIDR_LINESIZE_Pos*/) /*!< SCB CCSIDR: LineSize Mask */
+
+/* SCB Cache Size Selection Register Definitions */
+#define SCB_CSSELR_LEVEL_Pos 1U /*!< SCB CSSELR: Level Position */
+#define SCB_CSSELR_LEVEL_Msk (7UL << SCB_CSSELR_LEVEL_Pos) /*!< SCB CSSELR: Level Mask */
+
+#define SCB_CSSELR_IND_Pos 0U /*!< SCB CSSELR: InD Position */
+#define SCB_CSSELR_IND_Msk (1UL /*<< SCB_CSSELR_IND_Pos*/) /*!< SCB CSSELR: InD Mask */
+
+/* SCB Software Triggered Interrupt Register Definitions */
+#define SCB_STIR_INTID_Pos 0U /*!< SCB STIR: INTID Position */
+#define SCB_STIR_INTID_Msk (0x1FFUL /*<< SCB_STIR_INTID_Pos*/) /*!< SCB STIR: INTID Mask */
+
+/* SCB D-Cache Invalidate by Set-way Register Definitions */
+#define SCB_DCISW_WAY_Pos 30U /*!< SCB DCISW: Way Position */
+#define SCB_DCISW_WAY_Msk (3UL << SCB_DCISW_WAY_Pos) /*!< SCB DCISW: Way Mask */
+
+#define SCB_DCISW_SET_Pos 5U /*!< SCB DCISW: Set Position */
+#define SCB_DCISW_SET_Msk (0x1FFUL << SCB_DCISW_SET_Pos) /*!< SCB DCISW: Set Mask */
+
+/* SCB D-Cache Clean by Set-way Register Definitions */
+#define SCB_DCCSW_WAY_Pos 30U /*!< SCB DCCSW: Way Position */
+#define SCB_DCCSW_WAY_Msk (3UL << SCB_DCCSW_WAY_Pos) /*!< SCB DCCSW: Way Mask */
+
+#define SCB_DCCSW_SET_Pos 5U /*!< SCB DCCSW: Set Position */
+#define SCB_DCCSW_SET_Msk (0x1FFUL << SCB_DCCSW_SET_Pos) /*!< SCB DCCSW: Set Mask */
+
+/* SCB D-Cache Clean and Invalidate by Set-way Register Definitions */
+#define SCB_DCCISW_WAY_Pos 30U /*!< SCB DCCISW: Way Position */
+#define SCB_DCCISW_WAY_Msk (3UL << SCB_DCCISW_WAY_Pos) /*!< SCB DCCISW: Way Mask */
+
+#define SCB_DCCISW_SET_Pos 5U /*!< SCB DCCISW: Set Position */
+#define SCB_DCCISW_SET_Msk (0x1FFUL << SCB_DCCISW_SET_Pos) /*!< SCB DCCISW: Set Mask */
+
+/* Instruction Tightly-Coupled Memory Control Register Definitions */
+#define SCB_ITCMCR_SZ_Pos 3U /*!< SCB ITCMCR: SZ Position */
+#define SCB_ITCMCR_SZ_Msk (0xFUL << SCB_ITCMCR_SZ_Pos) /*!< SCB ITCMCR: SZ Mask */
+
+#define SCB_ITCMCR_RETEN_Pos 2U /*!< SCB ITCMCR: RETEN Position */
+#define SCB_ITCMCR_RETEN_Msk (1UL << SCB_ITCMCR_RETEN_Pos) /*!< SCB ITCMCR: RETEN Mask */
+
+#define SCB_ITCMCR_RMW_Pos 1U /*!< SCB ITCMCR: RMW Position */
+#define SCB_ITCMCR_RMW_Msk (1UL << SCB_ITCMCR_RMW_Pos) /*!< SCB ITCMCR: RMW Mask */
+
+#define SCB_ITCMCR_EN_Pos 0U /*!< SCB ITCMCR: EN Position */
+#define SCB_ITCMCR_EN_Msk (1UL /*<< SCB_ITCMCR_EN_Pos*/) /*!< SCB ITCMCR: EN Mask */
+
+/* Data Tightly-Coupled Memory Control Register Definitions */
+#define SCB_DTCMCR_SZ_Pos 3U /*!< SCB DTCMCR: SZ Position */
+#define SCB_DTCMCR_SZ_Msk (0xFUL << SCB_DTCMCR_SZ_Pos) /*!< SCB DTCMCR: SZ Mask */
+
+#define SCB_DTCMCR_RETEN_Pos 2U /*!< SCB DTCMCR: RETEN Position */
+#define SCB_DTCMCR_RETEN_Msk (1UL << SCB_DTCMCR_RETEN_Pos) /*!< SCB DTCMCR: RETEN Mask */
+
+#define SCB_DTCMCR_RMW_Pos 1U /*!< SCB DTCMCR: RMW Position */
+#define SCB_DTCMCR_RMW_Msk (1UL << SCB_DTCMCR_RMW_Pos) /*!< SCB DTCMCR: RMW Mask */
+
+#define SCB_DTCMCR_EN_Pos 0U /*!< SCB DTCMCR: EN Position */
+#define SCB_DTCMCR_EN_Msk (1UL /*<< SCB_DTCMCR_EN_Pos*/) /*!< SCB DTCMCR: EN Mask */
+
+/* AHBP Control Register Definitions */
+#define SCB_AHBPCR_SZ_Pos 1U /*!< SCB AHBPCR: SZ Position */
+#define SCB_AHBPCR_SZ_Msk (7UL << SCB_AHBPCR_SZ_Pos) /*!< SCB AHBPCR: SZ Mask */
+
+#define SCB_AHBPCR_EN_Pos 0U /*!< SCB AHBPCR: EN Position */
+#define SCB_AHBPCR_EN_Msk (1UL /*<< SCB_AHBPCR_EN_Pos*/) /*!< SCB AHBPCR: EN Mask */
+
+/* L1 Cache Control Register Definitions */
+#define SCB_CACR_FORCEWT_Pos 2U /*!< SCB CACR: FORCEWT Position */
+#define SCB_CACR_FORCEWT_Msk (1UL << SCB_CACR_FORCEWT_Pos) /*!< SCB CACR: FORCEWT Mask */
+
+#define SCB_CACR_ECCEN_Pos 1U /*!< SCB CACR: ECCEN Position */
+#define SCB_CACR_ECCEN_Msk (1UL << SCB_CACR_ECCEN_Pos) /*!< SCB CACR: ECCEN Mask */
+
+#define SCB_CACR_SIWT_Pos 0U /*!< SCB CACR: SIWT Position */
+#define SCB_CACR_SIWT_Msk (1UL /*<< SCB_CACR_SIWT_Pos*/) /*!< SCB CACR: SIWT Mask */
+
+/* AHBS Control Register Definitions */
+#define SCB_AHBSCR_INITCOUNT_Pos 11U /*!< SCB AHBSCR: INITCOUNT Position */
+#define SCB_AHBSCR_INITCOUNT_Msk (0x1FUL << SCB_AHBPCR_INITCOUNT_Pos) /*!< SCB AHBSCR: INITCOUNT Mask */
+
+#define SCB_AHBSCR_TPRI_Pos 2U /*!< SCB AHBSCR: TPRI Position */
+#define SCB_AHBSCR_TPRI_Msk (0x1FFUL << SCB_AHBPCR_TPRI_Pos) /*!< SCB AHBSCR: TPRI Mask */
+
+#define SCB_AHBSCR_CTL_Pos 0U /*!< SCB AHBSCR: CTL Position*/
+#define SCB_AHBSCR_CTL_Msk (3UL /*<< SCB_AHBPCR_CTL_Pos*/) /*!< SCB AHBSCR: CTL Mask */
+
+/* Auxiliary Bus Fault Status Register Definitions */
+#define SCB_ABFSR_AXIMTYPE_Pos 8U /*!< SCB ABFSR: AXIMTYPE Position*/
+#define SCB_ABFSR_AXIMTYPE_Msk (3UL << SCB_ABFSR_AXIMTYPE_Pos) /*!< SCB ABFSR: AXIMTYPE Mask */
+
+#define SCB_ABFSR_EPPB_Pos 4U /*!< SCB ABFSR: EPPB Position*/
+#define SCB_ABFSR_EPPB_Msk (1UL << SCB_ABFSR_EPPB_Pos) /*!< SCB ABFSR: EPPB Mask */
+
+#define SCB_ABFSR_AXIM_Pos 3U /*!< SCB ABFSR: AXIM Position*/
+#define SCB_ABFSR_AXIM_Msk (1UL << SCB_ABFSR_AXIM_Pos) /*!< SCB ABFSR: AXIM Mask */
+
+#define SCB_ABFSR_AHBP_Pos 2U /*!< SCB ABFSR: AHBP Position*/
+#define SCB_ABFSR_AHBP_Msk (1UL << SCB_ABFSR_AHBP_Pos) /*!< SCB ABFSR: AHBP Mask */
+
+#define SCB_ABFSR_DTCM_Pos 1U /*!< SCB ABFSR: DTCM Position*/
+#define SCB_ABFSR_DTCM_Msk (1UL << SCB_ABFSR_DTCM_Pos) /*!< SCB ABFSR: DTCM Mask */
+
+#define SCB_ABFSR_ITCM_Pos 0U /*!< SCB ABFSR: ITCM Position*/
+#define SCB_ABFSR_ITCM_Msk (1UL /*<< SCB_ABFSR_ITCM_Pos*/) /*!< SCB ABFSR: ITCM Mask */
+
+/*@} end of group CMSIS_SCB */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_SCnSCB System Controls not in SCB (SCnSCB)
+ \brief Type definitions for the System Control and ID Register not in the SCB
+ @{
+ */
+
+/**
+ \brief Structure type to access the System Control and ID Register not in the SCB.
+ */
+typedef struct
+{
+ uint32_t RESERVED0[1U];
+ __IM uint32_t ICTR; /*!< Offset: 0x004 (R/ ) Interrupt Controller Type Register */
+ __IOM uint32_t ACTLR; /*!< Offset: 0x008 (R/W) Auxiliary Control Register */
+ __IOM uint32_t CPPWR; /*!< Offset: 0x00C (R/W) Coprocessor Power Control Register */
+} SCnSCB_Type;
+
+/* Interrupt Controller Type Register Definitions */
+#define SCnSCB_ICTR_INTLINESNUM_Pos 0U /*!< ICTR: INTLINESNUM Position */
+#define SCnSCB_ICTR_INTLINESNUM_Msk (0xFUL /*<< SCnSCB_ICTR_INTLINESNUM_Pos*/) /*!< ICTR: INTLINESNUM Mask */
+
+/*@} end of group CMSIS_SCnotSCB */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_SysTick System Tick Timer (SysTick)
+ \brief Type definitions for the System Timer Registers.
+ @{
+ */
+
+/**
+ \brief Structure type to access the System Timer (SysTick).
+ */
+typedef struct
+{
+ __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */
+ __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */
+ __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */
+ __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */
+} SysTick_Type;
+
+/* SysTick Control / Status Register Definitions */
+#define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */
+#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */
+
+#define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */
+#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */
+
+#define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */
+#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */
+
+#define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */
+#define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */
+
+/* SysTick Reload Register Definitions */
+#define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */
+#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */
+
+/* SysTick Current Register Definitions */
+#define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */
+#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */
+
+/* SysTick Calibration Register Definitions */
+#define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */
+#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */
+
+#define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */
+#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */
+
+#define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */
+#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */
+
+/*@} end of group CMSIS_SysTick */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_ITM Instrumentation Trace Macrocell (ITM)
+ \brief Type definitions for the Instrumentation Trace Macrocell (ITM)
+ @{
+ */
+
+/**
+ \brief Structure type to access the Instrumentation Trace Macrocell Register (ITM).
+ */
+typedef struct
+{
+ __OM union
+ {
+ __OM uint8_t u8; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 8-bit */
+ __OM uint16_t u16; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 16-bit */
+ __OM uint32_t u32; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 32-bit */
+ } PORT [32U]; /*!< Offset: 0x000 ( /W) ITM Stimulus Port Registers */
+ uint32_t RESERVED0[864U];
+ __IOM uint32_t TER; /*!< Offset: 0xE00 (R/W) ITM Trace Enable Register */
+ uint32_t RESERVED1[15U];
+ __IOM uint32_t TPR; /*!< Offset: 0xE40 (R/W) ITM Trace Privilege Register */
+ uint32_t RESERVED2[15U];
+ __IOM uint32_t TCR; /*!< Offset: 0xE80 (R/W) ITM Trace Control Register */
+ uint32_t RESERVED3[29U];
+ __OM uint32_t IWR; /*!< Offset: 0xEF8 ( /W) ITM Integration Write Register */
+ __IM uint32_t IRR; /*!< Offset: 0xEFC (R/ ) ITM Integration Read Register */
+ __IOM uint32_t IMCR; /*!< Offset: 0xF00 (R/W) ITM Integration Mode Control Register */
+ uint32_t RESERVED4[43U];
+ __OM uint32_t LAR; /*!< Offset: 0xFB0 ( /W) ITM Lock Access Register */
+ __IM uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) ITM Lock Status Register */
+ uint32_t RESERVED5[1U];
+ __IM uint32_t DEVARCH; /*!< Offset: 0xFBC (R/ ) ITM Device Architecture Register */
+ uint32_t RESERVED6[4U];
+ __IM uint32_t PID4; /*!< Offset: 0xFD0 (R/ ) ITM Peripheral Identification Register #4 */
+ __IM uint32_t PID5; /*!< Offset: 0xFD4 (R/ ) ITM Peripheral Identification Register #5 */
+ __IM uint32_t PID6; /*!< Offset: 0xFD8 (R/ ) ITM Peripheral Identification Register #6 */
+ __IM uint32_t PID7; /*!< Offset: 0xFDC (R/ ) ITM Peripheral Identification Register #7 */
+ __IM uint32_t PID0; /*!< Offset: 0xFE0 (R/ ) ITM Peripheral Identification Register #0 */
+ __IM uint32_t PID1; /*!< Offset: 0xFE4 (R/ ) ITM Peripheral Identification Register #1 */
+ __IM uint32_t PID2; /*!< Offset: 0xFE8 (R/ ) ITM Peripheral Identification Register #2 */
+ __IM uint32_t PID3; /*!< Offset: 0xFEC (R/ ) ITM Peripheral Identification Register #3 */
+ __IM uint32_t CID0; /*!< Offset: 0xFF0 (R/ ) ITM Component Identification Register #0 */
+ __IM uint32_t CID1; /*!< Offset: 0xFF4 (R/ ) ITM Component Identification Register #1 */
+ __IM uint32_t CID2; /*!< Offset: 0xFF8 (R/ ) ITM Component Identification Register #2 */
+ __IM uint32_t CID3; /*!< Offset: 0xFFC (R/ ) ITM Component Identification Register #3 */
+} ITM_Type;
+
+/* ITM Stimulus Port Register Definitions */
+#define ITM_STIM_DISABLED_Pos 1U /*!< ITM STIM: DISABLED Position */
+#define ITM_STIM_DISABLED_Msk (0x1UL << ITM_STIM_DISABLED_Pos) /*!< ITM STIM: DISABLED Mask */
+
+#define ITM_STIM_FIFOREADY_Pos 0U /*!< ITM STIM: FIFOREADY Position */
+#define ITM_STIM_FIFOREADY_Msk (0x1UL /*<< ITM_STIM_FIFOREADY_Pos*/) /*!< ITM STIM: FIFOREADY Mask */
+
+/* ITM Trace Privilege Register Definitions */
+#define ITM_TPR_PRIVMASK_Pos 0U /*!< ITM TPR: PRIVMASK Position */
+#define ITM_TPR_PRIVMASK_Msk (0xFUL /*<< ITM_TPR_PRIVMASK_Pos*/) /*!< ITM TPR: PRIVMASK Mask */
+
+/* ITM Trace Control Register Definitions */
+#define ITM_TCR_BUSY_Pos 23U /*!< ITM TCR: BUSY Position */
+#define ITM_TCR_BUSY_Msk (1UL << ITM_TCR_BUSY_Pos) /*!< ITM TCR: BUSY Mask */
+
+#define ITM_TCR_TRACEBUSID_Pos 16U /*!< ITM TCR: ATBID Position */
+#define ITM_TCR_TRACEBUSID_Msk (0x7FUL << ITM_TCR_TRACEBUSID_Pos) /*!< ITM TCR: ATBID Mask */
+
+#define ITM_TCR_GTSFREQ_Pos 10U /*!< ITM TCR: Global timestamp frequency Position */
+#define ITM_TCR_GTSFREQ_Msk (3UL << ITM_TCR_GTSFREQ_Pos) /*!< ITM TCR: Global timestamp frequency Mask */
+
+#define ITM_TCR_TSPRESCALE_Pos 8U /*!< ITM TCR: TSPRESCALE Position */
+#define ITM_TCR_TSPRESCALE_Msk (3UL << ITM_TCR_TSPRESCALE_Pos) /*!< ITM TCR: TSPRESCALE Mask */
+
+#define ITM_TCR_STALLENA_Pos 5U /*!< ITM TCR: STALLENA Position */
+#define ITM_TCR_STALLENA_Msk (1UL << ITM_TCR_STALLENA_Pos) /*!< ITM TCR: STALLENA Mask */
+
+#define ITM_TCR_SWOENA_Pos 4U /*!< ITM TCR: SWOENA Position */
+#define ITM_TCR_SWOENA_Msk (1UL << ITM_TCR_SWOENA_Pos) /*!< ITM TCR: SWOENA Mask */
+
+#define ITM_TCR_DWTENA_Pos 3U /*!< ITM TCR: DWTENA Position */
+#define ITM_TCR_DWTENA_Msk (1UL << ITM_TCR_DWTENA_Pos) /*!< ITM TCR: DWTENA Mask */
+
+#define ITM_TCR_SYNCENA_Pos 2U /*!< ITM TCR: SYNCENA Position */
+#define ITM_TCR_SYNCENA_Msk (1UL << ITM_TCR_SYNCENA_Pos) /*!< ITM TCR: SYNCENA Mask */
+
+#define ITM_TCR_TSENA_Pos 1U /*!< ITM TCR: TSENA Position */
+#define ITM_TCR_TSENA_Msk (1UL << ITM_TCR_TSENA_Pos) /*!< ITM TCR: TSENA Mask */
+
+#define ITM_TCR_ITMENA_Pos 0U /*!< ITM TCR: ITM Enable bit Position */
+#define ITM_TCR_ITMENA_Msk (1UL /*<< ITM_TCR_ITMENA_Pos*/) /*!< ITM TCR: ITM Enable bit Mask */
+
+/* ITM Integration Write Register Definitions */
+#define ITM_IWR_ATVALIDM_Pos 0U /*!< ITM IWR: ATVALIDM Position */
+#define ITM_IWR_ATVALIDM_Msk (1UL /*<< ITM_IWR_ATVALIDM_Pos*/) /*!< ITM IWR: ATVALIDM Mask */
+
+/* ITM Integration Read Register Definitions */
+#define ITM_IRR_ATREADYM_Pos 0U /*!< ITM IRR: ATREADYM Position */
+#define ITM_IRR_ATREADYM_Msk (1UL /*<< ITM_IRR_ATREADYM_Pos*/) /*!< ITM IRR: ATREADYM Mask */
+
+/* ITM Integration Mode Control Register Definitions */
+#define ITM_IMCR_INTEGRATION_Pos 0U /*!< ITM IMCR: INTEGRATION Position */
+#define ITM_IMCR_INTEGRATION_Msk (1UL /*<< ITM_IMCR_INTEGRATION_Pos*/) /*!< ITM IMCR: INTEGRATION Mask */
+
+/* ITM Lock Status Register Definitions */
+#define ITM_LSR_ByteAcc_Pos 2U /*!< ITM LSR: ByteAcc Position */
+#define ITM_LSR_ByteAcc_Msk (1UL << ITM_LSR_ByteAcc_Pos) /*!< ITM LSR: ByteAcc Mask */
+
+#define ITM_LSR_Access_Pos 1U /*!< ITM LSR: Access Position */
+#define ITM_LSR_Access_Msk (1UL << ITM_LSR_Access_Pos) /*!< ITM LSR: Access Mask */
+
+#define ITM_LSR_Present_Pos 0U /*!< ITM LSR: Present Position */
+#define ITM_LSR_Present_Msk (1UL /*<< ITM_LSR_Present_Pos*/) /*!< ITM LSR: Present Mask */
+
+/*@}*/ /* end of group CMSIS_ITM */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_DWT Data Watchpoint and Trace (DWT)
+ \brief Type definitions for the Data Watchpoint and Trace (DWT)
+ @{
+ */
+
+/**
+ \brief Structure type to access the Data Watchpoint and Trace Register (DWT).
+ */
+typedef struct
+{
+ __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) Control Register */
+ __IOM uint32_t CYCCNT; /*!< Offset: 0x004 (R/W) Cycle Count Register */
+ __IOM uint32_t CPICNT; /*!< Offset: 0x008 (R/W) CPI Count Register */
+ __IOM uint32_t EXCCNT; /*!< Offset: 0x00C (R/W) Exception Overhead Count Register */
+ __IOM uint32_t SLEEPCNT; /*!< Offset: 0x010 (R/W) Sleep Count Register */
+ __IOM uint32_t LSUCNT; /*!< Offset: 0x014 (R/W) LSU Count Register */
+ __IOM uint32_t FOLDCNT; /*!< Offset: 0x018 (R/W) Folded-instruction Count Register */
+ __IM uint32_t PCSR; /*!< Offset: 0x01C (R/ ) Program Counter Sample Register */
+ __IOM uint32_t COMP0; /*!< Offset: 0x020 (R/W) Comparator Register 0 */
+ uint32_t RESERVED1[1U];
+ __IOM uint32_t FUNCTION0; /*!< Offset: 0x028 (R/W) Function Register 0 */
+ uint32_t RESERVED2[1U];
+ __IOM uint32_t COMP1; /*!< Offset: 0x030 (R/W) Comparator Register 1 */
+ uint32_t RESERVED3[1U];
+ __IOM uint32_t FUNCTION1; /*!< Offset: 0x038 (R/W) Function Register 1 */
+ uint32_t RESERVED4[1U];
+ __IOM uint32_t COMP2; /*!< Offset: 0x040 (R/W) Comparator Register 2 */
+ uint32_t RESERVED5[1U];
+ __IOM uint32_t FUNCTION2; /*!< Offset: 0x048 (R/W) Function Register 2 */
+ uint32_t RESERVED6[1U];
+ __IOM uint32_t COMP3; /*!< Offset: 0x050 (R/W) Comparator Register 3 */
+ uint32_t RESERVED7[1U];
+ __IOM uint32_t FUNCTION3; /*!< Offset: 0x058 (R/W) Function Register 3 */
+ uint32_t RESERVED8[1U];
+ __IOM uint32_t COMP4; /*!< Offset: 0x060 (R/W) Comparator Register 4 */
+ uint32_t RESERVED9[1U];
+ __IOM uint32_t FUNCTION4; /*!< Offset: 0x068 (R/W) Function Register 4 */
+ uint32_t RESERVED10[1U];
+ __IOM uint32_t COMP5; /*!< Offset: 0x070 (R/W) Comparator Register 5 */
+ uint32_t RESERVED11[1U];
+ __IOM uint32_t FUNCTION5; /*!< Offset: 0x078 (R/W) Function Register 5 */
+ uint32_t RESERVED12[1U];
+ __IOM uint32_t COMP6; /*!< Offset: 0x080 (R/W) Comparator Register 6 */
+ uint32_t RESERVED13[1U];
+ __IOM uint32_t FUNCTION6; /*!< Offset: 0x088 (R/W) Function Register 6 */
+ uint32_t RESERVED14[1U];
+ __IOM uint32_t COMP7; /*!< Offset: 0x090 (R/W) Comparator Register 7 */
+ uint32_t RESERVED15[1U];
+ __IOM uint32_t FUNCTION7; /*!< Offset: 0x098 (R/W) Function Register 7 */
+ uint32_t RESERVED16[1U];
+ __IOM uint32_t COMP8; /*!< Offset: 0x0A0 (R/W) Comparator Register 8 */
+ uint32_t RESERVED17[1U];
+ __IOM uint32_t FUNCTION8; /*!< Offset: 0x0A8 (R/W) Function Register 8 */
+ uint32_t RESERVED18[1U];
+ __IOM uint32_t COMP9; /*!< Offset: 0x0B0 (R/W) Comparator Register 9 */
+ uint32_t RESERVED19[1U];
+ __IOM uint32_t FUNCTION9; /*!< Offset: 0x0B8 (R/W) Function Register 9 */
+ uint32_t RESERVED20[1U];
+ __IOM uint32_t COMP10; /*!< Offset: 0x0C0 (R/W) Comparator Register 10 */
+ uint32_t RESERVED21[1U];
+ __IOM uint32_t FUNCTION10; /*!< Offset: 0x0C8 (R/W) Function Register 10 */
+ uint32_t RESERVED22[1U];
+ __IOM uint32_t COMP11; /*!< Offset: 0x0D0 (R/W) Comparator Register 11 */
+ uint32_t RESERVED23[1U];
+ __IOM uint32_t FUNCTION11; /*!< Offset: 0x0D8 (R/W) Function Register 11 */
+ uint32_t RESERVED24[1U];
+ __IOM uint32_t COMP12; /*!< Offset: 0x0E0 (R/W) Comparator Register 12 */
+ uint32_t RESERVED25[1U];
+ __IOM uint32_t FUNCTION12; /*!< Offset: 0x0E8 (R/W) Function Register 12 */
+ uint32_t RESERVED26[1U];
+ __IOM uint32_t COMP13; /*!< Offset: 0x0F0 (R/W) Comparator Register 13 */
+ uint32_t RESERVED27[1U];
+ __IOM uint32_t FUNCTION13; /*!< Offset: 0x0F8 (R/W) Function Register 13 */
+ uint32_t RESERVED28[1U];
+ __IOM uint32_t COMP14; /*!< Offset: 0x100 (R/W) Comparator Register 14 */
+ uint32_t RESERVED29[1U];
+ __IOM uint32_t FUNCTION14; /*!< Offset: 0x108 (R/W) Function Register 14 */
+ uint32_t RESERVED30[1U];
+ __IOM uint32_t COMP15; /*!< Offset: 0x110 (R/W) Comparator Register 15 */
+ uint32_t RESERVED31[1U];
+ __IOM uint32_t FUNCTION15; /*!< Offset: 0x118 (R/W) Function Register 15 */
+ uint32_t RESERVED32[934U];
+ __IM uint32_t LSR; /*!< Offset: 0xFB4 (R ) Lock Status Register */
+ uint32_t RESERVED33[1U];
+ __IM uint32_t DEVARCH; /*!< Offset: 0xFBC (R/ ) Device Architecture Register */
+} DWT_Type;
+
+/* DWT Control Register Definitions */
+#define DWT_CTRL_NUMCOMP_Pos 28U /*!< DWT CTRL: NUMCOMP Position */
+#define DWT_CTRL_NUMCOMP_Msk (0xFUL << DWT_CTRL_NUMCOMP_Pos) /*!< DWT CTRL: NUMCOMP Mask */
+
+#define DWT_CTRL_NOTRCPKT_Pos 27U /*!< DWT CTRL: NOTRCPKT Position */
+#define DWT_CTRL_NOTRCPKT_Msk (0x1UL << DWT_CTRL_NOTRCPKT_Pos) /*!< DWT CTRL: NOTRCPKT Mask */
+
+#define DWT_CTRL_NOEXTTRIG_Pos 26U /*!< DWT CTRL: NOEXTTRIG Position */
+#define DWT_CTRL_NOEXTTRIG_Msk (0x1UL << DWT_CTRL_NOEXTTRIG_Pos) /*!< DWT CTRL: NOEXTTRIG Mask */
+
+#define DWT_CTRL_NOCYCCNT_Pos 25U /*!< DWT CTRL: NOCYCCNT Position */
+#define DWT_CTRL_NOCYCCNT_Msk (0x1UL << DWT_CTRL_NOCYCCNT_Pos) /*!< DWT CTRL: NOCYCCNT Mask */
+
+#define DWT_CTRL_NOPRFCNT_Pos 24U /*!< DWT CTRL: NOPRFCNT Position */
+#define DWT_CTRL_NOPRFCNT_Msk (0x1UL << DWT_CTRL_NOPRFCNT_Pos) /*!< DWT CTRL: NOPRFCNT Mask */
+
+#define DWT_CTRL_CYCDISS_Pos 23U /*!< DWT CTRL: CYCDISS Position */
+#define DWT_CTRL_CYCDISS_Msk (0x1UL << DWT_CTRL_CYCDISS_Pos) /*!< DWT CTRL: CYCDISS Mask */
+
+#define DWT_CTRL_CYCEVTENA_Pos 22U /*!< DWT CTRL: CYCEVTENA Position */
+#define DWT_CTRL_CYCEVTENA_Msk (0x1UL << DWT_CTRL_CYCEVTENA_Pos) /*!< DWT CTRL: CYCEVTENA Mask */
+
+#define DWT_CTRL_FOLDEVTENA_Pos 21U /*!< DWT CTRL: FOLDEVTENA Position */
+#define DWT_CTRL_FOLDEVTENA_Msk (0x1UL << DWT_CTRL_FOLDEVTENA_Pos) /*!< DWT CTRL: FOLDEVTENA Mask */
+
+#define DWT_CTRL_LSUEVTENA_Pos 20U /*!< DWT CTRL: LSUEVTENA Position */
+#define DWT_CTRL_LSUEVTENA_Msk (0x1UL << DWT_CTRL_LSUEVTENA_Pos) /*!< DWT CTRL: LSUEVTENA Mask */
+
+#define DWT_CTRL_SLEEPEVTENA_Pos 19U /*!< DWT CTRL: SLEEPEVTENA Position */
+#define DWT_CTRL_SLEEPEVTENA_Msk (0x1UL << DWT_CTRL_SLEEPEVTENA_Pos) /*!< DWT CTRL: SLEEPEVTENA Mask */
+
+#define DWT_CTRL_EXCEVTENA_Pos 18U /*!< DWT CTRL: EXCEVTENA Position */
+#define DWT_CTRL_EXCEVTENA_Msk (0x1UL << DWT_CTRL_EXCEVTENA_Pos) /*!< DWT CTRL: EXCEVTENA Mask */
+
+#define DWT_CTRL_CPIEVTENA_Pos 17U /*!< DWT CTRL: CPIEVTENA Position */
+#define DWT_CTRL_CPIEVTENA_Msk (0x1UL << DWT_CTRL_CPIEVTENA_Pos) /*!< DWT CTRL: CPIEVTENA Mask */
+
+#define DWT_CTRL_EXCTRCENA_Pos 16U /*!< DWT CTRL: EXCTRCENA Position */
+#define DWT_CTRL_EXCTRCENA_Msk (0x1UL << DWT_CTRL_EXCTRCENA_Pos) /*!< DWT CTRL: EXCTRCENA Mask */
+
+#define DWT_CTRL_PCSAMPLENA_Pos 12U /*!< DWT CTRL: PCSAMPLENA Position */
+#define DWT_CTRL_PCSAMPLENA_Msk (0x1UL << DWT_CTRL_PCSAMPLENA_Pos) /*!< DWT CTRL: PCSAMPLENA Mask */
+
+#define DWT_CTRL_SYNCTAP_Pos 10U /*!< DWT CTRL: SYNCTAP Position */
+#define DWT_CTRL_SYNCTAP_Msk (0x3UL << DWT_CTRL_SYNCTAP_Pos) /*!< DWT CTRL: SYNCTAP Mask */
+
+#define DWT_CTRL_CYCTAP_Pos 9U /*!< DWT CTRL: CYCTAP Position */
+#define DWT_CTRL_CYCTAP_Msk (0x1UL << DWT_CTRL_CYCTAP_Pos) /*!< DWT CTRL: CYCTAP Mask */
+
+#define DWT_CTRL_POSTINIT_Pos 5U /*!< DWT CTRL: POSTINIT Position */
+#define DWT_CTRL_POSTINIT_Msk (0xFUL << DWT_CTRL_POSTINIT_Pos) /*!< DWT CTRL: POSTINIT Mask */
+
+#define DWT_CTRL_POSTPRESET_Pos 1U /*!< DWT CTRL: POSTPRESET Position */
+#define DWT_CTRL_POSTPRESET_Msk (0xFUL << DWT_CTRL_POSTPRESET_Pos) /*!< DWT CTRL: POSTPRESET Mask */
+
+#define DWT_CTRL_CYCCNTENA_Pos 0U /*!< DWT CTRL: CYCCNTENA Position */
+#define DWT_CTRL_CYCCNTENA_Msk (0x1UL /*<< DWT_CTRL_CYCCNTENA_Pos*/) /*!< DWT CTRL: CYCCNTENA Mask */
+
+/* DWT CPI Count Register Definitions */
+#define DWT_CPICNT_CPICNT_Pos 0U /*!< DWT CPICNT: CPICNT Position */
+#define DWT_CPICNT_CPICNT_Msk (0xFFUL /*<< DWT_CPICNT_CPICNT_Pos*/) /*!< DWT CPICNT: CPICNT Mask */
+
+/* DWT Exception Overhead Count Register Definitions */
+#define DWT_EXCCNT_EXCCNT_Pos 0U /*!< DWT EXCCNT: EXCCNT Position */
+#define DWT_EXCCNT_EXCCNT_Msk (0xFFUL /*<< DWT_EXCCNT_EXCCNT_Pos*/) /*!< DWT EXCCNT: EXCCNT Mask */
+
+/* DWT Sleep Count Register Definitions */
+#define DWT_SLEEPCNT_SLEEPCNT_Pos 0U /*!< DWT SLEEPCNT: SLEEPCNT Position */
+#define DWT_SLEEPCNT_SLEEPCNT_Msk (0xFFUL /*<< DWT_SLEEPCNT_SLEEPCNT_Pos*/) /*!< DWT SLEEPCNT: SLEEPCNT Mask */
+
+/* DWT LSU Count Register Definitions */
+#define DWT_LSUCNT_LSUCNT_Pos 0U /*!< DWT LSUCNT: LSUCNT Position */
+#define DWT_LSUCNT_LSUCNT_Msk (0xFFUL /*<< DWT_LSUCNT_LSUCNT_Pos*/) /*!< DWT LSUCNT: LSUCNT Mask */
+
+/* DWT Folded-instruction Count Register Definitions */
+#define DWT_FOLDCNT_FOLDCNT_Pos 0U /*!< DWT FOLDCNT: FOLDCNT Position */
+#define DWT_FOLDCNT_FOLDCNT_Msk (0xFFUL /*<< DWT_FOLDCNT_FOLDCNT_Pos*/) /*!< DWT FOLDCNT: FOLDCNT Mask */
+
+/* DWT Comparator Function Register Definitions */
+#define DWT_FUNCTION_ID_Pos 27U /*!< DWT FUNCTION: ID Position */
+#define DWT_FUNCTION_ID_Msk (0x1FUL << DWT_FUNCTION_ID_Pos) /*!< DWT FUNCTION: ID Mask */
+
+#define DWT_FUNCTION_MATCHED_Pos 24U /*!< DWT FUNCTION: MATCHED Position */
+#define DWT_FUNCTION_MATCHED_Msk (0x1UL << DWT_FUNCTION_MATCHED_Pos) /*!< DWT FUNCTION: MATCHED Mask */
+
+#define DWT_FUNCTION_DATAVSIZE_Pos 10U /*!< DWT FUNCTION: DATAVSIZE Position */
+#define DWT_FUNCTION_DATAVSIZE_Msk (0x3UL << DWT_FUNCTION_DATAVSIZE_Pos) /*!< DWT FUNCTION: DATAVSIZE Mask */
+
+#define DWT_FUNCTION_ACTION_Pos 4U /*!< DWT FUNCTION: ACTION Position */
+#define DWT_FUNCTION_ACTION_Msk (0x1UL << DWT_FUNCTION_ACTION_Pos) /*!< DWT FUNCTION: ACTION Mask */
+
+#define DWT_FUNCTION_MATCH_Pos 0U /*!< DWT FUNCTION: MATCH Position */
+#define DWT_FUNCTION_MATCH_Msk (0xFUL /*<< DWT_FUNCTION_MATCH_Pos*/) /*!< DWT FUNCTION: MATCH Mask */
+
+/*@}*/ /* end of group CMSIS_DWT */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_TPI Trace Port Interface (TPI)
+ \brief Type definitions for the Trace Port Interface (TPI)
+ @{
+ */
+
+/**
+ \brief Structure type to access the Trace Port Interface Register (TPI).
+ */
+typedef struct
+{
+ __IM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Sizes Register */
+ __IOM uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Sizes Register */
+ uint32_t RESERVED0[2U];
+ __IOM uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */
+ uint32_t RESERVED1[55U];
+ __IOM uint32_t SPPR; /*!< Offset: 0x0F0 (R/W) Selected Pin Protocol Register */
+ uint32_t RESERVED2[131U];
+ __IM uint32_t FFSR; /*!< Offset: 0x300 (R/ ) Formatter and Flush Status Register */
+ __IOM uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */
+ __IM uint32_t FSCR; /*!< Offset: 0x308 (R/ ) Formatter Synchronization Counter Register */
+ uint32_t RESERVED3[759U];
+ __IM uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER */
+ __IM uint32_t FIFO0; /*!< Offset: 0xEEC (R/ ) Integration ETM Data */
+ __IM uint32_t ITATBCTR2; /*!< Offset: 0xEF0 (R/ ) ITATBCTR2 */
+ uint32_t RESERVED4[1U];
+ __IM uint32_t ITATBCTR0; /*!< Offset: 0xEF8 (R/ ) ITATBCTR0 */
+ __IM uint32_t FIFO1; /*!< Offset: 0xEFC (R/ ) Integration ITM Data */
+ __IOM uint32_t ITCTRL; /*!< Offset: 0xF00 (R/W) Integration Mode Control */
+ uint32_t RESERVED5[39U];
+ __IOM uint32_t CLAIMSET; /*!< Offset: 0xFA0 (R/W) Claim tag set */
+ __IOM uint32_t CLAIMCLR; /*!< Offset: 0xFA4 (R/W) Claim tag clear */
+ uint32_t RESERVED7[8U];
+ __IM uint32_t DEVID; /*!< Offset: 0xFC8 (R/ ) TPIU_DEVID */
+ __IM uint32_t DEVTYPE; /*!< Offset: 0xFCC (R/ ) TPIU_DEVTYPE */
+} TPI_Type;
+
+/* TPI Asynchronous Clock Prescaler Register Definitions */
+#define TPI_ACPR_PRESCALER_Pos 0U /*!< TPI ACPR: PRESCALER Position */
+#define TPI_ACPR_PRESCALER_Msk (0x1FFFUL /*<< TPI_ACPR_PRESCALER_Pos*/) /*!< TPI ACPR: PRESCALER Mask */
+
+/* TPI Selected Pin Protocol Register Definitions */
+#define TPI_SPPR_TXMODE_Pos 0U /*!< TPI SPPR: TXMODE Position */
+#define TPI_SPPR_TXMODE_Msk (0x3UL /*<< TPI_SPPR_TXMODE_Pos*/) /*!< TPI SPPR: TXMODE Mask */
+
+/* TPI Formatter and Flush Status Register Definitions */
+#define TPI_FFSR_FtNonStop_Pos 3U /*!< TPI FFSR: FtNonStop Position */
+#define TPI_FFSR_FtNonStop_Msk (0x1UL << TPI_FFSR_FtNonStop_Pos) /*!< TPI FFSR: FtNonStop Mask */
+
+#define TPI_FFSR_TCPresent_Pos 2U /*!< TPI FFSR: TCPresent Position */
+#define TPI_FFSR_TCPresent_Msk (0x1UL << TPI_FFSR_TCPresent_Pos) /*!< TPI FFSR: TCPresent Mask */
+
+#define TPI_FFSR_FtStopped_Pos 1U /*!< TPI FFSR: FtStopped Position */
+#define TPI_FFSR_FtStopped_Msk (0x1UL << TPI_FFSR_FtStopped_Pos) /*!< TPI FFSR: FtStopped Mask */
+
+#define TPI_FFSR_FlInProg_Pos 0U /*!< TPI FFSR: FlInProg Position */
+#define TPI_FFSR_FlInProg_Msk (0x1UL /*<< TPI_FFSR_FlInProg_Pos*/) /*!< TPI FFSR: FlInProg Mask */
+
+/* TPI Formatter and Flush Control Register Definitions */
+#define TPI_FFCR_TrigIn_Pos 8U /*!< TPI FFCR: TrigIn Position */
+#define TPI_FFCR_TrigIn_Msk (0x1UL << TPI_FFCR_TrigIn_Pos) /*!< TPI FFCR: TrigIn Mask */
+
+#define TPI_FFCR_EnFCont_Pos 1U /*!< TPI FFCR: EnFCont Position */
+#define TPI_FFCR_EnFCont_Msk (0x1UL << TPI_FFCR_EnFCont_Pos) /*!< TPI FFCR: EnFCont Mask */
+
+/* TPI TRIGGER Register Definitions */
+#define TPI_TRIGGER_TRIGGER_Pos 0U /*!< TPI TRIGGER: TRIGGER Position */
+#define TPI_TRIGGER_TRIGGER_Msk (0x1UL /*<< TPI_TRIGGER_TRIGGER_Pos*/) /*!< TPI TRIGGER: TRIGGER Mask */
+
+/* TPI Integration ETM Data Register Definitions (FIFO0) */
+#define TPI_FIFO0_ITM_ATVALID_Pos 29U /*!< TPI FIFO0: ITM_ATVALID Position */
+#define TPI_FIFO0_ITM_ATVALID_Msk (0x3UL << TPI_FIFO0_ITM_ATVALID_Pos) /*!< TPI FIFO0: ITM_ATVALID Mask */
+
+#define TPI_FIFO0_ITM_bytecount_Pos 27U /*!< TPI FIFO0: ITM_bytecount Position */
+#define TPI_FIFO0_ITM_bytecount_Msk (0x3UL << TPI_FIFO0_ITM_bytecount_Pos) /*!< TPI FIFO0: ITM_bytecount Mask */
+
+#define TPI_FIFO0_ETM_ATVALID_Pos 26U /*!< TPI FIFO0: ETM_ATVALID Position */
+#define TPI_FIFO0_ETM_ATVALID_Msk (0x3UL << TPI_FIFO0_ETM_ATVALID_Pos) /*!< TPI FIFO0: ETM_ATVALID Mask */
+
+#define TPI_FIFO0_ETM_bytecount_Pos 24U /*!< TPI FIFO0: ETM_bytecount Position */
+#define TPI_FIFO0_ETM_bytecount_Msk (0x3UL << TPI_FIFO0_ETM_bytecount_Pos) /*!< TPI FIFO0: ETM_bytecount Mask */
+
+#define TPI_FIFO0_ETM2_Pos 16U /*!< TPI FIFO0: ETM2 Position */
+#define TPI_FIFO0_ETM2_Msk (0xFFUL << TPI_FIFO0_ETM2_Pos) /*!< TPI FIFO0: ETM2 Mask */
+
+#define TPI_FIFO0_ETM1_Pos 8U /*!< TPI FIFO0: ETM1 Position */
+#define TPI_FIFO0_ETM1_Msk (0xFFUL << TPI_FIFO0_ETM1_Pos) /*!< TPI FIFO0: ETM1 Mask */
+
+#define TPI_FIFO0_ETM0_Pos 0U /*!< TPI FIFO0: ETM0 Position */
+#define TPI_FIFO0_ETM0_Msk (0xFFUL /*<< TPI_FIFO0_ETM0_Pos*/) /*!< TPI FIFO0: ETM0 Mask */
+
+/* TPI ITATBCTR2 Register Definitions */
+#define TPI_ITATBCTR2_ATREADY_Pos 0U /*!< TPI ITATBCTR2: ATREADY Position */
+#define TPI_ITATBCTR2_ATREADY_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY_Pos*/) /*!< TPI ITATBCTR2: ATREADY Mask */
+
+/* TPI Integration ITM Data Register Definitions (FIFO1) */
+#define TPI_FIFO1_ITM_ATVALID_Pos 29U /*!< TPI FIFO1: ITM_ATVALID Position */
+#define TPI_FIFO1_ITM_ATVALID_Msk (0x3UL << TPI_FIFO1_ITM_ATVALID_Pos) /*!< TPI FIFO1: ITM_ATVALID Mask */
+
+#define TPI_FIFO1_ITM_bytecount_Pos 27U /*!< TPI FIFO1: ITM_bytecount Position */
+#define TPI_FIFO1_ITM_bytecount_Msk (0x3UL << TPI_FIFO1_ITM_bytecount_Pos) /*!< TPI FIFO1: ITM_bytecount Mask */
+
+#define TPI_FIFO1_ETM_ATVALID_Pos 26U /*!< TPI FIFO1: ETM_ATVALID Position */
+#define TPI_FIFO1_ETM_ATVALID_Msk (0x3UL << TPI_FIFO1_ETM_ATVALID_Pos) /*!< TPI FIFO1: ETM_ATVALID Mask */
+
+#define TPI_FIFO1_ETM_bytecount_Pos 24U /*!< TPI FIFO1: ETM_bytecount Position */
+#define TPI_FIFO1_ETM_bytecount_Msk (0x3UL << TPI_FIFO1_ETM_bytecount_Pos) /*!< TPI FIFO1: ETM_bytecount Mask */
+
+#define TPI_FIFO1_ITM2_Pos 16U /*!< TPI FIFO1: ITM2 Position */
+#define TPI_FIFO1_ITM2_Msk (0xFFUL << TPI_FIFO1_ITM2_Pos) /*!< TPI FIFO1: ITM2 Mask */
+
+#define TPI_FIFO1_ITM1_Pos 8U /*!< TPI FIFO1: ITM1 Position */
+#define TPI_FIFO1_ITM1_Msk (0xFFUL << TPI_FIFO1_ITM1_Pos) /*!< TPI FIFO1: ITM1 Mask */
+
+#define TPI_FIFO1_ITM0_Pos 0U /*!< TPI FIFO1: ITM0 Position */
+#define TPI_FIFO1_ITM0_Msk (0xFFUL /*<< TPI_FIFO1_ITM0_Pos*/) /*!< TPI FIFO1: ITM0 Mask */
+
+/* TPI ITATBCTR0 Register Definitions */
+#define TPI_ITATBCTR0_ATREADY_Pos 0U /*!< TPI ITATBCTR0: ATREADY Position */
+#define TPI_ITATBCTR0_ATREADY_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY_Pos*/) /*!< TPI ITATBCTR0: ATREADY Mask */
+
+/* TPI Integration Mode Control Register Definitions */
+#define TPI_ITCTRL_Mode_Pos 0U /*!< TPI ITCTRL: Mode Position */
+#define TPI_ITCTRL_Mode_Msk (0x1UL /*<< TPI_ITCTRL_Mode_Pos*/) /*!< TPI ITCTRL: Mode Mask */
+
+/* TPI DEVID Register Definitions */
+#define TPI_DEVID_NRZVALID_Pos 11U /*!< TPI DEVID: NRZVALID Position */
+#define TPI_DEVID_NRZVALID_Msk (0x1UL << TPI_DEVID_NRZVALID_Pos) /*!< TPI DEVID: NRZVALID Mask */
+
+#define TPI_DEVID_MANCVALID_Pos 10U /*!< TPI DEVID: MANCVALID Position */
+#define TPI_DEVID_MANCVALID_Msk (0x1UL << TPI_DEVID_MANCVALID_Pos) /*!< TPI DEVID: MANCVALID Mask */
+
+#define TPI_DEVID_PTINVALID_Pos 9U /*!< TPI DEVID: PTINVALID Position */
+#define TPI_DEVID_PTINVALID_Msk (0x1UL << TPI_DEVID_PTINVALID_Pos) /*!< TPI DEVID: PTINVALID Mask */
+
+#define TPI_DEVID_MinBufSz_Pos 6U /*!< TPI DEVID: MinBufSz Position */
+#define TPI_DEVID_MinBufSz_Msk (0x7UL << TPI_DEVID_MinBufSz_Pos) /*!< TPI DEVID: MinBufSz Mask */
+
+#define TPI_DEVID_AsynClkIn_Pos 5U /*!< TPI DEVID: AsynClkIn Position */
+#define TPI_DEVID_AsynClkIn_Msk (0x1UL << TPI_DEVID_AsynClkIn_Pos) /*!< TPI DEVID: AsynClkIn Mask */
+
+#define TPI_DEVID_NrTraceInput_Pos 0U /*!< TPI DEVID: NrTraceInput Position */
+#define TPI_DEVID_NrTraceInput_Msk (0x1FUL /*<< TPI_DEVID_NrTraceInput_Pos*/) /*!< TPI DEVID: NrTraceInput Mask */
+
+/* TPI DEVTYPE Register Definitions */
+#define TPI_DEVTYPE_MajorType_Pos 4U /*!< TPI DEVTYPE: MajorType Position */
+#define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */
+
+#define TPI_DEVTYPE_SubType_Pos 0U /*!< TPI DEVTYPE: SubType Position */
+#define TPI_DEVTYPE_SubType_Msk (0xFUL /*<< TPI_DEVTYPE_SubType_Pos*/) /*!< TPI DEVTYPE: SubType Mask */
+
+/*@}*/ /* end of group CMSIS_TPI */
+
+
+#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U)
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_MPU Memory Protection Unit (MPU)
+ \brief Type definitions for the Memory Protection Unit (MPU)
+ @{
+ */
+
+/**
+ \brief Structure type to access the Memory Protection Unit (MPU).
+ */
+typedef struct
+{
+ __IM uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */
+ __IOM uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */
+ __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region Number Register */
+ __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */
+ __IOM uint32_t RLAR; /*!< Offset: 0x010 (R/W) MPU Region Limit Address Register */
+ __IOM uint32_t RBAR_A1; /*!< Offset: 0x014 (R/W) MPU Region Base Address Register Alias 1 */
+ __IOM uint32_t RLAR_A1; /*!< Offset: 0x018 (R/W) MPU Region Limit Address Register Alias 1 */
+ __IOM uint32_t RBAR_A2; /*!< Offset: 0x01C (R/W) MPU Region Base Address Register Alias 2 */
+ __IOM uint32_t RLAR_A2; /*!< Offset: 0x020 (R/W) MPU Region Limit Address Register Alias 2 */
+ __IOM uint32_t RBAR_A3; /*!< Offset: 0x024 (R/W) MPU Region Base Address Register Alias 3 */
+ __IOM uint32_t RLAR_A3; /*!< Offset: 0x028 (R/W) MPU Region Limit Address Register Alias 3 */
+ uint32_t RESERVED0[1];
+ union {
+ __IOM uint32_t MAIR[2];
+ struct {
+ __IOM uint32_t MAIR0; /*!< Offset: 0x030 (R/W) MPU Memory Attribute Indirection Register 0 */
+ __IOM uint32_t MAIR1; /*!< Offset: 0x034 (R/W) MPU Memory Attribute Indirection Register 1 */
+ };
+ };
+} MPU_Type;
+
+#define MPU_TYPE_RALIASES 4U
+
+/* MPU Type Register Definitions */
+#define MPU_TYPE_IREGION_Pos 16U /*!< MPU TYPE: IREGION Position */
+#define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */
+
+#define MPU_TYPE_DREGION_Pos 8U /*!< MPU TYPE: DREGION Position */
+#define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */
+
+#define MPU_TYPE_SEPARATE_Pos 0U /*!< MPU TYPE: SEPARATE Position */
+#define MPU_TYPE_SEPARATE_Msk (1UL /*<< MPU_TYPE_SEPARATE_Pos*/) /*!< MPU TYPE: SEPARATE Mask */
+
+/* MPU Control Register Definitions */
+#define MPU_CTRL_PRIVDEFENA_Pos 2U /*!< MPU CTRL: PRIVDEFENA Position */
+#define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */
+
+#define MPU_CTRL_HFNMIENA_Pos 1U /*!< MPU CTRL: HFNMIENA Position */
+#define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */
+
+#define MPU_CTRL_ENABLE_Pos 0U /*!< MPU CTRL: ENABLE Position */
+#define MPU_CTRL_ENABLE_Msk (1UL /*<< MPU_CTRL_ENABLE_Pos*/) /*!< MPU CTRL: ENABLE Mask */
+
+/* MPU Region Number Register Definitions */
+#define MPU_RNR_REGION_Pos 0U /*!< MPU RNR: REGION Position */
+#define MPU_RNR_REGION_Msk (0xFFUL /*<< MPU_RNR_REGION_Pos*/) /*!< MPU RNR: REGION Mask */
+
+/* MPU Region Base Address Register Definitions */
+#define MPU_RBAR_ADDR_Pos 5U /*!< MPU RBAR: ADDR Position */
+#define MPU_RBAR_ADDR_Msk (0x7FFFFFFUL << MPU_RBAR_ADDR_Pos) /*!< MPU RBAR: ADDR Mask */
+
+#define MPU_RBAR_SH_Pos 3U /*!< MPU RBAR: SH Position */
+#define MPU_RBAR_SH_Msk (0x3UL << MPU_RBAR_SH_Pos) /*!< MPU RBAR: SH Mask */
+
+#define MPU_RBAR_AP_Pos 1U /*!< MPU RBAR: AP Position */
+#define MPU_RBAR_AP_Msk (0x3UL << MPU_RBAR_AP_Pos) /*!< MPU RBAR: AP Mask */
+
+#define MPU_RBAR_XN_Pos 0U /*!< MPU RBAR: XN Position */
+#define MPU_RBAR_XN_Msk (01UL /*<< MPU_RBAR_XN_Pos*/) /*!< MPU RBAR: XN Mask */
+
+/* MPU Region Limit Address Register Definitions */
+#define MPU_RLAR_LIMIT_Pos 5U /*!< MPU RLAR: LIMIT Position */
+#define MPU_RLAR_LIMIT_Msk (0x7FFFFFFUL << MPU_RLAR_LIMIT_Pos) /*!< MPU RLAR: LIMIT Mask */
+
+#define MPU_RLAR_PXN_Pos 4U /*!< MPU RLAR: PXN Position */
+#define MPU_RLAR_PXN_Msk (0x1UL << MPU_RLAR_PXN_Pos) /*!< MPU RLAR: PXN Mask */
+
+#define MPU_RLAR_AttrIndx_Pos 1U /*!< MPU RLAR: AttrIndx Position */
+#define MPU_RLAR_AttrIndx_Msk (0x7UL << MPU_RLAR_AttrIndx_Pos) /*!< MPU RLAR: AttrIndx Mask */
+
+#define MPU_RLAR_EN_Pos 0U /*!< MPU RLAR: Region enable bit Position */
+#define MPU_RLAR_EN_Msk (1UL /*<< MPU_RLAR_EN_Pos*/) /*!< MPU RLAR: Region enable bit Disable Mask */
+
+/* MPU Memory Attribute Indirection Register 0 Definitions */
+#define MPU_MAIR0_Attr3_Pos 24U /*!< MPU MAIR0: Attr3 Position */
+#define MPU_MAIR0_Attr3_Msk (0xFFUL << MPU_MAIR0_Attr3_Pos) /*!< MPU MAIR0: Attr3 Mask */
+
+#define MPU_MAIR0_Attr2_Pos 16U /*!< MPU MAIR0: Attr2 Position */
+#define MPU_MAIR0_Attr2_Msk (0xFFUL << MPU_MAIR0_Attr2_Pos) /*!< MPU MAIR0: Attr2 Mask */
+
+#define MPU_MAIR0_Attr1_Pos 8U /*!< MPU MAIR0: Attr1 Position */
+#define MPU_MAIR0_Attr1_Msk (0xFFUL << MPU_MAIR0_Attr1_Pos) /*!< MPU MAIR0: Attr1 Mask */
+
+#define MPU_MAIR0_Attr0_Pos 0U /*!< MPU MAIR0: Attr0 Position */
+#define MPU_MAIR0_Attr0_Msk (0xFFUL /*<< MPU_MAIR0_Attr0_Pos*/) /*!< MPU MAIR0: Attr0 Mask */
+
+/* MPU Memory Attribute Indirection Register 1 Definitions */
+#define MPU_MAIR1_Attr7_Pos 24U /*!< MPU MAIR1: Attr7 Position */
+#define MPU_MAIR1_Attr7_Msk (0xFFUL << MPU_MAIR1_Attr7_Pos) /*!< MPU MAIR1: Attr7 Mask */
+
+#define MPU_MAIR1_Attr6_Pos 16U /*!< MPU MAIR1: Attr6 Position */
+#define MPU_MAIR1_Attr6_Msk (0xFFUL << MPU_MAIR1_Attr6_Pos) /*!< MPU MAIR1: Attr6 Mask */
+
+#define MPU_MAIR1_Attr5_Pos 8U /*!< MPU MAIR1: Attr5 Position */
+#define MPU_MAIR1_Attr5_Msk (0xFFUL << MPU_MAIR1_Attr5_Pos) /*!< MPU MAIR1: Attr5 Mask */
+
+#define MPU_MAIR1_Attr4_Pos 0U /*!< MPU MAIR1: Attr4 Position */
+#define MPU_MAIR1_Attr4_Msk (0xFFUL /*<< MPU_MAIR1_Attr4_Pos*/) /*!< MPU MAIR1: Attr4 Mask */
+
+/*@} end of group CMSIS_MPU */
+#endif
+
+
+#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_SAU Security Attribution Unit (SAU)
+ \brief Type definitions for the Security Attribution Unit (SAU)
+ @{
+ */
+
+/**
+ \brief Structure type to access the Security Attribution Unit (SAU).
+ */
+typedef struct
+{
+ __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SAU Control Register */
+ __IM uint32_t TYPE; /*!< Offset: 0x004 (R/ ) SAU Type Register */
+#if defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U)
+ __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) SAU Region Number Register */
+ __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) SAU Region Base Address Register */
+ __IOM uint32_t RLAR; /*!< Offset: 0x010 (R/W) SAU Region Limit Address Register */
+#else
+ uint32_t RESERVED0[3];
+#endif
+ __IOM uint32_t SFSR; /*!< Offset: 0x014 (R/W) Secure Fault Status Register */
+ __IOM uint32_t SFAR; /*!< Offset: 0x018 (R/W) Secure Fault Address Register */
+} SAU_Type;
+
+/* SAU Control Register Definitions */
+#define SAU_CTRL_ALLNS_Pos 1U /*!< SAU CTRL: ALLNS Position */
+#define SAU_CTRL_ALLNS_Msk (1UL << SAU_CTRL_ALLNS_Pos) /*!< SAU CTRL: ALLNS Mask */
+
+#define SAU_CTRL_ENABLE_Pos 0U /*!< SAU CTRL: ENABLE Position */
+#define SAU_CTRL_ENABLE_Msk (1UL /*<< SAU_CTRL_ENABLE_Pos*/) /*!< SAU CTRL: ENABLE Mask */
+
+/* SAU Type Register Definitions */
+#define SAU_TYPE_SREGION_Pos 0U /*!< SAU TYPE: SREGION Position */
+#define SAU_TYPE_SREGION_Msk (0xFFUL /*<< SAU_TYPE_SREGION_Pos*/) /*!< SAU TYPE: SREGION Mask */
+
+#if defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U)
+/* SAU Region Number Register Definitions */
+#define SAU_RNR_REGION_Pos 0U /*!< SAU RNR: REGION Position */
+#define SAU_RNR_REGION_Msk (0xFFUL /*<< SAU_RNR_REGION_Pos*/) /*!< SAU RNR: REGION Mask */
+
+/* SAU Region Base Address Register Definitions */
+#define SAU_RBAR_BADDR_Pos 5U /*!< SAU RBAR: BADDR Position */
+#define SAU_RBAR_BADDR_Msk (0x7FFFFFFUL << SAU_RBAR_BADDR_Pos) /*!< SAU RBAR: BADDR Mask */
+
+/* SAU Region Limit Address Register Definitions */
+#define SAU_RLAR_LADDR_Pos 5U /*!< SAU RLAR: LADDR Position */
+#define SAU_RLAR_LADDR_Msk (0x7FFFFFFUL << SAU_RLAR_LADDR_Pos) /*!< SAU RLAR: LADDR Mask */
+
+#define SAU_RLAR_NSC_Pos 1U /*!< SAU RLAR: NSC Position */
+#define SAU_RLAR_NSC_Msk (1UL << SAU_RLAR_NSC_Pos) /*!< SAU RLAR: NSC Mask */
+
+#define SAU_RLAR_ENABLE_Pos 0U /*!< SAU RLAR: ENABLE Position */
+#define SAU_RLAR_ENABLE_Msk (1UL /*<< SAU_RLAR_ENABLE_Pos*/) /*!< SAU RLAR: ENABLE Mask */
+
+#endif /* defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U) */
+
+/* Secure Fault Status Register Definitions */
+#define SAU_SFSR_LSERR_Pos 7U /*!< SAU SFSR: LSERR Position */
+#define SAU_SFSR_LSERR_Msk (1UL << SAU_SFSR_LSERR_Pos) /*!< SAU SFSR: LSERR Mask */
+
+#define SAU_SFSR_SFARVALID_Pos 6U /*!< SAU SFSR: SFARVALID Position */
+#define SAU_SFSR_SFARVALID_Msk (1UL << SAU_SFSR_SFARVALID_Pos) /*!< SAU SFSR: SFARVALID Mask */
+
+#define SAU_SFSR_LSPERR_Pos 5U /*!< SAU SFSR: LSPERR Position */
+#define SAU_SFSR_LSPERR_Msk (1UL << SAU_SFSR_LSPERR_Pos) /*!< SAU SFSR: LSPERR Mask */
+
+#define SAU_SFSR_INVTRAN_Pos 4U /*!< SAU SFSR: INVTRAN Position */
+#define SAU_SFSR_INVTRAN_Msk (1UL << SAU_SFSR_INVTRAN_Pos) /*!< SAU SFSR: INVTRAN Mask */
+
+#define SAU_SFSR_AUVIOL_Pos 3U /*!< SAU SFSR: AUVIOL Position */
+#define SAU_SFSR_AUVIOL_Msk (1UL << SAU_SFSR_AUVIOL_Pos) /*!< SAU SFSR: AUVIOL Mask */
+
+#define SAU_SFSR_INVER_Pos 2U /*!< SAU SFSR: INVER Position */
+#define SAU_SFSR_INVER_Msk (1UL << SAU_SFSR_INVER_Pos) /*!< SAU SFSR: INVER Mask */
+
+#define SAU_SFSR_INVIS_Pos 1U /*!< SAU SFSR: INVIS Position */
+#define SAU_SFSR_INVIS_Msk (1UL << SAU_SFSR_INVIS_Pos) /*!< SAU SFSR: INVIS Mask */
+
+#define SAU_SFSR_INVEP_Pos 0U /*!< SAU SFSR: INVEP Position */
+#define SAU_SFSR_INVEP_Msk (1UL /*<< SAU_SFSR_INVEP_Pos*/) /*!< SAU SFSR: INVEP Mask */
+
+/*@} end of group CMSIS_SAU */
+#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_FPU Floating Point Unit (FPU)
+ \brief Type definitions for the Floating Point Unit (FPU)
+ @{
+ */
+
+/**
+ \brief Structure type to access the Floating Point Unit (FPU).
+ */
+typedef struct
+{
+ uint32_t RESERVED0[1U];
+ __IOM uint32_t FPCCR; /*!< Offset: 0x004 (R/W) Floating-Point Context Control Register */
+ __IOM uint32_t FPCAR; /*!< Offset: 0x008 (R/W) Floating-Point Context Address Register */
+ __IOM uint32_t FPDSCR; /*!< Offset: 0x00C (R/W) Floating-Point Default Status Control Register */
+ __IM uint32_t MVFR0; /*!< Offset: 0x010 (R/ ) Media and FP Feature Register 0 */
+ __IM uint32_t MVFR1; /*!< Offset: 0x014 (R/ ) Media and FP Feature Register 1 */
+} FPU_Type;
+
+/* Floating-Point Context Control Register Definitions */
+#define FPU_FPCCR_ASPEN_Pos 31U /*!< FPCCR: ASPEN bit Position */
+#define FPU_FPCCR_ASPEN_Msk (1UL << FPU_FPCCR_ASPEN_Pos) /*!< FPCCR: ASPEN bit Mask */
+
+#define FPU_FPCCR_LSPEN_Pos 30U /*!< FPCCR: LSPEN Position */
+#define FPU_FPCCR_LSPEN_Msk (1UL << FPU_FPCCR_LSPEN_Pos) /*!< FPCCR: LSPEN bit Mask */
+
+#define FPU_FPCCR_LSPENS_Pos 29U /*!< FPCCR: LSPENS Position */
+#define FPU_FPCCR_LSPENS_Msk (1UL << FPU_FPCCR_LSPENS_Pos) /*!< FPCCR: LSPENS bit Mask */
+
+#define FPU_FPCCR_CLRONRET_Pos 28U /*!< FPCCR: CLRONRET Position */
+#define FPU_FPCCR_CLRONRET_Msk (1UL << FPU_FPCCR_CLRONRET_Pos) /*!< FPCCR: CLRONRET bit Mask */
+
+#define FPU_FPCCR_CLRONRETS_Pos 27U /*!< FPCCR: CLRONRETS Position */
+#define FPU_FPCCR_CLRONRETS_Msk (1UL << FPU_FPCCR_CLRONRETS_Pos) /*!< FPCCR: CLRONRETS bit Mask */
+
+#define FPU_FPCCR_TS_Pos 26U /*!< FPCCR: TS Position */
+#define FPU_FPCCR_TS_Msk (1UL << FPU_FPCCR_TS_Pos) /*!< FPCCR: TS bit Mask */
+
+#define FPU_FPCCR_UFRDY_Pos 10U /*!< FPCCR: UFRDY Position */
+#define FPU_FPCCR_UFRDY_Msk (1UL << FPU_FPCCR_UFRDY_Pos) /*!< FPCCR: UFRDY bit Mask */
+
+#define FPU_FPCCR_SPLIMVIOL_Pos 9U /*!< FPCCR: SPLIMVIOL Position */
+#define FPU_FPCCR_SPLIMVIOL_Msk (1UL << FPU_FPCCR_SPLIMVIOL_Pos) /*!< FPCCR: SPLIMVIOL bit Mask */
+
+#define FPU_FPCCR_MONRDY_Pos 8U /*!< FPCCR: MONRDY Position */
+#define FPU_FPCCR_MONRDY_Msk (1UL << FPU_FPCCR_MONRDY_Pos) /*!< FPCCR: MONRDY bit Mask */
+
+#define FPU_FPCCR_SFRDY_Pos 7U /*!< FPCCR: SFRDY Position */
+#define FPU_FPCCR_SFRDY_Msk (1UL << FPU_FPCCR_SFRDY_Pos) /*!< FPCCR: SFRDY bit Mask */
+
+#define FPU_FPCCR_BFRDY_Pos 6U /*!< FPCCR: BFRDY Position */
+#define FPU_FPCCR_BFRDY_Msk (1UL << FPU_FPCCR_BFRDY_Pos) /*!< FPCCR: BFRDY bit Mask */
+
+#define FPU_FPCCR_MMRDY_Pos 5U /*!< FPCCR: MMRDY Position */
+#define FPU_FPCCR_MMRDY_Msk (1UL << FPU_FPCCR_MMRDY_Pos) /*!< FPCCR: MMRDY bit Mask */
+
+#define FPU_FPCCR_HFRDY_Pos 4U /*!< FPCCR: HFRDY Position */
+#define FPU_FPCCR_HFRDY_Msk (1UL << FPU_FPCCR_HFRDY_Pos) /*!< FPCCR: HFRDY bit Mask */
+
+#define FPU_FPCCR_THREAD_Pos 3U /*!< FPCCR: processor mode bit Position */
+#define FPU_FPCCR_THREAD_Msk (1UL << FPU_FPCCR_THREAD_Pos) /*!< FPCCR: processor mode active bit Mask */
+
+#define FPU_FPCCR_S_Pos 2U /*!< FPCCR: Security status of the FP context bit Position */
+#define FPU_FPCCR_S_Msk (1UL << FPU_FPCCR_S_Pos) /*!< FPCCR: Security status of the FP context bit Mask */
+
+#define FPU_FPCCR_USER_Pos 1U /*!< FPCCR: privilege level bit Position */
+#define FPU_FPCCR_USER_Msk (1UL << FPU_FPCCR_USER_Pos) /*!< FPCCR: privilege level bit Mask */
+
+#define FPU_FPCCR_LSPACT_Pos 0U /*!< FPCCR: Lazy state preservation active bit Position */
+#define FPU_FPCCR_LSPACT_Msk (1UL /*<< FPU_FPCCR_LSPACT_Pos*/) /*!< FPCCR: Lazy state preservation active bit Mask */
+
+/* Floating-Point Context Address Register Definitions */
+#define FPU_FPCAR_ADDRESS_Pos 3U /*!< FPCAR: ADDRESS bit Position */
+#define FPU_FPCAR_ADDRESS_Msk (0x1FFFFFFFUL << FPU_FPCAR_ADDRESS_Pos) /*!< FPCAR: ADDRESS bit Mask */
+
+/* Floating-Point Default Status Control Register Definitions */
+#define FPU_FPDSCR_AHP_Pos 26U /*!< FPDSCR: AHP bit Position */
+#define FPU_FPDSCR_AHP_Msk (1UL << FPU_FPDSCR_AHP_Pos) /*!< FPDSCR: AHP bit Mask */
+
+#define FPU_FPDSCR_DN_Pos 25U /*!< FPDSCR: DN bit Position */
+#define FPU_FPDSCR_DN_Msk (1UL << FPU_FPDSCR_DN_Pos) /*!< FPDSCR: DN bit Mask */
+
+#define FPU_FPDSCR_FZ_Pos 24U /*!< FPDSCR: FZ bit Position */
+#define FPU_FPDSCR_FZ_Msk (1UL << FPU_FPDSCR_FZ_Pos) /*!< FPDSCR: FZ bit Mask */
+
+#define FPU_FPDSCR_RMode_Pos 22U /*!< FPDSCR: RMode bit Position */
+#define FPU_FPDSCR_RMode_Msk (3UL << FPU_FPDSCR_RMode_Pos) /*!< FPDSCR: RMode bit Mask */
+
+/* Media and FP Feature Register 0 Definitions */
+#define FPU_MVFR0_FP_rounding_modes_Pos 28U /*!< MVFR0: FP rounding modes bits Position */
+#define FPU_MVFR0_FP_rounding_modes_Msk (0xFUL << FPU_MVFR0_FP_rounding_modes_Pos) /*!< MVFR0: FP rounding modes bits Mask */
+
+#define FPU_MVFR0_Short_vectors_Pos 24U /*!< MVFR0: Short vectors bits Position */
+#define FPU_MVFR0_Short_vectors_Msk (0xFUL << FPU_MVFR0_Short_vectors_Pos) /*!< MVFR0: Short vectors bits Mask */
+
+#define FPU_MVFR0_Square_root_Pos 20U /*!< MVFR0: Square root bits Position */
+#define FPU_MVFR0_Square_root_Msk (0xFUL << FPU_MVFR0_Square_root_Pos) /*!< MVFR0: Square root bits Mask */
+
+#define FPU_MVFR0_Divide_Pos 16U /*!< MVFR0: Divide bits Position */
+#define FPU_MVFR0_Divide_Msk (0xFUL << FPU_MVFR0_Divide_Pos) /*!< MVFR0: Divide bits Mask */
+
+#define FPU_MVFR0_FP_excep_trapping_Pos 12U /*!< MVFR0: FP exception trapping bits Position */
+#define FPU_MVFR0_FP_excep_trapping_Msk (0xFUL << FPU_MVFR0_FP_excep_trapping_Pos) /*!< MVFR0: FP exception trapping bits Mask */
+
+#define FPU_MVFR0_Double_precision_Pos 8U /*!< MVFR0: Double-precision bits Position */
+#define FPU_MVFR0_Double_precision_Msk (0xFUL << FPU_MVFR0_Double_precision_Pos) /*!< MVFR0: Double-precision bits Mask */
+
+#define FPU_MVFR0_Single_precision_Pos 4U /*!< MVFR0: Single-precision bits Position */
+#define FPU_MVFR0_Single_precision_Msk (0xFUL << FPU_MVFR0_Single_precision_Pos) /*!< MVFR0: Single-precision bits Mask */
+
+#define FPU_MVFR0_A_SIMD_registers_Pos 0U /*!< MVFR0: A_SIMD registers bits Position */
+#define FPU_MVFR0_A_SIMD_registers_Msk (0xFUL /*<< FPU_MVFR0_A_SIMD_registers_Pos*/) /*!< MVFR0: A_SIMD registers bits Mask */
+
+/* Media and FP Feature Register 1 Definitions */
+#define FPU_MVFR1_FP_fused_MAC_Pos 28U /*!< MVFR1: FP fused MAC bits Position */
+#define FPU_MVFR1_FP_fused_MAC_Msk (0xFUL << FPU_MVFR1_FP_fused_MAC_Pos) /*!< MVFR1: FP fused MAC bits Mask */
+
+#define FPU_MVFR1_FP_HPFP_Pos 24U /*!< MVFR1: FP HPFP bits Position */
+#define FPU_MVFR1_FP_HPFP_Msk (0xFUL << FPU_MVFR1_FP_HPFP_Pos) /*!< MVFR1: FP HPFP bits Mask */
+
+#define FPU_MVFR1_D_NaN_mode_Pos 4U /*!< MVFR1: D_NaN mode bits Position */
+#define FPU_MVFR1_D_NaN_mode_Msk (0xFUL << FPU_MVFR1_D_NaN_mode_Pos) /*!< MVFR1: D_NaN mode bits Mask */
+
+#define FPU_MVFR1_FtZ_mode_Pos 0U /*!< MVFR1: FtZ mode bits Position */
+#define FPU_MVFR1_FtZ_mode_Msk (0xFUL /*<< FPU_MVFR1_FtZ_mode_Pos*/) /*!< MVFR1: FtZ mode bits Mask */
+
+/*@} end of group CMSIS_FPU */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug)
+ \brief Type definitions for the Core Debug Registers
+ @{
+ */
+
+/**
+ \brief Structure type to access the Core Debug Register (CoreDebug).
+ */
+typedef struct
+{
+ __IOM uint32_t DHCSR; /*!< Offset: 0x000 (R/W) Debug Halting Control and Status Register */
+ __OM uint32_t DCRSR; /*!< Offset: 0x004 ( /W) Debug Core Register Selector Register */
+ __IOM uint32_t DCRDR; /*!< Offset: 0x008 (R/W) Debug Core Register Data Register */
+ __IOM uint32_t DEMCR; /*!< Offset: 0x00C (R/W) Debug Exception and Monitor Control Register */
+ uint32_t RESERVED4[1U];
+ __IOM uint32_t DAUTHCTRL; /*!< Offset: 0x014 (R/W) Debug Authentication Control Register */
+ __IOM uint32_t DSCSR; /*!< Offset: 0x018 (R/W) Debug Security Control and Status Register */
+} CoreDebug_Type;
+
+/* Debug Halting Control and Status Register Definitions */
+#define CoreDebug_DHCSR_DBGKEY_Pos 16U /*!< CoreDebug DHCSR: DBGKEY Position */
+#define CoreDebug_DHCSR_DBGKEY_Msk (0xFFFFUL << CoreDebug_DHCSR_DBGKEY_Pos) /*!< CoreDebug DHCSR: DBGKEY Mask */
+
+#define CoreDebug_DHCSR_S_RESTART_ST_Pos 26U /*!< CoreDebug DHCSR: S_RESTART_ST Position */
+#define CoreDebug_DHCSR_S_RESTART_ST_Msk (1UL << CoreDebug_DHCSR_S_RESTART_ST_Pos) /*!< CoreDebug DHCSR: S_RESTART_ST Mask */
+
+#define CoreDebug_DHCSR_S_RESET_ST_Pos 25U /*!< CoreDebug DHCSR: S_RESET_ST Position */
+#define CoreDebug_DHCSR_S_RESET_ST_Msk (1UL << CoreDebug_DHCSR_S_RESET_ST_Pos) /*!< CoreDebug DHCSR: S_RESET_ST Mask */
+
+#define CoreDebug_DHCSR_S_RETIRE_ST_Pos 24U /*!< CoreDebug DHCSR: S_RETIRE_ST Position */
+#define CoreDebug_DHCSR_S_RETIRE_ST_Msk (1UL << CoreDebug_DHCSR_S_RETIRE_ST_Pos) /*!< CoreDebug DHCSR: S_RETIRE_ST Mask */
+
+#define CoreDebug_DHCSR_S_LOCKUP_Pos 19U /*!< CoreDebug DHCSR: S_LOCKUP Position */
+#define CoreDebug_DHCSR_S_LOCKUP_Msk (1UL << CoreDebug_DHCSR_S_LOCKUP_Pos) /*!< CoreDebug DHCSR: S_LOCKUP Mask */
+
+#define CoreDebug_DHCSR_S_SLEEP_Pos 18U /*!< CoreDebug DHCSR: S_SLEEP Position */
+#define CoreDebug_DHCSR_S_SLEEP_Msk (1UL << CoreDebug_DHCSR_S_SLEEP_Pos) /*!< CoreDebug DHCSR: S_SLEEP Mask */
+
+#define CoreDebug_DHCSR_S_HALT_Pos 17U /*!< CoreDebug DHCSR: S_HALT Position */
+#define CoreDebug_DHCSR_S_HALT_Msk (1UL << CoreDebug_DHCSR_S_HALT_Pos) /*!< CoreDebug DHCSR: S_HALT Mask */
+
+#define CoreDebug_DHCSR_S_REGRDY_Pos 16U /*!< CoreDebug DHCSR: S_REGRDY Position */
+#define CoreDebug_DHCSR_S_REGRDY_Msk (1UL << CoreDebug_DHCSR_S_REGRDY_Pos) /*!< CoreDebug DHCSR: S_REGRDY Mask */
+
+#define CoreDebug_DHCSR_C_SNAPSTALL_Pos 5U /*!< CoreDebug DHCSR: C_SNAPSTALL Position */
+#define CoreDebug_DHCSR_C_SNAPSTALL_Msk (1UL << CoreDebug_DHCSR_C_SNAPSTALL_Pos) /*!< CoreDebug DHCSR: C_SNAPSTALL Mask */
+
+#define CoreDebug_DHCSR_C_MASKINTS_Pos 3U /*!< CoreDebug DHCSR: C_MASKINTS Position */
+#define CoreDebug_DHCSR_C_MASKINTS_Msk (1UL << CoreDebug_DHCSR_C_MASKINTS_Pos) /*!< CoreDebug DHCSR: C_MASKINTS Mask */
+
+#define CoreDebug_DHCSR_C_STEP_Pos 2U /*!< CoreDebug DHCSR: C_STEP Position */
+#define CoreDebug_DHCSR_C_STEP_Msk (1UL << CoreDebug_DHCSR_C_STEP_Pos) /*!< CoreDebug DHCSR: C_STEP Mask */
+
+#define CoreDebug_DHCSR_C_HALT_Pos 1U /*!< CoreDebug DHCSR: C_HALT Position */
+#define CoreDebug_DHCSR_C_HALT_Msk (1UL << CoreDebug_DHCSR_C_HALT_Pos) /*!< CoreDebug DHCSR: C_HALT Mask */
+
+#define CoreDebug_DHCSR_C_DEBUGEN_Pos 0U /*!< CoreDebug DHCSR: C_DEBUGEN Position */
+#define CoreDebug_DHCSR_C_DEBUGEN_Msk (1UL /*<< CoreDebug_DHCSR_C_DEBUGEN_Pos*/) /*!< CoreDebug DHCSR: C_DEBUGEN Mask */
+
+/* Debug Core Register Selector Register Definitions */
+#define CoreDebug_DCRSR_REGWnR_Pos 16U /*!< CoreDebug DCRSR: REGWnR Position */
+#define CoreDebug_DCRSR_REGWnR_Msk (1UL << CoreDebug_DCRSR_REGWnR_Pos) /*!< CoreDebug DCRSR: REGWnR Mask */
+
+#define CoreDebug_DCRSR_REGSEL_Pos 0U /*!< CoreDebug DCRSR: REGSEL Position */
+#define CoreDebug_DCRSR_REGSEL_Msk (0x1FUL /*<< CoreDebug_DCRSR_REGSEL_Pos*/) /*!< CoreDebug DCRSR: REGSEL Mask */
+
+/* Debug Exception and Monitor Control Register Definitions */
+#define CoreDebug_DEMCR_TRCENA_Pos 24U /*!< CoreDebug DEMCR: TRCENA Position */
+#define CoreDebug_DEMCR_TRCENA_Msk (1UL << CoreDebug_DEMCR_TRCENA_Pos) /*!< CoreDebug DEMCR: TRCENA Mask */
+
+#define CoreDebug_DEMCR_MON_REQ_Pos 19U /*!< CoreDebug DEMCR: MON_REQ Position */
+#define CoreDebug_DEMCR_MON_REQ_Msk (1UL << CoreDebug_DEMCR_MON_REQ_Pos) /*!< CoreDebug DEMCR: MON_REQ Mask */
+
+#define CoreDebug_DEMCR_MON_STEP_Pos 18U /*!< CoreDebug DEMCR: MON_STEP Position */
+#define CoreDebug_DEMCR_MON_STEP_Msk (1UL << CoreDebug_DEMCR_MON_STEP_Pos) /*!< CoreDebug DEMCR: MON_STEP Mask */
+
+#define CoreDebug_DEMCR_MON_PEND_Pos 17U /*!< CoreDebug DEMCR: MON_PEND Position */
+#define CoreDebug_DEMCR_MON_PEND_Msk (1UL << CoreDebug_DEMCR_MON_PEND_Pos) /*!< CoreDebug DEMCR: MON_PEND Mask */
+
+#define CoreDebug_DEMCR_MON_EN_Pos 16U /*!< CoreDebug DEMCR: MON_EN Position */
+#define CoreDebug_DEMCR_MON_EN_Msk (1UL << CoreDebug_DEMCR_MON_EN_Pos) /*!< CoreDebug DEMCR: MON_EN Mask */
+
+#define CoreDebug_DEMCR_VC_HARDERR_Pos 10U /*!< CoreDebug DEMCR: VC_HARDERR Position */
+#define CoreDebug_DEMCR_VC_HARDERR_Msk (1UL << CoreDebug_DEMCR_VC_HARDERR_Pos) /*!< CoreDebug DEMCR: VC_HARDERR Mask */
+
+#define CoreDebug_DEMCR_VC_INTERR_Pos 9U /*!< CoreDebug DEMCR: VC_INTERR Position */
+#define CoreDebug_DEMCR_VC_INTERR_Msk (1UL << CoreDebug_DEMCR_VC_INTERR_Pos) /*!< CoreDebug DEMCR: VC_INTERR Mask */
+
+#define CoreDebug_DEMCR_VC_BUSERR_Pos 8U /*!< CoreDebug DEMCR: VC_BUSERR Position */
+#define CoreDebug_DEMCR_VC_BUSERR_Msk (1UL << CoreDebug_DEMCR_VC_BUSERR_Pos) /*!< CoreDebug DEMCR: VC_BUSERR Mask */
+
+#define CoreDebug_DEMCR_VC_STATERR_Pos 7U /*!< CoreDebug DEMCR: VC_STATERR Position */
+#define CoreDebug_DEMCR_VC_STATERR_Msk (1UL << CoreDebug_DEMCR_VC_STATERR_Pos) /*!< CoreDebug DEMCR: VC_STATERR Mask */
+
+#define CoreDebug_DEMCR_VC_CHKERR_Pos 6U /*!< CoreDebug DEMCR: VC_CHKERR Position */
+#define CoreDebug_DEMCR_VC_CHKERR_Msk (1UL << CoreDebug_DEMCR_VC_CHKERR_Pos) /*!< CoreDebug DEMCR: VC_CHKERR Mask */
+
+#define CoreDebug_DEMCR_VC_NOCPERR_Pos 5U /*!< CoreDebug DEMCR: VC_NOCPERR Position */
+#define CoreDebug_DEMCR_VC_NOCPERR_Msk (1UL << CoreDebug_DEMCR_VC_NOCPERR_Pos) /*!< CoreDebug DEMCR: VC_NOCPERR Mask */
+
+#define CoreDebug_DEMCR_VC_MMERR_Pos 4U /*!< CoreDebug DEMCR: VC_MMERR Position */
+#define CoreDebug_DEMCR_VC_MMERR_Msk (1UL << CoreDebug_DEMCR_VC_MMERR_Pos) /*!< CoreDebug DEMCR: VC_MMERR Mask */
+
+#define CoreDebug_DEMCR_VC_CORERESET_Pos 0U /*!< CoreDebug DEMCR: VC_CORERESET Position */
+#define CoreDebug_DEMCR_VC_CORERESET_Msk (1UL /*<< CoreDebug_DEMCR_VC_CORERESET_Pos*/) /*!< CoreDebug DEMCR: VC_CORERESET Mask */
+
+/* Debug Authentication Control Register Definitions */
+#define CoreDebug_DAUTHCTRL_INTSPNIDEN_Pos 3U /*!< CoreDebug DAUTHCTRL: INTSPNIDEN, Position */
+#define CoreDebug_DAUTHCTRL_INTSPNIDEN_Msk (1UL << CoreDebug_DAUTHCTRL_INTSPNIDEN_Pos) /*!< CoreDebug DAUTHCTRL: INTSPNIDEN, Mask */
+
+#define CoreDebug_DAUTHCTRL_SPNIDENSEL_Pos 2U /*!< CoreDebug DAUTHCTRL: SPNIDENSEL Position */
+#define CoreDebug_DAUTHCTRL_SPNIDENSEL_Msk (1UL << CoreDebug_DAUTHCTRL_SPNIDENSEL_Pos) /*!< CoreDebug DAUTHCTRL: SPNIDENSEL Mask */
+
+#define CoreDebug_DAUTHCTRL_INTSPIDEN_Pos 1U /*!< CoreDebug DAUTHCTRL: INTSPIDEN Position */
+#define CoreDebug_DAUTHCTRL_INTSPIDEN_Msk (1UL << CoreDebug_DAUTHCTRL_INTSPIDEN_Pos) /*!< CoreDebug DAUTHCTRL: INTSPIDEN Mask */
+
+#define CoreDebug_DAUTHCTRL_SPIDENSEL_Pos 0U /*!< CoreDebug DAUTHCTRL: SPIDENSEL Position */
+#define CoreDebug_DAUTHCTRL_SPIDENSEL_Msk (1UL /*<< CoreDebug_DAUTHCTRL_SPIDENSEL_Pos*/) /*!< CoreDebug DAUTHCTRL: SPIDENSEL Mask */
+
+/* Debug Security Control and Status Register Definitions */
+#define CoreDebug_DSCSR_CDS_Pos 16U /*!< CoreDebug DSCSR: CDS Position */
+#define CoreDebug_DSCSR_CDS_Msk (1UL << CoreDebug_DSCSR_CDS_Pos) /*!< CoreDebug DSCSR: CDS Mask */
+
+#define CoreDebug_DSCSR_SBRSEL_Pos 1U /*!< CoreDebug DSCSR: SBRSEL Position */
+#define CoreDebug_DSCSR_SBRSEL_Msk (1UL << CoreDebug_DSCSR_SBRSEL_Pos) /*!< CoreDebug DSCSR: SBRSEL Mask */
+
+#define CoreDebug_DSCSR_SBRSELEN_Pos 0U /*!< CoreDebug DSCSR: SBRSELEN Position */
+#define CoreDebug_DSCSR_SBRSELEN_Msk (1UL /*<< CoreDebug_DSCSR_SBRSELEN_Pos*/) /*!< CoreDebug DSCSR: SBRSELEN Mask */
+
+/*@} end of group CMSIS_CoreDebug */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_core_bitfield Core register bit field macros
+ \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk).
+ @{
+ */
+
+/**
+ \brief Mask and shift a bit field value for use in a register bit range.
+ \param[in] field Name of the register bit field.
+ \param[in] value Value of the bit field. This parameter is interpreted as an uint32_t type.
+ \return Masked and shifted value.
+*/
+#define _VAL2FLD(field, value) (((uint32_t)(value) << field ## _Pos) & field ## _Msk)
+
+/**
+ \brief Mask and shift a register value to extract a bit filed value.
+ \param[in] field Name of the register bit field.
+ \param[in] value Value of register. This parameter is interpreted as an uint32_t type.
+ \return Masked and shifted bit field value.
+*/
+#define _FLD2VAL(field, value) (((uint32_t)(value) & field ## _Msk) >> field ## _Pos)
+
+/*@} end of group CMSIS_core_bitfield */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_core_base Core Definitions
+ \brief Definitions for base addresses, unions, and structures.
+ @{
+ */
+
+/* Memory mapping of Core Hardware */
+ #define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */
+ #define ITM_BASE (0xE0000000UL) /*!< ITM Base Address */
+ #define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */
+ #define TPI_BASE (0xE0040000UL) /*!< TPI Base Address */
+ #define CoreDebug_BASE (0xE000EDF0UL) /*!< Core Debug Base Address */
+ #define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */
+ #define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */
+ #define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */
+
+ #define SCnSCB ((SCnSCB_Type *) SCS_BASE ) /*!< System control Register not in SCB */
+ #define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */
+ #define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */
+ #define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */
+ #define ITM ((ITM_Type *) ITM_BASE ) /*!< ITM configuration struct */
+ #define DWT ((DWT_Type *) DWT_BASE ) /*!< DWT configuration struct */
+ #define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */
+ #define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE ) /*!< Core Debug configuration struct */
+
+ #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U)
+ #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */
+ #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */
+ #endif
+
+ #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
+ #define SAU_BASE (SCS_BASE + 0x0DD0UL) /*!< Security Attribution Unit */
+ #define SAU ((SAU_Type *) SAU_BASE ) /*!< Security Attribution Unit */
+ #endif
+
+ #define FPU_BASE (SCS_BASE + 0x0F30UL) /*!< Floating Point Unit */
+ #define FPU ((FPU_Type *) FPU_BASE ) /*!< Floating Point Unit */
+
+#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
+ #define SCS_BASE_NS (0xE002E000UL) /*!< System Control Space Base Address (non-secure address space) */
+ #define CoreDebug_BASE_NS (0xE002EDF0UL) /*!< Core Debug Base Address (non-secure address space) */
+ #define SysTick_BASE_NS (SCS_BASE_NS + 0x0010UL) /*!< SysTick Base Address (non-secure address space) */
+ #define NVIC_BASE_NS (SCS_BASE_NS + 0x0100UL) /*!< NVIC Base Address (non-secure address space) */
+ #define SCB_BASE_NS (SCS_BASE_NS + 0x0D00UL) /*!< System Control Block Base Address (non-secure address space) */
+
+ #define SCnSCB_NS ((SCnSCB_Type *) SCS_BASE_NS ) /*!< System control Register not in SCB(non-secure address space) */
+ #define SCB_NS ((SCB_Type *) SCB_BASE_NS ) /*!< SCB configuration struct (non-secure address space) */
+ #define SysTick_NS ((SysTick_Type *) SysTick_BASE_NS ) /*!< SysTick configuration struct (non-secure address space) */
+ #define NVIC_NS ((NVIC_Type *) NVIC_BASE_NS ) /*!< NVIC configuration struct (non-secure address space) */
+ #define CoreDebug_NS ((CoreDebug_Type *) CoreDebug_BASE_NS) /*!< Core Debug configuration struct (non-secure address space) */
+
+ #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U)
+ #define MPU_BASE_NS (SCS_BASE_NS + 0x0D90UL) /*!< Memory Protection Unit (non-secure address space) */
+ #define MPU_NS ((MPU_Type *) MPU_BASE_NS ) /*!< Memory Protection Unit (non-secure address space) */
+ #endif
+
+ #define FPU_BASE_NS (SCS_BASE_NS + 0x0F30UL) /*!< Floating Point Unit (non-secure address space) */
+ #define FPU_NS ((FPU_Type *) FPU_BASE_NS ) /*!< Floating Point Unit (non-secure address space) */
+
+#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */
+/*@} */
+
+
+
+/*******************************************************************************
+ * Hardware Abstraction Layer
+ Core Function Interface contains:
+ - Core NVIC Functions
+ - Core SysTick Functions
+ - Core Debug Functions
+ - Core Register Access Functions
+ ******************************************************************************/
+/**
+ \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference
+*/
+
+
+
+/* ########################## NVIC functions #################################### */
+/**
+ \ingroup CMSIS_Core_FunctionInterface
+ \defgroup CMSIS_Core_NVICFunctions NVIC Functions
+ \brief Functions that manage interrupts and exceptions via the NVIC.
+ @{
+ */
+
+#ifdef CMSIS_NVIC_VIRTUAL
+ #ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE
+ #define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h"
+ #endif
+ #include CMSIS_NVIC_VIRTUAL_HEADER_FILE
+#else
+ #define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping
+ #define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping
+ #define NVIC_EnableIRQ __NVIC_EnableIRQ
+ #define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ
+ #define NVIC_DisableIRQ __NVIC_DisableIRQ
+ #define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ
+ #define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ
+ #define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ
+ #define NVIC_GetActive __NVIC_GetActive
+ #define NVIC_SetPriority __NVIC_SetPriority
+ #define NVIC_GetPriority __NVIC_GetPriority
+ #define NVIC_SystemReset __NVIC_SystemReset
+#endif /* CMSIS_NVIC_VIRTUAL */
+
+#ifdef CMSIS_VECTAB_VIRTUAL
+ #ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE
+ #define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h"
+ #endif
+ #include CMSIS_VECTAB_VIRTUAL_HEADER_FILE
+#else
+ #define NVIC_SetVector __NVIC_SetVector
+ #define NVIC_GetVector __NVIC_GetVector
+#endif /* (CMSIS_VECTAB_VIRTUAL) */
+
+#define NVIC_USER_IRQ_OFFSET 16
+
+
+
+/**
+ \brief Set Priority Grouping
+ \details Sets the priority grouping field using the required unlock sequence.
+ The parameter PriorityGroup is assigned to the field SCB->AIRCR [10:8] PRIGROUP field.
+ Only values from 0..7 are used.
+ In case of a conflict between priority grouping and available
+ priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set.
+ \param [in] PriorityGroup Priority grouping field.
+ */
+__STATIC_INLINE void __NVIC_SetPriorityGrouping(uint32_t PriorityGroup)
+{
+ uint32_t reg_value;
+ uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */
+
+ reg_value = SCB->AIRCR; /* read old register configuration */
+ reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */
+ reg_value = (reg_value |
+ ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) |
+ (PriorityGroupTmp << 8U) ); /* Insert write key and priorty group */
+ SCB->AIRCR = reg_value;
+}
+
+
+/**
+ \brief Get Priority Grouping
+ \details Reads the priority grouping field from the NVIC Interrupt Controller.
+ \return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field).
+ */
+__STATIC_INLINE uint32_t __NVIC_GetPriorityGrouping(void)
+{
+ return ((uint32_t)((SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos));
+}
+
+
+/**
+ \brief Enable Interrupt
+ \details Enables a device specific interrupt in the NVIC interrupt controller.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Get Interrupt Enable status
+ \details Returns a device specific interrupt enable status from the NVIC interrupt controller.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 Interrupt is not enabled.
+ \return 1 Interrupt is enabled.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Disable Interrupt
+ \details Disables a device specific interrupt in the NVIC interrupt controller.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ICER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ __DSB();
+ __ISB();
+ }
+}
+
+
+/**
+ \brief Get Pending Interrupt
+ \details Reads the NVIC pending register and returns the pending bit for the specified device specific interrupt.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 Interrupt status is not pending.
+ \return 1 Interrupt status is pending.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Set Pending Interrupt
+ \details Sets the pending bit of a device specific interrupt in the NVIC pending register.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Clear Pending Interrupt
+ \details Clears the pending bit of a device specific interrupt in the NVIC pending register.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Get Active Interrupt
+ \details Reads the active register in the NVIC and returns the active bit for the device specific interrupt.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 Interrupt status is not active.
+ \return 1 Interrupt status is active.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t __NVIC_GetActive(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC->IABR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
+/**
+ \brief Get Interrupt Target State
+ \details Reads the interrupt target field in the NVIC and returns the interrupt target bit for the device specific interrupt.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 if interrupt is assigned to Secure
+ \return 1 if interrupt is assigned to Non Secure
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t NVIC_GetTargetState(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Set Interrupt Target State
+ \details Sets the interrupt target field in the NVIC and returns the interrupt target bit for the device specific interrupt.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 if interrupt is assigned to Secure
+ 1 if interrupt is assigned to Non Secure
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t NVIC_SetTargetState(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] |= ((uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)));
+ return((uint32_t)(((NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Clear Interrupt Target State
+ \details Clears the interrupt target field in the NVIC and returns the interrupt target bit for the device specific interrupt.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 if interrupt is assigned to Secure
+ 1 if interrupt is assigned to Non Secure
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t NVIC_ClearTargetState(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] &= ~((uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)));
+ return((uint32_t)(((NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */
+
+
+/**
+ \brief Set Interrupt Priority
+ \details Sets the priority of a device specific interrupt or a processor exception.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ \param [in] IRQn Interrupt number.
+ \param [in] priority Priority to set.
+ \note The priority cannot be set for every processor exception.
+ */
+__STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->IPR[((uint32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL);
+ }
+ else
+ {
+ SCB->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL);
+ }
+}
+
+
+/**
+ \brief Get Interrupt Priority
+ \details Reads the priority of a device specific interrupt or a processor exception.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ \param [in] IRQn Interrupt number.
+ \return Interrupt Priority.
+ Value is aligned automatically to the implemented priority bits of the microcontroller.
+ */
+__STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn)
+{
+
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return(((uint32_t)NVIC->IPR[((uint32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS)));
+ }
+ else
+ {
+ return(((uint32_t)SCB->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS)));
+ }
+}
+
+
+/**
+ \brief Encode Priority
+ \details Encodes the priority for an interrupt with the given priority group,
+ preemptive priority value, and subpriority value.
+ In case of a conflict between priority grouping and available
+ priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set.
+ \param [in] PriorityGroup Used priority group.
+ \param [in] PreemptPriority Preemptive priority value (starting from 0).
+ \param [in] SubPriority Subpriority value (starting from 0).
+ \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority().
+ */
+__STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority)
+{
+ uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */
+ uint32_t PreemptPriorityBits;
+ uint32_t SubPriorityBits;
+
+ PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp);
+ SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS));
+
+ return (
+ ((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) |
+ ((SubPriority & (uint32_t)((1UL << (SubPriorityBits )) - 1UL)))
+ );
+}
+
+
+/**
+ \brief Decode Priority
+ \details Decodes an interrupt priority value with a given priority group to
+ preemptive priority value and subpriority value.
+ In case of a conflict between priority grouping and available
+ priority bits (__NVIC_PRIO_BITS) the smallest possible priority group is set.
+ \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority().
+ \param [in] PriorityGroup Used priority group.
+ \param [out] pPreemptPriority Preemptive priority value (starting from 0).
+ \param [out] pSubPriority Subpriority value (starting from 0).
+ */
+__STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* const pPreemptPriority, uint32_t* const pSubPriority)
+{
+ uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */
+ uint32_t PreemptPriorityBits;
+ uint32_t SubPriorityBits;
+
+ PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp);
+ SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS));
+
+ *pPreemptPriority = (Priority >> SubPriorityBits) & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL);
+ *pSubPriority = (Priority ) & (uint32_t)((1UL << (SubPriorityBits )) - 1UL);
+}
+
+
+/**
+ \brief Set Interrupt Vector
+ \details Sets an interrupt vector in SRAM based interrupt vector table.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ VTOR must been relocated to SRAM before.
+ \param [in] IRQn Interrupt number
+ \param [in] vector Address of interrupt handler function
+ */
+__STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector)
+{
+ uint32_t *vectors = (uint32_t *)SCB->VTOR;
+ vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET] = vector;
+}
+
+
+/**
+ \brief Get Interrupt Vector
+ \details Reads an interrupt vector from interrupt vector table.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ \param [in] IRQn Interrupt number.
+ \return Address of interrupt handler function
+ */
+__STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn)
+{
+ uint32_t *vectors = (uint32_t *)SCB->VTOR;
+ return vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET];
+}
+
+
+/**
+ \brief System Reset
+ \details Initiates a system reset request to reset the MCU.
+ */
+__NO_RETURN __STATIC_INLINE void __NVIC_SystemReset(void)
+{
+ __DSB(); /* Ensure all outstanding memory accesses included
+ buffered write are completed before reset */
+ SCB->AIRCR = (uint32_t)((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) |
+ (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) |
+ SCB_AIRCR_SYSRESETREQ_Msk ); /* Keep priority group unchanged */
+ __DSB(); /* Ensure completion of memory access */
+
+ for(;;) /* wait until reset */
+ {
+ __NOP();
+ }
+}
+
+#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
+/**
+ \brief Set Priority Grouping (non-secure)
+ \details Sets the non-secure priority grouping field when in secure state using the required unlock sequence.
+ The parameter PriorityGroup is assigned to the field SCB->AIRCR [10:8] PRIGROUP field.
+ Only values from 0..7 are used.
+ In case of a conflict between priority grouping and available
+ priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set.
+ \param [in] PriorityGroup Priority grouping field.
+ */
+__STATIC_INLINE void TZ_NVIC_SetPriorityGrouping_NS(uint32_t PriorityGroup)
+{
+ uint32_t reg_value;
+ uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */
+
+ reg_value = SCB_NS->AIRCR; /* read old register configuration */
+ reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */
+ reg_value = (reg_value |
+ ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) |
+ (PriorityGroupTmp << 8U) ); /* Insert write key and priorty group */
+ SCB_NS->AIRCR = reg_value;
+}
+
+
+/**
+ \brief Get Priority Grouping (non-secure)
+ \details Reads the priority grouping field from the non-secure NVIC when in secure state.
+ \return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field).
+ */
+__STATIC_INLINE uint32_t TZ_NVIC_GetPriorityGrouping_NS(void)
+{
+ return ((uint32_t)((SCB_NS->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos));
+}
+
+
+/**
+ \brief Enable Interrupt (non-secure)
+ \details Enables a device specific interrupt in the non-secure NVIC interrupt controller when in secure state.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void TZ_NVIC_EnableIRQ_NS(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC_NS->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Get Interrupt Enable status (non-secure)
+ \details Returns a device specific interrupt enable status from the non-secure NVIC interrupt controller when in secure state.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 Interrupt is not enabled.
+ \return 1 Interrupt is enabled.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t TZ_NVIC_GetEnableIRQ_NS(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC_NS->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Disable Interrupt (non-secure)
+ \details Disables a device specific interrupt in the non-secure NVIC interrupt controller when in secure state.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void TZ_NVIC_DisableIRQ_NS(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC_NS->ICER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Get Pending Interrupt (non-secure)
+ \details Reads the NVIC pending register in the non-secure NVIC when in secure state and returns the pending bit for the specified device specific interrupt.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 Interrupt status is not pending.
+ \return 1 Interrupt status is pending.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t TZ_NVIC_GetPendingIRQ_NS(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC_NS->ISPR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Set Pending Interrupt (non-secure)
+ \details Sets the pending bit of a device specific interrupt in the non-secure NVIC pending register when in secure state.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void TZ_NVIC_SetPendingIRQ_NS(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC_NS->ISPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Clear Pending Interrupt (non-secure)
+ \details Clears the pending bit of a device specific interrupt in the non-secure NVIC pending register when in secure state.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void TZ_NVIC_ClearPendingIRQ_NS(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC_NS->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Get Active Interrupt (non-secure)
+ \details Reads the active register in non-secure NVIC when in secure state and returns the active bit for the device specific interrupt.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 Interrupt status is not active.
+ \return 1 Interrupt status is active.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t TZ_NVIC_GetActive_NS(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC_NS->IABR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Set Interrupt Priority (non-secure)
+ \details Sets the priority of a non-secure device specific interrupt or a non-secure processor exception when in secure state.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ \param [in] IRQn Interrupt number.
+ \param [in] priority Priority to set.
+ \note The priority cannot be set for every non-secure processor exception.
+ */
+__STATIC_INLINE void TZ_NVIC_SetPriority_NS(IRQn_Type IRQn, uint32_t priority)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC_NS->IPR[((uint32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL);
+ }
+ else
+ {
+ SCB_NS->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL);
+ }
+}
+
+
+/**
+ \brief Get Interrupt Priority (non-secure)
+ \details Reads the priority of a non-secure device specific interrupt or a non-secure processor exception when in secure state.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ \param [in] IRQn Interrupt number.
+ \return Interrupt Priority. Value is aligned automatically to the implemented priority bits of the microcontroller.
+ */
+__STATIC_INLINE uint32_t TZ_NVIC_GetPriority_NS(IRQn_Type IRQn)
+{
+
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return(((uint32_t)NVIC_NS->IPR[((uint32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS)));
+ }
+ else
+ {
+ return(((uint32_t)SCB_NS->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS)));
+ }
+}
+#endif /* defined (__ARM_FEATURE_CMSE) &&(__ARM_FEATURE_CMSE == 3U) */
+
+/*@} end of CMSIS_Core_NVICFunctions */
+
+/* ########################## MPU functions #################################### */
+
+#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U)
+
+#include "mpu_armv8.h"
+
+#endif
+
+/* ########################## FPU functions #################################### */
+/**
+ \ingroup CMSIS_Core_FunctionInterface
+ \defgroup CMSIS_Core_FpuFunctions FPU Functions
+ \brief Function that provides FPU type.
+ @{
+ */
+
+/**
+ \brief get FPU type
+ \details returns the FPU type
+ \returns
+ - \b 0: No FPU
+ - \b 1: Single precision FPU
+ - \b 2: Double + Single precision FPU
+ */
+__STATIC_INLINE uint32_t SCB_GetFPUType(void)
+{
+ uint32_t mvfr0;
+
+ mvfr0 = FPU->MVFR0;
+ if ((mvfr0 & (FPU_MVFR0_Single_precision_Msk | FPU_MVFR0_Double_precision_Msk)) == 0x220U)
+ {
+ return 2U; /* Double + Single precision FPU */
+ }
+ else if ((mvfr0 & (FPU_MVFR0_Single_precision_Msk | FPU_MVFR0_Double_precision_Msk)) == 0x020U)
+ {
+ return 1U; /* Single precision FPU */
+ }
+ else
+ {
+ return 0U; /* No FPU */
+ }
+}
+
+
+/*@} end of CMSIS_Core_FpuFunctions */
+
+
+
+/* ########################## SAU functions #################################### */
+/**
+ \ingroup CMSIS_Core_FunctionInterface
+ \defgroup CMSIS_Core_SAUFunctions SAU Functions
+ \brief Functions that configure the SAU.
+ @{
+ */
+
+#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
+
+/**
+ \brief Enable SAU
+ \details Enables the Security Attribution Unit (SAU).
+ */
+__STATIC_INLINE void TZ_SAU_Enable(void)
+{
+ SAU->CTRL |= (SAU_CTRL_ENABLE_Msk);
+}
+
+
+
+/**
+ \brief Disable SAU
+ \details Disables the Security Attribution Unit (SAU).
+ */
+__STATIC_INLINE void TZ_SAU_Disable(void)
+{
+ SAU->CTRL &= ~(SAU_CTRL_ENABLE_Msk);
+}
+
+#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */
+
+/*@} end of CMSIS_Core_SAUFunctions */
+
+
+
+
+/* ################################## SysTick function ############################################ */
+/**
+ \ingroup CMSIS_Core_FunctionInterface
+ \defgroup CMSIS_Core_SysTickFunctions SysTick Functions
+ \brief Functions that configure the System.
+ @{
+ */
+
+#if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U)
+
+/**
+ \brief System Tick Configuration
+ \details Initializes the System Timer and its interrupt, and starts the System Tick Timer.
+ Counter is in free running mode to generate periodic interrupts.
+ \param [in] ticks Number of ticks between two interrupts.
+ \return 0 Function succeeded.
+ \return 1 Function failed.
+ \note When the variable __Vendor_SysTickConfig is set to 1, then the
+ function SysTick_Config is not included. In this case, the file device.h
+ must contain a vendor-specific implementation of this function.
+ */
+__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)
+{
+ if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk)
+ {
+ return (1UL); /* Reload value impossible */
+ }
+
+ SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */
+ NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */
+ SysTick->VAL = 0UL; /* Load the SysTick Counter Value */
+ SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
+ SysTick_CTRL_TICKINT_Msk |
+ SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */
+ return (0UL); /* Function successful */
+}
+
+#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
+/**
+ \brief System Tick Configuration (non-secure)
+ \details Initializes the non-secure System Timer and its interrupt when in secure state, and starts the System Tick Timer.
+ Counter is in free running mode to generate periodic interrupts.
+ \param [in] ticks Number of ticks between two interrupts.
+ \return 0 Function succeeded.
+ \return 1 Function failed.
+ \note When the variable __Vendor_SysTickConfig is set to 1, then the
+ function TZ_SysTick_Config_NS is not included. In this case, the file device.h
+ must contain a vendor-specific implementation of this function.
+
+ */
+__STATIC_INLINE uint32_t TZ_SysTick_Config_NS(uint32_t ticks)
+{
+ if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk)
+ {
+ return (1UL); /* Reload value impossible */
+ }
+
+ SysTick_NS->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */
+ TZ_NVIC_SetPriority_NS (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */
+ SysTick_NS->VAL = 0UL; /* Load the SysTick Counter Value */
+ SysTick_NS->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
+ SysTick_CTRL_TICKINT_Msk |
+ SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */
+ return (0UL); /* Function successful */
+}
+#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */
+
+#endif
+
+/*@} end of CMSIS_Core_SysTickFunctions */
+
+
+
+/* ##################################### Debug In/Output function ########################################### */
+/**
+ \ingroup CMSIS_Core_FunctionInterface
+ \defgroup CMSIS_core_DebugFunctions ITM Functions
+ \brief Functions that access the ITM debug interface.
+ @{
+ */
+
+extern volatile int32_t ITM_RxBuffer; /*!< External variable to receive characters. */
+#define ITM_RXBUFFER_EMPTY ((int32_t)0x5AA55AA5U) /*!< Value identifying \ref ITM_RxBuffer is ready for next character. */
+
+
+/**
+ \brief ITM Send Character
+ \details Transmits a character via the ITM channel 0, and
+ \li Just returns when no debugger is connected that has booked the output.
+ \li Is blocking when a debugger is connected, but the previous character sent has not been transmitted.
+ \param [in] ch Character to transmit.
+ \returns Character to transmit.
+ */
+__STATIC_INLINE uint32_t ITM_SendChar (uint32_t ch)
+{
+ if (((ITM->TCR & ITM_TCR_ITMENA_Msk) != 0UL) && /* ITM enabled */
+ ((ITM->TER & 1UL ) != 0UL) ) /* ITM Port #0 enabled */
+ {
+ while (ITM->PORT[0U].u32 == 0UL)
+ {
+ __NOP();
+ }
+ ITM->PORT[0U].u8 = (uint8_t)ch;
+ }
+ return (ch);
+}
+
+
+/**
+ \brief ITM Receive Character
+ \details Inputs a character via the external variable \ref ITM_RxBuffer.
+ \return Received character.
+ \return -1 No character pending.
+ */
+__STATIC_INLINE int32_t ITM_ReceiveChar (void)
+{
+ int32_t ch = -1; /* no character available */
+
+ if (ITM_RxBuffer != ITM_RXBUFFER_EMPTY)
+ {
+ ch = ITM_RxBuffer;
+ ITM_RxBuffer = ITM_RXBUFFER_EMPTY; /* ready for next character */
+ }
+
+ return (ch);
+}
+
+
+/**
+ \brief ITM Check Character
+ \details Checks whether a character is pending for reading in the variable \ref ITM_RxBuffer.
+ \return 0 No character available.
+ \return 1 Character available.
+ */
+__STATIC_INLINE int32_t ITM_CheckChar (void)
+{
+
+ if (ITM_RxBuffer == ITM_RXBUFFER_EMPTY)
+ {
+ return (0); /* no character available */
+ }
+ else
+ {
+ return (1); /* character available */
+ }
+}
+
+/*@} end of CMSIS_core_DebugFunctions */
+
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CORE_ARMV81MML_H_DEPENDANT */
+
+#endif /* __CMSIS_GENERIC */
diff --git a/lib/cmsis/inc/core_armv8mbl.h b/lib/cmsis/inc/core_armv8mbl.h
new file mode 100644
index 0000000000..57d9f663fd
--- /dev/null
+++ b/lib/cmsis/inc/core_armv8mbl.h
@@ -0,0 +1,1918 @@
+/**************************************************************************//**
+ * @file core_armv8mbl.h
+ * @brief CMSIS Armv8-M Baseline Core Peripheral Access Layer Header File
+ * @version V5.0.8
+ * @date 12. November 2018
+ ******************************************************************************/
+/*
+ * Copyright (c) 2009-2018 Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#if defined ( __ICCARM__ )
+ #pragma system_include /* treat file as system include file for MISRA check */
+#elif defined (__clang__)
+ #pragma clang system_header /* treat file as system include file */
+#endif
+
+#ifndef __CORE_ARMV8MBL_H_GENERIC
+#define __CORE_ARMV8MBL_H_GENERIC
+
+#include
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/**
+ \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions
+ CMSIS violates the following MISRA-C:2004 rules:
+
+ \li Required Rule 8.5, object/function definition in header file.
+ Function definitions in header files are used to allow 'inlining'.
+
+ \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
+ Unions are used for effective representation of core registers.
+
+ \li Advisory Rule 19.7, Function-like macro defined.
+ Function-like macros are used to allow more efficient code.
+ */
+
+
+/*******************************************************************************
+ * CMSIS definitions
+ ******************************************************************************/
+/**
+ \ingroup Cortex_ARMv8MBL
+ @{
+ */
+
+#include "cmsis_version.h"
+
+/* CMSIS definitions */
+#define __ARMv8MBL_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */
+#define __ARMv8MBL_CMSIS_VERSION_SUB (__CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */
+#define __ARMv8MBL_CMSIS_VERSION ((__ARMv8MBL_CMSIS_VERSION_MAIN << 16U) | \
+ __ARMv8MBL_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */
+
+#define __CORTEX_M ( 2U) /*!< Cortex-M Core */
+
+/** __FPU_USED indicates whether an FPU is used or not.
+ This core does not support an FPU at all
+*/
+#define __FPU_USED 0U
+
+#if defined ( __CC_ARM )
+ #if defined __TARGET_FPU_VFP
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #endif
+
+#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
+ #if defined __ARM_FP
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #endif
+
+#elif defined ( __GNUC__ )
+ #if defined (__VFP_FP__) && !defined(__SOFTFP__)
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #endif
+
+#elif defined ( __ICCARM__ )
+ #if defined __ARMVFP__
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #endif
+
+#elif defined ( __TI_ARM__ )
+ #if defined __TI_VFP_SUPPORT__
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #endif
+
+#elif defined ( __TASKING__ )
+ #if defined __FPU_VFP__
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #endif
+
+#elif defined ( __CSMC__ )
+ #if ( __CSMC__ & 0x400U)
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #endif
+
+#endif
+
+#include "cmsis_compiler.h" /* CMSIS compiler specific defines */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CORE_ARMV8MBL_H_GENERIC */
+
+#ifndef __CMSIS_GENERIC
+
+#ifndef __CORE_ARMV8MBL_H_DEPENDANT
+#define __CORE_ARMV8MBL_H_DEPENDANT
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/* check device defines and use defaults */
+#if defined __CHECK_DEVICE_DEFINES
+ #ifndef __ARMv8MBL_REV
+ #define __ARMv8MBL_REV 0x0000U
+ #warning "__ARMv8MBL_REV not defined in device header file; using default!"
+ #endif
+
+ #ifndef __FPU_PRESENT
+ #define __FPU_PRESENT 0U
+ #warning "__FPU_PRESENT not defined in device header file; using default!"
+ #endif
+
+ #ifndef __MPU_PRESENT
+ #define __MPU_PRESENT 0U
+ #warning "__MPU_PRESENT not defined in device header file; using default!"
+ #endif
+
+ #ifndef __SAUREGION_PRESENT
+ #define __SAUREGION_PRESENT 0U
+ #warning "__SAUREGION_PRESENT not defined in device header file; using default!"
+ #endif
+
+ #ifndef __VTOR_PRESENT
+ #define __VTOR_PRESENT 0U
+ #warning "__VTOR_PRESENT not defined in device header file; using default!"
+ #endif
+
+ #ifndef __NVIC_PRIO_BITS
+ #define __NVIC_PRIO_BITS 2U
+ #warning "__NVIC_PRIO_BITS not defined in device header file; using default!"
+ #endif
+
+ #ifndef __Vendor_SysTickConfig
+ #define __Vendor_SysTickConfig 0U
+ #warning "__Vendor_SysTickConfig not defined in device header file; using default!"
+ #endif
+
+ #ifndef __ETM_PRESENT
+ #define __ETM_PRESENT 0U
+ #warning "__ETM_PRESENT not defined in device header file; using default!"
+ #endif
+
+ #ifndef __MTB_PRESENT
+ #define __MTB_PRESENT 0U
+ #warning "__MTB_PRESENT not defined in device header file; using default!"
+ #endif
+
+#endif
+
+/* IO definitions (access restrictions to peripheral registers) */
+/**
+ \defgroup CMSIS_glob_defs CMSIS Global Defines
+
+ IO Type Qualifiers are used
+ \li to specify the access to peripheral variables.
+ \li for automatic generation of peripheral register debug information.
+*/
+#ifdef __cplusplus
+ #define __I volatile /*!< Defines 'read only' permissions */
+#else
+ #define __I volatile const /*!< Defines 'read only' permissions */
+#endif
+#define __O volatile /*!< Defines 'write only' permissions */
+#define __IO volatile /*!< Defines 'read / write' permissions */
+
+/* following defines should be used for structure members */
+#define __IM volatile const /*! Defines 'read only' structure member permissions */
+#define __OM volatile /*! Defines 'write only' structure member permissions */
+#define __IOM volatile /*! Defines 'read / write' structure member permissions */
+
+/*@} end of group ARMv8MBL */
+
+
+
+/*******************************************************************************
+ * Register Abstraction
+ Core Register contain:
+ - Core Register
+ - Core NVIC Register
+ - Core SCB Register
+ - Core SysTick Register
+ - Core Debug Register
+ - Core MPU Register
+ - Core SAU Register
+ ******************************************************************************/
+/**
+ \defgroup CMSIS_core_register Defines and Type Definitions
+ \brief Type definitions and defines for Cortex-M processor based devices.
+*/
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_CORE Status and Control Registers
+ \brief Core Register type definitions.
+ @{
+ */
+
+/**
+ \brief Union type to access the Application Program Status Register (APSR).
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t _reserved0:28; /*!< bit: 0..27 Reserved */
+ uint32_t V:1; /*!< bit: 28 Overflow condition code flag */
+ uint32_t C:1; /*!< bit: 29 Carry condition code flag */
+ uint32_t Z:1; /*!< bit: 30 Zero condition code flag */
+ uint32_t N:1; /*!< bit: 31 Negative condition code flag */
+ } b; /*!< Structure used for bit access */
+ uint32_t w; /*!< Type used for word access */
+} APSR_Type;
+
+/* APSR Register Definitions */
+#define APSR_N_Pos 31U /*!< APSR: N Position */
+#define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */
+
+#define APSR_Z_Pos 30U /*!< APSR: Z Position */
+#define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */
+
+#define APSR_C_Pos 29U /*!< APSR: C Position */
+#define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */
+
+#define APSR_V_Pos 28U /*!< APSR: V Position */
+#define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */
+
+
+/**
+ \brief Union type to access the Interrupt Program Status Register (IPSR).
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */
+ uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */
+ } b; /*!< Structure used for bit access */
+ uint32_t w; /*!< Type used for word access */
+} IPSR_Type;
+
+/* IPSR Register Definitions */
+#define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */
+#define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */
+
+
+/**
+ \brief Union type to access the Special-Purpose Program Status Registers (xPSR).
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */
+ uint32_t _reserved0:15; /*!< bit: 9..23 Reserved */
+ uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */
+ uint32_t _reserved1:3; /*!< bit: 25..27 Reserved */
+ uint32_t V:1; /*!< bit: 28 Overflow condition code flag */
+ uint32_t C:1; /*!< bit: 29 Carry condition code flag */
+ uint32_t Z:1; /*!< bit: 30 Zero condition code flag */
+ uint32_t N:1; /*!< bit: 31 Negative condition code flag */
+ } b; /*!< Structure used for bit access */
+ uint32_t w; /*!< Type used for word access */
+} xPSR_Type;
+
+/* xPSR Register Definitions */
+#define xPSR_N_Pos 31U /*!< xPSR: N Position */
+#define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */
+
+#define xPSR_Z_Pos 30U /*!< xPSR: Z Position */
+#define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */
+
+#define xPSR_C_Pos 29U /*!< xPSR: C Position */
+#define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */
+
+#define xPSR_V_Pos 28U /*!< xPSR: V Position */
+#define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */
+
+#define xPSR_T_Pos 24U /*!< xPSR: T Position */
+#define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */
+
+#define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */
+#define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */
+
+
+/**
+ \brief Union type to access the Control Registers (CONTROL).
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */
+ uint32_t SPSEL:1; /*!< bit: 1 Stack-pointer select */
+ uint32_t _reserved1:30; /*!< bit: 2..31 Reserved */
+ } b; /*!< Structure used for bit access */
+ uint32_t w; /*!< Type used for word access */
+} CONTROL_Type;
+
+/* CONTROL Register Definitions */
+#define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */
+#define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */
+
+#define CONTROL_nPRIV_Pos 0U /*!< CONTROL: nPRIV Position */
+#define CONTROL_nPRIV_Msk (1UL /*<< CONTROL_nPRIV_Pos*/) /*!< CONTROL: nPRIV Mask */
+
+/*@} end of group CMSIS_CORE */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC)
+ \brief Type definitions for the NVIC Registers
+ @{
+ */
+
+/**
+ \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC).
+ */
+typedef struct
+{
+ __IOM uint32_t ISER[16U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */
+ uint32_t RESERVED0[16U];
+ __IOM uint32_t ICER[16U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */
+ uint32_t RSERVED1[16U];
+ __IOM uint32_t ISPR[16U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */
+ uint32_t RESERVED2[16U];
+ __IOM uint32_t ICPR[16U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */
+ uint32_t RESERVED3[16U];
+ __IOM uint32_t IABR[16U]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */
+ uint32_t RESERVED4[16U];
+ __IOM uint32_t ITNS[16U]; /*!< Offset: 0x280 (R/W) Interrupt Non-Secure State Register */
+ uint32_t RESERVED5[16U];
+ __IOM uint32_t IPR[124U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register */
+} NVIC_Type;
+
+/*@} end of group CMSIS_NVIC */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_SCB System Control Block (SCB)
+ \brief Type definitions for the System Control Block Registers
+ @{
+ */
+
+/**
+ \brief Structure type to access the System Control Block (SCB).
+ */
+typedef struct
+{
+ __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */
+ __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */
+#if defined (__VTOR_PRESENT) && (__VTOR_PRESENT == 1U)
+ __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */
+#else
+ uint32_t RESERVED0;
+#endif
+ __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */
+ __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */
+ __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */
+ uint32_t RESERVED1;
+ __IOM uint32_t SHPR[2U]; /*!< Offset: 0x01C (R/W) System Handlers Priority Registers. [0] is RESERVED */
+ __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */
+} SCB_Type;
+
+/* SCB CPUID Register Definitions */
+#define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */
+#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */
+
+#define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */
+#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */
+
+#define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */
+#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */
+
+#define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */
+#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */
+
+#define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */
+#define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */
+
+/* SCB Interrupt Control State Register Definitions */
+#define SCB_ICSR_PENDNMISET_Pos 31U /*!< SCB ICSR: PENDNMISET Position */
+#define SCB_ICSR_PENDNMISET_Msk (1UL << SCB_ICSR_PENDNMISET_Pos) /*!< SCB ICSR: PENDNMISET Mask */
+
+#define SCB_ICSR_NMIPENDSET_Pos SCB_ICSR_PENDNMISET_Pos /*!< SCB ICSR: NMIPENDSET Position, backward compatibility */
+#define SCB_ICSR_NMIPENDSET_Msk SCB_ICSR_PENDNMISET_Msk /*!< SCB ICSR: NMIPENDSET Mask, backward compatibility */
+
+#define SCB_ICSR_PENDNMICLR_Pos 30U /*!< SCB ICSR: PENDNMICLR Position */
+#define SCB_ICSR_PENDNMICLR_Msk (1UL << SCB_ICSR_PENDNMICLR_Pos) /*!< SCB ICSR: PENDNMICLR Mask */
+
+#define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */
+#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */
+
+#define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */
+#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */
+
+#define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */
+#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */
+
+#define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */
+#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */
+
+#define SCB_ICSR_STTNS_Pos 24U /*!< SCB ICSR: STTNS Position (Security Extension) */
+#define SCB_ICSR_STTNS_Msk (1UL << SCB_ICSR_STTNS_Pos) /*!< SCB ICSR: STTNS Mask (Security Extension) */
+
+#define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */
+#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */
+
+#define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */
+#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */
+
+#define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */
+#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */
+
+#define SCB_ICSR_RETTOBASE_Pos 11U /*!< SCB ICSR: RETTOBASE Position */
+#define SCB_ICSR_RETTOBASE_Msk (1UL << SCB_ICSR_RETTOBASE_Pos) /*!< SCB ICSR: RETTOBASE Mask */
+
+#define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */
+#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */
+
+#if defined (__VTOR_PRESENT) && (__VTOR_PRESENT == 1U)
+/* SCB Vector Table Offset Register Definitions */
+#define SCB_VTOR_TBLOFF_Pos 7U /*!< SCB VTOR: TBLOFF Position */
+#define SCB_VTOR_TBLOFF_Msk (0x1FFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */
+#endif
+
+/* SCB Application Interrupt and Reset Control Register Definitions */
+#define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */
+#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */
+
+#define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */
+#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */
+
+#define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */
+#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */
+
+#define SCB_AIRCR_PRIS_Pos 14U /*!< SCB AIRCR: PRIS Position */
+#define SCB_AIRCR_PRIS_Msk (1UL << SCB_AIRCR_PRIS_Pos) /*!< SCB AIRCR: PRIS Mask */
+
+#define SCB_AIRCR_BFHFNMINS_Pos 13U /*!< SCB AIRCR: BFHFNMINS Position */
+#define SCB_AIRCR_BFHFNMINS_Msk (1UL << SCB_AIRCR_BFHFNMINS_Pos) /*!< SCB AIRCR: BFHFNMINS Mask */
+
+#define SCB_AIRCR_SYSRESETREQS_Pos 3U /*!< SCB AIRCR: SYSRESETREQS Position */
+#define SCB_AIRCR_SYSRESETREQS_Msk (1UL << SCB_AIRCR_SYSRESETREQS_Pos) /*!< SCB AIRCR: SYSRESETREQS Mask */
+
+#define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */
+#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */
+
+#define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */
+#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */
+
+/* SCB System Control Register Definitions */
+#define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */
+#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */
+
+#define SCB_SCR_SLEEPDEEPS_Pos 3U /*!< SCB SCR: SLEEPDEEPS Position */
+#define SCB_SCR_SLEEPDEEPS_Msk (1UL << SCB_SCR_SLEEPDEEPS_Pos) /*!< SCB SCR: SLEEPDEEPS Mask */
+
+#define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */
+#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */
+
+#define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */
+#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */
+
+/* SCB Configuration Control Register Definitions */
+#define SCB_CCR_BP_Pos 18U /*!< SCB CCR: BP Position */
+#define SCB_CCR_BP_Msk (1UL << SCB_CCR_BP_Pos) /*!< SCB CCR: BP Mask */
+
+#define SCB_CCR_IC_Pos 17U /*!< SCB CCR: IC Position */
+#define SCB_CCR_IC_Msk (1UL << SCB_CCR_IC_Pos) /*!< SCB CCR: IC Mask */
+
+#define SCB_CCR_DC_Pos 16U /*!< SCB CCR: DC Position */
+#define SCB_CCR_DC_Msk (1UL << SCB_CCR_DC_Pos) /*!< SCB CCR: DC Mask */
+
+#define SCB_CCR_STKOFHFNMIGN_Pos 10U /*!< SCB CCR: STKOFHFNMIGN Position */
+#define SCB_CCR_STKOFHFNMIGN_Msk (1UL << SCB_CCR_STKOFHFNMIGN_Pos) /*!< SCB CCR: STKOFHFNMIGN Mask */
+
+#define SCB_CCR_BFHFNMIGN_Pos 8U /*!< SCB CCR: BFHFNMIGN Position */
+#define SCB_CCR_BFHFNMIGN_Msk (1UL << SCB_CCR_BFHFNMIGN_Pos) /*!< SCB CCR: BFHFNMIGN Mask */
+
+#define SCB_CCR_DIV_0_TRP_Pos 4U /*!< SCB CCR: DIV_0_TRP Position */
+#define SCB_CCR_DIV_0_TRP_Msk (1UL << SCB_CCR_DIV_0_TRP_Pos) /*!< SCB CCR: DIV_0_TRP Mask */
+
+#define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */
+#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */
+
+#define SCB_CCR_USERSETMPEND_Pos 1U /*!< SCB CCR: USERSETMPEND Position */
+#define SCB_CCR_USERSETMPEND_Msk (1UL << SCB_CCR_USERSETMPEND_Pos) /*!< SCB CCR: USERSETMPEND Mask */
+
+/* SCB System Handler Control and State Register Definitions */
+#define SCB_SHCSR_HARDFAULTPENDED_Pos 21U /*!< SCB SHCSR: HARDFAULTPENDED Position */
+#define SCB_SHCSR_HARDFAULTPENDED_Msk (1UL << SCB_SHCSR_HARDFAULTPENDED_Pos) /*!< SCB SHCSR: HARDFAULTPENDED Mask */
+
+#define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */
+#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */
+
+#define SCB_SHCSR_SYSTICKACT_Pos 11U /*!< SCB SHCSR: SYSTICKACT Position */
+#define SCB_SHCSR_SYSTICKACT_Msk (1UL << SCB_SHCSR_SYSTICKACT_Pos) /*!< SCB SHCSR: SYSTICKACT Mask */
+
+#define SCB_SHCSR_PENDSVACT_Pos 10U /*!< SCB SHCSR: PENDSVACT Position */
+#define SCB_SHCSR_PENDSVACT_Msk (1UL << SCB_SHCSR_PENDSVACT_Pos) /*!< SCB SHCSR: PENDSVACT Mask */
+
+#define SCB_SHCSR_SVCALLACT_Pos 7U /*!< SCB SHCSR: SVCALLACT Position */
+#define SCB_SHCSR_SVCALLACT_Msk (1UL << SCB_SHCSR_SVCALLACT_Pos) /*!< SCB SHCSR: SVCALLACT Mask */
+
+#define SCB_SHCSR_NMIACT_Pos 5U /*!< SCB SHCSR: NMIACT Position */
+#define SCB_SHCSR_NMIACT_Msk (1UL << SCB_SHCSR_NMIACT_Pos) /*!< SCB SHCSR: NMIACT Mask */
+
+#define SCB_SHCSR_HARDFAULTACT_Pos 2U /*!< SCB SHCSR: HARDFAULTACT Position */
+#define SCB_SHCSR_HARDFAULTACT_Msk (1UL << SCB_SHCSR_HARDFAULTACT_Pos) /*!< SCB SHCSR: HARDFAULTACT Mask */
+
+/*@} end of group CMSIS_SCB */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_SysTick System Tick Timer (SysTick)
+ \brief Type definitions for the System Timer Registers.
+ @{
+ */
+
+/**
+ \brief Structure type to access the System Timer (SysTick).
+ */
+typedef struct
+{
+ __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */
+ __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */
+ __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */
+ __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */
+} SysTick_Type;
+
+/* SysTick Control / Status Register Definitions */
+#define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */
+#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */
+
+#define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */
+#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */
+
+#define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */
+#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */
+
+#define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */
+#define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */
+
+/* SysTick Reload Register Definitions */
+#define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */
+#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */
+
+/* SysTick Current Register Definitions */
+#define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */
+#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */
+
+/* SysTick Calibration Register Definitions */
+#define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */
+#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */
+
+#define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */
+#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */
+
+#define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */
+#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */
+
+/*@} end of group CMSIS_SysTick */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_DWT Data Watchpoint and Trace (DWT)
+ \brief Type definitions for the Data Watchpoint and Trace (DWT)
+ @{
+ */
+
+/**
+ \brief Structure type to access the Data Watchpoint and Trace Register (DWT).
+ */
+typedef struct
+{
+ __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) Control Register */
+ uint32_t RESERVED0[6U];
+ __IM uint32_t PCSR; /*!< Offset: 0x01C (R/ ) Program Counter Sample Register */
+ __IOM uint32_t COMP0; /*!< Offset: 0x020 (R/W) Comparator Register 0 */
+ uint32_t RESERVED1[1U];
+ __IOM uint32_t FUNCTION0; /*!< Offset: 0x028 (R/W) Function Register 0 */
+ uint32_t RESERVED2[1U];
+ __IOM uint32_t COMP1; /*!< Offset: 0x030 (R/W) Comparator Register 1 */
+ uint32_t RESERVED3[1U];
+ __IOM uint32_t FUNCTION1; /*!< Offset: 0x038 (R/W) Function Register 1 */
+ uint32_t RESERVED4[1U];
+ __IOM uint32_t COMP2; /*!< Offset: 0x040 (R/W) Comparator Register 2 */
+ uint32_t RESERVED5[1U];
+ __IOM uint32_t FUNCTION2; /*!< Offset: 0x048 (R/W) Function Register 2 */
+ uint32_t RESERVED6[1U];
+ __IOM uint32_t COMP3; /*!< Offset: 0x050 (R/W) Comparator Register 3 */
+ uint32_t RESERVED7[1U];
+ __IOM uint32_t FUNCTION3; /*!< Offset: 0x058 (R/W) Function Register 3 */
+ uint32_t RESERVED8[1U];
+ __IOM uint32_t COMP4; /*!< Offset: 0x060 (R/W) Comparator Register 4 */
+ uint32_t RESERVED9[1U];
+ __IOM uint32_t FUNCTION4; /*!< Offset: 0x068 (R/W) Function Register 4 */
+ uint32_t RESERVED10[1U];
+ __IOM uint32_t COMP5; /*!< Offset: 0x070 (R/W) Comparator Register 5 */
+ uint32_t RESERVED11[1U];
+ __IOM uint32_t FUNCTION5; /*!< Offset: 0x078 (R/W) Function Register 5 */
+ uint32_t RESERVED12[1U];
+ __IOM uint32_t COMP6; /*!< Offset: 0x080 (R/W) Comparator Register 6 */
+ uint32_t RESERVED13[1U];
+ __IOM uint32_t FUNCTION6; /*!< Offset: 0x088 (R/W) Function Register 6 */
+ uint32_t RESERVED14[1U];
+ __IOM uint32_t COMP7; /*!< Offset: 0x090 (R/W) Comparator Register 7 */
+ uint32_t RESERVED15[1U];
+ __IOM uint32_t FUNCTION7; /*!< Offset: 0x098 (R/W) Function Register 7 */
+ uint32_t RESERVED16[1U];
+ __IOM uint32_t COMP8; /*!< Offset: 0x0A0 (R/W) Comparator Register 8 */
+ uint32_t RESERVED17[1U];
+ __IOM uint32_t FUNCTION8; /*!< Offset: 0x0A8 (R/W) Function Register 8 */
+ uint32_t RESERVED18[1U];
+ __IOM uint32_t COMP9; /*!< Offset: 0x0B0 (R/W) Comparator Register 9 */
+ uint32_t RESERVED19[1U];
+ __IOM uint32_t FUNCTION9; /*!< Offset: 0x0B8 (R/W) Function Register 9 */
+ uint32_t RESERVED20[1U];
+ __IOM uint32_t COMP10; /*!< Offset: 0x0C0 (R/W) Comparator Register 10 */
+ uint32_t RESERVED21[1U];
+ __IOM uint32_t FUNCTION10; /*!< Offset: 0x0C8 (R/W) Function Register 10 */
+ uint32_t RESERVED22[1U];
+ __IOM uint32_t COMP11; /*!< Offset: 0x0D0 (R/W) Comparator Register 11 */
+ uint32_t RESERVED23[1U];
+ __IOM uint32_t FUNCTION11; /*!< Offset: 0x0D8 (R/W) Function Register 11 */
+ uint32_t RESERVED24[1U];
+ __IOM uint32_t COMP12; /*!< Offset: 0x0E0 (R/W) Comparator Register 12 */
+ uint32_t RESERVED25[1U];
+ __IOM uint32_t FUNCTION12; /*!< Offset: 0x0E8 (R/W) Function Register 12 */
+ uint32_t RESERVED26[1U];
+ __IOM uint32_t COMP13; /*!< Offset: 0x0F0 (R/W) Comparator Register 13 */
+ uint32_t RESERVED27[1U];
+ __IOM uint32_t FUNCTION13; /*!< Offset: 0x0F8 (R/W) Function Register 13 */
+ uint32_t RESERVED28[1U];
+ __IOM uint32_t COMP14; /*!< Offset: 0x100 (R/W) Comparator Register 14 */
+ uint32_t RESERVED29[1U];
+ __IOM uint32_t FUNCTION14; /*!< Offset: 0x108 (R/W) Function Register 14 */
+ uint32_t RESERVED30[1U];
+ __IOM uint32_t COMP15; /*!< Offset: 0x110 (R/W) Comparator Register 15 */
+ uint32_t RESERVED31[1U];
+ __IOM uint32_t FUNCTION15; /*!< Offset: 0x118 (R/W) Function Register 15 */
+} DWT_Type;
+
+/* DWT Control Register Definitions */
+#define DWT_CTRL_NUMCOMP_Pos 28U /*!< DWT CTRL: NUMCOMP Position */
+#define DWT_CTRL_NUMCOMP_Msk (0xFUL << DWT_CTRL_NUMCOMP_Pos) /*!< DWT CTRL: NUMCOMP Mask */
+
+#define DWT_CTRL_NOTRCPKT_Pos 27U /*!< DWT CTRL: NOTRCPKT Position */
+#define DWT_CTRL_NOTRCPKT_Msk (0x1UL << DWT_CTRL_NOTRCPKT_Pos) /*!< DWT CTRL: NOTRCPKT Mask */
+
+#define DWT_CTRL_NOEXTTRIG_Pos 26U /*!< DWT CTRL: NOEXTTRIG Position */
+#define DWT_CTRL_NOEXTTRIG_Msk (0x1UL << DWT_CTRL_NOEXTTRIG_Pos) /*!< DWT CTRL: NOEXTTRIG Mask */
+
+#define DWT_CTRL_NOCYCCNT_Pos 25U /*!< DWT CTRL: NOCYCCNT Position */
+#define DWT_CTRL_NOCYCCNT_Msk (0x1UL << DWT_CTRL_NOCYCCNT_Pos) /*!< DWT CTRL: NOCYCCNT Mask */
+
+#define DWT_CTRL_NOPRFCNT_Pos 24U /*!< DWT CTRL: NOPRFCNT Position */
+#define DWT_CTRL_NOPRFCNT_Msk (0x1UL << DWT_CTRL_NOPRFCNT_Pos) /*!< DWT CTRL: NOPRFCNT Mask */
+
+/* DWT Comparator Function Register Definitions */
+#define DWT_FUNCTION_ID_Pos 27U /*!< DWT FUNCTION: ID Position */
+#define DWT_FUNCTION_ID_Msk (0x1FUL << DWT_FUNCTION_ID_Pos) /*!< DWT FUNCTION: ID Mask */
+
+#define DWT_FUNCTION_MATCHED_Pos 24U /*!< DWT FUNCTION: MATCHED Position */
+#define DWT_FUNCTION_MATCHED_Msk (0x1UL << DWT_FUNCTION_MATCHED_Pos) /*!< DWT FUNCTION: MATCHED Mask */
+
+#define DWT_FUNCTION_DATAVSIZE_Pos 10U /*!< DWT FUNCTION: DATAVSIZE Position */
+#define DWT_FUNCTION_DATAVSIZE_Msk (0x3UL << DWT_FUNCTION_DATAVSIZE_Pos) /*!< DWT FUNCTION: DATAVSIZE Mask */
+
+#define DWT_FUNCTION_ACTION_Pos 4U /*!< DWT FUNCTION: ACTION Position */
+#define DWT_FUNCTION_ACTION_Msk (0x3UL << DWT_FUNCTION_ACTION_Pos) /*!< DWT FUNCTION: ACTION Mask */
+
+#define DWT_FUNCTION_MATCH_Pos 0U /*!< DWT FUNCTION: MATCH Position */
+#define DWT_FUNCTION_MATCH_Msk (0xFUL /*<< DWT_FUNCTION_MATCH_Pos*/) /*!< DWT FUNCTION: MATCH Mask */
+
+/*@}*/ /* end of group CMSIS_DWT */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_TPI Trace Port Interface (TPI)
+ \brief Type definitions for the Trace Port Interface (TPI)
+ @{
+ */
+
+/**
+ \brief Structure type to access the Trace Port Interface Register (TPI).
+ */
+typedef struct
+{
+ __IM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Sizes Register */
+ __IOM uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Sizes Register */
+ uint32_t RESERVED0[2U];
+ __IOM uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */
+ uint32_t RESERVED1[55U];
+ __IOM uint32_t SPPR; /*!< Offset: 0x0F0 (R/W) Selected Pin Protocol Register */
+ uint32_t RESERVED2[131U];
+ __IM uint32_t FFSR; /*!< Offset: 0x300 (R/ ) Formatter and Flush Status Register */
+ __IOM uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */
+ __IOM uint32_t PSCR; /*!< Offset: 0x308 (R/W) Periodic Synchronization Control Register */
+ uint32_t RESERVED3[809U];
+ __OM uint32_t LAR; /*!< Offset: 0xFB0 ( /W) Software Lock Access Register */
+ __IM uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) Software Lock Status Register */
+ uint32_t RESERVED4[4U];
+ __IM uint32_t TYPE; /*!< Offset: 0xFC8 (R/ ) Device Identifier Register */
+ __IM uint32_t DEVTYPE; /*!< Offset: 0xFCC (R/ ) Device Type Register */
+} TPI_Type;
+
+/* TPI Asynchronous Clock Prescaler Register Definitions */
+#define TPI_ACPR_SWOSCALER_Pos 0U /*!< TPI ACPR: SWOSCALER Position */
+#define TPI_ACPR_SWOSCALER_Msk (0xFFFFUL /*<< TPI_ACPR_SWOSCALER_Pos*/) /*!< TPI ACPR: SWOSCALER Mask */
+
+/* TPI Selected Pin Protocol Register Definitions */
+#define TPI_SPPR_TXMODE_Pos 0U /*!< TPI SPPR: TXMODE Position */
+#define TPI_SPPR_TXMODE_Msk (0x3UL /*<< TPI_SPPR_TXMODE_Pos*/) /*!< TPI SPPR: TXMODE Mask */
+
+/* TPI Formatter and Flush Status Register Definitions */
+#define TPI_FFSR_FtNonStop_Pos 3U /*!< TPI FFSR: FtNonStop Position */
+#define TPI_FFSR_FtNonStop_Msk (0x1UL << TPI_FFSR_FtNonStop_Pos) /*!< TPI FFSR: FtNonStop Mask */
+
+#define TPI_FFSR_TCPresent_Pos 2U /*!< TPI FFSR: TCPresent Position */
+#define TPI_FFSR_TCPresent_Msk (0x1UL << TPI_FFSR_TCPresent_Pos) /*!< TPI FFSR: TCPresent Mask */
+
+#define TPI_FFSR_FtStopped_Pos 1U /*!< TPI FFSR: FtStopped Position */
+#define TPI_FFSR_FtStopped_Msk (0x1UL << TPI_FFSR_FtStopped_Pos) /*!< TPI FFSR: FtStopped Mask */
+
+#define TPI_FFSR_FlInProg_Pos 0U /*!< TPI FFSR: FlInProg Position */
+#define TPI_FFSR_FlInProg_Msk (0x1UL /*<< TPI_FFSR_FlInProg_Pos*/) /*!< TPI FFSR: FlInProg Mask */
+
+/* TPI Formatter and Flush Control Register Definitions */
+#define TPI_FFCR_TrigIn_Pos 8U /*!< TPI FFCR: TrigIn Position */
+#define TPI_FFCR_TrigIn_Msk (0x1UL << TPI_FFCR_TrigIn_Pos) /*!< TPI FFCR: TrigIn Mask */
+
+#define TPI_FFCR_FOnMan_Pos 6U /*!< TPI FFCR: FOnMan Position */
+#define TPI_FFCR_FOnMan_Msk (0x1UL << TPI_FFCR_FOnMan_Pos) /*!< TPI FFCR: FOnMan Mask */
+
+#define TPI_FFCR_EnFCont_Pos 1U /*!< TPI FFCR: EnFCont Position */
+#define TPI_FFCR_EnFCont_Msk (0x1UL << TPI_FFCR_EnFCont_Pos) /*!< TPI FFCR: EnFCont Mask */
+
+/* TPI Periodic Synchronization Control Register Definitions */
+#define TPI_PSCR_PSCount_Pos 0U /*!< TPI PSCR: PSCount Position */
+#define TPI_PSCR_PSCount_Msk (0x1FUL /*<< TPI_PSCR_PSCount_Pos*/) /*!< TPI PSCR: TPSCount Mask */
+
+/* TPI Software Lock Status Register Definitions */
+#define TPI_LSR_nTT_Pos 1U /*!< TPI LSR: Not thirty-two bit. Position */
+#define TPI_LSR_nTT_Msk (0x1UL << TPI_LSR_nTT_Pos) /*!< TPI LSR: Not thirty-two bit. Mask */
+
+#define TPI_LSR_SLK_Pos 1U /*!< TPI LSR: Software Lock status Position */
+#define TPI_LSR_SLK_Msk (0x1UL << TPI_LSR_SLK_Pos) /*!< TPI LSR: Software Lock status Mask */
+
+#define TPI_LSR_SLI_Pos 0U /*!< TPI LSR: Software Lock implemented Position */
+#define TPI_LSR_SLI_Msk (0x1UL /*<< TPI_LSR_SLI_Pos*/) /*!< TPI LSR: Software Lock implemented Mask */
+
+/* TPI DEVID Register Definitions */
+#define TPI_DEVID_NRZVALID_Pos 11U /*!< TPI DEVID: NRZVALID Position */
+#define TPI_DEVID_NRZVALID_Msk (0x1UL << TPI_DEVID_NRZVALID_Pos) /*!< TPI DEVID: NRZVALID Mask */
+
+#define TPI_DEVID_MANCVALID_Pos 10U /*!< TPI DEVID: MANCVALID Position */
+#define TPI_DEVID_MANCVALID_Msk (0x1UL << TPI_DEVID_MANCVALID_Pos) /*!< TPI DEVID: MANCVALID Mask */
+
+#define TPI_DEVID_PTINVALID_Pos 9U /*!< TPI DEVID: PTINVALID Position */
+#define TPI_DEVID_PTINVALID_Msk (0x1UL << TPI_DEVID_PTINVALID_Pos) /*!< TPI DEVID: PTINVALID Mask */
+
+#define TPI_DEVID_FIFOSZ_Pos 6U /*!< TPI DEVID: FIFO depth Position */
+#define TPI_DEVID_FIFOSZ_Msk (0x7UL << TPI_DEVID_FIFOSZ_Pos) /*!< TPI DEVID: FIFO depth Mask */
+
+/* TPI DEVTYPE Register Definitions */
+#define TPI_DEVTYPE_SubType_Pos 4U /*!< TPI DEVTYPE: SubType Position */
+#define TPI_DEVTYPE_SubType_Msk (0xFUL /*<< TPI_DEVTYPE_SubType_Pos*/) /*!< TPI DEVTYPE: SubType Mask */
+
+#define TPI_DEVTYPE_MajorType_Pos 0U /*!< TPI DEVTYPE: MajorType Position */
+#define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */
+
+/*@}*/ /* end of group CMSIS_TPI */
+
+
+#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U)
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_MPU Memory Protection Unit (MPU)
+ \brief Type definitions for the Memory Protection Unit (MPU)
+ @{
+ */
+
+/**
+ \brief Structure type to access the Memory Protection Unit (MPU).
+ */
+typedef struct
+{
+ __IM uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */
+ __IOM uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */
+ __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region Number Register */
+ __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */
+ __IOM uint32_t RLAR; /*!< Offset: 0x010 (R/W) MPU Region Limit Address Register */
+ uint32_t RESERVED0[7U];
+ union {
+ __IOM uint32_t MAIR[2];
+ struct {
+ __IOM uint32_t MAIR0; /*!< Offset: 0x030 (R/W) MPU Memory Attribute Indirection Register 0 */
+ __IOM uint32_t MAIR1; /*!< Offset: 0x034 (R/W) MPU Memory Attribute Indirection Register 1 */
+ };
+ };
+} MPU_Type;
+
+#define MPU_TYPE_RALIASES 1U
+
+/* MPU Type Register Definitions */
+#define MPU_TYPE_IREGION_Pos 16U /*!< MPU TYPE: IREGION Position */
+#define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */
+
+#define MPU_TYPE_DREGION_Pos 8U /*!< MPU TYPE: DREGION Position */
+#define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */
+
+#define MPU_TYPE_SEPARATE_Pos 0U /*!< MPU TYPE: SEPARATE Position */
+#define MPU_TYPE_SEPARATE_Msk (1UL /*<< MPU_TYPE_SEPARATE_Pos*/) /*!< MPU TYPE: SEPARATE Mask */
+
+/* MPU Control Register Definitions */
+#define MPU_CTRL_PRIVDEFENA_Pos 2U /*!< MPU CTRL: PRIVDEFENA Position */
+#define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */
+
+#define MPU_CTRL_HFNMIENA_Pos 1U /*!< MPU CTRL: HFNMIENA Position */
+#define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */
+
+#define MPU_CTRL_ENABLE_Pos 0U /*!< MPU CTRL: ENABLE Position */
+#define MPU_CTRL_ENABLE_Msk (1UL /*<< MPU_CTRL_ENABLE_Pos*/) /*!< MPU CTRL: ENABLE Mask */
+
+/* MPU Region Number Register Definitions */
+#define MPU_RNR_REGION_Pos 0U /*!< MPU RNR: REGION Position */
+#define MPU_RNR_REGION_Msk (0xFFUL /*<< MPU_RNR_REGION_Pos*/) /*!< MPU RNR: REGION Mask */
+
+/* MPU Region Base Address Register Definitions */
+#define MPU_RBAR_BASE_Pos 5U /*!< MPU RBAR: BASE Position */
+#define MPU_RBAR_BASE_Msk (0x7FFFFFFUL << MPU_RBAR_BASE_Pos) /*!< MPU RBAR: BASE Mask */
+
+#define MPU_RBAR_SH_Pos 3U /*!< MPU RBAR: SH Position */
+#define MPU_RBAR_SH_Msk (0x3UL << MPU_RBAR_SH_Pos) /*!< MPU RBAR: SH Mask */
+
+#define MPU_RBAR_AP_Pos 1U /*!< MPU RBAR: AP Position */
+#define MPU_RBAR_AP_Msk (0x3UL << MPU_RBAR_AP_Pos) /*!< MPU RBAR: AP Mask */
+
+#define MPU_RBAR_XN_Pos 0U /*!< MPU RBAR: XN Position */
+#define MPU_RBAR_XN_Msk (01UL /*<< MPU_RBAR_XN_Pos*/) /*!< MPU RBAR: XN Mask */
+
+/* MPU Region Limit Address Register Definitions */
+#define MPU_RLAR_LIMIT_Pos 5U /*!< MPU RLAR: LIMIT Position */
+#define MPU_RLAR_LIMIT_Msk (0x7FFFFFFUL << MPU_RLAR_LIMIT_Pos) /*!< MPU RLAR: LIMIT Mask */
+
+#define MPU_RLAR_AttrIndx_Pos 1U /*!< MPU RLAR: AttrIndx Position */
+#define MPU_RLAR_AttrIndx_Msk (0x7UL << MPU_RLAR_AttrIndx_Pos) /*!< MPU RLAR: AttrIndx Mask */
+
+#define MPU_RLAR_EN_Pos 0U /*!< MPU RLAR: EN Position */
+#define MPU_RLAR_EN_Msk (1UL /*<< MPU_RLAR_EN_Pos*/) /*!< MPU RLAR: EN Mask */
+
+/* MPU Memory Attribute Indirection Register 0 Definitions */
+#define MPU_MAIR0_Attr3_Pos 24U /*!< MPU MAIR0: Attr3 Position */
+#define MPU_MAIR0_Attr3_Msk (0xFFUL << MPU_MAIR0_Attr3_Pos) /*!< MPU MAIR0: Attr3 Mask */
+
+#define MPU_MAIR0_Attr2_Pos 16U /*!< MPU MAIR0: Attr2 Position */
+#define MPU_MAIR0_Attr2_Msk (0xFFUL << MPU_MAIR0_Attr2_Pos) /*!< MPU MAIR0: Attr2 Mask */
+
+#define MPU_MAIR0_Attr1_Pos 8U /*!< MPU MAIR0: Attr1 Position */
+#define MPU_MAIR0_Attr1_Msk (0xFFUL << MPU_MAIR0_Attr1_Pos) /*!< MPU MAIR0: Attr1 Mask */
+
+#define MPU_MAIR0_Attr0_Pos 0U /*!< MPU MAIR0: Attr0 Position */
+#define MPU_MAIR0_Attr0_Msk (0xFFUL /*<< MPU_MAIR0_Attr0_Pos*/) /*!< MPU MAIR0: Attr0 Mask */
+
+/* MPU Memory Attribute Indirection Register 1 Definitions */
+#define MPU_MAIR1_Attr7_Pos 24U /*!< MPU MAIR1: Attr7 Position */
+#define MPU_MAIR1_Attr7_Msk (0xFFUL << MPU_MAIR1_Attr7_Pos) /*!< MPU MAIR1: Attr7 Mask */
+
+#define MPU_MAIR1_Attr6_Pos 16U /*!< MPU MAIR1: Attr6 Position */
+#define MPU_MAIR1_Attr6_Msk (0xFFUL << MPU_MAIR1_Attr6_Pos) /*!< MPU MAIR1: Attr6 Mask */
+
+#define MPU_MAIR1_Attr5_Pos 8U /*!< MPU MAIR1: Attr5 Position */
+#define MPU_MAIR1_Attr5_Msk (0xFFUL << MPU_MAIR1_Attr5_Pos) /*!< MPU MAIR1: Attr5 Mask */
+
+#define MPU_MAIR1_Attr4_Pos 0U /*!< MPU MAIR1: Attr4 Position */
+#define MPU_MAIR1_Attr4_Msk (0xFFUL /*<< MPU_MAIR1_Attr4_Pos*/) /*!< MPU MAIR1: Attr4 Mask */
+
+/*@} end of group CMSIS_MPU */
+#endif
+
+
+#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_SAU Security Attribution Unit (SAU)
+ \brief Type definitions for the Security Attribution Unit (SAU)
+ @{
+ */
+
+/**
+ \brief Structure type to access the Security Attribution Unit (SAU).
+ */
+typedef struct
+{
+ __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SAU Control Register */
+ __IM uint32_t TYPE; /*!< Offset: 0x004 (R/ ) SAU Type Register */
+#if defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U)
+ __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) SAU Region Number Register */
+ __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) SAU Region Base Address Register */
+ __IOM uint32_t RLAR; /*!< Offset: 0x010 (R/W) SAU Region Limit Address Register */
+#endif
+} SAU_Type;
+
+/* SAU Control Register Definitions */
+#define SAU_CTRL_ALLNS_Pos 1U /*!< SAU CTRL: ALLNS Position */
+#define SAU_CTRL_ALLNS_Msk (1UL << SAU_CTRL_ALLNS_Pos) /*!< SAU CTRL: ALLNS Mask */
+
+#define SAU_CTRL_ENABLE_Pos 0U /*!< SAU CTRL: ENABLE Position */
+#define SAU_CTRL_ENABLE_Msk (1UL /*<< SAU_CTRL_ENABLE_Pos*/) /*!< SAU CTRL: ENABLE Mask */
+
+/* SAU Type Register Definitions */
+#define SAU_TYPE_SREGION_Pos 0U /*!< SAU TYPE: SREGION Position */
+#define SAU_TYPE_SREGION_Msk (0xFFUL /*<< SAU_TYPE_SREGION_Pos*/) /*!< SAU TYPE: SREGION Mask */
+
+#if defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U)
+/* SAU Region Number Register Definitions */
+#define SAU_RNR_REGION_Pos 0U /*!< SAU RNR: REGION Position */
+#define SAU_RNR_REGION_Msk (0xFFUL /*<< SAU_RNR_REGION_Pos*/) /*!< SAU RNR: REGION Mask */
+
+/* SAU Region Base Address Register Definitions */
+#define SAU_RBAR_BADDR_Pos 5U /*!< SAU RBAR: BADDR Position */
+#define SAU_RBAR_BADDR_Msk (0x7FFFFFFUL << SAU_RBAR_BADDR_Pos) /*!< SAU RBAR: BADDR Mask */
+
+/* SAU Region Limit Address Register Definitions */
+#define SAU_RLAR_LADDR_Pos 5U /*!< SAU RLAR: LADDR Position */
+#define SAU_RLAR_LADDR_Msk (0x7FFFFFFUL << SAU_RLAR_LADDR_Pos) /*!< SAU RLAR: LADDR Mask */
+
+#define SAU_RLAR_NSC_Pos 1U /*!< SAU RLAR: NSC Position */
+#define SAU_RLAR_NSC_Msk (1UL << SAU_RLAR_NSC_Pos) /*!< SAU RLAR: NSC Mask */
+
+#define SAU_RLAR_ENABLE_Pos 0U /*!< SAU RLAR: ENABLE Position */
+#define SAU_RLAR_ENABLE_Msk (1UL /*<< SAU_RLAR_ENABLE_Pos*/) /*!< SAU RLAR: ENABLE Mask */
+
+#endif /* defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U) */
+
+/*@} end of group CMSIS_SAU */
+#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug)
+ \brief Type definitions for the Core Debug Registers
+ @{
+ */
+
+/**
+ \brief Structure type to access the Core Debug Register (CoreDebug).
+ */
+typedef struct
+{
+ __IOM uint32_t DHCSR; /*!< Offset: 0x000 (R/W) Debug Halting Control and Status Register */
+ __OM uint32_t DCRSR; /*!< Offset: 0x004 ( /W) Debug Core Register Selector Register */
+ __IOM uint32_t DCRDR; /*!< Offset: 0x008 (R/W) Debug Core Register Data Register */
+ __IOM uint32_t DEMCR; /*!< Offset: 0x00C (R/W) Debug Exception and Monitor Control Register */
+ uint32_t RESERVED4[1U];
+ __IOM uint32_t DAUTHCTRL; /*!< Offset: 0x014 (R/W) Debug Authentication Control Register */
+ __IOM uint32_t DSCSR; /*!< Offset: 0x018 (R/W) Debug Security Control and Status Register */
+} CoreDebug_Type;
+
+/* Debug Halting Control and Status Register Definitions */
+#define CoreDebug_DHCSR_DBGKEY_Pos 16U /*!< CoreDebug DHCSR: DBGKEY Position */
+#define CoreDebug_DHCSR_DBGKEY_Msk (0xFFFFUL << CoreDebug_DHCSR_DBGKEY_Pos) /*!< CoreDebug DHCSR: DBGKEY Mask */
+
+#define CoreDebug_DHCSR_S_RESTART_ST_Pos 26U /*!< CoreDebug DHCSR: S_RESTART_ST Position */
+#define CoreDebug_DHCSR_S_RESTART_ST_Msk (1UL << CoreDebug_DHCSR_S_RESTART_ST_Pos) /*!< CoreDebug DHCSR: S_RESTART_ST Mask */
+
+#define CoreDebug_DHCSR_S_RESET_ST_Pos 25U /*!< CoreDebug DHCSR: S_RESET_ST Position */
+#define CoreDebug_DHCSR_S_RESET_ST_Msk (1UL << CoreDebug_DHCSR_S_RESET_ST_Pos) /*!< CoreDebug DHCSR: S_RESET_ST Mask */
+
+#define CoreDebug_DHCSR_S_RETIRE_ST_Pos 24U /*!< CoreDebug DHCSR: S_RETIRE_ST Position */
+#define CoreDebug_DHCSR_S_RETIRE_ST_Msk (1UL << CoreDebug_DHCSR_S_RETIRE_ST_Pos) /*!< CoreDebug DHCSR: S_RETIRE_ST Mask */
+
+#define CoreDebug_DHCSR_S_LOCKUP_Pos 19U /*!< CoreDebug DHCSR: S_LOCKUP Position */
+#define CoreDebug_DHCSR_S_LOCKUP_Msk (1UL << CoreDebug_DHCSR_S_LOCKUP_Pos) /*!< CoreDebug DHCSR: S_LOCKUP Mask */
+
+#define CoreDebug_DHCSR_S_SLEEP_Pos 18U /*!< CoreDebug DHCSR: S_SLEEP Position */
+#define CoreDebug_DHCSR_S_SLEEP_Msk (1UL << CoreDebug_DHCSR_S_SLEEP_Pos) /*!< CoreDebug DHCSR: S_SLEEP Mask */
+
+#define CoreDebug_DHCSR_S_HALT_Pos 17U /*!< CoreDebug DHCSR: S_HALT Position */
+#define CoreDebug_DHCSR_S_HALT_Msk (1UL << CoreDebug_DHCSR_S_HALT_Pos) /*!< CoreDebug DHCSR: S_HALT Mask */
+
+#define CoreDebug_DHCSR_S_REGRDY_Pos 16U /*!< CoreDebug DHCSR: S_REGRDY Position */
+#define CoreDebug_DHCSR_S_REGRDY_Msk (1UL << CoreDebug_DHCSR_S_REGRDY_Pos) /*!< CoreDebug DHCSR: S_REGRDY Mask */
+
+#define CoreDebug_DHCSR_C_MASKINTS_Pos 3U /*!< CoreDebug DHCSR: C_MASKINTS Position */
+#define CoreDebug_DHCSR_C_MASKINTS_Msk (1UL << CoreDebug_DHCSR_C_MASKINTS_Pos) /*!< CoreDebug DHCSR: C_MASKINTS Mask */
+
+#define CoreDebug_DHCSR_C_STEP_Pos 2U /*!< CoreDebug DHCSR: C_STEP Position */
+#define CoreDebug_DHCSR_C_STEP_Msk (1UL << CoreDebug_DHCSR_C_STEP_Pos) /*!< CoreDebug DHCSR: C_STEP Mask */
+
+#define CoreDebug_DHCSR_C_HALT_Pos 1U /*!< CoreDebug DHCSR: C_HALT Position */
+#define CoreDebug_DHCSR_C_HALT_Msk (1UL << CoreDebug_DHCSR_C_HALT_Pos) /*!< CoreDebug DHCSR: C_HALT Mask */
+
+#define CoreDebug_DHCSR_C_DEBUGEN_Pos 0U /*!< CoreDebug DHCSR: C_DEBUGEN Position */
+#define CoreDebug_DHCSR_C_DEBUGEN_Msk (1UL /*<< CoreDebug_DHCSR_C_DEBUGEN_Pos*/) /*!< CoreDebug DHCSR: C_DEBUGEN Mask */
+
+/* Debug Core Register Selector Register Definitions */
+#define CoreDebug_DCRSR_REGWnR_Pos 16U /*!< CoreDebug DCRSR: REGWnR Position */
+#define CoreDebug_DCRSR_REGWnR_Msk (1UL << CoreDebug_DCRSR_REGWnR_Pos) /*!< CoreDebug DCRSR: REGWnR Mask */
+
+#define CoreDebug_DCRSR_REGSEL_Pos 0U /*!< CoreDebug DCRSR: REGSEL Position */
+#define CoreDebug_DCRSR_REGSEL_Msk (0x1FUL /*<< CoreDebug_DCRSR_REGSEL_Pos*/) /*!< CoreDebug DCRSR: REGSEL Mask */
+
+/* Debug Exception and Monitor Control Register */
+#define CoreDebug_DEMCR_DWTENA_Pos 24U /*!< CoreDebug DEMCR: DWTENA Position */
+#define CoreDebug_DEMCR_DWTENA_Msk (1UL << CoreDebug_DEMCR_DWTENA_Pos) /*!< CoreDebug DEMCR: DWTENA Mask */
+
+#define CoreDebug_DEMCR_VC_HARDERR_Pos 10U /*!< CoreDebug DEMCR: VC_HARDERR Position */
+#define CoreDebug_DEMCR_VC_HARDERR_Msk (1UL << CoreDebug_DEMCR_VC_HARDERR_Pos) /*!< CoreDebug DEMCR: VC_HARDERR Mask */
+
+#define CoreDebug_DEMCR_VC_CORERESET_Pos 0U /*!< CoreDebug DEMCR: VC_CORERESET Position */
+#define CoreDebug_DEMCR_VC_CORERESET_Msk (1UL /*<< CoreDebug_DEMCR_VC_CORERESET_Pos*/) /*!< CoreDebug DEMCR: VC_CORERESET Mask */
+
+/* Debug Authentication Control Register Definitions */
+#define CoreDebug_DAUTHCTRL_INTSPNIDEN_Pos 3U /*!< CoreDebug DAUTHCTRL: INTSPNIDEN, Position */
+#define CoreDebug_DAUTHCTRL_INTSPNIDEN_Msk (1UL << CoreDebug_DAUTHCTRL_INTSPNIDEN_Pos) /*!< CoreDebug DAUTHCTRL: INTSPNIDEN, Mask */
+
+#define CoreDebug_DAUTHCTRL_SPNIDENSEL_Pos 2U /*!< CoreDebug DAUTHCTRL: SPNIDENSEL Position */
+#define CoreDebug_DAUTHCTRL_SPNIDENSEL_Msk (1UL << CoreDebug_DAUTHCTRL_SPNIDENSEL_Pos) /*!< CoreDebug DAUTHCTRL: SPNIDENSEL Mask */
+
+#define CoreDebug_DAUTHCTRL_INTSPIDEN_Pos 1U /*!< CoreDebug DAUTHCTRL: INTSPIDEN Position */
+#define CoreDebug_DAUTHCTRL_INTSPIDEN_Msk (1UL << CoreDebug_DAUTHCTRL_INTSPIDEN_Pos) /*!< CoreDebug DAUTHCTRL: INTSPIDEN Mask */
+
+#define CoreDebug_DAUTHCTRL_SPIDENSEL_Pos 0U /*!< CoreDebug DAUTHCTRL: SPIDENSEL Position */
+#define CoreDebug_DAUTHCTRL_SPIDENSEL_Msk (1UL /*<< CoreDebug_DAUTHCTRL_SPIDENSEL_Pos*/) /*!< CoreDebug DAUTHCTRL: SPIDENSEL Mask */
+
+/* Debug Security Control and Status Register Definitions */
+#define CoreDebug_DSCSR_CDS_Pos 16U /*!< CoreDebug DSCSR: CDS Position */
+#define CoreDebug_DSCSR_CDS_Msk (1UL << CoreDebug_DSCSR_CDS_Pos) /*!< CoreDebug DSCSR: CDS Mask */
+
+#define CoreDebug_DSCSR_SBRSEL_Pos 1U /*!< CoreDebug DSCSR: SBRSEL Position */
+#define CoreDebug_DSCSR_SBRSEL_Msk (1UL << CoreDebug_DSCSR_SBRSEL_Pos) /*!< CoreDebug DSCSR: SBRSEL Mask */
+
+#define CoreDebug_DSCSR_SBRSELEN_Pos 0U /*!< CoreDebug DSCSR: SBRSELEN Position */
+#define CoreDebug_DSCSR_SBRSELEN_Msk (1UL /*<< CoreDebug_DSCSR_SBRSELEN_Pos*/) /*!< CoreDebug DSCSR: SBRSELEN Mask */
+
+/*@} end of group CMSIS_CoreDebug */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_core_bitfield Core register bit field macros
+ \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk).
+ @{
+ */
+
+/**
+ \brief Mask and shift a bit field value for use in a register bit range.
+ \param[in] field Name of the register bit field.
+ \param[in] value Value of the bit field. This parameter is interpreted as an uint32_t type.
+ \return Masked and shifted value.
+*/
+#define _VAL2FLD(field, value) (((uint32_t)(value) << field ## _Pos) & field ## _Msk)
+
+/**
+ \brief Mask and shift a register value to extract a bit filed value.
+ \param[in] field Name of the register bit field.
+ \param[in] value Value of register. This parameter is interpreted as an uint32_t type.
+ \return Masked and shifted bit field value.
+*/
+#define _FLD2VAL(field, value) (((uint32_t)(value) & field ## _Msk) >> field ## _Pos)
+
+/*@} end of group CMSIS_core_bitfield */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_core_base Core Definitions
+ \brief Definitions for base addresses, unions, and structures.
+ @{
+ */
+
+/* Memory mapping of Core Hardware */
+ #define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */
+ #define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */
+ #define TPI_BASE (0xE0040000UL) /*!< TPI Base Address */
+ #define CoreDebug_BASE (0xE000EDF0UL) /*!< Core Debug Base Address */
+ #define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */
+ #define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */
+ #define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */
+
+
+ #define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */
+ #define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */
+ #define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */
+ #define DWT ((DWT_Type *) DWT_BASE ) /*!< DWT configuration struct */
+ #define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */
+ #define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE ) /*!< Core Debug configuration struct */
+
+ #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U)
+ #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */
+ #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */
+ #endif
+
+ #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
+ #define SAU_BASE (SCS_BASE + 0x0DD0UL) /*!< Security Attribution Unit */
+ #define SAU ((SAU_Type *) SAU_BASE ) /*!< Security Attribution Unit */
+ #endif
+
+#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
+ #define SCS_BASE_NS (0xE002E000UL) /*!< System Control Space Base Address (non-secure address space) */
+ #define CoreDebug_BASE_NS (0xE002EDF0UL) /*!< Core Debug Base Address (non-secure address space) */
+ #define SysTick_BASE_NS (SCS_BASE_NS + 0x0010UL) /*!< SysTick Base Address (non-secure address space) */
+ #define NVIC_BASE_NS (SCS_BASE_NS + 0x0100UL) /*!< NVIC Base Address (non-secure address space) */
+ #define SCB_BASE_NS (SCS_BASE_NS + 0x0D00UL) /*!< System Control Block Base Address (non-secure address space) */
+
+ #define SCB_NS ((SCB_Type *) SCB_BASE_NS ) /*!< SCB configuration struct (non-secure address space) */
+ #define SysTick_NS ((SysTick_Type *) SysTick_BASE_NS ) /*!< SysTick configuration struct (non-secure address space) */
+ #define NVIC_NS ((NVIC_Type *) NVIC_BASE_NS ) /*!< NVIC configuration struct (non-secure address space) */
+ #define CoreDebug_NS ((CoreDebug_Type *) CoreDebug_BASE_NS) /*!< Core Debug configuration struct (non-secure address space) */
+
+ #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U)
+ #define MPU_BASE_NS (SCS_BASE_NS + 0x0D90UL) /*!< Memory Protection Unit (non-secure address space) */
+ #define MPU_NS ((MPU_Type *) MPU_BASE_NS ) /*!< Memory Protection Unit (non-secure address space) */
+ #endif
+
+#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */
+/*@} */
+
+
+
+/*******************************************************************************
+ * Hardware Abstraction Layer
+ Core Function Interface contains:
+ - Core NVIC Functions
+ - Core SysTick Functions
+ - Core Register Access Functions
+ ******************************************************************************/
+/**
+ \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference
+*/
+
+
+
+/* ########################## NVIC functions #################################### */
+/**
+ \ingroup CMSIS_Core_FunctionInterface
+ \defgroup CMSIS_Core_NVICFunctions NVIC Functions
+ \brief Functions that manage interrupts and exceptions via the NVIC.
+ @{
+ */
+
+#ifdef CMSIS_NVIC_VIRTUAL
+ #ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE
+ #define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h"
+ #endif
+ #include CMSIS_NVIC_VIRTUAL_HEADER_FILE
+#else
+ #define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping
+ #define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping
+ #define NVIC_EnableIRQ __NVIC_EnableIRQ
+ #define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ
+ #define NVIC_DisableIRQ __NVIC_DisableIRQ
+ #define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ
+ #define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ
+ #define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ
+ #define NVIC_GetActive __NVIC_GetActive
+ #define NVIC_SetPriority __NVIC_SetPriority
+ #define NVIC_GetPriority __NVIC_GetPriority
+ #define NVIC_SystemReset __NVIC_SystemReset
+#endif /* CMSIS_NVIC_VIRTUAL */
+
+#ifdef CMSIS_VECTAB_VIRTUAL
+ #ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE
+ #define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h"
+ #endif
+ #include CMSIS_VECTAB_VIRTUAL_HEADER_FILE
+#else
+ #define NVIC_SetVector __NVIC_SetVector
+ #define NVIC_GetVector __NVIC_GetVector
+#endif /* (CMSIS_VECTAB_VIRTUAL) */
+
+#define NVIC_USER_IRQ_OFFSET 16
+
+
+/* Special LR values for Secure/Non-Secure call handling and exception handling */
+
+/* Function Return Payload (from ARMv8-M Architecture Reference Manual) LR value on entry from Secure BLXNS */
+#define FNC_RETURN (0xFEFFFFFFUL) /* bit [0] ignored when processing a branch */
+
+/* The following EXC_RETURN mask values are used to evaluate the LR on exception entry */
+#define EXC_RETURN_PREFIX (0xFF000000UL) /* bits [31:24] set to indicate an EXC_RETURN value */
+#define EXC_RETURN_S (0x00000040UL) /* bit [6] stack used to push registers: 0=Non-secure 1=Secure */
+#define EXC_RETURN_DCRS (0x00000020UL) /* bit [5] stacking rules for called registers: 0=skipped 1=saved */
+#define EXC_RETURN_FTYPE (0x00000010UL) /* bit [4] allocate stack for floating-point context: 0=done 1=skipped */
+#define EXC_RETURN_MODE (0x00000008UL) /* bit [3] processor mode for return: 0=Handler mode 1=Thread mode */
+#define EXC_RETURN_SPSEL (0x00000004UL) /* bit [2] stack pointer used to restore context: 0=MSP 1=PSP */
+#define EXC_RETURN_ES (0x00000001UL) /* bit [0] security state exception was taken to: 0=Non-secure 1=Secure */
+
+/* Integrity Signature (from ARMv8-M Architecture Reference Manual) for exception context stacking */
+#if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) /* Value for processors with floating-point extension: */
+#define EXC_INTEGRITY_SIGNATURE (0xFEFA125AUL) /* bit [0] SFTC must match LR bit[4] EXC_RETURN_FTYPE */
+#else
+#define EXC_INTEGRITY_SIGNATURE (0xFEFA125BUL) /* Value for processors without floating-point extension */
+#endif
+
+
+/* Interrupt Priorities are WORD accessible only under Armv6-M */
+/* The following MACROS handle generation of the register offset and byte masks */
+#define _BIT_SHIFT(IRQn) ( ((((uint32_t)(int32_t)(IRQn)) ) & 0x03UL) * 8UL)
+#define _SHP_IDX(IRQn) ( (((((uint32_t)(int32_t)(IRQn)) & 0x0FUL)-8UL) >> 2UL) )
+#define _IP_IDX(IRQn) ( (((uint32_t)(int32_t)(IRQn)) >> 2UL) )
+
+#define __NVIC_SetPriorityGrouping(X) (void)(X)
+#define __NVIC_GetPriorityGrouping() (0U)
+
+/**
+ \brief Enable Interrupt
+ \details Enables a device specific interrupt in the NVIC interrupt controller.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Get Interrupt Enable status
+ \details Returns a device specific interrupt enable status from the NVIC interrupt controller.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 Interrupt is not enabled.
+ \return 1 Interrupt is enabled.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Disable Interrupt
+ \details Disables a device specific interrupt in the NVIC interrupt controller.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ICER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ __DSB();
+ __ISB();
+ }
+}
+
+
+/**
+ \brief Get Pending Interrupt
+ \details Reads the NVIC pending register and returns the pending bit for the specified device specific interrupt.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 Interrupt status is not pending.
+ \return 1 Interrupt status is pending.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Set Pending Interrupt
+ \details Sets the pending bit of a device specific interrupt in the NVIC pending register.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Clear Pending Interrupt
+ \details Clears the pending bit of a device specific interrupt in the NVIC pending register.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Get Active Interrupt
+ \details Reads the active register in the NVIC and returns the active bit for the device specific interrupt.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 Interrupt status is not active.
+ \return 1 Interrupt status is active.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t __NVIC_GetActive(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC->IABR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
+/**
+ \brief Get Interrupt Target State
+ \details Reads the interrupt target field in the NVIC and returns the interrupt target bit for the device specific interrupt.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 if interrupt is assigned to Secure
+ \return 1 if interrupt is assigned to Non Secure
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t NVIC_GetTargetState(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Set Interrupt Target State
+ \details Sets the interrupt target field in the NVIC and returns the interrupt target bit for the device specific interrupt.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 if interrupt is assigned to Secure
+ 1 if interrupt is assigned to Non Secure
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t NVIC_SetTargetState(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] |= ((uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)));
+ return((uint32_t)(((NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Clear Interrupt Target State
+ \details Clears the interrupt target field in the NVIC and returns the interrupt target bit for the device specific interrupt.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 if interrupt is assigned to Secure
+ 1 if interrupt is assigned to Non Secure
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t NVIC_ClearTargetState(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] &= ~((uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)));
+ return((uint32_t)(((NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */
+
+
+/**
+ \brief Set Interrupt Priority
+ \details Sets the priority of a device specific interrupt or a processor exception.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ \param [in] IRQn Interrupt number.
+ \param [in] priority Priority to set.
+ \note The priority cannot be set for every processor exception.
+ */
+__STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->IPR[_IP_IDX(IRQn)] = ((uint32_t)(NVIC->IPR[_IP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) |
+ (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn)));
+ }
+ else
+ {
+ SCB->SHPR[_SHP_IDX(IRQn)] = ((uint32_t)(SCB->SHPR[_SHP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) |
+ (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn)));
+ }
+}
+
+
+/**
+ \brief Get Interrupt Priority
+ \details Reads the priority of a device specific interrupt or a processor exception.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ \param [in] IRQn Interrupt number.
+ \return Interrupt Priority.
+ Value is aligned automatically to the implemented priority bits of the microcontroller.
+ */
+__STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn)
+{
+
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC->IPR[ _IP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS)));
+ }
+ else
+ {
+ return((uint32_t)(((SCB->SHPR[_SHP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS)));
+ }
+}
+
+
+/**
+ \brief Encode Priority
+ \details Encodes the priority for an interrupt with the given priority group,
+ preemptive priority value, and subpriority value.
+ In case of a conflict between priority grouping and available
+ priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set.
+ \param [in] PriorityGroup Used priority group.
+ \param [in] PreemptPriority Preemptive priority value (starting from 0).
+ \param [in] SubPriority Subpriority value (starting from 0).
+ \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority().
+ */
+__STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority)
+{
+ uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */
+ uint32_t PreemptPriorityBits;
+ uint32_t SubPriorityBits;
+
+ PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp);
+ SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS));
+
+ return (
+ ((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) |
+ ((SubPriority & (uint32_t)((1UL << (SubPriorityBits )) - 1UL)))
+ );
+}
+
+
+/**
+ \brief Decode Priority
+ \details Decodes an interrupt priority value with a given priority group to
+ preemptive priority value and subpriority value.
+ In case of a conflict between priority grouping and available
+ priority bits (__NVIC_PRIO_BITS) the smallest possible priority group is set.
+ \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority().
+ \param [in] PriorityGroup Used priority group.
+ \param [out] pPreemptPriority Preemptive priority value (starting from 0).
+ \param [out] pSubPriority Subpriority value (starting from 0).
+ */
+__STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* const pPreemptPriority, uint32_t* const pSubPriority)
+{
+ uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */
+ uint32_t PreemptPriorityBits;
+ uint32_t SubPriorityBits;
+
+ PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp);
+ SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS));
+
+ *pPreemptPriority = (Priority >> SubPriorityBits) & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL);
+ *pSubPriority = (Priority ) & (uint32_t)((1UL << (SubPriorityBits )) - 1UL);
+}
+
+
+/**
+ \brief Set Interrupt Vector
+ \details Sets an interrupt vector in SRAM based interrupt vector table.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ VTOR must been relocated to SRAM before.
+ If VTOR is not present address 0 must be mapped to SRAM.
+ \param [in] IRQn Interrupt number
+ \param [in] vector Address of interrupt handler function
+ */
+__STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector)
+{
+#if defined (__VTOR_PRESENT) && (__VTOR_PRESENT == 1U)
+ uint32_t *vectors = (uint32_t *)SCB->VTOR;
+#else
+ uint32_t *vectors = (uint32_t *)0x0U;
+#endif
+ vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET] = vector;
+}
+
+
+/**
+ \brief Get Interrupt Vector
+ \details Reads an interrupt vector from interrupt vector table.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ \param [in] IRQn Interrupt number.
+ \return Address of interrupt handler function
+ */
+__STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn)
+{
+#if defined (__VTOR_PRESENT) && (__VTOR_PRESENT == 1U)
+ uint32_t *vectors = (uint32_t *)SCB->VTOR;
+#else
+ uint32_t *vectors = (uint32_t *)0x0U;
+#endif
+ return vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET];
+}
+
+
+/**
+ \brief System Reset
+ \details Initiates a system reset request to reset the MCU.
+ */
+__NO_RETURN __STATIC_INLINE void __NVIC_SystemReset(void)
+{
+ __DSB(); /* Ensure all outstanding memory accesses included
+ buffered write are completed before reset */
+ SCB->AIRCR = ((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) |
+ SCB_AIRCR_SYSRESETREQ_Msk);
+ __DSB(); /* Ensure completion of memory access */
+
+ for(;;) /* wait until reset */
+ {
+ __NOP();
+ }
+}
+
+#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
+/**
+ \brief Enable Interrupt (non-secure)
+ \details Enables a device specific interrupt in the non-secure NVIC interrupt controller when in secure state.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void TZ_NVIC_EnableIRQ_NS(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC_NS->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Get Interrupt Enable status (non-secure)
+ \details Returns a device specific interrupt enable status from the non-secure NVIC interrupt controller when in secure state.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 Interrupt is not enabled.
+ \return 1 Interrupt is enabled.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t TZ_NVIC_GetEnableIRQ_NS(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC_NS->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Disable Interrupt (non-secure)
+ \details Disables a device specific interrupt in the non-secure NVIC interrupt controller when in secure state.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void TZ_NVIC_DisableIRQ_NS(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC_NS->ICER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Get Pending Interrupt (non-secure)
+ \details Reads the NVIC pending register in the non-secure NVIC when in secure state and returns the pending bit for the specified device specific interrupt.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 Interrupt status is not pending.
+ \return 1 Interrupt status is pending.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t TZ_NVIC_GetPendingIRQ_NS(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC_NS->ISPR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Set Pending Interrupt (non-secure)
+ \details Sets the pending bit of a device specific interrupt in the non-secure NVIC pending register when in secure state.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void TZ_NVIC_SetPendingIRQ_NS(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC_NS->ISPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Clear Pending Interrupt (non-secure)
+ \details Clears the pending bit of a device specific interrupt in the non-secure NVIC pending register when in secure state.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void TZ_NVIC_ClearPendingIRQ_NS(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC_NS->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Get Active Interrupt (non-secure)
+ \details Reads the active register in non-secure NVIC when in secure state and returns the active bit for the device specific interrupt.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 Interrupt status is not active.
+ \return 1 Interrupt status is active.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t TZ_NVIC_GetActive_NS(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC_NS->IABR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Set Interrupt Priority (non-secure)
+ \details Sets the priority of a non-secure device specific interrupt or a non-secure processor exception when in secure state.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ \param [in] IRQn Interrupt number.
+ \param [in] priority Priority to set.
+ \note The priority cannot be set for every non-secure processor exception.
+ */
+__STATIC_INLINE void TZ_NVIC_SetPriority_NS(IRQn_Type IRQn, uint32_t priority)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC_NS->IPR[_IP_IDX(IRQn)] = ((uint32_t)(NVIC_NS->IPR[_IP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) |
+ (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn)));
+ }
+ else
+ {
+ SCB_NS->SHPR[_SHP_IDX(IRQn)] = ((uint32_t)(SCB_NS->SHPR[_SHP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) |
+ (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn)));
+ }
+}
+
+
+/**
+ \brief Get Interrupt Priority (non-secure)
+ \details Reads the priority of a non-secure device specific interrupt or a non-secure processor exception when in secure state.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ \param [in] IRQn Interrupt number.
+ \return Interrupt Priority. Value is aligned automatically to the implemented priority bits of the microcontroller.
+ */
+__STATIC_INLINE uint32_t TZ_NVIC_GetPriority_NS(IRQn_Type IRQn)
+{
+
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC_NS->IPR[ _IP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS)));
+ }
+ else
+ {
+ return((uint32_t)(((SCB_NS->SHPR[_SHP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS)));
+ }
+}
+#endif /* defined (__ARM_FEATURE_CMSE) &&(__ARM_FEATURE_CMSE == 3U) */
+
+/*@} end of CMSIS_Core_NVICFunctions */
+
+/* ########################## MPU functions #################################### */
+
+#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U)
+
+#include "mpu_armv8.h"
+
+#endif
+
+/* ########################## FPU functions #################################### */
+/**
+ \ingroup CMSIS_Core_FunctionInterface
+ \defgroup CMSIS_Core_FpuFunctions FPU Functions
+ \brief Function that provides FPU type.
+ @{
+ */
+
+/**
+ \brief get FPU type
+ \details returns the FPU type
+ \returns
+ - \b 0: No FPU
+ - \b 1: Single precision FPU
+ - \b 2: Double + Single precision FPU
+ */
+__STATIC_INLINE uint32_t SCB_GetFPUType(void)
+{
+ return 0U; /* No FPU */
+}
+
+
+/*@} end of CMSIS_Core_FpuFunctions */
+
+
+
+/* ########################## SAU functions #################################### */
+/**
+ \ingroup CMSIS_Core_FunctionInterface
+ \defgroup CMSIS_Core_SAUFunctions SAU Functions
+ \brief Functions that configure the SAU.
+ @{
+ */
+
+#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
+
+/**
+ \brief Enable SAU
+ \details Enables the Security Attribution Unit (SAU).
+ */
+__STATIC_INLINE void TZ_SAU_Enable(void)
+{
+ SAU->CTRL |= (SAU_CTRL_ENABLE_Msk);
+}
+
+
+
+/**
+ \brief Disable SAU
+ \details Disables the Security Attribution Unit (SAU).
+ */
+__STATIC_INLINE void TZ_SAU_Disable(void)
+{
+ SAU->CTRL &= ~(SAU_CTRL_ENABLE_Msk);
+}
+
+#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */
+
+/*@} end of CMSIS_Core_SAUFunctions */
+
+
+
+
+/* ################################## SysTick function ############################################ */
+/**
+ \ingroup CMSIS_Core_FunctionInterface
+ \defgroup CMSIS_Core_SysTickFunctions SysTick Functions
+ \brief Functions that configure the System.
+ @{
+ */
+
+#if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U)
+
+/**
+ \brief System Tick Configuration
+ \details Initializes the System Timer and its interrupt, and starts the System Tick Timer.
+ Counter is in free running mode to generate periodic interrupts.
+ \param [in] ticks Number of ticks between two interrupts.
+ \return 0 Function succeeded.
+ \return 1 Function failed.
+ \note When the variable __Vendor_SysTickConfig is set to 1, then the
+ function SysTick_Config is not included. In this case, the file device.h
+ must contain a vendor-specific implementation of this function.
+ */
+__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)
+{
+ if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk)
+ {
+ return (1UL); /* Reload value impossible */
+ }
+
+ SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */
+ NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */
+ SysTick->VAL = 0UL; /* Load the SysTick Counter Value */
+ SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
+ SysTick_CTRL_TICKINT_Msk |
+ SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */
+ return (0UL); /* Function successful */
+}
+
+#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
+/**
+ \brief System Tick Configuration (non-secure)
+ \details Initializes the non-secure System Timer and its interrupt when in secure state, and starts the System Tick Timer.
+ Counter is in free running mode to generate periodic interrupts.
+ \param [in] ticks Number of ticks between two interrupts.
+ \return 0 Function succeeded.
+ \return 1 Function failed.
+ \note When the variable __Vendor_SysTickConfig is set to 1, then the
+ function TZ_SysTick_Config_NS is not included. In this case, the file device.h
+ must contain a vendor-specific implementation of this function.
+
+ */
+__STATIC_INLINE uint32_t TZ_SysTick_Config_NS(uint32_t ticks)
+{
+ if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk)
+ {
+ return (1UL); /* Reload value impossible */
+ }
+
+ SysTick_NS->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */
+ TZ_NVIC_SetPriority_NS (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */
+ SysTick_NS->VAL = 0UL; /* Load the SysTick Counter Value */
+ SysTick_NS->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
+ SysTick_CTRL_TICKINT_Msk |
+ SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */
+ return (0UL); /* Function successful */
+}
+#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */
+
+#endif
+
+/*@} end of CMSIS_Core_SysTickFunctions */
+
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CORE_ARMV8MBL_H_DEPENDANT */
+
+#endif /* __CMSIS_GENERIC */
diff --git a/lib/cmsis/inc/core_armv8mml.h b/lib/cmsis/inc/core_armv8mml.h
new file mode 100644
index 0000000000..30aab58722
--- /dev/null
+++ b/lib/cmsis/inc/core_armv8mml.h
@@ -0,0 +1,2832 @@
+/**************************************************************************//**
+ * @file core_armv8mml.h
+ * @brief CMSIS Armv8-M Mainline Core Peripheral Access Layer Header File
+ * @version V5.1.0
+ * @date 12. September 2018
+ ******************************************************************************/
+/*
+ * Copyright (c) 2009-2018 Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#if defined ( __ICCARM__ )
+ #pragma system_include /* treat file as system include file for MISRA check */
+#elif defined (__clang__)
+ #pragma clang system_header /* treat file as system include file */
+#endif
+
+#ifndef __CORE_ARMV8MML_H_GENERIC
+#define __CORE_ARMV8MML_H_GENERIC
+
+#include
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/**
+ \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions
+ CMSIS violates the following MISRA-C:2004 rules:
+
+ \li Required Rule 8.5, object/function definition in header file.
+ Function definitions in header files are used to allow 'inlining'.
+
+ \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
+ Unions are used for effective representation of core registers.
+
+ \li Advisory Rule 19.7, Function-like macro defined.
+ Function-like macros are used to allow more efficient code.
+ */
+
+
+/*******************************************************************************
+ * CMSIS definitions
+ ******************************************************************************/
+/**
+ \ingroup Cortex_ARMv8MML
+ @{
+ */
+
+#include "cmsis_version.h"
+
+/* CMSIS Armv8MML definitions */
+#define __ARMv8MML_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */
+#define __ARMv8MML_CMSIS_VERSION_SUB (__CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */
+#define __ARMv8MML_CMSIS_VERSION ((__ARMv8MML_CMSIS_VERSION_MAIN << 16U) | \
+ __ARMv8MML_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */
+
+#define __CORTEX_M (81U) /*!< Cortex-M Core */
+
+/** __FPU_USED indicates whether an FPU is used or not.
+ For this, __FPU_PRESENT has to be checked prior to making use of FPU specific registers and functions.
+*/
+#if defined ( __CC_ARM )
+ #if defined __TARGET_FPU_VFP
+ #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)
+ #define __FPU_USED 1U
+ #else
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #define __FPU_USED 0U
+ #endif
+ #else
+ #define __FPU_USED 0U
+ #endif
+
+ #if defined(__ARM_FEATURE_DSP)
+ #if defined(__DSP_PRESENT) && (__DSP_PRESENT == 1U)
+ #define __DSP_USED 1U
+ #else
+ #error "Compiler generates DSP (SIMD) instructions for a devices without DSP extensions (check __DSP_PRESENT)"
+ #define __DSP_USED 0U
+ #endif
+ #else
+ #define __DSP_USED 0U
+ #endif
+
+#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
+ #if defined __ARM_FP
+ #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)
+ #define __FPU_USED 1U
+ #else
+ #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #define __FPU_USED 0U
+ #endif
+ #else
+ #define __FPU_USED 0U
+ #endif
+
+ #if defined(__ARM_FEATURE_DSP)
+ #if defined(__DSP_PRESENT) && (__DSP_PRESENT == 1U)
+ #define __DSP_USED 1U
+ #else
+ #error "Compiler generates DSP (SIMD) instructions for a devices without DSP extensions (check __DSP_PRESENT)"
+ #define __DSP_USED 0U
+ #endif
+ #else
+ #define __DSP_USED 0U
+ #endif
+
+#elif defined ( __GNUC__ )
+ #if defined (__VFP_FP__) && !defined(__SOFTFP__)
+ #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)
+ #define __FPU_USED 1U
+ #else
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #define __FPU_USED 0U
+ #endif
+ #else
+ #define __FPU_USED 0U
+ #endif
+
+ #if defined(__ARM_FEATURE_DSP)
+ #if defined(__DSP_PRESENT) && (__DSP_PRESENT == 1U)
+ #define __DSP_USED 1U
+ #else
+ #error "Compiler generates DSP (SIMD) instructions for a devices without DSP extensions (check __DSP_PRESENT)"
+ #define __DSP_USED 0U
+ #endif
+ #else
+ #define __DSP_USED 0U
+ #endif
+
+#elif defined ( __ICCARM__ )
+ #if defined __ARMVFP__
+ #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)
+ #define __FPU_USED 1U
+ #else
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #define __FPU_USED 0U
+ #endif
+ #else
+ #define __FPU_USED 0U
+ #endif
+
+ #if defined(__ARM_FEATURE_DSP)
+ #if defined(__DSP_PRESENT) && (__DSP_PRESENT == 1U)
+ #define __DSP_USED 1U
+ #else
+ #error "Compiler generates DSP (SIMD) instructions for a devices without DSP extensions (check __DSP_PRESENT)"
+ #define __DSP_USED 0U
+ #endif
+ #else
+ #define __DSP_USED 0U
+ #endif
+
+#elif defined ( __TI_ARM__ )
+ #if defined __TI_VFP_SUPPORT__
+ #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)
+ #define __FPU_USED 1U
+ #else
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #define __FPU_USED 0U
+ #endif
+ #else
+ #define __FPU_USED 0U
+ #endif
+
+#elif defined ( __TASKING__ )
+ #if defined __FPU_VFP__
+ #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)
+ #define __FPU_USED 1U
+ #else
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #define __FPU_USED 0U
+ #endif
+ #else
+ #define __FPU_USED 0U
+ #endif
+
+#elif defined ( __CSMC__ )
+ #if ( __CSMC__ & 0x400U)
+ #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)
+ #define __FPU_USED 1U
+ #else
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #define __FPU_USED 0U
+ #endif
+ #else
+ #define __FPU_USED 0U
+ #endif
+
+#endif
+
+#include "cmsis_compiler.h" /* CMSIS compiler specific defines */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CORE_ARMV8MML_H_GENERIC */
+
+#ifndef __CMSIS_GENERIC
+
+#ifndef __CORE_ARMV8MML_H_DEPENDANT
+#define __CORE_ARMV8MML_H_DEPENDANT
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/* check device defines and use defaults */
+#if defined __CHECK_DEVICE_DEFINES
+ #ifndef __ARMv8MML_REV
+ #define __ARMv8MML_REV 0x0000U
+ #warning "__ARMv8MML_REV not defined in device header file; using default!"
+ #endif
+
+ #ifndef __FPU_PRESENT
+ #define __FPU_PRESENT 0U
+ #warning "__FPU_PRESENT not defined in device header file; using default!"
+ #endif
+
+ #ifndef __MPU_PRESENT
+ #define __MPU_PRESENT 0U
+ #warning "__MPU_PRESENT not defined in device header file; using default!"
+ #endif
+
+ #ifndef __SAUREGION_PRESENT
+ #define __SAUREGION_PRESENT 0U
+ #warning "__SAUREGION_PRESENT not defined in device header file; using default!"
+ #endif
+
+ #ifndef __DSP_PRESENT
+ #define __DSP_PRESENT 0U
+ #warning "__DSP_PRESENT not defined in device header file; using default!"
+ #endif
+
+ #ifndef __NVIC_PRIO_BITS
+ #define __NVIC_PRIO_BITS 3U
+ #warning "__NVIC_PRIO_BITS not defined in device header file; using default!"
+ #endif
+
+ #ifndef __Vendor_SysTickConfig
+ #define __Vendor_SysTickConfig 0U
+ #warning "__Vendor_SysTickConfig not defined in device header file; using default!"
+ #endif
+#endif
+
+/* IO definitions (access restrictions to peripheral registers) */
+/**
+ \defgroup CMSIS_glob_defs CMSIS Global Defines
+
+ IO Type Qualifiers are used
+ \li to specify the access to peripheral variables.
+ \li for automatic generation of peripheral register debug information.
+*/
+#ifdef __cplusplus
+ #define __I volatile /*!< Defines 'read only' permissions */
+#else
+ #define __I volatile const /*!< Defines 'read only' permissions */
+#endif
+#define __O volatile /*!< Defines 'write only' permissions */
+#define __IO volatile /*!< Defines 'read / write' permissions */
+
+/* following defines should be used for structure members */
+#define __IM volatile const /*! Defines 'read only' structure member permissions */
+#define __OM volatile /*! Defines 'write only' structure member permissions */
+#define __IOM volatile /*! Defines 'read / write' structure member permissions */
+
+/*@} end of group ARMv8MML */
+
+
+
+/*******************************************************************************
+ * Register Abstraction
+ Core Register contain:
+ - Core Register
+ - Core NVIC Register
+ - Core SCB Register
+ - Core SysTick Register
+ - Core Debug Register
+ - Core MPU Register
+ - Core SAU Register
+ - Core FPU Register
+ ******************************************************************************/
+/**
+ \defgroup CMSIS_core_register Defines and Type Definitions
+ \brief Type definitions and defines for Cortex-M processor based devices.
+*/
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_CORE Status and Control Registers
+ \brief Core Register type definitions.
+ @{
+ */
+
+/**
+ \brief Union type to access the Application Program Status Register (APSR).
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t _reserved0:16; /*!< bit: 0..15 Reserved */
+ uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */
+ uint32_t _reserved1:7; /*!< bit: 20..26 Reserved */
+ uint32_t Q:1; /*!< bit: 27 Saturation condition flag */
+ uint32_t V:1; /*!< bit: 28 Overflow condition code flag */
+ uint32_t C:1; /*!< bit: 29 Carry condition code flag */
+ uint32_t Z:1; /*!< bit: 30 Zero condition code flag */
+ uint32_t N:1; /*!< bit: 31 Negative condition code flag */
+ } b; /*!< Structure used for bit access */
+ uint32_t w; /*!< Type used for word access */
+} APSR_Type;
+
+/* APSR Register Definitions */
+#define APSR_N_Pos 31U /*!< APSR: N Position */
+#define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */
+
+#define APSR_Z_Pos 30U /*!< APSR: Z Position */
+#define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */
+
+#define APSR_C_Pos 29U /*!< APSR: C Position */
+#define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */
+
+#define APSR_V_Pos 28U /*!< APSR: V Position */
+#define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */
+
+#define APSR_Q_Pos 27U /*!< APSR: Q Position */
+#define APSR_Q_Msk (1UL << APSR_Q_Pos) /*!< APSR: Q Mask */
+
+#define APSR_GE_Pos 16U /*!< APSR: GE Position */
+#define APSR_GE_Msk (0xFUL << APSR_GE_Pos) /*!< APSR: GE Mask */
+
+
+/**
+ \brief Union type to access the Interrupt Program Status Register (IPSR).
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */
+ uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */
+ } b; /*!< Structure used for bit access */
+ uint32_t w; /*!< Type used for word access */
+} IPSR_Type;
+
+/* IPSR Register Definitions */
+#define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */
+#define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */
+
+
+/**
+ \brief Union type to access the Special-Purpose Program Status Registers (xPSR).
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */
+ uint32_t _reserved0:7; /*!< bit: 9..15 Reserved */
+ uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */
+ uint32_t _reserved1:4; /*!< bit: 20..23 Reserved */
+ uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */
+ uint32_t IT:2; /*!< bit: 25..26 saved IT state (read 0) */
+ uint32_t Q:1; /*!< bit: 27 Saturation condition flag */
+ uint32_t V:1; /*!< bit: 28 Overflow condition code flag */
+ uint32_t C:1; /*!< bit: 29 Carry condition code flag */
+ uint32_t Z:1; /*!< bit: 30 Zero condition code flag */
+ uint32_t N:1; /*!< bit: 31 Negative condition code flag */
+ } b; /*!< Structure used for bit access */
+ uint32_t w; /*!< Type used for word access */
+} xPSR_Type;
+
+/* xPSR Register Definitions */
+#define xPSR_N_Pos 31U /*!< xPSR: N Position */
+#define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */
+
+#define xPSR_Z_Pos 30U /*!< xPSR: Z Position */
+#define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */
+
+#define xPSR_C_Pos 29U /*!< xPSR: C Position */
+#define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */
+
+#define xPSR_V_Pos 28U /*!< xPSR: V Position */
+#define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */
+
+#define xPSR_Q_Pos 27U /*!< xPSR: Q Position */
+#define xPSR_Q_Msk (1UL << xPSR_Q_Pos) /*!< xPSR: Q Mask */
+
+#define xPSR_IT_Pos 25U /*!< xPSR: IT Position */
+#define xPSR_IT_Msk (3UL << xPSR_IT_Pos) /*!< xPSR: IT Mask */
+
+#define xPSR_T_Pos 24U /*!< xPSR: T Position */
+#define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */
+
+#define xPSR_GE_Pos 16U /*!< xPSR: GE Position */
+#define xPSR_GE_Msk (0xFUL << xPSR_GE_Pos) /*!< xPSR: GE Mask */
+
+#define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */
+#define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */
+
+
+/**
+ \brief Union type to access the Control Registers (CONTROL).
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */
+ uint32_t SPSEL:1; /*!< bit: 1 Stack-pointer select */
+ uint32_t FPCA:1; /*!< bit: 2 Floating-point context active */
+ uint32_t SFPA:1; /*!< bit: 3 Secure floating-point active */
+ uint32_t _reserved1:28; /*!< bit: 4..31 Reserved */
+ } b; /*!< Structure used for bit access */
+ uint32_t w; /*!< Type used for word access */
+} CONTROL_Type;
+
+/* CONTROL Register Definitions */
+#define CONTROL_SFPA_Pos 3U /*!< CONTROL: SFPA Position */
+#define CONTROL_SFPA_Msk (1UL << CONTROL_SFPA_Pos) /*!< CONTROL: SFPA Mask */
+
+#define CONTROL_FPCA_Pos 2U /*!< CONTROL: FPCA Position */
+#define CONTROL_FPCA_Msk (1UL << CONTROL_FPCA_Pos) /*!< CONTROL: FPCA Mask */
+
+#define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */
+#define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */
+
+#define CONTROL_nPRIV_Pos 0U /*!< CONTROL: nPRIV Position */
+#define CONTROL_nPRIV_Msk (1UL /*<< CONTROL_nPRIV_Pos*/) /*!< CONTROL: nPRIV Mask */
+
+/*@} end of group CMSIS_CORE */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC)
+ \brief Type definitions for the NVIC Registers
+ @{
+ */
+
+/**
+ \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC).
+ */
+typedef struct
+{
+ __IOM uint32_t ISER[16U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */
+ uint32_t RESERVED0[16U];
+ __IOM uint32_t ICER[16U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */
+ uint32_t RSERVED1[16U];
+ __IOM uint32_t ISPR[16U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */
+ uint32_t RESERVED2[16U];
+ __IOM uint32_t ICPR[16U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */
+ uint32_t RESERVED3[16U];
+ __IOM uint32_t IABR[16U]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */
+ uint32_t RESERVED4[16U];
+ __IOM uint32_t ITNS[16U]; /*!< Offset: 0x280 (R/W) Interrupt Non-Secure State Register */
+ uint32_t RESERVED5[16U];
+ __IOM uint8_t IPR[496U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register (8Bit wide) */
+ uint32_t RESERVED6[580U];
+ __OM uint32_t STIR; /*!< Offset: 0xE00 ( /W) Software Trigger Interrupt Register */
+} NVIC_Type;
+
+/* Software Triggered Interrupt Register Definitions */
+#define NVIC_STIR_INTID_Pos 0U /*!< STIR: INTLINESNUM Position */
+#define NVIC_STIR_INTID_Msk (0x1FFUL /*<< NVIC_STIR_INTID_Pos*/) /*!< STIR: INTLINESNUM Mask */
+
+/*@} end of group CMSIS_NVIC */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_SCB System Control Block (SCB)
+ \brief Type definitions for the System Control Block Registers
+ @{
+ */
+
+/**
+ \brief Structure type to access the System Control Block (SCB).
+ */
+typedef struct
+{
+ __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */
+ __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */
+ __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */
+ __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */
+ __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */
+ __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */
+ __IOM uint8_t SHPR[12U]; /*!< Offset: 0x018 (R/W) System Handlers Priority Registers (4-7, 8-11, 12-15) */
+ __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */
+ __IOM uint32_t CFSR; /*!< Offset: 0x028 (R/W) Configurable Fault Status Register */
+ __IOM uint32_t HFSR; /*!< Offset: 0x02C (R/W) HardFault Status Register */
+ __IOM uint32_t DFSR; /*!< Offset: 0x030 (R/W) Debug Fault Status Register */
+ __IOM uint32_t MMFAR; /*!< Offset: 0x034 (R/W) MemManage Fault Address Register */
+ __IOM uint32_t BFAR; /*!< Offset: 0x038 (R/W) BusFault Address Register */
+ __IOM uint32_t AFSR; /*!< Offset: 0x03C (R/W) Auxiliary Fault Status Register */
+ __IM uint32_t ID_PFR[2U]; /*!< Offset: 0x040 (R/ ) Processor Feature Register */
+ __IM uint32_t ID_DFR; /*!< Offset: 0x048 (R/ ) Debug Feature Register */
+ __IM uint32_t ID_ADR; /*!< Offset: 0x04C (R/ ) Auxiliary Feature Register */
+ __IM uint32_t ID_MMFR[4U]; /*!< Offset: 0x050 (R/ ) Memory Model Feature Register */
+ __IM uint32_t ID_ISAR[6U]; /*!< Offset: 0x060 (R/ ) Instruction Set Attributes Register */
+ __IM uint32_t CLIDR; /*!< Offset: 0x078 (R/ ) Cache Level ID register */
+ __IM uint32_t CTR; /*!< Offset: 0x07C (R/ ) Cache Type register */
+ __IM uint32_t CCSIDR; /*!< Offset: 0x080 (R/ ) Cache Size ID Register */
+ __IOM uint32_t CSSELR; /*!< Offset: 0x084 (R/W) Cache Size Selection Register */
+ __IOM uint32_t CPACR; /*!< Offset: 0x088 (R/W) Coprocessor Access Control Register */
+ __IOM uint32_t NSACR; /*!< Offset: 0x08C (R/W) Non-Secure Access Control Register */
+ uint32_t RESERVED3[92U];
+ __OM uint32_t STIR; /*!< Offset: 0x200 ( /W) Software Triggered Interrupt Register */
+ uint32_t RESERVED4[15U];
+ __IM uint32_t MVFR0; /*!< Offset: 0x240 (R/ ) Media and VFP Feature Register 0 */
+ __IM uint32_t MVFR1; /*!< Offset: 0x244 (R/ ) Media and VFP Feature Register 1 */
+ __IM uint32_t MVFR2; /*!< Offset: 0x248 (R/ ) Media and VFP Feature Register 2 */
+ uint32_t RESERVED5[1U];
+ __OM uint32_t ICIALLU; /*!< Offset: 0x250 ( /W) I-Cache Invalidate All to PoU */
+ uint32_t RESERVED6[1U];
+ __OM uint32_t ICIMVAU; /*!< Offset: 0x258 ( /W) I-Cache Invalidate by MVA to PoU */
+ __OM uint32_t DCIMVAC; /*!< Offset: 0x25C ( /W) D-Cache Invalidate by MVA to PoC */
+ __OM uint32_t DCISW; /*!< Offset: 0x260 ( /W) D-Cache Invalidate by Set-way */
+ __OM uint32_t DCCMVAU; /*!< Offset: 0x264 ( /W) D-Cache Clean by MVA to PoU */
+ __OM uint32_t DCCMVAC; /*!< Offset: 0x268 ( /W) D-Cache Clean by MVA to PoC */
+ __OM uint32_t DCCSW; /*!< Offset: 0x26C ( /W) D-Cache Clean by Set-way */
+ __OM uint32_t DCCIMVAC; /*!< Offset: 0x270 ( /W) D-Cache Clean and Invalidate by MVA to PoC */
+ __OM uint32_t DCCISW; /*!< Offset: 0x274 ( /W) D-Cache Clean and Invalidate by Set-way */
+} SCB_Type;
+
+/* SCB CPUID Register Definitions */
+#define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */
+#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */
+
+#define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */
+#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */
+
+#define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */
+#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */
+
+#define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */
+#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */
+
+#define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */
+#define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */
+
+/* SCB Interrupt Control State Register Definitions */
+#define SCB_ICSR_PENDNMISET_Pos 31U /*!< SCB ICSR: PENDNMISET Position */
+#define SCB_ICSR_PENDNMISET_Msk (1UL << SCB_ICSR_PENDNMISET_Pos) /*!< SCB ICSR: PENDNMISET Mask */
+
+#define SCB_ICSR_NMIPENDSET_Pos SCB_ICSR_PENDNMISET_Pos /*!< SCB ICSR: NMIPENDSET Position, backward compatibility */
+#define SCB_ICSR_NMIPENDSET_Msk SCB_ICSR_PENDNMISET_Msk /*!< SCB ICSR: NMIPENDSET Mask, backward compatibility */
+
+#define SCB_ICSR_PENDNMICLR_Pos 30U /*!< SCB ICSR: PENDNMICLR Position */
+#define SCB_ICSR_PENDNMICLR_Msk (1UL << SCB_ICSR_PENDNMICLR_Pos) /*!< SCB ICSR: PENDNMICLR Mask */
+
+#define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */
+#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */
+
+#define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */
+#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */
+
+#define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */
+#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */
+
+#define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */
+#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */
+
+#define SCB_ICSR_STTNS_Pos 24U /*!< SCB ICSR: STTNS Position (Security Extension) */
+#define SCB_ICSR_STTNS_Msk (1UL << SCB_ICSR_STTNS_Pos) /*!< SCB ICSR: STTNS Mask (Security Extension) */
+
+#define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */
+#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */
+
+#define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */
+#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */
+
+#define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */
+#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */
+
+#define SCB_ICSR_RETTOBASE_Pos 11U /*!< SCB ICSR: RETTOBASE Position */
+#define SCB_ICSR_RETTOBASE_Msk (1UL << SCB_ICSR_RETTOBASE_Pos) /*!< SCB ICSR: RETTOBASE Mask */
+
+#define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */
+#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */
+
+/* SCB Vector Table Offset Register Definitions */
+#define SCB_VTOR_TBLOFF_Pos 7U /*!< SCB VTOR: TBLOFF Position */
+#define SCB_VTOR_TBLOFF_Msk (0x1FFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */
+
+/* SCB Application Interrupt and Reset Control Register Definitions */
+#define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */
+#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */
+
+#define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */
+#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */
+
+#define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */
+#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */
+
+#define SCB_AIRCR_PRIS_Pos 14U /*!< SCB AIRCR: PRIS Position */
+#define SCB_AIRCR_PRIS_Msk (1UL << SCB_AIRCR_PRIS_Pos) /*!< SCB AIRCR: PRIS Mask */
+
+#define SCB_AIRCR_BFHFNMINS_Pos 13U /*!< SCB AIRCR: BFHFNMINS Position */
+#define SCB_AIRCR_BFHFNMINS_Msk (1UL << SCB_AIRCR_BFHFNMINS_Pos) /*!< SCB AIRCR: BFHFNMINS Mask */
+
+#define SCB_AIRCR_PRIGROUP_Pos 8U /*!< SCB AIRCR: PRIGROUP Position */
+#define SCB_AIRCR_PRIGROUP_Msk (7UL << SCB_AIRCR_PRIGROUP_Pos) /*!< SCB AIRCR: PRIGROUP Mask */
+
+#define SCB_AIRCR_SYSRESETREQS_Pos 3U /*!< SCB AIRCR: SYSRESETREQS Position */
+#define SCB_AIRCR_SYSRESETREQS_Msk (1UL << SCB_AIRCR_SYSRESETREQS_Pos) /*!< SCB AIRCR: SYSRESETREQS Mask */
+
+#define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */
+#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */
+
+#define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */
+#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */
+
+/* SCB System Control Register Definitions */
+#define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */
+#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */
+
+#define SCB_SCR_SLEEPDEEPS_Pos 3U /*!< SCB SCR: SLEEPDEEPS Position */
+#define SCB_SCR_SLEEPDEEPS_Msk (1UL << SCB_SCR_SLEEPDEEPS_Pos) /*!< SCB SCR: SLEEPDEEPS Mask */
+
+#define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */
+#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */
+
+#define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */
+#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */
+
+/* SCB Configuration Control Register Definitions */
+#define SCB_CCR_BP_Pos 18U /*!< SCB CCR: BP Position */
+#define SCB_CCR_BP_Msk (1UL << SCB_CCR_BP_Pos) /*!< SCB CCR: BP Mask */
+
+#define SCB_CCR_IC_Pos 17U /*!< SCB CCR: IC Position */
+#define SCB_CCR_IC_Msk (1UL << SCB_CCR_IC_Pos) /*!< SCB CCR: IC Mask */
+
+#define SCB_CCR_DC_Pos 16U /*!< SCB CCR: DC Position */
+#define SCB_CCR_DC_Msk (1UL << SCB_CCR_DC_Pos) /*!< SCB CCR: DC Mask */
+
+#define SCB_CCR_STKOFHFNMIGN_Pos 10U /*!< SCB CCR: STKOFHFNMIGN Position */
+#define SCB_CCR_STKOFHFNMIGN_Msk (1UL << SCB_CCR_STKOFHFNMIGN_Pos) /*!< SCB CCR: STKOFHFNMIGN Mask */
+
+#define SCB_CCR_BFHFNMIGN_Pos 8U /*!< SCB CCR: BFHFNMIGN Position */
+#define SCB_CCR_BFHFNMIGN_Msk (1UL << SCB_CCR_BFHFNMIGN_Pos) /*!< SCB CCR: BFHFNMIGN Mask */
+
+#define SCB_CCR_DIV_0_TRP_Pos 4U /*!< SCB CCR: DIV_0_TRP Position */
+#define SCB_CCR_DIV_0_TRP_Msk (1UL << SCB_CCR_DIV_0_TRP_Pos) /*!< SCB CCR: DIV_0_TRP Mask */
+
+#define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */
+#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */
+
+#define SCB_CCR_USERSETMPEND_Pos 1U /*!< SCB CCR: USERSETMPEND Position */
+#define SCB_CCR_USERSETMPEND_Msk (1UL << SCB_CCR_USERSETMPEND_Pos) /*!< SCB CCR: USERSETMPEND Mask */
+
+/* SCB System Handler Control and State Register Definitions */
+#define SCB_SHCSR_HARDFAULTPENDED_Pos 21U /*!< SCB SHCSR: HARDFAULTPENDED Position */
+#define SCB_SHCSR_HARDFAULTPENDED_Msk (1UL << SCB_SHCSR_HARDFAULTPENDED_Pos) /*!< SCB SHCSR: HARDFAULTPENDED Mask */
+
+#define SCB_SHCSR_SECUREFAULTPENDED_Pos 20U /*!< SCB SHCSR: SECUREFAULTPENDED Position */
+#define SCB_SHCSR_SECUREFAULTPENDED_Msk (1UL << SCB_SHCSR_SECUREFAULTPENDED_Pos) /*!< SCB SHCSR: SECUREFAULTPENDED Mask */
+
+#define SCB_SHCSR_SECUREFAULTENA_Pos 19U /*!< SCB SHCSR: SECUREFAULTENA Position */
+#define SCB_SHCSR_SECUREFAULTENA_Msk (1UL << SCB_SHCSR_SECUREFAULTENA_Pos) /*!< SCB SHCSR: SECUREFAULTENA Mask */
+
+#define SCB_SHCSR_USGFAULTENA_Pos 18U /*!< SCB SHCSR: USGFAULTENA Position */
+#define SCB_SHCSR_USGFAULTENA_Msk (1UL << SCB_SHCSR_USGFAULTENA_Pos) /*!< SCB SHCSR: USGFAULTENA Mask */
+
+#define SCB_SHCSR_BUSFAULTENA_Pos 17U /*!< SCB SHCSR: BUSFAULTENA Position */
+#define SCB_SHCSR_BUSFAULTENA_Msk (1UL << SCB_SHCSR_BUSFAULTENA_Pos) /*!< SCB SHCSR: BUSFAULTENA Mask */
+
+#define SCB_SHCSR_MEMFAULTENA_Pos 16U /*!< SCB SHCSR: MEMFAULTENA Position */
+#define SCB_SHCSR_MEMFAULTENA_Msk (1UL << SCB_SHCSR_MEMFAULTENA_Pos) /*!< SCB SHCSR: MEMFAULTENA Mask */
+
+#define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */
+#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */
+
+#define SCB_SHCSR_BUSFAULTPENDED_Pos 14U /*!< SCB SHCSR: BUSFAULTPENDED Position */
+#define SCB_SHCSR_BUSFAULTPENDED_Msk (1UL << SCB_SHCSR_BUSFAULTPENDED_Pos) /*!< SCB SHCSR: BUSFAULTPENDED Mask */
+
+#define SCB_SHCSR_MEMFAULTPENDED_Pos 13U /*!< SCB SHCSR: MEMFAULTPENDED Position */
+#define SCB_SHCSR_MEMFAULTPENDED_Msk (1UL << SCB_SHCSR_MEMFAULTPENDED_Pos) /*!< SCB SHCSR: MEMFAULTPENDED Mask */
+
+#define SCB_SHCSR_USGFAULTPENDED_Pos 12U /*!< SCB SHCSR: USGFAULTPENDED Position */
+#define SCB_SHCSR_USGFAULTPENDED_Msk (1UL << SCB_SHCSR_USGFAULTPENDED_Pos) /*!< SCB SHCSR: USGFAULTPENDED Mask */
+
+#define SCB_SHCSR_SYSTICKACT_Pos 11U /*!< SCB SHCSR: SYSTICKACT Position */
+#define SCB_SHCSR_SYSTICKACT_Msk (1UL << SCB_SHCSR_SYSTICKACT_Pos) /*!< SCB SHCSR: SYSTICKACT Mask */
+
+#define SCB_SHCSR_PENDSVACT_Pos 10U /*!< SCB SHCSR: PENDSVACT Position */
+#define SCB_SHCSR_PENDSVACT_Msk (1UL << SCB_SHCSR_PENDSVACT_Pos) /*!< SCB SHCSR: PENDSVACT Mask */
+
+#define SCB_SHCSR_MONITORACT_Pos 8U /*!< SCB SHCSR: MONITORACT Position */
+#define SCB_SHCSR_MONITORACT_Msk (1UL << SCB_SHCSR_MONITORACT_Pos) /*!< SCB SHCSR: MONITORACT Mask */
+
+#define SCB_SHCSR_SVCALLACT_Pos 7U /*!< SCB SHCSR: SVCALLACT Position */
+#define SCB_SHCSR_SVCALLACT_Msk (1UL << SCB_SHCSR_SVCALLACT_Pos) /*!< SCB SHCSR: SVCALLACT Mask */
+
+#define SCB_SHCSR_NMIACT_Pos 5U /*!< SCB SHCSR: NMIACT Position */
+#define SCB_SHCSR_NMIACT_Msk (1UL << SCB_SHCSR_NMIACT_Pos) /*!< SCB SHCSR: NMIACT Mask */
+
+#define SCB_SHCSR_SECUREFAULTACT_Pos 4U /*!< SCB SHCSR: SECUREFAULTACT Position */
+#define SCB_SHCSR_SECUREFAULTACT_Msk (1UL << SCB_SHCSR_SECUREFAULTACT_Pos) /*!< SCB SHCSR: SECUREFAULTACT Mask */
+
+#define SCB_SHCSR_USGFAULTACT_Pos 3U /*!< SCB SHCSR: USGFAULTACT Position */
+#define SCB_SHCSR_USGFAULTACT_Msk (1UL << SCB_SHCSR_USGFAULTACT_Pos) /*!< SCB SHCSR: USGFAULTACT Mask */
+
+#define SCB_SHCSR_HARDFAULTACT_Pos 2U /*!< SCB SHCSR: HARDFAULTACT Position */
+#define SCB_SHCSR_HARDFAULTACT_Msk (1UL << SCB_SHCSR_HARDFAULTACT_Pos) /*!< SCB SHCSR: HARDFAULTACT Mask */
+
+#define SCB_SHCSR_BUSFAULTACT_Pos 1U /*!< SCB SHCSR: BUSFAULTACT Position */
+#define SCB_SHCSR_BUSFAULTACT_Msk (1UL << SCB_SHCSR_BUSFAULTACT_Pos) /*!< SCB SHCSR: BUSFAULTACT Mask */
+
+#define SCB_SHCSR_MEMFAULTACT_Pos 0U /*!< SCB SHCSR: MEMFAULTACT Position */
+#define SCB_SHCSR_MEMFAULTACT_Msk (1UL /*<< SCB_SHCSR_MEMFAULTACT_Pos*/) /*!< SCB SHCSR: MEMFAULTACT Mask */
+
+/* SCB Configurable Fault Status Register Definitions */
+#define SCB_CFSR_USGFAULTSR_Pos 16U /*!< SCB CFSR: Usage Fault Status Register Position */
+#define SCB_CFSR_USGFAULTSR_Msk (0xFFFFUL << SCB_CFSR_USGFAULTSR_Pos) /*!< SCB CFSR: Usage Fault Status Register Mask */
+
+#define SCB_CFSR_BUSFAULTSR_Pos 8U /*!< SCB CFSR: Bus Fault Status Register Position */
+#define SCB_CFSR_BUSFAULTSR_Msk (0xFFUL << SCB_CFSR_BUSFAULTSR_Pos) /*!< SCB CFSR: Bus Fault Status Register Mask */
+
+#define SCB_CFSR_MEMFAULTSR_Pos 0U /*!< SCB CFSR: Memory Manage Fault Status Register Position */
+#define SCB_CFSR_MEMFAULTSR_Msk (0xFFUL /*<< SCB_CFSR_MEMFAULTSR_Pos*/) /*!< SCB CFSR: Memory Manage Fault Status Register Mask */
+
+/* MemManage Fault Status Register (part of SCB Configurable Fault Status Register) */
+#define SCB_CFSR_MMARVALID_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 7U) /*!< SCB CFSR (MMFSR): MMARVALID Position */
+#define SCB_CFSR_MMARVALID_Msk (1UL << SCB_CFSR_MMARVALID_Pos) /*!< SCB CFSR (MMFSR): MMARVALID Mask */
+
+#define SCB_CFSR_MLSPERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 5U) /*!< SCB CFSR (MMFSR): MLSPERR Position */
+#define SCB_CFSR_MLSPERR_Msk (1UL << SCB_CFSR_MLSPERR_Pos) /*!< SCB CFSR (MMFSR): MLSPERR Mask */
+
+#define SCB_CFSR_MSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 4U) /*!< SCB CFSR (MMFSR): MSTKERR Position */
+#define SCB_CFSR_MSTKERR_Msk (1UL << SCB_CFSR_MSTKERR_Pos) /*!< SCB CFSR (MMFSR): MSTKERR Mask */
+
+#define SCB_CFSR_MUNSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 3U) /*!< SCB CFSR (MMFSR): MUNSTKERR Position */
+#define SCB_CFSR_MUNSTKERR_Msk (1UL << SCB_CFSR_MUNSTKERR_Pos) /*!< SCB CFSR (MMFSR): MUNSTKERR Mask */
+
+#define SCB_CFSR_DACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 1U) /*!< SCB CFSR (MMFSR): DACCVIOL Position */
+#define SCB_CFSR_DACCVIOL_Msk (1UL << SCB_CFSR_DACCVIOL_Pos) /*!< SCB CFSR (MMFSR): DACCVIOL Mask */
+
+#define SCB_CFSR_IACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 0U) /*!< SCB CFSR (MMFSR): IACCVIOL Position */
+#define SCB_CFSR_IACCVIOL_Msk (1UL /*<< SCB_CFSR_IACCVIOL_Pos*/) /*!< SCB CFSR (MMFSR): IACCVIOL Mask */
+
+/* BusFault Status Register (part of SCB Configurable Fault Status Register) */
+#define SCB_CFSR_BFARVALID_Pos (SCB_CFSR_BUSFAULTSR_Pos + 7U) /*!< SCB CFSR (BFSR): BFARVALID Position */
+#define SCB_CFSR_BFARVALID_Msk (1UL << SCB_CFSR_BFARVALID_Pos) /*!< SCB CFSR (BFSR): BFARVALID Mask */
+
+#define SCB_CFSR_LSPERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 5U) /*!< SCB CFSR (BFSR): LSPERR Position */
+#define SCB_CFSR_LSPERR_Msk (1UL << SCB_CFSR_LSPERR_Pos) /*!< SCB CFSR (BFSR): LSPERR Mask */
+
+#define SCB_CFSR_STKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 4U) /*!< SCB CFSR (BFSR): STKERR Position */
+#define SCB_CFSR_STKERR_Msk (1UL << SCB_CFSR_STKERR_Pos) /*!< SCB CFSR (BFSR): STKERR Mask */
+
+#define SCB_CFSR_UNSTKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 3U) /*!< SCB CFSR (BFSR): UNSTKERR Position */
+#define SCB_CFSR_UNSTKERR_Msk (1UL << SCB_CFSR_UNSTKERR_Pos) /*!< SCB CFSR (BFSR): UNSTKERR Mask */
+
+#define SCB_CFSR_IMPRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 2U) /*!< SCB CFSR (BFSR): IMPRECISERR Position */
+#define SCB_CFSR_IMPRECISERR_Msk (1UL << SCB_CFSR_IMPRECISERR_Pos) /*!< SCB CFSR (BFSR): IMPRECISERR Mask */
+
+#define SCB_CFSR_PRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 1U) /*!< SCB CFSR (BFSR): PRECISERR Position */
+#define SCB_CFSR_PRECISERR_Msk (1UL << SCB_CFSR_PRECISERR_Pos) /*!< SCB CFSR (BFSR): PRECISERR Mask */
+
+#define SCB_CFSR_IBUSERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 0U) /*!< SCB CFSR (BFSR): IBUSERR Position */
+#define SCB_CFSR_IBUSERR_Msk (1UL << SCB_CFSR_IBUSERR_Pos) /*!< SCB CFSR (BFSR): IBUSERR Mask */
+
+/* UsageFault Status Register (part of SCB Configurable Fault Status Register) */
+#define SCB_CFSR_DIVBYZERO_Pos (SCB_CFSR_USGFAULTSR_Pos + 9U) /*!< SCB CFSR (UFSR): DIVBYZERO Position */
+#define SCB_CFSR_DIVBYZERO_Msk (1UL << SCB_CFSR_DIVBYZERO_Pos) /*!< SCB CFSR (UFSR): DIVBYZERO Mask */
+
+#define SCB_CFSR_UNALIGNED_Pos (SCB_CFSR_USGFAULTSR_Pos + 8U) /*!< SCB CFSR (UFSR): UNALIGNED Position */
+#define SCB_CFSR_UNALIGNED_Msk (1UL << SCB_CFSR_UNALIGNED_Pos) /*!< SCB CFSR (UFSR): UNALIGNED Mask */
+
+#define SCB_CFSR_STKOF_Pos (SCB_CFSR_USGFAULTSR_Pos + 4U) /*!< SCB CFSR (UFSR): STKOF Position */
+#define SCB_CFSR_STKOF_Msk (1UL << SCB_CFSR_STKOF_Pos) /*!< SCB CFSR (UFSR): STKOF Mask */
+
+#define SCB_CFSR_NOCP_Pos (SCB_CFSR_USGFAULTSR_Pos + 3U) /*!< SCB CFSR (UFSR): NOCP Position */
+#define SCB_CFSR_NOCP_Msk (1UL << SCB_CFSR_NOCP_Pos) /*!< SCB CFSR (UFSR): NOCP Mask */
+
+#define SCB_CFSR_INVPC_Pos (SCB_CFSR_USGFAULTSR_Pos + 2U) /*!< SCB CFSR (UFSR): INVPC Position */
+#define SCB_CFSR_INVPC_Msk (1UL << SCB_CFSR_INVPC_Pos) /*!< SCB CFSR (UFSR): INVPC Mask */
+
+#define SCB_CFSR_INVSTATE_Pos (SCB_CFSR_USGFAULTSR_Pos + 1U) /*!< SCB CFSR (UFSR): INVSTATE Position */
+#define SCB_CFSR_INVSTATE_Msk (1UL << SCB_CFSR_INVSTATE_Pos) /*!< SCB CFSR (UFSR): INVSTATE Mask */
+
+#define SCB_CFSR_UNDEFINSTR_Pos (SCB_CFSR_USGFAULTSR_Pos + 0U) /*!< SCB CFSR (UFSR): UNDEFINSTR Position */
+#define SCB_CFSR_UNDEFINSTR_Msk (1UL << SCB_CFSR_UNDEFINSTR_Pos) /*!< SCB CFSR (UFSR): UNDEFINSTR Mask */
+
+/* SCB Hard Fault Status Register Definitions */
+#define SCB_HFSR_DEBUGEVT_Pos 31U /*!< SCB HFSR: DEBUGEVT Position */
+#define SCB_HFSR_DEBUGEVT_Msk (1UL << SCB_HFSR_DEBUGEVT_Pos) /*!< SCB HFSR: DEBUGEVT Mask */
+
+#define SCB_HFSR_FORCED_Pos 30U /*!< SCB HFSR: FORCED Position */
+#define SCB_HFSR_FORCED_Msk (1UL << SCB_HFSR_FORCED_Pos) /*!< SCB HFSR: FORCED Mask */
+
+#define SCB_HFSR_VECTTBL_Pos 1U /*!< SCB HFSR: VECTTBL Position */
+#define SCB_HFSR_VECTTBL_Msk (1UL << SCB_HFSR_VECTTBL_Pos) /*!< SCB HFSR: VECTTBL Mask */
+
+/* SCB Debug Fault Status Register Definitions */
+#define SCB_DFSR_EXTERNAL_Pos 4U /*!< SCB DFSR: EXTERNAL Position */
+#define SCB_DFSR_EXTERNAL_Msk (1UL << SCB_DFSR_EXTERNAL_Pos) /*!< SCB DFSR: EXTERNAL Mask */
+
+#define SCB_DFSR_VCATCH_Pos 3U /*!< SCB DFSR: VCATCH Position */
+#define SCB_DFSR_VCATCH_Msk (1UL << SCB_DFSR_VCATCH_Pos) /*!< SCB DFSR: VCATCH Mask */
+
+#define SCB_DFSR_DWTTRAP_Pos 2U /*!< SCB DFSR: DWTTRAP Position */
+#define SCB_DFSR_DWTTRAP_Msk (1UL << SCB_DFSR_DWTTRAP_Pos) /*!< SCB DFSR: DWTTRAP Mask */
+
+#define SCB_DFSR_BKPT_Pos 1U /*!< SCB DFSR: BKPT Position */
+#define SCB_DFSR_BKPT_Msk (1UL << SCB_DFSR_BKPT_Pos) /*!< SCB DFSR: BKPT Mask */
+
+#define SCB_DFSR_HALTED_Pos 0U /*!< SCB DFSR: HALTED Position */
+#define SCB_DFSR_HALTED_Msk (1UL /*<< SCB_DFSR_HALTED_Pos*/) /*!< SCB DFSR: HALTED Mask */
+
+/* SCB Non-Secure Access Control Register Definitions */
+#define SCB_NSACR_CP11_Pos 11U /*!< SCB NSACR: CP11 Position */
+#define SCB_NSACR_CP11_Msk (1UL << SCB_NSACR_CP11_Pos) /*!< SCB NSACR: CP11 Mask */
+
+#define SCB_NSACR_CP10_Pos 10U /*!< SCB NSACR: CP10 Position */
+#define SCB_NSACR_CP10_Msk (1UL << SCB_NSACR_CP10_Pos) /*!< SCB NSACR: CP10 Mask */
+
+#define SCB_NSACR_CPn_Pos 0U /*!< SCB NSACR: CPn Position */
+#define SCB_NSACR_CPn_Msk (1UL /*<< SCB_NSACR_CPn_Pos*/) /*!< SCB NSACR: CPn Mask */
+
+/* SCB Cache Level ID Register Definitions */
+#define SCB_CLIDR_LOUU_Pos 27U /*!< SCB CLIDR: LoUU Position */
+#define SCB_CLIDR_LOUU_Msk (7UL << SCB_CLIDR_LOUU_Pos) /*!< SCB CLIDR: LoUU Mask */
+
+#define SCB_CLIDR_LOC_Pos 24U /*!< SCB CLIDR: LoC Position */
+#define SCB_CLIDR_LOC_Msk (7UL << SCB_CLIDR_LOC_Pos) /*!< SCB CLIDR: LoC Mask */
+
+/* SCB Cache Type Register Definitions */
+#define SCB_CTR_FORMAT_Pos 29U /*!< SCB CTR: Format Position */
+#define SCB_CTR_FORMAT_Msk (7UL << SCB_CTR_FORMAT_Pos) /*!< SCB CTR: Format Mask */
+
+#define SCB_CTR_CWG_Pos 24U /*!< SCB CTR: CWG Position */
+#define SCB_CTR_CWG_Msk (0xFUL << SCB_CTR_CWG_Pos) /*!< SCB CTR: CWG Mask */
+
+#define SCB_CTR_ERG_Pos 20U /*!< SCB CTR: ERG Position */
+#define SCB_CTR_ERG_Msk (0xFUL << SCB_CTR_ERG_Pos) /*!< SCB CTR: ERG Mask */
+
+#define SCB_CTR_DMINLINE_Pos 16U /*!< SCB CTR: DminLine Position */
+#define SCB_CTR_DMINLINE_Msk (0xFUL << SCB_CTR_DMINLINE_Pos) /*!< SCB CTR: DminLine Mask */
+
+#define SCB_CTR_IMINLINE_Pos 0U /*!< SCB CTR: ImInLine Position */
+#define SCB_CTR_IMINLINE_Msk (0xFUL /*<< SCB_CTR_IMINLINE_Pos*/) /*!< SCB CTR: ImInLine Mask */
+
+/* SCB Cache Size ID Register Definitions */
+#define SCB_CCSIDR_WT_Pos 31U /*!< SCB CCSIDR: WT Position */
+#define SCB_CCSIDR_WT_Msk (1UL << SCB_CCSIDR_WT_Pos) /*!< SCB CCSIDR: WT Mask */
+
+#define SCB_CCSIDR_WB_Pos 30U /*!< SCB CCSIDR: WB Position */
+#define SCB_CCSIDR_WB_Msk (1UL << SCB_CCSIDR_WB_Pos) /*!< SCB CCSIDR: WB Mask */
+
+#define SCB_CCSIDR_RA_Pos 29U /*!< SCB CCSIDR: RA Position */
+#define SCB_CCSIDR_RA_Msk (1UL << SCB_CCSIDR_RA_Pos) /*!< SCB CCSIDR: RA Mask */
+
+#define SCB_CCSIDR_WA_Pos 28U /*!< SCB CCSIDR: WA Position */
+#define SCB_CCSIDR_WA_Msk (1UL << SCB_CCSIDR_WA_Pos) /*!< SCB CCSIDR: WA Mask */
+
+#define SCB_CCSIDR_NUMSETS_Pos 13U /*!< SCB CCSIDR: NumSets Position */
+#define SCB_CCSIDR_NUMSETS_Msk (0x7FFFUL << SCB_CCSIDR_NUMSETS_Pos) /*!< SCB CCSIDR: NumSets Mask */
+
+#define SCB_CCSIDR_ASSOCIATIVITY_Pos 3U /*!< SCB CCSIDR: Associativity Position */
+#define SCB_CCSIDR_ASSOCIATIVITY_Msk (0x3FFUL << SCB_CCSIDR_ASSOCIATIVITY_Pos) /*!< SCB CCSIDR: Associativity Mask */
+
+#define SCB_CCSIDR_LINESIZE_Pos 0U /*!< SCB CCSIDR: LineSize Position */
+#define SCB_CCSIDR_LINESIZE_Msk (7UL /*<< SCB_CCSIDR_LINESIZE_Pos*/) /*!< SCB CCSIDR: LineSize Mask */
+
+/* SCB Cache Size Selection Register Definitions */
+#define SCB_CSSELR_LEVEL_Pos 1U /*!< SCB CSSELR: Level Position */
+#define SCB_CSSELR_LEVEL_Msk (7UL << SCB_CSSELR_LEVEL_Pos) /*!< SCB CSSELR: Level Mask */
+
+#define SCB_CSSELR_IND_Pos 0U /*!< SCB CSSELR: InD Position */
+#define SCB_CSSELR_IND_Msk (1UL /*<< SCB_CSSELR_IND_Pos*/) /*!< SCB CSSELR: InD Mask */
+
+/* SCB Software Triggered Interrupt Register Definitions */
+#define SCB_STIR_INTID_Pos 0U /*!< SCB STIR: INTID Position */
+#define SCB_STIR_INTID_Msk (0x1FFUL /*<< SCB_STIR_INTID_Pos*/) /*!< SCB STIR: INTID Mask */
+
+/* SCB D-Cache Invalidate by Set-way Register Definitions */
+#define SCB_DCISW_WAY_Pos 30U /*!< SCB DCISW: Way Position */
+#define SCB_DCISW_WAY_Msk (3UL << SCB_DCISW_WAY_Pos) /*!< SCB DCISW: Way Mask */
+
+#define SCB_DCISW_SET_Pos 5U /*!< SCB DCISW: Set Position */
+#define SCB_DCISW_SET_Msk (0x1FFUL << SCB_DCISW_SET_Pos) /*!< SCB DCISW: Set Mask */
+
+/* SCB D-Cache Clean by Set-way Register Definitions */
+#define SCB_DCCSW_WAY_Pos 30U /*!< SCB DCCSW: Way Position */
+#define SCB_DCCSW_WAY_Msk (3UL << SCB_DCCSW_WAY_Pos) /*!< SCB DCCSW: Way Mask */
+
+#define SCB_DCCSW_SET_Pos 5U /*!< SCB DCCSW: Set Position */
+#define SCB_DCCSW_SET_Msk (0x1FFUL << SCB_DCCSW_SET_Pos) /*!< SCB DCCSW: Set Mask */
+
+/* SCB D-Cache Clean and Invalidate by Set-way Register Definitions */
+#define SCB_DCCISW_WAY_Pos 30U /*!< SCB DCCISW: Way Position */
+#define SCB_DCCISW_WAY_Msk (3UL << SCB_DCCISW_WAY_Pos) /*!< SCB DCCISW: Way Mask */
+
+#define SCB_DCCISW_SET_Pos 5U /*!< SCB DCCISW: Set Position */
+#define SCB_DCCISW_SET_Msk (0x1FFUL << SCB_DCCISW_SET_Pos) /*!< SCB DCCISW: Set Mask */
+
+/*@} end of group CMSIS_SCB */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_SCnSCB System Controls not in SCB (SCnSCB)
+ \brief Type definitions for the System Control and ID Register not in the SCB
+ @{
+ */
+
+/**
+ \brief Structure type to access the System Control and ID Register not in the SCB.
+ */
+typedef struct
+{
+ uint32_t RESERVED0[1U];
+ __IM uint32_t ICTR; /*!< Offset: 0x004 (R/ ) Interrupt Controller Type Register */
+ __IOM uint32_t ACTLR; /*!< Offset: 0x008 (R/W) Auxiliary Control Register */
+ __IOM uint32_t CPPWR; /*!< Offset: 0x00C (R/W) Coprocessor Power Control Register */
+} SCnSCB_Type;
+
+/* Interrupt Controller Type Register Definitions */
+#define SCnSCB_ICTR_INTLINESNUM_Pos 0U /*!< ICTR: INTLINESNUM Position */
+#define SCnSCB_ICTR_INTLINESNUM_Msk (0xFUL /*<< SCnSCB_ICTR_INTLINESNUM_Pos*/) /*!< ICTR: INTLINESNUM Mask */
+
+/*@} end of group CMSIS_SCnotSCB */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_SysTick System Tick Timer (SysTick)
+ \brief Type definitions for the System Timer Registers.
+ @{
+ */
+
+/**
+ \brief Structure type to access the System Timer (SysTick).
+ */
+typedef struct
+{
+ __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */
+ __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */
+ __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */
+ __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */
+} SysTick_Type;
+
+/* SysTick Control / Status Register Definitions */
+#define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */
+#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */
+
+#define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */
+#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */
+
+#define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */
+#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */
+
+#define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */
+#define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */
+
+/* SysTick Reload Register Definitions */
+#define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */
+#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */
+
+/* SysTick Current Register Definitions */
+#define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */
+#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */
+
+/* SysTick Calibration Register Definitions */
+#define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */
+#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */
+
+#define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */
+#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */
+
+#define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */
+#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */
+
+/*@} end of group CMSIS_SysTick */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_ITM Instrumentation Trace Macrocell (ITM)
+ \brief Type definitions for the Instrumentation Trace Macrocell (ITM)
+ @{
+ */
+
+/**
+ \brief Structure type to access the Instrumentation Trace Macrocell Register (ITM).
+ */
+typedef struct
+{
+ __OM union
+ {
+ __OM uint8_t u8; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 8-bit */
+ __OM uint16_t u16; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 16-bit */
+ __OM uint32_t u32; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 32-bit */
+ } PORT [32U]; /*!< Offset: 0x000 ( /W) ITM Stimulus Port Registers */
+ uint32_t RESERVED0[864U];
+ __IOM uint32_t TER; /*!< Offset: 0xE00 (R/W) ITM Trace Enable Register */
+ uint32_t RESERVED1[15U];
+ __IOM uint32_t TPR; /*!< Offset: 0xE40 (R/W) ITM Trace Privilege Register */
+ uint32_t RESERVED2[15U];
+ __IOM uint32_t TCR; /*!< Offset: 0xE80 (R/W) ITM Trace Control Register */
+ uint32_t RESERVED3[32U];
+ uint32_t RESERVED4[43U];
+ __OM uint32_t LAR; /*!< Offset: 0xFB0 ( /W) ITM Lock Access Register */
+ __IM uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) ITM Lock Status Register */
+ uint32_t RESERVED5[1U];
+ __IM uint32_t DEVARCH; /*!< Offset: 0xFBC (R/ ) ITM Device Architecture Register */
+ uint32_t RESERVED6[4U];
+ __IM uint32_t PID4; /*!< Offset: 0xFD0 (R/ ) ITM Peripheral Identification Register #4 */
+ __IM uint32_t PID5; /*!< Offset: 0xFD4 (R/ ) ITM Peripheral Identification Register #5 */
+ __IM uint32_t PID6; /*!< Offset: 0xFD8 (R/ ) ITM Peripheral Identification Register #6 */
+ __IM uint32_t PID7; /*!< Offset: 0xFDC (R/ ) ITM Peripheral Identification Register #7 */
+ __IM uint32_t PID0; /*!< Offset: 0xFE0 (R/ ) ITM Peripheral Identification Register #0 */
+ __IM uint32_t PID1; /*!< Offset: 0xFE4 (R/ ) ITM Peripheral Identification Register #1 */
+ __IM uint32_t PID2; /*!< Offset: 0xFE8 (R/ ) ITM Peripheral Identification Register #2 */
+ __IM uint32_t PID3; /*!< Offset: 0xFEC (R/ ) ITM Peripheral Identification Register #3 */
+ __IM uint32_t CID0; /*!< Offset: 0xFF0 (R/ ) ITM Component Identification Register #0 */
+ __IM uint32_t CID1; /*!< Offset: 0xFF4 (R/ ) ITM Component Identification Register #1 */
+ __IM uint32_t CID2; /*!< Offset: 0xFF8 (R/ ) ITM Component Identification Register #2 */
+ __IM uint32_t CID3; /*!< Offset: 0xFFC (R/ ) ITM Component Identification Register #3 */
+} ITM_Type;
+
+/* ITM Stimulus Port Register Definitions */
+#define ITM_STIM_DISABLED_Pos 1U /*!< ITM STIM: DISABLED Position */
+#define ITM_STIM_DISABLED_Msk (0x1UL << ITM_STIM_DISABLED_Pos) /*!< ITM STIM: DISABLED Mask */
+
+#define ITM_STIM_FIFOREADY_Pos 0U /*!< ITM STIM: FIFOREADY Position */
+#define ITM_STIM_FIFOREADY_Msk (0x1UL /*<< ITM_STIM_FIFOREADY_Pos*/) /*!< ITM STIM: FIFOREADY Mask */
+
+/* ITM Trace Privilege Register Definitions */
+#define ITM_TPR_PRIVMASK_Pos 0U /*!< ITM TPR: PRIVMASK Position */
+#define ITM_TPR_PRIVMASK_Msk (0xFUL /*<< ITM_TPR_PRIVMASK_Pos*/) /*!< ITM TPR: PRIVMASK Mask */
+
+/* ITM Trace Control Register Definitions */
+#define ITM_TCR_BUSY_Pos 23U /*!< ITM TCR: BUSY Position */
+#define ITM_TCR_BUSY_Msk (1UL << ITM_TCR_BUSY_Pos) /*!< ITM TCR: BUSY Mask */
+
+#define ITM_TCR_TRACEBUSID_Pos 16U /*!< ITM TCR: ATBID Position */
+#define ITM_TCR_TRACEBUSID_Msk (0x7FUL << ITM_TCR_TRACEBUSID_Pos) /*!< ITM TCR: ATBID Mask */
+
+#define ITM_TCR_GTSFREQ_Pos 10U /*!< ITM TCR: Global timestamp frequency Position */
+#define ITM_TCR_GTSFREQ_Msk (3UL << ITM_TCR_GTSFREQ_Pos) /*!< ITM TCR: Global timestamp frequency Mask */
+
+#define ITM_TCR_TSPRESCALE_Pos 8U /*!< ITM TCR: TSPRESCALE Position */
+#define ITM_TCR_TSPRESCALE_Msk (3UL << ITM_TCR_TSPRESCALE_Pos) /*!< ITM TCR: TSPRESCALE Mask */
+
+#define ITM_TCR_STALLENA_Pos 5U /*!< ITM TCR: STALLENA Position */
+#define ITM_TCR_STALLENA_Msk (1UL << ITM_TCR_STALLENA_Pos) /*!< ITM TCR: STALLENA Mask */
+
+#define ITM_TCR_SWOENA_Pos 4U /*!< ITM TCR: SWOENA Position */
+#define ITM_TCR_SWOENA_Msk (1UL << ITM_TCR_SWOENA_Pos) /*!< ITM TCR: SWOENA Mask */
+
+#define ITM_TCR_DWTENA_Pos 3U /*!< ITM TCR: DWTENA Position */
+#define ITM_TCR_DWTENA_Msk (1UL << ITM_TCR_DWTENA_Pos) /*!< ITM TCR: DWTENA Mask */
+
+#define ITM_TCR_SYNCENA_Pos 2U /*!< ITM TCR: SYNCENA Position */
+#define ITM_TCR_SYNCENA_Msk (1UL << ITM_TCR_SYNCENA_Pos) /*!< ITM TCR: SYNCENA Mask */
+
+#define ITM_TCR_TSENA_Pos 1U /*!< ITM TCR: TSENA Position */
+#define ITM_TCR_TSENA_Msk (1UL << ITM_TCR_TSENA_Pos) /*!< ITM TCR: TSENA Mask */
+
+#define ITM_TCR_ITMENA_Pos 0U /*!< ITM TCR: ITM Enable bit Position */
+#define ITM_TCR_ITMENA_Msk (1UL /*<< ITM_TCR_ITMENA_Pos*/) /*!< ITM TCR: ITM Enable bit Mask */
+
+/* ITM Lock Status Register Definitions */
+#define ITM_LSR_ByteAcc_Pos 2U /*!< ITM LSR: ByteAcc Position */
+#define ITM_LSR_ByteAcc_Msk (1UL << ITM_LSR_ByteAcc_Pos) /*!< ITM LSR: ByteAcc Mask */
+
+#define ITM_LSR_Access_Pos 1U /*!< ITM LSR: Access Position */
+#define ITM_LSR_Access_Msk (1UL << ITM_LSR_Access_Pos) /*!< ITM LSR: Access Mask */
+
+#define ITM_LSR_Present_Pos 0U /*!< ITM LSR: Present Position */
+#define ITM_LSR_Present_Msk (1UL /*<< ITM_LSR_Present_Pos*/) /*!< ITM LSR: Present Mask */
+
+/*@}*/ /* end of group CMSIS_ITM */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_DWT Data Watchpoint and Trace (DWT)
+ \brief Type definitions for the Data Watchpoint and Trace (DWT)
+ @{
+ */
+
+/**
+ \brief Structure type to access the Data Watchpoint and Trace Register (DWT).
+ */
+typedef struct
+{
+ __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) Control Register */
+ __IOM uint32_t CYCCNT; /*!< Offset: 0x004 (R/W) Cycle Count Register */
+ __IOM uint32_t CPICNT; /*!< Offset: 0x008 (R/W) CPI Count Register */
+ __IOM uint32_t EXCCNT; /*!< Offset: 0x00C (R/W) Exception Overhead Count Register */
+ __IOM uint32_t SLEEPCNT; /*!< Offset: 0x010 (R/W) Sleep Count Register */
+ __IOM uint32_t LSUCNT; /*!< Offset: 0x014 (R/W) LSU Count Register */
+ __IOM uint32_t FOLDCNT; /*!< Offset: 0x018 (R/W) Folded-instruction Count Register */
+ __IM uint32_t PCSR; /*!< Offset: 0x01C (R/ ) Program Counter Sample Register */
+ __IOM uint32_t COMP0; /*!< Offset: 0x020 (R/W) Comparator Register 0 */
+ uint32_t RESERVED1[1U];
+ __IOM uint32_t FUNCTION0; /*!< Offset: 0x028 (R/W) Function Register 0 */
+ uint32_t RESERVED2[1U];
+ __IOM uint32_t COMP1; /*!< Offset: 0x030 (R/W) Comparator Register 1 */
+ uint32_t RESERVED3[1U];
+ __IOM uint32_t FUNCTION1; /*!< Offset: 0x038 (R/W) Function Register 1 */
+ uint32_t RESERVED4[1U];
+ __IOM uint32_t COMP2; /*!< Offset: 0x040 (R/W) Comparator Register 2 */
+ uint32_t RESERVED5[1U];
+ __IOM uint32_t FUNCTION2; /*!< Offset: 0x048 (R/W) Function Register 2 */
+ uint32_t RESERVED6[1U];
+ __IOM uint32_t COMP3; /*!< Offset: 0x050 (R/W) Comparator Register 3 */
+ uint32_t RESERVED7[1U];
+ __IOM uint32_t FUNCTION3; /*!< Offset: 0x058 (R/W) Function Register 3 */
+ uint32_t RESERVED8[1U];
+ __IOM uint32_t COMP4; /*!< Offset: 0x060 (R/W) Comparator Register 4 */
+ uint32_t RESERVED9[1U];
+ __IOM uint32_t FUNCTION4; /*!< Offset: 0x068 (R/W) Function Register 4 */
+ uint32_t RESERVED10[1U];
+ __IOM uint32_t COMP5; /*!< Offset: 0x070 (R/W) Comparator Register 5 */
+ uint32_t RESERVED11[1U];
+ __IOM uint32_t FUNCTION5; /*!< Offset: 0x078 (R/W) Function Register 5 */
+ uint32_t RESERVED12[1U];
+ __IOM uint32_t COMP6; /*!< Offset: 0x080 (R/W) Comparator Register 6 */
+ uint32_t RESERVED13[1U];
+ __IOM uint32_t FUNCTION6; /*!< Offset: 0x088 (R/W) Function Register 6 */
+ uint32_t RESERVED14[1U];
+ __IOM uint32_t COMP7; /*!< Offset: 0x090 (R/W) Comparator Register 7 */
+ uint32_t RESERVED15[1U];
+ __IOM uint32_t FUNCTION7; /*!< Offset: 0x098 (R/W) Function Register 7 */
+ uint32_t RESERVED16[1U];
+ __IOM uint32_t COMP8; /*!< Offset: 0x0A0 (R/W) Comparator Register 8 */
+ uint32_t RESERVED17[1U];
+ __IOM uint32_t FUNCTION8; /*!< Offset: 0x0A8 (R/W) Function Register 8 */
+ uint32_t RESERVED18[1U];
+ __IOM uint32_t COMP9; /*!< Offset: 0x0B0 (R/W) Comparator Register 9 */
+ uint32_t RESERVED19[1U];
+ __IOM uint32_t FUNCTION9; /*!< Offset: 0x0B8 (R/W) Function Register 9 */
+ uint32_t RESERVED20[1U];
+ __IOM uint32_t COMP10; /*!< Offset: 0x0C0 (R/W) Comparator Register 10 */
+ uint32_t RESERVED21[1U];
+ __IOM uint32_t FUNCTION10; /*!< Offset: 0x0C8 (R/W) Function Register 10 */
+ uint32_t RESERVED22[1U];
+ __IOM uint32_t COMP11; /*!< Offset: 0x0D0 (R/W) Comparator Register 11 */
+ uint32_t RESERVED23[1U];
+ __IOM uint32_t FUNCTION11; /*!< Offset: 0x0D8 (R/W) Function Register 11 */
+ uint32_t RESERVED24[1U];
+ __IOM uint32_t COMP12; /*!< Offset: 0x0E0 (R/W) Comparator Register 12 */
+ uint32_t RESERVED25[1U];
+ __IOM uint32_t FUNCTION12; /*!< Offset: 0x0E8 (R/W) Function Register 12 */
+ uint32_t RESERVED26[1U];
+ __IOM uint32_t COMP13; /*!< Offset: 0x0F0 (R/W) Comparator Register 13 */
+ uint32_t RESERVED27[1U];
+ __IOM uint32_t FUNCTION13; /*!< Offset: 0x0F8 (R/W) Function Register 13 */
+ uint32_t RESERVED28[1U];
+ __IOM uint32_t COMP14; /*!< Offset: 0x100 (R/W) Comparator Register 14 */
+ uint32_t RESERVED29[1U];
+ __IOM uint32_t FUNCTION14; /*!< Offset: 0x108 (R/W) Function Register 14 */
+ uint32_t RESERVED30[1U];
+ __IOM uint32_t COMP15; /*!< Offset: 0x110 (R/W) Comparator Register 15 */
+ uint32_t RESERVED31[1U];
+ __IOM uint32_t FUNCTION15; /*!< Offset: 0x118 (R/W) Function Register 15 */
+ uint32_t RESERVED32[934U];
+ __IM uint32_t LSR; /*!< Offset: 0xFB4 (R ) Lock Status Register */
+ uint32_t RESERVED33[1U];
+ __IM uint32_t DEVARCH; /*!< Offset: 0xFBC (R/ ) Device Architecture Register */
+} DWT_Type;
+
+/* DWT Control Register Definitions */
+#define DWT_CTRL_NUMCOMP_Pos 28U /*!< DWT CTRL: NUMCOMP Position */
+#define DWT_CTRL_NUMCOMP_Msk (0xFUL << DWT_CTRL_NUMCOMP_Pos) /*!< DWT CTRL: NUMCOMP Mask */
+
+#define DWT_CTRL_NOTRCPKT_Pos 27U /*!< DWT CTRL: NOTRCPKT Position */
+#define DWT_CTRL_NOTRCPKT_Msk (0x1UL << DWT_CTRL_NOTRCPKT_Pos) /*!< DWT CTRL: NOTRCPKT Mask */
+
+#define DWT_CTRL_NOEXTTRIG_Pos 26U /*!< DWT CTRL: NOEXTTRIG Position */
+#define DWT_CTRL_NOEXTTRIG_Msk (0x1UL << DWT_CTRL_NOEXTTRIG_Pos) /*!< DWT CTRL: NOEXTTRIG Mask */
+
+#define DWT_CTRL_NOCYCCNT_Pos 25U /*!< DWT CTRL: NOCYCCNT Position */
+#define DWT_CTRL_NOCYCCNT_Msk (0x1UL << DWT_CTRL_NOCYCCNT_Pos) /*!< DWT CTRL: NOCYCCNT Mask */
+
+#define DWT_CTRL_NOPRFCNT_Pos 24U /*!< DWT CTRL: NOPRFCNT Position */
+#define DWT_CTRL_NOPRFCNT_Msk (0x1UL << DWT_CTRL_NOPRFCNT_Pos) /*!< DWT CTRL: NOPRFCNT Mask */
+
+#define DWT_CTRL_CYCDISS_Pos 23U /*!< DWT CTRL: CYCDISS Position */
+#define DWT_CTRL_CYCDISS_Msk (0x1UL << DWT_CTRL_CYCDISS_Pos) /*!< DWT CTRL: CYCDISS Mask */
+
+#define DWT_CTRL_CYCEVTENA_Pos 22U /*!< DWT CTRL: CYCEVTENA Position */
+#define DWT_CTRL_CYCEVTENA_Msk (0x1UL << DWT_CTRL_CYCEVTENA_Pos) /*!< DWT CTRL: CYCEVTENA Mask */
+
+#define DWT_CTRL_FOLDEVTENA_Pos 21U /*!< DWT CTRL: FOLDEVTENA Position */
+#define DWT_CTRL_FOLDEVTENA_Msk (0x1UL << DWT_CTRL_FOLDEVTENA_Pos) /*!< DWT CTRL: FOLDEVTENA Mask */
+
+#define DWT_CTRL_LSUEVTENA_Pos 20U /*!< DWT CTRL: LSUEVTENA Position */
+#define DWT_CTRL_LSUEVTENA_Msk (0x1UL << DWT_CTRL_LSUEVTENA_Pos) /*!< DWT CTRL: LSUEVTENA Mask */
+
+#define DWT_CTRL_SLEEPEVTENA_Pos 19U /*!< DWT CTRL: SLEEPEVTENA Position */
+#define DWT_CTRL_SLEEPEVTENA_Msk (0x1UL << DWT_CTRL_SLEEPEVTENA_Pos) /*!< DWT CTRL: SLEEPEVTENA Mask */
+
+#define DWT_CTRL_EXCEVTENA_Pos 18U /*!< DWT CTRL: EXCEVTENA Position */
+#define DWT_CTRL_EXCEVTENA_Msk (0x1UL << DWT_CTRL_EXCEVTENA_Pos) /*!< DWT CTRL: EXCEVTENA Mask */
+
+#define DWT_CTRL_CPIEVTENA_Pos 17U /*!< DWT CTRL: CPIEVTENA Position */
+#define DWT_CTRL_CPIEVTENA_Msk (0x1UL << DWT_CTRL_CPIEVTENA_Pos) /*!< DWT CTRL: CPIEVTENA Mask */
+
+#define DWT_CTRL_EXCTRCENA_Pos 16U /*!< DWT CTRL: EXCTRCENA Position */
+#define DWT_CTRL_EXCTRCENA_Msk (0x1UL << DWT_CTRL_EXCTRCENA_Pos) /*!< DWT CTRL: EXCTRCENA Mask */
+
+#define DWT_CTRL_PCSAMPLENA_Pos 12U /*!< DWT CTRL: PCSAMPLENA Position */
+#define DWT_CTRL_PCSAMPLENA_Msk (0x1UL << DWT_CTRL_PCSAMPLENA_Pos) /*!< DWT CTRL: PCSAMPLENA Mask */
+
+#define DWT_CTRL_SYNCTAP_Pos 10U /*!< DWT CTRL: SYNCTAP Position */
+#define DWT_CTRL_SYNCTAP_Msk (0x3UL << DWT_CTRL_SYNCTAP_Pos) /*!< DWT CTRL: SYNCTAP Mask */
+
+#define DWT_CTRL_CYCTAP_Pos 9U /*!< DWT CTRL: CYCTAP Position */
+#define DWT_CTRL_CYCTAP_Msk (0x1UL << DWT_CTRL_CYCTAP_Pos) /*!< DWT CTRL: CYCTAP Mask */
+
+#define DWT_CTRL_POSTINIT_Pos 5U /*!< DWT CTRL: POSTINIT Position */
+#define DWT_CTRL_POSTINIT_Msk (0xFUL << DWT_CTRL_POSTINIT_Pos) /*!< DWT CTRL: POSTINIT Mask */
+
+#define DWT_CTRL_POSTPRESET_Pos 1U /*!< DWT CTRL: POSTPRESET Position */
+#define DWT_CTRL_POSTPRESET_Msk (0xFUL << DWT_CTRL_POSTPRESET_Pos) /*!< DWT CTRL: POSTPRESET Mask */
+
+#define DWT_CTRL_CYCCNTENA_Pos 0U /*!< DWT CTRL: CYCCNTENA Position */
+#define DWT_CTRL_CYCCNTENA_Msk (0x1UL /*<< DWT_CTRL_CYCCNTENA_Pos*/) /*!< DWT CTRL: CYCCNTENA Mask */
+
+/* DWT CPI Count Register Definitions */
+#define DWT_CPICNT_CPICNT_Pos 0U /*!< DWT CPICNT: CPICNT Position */
+#define DWT_CPICNT_CPICNT_Msk (0xFFUL /*<< DWT_CPICNT_CPICNT_Pos*/) /*!< DWT CPICNT: CPICNT Mask */
+
+/* DWT Exception Overhead Count Register Definitions */
+#define DWT_EXCCNT_EXCCNT_Pos 0U /*!< DWT EXCCNT: EXCCNT Position */
+#define DWT_EXCCNT_EXCCNT_Msk (0xFFUL /*<< DWT_EXCCNT_EXCCNT_Pos*/) /*!< DWT EXCCNT: EXCCNT Mask */
+
+/* DWT Sleep Count Register Definitions */
+#define DWT_SLEEPCNT_SLEEPCNT_Pos 0U /*!< DWT SLEEPCNT: SLEEPCNT Position */
+#define DWT_SLEEPCNT_SLEEPCNT_Msk (0xFFUL /*<< DWT_SLEEPCNT_SLEEPCNT_Pos*/) /*!< DWT SLEEPCNT: SLEEPCNT Mask */
+
+/* DWT LSU Count Register Definitions */
+#define DWT_LSUCNT_LSUCNT_Pos 0U /*!< DWT LSUCNT: LSUCNT Position */
+#define DWT_LSUCNT_LSUCNT_Msk (0xFFUL /*<< DWT_LSUCNT_LSUCNT_Pos*/) /*!< DWT LSUCNT: LSUCNT Mask */
+
+/* DWT Folded-instruction Count Register Definitions */
+#define DWT_FOLDCNT_FOLDCNT_Pos 0U /*!< DWT FOLDCNT: FOLDCNT Position */
+#define DWT_FOLDCNT_FOLDCNT_Msk (0xFFUL /*<< DWT_FOLDCNT_FOLDCNT_Pos*/) /*!< DWT FOLDCNT: FOLDCNT Mask */
+
+/* DWT Comparator Function Register Definitions */
+#define DWT_FUNCTION_ID_Pos 27U /*!< DWT FUNCTION: ID Position */
+#define DWT_FUNCTION_ID_Msk (0x1FUL << DWT_FUNCTION_ID_Pos) /*!< DWT FUNCTION: ID Mask */
+
+#define DWT_FUNCTION_MATCHED_Pos 24U /*!< DWT FUNCTION: MATCHED Position */
+#define DWT_FUNCTION_MATCHED_Msk (0x1UL << DWT_FUNCTION_MATCHED_Pos) /*!< DWT FUNCTION: MATCHED Mask */
+
+#define DWT_FUNCTION_DATAVSIZE_Pos 10U /*!< DWT FUNCTION: DATAVSIZE Position */
+#define DWT_FUNCTION_DATAVSIZE_Msk (0x3UL << DWT_FUNCTION_DATAVSIZE_Pos) /*!< DWT FUNCTION: DATAVSIZE Mask */
+
+#define DWT_FUNCTION_ACTION_Pos 4U /*!< DWT FUNCTION: ACTION Position */
+#define DWT_FUNCTION_ACTION_Msk (0x1UL << DWT_FUNCTION_ACTION_Pos) /*!< DWT FUNCTION: ACTION Mask */
+
+#define DWT_FUNCTION_MATCH_Pos 0U /*!< DWT FUNCTION: MATCH Position */
+#define DWT_FUNCTION_MATCH_Msk (0xFUL /*<< DWT_FUNCTION_MATCH_Pos*/) /*!< DWT FUNCTION: MATCH Mask */
+
+/*@}*/ /* end of group CMSIS_DWT */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_TPI Trace Port Interface (TPI)
+ \brief Type definitions for the Trace Port Interface (TPI)
+ @{
+ */
+
+/**
+ \brief Structure type to access the Trace Port Interface Register (TPI).
+ */
+typedef struct
+{
+ __IM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Sizes Register */
+ __IOM uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Sizes Register */
+ uint32_t RESERVED0[2U];
+ __IOM uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */
+ uint32_t RESERVED1[55U];
+ __IOM uint32_t SPPR; /*!< Offset: 0x0F0 (R/W) Selected Pin Protocol Register */
+ uint32_t RESERVED2[131U];
+ __IM uint32_t FFSR; /*!< Offset: 0x300 (R/ ) Formatter and Flush Status Register */
+ __IOM uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */
+ __IOM uint32_t PSCR; /*!< Offset: 0x308 (R/W) Periodic Synchronization Control Register */
+ uint32_t RESERVED3[809U];
+ __OM uint32_t LAR; /*!< Offset: 0xFB0 ( /W) Software Lock Access Register */
+ __IM uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) Software Lock Status Register */
+ uint32_t RESERVED4[4U];
+ __IM uint32_t TYPE; /*!< Offset: 0xFC8 (R/ ) Device Identifier Register */
+ __IM uint32_t DEVTYPE; /*!< Offset: 0xFCC (R/ ) Device Type Register */
+} TPI_Type;
+
+/* TPI Asynchronous Clock Prescaler Register Definitions */
+#define TPI_ACPR_SWOSCALER_Pos 0U /*!< TPI ACPR: SWOSCALER Position */
+#define TPI_ACPR_SWOSCALER_Msk (0xFFFFUL /*<< TPI_ACPR_SWOSCALER_Pos*/) /*!< TPI ACPR: SWOSCALER Mask */
+
+/* TPI Selected Pin Protocol Register Definitions */
+#define TPI_SPPR_TXMODE_Pos 0U /*!< TPI SPPR: TXMODE Position */
+#define TPI_SPPR_TXMODE_Msk (0x3UL /*<< TPI_SPPR_TXMODE_Pos*/) /*!< TPI SPPR: TXMODE Mask */
+
+/* TPI Formatter and Flush Status Register Definitions */
+#define TPI_FFSR_FtNonStop_Pos 3U /*!< TPI FFSR: FtNonStop Position */
+#define TPI_FFSR_FtNonStop_Msk (0x1UL << TPI_FFSR_FtNonStop_Pos) /*!< TPI FFSR: FtNonStop Mask */
+
+#define TPI_FFSR_TCPresent_Pos 2U /*!< TPI FFSR: TCPresent Position */
+#define TPI_FFSR_TCPresent_Msk (0x1UL << TPI_FFSR_TCPresent_Pos) /*!< TPI FFSR: TCPresent Mask */
+
+#define TPI_FFSR_FtStopped_Pos 1U /*!< TPI FFSR: FtStopped Position */
+#define TPI_FFSR_FtStopped_Msk (0x1UL << TPI_FFSR_FtStopped_Pos) /*!< TPI FFSR: FtStopped Mask */
+
+#define TPI_FFSR_FlInProg_Pos 0U /*!< TPI FFSR: FlInProg Position */
+#define TPI_FFSR_FlInProg_Msk (0x1UL /*<< TPI_FFSR_FlInProg_Pos*/) /*!< TPI FFSR: FlInProg Mask */
+
+/* TPI Formatter and Flush Control Register Definitions */
+#define TPI_FFCR_TrigIn_Pos 8U /*!< TPI FFCR: TrigIn Position */
+#define TPI_FFCR_TrigIn_Msk (0x1UL << TPI_FFCR_TrigIn_Pos) /*!< TPI FFCR: TrigIn Mask */
+
+#define TPI_FFCR_FOnMan_Pos 6U /*!< TPI FFCR: FOnMan Position */
+#define TPI_FFCR_FOnMan_Msk (0x1UL << TPI_FFCR_FOnMan_Pos) /*!< TPI FFCR: FOnMan Mask */
+
+#define TPI_FFCR_EnFCont_Pos 1U /*!< TPI FFCR: EnFCont Position */
+#define TPI_FFCR_EnFCont_Msk (0x1UL << TPI_FFCR_EnFCont_Pos) /*!< TPI FFCR: EnFCont Mask */
+
+/* TPI Periodic Synchronization Control Register Definitions */
+#define TPI_PSCR_PSCount_Pos 0U /*!< TPI PSCR: PSCount Position */
+#define TPI_PSCR_PSCount_Msk (0x1FUL /*<< TPI_PSCR_PSCount_Pos*/) /*!< TPI PSCR: TPSCount Mask */
+
+/* TPI Software Lock Status Register Definitions */
+#define TPI_LSR_nTT_Pos 1U /*!< TPI LSR: Not thirty-two bit. Position */
+#define TPI_LSR_nTT_Msk (0x1UL << TPI_LSR_nTT_Pos) /*!< TPI LSR: Not thirty-two bit. Mask */
+
+#define TPI_LSR_SLK_Pos 1U /*!< TPI LSR: Software Lock status Position */
+#define TPI_LSR_SLK_Msk (0x1UL << TPI_LSR_SLK_Pos) /*!< TPI LSR: Software Lock status Mask */
+
+#define TPI_LSR_SLI_Pos 0U /*!< TPI LSR: Software Lock implemented Position */
+#define TPI_LSR_SLI_Msk (0x1UL /*<< TPI_LSR_SLI_Pos*/) /*!< TPI LSR: Software Lock implemented Mask */
+
+/* TPI DEVID Register Definitions */
+#define TPI_DEVID_NRZVALID_Pos 11U /*!< TPI DEVID: NRZVALID Position */
+#define TPI_DEVID_NRZVALID_Msk (0x1UL << TPI_DEVID_NRZVALID_Pos) /*!< TPI DEVID: NRZVALID Mask */
+
+#define TPI_DEVID_MANCVALID_Pos 10U /*!< TPI DEVID: MANCVALID Position */
+#define TPI_DEVID_MANCVALID_Msk (0x1UL << TPI_DEVID_MANCVALID_Pos) /*!< TPI DEVID: MANCVALID Mask */
+
+#define TPI_DEVID_PTINVALID_Pos 9U /*!< TPI DEVID: PTINVALID Position */
+#define TPI_DEVID_PTINVALID_Msk (0x1UL << TPI_DEVID_PTINVALID_Pos) /*!< TPI DEVID: PTINVALID Mask */
+
+#define TPI_DEVID_FIFOSZ_Pos 6U /*!< TPI DEVID: FIFO depth Position */
+#define TPI_DEVID_FIFOSZ_Msk (0x7UL << TPI_DEVID_FIFOSZ_Pos) /*!< TPI DEVID: FIFO depth Mask */
+
+/* TPI DEVTYPE Register Definitions */
+#define TPI_DEVTYPE_SubType_Pos 4U /*!< TPI DEVTYPE: SubType Position */
+#define TPI_DEVTYPE_SubType_Msk (0xFUL /*<< TPI_DEVTYPE_SubType_Pos*/) /*!< TPI DEVTYPE: SubType Mask */
+
+#define TPI_DEVTYPE_MajorType_Pos 0U /*!< TPI DEVTYPE: MajorType Position */
+#define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */
+
+/*@}*/ /* end of group CMSIS_TPI */
+
+
+#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U)
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_MPU Memory Protection Unit (MPU)
+ \brief Type definitions for the Memory Protection Unit (MPU)
+ @{
+ */
+
+/**
+ \brief Structure type to access the Memory Protection Unit (MPU).
+ */
+typedef struct
+{
+ __IM uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */
+ __IOM uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */
+ __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region Number Register */
+ __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */
+ __IOM uint32_t RLAR; /*!< Offset: 0x010 (R/W) MPU Region Limit Address Register */
+ __IOM uint32_t RBAR_A1; /*!< Offset: 0x014 (R/W) MPU Region Base Address Register Alias 1 */
+ __IOM uint32_t RLAR_A1; /*!< Offset: 0x018 (R/W) MPU Region Limit Address Register Alias 1 */
+ __IOM uint32_t RBAR_A2; /*!< Offset: 0x01C (R/W) MPU Region Base Address Register Alias 2 */
+ __IOM uint32_t RLAR_A2; /*!< Offset: 0x020 (R/W) MPU Region Limit Address Register Alias 2 */
+ __IOM uint32_t RBAR_A3; /*!< Offset: 0x024 (R/W) MPU Region Base Address Register Alias 3 */
+ __IOM uint32_t RLAR_A3; /*!< Offset: 0x028 (R/W) MPU Region Limit Address Register Alias 3 */
+ uint32_t RESERVED0[1];
+ union {
+ __IOM uint32_t MAIR[2];
+ struct {
+ __IOM uint32_t MAIR0; /*!< Offset: 0x030 (R/W) MPU Memory Attribute Indirection Register 0 */
+ __IOM uint32_t MAIR1; /*!< Offset: 0x034 (R/W) MPU Memory Attribute Indirection Register 1 */
+ };
+ };
+} MPU_Type;
+
+#define MPU_TYPE_RALIASES 4U
+
+/* MPU Type Register Definitions */
+#define MPU_TYPE_IREGION_Pos 16U /*!< MPU TYPE: IREGION Position */
+#define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */
+
+#define MPU_TYPE_DREGION_Pos 8U /*!< MPU TYPE: DREGION Position */
+#define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */
+
+#define MPU_TYPE_SEPARATE_Pos 0U /*!< MPU TYPE: SEPARATE Position */
+#define MPU_TYPE_SEPARATE_Msk (1UL /*<< MPU_TYPE_SEPARATE_Pos*/) /*!< MPU TYPE: SEPARATE Mask */
+
+/* MPU Control Register Definitions */
+#define MPU_CTRL_PRIVDEFENA_Pos 2U /*!< MPU CTRL: PRIVDEFENA Position */
+#define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */
+
+#define MPU_CTRL_HFNMIENA_Pos 1U /*!< MPU CTRL: HFNMIENA Position */
+#define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */
+
+#define MPU_CTRL_ENABLE_Pos 0U /*!< MPU CTRL: ENABLE Position */
+#define MPU_CTRL_ENABLE_Msk (1UL /*<< MPU_CTRL_ENABLE_Pos*/) /*!< MPU CTRL: ENABLE Mask */
+
+/* MPU Region Number Register Definitions */
+#define MPU_RNR_REGION_Pos 0U /*!< MPU RNR: REGION Position */
+#define MPU_RNR_REGION_Msk (0xFFUL /*<< MPU_RNR_REGION_Pos*/) /*!< MPU RNR: REGION Mask */
+
+/* MPU Region Base Address Register Definitions */
+#define MPU_RBAR_BASE_Pos 5U /*!< MPU RBAR: BASE Position */
+#define MPU_RBAR_BASE_Msk (0x7FFFFFFUL << MPU_RBAR_BASE_Pos) /*!< MPU RBAR: BASE Mask */
+
+#define MPU_RBAR_SH_Pos 3U /*!< MPU RBAR: SH Position */
+#define MPU_RBAR_SH_Msk (0x3UL << MPU_RBAR_SH_Pos) /*!< MPU RBAR: SH Mask */
+
+#define MPU_RBAR_AP_Pos 1U /*!< MPU RBAR: AP Position */
+#define MPU_RBAR_AP_Msk (0x3UL << MPU_RBAR_AP_Pos) /*!< MPU RBAR: AP Mask */
+
+#define MPU_RBAR_XN_Pos 0U /*!< MPU RBAR: XN Position */
+#define MPU_RBAR_XN_Msk (01UL /*<< MPU_RBAR_XN_Pos*/) /*!< MPU RBAR: XN Mask */
+
+/* MPU Region Limit Address Register Definitions */
+#define MPU_RLAR_LIMIT_Pos 5U /*!< MPU RLAR: LIMIT Position */
+#define MPU_RLAR_LIMIT_Msk (0x7FFFFFFUL << MPU_RLAR_LIMIT_Pos) /*!< MPU RLAR: LIMIT Mask */
+
+#define MPU_RLAR_AttrIndx_Pos 1U /*!< MPU RLAR: AttrIndx Position */
+#define MPU_RLAR_AttrIndx_Msk (0x7UL << MPU_RLAR_AttrIndx_Pos) /*!< MPU RLAR: AttrIndx Mask */
+
+#define MPU_RLAR_EN_Pos 0U /*!< MPU RLAR: Region enable bit Position */
+#define MPU_RLAR_EN_Msk (1UL /*<< MPU_RLAR_EN_Pos*/) /*!< MPU RLAR: Region enable bit Disable Mask */
+
+/* MPU Memory Attribute Indirection Register 0 Definitions */
+#define MPU_MAIR0_Attr3_Pos 24U /*!< MPU MAIR0: Attr3 Position */
+#define MPU_MAIR0_Attr3_Msk (0xFFUL << MPU_MAIR0_Attr3_Pos) /*!< MPU MAIR0: Attr3 Mask */
+
+#define MPU_MAIR0_Attr2_Pos 16U /*!< MPU MAIR0: Attr2 Position */
+#define MPU_MAIR0_Attr2_Msk (0xFFUL << MPU_MAIR0_Attr2_Pos) /*!< MPU MAIR0: Attr2 Mask */
+
+#define MPU_MAIR0_Attr1_Pos 8U /*!< MPU MAIR0: Attr1 Position */
+#define MPU_MAIR0_Attr1_Msk (0xFFUL << MPU_MAIR0_Attr1_Pos) /*!< MPU MAIR0: Attr1 Mask */
+
+#define MPU_MAIR0_Attr0_Pos 0U /*!< MPU MAIR0: Attr0 Position */
+#define MPU_MAIR0_Attr0_Msk (0xFFUL /*<< MPU_MAIR0_Attr0_Pos*/) /*!< MPU MAIR0: Attr0 Mask */
+
+/* MPU Memory Attribute Indirection Register 1 Definitions */
+#define MPU_MAIR1_Attr7_Pos 24U /*!< MPU MAIR1: Attr7 Position */
+#define MPU_MAIR1_Attr7_Msk (0xFFUL << MPU_MAIR1_Attr7_Pos) /*!< MPU MAIR1: Attr7 Mask */
+
+#define MPU_MAIR1_Attr6_Pos 16U /*!< MPU MAIR1: Attr6 Position */
+#define MPU_MAIR1_Attr6_Msk (0xFFUL << MPU_MAIR1_Attr6_Pos) /*!< MPU MAIR1: Attr6 Mask */
+
+#define MPU_MAIR1_Attr5_Pos 8U /*!< MPU MAIR1: Attr5 Position */
+#define MPU_MAIR1_Attr5_Msk (0xFFUL << MPU_MAIR1_Attr5_Pos) /*!< MPU MAIR1: Attr5 Mask */
+
+#define MPU_MAIR1_Attr4_Pos 0U /*!< MPU MAIR1: Attr4 Position */
+#define MPU_MAIR1_Attr4_Msk (0xFFUL /*<< MPU_MAIR1_Attr4_Pos*/) /*!< MPU MAIR1: Attr4 Mask */
+
+/*@} end of group CMSIS_MPU */
+#endif
+
+
+#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_SAU Security Attribution Unit (SAU)
+ \brief Type definitions for the Security Attribution Unit (SAU)
+ @{
+ */
+
+/**
+ \brief Structure type to access the Security Attribution Unit (SAU).
+ */
+typedef struct
+{
+ __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SAU Control Register */
+ __IM uint32_t TYPE; /*!< Offset: 0x004 (R/ ) SAU Type Register */
+#if defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U)
+ __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) SAU Region Number Register */
+ __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) SAU Region Base Address Register */
+ __IOM uint32_t RLAR; /*!< Offset: 0x010 (R/W) SAU Region Limit Address Register */
+#else
+ uint32_t RESERVED0[3];
+#endif
+ __IOM uint32_t SFSR; /*!< Offset: 0x014 (R/W) Secure Fault Status Register */
+ __IOM uint32_t SFAR; /*!< Offset: 0x018 (R/W) Secure Fault Address Register */
+} SAU_Type;
+
+/* SAU Control Register Definitions */
+#define SAU_CTRL_ALLNS_Pos 1U /*!< SAU CTRL: ALLNS Position */
+#define SAU_CTRL_ALLNS_Msk (1UL << SAU_CTRL_ALLNS_Pos) /*!< SAU CTRL: ALLNS Mask */
+
+#define SAU_CTRL_ENABLE_Pos 0U /*!< SAU CTRL: ENABLE Position */
+#define SAU_CTRL_ENABLE_Msk (1UL /*<< SAU_CTRL_ENABLE_Pos*/) /*!< SAU CTRL: ENABLE Mask */
+
+/* SAU Type Register Definitions */
+#define SAU_TYPE_SREGION_Pos 0U /*!< SAU TYPE: SREGION Position */
+#define SAU_TYPE_SREGION_Msk (0xFFUL /*<< SAU_TYPE_SREGION_Pos*/) /*!< SAU TYPE: SREGION Mask */
+
+#if defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U)
+/* SAU Region Number Register Definitions */
+#define SAU_RNR_REGION_Pos 0U /*!< SAU RNR: REGION Position */
+#define SAU_RNR_REGION_Msk (0xFFUL /*<< SAU_RNR_REGION_Pos*/) /*!< SAU RNR: REGION Mask */
+
+/* SAU Region Base Address Register Definitions */
+#define SAU_RBAR_BADDR_Pos 5U /*!< SAU RBAR: BADDR Position */
+#define SAU_RBAR_BADDR_Msk (0x7FFFFFFUL << SAU_RBAR_BADDR_Pos) /*!< SAU RBAR: BADDR Mask */
+
+/* SAU Region Limit Address Register Definitions */
+#define SAU_RLAR_LADDR_Pos 5U /*!< SAU RLAR: LADDR Position */
+#define SAU_RLAR_LADDR_Msk (0x7FFFFFFUL << SAU_RLAR_LADDR_Pos) /*!< SAU RLAR: LADDR Mask */
+
+#define SAU_RLAR_NSC_Pos 1U /*!< SAU RLAR: NSC Position */
+#define SAU_RLAR_NSC_Msk (1UL << SAU_RLAR_NSC_Pos) /*!< SAU RLAR: NSC Mask */
+
+#define SAU_RLAR_ENABLE_Pos 0U /*!< SAU RLAR: ENABLE Position */
+#define SAU_RLAR_ENABLE_Msk (1UL /*<< SAU_RLAR_ENABLE_Pos*/) /*!< SAU RLAR: ENABLE Mask */
+
+#endif /* defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U) */
+
+/* Secure Fault Status Register Definitions */
+#define SAU_SFSR_LSERR_Pos 7U /*!< SAU SFSR: LSERR Position */
+#define SAU_SFSR_LSERR_Msk (1UL << SAU_SFSR_LSERR_Pos) /*!< SAU SFSR: LSERR Mask */
+
+#define SAU_SFSR_SFARVALID_Pos 6U /*!< SAU SFSR: SFARVALID Position */
+#define SAU_SFSR_SFARVALID_Msk (1UL << SAU_SFSR_SFARVALID_Pos) /*!< SAU SFSR: SFARVALID Mask */
+
+#define SAU_SFSR_LSPERR_Pos 5U /*!< SAU SFSR: LSPERR Position */
+#define SAU_SFSR_LSPERR_Msk (1UL << SAU_SFSR_LSPERR_Pos) /*!< SAU SFSR: LSPERR Mask */
+
+#define SAU_SFSR_INVTRAN_Pos 4U /*!< SAU SFSR: INVTRAN Position */
+#define SAU_SFSR_INVTRAN_Msk (1UL << SAU_SFSR_INVTRAN_Pos) /*!< SAU SFSR: INVTRAN Mask */
+
+#define SAU_SFSR_AUVIOL_Pos 3U /*!< SAU SFSR: AUVIOL Position */
+#define SAU_SFSR_AUVIOL_Msk (1UL << SAU_SFSR_AUVIOL_Pos) /*!< SAU SFSR: AUVIOL Mask */
+
+#define SAU_SFSR_INVER_Pos 2U /*!< SAU SFSR: INVER Position */
+#define SAU_SFSR_INVER_Msk (1UL << SAU_SFSR_INVER_Pos) /*!< SAU SFSR: INVER Mask */
+
+#define SAU_SFSR_INVIS_Pos 1U /*!< SAU SFSR: INVIS Position */
+#define SAU_SFSR_INVIS_Msk (1UL << SAU_SFSR_INVIS_Pos) /*!< SAU SFSR: INVIS Mask */
+
+#define SAU_SFSR_INVEP_Pos 0U /*!< SAU SFSR: INVEP Position */
+#define SAU_SFSR_INVEP_Msk (1UL /*<< SAU_SFSR_INVEP_Pos*/) /*!< SAU SFSR: INVEP Mask */
+
+/*@} end of group CMSIS_SAU */
+#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_FPU Floating Point Unit (FPU)
+ \brief Type definitions for the Floating Point Unit (FPU)
+ @{
+ */
+
+/**
+ \brief Structure type to access the Floating Point Unit (FPU).
+ */
+typedef struct
+{
+ uint32_t RESERVED0[1U];
+ __IOM uint32_t FPCCR; /*!< Offset: 0x004 (R/W) Floating-Point Context Control Register */
+ __IOM uint32_t FPCAR; /*!< Offset: 0x008 (R/W) Floating-Point Context Address Register */
+ __IOM uint32_t FPDSCR; /*!< Offset: 0x00C (R/W) Floating-Point Default Status Control Register */
+ __IM uint32_t MVFR0; /*!< Offset: 0x010 (R/ ) Media and FP Feature Register 0 */
+ __IM uint32_t MVFR1; /*!< Offset: 0x014 (R/ ) Media and FP Feature Register 1 */
+} FPU_Type;
+
+/* Floating-Point Context Control Register Definitions */
+#define FPU_FPCCR_ASPEN_Pos 31U /*!< FPCCR: ASPEN bit Position */
+#define FPU_FPCCR_ASPEN_Msk (1UL << FPU_FPCCR_ASPEN_Pos) /*!< FPCCR: ASPEN bit Mask */
+
+#define FPU_FPCCR_LSPEN_Pos 30U /*!< FPCCR: LSPEN Position */
+#define FPU_FPCCR_LSPEN_Msk (1UL << FPU_FPCCR_LSPEN_Pos) /*!< FPCCR: LSPEN bit Mask */
+
+#define FPU_FPCCR_LSPENS_Pos 29U /*!< FPCCR: LSPENS Position */
+#define FPU_FPCCR_LSPENS_Msk (1UL << FPU_FPCCR_LSPENS_Pos) /*!< FPCCR: LSPENS bit Mask */
+
+#define FPU_FPCCR_CLRONRET_Pos 28U /*!< FPCCR: CLRONRET Position */
+#define FPU_FPCCR_CLRONRET_Msk (1UL << FPU_FPCCR_CLRONRET_Pos) /*!< FPCCR: CLRONRET bit Mask */
+
+#define FPU_FPCCR_CLRONRETS_Pos 27U /*!< FPCCR: CLRONRETS Position */
+#define FPU_FPCCR_CLRONRETS_Msk (1UL << FPU_FPCCR_CLRONRETS_Pos) /*!< FPCCR: CLRONRETS bit Mask */
+
+#define FPU_FPCCR_TS_Pos 26U /*!< FPCCR: TS Position */
+#define FPU_FPCCR_TS_Msk (1UL << FPU_FPCCR_TS_Pos) /*!< FPCCR: TS bit Mask */
+
+#define FPU_FPCCR_UFRDY_Pos 10U /*!< FPCCR: UFRDY Position */
+#define FPU_FPCCR_UFRDY_Msk (1UL << FPU_FPCCR_UFRDY_Pos) /*!< FPCCR: UFRDY bit Mask */
+
+#define FPU_FPCCR_SPLIMVIOL_Pos 9U /*!< FPCCR: SPLIMVIOL Position */
+#define FPU_FPCCR_SPLIMVIOL_Msk (1UL << FPU_FPCCR_SPLIMVIOL_Pos) /*!< FPCCR: SPLIMVIOL bit Mask */
+
+#define FPU_FPCCR_MONRDY_Pos 8U /*!< FPCCR: MONRDY Position */
+#define FPU_FPCCR_MONRDY_Msk (1UL << FPU_FPCCR_MONRDY_Pos) /*!< FPCCR: MONRDY bit Mask */
+
+#define FPU_FPCCR_SFRDY_Pos 7U /*!< FPCCR: SFRDY Position */
+#define FPU_FPCCR_SFRDY_Msk (1UL << FPU_FPCCR_SFRDY_Pos) /*!< FPCCR: SFRDY bit Mask */
+
+#define FPU_FPCCR_BFRDY_Pos 6U /*!< FPCCR: BFRDY Position */
+#define FPU_FPCCR_BFRDY_Msk (1UL << FPU_FPCCR_BFRDY_Pos) /*!< FPCCR: BFRDY bit Mask */
+
+#define FPU_FPCCR_MMRDY_Pos 5U /*!< FPCCR: MMRDY Position */
+#define FPU_FPCCR_MMRDY_Msk (1UL << FPU_FPCCR_MMRDY_Pos) /*!< FPCCR: MMRDY bit Mask */
+
+#define FPU_FPCCR_HFRDY_Pos 4U /*!< FPCCR: HFRDY Position */
+#define FPU_FPCCR_HFRDY_Msk (1UL << FPU_FPCCR_HFRDY_Pos) /*!< FPCCR: HFRDY bit Mask */
+
+#define FPU_FPCCR_THREAD_Pos 3U /*!< FPCCR: processor mode bit Position */
+#define FPU_FPCCR_THREAD_Msk (1UL << FPU_FPCCR_THREAD_Pos) /*!< FPCCR: processor mode active bit Mask */
+
+#define FPU_FPCCR_S_Pos 2U /*!< FPCCR: Security status of the FP context bit Position */
+#define FPU_FPCCR_S_Msk (1UL << FPU_FPCCR_S_Pos) /*!< FPCCR: Security status of the FP context bit Mask */
+
+#define FPU_FPCCR_USER_Pos 1U /*!< FPCCR: privilege level bit Position */
+#define FPU_FPCCR_USER_Msk (1UL << FPU_FPCCR_USER_Pos) /*!< FPCCR: privilege level bit Mask */
+
+#define FPU_FPCCR_LSPACT_Pos 0U /*!< FPCCR: Lazy state preservation active bit Position */
+#define FPU_FPCCR_LSPACT_Msk (1UL /*<< FPU_FPCCR_LSPACT_Pos*/) /*!< FPCCR: Lazy state preservation active bit Mask */
+
+/* Floating-Point Context Address Register Definitions */
+#define FPU_FPCAR_ADDRESS_Pos 3U /*!< FPCAR: ADDRESS bit Position */
+#define FPU_FPCAR_ADDRESS_Msk (0x1FFFFFFFUL << FPU_FPCAR_ADDRESS_Pos) /*!< FPCAR: ADDRESS bit Mask */
+
+/* Floating-Point Default Status Control Register Definitions */
+#define FPU_FPDSCR_AHP_Pos 26U /*!< FPDSCR: AHP bit Position */
+#define FPU_FPDSCR_AHP_Msk (1UL << FPU_FPDSCR_AHP_Pos) /*!< FPDSCR: AHP bit Mask */
+
+#define FPU_FPDSCR_DN_Pos 25U /*!< FPDSCR: DN bit Position */
+#define FPU_FPDSCR_DN_Msk (1UL << FPU_FPDSCR_DN_Pos) /*!< FPDSCR: DN bit Mask */
+
+#define FPU_FPDSCR_FZ_Pos 24U /*!< FPDSCR: FZ bit Position */
+#define FPU_FPDSCR_FZ_Msk (1UL << FPU_FPDSCR_FZ_Pos) /*!< FPDSCR: FZ bit Mask */
+
+#define FPU_FPDSCR_RMode_Pos 22U /*!< FPDSCR: RMode bit Position */
+#define FPU_FPDSCR_RMode_Msk (3UL << FPU_FPDSCR_RMode_Pos) /*!< FPDSCR: RMode bit Mask */
+
+/* Media and FP Feature Register 0 Definitions */
+#define FPU_MVFR0_FP_rounding_modes_Pos 28U /*!< MVFR0: FP rounding modes bits Position */
+#define FPU_MVFR0_FP_rounding_modes_Msk (0xFUL << FPU_MVFR0_FP_rounding_modes_Pos) /*!< MVFR0: FP rounding modes bits Mask */
+
+#define FPU_MVFR0_Short_vectors_Pos 24U /*!< MVFR0: Short vectors bits Position */
+#define FPU_MVFR0_Short_vectors_Msk (0xFUL << FPU_MVFR0_Short_vectors_Pos) /*!< MVFR0: Short vectors bits Mask */
+
+#define FPU_MVFR0_Square_root_Pos 20U /*!< MVFR0: Square root bits Position */
+#define FPU_MVFR0_Square_root_Msk (0xFUL << FPU_MVFR0_Square_root_Pos) /*!< MVFR0: Square root bits Mask */
+
+#define FPU_MVFR0_Divide_Pos 16U /*!< MVFR0: Divide bits Position */
+#define FPU_MVFR0_Divide_Msk (0xFUL << FPU_MVFR0_Divide_Pos) /*!< MVFR0: Divide bits Mask */
+
+#define FPU_MVFR0_FP_excep_trapping_Pos 12U /*!< MVFR0: FP exception trapping bits Position */
+#define FPU_MVFR0_FP_excep_trapping_Msk (0xFUL << FPU_MVFR0_FP_excep_trapping_Pos) /*!< MVFR0: FP exception trapping bits Mask */
+
+#define FPU_MVFR0_Double_precision_Pos 8U /*!< MVFR0: Double-precision bits Position */
+#define FPU_MVFR0_Double_precision_Msk (0xFUL << FPU_MVFR0_Double_precision_Pos) /*!< MVFR0: Double-precision bits Mask */
+
+#define FPU_MVFR0_Single_precision_Pos 4U /*!< MVFR0: Single-precision bits Position */
+#define FPU_MVFR0_Single_precision_Msk (0xFUL << FPU_MVFR0_Single_precision_Pos) /*!< MVFR0: Single-precision bits Mask */
+
+#define FPU_MVFR0_A_SIMD_registers_Pos 0U /*!< MVFR0: A_SIMD registers bits Position */
+#define FPU_MVFR0_A_SIMD_registers_Msk (0xFUL /*<< FPU_MVFR0_A_SIMD_registers_Pos*/) /*!< MVFR0: A_SIMD registers bits Mask */
+
+/* Media and FP Feature Register 1 Definitions */
+#define FPU_MVFR1_FP_fused_MAC_Pos 28U /*!< MVFR1: FP fused MAC bits Position */
+#define FPU_MVFR1_FP_fused_MAC_Msk (0xFUL << FPU_MVFR1_FP_fused_MAC_Pos) /*!< MVFR1: FP fused MAC bits Mask */
+
+#define FPU_MVFR1_FP_HPFP_Pos 24U /*!< MVFR1: FP HPFP bits Position */
+#define FPU_MVFR1_FP_HPFP_Msk (0xFUL << FPU_MVFR1_FP_HPFP_Pos) /*!< MVFR1: FP HPFP bits Mask */
+
+#define FPU_MVFR1_D_NaN_mode_Pos 4U /*!< MVFR1: D_NaN mode bits Position */
+#define FPU_MVFR1_D_NaN_mode_Msk (0xFUL << FPU_MVFR1_D_NaN_mode_Pos) /*!< MVFR1: D_NaN mode bits Mask */
+
+#define FPU_MVFR1_FtZ_mode_Pos 0U /*!< MVFR1: FtZ mode bits Position */
+#define FPU_MVFR1_FtZ_mode_Msk (0xFUL /*<< FPU_MVFR1_FtZ_mode_Pos*/) /*!< MVFR1: FtZ mode bits Mask */
+
+/*@} end of group CMSIS_FPU */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug)
+ \brief Type definitions for the Core Debug Registers
+ @{
+ */
+
+/**
+ \brief Structure type to access the Core Debug Register (CoreDebug).
+ */
+typedef struct
+{
+ __IOM uint32_t DHCSR; /*!< Offset: 0x000 (R/W) Debug Halting Control and Status Register */
+ __OM uint32_t DCRSR; /*!< Offset: 0x004 ( /W) Debug Core Register Selector Register */
+ __IOM uint32_t DCRDR; /*!< Offset: 0x008 (R/W) Debug Core Register Data Register */
+ __IOM uint32_t DEMCR; /*!< Offset: 0x00C (R/W) Debug Exception and Monitor Control Register */
+ uint32_t RESERVED4[1U];
+ __IOM uint32_t DAUTHCTRL; /*!< Offset: 0x014 (R/W) Debug Authentication Control Register */
+ __IOM uint32_t DSCSR; /*!< Offset: 0x018 (R/W) Debug Security Control and Status Register */
+} CoreDebug_Type;
+
+/* Debug Halting Control and Status Register Definitions */
+#define CoreDebug_DHCSR_DBGKEY_Pos 16U /*!< CoreDebug DHCSR: DBGKEY Position */
+#define CoreDebug_DHCSR_DBGKEY_Msk (0xFFFFUL << CoreDebug_DHCSR_DBGKEY_Pos) /*!< CoreDebug DHCSR: DBGKEY Mask */
+
+#define CoreDebug_DHCSR_S_RESTART_ST_Pos 26U /*!< CoreDebug DHCSR: S_RESTART_ST Position */
+#define CoreDebug_DHCSR_S_RESTART_ST_Msk (1UL << CoreDebug_DHCSR_S_RESTART_ST_Pos) /*!< CoreDebug DHCSR: S_RESTART_ST Mask */
+
+#define CoreDebug_DHCSR_S_RESET_ST_Pos 25U /*!< CoreDebug DHCSR: S_RESET_ST Position */
+#define CoreDebug_DHCSR_S_RESET_ST_Msk (1UL << CoreDebug_DHCSR_S_RESET_ST_Pos) /*!< CoreDebug DHCSR: S_RESET_ST Mask */
+
+#define CoreDebug_DHCSR_S_RETIRE_ST_Pos 24U /*!< CoreDebug DHCSR: S_RETIRE_ST Position */
+#define CoreDebug_DHCSR_S_RETIRE_ST_Msk (1UL << CoreDebug_DHCSR_S_RETIRE_ST_Pos) /*!< CoreDebug DHCSR: S_RETIRE_ST Mask */
+
+#define CoreDebug_DHCSR_S_LOCKUP_Pos 19U /*!< CoreDebug DHCSR: S_LOCKUP Position */
+#define CoreDebug_DHCSR_S_LOCKUP_Msk (1UL << CoreDebug_DHCSR_S_LOCKUP_Pos) /*!< CoreDebug DHCSR: S_LOCKUP Mask */
+
+#define CoreDebug_DHCSR_S_SLEEP_Pos 18U /*!< CoreDebug DHCSR: S_SLEEP Position */
+#define CoreDebug_DHCSR_S_SLEEP_Msk (1UL << CoreDebug_DHCSR_S_SLEEP_Pos) /*!< CoreDebug DHCSR: S_SLEEP Mask */
+
+#define CoreDebug_DHCSR_S_HALT_Pos 17U /*!< CoreDebug DHCSR: S_HALT Position */
+#define CoreDebug_DHCSR_S_HALT_Msk (1UL << CoreDebug_DHCSR_S_HALT_Pos) /*!< CoreDebug DHCSR: S_HALT Mask */
+
+#define CoreDebug_DHCSR_S_REGRDY_Pos 16U /*!< CoreDebug DHCSR: S_REGRDY Position */
+#define CoreDebug_DHCSR_S_REGRDY_Msk (1UL << CoreDebug_DHCSR_S_REGRDY_Pos) /*!< CoreDebug DHCSR: S_REGRDY Mask */
+
+#define CoreDebug_DHCSR_C_SNAPSTALL_Pos 5U /*!< CoreDebug DHCSR: C_SNAPSTALL Position */
+#define CoreDebug_DHCSR_C_SNAPSTALL_Msk (1UL << CoreDebug_DHCSR_C_SNAPSTALL_Pos) /*!< CoreDebug DHCSR: C_SNAPSTALL Mask */
+
+#define CoreDebug_DHCSR_C_MASKINTS_Pos 3U /*!< CoreDebug DHCSR: C_MASKINTS Position */
+#define CoreDebug_DHCSR_C_MASKINTS_Msk (1UL << CoreDebug_DHCSR_C_MASKINTS_Pos) /*!< CoreDebug DHCSR: C_MASKINTS Mask */
+
+#define CoreDebug_DHCSR_C_STEP_Pos 2U /*!< CoreDebug DHCSR: C_STEP Position */
+#define CoreDebug_DHCSR_C_STEP_Msk (1UL << CoreDebug_DHCSR_C_STEP_Pos) /*!< CoreDebug DHCSR: C_STEP Mask */
+
+#define CoreDebug_DHCSR_C_HALT_Pos 1U /*!< CoreDebug DHCSR: C_HALT Position */
+#define CoreDebug_DHCSR_C_HALT_Msk (1UL << CoreDebug_DHCSR_C_HALT_Pos) /*!< CoreDebug DHCSR: C_HALT Mask */
+
+#define CoreDebug_DHCSR_C_DEBUGEN_Pos 0U /*!< CoreDebug DHCSR: C_DEBUGEN Position */
+#define CoreDebug_DHCSR_C_DEBUGEN_Msk (1UL /*<< CoreDebug_DHCSR_C_DEBUGEN_Pos*/) /*!< CoreDebug DHCSR: C_DEBUGEN Mask */
+
+/* Debug Core Register Selector Register Definitions */
+#define CoreDebug_DCRSR_REGWnR_Pos 16U /*!< CoreDebug DCRSR: REGWnR Position */
+#define CoreDebug_DCRSR_REGWnR_Msk (1UL << CoreDebug_DCRSR_REGWnR_Pos) /*!< CoreDebug DCRSR: REGWnR Mask */
+
+#define CoreDebug_DCRSR_REGSEL_Pos 0U /*!< CoreDebug DCRSR: REGSEL Position */
+#define CoreDebug_DCRSR_REGSEL_Msk (0x1FUL /*<< CoreDebug_DCRSR_REGSEL_Pos*/) /*!< CoreDebug DCRSR: REGSEL Mask */
+
+/* Debug Exception and Monitor Control Register Definitions */
+#define CoreDebug_DEMCR_TRCENA_Pos 24U /*!< CoreDebug DEMCR: TRCENA Position */
+#define CoreDebug_DEMCR_TRCENA_Msk (1UL << CoreDebug_DEMCR_TRCENA_Pos) /*!< CoreDebug DEMCR: TRCENA Mask */
+
+#define CoreDebug_DEMCR_MON_REQ_Pos 19U /*!< CoreDebug DEMCR: MON_REQ Position */
+#define CoreDebug_DEMCR_MON_REQ_Msk (1UL << CoreDebug_DEMCR_MON_REQ_Pos) /*!< CoreDebug DEMCR: MON_REQ Mask */
+
+#define CoreDebug_DEMCR_MON_STEP_Pos 18U /*!< CoreDebug DEMCR: MON_STEP Position */
+#define CoreDebug_DEMCR_MON_STEP_Msk (1UL << CoreDebug_DEMCR_MON_STEP_Pos) /*!< CoreDebug DEMCR: MON_STEP Mask */
+
+#define CoreDebug_DEMCR_MON_PEND_Pos 17U /*!< CoreDebug DEMCR: MON_PEND Position */
+#define CoreDebug_DEMCR_MON_PEND_Msk (1UL << CoreDebug_DEMCR_MON_PEND_Pos) /*!< CoreDebug DEMCR: MON_PEND Mask */
+
+#define CoreDebug_DEMCR_MON_EN_Pos 16U /*!< CoreDebug DEMCR: MON_EN Position */
+#define CoreDebug_DEMCR_MON_EN_Msk (1UL << CoreDebug_DEMCR_MON_EN_Pos) /*!< CoreDebug DEMCR: MON_EN Mask */
+
+#define CoreDebug_DEMCR_VC_HARDERR_Pos 10U /*!< CoreDebug DEMCR: VC_HARDERR Position */
+#define CoreDebug_DEMCR_VC_HARDERR_Msk (1UL << CoreDebug_DEMCR_VC_HARDERR_Pos) /*!< CoreDebug DEMCR: VC_HARDERR Mask */
+
+#define CoreDebug_DEMCR_VC_INTERR_Pos 9U /*!< CoreDebug DEMCR: VC_INTERR Position */
+#define CoreDebug_DEMCR_VC_INTERR_Msk (1UL << CoreDebug_DEMCR_VC_INTERR_Pos) /*!< CoreDebug DEMCR: VC_INTERR Mask */
+
+#define CoreDebug_DEMCR_VC_BUSERR_Pos 8U /*!< CoreDebug DEMCR: VC_BUSERR Position */
+#define CoreDebug_DEMCR_VC_BUSERR_Msk (1UL << CoreDebug_DEMCR_VC_BUSERR_Pos) /*!< CoreDebug DEMCR: VC_BUSERR Mask */
+
+#define CoreDebug_DEMCR_VC_STATERR_Pos 7U /*!< CoreDebug DEMCR: VC_STATERR Position */
+#define CoreDebug_DEMCR_VC_STATERR_Msk (1UL << CoreDebug_DEMCR_VC_STATERR_Pos) /*!< CoreDebug DEMCR: VC_STATERR Mask */
+
+#define CoreDebug_DEMCR_VC_CHKERR_Pos 6U /*!< CoreDebug DEMCR: VC_CHKERR Position */
+#define CoreDebug_DEMCR_VC_CHKERR_Msk (1UL << CoreDebug_DEMCR_VC_CHKERR_Pos) /*!< CoreDebug DEMCR: VC_CHKERR Mask */
+
+#define CoreDebug_DEMCR_VC_NOCPERR_Pos 5U /*!< CoreDebug DEMCR: VC_NOCPERR Position */
+#define CoreDebug_DEMCR_VC_NOCPERR_Msk (1UL << CoreDebug_DEMCR_VC_NOCPERR_Pos) /*!< CoreDebug DEMCR: VC_NOCPERR Mask */
+
+#define CoreDebug_DEMCR_VC_MMERR_Pos 4U /*!< CoreDebug DEMCR: VC_MMERR Position */
+#define CoreDebug_DEMCR_VC_MMERR_Msk (1UL << CoreDebug_DEMCR_VC_MMERR_Pos) /*!< CoreDebug DEMCR: VC_MMERR Mask */
+
+#define CoreDebug_DEMCR_VC_CORERESET_Pos 0U /*!< CoreDebug DEMCR: VC_CORERESET Position */
+#define CoreDebug_DEMCR_VC_CORERESET_Msk (1UL /*<< CoreDebug_DEMCR_VC_CORERESET_Pos*/) /*!< CoreDebug DEMCR: VC_CORERESET Mask */
+
+/* Debug Authentication Control Register Definitions */
+#define CoreDebug_DAUTHCTRL_INTSPNIDEN_Pos 3U /*!< CoreDebug DAUTHCTRL: INTSPNIDEN, Position */
+#define CoreDebug_DAUTHCTRL_INTSPNIDEN_Msk (1UL << CoreDebug_DAUTHCTRL_INTSPNIDEN_Pos) /*!< CoreDebug DAUTHCTRL: INTSPNIDEN, Mask */
+
+#define CoreDebug_DAUTHCTRL_SPNIDENSEL_Pos 2U /*!< CoreDebug DAUTHCTRL: SPNIDENSEL Position */
+#define CoreDebug_DAUTHCTRL_SPNIDENSEL_Msk (1UL << CoreDebug_DAUTHCTRL_SPNIDENSEL_Pos) /*!< CoreDebug DAUTHCTRL: SPNIDENSEL Mask */
+
+#define CoreDebug_DAUTHCTRL_INTSPIDEN_Pos 1U /*!< CoreDebug DAUTHCTRL: INTSPIDEN Position */
+#define CoreDebug_DAUTHCTRL_INTSPIDEN_Msk (1UL << CoreDebug_DAUTHCTRL_INTSPIDEN_Pos) /*!< CoreDebug DAUTHCTRL: INTSPIDEN Mask */
+
+#define CoreDebug_DAUTHCTRL_SPIDENSEL_Pos 0U /*!< CoreDebug DAUTHCTRL: SPIDENSEL Position */
+#define CoreDebug_DAUTHCTRL_SPIDENSEL_Msk (1UL /*<< CoreDebug_DAUTHCTRL_SPIDENSEL_Pos*/) /*!< CoreDebug DAUTHCTRL: SPIDENSEL Mask */
+
+/* Debug Security Control and Status Register Definitions */
+#define CoreDebug_DSCSR_CDS_Pos 16U /*!< CoreDebug DSCSR: CDS Position */
+#define CoreDebug_DSCSR_CDS_Msk (1UL << CoreDebug_DSCSR_CDS_Pos) /*!< CoreDebug DSCSR: CDS Mask */
+
+#define CoreDebug_DSCSR_SBRSEL_Pos 1U /*!< CoreDebug DSCSR: SBRSEL Position */
+#define CoreDebug_DSCSR_SBRSEL_Msk (1UL << CoreDebug_DSCSR_SBRSEL_Pos) /*!< CoreDebug DSCSR: SBRSEL Mask */
+
+#define CoreDebug_DSCSR_SBRSELEN_Pos 0U /*!< CoreDebug DSCSR: SBRSELEN Position */
+#define CoreDebug_DSCSR_SBRSELEN_Msk (1UL /*<< CoreDebug_DSCSR_SBRSELEN_Pos*/) /*!< CoreDebug DSCSR: SBRSELEN Mask */
+
+/*@} end of group CMSIS_CoreDebug */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_core_bitfield Core register bit field macros
+ \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk).
+ @{
+ */
+
+/**
+ \brief Mask and shift a bit field value for use in a register bit range.
+ \param[in] field Name of the register bit field.
+ \param[in] value Value of the bit field. This parameter is interpreted as an uint32_t type.
+ \return Masked and shifted value.
+*/
+#define _VAL2FLD(field, value) (((uint32_t)(value) << field ## _Pos) & field ## _Msk)
+
+/**
+ \brief Mask and shift a register value to extract a bit filed value.
+ \param[in] field Name of the register bit field.
+ \param[in] value Value of register. This parameter is interpreted as an uint32_t type.
+ \return Masked and shifted bit field value.
+*/
+#define _FLD2VAL(field, value) (((uint32_t)(value) & field ## _Msk) >> field ## _Pos)
+
+/*@} end of group CMSIS_core_bitfield */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_core_base Core Definitions
+ \brief Definitions for base addresses, unions, and structures.
+ @{
+ */
+
+/* Memory mapping of Core Hardware */
+ #define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */
+ #define ITM_BASE (0xE0000000UL) /*!< ITM Base Address */
+ #define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */
+ #define TPI_BASE (0xE0040000UL) /*!< TPI Base Address */
+ #define CoreDebug_BASE (0xE000EDF0UL) /*!< Core Debug Base Address */
+ #define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */
+ #define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */
+ #define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */
+
+ #define SCnSCB ((SCnSCB_Type *) SCS_BASE ) /*!< System control Register not in SCB */
+ #define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */
+ #define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */
+ #define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */
+ #define ITM ((ITM_Type *) ITM_BASE ) /*!< ITM configuration struct */
+ #define DWT ((DWT_Type *) DWT_BASE ) /*!< DWT configuration struct */
+ #define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */
+ #define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE ) /*!< Core Debug configuration struct */
+
+ #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U)
+ #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */
+ #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */
+ #endif
+
+ #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
+ #define SAU_BASE (SCS_BASE + 0x0DD0UL) /*!< Security Attribution Unit */
+ #define SAU ((SAU_Type *) SAU_BASE ) /*!< Security Attribution Unit */
+ #endif
+
+ #define FPU_BASE (SCS_BASE + 0x0F30UL) /*!< Floating Point Unit */
+ #define FPU ((FPU_Type *) FPU_BASE ) /*!< Floating Point Unit */
+
+#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
+ #define SCS_BASE_NS (0xE002E000UL) /*!< System Control Space Base Address (non-secure address space) */
+ #define CoreDebug_BASE_NS (0xE002EDF0UL) /*!< Core Debug Base Address (non-secure address space) */
+ #define SysTick_BASE_NS (SCS_BASE_NS + 0x0010UL) /*!< SysTick Base Address (non-secure address space) */
+ #define NVIC_BASE_NS (SCS_BASE_NS + 0x0100UL) /*!< NVIC Base Address (non-secure address space) */
+ #define SCB_BASE_NS (SCS_BASE_NS + 0x0D00UL) /*!< System Control Block Base Address (non-secure address space) */
+
+ #define SCnSCB_NS ((SCnSCB_Type *) SCS_BASE_NS ) /*!< System control Register not in SCB(non-secure address space) */
+ #define SCB_NS ((SCB_Type *) SCB_BASE_NS ) /*!< SCB configuration struct (non-secure address space) */
+ #define SysTick_NS ((SysTick_Type *) SysTick_BASE_NS ) /*!< SysTick configuration struct (non-secure address space) */
+ #define NVIC_NS ((NVIC_Type *) NVIC_BASE_NS ) /*!< NVIC configuration struct (non-secure address space) */
+ #define CoreDebug_NS ((CoreDebug_Type *) CoreDebug_BASE_NS) /*!< Core Debug configuration struct (non-secure address space) */
+
+ #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U)
+ #define MPU_BASE_NS (SCS_BASE_NS + 0x0D90UL) /*!< Memory Protection Unit (non-secure address space) */
+ #define MPU_NS ((MPU_Type *) MPU_BASE_NS ) /*!< Memory Protection Unit (non-secure address space) */
+ #endif
+
+ #define FPU_BASE_NS (SCS_BASE_NS + 0x0F30UL) /*!< Floating Point Unit (non-secure address space) */
+ #define FPU_NS ((FPU_Type *) FPU_BASE_NS ) /*!< Floating Point Unit (non-secure address space) */
+
+#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */
+/*@} */
+
+
+
+/*******************************************************************************
+ * Hardware Abstraction Layer
+ Core Function Interface contains:
+ - Core NVIC Functions
+ - Core SysTick Functions
+ - Core Debug Functions
+ - Core Register Access Functions
+ ******************************************************************************/
+/**
+ \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference
+*/
+
+
+
+/* ########################## NVIC functions #################################### */
+/**
+ \ingroup CMSIS_Core_FunctionInterface
+ \defgroup CMSIS_Core_NVICFunctions NVIC Functions
+ \brief Functions that manage interrupts and exceptions via the NVIC.
+ @{
+ */
+
+#ifdef CMSIS_NVIC_VIRTUAL
+ #ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE
+ #define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h"
+ #endif
+ #include CMSIS_NVIC_VIRTUAL_HEADER_FILE
+#else
+ #define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping
+ #define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping
+ #define NVIC_EnableIRQ __NVIC_EnableIRQ
+ #define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ
+ #define NVIC_DisableIRQ __NVIC_DisableIRQ
+ #define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ
+ #define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ
+ #define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ
+ #define NVIC_GetActive __NVIC_GetActive
+ #define NVIC_SetPriority __NVIC_SetPriority
+ #define NVIC_GetPriority __NVIC_GetPriority
+ #define NVIC_SystemReset __NVIC_SystemReset
+#endif /* CMSIS_NVIC_VIRTUAL */
+
+#ifdef CMSIS_VECTAB_VIRTUAL
+ #ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE
+ #define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h"
+ #endif
+ #include CMSIS_VECTAB_VIRTUAL_HEADER_FILE
+#else
+ #define NVIC_SetVector __NVIC_SetVector
+ #define NVIC_GetVector __NVIC_GetVector
+#endif /* (CMSIS_VECTAB_VIRTUAL) */
+
+#define NVIC_USER_IRQ_OFFSET 16
+
+
+/* Special LR values for Secure/Non-Secure call handling and exception handling */
+
+/* Function Return Payload (from ARMv8-M Architecture Reference Manual) LR value on entry from Secure BLXNS */
+#define FNC_RETURN (0xFEFFFFFFUL) /* bit [0] ignored when processing a branch */
+
+/* The following EXC_RETURN mask values are used to evaluate the LR on exception entry */
+#define EXC_RETURN_PREFIX (0xFF000000UL) /* bits [31:24] set to indicate an EXC_RETURN value */
+#define EXC_RETURN_S (0x00000040UL) /* bit [6] stack used to push registers: 0=Non-secure 1=Secure */
+#define EXC_RETURN_DCRS (0x00000020UL) /* bit [5] stacking rules for called registers: 0=skipped 1=saved */
+#define EXC_RETURN_FTYPE (0x00000010UL) /* bit [4] allocate stack for floating-point context: 0=done 1=skipped */
+#define EXC_RETURN_MODE (0x00000008UL) /* bit [3] processor mode for return: 0=Handler mode 1=Thread mode */
+#define EXC_RETURN_SPSEL (0x00000004UL) /* bit [2] stack pointer used to restore context: 0=MSP 1=PSP */
+#define EXC_RETURN_ES (0x00000001UL) /* bit [0] security state exception was taken to: 0=Non-secure 1=Secure */
+
+/* Integrity Signature (from ARMv8-M Architecture Reference Manual) for exception context stacking */
+#if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) /* Value for processors with floating-point extension: */
+#define EXC_INTEGRITY_SIGNATURE (0xFEFA125AUL) /* bit [0] SFTC must match LR bit[4] EXC_RETURN_FTYPE */
+#else
+#define EXC_INTEGRITY_SIGNATURE (0xFEFA125BUL) /* Value for processors without floating-point extension */
+#endif
+
+
+/**
+ \brief Set Priority Grouping
+ \details Sets the priority grouping field using the required unlock sequence.
+ The parameter PriorityGroup is assigned to the field SCB->AIRCR [10:8] PRIGROUP field.
+ Only values from 0..7 are used.
+ In case of a conflict between priority grouping and available
+ priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set.
+ \param [in] PriorityGroup Priority grouping field.
+ */
+__STATIC_INLINE void __NVIC_SetPriorityGrouping(uint32_t PriorityGroup)
+{
+ uint32_t reg_value;
+ uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */
+
+ reg_value = SCB->AIRCR; /* read old register configuration */
+ reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */
+ reg_value = (reg_value |
+ ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) |
+ (PriorityGroupTmp << SCB_AIRCR_PRIGROUP_Pos) ); /* Insert write key and priority group */
+ SCB->AIRCR = reg_value;
+}
+
+
+/**
+ \brief Get Priority Grouping
+ \details Reads the priority grouping field from the NVIC Interrupt Controller.
+ \return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field).
+ */
+__STATIC_INLINE uint32_t __NVIC_GetPriorityGrouping(void)
+{
+ return ((uint32_t)((SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos));
+}
+
+
+/**
+ \brief Enable Interrupt
+ \details Enables a device specific interrupt in the NVIC interrupt controller.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Get Interrupt Enable status
+ \details Returns a device specific interrupt enable status from the NVIC interrupt controller.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 Interrupt is not enabled.
+ \return 1 Interrupt is enabled.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Disable Interrupt
+ \details Disables a device specific interrupt in the NVIC interrupt controller.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ICER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ __DSB();
+ __ISB();
+ }
+}
+
+
+/**
+ \brief Get Pending Interrupt
+ \details Reads the NVIC pending register and returns the pending bit for the specified device specific interrupt.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 Interrupt status is not pending.
+ \return 1 Interrupt status is pending.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Set Pending Interrupt
+ \details Sets the pending bit of a device specific interrupt in the NVIC pending register.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Clear Pending Interrupt
+ \details Clears the pending bit of a device specific interrupt in the NVIC pending register.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Get Active Interrupt
+ \details Reads the active register in the NVIC and returns the active bit for the device specific interrupt.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 Interrupt status is not active.
+ \return 1 Interrupt status is active.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t __NVIC_GetActive(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC->IABR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
+/**
+ \brief Get Interrupt Target State
+ \details Reads the interrupt target field in the NVIC and returns the interrupt target bit for the device specific interrupt.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 if interrupt is assigned to Secure
+ \return 1 if interrupt is assigned to Non Secure
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t NVIC_GetTargetState(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Set Interrupt Target State
+ \details Sets the interrupt target field in the NVIC and returns the interrupt target bit for the device specific interrupt.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 if interrupt is assigned to Secure
+ 1 if interrupt is assigned to Non Secure
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t NVIC_SetTargetState(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] |= ((uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)));
+ return((uint32_t)(((NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Clear Interrupt Target State
+ \details Clears the interrupt target field in the NVIC and returns the interrupt target bit for the device specific interrupt.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 if interrupt is assigned to Secure
+ 1 if interrupt is assigned to Non Secure
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t NVIC_ClearTargetState(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] &= ~((uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)));
+ return((uint32_t)(((NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */
+
+
+/**
+ \brief Set Interrupt Priority
+ \details Sets the priority of a device specific interrupt or a processor exception.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ \param [in] IRQn Interrupt number.
+ \param [in] priority Priority to set.
+ \note The priority cannot be set for every processor exception.
+ */
+__STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->IPR[((uint32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL);
+ }
+ else
+ {
+ SCB->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL);
+ }
+}
+
+
+/**
+ \brief Get Interrupt Priority
+ \details Reads the priority of a device specific interrupt or a processor exception.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ \param [in] IRQn Interrupt number.
+ \return Interrupt Priority.
+ Value is aligned automatically to the implemented priority bits of the microcontroller.
+ */
+__STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn)
+{
+
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return(((uint32_t)NVIC->IPR[((uint32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS)));
+ }
+ else
+ {
+ return(((uint32_t)SCB->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS)));
+ }
+}
+
+
+/**
+ \brief Encode Priority
+ \details Encodes the priority for an interrupt with the given priority group,
+ preemptive priority value, and subpriority value.
+ In case of a conflict between priority grouping and available
+ priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set.
+ \param [in] PriorityGroup Used priority group.
+ \param [in] PreemptPriority Preemptive priority value (starting from 0).
+ \param [in] SubPriority Subpriority value (starting from 0).
+ \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority().
+ */
+__STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority)
+{
+ uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */
+ uint32_t PreemptPriorityBits;
+ uint32_t SubPriorityBits;
+
+ PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp);
+ SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS));
+
+ return (
+ ((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) |
+ ((SubPriority & (uint32_t)((1UL << (SubPriorityBits )) - 1UL)))
+ );
+}
+
+
+/**
+ \brief Decode Priority
+ \details Decodes an interrupt priority value with a given priority group to
+ preemptive priority value and subpriority value.
+ In case of a conflict between priority grouping and available
+ priority bits (__NVIC_PRIO_BITS) the smallest possible priority group is set.
+ \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority().
+ \param [in] PriorityGroup Used priority group.
+ \param [out] pPreemptPriority Preemptive priority value (starting from 0).
+ \param [out] pSubPriority Subpriority value (starting from 0).
+ */
+__STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* const pPreemptPriority, uint32_t* const pSubPriority)
+{
+ uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */
+ uint32_t PreemptPriorityBits;
+ uint32_t SubPriorityBits;
+
+ PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp);
+ SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS));
+
+ *pPreemptPriority = (Priority >> SubPriorityBits) & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL);
+ *pSubPriority = (Priority ) & (uint32_t)((1UL << (SubPriorityBits )) - 1UL);
+}
+
+
+/**
+ \brief Set Interrupt Vector
+ \details Sets an interrupt vector in SRAM based interrupt vector table.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ VTOR must been relocated to SRAM before.
+ \param [in] IRQn Interrupt number
+ \param [in] vector Address of interrupt handler function
+ */
+__STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector)
+{
+ uint32_t *vectors = (uint32_t *)SCB->VTOR;
+ vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET] = vector;
+}
+
+
+/**
+ \brief Get Interrupt Vector
+ \details Reads an interrupt vector from interrupt vector table.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ \param [in] IRQn Interrupt number.
+ \return Address of interrupt handler function
+ */
+__STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn)
+{
+ uint32_t *vectors = (uint32_t *)SCB->VTOR;
+ return vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET];
+}
+
+
+/**
+ \brief System Reset
+ \details Initiates a system reset request to reset the MCU.
+ */
+__NO_RETURN __STATIC_INLINE void __NVIC_SystemReset(void)
+{
+ __DSB(); /* Ensure all outstanding memory accesses included
+ buffered write are completed before reset */
+ SCB->AIRCR = (uint32_t)((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) |
+ (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) |
+ SCB_AIRCR_SYSRESETREQ_Msk ); /* Keep priority group unchanged */
+ __DSB(); /* Ensure completion of memory access */
+
+ for(;;) /* wait until reset */
+ {
+ __NOP();
+ }
+}
+
+#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
+/**
+ \brief Set Priority Grouping (non-secure)
+ \details Sets the non-secure priority grouping field when in secure state using the required unlock sequence.
+ The parameter PriorityGroup is assigned to the field SCB->AIRCR [10:8] PRIGROUP field.
+ Only values from 0..7 are used.
+ In case of a conflict between priority grouping and available
+ priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set.
+ \param [in] PriorityGroup Priority grouping field.
+ */
+__STATIC_INLINE void TZ_NVIC_SetPriorityGrouping_NS(uint32_t PriorityGroup)
+{
+ uint32_t reg_value;
+ uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */
+
+ reg_value = SCB_NS->AIRCR; /* read old register configuration */
+ reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */
+ reg_value = (reg_value |
+ ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) |
+ (PriorityGroupTmp << SCB_AIRCR_PRIGROUP_Pos) ); /* Insert write key and priority group */
+ SCB_NS->AIRCR = reg_value;
+}
+
+
+/**
+ \brief Get Priority Grouping (non-secure)
+ \details Reads the priority grouping field from the non-secure NVIC when in secure state.
+ \return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field).
+ */
+__STATIC_INLINE uint32_t TZ_NVIC_GetPriorityGrouping_NS(void)
+{
+ return ((uint32_t)((SCB_NS->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos));
+}
+
+
+/**
+ \brief Enable Interrupt (non-secure)
+ \details Enables a device specific interrupt in the non-secure NVIC interrupt controller when in secure state.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void TZ_NVIC_EnableIRQ_NS(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC_NS->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Get Interrupt Enable status (non-secure)
+ \details Returns a device specific interrupt enable status from the non-secure NVIC interrupt controller when in secure state.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 Interrupt is not enabled.
+ \return 1 Interrupt is enabled.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t TZ_NVIC_GetEnableIRQ_NS(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC_NS->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Disable Interrupt (non-secure)
+ \details Disables a device specific interrupt in the non-secure NVIC interrupt controller when in secure state.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void TZ_NVIC_DisableIRQ_NS(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC_NS->ICER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Get Pending Interrupt (non-secure)
+ \details Reads the NVIC pending register in the non-secure NVIC when in secure state and returns the pending bit for the specified device specific interrupt.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 Interrupt status is not pending.
+ \return 1 Interrupt status is pending.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t TZ_NVIC_GetPendingIRQ_NS(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC_NS->ISPR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Set Pending Interrupt (non-secure)
+ \details Sets the pending bit of a device specific interrupt in the non-secure NVIC pending register when in secure state.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void TZ_NVIC_SetPendingIRQ_NS(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC_NS->ISPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Clear Pending Interrupt (non-secure)
+ \details Clears the pending bit of a device specific interrupt in the non-secure NVIC pending register when in secure state.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void TZ_NVIC_ClearPendingIRQ_NS(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC_NS->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Get Active Interrupt (non-secure)
+ \details Reads the active register in non-secure NVIC when in secure state and returns the active bit for the device specific interrupt.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 Interrupt status is not active.
+ \return 1 Interrupt status is active.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t TZ_NVIC_GetActive_NS(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC_NS->IABR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Set Interrupt Priority (non-secure)
+ \details Sets the priority of a non-secure device specific interrupt or a non-secure processor exception when in secure state.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ \param [in] IRQn Interrupt number.
+ \param [in] priority Priority to set.
+ \note The priority cannot be set for every non-secure processor exception.
+ */
+__STATIC_INLINE void TZ_NVIC_SetPriority_NS(IRQn_Type IRQn, uint32_t priority)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC_NS->IPR[((uint32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL);
+ }
+ else
+ {
+ SCB_NS->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL);
+ }
+}
+
+
+/**
+ \brief Get Interrupt Priority (non-secure)
+ \details Reads the priority of a non-secure device specific interrupt or a non-secure processor exception when in secure state.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ \param [in] IRQn Interrupt number.
+ \return Interrupt Priority. Value is aligned automatically to the implemented priority bits of the microcontroller.
+ */
+__STATIC_INLINE uint32_t TZ_NVIC_GetPriority_NS(IRQn_Type IRQn)
+{
+
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return(((uint32_t)NVIC_NS->IPR[((uint32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS)));
+ }
+ else
+ {
+ return(((uint32_t)SCB_NS->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS)));
+ }
+}
+#endif /* defined (__ARM_FEATURE_CMSE) &&(__ARM_FEATURE_CMSE == 3U) */
+
+/*@} end of CMSIS_Core_NVICFunctions */
+
+/* ########################## MPU functions #################################### */
+
+#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U)
+
+#include "mpu_armv8.h"
+
+#endif
+
+/* ########################## FPU functions #################################### */
+/**
+ \ingroup CMSIS_Core_FunctionInterface
+ \defgroup CMSIS_Core_FpuFunctions FPU Functions
+ \brief Function that provides FPU type.
+ @{
+ */
+
+/**
+ \brief get FPU type
+ \details returns the FPU type
+ \returns
+ - \b 0: No FPU
+ - \b 1: Single precision FPU
+ - \b 2: Double + Single precision FPU
+ */
+__STATIC_INLINE uint32_t SCB_GetFPUType(void)
+{
+ uint32_t mvfr0;
+
+ mvfr0 = FPU->MVFR0;
+ if ((mvfr0 & (FPU_MVFR0_Single_precision_Msk | FPU_MVFR0_Double_precision_Msk)) == 0x220U)
+ {
+ return 2U; /* Double + Single precision FPU */
+ }
+ else if ((mvfr0 & (FPU_MVFR0_Single_precision_Msk | FPU_MVFR0_Double_precision_Msk)) == 0x020U)
+ {
+ return 1U; /* Single precision FPU */
+ }
+ else
+ {
+ return 0U; /* No FPU */
+ }
+}
+
+
+/*@} end of CMSIS_Core_FpuFunctions */
+
+
+
+/* ########################## SAU functions #################################### */
+/**
+ \ingroup CMSIS_Core_FunctionInterface
+ \defgroup CMSIS_Core_SAUFunctions SAU Functions
+ \brief Functions that configure the SAU.
+ @{
+ */
+
+#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
+
+/**
+ \brief Enable SAU
+ \details Enables the Security Attribution Unit (SAU).
+ */
+__STATIC_INLINE void TZ_SAU_Enable(void)
+{
+ SAU->CTRL |= (SAU_CTRL_ENABLE_Msk);
+}
+
+
+
+/**
+ \brief Disable SAU
+ \details Disables the Security Attribution Unit (SAU).
+ */
+__STATIC_INLINE void TZ_SAU_Disable(void)
+{
+ SAU->CTRL &= ~(SAU_CTRL_ENABLE_Msk);
+}
+
+#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */
+
+/*@} end of CMSIS_Core_SAUFunctions */
+
+
+
+
+/* ################################## SysTick function ############################################ */
+/**
+ \ingroup CMSIS_Core_FunctionInterface
+ \defgroup CMSIS_Core_SysTickFunctions SysTick Functions
+ \brief Functions that configure the System.
+ @{
+ */
+
+#if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U)
+
+/**
+ \brief System Tick Configuration
+ \details Initializes the System Timer and its interrupt, and starts the System Tick Timer.
+ Counter is in free running mode to generate periodic interrupts.
+ \param [in] ticks Number of ticks between two interrupts.
+ \return 0 Function succeeded.
+ \return 1 Function failed.
+ \note When the variable __Vendor_SysTickConfig is set to 1, then the
+ function SysTick_Config is not included. In this case, the file device.h
+ must contain a vendor-specific implementation of this function.
+ */
+__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)
+{
+ if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk)
+ {
+ return (1UL); /* Reload value impossible */
+ }
+
+ SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */
+ NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */
+ SysTick->VAL = 0UL; /* Load the SysTick Counter Value */
+ SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
+ SysTick_CTRL_TICKINT_Msk |
+ SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */
+ return (0UL); /* Function successful */
+}
+
+#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
+/**
+ \brief System Tick Configuration (non-secure)
+ \details Initializes the non-secure System Timer and its interrupt when in secure state, and starts the System Tick Timer.
+ Counter is in free running mode to generate periodic interrupts.
+ \param [in] ticks Number of ticks between two interrupts.
+ \return 0 Function succeeded.
+ \return 1 Function failed.
+ \note When the variable __Vendor_SysTickConfig is set to 1, then the
+ function TZ_SysTick_Config_NS is not included. In this case, the file device.h
+ must contain a vendor-specific implementation of this function.
+
+ */
+__STATIC_INLINE uint32_t TZ_SysTick_Config_NS(uint32_t ticks)
+{
+ if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk)
+ {
+ return (1UL); /* Reload value impossible */
+ }
+
+ SysTick_NS->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */
+ TZ_NVIC_SetPriority_NS (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */
+ SysTick_NS->VAL = 0UL; /* Load the SysTick Counter Value */
+ SysTick_NS->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
+ SysTick_CTRL_TICKINT_Msk |
+ SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */
+ return (0UL); /* Function successful */
+}
+#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */
+
+#endif
+
+/*@} end of CMSIS_Core_SysTickFunctions */
+
+
+
+/* ##################################### Debug In/Output function ########################################### */
+/**
+ \ingroup CMSIS_Core_FunctionInterface
+ \defgroup CMSIS_core_DebugFunctions ITM Functions
+ \brief Functions that access the ITM debug interface.
+ @{
+ */
+
+extern volatile int32_t ITM_RxBuffer; /*!< External variable to receive characters. */
+#define ITM_RXBUFFER_EMPTY ((int32_t)0x5AA55AA5U) /*!< Value identifying \ref ITM_RxBuffer is ready for next character. */
+
+
+/**
+ \brief ITM Send Character
+ \details Transmits a character via the ITM channel 0, and
+ \li Just returns when no debugger is connected that has booked the output.
+ \li Is blocking when a debugger is connected, but the previous character sent has not been transmitted.
+ \param [in] ch Character to transmit.
+ \returns Character to transmit.
+ */
+__STATIC_INLINE uint32_t ITM_SendChar (uint32_t ch)
+{
+ if (((ITM->TCR & ITM_TCR_ITMENA_Msk) != 0UL) && /* ITM enabled */
+ ((ITM->TER & 1UL ) != 0UL) ) /* ITM Port #0 enabled */
+ {
+ while (ITM->PORT[0U].u32 == 0UL)
+ {
+ __NOP();
+ }
+ ITM->PORT[0U].u8 = (uint8_t)ch;
+ }
+ return (ch);
+}
+
+
+/**
+ \brief ITM Receive Character
+ \details Inputs a character via the external variable \ref ITM_RxBuffer.
+ \return Received character.
+ \return -1 No character pending.
+ */
+__STATIC_INLINE int32_t ITM_ReceiveChar (void)
+{
+ int32_t ch = -1; /* no character available */
+
+ if (ITM_RxBuffer != ITM_RXBUFFER_EMPTY)
+ {
+ ch = ITM_RxBuffer;
+ ITM_RxBuffer = ITM_RXBUFFER_EMPTY; /* ready for next character */
+ }
+
+ return (ch);
+}
+
+
+/**
+ \brief ITM Check Character
+ \details Checks whether a character is pending for reading in the variable \ref ITM_RxBuffer.
+ \return 0 No character available.
+ \return 1 Character available.
+ */
+__STATIC_INLINE int32_t ITM_CheckChar (void)
+{
+
+ if (ITM_RxBuffer == ITM_RXBUFFER_EMPTY)
+ {
+ return (0); /* no character available */
+ }
+ else
+ {
+ return (1); /* character available */
+ }
+}
+
+/*@} end of CMSIS_core_DebugFunctions */
+
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CORE_ARMV8MML_H_DEPENDANT */
+
+#endif /* __CMSIS_GENERIC */
diff --git a/lib/cmsis/inc/core_cm0.h b/lib/cmsis/inc/core_cm0.h
index 711dad5517..fcf27578cc 100644
--- a/lib/cmsis/inc/core_cm0.h
+++ b/lib/cmsis/inc/core_cm0.h
@@ -1,40 +1,30 @@
/**************************************************************************//**
* @file core_cm0.h
* @brief CMSIS Cortex-M0 Core Peripheral Access Layer Header File
- * @version V4.30
- * @date 20. October 2015
+ * @version V5.0.6
+ * @date 13. March 2019
******************************************************************************/
-/* Copyright (c) 2009 - 2015 ARM LIMITED
-
- All rights reserved.
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are met:
- - Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- - Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
- - Neither the name of ARM nor the names of its contributors may be used
- to endorse or promote products derived from this software without
- specific prior written permission.
- *
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE
- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- POSSIBILITY OF SUCH DAMAGE.
- ---------------------------------------------------------------------------*/
-
+/*
+ * Copyright (c) 2009-2019 Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
#if defined ( __ICCARM__ )
- #pragma system_include /* treat file as system include file for MISRA check */
-#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
+ #pragma system_include /* treat file as system include file for MISRA check */
+#elif defined (__clang__)
#pragma clang system_header /* treat file as system include file */
#endif
@@ -70,53 +60,15 @@
@{
*/
+#include "cmsis_version.h"
+
/* CMSIS CM0 definitions */
-#define __CM0_CMSIS_VERSION_MAIN (0x04U) /*!< [31:16] CMSIS HAL main version */
-#define __CM0_CMSIS_VERSION_SUB (0x1EU) /*!< [15:0] CMSIS HAL sub version */
+#define __CM0_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */
+#define __CM0_CMSIS_VERSION_SUB (__CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */
#define __CM0_CMSIS_VERSION ((__CM0_CMSIS_VERSION_MAIN << 16U) | \
- __CM0_CMSIS_VERSION_SUB ) /*!< CMSIS HAL version number */
-
-#define __CORTEX_M (0x00U) /*!< Cortex-M Core */
-
-
-#if defined ( __CC_ARM )
- #define __ASM __asm /*!< asm keyword for ARM Compiler */
- #define __INLINE __inline /*!< inline keyword for ARM Compiler */
- #define __STATIC_INLINE static __inline
-
-#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
- #define __ASM __asm /*!< asm keyword for ARM Compiler */
- #define __INLINE __inline /*!< inline keyword for ARM Compiler */
- #define __STATIC_INLINE static __inline
-
-#elif defined ( __GNUC__ )
- #define __ASM __asm /*!< asm keyword for GNU Compiler */
- #define __INLINE inline /*!< inline keyword for GNU Compiler */
- #define __STATIC_INLINE static inline
-
-#elif defined ( __ICCARM__ )
- #define __ASM __asm /*!< asm keyword for IAR Compiler */
- #define __INLINE inline /*!< inline keyword for IAR Compiler. Only available in High optimization mode! */
- #define __STATIC_INLINE static inline
-
-#elif defined ( __TMS470__ )
- #define __ASM __asm /*!< asm keyword for TI CCS Compiler */
- #define __STATIC_INLINE static inline
-
-#elif defined ( __TASKING__ )
- #define __ASM __asm /*!< asm keyword for TASKING Compiler */
- #define __INLINE inline /*!< inline keyword for TASKING Compiler */
- #define __STATIC_INLINE static inline
+ __CM0_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */
-#elif defined ( __CSMC__ )
- #define __packed
- #define __ASM _asm /*!< asm keyword for COSMIC Compiler */
- #define __INLINE inline /*!< inline keyword for COSMIC Compiler. Use -pc99 on compile line */
- #define __STATIC_INLINE static inline
-
-#else
- #error Unknown compiler
-#endif
+#define __CORTEX_M (0U) /*!< Cortex-M Core */
/** __FPU_USED indicates whether an FPU is used or not.
This core does not support an FPU at all
@@ -128,8 +80,8 @@
#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
#endif
-#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
- #if defined __ARM_PCS_VFP
+#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
+ #if defined __ARM_FP
#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
#endif
@@ -143,7 +95,7 @@
#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
#endif
-#elif defined ( __TMS470__ )
+#elif defined ( __TI_ARM__ )
#if defined __TI_VFP_SUPPORT__
#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
#endif
@@ -160,8 +112,8 @@
#endif
-#include "core_cmInstr.h" /* Core Instruction Access */
-#include "core_cmFunc.h" /* Core Function Access */
+#include "cmsis_compiler.h" /* CMSIS compiler specific defines */
+
#ifdef __cplusplus
}
@@ -364,7 +316,7 @@ typedef struct
__IOM uint32_t ISER[1U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */
uint32_t RESERVED0[31U];
__IOM uint32_t ICER[1U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */
- uint32_t RSERVED1[31U];
+ uint32_t RESERVED1[31U];
__IOM uint32_t ISPR[1U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */
uint32_t RESERVED2[31U];
__IOM uint32_t ICPR[1U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */
@@ -555,18 +507,18 @@ typedef struct
/**
\brief Mask and shift a bit field value for use in a register bit range.
\param[in] field Name of the register bit field.
- \param[in] value Value of the bit field.
+ \param[in] value Value of the bit field. This parameter is interpreted as an uint32_t type.
\return Masked and shifted value.
*/
-#define _VAL2FLD(field, value) ((value << field ## _Pos) & field ## _Msk)
+#define _VAL2FLD(field, value) (((uint32_t)(value) << field ## _Pos) & field ## _Msk)
/**
\brief Mask and shift a register value to extract a bit filed value.
\param[in] field Name of the register bit field.
- \param[in] value Value of register.
+ \param[in] value Value of register. This parameter is interpreted as an uint32_t type.
\return Masked and shifted bit field value.
*/
-#define _FLD2VAL(field, value) ((value & field ## _Msk) >> field ## _Pos)
+#define _FLD2VAL(field, value) (((uint32_t)(value) & field ## _Msk) >> field ## _Pos)
/*@} end of group CMSIS_core_bitfield */
@@ -578,7 +530,7 @@ typedef struct
@{
*/
-/* Memory mapping of Cortex-M0 Hardware */
+/* Memory mapping of Core Hardware */
#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */
#define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */
#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */
@@ -614,87 +566,177 @@ typedef struct
@{
*/
-/* Interrupt Priorities are WORD accessible only under ARMv6M */
+#ifdef CMSIS_NVIC_VIRTUAL
+ #ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE
+ #define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h"
+ #endif
+ #include CMSIS_NVIC_VIRTUAL_HEADER_FILE
+#else
+ #define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping
+ #define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping
+ #define NVIC_EnableIRQ __NVIC_EnableIRQ
+ #define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ
+ #define NVIC_DisableIRQ __NVIC_DisableIRQ
+ #define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ
+ #define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ
+ #define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ
+/*#define NVIC_GetActive __NVIC_GetActive not available for Cortex-M0 */
+ #define NVIC_SetPriority __NVIC_SetPriority
+ #define NVIC_GetPriority __NVIC_GetPriority
+ #define NVIC_SystemReset __NVIC_SystemReset
+#endif /* CMSIS_NVIC_VIRTUAL */
+
+#ifdef CMSIS_VECTAB_VIRTUAL
+ #ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE
+ #define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h"
+ #endif
+ #include CMSIS_VECTAB_VIRTUAL_HEADER_FILE
+#else
+ #define NVIC_SetVector __NVIC_SetVector
+ #define NVIC_GetVector __NVIC_GetVector
+#endif /* (CMSIS_VECTAB_VIRTUAL) */
+
+#define NVIC_USER_IRQ_OFFSET 16
+
+
+/* The following EXC_RETURN values are saved the LR on exception entry */
+#define EXC_RETURN_HANDLER (0xFFFFFFF1UL) /* return to Handler mode, uses MSP after return */
+#define EXC_RETURN_THREAD_MSP (0xFFFFFFF9UL) /* return to Thread mode, uses MSP after return */
+#define EXC_RETURN_THREAD_PSP (0xFFFFFFFDUL) /* return to Thread mode, uses PSP after return */
+
+
+/* Interrupt Priorities are WORD accessible only under Armv6-M */
/* The following MACROS handle generation of the register offset and byte masks */
#define _BIT_SHIFT(IRQn) ( ((((uint32_t)(int32_t)(IRQn)) ) & 0x03UL) * 8UL)
#define _SHP_IDX(IRQn) ( (((((uint32_t)(int32_t)(IRQn)) & 0x0FUL)-8UL) >> 2UL) )
#define _IP_IDX(IRQn) ( (((uint32_t)(int32_t)(IRQn)) >> 2UL) )
+#define __NVIC_SetPriorityGrouping(X) (void)(X)
+#define __NVIC_GetPriorityGrouping() (0U)
/**
- \brief Enable External Interrupt
- \details Enables a device-specific interrupt in the NVIC interrupt controller.
- \param [in] IRQn External interrupt number. Value cannot be negative.
+ \brief Enable Interrupt
+ \details Enables a device specific interrupt in the NVIC interrupt controller.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
*/
-__STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn)
+__STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn)
{
- NVIC->ISER[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL));
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ISER[0U] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
}
/**
- \brief Disable External Interrupt
- \details Disables a device-specific interrupt in the NVIC interrupt controller.
- \param [in] IRQn External interrupt number. Value cannot be negative.
+ \brief Get Interrupt Enable status
+ \details Returns a device specific interrupt enable status from the NVIC interrupt controller.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 Interrupt is not enabled.
+ \return 1 Interrupt is enabled.
+ \note IRQn must not be negative.
*/
-__STATIC_INLINE void NVIC_DisableIRQ(IRQn_Type IRQn)
+__STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn)
{
- NVIC->ICER[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL));
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC->ISER[0U] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Disable Interrupt
+ \details Disables a device specific interrupt in the NVIC interrupt controller.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ICER[0U] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ __DSB();
+ __ISB();
+ }
}
/**
\brief Get Pending Interrupt
- \details Reads the pending register in the NVIC and returns the pending bit for the specified interrupt.
- \param [in] IRQn Interrupt number.
+ \details Reads the NVIC pending register and returns the pending bit for the specified device specific interrupt.
+ \param [in] IRQn Device specific interrupt number.
\return 0 Interrupt status is not pending.
\return 1 Interrupt status is pending.
+ \note IRQn must not be negative.
*/
-__STATIC_INLINE uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn)
+__STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn)
{
- return((uint32_t)(((NVIC->ISPR[0U] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC->ISPR[0U] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
}
/**
\brief Set Pending Interrupt
- \details Sets the pending bit of an external interrupt.
- \param [in] IRQn Interrupt number. Value cannot be negative.
+ \details Sets the pending bit of a device specific interrupt in the NVIC pending register.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
*/
-__STATIC_INLINE void NVIC_SetPendingIRQ(IRQn_Type IRQn)
+__STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn)
{
- NVIC->ISPR[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL));
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ISPR[0U] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
}
/**
\brief Clear Pending Interrupt
- \details Clears the pending bit of an external interrupt.
- \param [in] IRQn External interrupt number. Value cannot be negative.
+ \details Clears the pending bit of a device specific interrupt in the NVIC pending register.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
*/
-__STATIC_INLINE void NVIC_ClearPendingIRQ(IRQn_Type IRQn)
+__STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn)
{
- NVIC->ICPR[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL));
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ICPR[0U] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
}
/**
\brief Set Interrupt Priority
- \details Sets the priority of an interrupt.
- \note The priority cannot be set for every core interrupt.
+ \details Sets the priority of a device specific interrupt or a processor exception.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
\param [in] IRQn Interrupt number.
\param [in] priority Priority to set.
+ \note The priority cannot be set for every processor exception.
*/
-__STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
+__STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
{
- if ((int32_t)(IRQn) < 0)
+ if ((int32_t)(IRQn) >= 0)
{
- SCB->SHP[_SHP_IDX(IRQn)] = ((uint32_t)(SCB->SHP[_SHP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) |
+ NVIC->IP[_IP_IDX(IRQn)] = ((uint32_t)(NVIC->IP[_IP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) |
(((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn)));
}
else
{
- NVIC->IP[_IP_IDX(IRQn)] = ((uint32_t)(NVIC->IP[_IP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) |
+ SCB->SHP[_SHP_IDX(IRQn)] = ((uint32_t)(SCB->SHP[_SHP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) |
(((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn)));
}
}
@@ -702,32 +744,116 @@ __STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
/**
\brief Get Interrupt Priority
- \details Reads the priority of an interrupt.
- The interrupt number can be positive to specify an external (device specific) interrupt,
- or negative to specify an internal (core) interrupt.
+ \details Reads the priority of a device specific interrupt or a processor exception.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
\param [in] IRQn Interrupt number.
\return Interrupt Priority.
Value is aligned automatically to the implemented priority bits of the microcontroller.
*/
-__STATIC_INLINE uint32_t NVIC_GetPriority(IRQn_Type IRQn)
+__STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn)
{
- if ((int32_t)(IRQn) < 0)
+ if ((int32_t)(IRQn) >= 0)
{
- return((uint32_t)(((SCB->SHP[_SHP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS)));
+ return((uint32_t)(((NVIC->IP[ _IP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS)));
}
else
{
- return((uint32_t)(((NVIC->IP[ _IP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS)));
+ return((uint32_t)(((SCB->SHP[_SHP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS)));
}
}
+/**
+ \brief Encode Priority
+ \details Encodes the priority for an interrupt with the given priority group,
+ preemptive priority value, and subpriority value.
+ In case of a conflict between priority grouping and available
+ priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set.
+ \param [in] PriorityGroup Used priority group.
+ \param [in] PreemptPriority Preemptive priority value (starting from 0).
+ \param [in] SubPriority Subpriority value (starting from 0).
+ \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority().
+ */
+__STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority)
+{
+ uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */
+ uint32_t PreemptPriorityBits;
+ uint32_t SubPriorityBits;
+
+ PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp);
+ SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS));
+
+ return (
+ ((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) |
+ ((SubPriority & (uint32_t)((1UL << (SubPriorityBits )) - 1UL)))
+ );
+}
+
+
+/**
+ \brief Decode Priority
+ \details Decodes an interrupt priority value with a given priority group to
+ preemptive priority value and subpriority value.
+ In case of a conflict between priority grouping and available
+ priority bits (__NVIC_PRIO_BITS) the smallest possible priority group is set.
+ \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority().
+ \param [in] PriorityGroup Used priority group.
+ \param [out] pPreemptPriority Preemptive priority value (starting from 0).
+ \param [out] pSubPriority Subpriority value (starting from 0).
+ */
+__STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* const pPreemptPriority, uint32_t* const pSubPriority)
+{
+ uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */
+ uint32_t PreemptPriorityBits;
+ uint32_t SubPriorityBits;
+
+ PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp);
+ SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS));
+
+ *pPreemptPriority = (Priority >> SubPriorityBits) & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL);
+ *pSubPriority = (Priority ) & (uint32_t)((1UL << (SubPriorityBits )) - 1UL);
+}
+
+
+
+/**
+ \brief Set Interrupt Vector
+ \details Sets an interrupt vector in SRAM based interrupt vector table.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ Address 0 must be mapped to SRAM.
+ \param [in] IRQn Interrupt number
+ \param [in] vector Address of interrupt handler function
+ */
+__STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector)
+{
+ uint32_t vectors = 0x0U;
+ (* (int *) (vectors + ((int32_t)IRQn + NVIC_USER_IRQ_OFFSET) * 4)) = vector;
+}
+
+
+/**
+ \brief Get Interrupt Vector
+ \details Reads an interrupt vector from interrupt vector table.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ \param [in] IRQn Interrupt number.
+ \return Address of interrupt handler function
+ */
+__STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn)
+{
+ uint32_t vectors = 0x0U;
+ return (uint32_t)(* (int *) (vectors + ((int32_t)IRQn + NVIC_USER_IRQ_OFFSET) * 4));
+}
+
+
/**
\brief System Reset
\details Initiates a system reset request to reset the MCU.
*/
-__STATIC_INLINE void NVIC_SystemReset(void)
+__NO_RETURN __STATIC_INLINE void __NVIC_SystemReset(void)
{
__DSB(); /* Ensure all outstanding memory accesses included
buffered write are completed before reset */
@@ -744,6 +870,31 @@ __STATIC_INLINE void NVIC_SystemReset(void)
/*@} end of CMSIS_Core_NVICFunctions */
+/* ########################## FPU functions #################################### */
+/**
+ \ingroup CMSIS_Core_FunctionInterface
+ \defgroup CMSIS_Core_FpuFunctions FPU Functions
+ \brief Function that provides FPU type.
+ @{
+ */
+
+/**
+ \brief get FPU type
+ \details returns the FPU type
+ \returns
+ - \b 0: No FPU
+ - \b 1: Single precision FPU
+ - \b 2: Double + Single precision FPU
+ */
+__STATIC_INLINE uint32_t SCB_GetFPUType(void)
+{
+ return 0U; /* No FPU */
+}
+
+
+/*@} end of CMSIS_Core_FpuFunctions */
+
+
/* ################################## SysTick function ############################################ */
/**
@@ -753,7 +904,7 @@ __STATIC_INLINE void NVIC_SystemReset(void)
@{
*/
-#if (__Vendor_SysTickConfig == 0U)
+#if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U)
/**
\brief System Tick Configuration
diff --git a/lib/cmsis/inc/core_cm0plus.h b/lib/cmsis/inc/core_cm0plus.h
index b04aa39053..65ea443095 100644
--- a/lib/cmsis/inc/core_cm0plus.h
+++ b/lib/cmsis/inc/core_cm0plus.h
@@ -1,40 +1,30 @@
/**************************************************************************//**
* @file core_cm0plus.h
* @brief CMSIS Cortex-M0+ Core Peripheral Access Layer Header File
- * @version V4.30
- * @date 20. October 2015
+ * @version V5.0.7
+ * @date 13. March 2019
******************************************************************************/
-/* Copyright (c) 2009 - 2015 ARM LIMITED
-
- All rights reserved.
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are met:
- - Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- - Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
- - Neither the name of ARM nor the names of its contributors may be used
- to endorse or promote products derived from this software without
- specific prior written permission.
- *
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE
- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- POSSIBILITY OF SUCH DAMAGE.
- ---------------------------------------------------------------------------*/
-
+/*
+ * Copyright (c) 2009-2018 Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
#if defined ( __ICCARM__ )
- #pragma system_include /* treat file as system include file for MISRA check */
-#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
+ #pragma system_include /* treat file as system include file for MISRA check */
+#elif defined (__clang__)
#pragma clang system_header /* treat file as system include file */
#endif
@@ -70,53 +60,15 @@
@{
*/
+#include "cmsis_version.h"
+
/* CMSIS CM0+ definitions */
-#define __CM0PLUS_CMSIS_VERSION_MAIN (0x04U) /*!< [31:16] CMSIS HAL main version */
-#define __CM0PLUS_CMSIS_VERSION_SUB (0x1EU) /*!< [15:0] CMSIS HAL sub version */
+#define __CM0PLUS_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */
+#define __CM0PLUS_CMSIS_VERSION_SUB (__CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */
#define __CM0PLUS_CMSIS_VERSION ((__CM0PLUS_CMSIS_VERSION_MAIN << 16U) | \
- __CM0PLUS_CMSIS_VERSION_SUB ) /*!< CMSIS HAL version number */
-
-#define __CORTEX_M (0x00U) /*!< Cortex-M Core */
-
-
-#if defined ( __CC_ARM )
- #define __ASM __asm /*!< asm keyword for ARM Compiler */
- #define __INLINE __inline /*!< inline keyword for ARM Compiler */
- #define __STATIC_INLINE static __inline
-
-#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
- #define __ASM __asm /*!< asm keyword for ARM Compiler */
- #define __INLINE __inline /*!< inline keyword for ARM Compiler */
- #define __STATIC_INLINE static __inline
-
-#elif defined ( __GNUC__ )
- #define __ASM __asm /*!< asm keyword for GNU Compiler */
- #define __INLINE inline /*!< inline keyword for GNU Compiler */
- #define __STATIC_INLINE static inline
-
-#elif defined ( __ICCARM__ )
- #define __ASM __asm /*!< asm keyword for IAR Compiler */
- #define __INLINE inline /*!< inline keyword for IAR Compiler. Only available in High optimization mode! */
- #define __STATIC_INLINE static inline
-
-#elif defined ( __TMS470__ )
- #define __ASM __asm /*!< asm keyword for TI CCS Compiler */
- #define __STATIC_INLINE static inline
-
-#elif defined ( __TASKING__ )
- #define __ASM __asm /*!< asm keyword for TASKING Compiler */
- #define __INLINE inline /*!< inline keyword for TASKING Compiler */
- #define __STATIC_INLINE static inline
-
-#elif defined ( __CSMC__ )
- #define __packed
- #define __ASM _asm /*!< asm keyword for COSMIC Compiler */
- #define __INLINE inline /*!< inline keyword for COSMIC Compiler. Use -pc99 on compile line */
- #define __STATIC_INLINE static inline
+ __CM0PLUS_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */
-#else
- #error Unknown compiler
-#endif
+#define __CORTEX_M (0U) /*!< Cortex-M Core */
/** __FPU_USED indicates whether an FPU is used or not.
This core does not support an FPU at all
@@ -128,8 +80,8 @@
#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
#endif
-#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
- #if defined __ARM_PCS_VFP
+#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
+ #if defined __ARM_FP
#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
#endif
@@ -143,7 +95,7 @@
#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
#endif
-#elif defined ( __TMS470__ )
+#elif defined ( __TI_ARM__ )
#if defined __TI_VFP_SUPPORT__
#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
#endif
@@ -160,8 +112,8 @@
#endif
-#include "core_cmInstr.h" /* Core Instruction Access */
-#include "core_cmFunc.h" /* Core Function Access */
+#include "cmsis_compiler.h" /* CMSIS compiler specific defines */
+
#ifdef __cplusplus
}
@@ -378,7 +330,7 @@ typedef struct
__IOM uint32_t ISER[1U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */
uint32_t RESERVED0[31U];
__IOM uint32_t ICER[1U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */
- uint32_t RSERVED1[31U];
+ uint32_t RESERVED1[31U];
__IOM uint32_t ISPR[1U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */
uint32_t RESERVED2[31U];
__IOM uint32_t ICPR[1U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */
@@ -404,7 +356,7 @@ typedef struct
{
__IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */
__IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */
-#if (__VTOR_PRESENT == 1U)
+#if defined (__VTOR_PRESENT) && (__VTOR_PRESENT == 1U)
__IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */
#else
uint32_t RESERVED0;
@@ -461,7 +413,7 @@ typedef struct
#define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */
#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */
-#if (__VTOR_PRESENT == 1U)
+#if defined (__VTOR_PRESENT) && (__VTOR_PRESENT == 1U)
/* SCB Interrupt Control State Register Definitions */
#define SCB_VTOR_TBLOFF_Pos 8U /*!< SCB VTOR: TBLOFF Position */
#define SCB_VTOR_TBLOFF_Msk (0xFFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */
@@ -558,7 +510,7 @@ typedef struct
/*@} end of group CMSIS_SysTick */
-#if (__MPU_PRESENT == 1U)
+#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U)
/**
\ingroup CMSIS_core_register
\defgroup CMSIS_MPU Memory Protection Unit (MPU)
@@ -578,6 +530,8 @@ typedef struct
__IOM uint32_t RASR; /*!< Offset: 0x010 (R/W) MPU Region Attribute and Size Register */
} MPU_Type;
+#define MPU_TYPE_RALIASES 1U
+
/* MPU Type Register Definitions */
#define MPU_TYPE_IREGION_Pos 16U /*!< MPU TYPE: IREGION Position */
#define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */
@@ -667,18 +621,18 @@ typedef struct
/**
\brief Mask and shift a bit field value for use in a register bit range.
\param[in] field Name of the register bit field.
- \param[in] value Value of the bit field.
+ \param[in] value Value of the bit field. This parameter is interpreted as an uint32_t type.
\return Masked and shifted value.
*/
-#define _VAL2FLD(field, value) ((value << field ## _Pos) & field ## _Msk)
+#define _VAL2FLD(field, value) (((uint32_t)(value) << field ## _Pos) & field ## _Msk)
/**
\brief Mask and shift a register value to extract a bit filed value.
\param[in] field Name of the register bit field.
- \param[in] value Value of register.
+ \param[in] value Value of register. This parameter is interpreted as an uint32_t type.
\return Masked and shifted bit field value.
*/
-#define _FLD2VAL(field, value) ((value & field ## _Msk) >> field ## _Pos)
+#define _FLD2VAL(field, value) (((uint32_t)(value) & field ## _Msk) >> field ## _Pos)
/*@} end of group CMSIS_core_bitfield */
@@ -690,7 +644,7 @@ typedef struct
@{
*/
-/* Memory mapping of Cortex-M0+ Hardware */
+/* Memory mapping of Core Hardware */
#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */
#define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */
#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */
@@ -700,7 +654,7 @@ typedef struct
#define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */
#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */
-#if (__MPU_PRESENT == 1U)
+#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U)
#define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */
#define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */
#endif
@@ -730,87 +684,177 @@ typedef struct
@{
*/
-/* Interrupt Priorities are WORD accessible only under ARMv6M */
+#ifdef CMSIS_NVIC_VIRTUAL
+ #ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE
+ #define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h"
+ #endif
+ #include CMSIS_NVIC_VIRTUAL_HEADER_FILE
+#else
+ #define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping
+ #define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping
+ #define NVIC_EnableIRQ __NVIC_EnableIRQ
+ #define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ
+ #define NVIC_DisableIRQ __NVIC_DisableIRQ
+ #define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ
+ #define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ
+ #define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ
+/*#define NVIC_GetActive __NVIC_GetActive not available for Cortex-M0+ */
+ #define NVIC_SetPriority __NVIC_SetPriority
+ #define NVIC_GetPriority __NVIC_GetPriority
+ #define NVIC_SystemReset __NVIC_SystemReset
+#endif /* CMSIS_NVIC_VIRTUAL */
+
+#ifdef CMSIS_VECTAB_VIRTUAL
+ #ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE
+ #define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h"
+ #endif
+ #include CMSIS_VECTAB_VIRTUAL_HEADER_FILE
+#else
+ #define NVIC_SetVector __NVIC_SetVector
+ #define NVIC_GetVector __NVIC_GetVector
+#endif /* (CMSIS_VECTAB_VIRTUAL) */
+
+#define NVIC_USER_IRQ_OFFSET 16
+
+
+/* The following EXC_RETURN values are saved the LR on exception entry */
+#define EXC_RETURN_HANDLER (0xFFFFFFF1UL) /* return to Handler mode, uses MSP after return */
+#define EXC_RETURN_THREAD_MSP (0xFFFFFFF9UL) /* return to Thread mode, uses MSP after return */
+#define EXC_RETURN_THREAD_PSP (0xFFFFFFFDUL) /* return to Thread mode, uses PSP after return */
+
+
+/* Interrupt Priorities are WORD accessible only under Armv6-M */
/* The following MACROS handle generation of the register offset and byte masks */
#define _BIT_SHIFT(IRQn) ( ((((uint32_t)(int32_t)(IRQn)) ) & 0x03UL) * 8UL)
#define _SHP_IDX(IRQn) ( (((((uint32_t)(int32_t)(IRQn)) & 0x0FUL)-8UL) >> 2UL) )
#define _IP_IDX(IRQn) ( (((uint32_t)(int32_t)(IRQn)) >> 2UL) )
+#define __NVIC_SetPriorityGrouping(X) (void)(X)
+#define __NVIC_GetPriorityGrouping() (0U)
/**
- \brief Enable External Interrupt
- \details Enables a device-specific interrupt in the NVIC interrupt controller.
- \param [in] IRQn External interrupt number. Value cannot be negative.
+ \brief Enable Interrupt
+ \details Enables a device specific interrupt in the NVIC interrupt controller.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
*/
-__STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn)
+__STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn)
{
- NVIC->ISER[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL));
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ISER[0U] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
}
/**
- \brief Disable External Interrupt
- \details Disables a device-specific interrupt in the NVIC interrupt controller.
- \param [in] IRQn External interrupt number. Value cannot be negative.
+ \brief Get Interrupt Enable status
+ \details Returns a device specific interrupt enable status from the NVIC interrupt controller.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 Interrupt is not enabled.
+ \return 1 Interrupt is enabled.
+ \note IRQn must not be negative.
*/
-__STATIC_INLINE void NVIC_DisableIRQ(IRQn_Type IRQn)
+__STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn)
{
- NVIC->ICER[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL));
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC->ISER[0U] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Disable Interrupt
+ \details Disables a device specific interrupt in the NVIC interrupt controller.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ICER[0U] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ __DSB();
+ __ISB();
+ }
}
/**
\brief Get Pending Interrupt
- \details Reads the pending register in the NVIC and returns the pending bit for the specified interrupt.
- \param [in] IRQn Interrupt number.
+ \details Reads the NVIC pending register and returns the pending bit for the specified device specific interrupt.
+ \param [in] IRQn Device specific interrupt number.
\return 0 Interrupt status is not pending.
\return 1 Interrupt status is pending.
+ \note IRQn must not be negative.
*/
-__STATIC_INLINE uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn)
+__STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn)
{
- return((uint32_t)(((NVIC->ISPR[0U] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC->ISPR[0U] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
}
/**
\brief Set Pending Interrupt
- \details Sets the pending bit of an external interrupt.
- \param [in] IRQn Interrupt number. Value cannot be negative.
+ \details Sets the pending bit of a device specific interrupt in the NVIC pending register.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
*/
-__STATIC_INLINE void NVIC_SetPendingIRQ(IRQn_Type IRQn)
+__STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn)
{
- NVIC->ISPR[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL));
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ISPR[0U] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
}
/**
\brief Clear Pending Interrupt
- \details Clears the pending bit of an external interrupt.
- \param [in] IRQn External interrupt number. Value cannot be negative.
+ \details Clears the pending bit of a device specific interrupt in the NVIC pending register.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
*/
-__STATIC_INLINE void NVIC_ClearPendingIRQ(IRQn_Type IRQn)
+__STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn)
{
- NVIC->ICPR[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL));
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ICPR[0U] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
}
/**
\brief Set Interrupt Priority
- \details Sets the priority of an interrupt.
- \note The priority cannot be set for every core interrupt.
+ \details Sets the priority of a device specific interrupt or a processor exception.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
\param [in] IRQn Interrupt number.
\param [in] priority Priority to set.
+ \note The priority cannot be set for every processor exception.
*/
-__STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
+__STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
{
- if ((int32_t)(IRQn) < 0)
+ if ((int32_t)(IRQn) >= 0)
{
- SCB->SHP[_SHP_IDX(IRQn)] = ((uint32_t)(SCB->SHP[_SHP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) |
+ NVIC->IP[_IP_IDX(IRQn)] = ((uint32_t)(NVIC->IP[_IP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) |
(((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn)));
}
else
{
- NVIC->IP[_IP_IDX(IRQn)] = ((uint32_t)(NVIC->IP[_IP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) |
+ SCB->SHP[_SHP_IDX(IRQn)] = ((uint32_t)(SCB->SHP[_SHP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) |
(((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn)));
}
}
@@ -818,32 +862,124 @@ __STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
/**
\brief Get Interrupt Priority
- \details Reads the priority of an interrupt.
- The interrupt number can be positive to specify an external (device specific) interrupt,
- or negative to specify an internal (core) interrupt.
+ \details Reads the priority of a device specific interrupt or a processor exception.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
\param [in] IRQn Interrupt number.
\return Interrupt Priority.
Value is aligned automatically to the implemented priority bits of the microcontroller.
*/
-__STATIC_INLINE uint32_t NVIC_GetPriority(IRQn_Type IRQn)
+__STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn)
{
- if ((int32_t)(IRQn) < 0)
+ if ((int32_t)(IRQn) >= 0)
{
- return((uint32_t)(((SCB->SHP[_SHP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS)));
+ return((uint32_t)(((NVIC->IP[ _IP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS)));
}
else
{
- return((uint32_t)(((NVIC->IP[ _IP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS)));
+ return((uint32_t)(((SCB->SHP[_SHP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS)));
}
}
+/**
+ \brief Encode Priority
+ \details Encodes the priority for an interrupt with the given priority group,
+ preemptive priority value, and subpriority value.
+ In case of a conflict between priority grouping and available
+ priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set.
+ \param [in] PriorityGroup Used priority group.
+ \param [in] PreemptPriority Preemptive priority value (starting from 0).
+ \param [in] SubPriority Subpriority value (starting from 0).
+ \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority().
+ */
+__STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority)
+{
+ uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */
+ uint32_t PreemptPriorityBits;
+ uint32_t SubPriorityBits;
+
+ PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp);
+ SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS));
+
+ return (
+ ((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) |
+ ((SubPriority & (uint32_t)((1UL << (SubPriorityBits )) - 1UL)))
+ );
+}
+
+
+/**
+ \brief Decode Priority
+ \details Decodes an interrupt priority value with a given priority group to
+ preemptive priority value and subpriority value.
+ In case of a conflict between priority grouping and available
+ priority bits (__NVIC_PRIO_BITS) the smallest possible priority group is set.
+ \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority().
+ \param [in] PriorityGroup Used priority group.
+ \param [out] pPreemptPriority Preemptive priority value (starting from 0).
+ \param [out] pSubPriority Subpriority value (starting from 0).
+ */
+__STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* const pPreemptPriority, uint32_t* const pSubPriority)
+{
+ uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */
+ uint32_t PreemptPriorityBits;
+ uint32_t SubPriorityBits;
+
+ PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp);
+ SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS));
+
+ *pPreemptPriority = (Priority >> SubPriorityBits) & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL);
+ *pSubPriority = (Priority ) & (uint32_t)((1UL << (SubPriorityBits )) - 1UL);
+}
+
+
+/**
+ \brief Set Interrupt Vector
+ \details Sets an interrupt vector in SRAM based interrupt vector table.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ VTOR must been relocated to SRAM before.
+ If VTOR is not present address 0 must be mapped to SRAM.
+ \param [in] IRQn Interrupt number
+ \param [in] vector Address of interrupt handler function
+ */
+__STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector)
+{
+#if defined (__VTOR_PRESENT) && (__VTOR_PRESENT == 1U)
+ uint32_t vectors = SCB->VTOR;
+#else
+ uint32_t vectors = 0x0U;
+#endif
+ (* (int *) (vectors + ((int32_t)IRQn + NVIC_USER_IRQ_OFFSET) * 4)) = vector;
+}
+
+
+/**
+ \brief Get Interrupt Vector
+ \details Reads an interrupt vector from interrupt vector table.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ \param [in] IRQn Interrupt number.
+ \return Address of interrupt handler function
+ */
+__STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn)
+{
+#if defined (__VTOR_PRESENT) && (__VTOR_PRESENT == 1U)
+ uint32_t vectors = SCB->VTOR;
+#else
+ uint32_t vectors = 0x0U;
+#endif
+ return (uint32_t)(* (int *) (vectors + ((int32_t)IRQn + NVIC_USER_IRQ_OFFSET) * 4));
+}
+
+
/**
\brief System Reset
\details Initiates a system reset request to reset the MCU.
*/
-__STATIC_INLINE void NVIC_SystemReset(void)
+__NO_RETURN __STATIC_INLINE void __NVIC_SystemReset(void)
{
__DSB(); /* Ensure all outstanding memory accesses included
buffered write are completed before reset */
@@ -859,6 +995,38 @@ __STATIC_INLINE void NVIC_SystemReset(void)
/*@} end of CMSIS_Core_NVICFunctions */
+/* ########################## MPU functions #################################### */
+
+#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U)
+
+#include "mpu_armv7.h"
+
+#endif
+
+/* ########################## FPU functions #################################### */
+/**
+ \ingroup CMSIS_Core_FunctionInterface
+ \defgroup CMSIS_Core_FpuFunctions FPU Functions
+ \brief Function that provides FPU type.
+ @{
+ */
+
+/**
+ \brief get FPU type
+ \details returns the FPU type
+ \returns
+ - \b 0: No FPU
+ - \b 1: Single precision FPU
+ - \b 2: Double + Single precision FPU
+ */
+__STATIC_INLINE uint32_t SCB_GetFPUType(void)
+{
+ return 0U; /* No FPU */
+}
+
+
+/*@} end of CMSIS_Core_FpuFunctions */
+
/* ################################## SysTick function ############################################ */
@@ -869,7 +1037,7 @@ __STATIC_INLINE void NVIC_SystemReset(void)
@{
*/
-#if (__Vendor_SysTickConfig == 0U)
+#if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U)
/**
\brief System Tick Configuration
diff --git a/lib/cmsis/inc/core_cm1.h b/lib/cmsis/inc/core_cm1.h
new file mode 100644
index 0000000000..72c515cb09
--- /dev/null
+++ b/lib/cmsis/inc/core_cm1.h
@@ -0,0 +1,976 @@
+/**************************************************************************//**
+ * @file core_cm1.h
+ * @brief CMSIS Cortex-M1 Core Peripheral Access Layer Header File
+ * @version V1.0.1
+ * @date 12. November 2018
+ ******************************************************************************/
+/*
+ * Copyright (c) 2009-2018 Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#if defined ( __ICCARM__ )
+ #pragma system_include /* treat file as system include file for MISRA check */
+#elif defined (__clang__)
+ #pragma clang system_header /* treat file as system include file */
+#endif
+
+#ifndef __CORE_CM1_H_GENERIC
+#define __CORE_CM1_H_GENERIC
+
+#include
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/**
+ \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions
+ CMSIS violates the following MISRA-C:2004 rules:
+
+ \li Required Rule 8.5, object/function definition in header file.
+ Function definitions in header files are used to allow 'inlining'.
+
+ \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
+ Unions are used for effective representation of core registers.
+
+ \li Advisory Rule 19.7, Function-like macro defined.
+ Function-like macros are used to allow more efficient code.
+ */
+
+
+/*******************************************************************************
+ * CMSIS definitions
+ ******************************************************************************/
+/**
+ \ingroup Cortex_M1
+ @{
+ */
+
+#include "cmsis_version.h"
+
+/* CMSIS CM1 definitions */
+#define __CM1_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */
+#define __CM1_CMSIS_VERSION_SUB (__CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */
+#define __CM1_CMSIS_VERSION ((__CM1_CMSIS_VERSION_MAIN << 16U) | \
+ __CM1_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */
+
+#define __CORTEX_M (1U) /*!< Cortex-M Core */
+
+/** __FPU_USED indicates whether an FPU is used or not.
+ This core does not support an FPU at all
+*/
+#define __FPU_USED 0U
+
+#if defined ( __CC_ARM )
+ #if defined __TARGET_FPU_VFP
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #endif
+
+#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
+ #if defined __ARM_FP
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #endif
+
+#elif defined ( __GNUC__ )
+ #if defined (__VFP_FP__) && !defined(__SOFTFP__)
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #endif
+
+#elif defined ( __ICCARM__ )
+ #if defined __ARMVFP__
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #endif
+
+#elif defined ( __TI_ARM__ )
+ #if defined __TI_VFP_SUPPORT__
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #endif
+
+#elif defined ( __TASKING__ )
+ #if defined __FPU_VFP__
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #endif
+
+#elif defined ( __CSMC__ )
+ #if ( __CSMC__ & 0x400U)
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #endif
+
+#endif
+
+#include "cmsis_compiler.h" /* CMSIS compiler specific defines */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CORE_CM1_H_GENERIC */
+
+#ifndef __CMSIS_GENERIC
+
+#ifndef __CORE_CM1_H_DEPENDANT
+#define __CORE_CM1_H_DEPENDANT
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/* check device defines and use defaults */
+#if defined __CHECK_DEVICE_DEFINES
+ #ifndef __CM1_REV
+ #define __CM1_REV 0x0100U
+ #warning "__CM1_REV not defined in device header file; using default!"
+ #endif
+
+ #ifndef __NVIC_PRIO_BITS
+ #define __NVIC_PRIO_BITS 2U
+ #warning "__NVIC_PRIO_BITS not defined in device header file; using default!"
+ #endif
+
+ #ifndef __Vendor_SysTickConfig
+ #define __Vendor_SysTickConfig 0U
+ #warning "__Vendor_SysTickConfig not defined in device header file; using default!"
+ #endif
+#endif
+
+/* IO definitions (access restrictions to peripheral registers) */
+/**
+ \defgroup CMSIS_glob_defs CMSIS Global Defines
+
+ IO Type Qualifiers are used
+ \li to specify the access to peripheral variables.
+ \li for automatic generation of peripheral register debug information.
+*/
+#ifdef __cplusplus
+ #define __I volatile /*!< Defines 'read only' permissions */
+#else
+ #define __I volatile const /*!< Defines 'read only' permissions */
+#endif
+#define __O volatile /*!< Defines 'write only' permissions */
+#define __IO volatile /*!< Defines 'read / write' permissions */
+
+/* following defines should be used for structure members */
+#define __IM volatile const /*! Defines 'read only' structure member permissions */
+#define __OM volatile /*! Defines 'write only' structure member permissions */
+#define __IOM volatile /*! Defines 'read / write' structure member permissions */
+
+/*@} end of group Cortex_M1 */
+
+
+
+/*******************************************************************************
+ * Register Abstraction
+ Core Register contain:
+ - Core Register
+ - Core NVIC Register
+ - Core SCB Register
+ - Core SysTick Register
+ ******************************************************************************/
+/**
+ \defgroup CMSIS_core_register Defines and Type Definitions
+ \brief Type definitions and defines for Cortex-M processor based devices.
+*/
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_CORE Status and Control Registers
+ \brief Core Register type definitions.
+ @{
+ */
+
+/**
+ \brief Union type to access the Application Program Status Register (APSR).
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t _reserved0:28; /*!< bit: 0..27 Reserved */
+ uint32_t V:1; /*!< bit: 28 Overflow condition code flag */
+ uint32_t C:1; /*!< bit: 29 Carry condition code flag */
+ uint32_t Z:1; /*!< bit: 30 Zero condition code flag */
+ uint32_t N:1; /*!< bit: 31 Negative condition code flag */
+ } b; /*!< Structure used for bit access */
+ uint32_t w; /*!< Type used for word access */
+} APSR_Type;
+
+/* APSR Register Definitions */
+#define APSR_N_Pos 31U /*!< APSR: N Position */
+#define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */
+
+#define APSR_Z_Pos 30U /*!< APSR: Z Position */
+#define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */
+
+#define APSR_C_Pos 29U /*!< APSR: C Position */
+#define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */
+
+#define APSR_V_Pos 28U /*!< APSR: V Position */
+#define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */
+
+
+/**
+ \brief Union type to access the Interrupt Program Status Register (IPSR).
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */
+ uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */
+ } b; /*!< Structure used for bit access */
+ uint32_t w; /*!< Type used for word access */
+} IPSR_Type;
+
+/* IPSR Register Definitions */
+#define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */
+#define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */
+
+
+/**
+ \brief Union type to access the Special-Purpose Program Status Registers (xPSR).
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */
+ uint32_t _reserved0:15; /*!< bit: 9..23 Reserved */
+ uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */
+ uint32_t _reserved1:3; /*!< bit: 25..27 Reserved */
+ uint32_t V:1; /*!< bit: 28 Overflow condition code flag */
+ uint32_t C:1; /*!< bit: 29 Carry condition code flag */
+ uint32_t Z:1; /*!< bit: 30 Zero condition code flag */
+ uint32_t N:1; /*!< bit: 31 Negative condition code flag */
+ } b; /*!< Structure used for bit access */
+ uint32_t w; /*!< Type used for word access */
+} xPSR_Type;
+
+/* xPSR Register Definitions */
+#define xPSR_N_Pos 31U /*!< xPSR: N Position */
+#define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */
+
+#define xPSR_Z_Pos 30U /*!< xPSR: Z Position */
+#define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */
+
+#define xPSR_C_Pos 29U /*!< xPSR: C Position */
+#define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */
+
+#define xPSR_V_Pos 28U /*!< xPSR: V Position */
+#define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */
+
+#define xPSR_T_Pos 24U /*!< xPSR: T Position */
+#define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */
+
+#define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */
+#define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */
+
+
+/**
+ \brief Union type to access the Control Registers (CONTROL).
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t _reserved0:1; /*!< bit: 0 Reserved */
+ uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */
+ uint32_t _reserved1:30; /*!< bit: 2..31 Reserved */
+ } b; /*!< Structure used for bit access */
+ uint32_t w; /*!< Type used for word access */
+} CONTROL_Type;
+
+/* CONTROL Register Definitions */
+#define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */
+#define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */
+
+/*@} end of group CMSIS_CORE */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC)
+ \brief Type definitions for the NVIC Registers
+ @{
+ */
+
+/**
+ \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC).
+ */
+typedef struct
+{
+ __IOM uint32_t ISER[1U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */
+ uint32_t RESERVED0[31U];
+ __IOM uint32_t ICER[1U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */
+ uint32_t RSERVED1[31U];
+ __IOM uint32_t ISPR[1U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */
+ uint32_t RESERVED2[31U];
+ __IOM uint32_t ICPR[1U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */
+ uint32_t RESERVED3[31U];
+ uint32_t RESERVED4[64U];
+ __IOM uint32_t IP[8U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register */
+} NVIC_Type;
+
+/*@} end of group CMSIS_NVIC */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_SCB System Control Block (SCB)
+ \brief Type definitions for the System Control Block Registers
+ @{
+ */
+
+/**
+ \brief Structure type to access the System Control Block (SCB).
+ */
+typedef struct
+{
+ __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */
+ __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */
+ uint32_t RESERVED0;
+ __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */
+ __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */
+ __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */
+ uint32_t RESERVED1;
+ __IOM uint32_t SHP[2U]; /*!< Offset: 0x01C (R/W) System Handlers Priority Registers. [0] is RESERVED */
+ __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */
+} SCB_Type;
+
+/* SCB CPUID Register Definitions */
+#define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */
+#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */
+
+#define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */
+#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */
+
+#define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */
+#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */
+
+#define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */
+#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */
+
+#define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */
+#define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */
+
+/* SCB Interrupt Control State Register Definitions */
+#define SCB_ICSR_NMIPENDSET_Pos 31U /*!< SCB ICSR: NMIPENDSET Position */
+#define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */
+
+#define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */
+#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */
+
+#define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */
+#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */
+
+#define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */
+#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */
+
+#define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */
+#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */
+
+#define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */
+#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */
+
+#define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */
+#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */
+
+#define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */
+#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */
+
+#define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */
+#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */
+
+/* SCB Application Interrupt and Reset Control Register Definitions */
+#define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */
+#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */
+
+#define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */
+#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */
+
+#define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */
+#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */
+
+#define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */
+#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */
+
+#define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */
+#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */
+
+/* SCB System Control Register Definitions */
+#define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */
+#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */
+
+#define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */
+#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */
+
+#define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */
+#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */
+
+/* SCB Configuration Control Register Definitions */
+#define SCB_CCR_STKALIGN_Pos 9U /*!< SCB CCR: STKALIGN Position */
+#define SCB_CCR_STKALIGN_Msk (1UL << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */
+
+#define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */
+#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */
+
+/* SCB System Handler Control and State Register Definitions */
+#define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */
+#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */
+
+/*@} end of group CMSIS_SCB */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_SCnSCB System Controls not in SCB (SCnSCB)
+ \brief Type definitions for the System Control and ID Register not in the SCB
+ @{
+ */
+
+/**
+ \brief Structure type to access the System Control and ID Register not in the SCB.
+ */
+typedef struct
+{
+ uint32_t RESERVED0[2U];
+ __IOM uint32_t ACTLR; /*!< Offset: 0x008 (R/W) Auxiliary Control Register */
+} SCnSCB_Type;
+
+/* Auxiliary Control Register Definitions */
+#define SCnSCB_ACTLR_ITCMUAEN_Pos 4U /*!< ACTLR: Instruction TCM Upper Alias Enable Position */
+#define SCnSCB_ACTLR_ITCMUAEN_Msk (1UL << SCnSCB_ACTLR_ITCMUAEN_Pos) /*!< ACTLR: Instruction TCM Upper Alias Enable Mask */
+
+#define SCnSCB_ACTLR_ITCMLAEN_Pos 3U /*!< ACTLR: Instruction TCM Lower Alias Enable Position */
+#define SCnSCB_ACTLR_ITCMLAEN_Msk (1UL << SCnSCB_ACTLR_ITCMLAEN_Pos) /*!< ACTLR: Instruction TCM Lower Alias Enable Mask */
+
+/*@} end of group CMSIS_SCnotSCB */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_SysTick System Tick Timer (SysTick)
+ \brief Type definitions for the System Timer Registers.
+ @{
+ */
+
+/**
+ \brief Structure type to access the System Timer (SysTick).
+ */
+typedef struct
+{
+ __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */
+ __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */
+ __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */
+ __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */
+} SysTick_Type;
+
+/* SysTick Control / Status Register Definitions */
+#define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */
+#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */
+
+#define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */
+#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */
+
+#define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */
+#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */
+
+#define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */
+#define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */
+
+/* SysTick Reload Register Definitions */
+#define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */
+#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */
+
+/* SysTick Current Register Definitions */
+#define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */
+#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */
+
+/* SysTick Calibration Register Definitions */
+#define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */
+#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */
+
+#define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */
+#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */
+
+#define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */
+#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */
+
+/*@} end of group CMSIS_SysTick */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug)
+ \brief Cortex-M1 Core Debug Registers (DCB registers, SHCSR, and DFSR) are only accessible over DAP and not via processor.
+ Therefore they are not covered by the Cortex-M1 header file.
+ @{
+ */
+/*@} end of group CMSIS_CoreDebug */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_core_bitfield Core register bit field macros
+ \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk).
+ @{
+ */
+
+/**
+ \brief Mask and shift a bit field value for use in a register bit range.
+ \param[in] field Name of the register bit field.
+ \param[in] value Value of the bit field. This parameter is interpreted as an uint32_t type.
+ \return Masked and shifted value.
+*/
+#define _VAL2FLD(field, value) (((uint32_t)(value) << field ## _Pos) & field ## _Msk)
+
+/**
+ \brief Mask and shift a register value to extract a bit filed value.
+ \param[in] field Name of the register bit field.
+ \param[in] value Value of register. This parameter is interpreted as an uint32_t type.
+ \return Masked and shifted bit field value.
+*/
+#define _FLD2VAL(field, value) (((uint32_t)(value) & field ## _Msk) >> field ## _Pos)
+
+/*@} end of group CMSIS_core_bitfield */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_core_base Core Definitions
+ \brief Definitions for base addresses, unions, and structures.
+ @{
+ */
+
+/* Memory mapping of Core Hardware */
+#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */
+#define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */
+#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */
+#define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */
+
+#define SCnSCB ((SCnSCB_Type *) SCS_BASE ) /*!< System control Register not in SCB */
+#define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */
+#define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */
+#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */
+
+
+/*@} */
+
+
+
+/*******************************************************************************
+ * Hardware Abstraction Layer
+ Core Function Interface contains:
+ - Core NVIC Functions
+ - Core SysTick Functions
+ - Core Register Access Functions
+ ******************************************************************************/
+/**
+ \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference
+*/
+
+
+
+/* ########################## NVIC functions #################################### */
+/**
+ \ingroup CMSIS_Core_FunctionInterface
+ \defgroup CMSIS_Core_NVICFunctions NVIC Functions
+ \brief Functions that manage interrupts and exceptions via the NVIC.
+ @{
+ */
+
+#ifdef CMSIS_NVIC_VIRTUAL
+ #ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE
+ #define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h"
+ #endif
+ #include CMSIS_NVIC_VIRTUAL_HEADER_FILE
+#else
+ #define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping
+ #define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping
+ #define NVIC_EnableIRQ __NVIC_EnableIRQ
+ #define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ
+ #define NVIC_DisableIRQ __NVIC_DisableIRQ
+ #define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ
+ #define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ
+ #define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ
+/*#define NVIC_GetActive __NVIC_GetActive not available for Cortex-M1 */
+ #define NVIC_SetPriority __NVIC_SetPriority
+ #define NVIC_GetPriority __NVIC_GetPriority
+ #define NVIC_SystemReset __NVIC_SystemReset
+#endif /* CMSIS_NVIC_VIRTUAL */
+
+#ifdef CMSIS_VECTAB_VIRTUAL
+ #ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE
+ #define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h"
+ #endif
+ #include CMSIS_VECTAB_VIRTUAL_HEADER_FILE
+#else
+ #define NVIC_SetVector __NVIC_SetVector
+ #define NVIC_GetVector __NVIC_GetVector
+#endif /* (CMSIS_VECTAB_VIRTUAL) */
+
+#define NVIC_USER_IRQ_OFFSET 16
+
+
+/* The following EXC_RETURN values are saved the LR on exception entry */
+#define EXC_RETURN_HANDLER (0xFFFFFFF1UL) /* return to Handler mode, uses MSP after return */
+#define EXC_RETURN_THREAD_MSP (0xFFFFFFF9UL) /* return to Thread mode, uses MSP after return */
+#define EXC_RETURN_THREAD_PSP (0xFFFFFFFDUL) /* return to Thread mode, uses PSP after return */
+
+
+/* Interrupt Priorities are WORD accessible only under Armv6-M */
+/* The following MACROS handle generation of the register offset and byte masks */
+#define _BIT_SHIFT(IRQn) ( ((((uint32_t)(int32_t)(IRQn)) ) & 0x03UL) * 8UL)
+#define _SHP_IDX(IRQn) ( (((((uint32_t)(int32_t)(IRQn)) & 0x0FUL)-8UL) >> 2UL) )
+#define _IP_IDX(IRQn) ( (((uint32_t)(int32_t)(IRQn)) >> 2UL) )
+
+#define __NVIC_SetPriorityGrouping(X) (void)(X)
+#define __NVIC_GetPriorityGrouping() (0U)
+
+/**
+ \brief Enable Interrupt
+ \details Enables a device specific interrupt in the NVIC interrupt controller.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ISER[0U] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Get Interrupt Enable status
+ \details Returns a device specific interrupt enable status from the NVIC interrupt controller.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 Interrupt is not enabled.
+ \return 1 Interrupt is enabled.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC->ISER[0U] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Disable Interrupt
+ \details Disables a device specific interrupt in the NVIC interrupt controller.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ICER[0U] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ __DSB();
+ __ISB();
+ }
+}
+
+
+/**
+ \brief Get Pending Interrupt
+ \details Reads the NVIC pending register and returns the pending bit for the specified device specific interrupt.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 Interrupt status is not pending.
+ \return 1 Interrupt status is pending.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC->ISPR[0U] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Set Pending Interrupt
+ \details Sets the pending bit of a device specific interrupt in the NVIC pending register.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ISPR[0U] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Clear Pending Interrupt
+ \details Clears the pending bit of a device specific interrupt in the NVIC pending register.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ICPR[0U] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Set Interrupt Priority
+ \details Sets the priority of a device specific interrupt or a processor exception.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ \param [in] IRQn Interrupt number.
+ \param [in] priority Priority to set.
+ \note The priority cannot be set for every processor exception.
+ */
+__STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->IP[_IP_IDX(IRQn)] = ((uint32_t)(NVIC->IP[_IP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) |
+ (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn)));
+ }
+ else
+ {
+ SCB->SHP[_SHP_IDX(IRQn)] = ((uint32_t)(SCB->SHP[_SHP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) |
+ (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn)));
+ }
+}
+
+
+/**
+ \brief Get Interrupt Priority
+ \details Reads the priority of a device specific interrupt or a processor exception.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ \param [in] IRQn Interrupt number.
+ \return Interrupt Priority.
+ Value is aligned automatically to the implemented priority bits of the microcontroller.
+ */
+__STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn)
+{
+
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC->IP[ _IP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS)));
+ }
+ else
+ {
+ return((uint32_t)(((SCB->SHP[_SHP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS)));
+ }
+}
+
+
+/**
+ \brief Encode Priority
+ \details Encodes the priority for an interrupt with the given priority group,
+ preemptive priority value, and subpriority value.
+ In case of a conflict between priority grouping and available
+ priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set.
+ \param [in] PriorityGroup Used priority group.
+ \param [in] PreemptPriority Preemptive priority value (starting from 0).
+ \param [in] SubPriority Subpriority value (starting from 0).
+ \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority().
+ */
+__STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority)
+{
+ uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */
+ uint32_t PreemptPriorityBits;
+ uint32_t SubPriorityBits;
+
+ PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp);
+ SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS));
+
+ return (
+ ((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) |
+ ((SubPriority & (uint32_t)((1UL << (SubPriorityBits )) - 1UL)))
+ );
+}
+
+
+/**
+ \brief Decode Priority
+ \details Decodes an interrupt priority value with a given priority group to
+ preemptive priority value and subpriority value.
+ In case of a conflict between priority grouping and available
+ priority bits (__NVIC_PRIO_BITS) the smallest possible priority group is set.
+ \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority().
+ \param [in] PriorityGroup Used priority group.
+ \param [out] pPreemptPriority Preemptive priority value (starting from 0).
+ \param [out] pSubPriority Subpriority value (starting from 0).
+ */
+__STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* const pPreemptPriority, uint32_t* const pSubPriority)
+{
+ uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */
+ uint32_t PreemptPriorityBits;
+ uint32_t SubPriorityBits;
+
+ PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp);
+ SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS));
+
+ *pPreemptPriority = (Priority >> SubPriorityBits) & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL);
+ *pSubPriority = (Priority ) & (uint32_t)((1UL << (SubPriorityBits )) - 1UL);
+}
+
+
+
+/**
+ \brief Set Interrupt Vector
+ \details Sets an interrupt vector in SRAM based interrupt vector table.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ Address 0 must be mapped to SRAM.
+ \param [in] IRQn Interrupt number
+ \param [in] vector Address of interrupt handler function
+ */
+__STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector)
+{
+ uint32_t *vectors = (uint32_t *)0x0U;
+ vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET] = vector;
+}
+
+
+/**
+ \brief Get Interrupt Vector
+ \details Reads an interrupt vector from interrupt vector table.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ \param [in] IRQn Interrupt number.
+ \return Address of interrupt handler function
+ */
+__STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn)
+{
+ uint32_t *vectors = (uint32_t *)0x0U;
+ return vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET];
+}
+
+
+/**
+ \brief System Reset
+ \details Initiates a system reset request to reset the MCU.
+ */
+__NO_RETURN __STATIC_INLINE void __NVIC_SystemReset(void)
+{
+ __DSB(); /* Ensure all outstanding memory accesses included
+ buffered write are completed before reset */
+ SCB->AIRCR = ((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) |
+ SCB_AIRCR_SYSRESETREQ_Msk);
+ __DSB(); /* Ensure completion of memory access */
+
+ for(;;) /* wait until reset */
+ {
+ __NOP();
+ }
+}
+
+/*@} end of CMSIS_Core_NVICFunctions */
+
+
+/* ########################## FPU functions #################################### */
+/**
+ \ingroup CMSIS_Core_FunctionInterface
+ \defgroup CMSIS_Core_FpuFunctions FPU Functions
+ \brief Function that provides FPU type.
+ @{
+ */
+
+/**
+ \brief get FPU type
+ \details returns the FPU type
+ \returns
+ - \b 0: No FPU
+ - \b 1: Single precision FPU
+ - \b 2: Double + Single precision FPU
+ */
+__STATIC_INLINE uint32_t SCB_GetFPUType(void)
+{
+ return 0U; /* No FPU */
+}
+
+
+/*@} end of CMSIS_Core_FpuFunctions */
+
+
+
+/* ################################## SysTick function ############################################ */
+/**
+ \ingroup CMSIS_Core_FunctionInterface
+ \defgroup CMSIS_Core_SysTickFunctions SysTick Functions
+ \brief Functions that configure the System.
+ @{
+ */
+
+#if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U)
+
+/**
+ \brief System Tick Configuration
+ \details Initializes the System Timer and its interrupt, and starts the System Tick Timer.
+ Counter is in free running mode to generate periodic interrupts.
+ \param [in] ticks Number of ticks between two interrupts.
+ \return 0 Function succeeded.
+ \return 1 Function failed.
+ \note When the variable __Vendor_SysTickConfig is set to 1, then the
+ function SysTick_Config is not included. In this case, the file device.h
+ must contain a vendor-specific implementation of this function.
+ */
+__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)
+{
+ if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk)
+ {
+ return (1UL); /* Reload value impossible */
+ }
+
+ SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */
+ NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */
+ SysTick->VAL = 0UL; /* Load the SysTick Counter Value */
+ SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
+ SysTick_CTRL_TICKINT_Msk |
+ SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */
+ return (0UL); /* Function successful */
+}
+
+#endif
+
+/*@} end of CMSIS_Core_SysTickFunctions */
+
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CORE_CM1_H_DEPENDANT */
+
+#endif /* __CMSIS_GENERIC */
diff --git a/lib/cmsis/inc/core_cm23.h b/lib/cmsis/inc/core_cm23.h
new file mode 100644
index 0000000000..26fe163a0e
--- /dev/null
+++ b/lib/cmsis/inc/core_cm23.h
@@ -0,0 +1,1993 @@
+/**************************************************************************//**
+ * @file core_cm23.h
+ * @brief CMSIS Cortex-M23 Core Peripheral Access Layer Header File
+ * @version V5.0.8
+ * @date 12. November 2018
+ ******************************************************************************/
+/*
+ * Copyright (c) 2009-2018 Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#if defined ( __ICCARM__ )
+ #pragma system_include /* treat file as system include file for MISRA check */
+#elif defined (__clang__)
+ #pragma clang system_header /* treat file as system include file */
+#endif
+
+#ifndef __CORE_CM23_H_GENERIC
+#define __CORE_CM23_H_GENERIC
+
+#include
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/**
+ \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions
+ CMSIS violates the following MISRA-C:2004 rules:
+
+ \li Required Rule 8.5, object/function definition in header file.
+ Function definitions in header files are used to allow 'inlining'.
+
+ \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
+ Unions are used for effective representation of core registers.
+
+ \li Advisory Rule 19.7, Function-like macro defined.
+ Function-like macros are used to allow more efficient code.
+ */
+
+
+/*******************************************************************************
+ * CMSIS definitions
+ ******************************************************************************/
+/**
+ \ingroup Cortex_M23
+ @{
+ */
+
+#include "cmsis_version.h"
+
+/* CMSIS definitions */
+#define __CM23_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */
+#define __CM23_CMSIS_VERSION_SUB (__CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */
+#define __CM23_CMSIS_VERSION ((__CM23_CMSIS_VERSION_MAIN << 16U) | \
+ __CM23_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */
+
+#define __CORTEX_M (23U) /*!< Cortex-M Core */
+
+/** __FPU_USED indicates whether an FPU is used or not.
+ This core does not support an FPU at all
+*/
+#define __FPU_USED 0U
+
+#if defined ( __CC_ARM )
+ #if defined __TARGET_FPU_VFP
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #endif
+
+#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
+ #if defined __ARM_FP
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #endif
+
+#elif defined ( __GNUC__ )
+ #if defined (__VFP_FP__) && !defined(__SOFTFP__)
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #endif
+
+#elif defined ( __ICCARM__ )
+ #if defined __ARMVFP__
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #endif
+
+#elif defined ( __TI_ARM__ )
+ #if defined __TI_VFP_SUPPORT__
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #endif
+
+#elif defined ( __TASKING__ )
+ #if defined __FPU_VFP__
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #endif
+
+#elif defined ( __CSMC__ )
+ #if ( __CSMC__ & 0x400U)
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #endif
+
+#endif
+
+#include "cmsis_compiler.h" /* CMSIS compiler specific defines */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CORE_CM23_H_GENERIC */
+
+#ifndef __CMSIS_GENERIC
+
+#ifndef __CORE_CM23_H_DEPENDANT
+#define __CORE_CM23_H_DEPENDANT
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/* check device defines and use defaults */
+#if defined __CHECK_DEVICE_DEFINES
+ #ifndef __CM23_REV
+ #define __CM23_REV 0x0000U
+ #warning "__CM23_REV not defined in device header file; using default!"
+ #endif
+
+ #ifndef __FPU_PRESENT
+ #define __FPU_PRESENT 0U
+ #warning "__FPU_PRESENT not defined in device header file; using default!"
+ #endif
+
+ #ifndef __MPU_PRESENT
+ #define __MPU_PRESENT 0U
+ #warning "__MPU_PRESENT not defined in device header file; using default!"
+ #endif
+
+ #ifndef __SAUREGION_PRESENT
+ #define __SAUREGION_PRESENT 0U
+ #warning "__SAUREGION_PRESENT not defined in device header file; using default!"
+ #endif
+
+ #ifndef __VTOR_PRESENT
+ #define __VTOR_PRESENT 0U
+ #warning "__VTOR_PRESENT not defined in device header file; using default!"
+ #endif
+
+ #ifndef __NVIC_PRIO_BITS
+ #define __NVIC_PRIO_BITS 2U
+ #warning "__NVIC_PRIO_BITS not defined in device header file; using default!"
+ #endif
+
+ #ifndef __Vendor_SysTickConfig
+ #define __Vendor_SysTickConfig 0U
+ #warning "__Vendor_SysTickConfig not defined in device header file; using default!"
+ #endif
+
+ #ifndef __ETM_PRESENT
+ #define __ETM_PRESENT 0U
+ #warning "__ETM_PRESENT not defined in device header file; using default!"
+ #endif
+
+ #ifndef __MTB_PRESENT
+ #define __MTB_PRESENT 0U
+ #warning "__MTB_PRESENT not defined in device header file; using default!"
+ #endif
+
+#endif
+
+/* IO definitions (access restrictions to peripheral registers) */
+/**
+ \defgroup CMSIS_glob_defs CMSIS Global Defines
+
+ IO Type Qualifiers are used
+ \li to specify the access to peripheral variables.
+ \li for automatic generation of peripheral register debug information.
+*/
+#ifdef __cplusplus
+ #define __I volatile /*!< Defines 'read only' permissions */
+#else
+ #define __I volatile const /*!< Defines 'read only' permissions */
+#endif
+#define __O volatile /*!< Defines 'write only' permissions */
+#define __IO volatile /*!< Defines 'read / write' permissions */
+
+/* following defines should be used for structure members */
+#define __IM volatile const /*! Defines 'read only' structure member permissions */
+#define __OM volatile /*! Defines 'write only' structure member permissions */
+#define __IOM volatile /*! Defines 'read / write' structure member permissions */
+
+/*@} end of group Cortex_M23 */
+
+
+
+/*******************************************************************************
+ * Register Abstraction
+ Core Register contain:
+ - Core Register
+ - Core NVIC Register
+ - Core SCB Register
+ - Core SysTick Register
+ - Core Debug Register
+ - Core MPU Register
+ - Core SAU Register
+ ******************************************************************************/
+/**
+ \defgroup CMSIS_core_register Defines and Type Definitions
+ \brief Type definitions and defines for Cortex-M processor based devices.
+*/
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_CORE Status and Control Registers
+ \brief Core Register type definitions.
+ @{
+ */
+
+/**
+ \brief Union type to access the Application Program Status Register (APSR).
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t _reserved0:28; /*!< bit: 0..27 Reserved */
+ uint32_t V:1; /*!< bit: 28 Overflow condition code flag */
+ uint32_t C:1; /*!< bit: 29 Carry condition code flag */
+ uint32_t Z:1; /*!< bit: 30 Zero condition code flag */
+ uint32_t N:1; /*!< bit: 31 Negative condition code flag */
+ } b; /*!< Structure used for bit access */
+ uint32_t w; /*!< Type used for word access */
+} APSR_Type;
+
+/* APSR Register Definitions */
+#define APSR_N_Pos 31U /*!< APSR: N Position */
+#define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */
+
+#define APSR_Z_Pos 30U /*!< APSR: Z Position */
+#define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */
+
+#define APSR_C_Pos 29U /*!< APSR: C Position */
+#define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */
+
+#define APSR_V_Pos 28U /*!< APSR: V Position */
+#define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */
+
+
+/**
+ \brief Union type to access the Interrupt Program Status Register (IPSR).
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */
+ uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */
+ } b; /*!< Structure used for bit access */
+ uint32_t w; /*!< Type used for word access */
+} IPSR_Type;
+
+/* IPSR Register Definitions */
+#define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */
+#define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */
+
+
+/**
+ \brief Union type to access the Special-Purpose Program Status Registers (xPSR).
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */
+ uint32_t _reserved0:15; /*!< bit: 9..23 Reserved */
+ uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */
+ uint32_t _reserved1:3; /*!< bit: 25..27 Reserved */
+ uint32_t V:1; /*!< bit: 28 Overflow condition code flag */
+ uint32_t C:1; /*!< bit: 29 Carry condition code flag */
+ uint32_t Z:1; /*!< bit: 30 Zero condition code flag */
+ uint32_t N:1; /*!< bit: 31 Negative condition code flag */
+ } b; /*!< Structure used for bit access */
+ uint32_t w; /*!< Type used for word access */
+} xPSR_Type;
+
+/* xPSR Register Definitions */
+#define xPSR_N_Pos 31U /*!< xPSR: N Position */
+#define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */
+
+#define xPSR_Z_Pos 30U /*!< xPSR: Z Position */
+#define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */
+
+#define xPSR_C_Pos 29U /*!< xPSR: C Position */
+#define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */
+
+#define xPSR_V_Pos 28U /*!< xPSR: V Position */
+#define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */
+
+#define xPSR_T_Pos 24U /*!< xPSR: T Position */
+#define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */
+
+#define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */
+#define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */
+
+
+/**
+ \brief Union type to access the Control Registers (CONTROL).
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */
+ uint32_t SPSEL:1; /*!< bit: 1 Stack-pointer select */
+ uint32_t _reserved1:30; /*!< bit: 2..31 Reserved */
+ } b; /*!< Structure used for bit access */
+ uint32_t w; /*!< Type used for word access */
+} CONTROL_Type;
+
+/* CONTROL Register Definitions */
+#define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */
+#define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */
+
+#define CONTROL_nPRIV_Pos 0U /*!< CONTROL: nPRIV Position */
+#define CONTROL_nPRIV_Msk (1UL /*<< CONTROL_nPRIV_Pos*/) /*!< CONTROL: nPRIV Mask */
+
+/*@} end of group CMSIS_CORE */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC)
+ \brief Type definitions for the NVIC Registers
+ @{
+ */
+
+/**
+ \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC).
+ */
+typedef struct
+{
+ __IOM uint32_t ISER[16U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */
+ uint32_t RESERVED0[16U];
+ __IOM uint32_t ICER[16U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */
+ uint32_t RSERVED1[16U];
+ __IOM uint32_t ISPR[16U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */
+ uint32_t RESERVED2[16U];
+ __IOM uint32_t ICPR[16U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */
+ uint32_t RESERVED3[16U];
+ __IOM uint32_t IABR[16U]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */
+ uint32_t RESERVED4[16U];
+ __IOM uint32_t ITNS[16U]; /*!< Offset: 0x280 (R/W) Interrupt Non-Secure State Register */
+ uint32_t RESERVED5[16U];
+ __IOM uint32_t IPR[124U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register */
+} NVIC_Type;
+
+/*@} end of group CMSIS_NVIC */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_SCB System Control Block (SCB)
+ \brief Type definitions for the System Control Block Registers
+ @{
+ */
+
+/**
+ \brief Structure type to access the System Control Block (SCB).
+ */
+typedef struct
+{
+ __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */
+ __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */
+#if defined (__VTOR_PRESENT) && (__VTOR_PRESENT == 1U)
+ __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */
+#else
+ uint32_t RESERVED0;
+#endif
+ __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */
+ __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */
+ __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */
+ uint32_t RESERVED1;
+ __IOM uint32_t SHPR[2U]; /*!< Offset: 0x01C (R/W) System Handlers Priority Registers. [0] is RESERVED */
+ __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */
+} SCB_Type;
+
+/* SCB CPUID Register Definitions */
+#define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */
+#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */
+
+#define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */
+#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */
+
+#define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */
+#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */
+
+#define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */
+#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */
+
+#define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */
+#define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */
+
+/* SCB Interrupt Control State Register Definitions */
+#define SCB_ICSR_PENDNMISET_Pos 31U /*!< SCB ICSR: PENDNMISET Position */
+#define SCB_ICSR_PENDNMISET_Msk (1UL << SCB_ICSR_PENDNMISET_Pos) /*!< SCB ICSR: PENDNMISET Mask */
+
+#define SCB_ICSR_NMIPENDSET_Pos SCB_ICSR_PENDNMISET_Pos /*!< SCB ICSR: NMIPENDSET Position, backward compatibility */
+#define SCB_ICSR_NMIPENDSET_Msk SCB_ICSR_PENDNMISET_Msk /*!< SCB ICSR: NMIPENDSET Mask, backward compatibility */
+
+#define SCB_ICSR_PENDNMICLR_Pos 30U /*!< SCB ICSR: PENDNMICLR Position */
+#define SCB_ICSR_PENDNMICLR_Msk (1UL << SCB_ICSR_PENDNMICLR_Pos) /*!< SCB ICSR: PENDNMICLR Mask */
+
+#define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */
+#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */
+
+#define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */
+#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */
+
+#define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */
+#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */
+
+#define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */
+#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */
+
+#define SCB_ICSR_STTNS_Pos 24U /*!< SCB ICSR: STTNS Position (Security Extension) */
+#define SCB_ICSR_STTNS_Msk (1UL << SCB_ICSR_STTNS_Pos) /*!< SCB ICSR: STTNS Mask (Security Extension) */
+
+#define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */
+#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */
+
+#define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */
+#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */
+
+#define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */
+#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */
+
+#define SCB_ICSR_RETTOBASE_Pos 11U /*!< SCB ICSR: RETTOBASE Position */
+#define SCB_ICSR_RETTOBASE_Msk (1UL << SCB_ICSR_RETTOBASE_Pos) /*!< SCB ICSR: RETTOBASE Mask */
+
+#define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */
+#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */
+
+#if defined (__VTOR_PRESENT) && (__VTOR_PRESENT == 1U)
+/* SCB Vector Table Offset Register Definitions */
+#define SCB_VTOR_TBLOFF_Pos 7U /*!< SCB VTOR: TBLOFF Position */
+#define SCB_VTOR_TBLOFF_Msk (0x1FFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */
+#endif
+
+/* SCB Application Interrupt and Reset Control Register Definitions */
+#define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */
+#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */
+
+#define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */
+#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */
+
+#define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */
+#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */
+
+#define SCB_AIRCR_PRIS_Pos 14U /*!< SCB AIRCR: PRIS Position */
+#define SCB_AIRCR_PRIS_Msk (1UL << SCB_AIRCR_PRIS_Pos) /*!< SCB AIRCR: PRIS Mask */
+
+#define SCB_AIRCR_BFHFNMINS_Pos 13U /*!< SCB AIRCR: BFHFNMINS Position */
+#define SCB_AIRCR_BFHFNMINS_Msk (1UL << SCB_AIRCR_BFHFNMINS_Pos) /*!< SCB AIRCR: BFHFNMINS Mask */
+
+#define SCB_AIRCR_SYSRESETREQS_Pos 3U /*!< SCB AIRCR: SYSRESETREQS Position */
+#define SCB_AIRCR_SYSRESETREQS_Msk (1UL << SCB_AIRCR_SYSRESETREQS_Pos) /*!< SCB AIRCR: SYSRESETREQS Mask */
+
+#define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */
+#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */
+
+#define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */
+#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */
+
+/* SCB System Control Register Definitions */
+#define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */
+#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */
+
+#define SCB_SCR_SLEEPDEEPS_Pos 3U /*!< SCB SCR: SLEEPDEEPS Position */
+#define SCB_SCR_SLEEPDEEPS_Msk (1UL << SCB_SCR_SLEEPDEEPS_Pos) /*!< SCB SCR: SLEEPDEEPS Mask */
+
+#define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */
+#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */
+
+#define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */
+#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */
+
+/* SCB Configuration Control Register Definitions */
+#define SCB_CCR_BP_Pos 18U /*!< SCB CCR: BP Position */
+#define SCB_CCR_BP_Msk (1UL << SCB_CCR_BP_Pos) /*!< SCB CCR: BP Mask */
+
+#define SCB_CCR_IC_Pos 17U /*!< SCB CCR: IC Position */
+#define SCB_CCR_IC_Msk (1UL << SCB_CCR_IC_Pos) /*!< SCB CCR: IC Mask */
+
+#define SCB_CCR_DC_Pos 16U /*!< SCB CCR: DC Position */
+#define SCB_CCR_DC_Msk (1UL << SCB_CCR_DC_Pos) /*!< SCB CCR: DC Mask */
+
+#define SCB_CCR_STKOFHFNMIGN_Pos 10U /*!< SCB CCR: STKOFHFNMIGN Position */
+#define SCB_CCR_STKOFHFNMIGN_Msk (1UL << SCB_CCR_STKOFHFNMIGN_Pos) /*!< SCB CCR: STKOFHFNMIGN Mask */
+
+#define SCB_CCR_BFHFNMIGN_Pos 8U /*!< SCB CCR: BFHFNMIGN Position */
+#define SCB_CCR_BFHFNMIGN_Msk (1UL << SCB_CCR_BFHFNMIGN_Pos) /*!< SCB CCR: BFHFNMIGN Mask */
+
+#define SCB_CCR_DIV_0_TRP_Pos 4U /*!< SCB CCR: DIV_0_TRP Position */
+#define SCB_CCR_DIV_0_TRP_Msk (1UL << SCB_CCR_DIV_0_TRP_Pos) /*!< SCB CCR: DIV_0_TRP Mask */
+
+#define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */
+#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */
+
+#define SCB_CCR_USERSETMPEND_Pos 1U /*!< SCB CCR: USERSETMPEND Position */
+#define SCB_CCR_USERSETMPEND_Msk (1UL << SCB_CCR_USERSETMPEND_Pos) /*!< SCB CCR: USERSETMPEND Mask */
+
+/* SCB System Handler Control and State Register Definitions */
+#define SCB_SHCSR_HARDFAULTPENDED_Pos 21U /*!< SCB SHCSR: HARDFAULTPENDED Position */
+#define SCB_SHCSR_HARDFAULTPENDED_Msk (1UL << SCB_SHCSR_HARDFAULTPENDED_Pos) /*!< SCB SHCSR: HARDFAULTPENDED Mask */
+
+#define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */
+#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */
+
+#define SCB_SHCSR_SYSTICKACT_Pos 11U /*!< SCB SHCSR: SYSTICKACT Position */
+#define SCB_SHCSR_SYSTICKACT_Msk (1UL << SCB_SHCSR_SYSTICKACT_Pos) /*!< SCB SHCSR: SYSTICKACT Mask */
+
+#define SCB_SHCSR_PENDSVACT_Pos 10U /*!< SCB SHCSR: PENDSVACT Position */
+#define SCB_SHCSR_PENDSVACT_Msk (1UL << SCB_SHCSR_PENDSVACT_Pos) /*!< SCB SHCSR: PENDSVACT Mask */
+
+#define SCB_SHCSR_SVCALLACT_Pos 7U /*!< SCB SHCSR: SVCALLACT Position */
+#define SCB_SHCSR_SVCALLACT_Msk (1UL << SCB_SHCSR_SVCALLACT_Pos) /*!< SCB SHCSR: SVCALLACT Mask */
+
+#define SCB_SHCSR_NMIACT_Pos 5U /*!< SCB SHCSR: NMIACT Position */
+#define SCB_SHCSR_NMIACT_Msk (1UL << SCB_SHCSR_NMIACT_Pos) /*!< SCB SHCSR: NMIACT Mask */
+
+#define SCB_SHCSR_HARDFAULTACT_Pos 2U /*!< SCB SHCSR: HARDFAULTACT Position */
+#define SCB_SHCSR_HARDFAULTACT_Msk (1UL << SCB_SHCSR_HARDFAULTACT_Pos) /*!< SCB SHCSR: HARDFAULTACT Mask */
+
+/*@} end of group CMSIS_SCB */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_SysTick System Tick Timer (SysTick)
+ \brief Type definitions for the System Timer Registers.
+ @{
+ */
+
+/**
+ \brief Structure type to access the System Timer (SysTick).
+ */
+typedef struct
+{
+ __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */
+ __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */
+ __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */
+ __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */
+} SysTick_Type;
+
+/* SysTick Control / Status Register Definitions */
+#define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */
+#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */
+
+#define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */
+#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */
+
+#define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */
+#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */
+
+#define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */
+#define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */
+
+/* SysTick Reload Register Definitions */
+#define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */
+#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */
+
+/* SysTick Current Register Definitions */
+#define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */
+#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */
+
+/* SysTick Calibration Register Definitions */
+#define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */
+#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */
+
+#define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */
+#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */
+
+#define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */
+#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */
+
+/*@} end of group CMSIS_SysTick */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_DWT Data Watchpoint and Trace (DWT)
+ \brief Type definitions for the Data Watchpoint and Trace (DWT)
+ @{
+ */
+
+/**
+ \brief Structure type to access the Data Watchpoint and Trace Register (DWT).
+ */
+typedef struct
+{
+ __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) Control Register */
+ uint32_t RESERVED0[6U];
+ __IM uint32_t PCSR; /*!< Offset: 0x01C (R/ ) Program Counter Sample Register */
+ __IOM uint32_t COMP0; /*!< Offset: 0x020 (R/W) Comparator Register 0 */
+ uint32_t RESERVED1[1U];
+ __IOM uint32_t FUNCTION0; /*!< Offset: 0x028 (R/W) Function Register 0 */
+ uint32_t RESERVED2[1U];
+ __IOM uint32_t COMP1; /*!< Offset: 0x030 (R/W) Comparator Register 1 */
+ uint32_t RESERVED3[1U];
+ __IOM uint32_t FUNCTION1; /*!< Offset: 0x038 (R/W) Function Register 1 */
+ uint32_t RESERVED4[1U];
+ __IOM uint32_t COMP2; /*!< Offset: 0x040 (R/W) Comparator Register 2 */
+ uint32_t RESERVED5[1U];
+ __IOM uint32_t FUNCTION2; /*!< Offset: 0x048 (R/W) Function Register 2 */
+ uint32_t RESERVED6[1U];
+ __IOM uint32_t COMP3; /*!< Offset: 0x050 (R/W) Comparator Register 3 */
+ uint32_t RESERVED7[1U];
+ __IOM uint32_t FUNCTION3; /*!< Offset: 0x058 (R/W) Function Register 3 */
+ uint32_t RESERVED8[1U];
+ __IOM uint32_t COMP4; /*!< Offset: 0x060 (R/W) Comparator Register 4 */
+ uint32_t RESERVED9[1U];
+ __IOM uint32_t FUNCTION4; /*!< Offset: 0x068 (R/W) Function Register 4 */
+ uint32_t RESERVED10[1U];
+ __IOM uint32_t COMP5; /*!< Offset: 0x070 (R/W) Comparator Register 5 */
+ uint32_t RESERVED11[1U];
+ __IOM uint32_t FUNCTION5; /*!< Offset: 0x078 (R/W) Function Register 5 */
+ uint32_t RESERVED12[1U];
+ __IOM uint32_t COMP6; /*!< Offset: 0x080 (R/W) Comparator Register 6 */
+ uint32_t RESERVED13[1U];
+ __IOM uint32_t FUNCTION6; /*!< Offset: 0x088 (R/W) Function Register 6 */
+ uint32_t RESERVED14[1U];
+ __IOM uint32_t COMP7; /*!< Offset: 0x090 (R/W) Comparator Register 7 */
+ uint32_t RESERVED15[1U];
+ __IOM uint32_t FUNCTION7; /*!< Offset: 0x098 (R/W) Function Register 7 */
+ uint32_t RESERVED16[1U];
+ __IOM uint32_t COMP8; /*!< Offset: 0x0A0 (R/W) Comparator Register 8 */
+ uint32_t RESERVED17[1U];
+ __IOM uint32_t FUNCTION8; /*!< Offset: 0x0A8 (R/W) Function Register 8 */
+ uint32_t RESERVED18[1U];
+ __IOM uint32_t COMP9; /*!< Offset: 0x0B0 (R/W) Comparator Register 9 */
+ uint32_t RESERVED19[1U];
+ __IOM uint32_t FUNCTION9; /*!< Offset: 0x0B8 (R/W) Function Register 9 */
+ uint32_t RESERVED20[1U];
+ __IOM uint32_t COMP10; /*!< Offset: 0x0C0 (R/W) Comparator Register 10 */
+ uint32_t RESERVED21[1U];
+ __IOM uint32_t FUNCTION10; /*!< Offset: 0x0C8 (R/W) Function Register 10 */
+ uint32_t RESERVED22[1U];
+ __IOM uint32_t COMP11; /*!< Offset: 0x0D0 (R/W) Comparator Register 11 */
+ uint32_t RESERVED23[1U];
+ __IOM uint32_t FUNCTION11; /*!< Offset: 0x0D8 (R/W) Function Register 11 */
+ uint32_t RESERVED24[1U];
+ __IOM uint32_t COMP12; /*!< Offset: 0x0E0 (R/W) Comparator Register 12 */
+ uint32_t RESERVED25[1U];
+ __IOM uint32_t FUNCTION12; /*!< Offset: 0x0E8 (R/W) Function Register 12 */
+ uint32_t RESERVED26[1U];
+ __IOM uint32_t COMP13; /*!< Offset: 0x0F0 (R/W) Comparator Register 13 */
+ uint32_t RESERVED27[1U];
+ __IOM uint32_t FUNCTION13; /*!< Offset: 0x0F8 (R/W) Function Register 13 */
+ uint32_t RESERVED28[1U];
+ __IOM uint32_t COMP14; /*!< Offset: 0x100 (R/W) Comparator Register 14 */
+ uint32_t RESERVED29[1U];
+ __IOM uint32_t FUNCTION14; /*!< Offset: 0x108 (R/W) Function Register 14 */
+ uint32_t RESERVED30[1U];
+ __IOM uint32_t COMP15; /*!< Offset: 0x110 (R/W) Comparator Register 15 */
+ uint32_t RESERVED31[1U];
+ __IOM uint32_t FUNCTION15; /*!< Offset: 0x118 (R/W) Function Register 15 */
+} DWT_Type;
+
+/* DWT Control Register Definitions */
+#define DWT_CTRL_NUMCOMP_Pos 28U /*!< DWT CTRL: NUMCOMP Position */
+#define DWT_CTRL_NUMCOMP_Msk (0xFUL << DWT_CTRL_NUMCOMP_Pos) /*!< DWT CTRL: NUMCOMP Mask */
+
+#define DWT_CTRL_NOTRCPKT_Pos 27U /*!< DWT CTRL: NOTRCPKT Position */
+#define DWT_CTRL_NOTRCPKT_Msk (0x1UL << DWT_CTRL_NOTRCPKT_Pos) /*!< DWT CTRL: NOTRCPKT Mask */
+
+#define DWT_CTRL_NOEXTTRIG_Pos 26U /*!< DWT CTRL: NOEXTTRIG Position */
+#define DWT_CTRL_NOEXTTRIG_Msk (0x1UL << DWT_CTRL_NOEXTTRIG_Pos) /*!< DWT CTRL: NOEXTTRIG Mask */
+
+#define DWT_CTRL_NOCYCCNT_Pos 25U /*!< DWT CTRL: NOCYCCNT Position */
+#define DWT_CTRL_NOCYCCNT_Msk (0x1UL << DWT_CTRL_NOCYCCNT_Pos) /*!< DWT CTRL: NOCYCCNT Mask */
+
+#define DWT_CTRL_NOPRFCNT_Pos 24U /*!< DWT CTRL: NOPRFCNT Position */
+#define DWT_CTRL_NOPRFCNT_Msk (0x1UL << DWT_CTRL_NOPRFCNT_Pos) /*!< DWT CTRL: NOPRFCNT Mask */
+
+/* DWT Comparator Function Register Definitions */
+#define DWT_FUNCTION_ID_Pos 27U /*!< DWT FUNCTION: ID Position */
+#define DWT_FUNCTION_ID_Msk (0x1FUL << DWT_FUNCTION_ID_Pos) /*!< DWT FUNCTION: ID Mask */
+
+#define DWT_FUNCTION_MATCHED_Pos 24U /*!< DWT FUNCTION: MATCHED Position */
+#define DWT_FUNCTION_MATCHED_Msk (0x1UL << DWT_FUNCTION_MATCHED_Pos) /*!< DWT FUNCTION: MATCHED Mask */
+
+#define DWT_FUNCTION_DATAVSIZE_Pos 10U /*!< DWT FUNCTION: DATAVSIZE Position */
+#define DWT_FUNCTION_DATAVSIZE_Msk (0x3UL << DWT_FUNCTION_DATAVSIZE_Pos) /*!< DWT FUNCTION: DATAVSIZE Mask */
+
+#define DWT_FUNCTION_ACTION_Pos 4U /*!< DWT FUNCTION: ACTION Position */
+#define DWT_FUNCTION_ACTION_Msk (0x3UL << DWT_FUNCTION_ACTION_Pos) /*!< DWT FUNCTION: ACTION Mask */
+
+#define DWT_FUNCTION_MATCH_Pos 0U /*!< DWT FUNCTION: MATCH Position */
+#define DWT_FUNCTION_MATCH_Msk (0xFUL /*<< DWT_FUNCTION_MATCH_Pos*/) /*!< DWT FUNCTION: MATCH Mask */
+
+/*@}*/ /* end of group CMSIS_DWT */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_TPI Trace Port Interface (TPI)
+ \brief Type definitions for the Trace Port Interface (TPI)
+ @{
+ */
+
+/**
+ \brief Structure type to access the Trace Port Interface Register (TPI).
+ */
+typedef struct
+{
+ __IM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Size Register */
+ __IOM uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Size Register */
+ uint32_t RESERVED0[2U];
+ __IOM uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */
+ uint32_t RESERVED1[55U];
+ __IOM uint32_t SPPR; /*!< Offset: 0x0F0 (R/W) Selected Pin Protocol Register */
+ uint32_t RESERVED2[131U];
+ __IM uint32_t FFSR; /*!< Offset: 0x300 (R/ ) Formatter and Flush Status Register */
+ __IOM uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */
+ __IOM uint32_t PSCR; /*!< Offset: 0x308 (R/W) Periodic Synchronization Control Register */
+ uint32_t RESERVED3[759U];
+ __IM uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER Register */
+ __IM uint32_t ITFTTD0; /*!< Offset: 0xEEC (R/ ) Integration Test FIFO Test Data 0 Register */
+ __IOM uint32_t ITATBCTR2; /*!< Offset: 0xEF0 (R/W) Integration Test ATB Control Register 2 */
+ uint32_t RESERVED4[1U];
+ __IM uint32_t ITATBCTR0; /*!< Offset: 0xEF8 (R/ ) Integration Test ATB Control Register 0 */
+ __IM uint32_t ITFTTD1; /*!< Offset: 0xEFC (R/ ) Integration Test FIFO Test Data 1 Register */
+ __IOM uint32_t ITCTRL; /*!< Offset: 0xF00 (R/W) Integration Mode Control */
+ uint32_t RESERVED5[39U];
+ __IOM uint32_t CLAIMSET; /*!< Offset: 0xFA0 (R/W) Claim tag set */
+ __IOM uint32_t CLAIMCLR; /*!< Offset: 0xFA4 (R/W) Claim tag clear */
+ uint32_t RESERVED7[8U];
+ __IM uint32_t DEVID; /*!< Offset: 0xFC8 (R/ ) Device Configuration Register */
+ __IM uint32_t DEVTYPE; /*!< Offset: 0xFCC (R/ ) Device Type Identifier Register */
+} TPI_Type;
+
+/* TPI Asynchronous Clock Prescaler Register Definitions */
+#define TPI_ACPR_PRESCALER_Pos 0U /*!< TPI ACPR: PRESCALER Position */
+#define TPI_ACPR_PRESCALER_Msk (0x1FFFUL /*<< TPI_ACPR_PRESCALER_Pos*/) /*!< TPI ACPR: PRESCALER Mask */
+
+/* TPI Selected Pin Protocol Register Definitions */
+#define TPI_SPPR_TXMODE_Pos 0U /*!< TPI SPPR: TXMODE Position */
+#define TPI_SPPR_TXMODE_Msk (0x3UL /*<< TPI_SPPR_TXMODE_Pos*/) /*!< TPI SPPR: TXMODE Mask */
+
+/* TPI Formatter and Flush Status Register Definitions */
+#define TPI_FFSR_FtNonStop_Pos 3U /*!< TPI FFSR: FtNonStop Position */
+#define TPI_FFSR_FtNonStop_Msk (0x1UL << TPI_FFSR_FtNonStop_Pos) /*!< TPI FFSR: FtNonStop Mask */
+
+#define TPI_FFSR_TCPresent_Pos 2U /*!< TPI FFSR: TCPresent Position */
+#define TPI_FFSR_TCPresent_Msk (0x1UL << TPI_FFSR_TCPresent_Pos) /*!< TPI FFSR: TCPresent Mask */
+
+#define TPI_FFSR_FtStopped_Pos 1U /*!< TPI FFSR: FtStopped Position */
+#define TPI_FFSR_FtStopped_Msk (0x1UL << TPI_FFSR_FtStopped_Pos) /*!< TPI FFSR: FtStopped Mask */
+
+#define TPI_FFSR_FlInProg_Pos 0U /*!< TPI FFSR: FlInProg Position */
+#define TPI_FFSR_FlInProg_Msk (0x1UL /*<< TPI_FFSR_FlInProg_Pos*/) /*!< TPI FFSR: FlInProg Mask */
+
+/* TPI Formatter and Flush Control Register Definitions */
+#define TPI_FFCR_TrigIn_Pos 8U /*!< TPI FFCR: TrigIn Position */
+#define TPI_FFCR_TrigIn_Msk (0x1UL << TPI_FFCR_TrigIn_Pos) /*!< TPI FFCR: TrigIn Mask */
+
+#define TPI_FFCR_FOnMan_Pos 6U /*!< TPI FFCR: FOnMan Position */
+#define TPI_FFCR_FOnMan_Msk (0x1UL << TPI_FFCR_FOnMan_Pos) /*!< TPI FFCR: FOnMan Mask */
+
+#define TPI_FFCR_EnFCont_Pos 1U /*!< TPI FFCR: EnFCont Position */
+#define TPI_FFCR_EnFCont_Msk (0x1UL << TPI_FFCR_EnFCont_Pos) /*!< TPI FFCR: EnFCont Mask */
+
+/* TPI TRIGGER Register Definitions */
+#define TPI_TRIGGER_TRIGGER_Pos 0U /*!< TPI TRIGGER: TRIGGER Position */
+#define TPI_TRIGGER_TRIGGER_Msk (0x1UL /*<< TPI_TRIGGER_TRIGGER_Pos*/) /*!< TPI TRIGGER: TRIGGER Mask */
+
+/* TPI Integration Test FIFO Test Data 0 Register Definitions */
+#define TPI_ITFTTD0_ATB_IF2_ATVALID_Pos 29U /*!< TPI ITFTTD0: ATB Interface 2 ATVALIDPosition */
+#define TPI_ITFTTD0_ATB_IF2_ATVALID_Msk (0x3UL << TPI_ITFTTD0_ATB_IF2_ATVALID_Pos) /*!< TPI ITFTTD0: ATB Interface 2 ATVALID Mask */
+
+#define TPI_ITFTTD0_ATB_IF2_bytecount_Pos 27U /*!< TPI ITFTTD0: ATB Interface 2 byte count Position */
+#define TPI_ITFTTD0_ATB_IF2_bytecount_Msk (0x3UL << TPI_ITFTTD0_ATB_IF2_bytecount_Pos) /*!< TPI ITFTTD0: ATB Interface 2 byte count Mask */
+
+#define TPI_ITFTTD0_ATB_IF1_ATVALID_Pos 26U /*!< TPI ITFTTD0: ATB Interface 1 ATVALID Position */
+#define TPI_ITFTTD0_ATB_IF1_ATVALID_Msk (0x3UL << TPI_ITFTTD0_ATB_IF1_ATVALID_Pos) /*!< TPI ITFTTD0: ATB Interface 1 ATVALID Mask */
+
+#define TPI_ITFTTD0_ATB_IF1_bytecount_Pos 24U /*!< TPI ITFTTD0: ATB Interface 1 byte count Position */
+#define TPI_ITFTTD0_ATB_IF1_bytecount_Msk (0x3UL << TPI_ITFTTD0_ATB_IF1_bytecount_Pos) /*!< TPI ITFTTD0: ATB Interface 1 byte countt Mask */
+
+#define TPI_ITFTTD0_ATB_IF1_data2_Pos 16U /*!< TPI ITFTTD0: ATB Interface 1 data2 Position */
+#define TPI_ITFTTD0_ATB_IF1_data2_Msk (0xFFUL << TPI_ITFTTD0_ATB_IF1_data1_Pos) /*!< TPI ITFTTD0: ATB Interface 1 data2 Mask */
+
+#define TPI_ITFTTD0_ATB_IF1_data1_Pos 8U /*!< TPI ITFTTD0: ATB Interface 1 data1 Position */
+#define TPI_ITFTTD0_ATB_IF1_data1_Msk (0xFFUL << TPI_ITFTTD0_ATB_IF1_data1_Pos) /*!< TPI ITFTTD0: ATB Interface 1 data1 Mask */
+
+#define TPI_ITFTTD0_ATB_IF1_data0_Pos 0U /*!< TPI ITFTTD0: ATB Interface 1 data0 Position */
+#define TPI_ITFTTD0_ATB_IF1_data0_Msk (0xFFUL /*<< TPI_ITFTTD0_ATB_IF1_data0_Pos*/) /*!< TPI ITFTTD0: ATB Interface 1 data0 Mask */
+
+/* TPI Integration Test ATB Control Register 2 Register Definitions */
+#define TPI_ITATBCTR2_AFVALID2S_Pos 1U /*!< TPI ITATBCTR2: AFVALID2S Position */
+#define TPI_ITATBCTR2_AFVALID2S_Msk (0x1UL << TPI_ITATBCTR2_AFVALID2S_Pos) /*!< TPI ITATBCTR2: AFVALID2SS Mask */
+
+#define TPI_ITATBCTR2_AFVALID1S_Pos 1U /*!< TPI ITATBCTR2: AFVALID1S Position */
+#define TPI_ITATBCTR2_AFVALID1S_Msk (0x1UL << TPI_ITATBCTR2_AFVALID1S_Pos) /*!< TPI ITATBCTR2: AFVALID1SS Mask */
+
+#define TPI_ITATBCTR2_ATREADY2S_Pos 0U /*!< TPI ITATBCTR2: ATREADY2S Position */
+#define TPI_ITATBCTR2_ATREADY2S_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY2S_Pos*/) /*!< TPI ITATBCTR2: ATREADY2S Mask */
+
+#define TPI_ITATBCTR2_ATREADY1S_Pos 0U /*!< TPI ITATBCTR2: ATREADY1S Position */
+#define TPI_ITATBCTR2_ATREADY1S_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY1S_Pos*/) /*!< TPI ITATBCTR2: ATREADY1S Mask */
+
+/* TPI Integration Test FIFO Test Data 1 Register Definitions */
+#define TPI_ITFTTD1_ATB_IF2_ATVALID_Pos 29U /*!< TPI ITFTTD1: ATB Interface 2 ATVALID Position */
+#define TPI_ITFTTD1_ATB_IF2_ATVALID_Msk (0x3UL << TPI_ITFTTD1_ATB_IF2_ATVALID_Pos) /*!< TPI ITFTTD1: ATB Interface 2 ATVALID Mask */
+
+#define TPI_ITFTTD1_ATB_IF2_bytecount_Pos 27U /*!< TPI ITFTTD1: ATB Interface 2 byte count Position */
+#define TPI_ITFTTD1_ATB_IF2_bytecount_Msk (0x3UL << TPI_ITFTTD1_ATB_IF2_bytecount_Pos) /*!< TPI ITFTTD1: ATB Interface 2 byte count Mask */
+
+#define TPI_ITFTTD1_ATB_IF1_ATVALID_Pos 26U /*!< TPI ITFTTD1: ATB Interface 1 ATVALID Position */
+#define TPI_ITFTTD1_ATB_IF1_ATVALID_Msk (0x3UL << TPI_ITFTTD1_ATB_IF1_ATVALID_Pos) /*!< TPI ITFTTD1: ATB Interface 1 ATVALID Mask */
+
+#define TPI_ITFTTD1_ATB_IF1_bytecount_Pos 24U /*!< TPI ITFTTD1: ATB Interface 1 byte count Position */
+#define TPI_ITFTTD1_ATB_IF1_bytecount_Msk (0x3UL << TPI_ITFTTD1_ATB_IF1_bytecount_Pos) /*!< TPI ITFTTD1: ATB Interface 1 byte countt Mask */
+
+#define TPI_ITFTTD1_ATB_IF2_data2_Pos 16U /*!< TPI ITFTTD1: ATB Interface 2 data2 Position */
+#define TPI_ITFTTD1_ATB_IF2_data2_Msk (0xFFUL << TPI_ITFTTD1_ATB_IF2_data1_Pos) /*!< TPI ITFTTD1: ATB Interface 2 data2 Mask */
+
+#define TPI_ITFTTD1_ATB_IF2_data1_Pos 8U /*!< TPI ITFTTD1: ATB Interface 2 data1 Position */
+#define TPI_ITFTTD1_ATB_IF2_data1_Msk (0xFFUL << TPI_ITFTTD1_ATB_IF2_data1_Pos) /*!< TPI ITFTTD1: ATB Interface 2 data1 Mask */
+
+#define TPI_ITFTTD1_ATB_IF2_data0_Pos 0U /*!< TPI ITFTTD1: ATB Interface 2 data0 Position */
+#define TPI_ITFTTD1_ATB_IF2_data0_Msk (0xFFUL /*<< TPI_ITFTTD1_ATB_IF2_data0_Pos*/) /*!< TPI ITFTTD1: ATB Interface 2 data0 Mask */
+
+/* TPI Integration Test ATB Control Register 0 Definitions */
+#define TPI_ITATBCTR0_AFVALID2S_Pos 1U /*!< TPI ITATBCTR0: AFVALID2S Position */
+#define TPI_ITATBCTR0_AFVALID2S_Msk (0x1UL << TPI_ITATBCTR0_AFVALID2S_Pos) /*!< TPI ITATBCTR0: AFVALID2SS Mask */
+
+#define TPI_ITATBCTR0_AFVALID1S_Pos 1U /*!< TPI ITATBCTR0: AFVALID1S Position */
+#define TPI_ITATBCTR0_AFVALID1S_Msk (0x1UL << TPI_ITATBCTR0_AFVALID1S_Pos) /*!< TPI ITATBCTR0: AFVALID1SS Mask */
+
+#define TPI_ITATBCTR0_ATREADY2S_Pos 0U /*!< TPI ITATBCTR0: ATREADY2S Position */
+#define TPI_ITATBCTR0_ATREADY2S_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY2S_Pos*/) /*!< TPI ITATBCTR0: ATREADY2S Mask */
+
+#define TPI_ITATBCTR0_ATREADY1S_Pos 0U /*!< TPI ITATBCTR0: ATREADY1S Position */
+#define TPI_ITATBCTR0_ATREADY1S_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY1S_Pos*/) /*!< TPI ITATBCTR0: ATREADY1S Mask */
+
+/* TPI Integration Mode Control Register Definitions */
+#define TPI_ITCTRL_Mode_Pos 0U /*!< TPI ITCTRL: Mode Position */
+#define TPI_ITCTRL_Mode_Msk (0x3UL /*<< TPI_ITCTRL_Mode_Pos*/) /*!< TPI ITCTRL: Mode Mask */
+
+/* TPI DEVID Register Definitions */
+#define TPI_DEVID_NRZVALID_Pos 11U /*!< TPI DEVID: NRZVALID Position */
+#define TPI_DEVID_NRZVALID_Msk (0x1UL << TPI_DEVID_NRZVALID_Pos) /*!< TPI DEVID: NRZVALID Mask */
+
+#define TPI_DEVID_MANCVALID_Pos 10U /*!< TPI DEVID: MANCVALID Position */
+#define TPI_DEVID_MANCVALID_Msk (0x1UL << TPI_DEVID_MANCVALID_Pos) /*!< TPI DEVID: MANCVALID Mask */
+
+#define TPI_DEVID_PTINVALID_Pos 9U /*!< TPI DEVID: PTINVALID Position */
+#define TPI_DEVID_PTINVALID_Msk (0x1UL << TPI_DEVID_PTINVALID_Pos) /*!< TPI DEVID: PTINVALID Mask */
+
+#define TPI_DEVID_FIFOSZ_Pos 6U /*!< TPI DEVID: FIFOSZ Position */
+#define TPI_DEVID_FIFOSZ_Msk (0x7UL << TPI_DEVID_FIFOSZ_Pos) /*!< TPI DEVID: FIFOSZ Mask */
+
+#define TPI_DEVID_NrTraceInput_Pos 0U /*!< TPI DEVID: NrTraceInput Position */
+#define TPI_DEVID_NrTraceInput_Msk (0x3FUL /*<< TPI_DEVID_NrTraceInput_Pos*/) /*!< TPI DEVID: NrTraceInput Mask */
+
+/* TPI DEVTYPE Register Definitions */
+#define TPI_DEVTYPE_SubType_Pos 4U /*!< TPI DEVTYPE: SubType Position */
+#define TPI_DEVTYPE_SubType_Msk (0xFUL /*<< TPI_DEVTYPE_SubType_Pos*/) /*!< TPI DEVTYPE: SubType Mask */
+
+#define TPI_DEVTYPE_MajorType_Pos 0U /*!< TPI DEVTYPE: MajorType Position */
+#define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */
+
+/*@}*/ /* end of group CMSIS_TPI */
+
+
+#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U)
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_MPU Memory Protection Unit (MPU)
+ \brief Type definitions for the Memory Protection Unit (MPU)
+ @{
+ */
+
+/**
+ \brief Structure type to access the Memory Protection Unit (MPU).
+ */
+typedef struct
+{
+ __IM uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */
+ __IOM uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */
+ __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region Number Register */
+ __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */
+ __IOM uint32_t RLAR; /*!< Offset: 0x010 (R/W) MPU Region Limit Address Register */
+ uint32_t RESERVED0[7U];
+ union {
+ __IOM uint32_t MAIR[2];
+ struct {
+ __IOM uint32_t MAIR0; /*!< Offset: 0x030 (R/W) MPU Memory Attribute Indirection Register 0 */
+ __IOM uint32_t MAIR1; /*!< Offset: 0x034 (R/W) MPU Memory Attribute Indirection Register 1 */
+ };
+ };
+} MPU_Type;
+
+#define MPU_TYPE_RALIASES 1U
+
+/* MPU Type Register Definitions */
+#define MPU_TYPE_IREGION_Pos 16U /*!< MPU TYPE: IREGION Position */
+#define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */
+
+#define MPU_TYPE_DREGION_Pos 8U /*!< MPU TYPE: DREGION Position */
+#define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */
+
+#define MPU_TYPE_SEPARATE_Pos 0U /*!< MPU TYPE: SEPARATE Position */
+#define MPU_TYPE_SEPARATE_Msk (1UL /*<< MPU_TYPE_SEPARATE_Pos*/) /*!< MPU TYPE: SEPARATE Mask */
+
+/* MPU Control Register Definitions */
+#define MPU_CTRL_PRIVDEFENA_Pos 2U /*!< MPU CTRL: PRIVDEFENA Position */
+#define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */
+
+#define MPU_CTRL_HFNMIENA_Pos 1U /*!< MPU CTRL: HFNMIENA Position */
+#define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */
+
+#define MPU_CTRL_ENABLE_Pos 0U /*!< MPU CTRL: ENABLE Position */
+#define MPU_CTRL_ENABLE_Msk (1UL /*<< MPU_CTRL_ENABLE_Pos*/) /*!< MPU CTRL: ENABLE Mask */
+
+/* MPU Region Number Register Definitions */
+#define MPU_RNR_REGION_Pos 0U /*!< MPU RNR: REGION Position */
+#define MPU_RNR_REGION_Msk (0xFFUL /*<< MPU_RNR_REGION_Pos*/) /*!< MPU RNR: REGION Mask */
+
+/* MPU Region Base Address Register Definitions */
+#define MPU_RBAR_BASE_Pos 5U /*!< MPU RBAR: BASE Position */
+#define MPU_RBAR_BASE_Msk (0x7FFFFFFUL << MPU_RBAR_BASE_Pos) /*!< MPU RBAR: BASE Mask */
+
+#define MPU_RBAR_SH_Pos 3U /*!< MPU RBAR: SH Position */
+#define MPU_RBAR_SH_Msk (0x3UL << MPU_RBAR_SH_Pos) /*!< MPU RBAR: SH Mask */
+
+#define MPU_RBAR_AP_Pos 1U /*!< MPU RBAR: AP Position */
+#define MPU_RBAR_AP_Msk (0x3UL << MPU_RBAR_AP_Pos) /*!< MPU RBAR: AP Mask */
+
+#define MPU_RBAR_XN_Pos 0U /*!< MPU RBAR: XN Position */
+#define MPU_RBAR_XN_Msk (01UL /*<< MPU_RBAR_XN_Pos*/) /*!< MPU RBAR: XN Mask */
+
+/* MPU Region Limit Address Register Definitions */
+#define MPU_RLAR_LIMIT_Pos 5U /*!< MPU RLAR: LIMIT Position */
+#define MPU_RLAR_LIMIT_Msk (0x7FFFFFFUL << MPU_RLAR_LIMIT_Pos) /*!< MPU RLAR: LIMIT Mask */
+
+#define MPU_RLAR_AttrIndx_Pos 1U /*!< MPU RLAR: AttrIndx Position */
+#define MPU_RLAR_AttrIndx_Msk (0x7UL << MPU_RLAR_AttrIndx_Pos) /*!< MPU RLAR: AttrIndx Mask */
+
+#define MPU_RLAR_EN_Pos 0U /*!< MPU RLAR: EN Position */
+#define MPU_RLAR_EN_Msk (1UL /*<< MPU_RLAR_EN_Pos*/) /*!< MPU RLAR: EN Mask */
+
+/* MPU Memory Attribute Indirection Register 0 Definitions */
+#define MPU_MAIR0_Attr3_Pos 24U /*!< MPU MAIR0: Attr3 Position */
+#define MPU_MAIR0_Attr3_Msk (0xFFUL << MPU_MAIR0_Attr3_Pos) /*!< MPU MAIR0: Attr3 Mask */
+
+#define MPU_MAIR0_Attr2_Pos 16U /*!< MPU MAIR0: Attr2 Position */
+#define MPU_MAIR0_Attr2_Msk (0xFFUL << MPU_MAIR0_Attr2_Pos) /*!< MPU MAIR0: Attr2 Mask */
+
+#define MPU_MAIR0_Attr1_Pos 8U /*!< MPU MAIR0: Attr1 Position */
+#define MPU_MAIR0_Attr1_Msk (0xFFUL << MPU_MAIR0_Attr1_Pos) /*!< MPU MAIR0: Attr1 Mask */
+
+#define MPU_MAIR0_Attr0_Pos 0U /*!< MPU MAIR0: Attr0 Position */
+#define MPU_MAIR0_Attr0_Msk (0xFFUL /*<< MPU_MAIR0_Attr0_Pos*/) /*!< MPU MAIR0: Attr0 Mask */
+
+/* MPU Memory Attribute Indirection Register 1 Definitions */
+#define MPU_MAIR1_Attr7_Pos 24U /*!< MPU MAIR1: Attr7 Position */
+#define MPU_MAIR1_Attr7_Msk (0xFFUL << MPU_MAIR1_Attr7_Pos) /*!< MPU MAIR1: Attr7 Mask */
+
+#define MPU_MAIR1_Attr6_Pos 16U /*!< MPU MAIR1: Attr6 Position */
+#define MPU_MAIR1_Attr6_Msk (0xFFUL << MPU_MAIR1_Attr6_Pos) /*!< MPU MAIR1: Attr6 Mask */
+
+#define MPU_MAIR1_Attr5_Pos 8U /*!< MPU MAIR1: Attr5 Position */
+#define MPU_MAIR1_Attr5_Msk (0xFFUL << MPU_MAIR1_Attr5_Pos) /*!< MPU MAIR1: Attr5 Mask */
+
+#define MPU_MAIR1_Attr4_Pos 0U /*!< MPU MAIR1: Attr4 Position */
+#define MPU_MAIR1_Attr4_Msk (0xFFUL /*<< MPU_MAIR1_Attr4_Pos*/) /*!< MPU MAIR1: Attr4 Mask */
+
+/*@} end of group CMSIS_MPU */
+#endif
+
+
+#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_SAU Security Attribution Unit (SAU)
+ \brief Type definitions for the Security Attribution Unit (SAU)
+ @{
+ */
+
+/**
+ \brief Structure type to access the Security Attribution Unit (SAU).
+ */
+typedef struct
+{
+ __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SAU Control Register */
+ __IM uint32_t TYPE; /*!< Offset: 0x004 (R/ ) SAU Type Register */
+#if defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U)
+ __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) SAU Region Number Register */
+ __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) SAU Region Base Address Register */
+ __IOM uint32_t RLAR; /*!< Offset: 0x010 (R/W) SAU Region Limit Address Register */
+#endif
+} SAU_Type;
+
+/* SAU Control Register Definitions */
+#define SAU_CTRL_ALLNS_Pos 1U /*!< SAU CTRL: ALLNS Position */
+#define SAU_CTRL_ALLNS_Msk (1UL << SAU_CTRL_ALLNS_Pos) /*!< SAU CTRL: ALLNS Mask */
+
+#define SAU_CTRL_ENABLE_Pos 0U /*!< SAU CTRL: ENABLE Position */
+#define SAU_CTRL_ENABLE_Msk (1UL /*<< SAU_CTRL_ENABLE_Pos*/) /*!< SAU CTRL: ENABLE Mask */
+
+/* SAU Type Register Definitions */
+#define SAU_TYPE_SREGION_Pos 0U /*!< SAU TYPE: SREGION Position */
+#define SAU_TYPE_SREGION_Msk (0xFFUL /*<< SAU_TYPE_SREGION_Pos*/) /*!< SAU TYPE: SREGION Mask */
+
+#if defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U)
+/* SAU Region Number Register Definitions */
+#define SAU_RNR_REGION_Pos 0U /*!< SAU RNR: REGION Position */
+#define SAU_RNR_REGION_Msk (0xFFUL /*<< SAU_RNR_REGION_Pos*/) /*!< SAU RNR: REGION Mask */
+
+/* SAU Region Base Address Register Definitions */
+#define SAU_RBAR_BADDR_Pos 5U /*!< SAU RBAR: BADDR Position */
+#define SAU_RBAR_BADDR_Msk (0x7FFFFFFUL << SAU_RBAR_BADDR_Pos) /*!< SAU RBAR: BADDR Mask */
+
+/* SAU Region Limit Address Register Definitions */
+#define SAU_RLAR_LADDR_Pos 5U /*!< SAU RLAR: LADDR Position */
+#define SAU_RLAR_LADDR_Msk (0x7FFFFFFUL << SAU_RLAR_LADDR_Pos) /*!< SAU RLAR: LADDR Mask */
+
+#define SAU_RLAR_NSC_Pos 1U /*!< SAU RLAR: NSC Position */
+#define SAU_RLAR_NSC_Msk (1UL << SAU_RLAR_NSC_Pos) /*!< SAU RLAR: NSC Mask */
+
+#define SAU_RLAR_ENABLE_Pos 0U /*!< SAU RLAR: ENABLE Position */
+#define SAU_RLAR_ENABLE_Msk (1UL /*<< SAU_RLAR_ENABLE_Pos*/) /*!< SAU RLAR: ENABLE Mask */
+
+#endif /* defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U) */
+
+/*@} end of group CMSIS_SAU */
+#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug)
+ \brief Type definitions for the Core Debug Registers
+ @{
+ */
+
+/**
+ \brief Structure type to access the Core Debug Register (CoreDebug).
+ */
+typedef struct
+{
+ __IOM uint32_t DHCSR; /*!< Offset: 0x000 (R/W) Debug Halting Control and Status Register */
+ __OM uint32_t DCRSR; /*!< Offset: 0x004 ( /W) Debug Core Register Selector Register */
+ __IOM uint32_t DCRDR; /*!< Offset: 0x008 (R/W) Debug Core Register Data Register */
+ __IOM uint32_t DEMCR; /*!< Offset: 0x00C (R/W) Debug Exception and Monitor Control Register */
+ uint32_t RESERVED4[1U];
+ __IOM uint32_t DAUTHCTRL; /*!< Offset: 0x014 (R/W) Debug Authentication Control Register */
+ __IOM uint32_t DSCSR; /*!< Offset: 0x018 (R/W) Debug Security Control and Status Register */
+} CoreDebug_Type;
+
+/* Debug Halting Control and Status Register Definitions */
+#define CoreDebug_DHCSR_DBGKEY_Pos 16U /*!< CoreDebug DHCSR: DBGKEY Position */
+#define CoreDebug_DHCSR_DBGKEY_Msk (0xFFFFUL << CoreDebug_DHCSR_DBGKEY_Pos) /*!< CoreDebug DHCSR: DBGKEY Mask */
+
+#define CoreDebug_DHCSR_S_RESTART_ST_Pos 26U /*!< CoreDebug DHCSR: S_RESTART_ST Position */
+#define CoreDebug_DHCSR_S_RESTART_ST_Msk (1UL << CoreDebug_DHCSR_S_RESTART_ST_Pos) /*!< CoreDebug DHCSR: S_RESTART_ST Mask */
+
+#define CoreDebug_DHCSR_S_RESET_ST_Pos 25U /*!< CoreDebug DHCSR: S_RESET_ST Position */
+#define CoreDebug_DHCSR_S_RESET_ST_Msk (1UL << CoreDebug_DHCSR_S_RESET_ST_Pos) /*!< CoreDebug DHCSR: S_RESET_ST Mask */
+
+#define CoreDebug_DHCSR_S_RETIRE_ST_Pos 24U /*!< CoreDebug DHCSR: S_RETIRE_ST Position */
+#define CoreDebug_DHCSR_S_RETIRE_ST_Msk (1UL << CoreDebug_DHCSR_S_RETIRE_ST_Pos) /*!< CoreDebug DHCSR: S_RETIRE_ST Mask */
+
+#define CoreDebug_DHCSR_S_LOCKUP_Pos 19U /*!< CoreDebug DHCSR: S_LOCKUP Position */
+#define CoreDebug_DHCSR_S_LOCKUP_Msk (1UL << CoreDebug_DHCSR_S_LOCKUP_Pos) /*!< CoreDebug DHCSR: S_LOCKUP Mask */
+
+#define CoreDebug_DHCSR_S_SLEEP_Pos 18U /*!< CoreDebug DHCSR: S_SLEEP Position */
+#define CoreDebug_DHCSR_S_SLEEP_Msk (1UL << CoreDebug_DHCSR_S_SLEEP_Pos) /*!< CoreDebug DHCSR: S_SLEEP Mask */
+
+#define CoreDebug_DHCSR_S_HALT_Pos 17U /*!< CoreDebug DHCSR: S_HALT Position */
+#define CoreDebug_DHCSR_S_HALT_Msk (1UL << CoreDebug_DHCSR_S_HALT_Pos) /*!< CoreDebug DHCSR: S_HALT Mask */
+
+#define CoreDebug_DHCSR_S_REGRDY_Pos 16U /*!< CoreDebug DHCSR: S_REGRDY Position */
+#define CoreDebug_DHCSR_S_REGRDY_Msk (1UL << CoreDebug_DHCSR_S_REGRDY_Pos) /*!< CoreDebug DHCSR: S_REGRDY Mask */
+
+#define CoreDebug_DHCSR_C_MASKINTS_Pos 3U /*!< CoreDebug DHCSR: C_MASKINTS Position */
+#define CoreDebug_DHCSR_C_MASKINTS_Msk (1UL << CoreDebug_DHCSR_C_MASKINTS_Pos) /*!< CoreDebug DHCSR: C_MASKINTS Mask */
+
+#define CoreDebug_DHCSR_C_STEP_Pos 2U /*!< CoreDebug DHCSR: C_STEP Position */
+#define CoreDebug_DHCSR_C_STEP_Msk (1UL << CoreDebug_DHCSR_C_STEP_Pos) /*!< CoreDebug DHCSR: C_STEP Mask */
+
+#define CoreDebug_DHCSR_C_HALT_Pos 1U /*!< CoreDebug DHCSR: C_HALT Position */
+#define CoreDebug_DHCSR_C_HALT_Msk (1UL << CoreDebug_DHCSR_C_HALT_Pos) /*!< CoreDebug DHCSR: C_HALT Mask */
+
+#define CoreDebug_DHCSR_C_DEBUGEN_Pos 0U /*!< CoreDebug DHCSR: C_DEBUGEN Position */
+#define CoreDebug_DHCSR_C_DEBUGEN_Msk (1UL /*<< CoreDebug_DHCSR_C_DEBUGEN_Pos*/) /*!< CoreDebug DHCSR: C_DEBUGEN Mask */
+
+/* Debug Core Register Selector Register Definitions */
+#define CoreDebug_DCRSR_REGWnR_Pos 16U /*!< CoreDebug DCRSR: REGWnR Position */
+#define CoreDebug_DCRSR_REGWnR_Msk (1UL << CoreDebug_DCRSR_REGWnR_Pos) /*!< CoreDebug DCRSR: REGWnR Mask */
+
+#define CoreDebug_DCRSR_REGSEL_Pos 0U /*!< CoreDebug DCRSR: REGSEL Position */
+#define CoreDebug_DCRSR_REGSEL_Msk (0x1FUL /*<< CoreDebug_DCRSR_REGSEL_Pos*/) /*!< CoreDebug DCRSR: REGSEL Mask */
+
+/* Debug Exception and Monitor Control Register */
+#define CoreDebug_DEMCR_DWTENA_Pos 24U /*!< CoreDebug DEMCR: DWTENA Position */
+#define CoreDebug_DEMCR_DWTENA_Msk (1UL << CoreDebug_DEMCR_DWTENA_Pos) /*!< CoreDebug DEMCR: DWTENA Mask */
+
+#define CoreDebug_DEMCR_VC_HARDERR_Pos 10U /*!< CoreDebug DEMCR: VC_HARDERR Position */
+#define CoreDebug_DEMCR_VC_HARDERR_Msk (1UL << CoreDebug_DEMCR_VC_HARDERR_Pos) /*!< CoreDebug DEMCR: VC_HARDERR Mask */
+
+#define CoreDebug_DEMCR_VC_CORERESET_Pos 0U /*!< CoreDebug DEMCR: VC_CORERESET Position */
+#define CoreDebug_DEMCR_VC_CORERESET_Msk (1UL /*<< CoreDebug_DEMCR_VC_CORERESET_Pos*/) /*!< CoreDebug DEMCR: VC_CORERESET Mask */
+
+/* Debug Authentication Control Register Definitions */
+#define CoreDebug_DAUTHCTRL_INTSPNIDEN_Pos 3U /*!< CoreDebug DAUTHCTRL: INTSPNIDEN, Position */
+#define CoreDebug_DAUTHCTRL_INTSPNIDEN_Msk (1UL << CoreDebug_DAUTHCTRL_INTSPNIDEN_Pos) /*!< CoreDebug DAUTHCTRL: INTSPNIDEN, Mask */
+
+#define CoreDebug_DAUTHCTRL_SPNIDENSEL_Pos 2U /*!< CoreDebug DAUTHCTRL: SPNIDENSEL Position */
+#define CoreDebug_DAUTHCTRL_SPNIDENSEL_Msk (1UL << CoreDebug_DAUTHCTRL_SPNIDENSEL_Pos) /*!< CoreDebug DAUTHCTRL: SPNIDENSEL Mask */
+
+#define CoreDebug_DAUTHCTRL_INTSPIDEN_Pos 1U /*!< CoreDebug DAUTHCTRL: INTSPIDEN Position */
+#define CoreDebug_DAUTHCTRL_INTSPIDEN_Msk (1UL << CoreDebug_DAUTHCTRL_INTSPIDEN_Pos) /*!< CoreDebug DAUTHCTRL: INTSPIDEN Mask */
+
+#define CoreDebug_DAUTHCTRL_SPIDENSEL_Pos 0U /*!< CoreDebug DAUTHCTRL: SPIDENSEL Position */
+#define CoreDebug_DAUTHCTRL_SPIDENSEL_Msk (1UL /*<< CoreDebug_DAUTHCTRL_SPIDENSEL_Pos*/) /*!< CoreDebug DAUTHCTRL: SPIDENSEL Mask */
+
+/* Debug Security Control and Status Register Definitions */
+#define CoreDebug_DSCSR_CDS_Pos 16U /*!< CoreDebug DSCSR: CDS Position */
+#define CoreDebug_DSCSR_CDS_Msk (1UL << CoreDebug_DSCSR_CDS_Pos) /*!< CoreDebug DSCSR: CDS Mask */
+
+#define CoreDebug_DSCSR_SBRSEL_Pos 1U /*!< CoreDebug DSCSR: SBRSEL Position */
+#define CoreDebug_DSCSR_SBRSEL_Msk (1UL << CoreDebug_DSCSR_SBRSEL_Pos) /*!< CoreDebug DSCSR: SBRSEL Mask */
+
+#define CoreDebug_DSCSR_SBRSELEN_Pos 0U /*!< CoreDebug DSCSR: SBRSELEN Position */
+#define CoreDebug_DSCSR_SBRSELEN_Msk (1UL /*<< CoreDebug_DSCSR_SBRSELEN_Pos*/) /*!< CoreDebug DSCSR: SBRSELEN Mask */
+
+/*@} end of group CMSIS_CoreDebug */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_core_bitfield Core register bit field macros
+ \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk).
+ @{
+ */
+
+/**
+ \brief Mask and shift a bit field value for use in a register bit range.
+ \param[in] field Name of the register bit field.
+ \param[in] value Value of the bit field. This parameter is interpreted as an uint32_t type.
+ \return Masked and shifted value.
+*/
+#define _VAL2FLD(field, value) (((uint32_t)(value) << field ## _Pos) & field ## _Msk)
+
+/**
+ \brief Mask and shift a register value to extract a bit filed value.
+ \param[in] field Name of the register bit field.
+ \param[in] value Value of register. This parameter is interpreted as an uint32_t type.
+ \return Masked and shifted bit field value.
+*/
+#define _FLD2VAL(field, value) (((uint32_t)(value) & field ## _Msk) >> field ## _Pos)
+
+/*@} end of group CMSIS_core_bitfield */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_core_base Core Definitions
+ \brief Definitions for base addresses, unions, and structures.
+ @{
+ */
+
+/* Memory mapping of Core Hardware */
+ #define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */
+ #define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */
+ #define TPI_BASE (0xE0040000UL) /*!< TPI Base Address */
+ #define CoreDebug_BASE (0xE000EDF0UL) /*!< Core Debug Base Address */
+ #define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */
+ #define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */
+ #define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */
+
+
+ #define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */
+ #define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */
+ #define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */
+ #define DWT ((DWT_Type *) DWT_BASE ) /*!< DWT configuration struct */
+ #define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */
+ #define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE ) /*!< Core Debug configuration struct */
+
+ #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U)
+ #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */
+ #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */
+ #endif
+
+ #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
+ #define SAU_BASE (SCS_BASE + 0x0DD0UL) /*!< Security Attribution Unit */
+ #define SAU ((SAU_Type *) SAU_BASE ) /*!< Security Attribution Unit */
+ #endif
+
+#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
+ #define SCS_BASE_NS (0xE002E000UL) /*!< System Control Space Base Address (non-secure address space) */
+ #define CoreDebug_BASE_NS (0xE002EDF0UL) /*!< Core Debug Base Address (non-secure address space) */
+ #define SysTick_BASE_NS (SCS_BASE_NS + 0x0010UL) /*!< SysTick Base Address (non-secure address space) */
+ #define NVIC_BASE_NS (SCS_BASE_NS + 0x0100UL) /*!< NVIC Base Address (non-secure address space) */
+ #define SCB_BASE_NS (SCS_BASE_NS + 0x0D00UL) /*!< System Control Block Base Address (non-secure address space) */
+
+ #define SCB_NS ((SCB_Type *) SCB_BASE_NS ) /*!< SCB configuration struct (non-secure address space) */
+ #define SysTick_NS ((SysTick_Type *) SysTick_BASE_NS ) /*!< SysTick configuration struct (non-secure address space) */
+ #define NVIC_NS ((NVIC_Type *) NVIC_BASE_NS ) /*!< NVIC configuration struct (non-secure address space) */
+ #define CoreDebug_NS ((CoreDebug_Type *) CoreDebug_BASE_NS) /*!< Core Debug configuration struct (non-secure address space) */
+
+ #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U)
+ #define MPU_BASE_NS (SCS_BASE_NS + 0x0D90UL) /*!< Memory Protection Unit (non-secure address space) */
+ #define MPU_NS ((MPU_Type *) MPU_BASE_NS ) /*!< Memory Protection Unit (non-secure address space) */
+ #endif
+
+#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */
+/*@} */
+
+
+
+/*******************************************************************************
+ * Hardware Abstraction Layer
+ Core Function Interface contains:
+ - Core NVIC Functions
+ - Core SysTick Functions
+ - Core Register Access Functions
+ ******************************************************************************/
+/**
+ \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference
+*/
+
+
+
+/* ########################## NVIC functions #################################### */
+/**
+ \ingroup CMSIS_Core_FunctionInterface
+ \defgroup CMSIS_Core_NVICFunctions NVIC Functions
+ \brief Functions that manage interrupts and exceptions via the NVIC.
+ @{
+ */
+
+#ifdef CMSIS_NVIC_VIRTUAL
+ #ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE
+ #define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h"
+ #endif
+ #include CMSIS_NVIC_VIRTUAL_HEADER_FILE
+#else
+/*#define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping not available for Cortex-M23 */
+/*#define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping not available for Cortex-M23 */
+ #define NVIC_EnableIRQ __NVIC_EnableIRQ
+ #define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ
+ #define NVIC_DisableIRQ __NVIC_DisableIRQ
+ #define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ
+ #define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ
+ #define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ
+ #define NVIC_GetActive __NVIC_GetActive
+ #define NVIC_SetPriority __NVIC_SetPriority
+ #define NVIC_GetPriority __NVIC_GetPriority
+ #define NVIC_SystemReset __NVIC_SystemReset
+#endif /* CMSIS_NVIC_VIRTUAL */
+
+#ifdef CMSIS_VECTAB_VIRTUAL
+ #ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE
+ #define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h"
+ #endif
+ #include CMSIS_VECTAB_VIRTUAL_HEADER_FILE
+#else
+ #define NVIC_SetVector __NVIC_SetVector
+ #define NVIC_GetVector __NVIC_GetVector
+#endif /* (CMSIS_VECTAB_VIRTUAL) */
+
+#define NVIC_USER_IRQ_OFFSET 16
+
+
+/* Special LR values for Secure/Non-Secure call handling and exception handling */
+
+/* Function Return Payload (from ARMv8-M Architecture Reference Manual) LR value on entry from Secure BLXNS */
+#define FNC_RETURN (0xFEFFFFFFUL) /* bit [0] ignored when processing a branch */
+
+/* The following EXC_RETURN mask values are used to evaluate the LR on exception entry */
+#define EXC_RETURN_PREFIX (0xFF000000UL) /* bits [31:24] set to indicate an EXC_RETURN value */
+#define EXC_RETURN_S (0x00000040UL) /* bit [6] stack used to push registers: 0=Non-secure 1=Secure */
+#define EXC_RETURN_DCRS (0x00000020UL) /* bit [5] stacking rules for called registers: 0=skipped 1=saved */
+#define EXC_RETURN_FTYPE (0x00000010UL) /* bit [4] allocate stack for floating-point context: 0=done 1=skipped */
+#define EXC_RETURN_MODE (0x00000008UL) /* bit [3] processor mode for return: 0=Handler mode 1=Thread mode */
+#define EXC_RETURN_SPSEL (0x00000004UL) /* bit [2] stack pointer used to restore context: 0=MSP 1=PSP */
+#define EXC_RETURN_ES (0x00000001UL) /* bit [0] security state exception was taken to: 0=Non-secure 1=Secure */
+
+/* Integrity Signature (from ARMv8-M Architecture Reference Manual) for exception context stacking */
+#if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) /* Value for processors with floating-point extension: */
+#define EXC_INTEGRITY_SIGNATURE (0xFEFA125AUL) /* bit [0] SFTC must match LR bit[4] EXC_RETURN_FTYPE */
+#else
+#define EXC_INTEGRITY_SIGNATURE (0xFEFA125BUL) /* Value for processors without floating-point extension */
+#endif
+
+
+/* Interrupt Priorities are WORD accessible only under Armv6-M */
+/* The following MACROS handle generation of the register offset and byte masks */
+#define _BIT_SHIFT(IRQn) ( ((((uint32_t)(int32_t)(IRQn)) ) & 0x03UL) * 8UL)
+#define _SHP_IDX(IRQn) ( (((((uint32_t)(int32_t)(IRQn)) & 0x0FUL)-8UL) >> 2UL) )
+#define _IP_IDX(IRQn) ( (((uint32_t)(int32_t)(IRQn)) >> 2UL) )
+
+#define __NVIC_SetPriorityGrouping(X) (void)(X)
+#define __NVIC_GetPriorityGrouping() (0U)
+
+/**
+ \brief Enable Interrupt
+ \details Enables a device specific interrupt in the NVIC interrupt controller.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Get Interrupt Enable status
+ \details Returns a device specific interrupt enable status from the NVIC interrupt controller.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 Interrupt is not enabled.
+ \return 1 Interrupt is enabled.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Disable Interrupt
+ \details Disables a device specific interrupt in the NVIC interrupt controller.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ICER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ __DSB();
+ __ISB();
+ }
+}
+
+
+/**
+ \brief Get Pending Interrupt
+ \details Reads the NVIC pending register and returns the pending bit for the specified device specific interrupt.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 Interrupt status is not pending.
+ \return 1 Interrupt status is pending.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Set Pending Interrupt
+ \details Sets the pending bit of a device specific interrupt in the NVIC pending register.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Clear Pending Interrupt
+ \details Clears the pending bit of a device specific interrupt in the NVIC pending register.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Get Active Interrupt
+ \details Reads the active register in the NVIC and returns the active bit for the device specific interrupt.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 Interrupt status is not active.
+ \return 1 Interrupt status is active.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t __NVIC_GetActive(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC->IABR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
+/**
+ \brief Get Interrupt Target State
+ \details Reads the interrupt target field in the NVIC and returns the interrupt target bit for the device specific interrupt.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 if interrupt is assigned to Secure
+ \return 1 if interrupt is assigned to Non Secure
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t NVIC_GetTargetState(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Set Interrupt Target State
+ \details Sets the interrupt target field in the NVIC and returns the interrupt target bit for the device specific interrupt.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 if interrupt is assigned to Secure
+ 1 if interrupt is assigned to Non Secure
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t NVIC_SetTargetState(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] |= ((uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)));
+ return((uint32_t)(((NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Clear Interrupt Target State
+ \details Clears the interrupt target field in the NVIC and returns the interrupt target bit for the device specific interrupt.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 if interrupt is assigned to Secure
+ 1 if interrupt is assigned to Non Secure
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t NVIC_ClearTargetState(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] &= ~((uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)));
+ return((uint32_t)(((NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */
+
+
+/**
+ \brief Set Interrupt Priority
+ \details Sets the priority of a device specific interrupt or a processor exception.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ \param [in] IRQn Interrupt number.
+ \param [in] priority Priority to set.
+ \note The priority cannot be set for every processor exception.
+ */
+__STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->IPR[_IP_IDX(IRQn)] = ((uint32_t)(NVIC->IPR[_IP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) |
+ (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn)));
+ }
+ else
+ {
+ SCB->SHPR[_SHP_IDX(IRQn)] = ((uint32_t)(SCB->SHPR[_SHP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) |
+ (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn)));
+ }
+}
+
+
+/**
+ \brief Get Interrupt Priority
+ \details Reads the priority of a device specific interrupt or a processor exception.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ \param [in] IRQn Interrupt number.
+ \return Interrupt Priority.
+ Value is aligned automatically to the implemented priority bits of the microcontroller.
+ */
+__STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn)
+{
+
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC->IPR[ _IP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS)));
+ }
+ else
+ {
+ return((uint32_t)(((SCB->SHPR[_SHP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS)));
+ }
+}
+
+
+/**
+ \brief Encode Priority
+ \details Encodes the priority for an interrupt with the given priority group,
+ preemptive priority value, and subpriority value.
+ In case of a conflict between priority grouping and available
+ priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set.
+ \param [in] PriorityGroup Used priority group.
+ \param [in] PreemptPriority Preemptive priority value (starting from 0).
+ \param [in] SubPriority Subpriority value (starting from 0).
+ \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority().
+ */
+__STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority)
+{
+ uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */
+ uint32_t PreemptPriorityBits;
+ uint32_t SubPriorityBits;
+
+ PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp);
+ SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS));
+
+ return (
+ ((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) |
+ ((SubPriority & (uint32_t)((1UL << (SubPriorityBits )) - 1UL)))
+ );
+}
+
+
+/**
+ \brief Decode Priority
+ \details Decodes an interrupt priority value with a given priority group to
+ preemptive priority value and subpriority value.
+ In case of a conflict between priority grouping and available
+ priority bits (__NVIC_PRIO_BITS) the smallest possible priority group is set.
+ \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority().
+ \param [in] PriorityGroup Used priority group.
+ \param [out] pPreemptPriority Preemptive priority value (starting from 0).
+ \param [out] pSubPriority Subpriority value (starting from 0).
+ */
+__STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* const pPreemptPriority, uint32_t* const pSubPriority)
+{
+ uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */
+ uint32_t PreemptPriorityBits;
+ uint32_t SubPriorityBits;
+
+ PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp);
+ SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS));
+
+ *pPreemptPriority = (Priority >> SubPriorityBits) & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL);
+ *pSubPriority = (Priority ) & (uint32_t)((1UL << (SubPriorityBits )) - 1UL);
+}
+
+
+/**
+ \brief Set Interrupt Vector
+ \details Sets an interrupt vector in SRAM based interrupt vector table.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ VTOR must been relocated to SRAM before.
+ If VTOR is not present address 0 must be mapped to SRAM.
+ \param [in] IRQn Interrupt number
+ \param [in] vector Address of interrupt handler function
+ */
+__STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector)
+{
+#if defined (__VTOR_PRESENT) && (__VTOR_PRESENT == 1U)
+ uint32_t *vectors = (uint32_t *)SCB->VTOR;
+#else
+ uint32_t *vectors = (uint32_t *)0x0U;
+#endif
+ vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET] = vector;
+}
+
+
+/**
+ \brief Get Interrupt Vector
+ \details Reads an interrupt vector from interrupt vector table.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ \param [in] IRQn Interrupt number.
+ \return Address of interrupt handler function
+ */
+__STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn)
+{
+#if defined (__VTOR_PRESENT) && (__VTOR_PRESENT == 1U)
+ uint32_t *vectors = (uint32_t *)SCB->VTOR;
+#else
+ uint32_t *vectors = (uint32_t *)0x0U;
+#endif
+ return vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET];
+}
+
+
+/**
+ \brief System Reset
+ \details Initiates a system reset request to reset the MCU.
+ */
+__NO_RETURN __STATIC_INLINE void __NVIC_SystemReset(void)
+{
+ __DSB(); /* Ensure all outstanding memory accesses included
+ buffered write are completed before reset */
+ SCB->AIRCR = ((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) |
+ SCB_AIRCR_SYSRESETREQ_Msk);
+ __DSB(); /* Ensure completion of memory access */
+
+ for(;;) /* wait until reset */
+ {
+ __NOP();
+ }
+}
+
+#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
+/**
+ \brief Enable Interrupt (non-secure)
+ \details Enables a device specific interrupt in the non-secure NVIC interrupt controller when in secure state.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void TZ_NVIC_EnableIRQ_NS(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC_NS->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Get Interrupt Enable status (non-secure)
+ \details Returns a device specific interrupt enable status from the non-secure NVIC interrupt controller when in secure state.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 Interrupt is not enabled.
+ \return 1 Interrupt is enabled.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t TZ_NVIC_GetEnableIRQ_NS(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC_NS->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Disable Interrupt (non-secure)
+ \details Disables a device specific interrupt in the non-secure NVIC interrupt controller when in secure state.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void TZ_NVIC_DisableIRQ_NS(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC_NS->ICER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Get Pending Interrupt (non-secure)
+ \details Reads the NVIC pending register in the non-secure NVIC when in secure state and returns the pending bit for the specified device specific interrupt.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 Interrupt status is not pending.
+ \return 1 Interrupt status is pending.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t TZ_NVIC_GetPendingIRQ_NS(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC_NS->ISPR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Set Pending Interrupt (non-secure)
+ \details Sets the pending bit of a device specific interrupt in the non-secure NVIC pending register when in secure state.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void TZ_NVIC_SetPendingIRQ_NS(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC_NS->ISPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Clear Pending Interrupt (non-secure)
+ \details Clears the pending bit of a device specific interrupt in the non-secure NVIC pending register when in secure state.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void TZ_NVIC_ClearPendingIRQ_NS(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC_NS->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Get Active Interrupt (non-secure)
+ \details Reads the active register in non-secure NVIC when in secure state and returns the active bit for the device specific interrupt.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 Interrupt status is not active.
+ \return 1 Interrupt status is active.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t TZ_NVIC_GetActive_NS(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC_NS->IABR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Set Interrupt Priority (non-secure)
+ \details Sets the priority of a non-secure device specific interrupt or a non-secure processor exception when in secure state.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ \param [in] IRQn Interrupt number.
+ \param [in] priority Priority to set.
+ \note The priority cannot be set for every non-secure processor exception.
+ */
+__STATIC_INLINE void TZ_NVIC_SetPriority_NS(IRQn_Type IRQn, uint32_t priority)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC_NS->IPR[_IP_IDX(IRQn)] = ((uint32_t)(NVIC_NS->IPR[_IP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) |
+ (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn)));
+ }
+ else
+ {
+ SCB_NS->SHPR[_SHP_IDX(IRQn)] = ((uint32_t)(SCB_NS->SHPR[_SHP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) |
+ (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn)));
+ }
+}
+
+
+/**
+ \brief Get Interrupt Priority (non-secure)
+ \details Reads the priority of a non-secure device specific interrupt or a non-secure processor exception when in secure state.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ \param [in] IRQn Interrupt number.
+ \return Interrupt Priority. Value is aligned automatically to the implemented priority bits of the microcontroller.
+ */
+__STATIC_INLINE uint32_t TZ_NVIC_GetPriority_NS(IRQn_Type IRQn)
+{
+
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC_NS->IPR[ _IP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS)));
+ }
+ else
+ {
+ return((uint32_t)(((SCB_NS->SHPR[_SHP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS)));
+ }
+}
+#endif /* defined (__ARM_FEATURE_CMSE) &&(__ARM_FEATURE_CMSE == 3U) */
+
+/*@} end of CMSIS_Core_NVICFunctions */
+
+/* ########################## MPU functions #################################### */
+
+#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U)
+
+#include "mpu_armv8.h"
+
+#endif
+
+/* ########################## FPU functions #################################### */
+/**
+ \ingroup CMSIS_Core_FunctionInterface
+ \defgroup CMSIS_Core_FpuFunctions FPU Functions
+ \brief Function that provides FPU type.
+ @{
+ */
+
+/**
+ \brief get FPU type
+ \details returns the FPU type
+ \returns
+ - \b 0: No FPU
+ - \b 1: Single precision FPU
+ - \b 2: Double + Single precision FPU
+ */
+__STATIC_INLINE uint32_t SCB_GetFPUType(void)
+{
+ return 0U; /* No FPU */
+}
+
+
+/*@} end of CMSIS_Core_FpuFunctions */
+
+
+
+/* ########################## SAU functions #################################### */
+/**
+ \ingroup CMSIS_Core_FunctionInterface
+ \defgroup CMSIS_Core_SAUFunctions SAU Functions
+ \brief Functions that configure the SAU.
+ @{
+ */
+
+#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
+
+/**
+ \brief Enable SAU
+ \details Enables the Security Attribution Unit (SAU).
+ */
+__STATIC_INLINE void TZ_SAU_Enable(void)
+{
+ SAU->CTRL |= (SAU_CTRL_ENABLE_Msk);
+}
+
+
+
+/**
+ \brief Disable SAU
+ \details Disables the Security Attribution Unit (SAU).
+ */
+__STATIC_INLINE void TZ_SAU_Disable(void)
+{
+ SAU->CTRL &= ~(SAU_CTRL_ENABLE_Msk);
+}
+
+#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */
+
+/*@} end of CMSIS_Core_SAUFunctions */
+
+
+
+
+/* ################################## SysTick function ############################################ */
+/**
+ \ingroup CMSIS_Core_FunctionInterface
+ \defgroup CMSIS_Core_SysTickFunctions SysTick Functions
+ \brief Functions that configure the System.
+ @{
+ */
+
+#if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U)
+
+/**
+ \brief System Tick Configuration
+ \details Initializes the System Timer and its interrupt, and starts the System Tick Timer.
+ Counter is in free running mode to generate periodic interrupts.
+ \param [in] ticks Number of ticks between two interrupts.
+ \return 0 Function succeeded.
+ \return 1 Function failed.
+ \note When the variable __Vendor_SysTickConfig is set to 1, then the
+ function SysTick_Config is not included. In this case, the file device.h
+ must contain a vendor-specific implementation of this function.
+ */
+__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)
+{
+ if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk)
+ {
+ return (1UL); /* Reload value impossible */
+ }
+
+ SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */
+ NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */
+ SysTick->VAL = 0UL; /* Load the SysTick Counter Value */
+ SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
+ SysTick_CTRL_TICKINT_Msk |
+ SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */
+ return (0UL); /* Function successful */
+}
+
+#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
+/**
+ \brief System Tick Configuration (non-secure)
+ \details Initializes the non-secure System Timer and its interrupt when in secure state, and starts the System Tick Timer.
+ Counter is in free running mode to generate periodic interrupts.
+ \param [in] ticks Number of ticks between two interrupts.
+ \return 0 Function succeeded.
+ \return 1 Function failed.
+ \note When the variable __Vendor_SysTickConfig is set to 1, then the
+ function TZ_SysTick_Config_NS is not included. In this case, the file device.h
+ must contain a vendor-specific implementation of this function.
+
+ */
+__STATIC_INLINE uint32_t TZ_SysTick_Config_NS(uint32_t ticks)
+{
+ if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk)
+ {
+ return (1UL); /* Reload value impossible */
+ }
+
+ SysTick_NS->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */
+ TZ_NVIC_SetPriority_NS (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */
+ SysTick_NS->VAL = 0UL; /* Load the SysTick Counter Value */
+ SysTick_NS->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
+ SysTick_CTRL_TICKINT_Msk |
+ SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */
+ return (0UL); /* Function successful */
+}
+#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */
+
+#endif
+
+/*@} end of CMSIS_Core_SysTickFunctions */
+
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CORE_CM23_H_DEPENDANT */
+
+#endif /* __CMSIS_GENERIC */
diff --git a/lib/cmsis/inc/core_cm3.h b/lib/cmsis/inc/core_cm3.h
index b4ac4c7b05..ea5405088c 100644
--- a/lib/cmsis/inc/core_cm3.h
+++ b/lib/cmsis/inc/core_cm3.h
@@ -1,40 +1,30 @@
/**************************************************************************//**
* @file core_cm3.h
* @brief CMSIS Cortex-M3 Core Peripheral Access Layer Header File
- * @version V4.30
- * @date 20. October 2015
+ * @version V5.1.0
+ * @date 13. March 2019
******************************************************************************/
-/* Copyright (c) 2009 - 2015 ARM LIMITED
-
- All rights reserved.
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are met:
- - Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- - Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
- - Neither the name of ARM nor the names of its contributors may be used
- to endorse or promote products derived from this software without
- specific prior written permission.
- *
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE
- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- POSSIBILITY OF SUCH DAMAGE.
- ---------------------------------------------------------------------------*/
-
+/*
+ * Copyright (c) 2009-2019 Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
#if defined ( __ICCARM__ )
- #pragma system_include /* treat file as system include file for MISRA check */
-#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
+ #pragma system_include /* treat file as system include file for MISRA check */
+#elif defined (__clang__)
#pragma clang system_header /* treat file as system include file */
#endif
@@ -70,53 +60,15 @@
@{
*/
+#include "cmsis_version.h"
+
/* CMSIS CM3 definitions */
-#define __CM3_CMSIS_VERSION_MAIN (0x04U) /*!< [31:16] CMSIS HAL main version */
-#define __CM3_CMSIS_VERSION_SUB (0x1EU) /*!< [15:0] CMSIS HAL sub version */
+#define __CM3_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */
+#define __CM3_CMSIS_VERSION_SUB (__CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */
#define __CM3_CMSIS_VERSION ((__CM3_CMSIS_VERSION_MAIN << 16U) | \
- __CM3_CMSIS_VERSION_SUB ) /*!< CMSIS HAL version number */
-
-#define __CORTEX_M (0x03U) /*!< Cortex-M Core */
-
-
-#if defined ( __CC_ARM )
- #define __ASM __asm /*!< asm keyword for ARM Compiler */
- #define __INLINE __inline /*!< inline keyword for ARM Compiler */
- #define __STATIC_INLINE static __inline
-
-#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
- #define __ASM __asm /*!< asm keyword for ARM Compiler */
- #define __INLINE __inline /*!< inline keyword for ARM Compiler */
- #define __STATIC_INLINE static __inline
-
-#elif defined ( __GNUC__ )
- #define __ASM __asm /*!< asm keyword for GNU Compiler */
- #define __INLINE inline /*!< inline keyword for GNU Compiler */
- #define __STATIC_INLINE static inline
-
-#elif defined ( __ICCARM__ )
- #define __ASM __asm /*!< asm keyword for IAR Compiler */
- #define __INLINE inline /*!< inline keyword for IAR Compiler. Only available in High optimization mode! */
- #define __STATIC_INLINE static inline
-
-#elif defined ( __TMS470__ )
- #define __ASM __asm /*!< asm keyword for TI CCS Compiler */
- #define __STATIC_INLINE static inline
-
-#elif defined ( __TASKING__ )
- #define __ASM __asm /*!< asm keyword for TASKING Compiler */
- #define __INLINE inline /*!< inline keyword for TASKING Compiler */
- #define __STATIC_INLINE static inline
-
-#elif defined ( __CSMC__ )
- #define __packed
- #define __ASM _asm /*!< asm keyword for COSMIC Compiler */
- #define __INLINE inline /*!< inline keyword for COSMIC Compiler. Use -pc99 on compile line */
- #define __STATIC_INLINE static inline
+ __CM3_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */
-#else
- #error Unknown compiler
-#endif
+#define __CORTEX_M (3U) /*!< Cortex-M Core */
/** __FPU_USED indicates whether an FPU is used or not.
This core does not support an FPU at all
@@ -128,8 +80,8 @@
#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
#endif
-#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
- #if defined __ARM_PCS_VFP
+#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
+ #if defined __ARM_FP
#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
#endif
@@ -143,7 +95,7 @@
#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
#endif
-#elif defined ( __TMS470__ )
+#elif defined ( __TI_ARM__ )
#if defined __TI_VFP_SUPPORT__
#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
#endif
@@ -160,8 +112,8 @@
#endif
-#include "core_cmInstr.h" /* Core Instruction Access */
-#include "core_cmFunc.h" /* Core Function Access */
+#include "cmsis_compiler.h" /* CMSIS compiler specific defines */
+
#ifdef __cplusplus
}
@@ -191,7 +143,7 @@
#endif
#ifndef __NVIC_PRIO_BITS
- #define __NVIC_PRIO_BITS 4U
+ #define __NVIC_PRIO_BITS 3U
#warning "__NVIC_PRIO_BITS not defined in device header file; using default!"
#endif
@@ -308,9 +260,11 @@ typedef union
struct
{
uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */
- uint32_t _reserved0:15; /*!< bit: 9..23 Reserved */
- uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */
- uint32_t IT:2; /*!< bit: 25..26 saved IT state (read 0) */
+ uint32_t _reserved0:1; /*!< bit: 9 Reserved */
+ uint32_t ICI_IT_1:6; /*!< bit: 10..15 ICI/IT part 1 */
+ uint32_t _reserved1:8; /*!< bit: 16..23 Reserved */
+ uint32_t T:1; /*!< bit: 24 Thumb bit */
+ uint32_t ICI_IT_2:2; /*!< bit: 25..26 ICI/IT part 2 */
uint32_t Q:1; /*!< bit: 27 Saturation condition flag */
uint32_t V:1; /*!< bit: 28 Overflow condition code flag */
uint32_t C:1; /*!< bit: 29 Carry condition code flag */
@@ -336,12 +290,15 @@ typedef union
#define xPSR_Q_Pos 27U /*!< xPSR: Q Position */
#define xPSR_Q_Msk (1UL << xPSR_Q_Pos) /*!< xPSR: Q Mask */
-#define xPSR_IT_Pos 25U /*!< xPSR: IT Position */
-#define xPSR_IT_Msk (3UL << xPSR_IT_Pos) /*!< xPSR: IT Mask */
+#define xPSR_ICI_IT_2_Pos 25U /*!< xPSR: ICI/IT part 2 Position */
+#define xPSR_ICI_IT_2_Msk (3UL << xPSR_ICI_IT_2_Pos) /*!< xPSR: ICI/IT part 2 Mask */
#define xPSR_T_Pos 24U /*!< xPSR: T Position */
#define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */
+#define xPSR_ICI_IT_1_Pos 10U /*!< xPSR: ICI/IT part 1 Position */
+#define xPSR_ICI_IT_1_Msk (0x3FUL << xPSR_ICI_IT_1_Pos) /*!< xPSR: ICI/IT part 1 Mask */
+
#define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */
#define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */
@@ -385,7 +342,7 @@ typedef struct
__IOM uint32_t ISER[8U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */
uint32_t RESERVED0[24U];
__IOM uint32_t ICER[8U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */
- uint32_t RSERVED1[24U];
+ uint32_t RESERVED1[24U];
__IOM uint32_t ISPR[8U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */
uint32_t RESERVED2[24U];
__IOM uint32_t ICPR[8U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */
@@ -487,7 +444,7 @@ typedef struct
#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */
/* SCB Vector Table Offset Register Definitions */
-#if (__CM3_REV < 0x0201U) /* core r2p1 */
+#if defined (__CM3_REV) && (__CM3_REV < 0x0201U) /* core r2p1 */
#define SCB_VTOR_TBLBASE_Pos 29U /*!< SCB VTOR: TBLBASE Position */
#define SCB_VTOR_TBLBASE_Msk (1UL << SCB_VTOR_TBLBASE_Pos) /*!< SCB VTOR: TBLBASE Mask */
@@ -602,6 +559,60 @@ typedef struct
#define SCB_CFSR_MEMFAULTSR_Pos 0U /*!< SCB CFSR: Memory Manage Fault Status Register Position */
#define SCB_CFSR_MEMFAULTSR_Msk (0xFFUL /*<< SCB_CFSR_MEMFAULTSR_Pos*/) /*!< SCB CFSR: Memory Manage Fault Status Register Mask */
+/* MemManage Fault Status Register (part of SCB Configurable Fault Status Register) */
+#define SCB_CFSR_MMARVALID_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 7U) /*!< SCB CFSR (MMFSR): MMARVALID Position */
+#define SCB_CFSR_MMARVALID_Msk (1UL << SCB_CFSR_MMARVALID_Pos) /*!< SCB CFSR (MMFSR): MMARVALID Mask */
+
+#define SCB_CFSR_MSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 4U) /*!< SCB CFSR (MMFSR): MSTKERR Position */
+#define SCB_CFSR_MSTKERR_Msk (1UL << SCB_CFSR_MSTKERR_Pos) /*!< SCB CFSR (MMFSR): MSTKERR Mask */
+
+#define SCB_CFSR_MUNSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 3U) /*!< SCB CFSR (MMFSR): MUNSTKERR Position */
+#define SCB_CFSR_MUNSTKERR_Msk (1UL << SCB_CFSR_MUNSTKERR_Pos) /*!< SCB CFSR (MMFSR): MUNSTKERR Mask */
+
+#define SCB_CFSR_DACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 1U) /*!< SCB CFSR (MMFSR): DACCVIOL Position */
+#define SCB_CFSR_DACCVIOL_Msk (1UL << SCB_CFSR_DACCVIOL_Pos) /*!< SCB CFSR (MMFSR): DACCVIOL Mask */
+
+#define SCB_CFSR_IACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 0U) /*!< SCB CFSR (MMFSR): IACCVIOL Position */
+#define SCB_CFSR_IACCVIOL_Msk (1UL /*<< SCB_CFSR_IACCVIOL_Pos*/) /*!< SCB CFSR (MMFSR): IACCVIOL Mask */
+
+/* BusFault Status Register (part of SCB Configurable Fault Status Register) */
+#define SCB_CFSR_BFARVALID_Pos (SCB_CFSR_BUSFAULTSR_Pos + 7U) /*!< SCB CFSR (BFSR): BFARVALID Position */
+#define SCB_CFSR_BFARVALID_Msk (1UL << SCB_CFSR_BFARVALID_Pos) /*!< SCB CFSR (BFSR): BFARVALID Mask */
+
+#define SCB_CFSR_STKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 4U) /*!< SCB CFSR (BFSR): STKERR Position */
+#define SCB_CFSR_STKERR_Msk (1UL << SCB_CFSR_STKERR_Pos) /*!< SCB CFSR (BFSR): STKERR Mask */
+
+#define SCB_CFSR_UNSTKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 3U) /*!< SCB CFSR (BFSR): UNSTKERR Position */
+#define SCB_CFSR_UNSTKERR_Msk (1UL << SCB_CFSR_UNSTKERR_Pos) /*!< SCB CFSR (BFSR): UNSTKERR Mask */
+
+#define SCB_CFSR_IMPRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 2U) /*!< SCB CFSR (BFSR): IMPRECISERR Position */
+#define SCB_CFSR_IMPRECISERR_Msk (1UL << SCB_CFSR_IMPRECISERR_Pos) /*!< SCB CFSR (BFSR): IMPRECISERR Mask */
+
+#define SCB_CFSR_PRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 1U) /*!< SCB CFSR (BFSR): PRECISERR Position */
+#define SCB_CFSR_PRECISERR_Msk (1UL << SCB_CFSR_PRECISERR_Pos) /*!< SCB CFSR (BFSR): PRECISERR Mask */
+
+#define SCB_CFSR_IBUSERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 0U) /*!< SCB CFSR (BFSR): IBUSERR Position */
+#define SCB_CFSR_IBUSERR_Msk (1UL << SCB_CFSR_IBUSERR_Pos) /*!< SCB CFSR (BFSR): IBUSERR Mask */
+
+/* UsageFault Status Register (part of SCB Configurable Fault Status Register) */
+#define SCB_CFSR_DIVBYZERO_Pos (SCB_CFSR_USGFAULTSR_Pos + 9U) /*!< SCB CFSR (UFSR): DIVBYZERO Position */
+#define SCB_CFSR_DIVBYZERO_Msk (1UL << SCB_CFSR_DIVBYZERO_Pos) /*!< SCB CFSR (UFSR): DIVBYZERO Mask */
+
+#define SCB_CFSR_UNALIGNED_Pos (SCB_CFSR_USGFAULTSR_Pos + 8U) /*!< SCB CFSR (UFSR): UNALIGNED Position */
+#define SCB_CFSR_UNALIGNED_Msk (1UL << SCB_CFSR_UNALIGNED_Pos) /*!< SCB CFSR (UFSR): UNALIGNED Mask */
+
+#define SCB_CFSR_NOCP_Pos (SCB_CFSR_USGFAULTSR_Pos + 3U) /*!< SCB CFSR (UFSR): NOCP Position */
+#define SCB_CFSR_NOCP_Msk (1UL << SCB_CFSR_NOCP_Pos) /*!< SCB CFSR (UFSR): NOCP Mask */
+
+#define SCB_CFSR_INVPC_Pos (SCB_CFSR_USGFAULTSR_Pos + 2U) /*!< SCB CFSR (UFSR): INVPC Position */
+#define SCB_CFSR_INVPC_Msk (1UL << SCB_CFSR_INVPC_Pos) /*!< SCB CFSR (UFSR): INVPC Mask */
+
+#define SCB_CFSR_INVSTATE_Pos (SCB_CFSR_USGFAULTSR_Pos + 1U) /*!< SCB CFSR (UFSR): INVSTATE Position */
+#define SCB_CFSR_INVSTATE_Msk (1UL << SCB_CFSR_INVSTATE_Pos) /*!< SCB CFSR (UFSR): INVSTATE Mask */
+
+#define SCB_CFSR_UNDEFINSTR_Pos (SCB_CFSR_USGFAULTSR_Pos + 0U) /*!< SCB CFSR (UFSR): UNDEFINSTR Position */
+#define SCB_CFSR_UNDEFINSTR_Msk (1UL << SCB_CFSR_UNDEFINSTR_Pos) /*!< SCB CFSR (UFSR): UNDEFINSTR Mask */
+
/* SCB Hard Fault Status Register Definitions */
#define SCB_HFSR_DEBUGEVT_Pos 31U /*!< SCB HFSR: DEBUGEVT Position */
#define SCB_HFSR_DEBUGEVT_Msk (1UL << SCB_HFSR_DEBUGEVT_Pos) /*!< SCB HFSR: DEBUGEVT Mask */
@@ -645,7 +656,7 @@ typedef struct
{
uint32_t RESERVED0[1U];
__IM uint32_t ICTR; /*!< Offset: 0x004 (R/ ) Interrupt Controller Type Register */
-#if ((defined __CM3_REV) && (__CM3_REV >= 0x200U))
+#if defined (__CM3_REV) && (__CM3_REV >= 0x200U)
__IOM uint32_t ACTLR; /*!< Offset: 0x008 (R/W) Auxiliary Control Register */
#else
uint32_t RESERVED1[1U];
@@ -657,6 +668,12 @@ typedef struct
#define SCnSCB_ICTR_INTLINESNUM_Msk (0xFUL /*<< SCnSCB_ICTR_INTLINESNUM_Pos*/) /*!< ICTR: INTLINESNUM Mask */
/* Auxiliary Control Register Definitions */
+#if defined (__CM3_REV) && (__CM3_REV >= 0x200U)
+#define SCnSCB_ACTLR_DISOOFP_Pos 9U /*!< ACTLR: DISOOFP Position */
+#define SCnSCB_ACTLR_DISOOFP_Msk (1UL << SCnSCB_ACTLR_DISOOFP_Pos) /*!< ACTLR: DISOOFP Mask */
+
+#define SCnSCB_ACTLR_DISFPCA_Pos 8U /*!< ACTLR: DISFPCA Position */
+#define SCnSCB_ACTLR_DISFPCA_Msk (1UL << SCnSCB_ACTLR_DISFPCA_Pos) /*!< ACTLR: DISFPCA Mask */
#define SCnSCB_ACTLR_DISFOLD_Pos 2U /*!< ACTLR: DISFOLD Position */
#define SCnSCB_ACTLR_DISFOLD_Msk (1UL << SCnSCB_ACTLR_DISFOLD_Pos) /*!< ACTLR: DISFOLD Mask */
@@ -666,6 +683,7 @@ typedef struct
#define SCnSCB_ACTLR_DISMCYCINT_Pos 0U /*!< ACTLR: DISMCYCINT Position */
#define SCnSCB_ACTLR_DISMCYCINT_Msk (1UL /*<< SCnSCB_ACTLR_DISMCYCINT_Pos*/) /*!< ACTLR: DISMCYCINT Mask */
+#endif
/*@} end of group CMSIS_SCnotSCB */
@@ -746,10 +764,7 @@ typedef struct
__IOM uint32_t TPR; /*!< Offset: 0xE40 (R/W) ITM Trace Privilege Register */
uint32_t RESERVED2[15U];
__IOM uint32_t TCR; /*!< Offset: 0xE80 (R/W) ITM Trace Control Register */
- uint32_t RESERVED3[29U];
- __OM uint32_t IWR; /*!< Offset: 0xEF8 ( /W) ITM Integration Write Register */
- __IM uint32_t IRR; /*!< Offset: 0xEFC (R/ ) ITM Integration Read Register */
- __IOM uint32_t IMCR; /*!< Offset: 0xF00 (R/W) ITM Integration Mode Control Register */
+ uint32_t RESERVED3[32U];
uint32_t RESERVED4[43U];
__OM uint32_t LAR; /*!< Offset: 0xFB0 ( /W) ITM Lock Access Register */
__IM uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) ITM Lock Status Register */
@@ -770,7 +785,7 @@ typedef struct
/* ITM Trace Privilege Register Definitions */
#define ITM_TPR_PRIVMASK_Pos 0U /*!< ITM TPR: PRIVMASK Position */
-#define ITM_TPR_PRIVMASK_Msk (0xFUL /*<< ITM_TPR_PRIVMASK_Pos*/) /*!< ITM TPR: PRIVMASK Mask */
+#define ITM_TPR_PRIVMASK_Msk (0xFFFFFFFFUL /*<< ITM_TPR_PRIVMASK_Pos*/) /*!< ITM TPR: PRIVMASK Mask */
/* ITM Trace Control Register Definitions */
#define ITM_TCR_BUSY_Pos 23U /*!< ITM TCR: BUSY Position */
@@ -800,18 +815,6 @@ typedef struct
#define ITM_TCR_ITMENA_Pos 0U /*!< ITM TCR: ITM Enable bit Position */
#define ITM_TCR_ITMENA_Msk (1UL /*<< ITM_TCR_ITMENA_Pos*/) /*!< ITM TCR: ITM Enable bit Mask */
-/* ITM Integration Write Register Definitions */
-#define ITM_IWR_ATVALIDM_Pos 0U /*!< ITM IWR: ATVALIDM Position */
-#define ITM_IWR_ATVALIDM_Msk (1UL /*<< ITM_IWR_ATVALIDM_Pos*/) /*!< ITM IWR: ATVALIDM Mask */
-
-/* ITM Integration Read Register Definitions */
-#define ITM_IRR_ATREADYM_Pos 0U /*!< ITM IRR: ATREADYM Position */
-#define ITM_IRR_ATREADYM_Msk (1UL /*<< ITM_IRR_ATREADYM_Pos*/) /*!< ITM IRR: ATREADYM Mask */
-
-/* ITM Integration Mode Control Register Definitions */
-#define ITM_IMCR_INTEGRATION_Pos 0U /*!< ITM IMCR: INTEGRATION Position */
-#define ITM_IMCR_INTEGRATION_Msk (1UL /*<< ITM_IMCR_INTEGRATION_Pos*/) /*!< ITM IMCR: INTEGRATION Mask */
-
/* ITM Lock Status Register Definitions */
#define ITM_LSR_ByteAcc_Pos 2U /*!< ITM LSR: ByteAcc Position */
#define ITM_LSR_ByteAcc_Msk (1UL << ITM_LSR_ByteAcc_Pos) /*!< ITM LSR: ByteAcc Mask */
@@ -984,7 +987,7 @@ typedef struct
*/
typedef struct
{
- __IOM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Size Register */
+ __IM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Size Register */
__IOM uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Size Register */
uint32_t RESERVED0[2U];
__IOM uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */
@@ -995,7 +998,7 @@ typedef struct
__IOM uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */
__IM uint32_t FSCR; /*!< Offset: 0x308 (R/ ) Formatter Synchronization Counter Register */
uint32_t RESERVED3[759U];
- __IM uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER */
+ __IM uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER Register */
__IM uint32_t FIFO0; /*!< Offset: 0xEEC (R/ ) Integration ETM Data */
__IM uint32_t ITATBCTR2; /*!< Offset: 0xEF0 (R/ ) ITATBCTR2 */
uint32_t RESERVED4[1U];
@@ -1044,13 +1047,13 @@ typedef struct
/* TPI Integration ETM Data Register Definitions (FIFO0) */
#define TPI_FIFO0_ITM_ATVALID_Pos 29U /*!< TPI FIFO0: ITM_ATVALID Position */
-#define TPI_FIFO0_ITM_ATVALID_Msk (0x3UL << TPI_FIFO0_ITM_ATVALID_Pos) /*!< TPI FIFO0: ITM_ATVALID Mask */
+#define TPI_FIFO0_ITM_ATVALID_Msk (0x1UL << TPI_FIFO0_ITM_ATVALID_Pos) /*!< TPI FIFO0: ITM_ATVALID Mask */
#define TPI_FIFO0_ITM_bytecount_Pos 27U /*!< TPI FIFO0: ITM_bytecount Position */
#define TPI_FIFO0_ITM_bytecount_Msk (0x3UL << TPI_FIFO0_ITM_bytecount_Pos) /*!< TPI FIFO0: ITM_bytecount Mask */
#define TPI_FIFO0_ETM_ATVALID_Pos 26U /*!< TPI FIFO0: ETM_ATVALID Position */
-#define TPI_FIFO0_ETM_ATVALID_Msk (0x3UL << TPI_FIFO0_ETM_ATVALID_Pos) /*!< TPI FIFO0: ETM_ATVALID Mask */
+#define TPI_FIFO0_ETM_ATVALID_Msk (0x1UL << TPI_FIFO0_ETM_ATVALID_Pos) /*!< TPI FIFO0: ETM_ATVALID Mask */
#define TPI_FIFO0_ETM_bytecount_Pos 24U /*!< TPI FIFO0: ETM_bytecount Position */
#define TPI_FIFO0_ETM_bytecount_Msk (0x3UL << TPI_FIFO0_ETM_bytecount_Pos) /*!< TPI FIFO0: ETM_bytecount Mask */
@@ -1065,18 +1068,21 @@ typedef struct
#define TPI_FIFO0_ETM0_Msk (0xFFUL /*<< TPI_FIFO0_ETM0_Pos*/) /*!< TPI FIFO0: ETM0 Mask */
/* TPI ITATBCTR2 Register Definitions */
-#define TPI_ITATBCTR2_ATREADY_Pos 0U /*!< TPI ITATBCTR2: ATREADY Position */
-#define TPI_ITATBCTR2_ATREADY_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY_Pos*/) /*!< TPI ITATBCTR2: ATREADY Mask */
+#define TPI_ITATBCTR2_ATREADY2_Pos 0U /*!< TPI ITATBCTR2: ATREADY2 Position */
+#define TPI_ITATBCTR2_ATREADY2_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY2_Pos*/) /*!< TPI ITATBCTR2: ATREADY2 Mask */
+
+#define TPI_ITATBCTR2_ATREADY1_Pos 0U /*!< TPI ITATBCTR2: ATREADY1 Position */
+#define TPI_ITATBCTR2_ATREADY1_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY1_Pos*/) /*!< TPI ITATBCTR2: ATREADY1 Mask */
/* TPI Integration ITM Data Register Definitions (FIFO1) */
#define TPI_FIFO1_ITM_ATVALID_Pos 29U /*!< TPI FIFO1: ITM_ATVALID Position */
-#define TPI_FIFO1_ITM_ATVALID_Msk (0x3UL << TPI_FIFO1_ITM_ATVALID_Pos) /*!< TPI FIFO1: ITM_ATVALID Mask */
+#define TPI_FIFO1_ITM_ATVALID_Msk (0x1UL << TPI_FIFO1_ITM_ATVALID_Pos) /*!< TPI FIFO1: ITM_ATVALID Mask */
#define TPI_FIFO1_ITM_bytecount_Pos 27U /*!< TPI FIFO1: ITM_bytecount Position */
#define TPI_FIFO1_ITM_bytecount_Msk (0x3UL << TPI_FIFO1_ITM_bytecount_Pos) /*!< TPI FIFO1: ITM_bytecount Mask */
#define TPI_FIFO1_ETM_ATVALID_Pos 26U /*!< TPI FIFO1: ETM_ATVALID Position */
-#define TPI_FIFO1_ETM_ATVALID_Msk (0x3UL << TPI_FIFO1_ETM_ATVALID_Pos) /*!< TPI FIFO1: ETM_ATVALID Mask */
+#define TPI_FIFO1_ETM_ATVALID_Msk (0x1UL << TPI_FIFO1_ETM_ATVALID_Pos) /*!< TPI FIFO1: ETM_ATVALID Mask */
#define TPI_FIFO1_ETM_bytecount_Pos 24U /*!< TPI FIFO1: ETM_bytecount Position */
#define TPI_FIFO1_ETM_bytecount_Msk (0x3UL << TPI_FIFO1_ETM_bytecount_Pos) /*!< TPI FIFO1: ETM_bytecount Mask */
@@ -1091,12 +1097,15 @@ typedef struct
#define TPI_FIFO1_ITM0_Msk (0xFFUL /*<< TPI_FIFO1_ITM0_Pos*/) /*!< TPI FIFO1: ITM0 Mask */
/* TPI ITATBCTR0 Register Definitions */
-#define TPI_ITATBCTR0_ATREADY_Pos 0U /*!< TPI ITATBCTR0: ATREADY Position */
-#define TPI_ITATBCTR0_ATREADY_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY_Pos*/) /*!< TPI ITATBCTR0: ATREADY Mask */
+#define TPI_ITATBCTR0_ATREADY2_Pos 0U /*!< TPI ITATBCTR0: ATREADY2 Position */
+#define TPI_ITATBCTR0_ATREADY2_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY2_Pos*/) /*!< TPI ITATBCTR0: ATREADY2 Mask */
+
+#define TPI_ITATBCTR0_ATREADY1_Pos 0U /*!< TPI ITATBCTR0: ATREADY1 Position */
+#define TPI_ITATBCTR0_ATREADY1_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY1_Pos*/) /*!< TPI ITATBCTR0: ATREADY1 Mask */
/* TPI Integration Mode Control Register Definitions */
#define TPI_ITCTRL_Mode_Pos 0U /*!< TPI ITCTRL: Mode Position */
-#define TPI_ITCTRL_Mode_Msk (0x1UL /*<< TPI_ITCTRL_Mode_Pos*/) /*!< TPI ITCTRL: Mode Mask */
+#define TPI_ITCTRL_Mode_Msk (0x3UL /*<< TPI_ITCTRL_Mode_Pos*/) /*!< TPI ITCTRL: Mode Mask */
/* TPI DEVID Register Definitions */
#define TPI_DEVID_NRZVALID_Pos 11U /*!< TPI DEVID: NRZVALID Position */
@@ -1118,16 +1127,16 @@ typedef struct
#define TPI_DEVID_NrTraceInput_Msk (0x1FUL /*<< TPI_DEVID_NrTraceInput_Pos*/) /*!< TPI DEVID: NrTraceInput Mask */
/* TPI DEVTYPE Register Definitions */
-#define TPI_DEVTYPE_MajorType_Pos 4U /*!< TPI DEVTYPE: MajorType Position */
-#define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */
-
-#define TPI_DEVTYPE_SubType_Pos 0U /*!< TPI DEVTYPE: SubType Position */
+#define TPI_DEVTYPE_SubType_Pos 4U /*!< TPI DEVTYPE: SubType Position */
#define TPI_DEVTYPE_SubType_Msk (0xFUL /*<< TPI_DEVTYPE_SubType_Pos*/) /*!< TPI DEVTYPE: SubType Mask */
+#define TPI_DEVTYPE_MajorType_Pos 0U /*!< TPI DEVTYPE: MajorType Position */
+#define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */
+
/*@}*/ /* end of group CMSIS_TPI */
-#if (__MPU_PRESENT == 1U)
+#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U)
/**
\ingroup CMSIS_core_register
\defgroup CMSIS_MPU Memory Protection Unit (MPU)
@@ -1153,6 +1162,8 @@ typedef struct
__IOM uint32_t RASR_A3; /*!< Offset: 0x028 (R/W) MPU Alias 3 Region Attribute and Size Register */
} MPU_Type;
+#define MPU_TYPE_RALIASES 4U
+
/* MPU Type Register Definitions */
#define MPU_TYPE_IREGION_Pos 16U /*!< MPU TYPE: IREGION Position */
#define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */
@@ -1337,18 +1348,18 @@ typedef struct
/**
\brief Mask and shift a bit field value for use in a register bit range.
\param[in] field Name of the register bit field.
- \param[in] value Value of the bit field.
+ \param[in] value Value of the bit field. This parameter is interpreted as an uint32_t type.
\return Masked and shifted value.
*/
-#define _VAL2FLD(field, value) ((value << field ## _Pos) & field ## _Msk)
+#define _VAL2FLD(field, value) (((uint32_t)(value) << field ## _Pos) & field ## _Msk)
/**
\brief Mask and shift a register value to extract a bit filed value.
\param[in] field Name of the register bit field.
- \param[in] value Value of register.
+ \param[in] value Value of register. This parameter is interpreted as an uint32_t type.
\return Masked and shifted bit field value.
*/
-#define _FLD2VAL(field, value) ((value & field ## _Msk) >> field ## _Pos)
+#define _FLD2VAL(field, value) (((uint32_t)(value) & field ## _Msk) >> field ## _Pos)
/*@} end of group CMSIS_core_bitfield */
@@ -1360,7 +1371,7 @@ typedef struct
@{
*/
-/* Memory mapping of Cortex-M3 Hardware */
+/* Memory mapping of Core Hardware */
#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */
#define ITM_BASE (0xE0000000UL) /*!< ITM Base Address */
#define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */
@@ -1379,7 +1390,7 @@ typedef struct
#define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */
#define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE) /*!< Core Debug configuration struct */
-#if (__MPU_PRESENT == 1U)
+#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U)
#define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */
#define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */
#endif
@@ -1410,6 +1421,45 @@ typedef struct
@{
*/
+#ifdef CMSIS_NVIC_VIRTUAL
+ #ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE
+ #define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h"
+ #endif
+ #include CMSIS_NVIC_VIRTUAL_HEADER_FILE
+#else
+ #define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping
+ #define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping
+ #define NVIC_EnableIRQ __NVIC_EnableIRQ
+ #define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ
+ #define NVIC_DisableIRQ __NVIC_DisableIRQ
+ #define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ
+ #define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ
+ #define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ
+ #define NVIC_GetActive __NVIC_GetActive
+ #define NVIC_SetPriority __NVIC_SetPriority
+ #define NVIC_GetPriority __NVIC_GetPriority
+ #define NVIC_SystemReset __NVIC_SystemReset
+#endif /* CMSIS_NVIC_VIRTUAL */
+
+#ifdef CMSIS_VECTAB_VIRTUAL
+ #ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE
+ #define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h"
+ #endif
+ #include CMSIS_VECTAB_VIRTUAL_HEADER_FILE
+#else
+ #define NVIC_SetVector __NVIC_SetVector
+ #define NVIC_GetVector __NVIC_GetVector
+#endif /* (CMSIS_VECTAB_VIRTUAL) */
+
+#define NVIC_USER_IRQ_OFFSET 16
+
+
+/* The following EXC_RETURN values are saved the LR on exception entry */
+#define EXC_RETURN_HANDLER (0xFFFFFFF1UL) /* return to Handler mode, uses MSP after return */
+#define EXC_RETURN_THREAD_MSP (0xFFFFFFF9UL) /* return to Thread mode, uses MSP after return */
+#define EXC_RETURN_THREAD_PSP (0xFFFFFFFDUL) /* return to Thread mode, uses PSP after return */
+
+
/**
\brief Set Priority Grouping
\details Sets the priority grouping field using the required unlock sequence.
@@ -1419,7 +1469,7 @@ typedef struct
priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set.
\param [in] PriorityGroup Priority grouping field.
*/
-__STATIC_INLINE void NVIC_SetPriorityGrouping(uint32_t PriorityGroup)
+__STATIC_INLINE void __NVIC_SetPriorityGrouping(uint32_t PriorityGroup)
{
uint32_t reg_value;
uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */
@@ -1428,7 +1478,7 @@ __STATIC_INLINE void NVIC_SetPriorityGrouping(uint32_t PriorityGroup)
reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */
reg_value = (reg_value |
((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) |
- (PriorityGroupTmp << 8U) ); /* Insert write key and priorty group */
+ (PriorityGroupTmp << SCB_AIRCR_PRIGROUP_Pos) ); /* Insert write key and priority group */
SCB->AIRCR = reg_value;
}
@@ -1438,121 +1488,178 @@ __STATIC_INLINE void NVIC_SetPriorityGrouping(uint32_t PriorityGroup)
\details Reads the priority grouping field from the NVIC Interrupt Controller.
\return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field).
*/
-__STATIC_INLINE uint32_t NVIC_GetPriorityGrouping(void)
+__STATIC_INLINE uint32_t __NVIC_GetPriorityGrouping(void)
{
return ((uint32_t)((SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos));
}
/**
- \brief Enable External Interrupt
- \details Enables a device-specific interrupt in the NVIC interrupt controller.
- \param [in] IRQn External interrupt number. Value cannot be negative.
+ \brief Enable Interrupt
+ \details Enables a device specific interrupt in the NVIC interrupt controller.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
*/
-__STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn)
+__STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn)
{
- NVIC->ISER[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL));
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
}
/**
- \brief Disable External Interrupt
- \details Disables a device-specific interrupt in the NVIC interrupt controller.
- \param [in] IRQn External interrupt number. Value cannot be negative.
+ \brief Get Interrupt Enable status
+ \details Returns a device specific interrupt enable status from the NVIC interrupt controller.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 Interrupt is not enabled.
+ \return 1 Interrupt is enabled.
+ \note IRQn must not be negative.
*/
-__STATIC_INLINE void NVIC_DisableIRQ(IRQn_Type IRQn)
+__STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn)
{
- NVIC->ICER[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL));
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Disable Interrupt
+ \details Disables a device specific interrupt in the NVIC interrupt controller.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ICER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ __DSB();
+ __ISB();
+ }
}
/**
\brief Get Pending Interrupt
- \details Reads the pending register in the NVIC and returns the pending bit for the specified interrupt.
- \param [in] IRQn Interrupt number.
+ \details Reads the NVIC pending register and returns the pending bit for the specified device specific interrupt.
+ \param [in] IRQn Device specific interrupt number.
\return 0 Interrupt status is not pending.
\return 1 Interrupt status is pending.
+ \note IRQn must not be negative.
*/
-__STATIC_INLINE uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn)
+__STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn)
{
- return((uint32_t)(((NVIC->ISPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
}
/**
\brief Set Pending Interrupt
- \details Sets the pending bit of an external interrupt.
- \param [in] IRQn Interrupt number. Value cannot be negative.
+ \details Sets the pending bit of a device specific interrupt in the NVIC pending register.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
*/
-__STATIC_INLINE void NVIC_SetPendingIRQ(IRQn_Type IRQn)
+__STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn)
{
- NVIC->ISPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL));
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
}
/**
\brief Clear Pending Interrupt
- \details Clears the pending bit of an external interrupt.
- \param [in] IRQn External interrupt number. Value cannot be negative.
+ \details Clears the pending bit of a device specific interrupt in the NVIC pending register.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
*/
-__STATIC_INLINE void NVIC_ClearPendingIRQ(IRQn_Type IRQn)
+__STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn)
{
- NVIC->ICPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL));
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
}
/**
\brief Get Active Interrupt
- \details Reads the active register in NVIC and returns the active bit.
- \param [in] IRQn Interrupt number.
+ \details Reads the active register in the NVIC and returns the active bit for the device specific interrupt.
+ \param [in] IRQn Device specific interrupt number.
\return 0 Interrupt status is not active.
\return 1 Interrupt status is active.
+ \note IRQn must not be negative.
*/
-__STATIC_INLINE uint32_t NVIC_GetActive(IRQn_Type IRQn)
+__STATIC_INLINE uint32_t __NVIC_GetActive(IRQn_Type IRQn)
{
- return((uint32_t)(((NVIC->IABR[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC->IABR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
}
/**
\brief Set Interrupt Priority
- \details Sets the priority of an interrupt.
- \note The priority cannot be set for every core interrupt.
+ \details Sets the priority of a device specific interrupt or a processor exception.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
\param [in] IRQn Interrupt number.
\param [in] priority Priority to set.
+ \note The priority cannot be set for every processor exception.
*/
-__STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
+__STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
{
- if ((int32_t)(IRQn) < 0)
+ if ((int32_t)(IRQn) >= 0)
{
- SCB->SHP[(((uint32_t)(int32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL);
+ NVIC->IP[((uint32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL);
}
else
{
- NVIC->IP[((uint32_t)(int32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL);
+ SCB->SHP[(((uint32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL);
}
}
/**
\brief Get Interrupt Priority
- \details Reads the priority of an interrupt.
- The interrupt number can be positive to specify an external (device specific) interrupt,
- or negative to specify an internal (core) interrupt.
+ \details Reads the priority of a device specific interrupt or a processor exception.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
\param [in] IRQn Interrupt number.
\return Interrupt Priority.
Value is aligned automatically to the implemented priority bits of the microcontroller.
*/
-__STATIC_INLINE uint32_t NVIC_GetPriority(IRQn_Type IRQn)
+__STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn)
{
- if ((int32_t)(IRQn) < 0)
+ if ((int32_t)(IRQn) >= 0)
{
- return(((uint32_t)SCB->SHP[(((uint32_t)(int32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS)));
+ return(((uint32_t)NVIC->IP[((uint32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS)));
}
else
{
- return(((uint32_t)NVIC->IP[((uint32_t)(int32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS)));
+ return(((uint32_t)SCB->SHP[(((uint32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS)));
}
}
@@ -1609,11 +1716,42 @@ __STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGr
}
+/**
+ \brief Set Interrupt Vector
+ \details Sets an interrupt vector in SRAM based interrupt vector table.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ VTOR must been relocated to SRAM before.
+ \param [in] IRQn Interrupt number
+ \param [in] vector Address of interrupt handler function
+ */
+__STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector)
+{
+ uint32_t vectors = (uint32_t )SCB->VTOR;
+ (* (int *) (vectors + ((int32_t)IRQn + NVIC_USER_IRQ_OFFSET) * 4)) = vector;
+}
+
+
+/**
+ \brief Get Interrupt Vector
+ \details Reads an interrupt vector from interrupt vector table.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ \param [in] IRQn Interrupt number.
+ \return Address of interrupt handler function
+ */
+__STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn)
+{
+ uint32_t vectors = (uint32_t )SCB->VTOR;
+ return (uint32_t)(* (int *) (vectors + ((int32_t)IRQn + NVIC_USER_IRQ_OFFSET) * 4));
+}
+
+
/**
\brief System Reset
\details Initiates a system reset request to reset the MCU.
*/
-__STATIC_INLINE void NVIC_SystemReset(void)
+__NO_RETURN __STATIC_INLINE void __NVIC_SystemReset(void)
{
__DSB(); /* Ensure all outstanding memory accesses included
buffered write are completed before reset */
@@ -1630,6 +1768,39 @@ __STATIC_INLINE void NVIC_SystemReset(void)
/*@} end of CMSIS_Core_NVICFunctions */
+/* ########################## MPU functions #################################### */
+
+#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U)
+
+#include "mpu_armv7.h"
+
+#endif
+
+
+/* ########################## FPU functions #################################### */
+/**
+ \ingroup CMSIS_Core_FunctionInterface
+ \defgroup CMSIS_Core_FpuFunctions FPU Functions
+ \brief Function that provides FPU type.
+ @{
+ */
+
+/**
+ \brief get FPU type
+ \details returns the FPU type
+ \returns
+ - \b 0: No FPU
+ - \b 1: Single precision FPU
+ - \b 2: Double + Single precision FPU
+ */
+__STATIC_INLINE uint32_t SCB_GetFPUType(void)
+{
+ return 0U; /* No FPU */
+}
+
+
+/*@} end of CMSIS_Core_FpuFunctions */
+
/* ################################## SysTick function ############################################ */
@@ -1640,7 +1811,7 @@ __STATIC_INLINE void NVIC_SystemReset(void)
@{
*/
-#if (__Vendor_SysTickConfig == 0U)
+#if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U)
/**
\brief System Tick Configuration
@@ -1683,8 +1854,8 @@ __STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)
@{
*/
-extern volatile int32_t ITM_RxBuffer; /*!< External variable to receive characters. */
-#define ITM_RXBUFFER_EMPTY 0x5AA55AA5U /*!< Value identifying \ref ITM_RxBuffer is ready for next character. */
+extern volatile int32_t ITM_RxBuffer; /*!< External variable to receive characters. */
+#define ITM_RXBUFFER_EMPTY ((int32_t)0x5AA55AA5U) /*!< Value identifying \ref ITM_RxBuffer is ready for next character. */
/**
diff --git a/lib/cmsis/inc/core_cm33.h b/lib/cmsis/inc/core_cm33.h
new file mode 100644
index 0000000000..d5d97a96f2
--- /dev/null
+++ b/lib/cmsis/inc/core_cm33.h
@@ -0,0 +1,2907 @@
+/**************************************************************************//**
+ * @file core_cm33.h
+ * @brief CMSIS Cortex-M33 Core Peripheral Access Layer Header File
+ * @version V5.1.0
+ * @date 12. November 2018
+ ******************************************************************************/
+/*
+ * Copyright (c) 2009-2018 Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#if defined ( __ICCARM__ )
+ #pragma system_include /* treat file as system include file for MISRA check */
+#elif defined (__clang__)
+ #pragma clang system_header /* treat file as system include file */
+#endif
+
+#ifndef __CORE_CM33_H_GENERIC
+#define __CORE_CM33_H_GENERIC
+
+#include
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/**
+ \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions
+ CMSIS violates the following MISRA-C:2004 rules:
+
+ \li Required Rule 8.5, object/function definition in header file.
+ Function definitions in header files are used to allow 'inlining'.
+
+ \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
+ Unions are used for effective representation of core registers.
+
+ \li Advisory Rule 19.7, Function-like macro defined.
+ Function-like macros are used to allow more efficient code.
+ */
+
+
+/*******************************************************************************
+ * CMSIS definitions
+ ******************************************************************************/
+/**
+ \ingroup Cortex_M33
+ @{
+ */
+
+#include "cmsis_version.h"
+
+/* CMSIS CM33 definitions */
+#define __CM33_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */
+#define __CM33_CMSIS_VERSION_SUB (__CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */
+#define __CM33_CMSIS_VERSION ((__CM33_CMSIS_VERSION_MAIN << 16U) | \
+ __CM33_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */
+
+#define __CORTEX_M (33U) /*!< Cortex-M Core */
+
+/** __FPU_USED indicates whether an FPU is used or not.
+ For this, __FPU_PRESENT has to be checked prior to making use of FPU specific registers and functions.
+*/
+#if defined ( __CC_ARM )
+ #if defined (__TARGET_FPU_VFP)
+ #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)
+ #define __FPU_USED 1U
+ #else
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #define __FPU_USED 0U
+ #endif
+ #else
+ #define __FPU_USED 0U
+ #endif
+
+ #if defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1U)
+ #if defined (__DSP_PRESENT) && (__DSP_PRESENT == 1U)
+ #define __DSP_USED 1U
+ #else
+ #error "Compiler generates DSP (SIMD) instructions for a devices without DSP extensions (check __DSP_PRESENT)"
+ #define __DSP_USED 0U
+ #endif
+ #else
+ #define __DSP_USED 0U
+ #endif
+
+#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
+ #if defined (__ARM_FP)
+ #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)
+ #define __FPU_USED 1U
+ #else
+ #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #define __FPU_USED 0U
+ #endif
+ #else
+ #define __FPU_USED 0U
+ #endif
+
+ #if defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1U)
+ #if defined (__DSP_PRESENT) && (__DSP_PRESENT == 1U)
+ #define __DSP_USED 1U
+ #else
+ #error "Compiler generates DSP (SIMD) instructions for a devices without DSP extensions (check __DSP_PRESENT)"
+ #define __DSP_USED 0U
+ #endif
+ #else
+ #define __DSP_USED 0U
+ #endif
+
+#elif defined ( __GNUC__ )
+ #if defined (__VFP_FP__) && !defined(__SOFTFP__)
+ #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)
+ #define __FPU_USED 1U
+ #else
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #define __FPU_USED 0U
+ #endif
+ #else
+ #define __FPU_USED 0U
+ #endif
+
+ #if defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1U)
+ #if defined (__DSP_PRESENT) && (__DSP_PRESENT == 1U)
+ #define __DSP_USED 1U
+ #else
+ #error "Compiler generates DSP (SIMD) instructions for a devices without DSP extensions (check __DSP_PRESENT)"
+ #define __DSP_USED 0U
+ #endif
+ #else
+ #define __DSP_USED 0U
+ #endif
+
+#elif defined ( __ICCARM__ )
+ #if defined (__ARMVFP__)
+ #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)
+ #define __FPU_USED 1U
+ #else
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #define __FPU_USED 0U
+ #endif
+ #else
+ #define __FPU_USED 0U
+ #endif
+
+ #if defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1U)
+ #if defined (__DSP_PRESENT) && (__DSP_PRESENT == 1U)
+ #define __DSP_USED 1U
+ #else
+ #error "Compiler generates DSP (SIMD) instructions for a devices without DSP extensions (check __DSP_PRESENT)"
+ #define __DSP_USED 0U
+ #endif
+ #else
+ #define __DSP_USED 0U
+ #endif
+
+#elif defined ( __TI_ARM__ )
+ #if defined (__TI_VFP_SUPPORT__)
+ #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)
+ #define __FPU_USED 1U
+ #else
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #define __FPU_USED 0U
+ #endif
+ #else
+ #define __FPU_USED 0U
+ #endif
+
+#elif defined ( __TASKING__ )
+ #if defined (__FPU_VFP__)
+ #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)
+ #define __FPU_USED 1U
+ #else
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #define __FPU_USED 0U
+ #endif
+ #else
+ #define __FPU_USED 0U
+ #endif
+
+#elif defined ( __CSMC__ )
+ #if ( __CSMC__ & 0x400U)
+ #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)
+ #define __FPU_USED 1U
+ #else
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #define __FPU_USED 0U
+ #endif
+ #else
+ #define __FPU_USED 0U
+ #endif
+
+#endif
+
+#include "cmsis_compiler.h" /* CMSIS compiler specific defines */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CORE_CM33_H_GENERIC */
+
+#ifndef __CMSIS_GENERIC
+
+#ifndef __CORE_CM33_H_DEPENDANT
+#define __CORE_CM33_H_DEPENDANT
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/* check device defines and use defaults */
+#if defined __CHECK_DEVICE_DEFINES
+ #ifndef __CM33_REV
+ #define __CM33_REV 0x0000U
+ #warning "__CM33_REV not defined in device header file; using default!"
+ #endif
+
+ #ifndef __FPU_PRESENT
+ #define __FPU_PRESENT 0U
+ #warning "__FPU_PRESENT not defined in device header file; using default!"
+ #endif
+
+ #ifndef __MPU_PRESENT
+ #define __MPU_PRESENT 0U
+ #warning "__MPU_PRESENT not defined in device header file; using default!"
+ #endif
+
+ #ifndef __SAUREGION_PRESENT
+ #define __SAUREGION_PRESENT 0U
+ #warning "__SAUREGION_PRESENT not defined in device header file; using default!"
+ #endif
+
+ #ifndef __DSP_PRESENT
+ #define __DSP_PRESENT 0U
+ #warning "__DSP_PRESENT not defined in device header file; using default!"
+ #endif
+
+ #ifndef __NVIC_PRIO_BITS
+ #define __NVIC_PRIO_BITS 3U
+ #warning "__NVIC_PRIO_BITS not defined in device header file; using default!"
+ #endif
+
+ #ifndef __Vendor_SysTickConfig
+ #define __Vendor_SysTickConfig 0U
+ #warning "__Vendor_SysTickConfig not defined in device header file; using default!"
+ #endif
+#endif
+
+/* IO definitions (access restrictions to peripheral registers) */
+/**
+ \defgroup CMSIS_glob_defs CMSIS Global Defines
+
+ IO Type Qualifiers are used
+ \li to specify the access to peripheral variables.
+ \li for automatic generation of peripheral register debug information.
+*/
+#ifdef __cplusplus
+ #define __I volatile /*!< Defines 'read only' permissions */
+#else
+ #define __I volatile const /*!< Defines 'read only' permissions */
+#endif
+#define __O volatile /*!< Defines 'write only' permissions */
+#define __IO volatile /*!< Defines 'read / write' permissions */
+
+/* following defines should be used for structure members */
+#define __IM volatile const /*! Defines 'read only' structure member permissions */
+#define __OM volatile /*! Defines 'write only' structure member permissions */
+#define __IOM volatile /*! Defines 'read / write' structure member permissions */
+
+/*@} end of group Cortex_M33 */
+
+
+
+/*******************************************************************************
+ * Register Abstraction
+ Core Register contain:
+ - Core Register
+ - Core NVIC Register
+ - Core SCB Register
+ - Core SysTick Register
+ - Core Debug Register
+ - Core MPU Register
+ - Core SAU Register
+ - Core FPU Register
+ ******************************************************************************/
+/**
+ \defgroup CMSIS_core_register Defines and Type Definitions
+ \brief Type definitions and defines for Cortex-M processor based devices.
+*/
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_CORE Status and Control Registers
+ \brief Core Register type definitions.
+ @{
+ */
+
+/**
+ \brief Union type to access the Application Program Status Register (APSR).
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t _reserved0:16; /*!< bit: 0..15 Reserved */
+ uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */
+ uint32_t _reserved1:7; /*!< bit: 20..26 Reserved */
+ uint32_t Q:1; /*!< bit: 27 Saturation condition flag */
+ uint32_t V:1; /*!< bit: 28 Overflow condition code flag */
+ uint32_t C:1; /*!< bit: 29 Carry condition code flag */
+ uint32_t Z:1; /*!< bit: 30 Zero condition code flag */
+ uint32_t N:1; /*!< bit: 31 Negative condition code flag */
+ } b; /*!< Structure used for bit access */
+ uint32_t w; /*!< Type used for word access */
+} APSR_Type;
+
+/* APSR Register Definitions */
+#define APSR_N_Pos 31U /*!< APSR: N Position */
+#define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */
+
+#define APSR_Z_Pos 30U /*!< APSR: Z Position */
+#define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */
+
+#define APSR_C_Pos 29U /*!< APSR: C Position */
+#define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */
+
+#define APSR_V_Pos 28U /*!< APSR: V Position */
+#define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */
+
+#define APSR_Q_Pos 27U /*!< APSR: Q Position */
+#define APSR_Q_Msk (1UL << APSR_Q_Pos) /*!< APSR: Q Mask */
+
+#define APSR_GE_Pos 16U /*!< APSR: GE Position */
+#define APSR_GE_Msk (0xFUL << APSR_GE_Pos) /*!< APSR: GE Mask */
+
+
+/**
+ \brief Union type to access the Interrupt Program Status Register (IPSR).
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */
+ uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */
+ } b; /*!< Structure used for bit access */
+ uint32_t w; /*!< Type used for word access */
+} IPSR_Type;
+
+/* IPSR Register Definitions */
+#define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */
+#define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */
+
+
+/**
+ \brief Union type to access the Special-Purpose Program Status Registers (xPSR).
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */
+ uint32_t _reserved0:7; /*!< bit: 9..15 Reserved */
+ uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */
+ uint32_t _reserved1:4; /*!< bit: 20..23 Reserved */
+ uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */
+ uint32_t IT:2; /*!< bit: 25..26 saved IT state (read 0) */
+ uint32_t Q:1; /*!< bit: 27 Saturation condition flag */
+ uint32_t V:1; /*!< bit: 28 Overflow condition code flag */
+ uint32_t C:1; /*!< bit: 29 Carry condition code flag */
+ uint32_t Z:1; /*!< bit: 30 Zero condition code flag */
+ uint32_t N:1; /*!< bit: 31 Negative condition code flag */
+ } b; /*!< Structure used for bit access */
+ uint32_t w; /*!< Type used for word access */
+} xPSR_Type;
+
+/* xPSR Register Definitions */
+#define xPSR_N_Pos 31U /*!< xPSR: N Position */
+#define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */
+
+#define xPSR_Z_Pos 30U /*!< xPSR: Z Position */
+#define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */
+
+#define xPSR_C_Pos 29U /*!< xPSR: C Position */
+#define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */
+
+#define xPSR_V_Pos 28U /*!< xPSR: V Position */
+#define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */
+
+#define xPSR_Q_Pos 27U /*!< xPSR: Q Position */
+#define xPSR_Q_Msk (1UL << xPSR_Q_Pos) /*!< xPSR: Q Mask */
+
+#define xPSR_IT_Pos 25U /*!< xPSR: IT Position */
+#define xPSR_IT_Msk (3UL << xPSR_IT_Pos) /*!< xPSR: IT Mask */
+
+#define xPSR_T_Pos 24U /*!< xPSR: T Position */
+#define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */
+
+#define xPSR_GE_Pos 16U /*!< xPSR: GE Position */
+#define xPSR_GE_Msk (0xFUL << xPSR_GE_Pos) /*!< xPSR: GE Mask */
+
+#define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */
+#define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */
+
+
+/**
+ \brief Union type to access the Control Registers (CONTROL).
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */
+ uint32_t SPSEL:1; /*!< bit: 1 Stack-pointer select */
+ uint32_t FPCA:1; /*!< bit: 2 Floating-point context active */
+ uint32_t SFPA:1; /*!< bit: 3 Secure floating-point active */
+ uint32_t _reserved1:28; /*!< bit: 4..31 Reserved */
+ } b; /*!< Structure used for bit access */
+ uint32_t w; /*!< Type used for word access */
+} CONTROL_Type;
+
+/* CONTROL Register Definitions */
+#define CONTROL_SFPA_Pos 3U /*!< CONTROL: SFPA Position */
+#define CONTROL_SFPA_Msk (1UL << CONTROL_SFPA_Pos) /*!< CONTROL: SFPA Mask */
+
+#define CONTROL_FPCA_Pos 2U /*!< CONTROL: FPCA Position */
+#define CONTROL_FPCA_Msk (1UL << CONTROL_FPCA_Pos) /*!< CONTROL: FPCA Mask */
+
+#define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */
+#define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */
+
+#define CONTROL_nPRIV_Pos 0U /*!< CONTROL: nPRIV Position */
+#define CONTROL_nPRIV_Msk (1UL /*<< CONTROL_nPRIV_Pos*/) /*!< CONTROL: nPRIV Mask */
+
+/*@} end of group CMSIS_CORE */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC)
+ \brief Type definitions for the NVIC Registers
+ @{
+ */
+
+/**
+ \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC).
+ */
+typedef struct
+{
+ __IOM uint32_t ISER[16U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */
+ uint32_t RESERVED0[16U];
+ __IOM uint32_t ICER[16U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */
+ uint32_t RSERVED1[16U];
+ __IOM uint32_t ISPR[16U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */
+ uint32_t RESERVED2[16U];
+ __IOM uint32_t ICPR[16U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */
+ uint32_t RESERVED3[16U];
+ __IOM uint32_t IABR[16U]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */
+ uint32_t RESERVED4[16U];
+ __IOM uint32_t ITNS[16U]; /*!< Offset: 0x280 (R/W) Interrupt Non-Secure State Register */
+ uint32_t RESERVED5[16U];
+ __IOM uint8_t IPR[496U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register (8Bit wide) */
+ uint32_t RESERVED6[580U];
+ __OM uint32_t STIR; /*!< Offset: 0xE00 ( /W) Software Trigger Interrupt Register */
+} NVIC_Type;
+
+/* Software Triggered Interrupt Register Definitions */
+#define NVIC_STIR_INTID_Pos 0U /*!< STIR: INTLINESNUM Position */
+#define NVIC_STIR_INTID_Msk (0x1FFUL /*<< NVIC_STIR_INTID_Pos*/) /*!< STIR: INTLINESNUM Mask */
+
+/*@} end of group CMSIS_NVIC */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_SCB System Control Block (SCB)
+ \brief Type definitions for the System Control Block Registers
+ @{
+ */
+
+/**
+ \brief Structure type to access the System Control Block (SCB).
+ */
+typedef struct
+{
+ __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */
+ __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */
+ __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */
+ __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */
+ __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */
+ __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */
+ __IOM uint8_t SHPR[12U]; /*!< Offset: 0x018 (R/W) System Handlers Priority Registers (4-7, 8-11, 12-15) */
+ __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */
+ __IOM uint32_t CFSR; /*!< Offset: 0x028 (R/W) Configurable Fault Status Register */
+ __IOM uint32_t HFSR; /*!< Offset: 0x02C (R/W) HardFault Status Register */
+ __IOM uint32_t DFSR; /*!< Offset: 0x030 (R/W) Debug Fault Status Register */
+ __IOM uint32_t MMFAR; /*!< Offset: 0x034 (R/W) MemManage Fault Address Register */
+ __IOM uint32_t BFAR; /*!< Offset: 0x038 (R/W) BusFault Address Register */
+ __IOM uint32_t AFSR; /*!< Offset: 0x03C (R/W) Auxiliary Fault Status Register */
+ __IM uint32_t ID_PFR[2U]; /*!< Offset: 0x040 (R/ ) Processor Feature Register */
+ __IM uint32_t ID_DFR; /*!< Offset: 0x048 (R/ ) Debug Feature Register */
+ __IM uint32_t ID_ADR; /*!< Offset: 0x04C (R/ ) Auxiliary Feature Register */
+ __IM uint32_t ID_MMFR[4U]; /*!< Offset: 0x050 (R/ ) Memory Model Feature Register */
+ __IM uint32_t ID_ISAR[6U]; /*!< Offset: 0x060 (R/ ) Instruction Set Attributes Register */
+ __IM uint32_t CLIDR; /*!< Offset: 0x078 (R/ ) Cache Level ID register */
+ __IM uint32_t CTR; /*!< Offset: 0x07C (R/ ) Cache Type register */
+ __IM uint32_t CCSIDR; /*!< Offset: 0x080 (R/ ) Cache Size ID Register */
+ __IOM uint32_t CSSELR; /*!< Offset: 0x084 (R/W) Cache Size Selection Register */
+ __IOM uint32_t CPACR; /*!< Offset: 0x088 (R/W) Coprocessor Access Control Register */
+ __IOM uint32_t NSACR; /*!< Offset: 0x08C (R/W) Non-Secure Access Control Register */
+ uint32_t RESERVED3[92U];
+ __OM uint32_t STIR; /*!< Offset: 0x200 ( /W) Software Triggered Interrupt Register */
+ uint32_t RESERVED4[15U];
+ __IM uint32_t MVFR0; /*!< Offset: 0x240 (R/ ) Media and VFP Feature Register 0 */
+ __IM uint32_t MVFR1; /*!< Offset: 0x244 (R/ ) Media and VFP Feature Register 1 */
+ __IM uint32_t MVFR2; /*!< Offset: 0x248 (R/ ) Media and VFP Feature Register 2 */
+ uint32_t RESERVED5[1U];
+ __OM uint32_t ICIALLU; /*!< Offset: 0x250 ( /W) I-Cache Invalidate All to PoU */
+ uint32_t RESERVED6[1U];
+ __OM uint32_t ICIMVAU; /*!< Offset: 0x258 ( /W) I-Cache Invalidate by MVA to PoU */
+ __OM uint32_t DCIMVAC; /*!< Offset: 0x25C ( /W) D-Cache Invalidate by MVA to PoC */
+ __OM uint32_t DCISW; /*!< Offset: 0x260 ( /W) D-Cache Invalidate by Set-way */
+ __OM uint32_t DCCMVAU; /*!< Offset: 0x264 ( /W) D-Cache Clean by MVA to PoU */
+ __OM uint32_t DCCMVAC; /*!< Offset: 0x268 ( /W) D-Cache Clean by MVA to PoC */
+ __OM uint32_t DCCSW; /*!< Offset: 0x26C ( /W) D-Cache Clean by Set-way */
+ __OM uint32_t DCCIMVAC; /*!< Offset: 0x270 ( /W) D-Cache Clean and Invalidate by MVA to PoC */
+ __OM uint32_t DCCISW; /*!< Offset: 0x274 ( /W) D-Cache Clean and Invalidate by Set-way */
+} SCB_Type;
+
+/* SCB CPUID Register Definitions */
+#define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */
+#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */
+
+#define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */
+#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */
+
+#define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */
+#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */
+
+#define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */
+#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */
+
+#define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */
+#define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */
+
+/* SCB Interrupt Control State Register Definitions */
+#define SCB_ICSR_PENDNMISET_Pos 31U /*!< SCB ICSR: PENDNMISET Position */
+#define SCB_ICSR_PENDNMISET_Msk (1UL << SCB_ICSR_PENDNMISET_Pos) /*!< SCB ICSR: PENDNMISET Mask */
+
+#define SCB_ICSR_NMIPENDSET_Pos SCB_ICSR_PENDNMISET_Pos /*!< SCB ICSR: NMIPENDSET Position, backward compatibility */
+#define SCB_ICSR_NMIPENDSET_Msk SCB_ICSR_PENDNMISET_Msk /*!< SCB ICSR: NMIPENDSET Mask, backward compatibility */
+
+#define SCB_ICSR_PENDNMICLR_Pos 30U /*!< SCB ICSR: PENDNMICLR Position */
+#define SCB_ICSR_PENDNMICLR_Msk (1UL << SCB_ICSR_PENDNMICLR_Pos) /*!< SCB ICSR: PENDNMICLR Mask */
+
+#define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */
+#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */
+
+#define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */
+#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */
+
+#define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */
+#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */
+
+#define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */
+#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */
+
+#define SCB_ICSR_STTNS_Pos 24U /*!< SCB ICSR: STTNS Position (Security Extension) */
+#define SCB_ICSR_STTNS_Msk (1UL << SCB_ICSR_STTNS_Pos) /*!< SCB ICSR: STTNS Mask (Security Extension) */
+
+#define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */
+#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */
+
+#define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */
+#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */
+
+#define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */
+#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */
+
+#define SCB_ICSR_RETTOBASE_Pos 11U /*!< SCB ICSR: RETTOBASE Position */
+#define SCB_ICSR_RETTOBASE_Msk (1UL << SCB_ICSR_RETTOBASE_Pos) /*!< SCB ICSR: RETTOBASE Mask */
+
+#define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */
+#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */
+
+/* SCB Vector Table Offset Register Definitions */
+#define SCB_VTOR_TBLOFF_Pos 7U /*!< SCB VTOR: TBLOFF Position */
+#define SCB_VTOR_TBLOFF_Msk (0x1FFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */
+
+/* SCB Application Interrupt and Reset Control Register Definitions */
+#define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */
+#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */
+
+#define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */
+#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */
+
+#define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */
+#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */
+
+#define SCB_AIRCR_PRIS_Pos 14U /*!< SCB AIRCR: PRIS Position */
+#define SCB_AIRCR_PRIS_Msk (1UL << SCB_AIRCR_PRIS_Pos) /*!< SCB AIRCR: PRIS Mask */
+
+#define SCB_AIRCR_BFHFNMINS_Pos 13U /*!< SCB AIRCR: BFHFNMINS Position */
+#define SCB_AIRCR_BFHFNMINS_Msk (1UL << SCB_AIRCR_BFHFNMINS_Pos) /*!< SCB AIRCR: BFHFNMINS Mask */
+
+#define SCB_AIRCR_PRIGROUP_Pos 8U /*!< SCB AIRCR: PRIGROUP Position */
+#define SCB_AIRCR_PRIGROUP_Msk (7UL << SCB_AIRCR_PRIGROUP_Pos) /*!< SCB AIRCR: PRIGROUP Mask */
+
+#define SCB_AIRCR_SYSRESETREQS_Pos 3U /*!< SCB AIRCR: SYSRESETREQS Position */
+#define SCB_AIRCR_SYSRESETREQS_Msk (1UL << SCB_AIRCR_SYSRESETREQS_Pos) /*!< SCB AIRCR: SYSRESETREQS Mask */
+
+#define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */
+#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */
+
+#define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */
+#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */
+
+/* SCB System Control Register Definitions */
+#define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */
+#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */
+
+#define SCB_SCR_SLEEPDEEPS_Pos 3U /*!< SCB SCR: SLEEPDEEPS Position */
+#define SCB_SCR_SLEEPDEEPS_Msk (1UL << SCB_SCR_SLEEPDEEPS_Pos) /*!< SCB SCR: SLEEPDEEPS Mask */
+
+#define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */
+#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */
+
+#define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */
+#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */
+
+/* SCB Configuration Control Register Definitions */
+#define SCB_CCR_BP_Pos 18U /*!< SCB CCR: BP Position */
+#define SCB_CCR_BP_Msk (1UL << SCB_CCR_BP_Pos) /*!< SCB CCR: BP Mask */
+
+#define SCB_CCR_IC_Pos 17U /*!< SCB CCR: IC Position */
+#define SCB_CCR_IC_Msk (1UL << SCB_CCR_IC_Pos) /*!< SCB CCR: IC Mask */
+
+#define SCB_CCR_DC_Pos 16U /*!< SCB CCR: DC Position */
+#define SCB_CCR_DC_Msk (1UL << SCB_CCR_DC_Pos) /*!< SCB CCR: DC Mask */
+
+#define SCB_CCR_STKOFHFNMIGN_Pos 10U /*!< SCB CCR: STKOFHFNMIGN Position */
+#define SCB_CCR_STKOFHFNMIGN_Msk (1UL << SCB_CCR_STKOFHFNMIGN_Pos) /*!< SCB CCR: STKOFHFNMIGN Mask */
+
+#define SCB_CCR_BFHFNMIGN_Pos 8U /*!< SCB CCR: BFHFNMIGN Position */
+#define SCB_CCR_BFHFNMIGN_Msk (1UL << SCB_CCR_BFHFNMIGN_Pos) /*!< SCB CCR: BFHFNMIGN Mask */
+
+#define SCB_CCR_DIV_0_TRP_Pos 4U /*!< SCB CCR: DIV_0_TRP Position */
+#define SCB_CCR_DIV_0_TRP_Msk (1UL << SCB_CCR_DIV_0_TRP_Pos) /*!< SCB CCR: DIV_0_TRP Mask */
+
+#define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */
+#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */
+
+#define SCB_CCR_USERSETMPEND_Pos 1U /*!< SCB CCR: USERSETMPEND Position */
+#define SCB_CCR_USERSETMPEND_Msk (1UL << SCB_CCR_USERSETMPEND_Pos) /*!< SCB CCR: USERSETMPEND Mask */
+
+/* SCB System Handler Control and State Register Definitions */
+#define SCB_SHCSR_HARDFAULTPENDED_Pos 21U /*!< SCB SHCSR: HARDFAULTPENDED Position */
+#define SCB_SHCSR_HARDFAULTPENDED_Msk (1UL << SCB_SHCSR_HARDFAULTPENDED_Pos) /*!< SCB SHCSR: HARDFAULTPENDED Mask */
+
+#define SCB_SHCSR_SECUREFAULTPENDED_Pos 20U /*!< SCB SHCSR: SECUREFAULTPENDED Position */
+#define SCB_SHCSR_SECUREFAULTPENDED_Msk (1UL << SCB_SHCSR_SECUREFAULTPENDED_Pos) /*!< SCB SHCSR: SECUREFAULTPENDED Mask */
+
+#define SCB_SHCSR_SECUREFAULTENA_Pos 19U /*!< SCB SHCSR: SECUREFAULTENA Position */
+#define SCB_SHCSR_SECUREFAULTENA_Msk (1UL << SCB_SHCSR_SECUREFAULTENA_Pos) /*!< SCB SHCSR: SECUREFAULTENA Mask */
+
+#define SCB_SHCSR_USGFAULTENA_Pos 18U /*!< SCB SHCSR: USGFAULTENA Position */
+#define SCB_SHCSR_USGFAULTENA_Msk (1UL << SCB_SHCSR_USGFAULTENA_Pos) /*!< SCB SHCSR: USGFAULTENA Mask */
+
+#define SCB_SHCSR_BUSFAULTENA_Pos 17U /*!< SCB SHCSR: BUSFAULTENA Position */
+#define SCB_SHCSR_BUSFAULTENA_Msk (1UL << SCB_SHCSR_BUSFAULTENA_Pos) /*!< SCB SHCSR: BUSFAULTENA Mask */
+
+#define SCB_SHCSR_MEMFAULTENA_Pos 16U /*!< SCB SHCSR: MEMFAULTENA Position */
+#define SCB_SHCSR_MEMFAULTENA_Msk (1UL << SCB_SHCSR_MEMFAULTENA_Pos) /*!< SCB SHCSR: MEMFAULTENA Mask */
+
+#define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */
+#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */
+
+#define SCB_SHCSR_BUSFAULTPENDED_Pos 14U /*!< SCB SHCSR: BUSFAULTPENDED Position */
+#define SCB_SHCSR_BUSFAULTPENDED_Msk (1UL << SCB_SHCSR_BUSFAULTPENDED_Pos) /*!< SCB SHCSR: BUSFAULTPENDED Mask */
+
+#define SCB_SHCSR_MEMFAULTPENDED_Pos 13U /*!< SCB SHCSR: MEMFAULTPENDED Position */
+#define SCB_SHCSR_MEMFAULTPENDED_Msk (1UL << SCB_SHCSR_MEMFAULTPENDED_Pos) /*!< SCB SHCSR: MEMFAULTPENDED Mask */
+
+#define SCB_SHCSR_USGFAULTPENDED_Pos 12U /*!< SCB SHCSR: USGFAULTPENDED Position */
+#define SCB_SHCSR_USGFAULTPENDED_Msk (1UL << SCB_SHCSR_USGFAULTPENDED_Pos) /*!< SCB SHCSR: USGFAULTPENDED Mask */
+
+#define SCB_SHCSR_SYSTICKACT_Pos 11U /*!< SCB SHCSR: SYSTICKACT Position */
+#define SCB_SHCSR_SYSTICKACT_Msk (1UL << SCB_SHCSR_SYSTICKACT_Pos) /*!< SCB SHCSR: SYSTICKACT Mask */
+
+#define SCB_SHCSR_PENDSVACT_Pos 10U /*!< SCB SHCSR: PENDSVACT Position */
+#define SCB_SHCSR_PENDSVACT_Msk (1UL << SCB_SHCSR_PENDSVACT_Pos) /*!< SCB SHCSR: PENDSVACT Mask */
+
+#define SCB_SHCSR_MONITORACT_Pos 8U /*!< SCB SHCSR: MONITORACT Position */
+#define SCB_SHCSR_MONITORACT_Msk (1UL << SCB_SHCSR_MONITORACT_Pos) /*!< SCB SHCSR: MONITORACT Mask */
+
+#define SCB_SHCSR_SVCALLACT_Pos 7U /*!< SCB SHCSR: SVCALLACT Position */
+#define SCB_SHCSR_SVCALLACT_Msk (1UL << SCB_SHCSR_SVCALLACT_Pos) /*!< SCB SHCSR: SVCALLACT Mask */
+
+#define SCB_SHCSR_NMIACT_Pos 5U /*!< SCB SHCSR: NMIACT Position */
+#define SCB_SHCSR_NMIACT_Msk (1UL << SCB_SHCSR_NMIACT_Pos) /*!< SCB SHCSR: NMIACT Mask */
+
+#define SCB_SHCSR_SECUREFAULTACT_Pos 4U /*!< SCB SHCSR: SECUREFAULTACT Position */
+#define SCB_SHCSR_SECUREFAULTACT_Msk (1UL << SCB_SHCSR_SECUREFAULTACT_Pos) /*!< SCB SHCSR: SECUREFAULTACT Mask */
+
+#define SCB_SHCSR_USGFAULTACT_Pos 3U /*!< SCB SHCSR: USGFAULTACT Position */
+#define SCB_SHCSR_USGFAULTACT_Msk (1UL << SCB_SHCSR_USGFAULTACT_Pos) /*!< SCB SHCSR: USGFAULTACT Mask */
+
+#define SCB_SHCSR_HARDFAULTACT_Pos 2U /*!< SCB SHCSR: HARDFAULTACT Position */
+#define SCB_SHCSR_HARDFAULTACT_Msk (1UL << SCB_SHCSR_HARDFAULTACT_Pos) /*!< SCB SHCSR: HARDFAULTACT Mask */
+
+#define SCB_SHCSR_BUSFAULTACT_Pos 1U /*!< SCB SHCSR: BUSFAULTACT Position */
+#define SCB_SHCSR_BUSFAULTACT_Msk (1UL << SCB_SHCSR_BUSFAULTACT_Pos) /*!< SCB SHCSR: BUSFAULTACT Mask */
+
+#define SCB_SHCSR_MEMFAULTACT_Pos 0U /*!< SCB SHCSR: MEMFAULTACT Position */
+#define SCB_SHCSR_MEMFAULTACT_Msk (1UL /*<< SCB_SHCSR_MEMFAULTACT_Pos*/) /*!< SCB SHCSR: MEMFAULTACT Mask */
+
+/* SCB Configurable Fault Status Register Definitions */
+#define SCB_CFSR_USGFAULTSR_Pos 16U /*!< SCB CFSR: Usage Fault Status Register Position */
+#define SCB_CFSR_USGFAULTSR_Msk (0xFFFFUL << SCB_CFSR_USGFAULTSR_Pos) /*!< SCB CFSR: Usage Fault Status Register Mask */
+
+#define SCB_CFSR_BUSFAULTSR_Pos 8U /*!< SCB CFSR: Bus Fault Status Register Position */
+#define SCB_CFSR_BUSFAULTSR_Msk (0xFFUL << SCB_CFSR_BUSFAULTSR_Pos) /*!< SCB CFSR: Bus Fault Status Register Mask */
+
+#define SCB_CFSR_MEMFAULTSR_Pos 0U /*!< SCB CFSR: Memory Manage Fault Status Register Position */
+#define SCB_CFSR_MEMFAULTSR_Msk (0xFFUL /*<< SCB_CFSR_MEMFAULTSR_Pos*/) /*!< SCB CFSR: Memory Manage Fault Status Register Mask */
+
+/* MemManage Fault Status Register (part of SCB Configurable Fault Status Register) */
+#define SCB_CFSR_MMARVALID_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 7U) /*!< SCB CFSR (MMFSR): MMARVALID Position */
+#define SCB_CFSR_MMARVALID_Msk (1UL << SCB_CFSR_MMARVALID_Pos) /*!< SCB CFSR (MMFSR): MMARVALID Mask */
+
+#define SCB_CFSR_MLSPERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 5U) /*!< SCB CFSR (MMFSR): MLSPERR Position */
+#define SCB_CFSR_MLSPERR_Msk (1UL << SCB_CFSR_MLSPERR_Pos) /*!< SCB CFSR (MMFSR): MLSPERR Mask */
+
+#define SCB_CFSR_MSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 4U) /*!< SCB CFSR (MMFSR): MSTKERR Position */
+#define SCB_CFSR_MSTKERR_Msk (1UL << SCB_CFSR_MSTKERR_Pos) /*!< SCB CFSR (MMFSR): MSTKERR Mask */
+
+#define SCB_CFSR_MUNSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 3U) /*!< SCB CFSR (MMFSR): MUNSTKERR Position */
+#define SCB_CFSR_MUNSTKERR_Msk (1UL << SCB_CFSR_MUNSTKERR_Pos) /*!< SCB CFSR (MMFSR): MUNSTKERR Mask */
+
+#define SCB_CFSR_DACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 1U) /*!< SCB CFSR (MMFSR): DACCVIOL Position */
+#define SCB_CFSR_DACCVIOL_Msk (1UL << SCB_CFSR_DACCVIOL_Pos) /*!< SCB CFSR (MMFSR): DACCVIOL Mask */
+
+#define SCB_CFSR_IACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 0U) /*!< SCB CFSR (MMFSR): IACCVIOL Position */
+#define SCB_CFSR_IACCVIOL_Msk (1UL /*<< SCB_CFSR_IACCVIOL_Pos*/) /*!< SCB CFSR (MMFSR): IACCVIOL Mask */
+
+/* BusFault Status Register (part of SCB Configurable Fault Status Register) */
+#define SCB_CFSR_BFARVALID_Pos (SCB_CFSR_BUSFAULTSR_Pos + 7U) /*!< SCB CFSR (BFSR): BFARVALID Position */
+#define SCB_CFSR_BFARVALID_Msk (1UL << SCB_CFSR_BFARVALID_Pos) /*!< SCB CFSR (BFSR): BFARVALID Mask */
+
+#define SCB_CFSR_LSPERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 5U) /*!< SCB CFSR (BFSR): LSPERR Position */
+#define SCB_CFSR_LSPERR_Msk (1UL << SCB_CFSR_LSPERR_Pos) /*!< SCB CFSR (BFSR): LSPERR Mask */
+
+#define SCB_CFSR_STKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 4U) /*!< SCB CFSR (BFSR): STKERR Position */
+#define SCB_CFSR_STKERR_Msk (1UL << SCB_CFSR_STKERR_Pos) /*!< SCB CFSR (BFSR): STKERR Mask */
+
+#define SCB_CFSR_UNSTKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 3U) /*!< SCB CFSR (BFSR): UNSTKERR Position */
+#define SCB_CFSR_UNSTKERR_Msk (1UL << SCB_CFSR_UNSTKERR_Pos) /*!< SCB CFSR (BFSR): UNSTKERR Mask */
+
+#define SCB_CFSR_IMPRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 2U) /*!< SCB CFSR (BFSR): IMPRECISERR Position */
+#define SCB_CFSR_IMPRECISERR_Msk (1UL << SCB_CFSR_IMPRECISERR_Pos) /*!< SCB CFSR (BFSR): IMPRECISERR Mask */
+
+#define SCB_CFSR_PRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 1U) /*!< SCB CFSR (BFSR): PRECISERR Position */
+#define SCB_CFSR_PRECISERR_Msk (1UL << SCB_CFSR_PRECISERR_Pos) /*!< SCB CFSR (BFSR): PRECISERR Mask */
+
+#define SCB_CFSR_IBUSERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 0U) /*!< SCB CFSR (BFSR): IBUSERR Position */
+#define SCB_CFSR_IBUSERR_Msk (1UL << SCB_CFSR_IBUSERR_Pos) /*!< SCB CFSR (BFSR): IBUSERR Mask */
+
+/* UsageFault Status Register (part of SCB Configurable Fault Status Register) */
+#define SCB_CFSR_DIVBYZERO_Pos (SCB_CFSR_USGFAULTSR_Pos + 9U) /*!< SCB CFSR (UFSR): DIVBYZERO Position */
+#define SCB_CFSR_DIVBYZERO_Msk (1UL << SCB_CFSR_DIVBYZERO_Pos) /*!< SCB CFSR (UFSR): DIVBYZERO Mask */
+
+#define SCB_CFSR_UNALIGNED_Pos (SCB_CFSR_USGFAULTSR_Pos + 8U) /*!< SCB CFSR (UFSR): UNALIGNED Position */
+#define SCB_CFSR_UNALIGNED_Msk (1UL << SCB_CFSR_UNALIGNED_Pos) /*!< SCB CFSR (UFSR): UNALIGNED Mask */
+
+#define SCB_CFSR_STKOF_Pos (SCB_CFSR_USGFAULTSR_Pos + 4U) /*!< SCB CFSR (UFSR): STKOF Position */
+#define SCB_CFSR_STKOF_Msk (1UL << SCB_CFSR_STKOF_Pos) /*!< SCB CFSR (UFSR): STKOF Mask */
+
+#define SCB_CFSR_NOCP_Pos (SCB_CFSR_USGFAULTSR_Pos + 3U) /*!< SCB CFSR (UFSR): NOCP Position */
+#define SCB_CFSR_NOCP_Msk (1UL << SCB_CFSR_NOCP_Pos) /*!< SCB CFSR (UFSR): NOCP Mask */
+
+#define SCB_CFSR_INVPC_Pos (SCB_CFSR_USGFAULTSR_Pos + 2U) /*!< SCB CFSR (UFSR): INVPC Position */
+#define SCB_CFSR_INVPC_Msk (1UL << SCB_CFSR_INVPC_Pos) /*!< SCB CFSR (UFSR): INVPC Mask */
+
+#define SCB_CFSR_INVSTATE_Pos (SCB_CFSR_USGFAULTSR_Pos + 1U) /*!< SCB CFSR (UFSR): INVSTATE Position */
+#define SCB_CFSR_INVSTATE_Msk (1UL << SCB_CFSR_INVSTATE_Pos) /*!< SCB CFSR (UFSR): INVSTATE Mask */
+
+#define SCB_CFSR_UNDEFINSTR_Pos (SCB_CFSR_USGFAULTSR_Pos + 0U) /*!< SCB CFSR (UFSR): UNDEFINSTR Position */
+#define SCB_CFSR_UNDEFINSTR_Msk (1UL << SCB_CFSR_UNDEFINSTR_Pos) /*!< SCB CFSR (UFSR): UNDEFINSTR Mask */
+
+/* SCB Hard Fault Status Register Definitions */
+#define SCB_HFSR_DEBUGEVT_Pos 31U /*!< SCB HFSR: DEBUGEVT Position */
+#define SCB_HFSR_DEBUGEVT_Msk (1UL << SCB_HFSR_DEBUGEVT_Pos) /*!< SCB HFSR: DEBUGEVT Mask */
+
+#define SCB_HFSR_FORCED_Pos 30U /*!< SCB HFSR: FORCED Position */
+#define SCB_HFSR_FORCED_Msk (1UL << SCB_HFSR_FORCED_Pos) /*!< SCB HFSR: FORCED Mask */
+
+#define SCB_HFSR_VECTTBL_Pos 1U /*!< SCB HFSR: VECTTBL Position */
+#define SCB_HFSR_VECTTBL_Msk (1UL << SCB_HFSR_VECTTBL_Pos) /*!< SCB HFSR: VECTTBL Mask */
+
+/* SCB Debug Fault Status Register Definitions */
+#define SCB_DFSR_EXTERNAL_Pos 4U /*!< SCB DFSR: EXTERNAL Position */
+#define SCB_DFSR_EXTERNAL_Msk (1UL << SCB_DFSR_EXTERNAL_Pos) /*!< SCB DFSR: EXTERNAL Mask */
+
+#define SCB_DFSR_VCATCH_Pos 3U /*!< SCB DFSR: VCATCH Position */
+#define SCB_DFSR_VCATCH_Msk (1UL << SCB_DFSR_VCATCH_Pos) /*!< SCB DFSR: VCATCH Mask */
+
+#define SCB_DFSR_DWTTRAP_Pos 2U /*!< SCB DFSR: DWTTRAP Position */
+#define SCB_DFSR_DWTTRAP_Msk (1UL << SCB_DFSR_DWTTRAP_Pos) /*!< SCB DFSR: DWTTRAP Mask */
+
+#define SCB_DFSR_BKPT_Pos 1U /*!< SCB DFSR: BKPT Position */
+#define SCB_DFSR_BKPT_Msk (1UL << SCB_DFSR_BKPT_Pos) /*!< SCB DFSR: BKPT Mask */
+
+#define SCB_DFSR_HALTED_Pos 0U /*!< SCB DFSR: HALTED Position */
+#define SCB_DFSR_HALTED_Msk (1UL /*<< SCB_DFSR_HALTED_Pos*/) /*!< SCB DFSR: HALTED Mask */
+
+/* SCB Non-Secure Access Control Register Definitions */
+#define SCB_NSACR_CP11_Pos 11U /*!< SCB NSACR: CP11 Position */
+#define SCB_NSACR_CP11_Msk (1UL << SCB_NSACR_CP11_Pos) /*!< SCB NSACR: CP11 Mask */
+
+#define SCB_NSACR_CP10_Pos 10U /*!< SCB NSACR: CP10 Position */
+#define SCB_NSACR_CP10_Msk (1UL << SCB_NSACR_CP10_Pos) /*!< SCB NSACR: CP10 Mask */
+
+#define SCB_NSACR_CPn_Pos 0U /*!< SCB NSACR: CPn Position */
+#define SCB_NSACR_CPn_Msk (1UL /*<< SCB_NSACR_CPn_Pos*/) /*!< SCB NSACR: CPn Mask */
+
+/* SCB Cache Level ID Register Definitions */
+#define SCB_CLIDR_LOUU_Pos 27U /*!< SCB CLIDR: LoUU Position */
+#define SCB_CLIDR_LOUU_Msk (7UL << SCB_CLIDR_LOUU_Pos) /*!< SCB CLIDR: LoUU Mask */
+
+#define SCB_CLIDR_LOC_Pos 24U /*!< SCB CLIDR: LoC Position */
+#define SCB_CLIDR_LOC_Msk (7UL << SCB_CLIDR_LOC_Pos) /*!< SCB CLIDR: LoC Mask */
+
+/* SCB Cache Type Register Definitions */
+#define SCB_CTR_FORMAT_Pos 29U /*!< SCB CTR: Format Position */
+#define SCB_CTR_FORMAT_Msk (7UL << SCB_CTR_FORMAT_Pos) /*!< SCB CTR: Format Mask */
+
+#define SCB_CTR_CWG_Pos 24U /*!< SCB CTR: CWG Position */
+#define SCB_CTR_CWG_Msk (0xFUL << SCB_CTR_CWG_Pos) /*!< SCB CTR: CWG Mask */
+
+#define SCB_CTR_ERG_Pos 20U /*!< SCB CTR: ERG Position */
+#define SCB_CTR_ERG_Msk (0xFUL << SCB_CTR_ERG_Pos) /*!< SCB CTR: ERG Mask */
+
+#define SCB_CTR_DMINLINE_Pos 16U /*!< SCB CTR: DminLine Position */
+#define SCB_CTR_DMINLINE_Msk (0xFUL << SCB_CTR_DMINLINE_Pos) /*!< SCB CTR: DminLine Mask */
+
+#define SCB_CTR_IMINLINE_Pos 0U /*!< SCB CTR: ImInLine Position */
+#define SCB_CTR_IMINLINE_Msk (0xFUL /*<< SCB_CTR_IMINLINE_Pos*/) /*!< SCB CTR: ImInLine Mask */
+
+/* SCB Cache Size ID Register Definitions */
+#define SCB_CCSIDR_WT_Pos 31U /*!< SCB CCSIDR: WT Position */
+#define SCB_CCSIDR_WT_Msk (1UL << SCB_CCSIDR_WT_Pos) /*!< SCB CCSIDR: WT Mask */
+
+#define SCB_CCSIDR_WB_Pos 30U /*!< SCB CCSIDR: WB Position */
+#define SCB_CCSIDR_WB_Msk (1UL << SCB_CCSIDR_WB_Pos) /*!< SCB CCSIDR: WB Mask */
+
+#define SCB_CCSIDR_RA_Pos 29U /*!< SCB CCSIDR: RA Position */
+#define SCB_CCSIDR_RA_Msk (1UL << SCB_CCSIDR_RA_Pos) /*!< SCB CCSIDR: RA Mask */
+
+#define SCB_CCSIDR_WA_Pos 28U /*!< SCB CCSIDR: WA Position */
+#define SCB_CCSIDR_WA_Msk (1UL << SCB_CCSIDR_WA_Pos) /*!< SCB CCSIDR: WA Mask */
+
+#define SCB_CCSIDR_NUMSETS_Pos 13U /*!< SCB CCSIDR: NumSets Position */
+#define SCB_CCSIDR_NUMSETS_Msk (0x7FFFUL << SCB_CCSIDR_NUMSETS_Pos) /*!< SCB CCSIDR: NumSets Mask */
+
+#define SCB_CCSIDR_ASSOCIATIVITY_Pos 3U /*!< SCB CCSIDR: Associativity Position */
+#define SCB_CCSIDR_ASSOCIATIVITY_Msk (0x3FFUL << SCB_CCSIDR_ASSOCIATIVITY_Pos) /*!< SCB CCSIDR: Associativity Mask */
+
+#define SCB_CCSIDR_LINESIZE_Pos 0U /*!< SCB CCSIDR: LineSize Position */
+#define SCB_CCSIDR_LINESIZE_Msk (7UL /*<< SCB_CCSIDR_LINESIZE_Pos*/) /*!< SCB CCSIDR: LineSize Mask */
+
+/* SCB Cache Size Selection Register Definitions */
+#define SCB_CSSELR_LEVEL_Pos 1U /*!< SCB CSSELR: Level Position */
+#define SCB_CSSELR_LEVEL_Msk (7UL << SCB_CSSELR_LEVEL_Pos) /*!< SCB CSSELR: Level Mask */
+
+#define SCB_CSSELR_IND_Pos 0U /*!< SCB CSSELR: InD Position */
+#define SCB_CSSELR_IND_Msk (1UL /*<< SCB_CSSELR_IND_Pos*/) /*!< SCB CSSELR: InD Mask */
+
+/* SCB Software Triggered Interrupt Register Definitions */
+#define SCB_STIR_INTID_Pos 0U /*!< SCB STIR: INTID Position */
+#define SCB_STIR_INTID_Msk (0x1FFUL /*<< SCB_STIR_INTID_Pos*/) /*!< SCB STIR: INTID Mask */
+
+/* SCB D-Cache Invalidate by Set-way Register Definitions */
+#define SCB_DCISW_WAY_Pos 30U /*!< SCB DCISW: Way Position */
+#define SCB_DCISW_WAY_Msk (3UL << SCB_DCISW_WAY_Pos) /*!< SCB DCISW: Way Mask */
+
+#define SCB_DCISW_SET_Pos 5U /*!< SCB DCISW: Set Position */
+#define SCB_DCISW_SET_Msk (0x1FFUL << SCB_DCISW_SET_Pos) /*!< SCB DCISW: Set Mask */
+
+/* SCB D-Cache Clean by Set-way Register Definitions */
+#define SCB_DCCSW_WAY_Pos 30U /*!< SCB DCCSW: Way Position */
+#define SCB_DCCSW_WAY_Msk (3UL << SCB_DCCSW_WAY_Pos) /*!< SCB DCCSW: Way Mask */
+
+#define SCB_DCCSW_SET_Pos 5U /*!< SCB DCCSW: Set Position */
+#define SCB_DCCSW_SET_Msk (0x1FFUL << SCB_DCCSW_SET_Pos) /*!< SCB DCCSW: Set Mask */
+
+/* SCB D-Cache Clean and Invalidate by Set-way Register Definitions */
+#define SCB_DCCISW_WAY_Pos 30U /*!< SCB DCCISW: Way Position */
+#define SCB_DCCISW_WAY_Msk (3UL << SCB_DCCISW_WAY_Pos) /*!< SCB DCCISW: Way Mask */
+
+#define SCB_DCCISW_SET_Pos 5U /*!< SCB DCCISW: Set Position */
+#define SCB_DCCISW_SET_Msk (0x1FFUL << SCB_DCCISW_SET_Pos) /*!< SCB DCCISW: Set Mask */
+
+/*@} end of group CMSIS_SCB */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_SCnSCB System Controls not in SCB (SCnSCB)
+ \brief Type definitions for the System Control and ID Register not in the SCB
+ @{
+ */
+
+/**
+ \brief Structure type to access the System Control and ID Register not in the SCB.
+ */
+typedef struct
+{
+ uint32_t RESERVED0[1U];
+ __IM uint32_t ICTR; /*!< Offset: 0x004 (R/ ) Interrupt Controller Type Register */
+ __IOM uint32_t ACTLR; /*!< Offset: 0x008 (R/W) Auxiliary Control Register */
+ __IOM uint32_t CPPWR; /*!< Offset: 0x00C (R/W) Coprocessor Power Control Register */
+} SCnSCB_Type;
+
+/* Interrupt Controller Type Register Definitions */
+#define SCnSCB_ICTR_INTLINESNUM_Pos 0U /*!< ICTR: INTLINESNUM Position */
+#define SCnSCB_ICTR_INTLINESNUM_Msk (0xFUL /*<< SCnSCB_ICTR_INTLINESNUM_Pos*/) /*!< ICTR: INTLINESNUM Mask */
+
+/*@} end of group CMSIS_SCnotSCB */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_SysTick System Tick Timer (SysTick)
+ \brief Type definitions for the System Timer Registers.
+ @{
+ */
+
+/**
+ \brief Structure type to access the System Timer (SysTick).
+ */
+typedef struct
+{
+ __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */
+ __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */
+ __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */
+ __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */
+} SysTick_Type;
+
+/* SysTick Control / Status Register Definitions */
+#define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */
+#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */
+
+#define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */
+#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */
+
+#define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */
+#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */
+
+#define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */
+#define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */
+
+/* SysTick Reload Register Definitions */
+#define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */
+#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */
+
+/* SysTick Current Register Definitions */
+#define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */
+#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */
+
+/* SysTick Calibration Register Definitions */
+#define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */
+#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */
+
+#define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */
+#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */
+
+#define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */
+#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */
+
+/*@} end of group CMSIS_SysTick */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_ITM Instrumentation Trace Macrocell (ITM)
+ \brief Type definitions for the Instrumentation Trace Macrocell (ITM)
+ @{
+ */
+
+/**
+ \brief Structure type to access the Instrumentation Trace Macrocell Register (ITM).
+ */
+typedef struct
+{
+ __OM union
+ {
+ __OM uint8_t u8; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 8-bit */
+ __OM uint16_t u16; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 16-bit */
+ __OM uint32_t u32; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 32-bit */
+ } PORT [32U]; /*!< Offset: 0x000 ( /W) ITM Stimulus Port Registers */
+ uint32_t RESERVED0[864U];
+ __IOM uint32_t TER; /*!< Offset: 0xE00 (R/W) ITM Trace Enable Register */
+ uint32_t RESERVED1[15U];
+ __IOM uint32_t TPR; /*!< Offset: 0xE40 (R/W) ITM Trace Privilege Register */
+ uint32_t RESERVED2[15U];
+ __IOM uint32_t TCR; /*!< Offset: 0xE80 (R/W) ITM Trace Control Register */
+ uint32_t RESERVED3[32U];
+ uint32_t RESERVED4[43U];
+ __OM uint32_t LAR; /*!< Offset: 0xFB0 ( /W) ITM Lock Access Register */
+ __IM uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) ITM Lock Status Register */
+ uint32_t RESERVED5[1U];
+ __IM uint32_t DEVARCH; /*!< Offset: 0xFBC (R/ ) ITM Device Architecture Register */
+ uint32_t RESERVED6[4U];
+ __IM uint32_t PID4; /*!< Offset: 0xFD0 (R/ ) ITM Peripheral Identification Register #4 */
+ __IM uint32_t PID5; /*!< Offset: 0xFD4 (R/ ) ITM Peripheral Identification Register #5 */
+ __IM uint32_t PID6; /*!< Offset: 0xFD8 (R/ ) ITM Peripheral Identification Register #6 */
+ __IM uint32_t PID7; /*!< Offset: 0xFDC (R/ ) ITM Peripheral Identification Register #7 */
+ __IM uint32_t PID0; /*!< Offset: 0xFE0 (R/ ) ITM Peripheral Identification Register #0 */
+ __IM uint32_t PID1; /*!< Offset: 0xFE4 (R/ ) ITM Peripheral Identification Register #1 */
+ __IM uint32_t PID2; /*!< Offset: 0xFE8 (R/ ) ITM Peripheral Identification Register #2 */
+ __IM uint32_t PID3; /*!< Offset: 0xFEC (R/ ) ITM Peripheral Identification Register #3 */
+ __IM uint32_t CID0; /*!< Offset: 0xFF0 (R/ ) ITM Component Identification Register #0 */
+ __IM uint32_t CID1; /*!< Offset: 0xFF4 (R/ ) ITM Component Identification Register #1 */
+ __IM uint32_t CID2; /*!< Offset: 0xFF8 (R/ ) ITM Component Identification Register #2 */
+ __IM uint32_t CID3; /*!< Offset: 0xFFC (R/ ) ITM Component Identification Register #3 */
+} ITM_Type;
+
+/* ITM Stimulus Port Register Definitions */
+#define ITM_STIM_DISABLED_Pos 1U /*!< ITM STIM: DISABLED Position */
+#define ITM_STIM_DISABLED_Msk (0x1UL << ITM_STIM_DISABLED_Pos) /*!< ITM STIM: DISABLED Mask */
+
+#define ITM_STIM_FIFOREADY_Pos 0U /*!< ITM STIM: FIFOREADY Position */
+#define ITM_STIM_FIFOREADY_Msk (0x1UL /*<< ITM_STIM_FIFOREADY_Pos*/) /*!< ITM STIM: FIFOREADY Mask */
+
+/* ITM Trace Privilege Register Definitions */
+#define ITM_TPR_PRIVMASK_Pos 0U /*!< ITM TPR: PRIVMASK Position */
+#define ITM_TPR_PRIVMASK_Msk (0xFFFFFFFFUL /*<< ITM_TPR_PRIVMASK_Pos*/) /*!< ITM TPR: PRIVMASK Mask */
+
+/* ITM Trace Control Register Definitions */
+#define ITM_TCR_BUSY_Pos 23U /*!< ITM TCR: BUSY Position */
+#define ITM_TCR_BUSY_Msk (1UL << ITM_TCR_BUSY_Pos) /*!< ITM TCR: BUSY Mask */
+
+#define ITM_TCR_TRACEBUSID_Pos 16U /*!< ITM TCR: ATBID Position */
+#define ITM_TCR_TRACEBUSID_Msk (0x7FUL << ITM_TCR_TRACEBUSID_Pos) /*!< ITM TCR: ATBID Mask */
+
+#define ITM_TCR_GTSFREQ_Pos 10U /*!< ITM TCR: Global timestamp frequency Position */
+#define ITM_TCR_GTSFREQ_Msk (3UL << ITM_TCR_GTSFREQ_Pos) /*!< ITM TCR: Global timestamp frequency Mask */
+
+#define ITM_TCR_TSPRESCALE_Pos 8U /*!< ITM TCR: TSPRESCALE Position */
+#define ITM_TCR_TSPRESCALE_Msk (3UL << ITM_TCR_TSPRESCALE_Pos) /*!< ITM TCR: TSPRESCALE Mask */
+
+#define ITM_TCR_STALLENA_Pos 5U /*!< ITM TCR: STALLENA Position */
+#define ITM_TCR_STALLENA_Msk (1UL << ITM_TCR_STALLENA_Pos) /*!< ITM TCR: STALLENA Mask */
+
+#define ITM_TCR_SWOENA_Pos 4U /*!< ITM TCR: SWOENA Position */
+#define ITM_TCR_SWOENA_Msk (1UL << ITM_TCR_SWOENA_Pos) /*!< ITM TCR: SWOENA Mask */
+
+#define ITM_TCR_DWTENA_Pos 3U /*!< ITM TCR: DWTENA Position */
+#define ITM_TCR_DWTENA_Msk (1UL << ITM_TCR_DWTENA_Pos) /*!< ITM TCR: DWTENA Mask */
+
+#define ITM_TCR_SYNCENA_Pos 2U /*!< ITM TCR: SYNCENA Position */
+#define ITM_TCR_SYNCENA_Msk (1UL << ITM_TCR_SYNCENA_Pos) /*!< ITM TCR: SYNCENA Mask */
+
+#define ITM_TCR_TSENA_Pos 1U /*!< ITM TCR: TSENA Position */
+#define ITM_TCR_TSENA_Msk (1UL << ITM_TCR_TSENA_Pos) /*!< ITM TCR: TSENA Mask */
+
+#define ITM_TCR_ITMENA_Pos 0U /*!< ITM TCR: ITM Enable bit Position */
+#define ITM_TCR_ITMENA_Msk (1UL /*<< ITM_TCR_ITMENA_Pos*/) /*!< ITM TCR: ITM Enable bit Mask */
+
+/* ITM Lock Status Register Definitions */
+#define ITM_LSR_ByteAcc_Pos 2U /*!< ITM LSR: ByteAcc Position */
+#define ITM_LSR_ByteAcc_Msk (1UL << ITM_LSR_ByteAcc_Pos) /*!< ITM LSR: ByteAcc Mask */
+
+#define ITM_LSR_Access_Pos 1U /*!< ITM LSR: Access Position */
+#define ITM_LSR_Access_Msk (1UL << ITM_LSR_Access_Pos) /*!< ITM LSR: Access Mask */
+
+#define ITM_LSR_Present_Pos 0U /*!< ITM LSR: Present Position */
+#define ITM_LSR_Present_Msk (1UL /*<< ITM_LSR_Present_Pos*/) /*!< ITM LSR: Present Mask */
+
+/*@}*/ /* end of group CMSIS_ITM */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_DWT Data Watchpoint and Trace (DWT)
+ \brief Type definitions for the Data Watchpoint and Trace (DWT)
+ @{
+ */
+
+/**
+ \brief Structure type to access the Data Watchpoint and Trace Register (DWT).
+ */
+typedef struct
+{
+ __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) Control Register */
+ __IOM uint32_t CYCCNT; /*!< Offset: 0x004 (R/W) Cycle Count Register */
+ __IOM uint32_t CPICNT; /*!< Offset: 0x008 (R/W) CPI Count Register */
+ __IOM uint32_t EXCCNT; /*!< Offset: 0x00C (R/W) Exception Overhead Count Register */
+ __IOM uint32_t SLEEPCNT; /*!< Offset: 0x010 (R/W) Sleep Count Register */
+ __IOM uint32_t LSUCNT; /*!< Offset: 0x014 (R/W) LSU Count Register */
+ __IOM uint32_t FOLDCNT; /*!< Offset: 0x018 (R/W) Folded-instruction Count Register */
+ __IM uint32_t PCSR; /*!< Offset: 0x01C (R/ ) Program Counter Sample Register */
+ __IOM uint32_t COMP0; /*!< Offset: 0x020 (R/W) Comparator Register 0 */
+ uint32_t RESERVED1[1U];
+ __IOM uint32_t FUNCTION0; /*!< Offset: 0x028 (R/W) Function Register 0 */
+ uint32_t RESERVED2[1U];
+ __IOM uint32_t COMP1; /*!< Offset: 0x030 (R/W) Comparator Register 1 */
+ uint32_t RESERVED3[1U];
+ __IOM uint32_t FUNCTION1; /*!< Offset: 0x038 (R/W) Function Register 1 */
+ uint32_t RESERVED4[1U];
+ __IOM uint32_t COMP2; /*!< Offset: 0x040 (R/W) Comparator Register 2 */
+ uint32_t RESERVED5[1U];
+ __IOM uint32_t FUNCTION2; /*!< Offset: 0x048 (R/W) Function Register 2 */
+ uint32_t RESERVED6[1U];
+ __IOM uint32_t COMP3; /*!< Offset: 0x050 (R/W) Comparator Register 3 */
+ uint32_t RESERVED7[1U];
+ __IOM uint32_t FUNCTION3; /*!< Offset: 0x058 (R/W) Function Register 3 */
+ uint32_t RESERVED8[1U];
+ __IOM uint32_t COMP4; /*!< Offset: 0x060 (R/W) Comparator Register 4 */
+ uint32_t RESERVED9[1U];
+ __IOM uint32_t FUNCTION4; /*!< Offset: 0x068 (R/W) Function Register 4 */
+ uint32_t RESERVED10[1U];
+ __IOM uint32_t COMP5; /*!< Offset: 0x070 (R/W) Comparator Register 5 */
+ uint32_t RESERVED11[1U];
+ __IOM uint32_t FUNCTION5; /*!< Offset: 0x078 (R/W) Function Register 5 */
+ uint32_t RESERVED12[1U];
+ __IOM uint32_t COMP6; /*!< Offset: 0x080 (R/W) Comparator Register 6 */
+ uint32_t RESERVED13[1U];
+ __IOM uint32_t FUNCTION6; /*!< Offset: 0x088 (R/W) Function Register 6 */
+ uint32_t RESERVED14[1U];
+ __IOM uint32_t COMP7; /*!< Offset: 0x090 (R/W) Comparator Register 7 */
+ uint32_t RESERVED15[1U];
+ __IOM uint32_t FUNCTION7; /*!< Offset: 0x098 (R/W) Function Register 7 */
+ uint32_t RESERVED16[1U];
+ __IOM uint32_t COMP8; /*!< Offset: 0x0A0 (R/W) Comparator Register 8 */
+ uint32_t RESERVED17[1U];
+ __IOM uint32_t FUNCTION8; /*!< Offset: 0x0A8 (R/W) Function Register 8 */
+ uint32_t RESERVED18[1U];
+ __IOM uint32_t COMP9; /*!< Offset: 0x0B0 (R/W) Comparator Register 9 */
+ uint32_t RESERVED19[1U];
+ __IOM uint32_t FUNCTION9; /*!< Offset: 0x0B8 (R/W) Function Register 9 */
+ uint32_t RESERVED20[1U];
+ __IOM uint32_t COMP10; /*!< Offset: 0x0C0 (R/W) Comparator Register 10 */
+ uint32_t RESERVED21[1U];
+ __IOM uint32_t FUNCTION10; /*!< Offset: 0x0C8 (R/W) Function Register 10 */
+ uint32_t RESERVED22[1U];
+ __IOM uint32_t COMP11; /*!< Offset: 0x0D0 (R/W) Comparator Register 11 */
+ uint32_t RESERVED23[1U];
+ __IOM uint32_t FUNCTION11; /*!< Offset: 0x0D8 (R/W) Function Register 11 */
+ uint32_t RESERVED24[1U];
+ __IOM uint32_t COMP12; /*!< Offset: 0x0E0 (R/W) Comparator Register 12 */
+ uint32_t RESERVED25[1U];
+ __IOM uint32_t FUNCTION12; /*!< Offset: 0x0E8 (R/W) Function Register 12 */
+ uint32_t RESERVED26[1U];
+ __IOM uint32_t COMP13; /*!< Offset: 0x0F0 (R/W) Comparator Register 13 */
+ uint32_t RESERVED27[1U];
+ __IOM uint32_t FUNCTION13; /*!< Offset: 0x0F8 (R/W) Function Register 13 */
+ uint32_t RESERVED28[1U];
+ __IOM uint32_t COMP14; /*!< Offset: 0x100 (R/W) Comparator Register 14 */
+ uint32_t RESERVED29[1U];
+ __IOM uint32_t FUNCTION14; /*!< Offset: 0x108 (R/W) Function Register 14 */
+ uint32_t RESERVED30[1U];
+ __IOM uint32_t COMP15; /*!< Offset: 0x110 (R/W) Comparator Register 15 */
+ uint32_t RESERVED31[1U];
+ __IOM uint32_t FUNCTION15; /*!< Offset: 0x118 (R/W) Function Register 15 */
+ uint32_t RESERVED32[934U];
+ __IM uint32_t LSR; /*!< Offset: 0xFB4 (R ) Lock Status Register */
+ uint32_t RESERVED33[1U];
+ __IM uint32_t DEVARCH; /*!< Offset: 0xFBC (R/ ) Device Architecture Register */
+} DWT_Type;
+
+/* DWT Control Register Definitions */
+#define DWT_CTRL_NUMCOMP_Pos 28U /*!< DWT CTRL: NUMCOMP Position */
+#define DWT_CTRL_NUMCOMP_Msk (0xFUL << DWT_CTRL_NUMCOMP_Pos) /*!< DWT CTRL: NUMCOMP Mask */
+
+#define DWT_CTRL_NOTRCPKT_Pos 27U /*!< DWT CTRL: NOTRCPKT Position */
+#define DWT_CTRL_NOTRCPKT_Msk (0x1UL << DWT_CTRL_NOTRCPKT_Pos) /*!< DWT CTRL: NOTRCPKT Mask */
+
+#define DWT_CTRL_NOEXTTRIG_Pos 26U /*!< DWT CTRL: NOEXTTRIG Position */
+#define DWT_CTRL_NOEXTTRIG_Msk (0x1UL << DWT_CTRL_NOEXTTRIG_Pos) /*!< DWT CTRL: NOEXTTRIG Mask */
+
+#define DWT_CTRL_NOCYCCNT_Pos 25U /*!< DWT CTRL: NOCYCCNT Position */
+#define DWT_CTRL_NOCYCCNT_Msk (0x1UL << DWT_CTRL_NOCYCCNT_Pos) /*!< DWT CTRL: NOCYCCNT Mask */
+
+#define DWT_CTRL_NOPRFCNT_Pos 24U /*!< DWT CTRL: NOPRFCNT Position */
+#define DWT_CTRL_NOPRFCNT_Msk (0x1UL << DWT_CTRL_NOPRFCNT_Pos) /*!< DWT CTRL: NOPRFCNT Mask */
+
+#define DWT_CTRL_CYCDISS_Pos 23U /*!< DWT CTRL: CYCDISS Position */
+#define DWT_CTRL_CYCDISS_Msk (0x1UL << DWT_CTRL_CYCDISS_Pos) /*!< DWT CTRL: CYCDISS Mask */
+
+#define DWT_CTRL_CYCEVTENA_Pos 22U /*!< DWT CTRL: CYCEVTENA Position */
+#define DWT_CTRL_CYCEVTENA_Msk (0x1UL << DWT_CTRL_CYCEVTENA_Pos) /*!< DWT CTRL: CYCEVTENA Mask */
+
+#define DWT_CTRL_FOLDEVTENA_Pos 21U /*!< DWT CTRL: FOLDEVTENA Position */
+#define DWT_CTRL_FOLDEVTENA_Msk (0x1UL << DWT_CTRL_FOLDEVTENA_Pos) /*!< DWT CTRL: FOLDEVTENA Mask */
+
+#define DWT_CTRL_LSUEVTENA_Pos 20U /*!< DWT CTRL: LSUEVTENA Position */
+#define DWT_CTRL_LSUEVTENA_Msk (0x1UL << DWT_CTRL_LSUEVTENA_Pos) /*!< DWT CTRL: LSUEVTENA Mask */
+
+#define DWT_CTRL_SLEEPEVTENA_Pos 19U /*!< DWT CTRL: SLEEPEVTENA Position */
+#define DWT_CTRL_SLEEPEVTENA_Msk (0x1UL << DWT_CTRL_SLEEPEVTENA_Pos) /*!< DWT CTRL: SLEEPEVTENA Mask */
+
+#define DWT_CTRL_EXCEVTENA_Pos 18U /*!< DWT CTRL: EXCEVTENA Position */
+#define DWT_CTRL_EXCEVTENA_Msk (0x1UL << DWT_CTRL_EXCEVTENA_Pos) /*!< DWT CTRL: EXCEVTENA Mask */
+
+#define DWT_CTRL_CPIEVTENA_Pos 17U /*!< DWT CTRL: CPIEVTENA Position */
+#define DWT_CTRL_CPIEVTENA_Msk (0x1UL << DWT_CTRL_CPIEVTENA_Pos) /*!< DWT CTRL: CPIEVTENA Mask */
+
+#define DWT_CTRL_EXCTRCENA_Pos 16U /*!< DWT CTRL: EXCTRCENA Position */
+#define DWT_CTRL_EXCTRCENA_Msk (0x1UL << DWT_CTRL_EXCTRCENA_Pos) /*!< DWT CTRL: EXCTRCENA Mask */
+
+#define DWT_CTRL_PCSAMPLENA_Pos 12U /*!< DWT CTRL: PCSAMPLENA Position */
+#define DWT_CTRL_PCSAMPLENA_Msk (0x1UL << DWT_CTRL_PCSAMPLENA_Pos) /*!< DWT CTRL: PCSAMPLENA Mask */
+
+#define DWT_CTRL_SYNCTAP_Pos 10U /*!< DWT CTRL: SYNCTAP Position */
+#define DWT_CTRL_SYNCTAP_Msk (0x3UL << DWT_CTRL_SYNCTAP_Pos) /*!< DWT CTRL: SYNCTAP Mask */
+
+#define DWT_CTRL_CYCTAP_Pos 9U /*!< DWT CTRL: CYCTAP Position */
+#define DWT_CTRL_CYCTAP_Msk (0x1UL << DWT_CTRL_CYCTAP_Pos) /*!< DWT CTRL: CYCTAP Mask */
+
+#define DWT_CTRL_POSTINIT_Pos 5U /*!< DWT CTRL: POSTINIT Position */
+#define DWT_CTRL_POSTINIT_Msk (0xFUL << DWT_CTRL_POSTINIT_Pos) /*!< DWT CTRL: POSTINIT Mask */
+
+#define DWT_CTRL_POSTPRESET_Pos 1U /*!< DWT CTRL: POSTPRESET Position */
+#define DWT_CTRL_POSTPRESET_Msk (0xFUL << DWT_CTRL_POSTPRESET_Pos) /*!< DWT CTRL: POSTPRESET Mask */
+
+#define DWT_CTRL_CYCCNTENA_Pos 0U /*!< DWT CTRL: CYCCNTENA Position */
+#define DWT_CTRL_CYCCNTENA_Msk (0x1UL /*<< DWT_CTRL_CYCCNTENA_Pos*/) /*!< DWT CTRL: CYCCNTENA Mask */
+
+/* DWT CPI Count Register Definitions */
+#define DWT_CPICNT_CPICNT_Pos 0U /*!< DWT CPICNT: CPICNT Position */
+#define DWT_CPICNT_CPICNT_Msk (0xFFUL /*<< DWT_CPICNT_CPICNT_Pos*/) /*!< DWT CPICNT: CPICNT Mask */
+
+/* DWT Exception Overhead Count Register Definitions */
+#define DWT_EXCCNT_EXCCNT_Pos 0U /*!< DWT EXCCNT: EXCCNT Position */
+#define DWT_EXCCNT_EXCCNT_Msk (0xFFUL /*<< DWT_EXCCNT_EXCCNT_Pos*/) /*!< DWT EXCCNT: EXCCNT Mask */
+
+/* DWT Sleep Count Register Definitions */
+#define DWT_SLEEPCNT_SLEEPCNT_Pos 0U /*!< DWT SLEEPCNT: SLEEPCNT Position */
+#define DWT_SLEEPCNT_SLEEPCNT_Msk (0xFFUL /*<< DWT_SLEEPCNT_SLEEPCNT_Pos*/) /*!< DWT SLEEPCNT: SLEEPCNT Mask */
+
+/* DWT LSU Count Register Definitions */
+#define DWT_LSUCNT_LSUCNT_Pos 0U /*!< DWT LSUCNT: LSUCNT Position */
+#define DWT_LSUCNT_LSUCNT_Msk (0xFFUL /*<< DWT_LSUCNT_LSUCNT_Pos*/) /*!< DWT LSUCNT: LSUCNT Mask */
+
+/* DWT Folded-instruction Count Register Definitions */
+#define DWT_FOLDCNT_FOLDCNT_Pos 0U /*!< DWT FOLDCNT: FOLDCNT Position */
+#define DWT_FOLDCNT_FOLDCNT_Msk (0xFFUL /*<< DWT_FOLDCNT_FOLDCNT_Pos*/) /*!< DWT FOLDCNT: FOLDCNT Mask */
+
+/* DWT Comparator Function Register Definitions */
+#define DWT_FUNCTION_ID_Pos 27U /*!< DWT FUNCTION: ID Position */
+#define DWT_FUNCTION_ID_Msk (0x1FUL << DWT_FUNCTION_ID_Pos) /*!< DWT FUNCTION: ID Mask */
+
+#define DWT_FUNCTION_MATCHED_Pos 24U /*!< DWT FUNCTION: MATCHED Position */
+#define DWT_FUNCTION_MATCHED_Msk (0x1UL << DWT_FUNCTION_MATCHED_Pos) /*!< DWT FUNCTION: MATCHED Mask */
+
+#define DWT_FUNCTION_DATAVSIZE_Pos 10U /*!< DWT FUNCTION: DATAVSIZE Position */
+#define DWT_FUNCTION_DATAVSIZE_Msk (0x3UL << DWT_FUNCTION_DATAVSIZE_Pos) /*!< DWT FUNCTION: DATAVSIZE Mask */
+
+#define DWT_FUNCTION_ACTION_Pos 4U /*!< DWT FUNCTION: ACTION Position */
+#define DWT_FUNCTION_ACTION_Msk (0x1UL << DWT_FUNCTION_ACTION_Pos) /*!< DWT FUNCTION: ACTION Mask */
+
+#define DWT_FUNCTION_MATCH_Pos 0U /*!< DWT FUNCTION: MATCH Position */
+#define DWT_FUNCTION_MATCH_Msk (0xFUL /*<< DWT_FUNCTION_MATCH_Pos*/) /*!< DWT FUNCTION: MATCH Mask */
+
+/*@}*/ /* end of group CMSIS_DWT */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_TPI Trace Port Interface (TPI)
+ \brief Type definitions for the Trace Port Interface (TPI)
+ @{
+ */
+
+/**
+ \brief Structure type to access the Trace Port Interface Register (TPI).
+ */
+typedef struct
+{
+ __IM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Size Register */
+ __IOM uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Size Register */
+ uint32_t RESERVED0[2U];
+ __IOM uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */
+ uint32_t RESERVED1[55U];
+ __IOM uint32_t SPPR; /*!< Offset: 0x0F0 (R/W) Selected Pin Protocol Register */
+ uint32_t RESERVED2[131U];
+ __IM uint32_t FFSR; /*!< Offset: 0x300 (R/ ) Formatter and Flush Status Register */
+ __IOM uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */
+ __IOM uint32_t PSCR; /*!< Offset: 0x308 (R/W) Periodic Synchronization Control Register */
+ uint32_t RESERVED3[759U];
+ __IM uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER Register */
+ __IM uint32_t ITFTTD0; /*!< Offset: 0xEEC (R/ ) Integration Test FIFO Test Data 0 Register */
+ __IOM uint32_t ITATBCTR2; /*!< Offset: 0xEF0 (R/W) Integration Test ATB Control Register 2 */
+ uint32_t RESERVED4[1U];
+ __IM uint32_t ITATBCTR0; /*!< Offset: 0xEF8 (R/ ) Integration Test ATB Control Register 0 */
+ __IM uint32_t ITFTTD1; /*!< Offset: 0xEFC (R/ ) Integration Test FIFO Test Data 1 Register */
+ __IOM uint32_t ITCTRL; /*!< Offset: 0xF00 (R/W) Integration Mode Control */
+ uint32_t RESERVED5[39U];
+ __IOM uint32_t CLAIMSET; /*!< Offset: 0xFA0 (R/W) Claim tag set */
+ __IOM uint32_t CLAIMCLR; /*!< Offset: 0xFA4 (R/W) Claim tag clear */
+ uint32_t RESERVED7[8U];
+ __IM uint32_t DEVID; /*!< Offset: 0xFC8 (R/ ) Device Configuration Register */
+ __IM uint32_t DEVTYPE; /*!< Offset: 0xFCC (R/ ) Device Type Identifier Register */
+} TPI_Type;
+
+/* TPI Asynchronous Clock Prescaler Register Definitions */
+#define TPI_ACPR_PRESCALER_Pos 0U /*!< TPI ACPR: PRESCALER Position */
+#define TPI_ACPR_PRESCALER_Msk (0x1FFFUL /*<< TPI_ACPR_PRESCALER_Pos*/) /*!< TPI ACPR: PRESCALER Mask */
+
+/* TPI Selected Pin Protocol Register Definitions */
+#define TPI_SPPR_TXMODE_Pos 0U /*!< TPI SPPR: TXMODE Position */
+#define TPI_SPPR_TXMODE_Msk (0x3UL /*<< TPI_SPPR_TXMODE_Pos*/) /*!< TPI SPPR: TXMODE Mask */
+
+/* TPI Formatter and Flush Status Register Definitions */
+#define TPI_FFSR_FtNonStop_Pos 3U /*!< TPI FFSR: FtNonStop Position */
+#define TPI_FFSR_FtNonStop_Msk (0x1UL << TPI_FFSR_FtNonStop_Pos) /*!< TPI FFSR: FtNonStop Mask */
+
+#define TPI_FFSR_TCPresent_Pos 2U /*!< TPI FFSR: TCPresent Position */
+#define TPI_FFSR_TCPresent_Msk (0x1UL << TPI_FFSR_TCPresent_Pos) /*!< TPI FFSR: TCPresent Mask */
+
+#define TPI_FFSR_FtStopped_Pos 1U /*!< TPI FFSR: FtStopped Position */
+#define TPI_FFSR_FtStopped_Msk (0x1UL << TPI_FFSR_FtStopped_Pos) /*!< TPI FFSR: FtStopped Mask */
+
+#define TPI_FFSR_FlInProg_Pos 0U /*!< TPI FFSR: FlInProg Position */
+#define TPI_FFSR_FlInProg_Msk (0x1UL /*<< TPI_FFSR_FlInProg_Pos*/) /*!< TPI FFSR: FlInProg Mask */
+
+/* TPI Formatter and Flush Control Register Definitions */
+#define TPI_FFCR_TrigIn_Pos 8U /*!< TPI FFCR: TrigIn Position */
+#define TPI_FFCR_TrigIn_Msk (0x1UL << TPI_FFCR_TrigIn_Pos) /*!< TPI FFCR: TrigIn Mask */
+
+#define TPI_FFCR_FOnMan_Pos 6U /*!< TPI FFCR: FOnMan Position */
+#define TPI_FFCR_FOnMan_Msk (0x1UL << TPI_FFCR_FOnMan_Pos) /*!< TPI FFCR: FOnMan Mask */
+
+#define TPI_FFCR_EnFCont_Pos 1U /*!< TPI FFCR: EnFCont Position */
+#define TPI_FFCR_EnFCont_Msk (0x1UL << TPI_FFCR_EnFCont_Pos) /*!< TPI FFCR: EnFCont Mask */
+
+/* TPI TRIGGER Register Definitions */
+#define TPI_TRIGGER_TRIGGER_Pos 0U /*!< TPI TRIGGER: TRIGGER Position */
+#define TPI_TRIGGER_TRIGGER_Msk (0x1UL /*<< TPI_TRIGGER_TRIGGER_Pos*/) /*!< TPI TRIGGER: TRIGGER Mask */
+
+/* TPI Integration Test FIFO Test Data 0 Register Definitions */
+#define TPI_ITFTTD0_ATB_IF2_ATVALID_Pos 29U /*!< TPI ITFTTD0: ATB Interface 2 ATVALIDPosition */
+#define TPI_ITFTTD0_ATB_IF2_ATVALID_Msk (0x3UL << TPI_ITFTTD0_ATB_IF2_ATVALID_Pos) /*!< TPI ITFTTD0: ATB Interface 2 ATVALID Mask */
+
+#define TPI_ITFTTD0_ATB_IF2_bytecount_Pos 27U /*!< TPI ITFTTD0: ATB Interface 2 byte count Position */
+#define TPI_ITFTTD0_ATB_IF2_bytecount_Msk (0x3UL << TPI_ITFTTD0_ATB_IF2_bytecount_Pos) /*!< TPI ITFTTD0: ATB Interface 2 byte count Mask */
+
+#define TPI_ITFTTD0_ATB_IF1_ATVALID_Pos 26U /*!< TPI ITFTTD0: ATB Interface 1 ATVALID Position */
+#define TPI_ITFTTD0_ATB_IF1_ATVALID_Msk (0x3UL << TPI_ITFTTD0_ATB_IF1_ATVALID_Pos) /*!< TPI ITFTTD0: ATB Interface 1 ATVALID Mask */
+
+#define TPI_ITFTTD0_ATB_IF1_bytecount_Pos 24U /*!< TPI ITFTTD0: ATB Interface 1 byte count Position */
+#define TPI_ITFTTD0_ATB_IF1_bytecount_Msk (0x3UL << TPI_ITFTTD0_ATB_IF1_bytecount_Pos) /*!< TPI ITFTTD0: ATB Interface 1 byte countt Mask */
+
+#define TPI_ITFTTD0_ATB_IF1_data2_Pos 16U /*!< TPI ITFTTD0: ATB Interface 1 data2 Position */
+#define TPI_ITFTTD0_ATB_IF1_data2_Msk (0xFFUL << TPI_ITFTTD0_ATB_IF1_data1_Pos) /*!< TPI ITFTTD0: ATB Interface 1 data2 Mask */
+
+#define TPI_ITFTTD0_ATB_IF1_data1_Pos 8U /*!< TPI ITFTTD0: ATB Interface 1 data1 Position */
+#define TPI_ITFTTD0_ATB_IF1_data1_Msk (0xFFUL << TPI_ITFTTD0_ATB_IF1_data1_Pos) /*!< TPI ITFTTD0: ATB Interface 1 data1 Mask */
+
+#define TPI_ITFTTD0_ATB_IF1_data0_Pos 0U /*!< TPI ITFTTD0: ATB Interface 1 data0 Position */
+#define TPI_ITFTTD0_ATB_IF1_data0_Msk (0xFFUL /*<< TPI_ITFTTD0_ATB_IF1_data0_Pos*/) /*!< TPI ITFTTD0: ATB Interface 1 data0 Mask */
+
+/* TPI Integration Test ATB Control Register 2 Register Definitions */
+#define TPI_ITATBCTR2_AFVALID2S_Pos 1U /*!< TPI ITATBCTR2: AFVALID2S Position */
+#define TPI_ITATBCTR2_AFVALID2S_Msk (0x1UL << TPI_ITATBCTR2_AFVALID2S_Pos) /*!< TPI ITATBCTR2: AFVALID2SS Mask */
+
+#define TPI_ITATBCTR2_AFVALID1S_Pos 1U /*!< TPI ITATBCTR2: AFVALID1S Position */
+#define TPI_ITATBCTR2_AFVALID1S_Msk (0x1UL << TPI_ITATBCTR2_AFVALID1S_Pos) /*!< TPI ITATBCTR2: AFVALID1SS Mask */
+
+#define TPI_ITATBCTR2_ATREADY2S_Pos 0U /*!< TPI ITATBCTR2: ATREADY2S Position */
+#define TPI_ITATBCTR2_ATREADY2S_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY2S_Pos*/) /*!< TPI ITATBCTR2: ATREADY2S Mask */
+
+#define TPI_ITATBCTR2_ATREADY1S_Pos 0U /*!< TPI ITATBCTR2: ATREADY1S Position */
+#define TPI_ITATBCTR2_ATREADY1S_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY1S_Pos*/) /*!< TPI ITATBCTR2: ATREADY1S Mask */
+
+/* TPI Integration Test FIFO Test Data 1 Register Definitions */
+#define TPI_ITFTTD1_ATB_IF2_ATVALID_Pos 29U /*!< TPI ITFTTD1: ATB Interface 2 ATVALID Position */
+#define TPI_ITFTTD1_ATB_IF2_ATVALID_Msk (0x3UL << TPI_ITFTTD1_ATB_IF2_ATVALID_Pos) /*!< TPI ITFTTD1: ATB Interface 2 ATVALID Mask */
+
+#define TPI_ITFTTD1_ATB_IF2_bytecount_Pos 27U /*!< TPI ITFTTD1: ATB Interface 2 byte count Position */
+#define TPI_ITFTTD1_ATB_IF2_bytecount_Msk (0x3UL << TPI_ITFTTD1_ATB_IF2_bytecount_Pos) /*!< TPI ITFTTD1: ATB Interface 2 byte count Mask */
+
+#define TPI_ITFTTD1_ATB_IF1_ATVALID_Pos 26U /*!< TPI ITFTTD1: ATB Interface 1 ATVALID Position */
+#define TPI_ITFTTD1_ATB_IF1_ATVALID_Msk (0x3UL << TPI_ITFTTD1_ATB_IF1_ATVALID_Pos) /*!< TPI ITFTTD1: ATB Interface 1 ATVALID Mask */
+
+#define TPI_ITFTTD1_ATB_IF1_bytecount_Pos 24U /*!< TPI ITFTTD1: ATB Interface 1 byte count Position */
+#define TPI_ITFTTD1_ATB_IF1_bytecount_Msk (0x3UL << TPI_ITFTTD1_ATB_IF1_bytecount_Pos) /*!< TPI ITFTTD1: ATB Interface 1 byte countt Mask */
+
+#define TPI_ITFTTD1_ATB_IF2_data2_Pos 16U /*!< TPI ITFTTD1: ATB Interface 2 data2 Position */
+#define TPI_ITFTTD1_ATB_IF2_data2_Msk (0xFFUL << TPI_ITFTTD1_ATB_IF2_data1_Pos) /*!< TPI ITFTTD1: ATB Interface 2 data2 Mask */
+
+#define TPI_ITFTTD1_ATB_IF2_data1_Pos 8U /*!< TPI ITFTTD1: ATB Interface 2 data1 Position */
+#define TPI_ITFTTD1_ATB_IF2_data1_Msk (0xFFUL << TPI_ITFTTD1_ATB_IF2_data1_Pos) /*!< TPI ITFTTD1: ATB Interface 2 data1 Mask */
+
+#define TPI_ITFTTD1_ATB_IF2_data0_Pos 0U /*!< TPI ITFTTD1: ATB Interface 2 data0 Position */
+#define TPI_ITFTTD1_ATB_IF2_data0_Msk (0xFFUL /*<< TPI_ITFTTD1_ATB_IF2_data0_Pos*/) /*!< TPI ITFTTD1: ATB Interface 2 data0 Mask */
+
+/* TPI Integration Test ATB Control Register 0 Definitions */
+#define TPI_ITATBCTR0_AFVALID2S_Pos 1U /*!< TPI ITATBCTR0: AFVALID2S Position */
+#define TPI_ITATBCTR0_AFVALID2S_Msk (0x1UL << TPI_ITATBCTR0_AFVALID2S_Pos) /*!< TPI ITATBCTR0: AFVALID2SS Mask */
+
+#define TPI_ITATBCTR0_AFVALID1S_Pos 1U /*!< TPI ITATBCTR0: AFVALID1S Position */
+#define TPI_ITATBCTR0_AFVALID1S_Msk (0x1UL << TPI_ITATBCTR0_AFVALID1S_Pos) /*!< TPI ITATBCTR0: AFVALID1SS Mask */
+
+#define TPI_ITATBCTR0_ATREADY2S_Pos 0U /*!< TPI ITATBCTR0: ATREADY2S Position */
+#define TPI_ITATBCTR0_ATREADY2S_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY2S_Pos*/) /*!< TPI ITATBCTR0: ATREADY2S Mask */
+
+#define TPI_ITATBCTR0_ATREADY1S_Pos 0U /*!< TPI ITATBCTR0: ATREADY1S Position */
+#define TPI_ITATBCTR0_ATREADY1S_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY1S_Pos*/) /*!< TPI ITATBCTR0: ATREADY1S Mask */
+
+/* TPI Integration Mode Control Register Definitions */
+#define TPI_ITCTRL_Mode_Pos 0U /*!< TPI ITCTRL: Mode Position */
+#define TPI_ITCTRL_Mode_Msk (0x3UL /*<< TPI_ITCTRL_Mode_Pos*/) /*!< TPI ITCTRL: Mode Mask */
+
+/* TPI DEVID Register Definitions */
+#define TPI_DEVID_NRZVALID_Pos 11U /*!< TPI DEVID: NRZVALID Position */
+#define TPI_DEVID_NRZVALID_Msk (0x1UL << TPI_DEVID_NRZVALID_Pos) /*!< TPI DEVID: NRZVALID Mask */
+
+#define TPI_DEVID_MANCVALID_Pos 10U /*!< TPI DEVID: MANCVALID Position */
+#define TPI_DEVID_MANCVALID_Msk (0x1UL << TPI_DEVID_MANCVALID_Pos) /*!< TPI DEVID: MANCVALID Mask */
+
+#define TPI_DEVID_PTINVALID_Pos 9U /*!< TPI DEVID: PTINVALID Position */
+#define TPI_DEVID_PTINVALID_Msk (0x1UL << TPI_DEVID_PTINVALID_Pos) /*!< TPI DEVID: PTINVALID Mask */
+
+#define TPI_DEVID_FIFOSZ_Pos 6U /*!< TPI DEVID: FIFOSZ Position */
+#define TPI_DEVID_FIFOSZ_Msk (0x7UL << TPI_DEVID_FIFOSZ_Pos) /*!< TPI DEVID: FIFOSZ Mask */
+
+#define TPI_DEVID_NrTraceInput_Pos 0U /*!< TPI DEVID: NrTraceInput Position */
+#define TPI_DEVID_NrTraceInput_Msk (0x3FUL /*<< TPI_DEVID_NrTraceInput_Pos*/) /*!< TPI DEVID: NrTraceInput Mask */
+
+/* TPI DEVTYPE Register Definitions */
+#define TPI_DEVTYPE_SubType_Pos 4U /*!< TPI DEVTYPE: SubType Position */
+#define TPI_DEVTYPE_SubType_Msk (0xFUL /*<< TPI_DEVTYPE_SubType_Pos*/) /*!< TPI DEVTYPE: SubType Mask */
+
+#define TPI_DEVTYPE_MajorType_Pos 0U /*!< TPI DEVTYPE: MajorType Position */
+#define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */
+
+/*@}*/ /* end of group CMSIS_TPI */
+
+
+#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U)
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_MPU Memory Protection Unit (MPU)
+ \brief Type definitions for the Memory Protection Unit (MPU)
+ @{
+ */
+
+/**
+ \brief Structure type to access the Memory Protection Unit (MPU).
+ */
+typedef struct
+{
+ __IM uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */
+ __IOM uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */
+ __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region Number Register */
+ __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */
+ __IOM uint32_t RLAR; /*!< Offset: 0x010 (R/W) MPU Region Limit Address Register */
+ __IOM uint32_t RBAR_A1; /*!< Offset: 0x014 (R/W) MPU Region Base Address Register Alias 1 */
+ __IOM uint32_t RLAR_A1; /*!< Offset: 0x018 (R/W) MPU Region Limit Address Register Alias 1 */
+ __IOM uint32_t RBAR_A2; /*!< Offset: 0x01C (R/W) MPU Region Base Address Register Alias 2 */
+ __IOM uint32_t RLAR_A2; /*!< Offset: 0x020 (R/W) MPU Region Limit Address Register Alias 2 */
+ __IOM uint32_t RBAR_A3; /*!< Offset: 0x024 (R/W) MPU Region Base Address Register Alias 3 */
+ __IOM uint32_t RLAR_A3; /*!< Offset: 0x028 (R/W) MPU Region Limit Address Register Alias 3 */
+ uint32_t RESERVED0[1];
+ union {
+ __IOM uint32_t MAIR[2];
+ struct {
+ __IOM uint32_t MAIR0; /*!< Offset: 0x030 (R/W) MPU Memory Attribute Indirection Register 0 */
+ __IOM uint32_t MAIR1; /*!< Offset: 0x034 (R/W) MPU Memory Attribute Indirection Register 1 */
+ };
+ };
+} MPU_Type;
+
+#define MPU_TYPE_RALIASES 4U
+
+/* MPU Type Register Definitions */
+#define MPU_TYPE_IREGION_Pos 16U /*!< MPU TYPE: IREGION Position */
+#define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */
+
+#define MPU_TYPE_DREGION_Pos 8U /*!< MPU TYPE: DREGION Position */
+#define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */
+
+#define MPU_TYPE_SEPARATE_Pos 0U /*!< MPU TYPE: SEPARATE Position */
+#define MPU_TYPE_SEPARATE_Msk (1UL /*<< MPU_TYPE_SEPARATE_Pos*/) /*!< MPU TYPE: SEPARATE Mask */
+
+/* MPU Control Register Definitions */
+#define MPU_CTRL_PRIVDEFENA_Pos 2U /*!< MPU CTRL: PRIVDEFENA Position */
+#define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */
+
+#define MPU_CTRL_HFNMIENA_Pos 1U /*!< MPU CTRL: HFNMIENA Position */
+#define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */
+
+#define MPU_CTRL_ENABLE_Pos 0U /*!< MPU CTRL: ENABLE Position */
+#define MPU_CTRL_ENABLE_Msk (1UL /*<< MPU_CTRL_ENABLE_Pos*/) /*!< MPU CTRL: ENABLE Mask */
+
+/* MPU Region Number Register Definitions */
+#define MPU_RNR_REGION_Pos 0U /*!< MPU RNR: REGION Position */
+#define MPU_RNR_REGION_Msk (0xFFUL /*<< MPU_RNR_REGION_Pos*/) /*!< MPU RNR: REGION Mask */
+
+/* MPU Region Base Address Register Definitions */
+#define MPU_RBAR_BASE_Pos 5U /*!< MPU RBAR: BASE Position */
+#define MPU_RBAR_BASE_Msk (0x7FFFFFFUL << MPU_RBAR_BASE_Pos) /*!< MPU RBAR: BASE Mask */
+
+#define MPU_RBAR_SH_Pos 3U /*!< MPU RBAR: SH Position */
+#define MPU_RBAR_SH_Msk (0x3UL << MPU_RBAR_SH_Pos) /*!< MPU RBAR: SH Mask */
+
+#define MPU_RBAR_AP_Pos 1U /*!< MPU RBAR: AP Position */
+#define MPU_RBAR_AP_Msk (0x3UL << MPU_RBAR_AP_Pos) /*!< MPU RBAR: AP Mask */
+
+#define MPU_RBAR_XN_Pos 0U /*!< MPU RBAR: XN Position */
+#define MPU_RBAR_XN_Msk (01UL /*<< MPU_RBAR_XN_Pos*/) /*!< MPU RBAR: XN Mask */
+
+/* MPU Region Limit Address Register Definitions */
+#define MPU_RLAR_LIMIT_Pos 5U /*!< MPU RLAR: LIMIT Position */
+#define MPU_RLAR_LIMIT_Msk (0x7FFFFFFUL << MPU_RLAR_LIMIT_Pos) /*!< MPU RLAR: LIMIT Mask */
+
+#define MPU_RLAR_AttrIndx_Pos 1U /*!< MPU RLAR: AttrIndx Position */
+#define MPU_RLAR_AttrIndx_Msk (0x7UL << MPU_RLAR_AttrIndx_Pos) /*!< MPU RLAR: AttrIndx Mask */
+
+#define MPU_RLAR_EN_Pos 0U /*!< MPU RLAR: Region enable bit Position */
+#define MPU_RLAR_EN_Msk (1UL /*<< MPU_RLAR_EN_Pos*/) /*!< MPU RLAR: Region enable bit Disable Mask */
+
+/* MPU Memory Attribute Indirection Register 0 Definitions */
+#define MPU_MAIR0_Attr3_Pos 24U /*!< MPU MAIR0: Attr3 Position */
+#define MPU_MAIR0_Attr3_Msk (0xFFUL << MPU_MAIR0_Attr3_Pos) /*!< MPU MAIR0: Attr3 Mask */
+
+#define MPU_MAIR0_Attr2_Pos 16U /*!< MPU MAIR0: Attr2 Position */
+#define MPU_MAIR0_Attr2_Msk (0xFFUL << MPU_MAIR0_Attr2_Pos) /*!< MPU MAIR0: Attr2 Mask */
+
+#define MPU_MAIR0_Attr1_Pos 8U /*!< MPU MAIR0: Attr1 Position */
+#define MPU_MAIR0_Attr1_Msk (0xFFUL << MPU_MAIR0_Attr1_Pos) /*!< MPU MAIR0: Attr1 Mask */
+
+#define MPU_MAIR0_Attr0_Pos 0U /*!< MPU MAIR0: Attr0 Position */
+#define MPU_MAIR0_Attr0_Msk (0xFFUL /*<< MPU_MAIR0_Attr0_Pos*/) /*!< MPU MAIR0: Attr0 Mask */
+
+/* MPU Memory Attribute Indirection Register 1 Definitions */
+#define MPU_MAIR1_Attr7_Pos 24U /*!< MPU MAIR1: Attr7 Position */
+#define MPU_MAIR1_Attr7_Msk (0xFFUL << MPU_MAIR1_Attr7_Pos) /*!< MPU MAIR1: Attr7 Mask */
+
+#define MPU_MAIR1_Attr6_Pos 16U /*!< MPU MAIR1: Attr6 Position */
+#define MPU_MAIR1_Attr6_Msk (0xFFUL << MPU_MAIR1_Attr6_Pos) /*!< MPU MAIR1: Attr6 Mask */
+
+#define MPU_MAIR1_Attr5_Pos 8U /*!< MPU MAIR1: Attr5 Position */
+#define MPU_MAIR1_Attr5_Msk (0xFFUL << MPU_MAIR1_Attr5_Pos) /*!< MPU MAIR1: Attr5 Mask */
+
+#define MPU_MAIR1_Attr4_Pos 0U /*!< MPU MAIR1: Attr4 Position */
+#define MPU_MAIR1_Attr4_Msk (0xFFUL /*<< MPU_MAIR1_Attr4_Pos*/) /*!< MPU MAIR1: Attr4 Mask */
+
+/*@} end of group CMSIS_MPU */
+#endif
+
+
+#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_SAU Security Attribution Unit (SAU)
+ \brief Type definitions for the Security Attribution Unit (SAU)
+ @{
+ */
+
+/**
+ \brief Structure type to access the Security Attribution Unit (SAU).
+ */
+typedef struct
+{
+ __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SAU Control Register */
+ __IM uint32_t TYPE; /*!< Offset: 0x004 (R/ ) SAU Type Register */
+#if defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U)
+ __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) SAU Region Number Register */
+ __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) SAU Region Base Address Register */
+ __IOM uint32_t RLAR; /*!< Offset: 0x010 (R/W) SAU Region Limit Address Register */
+#else
+ uint32_t RESERVED0[3];
+#endif
+ __IOM uint32_t SFSR; /*!< Offset: 0x014 (R/W) Secure Fault Status Register */
+ __IOM uint32_t SFAR; /*!< Offset: 0x018 (R/W) Secure Fault Address Register */
+} SAU_Type;
+
+/* SAU Control Register Definitions */
+#define SAU_CTRL_ALLNS_Pos 1U /*!< SAU CTRL: ALLNS Position */
+#define SAU_CTRL_ALLNS_Msk (1UL << SAU_CTRL_ALLNS_Pos) /*!< SAU CTRL: ALLNS Mask */
+
+#define SAU_CTRL_ENABLE_Pos 0U /*!< SAU CTRL: ENABLE Position */
+#define SAU_CTRL_ENABLE_Msk (1UL /*<< SAU_CTRL_ENABLE_Pos*/) /*!< SAU CTRL: ENABLE Mask */
+
+/* SAU Type Register Definitions */
+#define SAU_TYPE_SREGION_Pos 0U /*!< SAU TYPE: SREGION Position */
+#define SAU_TYPE_SREGION_Msk (0xFFUL /*<< SAU_TYPE_SREGION_Pos*/) /*!< SAU TYPE: SREGION Mask */
+
+#if defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U)
+/* SAU Region Number Register Definitions */
+#define SAU_RNR_REGION_Pos 0U /*!< SAU RNR: REGION Position */
+#define SAU_RNR_REGION_Msk (0xFFUL /*<< SAU_RNR_REGION_Pos*/) /*!< SAU RNR: REGION Mask */
+
+/* SAU Region Base Address Register Definitions */
+#define SAU_RBAR_BADDR_Pos 5U /*!< SAU RBAR: BADDR Position */
+#define SAU_RBAR_BADDR_Msk (0x7FFFFFFUL << SAU_RBAR_BADDR_Pos) /*!< SAU RBAR: BADDR Mask */
+
+/* SAU Region Limit Address Register Definitions */
+#define SAU_RLAR_LADDR_Pos 5U /*!< SAU RLAR: LADDR Position */
+#define SAU_RLAR_LADDR_Msk (0x7FFFFFFUL << SAU_RLAR_LADDR_Pos) /*!< SAU RLAR: LADDR Mask */
+
+#define SAU_RLAR_NSC_Pos 1U /*!< SAU RLAR: NSC Position */
+#define SAU_RLAR_NSC_Msk (1UL << SAU_RLAR_NSC_Pos) /*!< SAU RLAR: NSC Mask */
+
+#define SAU_RLAR_ENABLE_Pos 0U /*!< SAU RLAR: ENABLE Position */
+#define SAU_RLAR_ENABLE_Msk (1UL /*<< SAU_RLAR_ENABLE_Pos*/) /*!< SAU RLAR: ENABLE Mask */
+
+#endif /* defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U) */
+
+/* Secure Fault Status Register Definitions */
+#define SAU_SFSR_LSERR_Pos 7U /*!< SAU SFSR: LSERR Position */
+#define SAU_SFSR_LSERR_Msk (1UL << SAU_SFSR_LSERR_Pos) /*!< SAU SFSR: LSERR Mask */
+
+#define SAU_SFSR_SFARVALID_Pos 6U /*!< SAU SFSR: SFARVALID Position */
+#define SAU_SFSR_SFARVALID_Msk (1UL << SAU_SFSR_SFARVALID_Pos) /*!< SAU SFSR: SFARVALID Mask */
+
+#define SAU_SFSR_LSPERR_Pos 5U /*!< SAU SFSR: LSPERR Position */
+#define SAU_SFSR_LSPERR_Msk (1UL << SAU_SFSR_LSPERR_Pos) /*!< SAU SFSR: LSPERR Mask */
+
+#define SAU_SFSR_INVTRAN_Pos 4U /*!< SAU SFSR: INVTRAN Position */
+#define SAU_SFSR_INVTRAN_Msk (1UL << SAU_SFSR_INVTRAN_Pos) /*!< SAU SFSR: INVTRAN Mask */
+
+#define SAU_SFSR_AUVIOL_Pos 3U /*!< SAU SFSR: AUVIOL Position */
+#define SAU_SFSR_AUVIOL_Msk (1UL << SAU_SFSR_AUVIOL_Pos) /*!< SAU SFSR: AUVIOL Mask */
+
+#define SAU_SFSR_INVER_Pos 2U /*!< SAU SFSR: INVER Position */
+#define SAU_SFSR_INVER_Msk (1UL << SAU_SFSR_INVER_Pos) /*!< SAU SFSR: INVER Mask */
+
+#define SAU_SFSR_INVIS_Pos 1U /*!< SAU SFSR: INVIS Position */
+#define SAU_SFSR_INVIS_Msk (1UL << SAU_SFSR_INVIS_Pos) /*!< SAU SFSR: INVIS Mask */
+
+#define SAU_SFSR_INVEP_Pos 0U /*!< SAU SFSR: INVEP Position */
+#define SAU_SFSR_INVEP_Msk (1UL /*<< SAU_SFSR_INVEP_Pos*/) /*!< SAU SFSR: INVEP Mask */
+
+/*@} end of group CMSIS_SAU */
+#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_FPU Floating Point Unit (FPU)
+ \brief Type definitions for the Floating Point Unit (FPU)
+ @{
+ */
+
+/**
+ \brief Structure type to access the Floating Point Unit (FPU).
+ */
+typedef struct
+{
+ uint32_t RESERVED0[1U];
+ __IOM uint32_t FPCCR; /*!< Offset: 0x004 (R/W) Floating-Point Context Control Register */
+ __IOM uint32_t FPCAR; /*!< Offset: 0x008 (R/W) Floating-Point Context Address Register */
+ __IOM uint32_t FPDSCR; /*!< Offset: 0x00C (R/W) Floating-Point Default Status Control Register */
+ __IM uint32_t MVFR0; /*!< Offset: 0x010 (R/ ) Media and FP Feature Register 0 */
+ __IM uint32_t MVFR1; /*!< Offset: 0x014 (R/ ) Media and FP Feature Register 1 */
+} FPU_Type;
+
+/* Floating-Point Context Control Register Definitions */
+#define FPU_FPCCR_ASPEN_Pos 31U /*!< FPCCR: ASPEN bit Position */
+#define FPU_FPCCR_ASPEN_Msk (1UL << FPU_FPCCR_ASPEN_Pos) /*!< FPCCR: ASPEN bit Mask */
+
+#define FPU_FPCCR_LSPEN_Pos 30U /*!< FPCCR: LSPEN Position */
+#define FPU_FPCCR_LSPEN_Msk (1UL << FPU_FPCCR_LSPEN_Pos) /*!< FPCCR: LSPEN bit Mask */
+
+#define FPU_FPCCR_LSPENS_Pos 29U /*!< FPCCR: LSPENS Position */
+#define FPU_FPCCR_LSPENS_Msk (1UL << FPU_FPCCR_LSPENS_Pos) /*!< FPCCR: LSPENS bit Mask */
+
+#define FPU_FPCCR_CLRONRET_Pos 28U /*!< FPCCR: CLRONRET Position */
+#define FPU_FPCCR_CLRONRET_Msk (1UL << FPU_FPCCR_CLRONRET_Pos) /*!< FPCCR: CLRONRET bit Mask */
+
+#define FPU_FPCCR_CLRONRETS_Pos 27U /*!< FPCCR: CLRONRETS Position */
+#define FPU_FPCCR_CLRONRETS_Msk (1UL << FPU_FPCCR_CLRONRETS_Pos) /*!< FPCCR: CLRONRETS bit Mask */
+
+#define FPU_FPCCR_TS_Pos 26U /*!< FPCCR: TS Position */
+#define FPU_FPCCR_TS_Msk (1UL << FPU_FPCCR_TS_Pos) /*!< FPCCR: TS bit Mask */
+
+#define FPU_FPCCR_UFRDY_Pos 10U /*!< FPCCR: UFRDY Position */
+#define FPU_FPCCR_UFRDY_Msk (1UL << FPU_FPCCR_UFRDY_Pos) /*!< FPCCR: UFRDY bit Mask */
+
+#define FPU_FPCCR_SPLIMVIOL_Pos 9U /*!< FPCCR: SPLIMVIOL Position */
+#define FPU_FPCCR_SPLIMVIOL_Msk (1UL << FPU_FPCCR_SPLIMVIOL_Pos) /*!< FPCCR: SPLIMVIOL bit Mask */
+
+#define FPU_FPCCR_MONRDY_Pos 8U /*!< FPCCR: MONRDY Position */
+#define FPU_FPCCR_MONRDY_Msk (1UL << FPU_FPCCR_MONRDY_Pos) /*!< FPCCR: MONRDY bit Mask */
+
+#define FPU_FPCCR_SFRDY_Pos 7U /*!< FPCCR: SFRDY Position */
+#define FPU_FPCCR_SFRDY_Msk (1UL << FPU_FPCCR_SFRDY_Pos) /*!< FPCCR: SFRDY bit Mask */
+
+#define FPU_FPCCR_BFRDY_Pos 6U /*!< FPCCR: BFRDY Position */
+#define FPU_FPCCR_BFRDY_Msk (1UL << FPU_FPCCR_BFRDY_Pos) /*!< FPCCR: BFRDY bit Mask */
+
+#define FPU_FPCCR_MMRDY_Pos 5U /*!< FPCCR: MMRDY Position */
+#define FPU_FPCCR_MMRDY_Msk (1UL << FPU_FPCCR_MMRDY_Pos) /*!< FPCCR: MMRDY bit Mask */
+
+#define FPU_FPCCR_HFRDY_Pos 4U /*!< FPCCR: HFRDY Position */
+#define FPU_FPCCR_HFRDY_Msk (1UL << FPU_FPCCR_HFRDY_Pos) /*!< FPCCR: HFRDY bit Mask */
+
+#define FPU_FPCCR_THREAD_Pos 3U /*!< FPCCR: processor mode bit Position */
+#define FPU_FPCCR_THREAD_Msk (1UL << FPU_FPCCR_THREAD_Pos) /*!< FPCCR: processor mode active bit Mask */
+
+#define FPU_FPCCR_S_Pos 2U /*!< FPCCR: Security status of the FP context bit Position */
+#define FPU_FPCCR_S_Msk (1UL << FPU_FPCCR_S_Pos) /*!< FPCCR: Security status of the FP context bit Mask */
+
+#define FPU_FPCCR_USER_Pos 1U /*!< FPCCR: privilege level bit Position */
+#define FPU_FPCCR_USER_Msk (1UL << FPU_FPCCR_USER_Pos) /*!< FPCCR: privilege level bit Mask */
+
+#define FPU_FPCCR_LSPACT_Pos 0U /*!< FPCCR: Lazy state preservation active bit Position */
+#define FPU_FPCCR_LSPACT_Msk (1UL /*<< FPU_FPCCR_LSPACT_Pos*/) /*!< FPCCR: Lazy state preservation active bit Mask */
+
+/* Floating-Point Context Address Register Definitions */
+#define FPU_FPCAR_ADDRESS_Pos 3U /*!< FPCAR: ADDRESS bit Position */
+#define FPU_FPCAR_ADDRESS_Msk (0x1FFFFFFFUL << FPU_FPCAR_ADDRESS_Pos) /*!< FPCAR: ADDRESS bit Mask */
+
+/* Floating-Point Default Status Control Register Definitions */
+#define FPU_FPDSCR_AHP_Pos 26U /*!< FPDSCR: AHP bit Position */
+#define FPU_FPDSCR_AHP_Msk (1UL << FPU_FPDSCR_AHP_Pos) /*!< FPDSCR: AHP bit Mask */
+
+#define FPU_FPDSCR_DN_Pos 25U /*!< FPDSCR: DN bit Position */
+#define FPU_FPDSCR_DN_Msk (1UL << FPU_FPDSCR_DN_Pos) /*!< FPDSCR: DN bit Mask */
+
+#define FPU_FPDSCR_FZ_Pos 24U /*!< FPDSCR: FZ bit Position */
+#define FPU_FPDSCR_FZ_Msk (1UL << FPU_FPDSCR_FZ_Pos) /*!< FPDSCR: FZ bit Mask */
+
+#define FPU_FPDSCR_RMode_Pos 22U /*!< FPDSCR: RMode bit Position */
+#define FPU_FPDSCR_RMode_Msk (3UL << FPU_FPDSCR_RMode_Pos) /*!< FPDSCR: RMode bit Mask */
+
+/* Media and FP Feature Register 0 Definitions */
+#define FPU_MVFR0_FP_rounding_modes_Pos 28U /*!< MVFR0: FP rounding modes bits Position */
+#define FPU_MVFR0_FP_rounding_modes_Msk (0xFUL << FPU_MVFR0_FP_rounding_modes_Pos) /*!< MVFR0: FP rounding modes bits Mask */
+
+#define FPU_MVFR0_Short_vectors_Pos 24U /*!< MVFR0: Short vectors bits Position */
+#define FPU_MVFR0_Short_vectors_Msk (0xFUL << FPU_MVFR0_Short_vectors_Pos) /*!< MVFR0: Short vectors bits Mask */
+
+#define FPU_MVFR0_Square_root_Pos 20U /*!< MVFR0: Square root bits Position */
+#define FPU_MVFR0_Square_root_Msk (0xFUL << FPU_MVFR0_Square_root_Pos) /*!< MVFR0: Square root bits Mask */
+
+#define FPU_MVFR0_Divide_Pos 16U /*!< MVFR0: Divide bits Position */
+#define FPU_MVFR0_Divide_Msk (0xFUL << FPU_MVFR0_Divide_Pos) /*!< MVFR0: Divide bits Mask */
+
+#define FPU_MVFR0_FP_excep_trapping_Pos 12U /*!< MVFR0: FP exception trapping bits Position */
+#define FPU_MVFR0_FP_excep_trapping_Msk (0xFUL << FPU_MVFR0_FP_excep_trapping_Pos) /*!< MVFR0: FP exception trapping bits Mask */
+
+#define FPU_MVFR0_Double_precision_Pos 8U /*!< MVFR0: Double-precision bits Position */
+#define FPU_MVFR0_Double_precision_Msk (0xFUL << FPU_MVFR0_Double_precision_Pos) /*!< MVFR0: Double-precision bits Mask */
+
+#define FPU_MVFR0_Single_precision_Pos 4U /*!< MVFR0: Single-precision bits Position */
+#define FPU_MVFR0_Single_precision_Msk (0xFUL << FPU_MVFR0_Single_precision_Pos) /*!< MVFR0: Single-precision bits Mask */
+
+#define FPU_MVFR0_A_SIMD_registers_Pos 0U /*!< MVFR0: A_SIMD registers bits Position */
+#define FPU_MVFR0_A_SIMD_registers_Msk (0xFUL /*<< FPU_MVFR0_A_SIMD_registers_Pos*/) /*!< MVFR0: A_SIMD registers bits Mask */
+
+/* Media and FP Feature Register 1 Definitions */
+#define FPU_MVFR1_FP_fused_MAC_Pos 28U /*!< MVFR1: FP fused MAC bits Position */
+#define FPU_MVFR1_FP_fused_MAC_Msk (0xFUL << FPU_MVFR1_FP_fused_MAC_Pos) /*!< MVFR1: FP fused MAC bits Mask */
+
+#define FPU_MVFR1_FP_HPFP_Pos 24U /*!< MVFR1: FP HPFP bits Position */
+#define FPU_MVFR1_FP_HPFP_Msk (0xFUL << FPU_MVFR1_FP_HPFP_Pos) /*!< MVFR1: FP HPFP bits Mask */
+
+#define FPU_MVFR1_D_NaN_mode_Pos 4U /*!< MVFR1: D_NaN mode bits Position */
+#define FPU_MVFR1_D_NaN_mode_Msk (0xFUL << FPU_MVFR1_D_NaN_mode_Pos) /*!< MVFR1: D_NaN mode bits Mask */
+
+#define FPU_MVFR1_FtZ_mode_Pos 0U /*!< MVFR1: FtZ mode bits Position */
+#define FPU_MVFR1_FtZ_mode_Msk (0xFUL /*<< FPU_MVFR1_FtZ_mode_Pos*/) /*!< MVFR1: FtZ mode bits Mask */
+
+/*@} end of group CMSIS_FPU */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug)
+ \brief Type definitions for the Core Debug Registers
+ @{
+ */
+
+/**
+ \brief Structure type to access the Core Debug Register (CoreDebug).
+ */
+typedef struct
+{
+ __IOM uint32_t DHCSR; /*!< Offset: 0x000 (R/W) Debug Halting Control and Status Register */
+ __OM uint32_t DCRSR; /*!< Offset: 0x004 ( /W) Debug Core Register Selector Register */
+ __IOM uint32_t DCRDR; /*!< Offset: 0x008 (R/W) Debug Core Register Data Register */
+ __IOM uint32_t DEMCR; /*!< Offset: 0x00C (R/W) Debug Exception and Monitor Control Register */
+ uint32_t RESERVED4[1U];
+ __IOM uint32_t DAUTHCTRL; /*!< Offset: 0x014 (R/W) Debug Authentication Control Register */
+ __IOM uint32_t DSCSR; /*!< Offset: 0x018 (R/W) Debug Security Control and Status Register */
+} CoreDebug_Type;
+
+/* Debug Halting Control and Status Register Definitions */
+#define CoreDebug_DHCSR_DBGKEY_Pos 16U /*!< CoreDebug DHCSR: DBGKEY Position */
+#define CoreDebug_DHCSR_DBGKEY_Msk (0xFFFFUL << CoreDebug_DHCSR_DBGKEY_Pos) /*!< CoreDebug DHCSR: DBGKEY Mask */
+
+#define CoreDebug_DHCSR_S_RESTART_ST_Pos 26U /*!< CoreDebug DHCSR: S_RESTART_ST Position */
+#define CoreDebug_DHCSR_S_RESTART_ST_Msk (1UL << CoreDebug_DHCSR_S_RESTART_ST_Pos) /*!< CoreDebug DHCSR: S_RESTART_ST Mask */
+
+#define CoreDebug_DHCSR_S_RESET_ST_Pos 25U /*!< CoreDebug DHCSR: S_RESET_ST Position */
+#define CoreDebug_DHCSR_S_RESET_ST_Msk (1UL << CoreDebug_DHCSR_S_RESET_ST_Pos) /*!< CoreDebug DHCSR: S_RESET_ST Mask */
+
+#define CoreDebug_DHCSR_S_RETIRE_ST_Pos 24U /*!< CoreDebug DHCSR: S_RETIRE_ST Position */
+#define CoreDebug_DHCSR_S_RETIRE_ST_Msk (1UL << CoreDebug_DHCSR_S_RETIRE_ST_Pos) /*!< CoreDebug DHCSR: S_RETIRE_ST Mask */
+
+#define CoreDebug_DHCSR_S_LOCKUP_Pos 19U /*!< CoreDebug DHCSR: S_LOCKUP Position */
+#define CoreDebug_DHCSR_S_LOCKUP_Msk (1UL << CoreDebug_DHCSR_S_LOCKUP_Pos) /*!< CoreDebug DHCSR: S_LOCKUP Mask */
+
+#define CoreDebug_DHCSR_S_SLEEP_Pos 18U /*!< CoreDebug DHCSR: S_SLEEP Position */
+#define CoreDebug_DHCSR_S_SLEEP_Msk (1UL << CoreDebug_DHCSR_S_SLEEP_Pos) /*!< CoreDebug DHCSR: S_SLEEP Mask */
+
+#define CoreDebug_DHCSR_S_HALT_Pos 17U /*!< CoreDebug DHCSR: S_HALT Position */
+#define CoreDebug_DHCSR_S_HALT_Msk (1UL << CoreDebug_DHCSR_S_HALT_Pos) /*!< CoreDebug DHCSR: S_HALT Mask */
+
+#define CoreDebug_DHCSR_S_REGRDY_Pos 16U /*!< CoreDebug DHCSR: S_REGRDY Position */
+#define CoreDebug_DHCSR_S_REGRDY_Msk (1UL << CoreDebug_DHCSR_S_REGRDY_Pos) /*!< CoreDebug DHCSR: S_REGRDY Mask */
+
+#define CoreDebug_DHCSR_C_SNAPSTALL_Pos 5U /*!< CoreDebug DHCSR: C_SNAPSTALL Position */
+#define CoreDebug_DHCSR_C_SNAPSTALL_Msk (1UL << CoreDebug_DHCSR_C_SNAPSTALL_Pos) /*!< CoreDebug DHCSR: C_SNAPSTALL Mask */
+
+#define CoreDebug_DHCSR_C_MASKINTS_Pos 3U /*!< CoreDebug DHCSR: C_MASKINTS Position */
+#define CoreDebug_DHCSR_C_MASKINTS_Msk (1UL << CoreDebug_DHCSR_C_MASKINTS_Pos) /*!< CoreDebug DHCSR: C_MASKINTS Mask */
+
+#define CoreDebug_DHCSR_C_STEP_Pos 2U /*!< CoreDebug DHCSR: C_STEP Position */
+#define CoreDebug_DHCSR_C_STEP_Msk (1UL << CoreDebug_DHCSR_C_STEP_Pos) /*!< CoreDebug DHCSR: C_STEP Mask */
+
+#define CoreDebug_DHCSR_C_HALT_Pos 1U /*!< CoreDebug DHCSR: C_HALT Position */
+#define CoreDebug_DHCSR_C_HALT_Msk (1UL << CoreDebug_DHCSR_C_HALT_Pos) /*!< CoreDebug DHCSR: C_HALT Mask */
+
+#define CoreDebug_DHCSR_C_DEBUGEN_Pos 0U /*!< CoreDebug DHCSR: C_DEBUGEN Position */
+#define CoreDebug_DHCSR_C_DEBUGEN_Msk (1UL /*<< CoreDebug_DHCSR_C_DEBUGEN_Pos*/) /*!< CoreDebug DHCSR: C_DEBUGEN Mask */
+
+/* Debug Core Register Selector Register Definitions */
+#define CoreDebug_DCRSR_REGWnR_Pos 16U /*!< CoreDebug DCRSR: REGWnR Position */
+#define CoreDebug_DCRSR_REGWnR_Msk (1UL << CoreDebug_DCRSR_REGWnR_Pos) /*!< CoreDebug DCRSR: REGWnR Mask */
+
+#define CoreDebug_DCRSR_REGSEL_Pos 0U /*!< CoreDebug DCRSR: REGSEL Position */
+#define CoreDebug_DCRSR_REGSEL_Msk (0x1FUL /*<< CoreDebug_DCRSR_REGSEL_Pos*/) /*!< CoreDebug DCRSR: REGSEL Mask */
+
+/* Debug Exception and Monitor Control Register Definitions */
+#define CoreDebug_DEMCR_TRCENA_Pos 24U /*!< CoreDebug DEMCR: TRCENA Position */
+#define CoreDebug_DEMCR_TRCENA_Msk (1UL << CoreDebug_DEMCR_TRCENA_Pos) /*!< CoreDebug DEMCR: TRCENA Mask */
+
+#define CoreDebug_DEMCR_MON_REQ_Pos 19U /*!< CoreDebug DEMCR: MON_REQ Position */
+#define CoreDebug_DEMCR_MON_REQ_Msk (1UL << CoreDebug_DEMCR_MON_REQ_Pos) /*!< CoreDebug DEMCR: MON_REQ Mask */
+
+#define CoreDebug_DEMCR_MON_STEP_Pos 18U /*!< CoreDebug DEMCR: MON_STEP Position */
+#define CoreDebug_DEMCR_MON_STEP_Msk (1UL << CoreDebug_DEMCR_MON_STEP_Pos) /*!< CoreDebug DEMCR: MON_STEP Mask */
+
+#define CoreDebug_DEMCR_MON_PEND_Pos 17U /*!< CoreDebug DEMCR: MON_PEND Position */
+#define CoreDebug_DEMCR_MON_PEND_Msk (1UL << CoreDebug_DEMCR_MON_PEND_Pos) /*!< CoreDebug DEMCR: MON_PEND Mask */
+
+#define CoreDebug_DEMCR_MON_EN_Pos 16U /*!< CoreDebug DEMCR: MON_EN Position */
+#define CoreDebug_DEMCR_MON_EN_Msk (1UL << CoreDebug_DEMCR_MON_EN_Pos) /*!< CoreDebug DEMCR: MON_EN Mask */
+
+#define CoreDebug_DEMCR_VC_HARDERR_Pos 10U /*!< CoreDebug DEMCR: VC_HARDERR Position */
+#define CoreDebug_DEMCR_VC_HARDERR_Msk (1UL << CoreDebug_DEMCR_VC_HARDERR_Pos) /*!< CoreDebug DEMCR: VC_HARDERR Mask */
+
+#define CoreDebug_DEMCR_VC_INTERR_Pos 9U /*!< CoreDebug DEMCR: VC_INTERR Position */
+#define CoreDebug_DEMCR_VC_INTERR_Msk (1UL << CoreDebug_DEMCR_VC_INTERR_Pos) /*!< CoreDebug DEMCR: VC_INTERR Mask */
+
+#define CoreDebug_DEMCR_VC_BUSERR_Pos 8U /*!< CoreDebug DEMCR: VC_BUSERR Position */
+#define CoreDebug_DEMCR_VC_BUSERR_Msk (1UL << CoreDebug_DEMCR_VC_BUSERR_Pos) /*!< CoreDebug DEMCR: VC_BUSERR Mask */
+
+#define CoreDebug_DEMCR_VC_STATERR_Pos 7U /*!< CoreDebug DEMCR: VC_STATERR Position */
+#define CoreDebug_DEMCR_VC_STATERR_Msk (1UL << CoreDebug_DEMCR_VC_STATERR_Pos) /*!< CoreDebug DEMCR: VC_STATERR Mask */
+
+#define CoreDebug_DEMCR_VC_CHKERR_Pos 6U /*!< CoreDebug DEMCR: VC_CHKERR Position */
+#define CoreDebug_DEMCR_VC_CHKERR_Msk (1UL << CoreDebug_DEMCR_VC_CHKERR_Pos) /*!< CoreDebug DEMCR: VC_CHKERR Mask */
+
+#define CoreDebug_DEMCR_VC_NOCPERR_Pos 5U /*!< CoreDebug DEMCR: VC_NOCPERR Position */
+#define CoreDebug_DEMCR_VC_NOCPERR_Msk (1UL << CoreDebug_DEMCR_VC_NOCPERR_Pos) /*!< CoreDebug DEMCR: VC_NOCPERR Mask */
+
+#define CoreDebug_DEMCR_VC_MMERR_Pos 4U /*!< CoreDebug DEMCR: VC_MMERR Position */
+#define CoreDebug_DEMCR_VC_MMERR_Msk (1UL << CoreDebug_DEMCR_VC_MMERR_Pos) /*!< CoreDebug DEMCR: VC_MMERR Mask */
+
+#define CoreDebug_DEMCR_VC_CORERESET_Pos 0U /*!< CoreDebug DEMCR: VC_CORERESET Position */
+#define CoreDebug_DEMCR_VC_CORERESET_Msk (1UL /*<< CoreDebug_DEMCR_VC_CORERESET_Pos*/) /*!< CoreDebug DEMCR: VC_CORERESET Mask */
+
+/* Debug Authentication Control Register Definitions */
+#define CoreDebug_DAUTHCTRL_INTSPNIDEN_Pos 3U /*!< CoreDebug DAUTHCTRL: INTSPNIDEN, Position */
+#define CoreDebug_DAUTHCTRL_INTSPNIDEN_Msk (1UL << CoreDebug_DAUTHCTRL_INTSPNIDEN_Pos) /*!< CoreDebug DAUTHCTRL: INTSPNIDEN, Mask */
+
+#define CoreDebug_DAUTHCTRL_SPNIDENSEL_Pos 2U /*!< CoreDebug DAUTHCTRL: SPNIDENSEL Position */
+#define CoreDebug_DAUTHCTRL_SPNIDENSEL_Msk (1UL << CoreDebug_DAUTHCTRL_SPNIDENSEL_Pos) /*!< CoreDebug DAUTHCTRL: SPNIDENSEL Mask */
+
+#define CoreDebug_DAUTHCTRL_INTSPIDEN_Pos 1U /*!< CoreDebug DAUTHCTRL: INTSPIDEN Position */
+#define CoreDebug_DAUTHCTRL_INTSPIDEN_Msk (1UL << CoreDebug_DAUTHCTRL_INTSPIDEN_Pos) /*!< CoreDebug DAUTHCTRL: INTSPIDEN Mask */
+
+#define CoreDebug_DAUTHCTRL_SPIDENSEL_Pos 0U /*!< CoreDebug DAUTHCTRL: SPIDENSEL Position */
+#define CoreDebug_DAUTHCTRL_SPIDENSEL_Msk (1UL /*<< CoreDebug_DAUTHCTRL_SPIDENSEL_Pos*/) /*!< CoreDebug DAUTHCTRL: SPIDENSEL Mask */
+
+/* Debug Security Control and Status Register Definitions */
+#define CoreDebug_DSCSR_CDS_Pos 16U /*!< CoreDebug DSCSR: CDS Position */
+#define CoreDebug_DSCSR_CDS_Msk (1UL << CoreDebug_DSCSR_CDS_Pos) /*!< CoreDebug DSCSR: CDS Mask */
+
+#define CoreDebug_DSCSR_SBRSEL_Pos 1U /*!< CoreDebug DSCSR: SBRSEL Position */
+#define CoreDebug_DSCSR_SBRSEL_Msk (1UL << CoreDebug_DSCSR_SBRSEL_Pos) /*!< CoreDebug DSCSR: SBRSEL Mask */
+
+#define CoreDebug_DSCSR_SBRSELEN_Pos 0U /*!< CoreDebug DSCSR: SBRSELEN Position */
+#define CoreDebug_DSCSR_SBRSELEN_Msk (1UL /*<< CoreDebug_DSCSR_SBRSELEN_Pos*/) /*!< CoreDebug DSCSR: SBRSELEN Mask */
+
+/*@} end of group CMSIS_CoreDebug */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_core_bitfield Core register bit field macros
+ \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk).
+ @{
+ */
+
+/**
+ \brief Mask and shift a bit field value for use in a register bit range.
+ \param[in] field Name of the register bit field.
+ \param[in] value Value of the bit field. This parameter is interpreted as an uint32_t type.
+ \return Masked and shifted value.
+*/
+#define _VAL2FLD(field, value) (((uint32_t)(value) << field ## _Pos) & field ## _Msk)
+
+/**
+ \brief Mask and shift a register value to extract a bit filed value.
+ \param[in] field Name of the register bit field.
+ \param[in] value Value of register. This parameter is interpreted as an uint32_t type.
+ \return Masked and shifted bit field value.
+*/
+#define _FLD2VAL(field, value) (((uint32_t)(value) & field ## _Msk) >> field ## _Pos)
+
+/*@} end of group CMSIS_core_bitfield */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_core_base Core Definitions
+ \brief Definitions for base addresses, unions, and structures.
+ @{
+ */
+
+/* Memory mapping of Core Hardware */
+ #define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */
+ #define ITM_BASE (0xE0000000UL) /*!< ITM Base Address */
+ #define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */
+ #define TPI_BASE (0xE0040000UL) /*!< TPI Base Address */
+ #define CoreDebug_BASE (0xE000EDF0UL) /*!< Core Debug Base Address */
+ #define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */
+ #define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */
+ #define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */
+
+ #define SCnSCB ((SCnSCB_Type *) SCS_BASE ) /*!< System control Register not in SCB */
+ #define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */
+ #define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */
+ #define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */
+ #define ITM ((ITM_Type *) ITM_BASE ) /*!< ITM configuration struct */
+ #define DWT ((DWT_Type *) DWT_BASE ) /*!< DWT configuration struct */
+ #define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */
+ #define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE ) /*!< Core Debug configuration struct */
+
+ #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U)
+ #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */
+ #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */
+ #endif
+
+ #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
+ #define SAU_BASE (SCS_BASE + 0x0DD0UL) /*!< Security Attribution Unit */
+ #define SAU ((SAU_Type *) SAU_BASE ) /*!< Security Attribution Unit */
+ #endif
+
+ #define FPU_BASE (SCS_BASE + 0x0F30UL) /*!< Floating Point Unit */
+ #define FPU ((FPU_Type *) FPU_BASE ) /*!< Floating Point Unit */
+
+#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
+ #define SCS_BASE_NS (0xE002E000UL) /*!< System Control Space Base Address (non-secure address space) */
+ #define CoreDebug_BASE_NS (0xE002EDF0UL) /*!< Core Debug Base Address (non-secure address space) */
+ #define SysTick_BASE_NS (SCS_BASE_NS + 0x0010UL) /*!< SysTick Base Address (non-secure address space) */
+ #define NVIC_BASE_NS (SCS_BASE_NS + 0x0100UL) /*!< NVIC Base Address (non-secure address space) */
+ #define SCB_BASE_NS (SCS_BASE_NS + 0x0D00UL) /*!< System Control Block Base Address (non-secure address space) */
+
+ #define SCnSCB_NS ((SCnSCB_Type *) SCS_BASE_NS ) /*!< System control Register not in SCB(non-secure address space) */
+ #define SCB_NS ((SCB_Type *) SCB_BASE_NS ) /*!< SCB configuration struct (non-secure address space) */
+ #define SysTick_NS ((SysTick_Type *) SysTick_BASE_NS ) /*!< SysTick configuration struct (non-secure address space) */
+ #define NVIC_NS ((NVIC_Type *) NVIC_BASE_NS ) /*!< NVIC configuration struct (non-secure address space) */
+ #define CoreDebug_NS ((CoreDebug_Type *) CoreDebug_BASE_NS) /*!< Core Debug configuration struct (non-secure address space) */
+
+ #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U)
+ #define MPU_BASE_NS (SCS_BASE_NS + 0x0D90UL) /*!< Memory Protection Unit (non-secure address space) */
+ #define MPU_NS ((MPU_Type *) MPU_BASE_NS ) /*!< Memory Protection Unit (non-secure address space) */
+ #endif
+
+ #define FPU_BASE_NS (SCS_BASE_NS + 0x0F30UL) /*!< Floating Point Unit (non-secure address space) */
+ #define FPU_NS ((FPU_Type *) FPU_BASE_NS ) /*!< Floating Point Unit (non-secure address space) */
+
+#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */
+/*@} */
+
+
+
+/*******************************************************************************
+ * Hardware Abstraction Layer
+ Core Function Interface contains:
+ - Core NVIC Functions
+ - Core SysTick Functions
+ - Core Debug Functions
+ - Core Register Access Functions
+ ******************************************************************************/
+/**
+ \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference
+*/
+
+
+
+/* ########################## NVIC functions #################################### */
+/**
+ \ingroup CMSIS_Core_FunctionInterface
+ \defgroup CMSIS_Core_NVICFunctions NVIC Functions
+ \brief Functions that manage interrupts and exceptions via the NVIC.
+ @{
+ */
+
+#ifdef CMSIS_NVIC_VIRTUAL
+ #ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE
+ #define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h"
+ #endif
+ #include CMSIS_NVIC_VIRTUAL_HEADER_FILE
+#else
+ #define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping
+ #define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping
+ #define NVIC_EnableIRQ __NVIC_EnableIRQ
+ #define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ
+ #define NVIC_DisableIRQ __NVIC_DisableIRQ
+ #define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ
+ #define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ
+ #define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ
+ #define NVIC_GetActive __NVIC_GetActive
+ #define NVIC_SetPriority __NVIC_SetPriority
+ #define NVIC_GetPriority __NVIC_GetPriority
+ #define NVIC_SystemReset __NVIC_SystemReset
+#endif /* CMSIS_NVIC_VIRTUAL */
+
+#ifdef CMSIS_VECTAB_VIRTUAL
+ #ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE
+ #define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h"
+ #endif
+ #include CMSIS_VECTAB_VIRTUAL_HEADER_FILE
+#else
+ #define NVIC_SetVector __NVIC_SetVector
+ #define NVIC_GetVector __NVIC_GetVector
+#endif /* (CMSIS_VECTAB_VIRTUAL) */
+
+#define NVIC_USER_IRQ_OFFSET 16
+
+
+/* Special LR values for Secure/Non-Secure call handling and exception handling */
+
+/* Function Return Payload (from ARMv8-M Architecture Reference Manual) LR value on entry from Secure BLXNS */
+#define FNC_RETURN (0xFEFFFFFFUL) /* bit [0] ignored when processing a branch */
+
+/* The following EXC_RETURN mask values are used to evaluate the LR on exception entry */
+#define EXC_RETURN_PREFIX (0xFF000000UL) /* bits [31:24] set to indicate an EXC_RETURN value */
+#define EXC_RETURN_S (0x00000040UL) /* bit [6] stack used to push registers: 0=Non-secure 1=Secure */
+#define EXC_RETURN_DCRS (0x00000020UL) /* bit [5] stacking rules for called registers: 0=skipped 1=saved */
+#define EXC_RETURN_FTYPE (0x00000010UL) /* bit [4] allocate stack for floating-point context: 0=done 1=skipped */
+#define EXC_RETURN_MODE (0x00000008UL) /* bit [3] processor mode for return: 0=Handler mode 1=Thread mode */
+#define EXC_RETURN_SPSEL (0x00000004UL) /* bit [2] stack pointer used to restore context: 0=MSP 1=PSP */
+#define EXC_RETURN_ES (0x00000001UL) /* bit [0] security state exception was taken to: 0=Non-secure 1=Secure */
+
+/* Integrity Signature (from ARMv8-M Architecture Reference Manual) for exception context stacking */
+#if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) /* Value for processors with floating-point extension: */
+#define EXC_INTEGRITY_SIGNATURE (0xFEFA125AUL) /* bit [0] SFTC must match LR bit[4] EXC_RETURN_FTYPE */
+#else
+#define EXC_INTEGRITY_SIGNATURE (0xFEFA125BUL) /* Value for processors without floating-point extension */
+#endif
+
+
+/**
+ \brief Set Priority Grouping
+ \details Sets the priority grouping field using the required unlock sequence.
+ The parameter PriorityGroup is assigned to the field SCB->AIRCR [10:8] PRIGROUP field.
+ Only values from 0..7 are used.
+ In case of a conflict between priority grouping and available
+ priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set.
+ \param [in] PriorityGroup Priority grouping field.
+ */
+__STATIC_INLINE void __NVIC_SetPriorityGrouping(uint32_t PriorityGroup)
+{
+ uint32_t reg_value;
+ uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */
+
+ reg_value = SCB->AIRCR; /* read old register configuration */
+ reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */
+ reg_value = (reg_value |
+ ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) |
+ (PriorityGroupTmp << SCB_AIRCR_PRIGROUP_Pos) ); /* Insert write key and priority group */
+ SCB->AIRCR = reg_value;
+}
+
+
+/**
+ \brief Get Priority Grouping
+ \details Reads the priority grouping field from the NVIC Interrupt Controller.
+ \return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field).
+ */
+__STATIC_INLINE uint32_t __NVIC_GetPriorityGrouping(void)
+{
+ return ((uint32_t)((SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos));
+}
+
+
+/**
+ \brief Enable Interrupt
+ \details Enables a device specific interrupt in the NVIC interrupt controller.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Get Interrupt Enable status
+ \details Returns a device specific interrupt enable status from the NVIC interrupt controller.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 Interrupt is not enabled.
+ \return 1 Interrupt is enabled.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Disable Interrupt
+ \details Disables a device specific interrupt in the NVIC interrupt controller.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ICER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ __DSB();
+ __ISB();
+ }
+}
+
+
+/**
+ \brief Get Pending Interrupt
+ \details Reads the NVIC pending register and returns the pending bit for the specified device specific interrupt.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 Interrupt status is not pending.
+ \return 1 Interrupt status is pending.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Set Pending Interrupt
+ \details Sets the pending bit of a device specific interrupt in the NVIC pending register.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Clear Pending Interrupt
+ \details Clears the pending bit of a device specific interrupt in the NVIC pending register.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Get Active Interrupt
+ \details Reads the active register in the NVIC and returns the active bit for the device specific interrupt.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 Interrupt status is not active.
+ \return 1 Interrupt status is active.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t __NVIC_GetActive(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC->IABR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
+/**
+ \brief Get Interrupt Target State
+ \details Reads the interrupt target field in the NVIC and returns the interrupt target bit for the device specific interrupt.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 if interrupt is assigned to Secure
+ \return 1 if interrupt is assigned to Non Secure
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t NVIC_GetTargetState(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Set Interrupt Target State
+ \details Sets the interrupt target field in the NVIC and returns the interrupt target bit for the device specific interrupt.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 if interrupt is assigned to Secure
+ 1 if interrupt is assigned to Non Secure
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t NVIC_SetTargetState(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] |= ((uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)));
+ return((uint32_t)(((NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Clear Interrupt Target State
+ \details Clears the interrupt target field in the NVIC and returns the interrupt target bit for the device specific interrupt.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 if interrupt is assigned to Secure
+ 1 if interrupt is assigned to Non Secure
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t NVIC_ClearTargetState(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] &= ~((uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)));
+ return((uint32_t)(((NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */
+
+
+/**
+ \brief Set Interrupt Priority
+ \details Sets the priority of a device specific interrupt or a processor exception.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ \param [in] IRQn Interrupt number.
+ \param [in] priority Priority to set.
+ \note The priority cannot be set for every processor exception.
+ */
+__STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->IPR[((uint32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL);
+ }
+ else
+ {
+ SCB->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL);
+ }
+}
+
+
+/**
+ \brief Get Interrupt Priority
+ \details Reads the priority of a device specific interrupt or a processor exception.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ \param [in] IRQn Interrupt number.
+ \return Interrupt Priority.
+ Value is aligned automatically to the implemented priority bits of the microcontroller.
+ */
+__STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn)
+{
+
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return(((uint32_t)NVIC->IPR[((uint32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS)));
+ }
+ else
+ {
+ return(((uint32_t)SCB->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS)));
+ }
+}
+
+
+/**
+ \brief Encode Priority
+ \details Encodes the priority for an interrupt with the given priority group,
+ preemptive priority value, and subpriority value.
+ In case of a conflict between priority grouping and available
+ priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set.
+ \param [in] PriorityGroup Used priority group.
+ \param [in] PreemptPriority Preemptive priority value (starting from 0).
+ \param [in] SubPriority Subpriority value (starting from 0).
+ \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority().
+ */
+__STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority)
+{
+ uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */
+ uint32_t PreemptPriorityBits;
+ uint32_t SubPriorityBits;
+
+ PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp);
+ SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS));
+
+ return (
+ ((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) |
+ ((SubPriority & (uint32_t)((1UL << (SubPriorityBits )) - 1UL)))
+ );
+}
+
+
+/**
+ \brief Decode Priority
+ \details Decodes an interrupt priority value with a given priority group to
+ preemptive priority value and subpriority value.
+ In case of a conflict between priority grouping and available
+ priority bits (__NVIC_PRIO_BITS) the smallest possible priority group is set.
+ \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority().
+ \param [in] PriorityGroup Used priority group.
+ \param [out] pPreemptPriority Preemptive priority value (starting from 0).
+ \param [out] pSubPriority Subpriority value (starting from 0).
+ */
+__STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* const pPreemptPriority, uint32_t* const pSubPriority)
+{
+ uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */
+ uint32_t PreemptPriorityBits;
+ uint32_t SubPriorityBits;
+
+ PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp);
+ SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS));
+
+ *pPreemptPriority = (Priority >> SubPriorityBits) & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL);
+ *pSubPriority = (Priority ) & (uint32_t)((1UL << (SubPriorityBits )) - 1UL);
+}
+
+
+/**
+ \brief Set Interrupt Vector
+ \details Sets an interrupt vector in SRAM based interrupt vector table.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ VTOR must been relocated to SRAM before.
+ \param [in] IRQn Interrupt number
+ \param [in] vector Address of interrupt handler function
+ */
+__STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector)
+{
+ uint32_t *vectors = (uint32_t *)SCB->VTOR;
+ vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET] = vector;
+}
+
+
+/**
+ \brief Get Interrupt Vector
+ \details Reads an interrupt vector from interrupt vector table.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ \param [in] IRQn Interrupt number.
+ \return Address of interrupt handler function
+ */
+__STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn)
+{
+ uint32_t *vectors = (uint32_t *)SCB->VTOR;
+ return vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET];
+}
+
+
+/**
+ \brief System Reset
+ \details Initiates a system reset request to reset the MCU.
+ */
+__NO_RETURN __STATIC_INLINE void __NVIC_SystemReset(void)
+{
+ __DSB(); /* Ensure all outstanding memory accesses included
+ buffered write are completed before reset */
+ SCB->AIRCR = (uint32_t)((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) |
+ (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) |
+ SCB_AIRCR_SYSRESETREQ_Msk ); /* Keep priority group unchanged */
+ __DSB(); /* Ensure completion of memory access */
+
+ for(;;) /* wait until reset */
+ {
+ __NOP();
+ }
+}
+
+#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
+/**
+ \brief Set Priority Grouping (non-secure)
+ \details Sets the non-secure priority grouping field when in secure state using the required unlock sequence.
+ The parameter PriorityGroup is assigned to the field SCB->AIRCR [10:8] PRIGROUP field.
+ Only values from 0..7 are used.
+ In case of a conflict between priority grouping and available
+ priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set.
+ \param [in] PriorityGroup Priority grouping field.
+ */
+__STATIC_INLINE void TZ_NVIC_SetPriorityGrouping_NS(uint32_t PriorityGroup)
+{
+ uint32_t reg_value;
+ uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */
+
+ reg_value = SCB_NS->AIRCR; /* read old register configuration */
+ reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */
+ reg_value = (reg_value |
+ ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) |
+ (PriorityGroupTmp << SCB_AIRCR_PRIGROUP_Pos) ); /* Insert write key and priority group */
+ SCB_NS->AIRCR = reg_value;
+}
+
+
+/**
+ \brief Get Priority Grouping (non-secure)
+ \details Reads the priority grouping field from the non-secure NVIC when in secure state.
+ \return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field).
+ */
+__STATIC_INLINE uint32_t TZ_NVIC_GetPriorityGrouping_NS(void)
+{
+ return ((uint32_t)((SCB_NS->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos));
+}
+
+
+/**
+ \brief Enable Interrupt (non-secure)
+ \details Enables a device specific interrupt in the non-secure NVIC interrupt controller when in secure state.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void TZ_NVIC_EnableIRQ_NS(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC_NS->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Get Interrupt Enable status (non-secure)
+ \details Returns a device specific interrupt enable status from the non-secure NVIC interrupt controller when in secure state.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 Interrupt is not enabled.
+ \return 1 Interrupt is enabled.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t TZ_NVIC_GetEnableIRQ_NS(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC_NS->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Disable Interrupt (non-secure)
+ \details Disables a device specific interrupt in the non-secure NVIC interrupt controller when in secure state.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void TZ_NVIC_DisableIRQ_NS(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC_NS->ICER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Get Pending Interrupt (non-secure)
+ \details Reads the NVIC pending register in the non-secure NVIC when in secure state and returns the pending bit for the specified device specific interrupt.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 Interrupt status is not pending.
+ \return 1 Interrupt status is pending.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t TZ_NVIC_GetPendingIRQ_NS(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC_NS->ISPR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Set Pending Interrupt (non-secure)
+ \details Sets the pending bit of a device specific interrupt in the non-secure NVIC pending register when in secure state.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void TZ_NVIC_SetPendingIRQ_NS(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC_NS->ISPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Clear Pending Interrupt (non-secure)
+ \details Clears the pending bit of a device specific interrupt in the non-secure NVIC pending register when in secure state.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void TZ_NVIC_ClearPendingIRQ_NS(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC_NS->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Get Active Interrupt (non-secure)
+ \details Reads the active register in non-secure NVIC when in secure state and returns the active bit for the device specific interrupt.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 Interrupt status is not active.
+ \return 1 Interrupt status is active.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t TZ_NVIC_GetActive_NS(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC_NS->IABR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Set Interrupt Priority (non-secure)
+ \details Sets the priority of a non-secure device specific interrupt or a non-secure processor exception when in secure state.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ \param [in] IRQn Interrupt number.
+ \param [in] priority Priority to set.
+ \note The priority cannot be set for every non-secure processor exception.
+ */
+__STATIC_INLINE void TZ_NVIC_SetPriority_NS(IRQn_Type IRQn, uint32_t priority)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC_NS->IPR[((uint32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL);
+ }
+ else
+ {
+ SCB_NS->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL);
+ }
+}
+
+
+/**
+ \brief Get Interrupt Priority (non-secure)
+ \details Reads the priority of a non-secure device specific interrupt or a non-secure processor exception when in secure state.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ \param [in] IRQn Interrupt number.
+ \return Interrupt Priority. Value is aligned automatically to the implemented priority bits of the microcontroller.
+ */
+__STATIC_INLINE uint32_t TZ_NVIC_GetPriority_NS(IRQn_Type IRQn)
+{
+
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return(((uint32_t)NVIC_NS->IPR[((uint32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS)));
+ }
+ else
+ {
+ return(((uint32_t)SCB_NS->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS)));
+ }
+}
+#endif /* defined (__ARM_FEATURE_CMSE) &&(__ARM_FEATURE_CMSE == 3U) */
+
+/*@} end of CMSIS_Core_NVICFunctions */
+
+/* ########################## MPU functions #################################### */
+
+#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U)
+
+#include "mpu_armv8.h"
+
+#endif
+
+/* ########################## FPU functions #################################### */
+/**
+ \ingroup CMSIS_Core_FunctionInterface
+ \defgroup CMSIS_Core_FpuFunctions FPU Functions
+ \brief Function that provides FPU type.
+ @{
+ */
+
+/**
+ \brief get FPU type
+ \details returns the FPU type
+ \returns
+ - \b 0: No FPU
+ - \b 1: Single precision FPU
+ - \b 2: Double + Single precision FPU
+ */
+__STATIC_INLINE uint32_t SCB_GetFPUType(void)
+{
+ uint32_t mvfr0;
+
+ mvfr0 = FPU->MVFR0;
+ if ((mvfr0 & (FPU_MVFR0_Single_precision_Msk | FPU_MVFR0_Double_precision_Msk)) == 0x220U)
+ {
+ return 2U; /* Double + Single precision FPU */
+ }
+ else if ((mvfr0 & (FPU_MVFR0_Single_precision_Msk | FPU_MVFR0_Double_precision_Msk)) == 0x020U)
+ {
+ return 1U; /* Single precision FPU */
+ }
+ else
+ {
+ return 0U; /* No FPU */
+ }
+}
+
+
+/*@} end of CMSIS_Core_FpuFunctions */
+
+
+
+/* ########################## SAU functions #################################### */
+/**
+ \ingroup CMSIS_Core_FunctionInterface
+ \defgroup CMSIS_Core_SAUFunctions SAU Functions
+ \brief Functions that configure the SAU.
+ @{
+ */
+
+#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
+
+/**
+ \brief Enable SAU
+ \details Enables the Security Attribution Unit (SAU).
+ */
+__STATIC_INLINE void TZ_SAU_Enable(void)
+{
+ SAU->CTRL |= (SAU_CTRL_ENABLE_Msk);
+}
+
+
+
+/**
+ \brief Disable SAU
+ \details Disables the Security Attribution Unit (SAU).
+ */
+__STATIC_INLINE void TZ_SAU_Disable(void)
+{
+ SAU->CTRL &= ~(SAU_CTRL_ENABLE_Msk);
+}
+
+#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */
+
+/*@} end of CMSIS_Core_SAUFunctions */
+
+
+
+
+/* ################################## SysTick function ############################################ */
+/**
+ \ingroup CMSIS_Core_FunctionInterface
+ \defgroup CMSIS_Core_SysTickFunctions SysTick Functions
+ \brief Functions that configure the System.
+ @{
+ */
+
+#if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U)
+
+/**
+ \brief System Tick Configuration
+ \details Initializes the System Timer and its interrupt, and starts the System Tick Timer.
+ Counter is in free running mode to generate periodic interrupts.
+ \param [in] ticks Number of ticks between two interrupts.
+ \return 0 Function succeeded.
+ \return 1 Function failed.
+ \note When the variable __Vendor_SysTickConfig is set to 1, then the
+ function SysTick_Config is not included. In this case, the file device.h
+ must contain a vendor-specific implementation of this function.
+ */
+__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)
+{
+ if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk)
+ {
+ return (1UL); /* Reload value impossible */
+ }
+
+ SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */
+ NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */
+ SysTick->VAL = 0UL; /* Load the SysTick Counter Value */
+ SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
+ SysTick_CTRL_TICKINT_Msk |
+ SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */
+ return (0UL); /* Function successful */
+}
+
+#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
+/**
+ \brief System Tick Configuration (non-secure)
+ \details Initializes the non-secure System Timer and its interrupt when in secure state, and starts the System Tick Timer.
+ Counter is in free running mode to generate periodic interrupts.
+ \param [in] ticks Number of ticks between two interrupts.
+ \return 0 Function succeeded.
+ \return 1 Function failed.
+ \note When the variable __Vendor_SysTickConfig is set to 1, then the
+ function TZ_SysTick_Config_NS is not included. In this case, the file device.h
+ must contain a vendor-specific implementation of this function.
+
+ */
+__STATIC_INLINE uint32_t TZ_SysTick_Config_NS(uint32_t ticks)
+{
+ if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk)
+ {
+ return (1UL); /* Reload value impossible */
+ }
+
+ SysTick_NS->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */
+ TZ_NVIC_SetPriority_NS (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */
+ SysTick_NS->VAL = 0UL; /* Load the SysTick Counter Value */
+ SysTick_NS->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
+ SysTick_CTRL_TICKINT_Msk |
+ SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */
+ return (0UL); /* Function successful */
+}
+#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */
+
+#endif
+
+/*@} end of CMSIS_Core_SysTickFunctions */
+
+
+
+/* ##################################### Debug In/Output function ########################################### */
+/**
+ \ingroup CMSIS_Core_FunctionInterface
+ \defgroup CMSIS_core_DebugFunctions ITM Functions
+ \brief Functions that access the ITM debug interface.
+ @{
+ */
+
+extern volatile int32_t ITM_RxBuffer; /*!< External variable to receive characters. */
+#define ITM_RXBUFFER_EMPTY ((int32_t)0x5AA55AA5U) /*!< Value identifying \ref ITM_RxBuffer is ready for next character. */
+
+
+/**
+ \brief ITM Send Character
+ \details Transmits a character via the ITM channel 0, and
+ \li Just returns when no debugger is connected that has booked the output.
+ \li Is blocking when a debugger is connected, but the previous character sent has not been transmitted.
+ \param [in] ch Character to transmit.
+ \returns Character to transmit.
+ */
+__STATIC_INLINE uint32_t ITM_SendChar (uint32_t ch)
+{
+ if (((ITM->TCR & ITM_TCR_ITMENA_Msk) != 0UL) && /* ITM enabled */
+ ((ITM->TER & 1UL ) != 0UL) ) /* ITM Port #0 enabled */
+ {
+ while (ITM->PORT[0U].u32 == 0UL)
+ {
+ __NOP();
+ }
+ ITM->PORT[0U].u8 = (uint8_t)ch;
+ }
+ return (ch);
+}
+
+
+/**
+ \brief ITM Receive Character
+ \details Inputs a character via the external variable \ref ITM_RxBuffer.
+ \return Received character.
+ \return -1 No character pending.
+ */
+__STATIC_INLINE int32_t ITM_ReceiveChar (void)
+{
+ int32_t ch = -1; /* no character available */
+
+ if (ITM_RxBuffer != ITM_RXBUFFER_EMPTY)
+ {
+ ch = ITM_RxBuffer;
+ ITM_RxBuffer = ITM_RXBUFFER_EMPTY; /* ready for next character */
+ }
+
+ return (ch);
+}
+
+
+/**
+ \brief ITM Check Character
+ \details Checks whether a character is pending for reading in the variable \ref ITM_RxBuffer.
+ \return 0 No character available.
+ \return 1 Character available.
+ */
+__STATIC_INLINE int32_t ITM_CheckChar (void)
+{
+
+ if (ITM_RxBuffer == ITM_RXBUFFER_EMPTY)
+ {
+ return (0); /* no character available */
+ }
+ else
+ {
+ return (1); /* character available */
+ }
+}
+
+/*@} end of CMSIS_core_DebugFunctions */
+
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CORE_CM33_H_DEPENDANT */
+
+#endif /* __CMSIS_GENERIC */
diff --git a/lib/cmsis/inc/core_cm35p.h b/lib/cmsis/inc/core_cm35p.h
new file mode 100644
index 0000000000..c00e54ca7a
--- /dev/null
+++ b/lib/cmsis/inc/core_cm35p.h
@@ -0,0 +1,2907 @@
+/**************************************************************************//**
+ * @file core_cm35p.h
+ * @brief CMSIS Cortex-M35P Core Peripheral Access Layer Header File
+ * @version V1.0.0
+ * @date 12. November 2018
+ ******************************************************************************/
+/*
+ * Copyright (c) 2018 Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#if defined ( __ICCARM__ )
+ #pragma system_include /* treat file as system include file for MISRA check */
+#elif defined (__clang__)
+ #pragma clang system_header /* treat file as system include file */
+#endif
+
+#ifndef __CORE_CM35P_H_GENERIC
+#define __CORE_CM35P_H_GENERIC
+
+#include
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/**
+ \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions
+ CMSIS violates the following MISRA-C:2004 rules:
+
+ \li Required Rule 8.5, object/function definition in header file.
+ Function definitions in header files are used to allow 'inlining'.
+
+ \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
+ Unions are used for effective representation of core registers.
+
+ \li Advisory Rule 19.7, Function-like macro defined.
+ Function-like macros are used to allow more efficient code.
+ */
+
+
+/*******************************************************************************
+ * CMSIS definitions
+ ******************************************************************************/
+/**
+ \ingroup Cortex_M35P
+ @{
+ */
+
+#include "cmsis_version.h"
+
+/* CMSIS CM35P definitions */
+#define __CM35P_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */
+#define __CM35P_CMSIS_VERSION_SUB (__CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */
+#define __CM35P_CMSIS_VERSION ((__CM35P_CMSIS_VERSION_MAIN << 16U) | \
+ __CM35P_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */
+
+#define __CORTEX_M (35U) /*!< Cortex-M Core */
+
+/** __FPU_USED indicates whether an FPU is used or not.
+ For this, __FPU_PRESENT has to be checked prior to making use of FPU specific registers and functions.
+*/
+#if defined ( __CC_ARM )
+ #if defined (__TARGET_FPU_VFP)
+ #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)
+ #define __FPU_USED 1U
+ #else
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #define __FPU_USED 0U
+ #endif
+ #else
+ #define __FPU_USED 0U
+ #endif
+
+ #if defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1U)
+ #if defined (__DSP_PRESENT) && (__DSP_PRESENT == 1U)
+ #define __DSP_USED 1U
+ #else
+ #error "Compiler generates DSP (SIMD) instructions for a devices without DSP extensions (check __DSP_PRESENT)"
+ #define __DSP_USED 0U
+ #endif
+ #else
+ #define __DSP_USED 0U
+ #endif
+
+#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
+ #if defined (__ARM_FP)
+ #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)
+ #define __FPU_USED 1U
+ #else
+ #warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #define __FPU_USED 0U
+ #endif
+ #else
+ #define __FPU_USED 0U
+ #endif
+
+ #if defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1U)
+ #if defined (__DSP_PRESENT) && (__DSP_PRESENT == 1U)
+ #define __DSP_USED 1U
+ #else
+ #error "Compiler generates DSP (SIMD) instructions for a devices without DSP extensions (check __DSP_PRESENT)"
+ #define __DSP_USED 0U
+ #endif
+ #else
+ #define __DSP_USED 0U
+ #endif
+
+#elif defined ( __GNUC__ )
+ #if defined (__VFP_FP__) && !defined(__SOFTFP__)
+ #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)
+ #define __FPU_USED 1U
+ #else
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #define __FPU_USED 0U
+ #endif
+ #else
+ #define __FPU_USED 0U
+ #endif
+
+ #if defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1U)
+ #if defined (__DSP_PRESENT) && (__DSP_PRESENT == 1U)
+ #define __DSP_USED 1U
+ #else
+ #error "Compiler generates DSP (SIMD) instructions for a devices without DSP extensions (check __DSP_PRESENT)"
+ #define __DSP_USED 0U
+ #endif
+ #else
+ #define __DSP_USED 0U
+ #endif
+
+#elif defined ( __ICCARM__ )
+ #if defined (__ARMVFP__)
+ #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)
+ #define __FPU_USED 1U
+ #else
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #define __FPU_USED 0U
+ #endif
+ #else
+ #define __FPU_USED 0U
+ #endif
+
+ #if defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1U)
+ #if defined (__DSP_PRESENT) && (__DSP_PRESENT == 1U)
+ #define __DSP_USED 1U
+ #else
+ #error "Compiler generates DSP (SIMD) instructions for a devices without DSP extensions (check __DSP_PRESENT)"
+ #define __DSP_USED 0U
+ #endif
+ #else
+ #define __DSP_USED 0U
+ #endif
+
+#elif defined ( __TI_ARM__ )
+ #if defined (__TI_VFP_SUPPORT__)
+ #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)
+ #define __FPU_USED 1U
+ #else
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #define __FPU_USED 0U
+ #endif
+ #else
+ #define __FPU_USED 0U
+ #endif
+
+#elif defined ( __TASKING__ )
+ #if defined (__FPU_VFP__)
+ #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)
+ #define __FPU_USED 1U
+ #else
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #define __FPU_USED 0U
+ #endif
+ #else
+ #define __FPU_USED 0U
+ #endif
+
+#elif defined ( __CSMC__ )
+ #if ( __CSMC__ & 0x400U)
+ #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)
+ #define __FPU_USED 1U
+ #else
+ #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
+ #define __FPU_USED 0U
+ #endif
+ #else
+ #define __FPU_USED 0U
+ #endif
+
+#endif
+
+#include "cmsis_compiler.h" /* CMSIS compiler specific defines */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CORE_CM35P_H_GENERIC */
+
+#ifndef __CMSIS_GENERIC
+
+#ifndef __CORE_CM35P_H_DEPENDANT
+#define __CORE_CM35P_H_DEPENDANT
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/* check device defines and use defaults */
+#if defined __CHECK_DEVICE_DEFINES
+ #ifndef __CM35P_REV
+ #define __CM35P_REV 0x0000U
+ #warning "__CM35P_REV not defined in device header file; using default!"
+ #endif
+
+ #ifndef __FPU_PRESENT
+ #define __FPU_PRESENT 0U
+ #warning "__FPU_PRESENT not defined in device header file; using default!"
+ #endif
+
+ #ifndef __MPU_PRESENT
+ #define __MPU_PRESENT 0U
+ #warning "__MPU_PRESENT not defined in device header file; using default!"
+ #endif
+
+ #ifndef __SAUREGION_PRESENT
+ #define __SAUREGION_PRESENT 0U
+ #warning "__SAUREGION_PRESENT not defined in device header file; using default!"
+ #endif
+
+ #ifndef __DSP_PRESENT
+ #define __DSP_PRESENT 0U
+ #warning "__DSP_PRESENT not defined in device header file; using default!"
+ #endif
+
+ #ifndef __NVIC_PRIO_BITS
+ #define __NVIC_PRIO_BITS 3U
+ #warning "__NVIC_PRIO_BITS not defined in device header file; using default!"
+ #endif
+
+ #ifndef __Vendor_SysTickConfig
+ #define __Vendor_SysTickConfig 0U
+ #warning "__Vendor_SysTickConfig not defined in device header file; using default!"
+ #endif
+#endif
+
+/* IO definitions (access restrictions to peripheral registers) */
+/**
+ \defgroup CMSIS_glob_defs CMSIS Global Defines
+
+ IO Type Qualifiers are used
+ \li to specify the access to peripheral variables.
+ \li for automatic generation of peripheral register debug information.
+*/
+#ifdef __cplusplus
+ #define __I volatile /*!< Defines 'read only' permissions */
+#else
+ #define __I volatile const /*!< Defines 'read only' permissions */
+#endif
+#define __O volatile /*!< Defines 'write only' permissions */
+#define __IO volatile /*!< Defines 'read / write' permissions */
+
+/* following defines should be used for structure members */
+#define __IM volatile const /*! Defines 'read only' structure member permissions */
+#define __OM volatile /*! Defines 'write only' structure member permissions */
+#define __IOM volatile /*! Defines 'read / write' structure member permissions */
+
+/*@} end of group Cortex_M35P */
+
+
+
+/*******************************************************************************
+ * Register Abstraction
+ Core Register contain:
+ - Core Register
+ - Core NVIC Register
+ - Core SCB Register
+ - Core SysTick Register
+ - Core Debug Register
+ - Core MPU Register
+ - Core SAU Register
+ - Core FPU Register
+ ******************************************************************************/
+/**
+ \defgroup CMSIS_core_register Defines and Type Definitions
+ \brief Type definitions and defines for Cortex-M processor based devices.
+*/
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_CORE Status and Control Registers
+ \brief Core Register type definitions.
+ @{
+ */
+
+/**
+ \brief Union type to access the Application Program Status Register (APSR).
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t _reserved0:16; /*!< bit: 0..15 Reserved */
+ uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */
+ uint32_t _reserved1:7; /*!< bit: 20..26 Reserved */
+ uint32_t Q:1; /*!< bit: 27 Saturation condition flag */
+ uint32_t V:1; /*!< bit: 28 Overflow condition code flag */
+ uint32_t C:1; /*!< bit: 29 Carry condition code flag */
+ uint32_t Z:1; /*!< bit: 30 Zero condition code flag */
+ uint32_t N:1; /*!< bit: 31 Negative condition code flag */
+ } b; /*!< Structure used for bit access */
+ uint32_t w; /*!< Type used for word access */
+} APSR_Type;
+
+/* APSR Register Definitions */
+#define APSR_N_Pos 31U /*!< APSR: N Position */
+#define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */
+
+#define APSR_Z_Pos 30U /*!< APSR: Z Position */
+#define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */
+
+#define APSR_C_Pos 29U /*!< APSR: C Position */
+#define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */
+
+#define APSR_V_Pos 28U /*!< APSR: V Position */
+#define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */
+
+#define APSR_Q_Pos 27U /*!< APSR: Q Position */
+#define APSR_Q_Msk (1UL << APSR_Q_Pos) /*!< APSR: Q Mask */
+
+#define APSR_GE_Pos 16U /*!< APSR: GE Position */
+#define APSR_GE_Msk (0xFUL << APSR_GE_Pos) /*!< APSR: GE Mask */
+
+
+/**
+ \brief Union type to access the Interrupt Program Status Register (IPSR).
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */
+ uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */
+ } b; /*!< Structure used for bit access */
+ uint32_t w; /*!< Type used for word access */
+} IPSR_Type;
+
+/* IPSR Register Definitions */
+#define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */
+#define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */
+
+
+/**
+ \brief Union type to access the Special-Purpose Program Status Registers (xPSR).
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */
+ uint32_t _reserved0:7; /*!< bit: 9..15 Reserved */
+ uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */
+ uint32_t _reserved1:4; /*!< bit: 20..23 Reserved */
+ uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */
+ uint32_t IT:2; /*!< bit: 25..26 saved IT state (read 0) */
+ uint32_t Q:1; /*!< bit: 27 Saturation condition flag */
+ uint32_t V:1; /*!< bit: 28 Overflow condition code flag */
+ uint32_t C:1; /*!< bit: 29 Carry condition code flag */
+ uint32_t Z:1; /*!< bit: 30 Zero condition code flag */
+ uint32_t N:1; /*!< bit: 31 Negative condition code flag */
+ } b; /*!< Structure used for bit access */
+ uint32_t w; /*!< Type used for word access */
+} xPSR_Type;
+
+/* xPSR Register Definitions */
+#define xPSR_N_Pos 31U /*!< xPSR: N Position */
+#define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */
+
+#define xPSR_Z_Pos 30U /*!< xPSR: Z Position */
+#define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */
+
+#define xPSR_C_Pos 29U /*!< xPSR: C Position */
+#define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */
+
+#define xPSR_V_Pos 28U /*!< xPSR: V Position */
+#define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */
+
+#define xPSR_Q_Pos 27U /*!< xPSR: Q Position */
+#define xPSR_Q_Msk (1UL << xPSR_Q_Pos) /*!< xPSR: Q Mask */
+
+#define xPSR_IT_Pos 25U /*!< xPSR: IT Position */
+#define xPSR_IT_Msk (3UL << xPSR_IT_Pos) /*!< xPSR: IT Mask */
+
+#define xPSR_T_Pos 24U /*!< xPSR: T Position */
+#define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */
+
+#define xPSR_GE_Pos 16U /*!< xPSR: GE Position */
+#define xPSR_GE_Msk (0xFUL << xPSR_GE_Pos) /*!< xPSR: GE Mask */
+
+#define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */
+#define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */
+
+
+/**
+ \brief Union type to access the Control Registers (CONTROL).
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */
+ uint32_t SPSEL:1; /*!< bit: 1 Stack-pointer select */
+ uint32_t FPCA:1; /*!< bit: 2 Floating-point context active */
+ uint32_t SFPA:1; /*!< bit: 3 Secure floating-point active */
+ uint32_t _reserved1:28; /*!< bit: 4..31 Reserved */
+ } b; /*!< Structure used for bit access */
+ uint32_t w; /*!< Type used for word access */
+} CONTROL_Type;
+
+/* CONTROL Register Definitions */
+#define CONTROL_SFPA_Pos 3U /*!< CONTROL: SFPA Position */
+#define CONTROL_SFPA_Msk (1UL << CONTROL_SFPA_Pos) /*!< CONTROL: SFPA Mask */
+
+#define CONTROL_FPCA_Pos 2U /*!< CONTROL: FPCA Position */
+#define CONTROL_FPCA_Msk (1UL << CONTROL_FPCA_Pos) /*!< CONTROL: FPCA Mask */
+
+#define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */
+#define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */
+
+#define CONTROL_nPRIV_Pos 0U /*!< CONTROL: nPRIV Position */
+#define CONTROL_nPRIV_Msk (1UL /*<< CONTROL_nPRIV_Pos*/) /*!< CONTROL: nPRIV Mask */
+
+/*@} end of group CMSIS_CORE */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC)
+ \brief Type definitions for the NVIC Registers
+ @{
+ */
+
+/**
+ \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC).
+ */
+typedef struct
+{
+ __IOM uint32_t ISER[16U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */
+ uint32_t RESERVED0[16U];
+ __IOM uint32_t ICER[16U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */
+ uint32_t RSERVED1[16U];
+ __IOM uint32_t ISPR[16U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */
+ uint32_t RESERVED2[16U];
+ __IOM uint32_t ICPR[16U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */
+ uint32_t RESERVED3[16U];
+ __IOM uint32_t IABR[16U]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */
+ uint32_t RESERVED4[16U];
+ __IOM uint32_t ITNS[16U]; /*!< Offset: 0x280 (R/W) Interrupt Non-Secure State Register */
+ uint32_t RESERVED5[16U];
+ __IOM uint8_t IPR[496U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register (8Bit wide) */
+ uint32_t RESERVED6[580U];
+ __OM uint32_t STIR; /*!< Offset: 0xE00 ( /W) Software Trigger Interrupt Register */
+} NVIC_Type;
+
+/* Software Triggered Interrupt Register Definitions */
+#define NVIC_STIR_INTID_Pos 0U /*!< STIR: INTLINESNUM Position */
+#define NVIC_STIR_INTID_Msk (0x1FFUL /*<< NVIC_STIR_INTID_Pos*/) /*!< STIR: INTLINESNUM Mask */
+
+/*@} end of group CMSIS_NVIC */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_SCB System Control Block (SCB)
+ \brief Type definitions for the System Control Block Registers
+ @{
+ */
+
+/**
+ \brief Structure type to access the System Control Block (SCB).
+ */
+typedef struct
+{
+ __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */
+ __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */
+ __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */
+ __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */
+ __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */
+ __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */
+ __IOM uint8_t SHPR[12U]; /*!< Offset: 0x018 (R/W) System Handlers Priority Registers (4-7, 8-11, 12-15) */
+ __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */
+ __IOM uint32_t CFSR; /*!< Offset: 0x028 (R/W) Configurable Fault Status Register */
+ __IOM uint32_t HFSR; /*!< Offset: 0x02C (R/W) HardFault Status Register */
+ __IOM uint32_t DFSR; /*!< Offset: 0x030 (R/W) Debug Fault Status Register */
+ __IOM uint32_t MMFAR; /*!< Offset: 0x034 (R/W) MemManage Fault Address Register */
+ __IOM uint32_t BFAR; /*!< Offset: 0x038 (R/W) BusFault Address Register */
+ __IOM uint32_t AFSR; /*!< Offset: 0x03C (R/W) Auxiliary Fault Status Register */
+ __IM uint32_t ID_PFR[2U]; /*!< Offset: 0x040 (R/ ) Processor Feature Register */
+ __IM uint32_t ID_DFR; /*!< Offset: 0x048 (R/ ) Debug Feature Register */
+ __IM uint32_t ID_ADR; /*!< Offset: 0x04C (R/ ) Auxiliary Feature Register */
+ __IM uint32_t ID_MMFR[4U]; /*!< Offset: 0x050 (R/ ) Memory Model Feature Register */
+ __IM uint32_t ID_ISAR[6U]; /*!< Offset: 0x060 (R/ ) Instruction Set Attributes Register */
+ __IM uint32_t CLIDR; /*!< Offset: 0x078 (R/ ) Cache Level ID register */
+ __IM uint32_t CTR; /*!< Offset: 0x07C (R/ ) Cache Type register */
+ __IM uint32_t CCSIDR; /*!< Offset: 0x080 (R/ ) Cache Size ID Register */
+ __IOM uint32_t CSSELR; /*!< Offset: 0x084 (R/W) Cache Size Selection Register */
+ __IOM uint32_t CPACR; /*!< Offset: 0x088 (R/W) Coprocessor Access Control Register */
+ __IOM uint32_t NSACR; /*!< Offset: 0x08C (R/W) Non-Secure Access Control Register */
+ uint32_t RESERVED3[92U];
+ __OM uint32_t STIR; /*!< Offset: 0x200 ( /W) Software Triggered Interrupt Register */
+ uint32_t RESERVED4[15U];
+ __IM uint32_t MVFR0; /*!< Offset: 0x240 (R/ ) Media and VFP Feature Register 0 */
+ __IM uint32_t MVFR1; /*!< Offset: 0x244 (R/ ) Media and VFP Feature Register 1 */
+ __IM uint32_t MVFR2; /*!< Offset: 0x248 (R/ ) Media and VFP Feature Register 2 */
+ uint32_t RESERVED5[1U];
+ __OM uint32_t ICIALLU; /*!< Offset: 0x250 ( /W) I-Cache Invalidate All to PoU */
+ uint32_t RESERVED6[1U];
+ __OM uint32_t ICIMVAU; /*!< Offset: 0x258 ( /W) I-Cache Invalidate by MVA to PoU */
+ __OM uint32_t DCIMVAC; /*!< Offset: 0x25C ( /W) D-Cache Invalidate by MVA to PoC */
+ __OM uint32_t DCISW; /*!< Offset: 0x260 ( /W) D-Cache Invalidate by Set-way */
+ __OM uint32_t DCCMVAU; /*!< Offset: 0x264 ( /W) D-Cache Clean by MVA to PoU */
+ __OM uint32_t DCCMVAC; /*!< Offset: 0x268 ( /W) D-Cache Clean by MVA to PoC */
+ __OM uint32_t DCCSW; /*!< Offset: 0x26C ( /W) D-Cache Clean by Set-way */
+ __OM uint32_t DCCIMVAC; /*!< Offset: 0x270 ( /W) D-Cache Clean and Invalidate by MVA to PoC */
+ __OM uint32_t DCCISW; /*!< Offset: 0x274 ( /W) D-Cache Clean and Invalidate by Set-way */
+} SCB_Type;
+
+/* SCB CPUID Register Definitions */
+#define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */
+#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */
+
+#define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */
+#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */
+
+#define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */
+#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */
+
+#define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */
+#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */
+
+#define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */
+#define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */
+
+/* SCB Interrupt Control State Register Definitions */
+#define SCB_ICSR_PENDNMISET_Pos 31U /*!< SCB ICSR: PENDNMISET Position */
+#define SCB_ICSR_PENDNMISET_Msk (1UL << SCB_ICSR_PENDNMISET_Pos) /*!< SCB ICSR: PENDNMISET Mask */
+
+#define SCB_ICSR_NMIPENDSET_Pos SCB_ICSR_PENDNMISET_Pos /*!< SCB ICSR: NMIPENDSET Position, backward compatibility */
+#define SCB_ICSR_NMIPENDSET_Msk SCB_ICSR_PENDNMISET_Msk /*!< SCB ICSR: NMIPENDSET Mask, backward compatibility */
+
+#define SCB_ICSR_PENDNMICLR_Pos 30U /*!< SCB ICSR: PENDNMICLR Position */
+#define SCB_ICSR_PENDNMICLR_Msk (1UL << SCB_ICSR_PENDNMICLR_Pos) /*!< SCB ICSR: PENDNMICLR Mask */
+
+#define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */
+#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */
+
+#define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */
+#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */
+
+#define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */
+#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */
+
+#define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */
+#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */
+
+#define SCB_ICSR_STTNS_Pos 24U /*!< SCB ICSR: STTNS Position (Security Extension) */
+#define SCB_ICSR_STTNS_Msk (1UL << SCB_ICSR_STTNS_Pos) /*!< SCB ICSR: STTNS Mask (Security Extension) */
+
+#define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */
+#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */
+
+#define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */
+#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */
+
+#define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */
+#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */
+
+#define SCB_ICSR_RETTOBASE_Pos 11U /*!< SCB ICSR: RETTOBASE Position */
+#define SCB_ICSR_RETTOBASE_Msk (1UL << SCB_ICSR_RETTOBASE_Pos) /*!< SCB ICSR: RETTOBASE Mask */
+
+#define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */
+#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */
+
+/* SCB Vector Table Offset Register Definitions */
+#define SCB_VTOR_TBLOFF_Pos 7U /*!< SCB VTOR: TBLOFF Position */
+#define SCB_VTOR_TBLOFF_Msk (0x1FFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */
+
+/* SCB Application Interrupt and Reset Control Register Definitions */
+#define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */
+#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */
+
+#define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */
+#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */
+
+#define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */
+#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */
+
+#define SCB_AIRCR_PRIS_Pos 14U /*!< SCB AIRCR: PRIS Position */
+#define SCB_AIRCR_PRIS_Msk (1UL << SCB_AIRCR_PRIS_Pos) /*!< SCB AIRCR: PRIS Mask */
+
+#define SCB_AIRCR_BFHFNMINS_Pos 13U /*!< SCB AIRCR: BFHFNMINS Position */
+#define SCB_AIRCR_BFHFNMINS_Msk (1UL << SCB_AIRCR_BFHFNMINS_Pos) /*!< SCB AIRCR: BFHFNMINS Mask */
+
+#define SCB_AIRCR_PRIGROUP_Pos 8U /*!< SCB AIRCR: PRIGROUP Position */
+#define SCB_AIRCR_PRIGROUP_Msk (7UL << SCB_AIRCR_PRIGROUP_Pos) /*!< SCB AIRCR: PRIGROUP Mask */
+
+#define SCB_AIRCR_SYSRESETREQS_Pos 3U /*!< SCB AIRCR: SYSRESETREQS Position */
+#define SCB_AIRCR_SYSRESETREQS_Msk (1UL << SCB_AIRCR_SYSRESETREQS_Pos) /*!< SCB AIRCR: SYSRESETREQS Mask */
+
+#define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */
+#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */
+
+#define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */
+#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */
+
+/* SCB System Control Register Definitions */
+#define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */
+#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */
+
+#define SCB_SCR_SLEEPDEEPS_Pos 3U /*!< SCB SCR: SLEEPDEEPS Position */
+#define SCB_SCR_SLEEPDEEPS_Msk (1UL << SCB_SCR_SLEEPDEEPS_Pos) /*!< SCB SCR: SLEEPDEEPS Mask */
+
+#define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */
+#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */
+
+#define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */
+#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */
+
+/* SCB Configuration Control Register Definitions */
+#define SCB_CCR_BP_Pos 18U /*!< SCB CCR: BP Position */
+#define SCB_CCR_BP_Msk (1UL << SCB_CCR_BP_Pos) /*!< SCB CCR: BP Mask */
+
+#define SCB_CCR_IC_Pos 17U /*!< SCB CCR: IC Position */
+#define SCB_CCR_IC_Msk (1UL << SCB_CCR_IC_Pos) /*!< SCB CCR: IC Mask */
+
+#define SCB_CCR_DC_Pos 16U /*!< SCB CCR: DC Position */
+#define SCB_CCR_DC_Msk (1UL << SCB_CCR_DC_Pos) /*!< SCB CCR: DC Mask */
+
+#define SCB_CCR_STKOFHFNMIGN_Pos 10U /*!< SCB CCR: STKOFHFNMIGN Position */
+#define SCB_CCR_STKOFHFNMIGN_Msk (1UL << SCB_CCR_STKOFHFNMIGN_Pos) /*!< SCB CCR: STKOFHFNMIGN Mask */
+
+#define SCB_CCR_BFHFNMIGN_Pos 8U /*!< SCB CCR: BFHFNMIGN Position */
+#define SCB_CCR_BFHFNMIGN_Msk (1UL << SCB_CCR_BFHFNMIGN_Pos) /*!< SCB CCR: BFHFNMIGN Mask */
+
+#define SCB_CCR_DIV_0_TRP_Pos 4U /*!< SCB CCR: DIV_0_TRP Position */
+#define SCB_CCR_DIV_0_TRP_Msk (1UL << SCB_CCR_DIV_0_TRP_Pos) /*!< SCB CCR: DIV_0_TRP Mask */
+
+#define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */
+#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */
+
+#define SCB_CCR_USERSETMPEND_Pos 1U /*!< SCB CCR: USERSETMPEND Position */
+#define SCB_CCR_USERSETMPEND_Msk (1UL << SCB_CCR_USERSETMPEND_Pos) /*!< SCB CCR: USERSETMPEND Mask */
+
+/* SCB System Handler Control and State Register Definitions */
+#define SCB_SHCSR_HARDFAULTPENDED_Pos 21U /*!< SCB SHCSR: HARDFAULTPENDED Position */
+#define SCB_SHCSR_HARDFAULTPENDED_Msk (1UL << SCB_SHCSR_HARDFAULTPENDED_Pos) /*!< SCB SHCSR: HARDFAULTPENDED Mask */
+
+#define SCB_SHCSR_SECUREFAULTPENDED_Pos 20U /*!< SCB SHCSR: SECUREFAULTPENDED Position */
+#define SCB_SHCSR_SECUREFAULTPENDED_Msk (1UL << SCB_SHCSR_SECUREFAULTPENDED_Pos) /*!< SCB SHCSR: SECUREFAULTPENDED Mask */
+
+#define SCB_SHCSR_SECUREFAULTENA_Pos 19U /*!< SCB SHCSR: SECUREFAULTENA Position */
+#define SCB_SHCSR_SECUREFAULTENA_Msk (1UL << SCB_SHCSR_SECUREFAULTENA_Pos) /*!< SCB SHCSR: SECUREFAULTENA Mask */
+
+#define SCB_SHCSR_USGFAULTENA_Pos 18U /*!< SCB SHCSR: USGFAULTENA Position */
+#define SCB_SHCSR_USGFAULTENA_Msk (1UL << SCB_SHCSR_USGFAULTENA_Pos) /*!< SCB SHCSR: USGFAULTENA Mask */
+
+#define SCB_SHCSR_BUSFAULTENA_Pos 17U /*!< SCB SHCSR: BUSFAULTENA Position */
+#define SCB_SHCSR_BUSFAULTENA_Msk (1UL << SCB_SHCSR_BUSFAULTENA_Pos) /*!< SCB SHCSR: BUSFAULTENA Mask */
+
+#define SCB_SHCSR_MEMFAULTENA_Pos 16U /*!< SCB SHCSR: MEMFAULTENA Position */
+#define SCB_SHCSR_MEMFAULTENA_Msk (1UL << SCB_SHCSR_MEMFAULTENA_Pos) /*!< SCB SHCSR: MEMFAULTENA Mask */
+
+#define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */
+#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */
+
+#define SCB_SHCSR_BUSFAULTPENDED_Pos 14U /*!< SCB SHCSR: BUSFAULTPENDED Position */
+#define SCB_SHCSR_BUSFAULTPENDED_Msk (1UL << SCB_SHCSR_BUSFAULTPENDED_Pos) /*!< SCB SHCSR: BUSFAULTPENDED Mask */
+
+#define SCB_SHCSR_MEMFAULTPENDED_Pos 13U /*!< SCB SHCSR: MEMFAULTPENDED Position */
+#define SCB_SHCSR_MEMFAULTPENDED_Msk (1UL << SCB_SHCSR_MEMFAULTPENDED_Pos) /*!< SCB SHCSR: MEMFAULTPENDED Mask */
+
+#define SCB_SHCSR_USGFAULTPENDED_Pos 12U /*!< SCB SHCSR: USGFAULTPENDED Position */
+#define SCB_SHCSR_USGFAULTPENDED_Msk (1UL << SCB_SHCSR_USGFAULTPENDED_Pos) /*!< SCB SHCSR: USGFAULTPENDED Mask */
+
+#define SCB_SHCSR_SYSTICKACT_Pos 11U /*!< SCB SHCSR: SYSTICKACT Position */
+#define SCB_SHCSR_SYSTICKACT_Msk (1UL << SCB_SHCSR_SYSTICKACT_Pos) /*!< SCB SHCSR: SYSTICKACT Mask */
+
+#define SCB_SHCSR_PENDSVACT_Pos 10U /*!< SCB SHCSR: PENDSVACT Position */
+#define SCB_SHCSR_PENDSVACT_Msk (1UL << SCB_SHCSR_PENDSVACT_Pos) /*!< SCB SHCSR: PENDSVACT Mask */
+
+#define SCB_SHCSR_MONITORACT_Pos 8U /*!< SCB SHCSR: MONITORACT Position */
+#define SCB_SHCSR_MONITORACT_Msk (1UL << SCB_SHCSR_MONITORACT_Pos) /*!< SCB SHCSR: MONITORACT Mask */
+
+#define SCB_SHCSR_SVCALLACT_Pos 7U /*!< SCB SHCSR: SVCALLACT Position */
+#define SCB_SHCSR_SVCALLACT_Msk (1UL << SCB_SHCSR_SVCALLACT_Pos) /*!< SCB SHCSR: SVCALLACT Mask */
+
+#define SCB_SHCSR_NMIACT_Pos 5U /*!< SCB SHCSR: NMIACT Position */
+#define SCB_SHCSR_NMIACT_Msk (1UL << SCB_SHCSR_NMIACT_Pos) /*!< SCB SHCSR: NMIACT Mask */
+
+#define SCB_SHCSR_SECUREFAULTACT_Pos 4U /*!< SCB SHCSR: SECUREFAULTACT Position */
+#define SCB_SHCSR_SECUREFAULTACT_Msk (1UL << SCB_SHCSR_SECUREFAULTACT_Pos) /*!< SCB SHCSR: SECUREFAULTACT Mask */
+
+#define SCB_SHCSR_USGFAULTACT_Pos 3U /*!< SCB SHCSR: USGFAULTACT Position */
+#define SCB_SHCSR_USGFAULTACT_Msk (1UL << SCB_SHCSR_USGFAULTACT_Pos) /*!< SCB SHCSR: USGFAULTACT Mask */
+
+#define SCB_SHCSR_HARDFAULTACT_Pos 2U /*!< SCB SHCSR: HARDFAULTACT Position */
+#define SCB_SHCSR_HARDFAULTACT_Msk (1UL << SCB_SHCSR_HARDFAULTACT_Pos) /*!< SCB SHCSR: HARDFAULTACT Mask */
+
+#define SCB_SHCSR_BUSFAULTACT_Pos 1U /*!< SCB SHCSR: BUSFAULTACT Position */
+#define SCB_SHCSR_BUSFAULTACT_Msk (1UL << SCB_SHCSR_BUSFAULTACT_Pos) /*!< SCB SHCSR: BUSFAULTACT Mask */
+
+#define SCB_SHCSR_MEMFAULTACT_Pos 0U /*!< SCB SHCSR: MEMFAULTACT Position */
+#define SCB_SHCSR_MEMFAULTACT_Msk (1UL /*<< SCB_SHCSR_MEMFAULTACT_Pos*/) /*!< SCB SHCSR: MEMFAULTACT Mask */
+
+/* SCB Configurable Fault Status Register Definitions */
+#define SCB_CFSR_USGFAULTSR_Pos 16U /*!< SCB CFSR: Usage Fault Status Register Position */
+#define SCB_CFSR_USGFAULTSR_Msk (0xFFFFUL << SCB_CFSR_USGFAULTSR_Pos) /*!< SCB CFSR: Usage Fault Status Register Mask */
+
+#define SCB_CFSR_BUSFAULTSR_Pos 8U /*!< SCB CFSR: Bus Fault Status Register Position */
+#define SCB_CFSR_BUSFAULTSR_Msk (0xFFUL << SCB_CFSR_BUSFAULTSR_Pos) /*!< SCB CFSR: Bus Fault Status Register Mask */
+
+#define SCB_CFSR_MEMFAULTSR_Pos 0U /*!< SCB CFSR: Memory Manage Fault Status Register Position */
+#define SCB_CFSR_MEMFAULTSR_Msk (0xFFUL /*<< SCB_CFSR_MEMFAULTSR_Pos*/) /*!< SCB CFSR: Memory Manage Fault Status Register Mask */
+
+/* MemManage Fault Status Register (part of SCB Configurable Fault Status Register) */
+#define SCB_CFSR_MMARVALID_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 7U) /*!< SCB CFSR (MMFSR): MMARVALID Position */
+#define SCB_CFSR_MMARVALID_Msk (1UL << SCB_CFSR_MMARVALID_Pos) /*!< SCB CFSR (MMFSR): MMARVALID Mask */
+
+#define SCB_CFSR_MLSPERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 5U) /*!< SCB CFSR (MMFSR): MLSPERR Position */
+#define SCB_CFSR_MLSPERR_Msk (1UL << SCB_CFSR_MLSPERR_Pos) /*!< SCB CFSR (MMFSR): MLSPERR Mask */
+
+#define SCB_CFSR_MSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 4U) /*!< SCB CFSR (MMFSR): MSTKERR Position */
+#define SCB_CFSR_MSTKERR_Msk (1UL << SCB_CFSR_MSTKERR_Pos) /*!< SCB CFSR (MMFSR): MSTKERR Mask */
+
+#define SCB_CFSR_MUNSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 3U) /*!< SCB CFSR (MMFSR): MUNSTKERR Position */
+#define SCB_CFSR_MUNSTKERR_Msk (1UL << SCB_CFSR_MUNSTKERR_Pos) /*!< SCB CFSR (MMFSR): MUNSTKERR Mask */
+
+#define SCB_CFSR_DACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 1U) /*!< SCB CFSR (MMFSR): DACCVIOL Position */
+#define SCB_CFSR_DACCVIOL_Msk (1UL << SCB_CFSR_DACCVIOL_Pos) /*!< SCB CFSR (MMFSR): DACCVIOL Mask */
+
+#define SCB_CFSR_IACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 0U) /*!< SCB CFSR (MMFSR): IACCVIOL Position */
+#define SCB_CFSR_IACCVIOL_Msk (1UL /*<< SCB_CFSR_IACCVIOL_Pos*/) /*!< SCB CFSR (MMFSR): IACCVIOL Mask */
+
+/* BusFault Status Register (part of SCB Configurable Fault Status Register) */
+#define SCB_CFSR_BFARVALID_Pos (SCB_CFSR_BUSFAULTSR_Pos + 7U) /*!< SCB CFSR (BFSR): BFARVALID Position */
+#define SCB_CFSR_BFARVALID_Msk (1UL << SCB_CFSR_BFARVALID_Pos) /*!< SCB CFSR (BFSR): BFARVALID Mask */
+
+#define SCB_CFSR_LSPERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 5U) /*!< SCB CFSR (BFSR): LSPERR Position */
+#define SCB_CFSR_LSPERR_Msk (1UL << SCB_CFSR_LSPERR_Pos) /*!< SCB CFSR (BFSR): LSPERR Mask */
+
+#define SCB_CFSR_STKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 4U) /*!< SCB CFSR (BFSR): STKERR Position */
+#define SCB_CFSR_STKERR_Msk (1UL << SCB_CFSR_STKERR_Pos) /*!< SCB CFSR (BFSR): STKERR Mask */
+
+#define SCB_CFSR_UNSTKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 3U) /*!< SCB CFSR (BFSR): UNSTKERR Position */
+#define SCB_CFSR_UNSTKERR_Msk (1UL << SCB_CFSR_UNSTKERR_Pos) /*!< SCB CFSR (BFSR): UNSTKERR Mask */
+
+#define SCB_CFSR_IMPRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 2U) /*!< SCB CFSR (BFSR): IMPRECISERR Position */
+#define SCB_CFSR_IMPRECISERR_Msk (1UL << SCB_CFSR_IMPRECISERR_Pos) /*!< SCB CFSR (BFSR): IMPRECISERR Mask */
+
+#define SCB_CFSR_PRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 1U) /*!< SCB CFSR (BFSR): PRECISERR Position */
+#define SCB_CFSR_PRECISERR_Msk (1UL << SCB_CFSR_PRECISERR_Pos) /*!< SCB CFSR (BFSR): PRECISERR Mask */
+
+#define SCB_CFSR_IBUSERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 0U) /*!< SCB CFSR (BFSR): IBUSERR Position */
+#define SCB_CFSR_IBUSERR_Msk (1UL << SCB_CFSR_IBUSERR_Pos) /*!< SCB CFSR (BFSR): IBUSERR Mask */
+
+/* UsageFault Status Register (part of SCB Configurable Fault Status Register) */
+#define SCB_CFSR_DIVBYZERO_Pos (SCB_CFSR_USGFAULTSR_Pos + 9U) /*!< SCB CFSR (UFSR): DIVBYZERO Position */
+#define SCB_CFSR_DIVBYZERO_Msk (1UL << SCB_CFSR_DIVBYZERO_Pos) /*!< SCB CFSR (UFSR): DIVBYZERO Mask */
+
+#define SCB_CFSR_UNALIGNED_Pos (SCB_CFSR_USGFAULTSR_Pos + 8U) /*!< SCB CFSR (UFSR): UNALIGNED Position */
+#define SCB_CFSR_UNALIGNED_Msk (1UL << SCB_CFSR_UNALIGNED_Pos) /*!< SCB CFSR (UFSR): UNALIGNED Mask */
+
+#define SCB_CFSR_STKOF_Pos (SCB_CFSR_USGFAULTSR_Pos + 4U) /*!< SCB CFSR (UFSR): STKOF Position */
+#define SCB_CFSR_STKOF_Msk (1UL << SCB_CFSR_STKOF_Pos) /*!< SCB CFSR (UFSR): STKOF Mask */
+
+#define SCB_CFSR_NOCP_Pos (SCB_CFSR_USGFAULTSR_Pos + 3U) /*!< SCB CFSR (UFSR): NOCP Position */
+#define SCB_CFSR_NOCP_Msk (1UL << SCB_CFSR_NOCP_Pos) /*!< SCB CFSR (UFSR): NOCP Mask */
+
+#define SCB_CFSR_INVPC_Pos (SCB_CFSR_USGFAULTSR_Pos + 2U) /*!< SCB CFSR (UFSR): INVPC Position */
+#define SCB_CFSR_INVPC_Msk (1UL << SCB_CFSR_INVPC_Pos) /*!< SCB CFSR (UFSR): INVPC Mask */
+
+#define SCB_CFSR_INVSTATE_Pos (SCB_CFSR_USGFAULTSR_Pos + 1U) /*!< SCB CFSR (UFSR): INVSTATE Position */
+#define SCB_CFSR_INVSTATE_Msk (1UL << SCB_CFSR_INVSTATE_Pos) /*!< SCB CFSR (UFSR): INVSTATE Mask */
+
+#define SCB_CFSR_UNDEFINSTR_Pos (SCB_CFSR_USGFAULTSR_Pos + 0U) /*!< SCB CFSR (UFSR): UNDEFINSTR Position */
+#define SCB_CFSR_UNDEFINSTR_Msk (1UL << SCB_CFSR_UNDEFINSTR_Pos) /*!< SCB CFSR (UFSR): UNDEFINSTR Mask */
+
+/* SCB Hard Fault Status Register Definitions */
+#define SCB_HFSR_DEBUGEVT_Pos 31U /*!< SCB HFSR: DEBUGEVT Position */
+#define SCB_HFSR_DEBUGEVT_Msk (1UL << SCB_HFSR_DEBUGEVT_Pos) /*!< SCB HFSR: DEBUGEVT Mask */
+
+#define SCB_HFSR_FORCED_Pos 30U /*!< SCB HFSR: FORCED Position */
+#define SCB_HFSR_FORCED_Msk (1UL << SCB_HFSR_FORCED_Pos) /*!< SCB HFSR: FORCED Mask */
+
+#define SCB_HFSR_VECTTBL_Pos 1U /*!< SCB HFSR: VECTTBL Position */
+#define SCB_HFSR_VECTTBL_Msk (1UL << SCB_HFSR_VECTTBL_Pos) /*!< SCB HFSR: VECTTBL Mask */
+
+/* SCB Debug Fault Status Register Definitions */
+#define SCB_DFSR_EXTERNAL_Pos 4U /*!< SCB DFSR: EXTERNAL Position */
+#define SCB_DFSR_EXTERNAL_Msk (1UL << SCB_DFSR_EXTERNAL_Pos) /*!< SCB DFSR: EXTERNAL Mask */
+
+#define SCB_DFSR_VCATCH_Pos 3U /*!< SCB DFSR: VCATCH Position */
+#define SCB_DFSR_VCATCH_Msk (1UL << SCB_DFSR_VCATCH_Pos) /*!< SCB DFSR: VCATCH Mask */
+
+#define SCB_DFSR_DWTTRAP_Pos 2U /*!< SCB DFSR: DWTTRAP Position */
+#define SCB_DFSR_DWTTRAP_Msk (1UL << SCB_DFSR_DWTTRAP_Pos) /*!< SCB DFSR: DWTTRAP Mask */
+
+#define SCB_DFSR_BKPT_Pos 1U /*!< SCB DFSR: BKPT Position */
+#define SCB_DFSR_BKPT_Msk (1UL << SCB_DFSR_BKPT_Pos) /*!< SCB DFSR: BKPT Mask */
+
+#define SCB_DFSR_HALTED_Pos 0U /*!< SCB DFSR: HALTED Position */
+#define SCB_DFSR_HALTED_Msk (1UL /*<< SCB_DFSR_HALTED_Pos*/) /*!< SCB DFSR: HALTED Mask */
+
+/* SCB Non-Secure Access Control Register Definitions */
+#define SCB_NSACR_CP11_Pos 11U /*!< SCB NSACR: CP11 Position */
+#define SCB_NSACR_CP11_Msk (1UL << SCB_NSACR_CP11_Pos) /*!< SCB NSACR: CP11 Mask */
+
+#define SCB_NSACR_CP10_Pos 10U /*!< SCB NSACR: CP10 Position */
+#define SCB_NSACR_CP10_Msk (1UL << SCB_NSACR_CP10_Pos) /*!< SCB NSACR: CP10 Mask */
+
+#define SCB_NSACR_CPn_Pos 0U /*!< SCB NSACR: CPn Position */
+#define SCB_NSACR_CPn_Msk (1UL /*<< SCB_NSACR_CPn_Pos*/) /*!< SCB NSACR: CPn Mask */
+
+/* SCB Cache Level ID Register Definitions */
+#define SCB_CLIDR_LOUU_Pos 27U /*!< SCB CLIDR: LoUU Position */
+#define SCB_CLIDR_LOUU_Msk (7UL << SCB_CLIDR_LOUU_Pos) /*!< SCB CLIDR: LoUU Mask */
+
+#define SCB_CLIDR_LOC_Pos 24U /*!< SCB CLIDR: LoC Position */
+#define SCB_CLIDR_LOC_Msk (7UL << SCB_CLIDR_LOC_Pos) /*!< SCB CLIDR: LoC Mask */
+
+/* SCB Cache Type Register Definitions */
+#define SCB_CTR_FORMAT_Pos 29U /*!< SCB CTR: Format Position */
+#define SCB_CTR_FORMAT_Msk (7UL << SCB_CTR_FORMAT_Pos) /*!< SCB CTR: Format Mask */
+
+#define SCB_CTR_CWG_Pos 24U /*!< SCB CTR: CWG Position */
+#define SCB_CTR_CWG_Msk (0xFUL << SCB_CTR_CWG_Pos) /*!< SCB CTR: CWG Mask */
+
+#define SCB_CTR_ERG_Pos 20U /*!< SCB CTR: ERG Position */
+#define SCB_CTR_ERG_Msk (0xFUL << SCB_CTR_ERG_Pos) /*!< SCB CTR: ERG Mask */
+
+#define SCB_CTR_DMINLINE_Pos 16U /*!< SCB CTR: DminLine Position */
+#define SCB_CTR_DMINLINE_Msk (0xFUL << SCB_CTR_DMINLINE_Pos) /*!< SCB CTR: DminLine Mask */
+
+#define SCB_CTR_IMINLINE_Pos 0U /*!< SCB CTR: ImInLine Position */
+#define SCB_CTR_IMINLINE_Msk (0xFUL /*<< SCB_CTR_IMINLINE_Pos*/) /*!< SCB CTR: ImInLine Mask */
+
+/* SCB Cache Size ID Register Definitions */
+#define SCB_CCSIDR_WT_Pos 31U /*!< SCB CCSIDR: WT Position */
+#define SCB_CCSIDR_WT_Msk (1UL << SCB_CCSIDR_WT_Pos) /*!< SCB CCSIDR: WT Mask */
+
+#define SCB_CCSIDR_WB_Pos 30U /*!< SCB CCSIDR: WB Position */
+#define SCB_CCSIDR_WB_Msk (1UL << SCB_CCSIDR_WB_Pos) /*!< SCB CCSIDR: WB Mask */
+
+#define SCB_CCSIDR_RA_Pos 29U /*!< SCB CCSIDR: RA Position */
+#define SCB_CCSIDR_RA_Msk (1UL << SCB_CCSIDR_RA_Pos) /*!< SCB CCSIDR: RA Mask */
+
+#define SCB_CCSIDR_WA_Pos 28U /*!< SCB CCSIDR: WA Position */
+#define SCB_CCSIDR_WA_Msk (1UL << SCB_CCSIDR_WA_Pos) /*!< SCB CCSIDR: WA Mask */
+
+#define SCB_CCSIDR_NUMSETS_Pos 13U /*!< SCB CCSIDR: NumSets Position */
+#define SCB_CCSIDR_NUMSETS_Msk (0x7FFFUL << SCB_CCSIDR_NUMSETS_Pos) /*!< SCB CCSIDR: NumSets Mask */
+
+#define SCB_CCSIDR_ASSOCIATIVITY_Pos 3U /*!< SCB CCSIDR: Associativity Position */
+#define SCB_CCSIDR_ASSOCIATIVITY_Msk (0x3FFUL << SCB_CCSIDR_ASSOCIATIVITY_Pos) /*!< SCB CCSIDR: Associativity Mask */
+
+#define SCB_CCSIDR_LINESIZE_Pos 0U /*!< SCB CCSIDR: LineSize Position */
+#define SCB_CCSIDR_LINESIZE_Msk (7UL /*<< SCB_CCSIDR_LINESIZE_Pos*/) /*!< SCB CCSIDR: LineSize Mask */
+
+/* SCB Cache Size Selection Register Definitions */
+#define SCB_CSSELR_LEVEL_Pos 1U /*!< SCB CSSELR: Level Position */
+#define SCB_CSSELR_LEVEL_Msk (7UL << SCB_CSSELR_LEVEL_Pos) /*!< SCB CSSELR: Level Mask */
+
+#define SCB_CSSELR_IND_Pos 0U /*!< SCB CSSELR: InD Position */
+#define SCB_CSSELR_IND_Msk (1UL /*<< SCB_CSSELR_IND_Pos*/) /*!< SCB CSSELR: InD Mask */
+
+/* SCB Software Triggered Interrupt Register Definitions */
+#define SCB_STIR_INTID_Pos 0U /*!< SCB STIR: INTID Position */
+#define SCB_STIR_INTID_Msk (0x1FFUL /*<< SCB_STIR_INTID_Pos*/) /*!< SCB STIR: INTID Mask */
+
+/* SCB D-Cache Invalidate by Set-way Register Definitions */
+#define SCB_DCISW_WAY_Pos 30U /*!< SCB DCISW: Way Position */
+#define SCB_DCISW_WAY_Msk (3UL << SCB_DCISW_WAY_Pos) /*!< SCB DCISW: Way Mask */
+
+#define SCB_DCISW_SET_Pos 5U /*!< SCB DCISW: Set Position */
+#define SCB_DCISW_SET_Msk (0x1FFUL << SCB_DCISW_SET_Pos) /*!< SCB DCISW: Set Mask */
+
+/* SCB D-Cache Clean by Set-way Register Definitions */
+#define SCB_DCCSW_WAY_Pos 30U /*!< SCB DCCSW: Way Position */
+#define SCB_DCCSW_WAY_Msk (3UL << SCB_DCCSW_WAY_Pos) /*!< SCB DCCSW: Way Mask */
+
+#define SCB_DCCSW_SET_Pos 5U /*!< SCB DCCSW: Set Position */
+#define SCB_DCCSW_SET_Msk (0x1FFUL << SCB_DCCSW_SET_Pos) /*!< SCB DCCSW: Set Mask */
+
+/* SCB D-Cache Clean and Invalidate by Set-way Register Definitions */
+#define SCB_DCCISW_WAY_Pos 30U /*!< SCB DCCISW: Way Position */
+#define SCB_DCCISW_WAY_Msk (3UL << SCB_DCCISW_WAY_Pos) /*!< SCB DCCISW: Way Mask */
+
+#define SCB_DCCISW_SET_Pos 5U /*!< SCB DCCISW: Set Position */
+#define SCB_DCCISW_SET_Msk (0x1FFUL << SCB_DCCISW_SET_Pos) /*!< SCB DCCISW: Set Mask */
+
+/*@} end of group CMSIS_SCB */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_SCnSCB System Controls not in SCB (SCnSCB)
+ \brief Type definitions for the System Control and ID Register not in the SCB
+ @{
+ */
+
+/**
+ \brief Structure type to access the System Control and ID Register not in the SCB.
+ */
+typedef struct
+{
+ uint32_t RESERVED0[1U];
+ __IM uint32_t ICTR; /*!< Offset: 0x004 (R/ ) Interrupt Controller Type Register */
+ __IOM uint32_t ACTLR; /*!< Offset: 0x008 (R/W) Auxiliary Control Register */
+ __IOM uint32_t CPPWR; /*!< Offset: 0x00C (R/W) Coprocessor Power Control Register */
+} SCnSCB_Type;
+
+/* Interrupt Controller Type Register Definitions */
+#define SCnSCB_ICTR_INTLINESNUM_Pos 0U /*!< ICTR: INTLINESNUM Position */
+#define SCnSCB_ICTR_INTLINESNUM_Msk (0xFUL /*<< SCnSCB_ICTR_INTLINESNUM_Pos*/) /*!< ICTR: INTLINESNUM Mask */
+
+/*@} end of group CMSIS_SCnotSCB */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_SysTick System Tick Timer (SysTick)
+ \brief Type definitions for the System Timer Registers.
+ @{
+ */
+
+/**
+ \brief Structure type to access the System Timer (SysTick).
+ */
+typedef struct
+{
+ __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */
+ __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */
+ __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */
+ __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */
+} SysTick_Type;
+
+/* SysTick Control / Status Register Definitions */
+#define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */
+#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */
+
+#define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */
+#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */
+
+#define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */
+#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */
+
+#define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */
+#define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */
+
+/* SysTick Reload Register Definitions */
+#define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */
+#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */
+
+/* SysTick Current Register Definitions */
+#define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */
+#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */
+
+/* SysTick Calibration Register Definitions */
+#define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */
+#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */
+
+#define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */
+#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */
+
+#define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */
+#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */
+
+/*@} end of group CMSIS_SysTick */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_ITM Instrumentation Trace Macrocell (ITM)
+ \brief Type definitions for the Instrumentation Trace Macrocell (ITM)
+ @{
+ */
+
+/**
+ \brief Structure type to access the Instrumentation Trace Macrocell Register (ITM).
+ */
+typedef struct
+{
+ __OM union
+ {
+ __OM uint8_t u8; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 8-bit */
+ __OM uint16_t u16; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 16-bit */
+ __OM uint32_t u32; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 32-bit */
+ } PORT [32U]; /*!< Offset: 0x000 ( /W) ITM Stimulus Port Registers */
+ uint32_t RESERVED0[864U];
+ __IOM uint32_t TER; /*!< Offset: 0xE00 (R/W) ITM Trace Enable Register */
+ uint32_t RESERVED1[15U];
+ __IOM uint32_t TPR; /*!< Offset: 0xE40 (R/W) ITM Trace Privilege Register */
+ uint32_t RESERVED2[15U];
+ __IOM uint32_t TCR; /*!< Offset: 0xE80 (R/W) ITM Trace Control Register */
+ uint32_t RESERVED3[32U];
+ uint32_t RESERVED4[43U];
+ __OM uint32_t LAR; /*!< Offset: 0xFB0 ( /W) ITM Lock Access Register */
+ __IM uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) ITM Lock Status Register */
+ uint32_t RESERVED5[1U];
+ __IM uint32_t DEVARCH; /*!< Offset: 0xFBC (R/ ) ITM Device Architecture Register */
+ uint32_t RESERVED6[4U];
+ __IM uint32_t PID4; /*!< Offset: 0xFD0 (R/ ) ITM Peripheral Identification Register #4 */
+ __IM uint32_t PID5; /*!< Offset: 0xFD4 (R/ ) ITM Peripheral Identification Register #5 */
+ __IM uint32_t PID6; /*!< Offset: 0xFD8 (R/ ) ITM Peripheral Identification Register #6 */
+ __IM uint32_t PID7; /*!< Offset: 0xFDC (R/ ) ITM Peripheral Identification Register #7 */
+ __IM uint32_t PID0; /*!< Offset: 0xFE0 (R/ ) ITM Peripheral Identification Register #0 */
+ __IM uint32_t PID1; /*!< Offset: 0xFE4 (R/ ) ITM Peripheral Identification Register #1 */
+ __IM uint32_t PID2; /*!< Offset: 0xFE8 (R/ ) ITM Peripheral Identification Register #2 */
+ __IM uint32_t PID3; /*!< Offset: 0xFEC (R/ ) ITM Peripheral Identification Register #3 */
+ __IM uint32_t CID0; /*!< Offset: 0xFF0 (R/ ) ITM Component Identification Register #0 */
+ __IM uint32_t CID1; /*!< Offset: 0xFF4 (R/ ) ITM Component Identification Register #1 */
+ __IM uint32_t CID2; /*!< Offset: 0xFF8 (R/ ) ITM Component Identification Register #2 */
+ __IM uint32_t CID3; /*!< Offset: 0xFFC (R/ ) ITM Component Identification Register #3 */
+} ITM_Type;
+
+/* ITM Stimulus Port Register Definitions */
+#define ITM_STIM_DISABLED_Pos 1U /*!< ITM STIM: DISABLED Position */
+#define ITM_STIM_DISABLED_Msk (0x1UL << ITM_STIM_DISABLED_Pos) /*!< ITM STIM: DISABLED Mask */
+
+#define ITM_STIM_FIFOREADY_Pos 0U /*!< ITM STIM: FIFOREADY Position */
+#define ITM_STIM_FIFOREADY_Msk (0x1UL /*<< ITM_STIM_FIFOREADY_Pos*/) /*!< ITM STIM: FIFOREADY Mask */
+
+/* ITM Trace Privilege Register Definitions */
+#define ITM_TPR_PRIVMASK_Pos 0U /*!< ITM TPR: PRIVMASK Position */
+#define ITM_TPR_PRIVMASK_Msk (0xFFFFFFFFUL /*<< ITM_TPR_PRIVMASK_Pos*/) /*!< ITM TPR: PRIVMASK Mask */
+
+/* ITM Trace Control Register Definitions */
+#define ITM_TCR_BUSY_Pos 23U /*!< ITM TCR: BUSY Position */
+#define ITM_TCR_BUSY_Msk (1UL << ITM_TCR_BUSY_Pos) /*!< ITM TCR: BUSY Mask */
+
+#define ITM_TCR_TRACEBUSID_Pos 16U /*!< ITM TCR: ATBID Position */
+#define ITM_TCR_TRACEBUSID_Msk (0x7FUL << ITM_TCR_TRACEBUSID_Pos) /*!< ITM TCR: ATBID Mask */
+
+#define ITM_TCR_GTSFREQ_Pos 10U /*!< ITM TCR: Global timestamp frequency Position */
+#define ITM_TCR_GTSFREQ_Msk (3UL << ITM_TCR_GTSFREQ_Pos) /*!< ITM TCR: Global timestamp frequency Mask */
+
+#define ITM_TCR_TSPRESCALE_Pos 8U /*!< ITM TCR: TSPRESCALE Position */
+#define ITM_TCR_TSPRESCALE_Msk (3UL << ITM_TCR_TSPRESCALE_Pos) /*!< ITM TCR: TSPRESCALE Mask */
+
+#define ITM_TCR_STALLENA_Pos 5U /*!< ITM TCR: STALLENA Position */
+#define ITM_TCR_STALLENA_Msk (1UL << ITM_TCR_STALLENA_Pos) /*!< ITM TCR: STALLENA Mask */
+
+#define ITM_TCR_SWOENA_Pos 4U /*!< ITM TCR: SWOENA Position */
+#define ITM_TCR_SWOENA_Msk (1UL << ITM_TCR_SWOENA_Pos) /*!< ITM TCR: SWOENA Mask */
+
+#define ITM_TCR_DWTENA_Pos 3U /*!< ITM TCR: DWTENA Position */
+#define ITM_TCR_DWTENA_Msk (1UL << ITM_TCR_DWTENA_Pos) /*!< ITM TCR: DWTENA Mask */
+
+#define ITM_TCR_SYNCENA_Pos 2U /*!< ITM TCR: SYNCENA Position */
+#define ITM_TCR_SYNCENA_Msk (1UL << ITM_TCR_SYNCENA_Pos) /*!< ITM TCR: SYNCENA Mask */
+
+#define ITM_TCR_TSENA_Pos 1U /*!< ITM TCR: TSENA Position */
+#define ITM_TCR_TSENA_Msk (1UL << ITM_TCR_TSENA_Pos) /*!< ITM TCR: TSENA Mask */
+
+#define ITM_TCR_ITMENA_Pos 0U /*!< ITM TCR: ITM Enable bit Position */
+#define ITM_TCR_ITMENA_Msk (1UL /*<< ITM_TCR_ITMENA_Pos*/) /*!< ITM TCR: ITM Enable bit Mask */
+
+/* ITM Lock Status Register Definitions */
+#define ITM_LSR_ByteAcc_Pos 2U /*!< ITM LSR: ByteAcc Position */
+#define ITM_LSR_ByteAcc_Msk (1UL << ITM_LSR_ByteAcc_Pos) /*!< ITM LSR: ByteAcc Mask */
+
+#define ITM_LSR_Access_Pos 1U /*!< ITM LSR: Access Position */
+#define ITM_LSR_Access_Msk (1UL << ITM_LSR_Access_Pos) /*!< ITM LSR: Access Mask */
+
+#define ITM_LSR_Present_Pos 0U /*!< ITM LSR: Present Position */
+#define ITM_LSR_Present_Msk (1UL /*<< ITM_LSR_Present_Pos*/) /*!< ITM LSR: Present Mask */
+
+/*@}*/ /* end of group CMSIS_ITM */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_DWT Data Watchpoint and Trace (DWT)
+ \brief Type definitions for the Data Watchpoint and Trace (DWT)
+ @{
+ */
+
+/**
+ \brief Structure type to access the Data Watchpoint and Trace Register (DWT).
+ */
+typedef struct
+{
+ __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) Control Register */
+ __IOM uint32_t CYCCNT; /*!< Offset: 0x004 (R/W) Cycle Count Register */
+ __IOM uint32_t CPICNT; /*!< Offset: 0x008 (R/W) CPI Count Register */
+ __IOM uint32_t EXCCNT; /*!< Offset: 0x00C (R/W) Exception Overhead Count Register */
+ __IOM uint32_t SLEEPCNT; /*!< Offset: 0x010 (R/W) Sleep Count Register */
+ __IOM uint32_t LSUCNT; /*!< Offset: 0x014 (R/W) LSU Count Register */
+ __IOM uint32_t FOLDCNT; /*!< Offset: 0x018 (R/W) Folded-instruction Count Register */
+ __IM uint32_t PCSR; /*!< Offset: 0x01C (R/ ) Program Counter Sample Register */
+ __IOM uint32_t COMP0; /*!< Offset: 0x020 (R/W) Comparator Register 0 */
+ uint32_t RESERVED1[1U];
+ __IOM uint32_t FUNCTION0; /*!< Offset: 0x028 (R/W) Function Register 0 */
+ uint32_t RESERVED2[1U];
+ __IOM uint32_t COMP1; /*!< Offset: 0x030 (R/W) Comparator Register 1 */
+ uint32_t RESERVED3[1U];
+ __IOM uint32_t FUNCTION1; /*!< Offset: 0x038 (R/W) Function Register 1 */
+ uint32_t RESERVED4[1U];
+ __IOM uint32_t COMP2; /*!< Offset: 0x040 (R/W) Comparator Register 2 */
+ uint32_t RESERVED5[1U];
+ __IOM uint32_t FUNCTION2; /*!< Offset: 0x048 (R/W) Function Register 2 */
+ uint32_t RESERVED6[1U];
+ __IOM uint32_t COMP3; /*!< Offset: 0x050 (R/W) Comparator Register 3 */
+ uint32_t RESERVED7[1U];
+ __IOM uint32_t FUNCTION3; /*!< Offset: 0x058 (R/W) Function Register 3 */
+ uint32_t RESERVED8[1U];
+ __IOM uint32_t COMP4; /*!< Offset: 0x060 (R/W) Comparator Register 4 */
+ uint32_t RESERVED9[1U];
+ __IOM uint32_t FUNCTION4; /*!< Offset: 0x068 (R/W) Function Register 4 */
+ uint32_t RESERVED10[1U];
+ __IOM uint32_t COMP5; /*!< Offset: 0x070 (R/W) Comparator Register 5 */
+ uint32_t RESERVED11[1U];
+ __IOM uint32_t FUNCTION5; /*!< Offset: 0x078 (R/W) Function Register 5 */
+ uint32_t RESERVED12[1U];
+ __IOM uint32_t COMP6; /*!< Offset: 0x080 (R/W) Comparator Register 6 */
+ uint32_t RESERVED13[1U];
+ __IOM uint32_t FUNCTION6; /*!< Offset: 0x088 (R/W) Function Register 6 */
+ uint32_t RESERVED14[1U];
+ __IOM uint32_t COMP7; /*!< Offset: 0x090 (R/W) Comparator Register 7 */
+ uint32_t RESERVED15[1U];
+ __IOM uint32_t FUNCTION7; /*!< Offset: 0x098 (R/W) Function Register 7 */
+ uint32_t RESERVED16[1U];
+ __IOM uint32_t COMP8; /*!< Offset: 0x0A0 (R/W) Comparator Register 8 */
+ uint32_t RESERVED17[1U];
+ __IOM uint32_t FUNCTION8; /*!< Offset: 0x0A8 (R/W) Function Register 8 */
+ uint32_t RESERVED18[1U];
+ __IOM uint32_t COMP9; /*!< Offset: 0x0B0 (R/W) Comparator Register 9 */
+ uint32_t RESERVED19[1U];
+ __IOM uint32_t FUNCTION9; /*!< Offset: 0x0B8 (R/W) Function Register 9 */
+ uint32_t RESERVED20[1U];
+ __IOM uint32_t COMP10; /*!< Offset: 0x0C0 (R/W) Comparator Register 10 */
+ uint32_t RESERVED21[1U];
+ __IOM uint32_t FUNCTION10; /*!< Offset: 0x0C8 (R/W) Function Register 10 */
+ uint32_t RESERVED22[1U];
+ __IOM uint32_t COMP11; /*!< Offset: 0x0D0 (R/W) Comparator Register 11 */
+ uint32_t RESERVED23[1U];
+ __IOM uint32_t FUNCTION11; /*!< Offset: 0x0D8 (R/W) Function Register 11 */
+ uint32_t RESERVED24[1U];
+ __IOM uint32_t COMP12; /*!< Offset: 0x0E0 (R/W) Comparator Register 12 */
+ uint32_t RESERVED25[1U];
+ __IOM uint32_t FUNCTION12; /*!< Offset: 0x0E8 (R/W) Function Register 12 */
+ uint32_t RESERVED26[1U];
+ __IOM uint32_t COMP13; /*!< Offset: 0x0F0 (R/W) Comparator Register 13 */
+ uint32_t RESERVED27[1U];
+ __IOM uint32_t FUNCTION13; /*!< Offset: 0x0F8 (R/W) Function Register 13 */
+ uint32_t RESERVED28[1U];
+ __IOM uint32_t COMP14; /*!< Offset: 0x100 (R/W) Comparator Register 14 */
+ uint32_t RESERVED29[1U];
+ __IOM uint32_t FUNCTION14; /*!< Offset: 0x108 (R/W) Function Register 14 */
+ uint32_t RESERVED30[1U];
+ __IOM uint32_t COMP15; /*!< Offset: 0x110 (R/W) Comparator Register 15 */
+ uint32_t RESERVED31[1U];
+ __IOM uint32_t FUNCTION15; /*!< Offset: 0x118 (R/W) Function Register 15 */
+ uint32_t RESERVED32[934U];
+ __IM uint32_t LSR; /*!< Offset: 0xFB4 (R ) Lock Status Register */
+ uint32_t RESERVED33[1U];
+ __IM uint32_t DEVARCH; /*!< Offset: 0xFBC (R/ ) Device Architecture Register */
+} DWT_Type;
+
+/* DWT Control Register Definitions */
+#define DWT_CTRL_NUMCOMP_Pos 28U /*!< DWT CTRL: NUMCOMP Position */
+#define DWT_CTRL_NUMCOMP_Msk (0xFUL << DWT_CTRL_NUMCOMP_Pos) /*!< DWT CTRL: NUMCOMP Mask */
+
+#define DWT_CTRL_NOTRCPKT_Pos 27U /*!< DWT CTRL: NOTRCPKT Position */
+#define DWT_CTRL_NOTRCPKT_Msk (0x1UL << DWT_CTRL_NOTRCPKT_Pos) /*!< DWT CTRL: NOTRCPKT Mask */
+
+#define DWT_CTRL_NOEXTTRIG_Pos 26U /*!< DWT CTRL: NOEXTTRIG Position */
+#define DWT_CTRL_NOEXTTRIG_Msk (0x1UL << DWT_CTRL_NOEXTTRIG_Pos) /*!< DWT CTRL: NOEXTTRIG Mask */
+
+#define DWT_CTRL_NOCYCCNT_Pos 25U /*!< DWT CTRL: NOCYCCNT Position */
+#define DWT_CTRL_NOCYCCNT_Msk (0x1UL << DWT_CTRL_NOCYCCNT_Pos) /*!< DWT CTRL: NOCYCCNT Mask */
+
+#define DWT_CTRL_NOPRFCNT_Pos 24U /*!< DWT CTRL: NOPRFCNT Position */
+#define DWT_CTRL_NOPRFCNT_Msk (0x1UL << DWT_CTRL_NOPRFCNT_Pos) /*!< DWT CTRL: NOPRFCNT Mask */
+
+#define DWT_CTRL_CYCDISS_Pos 23U /*!< DWT CTRL: CYCDISS Position */
+#define DWT_CTRL_CYCDISS_Msk (0x1UL << DWT_CTRL_CYCDISS_Pos) /*!< DWT CTRL: CYCDISS Mask */
+
+#define DWT_CTRL_CYCEVTENA_Pos 22U /*!< DWT CTRL: CYCEVTENA Position */
+#define DWT_CTRL_CYCEVTENA_Msk (0x1UL << DWT_CTRL_CYCEVTENA_Pos) /*!< DWT CTRL: CYCEVTENA Mask */
+
+#define DWT_CTRL_FOLDEVTENA_Pos 21U /*!< DWT CTRL: FOLDEVTENA Position */
+#define DWT_CTRL_FOLDEVTENA_Msk (0x1UL << DWT_CTRL_FOLDEVTENA_Pos) /*!< DWT CTRL: FOLDEVTENA Mask */
+
+#define DWT_CTRL_LSUEVTENA_Pos 20U /*!< DWT CTRL: LSUEVTENA Position */
+#define DWT_CTRL_LSUEVTENA_Msk (0x1UL << DWT_CTRL_LSUEVTENA_Pos) /*!< DWT CTRL: LSUEVTENA Mask */
+
+#define DWT_CTRL_SLEEPEVTENA_Pos 19U /*!< DWT CTRL: SLEEPEVTENA Position */
+#define DWT_CTRL_SLEEPEVTENA_Msk (0x1UL << DWT_CTRL_SLEEPEVTENA_Pos) /*!< DWT CTRL: SLEEPEVTENA Mask */
+
+#define DWT_CTRL_EXCEVTENA_Pos 18U /*!< DWT CTRL: EXCEVTENA Position */
+#define DWT_CTRL_EXCEVTENA_Msk (0x1UL << DWT_CTRL_EXCEVTENA_Pos) /*!< DWT CTRL: EXCEVTENA Mask */
+
+#define DWT_CTRL_CPIEVTENA_Pos 17U /*!< DWT CTRL: CPIEVTENA Position */
+#define DWT_CTRL_CPIEVTENA_Msk (0x1UL << DWT_CTRL_CPIEVTENA_Pos) /*!< DWT CTRL: CPIEVTENA Mask */
+
+#define DWT_CTRL_EXCTRCENA_Pos 16U /*!< DWT CTRL: EXCTRCENA Position */
+#define DWT_CTRL_EXCTRCENA_Msk (0x1UL << DWT_CTRL_EXCTRCENA_Pos) /*!< DWT CTRL: EXCTRCENA Mask */
+
+#define DWT_CTRL_PCSAMPLENA_Pos 12U /*!< DWT CTRL: PCSAMPLENA Position */
+#define DWT_CTRL_PCSAMPLENA_Msk (0x1UL << DWT_CTRL_PCSAMPLENA_Pos) /*!< DWT CTRL: PCSAMPLENA Mask */
+
+#define DWT_CTRL_SYNCTAP_Pos 10U /*!< DWT CTRL: SYNCTAP Position */
+#define DWT_CTRL_SYNCTAP_Msk (0x3UL << DWT_CTRL_SYNCTAP_Pos) /*!< DWT CTRL: SYNCTAP Mask */
+
+#define DWT_CTRL_CYCTAP_Pos 9U /*!< DWT CTRL: CYCTAP Position */
+#define DWT_CTRL_CYCTAP_Msk (0x1UL << DWT_CTRL_CYCTAP_Pos) /*!< DWT CTRL: CYCTAP Mask */
+
+#define DWT_CTRL_POSTINIT_Pos 5U /*!< DWT CTRL: POSTINIT Position */
+#define DWT_CTRL_POSTINIT_Msk (0xFUL << DWT_CTRL_POSTINIT_Pos) /*!< DWT CTRL: POSTINIT Mask */
+
+#define DWT_CTRL_POSTPRESET_Pos 1U /*!< DWT CTRL: POSTPRESET Position */
+#define DWT_CTRL_POSTPRESET_Msk (0xFUL << DWT_CTRL_POSTPRESET_Pos) /*!< DWT CTRL: POSTPRESET Mask */
+
+#define DWT_CTRL_CYCCNTENA_Pos 0U /*!< DWT CTRL: CYCCNTENA Position */
+#define DWT_CTRL_CYCCNTENA_Msk (0x1UL /*<< DWT_CTRL_CYCCNTENA_Pos*/) /*!< DWT CTRL: CYCCNTENA Mask */
+
+/* DWT CPI Count Register Definitions */
+#define DWT_CPICNT_CPICNT_Pos 0U /*!< DWT CPICNT: CPICNT Position */
+#define DWT_CPICNT_CPICNT_Msk (0xFFUL /*<< DWT_CPICNT_CPICNT_Pos*/) /*!< DWT CPICNT: CPICNT Mask */
+
+/* DWT Exception Overhead Count Register Definitions */
+#define DWT_EXCCNT_EXCCNT_Pos 0U /*!< DWT EXCCNT: EXCCNT Position */
+#define DWT_EXCCNT_EXCCNT_Msk (0xFFUL /*<< DWT_EXCCNT_EXCCNT_Pos*/) /*!< DWT EXCCNT: EXCCNT Mask */
+
+/* DWT Sleep Count Register Definitions */
+#define DWT_SLEEPCNT_SLEEPCNT_Pos 0U /*!< DWT SLEEPCNT: SLEEPCNT Position */
+#define DWT_SLEEPCNT_SLEEPCNT_Msk (0xFFUL /*<< DWT_SLEEPCNT_SLEEPCNT_Pos*/) /*!< DWT SLEEPCNT: SLEEPCNT Mask */
+
+/* DWT LSU Count Register Definitions */
+#define DWT_LSUCNT_LSUCNT_Pos 0U /*!< DWT LSUCNT: LSUCNT Position */
+#define DWT_LSUCNT_LSUCNT_Msk (0xFFUL /*<< DWT_LSUCNT_LSUCNT_Pos*/) /*!< DWT LSUCNT: LSUCNT Mask */
+
+/* DWT Folded-instruction Count Register Definitions */
+#define DWT_FOLDCNT_FOLDCNT_Pos 0U /*!< DWT FOLDCNT: FOLDCNT Position */
+#define DWT_FOLDCNT_FOLDCNT_Msk (0xFFUL /*<< DWT_FOLDCNT_FOLDCNT_Pos*/) /*!< DWT FOLDCNT: FOLDCNT Mask */
+
+/* DWT Comparator Function Register Definitions */
+#define DWT_FUNCTION_ID_Pos 27U /*!< DWT FUNCTION: ID Position */
+#define DWT_FUNCTION_ID_Msk (0x1FUL << DWT_FUNCTION_ID_Pos) /*!< DWT FUNCTION: ID Mask */
+
+#define DWT_FUNCTION_MATCHED_Pos 24U /*!< DWT FUNCTION: MATCHED Position */
+#define DWT_FUNCTION_MATCHED_Msk (0x1UL << DWT_FUNCTION_MATCHED_Pos) /*!< DWT FUNCTION: MATCHED Mask */
+
+#define DWT_FUNCTION_DATAVSIZE_Pos 10U /*!< DWT FUNCTION: DATAVSIZE Position */
+#define DWT_FUNCTION_DATAVSIZE_Msk (0x3UL << DWT_FUNCTION_DATAVSIZE_Pos) /*!< DWT FUNCTION: DATAVSIZE Mask */
+
+#define DWT_FUNCTION_ACTION_Pos 4U /*!< DWT FUNCTION: ACTION Position */
+#define DWT_FUNCTION_ACTION_Msk (0x1UL << DWT_FUNCTION_ACTION_Pos) /*!< DWT FUNCTION: ACTION Mask */
+
+#define DWT_FUNCTION_MATCH_Pos 0U /*!< DWT FUNCTION: MATCH Position */
+#define DWT_FUNCTION_MATCH_Msk (0xFUL /*<< DWT_FUNCTION_MATCH_Pos*/) /*!< DWT FUNCTION: MATCH Mask */
+
+/*@}*/ /* end of group CMSIS_DWT */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_TPI Trace Port Interface (TPI)
+ \brief Type definitions for the Trace Port Interface (TPI)
+ @{
+ */
+
+/**
+ \brief Structure type to access the Trace Port Interface Register (TPI).
+ */
+typedef struct
+{
+ __IM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Size Register */
+ __IOM uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Size Register */
+ uint32_t RESERVED0[2U];
+ __IOM uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */
+ uint32_t RESERVED1[55U];
+ __IOM uint32_t SPPR; /*!< Offset: 0x0F0 (R/W) Selected Pin Protocol Register */
+ uint32_t RESERVED2[131U];
+ __IM uint32_t FFSR; /*!< Offset: 0x300 (R/ ) Formatter and Flush Status Register */
+ __IOM uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */
+ __IOM uint32_t PSCR; /*!< Offset: 0x308 (R/W) Periodic Synchronization Control Register */
+ uint32_t RESERVED3[759U];
+ __IM uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER Register */
+ __IM uint32_t ITFTTD0; /*!< Offset: 0xEEC (R/ ) Integration Test FIFO Test Data 0 Register */
+ __IOM uint32_t ITATBCTR2; /*!< Offset: 0xEF0 (R/W) Integration Test ATB Control Register 2 */
+ uint32_t RESERVED4[1U];
+ __IM uint32_t ITATBCTR0; /*!< Offset: 0xEF8 (R/ ) Integration Test ATB Control Register 0 */
+ __IM uint32_t ITFTTD1; /*!< Offset: 0xEFC (R/ ) Integration Test FIFO Test Data 1 Register */
+ __IOM uint32_t ITCTRL; /*!< Offset: 0xF00 (R/W) Integration Mode Control */
+ uint32_t RESERVED5[39U];
+ __IOM uint32_t CLAIMSET; /*!< Offset: 0xFA0 (R/W) Claim tag set */
+ __IOM uint32_t CLAIMCLR; /*!< Offset: 0xFA4 (R/W) Claim tag clear */
+ uint32_t RESERVED7[8U];
+ __IM uint32_t DEVID; /*!< Offset: 0xFC8 (R/ ) Device Configuration Register */
+ __IM uint32_t DEVTYPE; /*!< Offset: 0xFCC (R/ ) Device Type Identifier Register */
+} TPI_Type;
+
+/* TPI Asynchronous Clock Prescaler Register Definitions */
+#define TPI_ACPR_PRESCALER_Pos 0U /*!< TPI ACPR: PRESCALER Position */
+#define TPI_ACPR_PRESCALER_Msk (0x1FFFUL /*<< TPI_ACPR_PRESCALER_Pos*/) /*!< TPI ACPR: PRESCALER Mask */
+
+/* TPI Selected Pin Protocol Register Definitions */
+#define TPI_SPPR_TXMODE_Pos 0U /*!< TPI SPPR: TXMODE Position */
+#define TPI_SPPR_TXMODE_Msk (0x3UL /*<< TPI_SPPR_TXMODE_Pos*/) /*!< TPI SPPR: TXMODE Mask */
+
+/* TPI Formatter and Flush Status Register Definitions */
+#define TPI_FFSR_FtNonStop_Pos 3U /*!< TPI FFSR: FtNonStop Position */
+#define TPI_FFSR_FtNonStop_Msk (0x1UL << TPI_FFSR_FtNonStop_Pos) /*!< TPI FFSR: FtNonStop Mask */
+
+#define TPI_FFSR_TCPresent_Pos 2U /*!< TPI FFSR: TCPresent Position */
+#define TPI_FFSR_TCPresent_Msk (0x1UL << TPI_FFSR_TCPresent_Pos) /*!< TPI FFSR: TCPresent Mask */
+
+#define TPI_FFSR_FtStopped_Pos 1U /*!< TPI FFSR: FtStopped Position */
+#define TPI_FFSR_FtStopped_Msk (0x1UL << TPI_FFSR_FtStopped_Pos) /*!< TPI FFSR: FtStopped Mask */
+
+#define TPI_FFSR_FlInProg_Pos 0U /*!< TPI FFSR: FlInProg Position */
+#define TPI_FFSR_FlInProg_Msk (0x1UL /*<< TPI_FFSR_FlInProg_Pos*/) /*!< TPI FFSR: FlInProg Mask */
+
+/* TPI Formatter and Flush Control Register Definitions */
+#define TPI_FFCR_TrigIn_Pos 8U /*!< TPI FFCR: TrigIn Position */
+#define TPI_FFCR_TrigIn_Msk (0x1UL << TPI_FFCR_TrigIn_Pos) /*!< TPI FFCR: TrigIn Mask */
+
+#define TPI_FFCR_FOnMan_Pos 6U /*!< TPI FFCR: FOnMan Position */
+#define TPI_FFCR_FOnMan_Msk (0x1UL << TPI_FFCR_FOnMan_Pos) /*!< TPI FFCR: FOnMan Mask */
+
+#define TPI_FFCR_EnFCont_Pos 1U /*!< TPI FFCR: EnFCont Position */
+#define TPI_FFCR_EnFCont_Msk (0x1UL << TPI_FFCR_EnFCont_Pos) /*!< TPI FFCR: EnFCont Mask */
+
+/* TPI TRIGGER Register Definitions */
+#define TPI_TRIGGER_TRIGGER_Pos 0U /*!< TPI TRIGGER: TRIGGER Position */
+#define TPI_TRIGGER_TRIGGER_Msk (0x1UL /*<< TPI_TRIGGER_TRIGGER_Pos*/) /*!< TPI TRIGGER: TRIGGER Mask */
+
+/* TPI Integration Test FIFO Test Data 0 Register Definitions */
+#define TPI_ITFTTD0_ATB_IF2_ATVALID_Pos 29U /*!< TPI ITFTTD0: ATB Interface 2 ATVALIDPosition */
+#define TPI_ITFTTD0_ATB_IF2_ATVALID_Msk (0x3UL << TPI_ITFTTD0_ATB_IF2_ATVALID_Pos) /*!< TPI ITFTTD0: ATB Interface 2 ATVALID Mask */
+
+#define TPI_ITFTTD0_ATB_IF2_bytecount_Pos 27U /*!< TPI ITFTTD0: ATB Interface 2 byte count Position */
+#define TPI_ITFTTD0_ATB_IF2_bytecount_Msk (0x3UL << TPI_ITFTTD0_ATB_IF2_bytecount_Pos) /*!< TPI ITFTTD0: ATB Interface 2 byte count Mask */
+
+#define TPI_ITFTTD0_ATB_IF1_ATVALID_Pos 26U /*!< TPI ITFTTD0: ATB Interface 1 ATVALID Position */
+#define TPI_ITFTTD0_ATB_IF1_ATVALID_Msk (0x3UL << TPI_ITFTTD0_ATB_IF1_ATVALID_Pos) /*!< TPI ITFTTD0: ATB Interface 1 ATVALID Mask */
+
+#define TPI_ITFTTD0_ATB_IF1_bytecount_Pos 24U /*!< TPI ITFTTD0: ATB Interface 1 byte count Position */
+#define TPI_ITFTTD0_ATB_IF1_bytecount_Msk (0x3UL << TPI_ITFTTD0_ATB_IF1_bytecount_Pos) /*!< TPI ITFTTD0: ATB Interface 1 byte countt Mask */
+
+#define TPI_ITFTTD0_ATB_IF1_data2_Pos 16U /*!< TPI ITFTTD0: ATB Interface 1 data2 Position */
+#define TPI_ITFTTD0_ATB_IF1_data2_Msk (0xFFUL << TPI_ITFTTD0_ATB_IF1_data1_Pos) /*!< TPI ITFTTD0: ATB Interface 1 data2 Mask */
+
+#define TPI_ITFTTD0_ATB_IF1_data1_Pos 8U /*!< TPI ITFTTD0: ATB Interface 1 data1 Position */
+#define TPI_ITFTTD0_ATB_IF1_data1_Msk (0xFFUL << TPI_ITFTTD0_ATB_IF1_data1_Pos) /*!< TPI ITFTTD0: ATB Interface 1 data1 Mask */
+
+#define TPI_ITFTTD0_ATB_IF1_data0_Pos 0U /*!< TPI ITFTTD0: ATB Interface 1 data0 Position */
+#define TPI_ITFTTD0_ATB_IF1_data0_Msk (0xFFUL /*<< TPI_ITFTTD0_ATB_IF1_data0_Pos*/) /*!< TPI ITFTTD0: ATB Interface 1 data0 Mask */
+
+/* TPI Integration Test ATB Control Register 2 Register Definitions */
+#define TPI_ITATBCTR2_AFVALID2S_Pos 1U /*!< TPI ITATBCTR2: AFVALID2S Position */
+#define TPI_ITATBCTR2_AFVALID2S_Msk (0x1UL << TPI_ITATBCTR2_AFVALID2S_Pos) /*!< TPI ITATBCTR2: AFVALID2SS Mask */
+
+#define TPI_ITATBCTR2_AFVALID1S_Pos 1U /*!< TPI ITATBCTR2: AFVALID1S Position */
+#define TPI_ITATBCTR2_AFVALID1S_Msk (0x1UL << TPI_ITATBCTR2_AFVALID1S_Pos) /*!< TPI ITATBCTR2: AFVALID1SS Mask */
+
+#define TPI_ITATBCTR2_ATREADY2S_Pos 0U /*!< TPI ITATBCTR2: ATREADY2S Position */
+#define TPI_ITATBCTR2_ATREADY2S_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY2S_Pos*/) /*!< TPI ITATBCTR2: ATREADY2S Mask */
+
+#define TPI_ITATBCTR2_ATREADY1S_Pos 0U /*!< TPI ITATBCTR2: ATREADY1S Position */
+#define TPI_ITATBCTR2_ATREADY1S_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY1S_Pos*/) /*!< TPI ITATBCTR2: ATREADY1S Mask */
+
+/* TPI Integration Test FIFO Test Data 1 Register Definitions */
+#define TPI_ITFTTD1_ATB_IF2_ATVALID_Pos 29U /*!< TPI ITFTTD1: ATB Interface 2 ATVALID Position */
+#define TPI_ITFTTD1_ATB_IF2_ATVALID_Msk (0x3UL << TPI_ITFTTD1_ATB_IF2_ATVALID_Pos) /*!< TPI ITFTTD1: ATB Interface 2 ATVALID Mask */
+
+#define TPI_ITFTTD1_ATB_IF2_bytecount_Pos 27U /*!< TPI ITFTTD1: ATB Interface 2 byte count Position */
+#define TPI_ITFTTD1_ATB_IF2_bytecount_Msk (0x3UL << TPI_ITFTTD1_ATB_IF2_bytecount_Pos) /*!< TPI ITFTTD1: ATB Interface 2 byte count Mask */
+
+#define TPI_ITFTTD1_ATB_IF1_ATVALID_Pos 26U /*!< TPI ITFTTD1: ATB Interface 1 ATVALID Position */
+#define TPI_ITFTTD1_ATB_IF1_ATVALID_Msk (0x3UL << TPI_ITFTTD1_ATB_IF1_ATVALID_Pos) /*!< TPI ITFTTD1: ATB Interface 1 ATVALID Mask */
+
+#define TPI_ITFTTD1_ATB_IF1_bytecount_Pos 24U /*!< TPI ITFTTD1: ATB Interface 1 byte count Position */
+#define TPI_ITFTTD1_ATB_IF1_bytecount_Msk (0x3UL << TPI_ITFTTD1_ATB_IF1_bytecount_Pos) /*!< TPI ITFTTD1: ATB Interface 1 byte countt Mask */
+
+#define TPI_ITFTTD1_ATB_IF2_data2_Pos 16U /*!< TPI ITFTTD1: ATB Interface 2 data2 Position */
+#define TPI_ITFTTD1_ATB_IF2_data2_Msk (0xFFUL << TPI_ITFTTD1_ATB_IF2_data1_Pos) /*!< TPI ITFTTD1: ATB Interface 2 data2 Mask */
+
+#define TPI_ITFTTD1_ATB_IF2_data1_Pos 8U /*!< TPI ITFTTD1: ATB Interface 2 data1 Position */
+#define TPI_ITFTTD1_ATB_IF2_data1_Msk (0xFFUL << TPI_ITFTTD1_ATB_IF2_data1_Pos) /*!< TPI ITFTTD1: ATB Interface 2 data1 Mask */
+
+#define TPI_ITFTTD1_ATB_IF2_data0_Pos 0U /*!< TPI ITFTTD1: ATB Interface 2 data0 Position */
+#define TPI_ITFTTD1_ATB_IF2_data0_Msk (0xFFUL /*<< TPI_ITFTTD1_ATB_IF2_data0_Pos*/) /*!< TPI ITFTTD1: ATB Interface 2 data0 Mask */
+
+/* TPI Integration Test ATB Control Register 0 Definitions */
+#define TPI_ITATBCTR0_AFVALID2S_Pos 1U /*!< TPI ITATBCTR0: AFVALID2S Position */
+#define TPI_ITATBCTR0_AFVALID2S_Msk (0x1UL << TPI_ITATBCTR0_AFVALID2S_Pos) /*!< TPI ITATBCTR0: AFVALID2SS Mask */
+
+#define TPI_ITATBCTR0_AFVALID1S_Pos 1U /*!< TPI ITATBCTR0: AFVALID1S Position */
+#define TPI_ITATBCTR0_AFVALID1S_Msk (0x1UL << TPI_ITATBCTR0_AFVALID1S_Pos) /*!< TPI ITATBCTR0: AFVALID1SS Mask */
+
+#define TPI_ITATBCTR0_ATREADY2S_Pos 0U /*!< TPI ITATBCTR0: ATREADY2S Position */
+#define TPI_ITATBCTR0_ATREADY2S_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY2S_Pos*/) /*!< TPI ITATBCTR0: ATREADY2S Mask */
+
+#define TPI_ITATBCTR0_ATREADY1S_Pos 0U /*!< TPI ITATBCTR0: ATREADY1S Position */
+#define TPI_ITATBCTR0_ATREADY1S_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY1S_Pos*/) /*!< TPI ITATBCTR0: ATREADY1S Mask */
+
+/* TPI Integration Mode Control Register Definitions */
+#define TPI_ITCTRL_Mode_Pos 0U /*!< TPI ITCTRL: Mode Position */
+#define TPI_ITCTRL_Mode_Msk (0x3UL /*<< TPI_ITCTRL_Mode_Pos*/) /*!< TPI ITCTRL: Mode Mask */
+
+/* TPI DEVID Register Definitions */
+#define TPI_DEVID_NRZVALID_Pos 11U /*!< TPI DEVID: NRZVALID Position */
+#define TPI_DEVID_NRZVALID_Msk (0x1UL << TPI_DEVID_NRZVALID_Pos) /*!< TPI DEVID: NRZVALID Mask */
+
+#define TPI_DEVID_MANCVALID_Pos 10U /*!< TPI DEVID: MANCVALID Position */
+#define TPI_DEVID_MANCVALID_Msk (0x1UL << TPI_DEVID_MANCVALID_Pos) /*!< TPI DEVID: MANCVALID Mask */
+
+#define TPI_DEVID_PTINVALID_Pos 9U /*!< TPI DEVID: PTINVALID Position */
+#define TPI_DEVID_PTINVALID_Msk (0x1UL << TPI_DEVID_PTINVALID_Pos) /*!< TPI DEVID: PTINVALID Mask */
+
+#define TPI_DEVID_FIFOSZ_Pos 6U /*!< TPI DEVID: FIFOSZ Position */
+#define TPI_DEVID_FIFOSZ_Msk (0x7UL << TPI_DEVID_FIFOSZ_Pos) /*!< TPI DEVID: FIFOSZ Mask */
+
+#define TPI_DEVID_NrTraceInput_Pos 0U /*!< TPI DEVID: NrTraceInput Position */
+#define TPI_DEVID_NrTraceInput_Msk (0x3FUL /*<< TPI_DEVID_NrTraceInput_Pos*/) /*!< TPI DEVID: NrTraceInput Mask */
+
+/* TPI DEVTYPE Register Definitions */
+#define TPI_DEVTYPE_SubType_Pos 4U /*!< TPI DEVTYPE: SubType Position */
+#define TPI_DEVTYPE_SubType_Msk (0xFUL /*<< TPI_DEVTYPE_SubType_Pos*/) /*!< TPI DEVTYPE: SubType Mask */
+
+#define TPI_DEVTYPE_MajorType_Pos 0U /*!< TPI DEVTYPE: MajorType Position */
+#define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */
+
+/*@}*/ /* end of group CMSIS_TPI */
+
+
+#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U)
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_MPU Memory Protection Unit (MPU)
+ \brief Type definitions for the Memory Protection Unit (MPU)
+ @{
+ */
+
+/**
+ \brief Structure type to access the Memory Protection Unit (MPU).
+ */
+typedef struct
+{
+ __IM uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */
+ __IOM uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */
+ __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region Number Register */
+ __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */
+ __IOM uint32_t RLAR; /*!< Offset: 0x010 (R/W) MPU Region Limit Address Register */
+ __IOM uint32_t RBAR_A1; /*!< Offset: 0x014 (R/W) MPU Region Base Address Register Alias 1 */
+ __IOM uint32_t RLAR_A1; /*!< Offset: 0x018 (R/W) MPU Region Limit Address Register Alias 1 */
+ __IOM uint32_t RBAR_A2; /*!< Offset: 0x01C (R/W) MPU Region Base Address Register Alias 2 */
+ __IOM uint32_t RLAR_A2; /*!< Offset: 0x020 (R/W) MPU Region Limit Address Register Alias 2 */
+ __IOM uint32_t RBAR_A3; /*!< Offset: 0x024 (R/W) MPU Region Base Address Register Alias 3 */
+ __IOM uint32_t RLAR_A3; /*!< Offset: 0x028 (R/W) MPU Region Limit Address Register Alias 3 */
+ uint32_t RESERVED0[1];
+ union {
+ __IOM uint32_t MAIR[2];
+ struct {
+ __IOM uint32_t MAIR0; /*!< Offset: 0x030 (R/W) MPU Memory Attribute Indirection Register 0 */
+ __IOM uint32_t MAIR1; /*!< Offset: 0x034 (R/W) MPU Memory Attribute Indirection Register 1 */
+ };
+ };
+} MPU_Type;
+
+#define MPU_TYPE_RALIASES 4U
+
+/* MPU Type Register Definitions */
+#define MPU_TYPE_IREGION_Pos 16U /*!< MPU TYPE: IREGION Position */
+#define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */
+
+#define MPU_TYPE_DREGION_Pos 8U /*!< MPU TYPE: DREGION Position */
+#define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */
+
+#define MPU_TYPE_SEPARATE_Pos 0U /*!< MPU TYPE: SEPARATE Position */
+#define MPU_TYPE_SEPARATE_Msk (1UL /*<< MPU_TYPE_SEPARATE_Pos*/) /*!< MPU TYPE: SEPARATE Mask */
+
+/* MPU Control Register Definitions */
+#define MPU_CTRL_PRIVDEFENA_Pos 2U /*!< MPU CTRL: PRIVDEFENA Position */
+#define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */
+
+#define MPU_CTRL_HFNMIENA_Pos 1U /*!< MPU CTRL: HFNMIENA Position */
+#define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */
+
+#define MPU_CTRL_ENABLE_Pos 0U /*!< MPU CTRL: ENABLE Position */
+#define MPU_CTRL_ENABLE_Msk (1UL /*<< MPU_CTRL_ENABLE_Pos*/) /*!< MPU CTRL: ENABLE Mask */
+
+/* MPU Region Number Register Definitions */
+#define MPU_RNR_REGION_Pos 0U /*!< MPU RNR: REGION Position */
+#define MPU_RNR_REGION_Msk (0xFFUL /*<< MPU_RNR_REGION_Pos*/) /*!< MPU RNR: REGION Mask */
+
+/* MPU Region Base Address Register Definitions */
+#define MPU_RBAR_BASE_Pos 5U /*!< MPU RBAR: BASE Position */
+#define MPU_RBAR_BASE_Msk (0x7FFFFFFUL << MPU_RBAR_BASE_Pos) /*!< MPU RBAR: BASE Mask */
+
+#define MPU_RBAR_SH_Pos 3U /*!< MPU RBAR: SH Position */
+#define MPU_RBAR_SH_Msk (0x3UL << MPU_RBAR_SH_Pos) /*!< MPU RBAR: SH Mask */
+
+#define MPU_RBAR_AP_Pos 1U /*!< MPU RBAR: AP Position */
+#define MPU_RBAR_AP_Msk (0x3UL << MPU_RBAR_AP_Pos) /*!< MPU RBAR: AP Mask */
+
+#define MPU_RBAR_XN_Pos 0U /*!< MPU RBAR: XN Position */
+#define MPU_RBAR_XN_Msk (01UL /*<< MPU_RBAR_XN_Pos*/) /*!< MPU RBAR: XN Mask */
+
+/* MPU Region Limit Address Register Definitions */
+#define MPU_RLAR_LIMIT_Pos 5U /*!< MPU RLAR: LIMIT Position */
+#define MPU_RLAR_LIMIT_Msk (0x7FFFFFFUL << MPU_RLAR_LIMIT_Pos) /*!< MPU RLAR: LIMIT Mask */
+
+#define MPU_RLAR_AttrIndx_Pos 1U /*!< MPU RLAR: AttrIndx Position */
+#define MPU_RLAR_AttrIndx_Msk (0x7UL << MPU_RLAR_AttrIndx_Pos) /*!< MPU RLAR: AttrIndx Mask */
+
+#define MPU_RLAR_EN_Pos 0U /*!< MPU RLAR: Region enable bit Position */
+#define MPU_RLAR_EN_Msk (1UL /*<< MPU_RLAR_EN_Pos*/) /*!< MPU RLAR: Region enable bit Disable Mask */
+
+/* MPU Memory Attribute Indirection Register 0 Definitions */
+#define MPU_MAIR0_Attr3_Pos 24U /*!< MPU MAIR0: Attr3 Position */
+#define MPU_MAIR0_Attr3_Msk (0xFFUL << MPU_MAIR0_Attr3_Pos) /*!< MPU MAIR0: Attr3 Mask */
+
+#define MPU_MAIR0_Attr2_Pos 16U /*!< MPU MAIR0: Attr2 Position */
+#define MPU_MAIR0_Attr2_Msk (0xFFUL << MPU_MAIR0_Attr2_Pos) /*!< MPU MAIR0: Attr2 Mask */
+
+#define MPU_MAIR0_Attr1_Pos 8U /*!< MPU MAIR0: Attr1 Position */
+#define MPU_MAIR0_Attr1_Msk (0xFFUL << MPU_MAIR0_Attr1_Pos) /*!< MPU MAIR0: Attr1 Mask */
+
+#define MPU_MAIR0_Attr0_Pos 0U /*!< MPU MAIR0: Attr0 Position */
+#define MPU_MAIR0_Attr0_Msk (0xFFUL /*<< MPU_MAIR0_Attr0_Pos*/) /*!< MPU MAIR0: Attr0 Mask */
+
+/* MPU Memory Attribute Indirection Register 1 Definitions */
+#define MPU_MAIR1_Attr7_Pos 24U /*!< MPU MAIR1: Attr7 Position */
+#define MPU_MAIR1_Attr7_Msk (0xFFUL << MPU_MAIR1_Attr7_Pos) /*!< MPU MAIR1: Attr7 Mask */
+
+#define MPU_MAIR1_Attr6_Pos 16U /*!< MPU MAIR1: Attr6 Position */
+#define MPU_MAIR1_Attr6_Msk (0xFFUL << MPU_MAIR1_Attr6_Pos) /*!< MPU MAIR1: Attr6 Mask */
+
+#define MPU_MAIR1_Attr5_Pos 8U /*!< MPU MAIR1: Attr5 Position */
+#define MPU_MAIR1_Attr5_Msk (0xFFUL << MPU_MAIR1_Attr5_Pos) /*!< MPU MAIR1: Attr5 Mask */
+
+#define MPU_MAIR1_Attr4_Pos 0U /*!< MPU MAIR1: Attr4 Position */
+#define MPU_MAIR1_Attr4_Msk (0xFFUL /*<< MPU_MAIR1_Attr4_Pos*/) /*!< MPU MAIR1: Attr4 Mask */
+
+/*@} end of group CMSIS_MPU */
+#endif
+
+
+#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_SAU Security Attribution Unit (SAU)
+ \brief Type definitions for the Security Attribution Unit (SAU)
+ @{
+ */
+
+/**
+ \brief Structure type to access the Security Attribution Unit (SAU).
+ */
+typedef struct
+{
+ __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SAU Control Register */
+ __IM uint32_t TYPE; /*!< Offset: 0x004 (R/ ) SAU Type Register */
+#if defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U)
+ __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) SAU Region Number Register */
+ __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) SAU Region Base Address Register */
+ __IOM uint32_t RLAR; /*!< Offset: 0x010 (R/W) SAU Region Limit Address Register */
+#else
+ uint32_t RESERVED0[3];
+#endif
+ __IOM uint32_t SFSR; /*!< Offset: 0x014 (R/W) Secure Fault Status Register */
+ __IOM uint32_t SFAR; /*!< Offset: 0x018 (R/W) Secure Fault Address Register */
+} SAU_Type;
+
+/* SAU Control Register Definitions */
+#define SAU_CTRL_ALLNS_Pos 1U /*!< SAU CTRL: ALLNS Position */
+#define SAU_CTRL_ALLNS_Msk (1UL << SAU_CTRL_ALLNS_Pos) /*!< SAU CTRL: ALLNS Mask */
+
+#define SAU_CTRL_ENABLE_Pos 0U /*!< SAU CTRL: ENABLE Position */
+#define SAU_CTRL_ENABLE_Msk (1UL /*<< SAU_CTRL_ENABLE_Pos*/) /*!< SAU CTRL: ENABLE Mask */
+
+/* SAU Type Register Definitions */
+#define SAU_TYPE_SREGION_Pos 0U /*!< SAU TYPE: SREGION Position */
+#define SAU_TYPE_SREGION_Msk (0xFFUL /*<< SAU_TYPE_SREGION_Pos*/) /*!< SAU TYPE: SREGION Mask */
+
+#if defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U)
+/* SAU Region Number Register Definitions */
+#define SAU_RNR_REGION_Pos 0U /*!< SAU RNR: REGION Position */
+#define SAU_RNR_REGION_Msk (0xFFUL /*<< SAU_RNR_REGION_Pos*/) /*!< SAU RNR: REGION Mask */
+
+/* SAU Region Base Address Register Definitions */
+#define SAU_RBAR_BADDR_Pos 5U /*!< SAU RBAR: BADDR Position */
+#define SAU_RBAR_BADDR_Msk (0x7FFFFFFUL << SAU_RBAR_BADDR_Pos) /*!< SAU RBAR: BADDR Mask */
+
+/* SAU Region Limit Address Register Definitions */
+#define SAU_RLAR_LADDR_Pos 5U /*!< SAU RLAR: LADDR Position */
+#define SAU_RLAR_LADDR_Msk (0x7FFFFFFUL << SAU_RLAR_LADDR_Pos) /*!< SAU RLAR: LADDR Mask */
+
+#define SAU_RLAR_NSC_Pos 1U /*!< SAU RLAR: NSC Position */
+#define SAU_RLAR_NSC_Msk (1UL << SAU_RLAR_NSC_Pos) /*!< SAU RLAR: NSC Mask */
+
+#define SAU_RLAR_ENABLE_Pos 0U /*!< SAU RLAR: ENABLE Position */
+#define SAU_RLAR_ENABLE_Msk (1UL /*<< SAU_RLAR_ENABLE_Pos*/) /*!< SAU RLAR: ENABLE Mask */
+
+#endif /* defined (__SAUREGION_PRESENT) && (__SAUREGION_PRESENT == 1U) */
+
+/* Secure Fault Status Register Definitions */
+#define SAU_SFSR_LSERR_Pos 7U /*!< SAU SFSR: LSERR Position */
+#define SAU_SFSR_LSERR_Msk (1UL << SAU_SFSR_LSERR_Pos) /*!< SAU SFSR: LSERR Mask */
+
+#define SAU_SFSR_SFARVALID_Pos 6U /*!< SAU SFSR: SFARVALID Position */
+#define SAU_SFSR_SFARVALID_Msk (1UL << SAU_SFSR_SFARVALID_Pos) /*!< SAU SFSR: SFARVALID Mask */
+
+#define SAU_SFSR_LSPERR_Pos 5U /*!< SAU SFSR: LSPERR Position */
+#define SAU_SFSR_LSPERR_Msk (1UL << SAU_SFSR_LSPERR_Pos) /*!< SAU SFSR: LSPERR Mask */
+
+#define SAU_SFSR_INVTRAN_Pos 4U /*!< SAU SFSR: INVTRAN Position */
+#define SAU_SFSR_INVTRAN_Msk (1UL << SAU_SFSR_INVTRAN_Pos) /*!< SAU SFSR: INVTRAN Mask */
+
+#define SAU_SFSR_AUVIOL_Pos 3U /*!< SAU SFSR: AUVIOL Position */
+#define SAU_SFSR_AUVIOL_Msk (1UL << SAU_SFSR_AUVIOL_Pos) /*!< SAU SFSR: AUVIOL Mask */
+
+#define SAU_SFSR_INVER_Pos 2U /*!< SAU SFSR: INVER Position */
+#define SAU_SFSR_INVER_Msk (1UL << SAU_SFSR_INVER_Pos) /*!< SAU SFSR: INVER Mask */
+
+#define SAU_SFSR_INVIS_Pos 1U /*!< SAU SFSR: INVIS Position */
+#define SAU_SFSR_INVIS_Msk (1UL << SAU_SFSR_INVIS_Pos) /*!< SAU SFSR: INVIS Mask */
+
+#define SAU_SFSR_INVEP_Pos 0U /*!< SAU SFSR: INVEP Position */
+#define SAU_SFSR_INVEP_Msk (1UL /*<< SAU_SFSR_INVEP_Pos*/) /*!< SAU SFSR: INVEP Mask */
+
+/*@} end of group CMSIS_SAU */
+#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_FPU Floating Point Unit (FPU)
+ \brief Type definitions for the Floating Point Unit (FPU)
+ @{
+ */
+
+/**
+ \brief Structure type to access the Floating Point Unit (FPU).
+ */
+typedef struct
+{
+ uint32_t RESERVED0[1U];
+ __IOM uint32_t FPCCR; /*!< Offset: 0x004 (R/W) Floating-Point Context Control Register */
+ __IOM uint32_t FPCAR; /*!< Offset: 0x008 (R/W) Floating-Point Context Address Register */
+ __IOM uint32_t FPDSCR; /*!< Offset: 0x00C (R/W) Floating-Point Default Status Control Register */
+ __IM uint32_t MVFR0; /*!< Offset: 0x010 (R/ ) Media and FP Feature Register 0 */
+ __IM uint32_t MVFR1; /*!< Offset: 0x014 (R/ ) Media and FP Feature Register 1 */
+} FPU_Type;
+
+/* Floating-Point Context Control Register Definitions */
+#define FPU_FPCCR_ASPEN_Pos 31U /*!< FPCCR: ASPEN bit Position */
+#define FPU_FPCCR_ASPEN_Msk (1UL << FPU_FPCCR_ASPEN_Pos) /*!< FPCCR: ASPEN bit Mask */
+
+#define FPU_FPCCR_LSPEN_Pos 30U /*!< FPCCR: LSPEN Position */
+#define FPU_FPCCR_LSPEN_Msk (1UL << FPU_FPCCR_LSPEN_Pos) /*!< FPCCR: LSPEN bit Mask */
+
+#define FPU_FPCCR_LSPENS_Pos 29U /*!< FPCCR: LSPENS Position */
+#define FPU_FPCCR_LSPENS_Msk (1UL << FPU_FPCCR_LSPENS_Pos) /*!< FPCCR: LSPENS bit Mask */
+
+#define FPU_FPCCR_CLRONRET_Pos 28U /*!< FPCCR: CLRONRET Position */
+#define FPU_FPCCR_CLRONRET_Msk (1UL << FPU_FPCCR_CLRONRET_Pos) /*!< FPCCR: CLRONRET bit Mask */
+
+#define FPU_FPCCR_CLRONRETS_Pos 27U /*!< FPCCR: CLRONRETS Position */
+#define FPU_FPCCR_CLRONRETS_Msk (1UL << FPU_FPCCR_CLRONRETS_Pos) /*!< FPCCR: CLRONRETS bit Mask */
+
+#define FPU_FPCCR_TS_Pos 26U /*!< FPCCR: TS Position */
+#define FPU_FPCCR_TS_Msk (1UL << FPU_FPCCR_TS_Pos) /*!< FPCCR: TS bit Mask */
+
+#define FPU_FPCCR_UFRDY_Pos 10U /*!< FPCCR: UFRDY Position */
+#define FPU_FPCCR_UFRDY_Msk (1UL << FPU_FPCCR_UFRDY_Pos) /*!< FPCCR: UFRDY bit Mask */
+
+#define FPU_FPCCR_SPLIMVIOL_Pos 9U /*!< FPCCR: SPLIMVIOL Position */
+#define FPU_FPCCR_SPLIMVIOL_Msk (1UL << FPU_FPCCR_SPLIMVIOL_Pos) /*!< FPCCR: SPLIMVIOL bit Mask */
+
+#define FPU_FPCCR_MONRDY_Pos 8U /*!< FPCCR: MONRDY Position */
+#define FPU_FPCCR_MONRDY_Msk (1UL << FPU_FPCCR_MONRDY_Pos) /*!< FPCCR: MONRDY bit Mask */
+
+#define FPU_FPCCR_SFRDY_Pos 7U /*!< FPCCR: SFRDY Position */
+#define FPU_FPCCR_SFRDY_Msk (1UL << FPU_FPCCR_SFRDY_Pos) /*!< FPCCR: SFRDY bit Mask */
+
+#define FPU_FPCCR_BFRDY_Pos 6U /*!< FPCCR: BFRDY Position */
+#define FPU_FPCCR_BFRDY_Msk (1UL << FPU_FPCCR_BFRDY_Pos) /*!< FPCCR: BFRDY bit Mask */
+
+#define FPU_FPCCR_MMRDY_Pos 5U /*!< FPCCR: MMRDY Position */
+#define FPU_FPCCR_MMRDY_Msk (1UL << FPU_FPCCR_MMRDY_Pos) /*!< FPCCR: MMRDY bit Mask */
+
+#define FPU_FPCCR_HFRDY_Pos 4U /*!< FPCCR: HFRDY Position */
+#define FPU_FPCCR_HFRDY_Msk (1UL << FPU_FPCCR_HFRDY_Pos) /*!< FPCCR: HFRDY bit Mask */
+
+#define FPU_FPCCR_THREAD_Pos 3U /*!< FPCCR: processor mode bit Position */
+#define FPU_FPCCR_THREAD_Msk (1UL << FPU_FPCCR_THREAD_Pos) /*!< FPCCR: processor mode active bit Mask */
+
+#define FPU_FPCCR_S_Pos 2U /*!< FPCCR: Security status of the FP context bit Position */
+#define FPU_FPCCR_S_Msk (1UL << FPU_FPCCR_S_Pos) /*!< FPCCR: Security status of the FP context bit Mask */
+
+#define FPU_FPCCR_USER_Pos 1U /*!< FPCCR: privilege level bit Position */
+#define FPU_FPCCR_USER_Msk (1UL << FPU_FPCCR_USER_Pos) /*!< FPCCR: privilege level bit Mask */
+
+#define FPU_FPCCR_LSPACT_Pos 0U /*!< FPCCR: Lazy state preservation active bit Position */
+#define FPU_FPCCR_LSPACT_Msk (1UL /*<< FPU_FPCCR_LSPACT_Pos*/) /*!< FPCCR: Lazy state preservation active bit Mask */
+
+/* Floating-Point Context Address Register Definitions */
+#define FPU_FPCAR_ADDRESS_Pos 3U /*!< FPCAR: ADDRESS bit Position */
+#define FPU_FPCAR_ADDRESS_Msk (0x1FFFFFFFUL << FPU_FPCAR_ADDRESS_Pos) /*!< FPCAR: ADDRESS bit Mask */
+
+/* Floating-Point Default Status Control Register Definitions */
+#define FPU_FPDSCR_AHP_Pos 26U /*!< FPDSCR: AHP bit Position */
+#define FPU_FPDSCR_AHP_Msk (1UL << FPU_FPDSCR_AHP_Pos) /*!< FPDSCR: AHP bit Mask */
+
+#define FPU_FPDSCR_DN_Pos 25U /*!< FPDSCR: DN bit Position */
+#define FPU_FPDSCR_DN_Msk (1UL << FPU_FPDSCR_DN_Pos) /*!< FPDSCR: DN bit Mask */
+
+#define FPU_FPDSCR_FZ_Pos 24U /*!< FPDSCR: FZ bit Position */
+#define FPU_FPDSCR_FZ_Msk (1UL << FPU_FPDSCR_FZ_Pos) /*!< FPDSCR: FZ bit Mask */
+
+#define FPU_FPDSCR_RMode_Pos 22U /*!< FPDSCR: RMode bit Position */
+#define FPU_FPDSCR_RMode_Msk (3UL << FPU_FPDSCR_RMode_Pos) /*!< FPDSCR: RMode bit Mask */
+
+/* Media and FP Feature Register 0 Definitions */
+#define FPU_MVFR0_FP_rounding_modes_Pos 28U /*!< MVFR0: FP rounding modes bits Position */
+#define FPU_MVFR0_FP_rounding_modes_Msk (0xFUL << FPU_MVFR0_FP_rounding_modes_Pos) /*!< MVFR0: FP rounding modes bits Mask */
+
+#define FPU_MVFR0_Short_vectors_Pos 24U /*!< MVFR0: Short vectors bits Position */
+#define FPU_MVFR0_Short_vectors_Msk (0xFUL << FPU_MVFR0_Short_vectors_Pos) /*!< MVFR0: Short vectors bits Mask */
+
+#define FPU_MVFR0_Square_root_Pos 20U /*!< MVFR0: Square root bits Position */
+#define FPU_MVFR0_Square_root_Msk (0xFUL << FPU_MVFR0_Square_root_Pos) /*!< MVFR0: Square root bits Mask */
+
+#define FPU_MVFR0_Divide_Pos 16U /*!< MVFR0: Divide bits Position */
+#define FPU_MVFR0_Divide_Msk (0xFUL << FPU_MVFR0_Divide_Pos) /*!< MVFR0: Divide bits Mask */
+
+#define FPU_MVFR0_FP_excep_trapping_Pos 12U /*!< MVFR0: FP exception trapping bits Position */
+#define FPU_MVFR0_FP_excep_trapping_Msk (0xFUL << FPU_MVFR0_FP_excep_trapping_Pos) /*!< MVFR0: FP exception trapping bits Mask */
+
+#define FPU_MVFR0_Double_precision_Pos 8U /*!< MVFR0: Double-precision bits Position */
+#define FPU_MVFR0_Double_precision_Msk (0xFUL << FPU_MVFR0_Double_precision_Pos) /*!< MVFR0: Double-precision bits Mask */
+
+#define FPU_MVFR0_Single_precision_Pos 4U /*!< MVFR0: Single-precision bits Position */
+#define FPU_MVFR0_Single_precision_Msk (0xFUL << FPU_MVFR0_Single_precision_Pos) /*!< MVFR0: Single-precision bits Mask */
+
+#define FPU_MVFR0_A_SIMD_registers_Pos 0U /*!< MVFR0: A_SIMD registers bits Position */
+#define FPU_MVFR0_A_SIMD_registers_Msk (0xFUL /*<< FPU_MVFR0_A_SIMD_registers_Pos*/) /*!< MVFR0: A_SIMD registers bits Mask */
+
+/* Media and FP Feature Register 1 Definitions */
+#define FPU_MVFR1_FP_fused_MAC_Pos 28U /*!< MVFR1: FP fused MAC bits Position */
+#define FPU_MVFR1_FP_fused_MAC_Msk (0xFUL << FPU_MVFR1_FP_fused_MAC_Pos) /*!< MVFR1: FP fused MAC bits Mask */
+
+#define FPU_MVFR1_FP_HPFP_Pos 24U /*!< MVFR1: FP HPFP bits Position */
+#define FPU_MVFR1_FP_HPFP_Msk (0xFUL << FPU_MVFR1_FP_HPFP_Pos) /*!< MVFR1: FP HPFP bits Mask */
+
+#define FPU_MVFR1_D_NaN_mode_Pos 4U /*!< MVFR1: D_NaN mode bits Position */
+#define FPU_MVFR1_D_NaN_mode_Msk (0xFUL << FPU_MVFR1_D_NaN_mode_Pos) /*!< MVFR1: D_NaN mode bits Mask */
+
+#define FPU_MVFR1_FtZ_mode_Pos 0U /*!< MVFR1: FtZ mode bits Position */
+#define FPU_MVFR1_FtZ_mode_Msk (0xFUL /*<< FPU_MVFR1_FtZ_mode_Pos*/) /*!< MVFR1: FtZ mode bits Mask */
+
+/*@} end of group CMSIS_FPU */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug)
+ \brief Type definitions for the Core Debug Registers
+ @{
+ */
+
+/**
+ \brief Structure type to access the Core Debug Register (CoreDebug).
+ */
+typedef struct
+{
+ __IOM uint32_t DHCSR; /*!< Offset: 0x000 (R/W) Debug Halting Control and Status Register */
+ __OM uint32_t DCRSR; /*!< Offset: 0x004 ( /W) Debug Core Register Selector Register */
+ __IOM uint32_t DCRDR; /*!< Offset: 0x008 (R/W) Debug Core Register Data Register */
+ __IOM uint32_t DEMCR; /*!< Offset: 0x00C (R/W) Debug Exception and Monitor Control Register */
+ uint32_t RESERVED4[1U];
+ __IOM uint32_t DAUTHCTRL; /*!< Offset: 0x014 (R/W) Debug Authentication Control Register */
+ __IOM uint32_t DSCSR; /*!< Offset: 0x018 (R/W) Debug Security Control and Status Register */
+} CoreDebug_Type;
+
+/* Debug Halting Control and Status Register Definitions */
+#define CoreDebug_DHCSR_DBGKEY_Pos 16U /*!< CoreDebug DHCSR: DBGKEY Position */
+#define CoreDebug_DHCSR_DBGKEY_Msk (0xFFFFUL << CoreDebug_DHCSR_DBGKEY_Pos) /*!< CoreDebug DHCSR: DBGKEY Mask */
+
+#define CoreDebug_DHCSR_S_RESTART_ST_Pos 26U /*!< CoreDebug DHCSR: S_RESTART_ST Position */
+#define CoreDebug_DHCSR_S_RESTART_ST_Msk (1UL << CoreDebug_DHCSR_S_RESTART_ST_Pos) /*!< CoreDebug DHCSR: S_RESTART_ST Mask */
+
+#define CoreDebug_DHCSR_S_RESET_ST_Pos 25U /*!< CoreDebug DHCSR: S_RESET_ST Position */
+#define CoreDebug_DHCSR_S_RESET_ST_Msk (1UL << CoreDebug_DHCSR_S_RESET_ST_Pos) /*!< CoreDebug DHCSR: S_RESET_ST Mask */
+
+#define CoreDebug_DHCSR_S_RETIRE_ST_Pos 24U /*!< CoreDebug DHCSR: S_RETIRE_ST Position */
+#define CoreDebug_DHCSR_S_RETIRE_ST_Msk (1UL << CoreDebug_DHCSR_S_RETIRE_ST_Pos) /*!< CoreDebug DHCSR: S_RETIRE_ST Mask */
+
+#define CoreDebug_DHCSR_S_LOCKUP_Pos 19U /*!< CoreDebug DHCSR: S_LOCKUP Position */
+#define CoreDebug_DHCSR_S_LOCKUP_Msk (1UL << CoreDebug_DHCSR_S_LOCKUP_Pos) /*!< CoreDebug DHCSR: S_LOCKUP Mask */
+
+#define CoreDebug_DHCSR_S_SLEEP_Pos 18U /*!< CoreDebug DHCSR: S_SLEEP Position */
+#define CoreDebug_DHCSR_S_SLEEP_Msk (1UL << CoreDebug_DHCSR_S_SLEEP_Pos) /*!< CoreDebug DHCSR: S_SLEEP Mask */
+
+#define CoreDebug_DHCSR_S_HALT_Pos 17U /*!< CoreDebug DHCSR: S_HALT Position */
+#define CoreDebug_DHCSR_S_HALT_Msk (1UL << CoreDebug_DHCSR_S_HALT_Pos) /*!< CoreDebug DHCSR: S_HALT Mask */
+
+#define CoreDebug_DHCSR_S_REGRDY_Pos 16U /*!< CoreDebug DHCSR: S_REGRDY Position */
+#define CoreDebug_DHCSR_S_REGRDY_Msk (1UL << CoreDebug_DHCSR_S_REGRDY_Pos) /*!< CoreDebug DHCSR: S_REGRDY Mask */
+
+#define CoreDebug_DHCSR_C_SNAPSTALL_Pos 5U /*!< CoreDebug DHCSR: C_SNAPSTALL Position */
+#define CoreDebug_DHCSR_C_SNAPSTALL_Msk (1UL << CoreDebug_DHCSR_C_SNAPSTALL_Pos) /*!< CoreDebug DHCSR: C_SNAPSTALL Mask */
+
+#define CoreDebug_DHCSR_C_MASKINTS_Pos 3U /*!< CoreDebug DHCSR: C_MASKINTS Position */
+#define CoreDebug_DHCSR_C_MASKINTS_Msk (1UL << CoreDebug_DHCSR_C_MASKINTS_Pos) /*!< CoreDebug DHCSR: C_MASKINTS Mask */
+
+#define CoreDebug_DHCSR_C_STEP_Pos 2U /*!< CoreDebug DHCSR: C_STEP Position */
+#define CoreDebug_DHCSR_C_STEP_Msk (1UL << CoreDebug_DHCSR_C_STEP_Pos) /*!< CoreDebug DHCSR: C_STEP Mask */
+
+#define CoreDebug_DHCSR_C_HALT_Pos 1U /*!< CoreDebug DHCSR: C_HALT Position */
+#define CoreDebug_DHCSR_C_HALT_Msk (1UL << CoreDebug_DHCSR_C_HALT_Pos) /*!< CoreDebug DHCSR: C_HALT Mask */
+
+#define CoreDebug_DHCSR_C_DEBUGEN_Pos 0U /*!< CoreDebug DHCSR: C_DEBUGEN Position */
+#define CoreDebug_DHCSR_C_DEBUGEN_Msk (1UL /*<< CoreDebug_DHCSR_C_DEBUGEN_Pos*/) /*!< CoreDebug DHCSR: C_DEBUGEN Mask */
+
+/* Debug Core Register Selector Register Definitions */
+#define CoreDebug_DCRSR_REGWnR_Pos 16U /*!< CoreDebug DCRSR: REGWnR Position */
+#define CoreDebug_DCRSR_REGWnR_Msk (1UL << CoreDebug_DCRSR_REGWnR_Pos) /*!< CoreDebug DCRSR: REGWnR Mask */
+
+#define CoreDebug_DCRSR_REGSEL_Pos 0U /*!< CoreDebug DCRSR: REGSEL Position */
+#define CoreDebug_DCRSR_REGSEL_Msk (0x1FUL /*<< CoreDebug_DCRSR_REGSEL_Pos*/) /*!< CoreDebug DCRSR: REGSEL Mask */
+
+/* Debug Exception and Monitor Control Register Definitions */
+#define CoreDebug_DEMCR_TRCENA_Pos 24U /*!< CoreDebug DEMCR: TRCENA Position */
+#define CoreDebug_DEMCR_TRCENA_Msk (1UL << CoreDebug_DEMCR_TRCENA_Pos) /*!< CoreDebug DEMCR: TRCENA Mask */
+
+#define CoreDebug_DEMCR_MON_REQ_Pos 19U /*!< CoreDebug DEMCR: MON_REQ Position */
+#define CoreDebug_DEMCR_MON_REQ_Msk (1UL << CoreDebug_DEMCR_MON_REQ_Pos) /*!< CoreDebug DEMCR: MON_REQ Mask */
+
+#define CoreDebug_DEMCR_MON_STEP_Pos 18U /*!< CoreDebug DEMCR: MON_STEP Position */
+#define CoreDebug_DEMCR_MON_STEP_Msk (1UL << CoreDebug_DEMCR_MON_STEP_Pos) /*!< CoreDebug DEMCR: MON_STEP Mask */
+
+#define CoreDebug_DEMCR_MON_PEND_Pos 17U /*!< CoreDebug DEMCR: MON_PEND Position */
+#define CoreDebug_DEMCR_MON_PEND_Msk (1UL << CoreDebug_DEMCR_MON_PEND_Pos) /*!< CoreDebug DEMCR: MON_PEND Mask */
+
+#define CoreDebug_DEMCR_MON_EN_Pos 16U /*!< CoreDebug DEMCR: MON_EN Position */
+#define CoreDebug_DEMCR_MON_EN_Msk (1UL << CoreDebug_DEMCR_MON_EN_Pos) /*!< CoreDebug DEMCR: MON_EN Mask */
+
+#define CoreDebug_DEMCR_VC_HARDERR_Pos 10U /*!< CoreDebug DEMCR: VC_HARDERR Position */
+#define CoreDebug_DEMCR_VC_HARDERR_Msk (1UL << CoreDebug_DEMCR_VC_HARDERR_Pos) /*!< CoreDebug DEMCR: VC_HARDERR Mask */
+
+#define CoreDebug_DEMCR_VC_INTERR_Pos 9U /*!< CoreDebug DEMCR: VC_INTERR Position */
+#define CoreDebug_DEMCR_VC_INTERR_Msk (1UL << CoreDebug_DEMCR_VC_INTERR_Pos) /*!< CoreDebug DEMCR: VC_INTERR Mask */
+
+#define CoreDebug_DEMCR_VC_BUSERR_Pos 8U /*!< CoreDebug DEMCR: VC_BUSERR Position */
+#define CoreDebug_DEMCR_VC_BUSERR_Msk (1UL << CoreDebug_DEMCR_VC_BUSERR_Pos) /*!< CoreDebug DEMCR: VC_BUSERR Mask */
+
+#define CoreDebug_DEMCR_VC_STATERR_Pos 7U /*!< CoreDebug DEMCR: VC_STATERR Position */
+#define CoreDebug_DEMCR_VC_STATERR_Msk (1UL << CoreDebug_DEMCR_VC_STATERR_Pos) /*!< CoreDebug DEMCR: VC_STATERR Mask */
+
+#define CoreDebug_DEMCR_VC_CHKERR_Pos 6U /*!< CoreDebug DEMCR: VC_CHKERR Position */
+#define CoreDebug_DEMCR_VC_CHKERR_Msk (1UL << CoreDebug_DEMCR_VC_CHKERR_Pos) /*!< CoreDebug DEMCR: VC_CHKERR Mask */
+
+#define CoreDebug_DEMCR_VC_NOCPERR_Pos 5U /*!< CoreDebug DEMCR: VC_NOCPERR Position */
+#define CoreDebug_DEMCR_VC_NOCPERR_Msk (1UL << CoreDebug_DEMCR_VC_NOCPERR_Pos) /*!< CoreDebug DEMCR: VC_NOCPERR Mask */
+
+#define CoreDebug_DEMCR_VC_MMERR_Pos 4U /*!< CoreDebug DEMCR: VC_MMERR Position */
+#define CoreDebug_DEMCR_VC_MMERR_Msk (1UL << CoreDebug_DEMCR_VC_MMERR_Pos) /*!< CoreDebug DEMCR: VC_MMERR Mask */
+
+#define CoreDebug_DEMCR_VC_CORERESET_Pos 0U /*!< CoreDebug DEMCR: VC_CORERESET Position */
+#define CoreDebug_DEMCR_VC_CORERESET_Msk (1UL /*<< CoreDebug_DEMCR_VC_CORERESET_Pos*/) /*!< CoreDebug DEMCR: VC_CORERESET Mask */
+
+/* Debug Authentication Control Register Definitions */
+#define CoreDebug_DAUTHCTRL_INTSPNIDEN_Pos 3U /*!< CoreDebug DAUTHCTRL: INTSPNIDEN, Position */
+#define CoreDebug_DAUTHCTRL_INTSPNIDEN_Msk (1UL << CoreDebug_DAUTHCTRL_INTSPNIDEN_Pos) /*!< CoreDebug DAUTHCTRL: INTSPNIDEN, Mask */
+
+#define CoreDebug_DAUTHCTRL_SPNIDENSEL_Pos 2U /*!< CoreDebug DAUTHCTRL: SPNIDENSEL Position */
+#define CoreDebug_DAUTHCTRL_SPNIDENSEL_Msk (1UL << CoreDebug_DAUTHCTRL_SPNIDENSEL_Pos) /*!< CoreDebug DAUTHCTRL: SPNIDENSEL Mask */
+
+#define CoreDebug_DAUTHCTRL_INTSPIDEN_Pos 1U /*!< CoreDebug DAUTHCTRL: INTSPIDEN Position */
+#define CoreDebug_DAUTHCTRL_INTSPIDEN_Msk (1UL << CoreDebug_DAUTHCTRL_INTSPIDEN_Pos) /*!< CoreDebug DAUTHCTRL: INTSPIDEN Mask */
+
+#define CoreDebug_DAUTHCTRL_SPIDENSEL_Pos 0U /*!< CoreDebug DAUTHCTRL: SPIDENSEL Position */
+#define CoreDebug_DAUTHCTRL_SPIDENSEL_Msk (1UL /*<< CoreDebug_DAUTHCTRL_SPIDENSEL_Pos*/) /*!< CoreDebug DAUTHCTRL: SPIDENSEL Mask */
+
+/* Debug Security Control and Status Register Definitions */
+#define CoreDebug_DSCSR_CDS_Pos 16U /*!< CoreDebug DSCSR: CDS Position */
+#define CoreDebug_DSCSR_CDS_Msk (1UL << CoreDebug_DSCSR_CDS_Pos) /*!< CoreDebug DSCSR: CDS Mask */
+
+#define CoreDebug_DSCSR_SBRSEL_Pos 1U /*!< CoreDebug DSCSR: SBRSEL Position */
+#define CoreDebug_DSCSR_SBRSEL_Msk (1UL << CoreDebug_DSCSR_SBRSEL_Pos) /*!< CoreDebug DSCSR: SBRSEL Mask */
+
+#define CoreDebug_DSCSR_SBRSELEN_Pos 0U /*!< CoreDebug DSCSR: SBRSELEN Position */
+#define CoreDebug_DSCSR_SBRSELEN_Msk (1UL /*<< CoreDebug_DSCSR_SBRSELEN_Pos*/) /*!< CoreDebug DSCSR: SBRSELEN Mask */
+
+/*@} end of group CMSIS_CoreDebug */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_core_bitfield Core register bit field macros
+ \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk).
+ @{
+ */
+
+/**
+ \brief Mask and shift a bit field value for use in a register bit range.
+ \param[in] field Name of the register bit field.
+ \param[in] value Value of the bit field. This parameter is interpreted as an uint32_t type.
+ \return Masked and shifted value.
+*/
+#define _VAL2FLD(field, value) (((uint32_t)(value) << field ## _Pos) & field ## _Msk)
+
+/**
+ \brief Mask and shift a register value to extract a bit filed value.
+ \param[in] field Name of the register bit field.
+ \param[in] value Value of register. This parameter is interpreted as an uint32_t type.
+ \return Masked and shifted bit field value.
+*/
+#define _FLD2VAL(field, value) (((uint32_t)(value) & field ## _Msk) >> field ## _Pos)
+
+/*@} end of group CMSIS_core_bitfield */
+
+
+/**
+ \ingroup CMSIS_core_register
+ \defgroup CMSIS_core_base Core Definitions
+ \brief Definitions for base addresses, unions, and structures.
+ @{
+ */
+
+/* Memory mapping of Core Hardware */
+ #define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */
+ #define ITM_BASE (0xE0000000UL) /*!< ITM Base Address */
+ #define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */
+ #define TPI_BASE (0xE0040000UL) /*!< TPI Base Address */
+ #define CoreDebug_BASE (0xE000EDF0UL) /*!< Core Debug Base Address */
+ #define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */
+ #define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */
+ #define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */
+
+ #define SCnSCB ((SCnSCB_Type *) SCS_BASE ) /*!< System control Register not in SCB */
+ #define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */
+ #define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */
+ #define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */
+ #define ITM ((ITM_Type *) ITM_BASE ) /*!< ITM configuration struct */
+ #define DWT ((DWT_Type *) DWT_BASE ) /*!< DWT configuration struct */
+ #define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */
+ #define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE ) /*!< Core Debug configuration struct */
+
+ #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U)
+ #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */
+ #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */
+ #endif
+
+ #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
+ #define SAU_BASE (SCS_BASE + 0x0DD0UL) /*!< Security Attribution Unit */
+ #define SAU ((SAU_Type *) SAU_BASE ) /*!< Security Attribution Unit */
+ #endif
+
+ #define FPU_BASE (SCS_BASE + 0x0F30UL) /*!< Floating Point Unit */
+ #define FPU ((FPU_Type *) FPU_BASE ) /*!< Floating Point Unit */
+
+#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
+ #define SCS_BASE_NS (0xE002E000UL) /*!< System Control Space Base Address (non-secure address space) */
+ #define CoreDebug_BASE_NS (0xE002EDF0UL) /*!< Core Debug Base Address (non-secure address space) */
+ #define SysTick_BASE_NS (SCS_BASE_NS + 0x0010UL) /*!< SysTick Base Address (non-secure address space) */
+ #define NVIC_BASE_NS (SCS_BASE_NS + 0x0100UL) /*!< NVIC Base Address (non-secure address space) */
+ #define SCB_BASE_NS (SCS_BASE_NS + 0x0D00UL) /*!< System Control Block Base Address (non-secure address space) */
+
+ #define SCnSCB_NS ((SCnSCB_Type *) SCS_BASE_NS ) /*!< System control Register not in SCB(non-secure address space) */
+ #define SCB_NS ((SCB_Type *) SCB_BASE_NS ) /*!< SCB configuration struct (non-secure address space) */
+ #define SysTick_NS ((SysTick_Type *) SysTick_BASE_NS ) /*!< SysTick configuration struct (non-secure address space) */
+ #define NVIC_NS ((NVIC_Type *) NVIC_BASE_NS ) /*!< NVIC configuration struct (non-secure address space) */
+ #define CoreDebug_NS ((CoreDebug_Type *) CoreDebug_BASE_NS) /*!< Core Debug configuration struct (non-secure address space) */
+
+ #if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U)
+ #define MPU_BASE_NS (SCS_BASE_NS + 0x0D90UL) /*!< Memory Protection Unit (non-secure address space) */
+ #define MPU_NS ((MPU_Type *) MPU_BASE_NS ) /*!< Memory Protection Unit (non-secure address space) */
+ #endif
+
+ #define FPU_BASE_NS (SCS_BASE_NS + 0x0F30UL) /*!< Floating Point Unit (non-secure address space) */
+ #define FPU_NS ((FPU_Type *) FPU_BASE_NS ) /*!< Floating Point Unit (non-secure address space) */
+
+#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */
+/*@} */
+
+
+
+/*******************************************************************************
+ * Hardware Abstraction Layer
+ Core Function Interface contains:
+ - Core NVIC Functions
+ - Core SysTick Functions
+ - Core Debug Functions
+ - Core Register Access Functions
+ ******************************************************************************/
+/**
+ \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference
+*/
+
+
+
+/* ########################## NVIC functions #################################### */
+/**
+ \ingroup CMSIS_Core_FunctionInterface
+ \defgroup CMSIS_Core_NVICFunctions NVIC Functions
+ \brief Functions that manage interrupts and exceptions via the NVIC.
+ @{
+ */
+
+#ifdef CMSIS_NVIC_VIRTUAL
+ #ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE
+ #define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h"
+ #endif
+ #include CMSIS_NVIC_VIRTUAL_HEADER_FILE
+#else
+ #define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping
+ #define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping
+ #define NVIC_EnableIRQ __NVIC_EnableIRQ
+ #define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ
+ #define NVIC_DisableIRQ __NVIC_DisableIRQ
+ #define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ
+ #define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ
+ #define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ
+ #define NVIC_GetActive __NVIC_GetActive
+ #define NVIC_SetPriority __NVIC_SetPriority
+ #define NVIC_GetPriority __NVIC_GetPriority
+ #define NVIC_SystemReset __NVIC_SystemReset
+#endif /* CMSIS_NVIC_VIRTUAL */
+
+#ifdef CMSIS_VECTAB_VIRTUAL
+ #ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE
+ #define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h"
+ #endif
+ #include CMSIS_VECTAB_VIRTUAL_HEADER_FILE
+#else
+ #define NVIC_SetVector __NVIC_SetVector
+ #define NVIC_GetVector __NVIC_GetVector
+#endif /* (CMSIS_VECTAB_VIRTUAL) */
+
+#define NVIC_USER_IRQ_OFFSET 16
+
+
+/* Special LR values for Secure/Non-Secure call handling and exception handling */
+
+/* Function Return Payload (from ARMv8-M Architecture Reference Manual) LR value on entry from Secure BLXNS */
+#define FNC_RETURN (0xFEFFFFFFUL) /* bit [0] ignored when processing a branch */
+
+/* The following EXC_RETURN mask values are used to evaluate the LR on exception entry */
+#define EXC_RETURN_PREFIX (0xFF000000UL) /* bits [31:24] set to indicate an EXC_RETURN value */
+#define EXC_RETURN_S (0x00000040UL) /* bit [6] stack used to push registers: 0=Non-secure 1=Secure */
+#define EXC_RETURN_DCRS (0x00000020UL) /* bit [5] stacking rules for called registers: 0=skipped 1=saved */
+#define EXC_RETURN_FTYPE (0x00000010UL) /* bit [4] allocate stack for floating-point context: 0=done 1=skipped */
+#define EXC_RETURN_MODE (0x00000008UL) /* bit [3] processor mode for return: 0=Handler mode 1=Thread mode */
+#define EXC_RETURN_SPSEL (0x00000004UL) /* bit [2] stack pointer used to restore context: 0=MSP 1=PSP */
+#define EXC_RETURN_ES (0x00000001UL) /* bit [0] security state exception was taken to: 0=Non-secure 1=Secure */
+
+/* Integrity Signature (from ARMv8-M Architecture Reference Manual) for exception context stacking */
+#if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U) /* Value for processors with floating-point extension: */
+#define EXC_INTEGRITY_SIGNATURE (0xFEFA125AUL) /* bit [0] SFTC must match LR bit[4] EXC_RETURN_FTYPE */
+#else
+#define EXC_INTEGRITY_SIGNATURE (0xFEFA125BUL) /* Value for processors without floating-point extension */
+#endif
+
+
+/**
+ \brief Set Priority Grouping
+ \details Sets the priority grouping field using the required unlock sequence.
+ The parameter PriorityGroup is assigned to the field SCB->AIRCR [10:8] PRIGROUP field.
+ Only values from 0..7 are used.
+ In case of a conflict between priority grouping and available
+ priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set.
+ \param [in] PriorityGroup Priority grouping field.
+ */
+__STATIC_INLINE void __NVIC_SetPriorityGrouping(uint32_t PriorityGroup)
+{
+ uint32_t reg_value;
+ uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */
+
+ reg_value = SCB->AIRCR; /* read old register configuration */
+ reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */
+ reg_value = (reg_value |
+ ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) |
+ (PriorityGroupTmp << SCB_AIRCR_PRIGROUP_Pos) ); /* Insert write key and priority group */
+ SCB->AIRCR = reg_value;
+}
+
+
+/**
+ \brief Get Priority Grouping
+ \details Reads the priority grouping field from the NVIC Interrupt Controller.
+ \return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field).
+ */
+__STATIC_INLINE uint32_t __NVIC_GetPriorityGrouping(void)
+{
+ return ((uint32_t)((SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos));
+}
+
+
+/**
+ \brief Enable Interrupt
+ \details Enables a device specific interrupt in the NVIC interrupt controller.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Get Interrupt Enable status
+ \details Returns a device specific interrupt enable status from the NVIC interrupt controller.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 Interrupt is not enabled.
+ \return 1 Interrupt is enabled.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Disable Interrupt
+ \details Disables a device specific interrupt in the NVIC interrupt controller.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ICER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ __DSB();
+ __ISB();
+ }
+}
+
+
+/**
+ \brief Get Pending Interrupt
+ \details Reads the NVIC pending register and returns the pending bit for the specified device specific interrupt.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 Interrupt status is not pending.
+ \return 1 Interrupt status is pending.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Set Pending Interrupt
+ \details Sets the pending bit of a device specific interrupt in the NVIC pending register.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Clear Pending Interrupt
+ \details Clears the pending bit of a device specific interrupt in the NVIC pending register.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Get Active Interrupt
+ \details Reads the active register in the NVIC and returns the active bit for the device specific interrupt.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 Interrupt status is not active.
+ \return 1 Interrupt status is active.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t __NVIC_GetActive(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC->IABR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
+/**
+ \brief Get Interrupt Target State
+ \details Reads the interrupt target field in the NVIC and returns the interrupt target bit for the device specific interrupt.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 if interrupt is assigned to Secure
+ \return 1 if interrupt is assigned to Non Secure
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t NVIC_GetTargetState(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Set Interrupt Target State
+ \details Sets the interrupt target field in the NVIC and returns the interrupt target bit for the device specific interrupt.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 if interrupt is assigned to Secure
+ 1 if interrupt is assigned to Non Secure
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t NVIC_SetTargetState(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] |= ((uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)));
+ return((uint32_t)(((NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Clear Interrupt Target State
+ \details Clears the interrupt target field in the NVIC and returns the interrupt target bit for the device specific interrupt.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 if interrupt is assigned to Secure
+ 1 if interrupt is assigned to Non Secure
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t NVIC_ClearTargetState(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] &= ~((uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)));
+ return((uint32_t)(((NVIC->ITNS[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */
+
+
+/**
+ \brief Set Interrupt Priority
+ \details Sets the priority of a device specific interrupt or a processor exception.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ \param [in] IRQn Interrupt number.
+ \param [in] priority Priority to set.
+ \note The priority cannot be set for every processor exception.
+ */
+__STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->IPR[((uint32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL);
+ }
+ else
+ {
+ SCB->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL);
+ }
+}
+
+
+/**
+ \brief Get Interrupt Priority
+ \details Reads the priority of a device specific interrupt or a processor exception.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ \param [in] IRQn Interrupt number.
+ \return Interrupt Priority.
+ Value is aligned automatically to the implemented priority bits of the microcontroller.
+ */
+__STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn)
+{
+
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return(((uint32_t)NVIC->IPR[((uint32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS)));
+ }
+ else
+ {
+ return(((uint32_t)SCB->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS)));
+ }
+}
+
+
+/**
+ \brief Encode Priority
+ \details Encodes the priority for an interrupt with the given priority group,
+ preemptive priority value, and subpriority value.
+ In case of a conflict between priority grouping and available
+ priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set.
+ \param [in] PriorityGroup Used priority group.
+ \param [in] PreemptPriority Preemptive priority value (starting from 0).
+ \param [in] SubPriority Subpriority value (starting from 0).
+ \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority().
+ */
+__STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority)
+{
+ uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */
+ uint32_t PreemptPriorityBits;
+ uint32_t SubPriorityBits;
+
+ PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp);
+ SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS));
+
+ return (
+ ((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) |
+ ((SubPriority & (uint32_t)((1UL << (SubPriorityBits )) - 1UL)))
+ );
+}
+
+
+/**
+ \brief Decode Priority
+ \details Decodes an interrupt priority value with a given priority group to
+ preemptive priority value and subpriority value.
+ In case of a conflict between priority grouping and available
+ priority bits (__NVIC_PRIO_BITS) the smallest possible priority group is set.
+ \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority().
+ \param [in] PriorityGroup Used priority group.
+ \param [out] pPreemptPriority Preemptive priority value (starting from 0).
+ \param [out] pSubPriority Subpriority value (starting from 0).
+ */
+__STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* const pPreemptPriority, uint32_t* const pSubPriority)
+{
+ uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */
+ uint32_t PreemptPriorityBits;
+ uint32_t SubPriorityBits;
+
+ PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp);
+ SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS));
+
+ *pPreemptPriority = (Priority >> SubPriorityBits) & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL);
+ *pSubPriority = (Priority ) & (uint32_t)((1UL << (SubPriorityBits )) - 1UL);
+}
+
+
+/**
+ \brief Set Interrupt Vector
+ \details Sets an interrupt vector in SRAM based interrupt vector table.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ VTOR must been relocated to SRAM before.
+ \param [in] IRQn Interrupt number
+ \param [in] vector Address of interrupt handler function
+ */
+__STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector)
+{
+ uint32_t *vectors = (uint32_t *)SCB->VTOR;
+ vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET] = vector;
+}
+
+
+/**
+ \brief Get Interrupt Vector
+ \details Reads an interrupt vector from interrupt vector table.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ \param [in] IRQn Interrupt number.
+ \return Address of interrupt handler function
+ */
+__STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn)
+{
+ uint32_t *vectors = (uint32_t *)SCB->VTOR;
+ return vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET];
+}
+
+
+/**
+ \brief System Reset
+ \details Initiates a system reset request to reset the MCU.
+ */
+__NO_RETURN __STATIC_INLINE void __NVIC_SystemReset(void)
+{
+ __DSB(); /* Ensure all outstanding memory accesses included
+ buffered write are completed before reset */
+ SCB->AIRCR = (uint32_t)((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) |
+ (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) |
+ SCB_AIRCR_SYSRESETREQ_Msk ); /* Keep priority group unchanged */
+ __DSB(); /* Ensure completion of memory access */
+
+ for(;;) /* wait until reset */
+ {
+ __NOP();
+ }
+}
+
+#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
+/**
+ \brief Set Priority Grouping (non-secure)
+ \details Sets the non-secure priority grouping field when in secure state using the required unlock sequence.
+ The parameter PriorityGroup is assigned to the field SCB->AIRCR [10:8] PRIGROUP field.
+ Only values from 0..7 are used.
+ In case of a conflict between priority grouping and available
+ priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set.
+ \param [in] PriorityGroup Priority grouping field.
+ */
+__STATIC_INLINE void TZ_NVIC_SetPriorityGrouping_NS(uint32_t PriorityGroup)
+{
+ uint32_t reg_value;
+ uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */
+
+ reg_value = SCB_NS->AIRCR; /* read old register configuration */
+ reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */
+ reg_value = (reg_value |
+ ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) |
+ (PriorityGroupTmp << SCB_AIRCR_PRIGROUP_Pos) ); /* Insert write key and priority group */
+ SCB_NS->AIRCR = reg_value;
+}
+
+
+/**
+ \brief Get Priority Grouping (non-secure)
+ \details Reads the priority grouping field from the non-secure NVIC when in secure state.
+ \return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field).
+ */
+__STATIC_INLINE uint32_t TZ_NVIC_GetPriorityGrouping_NS(void)
+{
+ return ((uint32_t)((SCB_NS->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos));
+}
+
+
+/**
+ \brief Enable Interrupt (non-secure)
+ \details Enables a device specific interrupt in the non-secure NVIC interrupt controller when in secure state.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void TZ_NVIC_EnableIRQ_NS(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC_NS->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Get Interrupt Enable status (non-secure)
+ \details Returns a device specific interrupt enable status from the non-secure NVIC interrupt controller when in secure state.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 Interrupt is not enabled.
+ \return 1 Interrupt is enabled.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t TZ_NVIC_GetEnableIRQ_NS(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC_NS->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Disable Interrupt (non-secure)
+ \details Disables a device specific interrupt in the non-secure NVIC interrupt controller when in secure state.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void TZ_NVIC_DisableIRQ_NS(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC_NS->ICER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Get Pending Interrupt (non-secure)
+ \details Reads the NVIC pending register in the non-secure NVIC when in secure state and returns the pending bit for the specified device specific interrupt.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 Interrupt status is not pending.
+ \return 1 Interrupt status is pending.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t TZ_NVIC_GetPendingIRQ_NS(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC_NS->ISPR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Set Pending Interrupt (non-secure)
+ \details Sets the pending bit of a device specific interrupt in the non-secure NVIC pending register when in secure state.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void TZ_NVIC_SetPendingIRQ_NS(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC_NS->ISPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Clear Pending Interrupt (non-secure)
+ \details Clears the pending bit of a device specific interrupt in the non-secure NVIC pending register when in secure state.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void TZ_NVIC_ClearPendingIRQ_NS(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC_NS->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
+}
+
+
+/**
+ \brief Get Active Interrupt (non-secure)
+ \details Reads the active register in non-secure NVIC when in secure state and returns the active bit for the device specific interrupt.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 Interrupt status is not active.
+ \return 1 Interrupt status is active.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE uint32_t TZ_NVIC_GetActive_NS(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC_NS->IABR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Set Interrupt Priority (non-secure)
+ \details Sets the priority of a non-secure device specific interrupt or a non-secure processor exception when in secure state.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ \param [in] IRQn Interrupt number.
+ \param [in] priority Priority to set.
+ \note The priority cannot be set for every non-secure processor exception.
+ */
+__STATIC_INLINE void TZ_NVIC_SetPriority_NS(IRQn_Type IRQn, uint32_t priority)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC_NS->IPR[((uint32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL);
+ }
+ else
+ {
+ SCB_NS->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL);
+ }
+}
+
+
+/**
+ \brief Get Interrupt Priority (non-secure)
+ \details Reads the priority of a non-secure device specific interrupt or a non-secure processor exception when in secure state.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ \param [in] IRQn Interrupt number.
+ \return Interrupt Priority. Value is aligned automatically to the implemented priority bits of the microcontroller.
+ */
+__STATIC_INLINE uint32_t TZ_NVIC_GetPriority_NS(IRQn_Type IRQn)
+{
+
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return(((uint32_t)NVIC_NS->IPR[((uint32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS)));
+ }
+ else
+ {
+ return(((uint32_t)SCB_NS->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS)));
+ }
+}
+#endif /* defined (__ARM_FEATURE_CMSE) &&(__ARM_FEATURE_CMSE == 3U) */
+
+/*@} end of CMSIS_Core_NVICFunctions */
+
+/* ########################## MPU functions #################################### */
+
+#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U)
+
+#include "mpu_armv8.h"
+
+#endif
+
+/* ########################## FPU functions #################################### */
+/**
+ \ingroup CMSIS_Core_FunctionInterface
+ \defgroup CMSIS_Core_FpuFunctions FPU Functions
+ \brief Function that provides FPU type.
+ @{
+ */
+
+/**
+ \brief get FPU type
+ \details returns the FPU type
+ \returns
+ - \b 0: No FPU
+ - \b 1: Single precision FPU
+ - \b 2: Double + Single precision FPU
+ */
+__STATIC_INLINE uint32_t SCB_GetFPUType(void)
+{
+ uint32_t mvfr0;
+
+ mvfr0 = FPU->MVFR0;
+ if ((mvfr0 & (FPU_MVFR0_Single_precision_Msk | FPU_MVFR0_Double_precision_Msk)) == 0x220U)
+ {
+ return 2U; /* Double + Single precision FPU */
+ }
+ else if ((mvfr0 & (FPU_MVFR0_Single_precision_Msk | FPU_MVFR0_Double_precision_Msk)) == 0x020U)
+ {
+ return 1U; /* Single precision FPU */
+ }
+ else
+ {
+ return 0U; /* No FPU */
+ }
+}
+
+
+/*@} end of CMSIS_Core_FpuFunctions */
+
+
+
+/* ########################## SAU functions #################################### */
+/**
+ \ingroup CMSIS_Core_FunctionInterface
+ \defgroup CMSIS_Core_SAUFunctions SAU Functions
+ \brief Functions that configure the SAU.
+ @{
+ */
+
+#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
+
+/**
+ \brief Enable SAU
+ \details Enables the Security Attribution Unit (SAU).
+ */
+__STATIC_INLINE void TZ_SAU_Enable(void)
+{
+ SAU->CTRL |= (SAU_CTRL_ENABLE_Msk);
+}
+
+
+
+/**
+ \brief Disable SAU
+ \details Disables the Security Attribution Unit (SAU).
+ */
+__STATIC_INLINE void TZ_SAU_Disable(void)
+{
+ SAU->CTRL &= ~(SAU_CTRL_ENABLE_Msk);
+}
+
+#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */
+
+/*@} end of CMSIS_Core_SAUFunctions */
+
+
+
+
+/* ################################## SysTick function ############################################ */
+/**
+ \ingroup CMSIS_Core_FunctionInterface
+ \defgroup CMSIS_Core_SysTickFunctions SysTick Functions
+ \brief Functions that configure the System.
+ @{
+ */
+
+#if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U)
+
+/**
+ \brief System Tick Configuration
+ \details Initializes the System Timer and its interrupt, and starts the System Tick Timer.
+ Counter is in free running mode to generate periodic interrupts.
+ \param [in] ticks Number of ticks between two interrupts.
+ \return 0 Function succeeded.
+ \return 1 Function failed.
+ \note When the variable __Vendor_SysTickConfig is set to 1, then the
+ function SysTick_Config is not included. In this case, the file device.h
+ must contain a vendor-specific implementation of this function.
+ */
+__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)
+{
+ if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk)
+ {
+ return (1UL); /* Reload value impossible */
+ }
+
+ SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */
+ NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */
+ SysTick->VAL = 0UL; /* Load the SysTick Counter Value */
+ SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
+ SysTick_CTRL_TICKINT_Msk |
+ SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */
+ return (0UL); /* Function successful */
+}
+
+#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
+/**
+ \brief System Tick Configuration (non-secure)
+ \details Initializes the non-secure System Timer and its interrupt when in secure state, and starts the System Tick Timer.
+ Counter is in free running mode to generate periodic interrupts.
+ \param [in] ticks Number of ticks between two interrupts.
+ \return 0 Function succeeded.
+ \return 1 Function failed.
+ \note When the variable __Vendor_SysTickConfig is set to 1, then the
+ function TZ_SysTick_Config_NS is not included. In this case, the file device.h
+ must contain a vendor-specific implementation of this function.
+
+ */
+__STATIC_INLINE uint32_t TZ_SysTick_Config_NS(uint32_t ticks)
+{
+ if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk)
+ {
+ return (1UL); /* Reload value impossible */
+ }
+
+ SysTick_NS->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */
+ TZ_NVIC_SetPriority_NS (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */
+ SysTick_NS->VAL = 0UL; /* Load the SysTick Counter Value */
+ SysTick_NS->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
+ SysTick_CTRL_TICKINT_Msk |
+ SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */
+ return (0UL); /* Function successful */
+}
+#endif /* defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) */
+
+#endif
+
+/*@} end of CMSIS_Core_SysTickFunctions */
+
+
+
+/* ##################################### Debug In/Output function ########################################### */
+/**
+ \ingroup CMSIS_Core_FunctionInterface
+ \defgroup CMSIS_core_DebugFunctions ITM Functions
+ \brief Functions that access the ITM debug interface.
+ @{
+ */
+
+extern volatile int32_t ITM_RxBuffer; /*!< External variable to receive characters. */
+#define ITM_RXBUFFER_EMPTY ((int32_t)0x5AA55AA5U) /*!< Value identifying \ref ITM_RxBuffer is ready for next character. */
+
+
+/**
+ \brief ITM Send Character
+ \details Transmits a character via the ITM channel 0, and
+ \li Just returns when no debugger is connected that has booked the output.
+ \li Is blocking when a debugger is connected, but the previous character sent has not been transmitted.
+ \param [in] ch Character to transmit.
+ \returns Character to transmit.
+ */
+__STATIC_INLINE uint32_t ITM_SendChar (uint32_t ch)
+{
+ if (((ITM->TCR & ITM_TCR_ITMENA_Msk) != 0UL) && /* ITM enabled */
+ ((ITM->TER & 1UL ) != 0UL) ) /* ITM Port #0 enabled */
+ {
+ while (ITM->PORT[0U].u32 == 0UL)
+ {
+ __NOP();
+ }
+ ITM->PORT[0U].u8 = (uint8_t)ch;
+ }
+ return (ch);
+}
+
+
+/**
+ \brief ITM Receive Character
+ \details Inputs a character via the external variable \ref ITM_RxBuffer.
+ \return Received character.
+ \return -1 No character pending.
+ */
+__STATIC_INLINE int32_t ITM_ReceiveChar (void)
+{
+ int32_t ch = -1; /* no character available */
+
+ if (ITM_RxBuffer != ITM_RXBUFFER_EMPTY)
+ {
+ ch = ITM_RxBuffer;
+ ITM_RxBuffer = ITM_RXBUFFER_EMPTY; /* ready for next character */
+ }
+
+ return (ch);
+}
+
+
+/**
+ \brief ITM Check Character
+ \details Checks whether a character is pending for reading in the variable \ref ITM_RxBuffer.
+ \return 0 No character available.
+ \return 1 Character available.
+ */
+__STATIC_INLINE int32_t ITM_CheckChar (void)
+{
+
+ if (ITM_RxBuffer == ITM_RXBUFFER_EMPTY)
+ {
+ return (0); /* no character available */
+ }
+ else
+ {
+ return (1); /* character available */
+ }
+}
+
+/*@} end of CMSIS_core_DebugFunctions */
+
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CORE_CM35P_H_DEPENDANT */
+
+#endif /* __CMSIS_GENERIC */
diff --git a/lib/cmsis/inc/core_cm4.h b/lib/cmsis/inc/core_cm4.h
index dc840ebf22..f205b333f3 100644
--- a/lib/cmsis/inc/core_cm4.h
+++ b/lib/cmsis/inc/core_cm4.h
@@ -1,40 +1,30 @@
/**************************************************************************//**
* @file core_cm4.h
* @brief CMSIS Cortex-M4 Core Peripheral Access Layer Header File
- * @version V4.30
- * @date 20. October 2015
+ * @version V5.1.0
+ * @date 13. March 2019
******************************************************************************/
-/* Copyright (c) 2009 - 2015 ARM LIMITED
-
- All rights reserved.
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are met:
- - Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- - Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
- - Neither the name of ARM nor the names of its contributors may be used
- to endorse or promote products derived from this software without
- specific prior written permission.
- *
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE
- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- POSSIBILITY OF SUCH DAMAGE.
- ---------------------------------------------------------------------------*/
-
+/*
+ * Copyright (c) 2009-2019 Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
#if defined ( __ICCARM__ )
- #pragma system_include /* treat file as system include file for MISRA check */
-#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
+ #pragma system_include /* treat file as system include file for MISRA check */
+#elif defined (__clang__)
#pragma clang system_header /* treat file as system include file */
#endif
@@ -70,60 +60,22 @@
@{
*/
-/* CMSIS CM4 definitions */
-#define __CM4_CMSIS_VERSION_MAIN (0x04U) /*!< [31:16] CMSIS HAL main version */
-#define __CM4_CMSIS_VERSION_SUB (0x1EU) /*!< [15:0] CMSIS HAL sub version */
-#define __CM4_CMSIS_VERSION ((__CM4_CMSIS_VERSION_MAIN << 16U) | \
- __CM4_CMSIS_VERSION_SUB ) /*!< CMSIS HAL version number */
-
-#define __CORTEX_M (0x04U) /*!< Cortex-M Core */
-
-
-#if defined ( __CC_ARM )
- #define __ASM __asm /*!< asm keyword for ARM Compiler */
- #define __INLINE __inline /*!< inline keyword for ARM Compiler */
- #define __STATIC_INLINE static __inline
-
-#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
- #define __ASM __asm /*!< asm keyword for ARM Compiler */
- #define __INLINE __inline /*!< inline keyword for ARM Compiler */
- #define __STATIC_INLINE static __inline
-
-#elif defined ( __GNUC__ )
- #define __ASM __asm /*!< asm keyword for GNU Compiler */
- #define __INLINE inline /*!< inline keyword for GNU Compiler */
- #define __STATIC_INLINE static inline
+#include "cmsis_version.h"
-#elif defined ( __ICCARM__ )
- #define __ASM __asm /*!< asm keyword for IAR Compiler */
- #define __INLINE inline /*!< inline keyword for IAR Compiler. Only available in High optimization mode! */
- #define __STATIC_INLINE static inline
-
-#elif defined ( __TMS470__ )
- #define __ASM __asm /*!< asm keyword for TI CCS Compiler */
- #define __STATIC_INLINE static inline
-
-#elif defined ( __TASKING__ )
- #define __ASM __asm /*!< asm keyword for TASKING Compiler */
- #define __INLINE inline /*!< inline keyword for TASKING Compiler */
- #define __STATIC_INLINE static inline
+/* CMSIS CM4 definitions */
+#define __CM4_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */
+#define __CM4_CMSIS_VERSION_SUB (__CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */
+#define __CM4_CMSIS_VERSION ((__CM4_CMSIS_VERSION_MAIN << 16U) | \
+ __CM4_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */
-#elif defined ( __CSMC__ )
- #define __packed
- #define __ASM _asm /*!< asm keyword for COSMIC Compiler */
- #define __INLINE inline /*!< inline keyword for COSMIC Compiler. Use -pc99 on compile line */
- #define __STATIC_INLINE static inline
-
-#else
- #error Unknown compiler
-#endif
+#define __CORTEX_M (4U) /*!< Cortex-M Core */
/** __FPU_USED indicates whether an FPU is used or not.
For this, __FPU_PRESENT has to be checked prior to making use of FPU specific registers and functions.
*/
#if defined ( __CC_ARM )
#if defined __TARGET_FPU_VFP
- #if (__FPU_PRESENT == 1U)
+ #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)
#define __FPU_USED 1U
#else
#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
@@ -133,9 +85,9 @@
#define __FPU_USED 0U
#endif
-#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
- #if defined __ARM_PCS_VFP
- #if (__FPU_PRESENT == 1)
+#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
+ #if defined __ARM_FP
+ #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)
#define __FPU_USED 1U
#else
#warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
@@ -147,7 +99,7 @@
#elif defined ( __GNUC__ )
#if defined (__VFP_FP__) && !defined(__SOFTFP__)
- #if (__FPU_PRESENT == 1U)
+ #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)
#define __FPU_USED 1U
#else
#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
@@ -159,7 +111,7 @@
#elif defined ( __ICCARM__ )
#if defined __ARMVFP__
- #if (__FPU_PRESENT == 1U)
+ #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)
#define __FPU_USED 1U
#else
#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
@@ -169,9 +121,9 @@
#define __FPU_USED 0U
#endif
-#elif defined ( __TMS470__ )
+#elif defined ( __TI_ARM__ )
#if defined __TI_VFP_SUPPORT__
- #if (__FPU_PRESENT == 1U)
+ #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)
#define __FPU_USED 1U
#else
#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
@@ -183,7 +135,7 @@
#elif defined ( __TASKING__ )
#if defined __FPU_VFP__
- #if (__FPU_PRESENT == 1U)
+ #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)
#define __FPU_USED 1U
#else
#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
@@ -195,7 +147,7 @@
#elif defined ( __CSMC__ )
#if ( __CSMC__ & 0x400U)
- #if (__FPU_PRESENT == 1U)
+ #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)
#define __FPU_USED 1U
#else
#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
@@ -207,9 +159,8 @@
#endif
-#include "core_cmInstr.h" /* Core Instruction Access */
-#include "core_cmFunc.h" /* Core Function Access */
-#include "core_cmSimd.h" /* Compiler specific SIMD Intrinsics */
+#include "cmsis_compiler.h" /* CMSIS compiler specific defines */
+
#ifdef __cplusplus
}
@@ -244,7 +195,7 @@
#endif
#ifndef __NVIC_PRIO_BITS
- #define __NVIC_PRIO_BITS 4U
+ #define __NVIC_PRIO_BITS 3U
#warning "__NVIC_PRIO_BITS not defined in device header file; using default!"
#endif
@@ -367,11 +318,12 @@ typedef union
struct
{
uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */
- uint32_t _reserved0:7; /*!< bit: 9..15 Reserved */
+ uint32_t _reserved0:1; /*!< bit: 9 Reserved */
+ uint32_t ICI_IT_1:6; /*!< bit: 10..15 ICI/IT part 1 */
uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */
uint32_t _reserved1:4; /*!< bit: 20..23 Reserved */
- uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */
- uint32_t IT:2; /*!< bit: 25..26 saved IT state (read 0) */
+ uint32_t T:1; /*!< bit: 24 Thumb bit */
+ uint32_t ICI_IT_2:2; /*!< bit: 25..26 ICI/IT part 2 */
uint32_t Q:1; /*!< bit: 27 Saturation condition flag */
uint32_t V:1; /*!< bit: 28 Overflow condition code flag */
uint32_t C:1; /*!< bit: 29 Carry condition code flag */
@@ -397,8 +349,8 @@ typedef union
#define xPSR_Q_Pos 27U /*!< xPSR: Q Position */
#define xPSR_Q_Msk (1UL << xPSR_Q_Pos) /*!< xPSR: Q Mask */
-#define xPSR_IT_Pos 25U /*!< xPSR: IT Position */
-#define xPSR_IT_Msk (3UL << xPSR_IT_Pos) /*!< xPSR: IT Mask */
+#define xPSR_ICI_IT_2_Pos 25U /*!< xPSR: ICI/IT part 2 Position */
+#define xPSR_ICI_IT_2_Msk (3UL << xPSR_ICI_IT_2_Pos) /*!< xPSR: ICI/IT part 2 Mask */
#define xPSR_T_Pos 24U /*!< xPSR: T Position */
#define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */
@@ -406,6 +358,9 @@ typedef union
#define xPSR_GE_Pos 16U /*!< xPSR: GE Position */
#define xPSR_GE_Msk (0xFUL << xPSR_GE_Pos) /*!< xPSR: GE Mask */
+#define xPSR_ICI_IT_1_Pos 10U /*!< xPSR: ICI/IT part 1 Position */
+#define xPSR_ICI_IT_1_Msk (0x3FUL << xPSR_ICI_IT_1_Pos) /*!< xPSR: ICI/IT part 1 Mask */
+
#define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */
#define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */
@@ -453,7 +408,7 @@ typedef struct
__IOM uint32_t ISER[8U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */
uint32_t RESERVED0[24U];
__IOM uint32_t ICER[8U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */
- uint32_t RSERVED1[24U];
+ uint32_t RESERVED1[24U];
__IOM uint32_t ISPR[8U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */
uint32_t RESERVED2[24U];
__IOM uint32_t ICPR[8U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */
@@ -662,6 +617,66 @@ typedef struct
#define SCB_CFSR_MEMFAULTSR_Pos 0U /*!< SCB CFSR: Memory Manage Fault Status Register Position */
#define SCB_CFSR_MEMFAULTSR_Msk (0xFFUL /*<< SCB_CFSR_MEMFAULTSR_Pos*/) /*!< SCB CFSR: Memory Manage Fault Status Register Mask */
+/* MemManage Fault Status Register (part of SCB Configurable Fault Status Register) */
+#define SCB_CFSR_MMARVALID_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 7U) /*!< SCB CFSR (MMFSR): MMARVALID Position */
+#define SCB_CFSR_MMARVALID_Msk (1UL << SCB_CFSR_MMARVALID_Pos) /*!< SCB CFSR (MMFSR): MMARVALID Mask */
+
+#define SCB_CFSR_MLSPERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 5U) /*!< SCB CFSR (MMFSR): MLSPERR Position */
+#define SCB_CFSR_MLSPERR_Msk (1UL << SCB_CFSR_MLSPERR_Pos) /*!< SCB CFSR (MMFSR): MLSPERR Mask */
+
+#define SCB_CFSR_MSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 4U) /*!< SCB CFSR (MMFSR): MSTKERR Position */
+#define SCB_CFSR_MSTKERR_Msk (1UL << SCB_CFSR_MSTKERR_Pos) /*!< SCB CFSR (MMFSR): MSTKERR Mask */
+
+#define SCB_CFSR_MUNSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 3U) /*!< SCB CFSR (MMFSR): MUNSTKERR Position */
+#define SCB_CFSR_MUNSTKERR_Msk (1UL << SCB_CFSR_MUNSTKERR_Pos) /*!< SCB CFSR (MMFSR): MUNSTKERR Mask */
+
+#define SCB_CFSR_DACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 1U) /*!< SCB CFSR (MMFSR): DACCVIOL Position */
+#define SCB_CFSR_DACCVIOL_Msk (1UL << SCB_CFSR_DACCVIOL_Pos) /*!< SCB CFSR (MMFSR): DACCVIOL Mask */
+
+#define SCB_CFSR_IACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 0U) /*!< SCB CFSR (MMFSR): IACCVIOL Position */
+#define SCB_CFSR_IACCVIOL_Msk (1UL /*<< SCB_CFSR_IACCVIOL_Pos*/) /*!< SCB CFSR (MMFSR): IACCVIOL Mask */
+
+/* BusFault Status Register (part of SCB Configurable Fault Status Register) */
+#define SCB_CFSR_BFARVALID_Pos (SCB_CFSR_BUSFAULTSR_Pos + 7U) /*!< SCB CFSR (BFSR): BFARVALID Position */
+#define SCB_CFSR_BFARVALID_Msk (1UL << SCB_CFSR_BFARVALID_Pos) /*!< SCB CFSR (BFSR): BFARVALID Mask */
+
+#define SCB_CFSR_LSPERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 5U) /*!< SCB CFSR (BFSR): LSPERR Position */
+#define SCB_CFSR_LSPERR_Msk (1UL << SCB_CFSR_LSPERR_Pos) /*!< SCB CFSR (BFSR): LSPERR Mask */
+
+#define SCB_CFSR_STKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 4U) /*!< SCB CFSR (BFSR): STKERR Position */
+#define SCB_CFSR_STKERR_Msk (1UL << SCB_CFSR_STKERR_Pos) /*!< SCB CFSR (BFSR): STKERR Mask */
+
+#define SCB_CFSR_UNSTKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 3U) /*!< SCB CFSR (BFSR): UNSTKERR Position */
+#define SCB_CFSR_UNSTKERR_Msk (1UL << SCB_CFSR_UNSTKERR_Pos) /*!< SCB CFSR (BFSR): UNSTKERR Mask */
+
+#define SCB_CFSR_IMPRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 2U) /*!< SCB CFSR (BFSR): IMPRECISERR Position */
+#define SCB_CFSR_IMPRECISERR_Msk (1UL << SCB_CFSR_IMPRECISERR_Pos) /*!< SCB CFSR (BFSR): IMPRECISERR Mask */
+
+#define SCB_CFSR_PRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 1U) /*!< SCB CFSR (BFSR): PRECISERR Position */
+#define SCB_CFSR_PRECISERR_Msk (1UL << SCB_CFSR_PRECISERR_Pos) /*!< SCB CFSR (BFSR): PRECISERR Mask */
+
+#define SCB_CFSR_IBUSERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 0U) /*!< SCB CFSR (BFSR): IBUSERR Position */
+#define SCB_CFSR_IBUSERR_Msk (1UL << SCB_CFSR_IBUSERR_Pos) /*!< SCB CFSR (BFSR): IBUSERR Mask */
+
+/* UsageFault Status Register (part of SCB Configurable Fault Status Register) */
+#define SCB_CFSR_DIVBYZERO_Pos (SCB_CFSR_USGFAULTSR_Pos + 9U) /*!< SCB CFSR (UFSR): DIVBYZERO Position */
+#define SCB_CFSR_DIVBYZERO_Msk (1UL << SCB_CFSR_DIVBYZERO_Pos) /*!< SCB CFSR (UFSR): DIVBYZERO Mask */
+
+#define SCB_CFSR_UNALIGNED_Pos (SCB_CFSR_USGFAULTSR_Pos + 8U) /*!< SCB CFSR (UFSR): UNALIGNED Position */
+#define SCB_CFSR_UNALIGNED_Msk (1UL << SCB_CFSR_UNALIGNED_Pos) /*!< SCB CFSR (UFSR): UNALIGNED Mask */
+
+#define SCB_CFSR_NOCP_Pos (SCB_CFSR_USGFAULTSR_Pos + 3U) /*!< SCB CFSR (UFSR): NOCP Position */
+#define SCB_CFSR_NOCP_Msk (1UL << SCB_CFSR_NOCP_Pos) /*!< SCB CFSR (UFSR): NOCP Mask */
+
+#define SCB_CFSR_INVPC_Pos (SCB_CFSR_USGFAULTSR_Pos + 2U) /*!< SCB CFSR (UFSR): INVPC Position */
+#define SCB_CFSR_INVPC_Msk (1UL << SCB_CFSR_INVPC_Pos) /*!< SCB CFSR (UFSR): INVPC Mask */
+
+#define SCB_CFSR_INVSTATE_Pos (SCB_CFSR_USGFAULTSR_Pos + 1U) /*!< SCB CFSR (UFSR): INVSTATE Position */
+#define SCB_CFSR_INVSTATE_Msk (1UL << SCB_CFSR_INVSTATE_Pos) /*!< SCB CFSR (UFSR): INVSTATE Mask */
+
+#define SCB_CFSR_UNDEFINSTR_Pos (SCB_CFSR_USGFAULTSR_Pos + 0U) /*!< SCB CFSR (UFSR): UNDEFINSTR Position */
+#define SCB_CFSR_UNDEFINSTR_Msk (1UL << SCB_CFSR_UNDEFINSTR_Pos) /*!< SCB CFSR (UFSR): UNDEFINSTR Mask */
+
/* SCB Hard Fault Status Register Definitions */
#define SCB_HFSR_DEBUGEVT_Pos 31U /*!< SCB HFSR: DEBUGEVT Position */
#define SCB_HFSR_DEBUGEVT_Msk (1UL << SCB_HFSR_DEBUGEVT_Pos) /*!< SCB HFSR: DEBUGEVT Mask */
@@ -807,10 +822,7 @@ typedef struct
__IOM uint32_t TPR; /*!< Offset: 0xE40 (R/W) ITM Trace Privilege Register */
uint32_t RESERVED2[15U];
__IOM uint32_t TCR; /*!< Offset: 0xE80 (R/W) ITM Trace Control Register */
- uint32_t RESERVED3[29U];
- __OM uint32_t IWR; /*!< Offset: 0xEF8 ( /W) ITM Integration Write Register */
- __IM uint32_t IRR; /*!< Offset: 0xEFC (R/ ) ITM Integration Read Register */
- __IOM uint32_t IMCR; /*!< Offset: 0xF00 (R/W) ITM Integration Mode Control Register */
+ uint32_t RESERVED3[32U];
uint32_t RESERVED4[43U];
__OM uint32_t LAR; /*!< Offset: 0xFB0 ( /W) ITM Lock Access Register */
__IM uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) ITM Lock Status Register */
@@ -831,7 +843,7 @@ typedef struct
/* ITM Trace Privilege Register Definitions */
#define ITM_TPR_PRIVMASK_Pos 0U /*!< ITM TPR: PRIVMASK Position */
-#define ITM_TPR_PRIVMASK_Msk (0xFUL /*<< ITM_TPR_PRIVMASK_Pos*/) /*!< ITM TPR: PRIVMASK Mask */
+#define ITM_TPR_PRIVMASK_Msk (0xFFFFFFFFUL /*<< ITM_TPR_PRIVMASK_Pos*/) /*!< ITM TPR: PRIVMASK Mask */
/* ITM Trace Control Register Definitions */
#define ITM_TCR_BUSY_Pos 23U /*!< ITM TCR: BUSY Position */
@@ -861,18 +873,6 @@ typedef struct
#define ITM_TCR_ITMENA_Pos 0U /*!< ITM TCR: ITM Enable bit Position */
#define ITM_TCR_ITMENA_Msk (1UL /*<< ITM_TCR_ITMENA_Pos*/) /*!< ITM TCR: ITM Enable bit Mask */
-/* ITM Integration Write Register Definitions */
-#define ITM_IWR_ATVALIDM_Pos 0U /*!< ITM IWR: ATVALIDM Position */
-#define ITM_IWR_ATVALIDM_Msk (1UL /*<< ITM_IWR_ATVALIDM_Pos*/) /*!< ITM IWR: ATVALIDM Mask */
-
-/* ITM Integration Read Register Definitions */
-#define ITM_IRR_ATREADYM_Pos 0U /*!< ITM IRR: ATREADYM Position */
-#define ITM_IRR_ATREADYM_Msk (1UL /*<< ITM_IRR_ATREADYM_Pos*/) /*!< ITM IRR: ATREADYM Mask */
-
-/* ITM Integration Mode Control Register Definitions */
-#define ITM_IMCR_INTEGRATION_Pos 0U /*!< ITM IMCR: INTEGRATION Position */
-#define ITM_IMCR_INTEGRATION_Msk (1UL /*<< ITM_IMCR_INTEGRATION_Pos*/) /*!< ITM IMCR: INTEGRATION Mask */
-
/* ITM Lock Status Register Definitions */
#define ITM_LSR_ByteAcc_Pos 2U /*!< ITM LSR: ByteAcc Position */
#define ITM_LSR_ByteAcc_Msk (1UL << ITM_LSR_ByteAcc_Pos) /*!< ITM LSR: ByteAcc Mask */
@@ -1045,7 +1045,7 @@ typedef struct
*/
typedef struct
{
- __IOM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Size Register */
+ __IM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Size Register */
__IOM uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Size Register */
uint32_t RESERVED0[2U];
__IOM uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */
@@ -1056,7 +1056,7 @@ typedef struct
__IOM uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */
__IM uint32_t FSCR; /*!< Offset: 0x308 (R/ ) Formatter Synchronization Counter Register */
uint32_t RESERVED3[759U];
- __IM uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER */
+ __IM uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER Register */
__IM uint32_t FIFO0; /*!< Offset: 0xEEC (R/ ) Integration ETM Data */
__IM uint32_t ITATBCTR2; /*!< Offset: 0xEF0 (R/ ) ITATBCTR2 */
uint32_t RESERVED4[1U];
@@ -1105,13 +1105,13 @@ typedef struct
/* TPI Integration ETM Data Register Definitions (FIFO0) */
#define TPI_FIFO0_ITM_ATVALID_Pos 29U /*!< TPI FIFO0: ITM_ATVALID Position */
-#define TPI_FIFO0_ITM_ATVALID_Msk (0x3UL << TPI_FIFO0_ITM_ATVALID_Pos) /*!< TPI FIFO0: ITM_ATVALID Mask */
+#define TPI_FIFO0_ITM_ATVALID_Msk (0x1UL << TPI_FIFO0_ITM_ATVALID_Pos) /*!< TPI FIFO0: ITM_ATVALID Mask */
#define TPI_FIFO0_ITM_bytecount_Pos 27U /*!< TPI FIFO0: ITM_bytecount Position */
#define TPI_FIFO0_ITM_bytecount_Msk (0x3UL << TPI_FIFO0_ITM_bytecount_Pos) /*!< TPI FIFO0: ITM_bytecount Mask */
#define TPI_FIFO0_ETM_ATVALID_Pos 26U /*!< TPI FIFO0: ETM_ATVALID Position */
-#define TPI_FIFO0_ETM_ATVALID_Msk (0x3UL << TPI_FIFO0_ETM_ATVALID_Pos) /*!< TPI FIFO0: ETM_ATVALID Mask */
+#define TPI_FIFO0_ETM_ATVALID_Msk (0x1UL << TPI_FIFO0_ETM_ATVALID_Pos) /*!< TPI FIFO0: ETM_ATVALID Mask */
#define TPI_FIFO0_ETM_bytecount_Pos 24U /*!< TPI FIFO0: ETM_bytecount Position */
#define TPI_FIFO0_ETM_bytecount_Msk (0x3UL << TPI_FIFO0_ETM_bytecount_Pos) /*!< TPI FIFO0: ETM_bytecount Mask */
@@ -1126,18 +1126,21 @@ typedef struct
#define TPI_FIFO0_ETM0_Msk (0xFFUL /*<< TPI_FIFO0_ETM0_Pos*/) /*!< TPI FIFO0: ETM0 Mask */
/* TPI ITATBCTR2 Register Definitions */
-#define TPI_ITATBCTR2_ATREADY_Pos 0U /*!< TPI ITATBCTR2: ATREADY Position */
-#define TPI_ITATBCTR2_ATREADY_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY_Pos*/) /*!< TPI ITATBCTR2: ATREADY Mask */
+#define TPI_ITATBCTR2_ATREADY2_Pos 0U /*!< TPI ITATBCTR2: ATREADY2 Position */
+#define TPI_ITATBCTR2_ATREADY2_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY2_Pos*/) /*!< TPI ITATBCTR2: ATREADY2 Mask */
+
+#define TPI_ITATBCTR2_ATREADY1_Pos 0U /*!< TPI ITATBCTR2: ATREADY1 Position */
+#define TPI_ITATBCTR2_ATREADY1_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY1_Pos*/) /*!< TPI ITATBCTR2: ATREADY1 Mask */
/* TPI Integration ITM Data Register Definitions (FIFO1) */
#define TPI_FIFO1_ITM_ATVALID_Pos 29U /*!< TPI FIFO1: ITM_ATVALID Position */
-#define TPI_FIFO1_ITM_ATVALID_Msk (0x3UL << TPI_FIFO1_ITM_ATVALID_Pos) /*!< TPI FIFO1: ITM_ATVALID Mask */
+#define TPI_FIFO1_ITM_ATVALID_Msk (0x1UL << TPI_FIFO1_ITM_ATVALID_Pos) /*!< TPI FIFO1: ITM_ATVALID Mask */
#define TPI_FIFO1_ITM_bytecount_Pos 27U /*!< TPI FIFO1: ITM_bytecount Position */
#define TPI_FIFO1_ITM_bytecount_Msk (0x3UL << TPI_FIFO1_ITM_bytecount_Pos) /*!< TPI FIFO1: ITM_bytecount Mask */
#define TPI_FIFO1_ETM_ATVALID_Pos 26U /*!< TPI FIFO1: ETM_ATVALID Position */
-#define TPI_FIFO1_ETM_ATVALID_Msk (0x3UL << TPI_FIFO1_ETM_ATVALID_Pos) /*!< TPI FIFO1: ETM_ATVALID Mask */
+#define TPI_FIFO1_ETM_ATVALID_Msk (0x1UL << TPI_FIFO1_ETM_ATVALID_Pos) /*!< TPI FIFO1: ETM_ATVALID Mask */
#define TPI_FIFO1_ETM_bytecount_Pos 24U /*!< TPI FIFO1: ETM_bytecount Position */
#define TPI_FIFO1_ETM_bytecount_Msk (0x3UL << TPI_FIFO1_ETM_bytecount_Pos) /*!< TPI FIFO1: ETM_bytecount Mask */
@@ -1152,12 +1155,15 @@ typedef struct
#define TPI_FIFO1_ITM0_Msk (0xFFUL /*<< TPI_FIFO1_ITM0_Pos*/) /*!< TPI FIFO1: ITM0 Mask */
/* TPI ITATBCTR0 Register Definitions */
-#define TPI_ITATBCTR0_ATREADY_Pos 0U /*!< TPI ITATBCTR0: ATREADY Position */
-#define TPI_ITATBCTR0_ATREADY_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY_Pos*/) /*!< TPI ITATBCTR0: ATREADY Mask */
+#define TPI_ITATBCTR0_ATREADY2_Pos 0U /*!< TPI ITATBCTR0: ATREADY2 Position */
+#define TPI_ITATBCTR0_ATREADY2_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY2_Pos*/) /*!< TPI ITATBCTR0: ATREADY2 Mask */
+
+#define TPI_ITATBCTR0_ATREADY1_Pos 0U /*!< TPI ITATBCTR0: ATREADY1 Position */
+#define TPI_ITATBCTR0_ATREADY1_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY1_Pos*/) /*!< TPI ITATBCTR0: ATREADY1 Mask */
/* TPI Integration Mode Control Register Definitions */
#define TPI_ITCTRL_Mode_Pos 0U /*!< TPI ITCTRL: Mode Position */
-#define TPI_ITCTRL_Mode_Msk (0x1UL /*<< TPI_ITCTRL_Mode_Pos*/) /*!< TPI ITCTRL: Mode Mask */
+#define TPI_ITCTRL_Mode_Msk (0x3UL /*<< TPI_ITCTRL_Mode_Pos*/) /*!< TPI ITCTRL: Mode Mask */
/* TPI DEVID Register Definitions */
#define TPI_DEVID_NRZVALID_Pos 11U /*!< TPI DEVID: NRZVALID Position */
@@ -1179,16 +1185,16 @@ typedef struct
#define TPI_DEVID_NrTraceInput_Msk (0x1FUL /*<< TPI_DEVID_NrTraceInput_Pos*/) /*!< TPI DEVID: NrTraceInput Mask */
/* TPI DEVTYPE Register Definitions */
-#define TPI_DEVTYPE_MajorType_Pos 4U /*!< TPI DEVTYPE: MajorType Position */
-#define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */
-
-#define TPI_DEVTYPE_SubType_Pos 0U /*!< TPI DEVTYPE: SubType Position */
+#define TPI_DEVTYPE_SubType_Pos 4U /*!< TPI DEVTYPE: SubType Position */
#define TPI_DEVTYPE_SubType_Msk (0xFUL /*<< TPI_DEVTYPE_SubType_Pos*/) /*!< TPI DEVTYPE: SubType Mask */
+#define TPI_DEVTYPE_MajorType_Pos 0U /*!< TPI DEVTYPE: MajorType Position */
+#define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */
+
/*@}*/ /* end of group CMSIS_TPI */
-#if (__MPU_PRESENT == 1U)
+#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U)
/**
\ingroup CMSIS_core_register
\defgroup CMSIS_MPU Memory Protection Unit (MPU)
@@ -1214,6 +1220,8 @@ typedef struct
__IOM uint32_t RASR_A3; /*!< Offset: 0x028 (R/W) MPU Alias 3 Region Attribute and Size Register */
} MPU_Type;
+#define MPU_TYPE_RALIASES 4U
+
/* MPU Type Register Definitions */
#define MPU_TYPE_IREGION_Pos 16U /*!< MPU TYPE: IREGION Position */
#define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */
@@ -1280,10 +1288,9 @@ typedef struct
#define MPU_RASR_ENABLE_Msk (1UL /*<< MPU_RASR_ENABLE_Pos*/) /*!< MPU RASR: Region enable bit Disable Mask */
/*@} end of group CMSIS_MPU */
-#endif
+#endif /* defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) */
-#if (__FPU_PRESENT == 1U)
/**
\ingroup CMSIS_core_register
\defgroup CMSIS_FPU Floating Point Unit (FPU)
@@ -1302,6 +1309,7 @@ typedef struct
__IOM uint32_t FPDSCR; /*!< Offset: 0x00C (R/W) Floating-Point Default Status Control Register */
__IM uint32_t MVFR0; /*!< Offset: 0x010 (R/ ) Media and FP Feature Register 0 */
__IM uint32_t MVFR1; /*!< Offset: 0x014 (R/ ) Media and FP Feature Register 1 */
+ __IM uint32_t MVFR2; /*!< Offset: 0x018 (R/ ) Media and FP Feature Register 2 */
} FPU_Type;
/* Floating-Point Context Control Register Definitions */
@@ -1387,8 +1395,12 @@ typedef struct
#define FPU_MVFR1_FtZ_mode_Pos 0U /*!< MVFR1: FtZ mode bits Position */
#define FPU_MVFR1_FtZ_mode_Msk (0xFUL /*<< FPU_MVFR1_FtZ_mode_Pos*/) /*!< MVFR1: FtZ mode bits Mask */
+/* Media and FP Feature Register 2 Definitions */
+
+#define FPU_MVFR2_VFP_Misc_Pos 4U /*!< MVFR2: VFP Misc bits Position */
+#define FPU_MVFR2_VFP_Misc_Msk (0xFUL << FPU_MVFR2_VFP_Misc_Pos) /*!< MVFR2: VFP Misc bits Mask */
+
/*@} end of group CMSIS_FPU */
-#endif
/**
@@ -1506,18 +1518,18 @@ typedef struct
/**
\brief Mask and shift a bit field value for use in a register bit range.
\param[in] field Name of the register bit field.
- \param[in] value Value of the bit field.
+ \param[in] value Value of the bit field. This parameter is interpreted as an uint32_t type.
\return Masked and shifted value.
*/
-#define _VAL2FLD(field, value) ((value << field ## _Pos) & field ## _Msk)
+#define _VAL2FLD(field, value) (((uint32_t)(value) << field ## _Pos) & field ## _Msk)
/**
\brief Mask and shift a register value to extract a bit filed value.
\param[in] field Name of the register bit field.
- \param[in] value Value of register.
+ \param[in] value Value of register. This parameter is interpreted as an uint32_t type.
\return Masked and shifted bit field value.
*/
-#define _FLD2VAL(field, value) ((value & field ## _Msk) >> field ## _Pos)
+#define _FLD2VAL(field, value) (((uint32_t)(value) & field ## _Msk) >> field ## _Pos)
/*@} end of group CMSIS_core_bitfield */
@@ -1529,7 +1541,7 @@ typedef struct
@{
*/
-/* Memory mapping of Cortex-M4 Hardware */
+/* Memory mapping of Core Hardware */
#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */
#define ITM_BASE (0xE0000000UL) /*!< ITM Base Address */
#define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */
@@ -1548,15 +1560,13 @@ typedef struct
#define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */
#define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE) /*!< Core Debug configuration struct */
-#if (__MPU_PRESENT == 1U)
+#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U)
#define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */
#define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */
#endif
-#if (__FPU_PRESENT == 1U)
- #define FPU_BASE (SCS_BASE + 0x0F30UL) /*!< Floating Point Unit */
- #define FPU ((FPU_Type *) FPU_BASE ) /*!< Floating Point Unit */
-#endif
+#define FPU_BASE (SCS_BASE + 0x0F30UL) /*!< Floating Point Unit */
+#define FPU ((FPU_Type *) FPU_BASE ) /*!< Floating Point Unit */
/*@} */
@@ -1584,6 +1594,48 @@ typedef struct
@{
*/
+#ifdef CMSIS_NVIC_VIRTUAL
+ #ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE
+ #define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h"
+ #endif
+ #include CMSIS_NVIC_VIRTUAL_HEADER_FILE
+#else
+ #define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping
+ #define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping
+ #define NVIC_EnableIRQ __NVIC_EnableIRQ
+ #define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ
+ #define NVIC_DisableIRQ __NVIC_DisableIRQ
+ #define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ
+ #define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ
+ #define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ
+ #define NVIC_GetActive __NVIC_GetActive
+ #define NVIC_SetPriority __NVIC_SetPriority
+ #define NVIC_GetPriority __NVIC_GetPriority
+ #define NVIC_SystemReset __NVIC_SystemReset
+#endif /* CMSIS_NVIC_VIRTUAL */
+
+#ifdef CMSIS_VECTAB_VIRTUAL
+ #ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE
+ #define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h"
+ #endif
+ #include CMSIS_VECTAB_VIRTUAL_HEADER_FILE
+#else
+ #define NVIC_SetVector __NVIC_SetVector
+ #define NVIC_GetVector __NVIC_GetVector
+#endif /* (CMSIS_VECTAB_VIRTUAL) */
+
+#define NVIC_USER_IRQ_OFFSET 16
+
+
+/* The following EXC_RETURN values are saved the LR on exception entry */
+#define EXC_RETURN_HANDLER (0xFFFFFFF1UL) /* return to Handler mode, uses MSP after return */
+#define EXC_RETURN_THREAD_MSP (0xFFFFFFF9UL) /* return to Thread mode, uses MSP after return */
+#define EXC_RETURN_THREAD_PSP (0xFFFFFFFDUL) /* return to Thread mode, uses PSP after return */
+#define EXC_RETURN_HANDLER_FPU (0xFFFFFFE1UL) /* return to Handler mode, uses MSP after return, restore floating-point state */
+#define EXC_RETURN_THREAD_MSP_FPU (0xFFFFFFE9UL) /* return to Thread mode, uses MSP after return, restore floating-point state */
+#define EXC_RETURN_THREAD_PSP_FPU (0xFFFFFFEDUL) /* return to Thread mode, uses PSP after return, restore floating-point state */
+
+
/**
\brief Set Priority Grouping
\details Sets the priority grouping field using the required unlock sequence.
@@ -1593,7 +1645,7 @@ typedef struct
priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set.
\param [in] PriorityGroup Priority grouping field.
*/
-__STATIC_INLINE void NVIC_SetPriorityGrouping(uint32_t PriorityGroup)
+__STATIC_INLINE void __NVIC_SetPriorityGrouping(uint32_t PriorityGroup)
{
uint32_t reg_value;
uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */
@@ -1602,7 +1654,7 @@ __STATIC_INLINE void NVIC_SetPriorityGrouping(uint32_t PriorityGroup)
reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */
reg_value = (reg_value |
((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) |
- (PriorityGroupTmp << 8U) ); /* Insert write key and priorty group */
+ (PriorityGroupTmp << SCB_AIRCR_PRIGROUP_Pos) ); /* Insert write key and priority group */
SCB->AIRCR = reg_value;
}
@@ -1612,121 +1664,178 @@ __STATIC_INLINE void NVIC_SetPriorityGrouping(uint32_t PriorityGroup)
\details Reads the priority grouping field from the NVIC Interrupt Controller.
\return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field).
*/
-__STATIC_INLINE uint32_t NVIC_GetPriorityGrouping(void)
+__STATIC_INLINE uint32_t __NVIC_GetPriorityGrouping(void)
{
return ((uint32_t)((SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos));
}
/**
- \brief Enable External Interrupt
- \details Enables a device-specific interrupt in the NVIC interrupt controller.
- \param [in] IRQn External interrupt number. Value cannot be negative.
+ \brief Enable Interrupt
+ \details Enables a device specific interrupt in the NVIC interrupt controller.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
*/
-__STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn)
+__STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn)
{
- NVIC->ISER[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL));
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
}
/**
- \brief Disable External Interrupt
- \details Disables a device-specific interrupt in the NVIC interrupt controller.
- \param [in] IRQn External interrupt number. Value cannot be negative.
+ \brief Get Interrupt Enable status
+ \details Returns a device specific interrupt enable status from the NVIC interrupt controller.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 Interrupt is not enabled.
+ \return 1 Interrupt is enabled.
+ \note IRQn must not be negative.
*/
-__STATIC_INLINE void NVIC_DisableIRQ(IRQn_Type IRQn)
+__STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn)
{
- NVIC->ICER[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL));
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Disable Interrupt
+ \details Disables a device specific interrupt in the NVIC interrupt controller.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ICER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ __DSB();
+ __ISB();
+ }
}
/**
\brief Get Pending Interrupt
- \details Reads the pending register in the NVIC and returns the pending bit for the specified interrupt.
- \param [in] IRQn Interrupt number.
+ \details Reads the NVIC pending register and returns the pending bit for the specified device specific interrupt.
+ \param [in] IRQn Device specific interrupt number.
\return 0 Interrupt status is not pending.
\return 1 Interrupt status is pending.
+ \note IRQn must not be negative.
*/
-__STATIC_INLINE uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn)
+__STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn)
{
- return((uint32_t)(((NVIC->ISPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
}
/**
\brief Set Pending Interrupt
- \details Sets the pending bit of an external interrupt.
- \param [in] IRQn Interrupt number. Value cannot be negative.
+ \details Sets the pending bit of a device specific interrupt in the NVIC pending register.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
*/
-__STATIC_INLINE void NVIC_SetPendingIRQ(IRQn_Type IRQn)
+__STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn)
{
- NVIC->ISPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL));
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
}
/**
\brief Clear Pending Interrupt
- \details Clears the pending bit of an external interrupt.
- \param [in] IRQn External interrupt number. Value cannot be negative.
+ \details Clears the pending bit of a device specific interrupt in the NVIC pending register.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
*/
-__STATIC_INLINE void NVIC_ClearPendingIRQ(IRQn_Type IRQn)
+__STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn)
{
- NVIC->ICPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL));
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
}
/**
\brief Get Active Interrupt
- \details Reads the active register in NVIC and returns the active bit.
- \param [in] IRQn Interrupt number.
+ \details Reads the active register in the NVIC and returns the active bit for the device specific interrupt.
+ \param [in] IRQn Device specific interrupt number.
\return 0 Interrupt status is not active.
\return 1 Interrupt status is active.
+ \note IRQn must not be negative.
*/
-__STATIC_INLINE uint32_t NVIC_GetActive(IRQn_Type IRQn)
+__STATIC_INLINE uint32_t __NVIC_GetActive(IRQn_Type IRQn)
{
- return((uint32_t)(((NVIC->IABR[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC->IABR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
}
/**
\brief Set Interrupt Priority
- \details Sets the priority of an interrupt.
- \note The priority cannot be set for every core interrupt.
+ \details Sets the priority of a device specific interrupt or a processor exception.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
\param [in] IRQn Interrupt number.
\param [in] priority Priority to set.
+ \note The priority cannot be set for every processor exception.
*/
-__STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
+__STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
{
- if ((int32_t)(IRQn) < 0)
+ if ((int32_t)(IRQn) >= 0)
{
- SCB->SHP[(((uint32_t)(int32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL);
+ NVIC->IP[((uint32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL);
}
else
{
- NVIC->IP[((uint32_t)(int32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL);
+ SCB->SHP[(((uint32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL);
}
}
/**
\brief Get Interrupt Priority
- \details Reads the priority of an interrupt.
- The interrupt number can be positive to specify an external (device specific) interrupt,
- or negative to specify an internal (core) interrupt.
+ \details Reads the priority of a device specific interrupt or a processor exception.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
\param [in] IRQn Interrupt number.
\return Interrupt Priority.
Value is aligned automatically to the implemented priority bits of the microcontroller.
*/
-__STATIC_INLINE uint32_t NVIC_GetPriority(IRQn_Type IRQn)
+__STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn)
{
- if ((int32_t)(IRQn) < 0)
+ if ((int32_t)(IRQn) >= 0)
{
- return(((uint32_t)SCB->SHP[(((uint32_t)(int32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS)));
+ return(((uint32_t)NVIC->IP[((uint32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS)));
}
else
{
- return(((uint32_t)NVIC->IP[((uint32_t)(int32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS)));
+ return(((uint32_t)SCB->SHP[(((uint32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS)));
}
}
@@ -1783,11 +1892,42 @@ __STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGr
}
+/**
+ \brief Set Interrupt Vector
+ \details Sets an interrupt vector in SRAM based interrupt vector table.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ VTOR must been relocated to SRAM before.
+ \param [in] IRQn Interrupt number
+ \param [in] vector Address of interrupt handler function
+ */
+__STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector)
+{
+ uint32_t vectors = (uint32_t )SCB->VTOR;
+ (* (int *) (vectors + ((int32_t)IRQn + NVIC_USER_IRQ_OFFSET) * 4)) = vector;
+}
+
+
+/**
+ \brief Get Interrupt Vector
+ \details Reads an interrupt vector from interrupt vector table.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ \param [in] IRQn Interrupt number.
+ \return Address of interrupt handler function
+ */
+__STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn)
+{
+ uint32_t vectors = (uint32_t )SCB->VTOR;
+ return (uint32_t)(* (int *) (vectors + ((int32_t)IRQn + NVIC_USER_IRQ_OFFSET) * 4));
+}
+
+
/**
\brief System Reset
\details Initiates a system reset request to reset the MCU.
*/
-__STATIC_INLINE void NVIC_SystemReset(void)
+__NO_RETURN __STATIC_INLINE void __NVIC_SystemReset(void)
{
__DSB(); /* Ensure all outstanding memory accesses included
buffered write are completed before reset */
@@ -1805,6 +1945,50 @@ __STATIC_INLINE void NVIC_SystemReset(void)
/*@} end of CMSIS_Core_NVICFunctions */
+/* ########################## MPU functions #################################### */
+
+#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U)
+
+#include "mpu_armv7.h"
+
+#endif
+
+
+/* ########################## FPU functions #################################### */
+/**
+ \ingroup CMSIS_Core_FunctionInterface
+ \defgroup CMSIS_Core_FpuFunctions FPU Functions
+ \brief Function that provides FPU type.
+ @{
+ */
+
+/**
+ \brief get FPU type
+ \details returns the FPU type
+ \returns
+ - \b 0: No FPU
+ - \b 1: Single precision FPU
+ - \b 2: Double + Single precision FPU
+ */
+__STATIC_INLINE uint32_t SCB_GetFPUType(void)
+{
+ uint32_t mvfr0;
+
+ mvfr0 = FPU->MVFR0;
+ if ((mvfr0 & (FPU_MVFR0_Single_precision_Msk | FPU_MVFR0_Double_precision_Msk)) == 0x020U)
+ {
+ return 1U; /* Single precision FPU */
+ }
+ else
+ {
+ return 0U; /* No FPU */
+ }
+}
+
+
+/*@} end of CMSIS_Core_FpuFunctions */
+
+
/* ################################## SysTick function ############################################ */
/**
@@ -1814,7 +1998,7 @@ __STATIC_INLINE void NVIC_SystemReset(void)
@{
*/
-#if (__Vendor_SysTickConfig == 0U)
+#if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U)
/**
\brief System Tick Configuration
@@ -1857,8 +2041,8 @@ __STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)
@{
*/
-extern volatile int32_t ITM_RxBuffer; /*!< External variable to receive characters. */
-#define ITM_RXBUFFER_EMPTY 0x5AA55AA5U /*!< Value identifying \ref ITM_RxBuffer is ready for next character. */
+extern volatile int32_t ITM_RxBuffer; /*!< External variable to receive characters. */
+#define ITM_RXBUFFER_EMPTY ((int32_t)0x5AA55AA5U) /*!< Value identifying \ref ITM_RxBuffer is ready for next character. */
/**
diff --git a/lib/cmsis/inc/core_cm7.h b/lib/cmsis/inc/core_cm7.h
index 3b7530ad50..41f9afb64d 100644
--- a/lib/cmsis/inc/core_cm7.h
+++ b/lib/cmsis/inc/core_cm7.h
@@ -1,40 +1,30 @@
/**************************************************************************//**
* @file core_cm7.h
* @brief CMSIS Cortex-M7 Core Peripheral Access Layer Header File
- * @version V4.30
- * @date 20. October 2015
+ * @version V5.1.0
+ * @date 13. March 2019
******************************************************************************/
-/* Copyright (c) 2009 - 2015 ARM LIMITED
-
- All rights reserved.
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are met:
- - Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- - Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
- - Neither the name of ARM nor the names of its contributors may be used
- to endorse or promote products derived from this software without
- specific prior written permission.
- *
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE
- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- POSSIBILITY OF SUCH DAMAGE.
- ---------------------------------------------------------------------------*/
-
+/*
+ * Copyright (c) 2009-2019 Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
#if defined ( __ICCARM__ )
- #pragma system_include /* treat file as system include file for MISRA check */
-#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
+ #pragma system_include /* treat file as system include file for MISRA check */
+#elif defined (__clang__)
#pragma clang system_header /* treat file as system include file */
#endif
@@ -70,60 +60,22 @@
@{
*/
-/* CMSIS CM7 definitions */
-#define __CM7_CMSIS_VERSION_MAIN (0x04U) /*!< [31:16] CMSIS HAL main version */
-#define __CM7_CMSIS_VERSION_SUB (0x1EU) /*!< [15:0] CMSIS HAL sub version */
-#define __CM7_CMSIS_VERSION ((__CM7_CMSIS_VERSION_MAIN << 16U) | \
- __CM7_CMSIS_VERSION_SUB ) /*!< CMSIS HAL version number */
-
-#define __CORTEX_M (0x07U) /*!< Cortex-M Core */
-
+#include "cmsis_version.h"
-#if defined ( __CC_ARM )
- #define __ASM __asm /*!< asm keyword for ARM Compiler */
- #define __INLINE __inline /*!< inline keyword for ARM Compiler */
- #define __STATIC_INLINE static __inline
-
-#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
- #define __ASM __asm /*!< asm keyword for ARM Compiler */
- #define __INLINE __inline /*!< inline keyword for ARM Compiler */
- #define __STATIC_INLINE static __inline
-
-#elif defined ( __GNUC__ )
- #define __ASM __asm /*!< asm keyword for GNU Compiler */
- #define __INLINE inline /*!< inline keyword for GNU Compiler */
- #define __STATIC_INLINE static inline
-
-#elif defined ( __ICCARM__ )
- #define __ASM __asm /*!< asm keyword for IAR Compiler */
- #define __INLINE inline /*!< inline keyword for IAR Compiler. Only available in High optimization mode! */
- #define __STATIC_INLINE static inline
-
-#elif defined ( __TMS470__ )
- #define __ASM __asm /*!< asm keyword for TI CCS Compiler */
- #define __STATIC_INLINE static inline
-
-#elif defined ( __TASKING__ )
- #define __ASM __asm /*!< asm keyword for TASKING Compiler */
- #define __INLINE inline /*!< inline keyword for TASKING Compiler */
- #define __STATIC_INLINE static inline
-
-#elif defined ( __CSMC__ )
- #define __packed
- #define __ASM _asm /*!< asm keyword for COSMIC Compiler */
- #define __INLINE inline /*!< inline keyword for COSMIC Compiler. Use -pc99 on compile line */
- #define __STATIC_INLINE static inline
+/* CMSIS CM7 definitions */
+#define __CM7_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */
+#define __CM7_CMSIS_VERSION_SUB ( __CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */
+#define __CM7_CMSIS_VERSION ((__CM7_CMSIS_VERSION_MAIN << 16U) | \
+ __CM7_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */
-#else
- #error Unknown compiler
-#endif
+#define __CORTEX_M (7U) /*!< Cortex-M Core */
/** __FPU_USED indicates whether an FPU is used or not.
For this, __FPU_PRESENT has to be checked prior to making use of FPU specific registers and functions.
*/
#if defined ( __CC_ARM )
#if defined __TARGET_FPU_VFP
- #if (__FPU_PRESENT == 1U)
+ #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)
#define __FPU_USED 1U
#else
#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
@@ -133,9 +85,9 @@
#define __FPU_USED 0U
#endif
-#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
- #if defined __ARM_PCS_VFP
- #if (__FPU_PRESENT == 1)
+#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
+ #if defined __ARM_FP
+ #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)
#define __FPU_USED 1U
#else
#warning "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
@@ -147,7 +99,7 @@
#elif defined ( __GNUC__ )
#if defined (__VFP_FP__) && !defined(__SOFTFP__)
- #if (__FPU_PRESENT == 1U)
+ #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)
#define __FPU_USED 1U
#else
#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
@@ -159,7 +111,7 @@
#elif defined ( __ICCARM__ )
#if defined __ARMVFP__
- #if (__FPU_PRESENT == 1U)
+ #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)
#define __FPU_USED 1U
#else
#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
@@ -169,9 +121,9 @@
#define __FPU_USED 0U
#endif
-#elif defined ( __TMS470__ )
+#elif defined ( __TI_ARM__ )
#if defined __TI_VFP_SUPPORT__
- #if (__FPU_PRESENT == 1U)
+ #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)
#define __FPU_USED 1U
#else
#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
@@ -183,7 +135,7 @@
#elif defined ( __TASKING__ )
#if defined __FPU_VFP__
- #if (__FPU_PRESENT == 1U)
+ #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)
#define __FPU_USED 1U
#else
#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
@@ -195,7 +147,7 @@
#elif defined ( __CSMC__ )
#if ( __CSMC__ & 0x400U)
- #if (__FPU_PRESENT == 1U)
+ #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)
#define __FPU_USED 1U
#else
#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
@@ -207,9 +159,8 @@
#endif
-#include "core_cmInstr.h" /* Core Instruction Access */
-#include "core_cmFunc.h" /* Core Function Access */
-#include "core_cmSimd.h" /* Compiler specific SIMD Intrinsics */
+#include "cmsis_compiler.h" /* CMSIS compiler specific defines */
+
#ifdef __cplusplus
}
@@ -382,11 +333,12 @@ typedef union
struct
{
uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */
- uint32_t _reserved0:7; /*!< bit: 9..15 Reserved */
+ uint32_t _reserved0:1; /*!< bit: 9 Reserved */
+ uint32_t ICI_IT_1:6; /*!< bit: 10..15 ICI/IT part 1 */
uint32_t GE:4; /*!< bit: 16..19 Greater than or Equal flags */
uint32_t _reserved1:4; /*!< bit: 20..23 Reserved */
- uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */
- uint32_t IT:2; /*!< bit: 25..26 saved IT state (read 0) */
+ uint32_t T:1; /*!< bit: 24 Thumb bit */
+ uint32_t ICI_IT_2:2; /*!< bit: 25..26 ICI/IT part 2 */
uint32_t Q:1; /*!< bit: 27 Saturation condition flag */
uint32_t V:1; /*!< bit: 28 Overflow condition code flag */
uint32_t C:1; /*!< bit: 29 Carry condition code flag */
@@ -412,8 +364,8 @@ typedef union
#define xPSR_Q_Pos 27U /*!< xPSR: Q Position */
#define xPSR_Q_Msk (1UL << xPSR_Q_Pos) /*!< xPSR: Q Mask */
-#define xPSR_IT_Pos 25U /*!< xPSR: IT Position */
-#define xPSR_IT_Msk (3UL << xPSR_IT_Pos) /*!< xPSR: IT Mask */
+#define xPSR_ICI_IT_2_Pos 25U /*!< xPSR: ICI/IT part 2 Position */
+#define xPSR_ICI_IT_2_Msk (3UL << xPSR_ICI_IT_2_Pos) /*!< xPSR: ICI/IT part 2 Mask */
#define xPSR_T_Pos 24U /*!< xPSR: T Position */
#define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */
@@ -421,6 +373,9 @@ typedef union
#define xPSR_GE_Pos 16U /*!< xPSR: GE Position */
#define xPSR_GE_Msk (0xFUL << xPSR_GE_Pos) /*!< xPSR: GE Mask */
+#define xPSR_ICI_IT_1_Pos 10U /*!< xPSR: ICI/IT part 1 Position */
+#define xPSR_ICI_IT_1_Msk (0x3FUL << xPSR_ICI_IT_1_Pos) /*!< xPSR: ICI/IT part 1 Mask */
+
#define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */
#define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */
@@ -468,7 +423,7 @@ typedef struct
__IOM uint32_t ISER[8U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */
uint32_t RESERVED0[24U];
__IOM uint32_t ICER[8U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */
- uint32_t RSERVED1[24U];
+ uint32_t RESERVED1[24U];
__IOM uint32_t ISPR[8U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */
uint32_t RESERVED2[24U];
__IOM uint32_t ICPR[8U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */
@@ -529,7 +484,7 @@ typedef struct
uint32_t RESERVED4[15U];
__IM uint32_t MVFR0; /*!< Offset: 0x240 (R/ ) Media and VFP Feature Register 0 */
__IM uint32_t MVFR1; /*!< Offset: 0x244 (R/ ) Media and VFP Feature Register 1 */
- __IM uint32_t MVFR2; /*!< Offset: 0x248 (R/ ) Media and VFP Feature Register 1 */
+ __IM uint32_t MVFR2; /*!< Offset: 0x248 (R/ ) Media and VFP Feature Register 2 */
uint32_t RESERVED5[1U];
__OM uint32_t ICIALLU; /*!< Offset: 0x250 ( /W) I-Cache Invalidate All to PoU */
uint32_t RESERVED6[1U];
@@ -715,6 +670,66 @@ typedef struct
#define SCB_CFSR_MEMFAULTSR_Pos 0U /*!< SCB CFSR: Memory Manage Fault Status Register Position */
#define SCB_CFSR_MEMFAULTSR_Msk (0xFFUL /*<< SCB_CFSR_MEMFAULTSR_Pos*/) /*!< SCB CFSR: Memory Manage Fault Status Register Mask */
+/* MemManage Fault Status Register (part of SCB Configurable Fault Status Register) */
+#define SCB_CFSR_MMARVALID_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 7U) /*!< SCB CFSR (MMFSR): MMARVALID Position */
+#define SCB_CFSR_MMARVALID_Msk (1UL << SCB_CFSR_MMARVALID_Pos) /*!< SCB CFSR (MMFSR): MMARVALID Mask */
+
+#define SCB_CFSR_MLSPERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 5U) /*!< SCB CFSR (MMFSR): MLSPERR Position */
+#define SCB_CFSR_MLSPERR_Msk (1UL << SCB_CFSR_MLSPERR_Pos) /*!< SCB CFSR (MMFSR): MLSPERR Mask */
+
+#define SCB_CFSR_MSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 4U) /*!< SCB CFSR (MMFSR): MSTKERR Position */
+#define SCB_CFSR_MSTKERR_Msk (1UL << SCB_CFSR_MSTKERR_Pos) /*!< SCB CFSR (MMFSR): MSTKERR Mask */
+
+#define SCB_CFSR_MUNSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 3U) /*!< SCB CFSR (MMFSR): MUNSTKERR Position */
+#define SCB_CFSR_MUNSTKERR_Msk (1UL << SCB_CFSR_MUNSTKERR_Pos) /*!< SCB CFSR (MMFSR): MUNSTKERR Mask */
+
+#define SCB_CFSR_DACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 1U) /*!< SCB CFSR (MMFSR): DACCVIOL Position */
+#define SCB_CFSR_DACCVIOL_Msk (1UL << SCB_CFSR_DACCVIOL_Pos) /*!< SCB CFSR (MMFSR): DACCVIOL Mask */
+
+#define SCB_CFSR_IACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 0U) /*!< SCB CFSR (MMFSR): IACCVIOL Position */
+#define SCB_CFSR_IACCVIOL_Msk (1UL /*<< SCB_CFSR_IACCVIOL_Pos*/) /*!< SCB CFSR (MMFSR): IACCVIOL Mask */
+
+/* BusFault Status Register (part of SCB Configurable Fault Status Register) */
+#define SCB_CFSR_BFARVALID_Pos (SCB_CFSR_BUSFAULTSR_Pos + 7U) /*!< SCB CFSR (BFSR): BFARVALID Position */
+#define SCB_CFSR_BFARVALID_Msk (1UL << SCB_CFSR_BFARVALID_Pos) /*!< SCB CFSR (BFSR): BFARVALID Mask */
+
+#define SCB_CFSR_LSPERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 5U) /*!< SCB CFSR (BFSR): LSPERR Position */
+#define SCB_CFSR_LSPERR_Msk (1UL << SCB_CFSR_LSPERR_Pos) /*!< SCB CFSR (BFSR): LSPERR Mask */
+
+#define SCB_CFSR_STKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 4U) /*!< SCB CFSR (BFSR): STKERR Position */
+#define SCB_CFSR_STKERR_Msk (1UL << SCB_CFSR_STKERR_Pos) /*!< SCB CFSR (BFSR): STKERR Mask */
+
+#define SCB_CFSR_UNSTKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 3U) /*!< SCB CFSR (BFSR): UNSTKERR Position */
+#define SCB_CFSR_UNSTKERR_Msk (1UL << SCB_CFSR_UNSTKERR_Pos) /*!< SCB CFSR (BFSR): UNSTKERR Mask */
+
+#define SCB_CFSR_IMPRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 2U) /*!< SCB CFSR (BFSR): IMPRECISERR Position */
+#define SCB_CFSR_IMPRECISERR_Msk (1UL << SCB_CFSR_IMPRECISERR_Pos) /*!< SCB CFSR (BFSR): IMPRECISERR Mask */
+
+#define SCB_CFSR_PRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 1U) /*!< SCB CFSR (BFSR): PRECISERR Position */
+#define SCB_CFSR_PRECISERR_Msk (1UL << SCB_CFSR_PRECISERR_Pos) /*!< SCB CFSR (BFSR): PRECISERR Mask */
+
+#define SCB_CFSR_IBUSERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 0U) /*!< SCB CFSR (BFSR): IBUSERR Position */
+#define SCB_CFSR_IBUSERR_Msk (1UL << SCB_CFSR_IBUSERR_Pos) /*!< SCB CFSR (BFSR): IBUSERR Mask */
+
+/* UsageFault Status Register (part of SCB Configurable Fault Status Register) */
+#define SCB_CFSR_DIVBYZERO_Pos (SCB_CFSR_USGFAULTSR_Pos + 9U) /*!< SCB CFSR (UFSR): DIVBYZERO Position */
+#define SCB_CFSR_DIVBYZERO_Msk (1UL << SCB_CFSR_DIVBYZERO_Pos) /*!< SCB CFSR (UFSR): DIVBYZERO Mask */
+
+#define SCB_CFSR_UNALIGNED_Pos (SCB_CFSR_USGFAULTSR_Pos + 8U) /*!< SCB CFSR (UFSR): UNALIGNED Position */
+#define SCB_CFSR_UNALIGNED_Msk (1UL << SCB_CFSR_UNALIGNED_Pos) /*!< SCB CFSR (UFSR): UNALIGNED Mask */
+
+#define SCB_CFSR_NOCP_Pos (SCB_CFSR_USGFAULTSR_Pos + 3U) /*!< SCB CFSR (UFSR): NOCP Position */
+#define SCB_CFSR_NOCP_Msk (1UL << SCB_CFSR_NOCP_Pos) /*!< SCB CFSR (UFSR): NOCP Mask */
+
+#define SCB_CFSR_INVPC_Pos (SCB_CFSR_USGFAULTSR_Pos + 2U) /*!< SCB CFSR (UFSR): INVPC Position */
+#define SCB_CFSR_INVPC_Msk (1UL << SCB_CFSR_INVPC_Pos) /*!< SCB CFSR (UFSR): INVPC Mask */
+
+#define SCB_CFSR_INVSTATE_Pos (SCB_CFSR_USGFAULTSR_Pos + 1U) /*!< SCB CFSR (UFSR): INVSTATE Position */
+#define SCB_CFSR_INVSTATE_Msk (1UL << SCB_CFSR_INVSTATE_Pos) /*!< SCB CFSR (UFSR): INVSTATE Mask */
+
+#define SCB_CFSR_UNDEFINSTR_Pos (SCB_CFSR_USGFAULTSR_Pos + 0U) /*!< SCB CFSR (UFSR): UNDEFINSTR Position */
+#define SCB_CFSR_UNDEFINSTR_Msk (1UL << SCB_CFSR_UNDEFINSTR_Pos) /*!< SCB CFSR (UFSR): UNDEFINSTR Mask */
+
/* SCB Hard Fault Status Register Definitions */
#define SCB_HFSR_DEBUGEVT_Pos 31U /*!< SCB HFSR: DEBUGEVT Position */
#define SCB_HFSR_DEBUGEVT_Msk (1UL << SCB_HFSR_DEBUGEVT_Pos) /*!< SCB HFSR: DEBUGEVT Mask */
@@ -915,6 +930,24 @@ typedef struct
#define SCnSCB_ICTR_INTLINESNUM_Msk (0xFUL /*<< SCnSCB_ICTR_INTLINESNUM_Pos*/) /*!< ICTR: INTLINESNUM Mask */
/* Auxiliary Control Register Definitions */
+#define SCnSCB_ACTLR_DISDYNADD_Pos 26U /*!< ACTLR: DISDYNADD Position */
+#define SCnSCB_ACTLR_DISDYNADD_Msk (1UL << SCnSCB_ACTLR_DISDYNADD_Pos) /*!< ACTLR: DISDYNADD Mask */
+
+#define SCnSCB_ACTLR_DISISSCH1_Pos 21U /*!< ACTLR: DISISSCH1 Position */
+#define SCnSCB_ACTLR_DISISSCH1_Msk (0x1FUL << SCnSCB_ACTLR_DISISSCH1_Pos) /*!< ACTLR: DISISSCH1 Mask */
+
+#define SCnSCB_ACTLR_DISDI_Pos 16U /*!< ACTLR: DISDI Position */
+#define SCnSCB_ACTLR_DISDI_Msk (0x1FUL << SCnSCB_ACTLR_DISDI_Pos) /*!< ACTLR: DISDI Mask */
+
+#define SCnSCB_ACTLR_DISCRITAXIRUR_Pos 15U /*!< ACTLR: DISCRITAXIRUR Position */
+#define SCnSCB_ACTLR_DISCRITAXIRUR_Msk (1UL << SCnSCB_ACTLR_DISCRITAXIRUR_Pos) /*!< ACTLR: DISCRITAXIRUR Mask */
+
+#define SCnSCB_ACTLR_DISBTACALLOC_Pos 14U /*!< ACTLR: DISBTACALLOC Position */
+#define SCnSCB_ACTLR_DISBTACALLOC_Msk (1UL << SCnSCB_ACTLR_DISBTACALLOC_Pos) /*!< ACTLR: DISBTACALLOC Mask */
+
+#define SCnSCB_ACTLR_DISBTACREAD_Pos 13U /*!< ACTLR: DISBTACREAD Position */
+#define SCnSCB_ACTLR_DISBTACREAD_Msk (1UL << SCnSCB_ACTLR_DISBTACREAD_Pos) /*!< ACTLR: DISBTACREAD Mask */
+
#define SCnSCB_ACTLR_DISITMATBFLUSH_Pos 12U /*!< ACTLR: DISITMATBFLUSH Position */
#define SCnSCB_ACTLR_DISITMATBFLUSH_Msk (1UL << SCnSCB_ACTLR_DISITMATBFLUSH_Pos) /*!< ACTLR: DISITMATBFLUSH Mask */
@@ -1009,10 +1042,7 @@ typedef struct
__IOM uint32_t TPR; /*!< Offset: 0xE40 (R/W) ITM Trace Privilege Register */
uint32_t RESERVED2[15U];
__IOM uint32_t TCR; /*!< Offset: 0xE80 (R/W) ITM Trace Control Register */
- uint32_t RESERVED3[29U];
- __OM uint32_t IWR; /*!< Offset: 0xEF8 ( /W) ITM Integration Write Register */
- __IM uint32_t IRR; /*!< Offset: 0xEFC (R/ ) ITM Integration Read Register */
- __IOM uint32_t IMCR; /*!< Offset: 0xF00 (R/W) ITM Integration Mode Control Register */
+ uint32_t RESERVED3[32U];
uint32_t RESERVED4[43U];
__OM uint32_t LAR; /*!< Offset: 0xFB0 ( /W) ITM Lock Access Register */
__IM uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) ITM Lock Status Register */
@@ -1033,7 +1063,7 @@ typedef struct
/* ITM Trace Privilege Register Definitions */
#define ITM_TPR_PRIVMASK_Pos 0U /*!< ITM TPR: PRIVMASK Position */
-#define ITM_TPR_PRIVMASK_Msk (0xFUL /*<< ITM_TPR_PRIVMASK_Pos*/) /*!< ITM TPR: PRIVMASK Mask */
+#define ITM_TPR_PRIVMASK_Msk (0xFFFFFFFFUL /*<< ITM_TPR_PRIVMASK_Pos*/) /*!< ITM TPR: PRIVMASK Mask */
/* ITM Trace Control Register Definitions */
#define ITM_TCR_BUSY_Pos 23U /*!< ITM TCR: BUSY Position */
@@ -1063,18 +1093,6 @@ typedef struct
#define ITM_TCR_ITMENA_Pos 0U /*!< ITM TCR: ITM Enable bit Position */
#define ITM_TCR_ITMENA_Msk (1UL /*<< ITM_TCR_ITMENA_Pos*/) /*!< ITM TCR: ITM Enable bit Mask */
-/* ITM Integration Write Register Definitions */
-#define ITM_IWR_ATVALIDM_Pos 0U /*!< ITM IWR: ATVALIDM Position */
-#define ITM_IWR_ATVALIDM_Msk (1UL /*<< ITM_IWR_ATVALIDM_Pos*/) /*!< ITM IWR: ATVALIDM Mask */
-
-/* ITM Integration Read Register Definitions */
-#define ITM_IRR_ATREADYM_Pos 0U /*!< ITM IRR: ATREADYM Position */
-#define ITM_IRR_ATREADYM_Msk (1UL /*<< ITM_IRR_ATREADYM_Pos*/) /*!< ITM IRR: ATREADYM Mask */
-
-/* ITM Integration Mode Control Register Definitions */
-#define ITM_IMCR_INTEGRATION_Pos 0U /*!< ITM IMCR: INTEGRATION Position */
-#define ITM_IMCR_INTEGRATION_Msk (1UL /*<< ITM_IMCR_INTEGRATION_Pos*/) /*!< ITM IMCR: INTEGRATION Mask */
-
/* ITM Lock Status Register Definitions */
#define ITM_LSR_ByteAcc_Pos 2U /*!< ITM LSR: ByteAcc Position */
#define ITM_LSR_ByteAcc_Msk (1UL << ITM_LSR_ByteAcc_Pos) /*!< ITM LSR: ByteAcc Mask */
@@ -1250,7 +1268,7 @@ typedef struct
*/
typedef struct
{
- __IOM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Size Register */
+ __IM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Size Register */
__IOM uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Size Register */
uint32_t RESERVED0[2U];
__IOM uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */
@@ -1261,7 +1279,7 @@ typedef struct
__IOM uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */
__IM uint32_t FSCR; /*!< Offset: 0x308 (R/ ) Formatter Synchronization Counter Register */
uint32_t RESERVED3[759U];
- __IM uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER */
+ __IM uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER Register */
__IM uint32_t FIFO0; /*!< Offset: 0xEEC (R/ ) Integration ETM Data */
__IM uint32_t ITATBCTR2; /*!< Offset: 0xEF0 (R/ ) ITATBCTR2 */
uint32_t RESERVED4[1U];
@@ -1310,13 +1328,13 @@ typedef struct
/* TPI Integration ETM Data Register Definitions (FIFO0) */
#define TPI_FIFO0_ITM_ATVALID_Pos 29U /*!< TPI FIFO0: ITM_ATVALID Position */
-#define TPI_FIFO0_ITM_ATVALID_Msk (0x3UL << TPI_FIFO0_ITM_ATVALID_Pos) /*!< TPI FIFO0: ITM_ATVALID Mask */
+#define TPI_FIFO0_ITM_ATVALID_Msk (0x1UL << TPI_FIFO0_ITM_ATVALID_Pos) /*!< TPI FIFO0: ITM_ATVALID Mask */
#define TPI_FIFO0_ITM_bytecount_Pos 27U /*!< TPI FIFO0: ITM_bytecount Position */
#define TPI_FIFO0_ITM_bytecount_Msk (0x3UL << TPI_FIFO0_ITM_bytecount_Pos) /*!< TPI FIFO0: ITM_bytecount Mask */
#define TPI_FIFO0_ETM_ATVALID_Pos 26U /*!< TPI FIFO0: ETM_ATVALID Position */
-#define TPI_FIFO0_ETM_ATVALID_Msk (0x3UL << TPI_FIFO0_ETM_ATVALID_Pos) /*!< TPI FIFO0: ETM_ATVALID Mask */
+#define TPI_FIFO0_ETM_ATVALID_Msk (0x1UL << TPI_FIFO0_ETM_ATVALID_Pos) /*!< TPI FIFO0: ETM_ATVALID Mask */
#define TPI_FIFO0_ETM_bytecount_Pos 24U /*!< TPI FIFO0: ETM_bytecount Position */
#define TPI_FIFO0_ETM_bytecount_Msk (0x3UL << TPI_FIFO0_ETM_bytecount_Pos) /*!< TPI FIFO0: ETM_bytecount Mask */
@@ -1331,18 +1349,21 @@ typedef struct
#define TPI_FIFO0_ETM0_Msk (0xFFUL /*<< TPI_FIFO0_ETM0_Pos*/) /*!< TPI FIFO0: ETM0 Mask */
/* TPI ITATBCTR2 Register Definitions */
-#define TPI_ITATBCTR2_ATREADY_Pos 0U /*!< TPI ITATBCTR2: ATREADY Position */
-#define TPI_ITATBCTR2_ATREADY_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY_Pos*/) /*!< TPI ITATBCTR2: ATREADY Mask */
+#define TPI_ITATBCTR2_ATREADY2_Pos 0U /*!< TPI ITATBCTR2: ATREADY2 Position */
+#define TPI_ITATBCTR2_ATREADY2_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY2_Pos*/) /*!< TPI ITATBCTR2: ATREADY2 Mask */
+
+#define TPI_ITATBCTR2_ATREADY1_Pos 0U /*!< TPI ITATBCTR2: ATREADY1 Position */
+#define TPI_ITATBCTR2_ATREADY1_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY1_Pos*/) /*!< TPI ITATBCTR2: ATREADY1 Mask */
/* TPI Integration ITM Data Register Definitions (FIFO1) */
#define TPI_FIFO1_ITM_ATVALID_Pos 29U /*!< TPI FIFO1: ITM_ATVALID Position */
-#define TPI_FIFO1_ITM_ATVALID_Msk (0x3UL << TPI_FIFO1_ITM_ATVALID_Pos) /*!< TPI FIFO1: ITM_ATVALID Mask */
+#define TPI_FIFO1_ITM_ATVALID_Msk (0x1UL << TPI_FIFO1_ITM_ATVALID_Pos) /*!< TPI FIFO1: ITM_ATVALID Mask */
#define TPI_FIFO1_ITM_bytecount_Pos 27U /*!< TPI FIFO1: ITM_bytecount Position */
#define TPI_FIFO1_ITM_bytecount_Msk (0x3UL << TPI_FIFO1_ITM_bytecount_Pos) /*!< TPI FIFO1: ITM_bytecount Mask */
#define TPI_FIFO1_ETM_ATVALID_Pos 26U /*!< TPI FIFO1: ETM_ATVALID Position */
-#define TPI_FIFO1_ETM_ATVALID_Msk (0x3UL << TPI_FIFO1_ETM_ATVALID_Pos) /*!< TPI FIFO1: ETM_ATVALID Mask */
+#define TPI_FIFO1_ETM_ATVALID_Msk (0x1UL << TPI_FIFO1_ETM_ATVALID_Pos) /*!< TPI FIFO1: ETM_ATVALID Mask */
#define TPI_FIFO1_ETM_bytecount_Pos 24U /*!< TPI FIFO1: ETM_bytecount Position */
#define TPI_FIFO1_ETM_bytecount_Msk (0x3UL << TPI_FIFO1_ETM_bytecount_Pos) /*!< TPI FIFO1: ETM_bytecount Mask */
@@ -1357,12 +1378,15 @@ typedef struct
#define TPI_FIFO1_ITM0_Msk (0xFFUL /*<< TPI_FIFO1_ITM0_Pos*/) /*!< TPI FIFO1: ITM0 Mask */
/* TPI ITATBCTR0 Register Definitions */
-#define TPI_ITATBCTR0_ATREADY_Pos 0U /*!< TPI ITATBCTR0: ATREADY Position */
-#define TPI_ITATBCTR0_ATREADY_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY_Pos*/) /*!< TPI ITATBCTR0: ATREADY Mask */
+#define TPI_ITATBCTR0_ATREADY2_Pos 0U /*!< TPI ITATBCTR0: ATREADY2 Position */
+#define TPI_ITATBCTR0_ATREADY2_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY2_Pos*/) /*!< TPI ITATBCTR0: ATREADY2 Mask */
+
+#define TPI_ITATBCTR0_ATREADY1_Pos 0U /*!< TPI ITATBCTR0: ATREADY1 Position */
+#define TPI_ITATBCTR0_ATREADY1_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY1_Pos*/) /*!< TPI ITATBCTR0: ATREADY1 Mask */
/* TPI Integration Mode Control Register Definitions */
#define TPI_ITCTRL_Mode_Pos 0U /*!< TPI ITCTRL: Mode Position */
-#define TPI_ITCTRL_Mode_Msk (0x1UL /*<< TPI_ITCTRL_Mode_Pos*/) /*!< TPI ITCTRL: Mode Mask */
+#define TPI_ITCTRL_Mode_Msk (0x3UL /*<< TPI_ITCTRL_Mode_Pos*/) /*!< TPI ITCTRL: Mode Mask */
/* TPI DEVID Register Definitions */
#define TPI_DEVID_NRZVALID_Pos 11U /*!< TPI DEVID: NRZVALID Position */
@@ -1384,16 +1408,16 @@ typedef struct
#define TPI_DEVID_NrTraceInput_Msk (0x1FUL /*<< TPI_DEVID_NrTraceInput_Pos*/) /*!< TPI DEVID: NrTraceInput Mask */
/* TPI DEVTYPE Register Definitions */
-#define TPI_DEVTYPE_MajorType_Pos 4U /*!< TPI DEVTYPE: MajorType Position */
-#define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */
-
-#define TPI_DEVTYPE_SubType_Pos 0U /*!< TPI DEVTYPE: SubType Position */
+#define TPI_DEVTYPE_SubType_Pos 4U /*!< TPI DEVTYPE: SubType Position */
#define TPI_DEVTYPE_SubType_Msk (0xFUL /*<< TPI_DEVTYPE_SubType_Pos*/) /*!< TPI DEVTYPE: SubType Mask */
+#define TPI_DEVTYPE_MajorType_Pos 0U /*!< TPI DEVTYPE: MajorType Position */
+#define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */
+
/*@}*/ /* end of group CMSIS_TPI */
-#if (__MPU_PRESENT == 1U)
+#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U)
/**
\ingroup CMSIS_core_register
\defgroup CMSIS_MPU Memory Protection Unit (MPU)
@@ -1419,6 +1443,8 @@ typedef struct
__IOM uint32_t RASR_A3; /*!< Offset: 0x028 (R/W) MPU Alias 3 Region Attribute and Size Register */
} MPU_Type;
+#define MPU_TYPE_RALIASES 4U
+
/* MPU Type Register Definitions */
#define MPU_TYPE_IREGION_Pos 16U /*!< MPU TYPE: IREGION Position */
#define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */
@@ -1485,10 +1511,9 @@ typedef struct
#define MPU_RASR_ENABLE_Msk (1UL /*<< MPU_RASR_ENABLE_Pos*/) /*!< MPU RASR: Region enable bit Disable Mask */
/*@} end of group CMSIS_MPU */
-#endif
+#endif /* defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) */
-#if (__FPU_PRESENT == 1U)
/**
\ingroup CMSIS_core_register
\defgroup CMSIS_FPU Floating Point Unit (FPU)
@@ -1595,8 +1620,10 @@ typedef struct
/* Media and FP Feature Register 2 Definitions */
+#define FPU_MVFR2_VFP_Misc_Pos 4U /*!< MVFR2: VFP Misc bits Position */
+#define FPU_MVFR2_VFP_Misc_Msk (0xFUL << FPU_MVFR2_VFP_Misc_Pos) /*!< MVFR2: VFP Misc bits Mask */
+
/*@} end of group CMSIS_FPU */
-#endif
/**
@@ -1714,18 +1741,18 @@ typedef struct
/**
\brief Mask and shift a bit field value for use in a register bit range.
\param[in] field Name of the register bit field.
- \param[in] value Value of the bit field.
+ \param[in] value Value of the bit field. This parameter is interpreted as an uint32_t type.
\return Masked and shifted value.
*/
-#define _VAL2FLD(field, value) ((value << field ## _Pos) & field ## _Msk)
+#define _VAL2FLD(field, value) (((uint32_t)(value) << field ## _Pos) & field ## _Msk)
/**
\brief Mask and shift a register value to extract a bit filed value.
\param[in] field Name of the register bit field.
- \param[in] value Value of register.
+ \param[in] value Value of register. This parameter is interpreted as an uint32_t type.
\return Masked and shifted bit field value.
*/
-#define _FLD2VAL(field, value) ((value & field ## _Msk) >> field ## _Pos)
+#define _FLD2VAL(field, value) (((uint32_t)(value) & field ## _Msk) >> field ## _Pos)
/*@} end of group CMSIS_core_bitfield */
@@ -1737,7 +1764,7 @@ typedef struct
@{
*/
-/* Memory mapping of Cortex-M4 Hardware */
+/* Memory mapping of Core Hardware */
#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */
#define ITM_BASE (0xE0000000UL) /*!< ITM Base Address */
#define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */
@@ -1756,15 +1783,13 @@ typedef struct
#define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */
#define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE) /*!< Core Debug configuration struct */
-#if (__MPU_PRESENT == 1U)
+#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U)
#define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */
#define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */
#endif
-#if (__FPU_PRESENT == 1U)
- #define FPU_BASE (SCS_BASE + 0x0F30UL) /*!< Floating Point Unit */
- #define FPU ((FPU_Type *) FPU_BASE ) /*!< Floating Point Unit */
-#endif
+#define FPU_BASE (SCS_BASE + 0x0F30UL) /*!< Floating Point Unit */
+#define FPU ((FPU_Type *) FPU_BASE ) /*!< Floating Point Unit */
/*@} */
@@ -1792,6 +1817,48 @@ typedef struct
@{
*/
+#ifdef CMSIS_NVIC_VIRTUAL
+ #ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE
+ #define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h"
+ #endif
+ #include CMSIS_NVIC_VIRTUAL_HEADER_FILE
+#else
+ #define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping
+ #define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping
+ #define NVIC_EnableIRQ __NVIC_EnableIRQ
+ #define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ
+ #define NVIC_DisableIRQ __NVIC_DisableIRQ
+ #define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ
+ #define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ
+ #define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ
+ #define NVIC_GetActive __NVIC_GetActive
+ #define NVIC_SetPriority __NVIC_SetPriority
+ #define NVIC_GetPriority __NVIC_GetPriority
+ #define NVIC_SystemReset __NVIC_SystemReset
+#endif /* CMSIS_NVIC_VIRTUAL */
+
+#ifdef CMSIS_VECTAB_VIRTUAL
+ #ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE
+ #define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h"
+ #endif
+ #include CMSIS_VECTAB_VIRTUAL_HEADER_FILE
+#else
+ #define NVIC_SetVector __NVIC_SetVector
+ #define NVIC_GetVector __NVIC_GetVector
+#endif /* (CMSIS_VECTAB_VIRTUAL) */
+
+#define NVIC_USER_IRQ_OFFSET 16
+
+
+/* The following EXC_RETURN values are saved the LR on exception entry */
+#define EXC_RETURN_HANDLER (0xFFFFFFF1UL) /* return to Handler mode, uses MSP after return */
+#define EXC_RETURN_THREAD_MSP (0xFFFFFFF9UL) /* return to Thread mode, uses MSP after return */
+#define EXC_RETURN_THREAD_PSP (0xFFFFFFFDUL) /* return to Thread mode, uses PSP after return */
+#define EXC_RETURN_HANDLER_FPU (0xFFFFFFE1UL) /* return to Handler mode, uses MSP after return, restore floating-point state */
+#define EXC_RETURN_THREAD_MSP_FPU (0xFFFFFFE9UL) /* return to Thread mode, uses MSP after return, restore floating-point state */
+#define EXC_RETURN_THREAD_PSP_FPU (0xFFFFFFEDUL) /* return to Thread mode, uses PSP after return, restore floating-point state */
+
+
/**
\brief Set Priority Grouping
\details Sets the priority grouping field using the required unlock sequence.
@@ -1801,7 +1868,7 @@ typedef struct
priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set.
\param [in] PriorityGroup Priority grouping field.
*/
-__STATIC_INLINE void NVIC_SetPriorityGrouping(uint32_t PriorityGroup)
+__STATIC_INLINE void __NVIC_SetPriorityGrouping(uint32_t PriorityGroup)
{
uint32_t reg_value;
uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */
@@ -1810,7 +1877,7 @@ __STATIC_INLINE void NVIC_SetPriorityGrouping(uint32_t PriorityGroup)
reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */
reg_value = (reg_value |
((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) |
- (PriorityGroupTmp << 8U) ); /* Insert write key and priorty group */
+ (PriorityGroupTmp << SCB_AIRCR_PRIGROUP_Pos) ); /* Insert write key and priority group */
SCB->AIRCR = reg_value;
}
@@ -1820,121 +1887,178 @@ __STATIC_INLINE void NVIC_SetPriorityGrouping(uint32_t PriorityGroup)
\details Reads the priority grouping field from the NVIC Interrupt Controller.
\return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field).
*/
-__STATIC_INLINE uint32_t NVIC_GetPriorityGrouping(void)
+__STATIC_INLINE uint32_t __NVIC_GetPriorityGrouping(void)
{
return ((uint32_t)((SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos));
}
/**
- \brief Enable External Interrupt
- \details Enables a device-specific interrupt in the NVIC interrupt controller.
- \param [in] IRQn External interrupt number. Value cannot be negative.
+ \brief Enable Interrupt
+ \details Enables a device specific interrupt in the NVIC interrupt controller.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
*/
-__STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn)
+__STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn)
{
- NVIC->ISER[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL));
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
}
/**
- \brief Disable External Interrupt
- \details Disables a device-specific interrupt in the NVIC interrupt controller.
- \param [in] IRQn External interrupt number. Value cannot be negative.
+ \brief Get Interrupt Enable status
+ \details Returns a device specific interrupt enable status from the NVIC interrupt controller.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 Interrupt is not enabled.
+ \return 1 Interrupt is enabled.
+ \note IRQn must not be negative.
*/
-__STATIC_INLINE void NVIC_DisableIRQ(IRQn_Type IRQn)
+__STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn)
{
- NVIC->ICER[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL));
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Disable Interrupt
+ \details Disables a device specific interrupt in the NVIC interrupt controller.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ICER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ __DSB();
+ __ISB();
+ }
}
/**
\brief Get Pending Interrupt
- \details Reads the pending register in the NVIC and returns the pending bit for the specified interrupt.
- \param [in] IRQn Interrupt number.
+ \details Reads the NVIC pending register and returns the pending bit for the specified device specific interrupt.
+ \param [in] IRQn Device specific interrupt number.
\return 0 Interrupt status is not pending.
\return 1 Interrupt status is pending.
+ \note IRQn must not be negative.
*/
-__STATIC_INLINE uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn)
+__STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn)
{
- return((uint32_t)(((NVIC->ISPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
}
/**
\brief Set Pending Interrupt
- \details Sets the pending bit of an external interrupt.
- \param [in] IRQn Interrupt number. Value cannot be negative.
+ \details Sets the pending bit of a device specific interrupt in the NVIC pending register.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
*/
-__STATIC_INLINE void NVIC_SetPendingIRQ(IRQn_Type IRQn)
+__STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn)
{
- NVIC->ISPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL));
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
}
/**
\brief Clear Pending Interrupt
- \details Clears the pending bit of an external interrupt.
- \param [in] IRQn External interrupt number. Value cannot be negative.
+ \details Clears the pending bit of a device specific interrupt in the NVIC pending register.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
*/
-__STATIC_INLINE void NVIC_ClearPendingIRQ(IRQn_Type IRQn)
+__STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn)
{
- NVIC->ICPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL));
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
}
/**
\brief Get Active Interrupt
- \details Reads the active register in NVIC and returns the active bit.
- \param [in] IRQn Interrupt number.
+ \details Reads the active register in the NVIC and returns the active bit for the device specific interrupt.
+ \param [in] IRQn Device specific interrupt number.
\return 0 Interrupt status is not active.
\return 1 Interrupt status is active.
+ \note IRQn must not be negative.
*/
-__STATIC_INLINE uint32_t NVIC_GetActive(IRQn_Type IRQn)
+__STATIC_INLINE uint32_t __NVIC_GetActive(IRQn_Type IRQn)
{
- return((uint32_t)(((NVIC->IABR[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC->IABR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
}
/**
\brief Set Interrupt Priority
- \details Sets the priority of an interrupt.
- \note The priority cannot be set for every core interrupt.
+ \details Sets the priority of a device specific interrupt or a processor exception.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
\param [in] IRQn Interrupt number.
\param [in] priority Priority to set.
+ \note The priority cannot be set for every processor exception.
*/
-__STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
+__STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
{
- if ((int32_t)(IRQn) < 0)
+ if ((int32_t)(IRQn) >= 0)
{
- SCB->SHPR[(((uint32_t)(int32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL);
+ NVIC->IP[((uint32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL);
}
else
{
- NVIC->IP[((uint32_t)(int32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL);
+ SCB->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL);
}
}
/**
\brief Get Interrupt Priority
- \details Reads the priority of an interrupt.
- The interrupt number can be positive to specify an external (device specific) interrupt,
- or negative to specify an internal (core) interrupt.
+ \details Reads the priority of a device specific interrupt or a processor exception.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
\param [in] IRQn Interrupt number.
\return Interrupt Priority.
Value is aligned automatically to the implemented priority bits of the microcontroller.
*/
-__STATIC_INLINE uint32_t NVIC_GetPriority(IRQn_Type IRQn)
+__STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn)
{
- if ((int32_t)(IRQn) < 0)
+ if ((int32_t)(IRQn) >= 0)
{
- return(((uint32_t)SCB->SHPR[(((uint32_t)(int32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS)));
+ return(((uint32_t)NVIC->IP[((uint32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS)));
}
else
{
- return(((uint32_t)NVIC->IP[((uint32_t)(int32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS)));
+ return(((uint32_t)SCB->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS)));
}
}
@@ -1991,11 +2115,42 @@ __STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGr
}
+/**
+ \brief Set Interrupt Vector
+ \details Sets an interrupt vector in SRAM based interrupt vector table.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ VTOR must been relocated to SRAM before.
+ \param [in] IRQn Interrupt number
+ \param [in] vector Address of interrupt handler function
+ */
+__STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector)
+{
+ uint32_t vectors = (uint32_t )SCB->VTOR;
+ (* (int *) (vectors + ((int32_t)IRQn + NVIC_USER_IRQ_OFFSET) * 4)) = vector;
+}
+
+
+/**
+ \brief Get Interrupt Vector
+ \details Reads an interrupt vector from interrupt vector table.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ \param [in] IRQn Interrupt number.
+ \return Address of interrupt handler function
+ */
+__STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn)
+{
+ uint32_t vectors = (uint32_t )SCB->VTOR;
+ return (uint32_t)(* (int *) (vectors + ((int32_t)IRQn + NVIC_USER_IRQ_OFFSET) * 4));
+}
+
+
/**
\brief System Reset
\details Initiates a system reset request to reset the MCU.
*/
-__STATIC_INLINE void NVIC_SystemReset(void)
+__NO_RETURN __STATIC_INLINE void __NVIC_SystemReset(void)
{
__DSB(); /* Ensure all outstanding memory accesses included
buffered write are completed before reset */
@@ -2013,6 +2168,15 @@ __STATIC_INLINE void NVIC_SystemReset(void)
/*@} end of CMSIS_Core_NVICFunctions */
+/* ########################## MPU functions #################################### */
+
+#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U)
+
+#include "mpu_armv7.h"
+
+#endif
+
+
/* ########################## FPU functions #################################### */
/**
\ingroup CMSIS_Core_FunctionInterface
@@ -2034,21 +2198,20 @@ __STATIC_INLINE uint32_t SCB_GetFPUType(void)
uint32_t mvfr0;
mvfr0 = SCB->MVFR0;
- if ((mvfr0 & 0x00000FF0UL) == 0x220UL)
+ if ((mvfr0 & (FPU_MVFR0_Single_precision_Msk | FPU_MVFR0_Double_precision_Msk)) == 0x220U)
{
- return 2UL; /* Double + Single precision FPU */
+ return 2U; /* Double + Single precision FPU */
}
- else if ((mvfr0 & 0x00000FF0UL) == 0x020UL)
+ else if ((mvfr0 & (FPU_MVFR0_Single_precision_Msk | FPU_MVFR0_Double_precision_Msk)) == 0x020U)
{
- return 1UL; /* Single precision FPU */
+ return 1U; /* Single precision FPU */
}
else
{
- return 0UL; /* No FPU */
+ return 0U; /* No FPU */
}
}
-
/*@} end of CMSIS_Core_FpuFunctions */
@@ -2065,17 +2228,22 @@ __STATIC_INLINE uint32_t SCB_GetFPUType(void)
#define CCSIDR_WAYS(x) (((x) & SCB_CCSIDR_ASSOCIATIVITY_Msk) >> SCB_CCSIDR_ASSOCIATIVITY_Pos)
#define CCSIDR_SETS(x) (((x) & SCB_CCSIDR_NUMSETS_Msk ) >> SCB_CCSIDR_NUMSETS_Pos )
+#define __SCB_DCACHE_LINE_SIZE 32U /*!< Cortex-M7 cache line size is fixed to 32 bytes (8 words). See also register SCB_CCSIDR */
/**
\brief Enable I-Cache
\details Turns on I-Cache
*/
-__STATIC_INLINE void SCB_EnableICache (void)
+__STATIC_FORCEINLINE void SCB_EnableICache (void)
{
- #if (__ICACHE_PRESENT == 1U)
+ #if defined (__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U)
+ if (SCB->CCR & SCB_CCR_IC_Msk) return; /* return if ICache is already enabled */
+
__DSB();
__ISB();
SCB->ICIALLU = 0UL; /* invalidate I-Cache */
+ __DSB();
+ __ISB();
SCB->CCR |= (uint32_t)SCB_CCR_IC_Msk; /* enable I-Cache */
__DSB();
__ISB();
@@ -2087,9 +2255,9 @@ __STATIC_INLINE void SCB_EnableICache (void)
\brief Disable I-Cache
\details Turns off I-Cache
*/
-__STATIC_INLINE void SCB_DisableICache (void)
+__STATIC_FORCEINLINE void SCB_DisableICache (void)
{
- #if (__ICACHE_PRESENT == 1U)
+ #if defined (__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U)
__DSB();
__ISB();
SCB->CCR &= ~(uint32_t)SCB_CCR_IC_Msk; /* disable I-Cache */
@@ -2104,9 +2272,9 @@ __STATIC_INLINE void SCB_DisableICache (void)
\brief Invalidate I-Cache
\details Invalidates I-Cache
*/
-__STATIC_INLINE void SCB_InvalidateICache (void)
+__STATIC_FORCEINLINE void SCB_InvalidateICache (void)
{
- #if (__ICACHE_PRESENT == 1U)
+ #if defined (__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U)
__DSB();
__ISB();
SCB->ICIALLU = 0UL;
@@ -2120,14 +2288,16 @@ __STATIC_INLINE void SCB_InvalidateICache (void)
\brief Enable D-Cache
\details Turns on D-Cache
*/
-__STATIC_INLINE void SCB_EnableDCache (void)
+__STATIC_FORCEINLINE void SCB_EnableDCache (void)
{
- #if (__DCACHE_PRESENT == 1U)
+ #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
uint32_t ccsidr;
uint32_t sets;
uint32_t ways;
- SCB->CSSELR = (0U << 1U) | 0U; /* Level 1 data cache */
+ if (SCB->CCR & SCB_CCR_DC_Msk) return; /* return if DCache is already enabled */
+
+ SCB->CSSELR = 0U; /* select Level 1 data cache */
__DSB();
ccsidr = SCB->CCSIDR;
@@ -2142,8 +2312,8 @@ __STATIC_INLINE void SCB_EnableDCache (void)
#if defined ( __CC_ARM )
__schedule_barrier();
#endif
- } while (ways--);
- } while(sets--);
+ } while (ways-- != 0U);
+ } while(sets-- != 0U);
__DSB();
SCB->CCR |= (uint32_t)SCB_CCR_DC_Msk; /* enable D-Cache */
@@ -2158,19 +2328,20 @@ __STATIC_INLINE void SCB_EnableDCache (void)
\brief Disable D-Cache
\details Turns off D-Cache
*/
-__STATIC_INLINE void SCB_DisableDCache (void)
+__STATIC_FORCEINLINE void SCB_DisableDCache (void)
{
- #if (__DCACHE_PRESENT == 1U)
+ #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
uint32_t ccsidr;
uint32_t sets;
uint32_t ways;
- SCB->CSSELR = (0U << 1U) | 0U; /* Level 1 data cache */
+ SCB->CSSELR = 0U; /* select Level 1 data cache */
__DSB();
- ccsidr = SCB->CCSIDR;
-
SCB->CCR &= ~(uint32_t)SCB_CCR_DC_Msk; /* disable D-Cache */
+ __DSB();
+
+ ccsidr = SCB->CCSIDR;
/* clean & invalidate D-Cache */
sets = (uint32_t)(CCSIDR_SETS(ccsidr));
@@ -2182,8 +2353,8 @@ __STATIC_INLINE void SCB_DisableDCache (void)
#if defined ( __CC_ARM )
__schedule_barrier();
#endif
- } while (ways--);
- } while(sets--);
+ } while (ways-- != 0U);
+ } while(sets-- != 0U);
__DSB();
__ISB();
@@ -2195,14 +2366,14 @@ __STATIC_INLINE void SCB_DisableDCache (void)
\brief Invalidate D-Cache
\details Invalidates D-Cache
*/
-__STATIC_INLINE void SCB_InvalidateDCache (void)
+__STATIC_FORCEINLINE void SCB_InvalidateDCache (void)
{
- #if (__DCACHE_PRESENT == 1U)
+ #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
uint32_t ccsidr;
uint32_t sets;
uint32_t ways;
- SCB->CSSELR = (0U << 1U) | 0U; /* Level 1 data cache */
+ SCB->CSSELR = 0U; /* select Level 1 data cache */
__DSB();
ccsidr = SCB->CCSIDR;
@@ -2217,8 +2388,8 @@ __STATIC_INLINE void SCB_InvalidateDCache (void)
#if defined ( __CC_ARM )
__schedule_barrier();
#endif
- } while (ways--);
- } while(sets--);
+ } while (ways-- != 0U);
+ } while(sets-- != 0U);
__DSB();
__ISB();
@@ -2230,14 +2401,14 @@ __STATIC_INLINE void SCB_InvalidateDCache (void)
\brief Clean D-Cache
\details Cleans D-Cache
*/
-__STATIC_INLINE void SCB_CleanDCache (void)
+__STATIC_FORCEINLINE void SCB_CleanDCache (void)
{
- #if (__DCACHE_PRESENT == 1U)
+ #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
uint32_t ccsidr;
uint32_t sets;
uint32_t ways;
- SCB->CSSELR = (0U << 1U) | 0U; /* Level 1 data cache */
+ SCB->CSSELR = 0U; /* select Level 1 data cache */
__DSB();
ccsidr = SCB->CCSIDR;
@@ -2252,8 +2423,8 @@ __STATIC_INLINE void SCB_CleanDCache (void)
#if defined ( __CC_ARM )
__schedule_barrier();
#endif
- } while (ways--);
- } while(sets--);
+ } while (ways-- != 0U);
+ } while(sets-- != 0U);
__DSB();
__ISB();
@@ -2265,14 +2436,14 @@ __STATIC_INLINE void SCB_CleanDCache (void)
\brief Clean & Invalidate D-Cache
\details Cleans and Invalidates D-Cache
*/
-__STATIC_INLINE void SCB_CleanInvalidateDCache (void)
+__STATIC_FORCEINLINE void SCB_CleanInvalidateDCache (void)
{
- #if (__DCACHE_PRESENT == 1U)
+ #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
uint32_t ccsidr;
uint32_t sets;
uint32_t ways;
- SCB->CSSELR = (0U << 1U) | 0U; /* Level 1 data cache */
+ SCB->CSSELR = 0U; /* select Level 1 data cache */
__DSB();
ccsidr = SCB->CCSIDR;
@@ -2287,8 +2458,8 @@ __STATIC_INLINE void SCB_CleanInvalidateDCache (void)
#if defined ( __CC_ARM )
__schedule_barrier();
#endif
- } while (ways--);
- } while(sets--);
+ } while (ways-- != 0U);
+ } while(sets-- != 0U);
__DSB();
__ISB();
@@ -2298,27 +2469,30 @@ __STATIC_INLINE void SCB_CleanInvalidateDCache (void)
/**
\brief D-Cache Invalidate by address
- \details Invalidates D-Cache for the given address
- \param[in] addr address (aligned to 32-byte boundary)
+ \details Invalidates D-Cache for the given address.
+ D-Cache is invalidated starting from a 32 byte aligned address in 32 byte granularity.
+ D-Cache memory blocks which are part of given address + given size are invalidated.
+ \param[in] addr address
\param[in] dsize size of memory block (in number of bytes)
*/
-__STATIC_INLINE void SCB_InvalidateDCache_by_Addr (uint32_t *addr, int32_t dsize)
+__STATIC_FORCEINLINE void SCB_InvalidateDCache_by_Addr (void *addr, int32_t dsize)
{
- #if (__DCACHE_PRESENT == 1U)
- int32_t op_size = dsize;
- uint32_t op_addr = (uint32_t)addr;
- int32_t linesize = 32U; /* in Cortex-M7 size of cache line is fixed to 8 words (32 bytes) */
+ #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
+ if ( dsize > 0 ) {
+ int32_t op_size = dsize + (((uint32_t)addr) & (__SCB_DCACHE_LINE_SIZE - 1U));
+ uint32_t op_addr = (uint32_t)addr /* & ~(__SCB_DCACHE_LINE_SIZE - 1U) */;
+
+ __DSB();
- __DSB();
+ do {
+ SCB->DCIMVAC = op_addr; /* register accepts only 32byte aligned values, only bits 31..5 are valid */
+ op_addr += __SCB_DCACHE_LINE_SIZE;
+ op_size -= __SCB_DCACHE_LINE_SIZE;
+ } while ( op_size > 0 );
- while (op_size > 0) {
- SCB->DCIMVAC = op_addr;
- op_addr += linesize;
- op_size -= linesize;
+ __DSB();
+ __ISB();
}
-
- __DSB();
- __ISB();
#endif
}
@@ -2326,26 +2500,29 @@ __STATIC_INLINE void SCB_InvalidateDCache_by_Addr (uint32_t *addr, int32_t dsize
/**
\brief D-Cache Clean by address
\details Cleans D-Cache for the given address
- \param[in] addr address (aligned to 32-byte boundary)
+ D-Cache is cleaned starting from a 32 byte aligned address in 32 byte granularity.
+ D-Cache memory blocks which are part of given address + given size are cleaned.
+ \param[in] addr address
\param[in] dsize size of memory block (in number of bytes)
*/
-__STATIC_INLINE void SCB_CleanDCache_by_Addr (uint32_t *addr, int32_t dsize)
+__STATIC_FORCEINLINE void SCB_CleanDCache_by_Addr (uint32_t *addr, int32_t dsize)
{
- #if (__DCACHE_PRESENT == 1)
- int32_t op_size = dsize;
- uint32_t op_addr = (uint32_t) addr;
- int32_t linesize = 32U; /* in Cortex-M7 size of cache line is fixed to 8 words (32 bytes) */
+ #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
+ if ( dsize > 0 ) {
+ int32_t op_size = dsize + (((uint32_t)addr) & (__SCB_DCACHE_LINE_SIZE - 1U));
+ uint32_t op_addr = (uint32_t)addr /* & ~(__SCB_DCACHE_LINE_SIZE - 1U) */;
+
+ __DSB();
- __DSB();
+ do {
+ SCB->DCCMVAC = op_addr; /* register accepts only 32byte aligned values, only bits 31..5 are valid */
+ op_addr += __SCB_DCACHE_LINE_SIZE;
+ op_size -= __SCB_DCACHE_LINE_SIZE;
+ } while ( op_size > 0 );
- while (op_size > 0) {
- SCB->DCCMVAC = op_addr;
- op_addr += linesize;
- op_size -= linesize;
+ __DSB();
+ __ISB();
}
-
- __DSB();
- __ISB();
#endif
}
@@ -2353,30 +2530,32 @@ __STATIC_INLINE void SCB_CleanDCache_by_Addr (uint32_t *addr, int32_t dsize)
/**
\brief D-Cache Clean and Invalidate by address
\details Cleans and invalidates D_Cache for the given address
+ D-Cache is cleaned and invalidated starting from a 32 byte aligned address in 32 byte granularity.
+ D-Cache memory blocks which are part of given address + given size are cleaned and invalidated.
\param[in] addr address (aligned to 32-byte boundary)
\param[in] dsize size of memory block (in number of bytes)
*/
-__STATIC_INLINE void SCB_CleanInvalidateDCache_by_Addr (uint32_t *addr, int32_t dsize)
+__STATIC_FORCEINLINE void SCB_CleanInvalidateDCache_by_Addr (uint32_t *addr, int32_t dsize)
{
- #if (__DCACHE_PRESENT == 1U)
- int32_t op_size = dsize;
- uint32_t op_addr = (uint32_t) addr;
- int32_t linesize = 32U; /* in Cortex-M7 size of cache line is fixed to 8 words (32 bytes) */
+ #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
+ if ( dsize > 0 ) {
+ int32_t op_size = dsize + (((uint32_t)addr) & (__SCB_DCACHE_LINE_SIZE - 1U));
+ uint32_t op_addr = (uint32_t)addr /* & ~(__SCB_DCACHE_LINE_SIZE - 1U) */;
+
+ __DSB();
- __DSB();
+ do {
+ SCB->DCCIMVAC = op_addr; /* register accepts only 32byte aligned values, only bits 31..5 are valid */
+ op_addr += __SCB_DCACHE_LINE_SIZE;
+ op_size -= __SCB_DCACHE_LINE_SIZE;
+ } while ( op_size > 0 );
- while (op_size > 0) {
- SCB->DCCIMVAC = op_addr;
- op_addr += linesize;
- op_size -= linesize;
+ __DSB();
+ __ISB();
}
-
- __DSB();
- __ISB();
#endif
}
-
/*@} end of CMSIS_Core_CacheFunctions */
@@ -2389,7 +2568,7 @@ __STATIC_INLINE void SCB_CleanInvalidateDCache_by_Addr (uint32_t *addr, int32_t
@{
*/
-#if (__Vendor_SysTickConfig == 0U)
+#if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U)
/**
\brief System Tick Configuration
@@ -2432,8 +2611,8 @@ __STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)
@{
*/
-extern volatile int32_t ITM_RxBuffer; /*!< External variable to receive characters. */
-#define ITM_RXBUFFER_EMPTY 0x5AA55AA5U /*!< Value identifying \ref ITM_RxBuffer is ready for next character. */
+extern volatile int32_t ITM_RxBuffer; /*!< External variable to receive characters. */
+#define ITM_RXBUFFER_EMPTY ((int32_t)0x5AA55AA5U) /*!< Value identifying \ref ITM_RxBuffer is ready for next character. */
/**
diff --git a/lib/cmsis/inc/core_cmFunc.h b/lib/cmsis/inc/core_cmFunc.h
deleted file mode 100644
index 652a48af07..0000000000
--- a/lib/cmsis/inc/core_cmFunc.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/**************************************************************************//**
- * @file core_cmFunc.h
- * @brief CMSIS Cortex-M Core Function Access Header File
- * @version V4.30
- * @date 20. October 2015
- ******************************************************************************/
-/* Copyright (c) 2009 - 2015 ARM LIMITED
-
- All rights reserved.
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are met:
- - Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- - Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
- - Neither the name of ARM nor the names of its contributors may be used
- to endorse or promote products derived from this software without
- specific prior written permission.
- *
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE
- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- POSSIBILITY OF SUCH DAMAGE.
- ---------------------------------------------------------------------------*/
-
-
-#if defined ( __ICCARM__ )
- #pragma system_include /* treat file as system include file for MISRA check */
-#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
- #pragma clang system_header /* treat file as system include file */
-#endif
-
-#ifndef __CORE_CMFUNC_H
-#define __CORE_CMFUNC_H
-
-
-/* ########################### Core Function Access ########################### */
-/** \ingroup CMSIS_Core_FunctionInterface
- \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions
- @{
-*/
-
-/*------------------ RealView Compiler -----------------*/
-#if defined ( __CC_ARM )
- #include "cmsis_armcc.h"
-
-/*------------------ ARM Compiler V6 -------------------*/
-#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
- #include "cmsis_armcc_V6.h"
-
-/*------------------ GNU Compiler ----------------------*/
-#elif defined ( __GNUC__ )
- #include "cmsis_gcc.h"
-
-/*------------------ ICC Compiler ----------------------*/
-#elif defined ( __ICCARM__ )
- #include
-
-/*------------------ TI CCS Compiler -------------------*/
-#elif defined ( __TMS470__ )
- #include
-
-/*------------------ TASKING Compiler ------------------*/
-#elif defined ( __TASKING__ )
- /*
- * The CMSIS functions have been implemented as intrinsics in the compiler.
- * Please use "carm -?i" to get an up to date list of all intrinsics,
- * Including the CMSIS ones.
- */
-
-/*------------------ COSMIC Compiler -------------------*/
-#elif defined ( __CSMC__ )
- #include
-
-#endif
-
-/*@} end of CMSIS_Core_RegAccFunctions */
-
-#endif /* __CORE_CMFUNC_H */
diff --git a/lib/cmsis/inc/core_cmInstr.h b/lib/cmsis/inc/core_cmInstr.h
deleted file mode 100644
index f474b0e6f3..0000000000
--- a/lib/cmsis/inc/core_cmInstr.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/**************************************************************************//**
- * @file core_cmInstr.h
- * @brief CMSIS Cortex-M Core Instruction Access Header File
- * @version V4.30
- * @date 20. October 2015
- ******************************************************************************/
-/* Copyright (c) 2009 - 2015 ARM LIMITED
-
- All rights reserved.
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are met:
- - Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- - Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
- - Neither the name of ARM nor the names of its contributors may be used
- to endorse or promote products derived from this software without
- specific prior written permission.
- *
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE
- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- POSSIBILITY OF SUCH DAMAGE.
- ---------------------------------------------------------------------------*/
-
-
-#if defined ( __ICCARM__ )
- #pragma system_include /* treat file as system include file for MISRA check */
-#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
- #pragma clang system_header /* treat file as system include file */
-#endif
-
-#ifndef __CORE_CMINSTR_H
-#define __CORE_CMINSTR_H
-
-
-/* ########################## Core Instruction Access ######################### */
-/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface
- Access to dedicated instructions
- @{
-*/
-
-/*------------------ RealView Compiler -----------------*/
-#if defined ( __CC_ARM )
- #include "cmsis_armcc.h"
-
-/*------------------ ARM Compiler V6 -------------------*/
-#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
- #include "cmsis_armcc_V6.h"
-
-/*------------------ GNU Compiler ----------------------*/
-#elif defined ( __GNUC__ )
- #include "cmsis_gcc.h"
-
-/*------------------ ICC Compiler ----------------------*/
-#elif defined ( __ICCARM__ )
- #include
-
-/*------------------ TI CCS Compiler -------------------*/
-#elif defined ( __TMS470__ )
- #include
-
-/*------------------ TASKING Compiler ------------------*/
-#elif defined ( __TASKING__ )
- /*
- * The CMSIS functions have been implemented as intrinsics in the compiler.
- * Please use "carm -?i" to get an up to date list of all intrinsics,
- * Including the CMSIS ones.
- */
-
-/*------------------ COSMIC Compiler -------------------*/
-#elif defined ( __CSMC__ )
- #include
-
-#endif
-
-/*@}*/ /* end of group CMSIS_Core_InstructionInterface */
-
-#endif /* __CORE_CMINSTR_H */
diff --git a/lib/cmsis/inc/core_cmSimd.h b/lib/cmsis/inc/core_cmSimd.h
deleted file mode 100644
index 66bf5c2a72..0000000000
--- a/lib/cmsis/inc/core_cmSimd.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/**************************************************************************//**
- * @file core_cmSimd.h
- * @brief CMSIS Cortex-M SIMD Header File
- * @version V4.30
- * @date 20. October 2015
- ******************************************************************************/
-/* Copyright (c) 2009 - 2015 ARM LIMITED
-
- All rights reserved.
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are met:
- - Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- - Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
- - Neither the name of ARM nor the names of its contributors may be used
- to endorse or promote products derived from this software without
- specific prior written permission.
- *
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE
- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- POSSIBILITY OF SUCH DAMAGE.
- ---------------------------------------------------------------------------*/
-
-
-#if defined ( __ICCARM__ )
- #pragma system_include /* treat file as system include file for MISRA check */
-#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
- #pragma clang system_header /* treat file as system include file */
-#endif
-
-#ifndef __CORE_CMSIMD_H
-#define __CORE_CMSIMD_H
-
-#ifdef __cplusplus
- extern "C" {
-#endif
-
-
-/* ################### Compiler specific Intrinsics ########################### */
-/** \defgroup CMSIS_SIMD_intrinsics CMSIS SIMD Intrinsics
- Access to dedicated SIMD instructions
- @{
-*/
-
-/*------------------ RealView Compiler -----------------*/
-#if defined ( __CC_ARM )
- #include "cmsis_armcc.h"
-
-/*------------------ ARM Compiler V6 -------------------*/
-#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
- #include "cmsis_armcc_V6.h"
-
-/*------------------ GNU Compiler ----------------------*/
-#elif defined ( __GNUC__ )
- #include "cmsis_gcc.h"
-
-/*------------------ ICC Compiler ----------------------*/
-#elif defined ( __ICCARM__ )
- #include
-
-/*------------------ TI CCS Compiler -------------------*/
-#elif defined ( __TMS470__ )
- #include
-
-/*------------------ TASKING Compiler ------------------*/
-#elif defined ( __TASKING__ )
- /*
- * The CMSIS functions have been implemented as intrinsics in the compiler.
- * Please use "carm -?i" to get an up to date list of all intrinsics,
- * Including the CMSIS ones.
- */
-
-/*------------------ COSMIC Compiler -------------------*/
-#elif defined ( __CSMC__ )
- #include
-
-#endif
-
-/*@} end of group CMSIS_SIMD_intrinsics */
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __CORE_CMSIMD_H */
diff --git a/lib/cmsis/inc/core_sc000.h b/lib/cmsis/inc/core_sc000.h
index 514dbd81b9..389535a7cf 100644
--- a/lib/cmsis/inc/core_sc000.h
+++ b/lib/cmsis/inc/core_sc000.h
@@ -1,40 +1,30 @@
/**************************************************************************//**
* @file core_sc000.h
* @brief CMSIS SC000 Core Peripheral Access Layer Header File
- * @version V4.30
- * @date 20. October 2015
+ * @version V5.0.6
+ * @date 12. November 2018
******************************************************************************/
-/* Copyright (c) 2009 - 2015 ARM LIMITED
-
- All rights reserved.
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are met:
- - Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- - Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
- - Neither the name of ARM nor the names of its contributors may be used
- to endorse or promote products derived from this software without
- specific prior written permission.
- *
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE
- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- POSSIBILITY OF SUCH DAMAGE.
- ---------------------------------------------------------------------------*/
-
+/*
+ * Copyright (c) 2009-2018 Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
#if defined ( __ICCARM__ )
- #pragma system_include /* treat file as system include file for MISRA check */
-#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
+ #pragma system_include /* treat file as system include file for MISRA check */
+#elif defined (__clang__)
#pragma clang system_header /* treat file as system include file */
#endif
@@ -70,53 +60,15 @@
@{
*/
+#include "cmsis_version.h"
+
/* CMSIS SC000 definitions */
-#define __SC000_CMSIS_VERSION_MAIN (0x04U) /*!< [31:16] CMSIS HAL main version */
-#define __SC000_CMSIS_VERSION_SUB (0x1EU) /*!< [15:0] CMSIS HAL sub version */
+#define __SC000_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */
+#define __SC000_CMSIS_VERSION_SUB (__CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */
#define __SC000_CMSIS_VERSION ((__SC000_CMSIS_VERSION_MAIN << 16U) | \
- __SC000_CMSIS_VERSION_SUB ) /*!< CMSIS HAL version number */
-
-#define __CORTEX_SC (000U) /*!< Cortex secure core */
-
-
-#if defined ( __CC_ARM )
- #define __ASM __asm /*!< asm keyword for ARM Compiler */
- #define __INLINE __inline /*!< inline keyword for ARM Compiler */
- #define __STATIC_INLINE static __inline
-
-#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
- #define __ASM __asm /*!< asm keyword for ARM Compiler */
- #define __INLINE __inline /*!< inline keyword for ARM Compiler */
- #define __STATIC_INLINE static __inline
-
-#elif defined ( __GNUC__ )
- #define __ASM __asm /*!< asm keyword for GNU Compiler */
- #define __INLINE inline /*!< inline keyword for GNU Compiler */
- #define __STATIC_INLINE static inline
-
-#elif defined ( __ICCARM__ )
- #define __ASM __asm /*!< asm keyword for IAR Compiler */
- #define __INLINE inline /*!< inline keyword for IAR Compiler. Only available in High optimization mode! */
- #define __STATIC_INLINE static inline
+ __SC000_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */
-#elif defined ( __TMS470__ )
- #define __ASM __asm /*!< asm keyword for TI CCS Compiler */
- #define __STATIC_INLINE static inline
-
-#elif defined ( __TASKING__ )
- #define __ASM __asm /*!< asm keyword for TASKING Compiler */
- #define __INLINE inline /*!< inline keyword for TASKING Compiler */
- #define __STATIC_INLINE static inline
-
-#elif defined ( __CSMC__ )
- #define __packed
- #define __ASM _asm /*!< asm keyword for COSMIC Compiler */
- #define __INLINE inline /*!< inline keyword for COSMIC Compiler. Use -pc99 on compile line */
- #define __STATIC_INLINE static inline
-
-#else
- #error Unknown compiler
-#endif
+#define __CORTEX_SC (000U) /*!< Cortex secure core */
/** __FPU_USED indicates whether an FPU is used or not.
This core does not support an FPU at all
@@ -128,8 +80,8 @@
#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
#endif
-#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
- #if defined __ARM_PCS_VFP
+#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
+ #if defined __ARM_FP
#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
#endif
@@ -143,7 +95,7 @@
#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
#endif
-#elif defined ( __TMS470__ )
+#elif defined ( __TI_ARM__ )
#if defined __TI_VFP_SUPPORT__
#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
#endif
@@ -160,8 +112,8 @@
#endif
-#include "core_cmInstr.h" /* Core Instruction Access */
-#include "core_cmFunc.h" /* Core Function Access */
+#include "cmsis_compiler.h" /* CMSIS compiler specific defines */
+
#ifdef __cplusplus
}
@@ -569,7 +521,7 @@ typedef struct
/*@} end of group CMSIS_SysTick */
-#if (__MPU_PRESENT == 1U)
+#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U)
/**
\ingroup CMSIS_core_register
\defgroup CMSIS_MPU Memory Protection Unit (MPU)
@@ -678,18 +630,18 @@ typedef struct
/**
\brief Mask and shift a bit field value for use in a register bit range.
\param[in] field Name of the register bit field.
- \param[in] value Value of the bit field.
+ \param[in] value Value of the bit field. This parameter is interpreted as an uint32_t type.
\return Masked and shifted value.
*/
-#define _VAL2FLD(field, value) ((value << field ## _Pos) & field ## _Msk)
+#define _VAL2FLD(field, value) (((uint32_t)(value) << field ## _Pos) & field ## _Msk)
/**
\brief Mask and shift a register value to extract a bit filed value.
\param[in] field Name of the register bit field.
- \param[in] value Value of register.
+ \param[in] value Value of register. This parameter is interpreted as an uint32_t type.
\return Masked and shifted bit field value.
*/
-#define _FLD2VAL(field, value) ((value & field ## _Msk) >> field ## _Pos)
+#define _FLD2VAL(field, value) (((uint32_t)(value) & field ## _Msk) >> field ## _Pos)
/*@} end of group CMSIS_core_bitfield */
@@ -701,7 +653,7 @@ typedef struct
@{
*/
-/* Memory mapping of SC000 Hardware */
+/* Memory mapping of Core Hardware */
#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */
#define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */
#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */
@@ -712,7 +664,7 @@ typedef struct
#define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */
#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */
-#if (__MPU_PRESENT == 1U)
+#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U)
#define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */
#define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */
#endif
@@ -742,7 +694,46 @@ typedef struct
@{
*/
-/* Interrupt Priorities are WORD accessible only under ARMv6M */
+#ifdef CMSIS_NVIC_VIRTUAL
+ #ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE
+ #define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h"
+ #endif
+ #include CMSIS_NVIC_VIRTUAL_HEADER_FILE
+#else
+/*#define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping not available for SC000 */
+/*#define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping not available for SC000 */
+ #define NVIC_EnableIRQ __NVIC_EnableIRQ
+ #define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ
+ #define NVIC_DisableIRQ __NVIC_DisableIRQ
+ #define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ
+ #define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ
+ #define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ
+/*#define NVIC_GetActive __NVIC_GetActive not available for SC000 */
+ #define NVIC_SetPriority __NVIC_SetPriority
+ #define NVIC_GetPriority __NVIC_GetPriority
+ #define NVIC_SystemReset __NVIC_SystemReset
+#endif /* CMSIS_NVIC_VIRTUAL */
+
+#ifdef CMSIS_VECTAB_VIRTUAL
+ #ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE
+ #define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h"
+ #endif
+ #include CMSIS_VECTAB_VIRTUAL_HEADER_FILE
+#else
+ #define NVIC_SetVector __NVIC_SetVector
+ #define NVIC_GetVector __NVIC_GetVector
+#endif /* (CMSIS_VECTAB_VIRTUAL) */
+
+#define NVIC_USER_IRQ_OFFSET 16
+
+
+/* The following EXC_RETURN values are saved the LR on exception entry */
+#define EXC_RETURN_HANDLER (0xFFFFFFF1UL) /* return to Handler mode, uses MSP after return */
+#define EXC_RETURN_THREAD_MSP (0xFFFFFFF9UL) /* return to Thread mode, uses MSP after return */
+#define EXC_RETURN_THREAD_PSP (0xFFFFFFFDUL) /* return to Thread mode, uses PSP after return */
+
+
+/* Interrupt Priorities are WORD accessible only under Armv6-M */
/* The following MACROS handle generation of the register offset and byte masks */
#define _BIT_SHIFT(IRQn) ( ((((uint32_t)(int32_t)(IRQn)) ) & 0x03UL) * 8UL)
#define _SHP_IDX(IRQn) ( (((((uint32_t)(int32_t)(IRQn)) & 0x0FUL)-8UL) >> 2UL) )
@@ -750,79 +741,128 @@ typedef struct
/**
- \brief Enable External Interrupt
- \details Enables a device-specific interrupt in the NVIC interrupt controller.
- \param [in] IRQn External interrupt number. Value cannot be negative.
+ \brief Enable Interrupt
+ \details Enables a device specific interrupt in the NVIC interrupt controller.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
*/
-__STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn)
+__STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn)
{
- NVIC->ISER[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL));
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ISER[0U] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
}
/**
- \brief Disable External Interrupt
- \details Disables a device-specific interrupt in the NVIC interrupt controller.
- \param [in] IRQn External interrupt number. Value cannot be negative.
+ \brief Get Interrupt Enable status
+ \details Returns a device specific interrupt enable status from the NVIC interrupt controller.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 Interrupt is not enabled.
+ \return 1 Interrupt is enabled.
+ \note IRQn must not be negative.
*/
-__STATIC_INLINE void NVIC_DisableIRQ(IRQn_Type IRQn)
+__STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn)
{
- NVIC->ICER[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL));
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC->ISER[0U] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Disable Interrupt
+ \details Disables a device specific interrupt in the NVIC interrupt controller.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ICER[0U] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ __DSB();
+ __ISB();
+ }
}
/**
\brief Get Pending Interrupt
- \details Reads the pending register in the NVIC and returns the pending bit for the specified interrupt.
- \param [in] IRQn Interrupt number.
+ \details Reads the NVIC pending register and returns the pending bit for the specified device specific interrupt.
+ \param [in] IRQn Device specific interrupt number.
\return 0 Interrupt status is not pending.
\return 1 Interrupt status is pending.
+ \note IRQn must not be negative.
*/
-__STATIC_INLINE uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn)
+__STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn)
{
- return((uint32_t)(((NVIC->ISPR[0U] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC->ISPR[0U] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
}
/**
\brief Set Pending Interrupt
- \details Sets the pending bit of an external interrupt.
- \param [in] IRQn Interrupt number. Value cannot be negative.
+ \details Sets the pending bit of a device specific interrupt in the NVIC pending register.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
*/
-__STATIC_INLINE void NVIC_SetPendingIRQ(IRQn_Type IRQn)
+__STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn)
{
- NVIC->ISPR[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL));
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ISPR[0U] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
}
/**
\brief Clear Pending Interrupt
- \details Clears the pending bit of an external interrupt.
- \param [in] IRQn External interrupt number. Value cannot be negative.
+ \details Clears the pending bit of a device specific interrupt in the NVIC pending register.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
*/
-__STATIC_INLINE void NVIC_ClearPendingIRQ(IRQn_Type IRQn)
+__STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn)
{
- NVIC->ICPR[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL));
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ICPR[0U] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
}
/**
\brief Set Interrupt Priority
- \details Sets the priority of an interrupt.
- \note The priority cannot be set for every core interrupt.
+ \details Sets the priority of a device specific interrupt or a processor exception.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
\param [in] IRQn Interrupt number.
\param [in] priority Priority to set.
+ \note The priority cannot be set for every processor exception.
*/
-__STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
+__STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
{
- if ((int32_t)(IRQn) < 0)
+ if ((int32_t)(IRQn) >= 0)
{
- SCB->SHP[_SHP_IDX(IRQn)] = ((uint32_t)(SCB->SHP[_SHP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) |
+ NVIC->IP[_IP_IDX(IRQn)] = ((uint32_t)(NVIC->IP[_IP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) |
(((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn)));
}
else
{
- NVIC->IP[_IP_IDX(IRQn)] = ((uint32_t)(NVIC->IP[_IP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) |
+ SCB->SHP[_SHP_IDX(IRQn)] = ((uint32_t)(SCB->SHP[_SHP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) |
(((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn)));
}
}
@@ -830,32 +870,63 @@ __STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
/**
\brief Get Interrupt Priority
- \details Reads the priority of an interrupt.
- The interrupt number can be positive to specify an external (device specific) interrupt,
- or negative to specify an internal (core) interrupt.
+ \details Reads the priority of a device specific interrupt or a processor exception.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
\param [in] IRQn Interrupt number.
\return Interrupt Priority.
Value is aligned automatically to the implemented priority bits of the microcontroller.
*/
-__STATIC_INLINE uint32_t NVIC_GetPriority(IRQn_Type IRQn)
+__STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn)
{
- if ((int32_t)(IRQn) < 0)
+ if ((int32_t)(IRQn) >= 0)
{
- return((uint32_t)(((SCB->SHP[_SHP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS)));
+ return((uint32_t)(((NVIC->IP[ _IP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS)));
}
else
{
- return((uint32_t)(((NVIC->IP[ _IP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS)));
+ return((uint32_t)(((SCB->SHP[_SHP_IDX(IRQn)] >> _BIT_SHIFT(IRQn) ) & (uint32_t)0xFFUL) >> (8U - __NVIC_PRIO_BITS)));
}
}
+/**
+ \brief Set Interrupt Vector
+ \details Sets an interrupt vector in SRAM based interrupt vector table.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ VTOR must been relocated to SRAM before.
+ \param [in] IRQn Interrupt number
+ \param [in] vector Address of interrupt handler function
+ */
+__STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector)
+{
+ uint32_t *vectors = (uint32_t *)SCB->VTOR;
+ vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET] = vector;
+}
+
+
+/**
+ \brief Get Interrupt Vector
+ \details Reads an interrupt vector from interrupt vector table.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ \param [in] IRQn Interrupt number.
+ \return Address of interrupt handler function
+ */
+__STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn)
+{
+ uint32_t *vectors = (uint32_t *)SCB->VTOR;
+ return vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET];
+}
+
+
/**
\brief System Reset
\details Initiates a system reset request to reset the MCU.
*/
-__STATIC_INLINE void NVIC_SystemReset(void)
+__NO_RETURN __STATIC_INLINE void __NVIC_SystemReset(void)
{
__DSB(); /* Ensure all outstanding memory accesses included
buffered write are completed before reset */
@@ -872,6 +943,31 @@ __STATIC_INLINE void NVIC_SystemReset(void)
/*@} end of CMSIS_Core_NVICFunctions */
+/* ########################## FPU functions #################################### */
+/**
+ \ingroup CMSIS_Core_FunctionInterface
+ \defgroup CMSIS_Core_FpuFunctions FPU Functions
+ \brief Function that provides FPU type.
+ @{
+ */
+
+/**
+ \brief get FPU type
+ \details returns the FPU type
+ \returns
+ - \b 0: No FPU
+ - \b 1: Single precision FPU
+ - \b 2: Double + Single precision FPU
+ */
+__STATIC_INLINE uint32_t SCB_GetFPUType(void)
+{
+ return 0U; /* No FPU */
+}
+
+
+/*@} end of CMSIS_Core_FpuFunctions */
+
+
/* ################################## SysTick function ############################################ */
/**
@@ -881,7 +977,7 @@ __STATIC_INLINE void NVIC_SystemReset(void)
@{
*/
-#if (__Vendor_SysTickConfig == 0U)
+#if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U)
/**
\brief System Tick Configuration
diff --git a/lib/cmsis/inc/core_sc300.h b/lib/cmsis/inc/core_sc300.h
index 8bd18aa318..5478ea74a5 100644
--- a/lib/cmsis/inc/core_sc300.h
+++ b/lib/cmsis/inc/core_sc300.h
@@ -1,40 +1,30 @@
/**************************************************************************//**
* @file core_sc300.h
* @brief CMSIS SC300 Core Peripheral Access Layer Header File
- * @version V4.30
- * @date 20. October 2015
+ * @version V5.0.7
+ * @date 12. November 2018
******************************************************************************/
-/* Copyright (c) 2009 - 2015 ARM LIMITED
-
- All rights reserved.
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are met:
- - Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- - Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
- - Neither the name of ARM nor the names of its contributors may be used
- to endorse or promote products derived from this software without
- specific prior written permission.
- *
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE
- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- POSSIBILITY OF SUCH DAMAGE.
- ---------------------------------------------------------------------------*/
-
+/*
+ * Copyright (c) 2009-2018 Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
#if defined ( __ICCARM__ )
- #pragma system_include /* treat file as system include file for MISRA check */
-#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
+ #pragma system_include /* treat file as system include file for MISRA check */
+#elif defined (__clang__)
#pragma clang system_header /* treat file as system include file */
#endif
@@ -70,53 +60,15 @@
@{
*/
+#include "cmsis_version.h"
+
/* CMSIS SC300 definitions */
-#define __SC300_CMSIS_VERSION_MAIN (0x04U) /*!< [31:16] CMSIS HAL main version */
-#define __SC300_CMSIS_VERSION_SUB (0x1EU) /*!< [15:0] CMSIS HAL sub version */
+#define __SC300_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */
+#define __SC300_CMSIS_VERSION_SUB (__CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */
#define __SC300_CMSIS_VERSION ((__SC300_CMSIS_VERSION_MAIN << 16U) | \
- __SC300_CMSIS_VERSION_SUB ) /*!< CMSIS HAL version number */
-
-#define __CORTEX_SC (300U) /*!< Cortex secure core */
-
-
-#if defined ( __CC_ARM )
- #define __ASM __asm /*!< asm keyword for ARM Compiler */
- #define __INLINE __inline /*!< inline keyword for ARM Compiler */
- #define __STATIC_INLINE static __inline
-
-#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
- #define __ASM __asm /*!< asm keyword for ARM Compiler */
- #define __INLINE __inline /*!< inline keyword for ARM Compiler */
- #define __STATIC_INLINE static __inline
-
-#elif defined ( __GNUC__ )
- #define __ASM __asm /*!< asm keyword for GNU Compiler */
- #define __INLINE inline /*!< inline keyword for GNU Compiler */
- #define __STATIC_INLINE static inline
-
-#elif defined ( __ICCARM__ )
- #define __ASM __asm /*!< asm keyword for IAR Compiler */
- #define __INLINE inline /*!< inline keyword for IAR Compiler. Only available in High optimization mode! */
- #define __STATIC_INLINE static inline
-
-#elif defined ( __TMS470__ )
- #define __ASM __asm /*!< asm keyword for TI CCS Compiler */
- #define __STATIC_INLINE static inline
-
-#elif defined ( __TASKING__ )
- #define __ASM __asm /*!< asm keyword for TASKING Compiler */
- #define __INLINE inline /*!< inline keyword for TASKING Compiler */
- #define __STATIC_INLINE static inline
+ __SC300_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */
-#elif defined ( __CSMC__ )
- #define __packed
- #define __ASM _asm /*!< asm keyword for COSMIC Compiler */
- #define __INLINE inline /*!< inline keyword for COSMIC Compiler. Use -pc99 on compile line */
- #define __STATIC_INLINE static inline
-
-#else
- #error Unknown compiler
-#endif
+#define __CORTEX_SC (300U) /*!< Cortex secure core */
/** __FPU_USED indicates whether an FPU is used or not.
This core does not support an FPU at all
@@ -128,8 +80,8 @@
#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
#endif
-#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
- #if defined __ARM_PCS_VFP
+#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
+ #if defined __ARM_FP
#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
#endif
@@ -143,7 +95,7 @@
#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
#endif
-#elif defined ( __TMS470__ )
+#elif defined ( __TI_ARM__ )
#if defined __TI_VFP_SUPPORT__
#error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
#endif
@@ -160,8 +112,8 @@
#endif
-#include "core_cmInstr.h" /* Core Instruction Access */
-#include "core_cmFunc.h" /* Core Function Access */
+#include "cmsis_compiler.h" /* CMSIS compiler specific defines */
+
#ifdef __cplusplus
}
@@ -191,7 +143,7 @@
#endif
#ifndef __NVIC_PRIO_BITS
- #define __NVIC_PRIO_BITS 4U
+ #define __NVIC_PRIO_BITS 3U
#warning "__NVIC_PRIO_BITS not defined in device header file; using default!"
#endif
@@ -308,9 +260,11 @@ typedef union
struct
{
uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */
- uint32_t _reserved0:15; /*!< bit: 9..23 Reserved */
- uint32_t T:1; /*!< bit: 24 Thumb bit (read 0) */
- uint32_t IT:2; /*!< bit: 25..26 saved IT state (read 0) */
+ uint32_t _reserved0:1; /*!< bit: 9 Reserved */
+ uint32_t ICI_IT_1:6; /*!< bit: 10..15 ICI/IT part 1 */
+ uint32_t _reserved1:8; /*!< bit: 16..23 Reserved */
+ uint32_t T:1; /*!< bit: 24 Thumb bit */
+ uint32_t ICI_IT_2:2; /*!< bit: 25..26 ICI/IT part 2 */
uint32_t Q:1; /*!< bit: 27 Saturation condition flag */
uint32_t V:1; /*!< bit: 28 Overflow condition code flag */
uint32_t C:1; /*!< bit: 29 Carry condition code flag */
@@ -336,12 +290,15 @@ typedef union
#define xPSR_Q_Pos 27U /*!< xPSR: Q Position */
#define xPSR_Q_Msk (1UL << xPSR_Q_Pos) /*!< xPSR: Q Mask */
-#define xPSR_IT_Pos 25U /*!< xPSR: IT Position */
-#define xPSR_IT_Msk (3UL << xPSR_IT_Pos) /*!< xPSR: IT Mask */
+#define xPSR_ICI_IT_2_Pos 25U /*!< xPSR: ICI/IT part 2 Position */
+#define xPSR_ICI_IT_2_Msk (3UL << xPSR_ICI_IT_2_Pos) /*!< xPSR: ICI/IT part 2 Mask */
#define xPSR_T_Pos 24U /*!< xPSR: T Position */
#define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */
+#define xPSR_ICI_IT_1_Pos 10U /*!< xPSR: ICI/IT part 1 Position */
+#define xPSR_ICI_IT_1_Msk (0x3FUL << xPSR_ICI_IT_1_Pos) /*!< xPSR: ICI/IT part 1 Mask */
+
#define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */
#define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */
@@ -599,6 +556,60 @@ typedef struct
#define SCB_CFSR_MEMFAULTSR_Pos 0U /*!< SCB CFSR: Memory Manage Fault Status Register Position */
#define SCB_CFSR_MEMFAULTSR_Msk (0xFFUL /*<< SCB_CFSR_MEMFAULTSR_Pos*/) /*!< SCB CFSR: Memory Manage Fault Status Register Mask */
+/* MemManage Fault Status Register (part of SCB Configurable Fault Status Register) */
+#define SCB_CFSR_MMARVALID_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 7U) /*!< SCB CFSR (MMFSR): MMARVALID Position */
+#define SCB_CFSR_MMARVALID_Msk (1UL << SCB_CFSR_MMARVALID_Pos) /*!< SCB CFSR (MMFSR): MMARVALID Mask */
+
+#define SCB_CFSR_MSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 4U) /*!< SCB CFSR (MMFSR): MSTKERR Position */
+#define SCB_CFSR_MSTKERR_Msk (1UL << SCB_CFSR_MSTKERR_Pos) /*!< SCB CFSR (MMFSR): MSTKERR Mask */
+
+#define SCB_CFSR_MUNSTKERR_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 3U) /*!< SCB CFSR (MMFSR): MUNSTKERR Position */
+#define SCB_CFSR_MUNSTKERR_Msk (1UL << SCB_CFSR_MUNSTKERR_Pos) /*!< SCB CFSR (MMFSR): MUNSTKERR Mask */
+
+#define SCB_CFSR_DACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 1U) /*!< SCB CFSR (MMFSR): DACCVIOL Position */
+#define SCB_CFSR_DACCVIOL_Msk (1UL << SCB_CFSR_DACCVIOL_Pos) /*!< SCB CFSR (MMFSR): DACCVIOL Mask */
+
+#define SCB_CFSR_IACCVIOL_Pos (SCB_SHCSR_MEMFAULTACT_Pos + 0U) /*!< SCB CFSR (MMFSR): IACCVIOL Position */
+#define SCB_CFSR_IACCVIOL_Msk (1UL /*<< SCB_CFSR_IACCVIOL_Pos*/) /*!< SCB CFSR (MMFSR): IACCVIOL Mask */
+
+/* BusFault Status Register (part of SCB Configurable Fault Status Register) */
+#define SCB_CFSR_BFARVALID_Pos (SCB_CFSR_BUSFAULTSR_Pos + 7U) /*!< SCB CFSR (BFSR): BFARVALID Position */
+#define SCB_CFSR_BFARVALID_Msk (1UL << SCB_CFSR_BFARVALID_Pos) /*!< SCB CFSR (BFSR): BFARVALID Mask */
+
+#define SCB_CFSR_STKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 4U) /*!< SCB CFSR (BFSR): STKERR Position */
+#define SCB_CFSR_STKERR_Msk (1UL << SCB_CFSR_STKERR_Pos) /*!< SCB CFSR (BFSR): STKERR Mask */
+
+#define SCB_CFSR_UNSTKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 3U) /*!< SCB CFSR (BFSR): UNSTKERR Position */
+#define SCB_CFSR_UNSTKERR_Msk (1UL << SCB_CFSR_UNSTKERR_Pos) /*!< SCB CFSR (BFSR): UNSTKERR Mask */
+
+#define SCB_CFSR_IMPRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 2U) /*!< SCB CFSR (BFSR): IMPRECISERR Position */
+#define SCB_CFSR_IMPRECISERR_Msk (1UL << SCB_CFSR_IMPRECISERR_Pos) /*!< SCB CFSR (BFSR): IMPRECISERR Mask */
+
+#define SCB_CFSR_PRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 1U) /*!< SCB CFSR (BFSR): PRECISERR Position */
+#define SCB_CFSR_PRECISERR_Msk (1UL << SCB_CFSR_PRECISERR_Pos) /*!< SCB CFSR (BFSR): PRECISERR Mask */
+
+#define SCB_CFSR_IBUSERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 0U) /*!< SCB CFSR (BFSR): IBUSERR Position */
+#define SCB_CFSR_IBUSERR_Msk (1UL << SCB_CFSR_IBUSERR_Pos) /*!< SCB CFSR (BFSR): IBUSERR Mask */
+
+/* UsageFault Status Register (part of SCB Configurable Fault Status Register) */
+#define SCB_CFSR_DIVBYZERO_Pos (SCB_CFSR_USGFAULTSR_Pos + 9U) /*!< SCB CFSR (UFSR): DIVBYZERO Position */
+#define SCB_CFSR_DIVBYZERO_Msk (1UL << SCB_CFSR_DIVBYZERO_Pos) /*!< SCB CFSR (UFSR): DIVBYZERO Mask */
+
+#define SCB_CFSR_UNALIGNED_Pos (SCB_CFSR_USGFAULTSR_Pos + 8U) /*!< SCB CFSR (UFSR): UNALIGNED Position */
+#define SCB_CFSR_UNALIGNED_Msk (1UL << SCB_CFSR_UNALIGNED_Pos) /*!< SCB CFSR (UFSR): UNALIGNED Mask */
+
+#define SCB_CFSR_NOCP_Pos (SCB_CFSR_USGFAULTSR_Pos + 3U) /*!< SCB CFSR (UFSR): NOCP Position */
+#define SCB_CFSR_NOCP_Msk (1UL << SCB_CFSR_NOCP_Pos) /*!< SCB CFSR (UFSR): NOCP Mask */
+
+#define SCB_CFSR_INVPC_Pos (SCB_CFSR_USGFAULTSR_Pos + 2U) /*!< SCB CFSR (UFSR): INVPC Position */
+#define SCB_CFSR_INVPC_Msk (1UL << SCB_CFSR_INVPC_Pos) /*!< SCB CFSR (UFSR): INVPC Mask */
+
+#define SCB_CFSR_INVSTATE_Pos (SCB_CFSR_USGFAULTSR_Pos + 1U) /*!< SCB CFSR (UFSR): INVSTATE Position */
+#define SCB_CFSR_INVSTATE_Msk (1UL << SCB_CFSR_INVSTATE_Pos) /*!< SCB CFSR (UFSR): INVSTATE Mask */
+
+#define SCB_CFSR_UNDEFINSTR_Pos (SCB_CFSR_USGFAULTSR_Pos + 0U) /*!< SCB CFSR (UFSR): UNDEFINSTR Position */
+#define SCB_CFSR_UNDEFINSTR_Msk (1UL << SCB_CFSR_UNDEFINSTR_Pos) /*!< SCB CFSR (UFSR): UNDEFINSTR Mask */
+
/* SCB Hard Fault Status Register Definitions */
#define SCB_HFSR_DEBUGEVT_Pos 31U /*!< SCB HFSR: DEBUGEVT Position */
#define SCB_HFSR_DEBUGEVT_Msk (1UL << SCB_HFSR_DEBUGEVT_Pos) /*!< SCB HFSR: DEBUGEVT Mask */
@@ -966,7 +977,7 @@ typedef struct
*/
typedef struct
{
- __IOM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Size Register */
+ __IM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Size Register */
__IOM uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Size Register */
uint32_t RESERVED0[2U];
__IOM uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */
@@ -977,7 +988,7 @@ typedef struct
__IOM uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */
__IM uint32_t FSCR; /*!< Offset: 0x308 (R/ ) Formatter Synchronization Counter Register */
uint32_t RESERVED3[759U];
- __IM uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER */
+ __IM uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER Register */
__IM uint32_t FIFO0; /*!< Offset: 0xEEC (R/ ) Integration ETM Data */
__IM uint32_t ITATBCTR2; /*!< Offset: 0xEF0 (R/ ) ITATBCTR2 */
uint32_t RESERVED4[1U];
@@ -1047,8 +1058,11 @@ typedef struct
#define TPI_FIFO0_ETM0_Msk (0xFFUL /*<< TPI_FIFO0_ETM0_Pos*/) /*!< TPI FIFO0: ETM0 Mask */
/* TPI ITATBCTR2 Register Definitions */
-#define TPI_ITATBCTR2_ATREADY_Pos 0U /*!< TPI ITATBCTR2: ATREADY Position */
-#define TPI_ITATBCTR2_ATREADY_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY_Pos*/) /*!< TPI ITATBCTR2: ATREADY Mask */
+#define TPI_ITATBCTR2_ATREADY2_Pos 0U /*!< TPI ITATBCTR2: ATREADY2 Position */
+#define TPI_ITATBCTR2_ATREADY2_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY2_Pos*/) /*!< TPI ITATBCTR2: ATREADY2 Mask */
+
+#define TPI_ITATBCTR2_ATREADY1_Pos 0U /*!< TPI ITATBCTR2: ATREADY1 Position */
+#define TPI_ITATBCTR2_ATREADY1_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY1_Pos*/) /*!< TPI ITATBCTR2: ATREADY1 Mask */
/* TPI Integration ITM Data Register Definitions (FIFO1) */
#define TPI_FIFO1_ITM_ATVALID_Pos 29U /*!< TPI FIFO1: ITM_ATVALID Position */
@@ -1073,12 +1087,15 @@ typedef struct
#define TPI_FIFO1_ITM0_Msk (0xFFUL /*<< TPI_FIFO1_ITM0_Pos*/) /*!< TPI FIFO1: ITM0 Mask */
/* TPI ITATBCTR0 Register Definitions */
-#define TPI_ITATBCTR0_ATREADY_Pos 0U /*!< TPI ITATBCTR0: ATREADY Position */
-#define TPI_ITATBCTR0_ATREADY_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY_Pos*/) /*!< TPI ITATBCTR0: ATREADY Mask */
+#define TPI_ITATBCTR0_ATREADY2_Pos 0U /*!< TPI ITATBCTR0: ATREADY2 Position */
+#define TPI_ITATBCTR0_ATREADY2_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY2_Pos*/) /*!< TPI ITATBCTR0: ATREADY2 Mask */
+
+#define TPI_ITATBCTR0_ATREADY1_Pos 0U /*!< TPI ITATBCTR0: ATREADY1 Position */
+#define TPI_ITATBCTR0_ATREADY1_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY1_Pos*/) /*!< TPI ITATBCTR0: ATREADY1 Mask */
/* TPI Integration Mode Control Register Definitions */
#define TPI_ITCTRL_Mode_Pos 0U /*!< TPI ITCTRL: Mode Position */
-#define TPI_ITCTRL_Mode_Msk (0x1UL /*<< TPI_ITCTRL_Mode_Pos*/) /*!< TPI ITCTRL: Mode Mask */
+#define TPI_ITCTRL_Mode_Msk (0x3UL /*<< TPI_ITCTRL_Mode_Pos*/) /*!< TPI ITCTRL: Mode Mask */
/* TPI DEVID Register Definitions */
#define TPI_DEVID_NRZVALID_Pos 11U /*!< TPI DEVID: NRZVALID Position */
@@ -1100,16 +1117,16 @@ typedef struct
#define TPI_DEVID_NrTraceInput_Msk (0x1FUL /*<< TPI_DEVID_NrTraceInput_Pos*/) /*!< TPI DEVID: NrTraceInput Mask */
/* TPI DEVTYPE Register Definitions */
-#define TPI_DEVTYPE_MajorType_Pos 4U /*!< TPI DEVTYPE: MajorType Position */
-#define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */
-
-#define TPI_DEVTYPE_SubType_Pos 0U /*!< TPI DEVTYPE: SubType Position */
+#define TPI_DEVTYPE_SubType_Pos 4U /*!< TPI DEVTYPE: SubType Position */
#define TPI_DEVTYPE_SubType_Msk (0xFUL /*<< TPI_DEVTYPE_SubType_Pos*/) /*!< TPI DEVTYPE: SubType Mask */
+#define TPI_DEVTYPE_MajorType_Pos 0U /*!< TPI DEVTYPE: MajorType Position */
+#define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */
+
/*@}*/ /* end of group CMSIS_TPI */
-#if (__MPU_PRESENT == 1U)
+#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U)
/**
\ingroup CMSIS_core_register
\defgroup CMSIS_MPU Memory Protection Unit (MPU)
@@ -1319,18 +1336,18 @@ typedef struct
/**
\brief Mask and shift a bit field value for use in a register bit range.
\param[in] field Name of the register bit field.
- \param[in] value Value of the bit field.
+ \param[in] value Value of the bit field. This parameter is interpreted as an uint32_t type.
\return Masked and shifted value.
*/
-#define _VAL2FLD(field, value) ((value << field ## _Pos) & field ## _Msk)
+#define _VAL2FLD(field, value) (((uint32_t)(value) << field ## _Pos) & field ## _Msk)
/**
\brief Mask and shift a register value to extract a bit filed value.
\param[in] field Name of the register bit field.
- \param[in] value Value of register.
+ \param[in] value Value of register. This parameter is interpreted as an uint32_t type.
\return Masked and shifted bit field value.
*/
-#define _FLD2VAL(field, value) ((value & field ## _Msk) >> field ## _Pos)
+#define _FLD2VAL(field, value) (((uint32_t)(value) & field ## _Msk) >> field ## _Pos)
/*@} end of group CMSIS_core_bitfield */
@@ -1342,7 +1359,7 @@ typedef struct
@{
*/
-/* Memory mapping of Cortex-M3 Hardware */
+/* Memory mapping of Core Hardware */
#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */
#define ITM_BASE (0xE0000000UL) /*!< ITM Base Address */
#define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */
@@ -1361,7 +1378,7 @@ typedef struct
#define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */
#define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE) /*!< Core Debug configuration struct */
-#if (__MPU_PRESENT == 1U)
+#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U)
#define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */
#define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */
#endif
@@ -1392,6 +1409,46 @@ typedef struct
@{
*/
+#ifdef CMSIS_NVIC_VIRTUAL
+ #ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE
+ #define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h"
+ #endif
+ #include CMSIS_NVIC_VIRTUAL_HEADER_FILE
+#else
+ #define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping
+ #define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping
+ #define NVIC_EnableIRQ __NVIC_EnableIRQ
+ #define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ
+ #define NVIC_DisableIRQ __NVIC_DisableIRQ
+ #define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ
+ #define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ
+ #define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ
+ #define NVIC_GetActive __NVIC_GetActive
+ #define NVIC_SetPriority __NVIC_SetPriority
+ #define NVIC_GetPriority __NVIC_GetPriority
+ #define NVIC_SystemReset __NVIC_SystemReset
+#endif /* CMSIS_NVIC_VIRTUAL */
+
+#ifdef CMSIS_VECTAB_VIRTUAL
+ #ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE
+ #define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h"
+ #endif
+ #include CMSIS_VECTAB_VIRTUAL_HEADER_FILE
+#else
+ #define NVIC_SetVector __NVIC_SetVector
+ #define NVIC_GetVector __NVIC_GetVector
+#endif /* (CMSIS_VECTAB_VIRTUAL) */
+
+#define NVIC_USER_IRQ_OFFSET 16
+
+
+/* The following EXC_RETURN values are saved the LR on exception entry */
+#define EXC_RETURN_HANDLER (0xFFFFFFF1UL) /* return to Handler mode, uses MSP after return */
+#define EXC_RETURN_THREAD_MSP (0xFFFFFFF9UL) /* return to Thread mode, uses MSP after return */
+#define EXC_RETURN_THREAD_PSP (0xFFFFFFFDUL) /* return to Thread mode, uses PSP after return */
+
+
+
/**
\brief Set Priority Grouping
\details Sets the priority grouping field using the required unlock sequence.
@@ -1401,7 +1458,7 @@ typedef struct
priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set.
\param [in] PriorityGroup Priority grouping field.
*/
-__STATIC_INLINE void NVIC_SetPriorityGrouping(uint32_t PriorityGroup)
+__STATIC_INLINE void __NVIC_SetPriorityGrouping(uint32_t PriorityGroup)
{
uint32_t reg_value;
uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */
@@ -1420,121 +1477,178 @@ __STATIC_INLINE void NVIC_SetPriorityGrouping(uint32_t PriorityGroup)
\details Reads the priority grouping field from the NVIC Interrupt Controller.
\return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field).
*/
-__STATIC_INLINE uint32_t NVIC_GetPriorityGrouping(void)
+__STATIC_INLINE uint32_t __NVIC_GetPriorityGrouping(void)
{
return ((uint32_t)((SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos));
}
/**
- \brief Enable External Interrupt
- \details Enables a device-specific interrupt in the NVIC interrupt controller.
- \param [in] IRQn External interrupt number. Value cannot be negative.
+ \brief Enable Interrupt
+ \details Enables a device specific interrupt in the NVIC interrupt controller.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
*/
-__STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn)
+__STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn)
{
- NVIC->ISER[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL));
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
}
/**
- \brief Disable External Interrupt
- \details Disables a device-specific interrupt in the NVIC interrupt controller.
- \param [in] IRQn External interrupt number. Value cannot be negative.
+ \brief Get Interrupt Enable status
+ \details Returns a device specific interrupt enable status from the NVIC interrupt controller.
+ \param [in] IRQn Device specific interrupt number.
+ \return 0 Interrupt is not enabled.
+ \return 1 Interrupt is enabled.
+ \note IRQn must not be negative.
*/
-__STATIC_INLINE void NVIC_DisableIRQ(IRQn_Type IRQn)
+__STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn)
{
- NVIC->ICER[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL));
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
+}
+
+
+/**
+ \brief Disable Interrupt
+ \details Disables a device specific interrupt in the NVIC interrupt controller.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
+ */
+__STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn)
+{
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ICER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ __DSB();
+ __ISB();
+ }
}
/**
\brief Get Pending Interrupt
- \details Reads the pending register in the NVIC and returns the pending bit for the specified interrupt.
- \param [in] IRQn Interrupt number.
+ \details Reads the NVIC pending register and returns the pending bit for the specified device specific interrupt.
+ \param [in] IRQn Device specific interrupt number.
\return 0 Interrupt status is not pending.
\return 1 Interrupt status is pending.
+ \note IRQn must not be negative.
*/
-__STATIC_INLINE uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn)
+__STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn)
{
- return((uint32_t)(((NVIC->ISPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
}
/**
\brief Set Pending Interrupt
- \details Sets the pending bit of an external interrupt.
- \param [in] IRQn Interrupt number. Value cannot be negative.
+ \details Sets the pending bit of a device specific interrupt in the NVIC pending register.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
*/
-__STATIC_INLINE void NVIC_SetPendingIRQ(IRQn_Type IRQn)
+__STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn)
{
- NVIC->ISPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL));
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
}
/**
\brief Clear Pending Interrupt
- \details Clears the pending bit of an external interrupt.
- \param [in] IRQn External interrupt number. Value cannot be negative.
+ \details Clears the pending bit of a device specific interrupt in the NVIC pending register.
+ \param [in] IRQn Device specific interrupt number.
+ \note IRQn must not be negative.
*/
-__STATIC_INLINE void NVIC_ClearPendingIRQ(IRQn_Type IRQn)
+__STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn)
{
- NVIC->ICPR[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL));
+ if ((int32_t)(IRQn) >= 0)
+ {
+ NVIC->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));
+ }
}
/**
\brief Get Active Interrupt
- \details Reads the active register in NVIC and returns the active bit.
- \param [in] IRQn Interrupt number.
+ \details Reads the active register in the NVIC and returns the active bit for the device specific interrupt.
+ \param [in] IRQn Device specific interrupt number.
\return 0 Interrupt status is not active.
\return 1 Interrupt status is active.
+ \note IRQn must not be negative.
*/
-__STATIC_INLINE uint32_t NVIC_GetActive(IRQn_Type IRQn)
+__STATIC_INLINE uint32_t __NVIC_GetActive(IRQn_Type IRQn)
{
- return((uint32_t)(((NVIC->IABR[(((uint32_t)(int32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ if ((int32_t)(IRQn) >= 0)
+ {
+ return((uint32_t)(((NVIC->IABR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL));
+ }
+ else
+ {
+ return(0U);
+ }
}
/**
\brief Set Interrupt Priority
- \details Sets the priority of an interrupt.
- \note The priority cannot be set for every core interrupt.
+ \details Sets the priority of a device specific interrupt or a processor exception.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
\param [in] IRQn Interrupt number.
\param [in] priority Priority to set.
+ \note The priority cannot be set for every processor exception.
*/
-__STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
+__STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
{
- if ((int32_t)(IRQn) < 0)
+ if ((int32_t)(IRQn) >= 0)
{
- SCB->SHP[(((uint32_t)(int32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL);
+ NVIC->IP[((uint32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL);
}
else
{
- NVIC->IP[((uint32_t)(int32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL);
+ SCB->SHP[(((uint32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL);
}
}
/**
\brief Get Interrupt Priority
- \details Reads the priority of an interrupt.
- The interrupt number can be positive to specify an external (device specific) interrupt,
- or negative to specify an internal (core) interrupt.
+ \details Reads the priority of a device specific interrupt or a processor exception.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
\param [in] IRQn Interrupt number.
\return Interrupt Priority.
Value is aligned automatically to the implemented priority bits of the microcontroller.
*/
-__STATIC_INLINE uint32_t NVIC_GetPriority(IRQn_Type IRQn)
+__STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn)
{
- if ((int32_t)(IRQn) < 0)
+ if ((int32_t)(IRQn) >= 0)
{
- return(((uint32_t)SCB->SHP[(((uint32_t)(int32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS)));
+ return(((uint32_t)NVIC->IP[((uint32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS)));
}
else
{
- return(((uint32_t)NVIC->IP[((uint32_t)(int32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS)));
+ return(((uint32_t)SCB->SHP[(((uint32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS)));
}
}
@@ -1591,11 +1705,42 @@ __STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGr
}
+/**
+ \brief Set Interrupt Vector
+ \details Sets an interrupt vector in SRAM based interrupt vector table.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ VTOR must been relocated to SRAM before.
+ \param [in] IRQn Interrupt number
+ \param [in] vector Address of interrupt handler function
+ */
+__STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector)
+{
+ uint32_t *vectors = (uint32_t *)SCB->VTOR;
+ vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET] = vector;
+}
+
+
+/**
+ \brief Get Interrupt Vector
+ \details Reads an interrupt vector from interrupt vector table.
+ The interrupt number can be positive to specify a device specific interrupt,
+ or negative to specify a processor exception.
+ \param [in] IRQn Interrupt number.
+ \return Address of interrupt handler function
+ */
+__STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn)
+{
+ uint32_t *vectors = (uint32_t *)SCB->VTOR;
+ return vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET];
+}
+
+
/**
\brief System Reset
\details Initiates a system reset request to reset the MCU.
*/
-__STATIC_INLINE void NVIC_SystemReset(void)
+__NO_RETURN __STATIC_INLINE void __NVIC_SystemReset(void)
{
__DSB(); /* Ensure all outstanding memory accesses included
buffered write are completed before reset */
@@ -1613,6 +1758,31 @@ __STATIC_INLINE void NVIC_SystemReset(void)
/*@} end of CMSIS_Core_NVICFunctions */
+/* ########################## FPU functions #################################### */
+/**
+ \ingroup CMSIS_Core_FunctionInterface
+ \defgroup CMSIS_Core_FpuFunctions FPU Functions
+ \brief Function that provides FPU type.
+ @{
+ */
+
+/**
+ \brief get FPU type
+ \details returns the FPU type
+ \returns
+ - \b 0: No FPU
+ - \b 1: Single precision FPU
+ - \b 2: Double + Single precision FPU
+ */
+__STATIC_INLINE uint32_t SCB_GetFPUType(void)
+{
+ return 0U; /* No FPU */
+}
+
+
+/*@} end of CMSIS_Core_FpuFunctions */
+
+
/* ################################## SysTick function ############################################ */
/**
@@ -1622,7 +1792,7 @@ __STATIC_INLINE void NVIC_SystemReset(void)
@{
*/
-#if (__Vendor_SysTickConfig == 0U)
+#if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U)
/**
\brief System Tick Configuration
@@ -1665,8 +1835,8 @@ __STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)
@{
*/
-extern volatile int32_t ITM_RxBuffer; /*!< External variable to receive characters. */
-#define ITM_RXBUFFER_EMPTY 0x5AA55AA5U /*!< Value identifying \ref ITM_RxBuffer is ready for next character. */
+extern volatile int32_t ITM_RxBuffer; /*!< External variable to receive characters. */
+#define ITM_RXBUFFER_EMPTY ((int32_t)0x5AA55AA5U) /*!< Value identifying \ref ITM_RxBuffer is ready for next character. */
/**
diff --git a/lib/cmsis/inc/mpu_armv7.h b/lib/cmsis/inc/mpu_armv7.h
new file mode 100644
index 0000000000..66ef59b4a0
--- /dev/null
+++ b/lib/cmsis/inc/mpu_armv7.h
@@ -0,0 +1,272 @@
+/******************************************************************************
+ * @file mpu_armv7.h
+ * @brief CMSIS MPU API for Armv7-M MPU
+ * @version V5.1.0
+ * @date 08. March 2019
+ ******************************************************************************/
+/*
+ * Copyright (c) 2017-2019 Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#if defined ( __ICCARM__ )
+ #pragma system_include /* treat file as system include file for MISRA check */
+#elif defined (__clang__)
+ #pragma clang system_header /* treat file as system include file */
+#endif
+
+#ifndef ARM_MPU_ARMV7_H
+#define ARM_MPU_ARMV7_H
+
+#define ARM_MPU_REGION_SIZE_32B ((uint8_t)0x04U) ///!< MPU Region Size 32 Bytes
+#define ARM_MPU_REGION_SIZE_64B ((uint8_t)0x05U) ///!< MPU Region Size 64 Bytes
+#define ARM_MPU_REGION_SIZE_128B ((uint8_t)0x06U) ///!< MPU Region Size 128 Bytes
+#define ARM_MPU_REGION_SIZE_256B ((uint8_t)0x07U) ///!< MPU Region Size 256 Bytes
+#define ARM_MPU_REGION_SIZE_512B ((uint8_t)0x08U) ///!< MPU Region Size 512 Bytes
+#define ARM_MPU_REGION_SIZE_1KB ((uint8_t)0x09U) ///!< MPU Region Size 1 KByte
+#define ARM_MPU_REGION_SIZE_2KB ((uint8_t)0x0AU) ///!< MPU Region Size 2 KBytes
+#define ARM_MPU_REGION_SIZE_4KB ((uint8_t)0x0BU) ///!< MPU Region Size 4 KBytes
+#define ARM_MPU_REGION_SIZE_8KB ((uint8_t)0x0CU) ///!< MPU Region Size 8 KBytes
+#define ARM_MPU_REGION_SIZE_16KB ((uint8_t)0x0DU) ///!< MPU Region Size 16 KBytes
+#define ARM_MPU_REGION_SIZE_32KB ((uint8_t)0x0EU) ///!< MPU Region Size 32 KBytes
+#define ARM_MPU_REGION_SIZE_64KB ((uint8_t)0x0FU) ///!< MPU Region Size 64 KBytes
+#define ARM_MPU_REGION_SIZE_128KB ((uint8_t)0x10U) ///!< MPU Region Size 128 KBytes
+#define ARM_MPU_REGION_SIZE_256KB ((uint8_t)0x11U) ///!< MPU Region Size 256 KBytes
+#define ARM_MPU_REGION_SIZE_512KB ((uint8_t)0x12U) ///!< MPU Region Size 512 KBytes
+#define ARM_MPU_REGION_SIZE_1MB ((uint8_t)0x13U) ///!< MPU Region Size 1 MByte
+#define ARM_MPU_REGION_SIZE_2MB ((uint8_t)0x14U) ///!< MPU Region Size 2 MBytes
+#define ARM_MPU_REGION_SIZE_4MB ((uint8_t)0x15U) ///!< MPU Region Size 4 MBytes
+#define ARM_MPU_REGION_SIZE_8MB ((uint8_t)0x16U) ///!< MPU Region Size 8 MBytes
+#define ARM_MPU_REGION_SIZE_16MB ((uint8_t)0x17U) ///!< MPU Region Size 16 MBytes
+#define ARM_MPU_REGION_SIZE_32MB ((uint8_t)0x18U) ///!< MPU Region Size 32 MBytes
+#define ARM_MPU_REGION_SIZE_64MB ((uint8_t)0x19U) ///!< MPU Region Size 64 MBytes
+#define ARM_MPU_REGION_SIZE_128MB ((uint8_t)0x1AU) ///!< MPU Region Size 128 MBytes
+#define ARM_MPU_REGION_SIZE_256MB ((uint8_t)0x1BU) ///!< MPU Region Size 256 MBytes
+#define ARM_MPU_REGION_SIZE_512MB ((uint8_t)0x1CU) ///!< MPU Region Size 512 MBytes
+#define ARM_MPU_REGION_SIZE_1GB ((uint8_t)0x1DU) ///!< MPU Region Size 1 GByte
+#define ARM_MPU_REGION_SIZE_2GB ((uint8_t)0x1EU) ///!< MPU Region Size 2 GBytes
+#define ARM_MPU_REGION_SIZE_4GB ((uint8_t)0x1FU) ///!< MPU Region Size 4 GBytes
+
+#define ARM_MPU_AP_NONE 0U ///!< MPU Access Permission no access
+#define ARM_MPU_AP_PRIV 1U ///!< MPU Access Permission privileged access only
+#define ARM_MPU_AP_URO 2U ///!< MPU Access Permission unprivileged access read-only
+#define ARM_MPU_AP_FULL 3U ///!< MPU Access Permission full access
+#define ARM_MPU_AP_PRO 5U ///!< MPU Access Permission privileged access read-only
+#define ARM_MPU_AP_RO 6U ///!< MPU Access Permission read-only access
+
+/** MPU Region Base Address Register Value
+*
+* \param Region The region to be configured, number 0 to 15.
+* \param BaseAddress The base address for the region.
+*/
+#define ARM_MPU_RBAR(Region, BaseAddress) \
+ (((BaseAddress) & MPU_RBAR_ADDR_Msk) | \
+ ((Region) & MPU_RBAR_REGION_Msk) | \
+ (MPU_RBAR_VALID_Msk))
+
+/**
+* MPU Memory Access Attributes
+*
+* \param TypeExtField Type extension field, allows you to configure memory access type, for example strongly ordered, peripheral.
+* \param IsShareable Region is shareable between multiple bus masters.
+* \param IsCacheable Region is cacheable, i.e. its value may be kept in cache.
+* \param IsBufferable Region is bufferable, i.e. using write-back caching. Cacheable but non-bufferable regions use write-through policy.
+*/
+#define ARM_MPU_ACCESS_(TypeExtField, IsShareable, IsCacheable, IsBufferable) \
+ ((((TypeExtField) << MPU_RASR_TEX_Pos) & MPU_RASR_TEX_Msk) | \
+ (((IsShareable) << MPU_RASR_S_Pos) & MPU_RASR_S_Msk) | \
+ (((IsCacheable) << MPU_RASR_C_Pos) & MPU_RASR_C_Msk) | \
+ (((IsBufferable) << MPU_RASR_B_Pos) & MPU_RASR_B_Msk))
+
+/**
+* MPU Region Attribute and Size Register Value
+*
+* \param DisableExec Instruction access disable bit, 1= disable instruction fetches.
+* \param AccessPermission Data access permissions, allows you to configure read/write access for User and Privileged mode.
+* \param AccessAttributes Memory access attribution, see \ref ARM_MPU_ACCESS_.
+* \param SubRegionDisable Sub-region disable field.
+* \param Size Region size of the region to be configured, for example 4K, 8K.
+*/
+#define ARM_MPU_RASR_EX(DisableExec, AccessPermission, AccessAttributes, SubRegionDisable, Size) \
+ ((((DisableExec) << MPU_RASR_XN_Pos) & MPU_RASR_XN_Msk) | \
+ (((AccessPermission) << MPU_RASR_AP_Pos) & MPU_RASR_AP_Msk) | \
+ (((AccessAttributes) & (MPU_RASR_TEX_Msk | MPU_RASR_S_Msk | MPU_RASR_C_Msk | MPU_RASR_B_Msk))) | \
+ (((SubRegionDisable) << MPU_RASR_SRD_Pos) & MPU_RASR_SRD_Msk) | \
+ (((Size) << MPU_RASR_SIZE_Pos) & MPU_RASR_SIZE_Msk) | \
+ (((MPU_RASR_ENABLE_Msk))))
+
+/**
+* MPU Region Attribute and Size Register Value
+*
+* \param DisableExec Instruction access disable bit, 1= disable instruction fetches.
+* \param AccessPermission Data access permissions, allows you to configure read/write access for User and Privileged mode.
+* \param TypeExtField Type extension field, allows you to configure memory access type, for example strongly ordered, peripheral.
+* \param IsShareable Region is shareable between multiple bus masters.
+* \param IsCacheable Region is cacheable, i.e. its value may be kept in cache.
+* \param IsBufferable Region is bufferable, i.e. using write-back caching. Cacheable but non-bufferable regions use write-through policy.
+* \param SubRegionDisable Sub-region disable field.
+* \param Size Region size of the region to be configured, for example 4K, 8K.
+*/
+#define ARM_MPU_RASR(DisableExec, AccessPermission, TypeExtField, IsShareable, IsCacheable, IsBufferable, SubRegionDisable, Size) \
+ ARM_MPU_RASR_EX(DisableExec, AccessPermission, ARM_MPU_ACCESS_(TypeExtField, IsShareable, IsCacheable, IsBufferable), SubRegionDisable, Size)
+
+/**
+* MPU Memory Access Attribute for strongly ordered memory.
+* - TEX: 000b
+* - Shareable
+* - Non-cacheable
+* - Non-bufferable
+*/
+#define ARM_MPU_ACCESS_ORDERED ARM_MPU_ACCESS_(0U, 1U, 0U, 0U)
+
+/**
+* MPU Memory Access Attribute for device memory.
+* - TEX: 000b (if shareable) or 010b (if non-shareable)
+* - Shareable or non-shareable
+* - Non-cacheable
+* - Bufferable (if shareable) or non-bufferable (if non-shareable)
+*
+* \param IsShareable Configures the device memory as shareable or non-shareable.
+*/
+#define ARM_MPU_ACCESS_DEVICE(IsShareable) ((IsShareable) ? ARM_MPU_ACCESS_(0U, 1U, 0U, 1U) : ARM_MPU_ACCESS_(2U, 0U, 0U, 0U))
+
+/**
+* MPU Memory Access Attribute for normal memory.
+* - TEX: 1BBb (reflecting outer cacheability rules)
+* - Shareable or non-shareable
+* - Cacheable or non-cacheable (reflecting inner cacheability rules)
+* - Bufferable or non-bufferable (reflecting inner cacheability rules)
+*
+* \param OuterCp Configures the outer cache policy.
+* \param InnerCp Configures the inner cache policy.
+* \param IsShareable Configures the memory as shareable or non-shareable.
+*/
+#define ARM_MPU_ACCESS_NORMAL(OuterCp, InnerCp, IsShareable) ARM_MPU_ACCESS_((4U | (OuterCp)), IsShareable, ((InnerCp) & 2U), ((InnerCp) & 1U))
+
+/**
+* MPU Memory Access Attribute non-cacheable policy.
+*/
+#define ARM_MPU_CACHEP_NOCACHE 0U
+
+/**
+* MPU Memory Access Attribute write-back, write and read allocate policy.
+*/
+#define ARM_MPU_CACHEP_WB_WRA 1U
+
+/**
+* MPU Memory Access Attribute write-through, no write allocate policy.
+*/
+#define ARM_MPU_CACHEP_WT_NWA 2U
+
+/**
+* MPU Memory Access Attribute write-back, no write allocate policy.
+*/
+#define ARM_MPU_CACHEP_WB_NWA 3U
+
+
+/**
+* Struct for a single MPU Region
+*/
+typedef struct {
+ uint32_t RBAR; //!< The region base address register value (RBAR)
+ uint32_t RASR; //!< The region attribute and size register value (RASR) \ref MPU_RASR
+} ARM_MPU_Region_t;
+
+/** Enable the MPU.
+* \param MPU_Control Default access permissions for unconfigured regions.
+*/
+__STATIC_INLINE void ARM_MPU_Enable(uint32_t MPU_Control)
+{
+ MPU->CTRL = MPU_Control | MPU_CTRL_ENABLE_Msk;
+#ifdef SCB_SHCSR_MEMFAULTENA_Msk
+ SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk;
+#endif
+ __DSB();
+ __ISB();
+}
+
+/** Disable the MPU.
+*/
+__STATIC_INLINE void ARM_MPU_Disable(void)
+{
+ __DMB();
+#ifdef SCB_SHCSR_MEMFAULTENA_Msk
+ SCB->SHCSR &= ~SCB_SHCSR_MEMFAULTENA_Msk;
+#endif
+ MPU->CTRL &= ~MPU_CTRL_ENABLE_Msk;
+}
+
+/** Clear and disable the given MPU region.
+* \param rnr Region number to be cleared.
+*/
+__STATIC_INLINE void ARM_MPU_ClrRegion(uint32_t rnr)
+{
+ MPU->RNR = rnr;
+ MPU->RASR = 0U;
+}
+
+/** Configure an MPU region.
+* \param rbar Value for RBAR register.
+* \param rsar Value for RSAR register.
+*/
+__STATIC_INLINE void ARM_MPU_SetRegion(uint32_t rbar, uint32_t rasr)
+{
+ MPU->RBAR = rbar;
+ MPU->RASR = rasr;
+}
+
+/** Configure the given MPU region.
+* \param rnr Region number to be configured.
+* \param rbar Value for RBAR register.
+* \param rsar Value for RSAR register.
+*/
+__STATIC_INLINE void ARM_MPU_SetRegionEx(uint32_t rnr, uint32_t rbar, uint32_t rasr)
+{
+ MPU->RNR = rnr;
+ MPU->RBAR = rbar;
+ MPU->RASR = rasr;
+}
+
+/** Memcopy with strictly ordered memory access, e.g. for register targets.
+* \param dst Destination data is copied to.
+* \param src Source data is copied from.
+* \param len Amount of data words to be copied.
+*/
+__STATIC_INLINE void ARM_MPU_OrderedMemcpy(volatile uint32_t* dst, const uint32_t* __RESTRICT src, uint32_t len)
+{
+ uint32_t i;
+ for (i = 0U; i < len; ++i)
+ {
+ dst[i] = src[i];
+ }
+}
+
+/** Load the given number of MPU regions from a table.
+* \param table Pointer to the MPU configuration table.
+* \param cnt Amount of regions to be configured.
+*/
+__STATIC_INLINE void ARM_MPU_Load(ARM_MPU_Region_t const* table, uint32_t cnt)
+{
+ const uint32_t rowWordSize = sizeof(ARM_MPU_Region_t)/4U;
+ while (cnt > MPU_TYPE_RALIASES) {
+ ARM_MPU_OrderedMemcpy(&(MPU->RBAR), &(table->RBAR), MPU_TYPE_RALIASES*rowWordSize);
+ table += MPU_TYPE_RALIASES;
+ cnt -= MPU_TYPE_RALIASES;
+ }
+ ARM_MPU_OrderedMemcpy(&(MPU->RBAR), &(table->RBAR), cnt*rowWordSize);
+}
+
+#endif
diff --git a/lib/cmsis/inc/mpu_armv8.h b/lib/cmsis/inc/mpu_armv8.h
new file mode 100644
index 0000000000..0041d4dc6f
--- /dev/null
+++ b/lib/cmsis/inc/mpu_armv8.h
@@ -0,0 +1,346 @@
+/******************************************************************************
+ * @file mpu_armv8.h
+ * @brief CMSIS MPU API for Armv8-M and Armv8.1-M MPU
+ * @version V5.1.0
+ * @date 08. March 2019
+ ******************************************************************************/
+/*
+ * Copyright (c) 2017-2019 Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#if defined ( __ICCARM__ )
+ #pragma system_include /* treat file as system include file for MISRA check */
+#elif defined (__clang__)
+ #pragma clang system_header /* treat file as system include file */
+#endif
+
+#ifndef ARM_MPU_ARMV8_H
+#define ARM_MPU_ARMV8_H
+
+/** \brief Attribute for device memory (outer only) */
+#define ARM_MPU_ATTR_DEVICE ( 0U )
+
+/** \brief Attribute for non-cacheable, normal memory */
+#define ARM_MPU_ATTR_NON_CACHEABLE ( 4U )
+
+/** \brief Attribute for normal memory (outer and inner)
+* \param NT Non-Transient: Set to 1 for non-transient data.
+* \param WB Write-Back: Set to 1 to use write-back update policy.
+* \param RA Read Allocation: Set to 1 to use cache allocation on read miss.
+* \param WA Write Allocation: Set to 1 to use cache allocation on write miss.
+*/
+#define ARM_MPU_ATTR_MEMORY_(NT, WB, RA, WA) \
+ (((NT & 1U) << 3U) | ((WB & 1U) << 2U) | ((RA & 1U) << 1U) | (WA & 1U))
+
+/** \brief Device memory type non Gathering, non Re-ordering, non Early Write Acknowledgement */
+#define ARM_MPU_ATTR_DEVICE_nGnRnE (0U)
+
+/** \brief Device memory type non Gathering, non Re-ordering, Early Write Acknowledgement */
+#define ARM_MPU_ATTR_DEVICE_nGnRE (1U)
+
+/** \brief Device memory type non Gathering, Re-ordering, Early Write Acknowledgement */
+#define ARM_MPU_ATTR_DEVICE_nGRE (2U)
+
+/** \brief Device memory type Gathering, Re-ordering, Early Write Acknowledgement */
+#define ARM_MPU_ATTR_DEVICE_GRE (3U)
+
+/** \brief Memory Attribute
+* \param O Outer memory attributes
+* \param I O == ARM_MPU_ATTR_DEVICE: Device memory attributes, else: Inner memory attributes
+*/
+#define ARM_MPU_ATTR(O, I) (((O & 0xFU) << 4U) | (((O & 0xFU) != 0U) ? (I & 0xFU) : ((I & 0x3U) << 2U)))
+
+/** \brief Normal memory non-shareable */
+#define ARM_MPU_SH_NON (0U)
+
+/** \brief Normal memory outer shareable */
+#define ARM_MPU_SH_OUTER (2U)
+
+/** \brief Normal memory inner shareable */
+#define ARM_MPU_SH_INNER (3U)
+
+/** \brief Memory access permissions
+* \param RO Read-Only: Set to 1 for read-only memory.
+* \param NP Non-Privileged: Set to 1 for non-privileged memory.
+*/
+#define ARM_MPU_AP_(RO, NP) (((RO & 1U) << 1U) | (NP & 1U))
+
+/** \brief Region Base Address Register value
+* \param BASE The base address bits [31:5] of a memory region. The value is zero extended. Effective address gets 32 byte aligned.
+* \param SH Defines the Shareability domain for this memory region.
+* \param RO Read-Only: Set to 1 for a read-only memory region.
+* \param NP Non-Privileged: Set to 1 for a non-privileged memory region.
+* \oaram XN eXecute Never: Set to 1 for a non-executable memory region.
+*/
+#define ARM_MPU_RBAR(BASE, SH, RO, NP, XN) \
+ ((BASE & MPU_RBAR_BASE_Msk) | \
+ ((SH << MPU_RBAR_SH_Pos) & MPU_RBAR_SH_Msk) | \
+ ((ARM_MPU_AP_(RO, NP) << MPU_RBAR_AP_Pos) & MPU_RBAR_AP_Msk) | \
+ ((XN << MPU_RBAR_XN_Pos) & MPU_RBAR_XN_Msk))
+
+/** \brief Region Limit Address Register value
+* \param LIMIT The limit address bits [31:5] for this memory region. The value is one extended.
+* \param IDX The attribute index to be associated with this memory region.
+*/
+#define ARM_MPU_RLAR(LIMIT, IDX) \
+ ((LIMIT & MPU_RLAR_LIMIT_Msk) | \
+ ((IDX << MPU_RLAR_AttrIndx_Pos) & MPU_RLAR_AttrIndx_Msk) | \
+ (MPU_RLAR_EN_Msk))
+
+#if defined(MPU_RLAR_PXN_Pos)
+
+/** \brief Region Limit Address Register with PXN value
+* \param LIMIT The limit address bits [31:5] for this memory region. The value is one extended.
+* \param PXN Privileged execute never. Defines whether code can be executed from this privileged region.
+* \param IDX The attribute index to be associated with this memory region.
+*/
+#define ARM_MPU_RLAR_PXN(LIMIT, PXN, IDX) \
+ ((LIMIT & MPU_RLAR_LIMIT_Msk) | \
+ ((PXN << MPU_RLAR_PXN_Pos) & MPU_RLAR_PXN_Msk) | \
+ ((IDX << MPU_RLAR_AttrIndx_Pos) & MPU_RLAR_AttrIndx_Msk) | \
+ (MPU_RLAR_EN_Msk))
+
+#endif
+
+/**
+* Struct for a single MPU Region
+*/
+typedef struct {
+ uint32_t RBAR; /*!< Region Base Address Register value */
+ uint32_t RLAR; /*!< Region Limit Address Register value */
+} ARM_MPU_Region_t;
+
+/** Enable the MPU.
+* \param MPU_Control Default access permissions for unconfigured regions.
+*/
+__STATIC_INLINE void ARM_MPU_Enable(uint32_t MPU_Control)
+{
+ MPU->CTRL = MPU_Control | MPU_CTRL_ENABLE_Msk;
+#ifdef SCB_SHCSR_MEMFAULTENA_Msk
+ SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk;
+#endif
+ __DSB();
+ __ISB();
+}
+
+/** Disable the MPU.
+*/
+__STATIC_INLINE void ARM_MPU_Disable(void)
+{
+ __DMB();
+#ifdef SCB_SHCSR_MEMFAULTENA_Msk
+ SCB->SHCSR &= ~SCB_SHCSR_MEMFAULTENA_Msk;
+#endif
+ MPU->CTRL &= ~MPU_CTRL_ENABLE_Msk;
+}
+
+#ifdef MPU_NS
+/** Enable the Non-secure MPU.
+* \param MPU_Control Default access permissions for unconfigured regions.
+*/
+__STATIC_INLINE void ARM_MPU_Enable_NS(uint32_t MPU_Control)
+{
+ MPU_NS->CTRL = MPU_Control | MPU_CTRL_ENABLE_Msk;
+#ifdef SCB_SHCSR_MEMFAULTENA_Msk
+ SCB_NS->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk;
+#endif
+ __DSB();
+ __ISB();
+}
+
+/** Disable the Non-secure MPU.
+*/
+__STATIC_INLINE void ARM_MPU_Disable_NS(void)
+{
+ __DMB();
+#ifdef SCB_SHCSR_MEMFAULTENA_Msk
+ SCB_NS->SHCSR &= ~SCB_SHCSR_MEMFAULTENA_Msk;
+#endif
+ MPU_NS->CTRL &= ~MPU_CTRL_ENABLE_Msk;
+}
+#endif
+
+/** Set the memory attribute encoding to the given MPU.
+* \param mpu Pointer to the MPU to be configured.
+* \param idx The attribute index to be set [0-7]
+* \param attr The attribute value to be set.
+*/
+__STATIC_INLINE void ARM_MPU_SetMemAttrEx(MPU_Type* mpu, uint8_t idx, uint8_t attr)
+{
+ const uint8_t reg = idx / 4U;
+ const uint32_t pos = ((idx % 4U) * 8U);
+ const uint32_t mask = 0xFFU << pos;
+
+ if (reg >= (sizeof(mpu->MAIR) / sizeof(mpu->MAIR[0]))) {
+ return; // invalid index
+ }
+
+ mpu->MAIR[reg] = ((mpu->MAIR[reg] & ~mask) | ((attr << pos) & mask));
+}
+
+/** Set the memory attribute encoding.
+* \param idx The attribute index to be set [0-7]
+* \param attr The attribute value to be set.
+*/
+__STATIC_INLINE void ARM_MPU_SetMemAttr(uint8_t idx, uint8_t attr)
+{
+ ARM_MPU_SetMemAttrEx(MPU, idx, attr);
+}
+
+#ifdef MPU_NS
+/** Set the memory attribute encoding to the Non-secure MPU.
+* \param idx The attribute index to be set [0-7]
+* \param attr The attribute value to be set.
+*/
+__STATIC_INLINE void ARM_MPU_SetMemAttr_NS(uint8_t idx, uint8_t attr)
+{
+ ARM_MPU_SetMemAttrEx(MPU_NS, idx, attr);
+}
+#endif
+
+/** Clear and disable the given MPU region of the given MPU.
+* \param mpu Pointer to MPU to be used.
+* \param rnr Region number to be cleared.
+*/
+__STATIC_INLINE void ARM_MPU_ClrRegionEx(MPU_Type* mpu, uint32_t rnr)
+{
+ mpu->RNR = rnr;
+ mpu->RLAR = 0U;
+}
+
+/** Clear and disable the given MPU region.
+* \param rnr Region number to be cleared.
+*/
+__STATIC_INLINE void ARM_MPU_ClrRegion(uint32_t rnr)
+{
+ ARM_MPU_ClrRegionEx(MPU, rnr);
+}
+
+#ifdef MPU_NS
+/** Clear and disable the given Non-secure MPU region.
+* \param rnr Region number to be cleared.
+*/
+__STATIC_INLINE void ARM_MPU_ClrRegion_NS(uint32_t rnr)
+{
+ ARM_MPU_ClrRegionEx(MPU_NS, rnr);
+}
+#endif
+
+/** Configure the given MPU region of the given MPU.
+* \param mpu Pointer to MPU to be used.
+* \param rnr Region number to be configured.
+* \param rbar Value for RBAR register.
+* \param rlar Value for RLAR register.
+*/
+__STATIC_INLINE void ARM_MPU_SetRegionEx(MPU_Type* mpu, uint32_t rnr, uint32_t rbar, uint32_t rlar)
+{
+ mpu->RNR = rnr;
+ mpu->RBAR = rbar;
+ mpu->RLAR = rlar;
+}
+
+/** Configure the given MPU region.
+* \param rnr Region number to be configured.
+* \param rbar Value for RBAR register.
+* \param rlar Value for RLAR register.
+*/
+__STATIC_INLINE void ARM_MPU_SetRegion(uint32_t rnr, uint32_t rbar, uint32_t rlar)
+{
+ ARM_MPU_SetRegionEx(MPU, rnr, rbar, rlar);
+}
+
+#ifdef MPU_NS
+/** Configure the given Non-secure MPU region.
+* \param rnr Region number to be configured.
+* \param rbar Value for RBAR register.
+* \param rlar Value for RLAR register.
+*/
+__STATIC_INLINE void ARM_MPU_SetRegion_NS(uint32_t rnr, uint32_t rbar, uint32_t rlar)
+{
+ ARM_MPU_SetRegionEx(MPU_NS, rnr, rbar, rlar);
+}
+#endif
+
+/** Memcopy with strictly ordered memory access, e.g. for register targets.
+* \param dst Destination data is copied to.
+* \param src Source data is copied from.
+* \param len Amount of data words to be copied.
+*/
+__STATIC_INLINE void ARM_MPU_OrderedMemcpy(volatile uint32_t* dst, const uint32_t* __RESTRICT src, uint32_t len)
+{
+ uint32_t i;
+ for (i = 0U; i < len; ++i)
+ {
+ dst[i] = src[i];
+ }
+}
+
+/** Load the given number of MPU regions from a table to the given MPU.
+* \param mpu Pointer to the MPU registers to be used.
+* \param rnr First region number to be configured.
+* \param table Pointer to the MPU configuration table.
+* \param cnt Amount of regions to be configured.
+*/
+__STATIC_INLINE void ARM_MPU_LoadEx(MPU_Type* mpu, uint32_t rnr, ARM_MPU_Region_t const* table, uint32_t cnt)
+{
+ const uint32_t rowWordSize = sizeof(ARM_MPU_Region_t)/4U;
+ if (cnt == 1U) {
+ mpu->RNR = rnr;
+ ARM_MPU_OrderedMemcpy(&(mpu->RBAR), &(table->RBAR), rowWordSize);
+ } else {
+ uint32_t rnrBase = rnr & ~(MPU_TYPE_RALIASES-1U);
+ uint32_t rnrOffset = rnr % MPU_TYPE_RALIASES;
+
+ mpu->RNR = rnrBase;
+ while ((rnrOffset + cnt) > MPU_TYPE_RALIASES) {
+ uint32_t c = MPU_TYPE_RALIASES - rnrOffset;
+ ARM_MPU_OrderedMemcpy(&(mpu->RBAR)+(rnrOffset*2U), &(table->RBAR), c*rowWordSize);
+ table += c;
+ cnt -= c;
+ rnrOffset = 0U;
+ rnrBase += MPU_TYPE_RALIASES;
+ mpu->RNR = rnrBase;
+ }
+
+ ARM_MPU_OrderedMemcpy(&(mpu->RBAR)+(rnrOffset*2U), &(table->RBAR), cnt*rowWordSize);
+ }
+}
+
+/** Load the given number of MPU regions from a table.
+* \param rnr First region number to be configured.
+* \param table Pointer to the MPU configuration table.
+* \param cnt Amount of regions to be configured.
+*/
+__STATIC_INLINE void ARM_MPU_Load(uint32_t rnr, ARM_MPU_Region_t const* table, uint32_t cnt)
+{
+ ARM_MPU_LoadEx(MPU, rnr, table, cnt);
+}
+
+#ifdef MPU_NS
+/** Load the given number of MPU regions from a table to the Non-secure MPU.
+* \param rnr First region number to be configured.
+* \param table Pointer to the MPU configuration table.
+* \param cnt Amount of regions to be configured.
+*/
+__STATIC_INLINE void ARM_MPU_Load_NS(uint32_t rnr, ARM_MPU_Region_t const* table, uint32_t cnt)
+{
+ ARM_MPU_LoadEx(MPU_NS, rnr, table, cnt);
+}
+#endif
+
+#endif
+
diff --git a/lib/cmsis/inc/tz_context.h b/lib/cmsis/inc/tz_context.h
new file mode 100644
index 0000000000..0d09749f3a
--- /dev/null
+++ b/lib/cmsis/inc/tz_context.h
@@ -0,0 +1,70 @@
+/******************************************************************************
+ * @file tz_context.h
+ * @brief Context Management for Armv8-M TrustZone
+ * @version V1.0.1
+ * @date 10. January 2018
+ ******************************************************************************/
+/*
+ * Copyright (c) 2017-2018 Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#if defined ( __ICCARM__ )
+ #pragma system_include /* treat file as system include file for MISRA check */
+#elif defined (__clang__)
+ #pragma clang system_header /* treat file as system include file */
+#endif
+
+#ifndef TZ_CONTEXT_H
+#define TZ_CONTEXT_H
+
+#include
+
+#ifndef TZ_MODULEID_T
+#define TZ_MODULEID_T
+/// \details Data type that identifies secure software modules called by a process.
+typedef uint32_t TZ_ModuleId_t;
+#endif
+
+/// \details TZ Memory ID identifies an allocated memory slot.
+typedef uint32_t TZ_MemoryId_t;
+
+/// Initialize secure context memory system
+/// \return execution status (1: success, 0: error)
+uint32_t TZ_InitContextSystem_S (void);
+
+/// Allocate context memory for calling secure software modules in TrustZone
+/// \param[in] module identifies software modules called from non-secure mode
+/// \return value != 0 id TrustZone memory slot identifier
+/// \return value 0 no memory available or internal error
+TZ_MemoryId_t TZ_AllocModuleContext_S (TZ_ModuleId_t module);
+
+/// Free context memory that was previously allocated with \ref TZ_AllocModuleContext_S
+/// \param[in] id TrustZone memory slot identifier
+/// \return execution status (1: success, 0: error)
+uint32_t TZ_FreeModuleContext_S (TZ_MemoryId_t id);
+
+/// Load secure context (called on RTOS thread context switch)
+/// \param[in] id TrustZone memory slot identifier
+/// \return execution status (1: success, 0: error)
+uint32_t TZ_LoadContext_S (TZ_MemoryId_t id);
+
+/// Store secure context (called on RTOS thread context switch)
+/// \param[in] id TrustZone memory slot identifier
+/// \return execution status (1: success, 0: error)
+uint32_t TZ_StoreContext_S (TZ_MemoryId_t id);
+
+#endif // TZ_CONTEXT_H
diff --git a/lib/embed/__errno.c b/lib/embed/__errno.c
new file mode 100644
index 0000000000..86417a02dd
--- /dev/null
+++ b/lib/embed/__errno.c
@@ -0,0 +1,13 @@
+// This file provides a version of __errno() for embedded systems that do not have one.
+// This function is needed for expressions of the form: &errno
+
+static int embed_errno;
+
+#if defined(__linux__)
+int *__errno_location(void)
+#else
+int *__errno(void)
+#endif
+{
+ return &embed_errno;
+}
diff --git a/lib/embed/abort_.c b/lib/embed/abort_.c
index 2fba0de4ea..3051eae81e 100644
--- a/lib/embed/abort_.c
+++ b/lib/embed/abort_.c
@@ -3,5 +3,5 @@
NORETURN void abort_(void);
NORETURN void abort_(void) {
- mp_raise_msg(&mp_type_RuntimeError, "abort() called");
+ mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("abort() called"));
}
diff --git a/lib/libc/string0.c b/lib/libc/string0.c
index c2f2abd0f9..19ad14d0f7 100644
--- a/lib/libc/string0.c
+++ b/lib/libc/string0.c
@@ -169,6 +169,25 @@ char *strcpy(char *dest, const char *src) {
return dest;
}
+// Public Domain implementation of strncpy from:
+// http://en.wikibooks.org/wiki/C_Programming/Strings#The_strncpy_function
+char *strncpy(char *s1, const char *s2, size_t n) {
+ char *dst = s1;
+ const char *src = s2;
+ /* Copy bytes, one at a time. */
+ while (n > 0) {
+ n--;
+ if ((*dst++ = *src++) == '\0') {
+ /* If we get here, we found a null character at the end
+ of s2, so use memset to put null bytes at the end of
+ s1. */
+ memset(dst, '\0', n);
+ break;
+ }
+ }
+ return s1;
+ }
+
// needed because gcc optimises strcpy + strcat to this
char *stpcpy(char *dest, const char *src) {
while (*src) {
@@ -217,3 +236,19 @@ char *strstr(const char *haystack, const char *needle)
return (char *) haystack;
return 0;
}
+
+size_t strspn(const char *s, const char *accept) {
+ const char *ss = s;
+ while (*s && strchr(accept, *s) != NULL) {
+ ++s;
+ }
+ return s - ss;
+}
+
+size_t strcspn(const char *s, const char *reject) {
+ const char *ss = s;
+ while (*s && strchr(reject, *s) == NULL) {
+ ++s;
+ }
+ return s - ss;
+}
diff --git a/lib/libm/asinfacosf.c b/lib/libm/asinfacosf.c
index 07ecad3f3f..22dbb3d228 100644
--- a/lib/libm/asinfacosf.c
+++ b/lib/libm/asinfacosf.c
@@ -23,15 +23,15 @@
// dpgeorge: pio2 was double in original implementation of asinf
static const float
-pio2_hi = 1.5707962513e+00, /* 0x3fc90fda */
-pio2_lo = 7.5497894159e-08; /* 0x33a22168 */
+pio2_hi = 1.5707962513e+00f, /* 0x3fc90fda */
+pio2_lo = 7.5497894159e-08f; /* 0x33a22168 */
static const float
/* coefficients for R(x^2) */
-pS0 = 1.6666586697e-01,
-pS1 = -4.2743422091e-02,
-pS2 = -8.6563630030e-03,
-qS1 = -7.0662963390e-01;
+pS0 = 1.6666586697e-01f,
+pS1 = -4.2743422091e-02f,
+pS2 = -8.6563630030e-03f,
+qS1 = -7.0662963390e-01f;
static float R(float z)
{
diff --git a/lib/libm/atan2f.c b/lib/libm/atan2f.c
index 03d000c9e1..dcbaf821b5 100644
--- a/lib/libm/atan2f.c
+++ b/lib/libm/atan2f.c
@@ -22,8 +22,8 @@
#include "libm.h"
static const float
-pi = 3.1415927410e+00, /* 0x40490fdb */
-pi_lo = -8.7422776573e-08; /* 0xb3bbbd2e */
+pi = 3.1415927410e+00f, /* 0x40490fdb */
+pi_lo = -8.7422776573e-08f; /* 0xb3bbbd2e */
float atan2f(float y, float x)
{
diff --git a/lib/libm/atanf.c b/lib/libm/atanf.c
index 053fc1b6d6..40bc363c29 100644
--- a/lib/libm/atanf.c
+++ b/lib/libm/atanf.c
@@ -23,25 +23,25 @@
#include "libm.h"
static const float atanhi[] = {
- 4.6364760399e-01, /* atan(0.5)hi 0x3eed6338 */
- 7.8539812565e-01, /* atan(1.0)hi 0x3f490fda */
- 9.8279368877e-01, /* atan(1.5)hi 0x3f7b985e */
- 1.5707962513e+00, /* atan(inf)hi 0x3fc90fda */
+ 4.6364760399e-01f, /* atan(0.5)hi 0x3eed6338 */
+ 7.8539812565e-01f, /* atan(1.0)hi 0x3f490fda */
+ 9.8279368877e-01f, /* atan(1.5)hi 0x3f7b985e */
+ 1.5707962513e+00f, /* atan(inf)hi 0x3fc90fda */
};
static const float atanlo[] = {
- 5.0121582440e-09, /* atan(0.5)lo 0x31ac3769 */
- 3.7748947079e-08, /* atan(1.0)lo 0x33222168 */
- 3.4473217170e-08, /* atan(1.5)lo 0x33140fb4 */
- 7.5497894159e-08, /* atan(inf)lo 0x33a22168 */
+ 5.0121582440e-09f, /* atan(0.5)lo 0x31ac3769 */
+ 3.7748947079e-08f, /* atan(1.0)lo 0x33222168 */
+ 3.4473217170e-08f, /* atan(1.5)lo 0x33140fb4 */
+ 7.5497894159e-08f, /* atan(inf)lo 0x33a22168 */
};
static const float aT[] = {
- 3.3333328366e-01,
- -1.9999158382e-01,
- 1.4253635705e-01,
- -1.0648017377e-01,
- 6.1687607318e-02,
+ 3.3333328366e-01f,
+ -1.9999158382e-01f,
+ 1.4253635705e-01f,
+ -1.0648017377e-01f,
+ 6.1687607318e-02f,
};
float atanf(float x)
diff --git a/lib/libm/ef_rem_pio2.c b/lib/libm/ef_rem_pio2.c
index ca55243fb4..8111ca197f 100644
--- a/lib/libm/ef_rem_pio2.c
+++ b/lib/libm/ef_rem_pio2.c
@@ -93,16 +93,16 @@ static const float
#else
static float
#endif
-zero = 0.0000000000e+00, /* 0x00000000 */
-half = 5.0000000000e-01, /* 0x3f000000 */
-two8 = 2.5600000000e+02, /* 0x43800000 */
-invpio2 = 6.3661980629e-01, /* 0x3f22f984 */
-pio2_1 = 1.5707855225e+00, /* 0x3fc90f80 */
-pio2_1t = 1.0804334124e-05, /* 0x37354443 */
-pio2_2 = 1.0804273188e-05, /* 0x37354400 */
-pio2_2t = 6.0770999344e-11, /* 0x2e85a308 */
-pio2_3 = 6.0770943833e-11, /* 0x2e85a300 */
-pio2_3t = 6.1232342629e-17; /* 0x248d3132 */
+zero = 0.0000000000e+00f, /* 0x00000000 */
+half = 5.0000000000e-01f, /* 0x3f000000 */
+two8 = 2.5600000000e+02f, /* 0x43800000 */
+invpio2 = 6.3661980629e-01f, /* 0x3f22f984 */
+pio2_1 = 1.5707855225e+00f, /* 0x3fc90f80 */
+pio2_1t = 1.0804334124e-05f, /* 0x37354443 */
+pio2_2 = 1.0804273188e-05f, /* 0x37354400 */
+pio2_2t = 6.0770999344e-11f, /* 0x2e85a308 */
+pio2_3 = 6.0770943833e-11f, /* 0x2e85a300 */
+pio2_3t = 6.1232342629e-17f; /* 0x248d3132 */
#ifdef __STDC__
__int32_t __ieee754_rem_pio2f(float x, float *y)
diff --git a/lib/libm/ef_sqrt.c b/lib/libm/ef_sqrt.c
index 87484d0bf0..7f46ef6387 100644
--- a/lib/libm/ef_sqrt.c
+++ b/lib/libm/ef_sqrt.c
@@ -25,9 +25,9 @@
#include "fdlibm.h"
#ifdef __STDC__
-static const float one = 1.0, tiny=1.0e-30;
+static const float one = 1.0f, tiny=1.0e-30f;
#else
-static float one = 1.0, tiny=1.0e-30;
+static float one = 1.0f, tiny=1.0e-30f;
#endif
// sqrtf is exactly __ieee754_sqrtf when _IEEE_LIBM defined
diff --git a/lib/libm/erf_lgamma.c b/lib/libm/erf_lgamma.c
index 877816a0c2..1a33f47035 100644
--- a/lib/libm/erf_lgamma.c
+++ b/lib/libm/erf_lgamma.c
@@ -32,77 +32,77 @@ static const float
#else
static float
#endif
-two23= 8.3886080000e+06, /* 0x4b000000 */
-half= 5.0000000000e-01, /* 0x3f000000 */
-one = 1.0000000000e+00, /* 0x3f800000 */
-pi = 3.1415927410e+00, /* 0x40490fdb */
-a0 = 7.7215664089e-02, /* 0x3d9e233f */
-a1 = 3.2246702909e-01, /* 0x3ea51a66 */
-a2 = 6.7352302372e-02, /* 0x3d89f001 */
-a3 = 2.0580807701e-02, /* 0x3ca89915 */
-a4 = 7.3855509982e-03, /* 0x3bf2027e */
-a5 = 2.8905137442e-03, /* 0x3b3d6ec6 */
-a6 = 1.1927076848e-03, /* 0x3a9c54a1 */
-a7 = 5.1006977446e-04, /* 0x3a05b634 */
-a8 = 2.2086278477e-04, /* 0x39679767 */
-a9 = 1.0801156895e-04, /* 0x38e28445 */
-a10 = 2.5214456400e-05, /* 0x37d383a2 */
-a11 = 4.4864096708e-05, /* 0x383c2c75 */
-tc = 1.4616321325e+00, /* 0x3fbb16c3 */
-tf = -1.2148628384e-01, /* 0xbdf8cdcd */
+two23= 8.3886080000e+06f, /* 0x4b000000 */
+half= 5.0000000000e-01f, /* 0x3f000000 */
+one = 1.0000000000e+00f, /* 0x3f800000 */
+pi = 3.1415927410e+00f, /* 0x40490fdb */
+a0 = 7.7215664089e-02f, /* 0x3d9e233f */
+a1 = 3.2246702909e-01f, /* 0x3ea51a66 */
+a2 = 6.7352302372e-02f, /* 0x3d89f001 */
+a3 = 2.0580807701e-02f, /* 0x3ca89915 */
+a4 = 7.3855509982e-03f, /* 0x3bf2027e */
+a5 = 2.8905137442e-03f, /* 0x3b3d6ec6 */
+a6 = 1.1927076848e-03f, /* 0x3a9c54a1 */
+a7 = 5.1006977446e-04f, /* 0x3a05b634 */
+a8 = 2.2086278477e-04f, /* 0x39679767 */
+a9 = 1.0801156895e-04f, /* 0x38e28445 */
+a10 = 2.5214456400e-05f, /* 0x37d383a2 */
+a11 = 4.4864096708e-05f, /* 0x383c2c75 */
+tc = 1.4616321325e+00f, /* 0x3fbb16c3 */
+tf = -1.2148628384e-01f, /* 0xbdf8cdcd */
/* tt = -(tail of tf) */
-tt = 6.6971006518e-09, /* 0x31e61c52 */
-t0 = 4.8383611441e-01, /* 0x3ef7b95e */
-t1 = -1.4758771658e-01, /* 0xbe17213c */
-t2 = 6.4624942839e-02, /* 0x3d845a15 */
-t3 = -3.2788541168e-02, /* 0xbd064d47 */
-t4 = 1.7970675603e-02, /* 0x3c93373d */
-t5 = -1.0314224288e-02, /* 0xbc28fcfe */
-t6 = 6.1005386524e-03, /* 0x3bc7e707 */
-t7 = -3.6845202558e-03, /* 0xbb7177fe */
-t8 = 2.2596477065e-03, /* 0x3b141699 */
-t9 = -1.4034647029e-03, /* 0xbab7f476 */
-t10 = 8.8108185446e-04, /* 0x3a66f867 */
-t11 = -5.3859531181e-04, /* 0xba0d3085 */
-t12 = 3.1563205994e-04, /* 0x39a57b6b */
-t13 = -3.1275415677e-04, /* 0xb9a3f927 */
-t14 = 3.3552918467e-04, /* 0x39afe9f7 */
-u0 = -7.7215664089e-02, /* 0xbd9e233f */
-u1 = 6.3282704353e-01, /* 0x3f2200f4 */
-u2 = 1.4549225569e+00, /* 0x3fba3ae7 */
-u3 = 9.7771751881e-01, /* 0x3f7a4bb2 */
-u4 = 2.2896373272e-01, /* 0x3e6a7578 */
-u5 = 1.3381091878e-02, /* 0x3c5b3c5e */
-v1 = 2.4559779167e+00, /* 0x401d2ebe */
-v2 = 2.1284897327e+00, /* 0x4008392d */
-v3 = 7.6928514242e-01, /* 0x3f44efdf */
-v4 = 1.0422264785e-01, /* 0x3dd572af */
-v5 = 3.2170924824e-03, /* 0x3b52d5db */
-s0 = -7.7215664089e-02, /* 0xbd9e233f */
-s1 = 2.1498242021e-01, /* 0x3e5c245a */
-s2 = 3.2577878237e-01, /* 0x3ea6cc7a */
-s3 = 1.4635047317e-01, /* 0x3e15dce6 */
-s4 = 2.6642270386e-02, /* 0x3cda40e4 */
-s5 = 1.8402845599e-03, /* 0x3af135b4 */
-s6 = 3.1947532989e-05, /* 0x3805ff67 */
-r1 = 1.3920053244e+00, /* 0x3fb22d3b */
-r2 = 7.2193557024e-01, /* 0x3f38d0c5 */
-r3 = 1.7193385959e-01, /* 0x3e300f6e */
-r4 = 1.8645919859e-02, /* 0x3c98bf54 */
-r5 = 7.7794247773e-04, /* 0x3a4beed6 */
-r6 = 7.3266842264e-06, /* 0x36f5d7bd */
-w0 = 4.1893854737e-01, /* 0x3ed67f1d */
-w1 = 8.3333335817e-02, /* 0x3daaaaab */
-w2 = -2.7777778450e-03, /* 0xbb360b61 */
-w3 = 7.9365057172e-04, /* 0x3a500cfd */
-w4 = -5.9518753551e-04, /* 0xba1c065c */
-w5 = 8.3633989561e-04, /* 0x3a5b3dd2 */
-w6 = -1.6309292987e-03; /* 0xbad5c4e8 */
+tt = 6.6971006518e-09f, /* 0x31e61c52 */
+t0 = 4.8383611441e-01f, /* 0x3ef7b95e */
+t1 = -1.4758771658e-01f, /* 0xbe17213c */
+t2 = 6.4624942839e-02f, /* 0x3d845a15 */
+t3 = -3.2788541168e-02f, /* 0xbd064d47 */
+t4 = 1.7970675603e-02f, /* 0x3c93373d */
+t5 = -1.0314224288e-02f, /* 0xbc28fcfe */
+t6 = 6.1005386524e-03f, /* 0x3bc7e707 */
+t7 = -3.6845202558e-03f, /* 0xbb7177fe */
+t8 = 2.2596477065e-03f, /* 0x3b141699 */
+t9 = -1.4034647029e-03f, /* 0xbab7f476 */
+t10 = 8.8108185446e-04f, /* 0x3a66f867 */
+t11 = -5.3859531181e-04f, /* 0xba0d3085 */
+t12 = 3.1563205994e-04f, /* 0x39a57b6b */
+t13 = -3.1275415677e-04f, /* 0xb9a3f927 */
+t14 = 3.3552918467e-04f, /* 0x39afe9f7 */
+u0 = -7.7215664089e-02f, /* 0xbd9e233f */
+u1 = 6.3282704353e-01f, /* 0x3f2200f4 */
+u2 = 1.4549225569e+00f, /* 0x3fba3ae7 */
+u3 = 9.7771751881e-01f, /* 0x3f7a4bb2 */
+u4 = 2.2896373272e-01f, /* 0x3e6a7578 */
+u5 = 1.3381091878e-02f, /* 0x3c5b3c5e */
+v1 = 2.4559779167e+00f, /* 0x401d2ebe */
+v2 = 2.1284897327e+00f, /* 0x4008392d */
+v3 = 7.6928514242e-01f, /* 0x3f44efdf */
+v4 = 1.0422264785e-01f, /* 0x3dd572af */
+v5 = 3.2170924824e-03f, /* 0x3b52d5db */
+s0 = -7.7215664089e-02f, /* 0xbd9e233f */
+s1 = 2.1498242021e-01f, /* 0x3e5c245a */
+s2 = 3.2577878237e-01f, /* 0x3ea6cc7a */
+s3 = 1.4635047317e-01f, /* 0x3e15dce6 */
+s4 = 2.6642270386e-02f, /* 0x3cda40e4 */
+s5 = 1.8402845599e-03f, /* 0x3af135b4 */
+s6 = 3.1947532989e-05f, /* 0x3805ff67 */
+r1 = 1.3920053244e+00f, /* 0x3fb22d3b */
+r2 = 7.2193557024e-01f, /* 0x3f38d0c5 */
+r3 = 1.7193385959e-01f, /* 0x3e300f6e */
+r4 = 1.8645919859e-02f, /* 0x3c98bf54 */
+r5 = 7.7794247773e-04f, /* 0x3a4beed6 */
+r6 = 7.3266842264e-06f, /* 0x36f5d7bd */
+w0 = 4.1893854737e-01f, /* 0x3ed67f1d */
+w1 = 8.3333335817e-02f, /* 0x3daaaaab */
+w2 = -2.7777778450e-03f, /* 0xbb360b61 */
+w3 = 7.9365057172e-04f, /* 0x3a500cfd */
+w4 = -5.9518753551e-04f, /* 0xba1c065c */
+w5 = 8.3633989561e-04f, /* 0x3a5b3dd2 */
+w6 = -1.6309292987e-03f; /* 0xbad5c4e8 */
#ifdef __STDC__
-static const float zero= 0.0000000000e+00;
+static const float zero= 0.0000000000e+00f;
#else
-static float zero= 0.0000000000e+00;
+static float zero= 0.0000000000e+00f;
#endif
#ifdef __STDC__
diff --git a/lib/libm/kf_cos.c b/lib/libm/kf_cos.c
index 691f9842fd..58ffc65861 100644
--- a/lib/libm/kf_cos.c
+++ b/lib/libm/kf_cos.c
@@ -29,13 +29,13 @@ static const float
#else
static float
#endif
-one = 1.0000000000e+00, /* 0x3f800000 */
-C1 = 4.1666667908e-02, /* 0x3d2aaaab */
-C2 = -1.3888889225e-03, /* 0xbab60b61 */
-C3 = 2.4801587642e-05, /* 0x37d00d01 */
-C4 = -2.7557314297e-07, /* 0xb493f27c */
-C5 = 2.0875723372e-09, /* 0x310f74f6 */
-C6 = -1.1359647598e-11; /* 0xad47d74e */
+one = 1.0000000000e+00f, /* 0x3f800000 */
+C1 = 4.1666667908e-02f, /* 0x3d2aaaab */
+C2 = -1.3888889225e-03f, /* 0xbab60b61 */
+C3 = 2.4801587642e-05f, /* 0x37d00d01 */
+C4 = -2.7557314297e-07f, /* 0xb493f27c */
+C5 = 2.0875723372e-09f, /* 0x310f74f6 */
+C6 = -1.1359647598e-11f; /* 0xad47d74e */
#ifdef __STDC__
float __kernel_cosf(float x, float y)
diff --git a/lib/libm/kf_rem_pio2.c b/lib/libm/kf_rem_pio2.c
index c7e9479571..6bd4d287e6 100644
--- a/lib/libm/kf_rem_pio2.c
+++ b/lib/libm/kf_rem_pio2.c
@@ -38,17 +38,17 @@ static const float PIo2[] = {
#else
static float PIo2[] = {
#endif
- 1.5703125000e+00, /* 0x3fc90000 */
- 4.5776367188e-04, /* 0x39f00000 */
- 2.5987625122e-05, /* 0x37da0000 */
- 7.5437128544e-08, /* 0x33a20000 */
- 6.0026650317e-11, /* 0x2e840000 */
- 7.3896444519e-13, /* 0x2b500000 */
- 5.3845816694e-15, /* 0x27c20000 */
- 5.6378512969e-18, /* 0x22d00000 */
- 8.3009228831e-20, /* 0x1fc40000 */
- 3.2756352257e-22, /* 0x1bc60000 */
- 6.3331015649e-25, /* 0x17440000 */
+ 1.5703125000e+00f, /* 0x3fc90000 */
+ 4.5776367188e-04f, /* 0x39f00000 */
+ 2.5987625122e-05f, /* 0x37da0000 */
+ 7.5437128544e-08f, /* 0x33a20000 */
+ 6.0026650317e-11f, /* 0x2e840000 */
+ 7.3896444519e-13f, /* 0x2b500000 */
+ 5.3845816694e-15f, /* 0x27c20000 */
+ 5.6378512969e-18f, /* 0x22d00000 */
+ 8.3009228831e-20f, /* 0x1fc40000 */
+ 3.2756352257e-22f, /* 0x1bc60000 */
+ 6.3331015649e-25f, /* 0x17440000 */
};
#ifdef __STDC__
@@ -56,10 +56,10 @@ static const float
#else
static float
#endif
-zero = 0.0,
-one = 1.0,
-two8 = 2.5600000000e+02, /* 0x43800000 */
-twon8 = 3.9062500000e-03; /* 0x3b800000 */
+zero = 0.0f,
+one = 1.0f,
+two8 = 2.5600000000e+02f, /* 0x43800000 */
+twon8 = 3.9062500000e-03f; /* 0x3b800000 */
#ifdef __STDC__
int __kernel_rem_pio2f(float *x, float *y, int e0, int nx, int prec, const __int32_t *ipio2)
diff --git a/lib/libm/kf_sin.c b/lib/libm/kf_sin.c
index 07ea993446..5fb86fbe82 100644
--- a/lib/libm/kf_sin.c
+++ b/lib/libm/kf_sin.c
@@ -29,13 +29,13 @@ static const float
#else
static float
#endif
-half = 5.0000000000e-01,/* 0x3f000000 */
-S1 = -1.6666667163e-01, /* 0xbe2aaaab */
-S2 = 8.3333337680e-03, /* 0x3c088889 */
-S3 = -1.9841270114e-04, /* 0xb9500d01 */
-S4 = 2.7557314297e-06, /* 0x3638ef1b */
-S5 = -2.5050759689e-08, /* 0xb2d72f34 */
-S6 = 1.5896910177e-10; /* 0x2f2ec9d3 */
+half = 5.0000000000e-01f,/* 0x3f000000 */
+S1 = -1.6666667163e-01f, /* 0xbe2aaaab */
+S2 = 8.3333337680e-03f, /* 0x3c088889 */
+S3 = -1.9841270114e-04f, /* 0xb9500d01 */
+S4 = 2.7557314297e-06f, /* 0x3638ef1b */
+S5 = -2.5050759689e-08f, /* 0xb2d72f34 */
+S6 = 1.5896910177e-10f; /* 0x2f2ec9d3 */
#ifdef __STDC__
float __kernel_sinf(float x, float y, int iy)
diff --git a/lib/libm/kf_tan.c b/lib/libm/kf_tan.c
index 6da9bd8171..a9c8993394 100644
--- a/lib/libm/kf_tan.c
+++ b/lib/libm/kf_tan.c
@@ -28,23 +28,23 @@ static const float
#else
static float
#endif
-one = 1.0000000000e+00, /* 0x3f800000 */
-pio4 = 7.8539812565e-01, /* 0x3f490fda */
-pio4lo= 3.7748947079e-08, /* 0x33222168 */
+one = 1.0000000000e+00f, /* 0x3f800000 */
+pio4 = 7.8539812565e-01f, /* 0x3f490fda */
+pio4lo= 3.7748947079e-08f, /* 0x33222168 */
T[] = {
- 3.3333334327e-01, /* 0x3eaaaaab */
- 1.3333334029e-01, /* 0x3e088889 */
- 5.3968254477e-02, /* 0x3d5d0dd1 */
- 2.1869488060e-02, /* 0x3cb327a4 */
- 8.8632395491e-03, /* 0x3c11371f */
- 3.5920790397e-03, /* 0x3b6b6916 */
- 1.4562094584e-03, /* 0x3abede48 */
- 5.8804126456e-04, /* 0x3a1a26c8 */
- 2.4646313977e-04, /* 0x398137b9 */
- 7.8179444245e-05, /* 0x38a3f445 */
- 7.1407252108e-05, /* 0x3895c07a */
- -1.8558637748e-05, /* 0xb79bae5f */
- 2.5907305826e-05, /* 0x37d95384 */
+ 3.3333334327e-01f, /* 0x3eaaaaab */
+ 1.3333334029e-01f, /* 0x3e088889 */
+ 5.3968254477e-02f, /* 0x3d5d0dd1 */
+ 2.1869488060e-02f, /* 0x3cb327a4 */
+ 8.8632395491e-03f, /* 0x3c11371f */
+ 3.5920790397e-03f, /* 0x3b6b6916 */
+ 1.4562094584e-03f, /* 0x3abede48 */
+ 5.8804126456e-04f, /* 0x3a1a26c8 */
+ 2.4646313977e-04f, /* 0x398137b9 */
+ 7.8179444245e-05f, /* 0x38a3f445 */
+ 7.1407252108e-05f, /* 0x3895c07a */
+ -1.8558637748e-05f, /* 0xb79bae5f */
+ 2.5907305826e-05f, /* 0x37d95384 */
};
#ifdef __STDC__
diff --git a/lib/libm/log1pf.c b/lib/libm/log1pf.c
index 0d32b0a2fe..9585f5b801 100644
--- a/lib/libm/log1pf.c
+++ b/lib/libm/log1pf.c
@@ -19,13 +19,13 @@
#include "libm.h"
static const float
-ln2_hi = 6.9313812256e-01, /* 0x3f317180 */
-ln2_lo = 9.0580006145e-06, /* 0x3717f7d1 */
+ln2_hi = 6.9313812256e-01f, /* 0x3f317180 */
+ln2_lo = 9.0580006145e-06f, /* 0x3717f7d1 */
/* |(log(1+s)-log(1-s))/s - Lg(s)| < 2**-34.24 (~[-4.95e-11, 4.97e-11]). */
-Lg1 = 0xaaaaaa.0p-24, /* 0.66666662693 */
-Lg2 = 0xccce13.0p-25, /* 0.40000972152 */
-Lg3 = 0x91e9ee.0p-25, /* 0.28498786688 */
-Lg4 = 0xf89e26.0p-26; /* 0.24279078841 */
+Lg1 = 0xaaaaaa.0p-24f, /* 0.66666662693 */
+Lg2 = 0xccce13.0p-25f, /* 0.40000972152 */
+Lg3 = 0x91e9ee.0p-25f, /* 0.28498786688 */
+Lg4 = 0xf89e26.0p-26f; /* 0.24279078841 */
float log1pf(float x)
{
diff --git a/lib/libm/math.c b/lib/libm/math.c
index c23b9f8d36..3dfd925655 100644
--- a/lib/libm/math.c
+++ b/lib/libm/math.c
@@ -53,7 +53,7 @@ float copysignf(float x, float y) {
}
#endif
-static const float _M_LN10 = 2.30258509299404; // 0x40135d8e
+static const float _M_LN10 = 2.30258509299404f; // 0x40135d8e
float log10f(float x) { return logf(x) / (float)_M_LN10; }
float tanhf(float x) {
@@ -139,34 +139,34 @@ float scalbnf(float x, int n)
*/
static const float
-bp[] = {1.0, 1.5,},
-dp_h[] = { 0.0, 5.84960938e-01,}, /* 0x3f15c000 */
-dp_l[] = { 0.0, 1.56322085e-06,}, /* 0x35d1cfdc */
-two24 = 16777216.0, /* 0x4b800000 */
-huge = 1.0e30,
-tiny = 1.0e-30,
+bp[] = {1.0f, 1.5f,},
+dp_h[] = { 0.0f, 5.84960938e-01f,}, /* 0x3f15c000 */
+dp_l[] = { 0.0f, 1.56322085e-06f,}, /* 0x35d1cfdc */
+two24 = 16777216.0f, /* 0x4b800000 */
+huge = 1.0e30f,
+tiny = 1.0e-30f,
/* poly coefs for (3/2)*(log(x)-2s-2/3*s**3 */
-L1 = 6.0000002384e-01, /* 0x3f19999a */
-L2 = 4.2857143283e-01, /* 0x3edb6db7 */
-L3 = 3.3333334327e-01, /* 0x3eaaaaab */
-L4 = 2.7272811532e-01, /* 0x3e8ba305 */
-L5 = 2.3066075146e-01, /* 0x3e6c3255 */
-L6 = 2.0697501302e-01, /* 0x3e53f142 */
-P1 = 1.6666667163e-01, /* 0x3e2aaaab */
-P2 = -2.7777778450e-03, /* 0xbb360b61 */
-P3 = 6.6137559770e-05, /* 0x388ab355 */
-P4 = -1.6533901999e-06, /* 0xb5ddea0e */
-P5 = 4.1381369442e-08, /* 0x3331bb4c */
-lg2 = 6.9314718246e-01, /* 0x3f317218 */
-lg2_h = 6.93145752e-01, /* 0x3f317200 */
-lg2_l = 1.42860654e-06, /* 0x35bfbe8c */
-ovt = 4.2995665694e-08, /* -(128-log2(ovfl+.5ulp)) */
-cp = 9.6179670095e-01, /* 0x3f76384f =2/(3ln2) */
-cp_h = 9.6191406250e-01, /* 0x3f764000 =12b cp */
-cp_l = -1.1736857402e-04, /* 0xb8f623c6 =tail of cp_h */
-ivln2 = 1.4426950216e+00, /* 0x3fb8aa3b =1/ln2 */
-ivln2_h = 1.4426879883e+00, /* 0x3fb8aa00 =16b 1/ln2*/
-ivln2_l = 7.0526075433e-06; /* 0x36eca570 =1/ln2 tail*/
+L1 = 6.0000002384e-01f, /* 0x3f19999a */
+L2 = 4.2857143283e-01f, /* 0x3edb6db7 */
+L3 = 3.3333334327e-01f, /* 0x3eaaaaab */
+L4 = 2.7272811532e-01f, /* 0x3e8ba305 */
+L5 = 2.3066075146e-01f, /* 0x3e6c3255 */
+L6 = 2.0697501302e-01f, /* 0x3e53f142 */
+P1 = 1.6666667163e-01f, /* 0x3e2aaaab */
+P2 = -2.7777778450e-03f, /* 0xbb360b61 */
+P3 = 6.6137559770e-05f, /* 0x388ab355 */
+P4 = -1.6533901999e-06f, /* 0xb5ddea0e */
+P5 = 4.1381369442e-08f, /* 0x3331bb4c */
+lg2 = 6.9314718246e-01f, /* 0x3f317218 */
+lg2_h = 6.93145752e-01f, /* 0x3f317200 */
+lg2_l = 1.42860654e-06f, /* 0x35bfbe8c */
+ovt = 4.2995665694e-08f, /* -(128-log2(ovfl+.5ulp)) */
+cp = 9.6179670095e-01f, /* 0x3f76384f =2/(3ln2) */
+cp_h = 9.6191406250e-01f, /* 0x3f764000 =12b cp */
+cp_l = -1.1736857402e-04f, /* 0xb8f623c6 =tail of cp_h */
+ivln2 = 1.4426950216e+00f, /* 0x3fb8aa3b =1/ln2 */
+ivln2_h = 1.4426879883e+00f, /* 0x3fb8aa00 =16b 1/ln2*/
+ivln2_l = 7.0526075433e-06f; /* 0x36eca570 =1/ln2 tail*/
float powf(float x, float y)
{
@@ -403,7 +403,7 @@ float powf(float x, float y)
*/
static const float
-half[2] = {0.5,-0.5},
+half[2] = {0.5f,-0.5f},
ln2hi = 6.9314575195e-1f, /* 0x3f317200 */
ln2lo = 1.4286067653e-6f, /* 0x35bfbe8e */
invln2 = 1.4426950216e+0f, /* 0x3fb8aa3b */
@@ -442,7 +442,7 @@ float expf(float x)
/* argument reduction */
if (hx > 0x3eb17218) { /* if |x| > 0.5 ln2 */
if (hx > 0x3f851592) /* if |x| > 1.5 ln2 */
- k = invln2*x + half[sign];
+ k = (int)(invln2*x + half[sign]);
else
k = 1 - sign - sign;
hi = x - k*ln2hi; /* k*ln2hi is exact here */
@@ -489,17 +489,17 @@ float expf(float x)
*/
static const float
-o_threshold = 8.8721679688e+01, /* 0x42b17180 */
-ln2_hi = 6.9313812256e-01, /* 0x3f317180 */
-ln2_lo = 9.0580006145e-06, /* 0x3717f7d1 */
+o_threshold = 8.8721679688e+01f, /* 0x42b17180 */
+ln2_hi = 6.9313812256e-01f, /* 0x3f317180 */
+ln2_lo = 9.0580006145e-06f, /* 0x3717f7d1 */
//invln2 = 1.4426950216e+00, /* 0x3fb8aa3b */
/*
* Domain [-0.34568, 0.34568], range ~[-6.694e-10, 6.696e-10]:
* |6 / x * (1 + 2 * (1 / (exp(x) - 1) - 1 / x)) - q(x)| < 2**-30.04
* Scaled coefficients: Qn_here = 2**n * Qn_for_q (see s_expm1.c):
*/
-Q1 = -3.3333212137e-2, /* -0x888868.0p-28 */
-Q2 = 1.5807170421e-3; /* 0xcf3010.0p-33 */
+Q1 = -3.3333212137e-2f, /* -0x888868.0p-28 */
+Q2 = 1.5807170421e-3f; /* 0xcf3010.0p-33 */
float expm1f(float x)
{
@@ -533,7 +533,7 @@ float expm1f(float x)
k = -1;
}
} else {
- k = invln2*x + (sign ? -0.5f : 0.5f);
+ k = (int)(invln2*x + (sign ? -0.5f : 0.5f));
t = k;
hi = x - t*ln2_hi; /* t*ln2_hi is exact here */
lo = t*ln2_lo;
diff --git a/lib/libm/sf_erf.c b/lib/libm/sf_erf.c
index 3f0172c6e9..85af35afd7 100644
--- a/lib/libm/sf_erf.c
+++ b/lib/libm/sf_erf.c
@@ -35,79 +35,79 @@ static const float
#else
static float
#endif
-tiny = 1e-30,
-half= 5.0000000000e-01, /* 0x3F000000 */
-one = 1.0000000000e+00, /* 0x3F800000 */
-two = 2.0000000000e+00, /* 0x40000000 */
+tiny = 1e-30f,
+half= 5.0000000000e-01f, /* 0x3F000000 */
+one = 1.0000000000e+00f, /* 0x3F800000 */
+two = 2.0000000000e+00f, /* 0x40000000 */
/* c = (subfloat)0.84506291151 */
-erx = 8.4506291151e-01, /* 0x3f58560b */
+erx = 8.4506291151e-01f, /* 0x3f58560b */
/*
* Coefficients for approximation to erf on [0,0.84375]
*/
-efx = 1.2837916613e-01, /* 0x3e0375d4 */
-efx8= 1.0270333290e+00, /* 0x3f8375d4 */
-pp0 = 1.2837916613e-01, /* 0x3e0375d4 */
-pp1 = -3.2504209876e-01, /* 0xbea66beb */
-pp2 = -2.8481749818e-02, /* 0xbce9528f */
-pp3 = -5.7702702470e-03, /* 0xbbbd1489 */
-pp4 = -2.3763017452e-05, /* 0xb7c756b1 */
-qq1 = 3.9791721106e-01, /* 0x3ecbbbce */
-qq2 = 6.5022252500e-02, /* 0x3d852a63 */
-qq3 = 5.0813062117e-03, /* 0x3ba68116 */
-qq4 = 1.3249473704e-04, /* 0x390aee49 */
-qq5 = -3.9602282413e-06, /* 0xb684e21a */
+efx = 1.2837916613e-01f, /* 0x3e0375d4 */
+efx8= 1.0270333290e+00f, /* 0x3f8375d4 */
+pp0 = 1.2837916613e-01f, /* 0x3e0375d4 */
+pp1 = -3.2504209876e-01f, /* 0xbea66beb */
+pp2 = -2.8481749818e-02f, /* 0xbce9528f */
+pp3 = -5.7702702470e-03f, /* 0xbbbd1489 */
+pp4 = -2.3763017452e-05f, /* 0xb7c756b1 */
+qq1 = 3.9791721106e-01f, /* 0x3ecbbbce */
+qq2 = 6.5022252500e-02f, /* 0x3d852a63 */
+qq3 = 5.0813062117e-03f, /* 0x3ba68116 */
+qq4 = 1.3249473704e-04f, /* 0x390aee49 */
+qq5 = -3.9602282413e-06f, /* 0xb684e21a */
/*
* Coefficients for approximation to erf in [0.84375,1.25]
*/
-pa0 = -2.3621185683e-03, /* 0xbb1acdc6 */
-pa1 = 4.1485610604e-01, /* 0x3ed46805 */
-pa2 = -3.7220788002e-01, /* 0xbebe9208 */
-pa3 = 3.1834661961e-01, /* 0x3ea2fe54 */
-pa4 = -1.1089469492e-01, /* 0xbde31cc2 */
-pa5 = 3.5478305072e-02, /* 0x3d1151b3 */
-pa6 = -2.1663755178e-03, /* 0xbb0df9c0 */
-qa1 = 1.0642088205e-01, /* 0x3dd9f331 */
-qa2 = 5.4039794207e-01, /* 0x3f0a5785 */
-qa3 = 7.1828655899e-02, /* 0x3d931ae7 */
-qa4 = 1.2617121637e-01, /* 0x3e013307 */
-qa5 = 1.3637083583e-02, /* 0x3c5f6e13 */
-qa6 = 1.1984500103e-02, /* 0x3c445aa3 */
+pa0 = -2.3621185683e-03f, /* 0xbb1acdc6 */
+pa1 = 4.1485610604e-01f, /* 0x3ed46805 */
+pa2 = -3.7220788002e-01f, /* 0xbebe9208 */
+pa3 = 3.1834661961e-01f, /* 0x3ea2fe54 */
+pa4 = -1.1089469492e-01f, /* 0xbde31cc2 */
+pa5 = 3.5478305072e-02f, /* 0x3d1151b3 */
+pa6 = -2.1663755178e-03f, /* 0xbb0df9c0 */
+qa1 = 1.0642088205e-01f, /* 0x3dd9f331 */
+qa2 = 5.4039794207e-01f, /* 0x3f0a5785 */
+qa3 = 7.1828655899e-02f, /* 0x3d931ae7 */
+qa4 = 1.2617121637e-01f, /* 0x3e013307 */
+qa5 = 1.3637083583e-02f, /* 0x3c5f6e13 */
+qa6 = 1.1984500103e-02f, /* 0x3c445aa3 */
/*
* Coefficients for approximation to erfc in [1.25,1/0.35]
*/
-ra0 = -9.8649440333e-03, /* 0xbc21a093 */
-ra1 = -6.9385856390e-01, /* 0xbf31a0b7 */
-ra2 = -1.0558626175e+01, /* 0xc128f022 */
-ra3 = -6.2375331879e+01, /* 0xc2798057 */
-ra4 = -1.6239666748e+02, /* 0xc322658c */
-ra5 = -1.8460508728e+02, /* 0xc3389ae7 */
-ra6 = -8.1287437439e+01, /* 0xc2a2932b */
-ra7 = -9.8143291473e+00, /* 0xc11d077e */
-sa1 = 1.9651271820e+01, /* 0x419d35ce */
-sa2 = 1.3765776062e+02, /* 0x4309a863 */
-sa3 = 4.3456588745e+02, /* 0x43d9486f */
-sa4 = 6.4538726807e+02, /* 0x442158c9 */
-sa5 = 4.2900814819e+02, /* 0x43d6810b */
-sa6 = 1.0863500214e+02, /* 0x42d9451f */
-sa7 = 6.5702495575e+00, /* 0x40d23f7c */
-sa8 = -6.0424413532e-02, /* 0xbd777f97 */
+ra0 = -9.8649440333e-03f, /* 0xbc21a093 */
+ra1 = -6.9385856390e-01f, /* 0xbf31a0b7 */
+ra2 = -1.0558626175e+01f, /* 0xc128f022 */
+ra3 = -6.2375331879e+01f, /* 0xc2798057 */
+ra4 = -1.6239666748e+02f, /* 0xc322658c */
+ra5 = -1.8460508728e+02f, /* 0xc3389ae7 */
+ra6 = -8.1287437439e+01f, /* 0xc2a2932b */
+ra7 = -9.8143291473e+00f, /* 0xc11d077e */
+sa1 = 1.9651271820e+01f, /* 0x419d35ce */
+sa2 = 1.3765776062e+02f, /* 0x4309a863 */
+sa3 = 4.3456588745e+02f, /* 0x43d9486f */
+sa4 = 6.4538726807e+02f, /* 0x442158c9 */
+sa5 = 4.2900814819e+02f, /* 0x43d6810b */
+sa6 = 1.0863500214e+02f, /* 0x42d9451f */
+sa7 = 6.5702495575e+00f, /* 0x40d23f7c */
+sa8 = -6.0424413532e-02f, /* 0xbd777f97 */
/*
* Coefficients for approximation to erfc in [1/.35,28]
*/
-rb0 = -9.8649431020e-03, /* 0xbc21a092 */
-rb1 = -7.9928326607e-01, /* 0xbf4c9dd4 */
-rb2 = -1.7757955551e+01, /* 0xc18e104b */
-rb3 = -1.6063638306e+02, /* 0xc320a2ea */
-rb4 = -6.3756646729e+02, /* 0xc41f6441 */
-rb5 = -1.0250950928e+03, /* 0xc480230b */
-rb6 = -4.8351919556e+02, /* 0xc3f1c275 */
-sb1 = 3.0338060379e+01, /* 0x41f2b459 */
-sb2 = 3.2579251099e+02, /* 0x43a2e571 */
-sb3 = 1.5367296143e+03, /* 0x44c01759 */
-sb4 = 3.1998581543e+03, /* 0x4547fdbb */
-sb5 = 2.5530502930e+03, /* 0x451f90ce */
-sb6 = 4.7452853394e+02, /* 0x43ed43a7 */
-sb7 = -2.2440952301e+01; /* 0xc1b38712 */
+rb0 = -9.8649431020e-03f, /* 0xbc21a092 */
+rb1 = -7.9928326607e-01f, /* 0xbf4c9dd4 */
+rb2 = -1.7757955551e+01f, /* 0xc18e104b */
+rb3 = -1.6063638306e+02f, /* 0xc320a2ea */
+rb4 = -6.3756646729e+02f, /* 0xc41f6441 */
+rb5 = -1.0250950928e+03f, /* 0xc480230b */
+rb6 = -4.8351919556e+02f, /* 0xc3f1c275 */
+sb1 = 3.0338060379e+01f, /* 0x41f2b459 */
+sb2 = 3.2579251099e+02f, /* 0x43a2e571 */
+sb3 = 1.5367296143e+03f, /* 0x44c01759 */
+sb4 = 3.1998581543e+03f, /* 0x4547fdbb */
+sb5 = 2.5530502930e+03f, /* 0x451f90ce */
+sb6 = 4.7452853394e+02f, /* 0x43ed43a7 */
+sb7 = -2.2440952301e+01f; /* 0xc1b38712 */
#ifdef __STDC__
float erff(float x)
diff --git a/lib/libm/sf_frexp.c b/lib/libm/sf_frexp.c
index df50fb7737..378f21fb2f 100644
--- a/lib/libm/sf_frexp.c
+++ b/lib/libm/sf_frexp.c
@@ -29,7 +29,7 @@ static const float
#else
static float
#endif
-two25 = 3.3554432000e+07; /* 0x4c000000 */
+two25 = 3.3554432000e+07f; /* 0x4c000000 */
#ifdef __STDC__
float frexpf(float x, int *eptr)
diff --git a/lib/libm/sf_ldexp.c b/lib/libm/sf_ldexp.c
index 37968d475a..31dd9b3d8d 100644
--- a/lib/libm/sf_ldexp.c
+++ b/lib/libm/sf_ldexp.c
@@ -23,7 +23,6 @@
*/
#include "fdlibm.h"
-//#include
#ifdef __STDC__
float ldexpf(float value, int exp)
diff --git a/lib/libm/sf_modf.c b/lib/libm/sf_modf.c
index 410db2a373..7c1b81399d 100644
--- a/lib/libm/sf_modf.c
+++ b/lib/libm/sf_modf.c
@@ -25,9 +25,9 @@
#include "fdlibm.h"
#ifdef __STDC__
-static const float one = 1.0;
+static const float one = 1.0f;
#else
-static float one = 1.0;
+static float one = 1.0f;
#endif
#ifdef __STDC__
diff --git a/lib/libm/wf_lgamma.c b/lib/libm/wf_lgamma.c
index d86ede790b..834a4de482 100644
--- a/lib/libm/wf_lgamma.c
+++ b/lib/libm/wf_lgamma.c
@@ -25,8 +25,6 @@
#include "fdlibm.h"
#define _IEEE_LIBM 1
-//#include
-//#include
#ifdef __STDC__
float lgammaf(float x)
diff --git a/lib/libm_dbl/nearbyint.c b/lib/libm_dbl/nearbyint.c
index 6e9b0c1f78..c3a0b88afe 100644
--- a/lib/libm_dbl/nearbyint.c
+++ b/lib/libm_dbl/nearbyint.c
@@ -1,4 +1,3 @@
-//#include
#include
/* nearbyint is the same as rint, but it must not raise the inexact exception */
diff --git a/lib/libm_dbl/round.c b/lib/libm_dbl/round.c
new file mode 100644
index 0000000000..130d58d257
--- /dev/null
+++ b/lib/libm_dbl/round.c
@@ -0,0 +1,35 @@
+#include "libm.h"
+
+#if FLT_EVAL_METHOD==0 || FLT_EVAL_METHOD==1
+#define EPS DBL_EPSILON
+#elif FLT_EVAL_METHOD==2
+#define EPS LDBL_EPSILON
+#endif
+static const double_t toint = 1/EPS;
+
+double round(double x)
+{
+ union {double f; uint64_t i;} u = {x};
+ int e = u.i >> 52 & 0x7ff;
+ double_t y;
+
+ if (e >= 0x3ff+52)
+ return x;
+ if (u.i >> 63)
+ x = -x;
+ if (e < 0x3ff-1) {
+ /* raise inexact if x!=0 */
+ FORCE_EVAL(x + toint);
+ return 0*u.f;
+ }
+ y = x + toint - toint - x;
+ if (y > 0.5)
+ y = y + x - 1;
+ else if (y <= -0.5)
+ y = y + x + 1;
+ else
+ y = y + x;
+ if (u.i >> 63)
+ y = -y;
+ return y;
+}
diff --git a/lib/libm_dbl/thumb_vfp_sqrt.c b/lib/libm_dbl/thumb_vfp_sqrt.c
new file mode 100644
index 0000000000..dd37a07b05
--- /dev/null
+++ b/lib/libm_dbl/thumb_vfp_sqrt.c
@@ -0,0 +1,10 @@
+// an implementation of sqrt for Thumb using hardware double-precision VFP instructions
+
+double sqrt(double x) {
+ double ret;
+ asm volatile (
+ "vsqrt.f64 %P0, %P1\n"
+ : "=w" (ret)
+ : "w" (x));
+ return ret;
+}
diff --git a/lib/littlefs/README.md b/lib/littlefs/README.md
new file mode 100644
index 0000000000..1f0aacbf98
--- /dev/null
+++ b/lib/littlefs/README.md
@@ -0,0 +1,19 @@
+littlefs library
+================
+
+The upstream source for the files in this directory is
+https://github.com/ARMmbed/littlefs
+
+To generate the separate files with lfs1 and lfs2 prefixes run the following
+commands in the top-level directory of the littlefs repository (replace the
+version tags with the latest/desired ones, and set `$MPY_DIR`):
+
+ git checkout v1.7.2
+ python2 ./scripts/prefix.py lfs1
+ cp lfs1*.[ch] $MPY_DIR/lib/littlefs
+ git reset --hard HEAD
+
+ git checkout v2.1.3
+ python2 ./scripts/prefix.py lfs2
+ cp lfs2*.[ch] $MPY_DIR/lib/littlefs
+ git reset --hard HEAD
diff --git a/lib/littlefs/lfs1.c b/lib/littlefs/lfs1.c
new file mode 100644
index 0000000000..6a3fd67001
--- /dev/null
+++ b/lib/littlefs/lfs1.c
@@ -0,0 +1,2583 @@
+/*
+ * The little filesystem
+ *
+ * Copyright (c) 2017, Arm Limited. All rights reserved.
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include "lfs1.h"
+#include "lfs1_util.h"
+
+#include
+
+
+/// Caching block device operations ///
+static int lfs1_cache_read(lfs1_t *lfs1, lfs1_cache_t *rcache,
+ const lfs1_cache_t *pcache, lfs1_block_t block,
+ lfs1_off_t off, void *buffer, lfs1_size_t size) {
+ uint8_t *data = buffer;
+ LFS1_ASSERT(block < lfs1->cfg->block_count);
+
+ while (size > 0) {
+ if (pcache && block == pcache->block && off >= pcache->off &&
+ off < pcache->off + lfs1->cfg->prog_size) {
+ // is already in pcache?
+ lfs1_size_t diff = lfs1_min(size,
+ lfs1->cfg->prog_size - (off-pcache->off));
+ memcpy(data, &pcache->buffer[off-pcache->off], diff);
+
+ data += diff;
+ off += diff;
+ size -= diff;
+ continue;
+ }
+
+ if (block == rcache->block && off >= rcache->off &&
+ off < rcache->off + lfs1->cfg->read_size) {
+ // is already in rcache?
+ lfs1_size_t diff = lfs1_min(size,
+ lfs1->cfg->read_size - (off-rcache->off));
+ memcpy(data, &rcache->buffer[off-rcache->off], diff);
+
+ data += diff;
+ off += diff;
+ size -= diff;
+ continue;
+ }
+
+ if (off % lfs1->cfg->read_size == 0 && size >= lfs1->cfg->read_size) {
+ // bypass cache?
+ lfs1_size_t diff = size - (size % lfs1->cfg->read_size);
+ int err = lfs1->cfg->read(lfs1->cfg, block, off, data, diff);
+ if (err) {
+ return err;
+ }
+
+ data += diff;
+ off += diff;
+ size -= diff;
+ continue;
+ }
+
+ // load to cache, first condition can no longer fail
+ rcache->block = block;
+ rcache->off = off - (off % lfs1->cfg->read_size);
+ int err = lfs1->cfg->read(lfs1->cfg, rcache->block,
+ rcache->off, rcache->buffer, lfs1->cfg->read_size);
+ if (err) {
+ return err;
+ }
+ }
+
+ return 0;
+}
+
+static int lfs1_cache_cmp(lfs1_t *lfs1, lfs1_cache_t *rcache,
+ const lfs1_cache_t *pcache, lfs1_block_t block,
+ lfs1_off_t off, const void *buffer, lfs1_size_t size) {
+ const uint8_t *data = buffer;
+
+ for (lfs1_off_t i = 0; i < size; i++) {
+ uint8_t c;
+ int err = lfs1_cache_read(lfs1, rcache, pcache,
+ block, off+i, &c, 1);
+ if (err) {
+ return err;
+ }
+
+ if (c != data[i]) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+static int lfs1_cache_crc(lfs1_t *lfs1, lfs1_cache_t *rcache,
+ const lfs1_cache_t *pcache, lfs1_block_t block,
+ lfs1_off_t off, lfs1_size_t size, uint32_t *crc) {
+ for (lfs1_off_t i = 0; i < size; i++) {
+ uint8_t c;
+ int err = lfs1_cache_read(lfs1, rcache, pcache,
+ block, off+i, &c, 1);
+ if (err) {
+ return err;
+ }
+
+ lfs1_crc(crc, &c, 1);
+ }
+
+ return 0;
+}
+
+static inline void lfs1_cache_drop(lfs1_t *lfs1, lfs1_cache_t *rcache) {
+ // do not zero, cheaper if cache is readonly or only going to be
+ // written with identical data (during relocates)
+ (void)lfs1;
+ rcache->block = 0xffffffff;
+}
+
+static inline void lfs1_cache_zero(lfs1_t *lfs1, lfs1_cache_t *pcache) {
+ // zero to avoid information leak
+ memset(pcache->buffer, 0xff, lfs1->cfg->prog_size);
+ pcache->block = 0xffffffff;
+}
+
+static int lfs1_cache_flush(lfs1_t *lfs1,
+ lfs1_cache_t *pcache, lfs1_cache_t *rcache) {
+ if (pcache->block != 0xffffffff) {
+ int err = lfs1->cfg->prog(lfs1->cfg, pcache->block,
+ pcache->off, pcache->buffer, lfs1->cfg->prog_size);
+ if (err) {
+ return err;
+ }
+
+ if (rcache) {
+ int res = lfs1_cache_cmp(lfs1, rcache, NULL, pcache->block,
+ pcache->off, pcache->buffer, lfs1->cfg->prog_size);
+ if (res < 0) {
+ return res;
+ }
+
+ if (!res) {
+ return LFS1_ERR_CORRUPT;
+ }
+ }
+
+ lfs1_cache_zero(lfs1, pcache);
+ }
+
+ return 0;
+}
+
+static int lfs1_cache_prog(lfs1_t *lfs1, lfs1_cache_t *pcache,
+ lfs1_cache_t *rcache, lfs1_block_t block,
+ lfs1_off_t off, const void *buffer, lfs1_size_t size) {
+ const uint8_t *data = buffer;
+ LFS1_ASSERT(block < lfs1->cfg->block_count);
+
+ while (size > 0) {
+ if (block == pcache->block && off >= pcache->off &&
+ off < pcache->off + lfs1->cfg->prog_size) {
+ // is already in pcache?
+ lfs1_size_t diff = lfs1_min(size,
+ lfs1->cfg->prog_size - (off-pcache->off));
+ memcpy(&pcache->buffer[off-pcache->off], data, diff);
+
+ data += diff;
+ off += diff;
+ size -= diff;
+
+ if (off % lfs1->cfg->prog_size == 0) {
+ // eagerly flush out pcache if we fill up
+ int err = lfs1_cache_flush(lfs1, pcache, rcache);
+ if (err) {
+ return err;
+ }
+ }
+
+ continue;
+ }
+
+ // pcache must have been flushed, either by programming and
+ // entire block or manually flushing the pcache
+ LFS1_ASSERT(pcache->block == 0xffffffff);
+
+ if (off % lfs1->cfg->prog_size == 0 &&
+ size >= lfs1->cfg->prog_size) {
+ // bypass pcache?
+ lfs1_size_t diff = size - (size % lfs1->cfg->prog_size);
+ int err = lfs1->cfg->prog(lfs1->cfg, block, off, data, diff);
+ if (err) {
+ return err;
+ }
+
+ if (rcache) {
+ int res = lfs1_cache_cmp(lfs1, rcache, NULL,
+ block, off, data, diff);
+ if (res < 0) {
+ return res;
+ }
+
+ if (!res) {
+ return LFS1_ERR_CORRUPT;
+ }
+ }
+
+ data += diff;
+ off += diff;
+ size -= diff;
+ continue;
+ }
+
+ // prepare pcache, first condition can no longer fail
+ pcache->block = block;
+ pcache->off = off - (off % lfs1->cfg->prog_size);
+ }
+
+ return 0;
+}
+
+
+/// General lfs1 block device operations ///
+static int lfs1_bd_read(lfs1_t *lfs1, lfs1_block_t block,
+ lfs1_off_t off, void *buffer, lfs1_size_t size) {
+ // if we ever do more than writes to alternating pairs,
+ // this may need to consider pcache
+ return lfs1_cache_read(lfs1, &lfs1->rcache, NULL,
+ block, off, buffer, size);
+}
+
+static int lfs1_bd_prog(lfs1_t *lfs1, lfs1_block_t block,
+ lfs1_off_t off, const void *buffer, lfs1_size_t size) {
+ return lfs1_cache_prog(lfs1, &lfs1->pcache, NULL,
+ block, off, buffer, size);
+}
+
+static int lfs1_bd_cmp(lfs1_t *lfs1, lfs1_block_t block,
+ lfs1_off_t off, const void *buffer, lfs1_size_t size) {
+ return lfs1_cache_cmp(lfs1, &lfs1->rcache, NULL, block, off, buffer, size);
+}
+
+static int lfs1_bd_crc(lfs1_t *lfs1, lfs1_block_t block,
+ lfs1_off_t off, lfs1_size_t size, uint32_t *crc) {
+ return lfs1_cache_crc(lfs1, &lfs1->rcache, NULL, block, off, size, crc);
+}
+
+static int lfs1_bd_erase(lfs1_t *lfs1, lfs1_block_t block) {
+ return lfs1->cfg->erase(lfs1->cfg, block);
+}
+
+static int lfs1_bd_sync(lfs1_t *lfs1) {
+ lfs1_cache_drop(lfs1, &lfs1->rcache);
+
+ int err = lfs1_cache_flush(lfs1, &lfs1->pcache, NULL);
+ if (err) {
+ return err;
+ }
+
+ return lfs1->cfg->sync(lfs1->cfg);
+}
+
+
+/// Internal operations predeclared here ///
+int lfs1_traverse(lfs1_t *lfs1, int (*cb)(void*, lfs1_block_t), void *data);
+static int lfs1_pred(lfs1_t *lfs1, const lfs1_block_t dir[2], lfs1_dir_t *pdir);
+static int lfs1_parent(lfs1_t *lfs1, const lfs1_block_t dir[2],
+ lfs1_dir_t *parent, lfs1_entry_t *entry);
+static int lfs1_moved(lfs1_t *lfs1, const void *e);
+static int lfs1_relocate(lfs1_t *lfs1,
+ const lfs1_block_t oldpair[2], const lfs1_block_t newpair[2]);
+int lfs1_deorphan(lfs1_t *lfs1);
+
+
+/// Block allocator ///
+static int lfs1_alloc_lookahead(void *p, lfs1_block_t block) {
+ lfs1_t *lfs1 = p;
+
+ lfs1_block_t off = ((block - lfs1->free.off)
+ + lfs1->cfg->block_count) % lfs1->cfg->block_count;
+
+ if (off < lfs1->free.size) {
+ lfs1->free.buffer[off / 32] |= 1U << (off % 32);
+ }
+
+ return 0;
+}
+
+static int lfs1_alloc(lfs1_t *lfs1, lfs1_block_t *block) {
+ while (true) {
+ while (lfs1->free.i != lfs1->free.size) {
+ lfs1_block_t off = lfs1->free.i;
+ lfs1->free.i += 1;
+ lfs1->free.ack -= 1;
+
+ if (!(lfs1->free.buffer[off / 32] & (1U << (off % 32)))) {
+ // found a free block
+ *block = (lfs1->free.off + off) % lfs1->cfg->block_count;
+
+ // eagerly find next off so an alloc ack can
+ // discredit old lookahead blocks
+ while (lfs1->free.i != lfs1->free.size &&
+ (lfs1->free.buffer[lfs1->free.i / 32]
+ & (1U << (lfs1->free.i % 32)))) {
+ lfs1->free.i += 1;
+ lfs1->free.ack -= 1;
+ }
+
+ return 0;
+ }
+ }
+
+ // check if we have looked at all blocks since last ack
+ if (lfs1->free.ack == 0) {
+ LFS1_WARN("No more free space %" PRIu32,
+ lfs1->free.i + lfs1->free.off);
+ return LFS1_ERR_NOSPC;
+ }
+
+ lfs1->free.off = (lfs1->free.off + lfs1->free.size)
+ % lfs1->cfg->block_count;
+ lfs1->free.size = lfs1_min(lfs1->cfg->lookahead, lfs1->free.ack);
+ lfs1->free.i = 0;
+
+ // find mask of free blocks from tree
+ memset(lfs1->free.buffer, 0, lfs1->cfg->lookahead/8);
+ int err = lfs1_traverse(lfs1, lfs1_alloc_lookahead, lfs1);
+ if (err) {
+ return err;
+ }
+ }
+}
+
+static void lfs1_alloc_ack(lfs1_t *lfs1) {
+ lfs1->free.ack = lfs1->cfg->block_count;
+}
+
+
+/// Endian swapping functions ///
+static void lfs1_dir_fromle32(struct lfs1_disk_dir *d) {
+ d->rev = lfs1_fromle32(d->rev);
+ d->size = lfs1_fromle32(d->size);
+ d->tail[0] = lfs1_fromle32(d->tail[0]);
+ d->tail[1] = lfs1_fromle32(d->tail[1]);
+}
+
+static void lfs1_dir_tole32(struct lfs1_disk_dir *d) {
+ d->rev = lfs1_tole32(d->rev);
+ d->size = lfs1_tole32(d->size);
+ d->tail[0] = lfs1_tole32(d->tail[0]);
+ d->tail[1] = lfs1_tole32(d->tail[1]);
+}
+
+static void lfs1_entry_fromle32(struct lfs1_disk_entry *d) {
+ d->u.dir[0] = lfs1_fromle32(d->u.dir[0]);
+ d->u.dir[1] = lfs1_fromle32(d->u.dir[1]);
+}
+
+static void lfs1_entry_tole32(struct lfs1_disk_entry *d) {
+ d->u.dir[0] = lfs1_tole32(d->u.dir[0]);
+ d->u.dir[1] = lfs1_tole32(d->u.dir[1]);
+}
+
+static void lfs1_superblock_fromle32(struct lfs1_disk_superblock *d) {
+ d->root[0] = lfs1_fromle32(d->root[0]);
+ d->root[1] = lfs1_fromle32(d->root[1]);
+ d->block_size = lfs1_fromle32(d->block_size);
+ d->block_count = lfs1_fromle32(d->block_count);
+ d->version = lfs1_fromle32(d->version);
+}
+
+static void lfs1_superblock_tole32(struct lfs1_disk_superblock *d) {
+ d->root[0] = lfs1_tole32(d->root[0]);
+ d->root[1] = lfs1_tole32(d->root[1]);
+ d->block_size = lfs1_tole32(d->block_size);
+ d->block_count = lfs1_tole32(d->block_count);
+ d->version = lfs1_tole32(d->version);
+}
+
+
+/// Metadata pair and directory operations ///
+static inline void lfs1_pairswap(lfs1_block_t pair[2]) {
+ lfs1_block_t t = pair[0];
+ pair[0] = pair[1];
+ pair[1] = t;
+}
+
+static inline bool lfs1_pairisnull(const lfs1_block_t pair[2]) {
+ return pair[0] == 0xffffffff || pair[1] == 0xffffffff;
+}
+
+static inline int lfs1_paircmp(
+ const lfs1_block_t paira[2],
+ const lfs1_block_t pairb[2]) {
+ return !(paira[0] == pairb[0] || paira[1] == pairb[1] ||
+ paira[0] == pairb[1] || paira[1] == pairb[0]);
+}
+
+static inline bool lfs1_pairsync(
+ const lfs1_block_t paira[2],
+ const lfs1_block_t pairb[2]) {
+ return (paira[0] == pairb[0] && paira[1] == pairb[1]) ||
+ (paira[0] == pairb[1] && paira[1] == pairb[0]);
+}
+
+static inline lfs1_size_t lfs1_entry_size(const lfs1_entry_t *entry) {
+ return 4 + entry->d.elen + entry->d.alen + entry->d.nlen;
+}
+
+static int lfs1_dir_alloc(lfs1_t *lfs1, lfs1_dir_t *dir) {
+ // allocate pair of dir blocks
+ for (int i = 0; i < 2; i++) {
+ int err = lfs1_alloc(lfs1, &dir->pair[i]);
+ if (err) {
+ return err;
+ }
+ }
+
+ // rather than clobbering one of the blocks we just pretend
+ // the revision may be valid
+ int err = lfs1_bd_read(lfs1, dir->pair[0], 0, &dir->d.rev, 4);
+ if (err && err != LFS1_ERR_CORRUPT) {
+ return err;
+ }
+
+ if (err != LFS1_ERR_CORRUPT) {
+ dir->d.rev = lfs1_fromle32(dir->d.rev);
+ }
+
+ // set defaults
+ dir->d.rev += 1;
+ dir->d.size = sizeof(dir->d)+4;
+ dir->d.tail[0] = 0xffffffff;
+ dir->d.tail[1] = 0xffffffff;
+ dir->off = sizeof(dir->d);
+
+ // don't write out yet, let caller take care of that
+ return 0;
+}
+
+static int lfs1_dir_fetch(lfs1_t *lfs1,
+ lfs1_dir_t *dir, const lfs1_block_t pair[2]) {
+ // copy out pair, otherwise may be aliasing dir
+ const lfs1_block_t tpair[2] = {pair[0], pair[1]};
+ bool valid = false;
+
+ // check both blocks for the most recent revision
+ for (int i = 0; i < 2; i++) {
+ struct lfs1_disk_dir test;
+ int err = lfs1_bd_read(lfs1, tpair[i], 0, &test, sizeof(test));
+ lfs1_dir_fromle32(&test);
+ if (err) {
+ if (err == LFS1_ERR_CORRUPT) {
+ continue;
+ }
+ return err;
+ }
+
+ if (valid && lfs1_scmp(test.rev, dir->d.rev) < 0) {
+ continue;
+ }
+
+ if ((0x7fffffff & test.size) < sizeof(test)+4 ||
+ (0x7fffffff & test.size) > lfs1->cfg->block_size) {
+ continue;
+ }
+
+ uint32_t crc = 0xffffffff;
+ lfs1_dir_tole32(&test);
+ lfs1_crc(&crc, &test, sizeof(test));
+ lfs1_dir_fromle32(&test);
+ err = lfs1_bd_crc(lfs1, tpair[i], sizeof(test),
+ (0x7fffffff & test.size) - sizeof(test), &crc);
+ if (err) {
+ if (err == LFS1_ERR_CORRUPT) {
+ continue;
+ }
+ return err;
+ }
+
+ if (crc != 0) {
+ continue;
+ }
+
+ valid = true;
+
+ // setup dir in case it's valid
+ dir->pair[0] = tpair[(i+0) % 2];
+ dir->pair[1] = tpair[(i+1) % 2];
+ dir->off = sizeof(dir->d);
+ dir->d = test;
+ }
+
+ if (!valid) {
+ LFS1_ERROR("Corrupted dir pair at %" PRIu32 " %" PRIu32 ,
+ tpair[0], tpair[1]);
+ return LFS1_ERR_CORRUPT;
+ }
+
+ return 0;
+}
+
+struct lfs1_region {
+ lfs1_off_t oldoff;
+ lfs1_size_t oldlen;
+ const void *newdata;
+ lfs1_size_t newlen;
+};
+
+static int lfs1_dir_commit(lfs1_t *lfs1, lfs1_dir_t *dir,
+ const struct lfs1_region *regions, int count) {
+ // increment revision count
+ dir->d.rev += 1;
+
+ // keep pairs in order such that pair[0] is most recent
+ lfs1_pairswap(dir->pair);
+ for (int i = 0; i < count; i++) {
+ dir->d.size += regions[i].newlen - regions[i].oldlen;
+ }
+
+ const lfs1_block_t oldpair[2] = {dir->pair[0], dir->pair[1]};
+ bool relocated = false;
+
+ while (true) {
+ if (true) {
+ int err = lfs1_bd_erase(lfs1, dir->pair[0]);
+ if (err) {
+ if (err == LFS1_ERR_CORRUPT) {
+ goto relocate;
+ }
+ return err;
+ }
+
+ uint32_t crc = 0xffffffff;
+ lfs1_dir_tole32(&dir->d);
+ lfs1_crc(&crc, &dir->d, sizeof(dir->d));
+ err = lfs1_bd_prog(lfs1, dir->pair[0], 0, &dir->d, sizeof(dir->d));
+ lfs1_dir_fromle32(&dir->d);
+ if (err) {
+ if (err == LFS1_ERR_CORRUPT) {
+ goto relocate;
+ }
+ return err;
+ }
+
+ int i = 0;
+ lfs1_off_t oldoff = sizeof(dir->d);
+ lfs1_off_t newoff = sizeof(dir->d);
+ while (newoff < (0x7fffffff & dir->d.size)-4) {
+ if (i < count && regions[i].oldoff == oldoff) {
+ lfs1_crc(&crc, regions[i].newdata, regions[i].newlen);
+ err = lfs1_bd_prog(lfs1, dir->pair[0],
+ newoff, regions[i].newdata, regions[i].newlen);
+ if (err) {
+ if (err == LFS1_ERR_CORRUPT) {
+ goto relocate;
+ }
+ return err;
+ }
+
+ oldoff += regions[i].oldlen;
+ newoff += regions[i].newlen;
+ i += 1;
+ } else {
+ uint8_t data;
+ err = lfs1_bd_read(lfs1, oldpair[1], oldoff, &data, 1);
+ if (err) {
+ return err;
+ }
+
+ lfs1_crc(&crc, &data, 1);
+ err = lfs1_bd_prog(lfs1, dir->pair[0], newoff, &data, 1);
+ if (err) {
+ if (err == LFS1_ERR_CORRUPT) {
+ goto relocate;
+ }
+ return err;
+ }
+
+ oldoff += 1;
+ newoff += 1;
+ }
+ }
+
+ crc = lfs1_tole32(crc);
+ err = lfs1_bd_prog(lfs1, dir->pair[0], newoff, &crc, 4);
+ crc = lfs1_fromle32(crc);
+ if (err) {
+ if (err == LFS1_ERR_CORRUPT) {
+ goto relocate;
+ }
+ return err;
+ }
+
+ err = lfs1_bd_sync(lfs1);
+ if (err) {
+ if (err == LFS1_ERR_CORRUPT) {
+ goto relocate;
+ }
+ return err;
+ }
+
+ // successful commit, check checksum to make sure
+ uint32_t ncrc = 0xffffffff;
+ err = lfs1_bd_crc(lfs1, dir->pair[0], 0,
+ (0x7fffffff & dir->d.size)-4, &ncrc);
+ if (err) {
+ return err;
+ }
+
+ if (ncrc != crc) {
+ goto relocate;
+ }
+ }
+
+ break;
+relocate:
+ //commit was corrupted
+ LFS1_DEBUG("Bad block at %" PRIu32, dir->pair[0]);
+
+ // drop caches and prepare to relocate block
+ relocated = true;
+ lfs1_cache_drop(lfs1, &lfs1->pcache);
+
+ // can't relocate superblock, filesystem is now frozen
+ if (lfs1_paircmp(oldpair, (const lfs1_block_t[2]){0, 1}) == 0) {
+ LFS1_WARN("Superblock %" PRIu32 " has become unwritable",
+ oldpair[0]);
+ return LFS1_ERR_CORRUPT;
+ }
+
+ // relocate half of pair
+ int err = lfs1_alloc(lfs1, &dir->pair[0]);
+ if (err) {
+ return err;
+ }
+ }
+
+ if (relocated) {
+ // update references if we relocated
+ LFS1_DEBUG("Relocating %" PRIu32 " %" PRIu32 " to %" PRIu32 " %" PRIu32,
+ oldpair[0], oldpair[1], dir->pair[0], dir->pair[1]);
+ int err = lfs1_relocate(lfs1, oldpair, dir->pair);
+ if (err) {
+ return err;
+ }
+ }
+
+ // shift over any directories that are affected
+ for (lfs1_dir_t *d = lfs1->dirs; d; d = d->next) {
+ if (lfs1_paircmp(d->pair, dir->pair) == 0) {
+ d->pair[0] = dir->pair[0];
+ d->pair[1] = dir->pair[1];
+ }
+ }
+
+ return 0;
+}
+
+static int lfs1_dir_update(lfs1_t *lfs1, lfs1_dir_t *dir,
+ lfs1_entry_t *entry, const void *data) {
+ lfs1_entry_tole32(&entry->d);
+ int err = lfs1_dir_commit(lfs1, dir, (struct lfs1_region[]){
+ {entry->off, sizeof(entry->d), &entry->d, sizeof(entry->d)},
+ {entry->off+sizeof(entry->d), entry->d.nlen, data, entry->d.nlen}
+ }, data ? 2 : 1);
+ lfs1_entry_fromle32(&entry->d);
+ return err;
+}
+
+static int lfs1_dir_append(lfs1_t *lfs1, lfs1_dir_t *dir,
+ lfs1_entry_t *entry, const void *data) {
+ // check if we fit, if top bit is set we do not and move on
+ while (true) {
+ if (dir->d.size + lfs1_entry_size(entry) <= lfs1->cfg->block_size) {
+ entry->off = dir->d.size - 4;
+
+ lfs1_entry_tole32(&entry->d);
+ int err = lfs1_dir_commit(lfs1, dir, (struct lfs1_region[]){
+ {entry->off, 0, &entry->d, sizeof(entry->d)},
+ {entry->off, 0, data, entry->d.nlen}
+ }, 2);
+ lfs1_entry_fromle32(&entry->d);
+ return err;
+ }
+
+ // we need to allocate a new dir block
+ if (!(0x80000000 & dir->d.size)) {
+ lfs1_dir_t olddir = *dir;
+ int err = lfs1_dir_alloc(lfs1, dir);
+ if (err) {
+ return err;
+ }
+
+ dir->d.tail[0] = olddir.d.tail[0];
+ dir->d.tail[1] = olddir.d.tail[1];
+ entry->off = dir->d.size - 4;
+ lfs1_entry_tole32(&entry->d);
+ err = lfs1_dir_commit(lfs1, dir, (struct lfs1_region[]){
+ {entry->off, 0, &entry->d, sizeof(entry->d)},
+ {entry->off, 0, data, entry->d.nlen}
+ }, 2);
+ lfs1_entry_fromle32(&entry->d);
+ if (err) {
+ return err;
+ }
+
+ olddir.d.size |= 0x80000000;
+ olddir.d.tail[0] = dir->pair[0];
+ olddir.d.tail[1] = dir->pair[1];
+ return lfs1_dir_commit(lfs1, &olddir, NULL, 0);
+ }
+
+ int err = lfs1_dir_fetch(lfs1, dir, dir->d.tail);
+ if (err) {
+ return err;
+ }
+ }
+}
+
+static int lfs1_dir_remove(lfs1_t *lfs1, lfs1_dir_t *dir, lfs1_entry_t *entry) {
+ // check if we should just drop the directory block
+ if ((dir->d.size & 0x7fffffff) == sizeof(dir->d)+4
+ + lfs1_entry_size(entry)) {
+ lfs1_dir_t pdir;
+ int res = lfs1_pred(lfs1, dir->pair, &pdir);
+ if (res < 0) {
+ return res;
+ }
+
+ if (pdir.d.size & 0x80000000) {
+ pdir.d.size &= dir->d.size | 0x7fffffff;
+ pdir.d.tail[0] = dir->d.tail[0];
+ pdir.d.tail[1] = dir->d.tail[1];
+ return lfs1_dir_commit(lfs1, &pdir, NULL, 0);
+ }
+ }
+
+ // shift out the entry
+ int err = lfs1_dir_commit(lfs1, dir, (struct lfs1_region[]){
+ {entry->off, lfs1_entry_size(entry), NULL, 0},
+ }, 1);
+ if (err) {
+ return err;
+ }
+
+ // shift over any files/directories that are affected
+ for (lfs1_file_t *f = lfs1->files; f; f = f->next) {
+ if (lfs1_paircmp(f->pair, dir->pair) == 0) {
+ if (f->poff == entry->off) {
+ f->pair[0] = 0xffffffff;
+ f->pair[1] = 0xffffffff;
+ } else if (f->poff > entry->off) {
+ f->poff -= lfs1_entry_size(entry);
+ }
+ }
+ }
+
+ for (lfs1_dir_t *d = lfs1->dirs; d; d = d->next) {
+ if (lfs1_paircmp(d->pair, dir->pair) == 0) {
+ if (d->off > entry->off) {
+ d->off -= lfs1_entry_size(entry);
+ d->pos -= lfs1_entry_size(entry);
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int lfs1_dir_next(lfs1_t *lfs1, lfs1_dir_t *dir, lfs1_entry_t *entry) {
+ while (dir->off + sizeof(entry->d) > (0x7fffffff & dir->d.size)-4) {
+ if (!(0x80000000 & dir->d.size)) {
+ entry->off = dir->off;
+ return LFS1_ERR_NOENT;
+ }
+
+ int err = lfs1_dir_fetch(lfs1, dir, dir->d.tail);
+ if (err) {
+ return err;
+ }
+
+ dir->off = sizeof(dir->d);
+ dir->pos += sizeof(dir->d) + 4;
+ }
+
+ int err = lfs1_bd_read(lfs1, dir->pair[0], dir->off,
+ &entry->d, sizeof(entry->d));
+ lfs1_entry_fromle32(&entry->d);
+ if (err) {
+ return err;
+ }
+
+ entry->off = dir->off;
+ dir->off += lfs1_entry_size(entry);
+ dir->pos += lfs1_entry_size(entry);
+ return 0;
+}
+
+static int lfs1_dir_find(lfs1_t *lfs1, lfs1_dir_t *dir,
+ lfs1_entry_t *entry, const char **path) {
+ const char *pathname = *path;
+ size_t pathlen;
+ entry->d.type = LFS1_TYPE_DIR;
+ entry->d.elen = sizeof(entry->d) - 4;
+ entry->d.alen = 0;
+ entry->d.nlen = 0;
+ entry->d.u.dir[0] = lfs1->root[0];
+ entry->d.u.dir[1] = lfs1->root[1];
+
+ while (true) {
+nextname:
+ // skip slashes
+ pathname += strspn(pathname, "/");
+ pathlen = strcspn(pathname, "/");
+
+ // skip '.' and root '..'
+ if ((pathlen == 1 && memcmp(pathname, ".", 1) == 0) ||
+ (pathlen == 2 && memcmp(pathname, "..", 2) == 0)) {
+ pathname += pathlen;
+ goto nextname;
+ }
+
+ // skip if matched by '..' in name
+ const char *suffix = pathname + pathlen;
+ size_t sufflen;
+ int depth = 1;
+ while (true) {
+ suffix += strspn(suffix, "/");
+ sufflen = strcspn(suffix, "/");
+ if (sufflen == 0) {
+ break;
+ }
+
+ if (sufflen == 2 && memcmp(suffix, "..", 2) == 0) {
+ depth -= 1;
+ if (depth == 0) {
+ pathname = suffix + sufflen;
+ goto nextname;
+ }
+ } else {
+ depth += 1;
+ }
+
+ suffix += sufflen;
+ }
+
+ // found path
+ if (pathname[0] == '\0') {
+ return 0;
+ }
+
+ // update what we've found
+ *path = pathname;
+
+ // continue on if we hit a directory
+ if (entry->d.type != LFS1_TYPE_DIR) {
+ return LFS1_ERR_NOTDIR;
+ }
+
+ int err = lfs1_dir_fetch(lfs1, dir, entry->d.u.dir);
+ if (err) {
+ return err;
+ }
+
+ // find entry matching name
+ while (true) {
+ err = lfs1_dir_next(lfs1, dir, entry);
+ if (err) {
+ return err;
+ }
+
+ if (((0x7f & entry->d.type) != LFS1_TYPE_REG &&
+ (0x7f & entry->d.type) != LFS1_TYPE_DIR) ||
+ entry->d.nlen != pathlen) {
+ continue;
+ }
+
+ int res = lfs1_bd_cmp(lfs1, dir->pair[0],
+ entry->off + 4+entry->d.elen+entry->d.alen,
+ pathname, pathlen);
+ if (res < 0) {
+ return res;
+ }
+
+ // found match
+ if (res) {
+ break;
+ }
+ }
+
+ // check that entry has not been moved
+ if (!lfs1->moving && entry->d.type & 0x80) {
+ int moved = lfs1_moved(lfs1, &entry->d.u);
+ if (moved < 0 || moved) {
+ return (moved < 0) ? moved : LFS1_ERR_NOENT;
+ }
+
+ entry->d.type &= ~0x80;
+ }
+
+ // to next name
+ pathname += pathlen;
+ }
+}
+
+
+/// Top level directory operations ///
+int lfs1_mkdir(lfs1_t *lfs1, const char *path) {
+ // deorphan if we haven't yet, needed at most once after poweron
+ if (!lfs1->deorphaned) {
+ int err = lfs1_deorphan(lfs1);
+ if (err) {
+ return err;
+ }
+ }
+
+ // fetch parent directory
+ lfs1_dir_t cwd;
+ lfs1_entry_t entry;
+ int err = lfs1_dir_find(lfs1, &cwd, &entry, &path);
+ if (err != LFS1_ERR_NOENT || strchr(path, '/') != NULL) {
+ return err ? err : LFS1_ERR_EXIST;
+ }
+
+ // build up new directory
+ lfs1_alloc_ack(lfs1);
+
+ lfs1_dir_t dir;
+ err = lfs1_dir_alloc(lfs1, &dir);
+ if (err) {
+ return err;
+ }
+ dir.d.tail[0] = cwd.d.tail[0];
+ dir.d.tail[1] = cwd.d.tail[1];
+
+ err = lfs1_dir_commit(lfs1, &dir, NULL, 0);
+ if (err) {
+ return err;
+ }
+
+ entry.d.type = LFS1_TYPE_DIR;
+ entry.d.elen = sizeof(entry.d) - 4;
+ entry.d.alen = 0;
+ entry.d.nlen = strlen(path);
+ entry.d.u.dir[0] = dir.pair[0];
+ entry.d.u.dir[1] = dir.pair[1];
+
+ cwd.d.tail[0] = dir.pair[0];
+ cwd.d.tail[1] = dir.pair[1];
+
+ err = lfs1_dir_append(lfs1, &cwd, &entry, path);
+ if (err) {
+ return err;
+ }
+
+ lfs1_alloc_ack(lfs1);
+ return 0;
+}
+
+int lfs1_dir_open(lfs1_t *lfs1, lfs1_dir_t *dir, const char *path) {
+ dir->pair[0] = lfs1->root[0];
+ dir->pair[1] = lfs1->root[1];
+
+ lfs1_entry_t entry;
+ int err = lfs1_dir_find(lfs1, dir, &entry, &path);
+ if (err) {
+ return err;
+ } else if (entry.d.type != LFS1_TYPE_DIR) {
+ return LFS1_ERR_NOTDIR;
+ }
+
+ err = lfs1_dir_fetch(lfs1, dir, entry.d.u.dir);
+ if (err) {
+ return err;
+ }
+
+ // setup head dir
+ // special offset for '.' and '..'
+ dir->head[0] = dir->pair[0];
+ dir->head[1] = dir->pair[1];
+ dir->pos = sizeof(dir->d) - 2;
+ dir->off = sizeof(dir->d);
+
+ // add to list of directories
+ dir->next = lfs1->dirs;
+ lfs1->dirs = dir;
+
+ return 0;
+}
+
+int lfs1_dir_close(lfs1_t *lfs1, lfs1_dir_t *dir) {
+ // remove from list of directories
+ for (lfs1_dir_t **p = &lfs1->dirs; *p; p = &(*p)->next) {
+ if (*p == dir) {
+ *p = dir->next;
+ break;
+ }
+ }
+
+ return 0;
+}
+
+int lfs1_dir_read(lfs1_t *lfs1, lfs1_dir_t *dir, struct lfs1_info *info) {
+ memset(info, 0, sizeof(*info));
+
+ // special offset for '.' and '..'
+ if (dir->pos == sizeof(dir->d) - 2) {
+ info->type = LFS1_TYPE_DIR;
+ strcpy(info->name, ".");
+ dir->pos += 1;
+ return 1;
+ } else if (dir->pos == sizeof(dir->d) - 1) {
+ info->type = LFS1_TYPE_DIR;
+ strcpy(info->name, "..");
+ dir->pos += 1;
+ return 1;
+ }
+
+ lfs1_entry_t entry;
+ while (true) {
+ int err = lfs1_dir_next(lfs1, dir, &entry);
+ if (err) {
+ return (err == LFS1_ERR_NOENT) ? 0 : err;
+ }
+
+ if ((0x7f & entry.d.type) != LFS1_TYPE_REG &&
+ (0x7f & entry.d.type) != LFS1_TYPE_DIR) {
+ continue;
+ }
+
+ // check that entry has not been moved
+ if (entry.d.type & 0x80) {
+ int moved = lfs1_moved(lfs1, &entry.d.u);
+ if (moved < 0) {
+ return moved;
+ }
+
+ if (moved) {
+ continue;
+ }
+
+ entry.d.type &= ~0x80;
+ }
+
+ break;
+ }
+
+ info->type = entry.d.type;
+ if (info->type == LFS1_TYPE_REG) {
+ info->size = entry.d.u.file.size;
+ }
+
+ int err = lfs1_bd_read(lfs1, dir->pair[0],
+ entry.off + 4+entry.d.elen+entry.d.alen,
+ info->name, entry.d.nlen);
+ if (err) {
+ return err;
+ }
+
+ return 1;
+}
+
+int lfs1_dir_seek(lfs1_t *lfs1, lfs1_dir_t *dir, lfs1_off_t off) {
+ // simply walk from head dir
+ int err = lfs1_dir_rewind(lfs1, dir);
+ if (err) {
+ return err;
+ }
+ dir->pos = off;
+
+ while (off > (0x7fffffff & dir->d.size)) {
+ off -= 0x7fffffff & dir->d.size;
+ if (!(0x80000000 & dir->d.size)) {
+ return LFS1_ERR_INVAL;
+ }
+
+ err = lfs1_dir_fetch(lfs1, dir, dir->d.tail);
+ if (err) {
+ return err;
+ }
+ }
+
+ dir->off = off;
+ return 0;
+}
+
+lfs1_soff_t lfs1_dir_tell(lfs1_t *lfs1, lfs1_dir_t *dir) {
+ (void)lfs1;
+ return dir->pos;
+}
+
+int lfs1_dir_rewind(lfs1_t *lfs1, lfs1_dir_t *dir) {
+ // reload the head dir
+ int err = lfs1_dir_fetch(lfs1, dir, dir->head);
+ if (err) {
+ return err;
+ }
+
+ dir->pair[0] = dir->head[0];
+ dir->pair[1] = dir->head[1];
+ dir->pos = sizeof(dir->d) - 2;
+ dir->off = sizeof(dir->d);
+ return 0;
+}
+
+
+/// File index list operations ///
+static int lfs1_ctz_index(lfs1_t *lfs1, lfs1_off_t *off) {
+ lfs1_off_t size = *off;
+ lfs1_off_t b = lfs1->cfg->block_size - 2*4;
+ lfs1_off_t i = size / b;
+ if (i == 0) {
+ return 0;
+ }
+
+ i = (size - 4*(lfs1_popc(i-1)+2)) / b;
+ *off = size - b*i - 4*lfs1_popc(i);
+ return i;
+}
+
+static int lfs1_ctz_find(lfs1_t *lfs1,
+ lfs1_cache_t *rcache, const lfs1_cache_t *pcache,
+ lfs1_block_t head, lfs1_size_t size,
+ lfs1_size_t pos, lfs1_block_t *block, lfs1_off_t *off) {
+ if (size == 0) {
+ *block = 0xffffffff;
+ *off = 0;
+ return 0;
+ }
+
+ lfs1_off_t current = lfs1_ctz_index(lfs1, &(lfs1_off_t){size-1});
+ lfs1_off_t target = lfs1_ctz_index(lfs1, &pos);
+
+ while (current > target) {
+ lfs1_size_t skip = lfs1_min(
+ lfs1_npw2(current-target+1) - 1,
+ lfs1_ctz(current));
+
+ int err = lfs1_cache_read(lfs1, rcache, pcache, head, 4*skip, &head, 4);
+ head = lfs1_fromle32(head);
+ if (err) {
+ return err;
+ }
+
+ LFS1_ASSERT(head >= 2 && head <= lfs1->cfg->block_count);
+ current -= 1 << skip;
+ }
+
+ *block = head;
+ *off = pos;
+ return 0;
+}
+
+static int lfs1_ctz_extend(lfs1_t *lfs1,
+ lfs1_cache_t *rcache, lfs1_cache_t *pcache,
+ lfs1_block_t head, lfs1_size_t size,
+ lfs1_block_t *block, lfs1_off_t *off) {
+ while (true) {
+ // go ahead and grab a block
+ lfs1_block_t nblock;
+ int err = lfs1_alloc(lfs1, &nblock);
+ if (err) {
+ return err;
+ }
+ LFS1_ASSERT(nblock >= 2 && nblock <= lfs1->cfg->block_count);
+
+ if (true) {
+ err = lfs1_bd_erase(lfs1, nblock);
+ if (err) {
+ if (err == LFS1_ERR_CORRUPT) {
+ goto relocate;
+ }
+ return err;
+ }
+
+ if (size == 0) {
+ *block = nblock;
+ *off = 0;
+ return 0;
+ }
+
+ size -= 1;
+ lfs1_off_t index = lfs1_ctz_index(lfs1, &size);
+ size += 1;
+
+ // just copy out the last block if it is incomplete
+ if (size != lfs1->cfg->block_size) {
+ for (lfs1_off_t i = 0; i < size; i++) {
+ uint8_t data;
+ err = lfs1_cache_read(lfs1, rcache, NULL,
+ head, i, &data, 1);
+ if (err) {
+ return err;
+ }
+
+ err = lfs1_cache_prog(lfs1, pcache, rcache,
+ nblock, i, &data, 1);
+ if (err) {
+ if (err == LFS1_ERR_CORRUPT) {
+ goto relocate;
+ }
+ return err;
+ }
+ }
+
+ *block = nblock;
+ *off = size;
+ return 0;
+ }
+
+ // append block
+ index += 1;
+ lfs1_size_t skips = lfs1_ctz(index) + 1;
+
+ for (lfs1_off_t i = 0; i < skips; i++) {
+ head = lfs1_tole32(head);
+ err = lfs1_cache_prog(lfs1, pcache, rcache,
+ nblock, 4*i, &head, 4);
+ head = lfs1_fromle32(head);
+ if (err) {
+ if (err == LFS1_ERR_CORRUPT) {
+ goto relocate;
+ }
+ return err;
+ }
+
+ if (i != skips-1) {
+ err = lfs1_cache_read(lfs1, rcache, NULL,
+ head, 4*i, &head, 4);
+ head = lfs1_fromle32(head);
+ if (err) {
+ return err;
+ }
+ }
+
+ LFS1_ASSERT(head >= 2 && head <= lfs1->cfg->block_count);
+ }
+
+ *block = nblock;
+ *off = 4*skips;
+ return 0;
+ }
+
+relocate:
+ LFS1_DEBUG("Bad block at %" PRIu32, nblock);
+
+ // just clear cache and try a new block
+ lfs1_cache_drop(lfs1, &lfs1->pcache);
+ }
+}
+
+static int lfs1_ctz_traverse(lfs1_t *lfs1,
+ lfs1_cache_t *rcache, const lfs1_cache_t *pcache,
+ lfs1_block_t head, lfs1_size_t size,
+ int (*cb)(void*, lfs1_block_t), void *data) {
+ if (size == 0) {
+ return 0;
+ }
+
+ lfs1_off_t index = lfs1_ctz_index(lfs1, &(lfs1_off_t){size-1});
+
+ while (true) {
+ int err = cb(data, head);
+ if (err) {
+ return err;
+ }
+
+ if (index == 0) {
+ return 0;
+ }
+
+ lfs1_block_t heads[2];
+ int count = 2 - (index & 1);
+ err = lfs1_cache_read(lfs1, rcache, pcache, head, 0, &heads, count*4);
+ heads[0] = lfs1_fromle32(heads[0]);
+ heads[1] = lfs1_fromle32(heads[1]);
+ if (err) {
+ return err;
+ }
+
+ for (int i = 0; i < count-1; i++) {
+ err = cb(data, heads[i]);
+ if (err) {
+ return err;
+ }
+ }
+
+ head = heads[count-1];
+ index -= count;
+ }
+}
+
+
+/// Top level file operations ///
+int lfs1_file_opencfg(lfs1_t *lfs1, lfs1_file_t *file,
+ const char *path, int flags,
+ const struct lfs1_file_config *cfg) {
+ // deorphan if we haven't yet, needed at most once after poweron
+ if ((flags & 3) != LFS1_O_RDONLY && !lfs1->deorphaned) {
+ int err = lfs1_deorphan(lfs1);
+ if (err) {
+ return err;
+ }
+ }
+
+ // allocate entry for file if it doesn't exist
+ lfs1_dir_t cwd;
+ lfs1_entry_t entry;
+ int err = lfs1_dir_find(lfs1, &cwd, &entry, &path);
+ if (err && (err != LFS1_ERR_NOENT || strchr(path, '/') != NULL)) {
+ return err;
+ }
+
+ if (err == LFS1_ERR_NOENT) {
+ if (!(flags & LFS1_O_CREAT)) {
+ return LFS1_ERR_NOENT;
+ }
+
+ // create entry to remember name
+ entry.d.type = LFS1_TYPE_REG;
+ entry.d.elen = sizeof(entry.d) - 4;
+ entry.d.alen = 0;
+ entry.d.nlen = strlen(path);
+ entry.d.u.file.head = 0xffffffff;
+ entry.d.u.file.size = 0;
+ err = lfs1_dir_append(lfs1, &cwd, &entry, path);
+ if (err) {
+ return err;
+ }
+ } else if (entry.d.type == LFS1_TYPE_DIR) {
+ return LFS1_ERR_ISDIR;
+ } else if (flags & LFS1_O_EXCL) {
+ return LFS1_ERR_EXIST;
+ }
+
+ // setup file struct
+ file->cfg = cfg;
+ file->pair[0] = cwd.pair[0];
+ file->pair[1] = cwd.pair[1];
+ file->poff = entry.off;
+ file->head = entry.d.u.file.head;
+ file->size = entry.d.u.file.size;
+ file->flags = flags;
+ file->pos = 0;
+
+ if (flags & LFS1_O_TRUNC) {
+ if (file->size != 0) {
+ file->flags |= LFS1_F_DIRTY;
+ }
+ file->head = 0xffffffff;
+ file->size = 0;
+ }
+
+ // allocate buffer if needed
+ file->cache.block = 0xffffffff;
+ if (file->cfg && file->cfg->buffer) {
+ file->cache.buffer = file->cfg->buffer;
+ } else if (lfs1->cfg->file_buffer) {
+ if (lfs1->files) {
+ // already in use
+ return LFS1_ERR_NOMEM;
+ }
+ file->cache.buffer = lfs1->cfg->file_buffer;
+ } else if ((file->flags & 3) == LFS1_O_RDONLY) {
+ file->cache.buffer = lfs1_malloc(lfs1->cfg->read_size);
+ if (!file->cache.buffer) {
+ return LFS1_ERR_NOMEM;
+ }
+ } else {
+ file->cache.buffer = lfs1_malloc(lfs1->cfg->prog_size);
+ if (!file->cache.buffer) {
+ return LFS1_ERR_NOMEM;
+ }
+ }
+
+ // zero to avoid information leak
+ lfs1_cache_drop(lfs1, &file->cache);
+ if ((file->flags & 3) != LFS1_O_RDONLY) {
+ lfs1_cache_zero(lfs1, &file->cache);
+ }
+
+ // add to list of files
+ file->next = lfs1->files;
+ lfs1->files = file;
+
+ return 0;
+}
+
+int lfs1_file_open(lfs1_t *lfs1, lfs1_file_t *file,
+ const char *path, int flags) {
+ return lfs1_file_opencfg(lfs1, file, path, flags, NULL);
+}
+
+int lfs1_file_close(lfs1_t *lfs1, lfs1_file_t *file) {
+ int err = lfs1_file_sync(lfs1, file);
+
+ // remove from list of files
+ for (lfs1_file_t **p = &lfs1->files; *p; p = &(*p)->next) {
+ if (*p == file) {
+ *p = file->next;
+ break;
+ }
+ }
+
+ // clean up memory
+ if (!(file->cfg && file->cfg->buffer) && !lfs1->cfg->file_buffer) {
+ lfs1_free(file->cache.buffer);
+ }
+
+ return err;
+}
+
+static int lfs1_file_relocate(lfs1_t *lfs1, lfs1_file_t *file) {
+relocate:
+ LFS1_DEBUG("Bad block at %" PRIu32, file->block);
+
+ // just relocate what exists into new block
+ lfs1_block_t nblock;
+ int err = lfs1_alloc(lfs1, &nblock);
+ if (err) {
+ return err;
+ }
+
+ err = lfs1_bd_erase(lfs1, nblock);
+ if (err) {
+ if (err == LFS1_ERR_CORRUPT) {
+ goto relocate;
+ }
+ return err;
+ }
+
+ // either read from dirty cache or disk
+ for (lfs1_off_t i = 0; i < file->off; i++) {
+ uint8_t data;
+ err = lfs1_cache_read(lfs1, &lfs1->rcache, &file->cache,
+ file->block, i, &data, 1);
+ if (err) {
+ return err;
+ }
+
+ err = lfs1_cache_prog(lfs1, &lfs1->pcache, &lfs1->rcache,
+ nblock, i, &data, 1);
+ if (err) {
+ if (err == LFS1_ERR_CORRUPT) {
+ goto relocate;
+ }
+ return err;
+ }
+ }
+
+ // copy over new state of file
+ memcpy(file->cache.buffer, lfs1->pcache.buffer, lfs1->cfg->prog_size);
+ file->cache.block = lfs1->pcache.block;
+ file->cache.off = lfs1->pcache.off;
+ lfs1_cache_zero(lfs1, &lfs1->pcache);
+
+ file->block = nblock;
+ return 0;
+}
+
+static int lfs1_file_flush(lfs1_t *lfs1, lfs1_file_t *file) {
+ if (file->flags & LFS1_F_READING) {
+ // just drop read cache
+ lfs1_cache_drop(lfs1, &file->cache);
+ file->flags &= ~LFS1_F_READING;
+ }
+
+ if (file->flags & LFS1_F_WRITING) {
+ lfs1_off_t pos = file->pos;
+
+ // copy over anything after current branch
+ lfs1_file_t orig = {
+ .head = file->head,
+ .size = file->size,
+ .flags = LFS1_O_RDONLY,
+ .pos = file->pos,
+ .cache = lfs1->rcache,
+ };
+ lfs1_cache_drop(lfs1, &lfs1->rcache);
+
+ while (file->pos < file->size) {
+ // copy over a byte at a time, leave it up to caching
+ // to make this efficient
+ uint8_t data;
+ lfs1_ssize_t res = lfs1_file_read(lfs1, &orig, &data, 1);
+ if (res < 0) {
+ return res;
+ }
+
+ res = lfs1_file_write(lfs1, file, &data, 1);
+ if (res < 0) {
+ return res;
+ }
+
+ // keep our reference to the rcache in sync
+ if (lfs1->rcache.block != 0xffffffff) {
+ lfs1_cache_drop(lfs1, &orig.cache);
+ lfs1_cache_drop(lfs1, &lfs1->rcache);
+ }
+ }
+
+ // write out what we have
+ while (true) {
+ int err = lfs1_cache_flush(lfs1, &file->cache, &lfs1->rcache);
+ if (err) {
+ if (err == LFS1_ERR_CORRUPT) {
+ goto relocate;
+ }
+ return err;
+ }
+
+ break;
+relocate:
+ err = lfs1_file_relocate(lfs1, file);
+ if (err) {
+ return err;
+ }
+ }
+
+ // actual file updates
+ file->head = file->block;
+ file->size = file->pos;
+ file->flags &= ~LFS1_F_WRITING;
+ file->flags |= LFS1_F_DIRTY;
+
+ file->pos = pos;
+ }
+
+ return 0;
+}
+
+int lfs1_file_sync(lfs1_t *lfs1, lfs1_file_t *file) {
+ int err = lfs1_file_flush(lfs1, file);
+ if (err) {
+ return err;
+ }
+
+ if ((file->flags & LFS1_F_DIRTY) &&
+ !(file->flags & LFS1_F_ERRED) &&
+ !lfs1_pairisnull(file->pair)) {
+ // update dir entry
+ lfs1_dir_t cwd;
+ err = lfs1_dir_fetch(lfs1, &cwd, file->pair);
+ if (err) {
+ return err;
+ }
+
+ lfs1_entry_t entry = {.off = file->poff};
+ err = lfs1_bd_read(lfs1, cwd.pair[0], entry.off,
+ &entry.d, sizeof(entry.d));
+ lfs1_entry_fromle32(&entry.d);
+ if (err) {
+ return err;
+ }
+
+ LFS1_ASSERT(entry.d.type == LFS1_TYPE_REG);
+ entry.d.u.file.head = file->head;
+ entry.d.u.file.size = file->size;
+
+ err = lfs1_dir_update(lfs1, &cwd, &entry, NULL);
+ if (err) {
+ return err;
+ }
+
+ file->flags &= ~LFS1_F_DIRTY;
+ }
+
+ return 0;
+}
+
+lfs1_ssize_t lfs1_file_read(lfs1_t *lfs1, lfs1_file_t *file,
+ void *buffer, lfs1_size_t size) {
+ uint8_t *data = buffer;
+ lfs1_size_t nsize = size;
+
+ if ((file->flags & 3) == LFS1_O_WRONLY) {
+ return LFS1_ERR_BADF;
+ }
+
+ if (file->flags & LFS1_F_WRITING) {
+ // flush out any writes
+ int err = lfs1_file_flush(lfs1, file);
+ if (err) {
+ return err;
+ }
+ }
+
+ if (file->pos >= file->size) {
+ // eof if past end
+ return 0;
+ }
+
+ size = lfs1_min(size, file->size - file->pos);
+ nsize = size;
+
+ while (nsize > 0) {
+ // check if we need a new block
+ if (!(file->flags & LFS1_F_READING) ||
+ file->off == lfs1->cfg->block_size) {
+ int err = lfs1_ctz_find(lfs1, &file->cache, NULL,
+ file->head, file->size,
+ file->pos, &file->block, &file->off);
+ if (err) {
+ return err;
+ }
+
+ file->flags |= LFS1_F_READING;
+ }
+
+ // read as much as we can in current block
+ lfs1_size_t diff = lfs1_min(nsize, lfs1->cfg->block_size - file->off);
+ int err = lfs1_cache_read(lfs1, &file->cache, NULL,
+ file->block, file->off, data, diff);
+ if (err) {
+ return err;
+ }
+
+ file->pos += diff;
+ file->off += diff;
+ data += diff;
+ nsize -= diff;
+ }
+
+ return size;
+}
+
+lfs1_ssize_t lfs1_file_write(lfs1_t *lfs1, lfs1_file_t *file,
+ const void *buffer, lfs1_size_t size) {
+ const uint8_t *data = buffer;
+ lfs1_size_t nsize = size;
+
+ if ((file->flags & 3) == LFS1_O_RDONLY) {
+ return LFS1_ERR_BADF;
+ }
+
+ if (file->flags & LFS1_F_READING) {
+ // drop any reads
+ int err = lfs1_file_flush(lfs1, file);
+ if (err) {
+ return err;
+ }
+ }
+
+ if ((file->flags & LFS1_O_APPEND) && file->pos < file->size) {
+ file->pos = file->size;
+ }
+
+ if (file->pos + size > LFS1_FILE_MAX) {
+ // larger than file limit?
+ return LFS1_ERR_FBIG;
+ }
+
+ if (!(file->flags & LFS1_F_WRITING) && file->pos > file->size) {
+ // fill with zeros
+ lfs1_off_t pos = file->pos;
+ file->pos = file->size;
+
+ while (file->pos < pos) {
+ lfs1_ssize_t res = lfs1_file_write(lfs1, file, &(uint8_t){0}, 1);
+ if (res < 0) {
+ return res;
+ }
+ }
+ }
+
+ while (nsize > 0) {
+ // check if we need a new block
+ if (!(file->flags & LFS1_F_WRITING) ||
+ file->off == lfs1->cfg->block_size) {
+ if (!(file->flags & LFS1_F_WRITING) && file->pos > 0) {
+ // find out which block we're extending from
+ int err = lfs1_ctz_find(lfs1, &file->cache, NULL,
+ file->head, file->size,
+ file->pos-1, &file->block, &file->off);
+ if (err) {
+ file->flags |= LFS1_F_ERRED;
+ return err;
+ }
+
+ // mark cache as dirty since we may have read data into it
+ lfs1_cache_zero(lfs1, &file->cache);
+ }
+
+ // extend file with new blocks
+ lfs1_alloc_ack(lfs1);
+ int err = lfs1_ctz_extend(lfs1, &lfs1->rcache, &file->cache,
+ file->block, file->pos,
+ &file->block, &file->off);
+ if (err) {
+ file->flags |= LFS1_F_ERRED;
+ return err;
+ }
+
+ file->flags |= LFS1_F_WRITING;
+ }
+
+ // program as much as we can in current block
+ lfs1_size_t diff = lfs1_min(nsize, lfs1->cfg->block_size - file->off);
+ while (true) {
+ int err = lfs1_cache_prog(lfs1, &file->cache, &lfs1->rcache,
+ file->block, file->off, data, diff);
+ if (err) {
+ if (err == LFS1_ERR_CORRUPT) {
+ goto relocate;
+ }
+ file->flags |= LFS1_F_ERRED;
+ return err;
+ }
+
+ break;
+relocate:
+ err = lfs1_file_relocate(lfs1, file);
+ if (err) {
+ file->flags |= LFS1_F_ERRED;
+ return err;
+ }
+ }
+
+ file->pos += diff;
+ file->off += diff;
+ data += diff;
+ nsize -= diff;
+
+ lfs1_alloc_ack(lfs1);
+ }
+
+ file->flags &= ~LFS1_F_ERRED;
+ return size;
+}
+
+lfs1_soff_t lfs1_file_seek(lfs1_t *lfs1, lfs1_file_t *file,
+ lfs1_soff_t off, int whence) {
+ // write out everything beforehand, may be noop if rdonly
+ int err = lfs1_file_flush(lfs1, file);
+ if (err) {
+ return err;
+ }
+
+ // find new pos
+ lfs1_soff_t npos = file->pos;
+ if (whence == LFS1_SEEK_SET) {
+ npos = off;
+ } else if (whence == LFS1_SEEK_CUR) {
+ npos = file->pos + off;
+ } else if (whence == LFS1_SEEK_END) {
+ npos = file->size + off;
+ }
+
+ if (npos < 0 || npos > LFS1_FILE_MAX) {
+ // file position out of range
+ return LFS1_ERR_INVAL;
+ }
+
+ // update pos
+ file->pos = npos;
+ return npos;
+}
+
+int lfs1_file_truncate(lfs1_t *lfs1, lfs1_file_t *file, lfs1_off_t size) {
+ if ((file->flags & 3) == LFS1_O_RDONLY) {
+ return LFS1_ERR_BADF;
+ }
+
+ lfs1_off_t oldsize = lfs1_file_size(lfs1, file);
+ if (size < oldsize) {
+ // need to flush since directly changing metadata
+ int err = lfs1_file_flush(lfs1, file);
+ if (err) {
+ return err;
+ }
+
+ // lookup new head in ctz skip list
+ err = lfs1_ctz_find(lfs1, &file->cache, NULL,
+ file->head, file->size,
+ size, &file->head, &(lfs1_off_t){0});
+ if (err) {
+ return err;
+ }
+
+ file->size = size;
+ file->flags |= LFS1_F_DIRTY;
+ } else if (size > oldsize) {
+ lfs1_off_t pos = file->pos;
+
+ // flush+seek if not already at end
+ if (file->pos != oldsize) {
+ int err = lfs1_file_seek(lfs1, file, 0, LFS1_SEEK_END);
+ if (err < 0) {
+ return err;
+ }
+ }
+
+ // fill with zeros
+ while (file->pos < size) {
+ lfs1_ssize_t res = lfs1_file_write(lfs1, file, &(uint8_t){0}, 1);
+ if (res < 0) {
+ return res;
+ }
+ }
+
+ // restore pos
+ int err = lfs1_file_seek(lfs1, file, pos, LFS1_SEEK_SET);
+ if (err < 0) {
+ return err;
+ }
+ }
+
+ return 0;
+}
+
+lfs1_soff_t lfs1_file_tell(lfs1_t *lfs1, lfs1_file_t *file) {
+ (void)lfs1;
+ return file->pos;
+}
+
+int lfs1_file_rewind(lfs1_t *lfs1, lfs1_file_t *file) {
+ lfs1_soff_t res = lfs1_file_seek(lfs1, file, 0, LFS1_SEEK_SET);
+ if (res < 0) {
+ return res;
+ }
+
+ return 0;
+}
+
+lfs1_soff_t lfs1_file_size(lfs1_t *lfs1, lfs1_file_t *file) {
+ (void)lfs1;
+ if (file->flags & LFS1_F_WRITING) {
+ return lfs1_max(file->pos, file->size);
+ } else {
+ return file->size;
+ }
+}
+
+
+/// General fs operations ///
+int lfs1_stat(lfs1_t *lfs1, const char *path, struct lfs1_info *info) {
+ lfs1_dir_t cwd;
+ lfs1_entry_t entry;
+ int err = lfs1_dir_find(lfs1, &cwd, &entry, &path);
+ if (err) {
+ return err;
+ }
+
+ memset(info, 0, sizeof(*info));
+ info->type = entry.d.type;
+ if (info->type == LFS1_TYPE_REG) {
+ info->size = entry.d.u.file.size;
+ }
+
+ if (lfs1_paircmp(entry.d.u.dir, lfs1->root) == 0) {
+ strcpy(info->name, "/");
+ } else {
+ err = lfs1_bd_read(lfs1, cwd.pair[0],
+ entry.off + 4+entry.d.elen+entry.d.alen,
+ info->name, entry.d.nlen);
+ if (err) {
+ return err;
+ }
+ }
+
+ return 0;
+}
+
+int lfs1_remove(lfs1_t *lfs1, const char *path) {
+ // deorphan if we haven't yet, needed at most once after poweron
+ if (!lfs1->deorphaned) {
+ int err = lfs1_deorphan(lfs1);
+ if (err) {
+ return err;
+ }
+ }
+
+ lfs1_dir_t cwd;
+ lfs1_entry_t entry;
+ int err = lfs1_dir_find(lfs1, &cwd, &entry, &path);
+ if (err) {
+ return err;
+ }
+
+ lfs1_dir_t dir;
+ if (entry.d.type == LFS1_TYPE_DIR) {
+ // must be empty before removal, checking size
+ // without masking top bit checks for any case where
+ // dir is not empty
+ err = lfs1_dir_fetch(lfs1, &dir, entry.d.u.dir);
+ if (err) {
+ return err;
+ } else if (dir.d.size != sizeof(dir.d)+4) {
+ return LFS1_ERR_NOTEMPTY;
+ }
+ }
+
+ // remove the entry
+ err = lfs1_dir_remove(lfs1, &cwd, &entry);
+ if (err) {
+ return err;
+ }
+
+ // if we were a directory, find pred, replace tail
+ if (entry.d.type == LFS1_TYPE_DIR) {
+ int res = lfs1_pred(lfs1, dir.pair, &cwd);
+ if (res < 0) {
+ return res;
+ }
+
+ LFS1_ASSERT(res); // must have pred
+ cwd.d.tail[0] = dir.d.tail[0];
+ cwd.d.tail[1] = dir.d.tail[1];
+
+ err = lfs1_dir_commit(lfs1, &cwd, NULL, 0);
+ if (err) {
+ return err;
+ }
+ }
+
+ return 0;
+}
+
+int lfs1_rename(lfs1_t *lfs1, const char *oldpath, const char *newpath) {
+ // deorphan if we haven't yet, needed at most once after poweron
+ if (!lfs1->deorphaned) {
+ int err = lfs1_deorphan(lfs1);
+ if (err) {
+ return err;
+ }
+ }
+
+ // find old entry
+ lfs1_dir_t oldcwd;
+ lfs1_entry_t oldentry;
+ int err = lfs1_dir_find(lfs1, &oldcwd, &oldentry, &(const char *){oldpath});
+ if (err) {
+ return err;
+ }
+
+ // mark as moving
+ oldentry.d.type |= 0x80;
+ err = lfs1_dir_update(lfs1, &oldcwd, &oldentry, NULL);
+ if (err) {
+ return err;
+ }
+
+ // allocate new entry
+ lfs1_dir_t newcwd;
+ lfs1_entry_t preventry;
+ err = lfs1_dir_find(lfs1, &newcwd, &preventry, &newpath);
+ if (err && (err != LFS1_ERR_NOENT || strchr(newpath, '/') != NULL)) {
+ return err;
+ }
+
+ // must have same type
+ bool prevexists = (err != LFS1_ERR_NOENT);
+ if (prevexists && preventry.d.type != (0x7f & oldentry.d.type)) {
+ return LFS1_ERR_ISDIR;
+ }
+
+ lfs1_dir_t dir;
+ if (prevexists && preventry.d.type == LFS1_TYPE_DIR) {
+ // must be empty before removal, checking size
+ // without masking top bit checks for any case where
+ // dir is not empty
+ err = lfs1_dir_fetch(lfs1, &dir, preventry.d.u.dir);
+ if (err) {
+ return err;
+ } else if (dir.d.size != sizeof(dir.d)+4) {
+ return LFS1_ERR_NOTEMPTY;
+ }
+ }
+
+ // move to new location
+ lfs1_entry_t newentry = preventry;
+ newentry.d = oldentry.d;
+ newentry.d.type &= ~0x80;
+ newentry.d.nlen = strlen(newpath);
+
+ if (prevexists) {
+ err = lfs1_dir_update(lfs1, &newcwd, &newentry, newpath);
+ if (err) {
+ return err;
+ }
+ } else {
+ err = lfs1_dir_append(lfs1, &newcwd, &newentry, newpath);
+ if (err) {
+ return err;
+ }
+ }
+
+ // fetch old pair again in case dir block changed
+ lfs1->moving = true;
+ err = lfs1_dir_find(lfs1, &oldcwd, &oldentry, &oldpath);
+ if (err) {
+ return err;
+ }
+ lfs1->moving = false;
+
+ // remove old entry
+ err = lfs1_dir_remove(lfs1, &oldcwd, &oldentry);
+ if (err) {
+ return err;
+ }
+
+ // if we were a directory, find pred, replace tail
+ if (prevexists && preventry.d.type == LFS1_TYPE_DIR) {
+ int res = lfs1_pred(lfs1, dir.pair, &newcwd);
+ if (res < 0) {
+ return res;
+ }
+
+ LFS1_ASSERT(res); // must have pred
+ newcwd.d.tail[0] = dir.d.tail[0];
+ newcwd.d.tail[1] = dir.d.tail[1];
+
+ err = lfs1_dir_commit(lfs1, &newcwd, NULL, 0);
+ if (err) {
+ return err;
+ }
+ }
+
+ return 0;
+}
+
+
+/// Filesystem operations ///
+static void lfs1_deinit(lfs1_t *lfs1) {
+ // free allocated memory
+ if (!lfs1->cfg->read_buffer) {
+ lfs1_free(lfs1->rcache.buffer);
+ }
+
+ if (!lfs1->cfg->prog_buffer) {
+ lfs1_free(lfs1->pcache.buffer);
+ }
+
+ if (!lfs1->cfg->lookahead_buffer) {
+ lfs1_free(lfs1->free.buffer);
+ }
+}
+
+static int lfs1_init(lfs1_t *lfs1, const struct lfs1_config *cfg) {
+ lfs1->cfg = cfg;
+
+ // setup read cache
+ if (lfs1->cfg->read_buffer) {
+ lfs1->rcache.buffer = lfs1->cfg->read_buffer;
+ } else {
+ lfs1->rcache.buffer = lfs1_malloc(lfs1->cfg->read_size);
+ if (!lfs1->rcache.buffer) {
+ goto cleanup;
+ }
+ }
+
+ // setup program cache
+ if (lfs1->cfg->prog_buffer) {
+ lfs1->pcache.buffer = lfs1->cfg->prog_buffer;
+ } else {
+ lfs1->pcache.buffer = lfs1_malloc(lfs1->cfg->prog_size);
+ if (!lfs1->pcache.buffer) {
+ goto cleanup;
+ }
+ }
+
+ // zero to avoid information leaks
+ lfs1_cache_zero(lfs1, &lfs1->pcache);
+ lfs1_cache_drop(lfs1, &lfs1->rcache);
+
+ // setup lookahead, round down to nearest 32-bits
+ LFS1_ASSERT(lfs1->cfg->lookahead % 32 == 0);
+ LFS1_ASSERT(lfs1->cfg->lookahead > 0);
+ if (lfs1->cfg->lookahead_buffer) {
+ lfs1->free.buffer = lfs1->cfg->lookahead_buffer;
+ } else {
+ lfs1->free.buffer = lfs1_malloc(lfs1->cfg->lookahead/8);
+ if (!lfs1->free.buffer) {
+ goto cleanup;
+ }
+ }
+
+ // check that program and read sizes are multiples of the block size
+ LFS1_ASSERT(lfs1->cfg->prog_size % lfs1->cfg->read_size == 0);
+ LFS1_ASSERT(lfs1->cfg->block_size % lfs1->cfg->prog_size == 0);
+
+ // check that the block size is large enough to fit ctz pointers
+ LFS1_ASSERT(4*lfs1_npw2(0xffffffff / (lfs1->cfg->block_size-2*4))
+ <= lfs1->cfg->block_size);
+
+ // setup default state
+ lfs1->root[0] = 0xffffffff;
+ lfs1->root[1] = 0xffffffff;
+ lfs1->files = NULL;
+ lfs1->dirs = NULL;
+ lfs1->deorphaned = false;
+ lfs1->moving = false;
+
+ return 0;
+
+cleanup:
+ lfs1_deinit(lfs1);
+ return LFS1_ERR_NOMEM;
+}
+
+int lfs1_format(lfs1_t *lfs1, const struct lfs1_config *cfg) {
+ int err = 0;
+ if (true) {
+ err = lfs1_init(lfs1, cfg);
+ if (err) {
+ return err;
+ }
+
+ // create free lookahead
+ memset(lfs1->free.buffer, 0, lfs1->cfg->lookahead/8);
+ lfs1->free.off = 0;
+ lfs1->free.size = lfs1_min(lfs1->cfg->lookahead, lfs1->cfg->block_count);
+ lfs1->free.i = 0;
+ lfs1_alloc_ack(lfs1);
+
+ // create superblock dir
+ lfs1_dir_t superdir;
+ err = lfs1_dir_alloc(lfs1, &superdir);
+ if (err) {
+ goto cleanup;
+ }
+
+ // write root directory
+ lfs1_dir_t root;
+ err = lfs1_dir_alloc(lfs1, &root);
+ if (err) {
+ goto cleanup;
+ }
+
+ err = lfs1_dir_commit(lfs1, &root, NULL, 0);
+ if (err) {
+ goto cleanup;
+ }
+
+ lfs1->root[0] = root.pair[0];
+ lfs1->root[1] = root.pair[1];
+
+ // write superblocks
+ lfs1_superblock_t superblock = {
+ .off = sizeof(superdir.d),
+ .d.type = LFS1_TYPE_SUPERBLOCK,
+ .d.elen = sizeof(superblock.d) - sizeof(superblock.d.magic) - 4,
+ .d.nlen = sizeof(superblock.d.magic),
+ .d.version = LFS1_DISK_VERSION,
+ .d.magic = {"littlefs"},
+ .d.block_size = lfs1->cfg->block_size,
+ .d.block_count = lfs1->cfg->block_count,
+ .d.root = {lfs1->root[0], lfs1->root[1]},
+ };
+ superdir.d.tail[0] = root.pair[0];
+ superdir.d.tail[1] = root.pair[1];
+ superdir.d.size = sizeof(superdir.d) + sizeof(superblock.d) + 4;
+
+ // write both pairs to be safe
+ lfs1_superblock_tole32(&superblock.d);
+ bool valid = false;
+ for (int i = 0; i < 2; i++) {
+ err = lfs1_dir_commit(lfs1, &superdir, (struct lfs1_region[]){
+ {sizeof(superdir.d), sizeof(superblock.d),
+ &superblock.d, sizeof(superblock.d)}
+ }, 1);
+ if (err && err != LFS1_ERR_CORRUPT) {
+ goto cleanup;
+ }
+
+ valid = valid || !err;
+ }
+
+ if (!valid) {
+ err = LFS1_ERR_CORRUPT;
+ goto cleanup;
+ }
+
+ // sanity check that fetch works
+ err = lfs1_dir_fetch(lfs1, &superdir, (const lfs1_block_t[2]){0, 1});
+ if (err) {
+ goto cleanup;
+ }
+
+ lfs1_alloc_ack(lfs1);
+ }
+
+cleanup:
+ lfs1_deinit(lfs1);
+ return err;
+}
+
+int lfs1_mount(lfs1_t *lfs1, const struct lfs1_config *cfg) {
+ int err = 0;
+ if (true) {
+ err = lfs1_init(lfs1, cfg);
+ if (err) {
+ return err;
+ }
+
+ // setup free lookahead
+ lfs1->free.off = 0;
+ lfs1->free.size = 0;
+ lfs1->free.i = 0;
+ lfs1_alloc_ack(lfs1);
+
+ // load superblock
+ lfs1_dir_t dir;
+ lfs1_superblock_t superblock;
+ err = lfs1_dir_fetch(lfs1, &dir, (const lfs1_block_t[2]){0, 1});
+ if (err && err != LFS1_ERR_CORRUPT) {
+ goto cleanup;
+ }
+
+ if (!err) {
+ err = lfs1_bd_read(lfs1, dir.pair[0], sizeof(dir.d),
+ &superblock.d, sizeof(superblock.d));
+ lfs1_superblock_fromle32(&superblock.d);
+ if (err) {
+ goto cleanup;
+ }
+
+ lfs1->root[0] = superblock.d.root[0];
+ lfs1->root[1] = superblock.d.root[1];
+ }
+
+ if (err || memcmp(superblock.d.magic, "littlefs", 8) != 0) {
+ LFS1_ERROR("Invalid superblock at %d %d", 0, 1);
+ err = LFS1_ERR_CORRUPT;
+ goto cleanup;
+ }
+
+ uint16_t major_version = (0xffff & (superblock.d.version >> 16));
+ uint16_t minor_version = (0xffff & (superblock.d.version >> 0));
+ if ((major_version != LFS1_DISK_VERSION_MAJOR ||
+ minor_version > LFS1_DISK_VERSION_MINOR)) {
+ LFS1_ERROR("Invalid version %d.%d", major_version, minor_version);
+ err = LFS1_ERR_INVAL;
+ goto cleanup;
+ }
+
+ return 0;
+ }
+
+cleanup:
+
+ lfs1_deinit(lfs1);
+ return err;
+}
+
+int lfs1_unmount(lfs1_t *lfs1) {
+ lfs1_deinit(lfs1);
+ return 0;
+}
+
+
+/// Littlefs specific operations ///
+int lfs1_traverse(lfs1_t *lfs1, int (*cb)(void*, lfs1_block_t), void *data) {
+ if (lfs1_pairisnull(lfs1->root)) {
+ return 0;
+ }
+
+ // iterate over metadata pairs
+ lfs1_dir_t dir;
+ lfs1_entry_t entry;
+ lfs1_block_t cwd[2] = {0, 1};
+
+ while (true) {
+ for (int i = 0; i < 2; i++) {
+ int err = cb(data, cwd[i]);
+ if (err) {
+ return err;
+ }
+ }
+
+ int err = lfs1_dir_fetch(lfs1, &dir, cwd);
+ if (err) {
+ return err;
+ }
+
+ // iterate over contents
+ while (dir.off + sizeof(entry.d) <= (0x7fffffff & dir.d.size)-4) {
+ err = lfs1_bd_read(lfs1, dir.pair[0], dir.off,
+ &entry.d, sizeof(entry.d));
+ lfs1_entry_fromle32(&entry.d);
+ if (err) {
+ return err;
+ }
+
+ dir.off += lfs1_entry_size(&entry);
+ if ((0x70 & entry.d.type) == (0x70 & LFS1_TYPE_REG)) {
+ err = lfs1_ctz_traverse(lfs1, &lfs1->rcache, NULL,
+ entry.d.u.file.head, entry.d.u.file.size, cb, data);
+ if (err) {
+ return err;
+ }
+ }
+ }
+
+ cwd[0] = dir.d.tail[0];
+ cwd[1] = dir.d.tail[1];
+
+ if (lfs1_pairisnull(cwd)) {
+ break;
+ }
+ }
+
+ // iterate over any open files
+ for (lfs1_file_t *f = lfs1->files; f; f = f->next) {
+ if (f->flags & LFS1_F_DIRTY) {
+ int err = lfs1_ctz_traverse(lfs1, &lfs1->rcache, &f->cache,
+ f->head, f->size, cb, data);
+ if (err) {
+ return err;
+ }
+ }
+
+ if (f->flags & LFS1_F_WRITING) {
+ int err = lfs1_ctz_traverse(lfs1, &lfs1->rcache, &f->cache,
+ f->block, f->pos, cb, data);
+ if (err) {
+ return err;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int lfs1_pred(lfs1_t *lfs1, const lfs1_block_t dir[2], lfs1_dir_t *pdir) {
+ if (lfs1_pairisnull(lfs1->root)) {
+ return 0;
+ }
+
+ // iterate over all directory directory entries
+ int err = lfs1_dir_fetch(lfs1, pdir, (const lfs1_block_t[2]){0, 1});
+ if (err) {
+ return err;
+ }
+
+ while (!lfs1_pairisnull(pdir->d.tail)) {
+ if (lfs1_paircmp(pdir->d.tail, dir) == 0) {
+ return true;
+ }
+
+ err = lfs1_dir_fetch(lfs1, pdir, pdir->d.tail);
+ if (err) {
+ return err;
+ }
+ }
+
+ return false;
+}
+
+static int lfs1_parent(lfs1_t *lfs1, const lfs1_block_t dir[2],
+ lfs1_dir_t *parent, lfs1_entry_t *entry) {
+ if (lfs1_pairisnull(lfs1->root)) {
+ return 0;
+ }
+
+ parent->d.tail[0] = 0;
+ parent->d.tail[1] = 1;
+
+ // iterate over all directory directory entries
+ while (!lfs1_pairisnull(parent->d.tail)) {
+ int err = lfs1_dir_fetch(lfs1, parent, parent->d.tail);
+ if (err) {
+ return err;
+ }
+
+ while (true) {
+ err = lfs1_dir_next(lfs1, parent, entry);
+ if (err && err != LFS1_ERR_NOENT) {
+ return err;
+ }
+
+ if (err == LFS1_ERR_NOENT) {
+ break;
+ }
+
+ if (((0x70 & entry->d.type) == (0x70 & LFS1_TYPE_DIR)) &&
+ lfs1_paircmp(entry->d.u.dir, dir) == 0) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+static int lfs1_moved(lfs1_t *lfs1, const void *e) {
+ if (lfs1_pairisnull(lfs1->root)) {
+ return 0;
+ }
+
+ // skip superblock
+ lfs1_dir_t cwd;
+ int err = lfs1_dir_fetch(lfs1, &cwd, (const lfs1_block_t[2]){0, 1});
+ if (err) {
+ return err;
+ }
+
+ // iterate over all directory directory entries
+ lfs1_entry_t entry;
+ while (!lfs1_pairisnull(cwd.d.tail)) {
+ err = lfs1_dir_fetch(lfs1, &cwd, cwd.d.tail);
+ if (err) {
+ return err;
+ }
+
+ while (true) {
+ err = lfs1_dir_next(lfs1, &cwd, &entry);
+ if (err && err != LFS1_ERR_NOENT) {
+ return err;
+ }
+
+ if (err == LFS1_ERR_NOENT) {
+ break;
+ }
+
+ if (!(0x80 & entry.d.type) &&
+ memcmp(&entry.d.u, e, sizeof(entry.d.u)) == 0) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+static int lfs1_relocate(lfs1_t *lfs1,
+ const lfs1_block_t oldpair[2], const lfs1_block_t newpair[2]) {
+ // find parent
+ lfs1_dir_t parent;
+ lfs1_entry_t entry;
+ int res = lfs1_parent(lfs1, oldpair, &parent, &entry);
+ if (res < 0) {
+ return res;
+ }
+
+ if (res) {
+ // update disk, this creates a desync
+ entry.d.u.dir[0] = newpair[0];
+ entry.d.u.dir[1] = newpair[1];
+
+ int err = lfs1_dir_update(lfs1, &parent, &entry, NULL);
+ if (err) {
+ return err;
+ }
+
+ // update internal root
+ if (lfs1_paircmp(oldpair, lfs1->root) == 0) {
+ LFS1_DEBUG("Relocating root %" PRIu32 " %" PRIu32,
+ newpair[0], newpair[1]);
+ lfs1->root[0] = newpair[0];
+ lfs1->root[1] = newpair[1];
+ }
+
+ // clean up bad block, which should now be a desync
+ return lfs1_deorphan(lfs1);
+ }
+
+ // find pred
+ res = lfs1_pred(lfs1, oldpair, &parent);
+ if (res < 0) {
+ return res;
+ }
+
+ if (res) {
+ // just replace bad pair, no desync can occur
+ parent.d.tail[0] = newpair[0];
+ parent.d.tail[1] = newpair[1];
+
+ return lfs1_dir_commit(lfs1, &parent, NULL, 0);
+ }
+
+ // couldn't find dir, must be new
+ return 0;
+}
+
+int lfs1_deorphan(lfs1_t *lfs1) {
+ lfs1->deorphaned = true;
+
+ if (lfs1_pairisnull(lfs1->root)) {
+ return 0;
+ }
+
+ lfs1_dir_t pdir = {.d.size = 0x80000000};
+ lfs1_dir_t cwd = {.d.tail[0] = 0, .d.tail[1] = 1};
+
+ // iterate over all directory directory entries
+ for (lfs1_size_t i = 0; i < lfs1->cfg->block_count; i++) {
+ if (lfs1_pairisnull(cwd.d.tail)) {
+ return 0;
+ }
+
+ int err = lfs1_dir_fetch(lfs1, &cwd, cwd.d.tail);
+ if (err) {
+ return err;
+ }
+
+ // check head blocks for orphans
+ if (!(0x80000000 & pdir.d.size)) {
+ // check if we have a parent
+ lfs1_dir_t parent;
+ lfs1_entry_t entry;
+ int res = lfs1_parent(lfs1, pdir.d.tail, &parent, &entry);
+ if (res < 0) {
+ return res;
+ }
+
+ if (!res) {
+ // we are an orphan
+ LFS1_DEBUG("Found orphan %" PRIu32 " %" PRIu32,
+ pdir.d.tail[0], pdir.d.tail[1]);
+
+ pdir.d.tail[0] = cwd.d.tail[0];
+ pdir.d.tail[1] = cwd.d.tail[1];
+
+ err = lfs1_dir_commit(lfs1, &pdir, NULL, 0);
+ if (err) {
+ return err;
+ }
+
+ return 0;
+ }
+
+ if (!lfs1_pairsync(entry.d.u.dir, pdir.d.tail)) {
+ // we have desynced
+ LFS1_DEBUG("Found desync %" PRIu32 " %" PRIu32,
+ entry.d.u.dir[0], entry.d.u.dir[1]);
+
+ pdir.d.tail[0] = entry.d.u.dir[0];
+ pdir.d.tail[1] = entry.d.u.dir[1];
+
+ err = lfs1_dir_commit(lfs1, &pdir, NULL, 0);
+ if (err) {
+ return err;
+ }
+
+ return 0;
+ }
+ }
+
+ // check entries for moves
+ lfs1_entry_t entry;
+ while (true) {
+ err = lfs1_dir_next(lfs1, &cwd, &entry);
+ if (err && err != LFS1_ERR_NOENT) {
+ return err;
+ }
+
+ if (err == LFS1_ERR_NOENT) {
+ break;
+ }
+
+ // found moved entry
+ if (entry.d.type & 0x80) {
+ int moved = lfs1_moved(lfs1, &entry.d.u);
+ if (moved < 0) {
+ return moved;
+ }
+
+ if (moved) {
+ LFS1_DEBUG("Found move %" PRIu32 " %" PRIu32,
+ entry.d.u.dir[0], entry.d.u.dir[1]);
+ err = lfs1_dir_remove(lfs1, &cwd, &entry);
+ if (err) {
+ return err;
+ }
+ } else {
+ LFS1_DEBUG("Found partial move %" PRIu32 " %" PRIu32,
+ entry.d.u.dir[0], entry.d.u.dir[1]);
+ entry.d.type &= ~0x80;
+ err = lfs1_dir_update(lfs1, &cwd, &entry, NULL);
+ if (err) {
+ return err;
+ }
+ }
+ }
+ }
+
+ memcpy(&pdir, &cwd, sizeof(pdir));
+ }
+
+ // If we reached here, we have more directory pairs than blocks in the
+ // filesystem... So something must be horribly wrong
+ return LFS1_ERR_CORRUPT;
+}
diff --git a/lib/littlefs/lfs1.h b/lib/littlefs/lfs1.h
new file mode 100644
index 0000000000..355c145d08
--- /dev/null
+++ b/lib/littlefs/lfs1.h
@@ -0,0 +1,501 @@
+/*
+ * The little filesystem
+ *
+ * Copyright (c) 2017, Arm Limited. All rights reserved.
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef LFS1_H
+#define LFS1_H
+
+#include
+#include
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+
+/// Version info ///
+
+// Software library version
+// Major (top-nibble), incremented on backwards incompatible changes
+// Minor (bottom-nibble), incremented on feature additions
+#define LFS1_VERSION 0x00010007
+#define LFS1_VERSION_MAJOR (0xffff & (LFS1_VERSION >> 16))
+#define LFS1_VERSION_MINOR (0xffff & (LFS1_VERSION >> 0))
+
+// Version of On-disk data structures
+// Major (top-nibble), incremented on backwards incompatible changes
+// Minor (bottom-nibble), incremented on feature additions
+#define LFS1_DISK_VERSION 0x00010001
+#define LFS1_DISK_VERSION_MAJOR (0xffff & (LFS1_DISK_VERSION >> 16))
+#define LFS1_DISK_VERSION_MINOR (0xffff & (LFS1_DISK_VERSION >> 0))
+
+
+/// Definitions ///
+
+// Type definitions
+typedef uint32_t lfs1_size_t;
+typedef uint32_t lfs1_off_t;
+
+typedef int32_t lfs1_ssize_t;
+typedef int32_t lfs1_soff_t;
+
+typedef uint32_t lfs1_block_t;
+
+// Max name size in bytes
+#ifndef LFS1_NAME_MAX
+#define LFS1_NAME_MAX 255
+#endif
+
+// Max file size in bytes
+#ifndef LFS1_FILE_MAX
+#define LFS1_FILE_MAX 2147483647
+#endif
+
+// Possible error codes, these are negative to allow
+// valid positive return values
+enum lfs1_error {
+ LFS1_ERR_OK = 0, // No error
+ LFS1_ERR_IO = -5, // Error during device operation
+ LFS1_ERR_CORRUPT = -52, // Corrupted
+ LFS1_ERR_NOENT = -2, // No directory entry
+ LFS1_ERR_EXIST = -17, // Entry already exists
+ LFS1_ERR_NOTDIR = -20, // Entry is not a dir
+ LFS1_ERR_ISDIR = -21, // Entry is a dir
+ LFS1_ERR_NOTEMPTY = -39, // Dir is not empty
+ LFS1_ERR_BADF = -9, // Bad file number
+ LFS1_ERR_FBIG = -27, // File too large
+ LFS1_ERR_INVAL = -22, // Invalid parameter
+ LFS1_ERR_NOSPC = -28, // No space left on device
+ LFS1_ERR_NOMEM = -12, // No more memory available
+};
+
+// File types
+enum lfs1_type {
+ LFS1_TYPE_REG = 0x11,
+ LFS1_TYPE_DIR = 0x22,
+ LFS1_TYPE_SUPERBLOCK = 0x2e,
+};
+
+// File open flags
+enum lfs1_open_flags {
+ // open flags
+ LFS1_O_RDONLY = 1, // Open a file as read only
+ LFS1_O_WRONLY = 2, // Open a file as write only
+ LFS1_O_RDWR = 3, // Open a file as read and write
+ LFS1_O_CREAT = 0x0100, // Create a file if it does not exist
+ LFS1_O_EXCL = 0x0200, // Fail if a file already exists
+ LFS1_O_TRUNC = 0x0400, // Truncate the existing file to zero size
+ LFS1_O_APPEND = 0x0800, // Move to end of file on every write
+
+ // internally used flags
+ LFS1_F_DIRTY = 0x10000, // File does not match storage
+ LFS1_F_WRITING = 0x20000, // File has been written since last flush
+ LFS1_F_READING = 0x40000, // File has been read since last flush
+ LFS1_F_ERRED = 0x80000, // An error occured during write
+};
+
+// File seek flags
+enum lfs1_whence_flags {
+ LFS1_SEEK_SET = 0, // Seek relative to an absolute position
+ LFS1_SEEK_CUR = 1, // Seek relative to the current file position
+ LFS1_SEEK_END = 2, // Seek relative to the end of the file
+};
+
+
+// Configuration provided during initialization of the littlefs
+struct lfs1_config {
+ // Opaque user provided context that can be used to pass
+ // information to the block device operations
+ void *context;
+
+ // Read a region in a block. Negative error codes are propogated
+ // to the user.
+ int (*read)(const struct lfs1_config *c, lfs1_block_t block,
+ lfs1_off_t off, void *buffer, lfs1_size_t size);
+
+ // Program a region in a block. The block must have previously
+ // been erased. Negative error codes are propogated to the user.
+ // May return LFS1_ERR_CORRUPT if the block should be considered bad.
+ int (*prog)(const struct lfs1_config *c, lfs1_block_t block,
+ lfs1_off_t off, const void *buffer, lfs1_size_t size);
+
+ // Erase a block. A block must be erased before being programmed.
+ // The state of an erased block is undefined. Negative error codes
+ // are propogated to the user.
+ // May return LFS1_ERR_CORRUPT if the block should be considered bad.
+ int (*erase)(const struct lfs1_config *c, lfs1_block_t block);
+
+ // Sync the state of the underlying block device. Negative error codes
+ // are propogated to the user.
+ int (*sync)(const struct lfs1_config *c);
+
+ // Minimum size of a block read. This determines the size of read buffers.
+ // This may be larger than the physical read size to improve performance
+ // by caching more of the block device.
+ lfs1_size_t read_size;
+
+ // Minimum size of a block program. This determines the size of program
+ // buffers. This may be larger than the physical program size to improve
+ // performance by caching more of the block device.
+ // Must be a multiple of the read size.
+ lfs1_size_t prog_size;
+
+ // Size of an erasable block. This does not impact ram consumption and
+ // may be larger than the physical erase size. However, this should be
+ // kept small as each file currently takes up an entire block.
+ // Must be a multiple of the program size.
+ lfs1_size_t block_size;
+
+ // Number of erasable blocks on the device.
+ lfs1_size_t block_count;
+
+ // Number of blocks to lookahead during block allocation. A larger
+ // lookahead reduces the number of passes required to allocate a block.
+ // The lookahead buffer requires only 1 bit per block so it can be quite
+ // large with little ram impact. Should be a multiple of 32.
+ lfs1_size_t lookahead;
+
+ // Optional, statically allocated read buffer. Must be read sized.
+ void *read_buffer;
+
+ // Optional, statically allocated program buffer. Must be program sized.
+ void *prog_buffer;
+
+ // Optional, statically allocated lookahead buffer. Must be 1 bit per
+ // lookahead block.
+ void *lookahead_buffer;
+
+ // Optional, statically allocated buffer for files. Must be program sized.
+ // If enabled, only one file may be opened at a time.
+ void *file_buffer;
+};
+
+// Optional configuration provided during lfs1_file_opencfg
+struct lfs1_file_config {
+ // Optional, statically allocated buffer for files. Must be program sized.
+ // If NULL, malloc will be used by default.
+ void *buffer;
+};
+
+// File info structure
+struct lfs1_info {
+ // Type of the file, either LFS1_TYPE_REG or LFS1_TYPE_DIR
+ uint8_t type;
+
+ // Size of the file, only valid for REG files
+ lfs1_size_t size;
+
+ // Name of the file stored as a null-terminated string
+ char name[LFS1_NAME_MAX+1];
+};
+
+
+/// littlefs data structures ///
+typedef struct lfs1_entry {
+ lfs1_off_t off;
+
+ struct lfs1_disk_entry {
+ uint8_t type;
+ uint8_t elen;
+ uint8_t alen;
+ uint8_t nlen;
+ union {
+ struct {
+ lfs1_block_t head;
+ lfs1_size_t size;
+ } file;
+ lfs1_block_t dir[2];
+ } u;
+ } d;
+} lfs1_entry_t;
+
+typedef struct lfs1_cache {
+ lfs1_block_t block;
+ lfs1_off_t off;
+ uint8_t *buffer;
+} lfs1_cache_t;
+
+typedef struct lfs1_file {
+ struct lfs1_file *next;
+ lfs1_block_t pair[2];
+ lfs1_off_t poff;
+
+ lfs1_block_t head;
+ lfs1_size_t size;
+
+ const struct lfs1_file_config *cfg;
+ uint32_t flags;
+ lfs1_off_t pos;
+ lfs1_block_t block;
+ lfs1_off_t off;
+ lfs1_cache_t cache;
+} lfs1_file_t;
+
+typedef struct lfs1_dir {
+ struct lfs1_dir *next;
+ lfs1_block_t pair[2];
+ lfs1_off_t off;
+
+ lfs1_block_t head[2];
+ lfs1_off_t pos;
+
+ struct lfs1_disk_dir {
+ uint32_t rev;
+ lfs1_size_t size;
+ lfs1_block_t tail[2];
+ } d;
+} lfs1_dir_t;
+
+typedef struct lfs1_superblock {
+ lfs1_off_t off;
+
+ struct lfs1_disk_superblock {
+ uint8_t type;
+ uint8_t elen;
+ uint8_t alen;
+ uint8_t nlen;
+ lfs1_block_t root[2];
+ uint32_t block_size;
+ uint32_t block_count;
+ uint32_t version;
+ char magic[8];
+ } d;
+} lfs1_superblock_t;
+
+typedef struct lfs1_free {
+ lfs1_block_t off;
+ lfs1_block_t size;
+ lfs1_block_t i;
+ lfs1_block_t ack;
+ uint32_t *buffer;
+} lfs1_free_t;
+
+// The littlefs type
+typedef struct lfs1 {
+ const struct lfs1_config *cfg;
+
+ lfs1_block_t root[2];
+ lfs1_file_t *files;
+ lfs1_dir_t *dirs;
+
+ lfs1_cache_t rcache;
+ lfs1_cache_t pcache;
+
+ lfs1_free_t free;
+ bool deorphaned;
+ bool moving;
+} lfs1_t;
+
+
+/// Filesystem functions ///
+
+// Format a block device with the littlefs
+//
+// Requires a littlefs object and config struct. This clobbers the littlefs
+// object, and does not leave the filesystem mounted. The config struct must
+// be zeroed for defaults and backwards compatibility.
+//
+// Returns a negative error code on failure.
+int lfs1_format(lfs1_t *lfs1, const struct lfs1_config *config);
+
+// Mounts a littlefs
+//
+// Requires a littlefs object and config struct. Multiple filesystems
+// may be mounted simultaneously with multiple littlefs objects. Both
+// lfs1 and config must be allocated while mounted. The config struct must
+// be zeroed for defaults and backwards compatibility.
+//
+// Returns a negative error code on failure.
+int lfs1_mount(lfs1_t *lfs1, const struct lfs1_config *config);
+
+// Unmounts a littlefs
+//
+// Does nothing besides releasing any allocated resources.
+// Returns a negative error code on failure.
+int lfs1_unmount(lfs1_t *lfs1);
+
+/// General operations ///
+
+// Removes a file or directory
+//
+// If removing a directory, the directory must be empty.
+// Returns a negative error code on failure.
+int lfs1_remove(lfs1_t *lfs1, const char *path);
+
+// Rename or move a file or directory
+//
+// If the destination exists, it must match the source in type.
+// If the destination is a directory, the directory must be empty.
+//
+// Returns a negative error code on failure.
+int lfs1_rename(lfs1_t *lfs1, const char *oldpath, const char *newpath);
+
+// Find info about a file or directory
+//
+// Fills out the info structure, based on the specified file or directory.
+// Returns a negative error code on failure.
+int lfs1_stat(lfs1_t *lfs1, const char *path, struct lfs1_info *info);
+
+
+/// File operations ///
+
+// Open a file
+//
+// The mode that the file is opened in is determined by the flags, which
+// are values from the enum lfs1_open_flags that are bitwise-ored together.
+//
+// Returns a negative error code on failure.
+int lfs1_file_open(lfs1_t *lfs1, lfs1_file_t *file,
+ const char *path, int flags);
+
+// Open a file with extra configuration
+//
+// The mode that the file is opened in is determined by the flags, which
+// are values from the enum lfs1_open_flags that are bitwise-ored together.
+//
+// The config struct provides additional config options per file as described
+// above. The config struct must be allocated while the file is open, and the
+// config struct must be zeroed for defaults and backwards compatibility.
+//
+// Returns a negative error code on failure.
+int lfs1_file_opencfg(lfs1_t *lfs1, lfs1_file_t *file,
+ const char *path, int flags,
+ const struct lfs1_file_config *config);
+
+// Close a file
+//
+// Any pending writes are written out to storage as though
+// sync had been called and releases any allocated resources.
+//
+// Returns a negative error code on failure.
+int lfs1_file_close(lfs1_t *lfs1, lfs1_file_t *file);
+
+// Synchronize a file on storage
+//
+// Any pending writes are written out to storage.
+// Returns a negative error code on failure.
+int lfs1_file_sync(lfs1_t *lfs1, lfs1_file_t *file);
+
+// Read data from file
+//
+// Takes a buffer and size indicating where to store the read data.
+// Returns the number of bytes read, or a negative error code on failure.
+lfs1_ssize_t lfs1_file_read(lfs1_t *lfs1, lfs1_file_t *file,
+ void *buffer, lfs1_size_t size);
+
+// Write data to file
+//
+// Takes a buffer and size indicating the data to write. The file will not
+// actually be updated on the storage until either sync or close is called.
+//
+// Returns the number of bytes written, or a negative error code on failure.
+lfs1_ssize_t lfs1_file_write(lfs1_t *lfs1, lfs1_file_t *file,
+ const void *buffer, lfs1_size_t size);
+
+// Change the position of the file
+//
+// The change in position is determined by the offset and whence flag.
+// Returns the old position of the file, or a negative error code on failure.
+lfs1_soff_t lfs1_file_seek(lfs1_t *lfs1, lfs1_file_t *file,
+ lfs1_soff_t off, int whence);
+
+// Truncates the size of the file to the specified size
+//
+// Returns a negative error code on failure.
+int lfs1_file_truncate(lfs1_t *lfs1, lfs1_file_t *file, lfs1_off_t size);
+
+// Return the position of the file
+//
+// Equivalent to lfs1_file_seek(lfs1, file, 0, LFS1_SEEK_CUR)
+// Returns the position of the file, or a negative error code on failure.
+lfs1_soff_t lfs1_file_tell(lfs1_t *lfs1, lfs1_file_t *file);
+
+// Change the position of the file to the beginning of the file
+//
+// Equivalent to lfs1_file_seek(lfs1, file, 0, LFS1_SEEK_CUR)
+// Returns a negative error code on failure.
+int lfs1_file_rewind(lfs1_t *lfs1, lfs1_file_t *file);
+
+// Return the size of the file
+//
+// Similar to lfs1_file_seek(lfs1, file, 0, LFS1_SEEK_END)
+// Returns the size of the file, or a negative error code on failure.
+lfs1_soff_t lfs1_file_size(lfs1_t *lfs1, lfs1_file_t *file);
+
+
+/// Directory operations ///
+
+// Create a directory
+//
+// Returns a negative error code on failure.
+int lfs1_mkdir(lfs1_t *lfs1, const char *path);
+
+// Open a directory
+//
+// Once open a directory can be used with read to iterate over files.
+// Returns a negative error code on failure.
+int lfs1_dir_open(lfs1_t *lfs1, lfs1_dir_t *dir, const char *path);
+
+// Close a directory
+//
+// Releases any allocated resources.
+// Returns a negative error code on failure.
+int lfs1_dir_close(lfs1_t *lfs1, lfs1_dir_t *dir);
+
+// Read an entry in the directory
+//
+// Fills out the info structure, based on the specified file or directory.
+// Returns a negative error code on failure.
+int lfs1_dir_read(lfs1_t *lfs1, lfs1_dir_t *dir, struct lfs1_info *info);
+
+// Change the position of the directory
+//
+// The new off must be a value previous returned from tell and specifies
+// an absolute offset in the directory seek.
+//
+// Returns a negative error code on failure.
+int lfs1_dir_seek(lfs1_t *lfs1, lfs1_dir_t *dir, lfs1_off_t off);
+
+// Return the position of the directory
+//
+// The returned offset is only meant to be consumed by seek and may not make
+// sense, but does indicate the current position in the directory iteration.
+//
+// Returns the position of the directory, or a negative error code on failure.
+lfs1_soff_t lfs1_dir_tell(lfs1_t *lfs1, lfs1_dir_t *dir);
+
+// Change the position of the directory to the beginning of the directory
+//
+// Returns a negative error code on failure.
+int lfs1_dir_rewind(lfs1_t *lfs1, lfs1_dir_t *dir);
+
+
+/// Miscellaneous littlefs specific operations ///
+
+// Traverse through all blocks in use by the filesystem
+//
+// The provided callback will be called with each block address that is
+// currently in use by the filesystem. This can be used to determine which
+// blocks are in use or how much of the storage is available.
+//
+// Returns a negative error code on failure.
+int lfs1_traverse(lfs1_t *lfs1, int (*cb)(void*, lfs1_block_t), void *data);
+
+// Prunes any recoverable errors that may have occured in the filesystem
+//
+// Not needed to be called by user unless an operation is interrupted
+// but the filesystem is still mounted. This is already called on first
+// allocation.
+//
+// Returns a negative error code on failure.
+int lfs1_deorphan(lfs1_t *lfs1);
+
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif
diff --git a/lib/littlefs/lfs1_util.c b/lib/littlefs/lfs1_util.c
new file mode 100644
index 0000000000..3832a5ddb3
--- /dev/null
+++ b/lib/littlefs/lfs1_util.c
@@ -0,0 +1,31 @@
+/*
+ * lfs1 util functions
+ *
+ * Copyright (c) 2017, Arm Limited. All rights reserved.
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include "lfs1_util.h"
+
+// Only compile if user does not provide custom config
+#ifndef LFS1_CONFIG
+
+
+// Software CRC implementation with small lookup table
+void lfs1_crc(uint32_t *restrict crc, const void *buffer, size_t size) {
+ static const uint32_t rtable[16] = {
+ 0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,
+ 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
+ 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
+ 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c,
+ };
+
+ const uint8_t *data = buffer;
+
+ for (size_t i = 0; i < size; i++) {
+ *crc = (*crc >> 4) ^ rtable[(*crc ^ (data[i] >> 0)) & 0xf];
+ *crc = (*crc >> 4) ^ rtable[(*crc ^ (data[i] >> 4)) & 0xf];
+ }
+}
+
+
+#endif
diff --git a/lib/littlefs/lfs1_util.h b/lib/littlefs/lfs1_util.h
new file mode 100644
index 0000000000..b33b6a7adc
--- /dev/null
+++ b/lib/littlefs/lfs1_util.h
@@ -0,0 +1,186 @@
+/*
+ * lfs1 utility functions
+ *
+ * Copyright (c) 2017, Arm Limited. All rights reserved.
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef LFS1_UTIL_H
+#define LFS1_UTIL_H
+
+// Users can override lfs1_util.h with their own configuration by defining
+// LFS1_CONFIG as a header file to include (-DLFS1_CONFIG=lfs1_config.h).
+//
+// If LFS1_CONFIG is used, none of the default utils will be emitted and must be
+// provided by the config file. To start I would suggest copying lfs1_util.h and
+// modifying as needed.
+#ifdef LFS1_CONFIG
+#define LFS1_STRINGIZE(x) LFS1_STRINGIZE2(x)
+#define LFS1_STRINGIZE2(x) #x
+#include LFS1_STRINGIZE(LFS1_CONFIG)
+#else
+
+// System includes
+#include
+#include
+#include
+
+#ifndef LFS1_NO_MALLOC
+#include
+#endif
+#ifndef LFS1_NO_ASSERT
+#include
+#endif
+#if !defined(LFS1_NO_DEBUG) || !defined(LFS1_NO_WARN) || !defined(LFS1_NO_ERROR)
+#include
+#endif
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+
+// Macros, may be replaced by system specific wrappers. Arguments to these
+// macros must not have side-effects as the macros can be removed for a smaller
+// code footprint
+
+// Logging functions
+#ifndef LFS1_NO_DEBUG
+#define LFS1_DEBUG(fmt, ...) \
+ printf("lfs1 debug:%d: " fmt "\n", __LINE__, __VA_ARGS__)
+#else
+#define LFS1_DEBUG(fmt, ...)
+#endif
+
+#ifndef LFS1_NO_WARN
+#define LFS1_WARN(fmt, ...) \
+ printf("lfs1 warn:%d: " fmt "\n", __LINE__, __VA_ARGS__)
+#else
+#define LFS1_WARN(fmt, ...)
+#endif
+
+#ifndef LFS1_NO_ERROR
+#define LFS1_ERROR(fmt, ...) \
+ printf("lfs1 error:%d: " fmt "\n", __LINE__, __VA_ARGS__)
+#else
+#define LFS1_ERROR(fmt, ...)
+#endif
+
+// Runtime assertions
+#ifndef LFS1_NO_ASSERT
+#define LFS1_ASSERT(test) assert(test)
+#else
+#define LFS1_ASSERT(test)
+#endif
+
+
+// Builtin functions, these may be replaced by more efficient
+// toolchain-specific implementations. LFS1_NO_INTRINSICS falls back to a more
+// expensive basic C implementation for debugging purposes
+
+// Min/max functions for unsigned 32-bit numbers
+static inline uint32_t lfs1_max(uint32_t a, uint32_t b) {
+ return (a > b) ? a : b;
+}
+
+static inline uint32_t lfs1_min(uint32_t a, uint32_t b) {
+ return (a < b) ? a : b;
+}
+
+// Find the next smallest power of 2 less than or equal to a
+static inline uint32_t lfs1_npw2(uint32_t a) {
+#if !defined(LFS1_NO_INTRINSICS) && (defined(__GNUC__) || defined(__CC_ARM))
+ return 32 - __builtin_clz(a-1);
+#else
+ uint32_t r = 0;
+ uint32_t s;
+ a -= 1;
+ s = (a > 0xffff) << 4; a >>= s; r |= s;
+ s = (a > 0xff ) << 3; a >>= s; r |= s;
+ s = (a > 0xf ) << 2; a >>= s; r |= s;
+ s = (a > 0x3 ) << 1; a >>= s; r |= s;
+ return (r | (a >> 1)) + 1;
+#endif
+}
+
+// Count the number of trailing binary zeros in a
+// lfs1_ctz(0) may be undefined
+static inline uint32_t lfs1_ctz(uint32_t a) {
+#if !defined(LFS1_NO_INTRINSICS) && defined(__GNUC__)
+ return __builtin_ctz(a);
+#else
+ return lfs1_npw2((a & -a) + 1) - 1;
+#endif
+}
+
+// Count the number of binary ones in a
+static inline uint32_t lfs1_popc(uint32_t a) {
+#if !defined(LFS1_NO_INTRINSICS) && (defined(__GNUC__) || defined(__CC_ARM))
+ return __builtin_popcount(a);
+#else
+ a = a - ((a >> 1) & 0x55555555);
+ a = (a & 0x33333333) + ((a >> 2) & 0x33333333);
+ return (((a + (a >> 4)) & 0xf0f0f0f) * 0x1010101) >> 24;
+#endif
+}
+
+// Find the sequence comparison of a and b, this is the distance
+// between a and b ignoring overflow
+static inline int lfs1_scmp(uint32_t a, uint32_t b) {
+ return (int)(unsigned)(a - b);
+}
+
+// Convert from 32-bit little-endian to native order
+static inline uint32_t lfs1_fromle32(uint32_t a) {
+#if !defined(LFS1_NO_INTRINSICS) && ( \
+ (defined( BYTE_ORDER ) && BYTE_ORDER == ORDER_LITTLE_ENDIAN ) || \
+ (defined(__BYTE_ORDER ) && __BYTE_ORDER == __ORDER_LITTLE_ENDIAN ) || \
+ (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__))
+ return a;
+#elif !defined(LFS1_NO_INTRINSICS) && ( \
+ (defined( BYTE_ORDER ) && BYTE_ORDER == ORDER_BIG_ENDIAN ) || \
+ (defined(__BYTE_ORDER ) && __BYTE_ORDER == __ORDER_BIG_ENDIAN ) || \
+ (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__))
+ return __builtin_bswap32(a);
+#else
+ return (((uint8_t*)&a)[0] << 0) |
+ (((uint8_t*)&a)[1] << 8) |
+ (((uint8_t*)&a)[2] << 16) |
+ (((uint8_t*)&a)[3] << 24);
+#endif
+}
+
+// Convert to 32-bit little-endian from native order
+static inline uint32_t lfs1_tole32(uint32_t a) {
+ return lfs1_fromle32(a);
+}
+
+// Calculate CRC-32 with polynomial = 0x04c11db7
+void lfs1_crc(uint32_t *crc, const void *buffer, size_t size);
+
+// Allocate memory, only used if buffers are not provided to littlefs
+static inline void *lfs1_malloc(size_t size) {
+#ifndef LFS1_NO_MALLOC
+ return malloc(size);
+#else
+ (void)size;
+ return NULL;
+#endif
+}
+
+// Deallocate memory, only used if buffers are not provided to littlefs
+static inline void lfs1_free(void *p) {
+#ifndef LFS1_NO_MALLOC
+ free(p);
+#else
+ (void)p;
+#endif
+}
+
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif
+#endif
diff --git a/lib/littlefs/lfs2.c b/lib/littlefs/lfs2.c
new file mode 100644
index 0000000000..6bae806ceb
--- /dev/null
+++ b/lib/littlefs/lfs2.c
@@ -0,0 +1,4913 @@
+/*
+ * The little filesystem
+ *
+ * Copyright (c) 2017, Arm Limited. All rights reserved.
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include "lfs2.h"
+#include "lfs2_util.h"
+
+#define LFS2_BLOCK_NULL ((lfs2_block_t)-1)
+#define LFS2_BLOCK_INLINE ((lfs2_block_t)-2)
+
+/// Caching block device operations ///
+static inline void lfs2_cache_drop(lfs2_t *lfs2, lfs2_cache_t *rcache) {
+ // do not zero, cheaper if cache is readonly or only going to be
+ // written with identical data (during relocates)
+ (void)lfs2;
+ rcache->block = LFS2_BLOCK_NULL;
+}
+
+static inline void lfs2_cache_zero(lfs2_t *lfs2, lfs2_cache_t *pcache) {
+ // zero to avoid information leak
+ memset(pcache->buffer, 0xff, lfs2->cfg->cache_size);
+ pcache->block = LFS2_BLOCK_NULL;
+}
+
+static int lfs2_bd_read(lfs2_t *lfs2,
+ const lfs2_cache_t *pcache, lfs2_cache_t *rcache, lfs2_size_t hint,
+ lfs2_block_t block, lfs2_off_t off,
+ void *buffer, lfs2_size_t size) {
+ uint8_t *data = buffer;
+ if (block >= lfs2->cfg->block_count ||
+ off+size > lfs2->cfg->block_size) {
+ return LFS2_ERR_CORRUPT;
+ }
+
+ while (size > 0) {
+ lfs2_size_t diff = size;
+
+ if (pcache && block == pcache->block &&
+ off < pcache->off + pcache->size) {
+ if (off >= pcache->off) {
+ // is already in pcache?
+ diff = lfs2_min(diff, pcache->size - (off-pcache->off));
+ memcpy(data, &pcache->buffer[off-pcache->off], diff);
+
+ data += diff;
+ off += diff;
+ size -= diff;
+ continue;
+ }
+
+ // pcache takes priority
+ diff = lfs2_min(diff, pcache->off-off);
+ }
+
+ if (block == rcache->block &&
+ off < rcache->off + rcache->size) {
+ if (off >= rcache->off) {
+ // is already in rcache?
+ diff = lfs2_min(diff, rcache->size - (off-rcache->off));
+ memcpy(data, &rcache->buffer[off-rcache->off], diff);
+
+ data += diff;
+ off += diff;
+ size -= diff;
+ continue;
+ }
+
+ // rcache takes priority
+ diff = lfs2_min(diff, rcache->off-off);
+ }
+
+ if (size >= hint && off % lfs2->cfg->read_size == 0 &&
+ size >= lfs2->cfg->read_size) {
+ // bypass cache?
+ diff = lfs2_aligndown(diff, lfs2->cfg->read_size);
+ int err = lfs2->cfg->read(lfs2->cfg, block, off, data, diff);
+ if (err) {
+ return err;
+ }
+
+ data += diff;
+ off += diff;
+ size -= diff;
+ continue;
+ }
+
+ // load to cache, first condition can no longer fail
+ LFS2_ASSERT(block < lfs2->cfg->block_count);
+ rcache->block = block;
+ rcache->off = lfs2_aligndown(off, lfs2->cfg->read_size);
+ rcache->size = lfs2_min(
+ lfs2_min(
+ lfs2_alignup(off+hint, lfs2->cfg->read_size),
+ lfs2->cfg->block_size)
+ - rcache->off,
+ lfs2->cfg->cache_size);
+ int err = lfs2->cfg->read(lfs2->cfg, rcache->block,
+ rcache->off, rcache->buffer, rcache->size);
+ LFS2_ASSERT(err <= 0);
+ if (err) {
+ return err;
+ }
+ }
+
+ return 0;
+}
+
+enum {
+ LFS2_CMP_EQ = 0,
+ LFS2_CMP_LT = 1,
+ LFS2_CMP_GT = 2,
+};
+
+static int lfs2_bd_cmp(lfs2_t *lfs2,
+ const lfs2_cache_t *pcache, lfs2_cache_t *rcache, lfs2_size_t hint,
+ lfs2_block_t block, lfs2_off_t off,
+ const void *buffer, lfs2_size_t size) {
+ const uint8_t *data = buffer;
+
+ for (lfs2_off_t i = 0; i < size; i++) {
+ uint8_t dat;
+ int err = lfs2_bd_read(lfs2,
+ pcache, rcache, hint-i,
+ block, off+i, &dat, 1);
+ if (err) {
+ return err;
+ }
+
+ if (dat != data[i]) {
+ return (dat < data[i]) ? LFS2_CMP_LT : LFS2_CMP_GT;
+ }
+ }
+
+ return LFS2_CMP_EQ;
+}
+
+static int lfs2_bd_flush(lfs2_t *lfs2,
+ lfs2_cache_t *pcache, lfs2_cache_t *rcache, bool validate) {
+ if (pcache->block != LFS2_BLOCK_NULL && pcache->block != LFS2_BLOCK_INLINE) {
+ LFS2_ASSERT(pcache->block < lfs2->cfg->block_count);
+ lfs2_size_t diff = lfs2_alignup(pcache->size, lfs2->cfg->prog_size);
+ int err = lfs2->cfg->prog(lfs2->cfg, pcache->block,
+ pcache->off, pcache->buffer, diff);
+ LFS2_ASSERT(err <= 0);
+ if (err) {
+ return err;
+ }
+
+ if (validate) {
+ // check data on disk
+ lfs2_cache_drop(lfs2, rcache);
+ int res = lfs2_bd_cmp(lfs2,
+ NULL, rcache, diff,
+ pcache->block, pcache->off, pcache->buffer, diff);
+ if (res < 0) {
+ return res;
+ }
+
+ if (res != LFS2_CMP_EQ) {
+ return LFS2_ERR_CORRUPT;
+ }
+ }
+
+ lfs2_cache_zero(lfs2, pcache);
+ }
+
+ return 0;
+}
+
+static int lfs2_bd_sync(lfs2_t *lfs2,
+ lfs2_cache_t *pcache, lfs2_cache_t *rcache, bool validate) {
+ lfs2_cache_drop(lfs2, rcache);
+
+ int err = lfs2_bd_flush(lfs2, pcache, rcache, validate);
+ if (err) {
+ return err;
+ }
+
+ err = lfs2->cfg->sync(lfs2->cfg);
+ LFS2_ASSERT(err <= 0);
+ return err;
+}
+
+static int lfs2_bd_prog(lfs2_t *lfs2,
+ lfs2_cache_t *pcache, lfs2_cache_t *rcache, bool validate,
+ lfs2_block_t block, lfs2_off_t off,
+ const void *buffer, lfs2_size_t size) {
+ const uint8_t *data = buffer;
+ LFS2_ASSERT(block == LFS2_BLOCK_INLINE || block < lfs2->cfg->block_count);
+ LFS2_ASSERT(off + size <= lfs2->cfg->block_size);
+
+ while (size > 0) {
+ if (block == pcache->block &&
+ off >= pcache->off &&
+ off < pcache->off + lfs2->cfg->cache_size) {
+ // already fits in pcache?
+ lfs2_size_t diff = lfs2_min(size,
+ lfs2->cfg->cache_size - (off-pcache->off));
+ memcpy(&pcache->buffer[off-pcache->off], data, diff);
+
+ data += diff;
+ off += diff;
+ size -= diff;
+
+ pcache->size = lfs2_max(pcache->size, off - pcache->off);
+ if (pcache->size == lfs2->cfg->cache_size) {
+ // eagerly flush out pcache if we fill up
+ int err = lfs2_bd_flush(lfs2, pcache, rcache, validate);
+ if (err) {
+ return err;
+ }
+ }
+
+ continue;
+ }
+
+ // pcache must have been flushed, either by programming and
+ // entire block or manually flushing the pcache
+ LFS2_ASSERT(pcache->block == LFS2_BLOCK_NULL);
+
+ // prepare pcache, first condition can no longer fail
+ pcache->block = block;
+ pcache->off = lfs2_aligndown(off, lfs2->cfg->prog_size);
+ pcache->size = 0;
+ }
+
+ return 0;
+}
+
+static int lfs2_bd_erase(lfs2_t *lfs2, lfs2_block_t block) {
+ LFS2_ASSERT(block < lfs2->cfg->block_count);
+ int err = lfs2->cfg->erase(lfs2->cfg, block);
+ LFS2_ASSERT(err <= 0);
+ return err;
+}
+
+
+/// Small type-level utilities ///
+// operations on block pairs
+static inline void lfs2_pair_swap(lfs2_block_t pair[2]) {
+ lfs2_block_t t = pair[0];
+ pair[0] = pair[1];
+ pair[1] = t;
+}
+
+static inline bool lfs2_pair_isnull(const lfs2_block_t pair[2]) {
+ return pair[0] == LFS2_BLOCK_NULL || pair[1] == LFS2_BLOCK_NULL;
+}
+
+static inline int lfs2_pair_cmp(
+ const lfs2_block_t paira[2],
+ const lfs2_block_t pairb[2]) {
+ return !(paira[0] == pairb[0] || paira[1] == pairb[1] ||
+ paira[0] == pairb[1] || paira[1] == pairb[0]);
+}
+
+static inline bool lfs2_pair_sync(
+ const lfs2_block_t paira[2],
+ const lfs2_block_t pairb[2]) {
+ return (paira[0] == pairb[0] && paira[1] == pairb[1]) ||
+ (paira[0] == pairb[1] && paira[1] == pairb[0]);
+}
+
+static inline void lfs2_pair_fromle32(lfs2_block_t pair[2]) {
+ pair[0] = lfs2_fromle32(pair[0]);
+ pair[1] = lfs2_fromle32(pair[1]);
+}
+
+static inline void lfs2_pair_tole32(lfs2_block_t pair[2]) {
+ pair[0] = lfs2_tole32(pair[0]);
+ pair[1] = lfs2_tole32(pair[1]);
+}
+
+// operations on 32-bit entry tags
+typedef uint32_t lfs2_tag_t;
+typedef int32_t lfs2_stag_t;
+
+#define LFS2_MKTAG(type, id, size) \
+ (((lfs2_tag_t)(type) << 20) | ((lfs2_tag_t)(id) << 10) | (lfs2_tag_t)(size))
+
+#define LFS2_MKTAG_IF(cond, type, id, size) \
+ ((cond) ? LFS2_MKTAG(type, id, size) : LFS2_MKTAG(LFS2_FROM_NOOP, 0, 0))
+
+#define LFS2_MKTAG_IF_ELSE(cond, type1, id1, size1, type2, id2, size2) \
+ ((cond) ? LFS2_MKTAG(type1, id1, size1) : LFS2_MKTAG(type2, id2, size2))
+
+static inline bool lfs2_tag_isvalid(lfs2_tag_t tag) {
+ return !(tag & 0x80000000);
+}
+
+static inline bool lfs2_tag_isdelete(lfs2_tag_t tag) {
+ return ((int32_t)(tag << 22) >> 22) == -1;
+}
+
+static inline uint16_t lfs2_tag_type1(lfs2_tag_t tag) {
+ return (tag & 0x70000000) >> 20;
+}
+
+static inline uint16_t lfs2_tag_type3(lfs2_tag_t tag) {
+ return (tag & 0x7ff00000) >> 20;
+}
+
+static inline uint8_t lfs2_tag_chunk(lfs2_tag_t tag) {
+ return (tag & 0x0ff00000) >> 20;
+}
+
+static inline int8_t lfs2_tag_splice(lfs2_tag_t tag) {
+ return (int8_t)lfs2_tag_chunk(tag);
+}
+
+static inline uint16_t lfs2_tag_id(lfs2_tag_t tag) {
+ return (tag & 0x000ffc00) >> 10;
+}
+
+static inline lfs2_size_t lfs2_tag_size(lfs2_tag_t tag) {
+ return tag & 0x000003ff;
+}
+
+static inline lfs2_size_t lfs2_tag_dsize(lfs2_tag_t tag) {
+ return sizeof(tag) + lfs2_tag_size(tag + lfs2_tag_isdelete(tag));
+}
+
+// operations on attributes in attribute lists
+struct lfs2_mattr {
+ lfs2_tag_t tag;
+ const void *buffer;
+};
+
+struct lfs2_diskoff {
+ lfs2_block_t block;
+ lfs2_off_t off;
+};
+
+#define LFS2_MKATTRS(...) \
+ (struct lfs2_mattr[]){__VA_ARGS__}, \
+ sizeof((struct lfs2_mattr[]){__VA_ARGS__}) / sizeof(struct lfs2_mattr)
+
+// operations on global state
+static inline void lfs2_gstate_xor(lfs2_gstate_t *a, const lfs2_gstate_t *b) {
+ for (int i = 0; i < 3; i++) {
+ ((uint32_t*)a)[i] ^= ((const uint32_t*)b)[i];
+ }
+}
+
+static inline bool lfs2_gstate_iszero(const lfs2_gstate_t *a) {
+ for (int i = 0; i < 3; i++) {
+ if (((uint32_t*)a)[i] != 0) {
+ return false;
+ }
+ }
+ return true;
+}
+
+static inline bool lfs2_gstate_hasorphans(const lfs2_gstate_t *a) {
+ return lfs2_tag_size(a->tag);
+}
+
+static inline uint8_t lfs2_gstate_getorphans(const lfs2_gstate_t *a) {
+ return lfs2_tag_size(a->tag);
+}
+
+static inline bool lfs2_gstate_hasmove(const lfs2_gstate_t *a) {
+ return lfs2_tag_type1(a->tag);
+}
+
+static inline bool lfs2_gstate_hasmovehere(const lfs2_gstate_t *a,
+ const lfs2_block_t *pair) {
+ return lfs2_tag_type1(a->tag) && lfs2_pair_cmp(a->pair, pair) == 0;
+}
+
+static inline void lfs2_gstate_fromle32(lfs2_gstate_t *a) {
+ a->tag = lfs2_fromle32(a->tag);
+ a->pair[0] = lfs2_fromle32(a->pair[0]);
+ a->pair[1] = lfs2_fromle32(a->pair[1]);
+}
+
+static inline void lfs2_gstate_tole32(lfs2_gstate_t *a) {
+ a->tag = lfs2_tole32(a->tag);
+ a->pair[0] = lfs2_tole32(a->pair[0]);
+ a->pair[1] = lfs2_tole32(a->pair[1]);
+}
+
+// other endianness operations
+static void lfs2_ctz_fromle32(struct lfs2_ctz *ctz) {
+ ctz->head = lfs2_fromle32(ctz->head);
+ ctz->size = lfs2_fromle32(ctz->size);
+}
+
+static void lfs2_ctz_tole32(struct lfs2_ctz *ctz) {
+ ctz->head = lfs2_tole32(ctz->head);
+ ctz->size = lfs2_tole32(ctz->size);
+}
+
+static inline void lfs2_superblock_fromle32(lfs2_superblock_t *superblock) {
+ superblock->version = lfs2_fromle32(superblock->version);
+ superblock->block_size = lfs2_fromle32(superblock->block_size);
+ superblock->block_count = lfs2_fromle32(superblock->block_count);
+ superblock->name_max = lfs2_fromle32(superblock->name_max);
+ superblock->file_max = lfs2_fromle32(superblock->file_max);
+ superblock->attr_max = lfs2_fromle32(superblock->attr_max);
+}
+
+static inline void lfs2_superblock_tole32(lfs2_superblock_t *superblock) {
+ superblock->version = lfs2_tole32(superblock->version);
+ superblock->block_size = lfs2_tole32(superblock->block_size);
+ superblock->block_count = lfs2_tole32(superblock->block_count);
+ superblock->name_max = lfs2_tole32(superblock->name_max);
+ superblock->file_max = lfs2_tole32(superblock->file_max);
+ superblock->attr_max = lfs2_tole32(superblock->attr_max);
+}
+
+
+/// Internal operations predeclared here ///
+static int lfs2_dir_commit(lfs2_t *lfs2, lfs2_mdir_t *dir,
+ const struct lfs2_mattr *attrs, int attrcount);
+static int lfs2_dir_compact(lfs2_t *lfs2,
+ lfs2_mdir_t *dir, const struct lfs2_mattr *attrs, int attrcount,
+ lfs2_mdir_t *source, uint16_t begin, uint16_t end);
+static int lfs2_file_outline(lfs2_t *lfs2, lfs2_file_t *file);
+static int lfs2_file_flush(lfs2_t *lfs2, lfs2_file_t *file);
+static void lfs2_fs_preporphans(lfs2_t *lfs2, int8_t orphans);
+static void lfs2_fs_prepmove(lfs2_t *lfs2,
+ uint16_t id, const lfs2_block_t pair[2]);
+static int lfs2_fs_pred(lfs2_t *lfs2, const lfs2_block_t dir[2],
+ lfs2_mdir_t *pdir);
+static lfs2_stag_t lfs2_fs_parent(lfs2_t *lfs2, const lfs2_block_t dir[2],
+ lfs2_mdir_t *parent);
+static int lfs2_fs_relocate(lfs2_t *lfs2,
+ const lfs2_block_t oldpair[2], lfs2_block_t newpair[2]);
+int lfs2_fs_traverseraw(lfs2_t *lfs2,
+ int (*cb)(void *data, lfs2_block_t block), void *data,
+ bool includeorphans);
+static int lfs2_fs_forceconsistency(lfs2_t *lfs2);
+static int lfs2_deinit(lfs2_t *lfs2);
+#ifdef LFS2_MIGRATE
+static int lfs21_traverse(lfs2_t *lfs2,
+ int (*cb)(void*, lfs2_block_t), void *data);
+#endif
+
+/// Block allocator ///
+static int lfs2_alloc_lookahead(void *p, lfs2_block_t block) {
+ lfs2_t *lfs2 = (lfs2_t*)p;
+ lfs2_block_t off = ((block - lfs2->free.off)
+ + lfs2->cfg->block_count) % lfs2->cfg->block_count;
+
+ if (off < lfs2->free.size) {
+ lfs2->free.buffer[off / 32] |= 1U << (off % 32);
+ }
+
+ return 0;
+}
+
+static void lfs2_alloc_ack(lfs2_t *lfs2) {
+ lfs2->free.ack = lfs2->cfg->block_count;
+}
+
+// Invalidate the lookahead buffer. This is done during mounting and
+// failed traversals
+static void lfs2_alloc_reset(lfs2_t *lfs2) {
+ lfs2->free.off = lfs2->seed % lfs2->cfg->block_size;
+ lfs2->free.size = 0;
+ lfs2->free.i = 0;
+ lfs2_alloc_ack(lfs2);
+}
+
+static int lfs2_alloc(lfs2_t *lfs2, lfs2_block_t *block) {
+ while (true) {
+ while (lfs2->free.i != lfs2->free.size) {
+ lfs2_block_t off = lfs2->free.i;
+ lfs2->free.i += 1;
+ lfs2->free.ack -= 1;
+
+ if (!(lfs2->free.buffer[off / 32] & (1U << (off % 32)))) {
+ // found a free block
+ *block = (lfs2->free.off + off) % lfs2->cfg->block_count;
+
+ // eagerly find next off so an alloc ack can
+ // discredit old lookahead blocks
+ while (lfs2->free.i != lfs2->free.size &&
+ (lfs2->free.buffer[lfs2->free.i / 32]
+ & (1U << (lfs2->free.i % 32)))) {
+ lfs2->free.i += 1;
+ lfs2->free.ack -= 1;
+ }
+
+ return 0;
+ }
+ }
+
+ // check if we have looked at all blocks since last ack
+ if (lfs2->free.ack == 0) {
+ LFS2_ERROR("No more free space %"PRIu32,
+ lfs2->free.i + lfs2->free.off);
+ return LFS2_ERR_NOSPC;
+ }
+
+ lfs2->free.off = (lfs2->free.off + lfs2->free.size)
+ % lfs2->cfg->block_count;
+ lfs2->free.size = lfs2_min(8*lfs2->cfg->lookahead_size, lfs2->free.ack);
+ lfs2->free.i = 0;
+
+ // find mask of free blocks from tree
+ memset(lfs2->free.buffer, 0, lfs2->cfg->lookahead_size);
+ int err = lfs2_fs_traverseraw(lfs2, lfs2_alloc_lookahead, lfs2, true);
+ if (err) {
+ lfs2_alloc_reset(lfs2);
+ return err;
+ }
+ }
+}
+
+/// Metadata pair and directory operations ///
+static lfs2_stag_t lfs2_dir_getslice(lfs2_t *lfs2, const lfs2_mdir_t *dir,
+ lfs2_tag_t gmask, lfs2_tag_t gtag,
+ lfs2_off_t goff, void *gbuffer, lfs2_size_t gsize) {
+ lfs2_off_t off = dir->off;
+ lfs2_tag_t ntag = dir->etag;
+ lfs2_stag_t gdiff = 0;
+
+ if (lfs2_gstate_hasmovehere(&lfs2->gdisk, dir->pair) &&
+ lfs2_tag_id(gmask) != 0 &&
+ lfs2_tag_id(lfs2->gdisk.tag) <= lfs2_tag_id(gtag)) {
+ // synthetic moves
+ gdiff -= LFS2_MKTAG(0, 1, 0);
+ }
+
+ // iterate over dir block backwards (for faster lookups)
+ while (off >= sizeof(lfs2_tag_t) + lfs2_tag_dsize(ntag)) {
+ off -= lfs2_tag_dsize(ntag);
+ lfs2_tag_t tag = ntag;
+ int err = lfs2_bd_read(lfs2,
+ NULL, &lfs2->rcache, sizeof(ntag),
+ dir->pair[0], off, &ntag, sizeof(ntag));
+ if (err) {
+ return err;
+ }
+
+ ntag = (lfs2_frombe32(ntag) ^ tag) & 0x7fffffff;
+
+ if (lfs2_tag_id(gmask) != 0 &&
+ lfs2_tag_type1(tag) == LFS2_TYPE_SPLICE &&
+ lfs2_tag_id(tag) <= lfs2_tag_id(gtag - gdiff)) {
+ if (tag == (LFS2_MKTAG(LFS2_TYPE_CREATE, 0, 0) |
+ (LFS2_MKTAG(0, 0x3ff, 0) & (gtag - gdiff)))) {
+ // found where we were created
+ return LFS2_ERR_NOENT;
+ }
+
+ // move around splices
+ gdiff += LFS2_MKTAG(0, lfs2_tag_splice(tag), 0);
+ }
+
+ if ((gmask & tag) == (gmask & (gtag - gdiff))) {
+ if (lfs2_tag_isdelete(tag)) {
+ return LFS2_ERR_NOENT;
+ }
+
+ lfs2_size_t diff = lfs2_min(lfs2_tag_size(tag), gsize);
+ err = lfs2_bd_read(lfs2,
+ NULL, &lfs2->rcache, diff,
+ dir->pair[0], off+sizeof(tag)+goff, gbuffer, diff);
+ if (err) {
+ return err;
+ }
+
+ memset((uint8_t*)gbuffer + diff, 0, gsize - diff);
+
+ return tag + gdiff;
+ }
+ }
+
+ return LFS2_ERR_NOENT;
+}
+
+static lfs2_stag_t lfs2_dir_get(lfs2_t *lfs2, const lfs2_mdir_t *dir,
+ lfs2_tag_t gmask, lfs2_tag_t gtag, void *buffer) {
+ return lfs2_dir_getslice(lfs2, dir,
+ gmask, gtag,
+ 0, buffer, lfs2_tag_size(gtag));
+}
+
+static int lfs2_dir_getread(lfs2_t *lfs2, const lfs2_mdir_t *dir,
+ const lfs2_cache_t *pcache, lfs2_cache_t *rcache, lfs2_size_t hint,
+ lfs2_tag_t gmask, lfs2_tag_t gtag,
+ lfs2_off_t off, void *buffer, lfs2_size_t size) {
+ uint8_t *data = buffer;
+ if (off+size > lfs2->cfg->block_size) {
+ return LFS2_ERR_CORRUPT;
+ }
+
+ while (size > 0) {
+ lfs2_size_t diff = size;
+
+ if (pcache && pcache->block == LFS2_BLOCK_INLINE &&
+ off < pcache->off + pcache->size) {
+ if (off >= pcache->off) {
+ // is already in pcache?
+ diff = lfs2_min(diff, pcache->size - (off-pcache->off));
+ memcpy(data, &pcache->buffer[off-pcache->off], diff);
+
+ data += diff;
+ off += diff;
+ size -= diff;
+ continue;
+ }
+
+ // pcache takes priority
+ diff = lfs2_min(diff, pcache->off-off);
+ }
+
+ if (rcache->block == LFS2_BLOCK_INLINE &&
+ off < rcache->off + rcache->size) {
+ if (off >= rcache->off) {
+ // is already in rcache?
+ diff = lfs2_min(diff, rcache->size - (off-rcache->off));
+ memcpy(data, &rcache->buffer[off-rcache->off], diff);
+
+ data += diff;
+ off += diff;
+ size -= diff;
+ continue;
+ }
+
+ // rcache takes priority
+ diff = lfs2_min(diff, rcache->off-off);
+ }
+
+ // load to cache, first condition can no longer fail
+ rcache->block = LFS2_BLOCK_INLINE;
+ rcache->off = lfs2_aligndown(off, lfs2->cfg->read_size);
+ rcache->size = lfs2_min(lfs2_alignup(off+hint, lfs2->cfg->read_size),
+ lfs2->cfg->cache_size);
+ int err = lfs2_dir_getslice(lfs2, dir, gmask, gtag,
+ rcache->off, rcache->buffer, rcache->size);
+ if (err < 0) {
+ return err;
+ }
+ }
+
+ return 0;
+}
+
+static int lfs2_dir_traverse_filter(void *p,
+ lfs2_tag_t tag, const void *buffer) {
+ lfs2_tag_t *filtertag = p;
+ (void)buffer;
+
+ // which mask depends on unique bit in tag structure
+ uint32_t mask = (tag & LFS2_MKTAG(0x100, 0, 0))
+ ? LFS2_MKTAG(0x7ff, 0x3ff, 0)
+ : LFS2_MKTAG(0x700, 0x3ff, 0);
+
+ // check for redundancy
+ if ((mask & tag) == (mask & *filtertag) ||
+ lfs2_tag_isdelete(*filtertag) ||
+ (LFS2_MKTAG(0x7ff, 0x3ff, 0) & tag) == (
+ LFS2_MKTAG(LFS2_TYPE_DELETE, 0, 0) |
+ (LFS2_MKTAG(0, 0x3ff, 0) & *filtertag))) {
+ return true;
+ }
+
+ // check if we need to adjust for created/deleted tags
+ if (lfs2_tag_type1(tag) == LFS2_TYPE_SPLICE &&
+ lfs2_tag_id(tag) <= lfs2_tag_id(*filtertag)) {
+ *filtertag += LFS2_MKTAG(0, lfs2_tag_splice(tag), 0);
+ }
+
+ return false;
+}
+
+static int lfs2_dir_traverse(lfs2_t *lfs2,
+ const lfs2_mdir_t *dir, lfs2_off_t off, lfs2_tag_t ptag,
+ const struct lfs2_mattr *attrs, int attrcount,
+ lfs2_tag_t tmask, lfs2_tag_t ttag,
+ uint16_t begin, uint16_t end, int16_t diff,
+ int (*cb)(void *data, lfs2_tag_t tag, const void *buffer), void *data) {
+ // iterate over directory and attrs
+ while (true) {
+ lfs2_tag_t tag;
+ const void *buffer;
+ struct lfs2_diskoff disk;
+ if (off+lfs2_tag_dsize(ptag) < dir->off) {
+ off += lfs2_tag_dsize(ptag);
+ int err = lfs2_bd_read(lfs2,
+ NULL, &lfs2->rcache, sizeof(tag),
+ dir->pair[0], off, &tag, sizeof(tag));
+ if (err) {
+ return err;
+ }
+
+ tag = (lfs2_frombe32(tag) ^ ptag) | 0x80000000;
+ disk.block = dir->pair[0];
+ disk.off = off+sizeof(lfs2_tag_t);
+ buffer = &disk;
+ ptag = tag;
+ } else if (attrcount > 0) {
+ tag = attrs[0].tag;
+ buffer = attrs[0].buffer;
+ attrs += 1;
+ attrcount -= 1;
+ } else {
+ return 0;
+ }
+
+ lfs2_tag_t mask = LFS2_MKTAG(0x7ff, 0, 0);
+ if ((mask & tmask & tag) != (mask & tmask & ttag)) {
+ continue;
+ }
+
+ // do we need to filter? inlining the filtering logic here allows
+ // for some minor optimizations
+ if (lfs2_tag_id(tmask) != 0) {
+ // scan for duplicates and update tag based on creates/deletes
+ int filter = lfs2_dir_traverse(lfs2,
+ dir, off, ptag, attrs, attrcount,
+ 0, 0, 0, 0, 0,
+ lfs2_dir_traverse_filter, &tag);
+ if (filter < 0) {
+ return filter;
+ }
+
+ if (filter) {
+ continue;
+ }
+
+ // in filter range?
+ if (!(lfs2_tag_id(tag) >= begin && lfs2_tag_id(tag) < end)) {
+ continue;
+ }
+ }
+
+ // handle special cases for mcu-side operations
+ if (lfs2_tag_type3(tag) == LFS2_FROM_NOOP) {
+ // do nothing
+ } else if (lfs2_tag_type3(tag) == LFS2_FROM_MOVE) {
+ uint16_t fromid = lfs2_tag_size(tag);
+ uint16_t toid = lfs2_tag_id(tag);
+ int err = lfs2_dir_traverse(lfs2,
+ buffer, 0, 0xffffffff, NULL, 0,
+ LFS2_MKTAG(0x600, 0x3ff, 0),
+ LFS2_MKTAG(LFS2_TYPE_STRUCT, 0, 0),
+ fromid, fromid+1, toid-fromid+diff,
+ cb, data);
+ if (err) {
+ return err;
+ }
+ } else if (lfs2_tag_type3(tag) == LFS2_FROM_USERATTRS) {
+ for (unsigned i = 0; i < lfs2_tag_size(tag); i++) {
+ const struct lfs2_attr *a = buffer;
+ int err = cb(data, LFS2_MKTAG(LFS2_TYPE_USERATTR + a[i].type,
+ lfs2_tag_id(tag) + diff, a[i].size), a[i].buffer);
+ if (err) {
+ return err;
+ }
+ }
+ } else {
+ int err = cb(data, tag + LFS2_MKTAG(0, diff, 0), buffer);
+ if (err) {
+ return err;
+ }
+ }
+ }
+}
+
+static lfs2_stag_t lfs2_dir_fetchmatch(lfs2_t *lfs2,
+ lfs2_mdir_t *dir, const lfs2_block_t pair[2],
+ lfs2_tag_t fmask, lfs2_tag_t ftag, uint16_t *id,
+ int (*cb)(void *data, lfs2_tag_t tag, const void *buffer), void *data) {
+ // we can find tag very efficiently during a fetch, since we're already
+ // scanning the entire directory
+ lfs2_stag_t besttag = -1;
+
+ // if either block address is invalid we return LFS2_ERR_CORRUPT here,
+ // otherwise later writes to the pair could fail
+ if (pair[0] >= lfs2->cfg->block_count || pair[1] >= lfs2->cfg->block_count) {
+ return LFS2_ERR_CORRUPT;
+ }
+
+ // find the block with the most recent revision
+ uint32_t revs[2] = {0, 0};
+ int r = 0;
+ for (int i = 0; i < 2; i++) {
+ int err = lfs2_bd_read(lfs2,
+ NULL, &lfs2->rcache, sizeof(revs[i]),
+ pair[i], 0, &revs[i], sizeof(revs[i]));
+ revs[i] = lfs2_fromle32(revs[i]);
+ if (err && err != LFS2_ERR_CORRUPT) {
+ return err;
+ }
+
+ if (err != LFS2_ERR_CORRUPT &&
+ lfs2_scmp(revs[i], revs[(i+1)%2]) > 0) {
+ r = i;
+ }
+ }
+
+ dir->pair[0] = pair[(r+0)%2];
+ dir->pair[1] = pair[(r+1)%2];
+ dir->rev = revs[(r+0)%2];
+ dir->off = 0; // nonzero = found some commits
+
+ // now scan tags to fetch the actual dir and find possible match
+ for (int i = 0; i < 2; i++) {
+ lfs2_off_t off = 0;
+ lfs2_tag_t ptag = 0xffffffff;
+
+ uint16_t tempcount = 0;
+ lfs2_block_t temptail[2] = {LFS2_BLOCK_NULL, LFS2_BLOCK_NULL};
+ bool tempsplit = false;
+ lfs2_stag_t tempbesttag = besttag;
+
+ dir->rev = lfs2_tole32(dir->rev);
+ uint32_t crc = lfs2_crc(0xffffffff, &dir->rev, sizeof(dir->rev));
+ dir->rev = lfs2_fromle32(dir->rev);
+
+ while (true) {
+ // extract next tag
+ lfs2_tag_t tag;
+ off += lfs2_tag_dsize(ptag);
+ int err = lfs2_bd_read(lfs2,
+ NULL, &lfs2->rcache, lfs2->cfg->block_size,
+ dir->pair[0], off, &tag, sizeof(tag));
+ if (err) {
+ if (err == LFS2_ERR_CORRUPT) {
+ // can't continue?
+ dir->erased = false;
+ break;
+ }
+ return err;
+ }
+
+ crc = lfs2_crc(crc, &tag, sizeof(tag));
+ tag = lfs2_frombe32(tag) ^ ptag;
+
+ // next commit not yet programmed or we're not in valid range
+ if (!lfs2_tag_isvalid(tag)) {
+ dir->erased = (lfs2_tag_type1(ptag) == LFS2_TYPE_CRC &&
+ dir->off % lfs2->cfg->prog_size == 0);
+ break;
+ } else if (off + lfs2_tag_dsize(tag) > lfs2->cfg->block_size) {
+ dir->erased = false;
+ break;
+ }
+
+ ptag = tag;
+
+ if (lfs2_tag_type1(tag) == LFS2_TYPE_CRC) {
+ // check the crc attr
+ uint32_t dcrc;
+ err = lfs2_bd_read(lfs2,
+ NULL, &lfs2->rcache, lfs2->cfg->block_size,
+ dir->pair[0], off+sizeof(tag), &dcrc, sizeof(dcrc));
+ if (err) {
+ if (err == LFS2_ERR_CORRUPT) {
+ dir->erased = false;
+ break;
+ }
+ return err;
+ }
+ dcrc = lfs2_fromle32(dcrc);
+
+ if (crc != dcrc) {
+ dir->erased = false;
+ break;
+ }
+
+ // reset the next bit if we need to
+ ptag ^= (lfs2_tag_t)(lfs2_tag_chunk(tag) & 1U) << 31;
+
+ // toss our crc into the filesystem seed for
+ // pseudorandom numbers
+ lfs2->seed ^= crc;
+
+ // update with what's found so far
+ besttag = tempbesttag;
+ dir->off = off + lfs2_tag_dsize(tag);
+ dir->etag = ptag;
+ dir->count = tempcount;
+ dir->tail[0] = temptail[0];
+ dir->tail[1] = temptail[1];
+ dir->split = tempsplit;
+
+ // reset crc
+ crc = 0xffffffff;
+ continue;
+ }
+
+ // crc the entry first, hopefully leaving it in the cache
+ for (lfs2_off_t j = sizeof(tag); j < lfs2_tag_dsize(tag); j++) {
+ uint8_t dat;
+ err = lfs2_bd_read(lfs2,
+ NULL, &lfs2->rcache, lfs2->cfg->block_size,
+ dir->pair[0], off+j, &dat, 1);
+ if (err) {
+ if (err == LFS2_ERR_CORRUPT) {
+ dir->erased = false;
+ break;
+ }
+ return err;
+ }
+
+ crc = lfs2_crc(crc, &dat, 1);
+ }
+
+ // directory modification tags?
+ if (lfs2_tag_type1(tag) == LFS2_TYPE_NAME) {
+ // increase count of files if necessary
+ if (lfs2_tag_id(tag) >= tempcount) {
+ tempcount = lfs2_tag_id(tag) + 1;
+ }
+ } else if (lfs2_tag_type1(tag) == LFS2_TYPE_SPLICE) {
+ tempcount += lfs2_tag_splice(tag);
+
+ if (tag == (LFS2_MKTAG(LFS2_TYPE_DELETE, 0, 0) |
+ (LFS2_MKTAG(0, 0x3ff, 0) & tempbesttag))) {
+ tempbesttag |= 0x80000000;
+ } else if (tempbesttag != -1 &&
+ lfs2_tag_id(tag) <= lfs2_tag_id(tempbesttag)) {
+ tempbesttag += LFS2_MKTAG(0, lfs2_tag_splice(tag), 0);
+ }
+ } else if (lfs2_tag_type1(tag) == LFS2_TYPE_TAIL) {
+ tempsplit = (lfs2_tag_chunk(tag) & 1);
+
+ err = lfs2_bd_read(lfs2,
+ NULL, &lfs2->rcache, lfs2->cfg->block_size,
+ dir->pair[0], off+sizeof(tag), &temptail, 8);
+ if (err) {
+ if (err == LFS2_ERR_CORRUPT) {
+ dir->erased = false;
+ break;
+ }
+ }
+ lfs2_pair_fromle32(temptail);
+ }
+
+ // found a match for our fetcher?
+ if ((fmask & tag) == (fmask & ftag)) {
+ int res = cb(data, tag, &(struct lfs2_diskoff){
+ dir->pair[0], off+sizeof(tag)});
+ if (res < 0) {
+ if (res == LFS2_ERR_CORRUPT) {
+ dir->erased = false;
+ break;
+ }
+ return res;
+ }
+
+ if (res == LFS2_CMP_EQ) {
+ // found a match
+ tempbesttag = tag;
+ } else if ((LFS2_MKTAG(0x7ff, 0x3ff, 0) & tag) ==
+ (LFS2_MKTAG(0x7ff, 0x3ff, 0) & tempbesttag)) {
+ // found an identical tag, but contents didn't match
+ // this must mean that our besttag has been overwritten
+ tempbesttag = -1;
+ } else if (res == LFS2_CMP_GT &&
+ lfs2_tag_id(tag) <= lfs2_tag_id(tempbesttag)) {
+ // found a greater match, keep track to keep things sorted
+ tempbesttag = tag | 0x80000000;
+ }
+ }
+ }
+
+ // consider what we have good enough
+ if (dir->off > 0) {
+ // synthetic move
+ if (lfs2_gstate_hasmovehere(&lfs2->gdisk, dir->pair)) {
+ if (lfs2_tag_id(lfs2->gdisk.tag) == lfs2_tag_id(besttag)) {
+ besttag |= 0x80000000;
+ } else if (besttag != -1 &&
+ lfs2_tag_id(lfs2->gdisk.tag) < lfs2_tag_id(besttag)) {
+ besttag -= LFS2_MKTAG(0, 1, 0);
+ }
+ }
+
+ // found tag? or found best id?
+ if (id) {
+ *id = lfs2_min(lfs2_tag_id(besttag), dir->count);
+ }
+
+ if (lfs2_tag_isvalid(besttag)) {
+ return besttag;
+ } else if (lfs2_tag_id(besttag) < dir->count) {
+ return LFS2_ERR_NOENT;
+ } else {
+ return 0;
+ }
+ }
+
+ // failed, try the other block?
+ lfs2_pair_swap(dir->pair);
+ dir->rev = revs[(r+1)%2];
+ }
+
+ LFS2_ERROR("Corrupted dir pair at {0x%"PRIx32", 0x%"PRIx32"}",
+ dir->pair[0], dir->pair[1]);
+ return LFS2_ERR_CORRUPT;
+}
+
+static int lfs2_dir_fetch(lfs2_t *lfs2,
+ lfs2_mdir_t *dir, const lfs2_block_t pair[2]) {
+ // note, mask=-1, tag=-1 can never match a tag since this
+ // pattern has the invalid bit set
+ return (int)lfs2_dir_fetchmatch(lfs2, dir, pair,
+ (lfs2_tag_t)-1, (lfs2_tag_t)-1, NULL, NULL, NULL);
+}
+
+static int lfs2_dir_getgstate(lfs2_t *lfs2, const lfs2_mdir_t *dir,
+ lfs2_gstate_t *gstate) {
+ lfs2_gstate_t temp;
+ lfs2_stag_t res = lfs2_dir_get(lfs2, dir, LFS2_MKTAG(0x7ff, 0, 0),
+ LFS2_MKTAG(LFS2_TYPE_MOVESTATE, 0, sizeof(temp)), &temp);
+ if (res < 0 && res != LFS2_ERR_NOENT) {
+ return res;
+ }
+
+ if (res != LFS2_ERR_NOENT) {
+ // xor together to find resulting gstate
+ lfs2_gstate_fromle32(&temp);
+ lfs2_gstate_xor(gstate, &temp);
+ }
+
+ return 0;
+}
+
+static int lfs2_dir_getinfo(lfs2_t *lfs2, lfs2_mdir_t *dir,
+ uint16_t id, struct lfs2_info *info) {
+ if (id == 0x3ff) {
+ // special case for root
+ strcpy(info->name, "/");
+ info->type = LFS2_TYPE_DIR;
+ return 0;
+ }
+
+ lfs2_stag_t tag = lfs2_dir_get(lfs2, dir, LFS2_MKTAG(0x780, 0x3ff, 0),
+ LFS2_MKTAG(LFS2_TYPE_NAME, id, lfs2->name_max+1), info->name);
+ if (tag < 0) {
+ return (int)tag;
+ }
+
+ info->type = lfs2_tag_type3(tag);
+
+ struct lfs2_ctz ctz;
+ tag = lfs2_dir_get(lfs2, dir, LFS2_MKTAG(0x700, 0x3ff, 0),
+ LFS2_MKTAG(LFS2_TYPE_STRUCT, id, sizeof(ctz)), &ctz);
+ if (tag < 0) {
+ return (int)tag;
+ }
+ lfs2_ctz_fromle32(&ctz);
+
+ if (lfs2_tag_type3(tag) == LFS2_TYPE_CTZSTRUCT) {
+ info->size = ctz.size;
+ } else if (lfs2_tag_type3(tag) == LFS2_TYPE_INLINESTRUCT) {
+ info->size = lfs2_tag_size(tag);
+ }
+
+ return 0;
+}
+
+struct lfs2_dir_find_match {
+ lfs2_t *lfs2;
+ const void *name;
+ lfs2_size_t size;
+};
+
+static int lfs2_dir_find_match(void *data,
+ lfs2_tag_t tag, const void *buffer) {
+ struct lfs2_dir_find_match *name = data;
+ lfs2_t *lfs2 = name->lfs2;
+ const struct lfs2_diskoff *disk = buffer;
+
+ // compare with disk
+ lfs2_size_t diff = lfs2_min(name->size, lfs2_tag_size(tag));
+ int res = lfs2_bd_cmp(lfs2,
+ NULL, &lfs2->rcache, diff,
+ disk->block, disk->off, name->name, diff);
+ if (res != LFS2_CMP_EQ) {
+ return res;
+ }
+
+ // only equal if our size is still the same
+ if (name->size != lfs2_tag_size(tag)) {
+ return (name->size < lfs2_tag_size(tag)) ? LFS2_CMP_LT : LFS2_CMP_GT;
+ }
+
+ // found a match!
+ return LFS2_CMP_EQ;
+}
+
+static lfs2_stag_t lfs2_dir_find(lfs2_t *lfs2, lfs2_mdir_t *dir,
+ const char **path, uint16_t *id) {
+ // we reduce path to a single name if we can find it
+ const char *name = *path;
+ if (id) {
+ *id = 0x3ff;
+ }
+
+ // default to root dir
+ lfs2_stag_t tag = LFS2_MKTAG(LFS2_TYPE_DIR, 0x3ff, 0);
+ dir->tail[0] = lfs2->root[0];
+ dir->tail[1] = lfs2->root[1];
+
+ while (true) {
+nextname:
+ // skip slashes
+ name += strspn(name, "/");
+ lfs2_size_t namelen = strcspn(name, "/");
+
+ // skip '.' and root '..'
+ if ((namelen == 1 && memcmp(name, ".", 1) == 0) ||
+ (namelen == 2 && memcmp(name, "..", 2) == 0)) {
+ name += namelen;
+ goto nextname;
+ }
+
+ // skip if matched by '..' in name
+ const char *suffix = name + namelen;
+ lfs2_size_t sufflen;
+ int depth = 1;
+ while (true) {
+ suffix += strspn(suffix, "/");
+ sufflen = strcspn(suffix, "/");
+ if (sufflen == 0) {
+ break;
+ }
+
+ if (sufflen == 2 && memcmp(suffix, "..", 2) == 0) {
+ depth -= 1;
+ if (depth == 0) {
+ name = suffix + sufflen;
+ goto nextname;
+ }
+ } else {
+ depth += 1;
+ }
+
+ suffix += sufflen;
+ }
+
+ // found path
+ if (name[0] == '\0') {
+ return tag;
+ }
+
+ // update what we've found so far
+ *path = name;
+
+ // only continue if we hit a directory
+ if (lfs2_tag_type3(tag) != LFS2_TYPE_DIR) {
+ return LFS2_ERR_NOTDIR;
+ }
+
+ // grab the entry data
+ if (lfs2_tag_id(tag) != 0x3ff) {
+ lfs2_stag_t res = lfs2_dir_get(lfs2, dir, LFS2_MKTAG(0x700, 0x3ff, 0),
+ LFS2_MKTAG(LFS2_TYPE_STRUCT, lfs2_tag_id(tag), 8), dir->tail);
+ if (res < 0) {
+ return res;
+ }
+ lfs2_pair_fromle32(dir->tail);
+ }
+
+ // find entry matching name
+ while (true) {
+ tag = lfs2_dir_fetchmatch(lfs2, dir, dir->tail,
+ LFS2_MKTAG(0x780, 0, 0),
+ LFS2_MKTAG(LFS2_TYPE_NAME, 0, namelen),
+ // are we last name?
+ (strchr(name, '/') == NULL) ? id : NULL,
+ lfs2_dir_find_match, &(struct lfs2_dir_find_match){
+ lfs2, name, namelen});
+ if (tag < 0) {
+ return tag;
+ }
+
+ if (tag) {
+ break;
+ }
+
+ if (!dir->split) {
+ return LFS2_ERR_NOENT;
+ }
+ }
+
+ // to next name
+ name += namelen;
+ }
+}
+
+// commit logic
+struct lfs2_commit {
+ lfs2_block_t block;
+ lfs2_off_t off;
+ lfs2_tag_t ptag;
+ uint32_t crc;
+
+ lfs2_off_t begin;
+ lfs2_off_t end;
+};
+
+static int lfs2_dir_commitprog(lfs2_t *lfs2, struct lfs2_commit *commit,
+ const void *buffer, lfs2_size_t size) {
+ int err = lfs2_bd_prog(lfs2,
+ &lfs2->pcache, &lfs2->rcache, false,
+ commit->block, commit->off ,
+ (const uint8_t*)buffer, size);
+ if (err) {
+ return err;
+ }
+
+ commit->crc = lfs2_crc(commit->crc, buffer, size);
+ commit->off += size;
+ return 0;
+}
+
+static int lfs2_dir_commitattr(lfs2_t *lfs2, struct lfs2_commit *commit,
+ lfs2_tag_t tag, const void *buffer) {
+ // check if we fit
+ lfs2_size_t dsize = lfs2_tag_dsize(tag);
+ if (commit->off + dsize > commit->end) {
+ return LFS2_ERR_NOSPC;
+ }
+
+ // write out tag
+ lfs2_tag_t ntag = lfs2_tobe32((tag & 0x7fffffff) ^ commit->ptag);
+ int err = lfs2_dir_commitprog(lfs2, commit, &ntag, sizeof(ntag));
+ if (err) {
+ return err;
+ }
+
+ if (!(tag & 0x80000000)) {
+ // from memory
+ err = lfs2_dir_commitprog(lfs2, commit, buffer, dsize-sizeof(tag));
+ if (err) {
+ return err;
+ }
+ } else {
+ // from disk
+ const struct lfs2_diskoff *disk = buffer;
+ for (lfs2_off_t i = 0; i < dsize-sizeof(tag); i++) {
+ // rely on caching to make this efficient
+ uint8_t dat;
+ err = lfs2_bd_read(lfs2,
+ NULL, &lfs2->rcache, dsize-sizeof(tag)-i,
+ disk->block, disk->off+i, &dat, 1);
+ if (err) {
+ return err;
+ }
+
+ err = lfs2_dir_commitprog(lfs2, commit, &dat, 1);
+ if (err) {
+ return err;
+ }
+ }
+ }
+
+ commit->ptag = tag & 0x7fffffff;
+ return 0;
+}
+
+static int lfs2_dir_commitcrc(lfs2_t *lfs2, struct lfs2_commit *commit) {
+ const lfs2_off_t off1 = commit->off;
+ const uint32_t crc1 = commit->crc;
+ // align to program units
+ const lfs2_off_t end = lfs2_alignup(off1 + 2*sizeof(uint32_t),
+ lfs2->cfg->prog_size);
+
+ // create crc tags to fill up remainder of commit, note that
+ // padding is not crced, which lets fetches skip padding but
+ // makes committing a bit more complicated
+ while (commit->off < end) {
+ lfs2_off_t off = commit->off + sizeof(lfs2_tag_t);
+ lfs2_off_t noff = lfs2_min(end - off, 0x3fe) + off;
+ if (noff < end) {
+ noff = lfs2_min(noff, end - 2*sizeof(uint32_t));
+ }
+
+ // read erased state from next program unit
+ lfs2_tag_t tag = 0xffffffff;
+ int err = lfs2_bd_read(lfs2,
+ NULL, &lfs2->rcache, sizeof(tag),
+ commit->block, noff, &tag, sizeof(tag));
+ if (err && err != LFS2_ERR_CORRUPT) {
+ return err;
+ }
+
+ // build crc tag
+ bool reset = ~lfs2_frombe32(tag) >> 31;
+ tag = LFS2_MKTAG(LFS2_TYPE_CRC + reset, 0x3ff, noff - off);
+
+ // write out crc
+ uint32_t footer[2];
+ footer[0] = lfs2_tobe32(tag ^ commit->ptag);
+ commit->crc = lfs2_crc(commit->crc, &footer[0], sizeof(footer[0]));
+ footer[1] = lfs2_tole32(commit->crc);
+ err = lfs2_bd_prog(lfs2,
+ &lfs2->pcache, &lfs2->rcache, false,
+ commit->block, commit->off, &footer, sizeof(footer));
+ if (err) {
+ return err;
+ }
+
+ commit->off += sizeof(tag)+lfs2_tag_size(tag);
+ commit->ptag = tag ^ ((lfs2_tag_t)reset << 31);
+ commit->crc = 0xffffffff; // reset crc for next "commit"
+ }
+
+ // flush buffers
+ int err = lfs2_bd_sync(lfs2, &lfs2->pcache, &lfs2->rcache, false);
+ if (err) {
+ return err;
+ }
+
+ // successful commit, check checksums to make sure
+ lfs2_off_t off = commit->begin;
+ lfs2_off_t noff = off1 + sizeof(uint32_t);
+ while (off < end) {
+ uint32_t crc = 0xffffffff;
+ for (lfs2_off_t i = off; i < noff+sizeof(uint32_t); i++) {
+ // check against written crc, may catch blocks that
+ // become readonly and match our commit size exactly
+ if (i == off1 && crc != crc1) {
+ return LFS2_ERR_CORRUPT;
+ }
+
+ // leave it up to caching to make this efficient
+ uint8_t dat;
+ err = lfs2_bd_read(lfs2,
+ NULL, &lfs2->rcache, noff+sizeof(uint32_t)-i,
+ commit->block, i, &dat, 1);
+ if (err) {
+ return err;
+ }
+
+ crc = lfs2_crc(crc, &dat, 1);
+ }
+
+ // detected write error?
+ if (crc != 0) {
+ return LFS2_ERR_CORRUPT;
+ }
+
+ // skip padding
+ off = lfs2_min(end - noff, 0x3fe) + noff;
+ if (off < end) {
+ off = lfs2_min(off, end - 2*sizeof(uint32_t));
+ }
+ noff = off + sizeof(uint32_t);
+ }
+
+ return 0;
+}
+
+static int lfs2_dir_alloc(lfs2_t *lfs2, lfs2_mdir_t *dir) {
+ // allocate pair of dir blocks (backwards, so we write block 1 first)
+ for (int i = 0; i < 2; i++) {
+ int err = lfs2_alloc(lfs2, &dir->pair[(i+1)%2]);
+ if (err) {
+ return err;
+ }
+ }
+
+ // zero for reproducability in case initial block is unreadable
+ dir->rev = 0;
+
+ // rather than clobbering one of the blocks we just pretend
+ // the revision may be valid
+ int err = lfs2_bd_read(lfs2,
+ NULL, &lfs2->rcache, sizeof(dir->rev),
+ dir->pair[0], 0, &dir->rev, sizeof(dir->rev));
+ dir->rev = lfs2_fromle32(dir->rev);
+ if (err && err != LFS2_ERR_CORRUPT) {
+ return err;
+ }
+
+ // make sure we don't immediately evict
+ dir->rev += dir->rev & 1;
+
+ // set defaults
+ dir->off = sizeof(dir->rev);
+ dir->etag = 0xffffffff;
+ dir->count = 0;
+ dir->tail[0] = LFS2_BLOCK_NULL;
+ dir->tail[1] = LFS2_BLOCK_NULL;
+ dir->erased = false;
+ dir->split = false;
+
+ // don't write out yet, let caller take care of that
+ return 0;
+}
+
+static int lfs2_dir_drop(lfs2_t *lfs2, lfs2_mdir_t *dir, lfs2_mdir_t *tail) {
+ // steal state
+ int err = lfs2_dir_getgstate(lfs2, tail, &lfs2->gdelta);
+ if (err) {
+ return err;
+ }
+
+ // steal tail
+ lfs2_pair_tole32(tail->tail);
+ err = lfs2_dir_commit(lfs2, dir, LFS2_MKATTRS(
+ {LFS2_MKTAG(LFS2_TYPE_TAIL + tail->split, 0x3ff, 8), tail->tail}));
+ lfs2_pair_fromle32(tail->tail);
+ if (err) {
+ return err;
+ }
+
+ return 0;
+}
+
+static int lfs2_dir_split(lfs2_t *lfs2,
+ lfs2_mdir_t *dir, const struct lfs2_mattr *attrs, int attrcount,
+ lfs2_mdir_t *source, uint16_t split, uint16_t end) {
+ // create tail directory
+ lfs2_alloc_ack(lfs2);
+ lfs2_mdir_t tail;
+ int err = lfs2_dir_alloc(lfs2, &tail);
+ if (err) {
+ return err;
+ }
+
+ tail.split = dir->split;
+ tail.tail[0] = dir->tail[0];
+ tail.tail[1] = dir->tail[1];
+
+ err = lfs2_dir_compact(lfs2, &tail, attrs, attrcount, source, split, end);
+ if (err) {
+ return err;
+ }
+
+ dir->tail[0] = tail.pair[0];
+ dir->tail[1] = tail.pair[1];
+ dir->split = true;
+
+ // update root if needed
+ if (lfs2_pair_cmp(dir->pair, lfs2->root) == 0 && split == 0) {
+ lfs2->root[0] = tail.pair[0];
+ lfs2->root[1] = tail.pair[1];
+ }
+
+ return 0;
+}
+
+static int lfs2_dir_commit_size(void *p, lfs2_tag_t tag, const void *buffer) {
+ lfs2_size_t *size = p;
+ (void)buffer;
+
+ *size += lfs2_tag_dsize(tag);
+ return 0;
+}
+
+struct lfs2_dir_commit_commit {
+ lfs2_t *lfs2;
+ struct lfs2_commit *commit;
+};
+
+static int lfs2_dir_commit_commit(void *p, lfs2_tag_t tag, const void *buffer) {
+ struct lfs2_dir_commit_commit *commit = p;
+ return lfs2_dir_commitattr(commit->lfs2, commit->commit, tag, buffer);
+}
+
+static int lfs2_dir_compact(lfs2_t *lfs2,
+ lfs2_mdir_t *dir, const struct lfs2_mattr *attrs, int attrcount,
+ lfs2_mdir_t *source, uint16_t begin, uint16_t end) {
+ // save some state in case block is bad
+ const lfs2_block_t oldpair[2] = {dir->pair[0], dir->pair[1]};
+ bool relocated = false;
+ bool tired = false;
+
+ // should we split?
+ while (end - begin > 1) {
+ // find size
+ lfs2_size_t size = 0;
+ int err = lfs2_dir_traverse(lfs2,
+ source, 0, 0xffffffff, attrs, attrcount,
+ LFS2_MKTAG(0x400, 0x3ff, 0),
+ LFS2_MKTAG(LFS2_TYPE_NAME, 0, 0),
+ begin, end, -begin,
+ lfs2_dir_commit_size, &size);
+ if (err) {
+ return err;
+ }
+
+ // space is complicated, we need room for tail, crc, gstate,
+ // cleanup delete, and we cap at half a block to give room
+ // for metadata updates.
+ if (end - begin < 0xff &&
+ size <= lfs2_min(lfs2->cfg->block_size - 36,
+ lfs2_alignup(lfs2->cfg->block_size/2,
+ lfs2->cfg->prog_size))) {
+ break;
+ }
+
+ // can't fit, need to split, we should really be finding the
+ // largest size that fits with a small binary search, but right now
+ // it's not worth the code size
+ uint16_t split = (end - begin) / 2;
+ err = lfs2_dir_split(lfs2, dir, attrs, attrcount,
+ source, begin+split, end);
+ if (err) {
+ // if we fail to split, we may be able to overcompact, unless
+ // we're too big for even the full block, in which case our
+ // only option is to error
+ if (err == LFS2_ERR_NOSPC && size <= lfs2->cfg->block_size - 36) {
+ break;
+ }
+ return err;
+ }
+
+ end = begin + split;
+ }
+
+ // increment revision count
+ dir->rev += 1;
+ // If our revision count == n * block_cycles, we should force a relocation,
+ // this is how littlefs wear-levels at the metadata-pair level. Note that we
+ // actually use (block_cycles+1)|1, this is to avoid two corner cases:
+ // 1. block_cycles = 1, which would prevent relocations from terminating
+ // 2. block_cycles = 2n, which, due to aliasing, would only ever relocate
+ // one metadata block in the pair, effectively making this useless
+ if (lfs2->cfg->block_cycles > 0 &&
+ (dir->rev % ((lfs2->cfg->block_cycles+1)|1) == 0)) {
+ if (lfs2_pair_cmp(dir->pair, (const lfs2_block_t[2]){0, 1}) == 0) {
+ // oh no! we're writing too much to the superblock,
+ // should we expand?
+ lfs2_ssize_t res = lfs2_fs_size(lfs2);
+ if (res < 0) {
+ return res;
+ }
+
+ // do we have extra space? littlefs can't reclaim this space
+ // by itself, so expand cautiously
+ if ((lfs2_size_t)res < lfs2->cfg->block_count/2) {
+ LFS2_DEBUG("Expanding superblock at rev %"PRIu32, dir->rev);
+ int err = lfs2_dir_split(lfs2, dir, attrs, attrcount,
+ source, begin, end);
+ if (err && err != LFS2_ERR_NOSPC) {
+ return err;
+ }
+
+ // welp, we tried, if we ran out of space there's not much
+ // we can do, we'll error later if we've become frozen
+ if (!err) {
+ end = begin;
+ }
+ }
+#ifdef LFS2_MIGRATE
+ } else if (lfs2->lfs21) {
+ // do not proactively relocate blocks during migrations, this
+ // can cause a number of failure states such: clobbering the
+ // v1 superblock if we relocate root, and invalidating directory
+ // pointers if we relocate the head of a directory. On top of
+ // this, relocations increase the overall complexity of
+ // lfs2_migration, which is already a delicate operation.
+#endif
+ } else {
+ // we're writing too much, time to relocate
+ tired = true;
+ goto relocate;
+ }
+ }
+
+ // begin loop to commit compaction to blocks until a compact sticks
+ while (true) {
+ {
+ // setup commit state
+ struct lfs2_commit commit = {
+ .block = dir->pair[1],
+ .off = 0,
+ .ptag = 0xffffffff,
+ .crc = 0xffffffff,
+
+ .begin = 0,
+ .end = lfs2->cfg->block_size - 8,
+ };
+
+ // erase block to write to
+ int err = lfs2_bd_erase(lfs2, dir->pair[1]);
+ if (err) {
+ if (err == LFS2_ERR_CORRUPT) {
+ goto relocate;
+ }
+ return err;
+ }
+
+ // write out header
+ dir->rev = lfs2_tole32(dir->rev);
+ err = lfs2_dir_commitprog(lfs2, &commit,
+ &dir->rev, sizeof(dir->rev));
+ dir->rev = lfs2_fromle32(dir->rev);
+ if (err) {
+ if (err == LFS2_ERR_CORRUPT) {
+ goto relocate;
+ }
+ return err;
+ }
+
+ // traverse the directory, this time writing out all unique tags
+ err = lfs2_dir_traverse(lfs2,
+ source, 0, 0xffffffff, attrs, attrcount,
+ LFS2_MKTAG(0x400, 0x3ff, 0),
+ LFS2_MKTAG(LFS2_TYPE_NAME, 0, 0),
+ begin, end, -begin,
+ lfs2_dir_commit_commit, &(struct lfs2_dir_commit_commit){
+ lfs2, &commit});
+ if (err) {
+ if (err == LFS2_ERR_CORRUPT) {
+ goto relocate;
+ }
+ return err;
+ }
+
+ // commit tail, which may be new after last size check
+ if (!lfs2_pair_isnull(dir->tail)) {
+ lfs2_pair_tole32(dir->tail);
+ err = lfs2_dir_commitattr(lfs2, &commit,
+ LFS2_MKTAG(LFS2_TYPE_TAIL + dir->split, 0x3ff, 8),
+ dir->tail);
+ lfs2_pair_fromle32(dir->tail);
+ if (err) {
+ if (err == LFS2_ERR_CORRUPT) {
+ goto relocate;
+ }
+ return err;
+ }
+ }
+
+ // bring over gstate?
+ lfs2_gstate_t delta = {0};
+ if (!relocated) {
+ lfs2_gstate_xor(&delta, &lfs2->gdisk);
+ lfs2_gstate_xor(&delta, &lfs2->gstate);
+ }
+ lfs2_gstate_xor(&delta, &lfs2->gdelta);
+ delta.tag &= ~LFS2_MKTAG(0, 0, 0x3ff);
+
+ err = lfs2_dir_getgstate(lfs2, dir, &delta);
+ if (err) {
+ return err;
+ }
+
+ if (!lfs2_gstate_iszero(&delta)) {
+ lfs2_gstate_tole32(&delta);
+ err = lfs2_dir_commitattr(lfs2, &commit,
+ LFS2_MKTAG(LFS2_TYPE_MOVESTATE, 0x3ff,
+ sizeof(delta)), &delta);
+ if (err) {
+ if (err == LFS2_ERR_CORRUPT) {
+ goto relocate;
+ }
+ return err;
+ }
+ }
+
+ // complete commit with crc
+ err = lfs2_dir_commitcrc(lfs2, &commit);
+ if (err) {
+ if (err == LFS2_ERR_CORRUPT) {
+ goto relocate;
+ }
+ return err;
+ }
+
+ // successful compaction, swap dir pair to indicate most recent
+ LFS2_ASSERT(commit.off % lfs2->cfg->prog_size == 0);
+ lfs2_pair_swap(dir->pair);
+ dir->count = end - begin;
+ dir->off = commit.off;
+ dir->etag = commit.ptag;
+ // update gstate
+ lfs2->gdelta = (lfs2_gstate_t){0};
+ if (!relocated) {
+ lfs2->gdisk = lfs2->gstate;
+ }
+ }
+ break;
+
+relocate:
+ // commit was corrupted, drop caches and prepare to relocate block
+ relocated = true;
+ lfs2_cache_drop(lfs2, &lfs2->pcache);
+ if (!tired) {
+ LFS2_DEBUG("Bad block at 0x%"PRIx32, dir->pair[1]);
+ }
+
+ // can't relocate superblock, filesystem is now frozen
+ if (lfs2_pair_cmp(dir->pair, (const lfs2_block_t[2]){0, 1}) == 0) {
+ LFS2_WARN("Superblock 0x%"PRIx32" has become unwritable",
+ dir->pair[1]);
+ return LFS2_ERR_NOSPC;
+ }
+
+ // relocate half of pair
+ int err = lfs2_alloc(lfs2, &dir->pair[1]);
+ if (err && (err != LFS2_ERR_NOSPC || !tired)) {
+ return err;
+ }
+
+ tired = false;
+ continue;
+ }
+
+ if (relocated) {
+ // update references if we relocated
+ LFS2_DEBUG("Relocating {0x%"PRIx32", 0x%"PRIx32"} "
+ "-> {0x%"PRIx32", 0x%"PRIx32"}",
+ oldpair[0], oldpair[1], dir->pair[0], dir->pair[1]);
+ int err = lfs2_fs_relocate(lfs2, oldpair, dir->pair);
+ if (err) {
+ return err;
+ }
+ }
+
+ return 0;
+}
+
+static int lfs2_dir_commit(lfs2_t *lfs2, lfs2_mdir_t *dir,
+ const struct lfs2_mattr *attrs, int attrcount) {
+ // check for any inline files that aren't RAM backed and
+ // forcefully evict them, needed for filesystem consistency
+ for (lfs2_file_t *f = (lfs2_file_t*)lfs2->mlist; f; f = f->next) {
+ if (dir != &f->m && lfs2_pair_cmp(f->m.pair, dir->pair) == 0 &&
+ f->type == LFS2_TYPE_REG && (f->flags & LFS2_F_INLINE) &&
+ f->ctz.size > lfs2->cfg->cache_size) {
+ int err = lfs2_file_outline(lfs2, f);
+ if (err) {
+ return err;
+ }
+
+ err = lfs2_file_flush(lfs2, f);
+ if (err) {
+ return err;
+ }
+ }
+ }
+
+ // calculate changes to the directory
+ lfs2_mdir_t olddir = *dir;
+ bool hasdelete = false;
+ for (int i = 0; i < attrcount; i++) {
+ if (lfs2_tag_type3(attrs[i].tag) == LFS2_TYPE_CREATE) {
+ dir->count += 1;
+ } else if (lfs2_tag_type3(attrs[i].tag) == LFS2_TYPE_DELETE) {
+ LFS2_ASSERT(dir->count > 0);
+ dir->count -= 1;
+ hasdelete = true;
+ } else if (lfs2_tag_type1(attrs[i].tag) == LFS2_TYPE_TAIL) {
+ dir->tail[0] = ((lfs2_block_t*)attrs[i].buffer)[0];
+ dir->tail[1] = ((lfs2_block_t*)attrs[i].buffer)[1];
+ dir->split = (lfs2_tag_chunk(attrs[i].tag) & 1);
+ lfs2_pair_fromle32(dir->tail);
+ }
+ }
+
+ // should we actually drop the directory block?
+ if (hasdelete && dir->count == 0) {
+ lfs2_mdir_t pdir;
+ int err = lfs2_fs_pred(lfs2, dir->pair, &pdir);
+ if (err && err != LFS2_ERR_NOENT) {
+ *dir = olddir;
+ return err;
+ }
+
+ if (err != LFS2_ERR_NOENT && pdir.split) {
+ err = lfs2_dir_drop(lfs2, &pdir, dir);
+ if (err) {
+ *dir = olddir;
+ return err;
+ }
+ }
+ }
+
+ if (dir->erased || dir->count >= 0xff) {
+ // try to commit
+ struct lfs2_commit commit = {
+ .block = dir->pair[0],
+ .off = dir->off,
+ .ptag = dir->etag,
+ .crc = 0xffffffff,
+
+ .begin = dir->off,
+ .end = lfs2->cfg->block_size - 8,
+ };
+
+ // traverse attrs that need to be written out
+ lfs2_pair_tole32(dir->tail);
+ int err = lfs2_dir_traverse(lfs2,
+ dir, dir->off, dir->etag, attrs, attrcount,
+ 0, 0, 0, 0, 0,
+ lfs2_dir_commit_commit, &(struct lfs2_dir_commit_commit){
+ lfs2, &commit});
+ lfs2_pair_fromle32(dir->tail);
+ if (err) {
+ if (err == LFS2_ERR_NOSPC || err == LFS2_ERR_CORRUPT) {
+ goto compact;
+ }
+ *dir = olddir;
+ return err;
+ }
+
+ // commit any global diffs if we have any
+ lfs2_gstate_t delta = {0};
+ lfs2_gstate_xor(&delta, &lfs2->gstate);
+ lfs2_gstate_xor(&delta, &lfs2->gdisk);
+ lfs2_gstate_xor(&delta, &lfs2->gdelta);
+ delta.tag &= ~LFS2_MKTAG(0, 0, 0x3ff);
+ if (!lfs2_gstate_iszero(&delta)) {
+ err = lfs2_dir_getgstate(lfs2, dir, &delta);
+ if (err) {
+ *dir = olddir;
+ return err;
+ }
+
+ lfs2_gstate_tole32(&delta);
+ err = lfs2_dir_commitattr(lfs2, &commit,
+ LFS2_MKTAG(LFS2_TYPE_MOVESTATE, 0x3ff,
+ sizeof(delta)), &delta);
+ if (err) {
+ if (err == LFS2_ERR_NOSPC || err == LFS2_ERR_CORRUPT) {
+ goto compact;
+ }
+ *dir = olddir;
+ return err;
+ }
+ }
+
+ // finalize commit with the crc
+ err = lfs2_dir_commitcrc(lfs2, &commit);
+ if (err) {
+ if (err == LFS2_ERR_NOSPC || err == LFS2_ERR_CORRUPT) {
+ goto compact;
+ }
+ *dir = olddir;
+ return err;
+ }
+
+ // successful commit, update dir
+ LFS2_ASSERT(commit.off % lfs2->cfg->prog_size == 0);
+ dir->off = commit.off;
+ dir->etag = commit.ptag;
+ // and update gstate
+ lfs2->gdisk = lfs2->gstate;
+ lfs2->gdelta = (lfs2_gstate_t){0};
+ } else {
+compact:
+ // fall back to compaction
+ lfs2_cache_drop(lfs2, &lfs2->pcache);
+
+ int err = lfs2_dir_compact(lfs2, dir, attrs, attrcount,
+ dir, 0, dir->count);
+ if (err) {
+ *dir = olddir;
+ return err;
+ }
+ }
+
+ // this complicated bit of logic is for fixing up any active
+ // metadata-pairs that we may have affected
+ //
+ // note we have to make two passes since the mdir passed to
+ // lfs2_dir_commit could also be in this list, and even then
+ // we need to copy the pair so they don't get clobbered if we refetch
+ // our mdir.
+ for (struct lfs2_mlist *d = lfs2->mlist; d; d = d->next) {
+ if (&d->m != dir && lfs2_pair_cmp(d->m.pair, olddir.pair) == 0) {
+ d->m = *dir;
+ for (int i = 0; i < attrcount; i++) {
+ if (lfs2_tag_type3(attrs[i].tag) == LFS2_TYPE_DELETE &&
+ d->id == lfs2_tag_id(attrs[i].tag)) {
+ d->m.pair[0] = LFS2_BLOCK_NULL;
+ d->m.pair[1] = LFS2_BLOCK_NULL;
+ } else if (lfs2_tag_type3(attrs[i].tag) == LFS2_TYPE_DELETE &&
+ d->id > lfs2_tag_id(attrs[i].tag)) {
+ d->id -= 1;
+ if (d->type == LFS2_TYPE_DIR) {
+ ((lfs2_dir_t*)d)->pos -= 1;
+ }
+ } else if (lfs2_tag_type3(attrs[i].tag) == LFS2_TYPE_CREATE &&
+ d->id >= lfs2_tag_id(attrs[i].tag)) {
+ d->id += 1;
+ if (d->type == LFS2_TYPE_DIR) {
+ ((lfs2_dir_t*)d)->pos += 1;
+ }
+ }
+ }
+ }
+ }
+
+ for (struct lfs2_mlist *d = lfs2->mlist; d; d = d->next) {
+ if (lfs2_pair_cmp(d->m.pair, olddir.pair) == 0) {
+ while (d->id >= d->m.count && d->m.split) {
+ // we split and id is on tail now
+ d->id -= d->m.count;
+ int err = lfs2_dir_fetch(lfs2, &d->m, d->m.tail);
+ if (err) {
+ return err;
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
+
+/// Top level directory operations ///
+int lfs2_mkdir(lfs2_t *lfs2, const char *path) {
+ LFS2_TRACE("lfs2_mkdir(%p, \"%s\")", (void*)lfs2, path);
+ // deorphan if we haven't yet, needed at most once after poweron
+ int err = lfs2_fs_forceconsistency(lfs2);
+ if (err) {
+ LFS2_TRACE("lfs2_mkdir -> %d", err);
+ return err;
+ }
+
+ struct lfs2_mlist cwd;
+ cwd.next = lfs2->mlist;
+ uint16_t id;
+ err = lfs2_dir_find(lfs2, &cwd.m, &path, &id);
+ if (!(err == LFS2_ERR_NOENT && id != 0x3ff)) {
+ LFS2_TRACE("lfs2_mkdir -> %d", (err < 0) ? err : LFS2_ERR_EXIST);
+ return (err < 0) ? err : LFS2_ERR_EXIST;
+ }
+
+ // check that name fits
+ lfs2_size_t nlen = strlen(path);
+ if (nlen > lfs2->name_max) {
+ LFS2_TRACE("lfs2_mkdir -> %d", LFS2_ERR_NAMETOOLONG);
+ return LFS2_ERR_NAMETOOLONG;
+ }
+
+ // build up new directory
+ lfs2_alloc_ack(lfs2);
+ lfs2_mdir_t dir;
+ err = lfs2_dir_alloc(lfs2, &dir);
+ if (err) {
+ LFS2_TRACE("lfs2_mkdir -> %d", err);
+ return err;
+ }
+
+ // find end of list
+ lfs2_mdir_t pred = cwd.m;
+ while (pred.split) {
+ err = lfs2_dir_fetch(lfs2, &pred, pred.tail);
+ if (err) {
+ LFS2_TRACE("lfs2_mkdir -> %d", err);
+ return err;
+ }
+ }
+
+ // setup dir
+ lfs2_pair_tole32(pred.tail);
+ err = lfs2_dir_commit(lfs2, &dir, LFS2_MKATTRS(
+ {LFS2_MKTAG(LFS2_TYPE_SOFTTAIL, 0x3ff, 8), pred.tail}));
+ lfs2_pair_fromle32(pred.tail);
+ if (err) {
+ LFS2_TRACE("lfs2_mkdir -> %d", err);
+ return err;
+ }
+
+ // current block end of list?
+ if (cwd.m.split) {
+ // update tails, this creates a desync
+ lfs2_fs_preporphans(lfs2, +1);
+
+ // it's possible our predecessor has to be relocated, and if
+ // our parent is our predecessor's predecessor, this could have
+ // caused our parent to go out of date, fortunately we can hook
+ // ourselves into littlefs to catch this
+ cwd.type = 0;
+ cwd.id = 0;
+ lfs2->mlist = &cwd;
+
+ lfs2_pair_tole32(dir.pair);
+ err = lfs2_dir_commit(lfs2, &pred, LFS2_MKATTRS(
+ {LFS2_MKTAG(LFS2_TYPE_SOFTTAIL, 0x3ff, 8), dir.pair}));
+ lfs2_pair_fromle32(dir.pair);
+ if (err) {
+ lfs2->mlist = cwd.next;
+ LFS2_TRACE("lfs2_mkdir -> %d", err);
+ return err;
+ }
+
+ lfs2->mlist = cwd.next;
+ lfs2_fs_preporphans(lfs2, -1);
+ }
+
+ // now insert into our parent block
+ lfs2_pair_tole32(dir.pair);
+ err = lfs2_dir_commit(lfs2, &cwd.m, LFS2_MKATTRS(
+ {LFS2_MKTAG(LFS2_TYPE_CREATE, id, 0), NULL},
+ {LFS2_MKTAG(LFS2_TYPE_DIR, id, nlen), path},
+ {LFS2_MKTAG(LFS2_TYPE_DIRSTRUCT, id, 8), dir.pair},
+ {LFS2_MKTAG_IF(!cwd.m.split,
+ LFS2_TYPE_SOFTTAIL, 0x3ff, 8), dir.pair}));
+ lfs2_pair_fromle32(dir.pair);
+ if (err) {
+ LFS2_TRACE("lfs2_mkdir -> %d", err);
+ return err;
+ }
+
+ LFS2_TRACE("lfs2_mkdir -> %d", 0);
+ return 0;
+}
+
+int lfs2_dir_open(lfs2_t *lfs2, lfs2_dir_t *dir, const char *path) {
+ LFS2_TRACE("lfs2_dir_open(%p, %p, \"%s\")", (void*)lfs2, (void*)dir, path);
+ lfs2_stag_t tag = lfs2_dir_find(lfs2, &dir->m, &path, NULL);
+ if (tag < 0) {
+ LFS2_TRACE("lfs2_dir_open -> %"PRId32, tag);
+ return tag;
+ }
+
+ if (lfs2_tag_type3(tag) != LFS2_TYPE_DIR) {
+ LFS2_TRACE("lfs2_dir_open -> %d", LFS2_ERR_NOTDIR);
+ return LFS2_ERR_NOTDIR;
+ }
+
+ lfs2_block_t pair[2];
+ if (lfs2_tag_id(tag) == 0x3ff) {
+ // handle root dir separately
+ pair[0] = lfs2->root[0];
+ pair[1] = lfs2->root[1];
+ } else {
+ // get dir pair from parent
+ lfs2_stag_t res = lfs2_dir_get(lfs2, &dir->m, LFS2_MKTAG(0x700, 0x3ff, 0),
+ LFS2_MKTAG(LFS2_TYPE_STRUCT, lfs2_tag_id(tag), 8), pair);
+ if (res < 0) {
+ LFS2_TRACE("lfs2_dir_open -> %"PRId32, res);
+ return res;
+ }
+ lfs2_pair_fromle32(pair);
+ }
+
+ // fetch first pair
+ int err = lfs2_dir_fetch(lfs2, &dir->m, pair);
+ if (err) {
+ LFS2_TRACE("lfs2_dir_open -> %d", err);
+ return err;
+ }
+
+ // setup entry
+ dir->head[0] = dir->m.pair[0];
+ dir->head[1] = dir->m.pair[1];
+ dir->id = 0;
+ dir->pos = 0;
+
+ // add to list of mdirs
+ dir->type = LFS2_TYPE_DIR;
+ dir->next = (lfs2_dir_t*)lfs2->mlist;
+ lfs2->mlist = (struct lfs2_mlist*)dir;
+
+ LFS2_TRACE("lfs2_dir_open -> %d", 0);
+ return 0;
+}
+
+int lfs2_dir_close(lfs2_t *lfs2, lfs2_dir_t *dir) {
+ LFS2_TRACE("lfs2_dir_close(%p, %p)", (void*)lfs2, (void*)dir);
+ // remove from list of mdirs
+ for (struct lfs2_mlist **p = &lfs2->mlist; *p; p = &(*p)->next) {
+ if (*p == (struct lfs2_mlist*)dir) {
+ *p = (*p)->next;
+ break;
+ }
+ }
+
+ LFS2_TRACE("lfs2_dir_close -> %d", 0);
+ return 0;
+}
+
+int lfs2_dir_read(lfs2_t *lfs2, lfs2_dir_t *dir, struct lfs2_info *info) {
+ LFS2_TRACE("lfs2_dir_read(%p, %p, %p)",
+ (void*)lfs2, (void*)dir, (void*)info);
+ memset(info, 0, sizeof(*info));
+
+ // special offset for '.' and '..'
+ if (dir->pos == 0) {
+ info->type = LFS2_TYPE_DIR;
+ strcpy(info->name, ".");
+ dir->pos += 1;
+ LFS2_TRACE("lfs2_dir_read -> %d", true);
+ return true;
+ } else if (dir->pos == 1) {
+ info->type = LFS2_TYPE_DIR;
+ strcpy(info->name, "..");
+ dir->pos += 1;
+ LFS2_TRACE("lfs2_dir_read -> %d", true);
+ return true;
+ }
+
+ while (true) {
+ if (dir->id == dir->m.count) {
+ if (!dir->m.split) {
+ LFS2_TRACE("lfs2_dir_read -> %d", false);
+ return false;
+ }
+
+ int err = lfs2_dir_fetch(lfs2, &dir->m, dir->m.tail);
+ if (err) {
+ LFS2_TRACE("lfs2_dir_read -> %d", err);
+ return err;
+ }
+
+ dir->id = 0;
+ }
+
+ int err = lfs2_dir_getinfo(lfs2, &dir->m, dir->id, info);
+ if (err && err != LFS2_ERR_NOENT) {
+ LFS2_TRACE("lfs2_dir_read -> %d", err);
+ return err;
+ }
+
+ dir->id += 1;
+ if (err != LFS2_ERR_NOENT) {
+ break;
+ }
+ }
+
+ dir->pos += 1;
+ LFS2_TRACE("lfs2_dir_read -> %d", true);
+ return true;
+}
+
+int lfs2_dir_seek(lfs2_t *lfs2, lfs2_dir_t *dir, lfs2_off_t off) {
+ LFS2_TRACE("lfs2_dir_seek(%p, %p, %"PRIu32")",
+ (void*)lfs2, (void*)dir, off);
+ // simply walk from head dir
+ int err = lfs2_dir_rewind(lfs2, dir);
+ if (err) {
+ LFS2_TRACE("lfs2_dir_seek -> %d", err);
+ return err;
+ }
+
+ // first two for ./..
+ dir->pos = lfs2_min(2, off);
+ off -= dir->pos;
+
+ // skip superblock entry
+ dir->id = (off > 0 && lfs2_pair_cmp(dir->head, lfs2->root) == 0);
+
+ while (off > 0) {
+ int diff = lfs2_min(dir->m.count - dir->id, off);
+ dir->id += diff;
+ dir->pos += diff;
+ off -= diff;
+
+ if (dir->id == dir->m.count) {
+ if (!dir->m.split) {
+ LFS2_TRACE("lfs2_dir_seek -> %d", LFS2_ERR_INVAL);
+ return LFS2_ERR_INVAL;
+ }
+
+ err = lfs2_dir_fetch(lfs2, &dir->m, dir->m.tail);
+ if (err) {
+ LFS2_TRACE("lfs2_dir_seek -> %d", err);
+ return err;
+ }
+
+ dir->id = 0;
+ }
+ }
+
+ LFS2_TRACE("lfs2_dir_seek -> %d", 0);
+ return 0;
+}
+
+lfs2_soff_t lfs2_dir_tell(lfs2_t *lfs2, lfs2_dir_t *dir) {
+ LFS2_TRACE("lfs2_dir_tell(%p, %p)", (void*)lfs2, (void*)dir);
+ (void)lfs2;
+ LFS2_TRACE("lfs2_dir_tell -> %"PRId32, dir->pos);
+ return dir->pos;
+}
+
+int lfs2_dir_rewind(lfs2_t *lfs2, lfs2_dir_t *dir) {
+ LFS2_TRACE("lfs2_dir_rewind(%p, %p)", (void*)lfs2, (void*)dir);
+ // reload the head dir
+ int err = lfs2_dir_fetch(lfs2, &dir->m, dir->head);
+ if (err) {
+ LFS2_TRACE("lfs2_dir_rewind -> %d", err);
+ return err;
+ }
+
+ dir->id = 0;
+ dir->pos = 0;
+ LFS2_TRACE("lfs2_dir_rewind -> %d", 0);
+ return 0;
+}
+
+
+/// File index list operations ///
+static int lfs2_ctz_index(lfs2_t *lfs2, lfs2_off_t *off) {
+ lfs2_off_t size = *off;
+ lfs2_off_t b = lfs2->cfg->block_size - 2*4;
+ lfs2_off_t i = size / b;
+ if (i == 0) {
+ return 0;
+ }
+
+ i = (size - 4*(lfs2_popc(i-1)+2)) / b;
+ *off = size - b*i - 4*lfs2_popc(i);
+ return i;
+}
+
+static int lfs2_ctz_find(lfs2_t *lfs2,
+ const lfs2_cache_t *pcache, lfs2_cache_t *rcache,
+ lfs2_block_t head, lfs2_size_t size,
+ lfs2_size_t pos, lfs2_block_t *block, lfs2_off_t *off) {
+ if (size == 0) {
+ *block = LFS2_BLOCK_NULL;
+ *off = 0;
+ return 0;
+ }
+
+ lfs2_off_t current = lfs2_ctz_index(lfs2, &(lfs2_off_t){size-1});
+ lfs2_off_t target = lfs2_ctz_index(lfs2, &pos);
+
+ while (current > target) {
+ lfs2_size_t skip = lfs2_min(
+ lfs2_npw2(current-target+1) - 1,
+ lfs2_ctz(current));
+
+ int err = lfs2_bd_read(lfs2,
+ pcache, rcache, sizeof(head),
+ head, 4*skip, &head, sizeof(head));
+ head = lfs2_fromle32(head);
+ if (err) {
+ return err;
+ }
+
+ current -= 1 << skip;
+ }
+
+ *block = head;
+ *off = pos;
+ return 0;
+}
+
+static int lfs2_ctz_extend(lfs2_t *lfs2,
+ lfs2_cache_t *pcache, lfs2_cache_t *rcache,
+ lfs2_block_t head, lfs2_size_t size,
+ lfs2_block_t *block, lfs2_off_t *off) {
+ while (true) {
+ // go ahead and grab a block
+ lfs2_block_t nblock;
+ int err = lfs2_alloc(lfs2, &nblock);
+ if (err) {
+ return err;
+ }
+
+ {
+ err = lfs2_bd_erase(lfs2, nblock);
+ if (err) {
+ if (err == LFS2_ERR_CORRUPT) {
+ goto relocate;
+ }
+ return err;
+ }
+
+ if (size == 0) {
+ *block = nblock;
+ *off = 0;
+ return 0;
+ }
+
+ lfs2_size_t noff = size - 1;
+ lfs2_off_t index = lfs2_ctz_index(lfs2, &noff);
+ noff = noff + 1;
+
+ // just copy out the last block if it is incomplete
+ if (noff != lfs2->cfg->block_size) {
+ for (lfs2_off_t i = 0; i < noff; i++) {
+ uint8_t data;
+ err = lfs2_bd_read(lfs2,
+ NULL, rcache, noff-i,
+ head, i, &data, 1);
+ if (err) {
+ return err;
+ }
+
+ err = lfs2_bd_prog(lfs2,
+ pcache, rcache, true,
+ nblock, i, &data, 1);
+ if (err) {
+ if (err == LFS2_ERR_CORRUPT) {
+ goto relocate;
+ }
+ return err;
+ }
+ }
+
+ *block = nblock;
+ *off = noff;
+ return 0;
+ }
+
+ // append block
+ index += 1;
+ lfs2_size_t skips = lfs2_ctz(index) + 1;
+ lfs2_block_t nhead = head;
+ for (lfs2_off_t i = 0; i < skips; i++) {
+ nhead = lfs2_tole32(nhead);
+ err = lfs2_bd_prog(lfs2, pcache, rcache, true,
+ nblock, 4*i, &nhead, 4);
+ nhead = lfs2_fromle32(nhead);
+ if (err) {
+ if (err == LFS2_ERR_CORRUPT) {
+ goto relocate;
+ }
+ return err;
+ }
+
+ if (i != skips-1) {
+ err = lfs2_bd_read(lfs2,
+ NULL, rcache, sizeof(nhead),
+ nhead, 4*i, &nhead, sizeof(nhead));
+ nhead = lfs2_fromle32(nhead);
+ if (err) {
+ return err;
+ }
+ }
+ }
+
+ *block = nblock;
+ *off = 4*skips;
+ return 0;
+ }
+
+relocate:
+ LFS2_DEBUG("Bad block at 0x%"PRIx32, nblock);
+
+ // just clear cache and try a new block
+ lfs2_cache_drop(lfs2, pcache);
+ }
+}
+
+static int lfs2_ctz_traverse(lfs2_t *lfs2,
+ const lfs2_cache_t *pcache, lfs2_cache_t *rcache,
+ lfs2_block_t head, lfs2_size_t size,
+ int (*cb)(void*, lfs2_block_t), void *data) {
+ if (size == 0) {
+ return 0;
+ }
+
+ lfs2_off_t index = lfs2_ctz_index(lfs2, &(lfs2_off_t){size-1});
+
+ while (true) {
+ int err = cb(data, head);
+ if (err) {
+ return err;
+ }
+
+ if (index == 0) {
+ return 0;
+ }
+
+ lfs2_block_t heads[2];
+ int count = 2 - (index & 1);
+ err = lfs2_bd_read(lfs2,
+ pcache, rcache, count*sizeof(head),
+ head, 0, &heads, count*sizeof(head));
+ heads[0] = lfs2_fromle32(heads[0]);
+ heads[1] = lfs2_fromle32(heads[1]);
+ if (err) {
+ return err;
+ }
+
+ for (int i = 0; i < count-1; i++) {
+ err = cb(data, heads[i]);
+ if (err) {
+ return err;
+ }
+ }
+
+ head = heads[count-1];
+ index -= count;
+ }
+}
+
+
+/// Top level file operations ///
+int lfs2_file_opencfg(lfs2_t *lfs2, lfs2_file_t *file,
+ const char *path, int flags,
+ const struct lfs2_file_config *cfg) {
+ LFS2_TRACE("lfs2_file_opencfg(%p, %p, \"%s\", %x, %p {"
+ ".buffer=%p, .attrs=%p, .attr_count=%"PRIu32"})",
+ (void*)lfs2, (void*)file, path, flags,
+ (void*)cfg, cfg->buffer, (void*)cfg->attrs, cfg->attr_count);
+
+ // deorphan if we haven't yet, needed at most once after poweron
+ if ((flags & 3) != LFS2_O_RDONLY) {
+ int err = lfs2_fs_forceconsistency(lfs2);
+ if (err) {
+ LFS2_TRACE("lfs2_file_opencfg -> %d", err);
+ return err;
+ }
+ }
+
+ // setup simple file details
+ int err;
+ file->cfg = cfg;
+ file->flags = flags | LFS2_F_OPENED;
+ file->pos = 0;
+ file->off = 0;
+ file->cache.buffer = NULL;
+
+ // allocate entry for file if it doesn't exist
+ lfs2_stag_t tag = lfs2_dir_find(lfs2, &file->m, &path, &file->id);
+ if (tag < 0 && !(tag == LFS2_ERR_NOENT && file->id != 0x3ff)) {
+ err = tag;
+ goto cleanup;
+ }
+
+ // get id, add to list of mdirs to catch update changes
+ file->type = LFS2_TYPE_REG;
+ file->next = (lfs2_file_t*)lfs2->mlist;
+ lfs2->mlist = (struct lfs2_mlist*)file;
+
+ if (tag == LFS2_ERR_NOENT) {
+ if (!(flags & LFS2_O_CREAT)) {
+ err = LFS2_ERR_NOENT;
+ goto cleanup;
+ }
+
+ // check that name fits
+ lfs2_size_t nlen = strlen(path);
+ if (nlen > lfs2->name_max) {
+ err = LFS2_ERR_NAMETOOLONG;
+ goto cleanup;
+ }
+
+ // get next slot and create entry to remember name
+ err = lfs2_dir_commit(lfs2, &file->m, LFS2_MKATTRS(
+ {LFS2_MKTAG(LFS2_TYPE_CREATE, file->id, 0)},
+ {LFS2_MKTAG(LFS2_TYPE_REG, file->id, nlen), path},
+ {LFS2_MKTAG(LFS2_TYPE_INLINESTRUCT, file->id, 0)}));
+ if (err) {
+ err = LFS2_ERR_NAMETOOLONG;
+ goto cleanup;
+ }
+
+ tag = LFS2_MKTAG(LFS2_TYPE_INLINESTRUCT, 0, 0);
+ } else if (flags & LFS2_O_EXCL) {
+ err = LFS2_ERR_EXIST;
+ goto cleanup;
+ } else if (lfs2_tag_type3(tag) != LFS2_TYPE_REG) {
+ err = LFS2_ERR_ISDIR;
+ goto cleanup;
+ } else if (flags & LFS2_O_TRUNC) {
+ // truncate if requested
+ tag = LFS2_MKTAG(LFS2_TYPE_INLINESTRUCT, file->id, 0);
+ file->flags |= LFS2_F_DIRTY;
+ } else {
+ // try to load what's on disk, if it's inlined we'll fix it later
+ tag = lfs2_dir_get(lfs2, &file->m, LFS2_MKTAG(0x700, 0x3ff, 0),
+ LFS2_MKTAG(LFS2_TYPE_STRUCT, file->id, 8), &file->ctz);
+ if (tag < 0) {
+ err = tag;
+ goto cleanup;
+ }
+ lfs2_ctz_fromle32(&file->ctz);
+ }
+
+ // fetch attrs
+ for (unsigned i = 0; i < file->cfg->attr_count; i++) {
+ if ((file->flags & 3) != LFS2_O_WRONLY) {
+ lfs2_stag_t res = lfs2_dir_get(lfs2, &file->m,
+ LFS2_MKTAG(0x7ff, 0x3ff, 0),
+ LFS2_MKTAG(LFS2_TYPE_USERATTR + file->cfg->attrs[i].type,
+ file->id, file->cfg->attrs[i].size),
+ file->cfg->attrs[i].buffer);
+ if (res < 0 && res != LFS2_ERR_NOENT) {
+ err = res;
+ goto cleanup;
+ }
+ }
+
+ if ((file->flags & 3) != LFS2_O_RDONLY) {
+ if (file->cfg->attrs[i].size > lfs2->attr_max) {
+ err = LFS2_ERR_NOSPC;
+ goto cleanup;
+ }
+
+ file->flags |= LFS2_F_DIRTY;
+ }
+ }
+
+ // allocate buffer if needed
+ if (file->cfg->buffer) {
+ file->cache.buffer = file->cfg->buffer;
+ } else {
+ file->cache.buffer = lfs2_malloc(lfs2->cfg->cache_size);
+ if (!file->cache.buffer) {
+ err = LFS2_ERR_NOMEM;
+ goto cleanup;
+ }
+ }
+
+ // zero to avoid information leak
+ lfs2_cache_zero(lfs2, &file->cache);
+
+ if (lfs2_tag_type3(tag) == LFS2_TYPE_INLINESTRUCT) {
+ // load inline files
+ file->ctz.head = LFS2_BLOCK_INLINE;
+ file->ctz.size = lfs2_tag_size(tag);
+ file->flags |= LFS2_F_INLINE;
+ file->cache.block = file->ctz.head;
+ file->cache.off = 0;
+ file->cache.size = lfs2->cfg->cache_size;
+
+ // don't always read (may be new/trunc file)
+ if (file->ctz.size > 0) {
+ lfs2_stag_t res = lfs2_dir_get(lfs2, &file->m,
+ LFS2_MKTAG(0x700, 0x3ff, 0),
+ LFS2_MKTAG(LFS2_TYPE_STRUCT, file->id,
+ lfs2_min(file->cache.size, 0x3fe)),
+ file->cache.buffer);
+ if (res < 0) {
+ err = res;
+ goto cleanup;
+ }
+ }
+ }
+
+ LFS2_TRACE("lfs2_file_opencfg -> %d", 0);
+ return 0;
+
+cleanup:
+ // clean up lingering resources
+ file->flags |= LFS2_F_ERRED;
+ lfs2_file_close(lfs2, file);
+ LFS2_TRACE("lfs2_file_opencfg -> %d", err);
+ return err;
+}
+
+int lfs2_file_open(lfs2_t *lfs2, lfs2_file_t *file,
+ const char *path, int flags) {
+ LFS2_TRACE("lfs2_file_open(%p, %p, \"%s\", %x)",
+ (void*)lfs2, (void*)file, path, flags);
+ static const struct lfs2_file_config defaults = {0};
+ int err = lfs2_file_opencfg(lfs2, file, path, flags, &defaults);
+ LFS2_TRACE("lfs2_file_open -> %d", err);
+ return err;
+}
+
+int lfs2_file_close(lfs2_t *lfs2, lfs2_file_t *file) {
+ LFS2_TRACE("lfs2_file_close(%p, %p)", (void*)lfs2, (void*)file);
+ LFS2_ASSERT(file->flags & LFS2_F_OPENED);
+
+ int err = lfs2_file_sync(lfs2, file);
+
+ // remove from list of mdirs
+ for (struct lfs2_mlist **p = &lfs2->mlist; *p; p = &(*p)->next) {
+ if (*p == (struct lfs2_mlist*)file) {
+ *p = (*p)->next;
+ break;
+ }
+ }
+
+ // clean up memory
+ if (!file->cfg->buffer) {
+ lfs2_free(file->cache.buffer);
+ }
+
+ file->flags &= ~LFS2_F_OPENED;
+ LFS2_TRACE("lfs2_file_close -> %d", err);
+ return err;
+}
+
+static int lfs2_file_relocate(lfs2_t *lfs2, lfs2_file_t *file) {
+ LFS2_ASSERT(file->flags & LFS2_F_OPENED);
+
+ while (true) {
+ // just relocate what exists into new block
+ lfs2_block_t nblock;
+ int err = lfs2_alloc(lfs2, &nblock);
+ if (err) {
+ return err;
+ }
+
+ err = lfs2_bd_erase(lfs2, nblock);
+ if (err) {
+ if (err == LFS2_ERR_CORRUPT) {
+ goto relocate;
+ }
+ return err;
+ }
+
+ // either read from dirty cache or disk
+ for (lfs2_off_t i = 0; i < file->off; i++) {
+ uint8_t data;
+ if (file->flags & LFS2_F_INLINE) {
+ err = lfs2_dir_getread(lfs2, &file->m,
+ // note we evict inline files before they can be dirty
+ NULL, &file->cache, file->off-i,
+ LFS2_MKTAG(0xfff, 0x1ff, 0),
+ LFS2_MKTAG(LFS2_TYPE_INLINESTRUCT, file->id, 0),
+ i, &data, 1);
+ if (err) {
+ return err;
+ }
+ } else {
+ err = lfs2_bd_read(lfs2,
+ &file->cache, &lfs2->rcache, file->off-i,
+ file->block, i, &data, 1);
+ if (err) {
+ return err;
+ }
+ }
+
+ err = lfs2_bd_prog(lfs2,
+ &lfs2->pcache, &lfs2->rcache, true,
+ nblock, i, &data, 1);
+ if (err) {
+ if (err == LFS2_ERR_CORRUPT) {
+ goto relocate;
+ }
+ return err;
+ }
+ }
+
+ // copy over new state of file
+ memcpy(file->cache.buffer, lfs2->pcache.buffer, lfs2->cfg->cache_size);
+ file->cache.block = lfs2->pcache.block;
+ file->cache.off = lfs2->pcache.off;
+ file->cache.size = lfs2->pcache.size;
+ lfs2_cache_zero(lfs2, &lfs2->pcache);
+
+ file->block = nblock;
+ file->flags |= LFS2_F_WRITING;
+ return 0;
+
+relocate:
+ LFS2_DEBUG("Bad block at 0x%"PRIx32, nblock);
+
+ // just clear cache and try a new block
+ lfs2_cache_drop(lfs2, &lfs2->pcache);
+ }
+}
+
+static int lfs2_file_outline(lfs2_t *lfs2, lfs2_file_t *file) {
+ file->off = file->pos;
+ lfs2_alloc_ack(lfs2);
+ int err = lfs2_file_relocate(lfs2, file);
+ if (err) {
+ return err;
+ }
+
+ file->flags &= ~LFS2_F_INLINE;
+ return 0;
+}
+
+static int lfs2_file_flush(lfs2_t *lfs2, lfs2_file_t *file) {
+ LFS2_ASSERT(file->flags & LFS2_F_OPENED);
+
+ if (file->flags & LFS2_F_READING) {
+ if (!(file->flags & LFS2_F_INLINE)) {
+ lfs2_cache_drop(lfs2, &file->cache);
+ }
+ file->flags &= ~LFS2_F_READING;
+ }
+
+ if (file->flags & LFS2_F_WRITING) {
+ lfs2_off_t pos = file->pos;
+
+ if (!(file->flags & LFS2_F_INLINE)) {
+ // copy over anything after current branch
+ lfs2_file_t orig = {
+ .ctz.head = file->ctz.head,
+ .ctz.size = file->ctz.size,
+ .flags = LFS2_O_RDONLY | LFS2_F_OPENED,
+ .pos = file->pos,
+ .cache = lfs2->rcache,
+ };
+ lfs2_cache_drop(lfs2, &lfs2->rcache);
+
+ while (file->pos < file->ctz.size) {
+ // copy over a byte at a time, leave it up to caching
+ // to make this efficient
+ uint8_t data;
+ lfs2_ssize_t res = lfs2_file_read(lfs2, &orig, &data, 1);
+ if (res < 0) {
+ return res;
+ }
+
+ res = lfs2_file_write(lfs2, file, &data, 1);
+ if (res < 0) {
+ return res;
+ }
+
+ // keep our reference to the rcache in sync
+ if (lfs2->rcache.block != LFS2_BLOCK_NULL) {
+ lfs2_cache_drop(lfs2, &orig.cache);
+ lfs2_cache_drop(lfs2, &lfs2->rcache);
+ }
+ }
+
+ // write out what we have
+ while (true) {
+ int err = lfs2_bd_flush(lfs2, &file->cache, &lfs2->rcache, true);
+ if (err) {
+ if (err == LFS2_ERR_CORRUPT) {
+ goto relocate;
+ }
+ return err;
+ }
+
+ break;
+
+relocate:
+ LFS2_DEBUG("Bad block at 0x%"PRIx32, file->block);
+ err = lfs2_file_relocate(lfs2, file);
+ if (err) {
+ return err;
+ }
+ }
+ } else {
+ file->pos = lfs2_max(file->pos, file->ctz.size);
+ }
+
+ // actual file updates
+ file->ctz.head = file->block;
+ file->ctz.size = file->pos;
+ file->flags &= ~LFS2_F_WRITING;
+ file->flags |= LFS2_F_DIRTY;
+
+ file->pos = pos;
+ }
+
+ return 0;
+}
+
+int lfs2_file_sync(lfs2_t *lfs2, lfs2_file_t *file) {
+ LFS2_TRACE("lfs2_file_sync(%p, %p)", (void*)lfs2, (void*)file);
+ LFS2_ASSERT(file->flags & LFS2_F_OPENED);
+
+ if (file->flags & LFS2_F_ERRED) {
+ // it's not safe to do anything if our file errored
+ LFS2_TRACE("lfs2_file_sync -> %d", 0);
+ return 0;
+ }
+
+ int err = lfs2_file_flush(lfs2, file);
+ if (err) {
+ file->flags |= LFS2_F_ERRED;
+ LFS2_TRACE("lfs2_file_sync -> %d", err);
+ return err;
+ }
+
+ if ((file->flags & LFS2_F_DIRTY) &&
+ !lfs2_pair_isnull(file->m.pair)) {
+ // update dir entry
+ uint16_t type;
+ const void *buffer;
+ lfs2_size_t size;
+ struct lfs2_ctz ctz;
+ if (file->flags & LFS2_F_INLINE) {
+ // inline the whole file
+ type = LFS2_TYPE_INLINESTRUCT;
+ buffer = file->cache.buffer;
+ size = file->ctz.size;
+ } else {
+ // update the ctz reference
+ type = LFS2_TYPE_CTZSTRUCT;
+ // copy ctz so alloc will work during a relocate
+ ctz = file->ctz;
+ lfs2_ctz_tole32(&ctz);
+ buffer = &ctz;
+ size = sizeof(ctz);
+ }
+
+ // commit file data and attributes
+ err = lfs2_dir_commit(lfs2, &file->m, LFS2_MKATTRS(
+ {LFS2_MKTAG(type, file->id, size), buffer},
+ {LFS2_MKTAG(LFS2_FROM_USERATTRS, file->id,
+ file->cfg->attr_count), file->cfg->attrs}));
+ if (err) {
+ file->flags |= LFS2_F_ERRED;
+ LFS2_TRACE("lfs2_file_sync -> %d", err);
+ return err;
+ }
+
+ file->flags &= ~LFS2_F_DIRTY;
+ }
+
+ LFS2_TRACE("lfs2_file_sync -> %d", 0);
+ return 0;
+}
+
+lfs2_ssize_t lfs2_file_read(lfs2_t *lfs2, lfs2_file_t *file,
+ void *buffer, lfs2_size_t size) {
+ LFS2_TRACE("lfs2_file_read(%p, %p, %p, %"PRIu32")",
+ (void*)lfs2, (void*)file, buffer, size);
+ LFS2_ASSERT(file->flags & LFS2_F_OPENED);
+ LFS2_ASSERT((file->flags & 3) != LFS2_O_WRONLY);
+
+ uint8_t *data = buffer;
+ lfs2_size_t nsize = size;
+
+ if (file->flags & LFS2_F_WRITING) {
+ // flush out any writes
+ int err = lfs2_file_flush(lfs2, file);
+ if (err) {
+ LFS2_TRACE("lfs2_file_read -> %d", err);
+ return err;
+ }
+ }
+
+ if (file->pos >= file->ctz.size) {
+ // eof if past end
+ LFS2_TRACE("lfs2_file_read -> %d", 0);
+ return 0;
+ }
+
+ size = lfs2_min(size, file->ctz.size - file->pos);
+ nsize = size;
+
+ while (nsize > 0) {
+ // check if we need a new block
+ if (!(file->flags & LFS2_F_READING) ||
+ file->off == lfs2->cfg->block_size) {
+ if (!(file->flags & LFS2_F_INLINE)) {
+ int err = lfs2_ctz_find(lfs2, NULL, &file->cache,
+ file->ctz.head, file->ctz.size,
+ file->pos, &file->block, &file->off);
+ if (err) {
+ LFS2_TRACE("lfs2_file_read -> %d", err);
+ return err;
+ }
+ } else {
+ file->block = LFS2_BLOCK_INLINE;
+ file->off = file->pos;
+ }
+
+ file->flags |= LFS2_F_READING;
+ }
+
+ // read as much as we can in current block
+ lfs2_size_t diff = lfs2_min(nsize, lfs2->cfg->block_size - file->off);
+ if (file->flags & LFS2_F_INLINE) {
+ int err = lfs2_dir_getread(lfs2, &file->m,
+ NULL, &file->cache, lfs2->cfg->block_size,
+ LFS2_MKTAG(0xfff, 0x1ff, 0),
+ LFS2_MKTAG(LFS2_TYPE_INLINESTRUCT, file->id, 0),
+ file->off, data, diff);
+ if (err) {
+ LFS2_TRACE("lfs2_file_read -> %d", err);
+ return err;
+ }
+ } else {
+ int err = lfs2_bd_read(lfs2,
+ NULL, &file->cache, lfs2->cfg->block_size,
+ file->block, file->off, data, diff);
+ if (err) {
+ LFS2_TRACE("lfs2_file_read -> %d", err);
+ return err;
+ }
+ }
+
+ file->pos += diff;
+ file->off += diff;
+ data += diff;
+ nsize -= diff;
+ }
+
+ LFS2_TRACE("lfs2_file_read -> %"PRId32, size);
+ return size;
+}
+
+lfs2_ssize_t lfs2_file_write(lfs2_t *lfs2, lfs2_file_t *file,
+ const void *buffer, lfs2_size_t size) {
+ LFS2_TRACE("lfs2_file_write(%p, %p, %p, %"PRIu32")",
+ (void*)lfs2, (void*)file, buffer, size);
+ LFS2_ASSERT(file->flags & LFS2_F_OPENED);
+ LFS2_ASSERT((file->flags & 3) != LFS2_O_RDONLY);
+
+ const uint8_t *data = buffer;
+ lfs2_size_t nsize = size;
+
+ if (file->flags & LFS2_F_READING) {
+ // drop any reads
+ int err = lfs2_file_flush(lfs2, file);
+ if (err) {
+ LFS2_TRACE("lfs2_file_write -> %d", err);
+ return err;
+ }
+ }
+
+ if ((file->flags & LFS2_O_APPEND) && file->pos < file->ctz.size) {
+ file->pos = file->ctz.size;
+ }
+
+ if (file->pos + size > lfs2->file_max) {
+ // Larger than file limit?
+ LFS2_TRACE("lfs2_file_write -> %d", LFS2_ERR_FBIG);
+ return LFS2_ERR_FBIG;
+ }
+
+ if (!(file->flags & LFS2_F_WRITING) && file->pos > file->ctz.size) {
+ // fill with zeros
+ lfs2_off_t pos = file->pos;
+ file->pos = file->ctz.size;
+
+ while (file->pos < pos) {
+ lfs2_ssize_t res = lfs2_file_write(lfs2, file, &(uint8_t){0}, 1);
+ if (res < 0) {
+ LFS2_TRACE("lfs2_file_write -> %"PRId32, res);
+ return res;
+ }
+ }
+ }
+
+ if ((file->flags & LFS2_F_INLINE) &&
+ lfs2_max(file->pos+nsize, file->ctz.size) >
+ lfs2_min(0x3fe, lfs2_min(
+ lfs2->cfg->cache_size, lfs2->cfg->block_size/8))) {
+ // inline file doesn't fit anymore
+ int err = lfs2_file_outline(lfs2, file);
+ if (err) {
+ file->flags |= LFS2_F_ERRED;
+ LFS2_TRACE("lfs2_file_write -> %d", err);
+ return err;
+ }
+ }
+
+ while (nsize > 0) {
+ // check if we need a new block
+ if (!(file->flags & LFS2_F_WRITING) ||
+ file->off == lfs2->cfg->block_size) {
+ if (!(file->flags & LFS2_F_INLINE)) {
+ if (!(file->flags & LFS2_F_WRITING) && file->pos > 0) {
+ // find out which block we're extending from
+ int err = lfs2_ctz_find(lfs2, NULL, &file->cache,
+ file->ctz.head, file->ctz.size,
+ file->pos-1, &file->block, &file->off);
+ if (err) {
+ file->flags |= LFS2_F_ERRED;
+ LFS2_TRACE("lfs2_file_write -> %d", err);
+ return err;
+ }
+
+ // mark cache as dirty since we may have read data into it
+ lfs2_cache_zero(lfs2, &file->cache);
+ }
+
+ // extend file with new blocks
+ lfs2_alloc_ack(lfs2);
+ int err = lfs2_ctz_extend(lfs2, &file->cache, &lfs2->rcache,
+ file->block, file->pos,
+ &file->block, &file->off);
+ if (err) {
+ file->flags |= LFS2_F_ERRED;
+ LFS2_TRACE("lfs2_file_write -> %d", err);
+ return err;
+ }
+ } else {
+ file->block = LFS2_BLOCK_INLINE;
+ file->off = file->pos;
+ }
+
+ file->flags |= LFS2_F_WRITING;
+ }
+
+ // program as much as we can in current block
+ lfs2_size_t diff = lfs2_min(nsize, lfs2->cfg->block_size - file->off);
+ while (true) {
+ int err = lfs2_bd_prog(lfs2, &file->cache, &lfs2->rcache, true,
+ file->block, file->off, data, diff);
+ if (err) {
+ if (err == LFS2_ERR_CORRUPT) {
+ goto relocate;
+ }
+ file->flags |= LFS2_F_ERRED;
+ LFS2_TRACE("lfs2_file_write -> %d", err);
+ return err;
+ }
+
+ break;
+relocate:
+ err = lfs2_file_relocate(lfs2, file);
+ if (err) {
+ file->flags |= LFS2_F_ERRED;
+ LFS2_TRACE("lfs2_file_write -> %d", err);
+ return err;
+ }
+ }
+
+ file->pos += diff;
+ file->off += diff;
+ data += diff;
+ nsize -= diff;
+
+ lfs2_alloc_ack(lfs2);
+ }
+
+ file->flags &= ~LFS2_F_ERRED;
+ LFS2_TRACE("lfs2_file_write -> %"PRId32, size);
+ return size;
+}
+
+lfs2_soff_t lfs2_file_seek(lfs2_t *lfs2, lfs2_file_t *file,
+ lfs2_soff_t off, int whence) {
+ LFS2_TRACE("lfs2_file_seek(%p, %p, %"PRId32", %d)",
+ (void*)lfs2, (void*)file, off, whence);
+ LFS2_ASSERT(file->flags & LFS2_F_OPENED);
+
+ // write out everything beforehand, may be noop if rdonly
+ int err = lfs2_file_flush(lfs2, file);
+ if (err) {
+ LFS2_TRACE("lfs2_file_seek -> %d", err);
+ return err;
+ }
+
+ // find new pos
+ lfs2_off_t npos = file->pos;
+ if (whence == LFS2_SEEK_SET) {
+ npos = off;
+ } else if (whence == LFS2_SEEK_CUR) {
+ npos = file->pos + off;
+ } else if (whence == LFS2_SEEK_END) {
+ npos = file->ctz.size + off;
+ }
+
+ if (npos > lfs2->file_max) {
+ // file position out of range
+ LFS2_TRACE("lfs2_file_seek -> %d", LFS2_ERR_INVAL);
+ return LFS2_ERR_INVAL;
+ }
+
+ // update pos
+ file->pos = npos;
+ LFS2_TRACE("lfs2_file_seek -> %"PRId32, npos);
+ return npos;
+}
+
+int lfs2_file_truncate(lfs2_t *lfs2, lfs2_file_t *file, lfs2_off_t size) {
+ LFS2_TRACE("lfs2_file_truncate(%p, %p, %"PRIu32")",
+ (void*)lfs2, (void*)file, size);
+ LFS2_ASSERT(file->flags & LFS2_F_OPENED);
+ LFS2_ASSERT((file->flags & 3) != LFS2_O_RDONLY);
+
+ if (size > LFS2_FILE_MAX) {
+ LFS2_TRACE("lfs2_file_truncate -> %d", LFS2_ERR_INVAL);
+ return LFS2_ERR_INVAL;
+ }
+
+ lfs2_off_t pos = file->pos;
+ lfs2_off_t oldsize = lfs2_file_size(lfs2, file);
+ if (size < oldsize) {
+ // need to flush since directly changing metadata
+ int err = lfs2_file_flush(lfs2, file);
+ if (err) {
+ LFS2_TRACE("lfs2_file_truncate -> %d", err);
+ return err;
+ }
+
+ // lookup new head in ctz skip list
+ err = lfs2_ctz_find(lfs2, NULL, &file->cache,
+ file->ctz.head, file->ctz.size,
+ size, &file->block, &file->off);
+ if (err) {
+ LFS2_TRACE("lfs2_file_truncate -> %d", err);
+ return err;
+ }
+
+ file->ctz.head = file->block;
+ file->ctz.size = size;
+ file->flags |= LFS2_F_DIRTY | LFS2_F_READING;
+ } else if (size > oldsize) {
+ // flush+seek if not already at end
+ if (file->pos != oldsize) {
+ lfs2_soff_t res = lfs2_file_seek(lfs2, file, 0, LFS2_SEEK_END);
+ if (res < 0) {
+ LFS2_TRACE("lfs2_file_truncate -> %"PRId32, res);
+ return (int)res;
+ }
+ }
+
+ // fill with zeros
+ while (file->pos < size) {
+ lfs2_ssize_t res = lfs2_file_write(lfs2, file, &(uint8_t){0}, 1);
+ if (res < 0) {
+ LFS2_TRACE("lfs2_file_truncate -> %"PRId32, res);
+ return (int)res;
+ }
+ }
+ }
+
+ // restore pos
+ lfs2_soff_t res = lfs2_file_seek(lfs2, file, pos, LFS2_SEEK_SET);
+ if (res < 0) {
+ LFS2_TRACE("lfs2_file_truncate -> %"PRId32, res);
+ return (int)res;
+ }
+
+ LFS2_TRACE("lfs2_file_truncate -> %d", 0);
+ return 0;
+}
+
+lfs2_soff_t lfs2_file_tell(lfs2_t *lfs2, lfs2_file_t *file) {
+ LFS2_TRACE("lfs2_file_tell(%p, %p)", (void*)lfs2, (void*)file);
+ LFS2_ASSERT(file->flags & LFS2_F_OPENED);
+ (void)lfs2;
+ LFS2_TRACE("lfs2_file_tell -> %"PRId32, file->pos);
+ return file->pos;
+}
+
+int lfs2_file_rewind(lfs2_t *lfs2, lfs2_file_t *file) {
+ LFS2_TRACE("lfs2_file_rewind(%p, %p)", (void*)lfs2, (void*)file);
+ lfs2_soff_t res = lfs2_file_seek(lfs2, file, 0, LFS2_SEEK_SET);
+ if (res < 0) {
+ LFS2_TRACE("lfs2_file_rewind -> %"PRId32, res);
+ return (int)res;
+ }
+
+ LFS2_TRACE("lfs2_file_rewind -> %d", 0);
+ return 0;
+}
+
+lfs2_soff_t lfs2_file_size(lfs2_t *lfs2, lfs2_file_t *file) {
+ LFS2_TRACE("lfs2_file_size(%p, %p)", (void*)lfs2, (void*)file);
+ LFS2_ASSERT(file->flags & LFS2_F_OPENED);
+ (void)lfs2;
+ if (file->flags & LFS2_F_WRITING) {
+ LFS2_TRACE("lfs2_file_size -> %"PRId32,
+ lfs2_max(file->pos, file->ctz.size));
+ return lfs2_max(file->pos, file->ctz.size);
+ } else {
+ LFS2_TRACE("lfs2_file_size -> %"PRId32, file->ctz.size);
+ return file->ctz.size;
+ }
+}
+
+
+/// General fs operations ///
+int lfs2_stat(lfs2_t *lfs2, const char *path, struct lfs2_info *info) {
+ LFS2_TRACE("lfs2_stat(%p, \"%s\", %p)", (void*)lfs2, path, (void*)info);
+ lfs2_mdir_t cwd;
+ lfs2_stag_t tag = lfs2_dir_find(lfs2, &cwd, &path, NULL);
+ if (tag < 0) {
+ LFS2_TRACE("lfs2_stat -> %"PRId32, tag);
+ return (int)tag;
+ }
+
+ int err = lfs2_dir_getinfo(lfs2, &cwd, lfs2_tag_id(tag), info);
+ LFS2_TRACE("lfs2_stat -> %d", err);
+ return err;
+}
+
+int lfs2_remove(lfs2_t *lfs2, const char *path) {
+ LFS2_TRACE("lfs2_remove(%p, \"%s\")", (void*)lfs2, path);
+ // deorphan if we haven't yet, needed at most once after poweron
+ int err = lfs2_fs_forceconsistency(lfs2);
+ if (err) {
+ LFS2_TRACE("lfs2_remove -> %d", err);
+ return err;
+ }
+
+ lfs2_mdir_t cwd;
+ lfs2_stag_t tag = lfs2_dir_find(lfs2, &cwd, &path, NULL);
+ if (tag < 0 || lfs2_tag_id(tag) == 0x3ff) {
+ LFS2_TRACE("lfs2_remove -> %"PRId32, (tag < 0) ? tag : LFS2_ERR_INVAL);
+ return (tag < 0) ? (int)tag : LFS2_ERR_INVAL;
+ }
+
+ struct lfs2_mlist dir;
+ dir.next = lfs2->mlist;
+ if (lfs2_tag_type3(tag) == LFS2_TYPE_DIR) {
+ // must be empty before removal
+ lfs2_block_t pair[2];
+ lfs2_stag_t res = lfs2_dir_get(lfs2, &cwd, LFS2_MKTAG(0x700, 0x3ff, 0),
+ LFS2_MKTAG(LFS2_TYPE_STRUCT, lfs2_tag_id(tag), 8), pair);
+ if (res < 0) {
+ LFS2_TRACE("lfs2_remove -> %"PRId32, res);
+ return (int)res;
+ }
+ lfs2_pair_fromle32(pair);
+
+ err = lfs2_dir_fetch(lfs2, &dir.m, pair);
+ if (err) {
+ LFS2_TRACE("lfs2_remove -> %d", err);
+ return err;
+ }
+
+ if (dir.m.count > 0 || dir.m.split) {
+ LFS2_TRACE("lfs2_remove -> %d", LFS2_ERR_NOTEMPTY);
+ return LFS2_ERR_NOTEMPTY;
+ }
+
+ // mark fs as orphaned
+ lfs2_fs_preporphans(lfs2, +1);
+
+ // I know it's crazy but yes, dir can be changed by our parent's
+ // commit (if predecessor is child)
+ dir.type = 0;
+ dir.id = 0;
+ lfs2->mlist = &dir;
+ }
+
+ // delete the entry
+ err = lfs2_dir_commit(lfs2, &cwd, LFS2_MKATTRS(
+ {LFS2_MKTAG(LFS2_TYPE_DELETE, lfs2_tag_id(tag), 0)}));
+ if (err) {
+ lfs2->mlist = dir.next;
+ LFS2_TRACE("lfs2_remove -> %d", err);
+ return err;
+ }
+
+ lfs2->mlist = dir.next;
+ if (lfs2_tag_type3(tag) == LFS2_TYPE_DIR) {
+ // fix orphan
+ lfs2_fs_preporphans(lfs2, -1);
+
+ err = lfs2_fs_pred(lfs2, dir.m.pair, &cwd);
+ if (err) {
+ LFS2_TRACE("lfs2_remove -> %d", err);
+ return err;
+ }
+
+ err = lfs2_dir_drop(lfs2, &cwd, &dir.m);
+ if (err) {
+ LFS2_TRACE("lfs2_remove -> %d", err);
+ return err;
+ }
+ }
+
+ LFS2_TRACE("lfs2_remove -> %d", 0);
+ return 0;
+}
+
+int lfs2_rename(lfs2_t *lfs2, const char *oldpath, const char *newpath) {
+ LFS2_TRACE("lfs2_rename(%p, \"%s\", \"%s\")", (void*)lfs2, oldpath, newpath);
+
+ // deorphan if we haven't yet, needed at most once after poweron
+ int err = lfs2_fs_forceconsistency(lfs2);
+ if (err) {
+ LFS2_TRACE("lfs2_rename -> %d", err);
+ return err;
+ }
+
+ // find old entry
+ lfs2_mdir_t oldcwd;
+ lfs2_stag_t oldtag = lfs2_dir_find(lfs2, &oldcwd, &oldpath, NULL);
+ if (oldtag < 0 || lfs2_tag_id(oldtag) == 0x3ff) {
+ LFS2_TRACE("lfs2_rename -> %"PRId32,
+ (oldtag < 0) ? oldtag : LFS2_ERR_INVAL);
+ return (oldtag < 0) ? (int)oldtag : LFS2_ERR_INVAL;
+ }
+
+ // find new entry
+ lfs2_mdir_t newcwd;
+ uint16_t newid;
+ lfs2_stag_t prevtag = lfs2_dir_find(lfs2, &newcwd, &newpath, &newid);
+ if ((prevtag < 0 || lfs2_tag_id(prevtag) == 0x3ff) &&
+ !(prevtag == LFS2_ERR_NOENT && newid != 0x3ff)) {
+ LFS2_TRACE("lfs2_rename -> %"PRId32,
+ (prevtag < 0) ? prevtag : LFS2_ERR_INVAL);
+ return (prevtag < 0) ? (int)prevtag : LFS2_ERR_INVAL;
+ }
+
+ // if we're in the same pair there's a few special cases...
+ bool samepair = (lfs2_pair_cmp(oldcwd.pair, newcwd.pair) == 0);
+ uint16_t newoldid = lfs2_tag_id(oldtag);
+
+ struct lfs2_mlist prevdir;
+ prevdir.next = lfs2->mlist;
+ if (prevtag == LFS2_ERR_NOENT) {
+ // check that name fits
+ lfs2_size_t nlen = strlen(newpath);
+ if (nlen > lfs2->name_max) {
+ LFS2_TRACE("lfs2_rename -> %d", LFS2_ERR_NAMETOOLONG);
+ return LFS2_ERR_NAMETOOLONG;
+ }
+
+ // there is a small chance we are being renamed in the same
+ // directory/ to an id less than our old id, the global update
+ // to handle this is a bit messy
+ if (samepair && newid <= newoldid) {
+ newoldid += 1;
+ }
+ } else if (lfs2_tag_type3(prevtag) != lfs2_tag_type3(oldtag)) {
+ LFS2_TRACE("lfs2_rename -> %d", LFS2_ERR_ISDIR);
+ return LFS2_ERR_ISDIR;
+ } else if (samepair && newid == newoldid) {
+ // we're renaming to ourselves??
+ LFS2_TRACE("lfs2_rename -> %d", 0);
+ return 0;
+ } else if (lfs2_tag_type3(prevtag) == LFS2_TYPE_DIR) {
+ // must be empty before removal
+ lfs2_block_t prevpair[2];
+ lfs2_stag_t res = lfs2_dir_get(lfs2, &newcwd, LFS2_MKTAG(0x700, 0x3ff, 0),
+ LFS2_MKTAG(LFS2_TYPE_STRUCT, newid, 8), prevpair);
+ if (res < 0) {
+ LFS2_TRACE("lfs2_rename -> %"PRId32, res);
+ return (int)res;
+ }
+ lfs2_pair_fromle32(prevpair);
+
+ // must be empty before removal
+ err = lfs2_dir_fetch(lfs2, &prevdir.m, prevpair);
+ if (err) {
+ LFS2_TRACE("lfs2_rename -> %d", err);
+ return err;
+ }
+
+ if (prevdir.m.count > 0 || prevdir.m.split) {
+ LFS2_TRACE("lfs2_rename -> %d", LFS2_ERR_NOTEMPTY);
+ return LFS2_ERR_NOTEMPTY;
+ }
+
+ // mark fs as orphaned
+ lfs2_fs_preporphans(lfs2, +1);
+
+ // I know it's crazy but yes, dir can be changed by our parent's
+ // commit (if predecessor is child)
+ prevdir.type = 0;
+ prevdir.id = 0;
+ lfs2->mlist = &prevdir;
+ }
+
+ if (!samepair) {
+ lfs2_fs_prepmove(lfs2, newoldid, oldcwd.pair);
+ }
+
+ // move over all attributes
+ err = lfs2_dir_commit(lfs2, &newcwd, LFS2_MKATTRS(
+ {LFS2_MKTAG_IF(prevtag != LFS2_ERR_NOENT,
+ LFS2_TYPE_DELETE, newid, 0)},
+ {LFS2_MKTAG(LFS2_TYPE_CREATE, newid, 0)},
+ {LFS2_MKTAG(lfs2_tag_type3(oldtag), newid, strlen(newpath)), newpath},
+ {LFS2_MKTAG(LFS2_FROM_MOVE, newid, lfs2_tag_id(oldtag)), &oldcwd},
+ {LFS2_MKTAG_IF(samepair,
+ LFS2_TYPE_DELETE, newoldid, 0)}));
+ if (err) {
+ lfs2->mlist = prevdir.next;
+ LFS2_TRACE("lfs2_rename -> %d", err);
+ return err;
+ }
+
+ // let commit clean up after move (if we're different! otherwise move
+ // logic already fixed it for us)
+ if (!samepair && lfs2_gstate_hasmove(&lfs2->gstate)) {
+ // prep gstate and delete move id
+ lfs2_fs_prepmove(lfs2, 0x3ff, NULL);
+ err = lfs2_dir_commit(lfs2, &oldcwd, LFS2_MKATTRS(
+ {LFS2_MKTAG(LFS2_TYPE_DELETE, lfs2_tag_id(oldtag), 0)}));
+ if (err) {
+ lfs2->mlist = prevdir.next;
+ LFS2_TRACE("lfs2_rename -> %d", err);
+ return err;
+ }
+ }
+
+ lfs2->mlist = prevdir.next;
+ if (prevtag != LFS2_ERR_NOENT && lfs2_tag_type3(prevtag) == LFS2_TYPE_DIR) {
+ // fix orphan
+ lfs2_fs_preporphans(lfs2, -1);
+
+ err = lfs2_fs_pred(lfs2, prevdir.m.pair, &newcwd);
+ if (err) {
+ LFS2_TRACE("lfs2_rename -> %d", err);
+ return err;
+ }
+
+ err = lfs2_dir_drop(lfs2, &newcwd, &prevdir.m);
+ if (err) {
+ LFS2_TRACE("lfs2_rename -> %d", err);
+ return err;
+ }
+ }
+
+ LFS2_TRACE("lfs2_rename -> %d", 0);
+ return 0;
+}
+
+lfs2_ssize_t lfs2_getattr(lfs2_t *lfs2, const char *path,
+ uint8_t type, void *buffer, lfs2_size_t size) {
+ LFS2_TRACE("lfs2_getattr(%p, \"%s\", %"PRIu8", %p, %"PRIu32")",
+ (void*)lfs2, path, type, buffer, size);
+ lfs2_mdir_t cwd;
+ lfs2_stag_t tag = lfs2_dir_find(lfs2, &cwd, &path, NULL);
+ if (tag < 0) {
+ LFS2_TRACE("lfs2_getattr -> %"PRId32, tag);
+ return tag;
+ }
+
+ uint16_t id = lfs2_tag_id(tag);
+ if (id == 0x3ff) {
+ // special case for root
+ id = 0;
+ int err = lfs2_dir_fetch(lfs2, &cwd, lfs2->root);
+ if (err) {
+ LFS2_TRACE("lfs2_getattr -> %d", err);
+ return err;
+ }
+ }
+
+ tag = lfs2_dir_get(lfs2, &cwd, LFS2_MKTAG(0x7ff, 0x3ff, 0),
+ LFS2_MKTAG(LFS2_TYPE_USERATTR + type,
+ id, lfs2_min(size, lfs2->attr_max)),
+ buffer);
+ if (tag < 0) {
+ if (tag == LFS2_ERR_NOENT) {
+ LFS2_TRACE("lfs2_getattr -> %d", LFS2_ERR_NOATTR);
+ return LFS2_ERR_NOATTR;
+ }
+
+ LFS2_TRACE("lfs2_getattr -> %"PRId32, tag);
+ return tag;
+ }
+
+ size = lfs2_tag_size(tag);
+ LFS2_TRACE("lfs2_getattr -> %"PRId32, size);
+ return size;
+}
+
+static int lfs2_commitattr(lfs2_t *lfs2, const char *path,
+ uint8_t type, const void *buffer, lfs2_size_t size) {
+ lfs2_mdir_t cwd;
+ lfs2_stag_t tag = lfs2_dir_find(lfs2, &cwd, &path, NULL);
+ if (tag < 0) {
+ return tag;
+ }
+
+ uint16_t id = lfs2_tag_id(tag);
+ if (id == 0x3ff) {
+ // special case for root
+ id = 0;
+ int err = lfs2_dir_fetch(lfs2, &cwd, lfs2->root);
+ if (err) {
+ return err;
+ }
+ }
+
+ return lfs2_dir_commit(lfs2, &cwd, LFS2_MKATTRS(
+ {LFS2_MKTAG(LFS2_TYPE_USERATTR + type, id, size), buffer}));
+}
+
+int lfs2_setattr(lfs2_t *lfs2, const char *path,
+ uint8_t type, const void *buffer, lfs2_size_t size) {
+ LFS2_TRACE("lfs2_setattr(%p, \"%s\", %"PRIu8", %p, %"PRIu32")",
+ (void*)lfs2, path, type, buffer, size);
+ if (size > lfs2->attr_max) {
+ LFS2_TRACE("lfs2_setattr -> %d", LFS2_ERR_NOSPC);
+ return LFS2_ERR_NOSPC;
+ }
+
+ int err = lfs2_commitattr(lfs2, path, type, buffer, size);
+ LFS2_TRACE("lfs2_setattr -> %d", err);
+ return err;
+}
+
+int lfs2_removeattr(lfs2_t *lfs2, const char *path, uint8_t type) {
+ LFS2_TRACE("lfs2_removeattr(%p, \"%s\", %"PRIu8")", (void*)lfs2, path, type);
+ int err = lfs2_commitattr(lfs2, path, type, NULL, 0x3ff);
+ LFS2_TRACE("lfs2_removeattr -> %d", err);
+ return err;
+}
+
+
+/// Filesystem operations ///
+static int lfs2_init(lfs2_t *lfs2, const struct lfs2_config *cfg) {
+ lfs2->cfg = cfg;
+ int err = 0;
+
+ // validate that the lfs2-cfg sizes were initiated properly before
+ // performing any arithmetic logics with them
+ LFS2_ASSERT(lfs2->cfg->read_size != 0);
+ LFS2_ASSERT(lfs2->cfg->prog_size != 0);
+ LFS2_ASSERT(lfs2->cfg->cache_size != 0);
+
+ // check that block size is a multiple of cache size is a multiple
+ // of prog and read sizes
+ LFS2_ASSERT(lfs2->cfg->cache_size % lfs2->cfg->read_size == 0);
+ LFS2_ASSERT(lfs2->cfg->cache_size % lfs2->cfg->prog_size == 0);
+ LFS2_ASSERT(lfs2->cfg->block_size % lfs2->cfg->cache_size == 0);
+
+ // check that the block size is large enough to fit ctz pointers
+ LFS2_ASSERT(4*lfs2_npw2(0xffffffff / (lfs2->cfg->block_size-2*4))
+ <= lfs2->cfg->block_size);
+
+ // block_cycles = 0 is no longer supported.
+ //
+ // block_cycles is the number of erase cycles before littlefs evicts
+ // metadata logs as a part of wear leveling. Suggested values are in the
+ // range of 100-1000, or set block_cycles to -1 to disable block-level
+ // wear-leveling.
+ LFS2_ASSERT(lfs2->cfg->block_cycles != 0);
+
+
+ // setup read cache
+ if (lfs2->cfg->read_buffer) {
+ lfs2->rcache.buffer = lfs2->cfg->read_buffer;
+ } else {
+ lfs2->rcache.buffer = lfs2_malloc(lfs2->cfg->cache_size);
+ if (!lfs2->rcache.buffer) {
+ err = LFS2_ERR_NOMEM;
+ goto cleanup;
+ }
+ }
+
+ // setup program cache
+ if (lfs2->cfg->prog_buffer) {
+ lfs2->pcache.buffer = lfs2->cfg->prog_buffer;
+ } else {
+ lfs2->pcache.buffer = lfs2_malloc(lfs2->cfg->cache_size);
+ if (!lfs2->pcache.buffer) {
+ err = LFS2_ERR_NOMEM;
+ goto cleanup;
+ }
+ }
+
+ // zero to avoid information leaks
+ lfs2_cache_zero(lfs2, &lfs2->rcache);
+ lfs2_cache_zero(lfs2, &lfs2->pcache);
+
+ // setup lookahead, must be multiple of 64-bits, 32-bit aligned
+ LFS2_ASSERT(lfs2->cfg->lookahead_size > 0);
+ LFS2_ASSERT(lfs2->cfg->lookahead_size % 8 == 0 &&
+ (uintptr_t)lfs2->cfg->lookahead_buffer % 4 == 0);
+ if (lfs2->cfg->lookahead_buffer) {
+ lfs2->free.buffer = lfs2->cfg->lookahead_buffer;
+ } else {
+ lfs2->free.buffer = lfs2_malloc(lfs2->cfg->lookahead_size);
+ if (!lfs2->free.buffer) {
+ err = LFS2_ERR_NOMEM;
+ goto cleanup;
+ }
+ }
+
+ // check that the size limits are sane
+ LFS2_ASSERT(lfs2->cfg->name_max <= LFS2_NAME_MAX);
+ lfs2->name_max = lfs2->cfg->name_max;
+ if (!lfs2->name_max) {
+ lfs2->name_max = LFS2_NAME_MAX;
+ }
+
+ LFS2_ASSERT(lfs2->cfg->file_max <= LFS2_FILE_MAX);
+ lfs2->file_max = lfs2->cfg->file_max;
+ if (!lfs2->file_max) {
+ lfs2->file_max = LFS2_FILE_MAX;
+ }
+
+ LFS2_ASSERT(lfs2->cfg->attr_max <= LFS2_ATTR_MAX);
+ lfs2->attr_max = lfs2->cfg->attr_max;
+ if (!lfs2->attr_max) {
+ lfs2->attr_max = LFS2_ATTR_MAX;
+ }
+
+ // setup default state
+ lfs2->root[0] = LFS2_BLOCK_NULL;
+ lfs2->root[1] = LFS2_BLOCK_NULL;
+ lfs2->mlist = NULL;
+ lfs2->seed = 0;
+ lfs2->gdisk = (lfs2_gstate_t){0};
+ lfs2->gstate = (lfs2_gstate_t){0};
+ lfs2->gdelta = (lfs2_gstate_t){0};
+#ifdef LFS2_MIGRATE
+ lfs2->lfs21 = NULL;
+#endif
+
+ return 0;
+
+cleanup:
+ lfs2_deinit(lfs2);
+ return err;
+}
+
+static int lfs2_deinit(lfs2_t *lfs2) {
+ // free allocated memory
+ if (!lfs2->cfg->read_buffer) {
+ lfs2_free(lfs2->rcache.buffer);
+ }
+
+ if (!lfs2->cfg->prog_buffer) {
+ lfs2_free(lfs2->pcache.buffer);
+ }
+
+ if (!lfs2->cfg->lookahead_buffer) {
+ lfs2_free(lfs2->free.buffer);
+ }
+
+ return 0;
+}
+
+int lfs2_format(lfs2_t *lfs2, const struct lfs2_config *cfg) {
+ LFS2_TRACE("lfs2_format(%p, %p {.context=%p, "
+ ".read=%p, .prog=%p, .erase=%p, .sync=%p, "
+ ".read_size=%"PRIu32", .prog_size=%"PRIu32", "
+ ".block_size=%"PRIu32", .block_count=%"PRIu32", "
+ ".block_cycles=%"PRIu32", .cache_size=%"PRIu32", "
+ ".lookahead_size=%"PRIu32", .read_buffer=%p, "
+ ".prog_buffer=%p, .lookahead_buffer=%p, "
+ ".name_max=%"PRIu32", .file_max=%"PRIu32", "
+ ".attr_max=%"PRIu32"})",
+ (void*)lfs2, (void*)cfg, cfg->context,
+ (void*)(uintptr_t)cfg->read, (void*)(uintptr_t)cfg->prog,
+ (void*)(uintptr_t)cfg->erase, (void*)(uintptr_t)cfg->sync,
+ cfg->read_size, cfg->prog_size, cfg->block_size, cfg->block_count,
+ cfg->block_cycles, cfg->cache_size, cfg->lookahead_size,
+ cfg->read_buffer, cfg->prog_buffer, cfg->lookahead_buffer,
+ cfg->name_max, cfg->file_max, cfg->attr_max);
+ int err = 0;
+ {
+ err = lfs2_init(lfs2, cfg);
+ if (err) {
+ LFS2_TRACE("lfs2_format -> %d", err);
+ return err;
+ }
+
+ // create free lookahead
+ memset(lfs2->free.buffer, 0, lfs2->cfg->lookahead_size);
+ lfs2->free.off = 0;
+ lfs2->free.size = lfs2_min(8*lfs2->cfg->lookahead_size,
+ lfs2->cfg->block_count);
+ lfs2->free.i = 0;
+ lfs2_alloc_ack(lfs2);
+
+ // create root dir
+ lfs2_mdir_t root;
+ err = lfs2_dir_alloc(lfs2, &root);
+ if (err) {
+ goto cleanup;
+ }
+
+ // write one superblock
+ lfs2_superblock_t superblock = {
+ .version = LFS2_DISK_VERSION,
+ .block_size = lfs2->cfg->block_size,
+ .block_count = lfs2->cfg->block_count,
+ .name_max = lfs2->name_max,
+ .file_max = lfs2->file_max,
+ .attr_max = lfs2->attr_max,
+ };
+
+ lfs2_superblock_tole32(&superblock);
+ err = lfs2_dir_commit(lfs2, &root, LFS2_MKATTRS(
+ {LFS2_MKTAG(LFS2_TYPE_CREATE, 0, 0)},
+ {LFS2_MKTAG(LFS2_TYPE_SUPERBLOCK, 0, 8), "littlefs"},
+ {LFS2_MKTAG(LFS2_TYPE_INLINESTRUCT, 0, sizeof(superblock)),
+ &superblock}));
+ if (err) {
+ goto cleanup;
+ }
+
+ // sanity check that fetch works
+ err = lfs2_dir_fetch(lfs2, &root, (const lfs2_block_t[2]){0, 1});
+ if (err) {
+ goto cleanup;
+ }
+
+ // force compaction to prevent accidentally mounting any
+ // older version of littlefs that may live on disk
+ root.erased = false;
+ err = lfs2_dir_commit(lfs2, &root, NULL, 0);
+ if (err) {
+ goto cleanup;
+ }
+ }
+
+cleanup:
+ lfs2_deinit(lfs2);
+ LFS2_TRACE("lfs2_format -> %d", err);
+ return err;
+}
+
+int lfs2_mount(lfs2_t *lfs2, const struct lfs2_config *cfg) {
+ LFS2_TRACE("lfs2_mount(%p, %p {.context=%p, "
+ ".read=%p, .prog=%p, .erase=%p, .sync=%p, "
+ ".read_size=%"PRIu32", .prog_size=%"PRIu32", "
+ ".block_size=%"PRIu32", .block_count=%"PRIu32", "
+ ".block_cycles=%"PRIu32", .cache_size=%"PRIu32", "
+ ".lookahead_size=%"PRIu32", .read_buffer=%p, "
+ ".prog_buffer=%p, .lookahead_buffer=%p, "
+ ".name_max=%"PRIu32", .file_max=%"PRIu32", "
+ ".attr_max=%"PRIu32"})",
+ (void*)lfs2, (void*)cfg, cfg->context,
+ (void*)(uintptr_t)cfg->read, (void*)(uintptr_t)cfg->prog,
+ (void*)(uintptr_t)cfg->erase, (void*)(uintptr_t)cfg->sync,
+ cfg->read_size, cfg->prog_size, cfg->block_size, cfg->block_count,
+ cfg->block_cycles, cfg->cache_size, cfg->lookahead_size,
+ cfg->read_buffer, cfg->prog_buffer, cfg->lookahead_buffer,
+ cfg->name_max, cfg->file_max, cfg->attr_max);
+ int err = lfs2_init(lfs2, cfg);
+ if (err) {
+ LFS2_TRACE("lfs2_mount -> %d", err);
+ return err;
+ }
+
+ // scan directory blocks for superblock and any global updates
+ lfs2_mdir_t dir = {.tail = {0, 1}};
+ lfs2_block_t cycle = 0;
+ while (!lfs2_pair_isnull(dir.tail)) {
+ if (cycle >= lfs2->cfg->block_count/2) {
+ // loop detected
+ err = LFS2_ERR_CORRUPT;
+ goto cleanup;
+ }
+ cycle += 1;
+
+ // fetch next block in tail list
+ lfs2_stag_t tag = lfs2_dir_fetchmatch(lfs2, &dir, dir.tail,
+ LFS2_MKTAG(0x7ff, 0x3ff, 0),
+ LFS2_MKTAG(LFS2_TYPE_SUPERBLOCK, 0, 8),
+ NULL,
+ lfs2_dir_find_match, &(struct lfs2_dir_find_match){
+ lfs2, "littlefs", 8});
+ if (tag < 0) {
+ err = tag;
+ goto cleanup;
+ }
+
+ // has superblock?
+ if (tag && !lfs2_tag_isdelete(tag)) {
+ // update root
+ lfs2->root[0] = dir.pair[0];
+ lfs2->root[1] = dir.pair[1];
+
+ // grab superblock
+ lfs2_superblock_t superblock;
+ tag = lfs2_dir_get(lfs2, &dir, LFS2_MKTAG(0x7ff, 0x3ff, 0),
+ LFS2_MKTAG(LFS2_TYPE_INLINESTRUCT, 0, sizeof(superblock)),
+ &superblock);
+ if (tag < 0) {
+ err = tag;
+ goto cleanup;
+ }
+ lfs2_superblock_fromle32(&superblock);
+
+ // check version
+ uint16_t major_version = (0xffff & (superblock.version >> 16));
+ uint16_t minor_version = (0xffff & (superblock.version >> 0));
+ if ((major_version != LFS2_DISK_VERSION_MAJOR ||
+ minor_version > LFS2_DISK_VERSION_MINOR)) {
+ LFS2_ERROR("Invalid version v%"PRIu16".%"PRIu16,
+ major_version, minor_version);
+ err = LFS2_ERR_INVAL;
+ goto cleanup;
+ }
+
+ // check superblock configuration
+ if (superblock.name_max) {
+ if (superblock.name_max > lfs2->name_max) {
+ LFS2_ERROR("Unsupported name_max (%"PRIu32" > %"PRIu32")",
+ superblock.name_max, lfs2->name_max);
+ err = LFS2_ERR_INVAL;
+ goto cleanup;
+ }
+
+ lfs2->name_max = superblock.name_max;
+ }
+
+ if (superblock.file_max) {
+ if (superblock.file_max > lfs2->file_max) {
+ LFS2_ERROR("Unsupported file_max (%"PRIu32" > %"PRIu32")",
+ superblock.file_max, lfs2->file_max);
+ err = LFS2_ERR_INVAL;
+ goto cleanup;
+ }
+
+ lfs2->file_max = superblock.file_max;
+ }
+
+ if (superblock.attr_max) {
+ if (superblock.attr_max > lfs2->attr_max) {
+ LFS2_ERROR("Unsupported attr_max (%"PRIu32" > %"PRIu32")",
+ superblock.attr_max, lfs2->attr_max);
+ err = LFS2_ERR_INVAL;
+ goto cleanup;
+ }
+
+ lfs2->attr_max = superblock.attr_max;
+ }
+ }
+
+ // has gstate?
+ err = lfs2_dir_getgstate(lfs2, &dir, &lfs2->gstate);
+ if (err) {
+ goto cleanup;
+ }
+ }
+
+ // found superblock?
+ if (lfs2_pair_isnull(lfs2->root)) {
+ err = LFS2_ERR_INVAL;
+ goto cleanup;
+ }
+
+ // update littlefs with gstate
+ if (!lfs2_gstate_iszero(&lfs2->gstate)) {
+ LFS2_DEBUG("Found pending gstate 0x%08"PRIx32"%08"PRIx32"%08"PRIx32,
+ lfs2->gstate.tag,
+ lfs2->gstate.pair[0],
+ lfs2->gstate.pair[1]);
+ }
+ lfs2->gstate.tag += !lfs2_tag_isvalid(lfs2->gstate.tag);
+ lfs2->gdisk = lfs2->gstate;
+
+ // setup free lookahead
+ lfs2_alloc_reset(lfs2);
+
+ LFS2_TRACE("lfs2_mount -> %d", 0);
+ return 0;
+
+cleanup:
+ lfs2_unmount(lfs2);
+ LFS2_TRACE("lfs2_mount -> %d", err);
+ return err;
+}
+
+int lfs2_unmount(lfs2_t *lfs2) {
+ LFS2_TRACE("lfs2_unmount(%p)", (void*)lfs2);
+ int err = lfs2_deinit(lfs2);
+ LFS2_TRACE("lfs2_unmount -> %d", err);
+ return err;
+}
+
+
+/// Filesystem filesystem operations ///
+int lfs2_fs_traverseraw(lfs2_t *lfs2,
+ int (*cb)(void *data, lfs2_block_t block), void *data,
+ bool includeorphans) {
+ // iterate over metadata pairs
+ lfs2_mdir_t dir = {.tail = {0, 1}};
+
+#ifdef LFS2_MIGRATE
+ // also consider v1 blocks during migration
+ if (lfs2->lfs21) {
+ int err = lfs21_traverse(lfs2, cb, data);
+ if (err) {
+ return err;
+ }
+
+ dir.tail[0] = lfs2->root[0];
+ dir.tail[1] = lfs2->root[1];
+ }
+#endif
+
+ lfs2_block_t cycle = 0;
+ while (!lfs2_pair_isnull(dir.tail)) {
+ if (cycle >= lfs2->cfg->block_count/2) {
+ // loop detected
+ return LFS2_ERR_CORRUPT;
+ }
+ cycle += 1;
+
+ for (int i = 0; i < 2; i++) {
+ int err = cb(data, dir.tail[i]);
+ if (err) {
+ return err;
+ }
+ }
+
+ // iterate through ids in directory
+ int err = lfs2_dir_fetch(lfs2, &dir, dir.tail);
+ if (err) {
+ return err;
+ }
+
+ for (uint16_t id = 0; id < dir.count; id++) {
+ struct lfs2_ctz ctz;
+ lfs2_stag_t tag = lfs2_dir_get(lfs2, &dir, LFS2_MKTAG(0x700, 0x3ff, 0),
+ LFS2_MKTAG(LFS2_TYPE_STRUCT, id, sizeof(ctz)), &ctz);
+ if (tag < 0) {
+ if (tag == LFS2_ERR_NOENT) {
+ continue;
+ }
+ return tag;
+ }
+ lfs2_ctz_fromle32(&ctz);
+
+ if (lfs2_tag_type3(tag) == LFS2_TYPE_CTZSTRUCT) {
+ err = lfs2_ctz_traverse(lfs2, NULL, &lfs2->rcache,
+ ctz.head, ctz.size, cb, data);
+ if (err) {
+ return err;
+ }
+ } else if (includeorphans &&
+ lfs2_tag_type3(tag) == LFS2_TYPE_DIRSTRUCT) {
+ for (int i = 0; i < 2; i++) {
+ err = cb(data, (&ctz.head)[i]);
+ if (err) {
+ return err;
+ }
+ }
+ }
+ }
+ }
+
+ // iterate over any open files
+ for (lfs2_file_t *f = (lfs2_file_t*)lfs2->mlist; f; f = f->next) {
+ if (f->type != LFS2_TYPE_REG) {
+ continue;
+ }
+
+ if ((f->flags & LFS2_F_DIRTY) && !(f->flags & LFS2_F_INLINE)) {
+ int err = lfs2_ctz_traverse(lfs2, &f->cache, &lfs2->rcache,
+ f->ctz.head, f->ctz.size, cb, data);
+ if (err) {
+ return err;
+ }
+ }
+
+ if ((f->flags & LFS2_F_WRITING) && !(f->flags & LFS2_F_INLINE)) {
+ int err = lfs2_ctz_traverse(lfs2, &f->cache, &lfs2->rcache,
+ f->block, f->pos, cb, data);
+ if (err) {
+ return err;
+ }
+ }
+ }
+
+ return 0;
+}
+
+int lfs2_fs_traverse(lfs2_t *lfs2,
+ int (*cb)(void *data, lfs2_block_t block), void *data) {
+ LFS2_TRACE("lfs2_fs_traverse(%p, %p, %p)",
+ (void*)lfs2, (void*)(uintptr_t)cb, data);
+ int err = lfs2_fs_traverseraw(lfs2, cb, data, true);
+ LFS2_TRACE("lfs2_fs_traverse -> %d", 0);
+ return err;
+}
+
+static int lfs2_fs_pred(lfs2_t *lfs2,
+ const lfs2_block_t pair[2], lfs2_mdir_t *pdir) {
+ // iterate over all directory directory entries
+ pdir->tail[0] = 0;
+ pdir->tail[1] = 1;
+ lfs2_block_t cycle = 0;
+ while (!lfs2_pair_isnull(pdir->tail)) {
+ if (cycle >= lfs2->cfg->block_count/2) {
+ // loop detected
+ return LFS2_ERR_CORRUPT;
+ }
+ cycle += 1;
+
+ if (lfs2_pair_cmp(pdir->tail, pair) == 0) {
+ return 0;
+ }
+
+ int err = lfs2_dir_fetch(lfs2, pdir, pdir->tail);
+ if (err) {
+ return err;
+ }
+ }
+
+ return LFS2_ERR_NOENT;
+}
+
+struct lfs2_fs_parent_match {
+ lfs2_t *lfs2;
+ const lfs2_block_t pair[2];
+};
+
+static int lfs2_fs_parent_match(void *data,
+ lfs2_tag_t tag, const void *buffer) {
+ struct lfs2_fs_parent_match *find = data;
+ lfs2_t *lfs2 = find->lfs2;
+ const struct lfs2_diskoff *disk = buffer;
+ (void)tag;
+
+ lfs2_block_t child[2];
+ int err = lfs2_bd_read(lfs2,
+ &lfs2->pcache, &lfs2->rcache, lfs2->cfg->block_size,
+ disk->block, disk->off, &child, sizeof(child));
+ if (err) {
+ return err;
+ }
+
+ lfs2_pair_fromle32(child);
+ return (lfs2_pair_cmp(child, find->pair) == 0) ? LFS2_CMP_EQ : LFS2_CMP_LT;
+}
+
+static lfs2_stag_t lfs2_fs_parent(lfs2_t *lfs2, const lfs2_block_t pair[2],
+ lfs2_mdir_t *parent) {
+ // use fetchmatch with callback to find pairs
+ parent->tail[0] = 0;
+ parent->tail[1] = 1;
+ lfs2_block_t cycle = 0;
+ while (!lfs2_pair_isnull(parent->tail)) {
+ if (cycle >= lfs2->cfg->block_count/2) {
+ // loop detected
+ return LFS2_ERR_CORRUPT;
+ }
+ cycle += 1;
+
+ lfs2_stag_t tag = lfs2_dir_fetchmatch(lfs2, parent, parent->tail,
+ LFS2_MKTAG(0x7ff, 0, 0x3ff),
+ LFS2_MKTAG(LFS2_TYPE_DIRSTRUCT, 0, 8),
+ NULL,
+ lfs2_fs_parent_match, &(struct lfs2_fs_parent_match){
+ lfs2, {pair[0], pair[1]}});
+ if (tag && tag != LFS2_ERR_NOENT) {
+ return tag;
+ }
+ }
+
+ return LFS2_ERR_NOENT;
+}
+
+static int lfs2_fs_relocate(lfs2_t *lfs2,
+ const lfs2_block_t oldpair[2], lfs2_block_t newpair[2]) {
+ // update internal root
+ if (lfs2_pair_cmp(oldpair, lfs2->root) == 0) {
+ lfs2->root[0] = newpair[0];
+ lfs2->root[1] = newpair[1];
+ }
+
+ // update internally tracked dirs
+ for (struct lfs2_mlist *d = lfs2->mlist; d; d = d->next) {
+ if (lfs2_pair_cmp(oldpair, d->m.pair) == 0) {
+ d->m.pair[0] = newpair[0];
+ d->m.pair[1] = newpair[1];
+ }
+
+ if (d->type == LFS2_TYPE_DIR &&
+ lfs2_pair_cmp(oldpair, ((lfs2_dir_t*)d)->head) == 0) {
+ ((lfs2_dir_t*)d)->head[0] = newpair[0];
+ ((lfs2_dir_t*)d)->head[1] = newpair[1];
+ }
+ }
+
+ // find parent
+ lfs2_mdir_t parent;
+ lfs2_stag_t tag = lfs2_fs_parent(lfs2, oldpair, &parent);
+ if (tag < 0 && tag != LFS2_ERR_NOENT) {
+ return tag;
+ }
+
+ if (tag != LFS2_ERR_NOENT) {
+ // update disk, this creates a desync
+ lfs2_fs_preporphans(lfs2, +1);
+
+ // fix pending move in this pair? this looks like an optimization but
+ // is in fact _required_ since relocating may outdate the move.
+ uint16_t moveid = 0x3ff;
+ if (lfs2_gstate_hasmovehere(&lfs2->gstate, parent.pair)) {
+ moveid = lfs2_tag_id(lfs2->gstate.tag);
+ LFS2_DEBUG("Fixing move while relocating "
+ "{0x%"PRIx32", 0x%"PRIx32"} 0x%"PRIx16"\n",
+ parent.pair[0], parent.pair[1], moveid);
+ lfs2_fs_prepmove(lfs2, 0x3ff, NULL);
+ if (moveid < lfs2_tag_id(tag)) {
+ tag -= LFS2_MKTAG(0, 1, 0);
+ }
+ }
+
+ lfs2_pair_tole32(newpair);
+ int err = lfs2_dir_commit(lfs2, &parent, LFS2_MKATTRS(
+ {LFS2_MKTAG_IF(moveid != 0x3ff,
+ LFS2_TYPE_DELETE, moveid, 0)},
+ {tag, newpair}));
+ lfs2_pair_fromle32(newpair);
+ if (err) {
+ return err;
+ }
+
+ // next step, clean up orphans
+ lfs2_fs_preporphans(lfs2, -1);
+ }
+
+ // find pred
+ int err = lfs2_fs_pred(lfs2, oldpair, &parent);
+ if (err && err != LFS2_ERR_NOENT) {
+ return err;
+ }
+
+ // if we can't find dir, it must be new
+ if (err != LFS2_ERR_NOENT) {
+ // fix pending move in this pair? this looks like an optimization but
+ // is in fact _required_ since relocating may outdate the move.
+ uint16_t moveid = 0x3ff;
+ if (lfs2_gstate_hasmovehere(&lfs2->gstate, parent.pair)) {
+ moveid = lfs2_tag_id(lfs2->gstate.tag);
+ LFS2_DEBUG("Fixing move while relocating "
+ "{0x%"PRIx32", 0x%"PRIx32"} 0x%"PRIx16"\n",
+ parent.pair[0], parent.pair[1], moveid);
+ lfs2_fs_prepmove(lfs2, 0x3ff, NULL);
+ }
+
+ // replace bad pair, either we clean up desync, or no desync occured
+ lfs2_pair_tole32(newpair);
+ err = lfs2_dir_commit(lfs2, &parent, LFS2_MKATTRS(
+ {LFS2_MKTAG_IF(moveid != 0x3ff,
+ LFS2_TYPE_DELETE, moveid, 0)},
+ {LFS2_MKTAG(LFS2_TYPE_TAIL + parent.split, 0x3ff, 8), newpair}));
+ lfs2_pair_fromle32(newpair);
+ if (err) {
+ return err;
+ }
+ }
+
+ return 0;
+}
+
+static void lfs2_fs_preporphans(lfs2_t *lfs2, int8_t orphans) {
+ LFS2_ASSERT(lfs2_tag_size(lfs2->gstate.tag) > 0 || orphans >= 0);
+ lfs2->gstate.tag += orphans;
+ lfs2->gstate.tag = ((lfs2->gstate.tag & ~LFS2_MKTAG(0x800, 0, 0)) |
+ ((uint32_t)lfs2_gstate_hasorphans(&lfs2->gstate) << 31));
+}
+
+static void lfs2_fs_prepmove(lfs2_t *lfs2,
+ uint16_t id, const lfs2_block_t pair[2]) {
+ lfs2->gstate.tag = ((lfs2->gstate.tag & ~LFS2_MKTAG(0x7ff, 0x3ff, 0)) |
+ ((id != 0x3ff) ? LFS2_MKTAG(LFS2_TYPE_DELETE, id, 0) : 0));
+ lfs2->gstate.pair[0] = (id != 0x3ff) ? pair[0] : 0;
+ lfs2->gstate.pair[1] = (id != 0x3ff) ? pair[1] : 0;
+}
+
+static int lfs2_fs_demove(lfs2_t *lfs2) {
+ if (!lfs2_gstate_hasmove(&lfs2->gdisk)) {
+ return 0;
+ }
+
+ // Fix bad moves
+ LFS2_DEBUG("Fixing move {0x%"PRIx32", 0x%"PRIx32"} 0x%"PRIx16,
+ lfs2->gdisk.pair[0],
+ lfs2->gdisk.pair[1],
+ lfs2_tag_id(lfs2->gdisk.tag));
+
+ // fetch and delete the moved entry
+ lfs2_mdir_t movedir;
+ int err = lfs2_dir_fetch(lfs2, &movedir, lfs2->gdisk.pair);
+ if (err) {
+ return err;
+ }
+
+ // prep gstate and delete move id
+ uint16_t moveid = lfs2_tag_id(lfs2->gdisk.tag);
+ lfs2_fs_prepmove(lfs2, 0x3ff, NULL);
+ err = lfs2_dir_commit(lfs2, &movedir, LFS2_MKATTRS(
+ {LFS2_MKTAG(LFS2_TYPE_DELETE, moveid, 0)}));
+ if (err) {
+ return err;
+ }
+
+ return 0;
+}
+
+static int lfs2_fs_deorphan(lfs2_t *lfs2) {
+ if (!lfs2_gstate_hasorphans(&lfs2->gstate)) {
+ return 0;
+ }
+
+ // Fix any orphans
+ lfs2_mdir_t pdir = {.split = true, .tail = {0, 1}};
+ lfs2_mdir_t dir;
+
+ // iterate over all directory directory entries
+ while (!lfs2_pair_isnull(pdir.tail)) {
+ int err = lfs2_dir_fetch(lfs2, &dir, pdir.tail);
+ if (err) {
+ return err;
+ }
+
+ // check head blocks for orphans
+ if (!pdir.split) {
+ // check if we have a parent
+ lfs2_mdir_t parent;
+ lfs2_stag_t tag = lfs2_fs_parent(lfs2, pdir.tail, &parent);
+ if (tag < 0 && tag != LFS2_ERR_NOENT) {
+ return tag;
+ }
+
+ if (tag == LFS2_ERR_NOENT) {
+ // we are an orphan
+ LFS2_DEBUG("Fixing orphan {0x%"PRIx32", 0x%"PRIx32"}",
+ pdir.tail[0], pdir.tail[1]);
+
+ err = lfs2_dir_drop(lfs2, &pdir, &dir);
+ if (err) {
+ return err;
+ }
+
+ // refetch tail
+ continue;
+ }
+
+ lfs2_block_t pair[2];
+ lfs2_stag_t res = lfs2_dir_get(lfs2, &parent,
+ LFS2_MKTAG(0x7ff, 0x3ff, 0), tag, pair);
+ if (res < 0) {
+ return res;
+ }
+ lfs2_pair_fromle32(pair);
+
+ if (!lfs2_pair_sync(pair, pdir.tail)) {
+ // we have desynced
+ LFS2_DEBUG("Fixing half-orphan {0x%"PRIx32", 0x%"PRIx32"} "
+ "-> {0x%"PRIx32", 0x%"PRIx32"}",
+ pdir.tail[0], pdir.tail[1], pair[0], pair[1]);
+
+ lfs2_pair_tole32(pair);
+ err = lfs2_dir_commit(lfs2, &pdir, LFS2_MKATTRS(
+ {LFS2_MKTAG(LFS2_TYPE_SOFTTAIL, 0x3ff, 8), pair}));
+ lfs2_pair_fromle32(pair);
+ if (err) {
+ return err;
+ }
+
+ // refetch tail
+ continue;
+ }
+ }
+
+ pdir = dir;
+ }
+
+ // mark orphans as fixed
+ lfs2_fs_preporphans(lfs2, -lfs2_gstate_getorphans(&lfs2->gstate));
+ return 0;
+}
+
+static int lfs2_fs_forceconsistency(lfs2_t *lfs2) {
+ int err = lfs2_fs_demove(lfs2);
+ if (err) {
+ return err;
+ }
+
+ err = lfs2_fs_deorphan(lfs2);
+ if (err) {
+ return err;
+ }
+
+ return 0;
+}
+
+static int lfs2_fs_size_count(void *p, lfs2_block_t block) {
+ (void)block;
+ lfs2_size_t *size = p;
+ *size += 1;
+ return 0;
+}
+
+lfs2_ssize_t lfs2_fs_size(lfs2_t *lfs2) {
+ LFS2_TRACE("lfs2_fs_size(%p)", (void*)lfs2);
+ lfs2_size_t size = 0;
+ int err = lfs2_fs_traverseraw(lfs2, lfs2_fs_size_count, &size, false);
+ if (err) {
+ LFS2_TRACE("lfs2_fs_size -> %d", err);
+ return err;
+ }
+
+ LFS2_TRACE("lfs2_fs_size -> %d", err);
+ return size;
+}
+
+#ifdef LFS2_MIGRATE
+////// Migration from littelfs v1 below this //////
+
+/// Version info ///
+
+// Software library version
+// Major (top-nibble), incremented on backwards incompatible changes
+// Minor (bottom-nibble), incremented on feature additions
+#define LFS21_VERSION 0x00010007
+#define LFS21_VERSION_MAJOR (0xffff & (LFS21_VERSION >> 16))
+#define LFS21_VERSION_MINOR (0xffff & (LFS21_VERSION >> 0))
+
+// Version of On-disk data structures
+// Major (top-nibble), incremented on backwards incompatible changes
+// Minor (bottom-nibble), incremented on feature additions
+#define LFS21_DISK_VERSION 0x00010001
+#define LFS21_DISK_VERSION_MAJOR (0xffff & (LFS21_DISK_VERSION >> 16))
+#define LFS21_DISK_VERSION_MINOR (0xffff & (LFS21_DISK_VERSION >> 0))
+
+
+/// v1 Definitions ///
+
+// File types
+enum lfs21_type {
+ LFS21_TYPE_REG = 0x11,
+ LFS21_TYPE_DIR = 0x22,
+ LFS21_TYPE_SUPERBLOCK = 0x2e,
+};
+
+typedef struct lfs21 {
+ lfs2_block_t root[2];
+} lfs21_t;
+
+typedef struct lfs21_entry {
+ lfs2_off_t off;
+
+ struct lfs21_disk_entry {
+ uint8_t type;
+ uint8_t elen;
+ uint8_t alen;
+ uint8_t nlen;
+ union {
+ struct {
+ lfs2_block_t head;
+ lfs2_size_t size;
+ } file;
+ lfs2_block_t dir[2];
+ } u;
+ } d;
+} lfs21_entry_t;
+
+typedef struct lfs21_dir {
+ struct lfs21_dir *next;
+ lfs2_block_t pair[2];
+ lfs2_off_t off;
+
+ lfs2_block_t head[2];
+ lfs2_off_t pos;
+
+ struct lfs21_disk_dir {
+ uint32_t rev;
+ lfs2_size_t size;
+ lfs2_block_t tail[2];
+ } d;
+} lfs21_dir_t;
+
+typedef struct lfs21_superblock {
+ lfs2_off_t off;
+
+ struct lfs21_disk_superblock {
+ uint8_t type;
+ uint8_t elen;
+ uint8_t alen;
+ uint8_t nlen;
+ lfs2_block_t root[2];
+ uint32_t block_size;
+ uint32_t block_count;
+ uint32_t version;
+ char magic[8];
+ } d;
+} lfs21_superblock_t;
+
+
+/// Low-level wrappers v1->v2 ///
+static void lfs21_crc(uint32_t *crc, const void *buffer, size_t size) {
+ *crc = lfs2_crc(*crc, buffer, size);
+}
+
+static int lfs21_bd_read(lfs2_t *lfs2, lfs2_block_t block,
+ lfs2_off_t off, void *buffer, lfs2_size_t size) {
+ // if we ever do more than writes to alternating pairs,
+ // this may need to consider pcache
+ return lfs2_bd_read(lfs2, &lfs2->pcache, &lfs2->rcache, size,
+ block, off, buffer, size);
+}
+
+static int lfs21_bd_crc(lfs2_t *lfs2, lfs2_block_t block,
+ lfs2_off_t off, lfs2_size_t size, uint32_t *crc) {
+ for (lfs2_off_t i = 0; i < size; i++) {
+ uint8_t c;
+ int err = lfs21_bd_read(lfs2, block, off+i, &c, 1);
+ if (err) {
+ return err;
+ }
+
+ lfs21_crc(crc, &c, 1);
+ }
+
+ return 0;
+}
+
+
+/// Endian swapping functions ///
+static void lfs21_dir_fromle32(struct lfs21_disk_dir *d) {
+ d->rev = lfs2_fromle32(d->rev);
+ d->size = lfs2_fromle32(d->size);
+ d->tail[0] = lfs2_fromle32(d->tail[0]);
+ d->tail[1] = lfs2_fromle32(d->tail[1]);
+}
+
+static void lfs21_dir_tole32(struct lfs21_disk_dir *d) {
+ d->rev = lfs2_tole32(d->rev);
+ d->size = lfs2_tole32(d->size);
+ d->tail[0] = lfs2_tole32(d->tail[0]);
+ d->tail[1] = lfs2_tole32(d->tail[1]);
+}
+
+static void lfs21_entry_fromle32(struct lfs21_disk_entry *d) {
+ d->u.dir[0] = lfs2_fromle32(d->u.dir[0]);
+ d->u.dir[1] = lfs2_fromle32(d->u.dir[1]);
+}
+
+static void lfs21_entry_tole32(struct lfs21_disk_entry *d) {
+ d->u.dir[0] = lfs2_tole32(d->u.dir[0]);
+ d->u.dir[1] = lfs2_tole32(d->u.dir[1]);
+}
+
+static void lfs21_superblock_fromle32(struct lfs21_disk_superblock *d) {
+ d->root[0] = lfs2_fromle32(d->root[0]);
+ d->root[1] = lfs2_fromle32(d->root[1]);
+ d->block_size = lfs2_fromle32(d->block_size);
+ d->block_count = lfs2_fromle32(d->block_count);
+ d->version = lfs2_fromle32(d->version);
+}
+
+
+///// Metadata pair and directory operations ///
+static inline lfs2_size_t lfs21_entry_size(const lfs21_entry_t *entry) {
+ return 4 + entry->d.elen + entry->d.alen + entry->d.nlen;
+}
+
+static int lfs21_dir_fetch(lfs2_t *lfs2,
+ lfs21_dir_t *dir, const lfs2_block_t pair[2]) {
+ // copy out pair, otherwise may be aliasing dir
+ const lfs2_block_t tpair[2] = {pair[0], pair[1]};
+ bool valid = false;
+
+ // check both blocks for the most recent revision
+ for (int i = 0; i < 2; i++) {
+ struct lfs21_disk_dir test;
+ int err = lfs21_bd_read(lfs2, tpair[i], 0, &test, sizeof(test));
+ lfs21_dir_fromle32(&test);
+ if (err) {
+ if (err == LFS2_ERR_CORRUPT) {
+ continue;
+ }
+ return err;
+ }
+
+ if (valid && lfs2_scmp(test.rev, dir->d.rev) < 0) {
+ continue;
+ }
+
+ if ((0x7fffffff & test.size) < sizeof(test)+4 ||
+ (0x7fffffff & test.size) > lfs2->cfg->block_size) {
+ continue;
+ }
+
+ uint32_t crc = 0xffffffff;
+ lfs21_dir_tole32(&test);
+ lfs21_crc(&crc, &test, sizeof(test));
+ lfs21_dir_fromle32(&test);
+ err = lfs21_bd_crc(lfs2, tpair[i], sizeof(test),
+ (0x7fffffff & test.size) - sizeof(test), &crc);
+ if (err) {
+ if (err == LFS2_ERR_CORRUPT) {
+ continue;
+ }
+ return err;
+ }
+
+ if (crc != 0) {
+ continue;
+ }
+
+ valid = true;
+
+ // setup dir in case it's valid
+ dir->pair[0] = tpair[(i+0) % 2];
+ dir->pair[1] = tpair[(i+1) % 2];
+ dir->off = sizeof(dir->d);
+ dir->d = test;
+ }
+
+ if (!valid) {
+ LFS2_ERROR("Corrupted dir pair at {0x%"PRIx32", 0x%"PRIx32"}",
+ tpair[0], tpair[1]);
+ return LFS2_ERR_CORRUPT;
+ }
+
+ return 0;
+}
+
+static int lfs21_dir_next(lfs2_t *lfs2, lfs21_dir_t *dir, lfs21_entry_t *entry) {
+ while (dir->off + sizeof(entry->d) > (0x7fffffff & dir->d.size)-4) {
+ if (!(0x80000000 & dir->d.size)) {
+ entry->off = dir->off;
+ return LFS2_ERR_NOENT;
+ }
+
+ int err = lfs21_dir_fetch(lfs2, dir, dir->d.tail);
+ if (err) {
+ return err;
+ }
+
+ dir->off = sizeof(dir->d);
+ dir->pos += sizeof(dir->d) + 4;
+ }
+
+ int err = lfs21_bd_read(lfs2, dir->pair[0], dir->off,
+ &entry->d, sizeof(entry->d));
+ lfs21_entry_fromle32(&entry->d);
+ if (err) {
+ return err;
+ }
+
+ entry->off = dir->off;
+ dir->off += lfs21_entry_size(entry);
+ dir->pos += lfs21_entry_size(entry);
+ return 0;
+}
+
+/// littlefs v1 specific operations ///
+int lfs21_traverse(lfs2_t *lfs2, int (*cb)(void*, lfs2_block_t), void *data) {
+ if (lfs2_pair_isnull(lfs2->lfs21->root)) {
+ return 0;
+ }
+
+ // iterate over metadata pairs
+ lfs21_dir_t dir;
+ lfs21_entry_t entry;
+ lfs2_block_t cwd[2] = {0, 1};
+
+ while (true) {
+ for (int i = 0; i < 2; i++) {
+ int err = cb(data, cwd[i]);
+ if (err) {
+ return err;
+ }
+ }
+
+ int err = lfs21_dir_fetch(lfs2, &dir, cwd);
+ if (err) {
+ return err;
+ }
+
+ // iterate over contents
+ while (dir.off + sizeof(entry.d) <= (0x7fffffff & dir.d.size)-4) {
+ err = lfs21_bd_read(lfs2, dir.pair[0], dir.off,
+ &entry.d, sizeof(entry.d));
+ lfs21_entry_fromle32(&entry.d);
+ if (err) {
+ return err;
+ }
+
+ dir.off += lfs21_entry_size(&entry);
+ if ((0x70 & entry.d.type) == (0x70 & LFS21_TYPE_REG)) {
+ err = lfs2_ctz_traverse(lfs2, NULL, &lfs2->rcache,
+ entry.d.u.file.head, entry.d.u.file.size, cb, data);
+ if (err) {
+ return err;
+ }
+ }
+ }
+
+ // we also need to check if we contain a threaded v2 directory
+ lfs2_mdir_t dir2 = {.split=true, .tail={cwd[0], cwd[1]}};
+ while (dir2.split) {
+ err = lfs2_dir_fetch(lfs2, &dir2, dir2.tail);
+ if (err) {
+ break;
+ }
+
+ for (int i = 0; i < 2; i++) {
+ err = cb(data, dir2.pair[i]);
+ if (err) {
+ return err;
+ }
+ }
+ }
+
+ cwd[0] = dir.d.tail[0];
+ cwd[1] = dir.d.tail[1];
+
+ if (lfs2_pair_isnull(cwd)) {
+ break;
+ }
+ }
+
+ return 0;
+}
+
+static int lfs21_moved(lfs2_t *lfs2, const void *e) {
+ if (lfs2_pair_isnull(lfs2->lfs21->root)) {
+ return 0;
+ }
+
+ // skip superblock
+ lfs21_dir_t cwd;
+ int err = lfs21_dir_fetch(lfs2, &cwd, (const lfs2_block_t[2]){0, 1});
+ if (err) {
+ return err;
+ }
+
+ // iterate over all directory directory entries
+ lfs21_entry_t entry;
+ while (!lfs2_pair_isnull(cwd.d.tail)) {
+ err = lfs21_dir_fetch(lfs2, &cwd, cwd.d.tail);
+ if (err) {
+ return err;
+ }
+
+ while (true) {
+ err = lfs21_dir_next(lfs2, &cwd, &entry);
+ if (err && err != LFS2_ERR_NOENT) {
+ return err;
+ }
+
+ if (err == LFS2_ERR_NOENT) {
+ break;
+ }
+
+ if (!(0x80 & entry.d.type) &&
+ memcmp(&entry.d.u, e, sizeof(entry.d.u)) == 0) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+/// Filesystem operations ///
+static int lfs21_mount(lfs2_t *lfs2, struct lfs21 *lfs21,
+ const struct lfs2_config *cfg) {
+ int err = 0;
+ {
+ err = lfs2_init(lfs2, cfg);
+ if (err) {
+ return err;
+ }
+
+ lfs2->lfs21 = lfs21;
+ lfs2->lfs21->root[0] = LFS2_BLOCK_NULL;
+ lfs2->lfs21->root[1] = LFS2_BLOCK_NULL;
+
+ // setup free lookahead
+ lfs2->free.off = 0;
+ lfs2->free.size = 0;
+ lfs2->free.i = 0;
+ lfs2_alloc_ack(lfs2);
+
+ // load superblock
+ lfs21_dir_t dir;
+ lfs21_superblock_t superblock;
+ err = lfs21_dir_fetch(lfs2, &dir, (const lfs2_block_t[2]){0, 1});
+ if (err && err != LFS2_ERR_CORRUPT) {
+ goto cleanup;
+ }
+
+ if (!err) {
+ err = lfs21_bd_read(lfs2, dir.pair[0], sizeof(dir.d),
+ &superblock.d, sizeof(superblock.d));
+ lfs21_superblock_fromle32(&superblock.d);
+ if (err) {
+ goto cleanup;
+ }
+
+ lfs2->lfs21->root[0] = superblock.d.root[0];
+ lfs2->lfs21->root[1] = superblock.d.root[1];
+ }
+
+ if (err || memcmp(superblock.d.magic, "littlefs", 8) != 0) {
+ LFS2_ERROR("Invalid superblock at {0x%"PRIx32", 0x%"PRIx32"}",
+ 0, 1);
+ err = LFS2_ERR_CORRUPT;
+ goto cleanup;
+ }
+
+ uint16_t major_version = (0xffff & (superblock.d.version >> 16));
+ uint16_t minor_version = (0xffff & (superblock.d.version >> 0));
+ if ((major_version != LFS21_DISK_VERSION_MAJOR ||
+ minor_version > LFS21_DISK_VERSION_MINOR)) {
+ LFS2_ERROR("Invalid version v%d.%d", major_version, minor_version);
+ err = LFS2_ERR_INVAL;
+ goto cleanup;
+ }
+
+ return 0;
+ }
+
+cleanup:
+ lfs2_deinit(lfs2);
+ return err;
+}
+
+static int lfs21_unmount(lfs2_t *lfs2) {
+ return lfs2_deinit(lfs2);
+}
+
+/// v1 migration ///
+int lfs2_migrate(lfs2_t *lfs2, const struct lfs2_config *cfg) {
+ LFS2_TRACE("lfs2_migrate(%p, %p {.context=%p, "
+ ".read=%p, .prog=%p, .erase=%p, .sync=%p, "
+ ".read_size=%"PRIu32", .prog_size=%"PRIu32", "
+ ".block_size=%"PRIu32", .block_count=%"PRIu32", "
+ ".block_cycles=%"PRIu32", .cache_size=%"PRIu32", "
+ ".lookahead_size=%"PRIu32", .read_buffer=%p, "
+ ".prog_buffer=%p, .lookahead_buffer=%p, "
+ ".name_max=%"PRIu32", .file_max=%"PRIu32", "
+ ".attr_max=%"PRIu32"})",
+ (void*)lfs2, (void*)cfg, cfg->context,
+ (void*)(uintptr_t)cfg->read, (void*)(uintptr_t)cfg->prog,
+ (void*)(uintptr_t)cfg->erase, (void*)(uintptr_t)cfg->sync,
+ cfg->read_size, cfg->prog_size, cfg->block_size, cfg->block_count,
+ cfg->block_cycles, cfg->cache_size, cfg->lookahead_size,
+ cfg->read_buffer, cfg->prog_buffer, cfg->lookahead_buffer,
+ cfg->name_max, cfg->file_max, cfg->attr_max);
+ struct lfs21 lfs21;
+ int err = lfs21_mount(lfs2, &lfs21, cfg);
+ if (err) {
+ LFS2_TRACE("lfs2_migrate -> %d", err);
+ return err;
+ }
+
+ {
+ // iterate through each directory, copying over entries
+ // into new directory
+ lfs21_dir_t dir1;
+ lfs2_mdir_t dir2;
+ dir1.d.tail[0] = lfs2->lfs21->root[0];
+ dir1.d.tail[1] = lfs2->lfs21->root[1];
+ while (!lfs2_pair_isnull(dir1.d.tail)) {
+ // iterate old dir
+ err = lfs21_dir_fetch(lfs2, &dir1, dir1.d.tail);
+ if (err) {
+ goto cleanup;
+ }
+
+ // create new dir and bind as temporary pretend root
+ err = lfs2_dir_alloc(lfs2, &dir2);
+ if (err) {
+ goto cleanup;
+ }
+
+ dir2.rev = dir1.d.rev;
+ dir1.head[0] = dir1.pair[0];
+ dir1.head[1] = dir1.pair[1];
+ lfs2->root[0] = dir2.pair[0];
+ lfs2->root[1] = dir2.pair[1];
+
+ err = lfs2_dir_commit(lfs2, &dir2, NULL, 0);
+ if (err) {
+ goto cleanup;
+ }
+
+ while (true) {
+ lfs21_entry_t entry1;
+ err = lfs21_dir_next(lfs2, &dir1, &entry1);
+ if (err && err != LFS2_ERR_NOENT) {
+ goto cleanup;
+ }
+
+ if (err == LFS2_ERR_NOENT) {
+ break;
+ }
+
+ // check that entry has not been moved
+ if (entry1.d.type & 0x80) {
+ int moved = lfs21_moved(lfs2, &entry1.d.u);
+ if (moved < 0) {
+ err = moved;
+ goto cleanup;
+ }
+
+ if (moved) {
+ continue;
+ }
+
+ entry1.d.type &= ~0x80;
+ }
+
+ // also fetch name
+ char name[LFS2_NAME_MAX+1];
+ memset(name, 0, sizeof(name));
+ err = lfs21_bd_read(lfs2, dir1.pair[0],
+ entry1.off + 4+entry1.d.elen+entry1.d.alen,
+ name, entry1.d.nlen);
+ if (err) {
+ goto cleanup;
+ }
+
+ bool isdir = (entry1.d.type == LFS21_TYPE_DIR);
+
+ // create entry in new dir
+ err = lfs2_dir_fetch(lfs2, &dir2, lfs2->root);
+ if (err) {
+ goto cleanup;
+ }
+
+ uint16_t id;
+ err = lfs2_dir_find(lfs2, &dir2, &(const char*){name}, &id);
+ if (!(err == LFS2_ERR_NOENT && id != 0x3ff)) {
+ err = (err < 0) ? err : LFS2_ERR_EXIST;
+ goto cleanup;
+ }
+
+ lfs21_entry_tole32(&entry1.d);
+ err = lfs2_dir_commit(lfs2, &dir2, LFS2_MKATTRS(
+ {LFS2_MKTAG(LFS2_TYPE_CREATE, id, 0)},
+ {LFS2_MKTAG_IF_ELSE(isdir,
+ LFS2_TYPE_DIR, id, entry1.d.nlen,
+ LFS2_TYPE_REG, id, entry1.d.nlen),
+ name},
+ {LFS2_MKTAG_IF_ELSE(isdir,
+ LFS2_TYPE_DIRSTRUCT, id, sizeof(entry1.d.u),
+ LFS2_TYPE_CTZSTRUCT, id, sizeof(entry1.d.u)),
+ &entry1.d.u}));
+ lfs21_entry_fromle32(&entry1.d);
+ if (err) {
+ goto cleanup;
+ }
+ }
+
+ if (!lfs2_pair_isnull(dir1.d.tail)) {
+ // find last block and update tail to thread into fs
+ err = lfs2_dir_fetch(lfs2, &dir2, lfs2->root);
+ if (err) {
+ goto cleanup;
+ }
+
+ while (dir2.split) {
+ err = lfs2_dir_fetch(lfs2, &dir2, dir2.tail);
+ if (err) {
+ goto cleanup;
+ }
+ }
+
+ lfs2_pair_tole32(dir2.pair);
+ err = lfs2_dir_commit(lfs2, &dir2, LFS2_MKATTRS(
+ {LFS2_MKTAG(LFS2_TYPE_SOFTTAIL, 0x3ff, 8), dir1.d.tail}));
+ lfs2_pair_fromle32(dir2.pair);
+ if (err) {
+ goto cleanup;
+ }
+ }
+
+ // Copy over first block to thread into fs. Unfortunately
+ // if this fails there is not much we can do.
+ LFS2_DEBUG("Migrating {0x%"PRIx32", 0x%"PRIx32"} "
+ "-> {0x%"PRIx32", 0x%"PRIx32"}",
+ lfs2->root[0], lfs2->root[1], dir1.head[0], dir1.head[1]);
+
+ err = lfs2_bd_erase(lfs2, dir1.head[1]);
+ if (err) {
+ goto cleanup;
+ }
+
+ err = lfs2_dir_fetch(lfs2, &dir2, lfs2->root);
+ if (err) {
+ goto cleanup;
+ }
+
+ for (lfs2_off_t i = 0; i < dir2.off; i++) {
+ uint8_t dat;
+ err = lfs2_bd_read(lfs2,
+ NULL, &lfs2->rcache, dir2.off,
+ dir2.pair[0], i, &dat, 1);
+ if (err) {
+ goto cleanup;
+ }
+
+ err = lfs2_bd_prog(lfs2,
+ &lfs2->pcache, &lfs2->rcache, true,
+ dir1.head[1], i, &dat, 1);
+ if (err) {
+ goto cleanup;
+ }
+ }
+
+ err = lfs2_bd_flush(lfs2, &lfs2->pcache, &lfs2->rcache, true);
+ if (err) {
+ goto cleanup;
+ }
+ }
+
+ // Create new superblock. This marks a successful migration!
+ err = lfs21_dir_fetch(lfs2, &dir1, (const lfs2_block_t[2]){0, 1});
+ if (err) {
+ goto cleanup;
+ }
+
+ dir2.pair[0] = dir1.pair[0];
+ dir2.pair[1] = dir1.pair[1];
+ dir2.rev = dir1.d.rev;
+ dir2.off = sizeof(dir2.rev);
+ dir2.etag = 0xffffffff;
+ dir2.count = 0;
+ dir2.tail[0] = lfs2->lfs21->root[0];
+ dir2.tail[1] = lfs2->lfs21->root[1];
+ dir2.erased = false;
+ dir2.split = true;
+
+ lfs2_superblock_t superblock = {
+ .version = LFS2_DISK_VERSION,
+ .block_size = lfs2->cfg->block_size,
+ .block_count = lfs2->cfg->block_count,
+ .name_max = lfs2->name_max,
+ .file_max = lfs2->file_max,
+ .attr_max = lfs2->attr_max,
+ };
+
+ lfs2_superblock_tole32(&superblock);
+ err = lfs2_dir_commit(lfs2, &dir2, LFS2_MKATTRS(
+ {LFS2_MKTAG(LFS2_TYPE_CREATE, 0, 0)},
+ {LFS2_MKTAG(LFS2_TYPE_SUPERBLOCK, 0, 8), "littlefs"},
+ {LFS2_MKTAG(LFS2_TYPE_INLINESTRUCT, 0, sizeof(superblock)),
+ &superblock}));
+ if (err) {
+ goto cleanup;
+ }
+
+ // sanity check that fetch works
+ err = lfs2_dir_fetch(lfs2, &dir2, (const lfs2_block_t[2]){0, 1});
+ if (err) {
+ goto cleanup;
+ }
+
+ // force compaction to prevent accidentally mounting v1
+ dir2.erased = false;
+ err = lfs2_dir_commit(lfs2, &dir2, NULL, 0);
+ if (err) {
+ goto cleanup;
+ }
+ }
+
+cleanup:
+ lfs21_unmount(lfs2);
+ LFS2_TRACE("lfs2_migrate -> %d", err);
+ return err;
+}
+
+#endif
diff --git a/lib/littlefs/lfs2.h b/lib/littlefs/lfs2.h
new file mode 100644
index 0000000000..c89af79cab
--- /dev/null
+++ b/lib/littlefs/lfs2.h
@@ -0,0 +1,655 @@
+/*
+ * The little filesystem
+ *
+ * Copyright (c) 2017, Arm Limited. All rights reserved.
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef LFS2_H
+#define LFS2_H
+
+#include
+#include
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+
+/// Version info ///
+
+// Software library version
+// Major (top-nibble), incremented on backwards incompatible changes
+// Minor (bottom-nibble), incremented on feature additions
+#define LFS2_VERSION 0x00020002
+#define LFS2_VERSION_MAJOR (0xffff & (LFS2_VERSION >> 16))
+#define LFS2_VERSION_MINOR (0xffff & (LFS2_VERSION >> 0))
+
+// Version of On-disk data structures
+// Major (top-nibble), incremented on backwards incompatible changes
+// Minor (bottom-nibble), incremented on feature additions
+#define LFS2_DISK_VERSION 0x00020000
+#define LFS2_DISK_VERSION_MAJOR (0xffff & (LFS2_DISK_VERSION >> 16))
+#define LFS2_DISK_VERSION_MINOR (0xffff & (LFS2_DISK_VERSION >> 0))
+
+
+/// Definitions ///
+
+// Type definitions
+typedef uint32_t lfs2_size_t;
+typedef uint32_t lfs2_off_t;
+
+typedef int32_t lfs2_ssize_t;
+typedef int32_t lfs2_soff_t;
+
+typedef uint32_t lfs2_block_t;
+
+// Maximum name size in bytes, may be redefined to reduce the size of the
+// info struct. Limited to <= 1022. Stored in superblock and must be
+// respected by other littlefs drivers.
+#ifndef LFS2_NAME_MAX
+#define LFS2_NAME_MAX 255
+#endif
+
+// Maximum size of a file in bytes, may be redefined to limit to support other
+// drivers. Limited on disk to <= 4294967296. However, above 2147483647 the
+// functions lfs2_file_seek, lfs2_file_size, and lfs2_file_tell will return
+// incorrect values due to using signed integers. Stored in superblock and
+// must be respected by other littlefs drivers.
+#ifndef LFS2_FILE_MAX
+#define LFS2_FILE_MAX 2147483647
+#endif
+
+// Maximum size of custom attributes in bytes, may be redefined, but there is
+// no real benefit to using a smaller LFS2_ATTR_MAX. Limited to <= 1022.
+#ifndef LFS2_ATTR_MAX
+#define LFS2_ATTR_MAX 1022
+#endif
+
+// Possible error codes, these are negative to allow
+// valid positive return values
+enum lfs2_error {
+ LFS2_ERR_OK = 0, // No error
+ LFS2_ERR_IO = -5, // Error during device operation
+ LFS2_ERR_CORRUPT = -84, // Corrupted
+ LFS2_ERR_NOENT = -2, // No directory entry
+ LFS2_ERR_EXIST = -17, // Entry already exists
+ LFS2_ERR_NOTDIR = -20, // Entry is not a dir
+ LFS2_ERR_ISDIR = -21, // Entry is a dir
+ LFS2_ERR_NOTEMPTY = -39, // Dir is not empty
+ LFS2_ERR_BADF = -9, // Bad file number
+ LFS2_ERR_FBIG = -27, // File too large
+ LFS2_ERR_INVAL = -22, // Invalid parameter
+ LFS2_ERR_NOSPC = -28, // No space left on device
+ LFS2_ERR_NOMEM = -12, // No more memory available
+ LFS2_ERR_NOATTR = -61, // No data/attr available
+ LFS2_ERR_NAMETOOLONG = -36, // File name too long
+};
+
+// File types
+enum lfs2_type {
+ // file types
+ LFS2_TYPE_REG = 0x001,
+ LFS2_TYPE_DIR = 0x002,
+
+ // internally used types
+ LFS2_TYPE_SPLICE = 0x400,
+ LFS2_TYPE_NAME = 0x000,
+ LFS2_TYPE_STRUCT = 0x200,
+ LFS2_TYPE_USERATTR = 0x300,
+ LFS2_TYPE_FROM = 0x100,
+ LFS2_TYPE_TAIL = 0x600,
+ LFS2_TYPE_GLOBALS = 0x700,
+ LFS2_TYPE_CRC = 0x500,
+
+ // internally used type specializations
+ LFS2_TYPE_CREATE = 0x401,
+ LFS2_TYPE_DELETE = 0x4ff,
+ LFS2_TYPE_SUPERBLOCK = 0x0ff,
+ LFS2_TYPE_DIRSTRUCT = 0x200,
+ LFS2_TYPE_CTZSTRUCT = 0x202,
+ LFS2_TYPE_INLINESTRUCT = 0x201,
+ LFS2_TYPE_SOFTTAIL = 0x600,
+ LFS2_TYPE_HARDTAIL = 0x601,
+ LFS2_TYPE_MOVESTATE = 0x7ff,
+
+ // internal chip sources
+ LFS2_FROM_NOOP = 0x000,
+ LFS2_FROM_MOVE = 0x101,
+ LFS2_FROM_USERATTRS = 0x102,
+};
+
+// File open flags
+enum lfs2_open_flags {
+ // open flags
+ LFS2_O_RDONLY = 1, // Open a file as read only
+ LFS2_O_WRONLY = 2, // Open a file as write only
+ LFS2_O_RDWR = 3, // Open a file as read and write
+ LFS2_O_CREAT = 0x0100, // Create a file if it does not exist
+ LFS2_O_EXCL = 0x0200, // Fail if a file already exists
+ LFS2_O_TRUNC = 0x0400, // Truncate the existing file to zero size
+ LFS2_O_APPEND = 0x0800, // Move to end of file on every write
+
+ // internally used flags
+ LFS2_F_DIRTY = 0x010000, // File does not match storage
+ LFS2_F_WRITING = 0x020000, // File has been written since last flush
+ LFS2_F_READING = 0x040000, // File has been read since last flush
+ LFS2_F_ERRED = 0x080000, // An error occured during write
+ LFS2_F_INLINE = 0x100000, // Currently inlined in directory entry
+ LFS2_F_OPENED = 0x200000, // File has been opened
+};
+
+// File seek flags
+enum lfs2_whence_flags {
+ LFS2_SEEK_SET = 0, // Seek relative to an absolute position
+ LFS2_SEEK_CUR = 1, // Seek relative to the current file position
+ LFS2_SEEK_END = 2, // Seek relative to the end of the file
+};
+
+
+// Configuration provided during initialization of the littlefs
+struct lfs2_config {
+ // Opaque user provided context that can be used to pass
+ // information to the block device operations
+ void *context;
+
+ // Read a region in a block. Negative error codes are propogated
+ // to the user.
+ int (*read)(const struct lfs2_config *c, lfs2_block_t block,
+ lfs2_off_t off, void *buffer, lfs2_size_t size);
+
+ // Program a region in a block. The block must have previously
+ // been erased. Negative error codes are propogated to the user.
+ // May return LFS2_ERR_CORRUPT if the block should be considered bad.
+ int (*prog)(const struct lfs2_config *c, lfs2_block_t block,
+ lfs2_off_t off, const void *buffer, lfs2_size_t size);
+
+ // Erase a block. A block must be erased before being programmed.
+ // The state of an erased block is undefined. Negative error codes
+ // are propogated to the user.
+ // May return LFS2_ERR_CORRUPT if the block should be considered bad.
+ int (*erase)(const struct lfs2_config *c, lfs2_block_t block);
+
+ // Sync the state of the underlying block device. Negative error codes
+ // are propogated to the user.
+ int (*sync)(const struct lfs2_config *c);
+
+ // Minimum size of a block read. All read operations will be a
+ // multiple of this value.
+ lfs2_size_t read_size;
+
+ // Minimum size of a block program. All program operations will be a
+ // multiple of this value.
+ lfs2_size_t prog_size;
+
+ // Size of an erasable block. This does not impact ram consumption and
+ // may be larger than the physical erase size. However, non-inlined files
+ // take up at minimum one block. Must be a multiple of the read
+ // and program sizes.
+ lfs2_size_t block_size;
+
+ // Number of erasable blocks on the device.
+ lfs2_size_t block_count;
+
+ // Number of erase cycles before littlefs evicts metadata logs and moves
+ // the metadata to another block. Suggested values are in the
+ // range 100-1000, with large values having better performance at the cost
+ // of less consistent wear distribution.
+ //
+ // Set to -1 to disable block-level wear-leveling.
+ int32_t block_cycles;
+
+ // Size of block caches. Each cache buffers a portion of a block in RAM.
+ // The littlefs needs a read cache, a program cache, and one additional
+ // cache per file. Larger caches can improve performance by storing more
+ // data and reducing the number of disk accesses. Must be a multiple of
+ // the read and program sizes, and a factor of the block size.
+ lfs2_size_t cache_size;
+
+ // Size of the lookahead buffer in bytes. A larger lookahead buffer
+ // increases the number of blocks found during an allocation pass. The
+ // lookahead buffer is stored as a compact bitmap, so each byte of RAM
+ // can track 8 blocks. Must be a multiple of 8.
+ lfs2_size_t lookahead_size;
+
+ // Optional statically allocated read buffer. Must be cache_size.
+ // By default lfs2_malloc is used to allocate this buffer.
+ void *read_buffer;
+
+ // Optional statically allocated program buffer. Must be cache_size.
+ // By default lfs2_malloc is used to allocate this buffer.
+ void *prog_buffer;
+
+ // Optional statically allocated lookahead buffer. Must be lookahead_size
+ // and aligned to a 32-bit boundary. By default lfs2_malloc is used to
+ // allocate this buffer.
+ void *lookahead_buffer;
+
+ // Optional upper limit on length of file names in bytes. No downside for
+ // larger names except the size of the info struct which is controlled by
+ // the LFS2_NAME_MAX define. Defaults to LFS2_NAME_MAX when zero. Stored in
+ // superblock and must be respected by other littlefs drivers.
+ lfs2_size_t name_max;
+
+ // Optional upper limit on files in bytes. No downside for larger files
+ // but must be <= LFS2_FILE_MAX. Defaults to LFS2_FILE_MAX when zero. Stored
+ // in superblock and must be respected by other littlefs drivers.
+ lfs2_size_t file_max;
+
+ // Optional upper limit on custom attributes in bytes. No downside for
+ // larger attributes size but must be <= LFS2_ATTR_MAX. Defaults to
+ // LFS2_ATTR_MAX when zero.
+ lfs2_size_t attr_max;
+};
+
+// File info structure
+struct lfs2_info {
+ // Type of the file, either LFS2_TYPE_REG or LFS2_TYPE_DIR
+ uint8_t type;
+
+ // Size of the file, only valid for REG files. Limited to 32-bits.
+ lfs2_size_t size;
+
+ // Name of the file stored as a null-terminated string. Limited to
+ // LFS2_NAME_MAX+1, which can be changed by redefining LFS2_NAME_MAX to
+ // reduce RAM. LFS2_NAME_MAX is stored in superblock and must be
+ // respected by other littlefs drivers.
+ char name[LFS2_NAME_MAX+1];
+};
+
+// Custom attribute structure, used to describe custom attributes
+// committed atomically during file writes.
+struct lfs2_attr {
+ // 8-bit type of attribute, provided by user and used to
+ // identify the attribute
+ uint8_t type;
+
+ // Pointer to buffer containing the attribute
+ void *buffer;
+
+ // Size of attribute in bytes, limited to LFS2_ATTR_MAX
+ lfs2_size_t size;
+};
+
+// Optional configuration provided during lfs2_file_opencfg
+struct lfs2_file_config {
+ // Optional statically allocated file buffer. Must be cache_size.
+ // By default lfs2_malloc is used to allocate this buffer.
+ void *buffer;
+
+ // Optional list of custom attributes related to the file. If the file
+ // is opened with read access, these attributes will be read from disk
+ // during the open call. If the file is opened with write access, the
+ // attributes will be written to disk every file sync or close. This
+ // write occurs atomically with update to the file's contents.
+ //
+ // Custom attributes are uniquely identified by an 8-bit type and limited
+ // to LFS2_ATTR_MAX bytes. When read, if the stored attribute is smaller
+ // than the buffer, it will be padded with zeros. If the stored attribute
+ // is larger, then it will be silently truncated. If the attribute is not
+ // found, it will be created implicitly.
+ struct lfs2_attr *attrs;
+
+ // Number of custom attributes in the list
+ lfs2_size_t attr_count;
+};
+
+
+/// internal littlefs data structures ///
+typedef struct lfs2_cache {
+ lfs2_block_t block;
+ lfs2_off_t off;
+ lfs2_size_t size;
+ uint8_t *buffer;
+} lfs2_cache_t;
+
+typedef struct lfs2_mdir {
+ lfs2_block_t pair[2];
+ uint32_t rev;
+ lfs2_off_t off;
+ uint32_t etag;
+ uint16_t count;
+ bool erased;
+ bool split;
+ lfs2_block_t tail[2];
+} lfs2_mdir_t;
+
+// littlefs directory type
+typedef struct lfs2_dir {
+ struct lfs2_dir *next;
+ uint16_t id;
+ uint8_t type;
+ lfs2_mdir_t m;
+
+ lfs2_off_t pos;
+ lfs2_block_t head[2];
+} lfs2_dir_t;
+
+// littlefs file type
+typedef struct lfs2_file {
+ struct lfs2_file *next;
+ uint16_t id;
+ uint8_t type;
+ lfs2_mdir_t m;
+
+ struct lfs2_ctz {
+ lfs2_block_t head;
+ lfs2_size_t size;
+ } ctz;
+
+ uint32_t flags;
+ lfs2_off_t pos;
+ lfs2_block_t block;
+ lfs2_off_t off;
+ lfs2_cache_t cache;
+
+ const struct lfs2_file_config *cfg;
+} lfs2_file_t;
+
+typedef struct lfs2_superblock {
+ uint32_t version;
+ lfs2_size_t block_size;
+ lfs2_size_t block_count;
+ lfs2_size_t name_max;
+ lfs2_size_t file_max;
+ lfs2_size_t attr_max;
+} lfs2_superblock_t;
+
+typedef struct lfs2_gstate {
+ uint32_t tag;
+ lfs2_block_t pair[2];
+} lfs2_gstate_t;
+
+// The littlefs filesystem type
+typedef struct lfs2 {
+ lfs2_cache_t rcache;
+ lfs2_cache_t pcache;
+
+ lfs2_block_t root[2];
+ struct lfs2_mlist {
+ struct lfs2_mlist *next;
+ uint16_t id;
+ uint8_t type;
+ lfs2_mdir_t m;
+ } *mlist;
+ uint32_t seed;
+
+ lfs2_gstate_t gstate;
+ lfs2_gstate_t gdisk;
+ lfs2_gstate_t gdelta;
+
+ struct lfs2_free {
+ lfs2_block_t off;
+ lfs2_block_t size;
+ lfs2_block_t i;
+ lfs2_block_t ack;
+ uint32_t *buffer;
+ } free;
+
+ const struct lfs2_config *cfg;
+ lfs2_size_t name_max;
+ lfs2_size_t file_max;
+ lfs2_size_t attr_max;
+
+#ifdef LFS2_MIGRATE
+ struct lfs21 *lfs21;
+#endif
+} lfs2_t;
+
+
+/// Filesystem functions ///
+
+// Format a block device with the littlefs
+//
+// Requires a littlefs object and config struct. This clobbers the littlefs
+// object, and does not leave the filesystem mounted. The config struct must
+// be zeroed for defaults and backwards compatibility.
+//
+// Returns a negative error code on failure.
+int lfs2_format(lfs2_t *lfs2, const struct lfs2_config *config);
+
+// Mounts a littlefs
+//
+// Requires a littlefs object and config struct. Multiple filesystems
+// may be mounted simultaneously with multiple littlefs objects. Both
+// lfs2 and config must be allocated while mounted. The config struct must
+// be zeroed for defaults and backwards compatibility.
+//
+// Returns a negative error code on failure.
+int lfs2_mount(lfs2_t *lfs2, const struct lfs2_config *config);
+
+// Unmounts a littlefs
+//
+// Does nothing besides releasing any allocated resources.
+// Returns a negative error code on failure.
+int lfs2_unmount(lfs2_t *lfs2);
+
+/// General operations ///
+
+// Removes a file or directory
+//
+// If removing a directory, the directory must be empty.
+// Returns a negative error code on failure.
+int lfs2_remove(lfs2_t *lfs2, const char *path);
+
+// Rename or move a file or directory
+//
+// If the destination exists, it must match the source in type.
+// If the destination is a directory, the directory must be empty.
+//
+// Returns a negative error code on failure.
+int lfs2_rename(lfs2_t *lfs2, const char *oldpath, const char *newpath);
+
+// Find info about a file or directory
+//
+// Fills out the info structure, based on the specified file or directory.
+// Returns a negative error code on failure.
+int lfs2_stat(lfs2_t *lfs2, const char *path, struct lfs2_info *info);
+
+// Get a custom attribute
+//
+// Custom attributes are uniquely identified by an 8-bit type and limited
+// to LFS2_ATTR_MAX bytes. When read, if the stored attribute is smaller than
+// the buffer, it will be padded with zeros. If the stored attribute is larger,
+// then it will be silently truncated. If no attribute is found, the error
+// LFS2_ERR_NOATTR is returned and the buffer is filled with zeros.
+//
+// Returns the size of the attribute, or a negative error code on failure.
+// Note, the returned size is the size of the attribute on disk, irrespective
+// of the size of the buffer. This can be used to dynamically allocate a buffer
+// or check for existance.
+lfs2_ssize_t lfs2_getattr(lfs2_t *lfs2, const char *path,
+ uint8_t type, void *buffer, lfs2_size_t size);
+
+// Set custom attributes
+//
+// Custom attributes are uniquely identified by an 8-bit type and limited
+// to LFS2_ATTR_MAX bytes. If an attribute is not found, it will be
+// implicitly created.
+//
+// Returns a negative error code on failure.
+int lfs2_setattr(lfs2_t *lfs2, const char *path,
+ uint8_t type, const void *buffer, lfs2_size_t size);
+
+// Removes a custom attribute
+//
+// If an attribute is not found, nothing happens.
+//
+// Returns a negative error code on failure.
+int lfs2_removeattr(lfs2_t *lfs2, const char *path, uint8_t type);
+
+
+/// File operations ///
+
+// Open a file
+//
+// The mode that the file is opened in is determined by the flags, which
+// are values from the enum lfs2_open_flags that are bitwise-ored together.
+//
+// Returns a negative error code on failure.
+int lfs2_file_open(lfs2_t *lfs2, lfs2_file_t *file,
+ const char *path, int flags);
+
+// Open a file with extra configuration
+//
+// The mode that the file is opened in is determined by the flags, which
+// are values from the enum lfs2_open_flags that are bitwise-ored together.
+//
+// The config struct provides additional config options per file as described
+// above. The config struct must be allocated while the file is open, and the
+// config struct must be zeroed for defaults and backwards compatibility.
+//
+// Returns a negative error code on failure.
+int lfs2_file_opencfg(lfs2_t *lfs2, lfs2_file_t *file,
+ const char *path, int flags,
+ const struct lfs2_file_config *config);
+
+// Close a file
+//
+// Any pending writes are written out to storage as though
+// sync had been called and releases any allocated resources.
+//
+// Returns a negative error code on failure.
+int lfs2_file_close(lfs2_t *lfs2, lfs2_file_t *file);
+
+// Synchronize a file on storage
+//
+// Any pending writes are written out to storage.
+// Returns a negative error code on failure.
+int lfs2_file_sync(lfs2_t *lfs2, lfs2_file_t *file);
+
+// Read data from file
+//
+// Takes a buffer and size indicating where to store the read data.
+// Returns the number of bytes read, or a negative error code on failure.
+lfs2_ssize_t lfs2_file_read(lfs2_t *lfs2, lfs2_file_t *file,
+ void *buffer, lfs2_size_t size);
+
+// Write data to file
+//
+// Takes a buffer and size indicating the data to write. The file will not
+// actually be updated on the storage until either sync or close is called.
+//
+// Returns the number of bytes written, or a negative error code on failure.
+lfs2_ssize_t lfs2_file_write(lfs2_t *lfs2, lfs2_file_t *file,
+ const void *buffer, lfs2_size_t size);
+
+// Change the position of the file
+//
+// The change in position is determined by the offset and whence flag.
+// Returns the new position of the file, or a negative error code on failure.
+lfs2_soff_t lfs2_file_seek(lfs2_t *lfs2, lfs2_file_t *file,
+ lfs2_soff_t off, int whence);
+
+// Truncates the size of the file to the specified size
+//
+// Returns a negative error code on failure.
+int lfs2_file_truncate(lfs2_t *lfs2, lfs2_file_t *file, lfs2_off_t size);
+
+// Return the position of the file
+//
+// Equivalent to lfs2_file_seek(lfs2, file, 0, LFS2_SEEK_CUR)
+// Returns the position of the file, or a negative error code on failure.
+lfs2_soff_t lfs2_file_tell(lfs2_t *lfs2, lfs2_file_t *file);
+
+// Change the position of the file to the beginning of the file
+//
+// Equivalent to lfs2_file_seek(lfs2, file, 0, LFS2_SEEK_SET)
+// Returns a negative error code on failure.
+int lfs2_file_rewind(lfs2_t *lfs2, lfs2_file_t *file);
+
+// Return the size of the file
+//
+// Similar to lfs2_file_seek(lfs2, file, 0, LFS2_SEEK_END)
+// Returns the size of the file, or a negative error code on failure.
+lfs2_soff_t lfs2_file_size(lfs2_t *lfs2, lfs2_file_t *file);
+
+
+/// Directory operations ///
+
+// Create a directory
+//
+// Returns a negative error code on failure.
+int lfs2_mkdir(lfs2_t *lfs2, const char *path);
+
+// Open a directory
+//
+// Once open a directory can be used with read to iterate over files.
+// Returns a negative error code on failure.
+int lfs2_dir_open(lfs2_t *lfs2, lfs2_dir_t *dir, const char *path);
+
+// Close a directory
+//
+// Releases any allocated resources.
+// Returns a negative error code on failure.
+int lfs2_dir_close(lfs2_t *lfs2, lfs2_dir_t *dir);
+
+// Read an entry in the directory
+//
+// Fills out the info structure, based on the specified file or directory.
+// Returns a positive value on success, 0 at the end of directory,
+// or a negative error code on failure.
+int lfs2_dir_read(lfs2_t *lfs2, lfs2_dir_t *dir, struct lfs2_info *info);
+
+// Change the position of the directory
+//
+// The new off must be a value previous returned from tell and specifies
+// an absolute offset in the directory seek.
+//
+// Returns a negative error code on failure.
+int lfs2_dir_seek(lfs2_t *lfs2, lfs2_dir_t *dir, lfs2_off_t off);
+
+// Return the position of the directory
+//
+// The returned offset is only meant to be consumed by seek and may not make
+// sense, but does indicate the current position in the directory iteration.
+//
+// Returns the position of the directory, or a negative error code on failure.
+lfs2_soff_t lfs2_dir_tell(lfs2_t *lfs2, lfs2_dir_t *dir);
+
+// Change the position of the directory to the beginning of the directory
+//
+// Returns a negative error code on failure.
+int lfs2_dir_rewind(lfs2_t *lfs2, lfs2_dir_t *dir);
+
+
+/// Filesystem-level filesystem operations
+
+// Finds the current size of the filesystem
+//
+// Note: Result is best effort. If files share COW structures, the returned
+// size may be larger than the filesystem actually is.
+//
+// Returns the number of allocated blocks, or a negative error code on failure.
+lfs2_ssize_t lfs2_fs_size(lfs2_t *lfs2);
+
+// Traverse through all blocks in use by the filesystem
+//
+// The provided callback will be called with each block address that is
+// currently in use by the filesystem. This can be used to determine which
+// blocks are in use or how much of the storage is available.
+//
+// Returns a negative error code on failure.
+int lfs2_fs_traverse(lfs2_t *lfs2, int (*cb)(void*, lfs2_block_t), void *data);
+
+#ifdef LFS2_MIGRATE
+// Attempts to migrate a previous version of littlefs
+//
+// Behaves similarly to the lfs2_format function. Attempts to mount
+// the previous version of littlefs and update the filesystem so it can be
+// mounted with the current version of littlefs.
+//
+// Requires a littlefs object and config struct. This clobbers the littlefs
+// object, and does not leave the filesystem mounted. The config struct must
+// be zeroed for defaults and backwards compatibility.
+//
+// Returns a negative error code on failure.
+int lfs2_migrate(lfs2_t *lfs2, const struct lfs2_config *cfg);
+#endif
+
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif
diff --git a/lib/littlefs/lfs2_util.c b/lib/littlefs/lfs2_util.c
new file mode 100644
index 0000000000..083a99c36c
--- /dev/null
+++ b/lib/littlefs/lfs2_util.c
@@ -0,0 +1,33 @@
+/*
+ * lfs2 util functions
+ *
+ * Copyright (c) 2017, Arm Limited. All rights reserved.
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include "lfs2_util.h"
+
+// Only compile if user does not provide custom config
+#ifndef LFS2_CONFIG
+
+
+// Software CRC implementation with small lookup table
+uint32_t lfs2_crc(uint32_t crc, const void *buffer, size_t size) {
+ static const uint32_t rtable[16] = {
+ 0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,
+ 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
+ 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
+ 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c,
+ };
+
+ const uint8_t *data = buffer;
+
+ for (size_t i = 0; i < size; i++) {
+ crc = (crc >> 4) ^ rtable[(crc ^ (data[i] >> 0)) & 0xf];
+ crc = (crc >> 4) ^ rtable[(crc ^ (data[i] >> 4)) & 0xf];
+ }
+
+ return crc;
+}
+
+
+#endif
diff --git a/lib/littlefs/lfs2_util.h b/lib/littlefs/lfs2_util.h
new file mode 100644
index 0000000000..70bca717c9
--- /dev/null
+++ b/lib/littlefs/lfs2_util.h
@@ -0,0 +1,234 @@
+/*
+ * lfs2 utility functions
+ *
+ * Copyright (c) 2017, Arm Limited. All rights reserved.
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef LFS2_UTIL_H
+#define LFS2_UTIL_H
+
+// Users can override lfs2_util.h with their own configuration by defining
+// LFS2_CONFIG as a header file to include (-DLFS2_CONFIG=lfs2_config.h).
+//
+// If LFS2_CONFIG is used, none of the default utils will be emitted and must be
+// provided by the config file. To start, I would suggest copying lfs2_util.h
+// and modifying as needed.
+#ifdef LFS2_CONFIG
+#define LFS2_STRINGIZE(x) LFS2_STRINGIZE2(x)
+#define LFS2_STRINGIZE2(x) #x
+#include LFS2_STRINGIZE(LFS2_CONFIG)
+#else
+
+// System includes
+#include
+#include
+#include
+#include
+
+#ifndef LFS2_NO_MALLOC
+#include
+#endif
+#ifndef LFS2_NO_ASSERT
+#include
+#endif
+#if !defined(LFS2_NO_DEBUG) || \
+ !defined(LFS2_NO_WARN) || \
+ !defined(LFS2_NO_ERROR) || \
+ defined(LFS2_YES_TRACE)
+#include
+#endif
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+
+// Macros, may be replaced by system specific wrappers. Arguments to these
+// macros must not have side-effects as the macros can be removed for a smaller
+// code footprint
+
+// Logging functions
+#ifdef LFS2_YES_TRACE
+#define LFS2_TRACE_(fmt, ...) \
+ printf("%s:%d:trace: " fmt "%s\n", __FILE__, __LINE__, __VA_ARGS__)
+#define LFS2_TRACE(...) LFS2_TRACE_(__VA_ARGS__, "")
+#else
+#define LFS2_TRACE(...)
+#endif
+
+#ifndef LFS2_NO_DEBUG
+#define LFS2_DEBUG_(fmt, ...) \
+ printf("%s:%d:debug: " fmt "%s\n", __FILE__, __LINE__, __VA_ARGS__)
+#define LFS2_DEBUG(...) LFS2_DEBUG_(__VA_ARGS__, "")
+#else
+#define LFS2_DEBUG(...)
+#endif
+
+#ifndef LFS2_NO_WARN
+#define LFS2_WARN_(fmt, ...) \
+ printf("%s:%d:warn: " fmt "%s\n", __FILE__, __LINE__, __VA_ARGS__)
+#define LFS2_WARN(...) LFS2_WARN_(__VA_ARGS__, "")
+#else
+#define LFS2_WARN(...)
+#endif
+
+#ifndef LFS2_NO_ERROR
+#define LFS2_ERROR_(fmt, ...) \
+ printf("%s:%d:error: " fmt "%s\n", __FILE__, __LINE__, __VA_ARGS__)
+#define LFS2_ERROR(...) LFS2_ERROR_(__VA_ARGS__, "")
+#else
+#define LFS2_ERROR(...)
+#endif
+
+// Runtime assertions
+#ifndef LFS2_NO_ASSERT
+#define LFS2_ASSERT(test) assert(test)
+#else
+#define LFS2_ASSERT(test)
+#endif
+
+
+// Builtin functions, these may be replaced by more efficient
+// toolchain-specific implementations. LFS2_NO_INTRINSICS falls back to a more
+// expensive basic C implementation for debugging purposes
+
+// Min/max functions for unsigned 32-bit numbers
+static inline uint32_t lfs2_max(uint32_t a, uint32_t b) {
+ return (a > b) ? a : b;
+}
+
+static inline uint32_t lfs2_min(uint32_t a, uint32_t b) {
+ return (a < b) ? a : b;
+}
+
+// Align to nearest multiple of a size
+static inline uint32_t lfs2_aligndown(uint32_t a, uint32_t alignment) {
+ return a - (a % alignment);
+}
+
+static inline uint32_t lfs2_alignup(uint32_t a, uint32_t alignment) {
+ return lfs2_aligndown(a + alignment-1, alignment);
+}
+
+// Find the smallest power of 2 greater than or equal to a
+static inline uint32_t lfs2_npw2(uint32_t a) {
+#if !defined(LFS2_NO_INTRINSICS) && (defined(__GNUC__) || defined(__CC_ARM))
+ return 32 - __builtin_clz(a-1);
+#else
+ uint32_t r = 0;
+ uint32_t s;
+ a -= 1;
+ s = (a > 0xffff) << 4; a >>= s; r |= s;
+ s = (a > 0xff ) << 3; a >>= s; r |= s;
+ s = (a > 0xf ) << 2; a >>= s; r |= s;
+ s = (a > 0x3 ) << 1; a >>= s; r |= s;
+ return (r | (a >> 1)) + 1;
+#endif
+}
+
+// Count the number of trailing binary zeros in a
+// lfs2_ctz(0) may be undefined
+static inline uint32_t lfs2_ctz(uint32_t a) {
+#if !defined(LFS2_NO_INTRINSICS) && defined(__GNUC__)
+ return __builtin_ctz(a);
+#else
+ return lfs2_npw2((a & -a) + 1) - 1;
+#endif
+}
+
+// Count the number of binary ones in a
+static inline uint32_t lfs2_popc(uint32_t a) {
+#if !defined(LFS2_NO_INTRINSICS) && (defined(__GNUC__) || defined(__CC_ARM))
+ return __builtin_popcount(a);
+#else
+ a = a - ((a >> 1) & 0x55555555);
+ a = (a & 0x33333333) + ((a >> 2) & 0x33333333);
+ return (((a + (a >> 4)) & 0xf0f0f0f) * 0x1010101) >> 24;
+#endif
+}
+
+// Find the sequence comparison of a and b, this is the distance
+// between a and b ignoring overflow
+static inline int lfs2_scmp(uint32_t a, uint32_t b) {
+ return (int)(unsigned)(a - b);
+}
+
+// Convert between 32-bit little-endian and native order
+static inline uint32_t lfs2_fromle32(uint32_t a) {
+#if !defined(LFS2_NO_INTRINSICS) && ( \
+ (defined( BYTE_ORDER ) && defined( ORDER_LITTLE_ENDIAN ) && BYTE_ORDER == ORDER_LITTLE_ENDIAN ) || \
+ (defined(__BYTE_ORDER ) && defined(__ORDER_LITTLE_ENDIAN ) && __BYTE_ORDER == __ORDER_LITTLE_ENDIAN ) || \
+ (defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__))
+ return a;
+#elif !defined(LFS2_NO_INTRINSICS) && ( \
+ (defined( BYTE_ORDER ) && defined( ORDER_BIG_ENDIAN ) && BYTE_ORDER == ORDER_BIG_ENDIAN ) || \
+ (defined(__BYTE_ORDER ) && defined(__ORDER_BIG_ENDIAN ) && __BYTE_ORDER == __ORDER_BIG_ENDIAN ) || \
+ (defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__))
+ return __builtin_bswap32(a);
+#else
+ return (((uint8_t*)&a)[0] << 0) |
+ (((uint8_t*)&a)[1] << 8) |
+ (((uint8_t*)&a)[2] << 16) |
+ (((uint8_t*)&a)[3] << 24);
+#endif
+}
+
+static inline uint32_t lfs2_tole32(uint32_t a) {
+ return lfs2_fromle32(a);
+}
+
+// Convert between 32-bit big-endian and native order
+static inline uint32_t lfs2_frombe32(uint32_t a) {
+#if !defined(LFS2_NO_INTRINSICS) && ( \
+ (defined( BYTE_ORDER ) && defined( ORDER_LITTLE_ENDIAN ) && BYTE_ORDER == ORDER_LITTLE_ENDIAN ) || \
+ (defined(__BYTE_ORDER ) && defined(__ORDER_LITTLE_ENDIAN ) && __BYTE_ORDER == __ORDER_LITTLE_ENDIAN ) || \
+ (defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__))
+ return __builtin_bswap32(a);
+#elif !defined(LFS2_NO_INTRINSICS) && ( \
+ (defined( BYTE_ORDER ) && defined( ORDER_BIG_ENDIAN ) && BYTE_ORDER == ORDER_BIG_ENDIAN ) || \
+ (defined(__BYTE_ORDER ) && defined(__ORDER_BIG_ENDIAN ) && __BYTE_ORDER == __ORDER_BIG_ENDIAN ) || \
+ (defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__))
+ return a;
+#else
+ return (((uint8_t*)&a)[0] << 24) |
+ (((uint8_t*)&a)[1] << 16) |
+ (((uint8_t*)&a)[2] << 8) |
+ (((uint8_t*)&a)[3] << 0);
+#endif
+}
+
+static inline uint32_t lfs2_tobe32(uint32_t a) {
+ return lfs2_frombe32(a);
+}
+
+// Calculate CRC-32 with polynomial = 0x04c11db7
+uint32_t lfs2_crc(uint32_t crc, const void *buffer, size_t size);
+
+// Allocate memory, only used if buffers are not provided to littlefs
+// Note, memory must be 64-bit aligned
+static inline void *lfs2_malloc(size_t size) {
+#ifndef LFS2_NO_MALLOC
+ return malloc(size);
+#else
+ (void)size;
+ return NULL;
+#endif
+}
+
+// Deallocate memory, only used if buffers are not provided to littlefs
+static inline void lfs2_free(void *p) {
+#ifndef LFS2_NO_MALLOC
+ free(p);
+#else
+ (void)p;
+#endif
+}
+
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif
+#endif
diff --git a/lib/lora/mac/LoRaMac.c b/lib/lora/mac/LoRaMac.c
index aaf8027127..afe8491f1f 100644
--- a/lib/lora/mac/LoRaMac.c
+++ b/lib/lora/mac/LoRaMac.c
@@ -1,28 +1,50 @@
-/*
- / _____) _ | |
-( (____ _____ ____ _| |_ _____ ____| |__
- \____ \| ___ | (_ _) ___ |/ ___) _ \
- _____) ) ____| | | || |_| ____( (___| | | |
-(______/|_____)_|_|_| \__)_____)\____)_| |_|
- (C)2013 Semtech
- ___ _____ _ ___ _ _____ ___ ___ ___ ___
-/ __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
-\__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
-|___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
-embedded.connectivity.solutions===============
-
-Description: LoRa MAC layer implementation
-
-License: Revised BSD License, see LICENSE.TXT file include in the project
-
-Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jaeckle ( STACKFORCE )
-*/
-#include "board.h"
-
-#include "LoRaMac.h"
+/*!
+ * \file LoRaMac.c
+ *
+ * \brief LoRa MAC layer implementation
+ *
+ * \copyright Revised BSD License, see section \ref LICENSE.
+ *
+ * \code
+ * ______ _
+ * / _____) _ | |
+ * ( (____ _____ ____ _| |_ _____ ____| |__
+ * \____ \| ___ | (_ _) ___ |/ ___) _ \
+ * _____) ) ____| | | || |_| ____( (___| | | |
+ * (______/|_____)_|_|_| \__)_____)\____)_| |_|
+ * (C)2013-2017 Semtech
+ *
+ * ___ _____ _ ___ _ _____ ___ ___ ___ ___
+ * / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
+ * \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
+ * |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
+ * embedded.connectivity.solutions===============
+ *
+ * \endcode
+ *
+ * \author Miguel Luis ( Semtech )
+ *
+ * \author Gregory Cristian ( Semtech )
+ *
+ * \author Daniel Jaeckle ( STACKFORCE )
+ *
+ * \author Johannes Bruder ( STACKFORCE )
+ */
+#include "utilities.h"
#include "region/Region.h"
+#include "LoRaMacClassB.h"
#include "LoRaMacCrypto.h"
+#include "secure-element.h"
#include "LoRaMacTest.h"
+#include "LoRaMacTypes.h"
+#include "LoRaMacConfirmQueue.h"
+#include "LoRaMacHeaderTypes.h"
+#include "LoRaMacMessageTypes.h"
+#include "LoRaMacParser.h"
+#include "LoRaMacCommands.h"
+#include "LoRaMacAdr.h"
+
+#include "LoRaMac.h"
#include "modlora.h"
@@ -41,11 +63,6 @@ Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jae
*/
#define LORA_MAC_COMMAND_MAX_FOPTS_LENGTH 15
-/*!
- * LoRaMac region.
- */
-static LoRaMacRegion_t LoRaMacRegion;
-
/*!
* LoRaMac duty cycle for the back-off procedure during the first hour.
*/
@@ -62,1565 +79,1845 @@ static LoRaMacRegion_t LoRaMacRegion;
#define BACKOFF_DC_24_HOURS 10000
/*!
- * Device IEEE EUI
- */
-static uint8_t *LoRaMacDevEui;
-
-/*!
- * Application IEEE EUI
- */
-static uint8_t *LoRaMacAppEui;
-
-/*!
- * AES encryption/decryption cipher application key
- */
-static uint8_t *LoRaMacAppKey;
-
-/*!
- * AES encryption/decryption cipher network session key
+ * LoRaMac internal states
*/
-static uint8_t LoRaMacNwkSKey[] =
+enum eLoRaMacState
{
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ LORAMAC_IDLE = 0x00000000,
+ LORAMAC_STOPPED = 0x00000001,
+ LORAMAC_TX_RUNNING = 0x00000002,
+ LORAMAC_RX = 0x00000004,
+ LORAMAC_ACK_RETRY = 0x00000010,
+ LORAMAC_TX_DELAYED = 0x00000020,
+ LORAMAC_TX_CONFIG = 0x00000040,
+ LORAMAC_RX_ABORT = 0x00000080,
};
-/*!
- * AES encryption/decryption cipher application session key
+/*
+ * Request permission state
*/
-static uint8_t LoRaMacAppSKey[] =
+typedef enum eLoRaMacRequestHandling
{
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-};
+ LORAMAC_REQUEST_HANDLING_OFF = 0,
+ LORAMAC_REQUEST_HANDLING_ON = !LORAMAC_REQUEST_HANDLING_OFF
+}LoRaMacRequestHandling_t;
-/*!
- * Device nonce is a random value extracted by issuing a sequence of RSSI
- * measurements
- */
-static uint16_t LoRaMacDevNonce;
+typedef struct sLoRaMacNvmCtx
+{
+ /*
+ * LoRaMac region.
+ */
+ LoRaMacRegion_t Region;
+ /*
+ * LoRaMac default parameters
+ */
+ LoRaMacParams_t MacParamsDefaults;
+ /*
+ * Network ID ( 3 bytes )
+ */
+ uint32_t NetID;
+ /*
+ * Mote Address
+ */
+ uint32_t DevAddr;
+ /*!
+ * Multicast channel list
+ */
+ MulticastCtx_t MulticastChannelList[LORAMAC_MAX_MC_CTX];
+ /*
+ * Actual device class
+ */
+ DeviceClass_t DeviceClass;
+ /*
+ * Indicates if the node is connected to
+ * a private or public network
+ */
+ bool PublicNetwork;
+ /*
+ * LoRaMac ADR control status
+ */
+ bool AdrCtrlOn;
+ /*
+ * Counts the number of missed ADR acknowledgements
+ */
+ uint32_t AdrAckCounter;
+
+ /*
+ * LoRaMac parameters
+ */
+ LoRaMacParams_t MacParams;
+ /*
+ * Maximum duty cycle
+ * \remark Possibility to shutdown the device.
+ */
+ uint8_t MaxDCycle;
+ /*
+ * Enables/Disables duty cycle management (Test only)
+ */
+ bool DutyCycleOn;
+ /*
+ * Current channel index
+ */
+ uint8_t LastTxChannel;
+ /*
+ * Holds the current rx window slot
+ */
+ bool RepeaterSupport;
+ /*
+ * Buffer containing the MAC layer commands
+ */
+ uint8_t MacCommandsBuffer[LORA_MAC_COMMAND_MAX_LENGTH];
+ /*
+ * If the server has sent a FRAME_TYPE_DATA_CONFIRMED_DOWN this variable indicates
+ * if the ACK bit must be set for the next transmission
+ */
+ bool SrvAckRequested;
+ /*
+ * Aggregated duty cycle management
+ */
+ uint16_t AggregatedDCycle;
+ /*
+ * Aggregated duty cycle management
+ */
+ TimerTime_t LastTxDoneTime;
+ TimerTime_t AggregatedTimeOff;
+ /*
+ * Stores the time at LoRaMac initialization.
+ *
+ * \remark Used for the BACKOFF_DC computation.
+ */
+ SysTime_t InitializationTime;
+ /*
+ * Current LoRaWAN Version
+ */
+ Version_t Version;
+ /*
+ * End-Device network activation
+ */
+ ActivationType_t NetworkActivation;
+ /*!
+ * Last received Message integrity Code (MIC)
+ */
+ uint32_t LastRxMic;
+}LoRaMacNvmCtx_t;
+
+typedef struct sLoRaMacCtx
+{
+ /*
+ * Length of packet in PktBuffer
+ */
+ uint16_t PktBufferLen;
+ /*
+ * Buffer containing the data to be sent or received.
+ */
+ uint8_t PktBuffer[LORAMAC_PHY_MAXPAYLOAD];
+ /*!
+ * Current processed transmit message
+ */
+ LoRaMacMessage_t TxMsg;
+ /*!
+ * Buffer containing the data received by the application.
+ */
+ uint8_t AppData[LORAMAC_PHY_MAXPAYLOAD];
+ /*
+ * Size of buffer containing the application data.
+ */
+ uint8_t AppDataSize;
+ /*
+ * Buffer containing the upper layer data.
+ */
+ uint8_t RxPayload[LORAMAC_PHY_MAXPAYLOAD];
+ SysTime_t LastTxSysTime;
+ /*
+ * LoRaMac internal state
+ */
+ uint32_t MacState;
+ /*
+ * LoRaMac upper layer event functions
+ */
+ LoRaMacPrimitives_t* MacPrimitives;
+ /*
+ * LoRaMac upper layer callback functions
+ */
+ LoRaMacCallback_t* MacCallbacks;
+ /*
+ * Radio events function pointer
+ */
+ RadioEvents_t RadioEvents;
+ /*
+ * LoRaMac duty cycle delayed Tx timer
+ */
+ TimerEvent_t TxDelayedTimer;
+ /*
+ * LoRaMac reception windows timers
+ */
+ TimerEvent_t RxWindowTimer1;
+ TimerEvent_t RxWindowTimer2;
+ /*
+ * LoRaMac reception windows delay
+ * \remark normal frame: RxWindowXDelay = ReceiveDelayX - RADIO_WAKEUP_TIME
+ * join frame : RxWindowXDelay = JoinAcceptDelayX - RADIO_WAKEUP_TIME
+ */
+ uint32_t RxWindow1Delay;
+ uint32_t RxWindow2Delay;
+ /*
+ * LoRaMac Rx windows configuration
+ */
+ RxConfigParams_t RxWindow1Config;
+ RxConfigParams_t RxWindow2Config;
+ RxConfigParams_t RxWindowCConfig;
+ /*
+ * Limit of uplinks without any donwlink response before the ADRACKReq bit will be set.
+ */
+ uint16_t AdrAckLimit;
+ /*
+ * Limit of uplinks without any donwlink response after a the first frame with set ADRACKReq bit
+ * before the trying to regain the connectivity.
+ */
+ uint16_t AdrAckDelay;
+ /*
+ * Acknowledge timeout timer. Used for packet retransmissions.
+ */
+ TimerEvent_t AckTimeoutTimer;
+ /*
+ * Uplink messages repetitions counter
+ */
+ uint8_t ChannelsNbTransCounter;
+ /*
+ * Number of trials to get a frame acknowledged
+ */
+ uint8_t AckTimeoutRetries;
+ /*
+ * Number of trials to get a frame acknowledged
+ */
+ uint8_t AckTimeoutRetriesCounter;
+ /*
+ * Indicates if the AckTimeout timer has expired or not
+ */
+ bool AckTimeoutRetry;
+ /*
+ * If the node has sent a FRAME_TYPE_DATA_CONFIRMED_UP this variable indicates
+ * if the nodes needs to manage the server acknowledgement.
+ */
+ bool NodeAckRequested;
+ /*
+ * Current channel index
+ */
+ uint8_t Channel;
+ /*
+ * Last transmission time on air
+ */
+ TimerTime_t TxTimeOnAir;
+ /*
+ * Structure to hold an MCPS indication data.
+ */
+ McpsIndication_t McpsIndication;
+ /*
+ * Structure to hold MCPS confirm data.
+ */
+ McpsConfirm_t McpsConfirm;
+ /*
+ * Structure to hold MLME confirm data.
+ */
+ MlmeConfirm_t MlmeConfirm;
+ /*
+ * Structure to hold MLME indication data.
+ */
+ MlmeIndication_t MlmeIndication;
+ /*
+ * Holds the current rx window slot
+ */
+ LoRaMacRxSlot_t RxSlot;
+ /*
+ * LoRaMac tx/rx operation state
+ */
+ LoRaMacFlags_t MacFlags;
+ /*
+ * Data structure indicating if a request is allowed or not.
+ */
+ LoRaMacRequestHandling_t AllowRequests;
+ /*
+ * Non-volatile module context structure
+ */
+ LoRaMacNvmCtx_t* NvmCtx;
+}LoRaMacCtx_t;
-/*!
- * Network ID ( 3 bytes )
+/*
+ * Module context.
*/
-static uint32_t LoRaMacNetID;
+static LoRaMacCtx_t MacCtx;
-/*!
- * Mote Address
+/*
+ * Non-volatile module context.
*/
-static uint32_t LoRaMacDevAddr;
+static LoRaMacNvmCtx_t NvmMacCtx;
-/*!
- * Multicast channels linked list
- */
-static MulticastParams_t *MulticastChannels = NULL;
-/*!
- * Actual device class
- */
-static DeviceClass_t LoRaMacDeviceClass;
/*
- * End-Device network activation
+ * List of module contexts.
*/
-static ActivationType_t NetworkActivation;
+LoRaMacCtxs_t Contexts;
/*!
- * Indicates if the node is connected to a private or public network
+ * Defines the LoRaMac radio events status
*/
-static bool PublicNetwork;
+typedef union uLoRaMacRadioEvents
+{
+ uint32_t Value;
+ struct sEvents
+ {
+ uint32_t RxTimeout : 1;
+ uint32_t RxError : 1;
+ uint32_t TxTimeout : 1;
+ uint32_t RxDone : 1;
+ uint32_t TxDone : 1;
+ }Events;
+}LoRaMacRadioEvents_t;
/*!
- * Indicates if the node supports repeaters
+ * LoRaMac radio events status
*/
-static bool RepeaterSupport;
+LoRaMacRadioEvents_t LoRaMacRadioEvents = { .Value = 0 };
/*!
- * Buffer containing the data to be sent or received.
+ * \brief Function to be executed on Radio Tx Done event
*/
-static uint8_t LoRaMacBuffer[LORAMAC_PHY_MAXPAYLOAD];
+static void OnRadioTxDone( void );
/*!
- * Length of packet in LoRaMacBuffer
+ * \brief This function prepares the MAC to abort the execution of function
+ * OnRadioRxDone in case of a reception error.
*/
-static uint16_t LoRaMacBufferPktLen = 0;
+static void PrepareRxDoneAbort( void );
/*!
- * Length of the payload in LoRaMacBuffer
+ * \brief Function to be executed on Radio Rx Done event
*/
-static uint8_t LoRaMacTxPayloadLen = 0;
+static void OnRadioRxDone( uint8_t *payload, uint32_t timestamp, uint16_t size, int16_t rssi, int8_t snr, uint8_t sf );
/*!
- * Buffer containing the upper layer data.
+ * \brief Function executed on Radio Tx Timeout event
*/
-static uint8_t LoRaMacRxPayload[LORAMAC_PHY_MAXPAYLOAD];
+static void OnRadioTxTimeout( void );
/*!
- * LoRaMAC frame counter. Each time a packet is sent the counter is incremented.
- * Only the 16 LSB bits are sent
+ * \brief Function executed on Radio Rx error event
*/
-static uint32_t UpLinkCounter = 0;
+static void OnRadioRxError( void );
/*!
- * LoRaMAC frame counter. Each time a packet is received the counter is incremented.
- * Only the 16 LSB bits are received
+ * \brief Function executed on Radio Rx Timeout event
*/
-static uint32_t DownLinkCounter = 0;
+static void OnRadioRxTimeout( void );
/*!
- * IsPacketCounterFixed enables the MIC field tests by fixing the
- * UpLinkCounter value
+ * \brief Function executed on duty cycle delayed Tx timer event
*/
-static bool IsUpLinkCounterFixed = false;
+static void OnTxDelayedTimerEvent( void* context );
/*!
- * Used for test purposes. Disables the opening of the reception windows.
+ * \brief Function executed on first Rx window timer event
*/
-static bool IsRxWindowsEnabled = true;
+static void OnRxWindow1TimerEvent( void* context );
/*!
- * Indicates if the MAC layer has already joined a network.
+ * \brief Function executed on second Rx window timer event
*/
-static bool IsLoRaMacNetworkJoined = false;
+static void OnRxWindow2TimerEvent( void* context );
/*!
- * LoRaMac ADR control status
+ * \brief Function executed on AckTimeout timer event
*/
-static bool AdrCtrlOn = false;
+static void OnAckTimeoutTimerEvent( void* context );
/*!
- * Counts the number of missed ADR acknowledgements
+ * \brief Configures the events to trigger an MLME-Indication with
+ * a MLME type of MLME_SCHEDULE_UPLINK.
*/
-static uint32_t AdrAckCounter = 0;
+static void SetMlmeScheduleUplinkIndication( void );
/*!
- * If the node has sent a FRAME_TYPE_DATA_CONFIRMED_UP this variable indicates
- * if the nodes needs to manage the server acknowledgement.
+ * Computes next 32 bit downlink counter value and determines the frame counter ID.
+ *
+ * \param[IN] addrID - Address identifier
+ * \param[IN] fType - Frame type
+ * \param[IN] macMsg - Data message object, holding the current 16 bit transmitted frame counter
+ * \param[IN] lrWanVersion - LoRaWAN version
+ * \param[IN] maxFCntGap - Maximum allowed frame counter difference (only for 1.0.X necessary)
+ * \param[OUT] fCntID - Frame counter identifier
+ * \param[OUT] currentDown - Current downlink counter value
+ *
+ * \retval - Status of the operation
*/
-static bool NodeAckRequested = false;
+static LoRaMacCryptoStatus_t GetFCntDown( AddressIdentifier_t addrID, FType_t fType, LoRaMacMessageData_t* macMsg, Version_t lrWanVersion,
+ uint16_t maxFCntGap, FCntIdentifier_t* fCntID, uint32_t* currentDown );
/*!
- * If the server has sent a FRAME_TYPE_DATA_CONFIRMED_DOWN this variable indicates
- * if the ACK bit must be set for the next transmission
+ * \brief Switches the device class
+ *
+ * \param [IN] deviceClass Device class to switch to
*/
-static bool SrvAckRequested = false;
+static LoRaMacStatus_t SwitchClass( DeviceClass_t deviceClass );
/*!
- * Indicates if the MAC layer wants to send MAC commands
+ * \brief Gets the maximum application payload length in the absence of the optional FOpt field.
+ *
+ * \param [IN] datarate Current datarate
+ *
+ * \retval Max length
*/
-static bool MacCommandsInNextTx = false;
+static uint8_t GetMaxAppPayloadWithoutFOptsLength( int8_t datarate );
/*!
- * Contains the current MacCommandsBuffer index
+ * \brief Validates if the payload fits into the frame, taking the datarate
+ * into account.
+ *
+ * \details Refer to chapter 4.3.2 of the LoRaWAN specification, v1.0
+ *
+ * \param lenN Length of the application payload. The length depends on the
+ * datarate and is region specific
+ *
+ * \param datarate Current datarate
+ *
+ * \param fOptsLen Length of the fOpts field
+ *
+ * \retval [false: payload does not fit into the frame, true: payload fits into
+ * the frame]
*/
-static uint8_t MacCommandsBufferIndex = 0;
+//static bool ValidatePayloadLength( uint8_t lenN, int8_t datarate, uint8_t fOptsLen ); Pycom: Changed to non-static
/*!
- * Contains the current MacCommandsBuffer index for MAC commands to repeat
+ * \brief Decodes MAC commands in the fOpts field and in the payload
+ *
+ * \param [IN] payload A pointer to the payload
+ * \param [IN] macIndex The index of the payload where the MAC commands start
+ * \param [IN] commandsSize The size of the MAC commands
+ * \param [IN] snr The SNR value of the frame
+ * \param [IN] rxSlot The RX slot where the frame was received
*/
-static uint8_t MacCommandsBufferToRepeatIndex = 0;
+static void ProcessMacCommands( uint8_t* payload, uint8_t macIndex, uint8_t commandsSize, int8_t snr, LoRaMacRxSlot_t rxSlot );
/*!
- * Buffer containing the MAC layer commands
+ * \brief LoRaMAC layer generic send frame
+ *
+ * \param [IN] macHdr MAC header field
+ * \param [IN] fPort MAC payload port
+ * \param [IN] fBuffer MAC data buffer to be sent
+ * \param [IN] fBufferSize MAC data buffer size
+ * \retval status Status of the operation.
*/
-static uint8_t MacCommandsBuffer[LORA_MAC_COMMAND_MAX_LENGTH];
+LoRaMacStatus_t Send( LoRaMacHeader_t* macHdr, uint8_t fPort, void* fBuffer, uint16_t fBufferSize );
/*!
- * Buffer containing the MAC layer commands which must be repeated
+ * \brief LoRaMAC layer send join/rejoin request
+ *
+ * \param [IN] joinReqType Type of join-request or rejoin
+ *
+ * \retval status Status of the operation.
*/
-static uint8_t MacCommandsBufferToRepeat[LORA_MAC_COMMAND_MAX_LENGTH];
+LoRaMacStatus_t SendReJoinReq( JoinReqIdentifier_t joinReqType );
/*!
- * LoRaMac parameters
+ * \brief LoRaMAC layer frame buffer initialization
+ *
+ * \param [IN] macHdr MAC header field
+ * \param [IN] fCtrl MAC frame control field
+ * \param [IN] fOpts MAC commands buffer
+ * \param [IN] fPort MAC payload port
+ * \param [IN] fBuffer MAC data buffer to be sent
+ * \param [IN] fBufferSize MAC data buffer size
+ * \retval status Status of the operation.
*/
-LoRaMacParams_t LoRaMacParams;
+LoRaMacStatus_t PrepareFrame( LoRaMacHeader_t* macHdr, LoRaMacFrameCtrl_t* fCtrl, uint8_t fPort, void* fBuffer, uint16_t fBufferSize );
-/*!
- * LoRaMac default parameters
+/*
+ * \brief Schedules the frame according to the duty cycle
+ *
+ * \param [IN] allowDelayedTx When set to true, the a frame will be delayed,
+ * the duty cycle restriction is active
+ * \retval Status of the operation
*/
-LoRaMacParams_t LoRaMacParamsDefaults;
+static LoRaMacStatus_t ScheduleTx( bool allowDelayedTx );
-/*!
- * Uplink messages repetitions counter
+/*
+ * \brief Secures the current processed frame ( TxMsg )
+ * \param[IN] txDr Data rate used for the transmission
+ * \param[IN] txCh Index of the channel used for the transmission
+ * \retval status Status of the operation
*/
-static uint8_t ChannelsNbRepCounter = 0;
+static LoRaMacStatus_t SecureFrame( uint8_t txDr, uint8_t txCh );
-/*!
- * Maximum duty cycle
- * \remark Possibility to shutdown the device.
+/*
+ * \brief Calculates the back-off time for the band of a channel.
+ *
+ * \param [IN] channel The last Tx channel index
*/
-static uint8_t MaxDCycle = 0;
+static void CalculateBackOff( uint8_t channel );
-/*!
- * Aggregated duty cycle management
+/*
+ * \brief Function to remove pending MAC commands
+ *
+ * \param [IN] rxSlot The RX slot on which the frame was received
+ * \param [IN] fCtrl The frame control field of the received frame
+ * \param [IN] request The request type
*/
-static uint16_t AggregatedDCycle;
-static TimerTime_t AggregatedLastTxDoneTime;
-static TimerTime_t AggregatedTimeOff;
-//static TimerEvent_t RadioTxDoneClassCTimer;
+static void RemoveMacCommands( LoRaMacRxSlot_t rxSlot, LoRaMacFrameCtrl_t fCtrl, Mcps_t request );
/*!
- * Enables/Disables duty cycle management (Test only)
+ * \brief LoRaMAC layer prepared frame buffer transmission with channel specification
+ *
+ * \remark PrepareFrame must be called at least once before calling this
+ * function.
+ *
+ * \param [IN] channel Channel to transmit on
+ * \retval status Status of the operation.
*/
-static bool DutyCycleOn;
+LoRaMacStatus_t SendFrameOnChannel( uint8_t channel );
/*!
- * Current channel index
+ * \brief Sets the radio in continuous transmission mode
+ *
+ * \remark Uses the radio parameters set on the previous transmission.
+ *
+ * \param [IN] timeout Time in seconds while the radio is kept in continuous wave mode
+ * \retval status Status of the operation.
*/
-static uint8_t Channel;
+LoRaMacStatus_t SetTxContinuousWave( uint16_t timeout );
/*!
- * Current channel index
+ * \brief Sets the radio in continuous transmission mode
+ *
+ * \remark Uses the radio parameters set on the previous transmission.
+ *
+ * \param [IN] timeout Time in seconds while the radio is kept in continuous wave mode
+ * \param [IN] frequency RF frequency to be set.
+ * \param [IN] power RF output power to be set.
+ * \retval status Status of the operation.
*/
-static uint8_t LastTxChannel;
+LoRaMacStatus_t SetTxContinuousWave1( uint16_t timeout, uint32_t frequency, uint8_t power );
/*!
- * Set to true, if the last uplink was a join request
+ * \brief Resets MAC specific parameters to default
*/
-static bool LastTxIsJoinRequest;
+static void ResetMacParameters( void );
/*!
- * Stores the time at LoRaMac initialization.
+ * \brief Initializes and opens the reception window
*
- * \remark Used for the BACKOFF_DC computation.
- */
-static TimerTime_t LoRaMacInitializationTime = 0;
-
-/*!
- * LoRaMac internal states
+ * \param [IN] rxTimer Window timer to be topped.
+ * \param [IN] rxConfig Window parameters to be setup
*/
-enum eLoRaMacState
-{
- LORAMAC_IDLE = 0x00000000,
- LORAMAC_TX_RUNNING = 0x00000001,
- LORAMAC_RX = 0x00000002,
- LORAMAC_ACK_REQ = 0x00000004,
- LORAMAC_ACK_RETRY = 0x00000008,
- LORAMAC_TX_DELAYED = 0x00000010,
- LORAMAC_TX_CONFIG = 0x00000020,
- LORAMAC_RX_ABORT = 0x00000040,
-};
+static void RxWindowSetup( TimerEvent_t* rxTimer, RxConfigParams_t* rxConfig );
/*!
- * LoRaMac internal state
+ * \brief Opens up a continuous RX C window. This is used for
+ * class c devices.
*/
-uint32_t LoRaMacState = LORAMAC_IDLE;
+static void OpenContinuousRxCWindow( void );
/*!
- * LoRaMac timer used to check the LoRaMacState (runs every second)
+ * \brief Returns a pointer to the internal contexts structure.
+ *
+ * \retval void Points to a structure containing all contexts
*/
-static TimerEvent_t MacStateCheckTimer;
+LoRaMacCtxs_t* GetCtxs( void );
/*!
- * LoRaMac upper layer event functions
+ * \brief Restoring of internal module contexts
+ *
+ * \details This function allows to restore module contexts by a given pointer.
+ *
+ *
+ * \retval LoRaMacStatus_t Status of the operation. Possible returns are:
+ * returns are:
+ * \ref LORAMAC_STATUS_OK,
+ * \ref LORAMAC_STATUS_PARAMETER_INVALID,
*/
-static LoRaMacPrimitives_t *LoRaMacPrimitives;
+LoRaMacStatus_t RestoreCtxs( LoRaMacCtxs_t* contexts );
/*!
- * LoRaMac upper layer callback functions
+ * \brief Determines the frame type
+ *
+ * \param [IN] macMsg Data message object
+ *
+ * \param [OUT] fType Frame type
+ *
+ * \retval LoRaMacStatus_t Status of the operation. Possible returns are:
+ * returns are:
+ * \ref LORAMAC_STATUS_OK,
+ * \ref LORAMAC_STATUS_PARAMETER_INVALID,
*/
-static LoRaMacCallback_t *LoRaMacCallbacks;
+LoRaMacStatus_t DetermineFrameType( LoRaMacMessageData_t* macMsg, FType_t* fType );
/*!
- * Radio events function pointer
+ * \brief Checks if the retransmission should be stopped in case of a unconfirmed uplink
+ *
+ * \retval Returns true if it should be stopped.
*/
-static RadioEvents_t RadioEvents;
+static bool CheckRetransUnconfirmedUplink( void );
/*!
- * LoRaMac duty cycle delayed Tx timer
+ * \brief Checks if the retransmission should be stopped in case of a confirmed uplink
+ *
+ * \retval Returns true it should be stopped.
*/
-static TimerEvent_t TxDelayedTimer;
+static bool CheckRetransConfirmedUplink( void );
/*!
- * LoRaMac reception windows timers
+ * \brief Stops the uplink retransmission
+ *
+ * \retval Returns true if successful.
*/
-static TimerEvent_t RxWindowTimer1;
-static TimerEvent_t RxWindowTimer2;
+static bool StopRetransmission( void );
/*!
- * LoRaMac reception windows delay
- * \remark normal frame: RxWindowXDelay = ReceiveDelayX - RADIO_WAKEUP_TIME
- * join frame : RxWindowXDelay = JoinAcceptDelayX - RADIO_WAKEUP_TIME
+ * \brief Handles the ACK retries algorithm.
+ * Increments the re-tries counter up until the specified number of
+ * trials or the allowed maximum. Decrease the uplink datarate every 2
+ * trials.
*/
-static uint32_t RxWindow1Delay;
-static uint32_t RxWindow2Delay;
+static void AckTimeoutRetriesProcess( void );
/*!
- * LoRaMac Rx windows configuration
+ * \brief Finalizes the ACK retries algorithm.
+ * If no ACK is received restores the default channels
*/
-static RxConfigParams_t RxWindow1Config;
-static RxConfigParams_t RxWindow2Config;
+static void AckTimeoutRetriesFinalize( void );
/*!
- * Acknowledge timeout timer. Used for packet retransmissions.
+ * \brief Calls the callback to indicate that a context changed
*/
-static TimerEvent_t AckTimeoutTimer;
+static void CallNvmCtxCallback( LoRaMacNvmCtxModule_t module );
/*!
- * Number of trials to get a frame acknowledged
+ * \brief MAC NVM Context has been changed
*/
-static uint8_t AckTimeoutRetries = 1;
+static void EventMacNvmCtxChanged( void );
/*!
- * Number of trials to get a frame acknowledged
+ * \brief Region NVM Context has been changed
*/
-static uint8_t AckTimeoutRetriesCounter = 1;
+static void EventRegionNvmCtxChanged( void );
/*!
- * Indicates if the AckTimeout timer has expired or not
+ * \brief Crypto NVM Context has been changed
*/
-static bool AckTimeoutRetry = false;
+static void EventCryptoNvmCtxChanged( void );
/*!
- * Last transmission time on air
+ * \brief Secure Element NVM Context has been changed
*/
-TimerTime_t TxTimeOnAir = 0;
+static void EventSecureElementNvmCtxChanged( void );
/*!
- * Number of trials for the Join Request
+ * \brief MAC commands module nvm context has been changed
*/
-static uint8_t JoinRequestTrials;
+static void EventCommandsNvmCtxChanged( void );
/*!
- * Maximum number of trials for the Join Request
+ * \brief Class B module nvm context has been changed
*/
-static uint8_t MaxJoinRequestTrials;
+static void EventClassBNvmCtxChanged( void );
/*!
- * Structure to hold an MCPS indication data.
+ * \brief Confirm Queue module nvm context has been changed
*/
-static McpsIndication_t McpsIndication;
+static void EventConfirmQueueNvmCtxChanged( void );
/*!
- * Structure to hold MCPS confirm data.
+ * \brief Verifies if a request is pending currently
+ *
+ *\retval 1: Request pending, 0: request not pending
*/
-static McpsConfirm_t McpsConfirm;
+static uint8_t IsRequestPending( void );
/*!
- * Structure to hold MLME indication data.
+ * \brief Enabled the possibility to perform requests
+ *
+ * \param [IN] requestState Request permission state
*/
-static MlmeIndication_t MlmeIndication;
+static void LoRaMacEnableRequests( LoRaMacRequestHandling_t requestState );
/*!
- * Structure to hold MLME confirm data.
+ * \brief This function verifies if a RX abort occurred
*/
-static MlmeConfirm_t MlmeConfirm;
+static void LoRaMacCheckForRxAbort( void );
/*!
- * Holds the current rx window slot
+ * \brief This function verifies if a beacon acquisition MLME
+ * request was pending
+ *
+ * \retval 1: Request pending, 0: no request pending
*/
-static uint8_t RxSlot = 0;
+static uint8_t LoRaMacCheckForBeaconAcquisition( void );
/*!
- * LoRaMac tx/rx operation state
+ * \brief This function handles join request
*/
-LoRaMacFlags_t LoRaMacFlags;
+static void LoRaMacHandleMlmeRequest( void );
/*!
- * \brief Function to be executed on Radio Tx Done event
+ * \brief This function handles mcps request
*/
-static void OnRadioTxDone( void );
+static void LoRaMacHandleMcpsRequest( void );
/*!
- * \brief This function prepares the MAC to abort the execution of function
- * OnRadioRxDone in case of a reception error.
+ * \brief This function handles callback events for requests
*/
-static void PrepareRxDoneAbort( void );
+static void LoRaMacHandleRequestEvents( void );
/*!
- * \brief Function to be executed on Radio Rx Done event
+ * \brief This function handles callback events for indications
*/
-static void OnRadioRxDone(uint8_t *payload, uint32_t timestamp, uint16_t size, int16_t rssi, int8_t snr, uint8_t sf);
+static void LoRaMacHandleIndicationEvents( void );
/*!
- * \brief Function executed on Radio Tx Timeout event
+ * Structure used to store the radio Tx event data
*/
-static void OnRadioTxTimeout( void );
+struct
+{
+ TimerTime_t CurTime;
+}TxDoneParams;
/*!
- * \brief Function executed on Radio Rx error event
+ * Structure used to store the radio Rx event data
*/
-static void OnRadioRxError( void );
+struct
+{
+ TimerTime_t LastRxDone;
+ uint8_t *Payload;
+ uint16_t Size;
+ int16_t Rssi;
+ int8_t Snr;
+}RxDoneParams;
+
+static void OnRadioTxDone( void )
+{
+ TxDoneParams.CurTime = TimerGetCurrentTime( );
+ MacCtx.LastTxSysTime = SysTimeGet( );
-/*!
- * \brief Function executed on Radio Rx Timeout event
- */
-static void OnRadioRxTimeout( void );
+ LoRaMacRadioEvents.Events.TxDone = 1;
-/*!
- * \brief Function executed on Resend Frame timer event.
- */
-static void OnMacStateCheckTimerEvent( void );
+ if( ( MacCtx.MacCallbacks != NULL ) && ( MacCtx.MacCallbacks->MacProcessNotify != NULL ) )
+ {
+ MacCtx.MacCallbacks->MacProcessNotify( );
+ }
+}
-/*!
- * \brief Function executed on duty cycle delayed Tx timer event
- */
-static void OnTxDelayedTimerEvent( void );
+static void OnRadioRxDone( uint8_t *payload, uint32_t timestamp, uint16_t size, int16_t rssi, int8_t snr, uint8_t sf )
+{
+ RxDoneParams.LastRxDone = TimerGetCurrentTime( );
+ RxDoneParams.Payload = payload;
+ RxDoneParams.Size = size;
+ RxDoneParams.Rssi = rssi;
+ RxDoneParams.Snr = snr;
-/*!
- * \brief Function executed on first Rx window timer event
- */
-static void OnRxWindow1TimerEvent( void );
+ LoRaMacRadioEvents.Events.RxDone = 1;
-/*!
- * \brief Function executed on second Rx window timer event
- */
-static void OnRxWindow2TimerEvent( void );
+ if( ( MacCtx.MacCallbacks != NULL ) && ( MacCtx.MacCallbacks->MacProcessNotify != NULL ) )
+ {
+ MacCtx.MacCallbacks->MacProcessNotify( );
+ }
+}
-/*!
- * \brief Check if the OnAckTimeoutTimer has do be disabled. If so, the
- * function disables it.
- *
- * \param [IN] nodeAckRequested Set to true, if the node has requested an ACK
- * \param [IN] class The device class
- * \param [IN] ackReceived Set to true, if the node has received an ACK
- * \param [IN] ackTimeoutRetriesCounter Retries counter for confirmed uplinks
- * \param [IN] ackTimeoutRetries Maximum retries for confirmed uplinks
- */
-static void CheckToDisableAckTimeout( bool nodeAckRequested, DeviceClass_t devClass, bool ackReceived,
- uint8_t ackTimeoutRetriesCounter, uint8_t ackTimeoutRetries );
+static void OnRadioTxTimeout( void )
+{
+ LoRaMacRadioEvents.Events.TxTimeout = 1;
-/*!
- * \brief Function executed on AckTimeout timer event
- */
-static void OnAckTimeoutTimerEvent( void );
+ if( ( MacCtx.MacCallbacks != NULL ) && ( MacCtx.MacCallbacks->MacProcessNotify != NULL ) )
+ {
+ MacCtx.MacCallbacks->MacProcessNotify( );
+ }
+}
-/*!
- * \brief Initializes and opens the reception window
- *
- * \param [IN] rxContinuous Set to true, if the RX is in continuous mode
- * \param [IN] maxRxWindow Maximum RX window timeout
- */
-static void RxWindowSetup( bool rxContinuous, uint32_t maxRxWindow );
+static void OnRadioRxError( void )
+{
+ LoRaMacRadioEvents.Events.RxError = 1;
-/*!
- * \brief Verifies if sticky MAC commands are pending.
- *
- * \retval [true: sticky MAC commands pending, false: No MAC commands pending]
- */
-static bool IsStickyMacCommandPending( void );
+ if( ( MacCtx.MacCallbacks != NULL ) && ( MacCtx.MacCallbacks->MacProcessNotify != NULL ) )
+ {
+ MacCtx.MacCallbacks->MacProcessNotify( );
+ }
+}
-/*!
- * \brief Configures the events to trigger an MLME-Indication with
- * a MLME type of MLME_SCHEDULE_UPLINK.
- */
-static void SetMlmeScheduleUplinkIndication( void );
+static void OnRadioRxTimeout( void )
+{
+ LoRaMacRadioEvents.Events.RxTimeout = 1;
-/*!
- * \brief Adds a new MAC command to be sent.
- *
- * \Remark MAC layer internal function
- *
- * \param [in] cmd MAC command to be added
- * [MOTE_MAC_LINK_CHECK_REQ,
- * MOTE_MAC_LINK_ADR_ANS,
- * MOTE_MAC_DUTY_CYCLE_ANS,
- * MOTE_MAC_RX2_PARAM_SET_ANS,
- * MOTE_MAC_DEV_STATUS_ANS
- * MOTE_MAC_NEW_CHANNEL_ANS]
- * \param [in] p1 1st parameter ( optional depends on the command )
- * \param [in] p2 2nd parameter ( optional depends on the command )
- *
- * \retval status Function status [0: OK, 1: Unknown command, 2: Buffer full]
- */
-static LoRaMacStatus_t AddMacCommand( uint8_t cmd, uint8_t p1, uint8_t p2 );
+ if( ( MacCtx.MacCallbacks != NULL ) && ( MacCtx.MacCallbacks->MacProcessNotify != NULL ) )
+ {
+ MacCtx.MacCallbacks->MacProcessNotify( );
+ }
+}
-/*!
- * \brief Parses the MAC commands which must be repeated.
- *
- * \Remark MAC layer internal function
- *
- * \param [IN] cmdBufIn Buffer which stores the MAC commands to send
- * \param [IN] length Length of the input buffer to parse
- * \param [OUT] cmdBufOut Buffer which stores the MAC commands which must be
- * repeated.
- *
- * \retval Size of the MAC commands to repeat.
- */
-static uint8_t ParseMacCommandsToRepeat( uint8_t* cmdBufIn, uint8_t length, uint8_t* cmdBufOut );
+static void UpdateRxSlotIdleState( void )
+{
+ if( MacCtx.NvmCtx->DeviceClass != CLASS_C )
+ {
+ MacCtx.RxSlot = RX_SLOT_NONE;
+ }
+ else
+ {
+ MacCtx.RxSlot = RX_SLOT_WIN_CLASS_C;
+ }
+}
-/*!
- * \brief Decodes MAC commands in the fOpts field and in the payload
- */
-static void ProcessMacCommands( uint8_t *payload, uint8_t macIndex, uint8_t commandsSize, uint8_t snr );
+static void ProcessRadioTxDone( void )
+{
+ GetPhyParams_t getPhy;
+ PhyParam_t phyParam;
+ SetBandTxDoneParams_t txDone;
-/*!
- * \brief LoRaMAC layer generic send frame
- *
- * \param [IN] macHdr MAC header field
- * \param [IN] fPort MAC payload port
- * \param [IN] fBuffer MAC data buffer to be sent
- * \param [IN] fBufferSize MAC data buffer size
- * \retval status Status of the operation.
- */
-LoRaMacStatus_t Send( LoRaMacHeader_t *macHdr, uint8_t fPort, void *fBuffer, uint16_t fBufferSize );
-
-/*!
- * \brief LoRaMAC layer frame buffer initialization
- *
- * \param [IN] macHdr MAC header field
- * \param [IN] fCtrl MAC frame control field
- * \param [IN] fOpts MAC commands buffer
- * \param [IN] fPort MAC payload port
- * \param [IN] fBuffer MAC data buffer to be sent
- * \param [IN] fBufferSize MAC data buffer size
- * \retval status Status of the operation.
- */
-LoRaMacStatus_t PrepareFrame( LoRaMacHeader_t *macHdr, LoRaMacFrameCtrl_t *fCtrl, uint8_t fPort, void *fBuffer, uint16_t fBufferSize );
-
-/*
- * \brief Schedules the frame according to the duty cycle
- *
- * \retval Status of the operation
- */
-static LoRaMacStatus_t ScheduleTx( void );
-
-/*
- * \brief Calculates the back-off time for the band of a channel.
- *
- * \param [IN] channel The last Tx channel index
- */
-static void CalculateBackOff( uint8_t channel );
-
-/*!
- * \brief LoRaMAC layer prepared frame buffer transmission with channel specification
- *
- * \remark PrepareFrame must be called at least once before calling this
- * function.
- *
- * \param [IN] channel Channel to transmit on
- * \retval status Status of the operation.
- */
-LoRaMacStatus_t SendFrameOnChannel( uint8_t channel );
-
-/*!
- * \brief Sets the radio in continuous transmission mode
- *
- * \remark Uses the radio parameters set on the previous transmission.
- *
- * \param [IN] timeout Time in seconds while the radio is kept in continuous wave mode
- * \retval status Status of the operation.
- */
-LoRaMacStatus_t SetTxContinuousWave( uint16_t timeout );
-
-/*!
- * \brief Sets the radio in continuous transmission mode
- *
- * \remark Uses the radio parameters set on the previous transmission.
- *
- * \param [IN] timeout Time in seconds while the radio is kept in continuous wave mode
- * \param [IN] frequency RF frequency to be set.
- * \param [IN] power RF output power to be set.
- * \retval status Status of the operation.
- */
-LoRaMacStatus_t SetTxContinuousWave1( uint16_t timeout, uint32_t frequency, uint8_t power );
-
-/*!
- * \brief Resets MAC specific parameters to default
- */
-static void ResetMacParameters( void );
-
-/*!
- * \brief Resets MAC specific parameters to default
- *
- * \param [IN] fPort The fPort
- *
- * \retval [false: fPort not allowed, true: fPort allowed]
- */
-static bool IsFPortAllowed( uint8_t fPort );
-
-/*!
- * \brief Opens up a continuous RX 2 window. This is used for
- * class c devices.
- */
-static void OpenContinuousRx2Window( void );
-
-static IRAM_ATTR void OnRadioTxDone( void )
-{
- GetPhyParams_t getPhy;
- PhyParam_t phyParam;
- SetBandTxDoneParams_t txDone;
- TimerTime_t curTime = TimerGetCurrentTime( );
-
- if( LoRaMacDeviceClass != CLASS_C )
+ if( MacCtx.NvmCtx->DeviceClass != CLASS_C )
{
Radio.Sleep( );
}
- else
- {
- OpenContinuousRx2Window( );
- }
-
// Setup timers
- if( IsRxWindowsEnabled == true )
- {
- TimerSetValue( &RxWindowTimer1, RxWindow1Delay );
- TimerStart( &RxWindowTimer1 );
- if( LoRaMacDeviceClass != CLASS_C )
- {
- TimerSetValue( &RxWindowTimer2, RxWindow2Delay );
- TimerStart( &RxWindowTimer2 );
- }
- if( ( LoRaMacDeviceClass == CLASS_C ) || ( NodeAckRequested == true ) )
- {
- getPhy.Attribute = PHY_ACK_TIMEOUT;
- phyParam = RegionGetPhyParam( LoRaMacRegion, &getPhy );
- TimerSetValue( &AckTimeoutTimer, RxWindow2Delay + phyParam.Value );
- TimerStart( &AckTimeoutTimer );
- }
- }
- else
- {
- McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_OK;
- MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_RX2_TIMEOUT;
+ TimerSetValue( &MacCtx.RxWindowTimer1, MacCtx.RxWindow1Delay );
+ TimerStart( &MacCtx.RxWindowTimer1 );
+ TimerSetValue( &MacCtx.RxWindowTimer2, MacCtx.RxWindow2Delay );
+ TimerStart( &MacCtx.RxWindowTimer2 );
- if( LoRaMacFlags.Value == 0 )
- {
- LoRaMacFlags.Bits.McpsReq = 1;
- }
- LoRaMacFlags.Bits.MacDone = 1;
+ if( ( MacCtx.NvmCtx->DeviceClass == CLASS_C ) || ( MacCtx.NodeAckRequested == true ) )
+ {
+ getPhy.Attribute = PHY_ACK_TIMEOUT;
+ phyParam = RegionGetPhyParam( MacCtx.NvmCtx->Region, &getPhy );
+ TimerSetValue( &MacCtx.AckTimeoutTimer, MacCtx.RxWindow2Delay + phyParam.Value );
+ TimerStart( &MacCtx.AckTimeoutTimer );
}
- // Verify if the last uplink was a join request
- if( ( LoRaMacFlags.Bits.MlmeReq == 1 ) && ( MlmeConfirm.MlmeRequest == MLME_JOIN ) )
+ // Store last Tx channel
+ MacCtx.NvmCtx->LastTxChannel = MacCtx.Channel;
+ // Update last tx done time for the current channel
+ txDone.Channel = MacCtx.Channel;
+ if( MacCtx.NvmCtx->NetworkActivation == ACTIVATION_TYPE_NONE )
{
- LastTxIsJoinRequest = true;
+ txDone.Joined = false;
}
else
{
- LastTxIsJoinRequest = false;
+ txDone.Joined = true;
}
-
- // Store last Tx channel
- LastTxChannel = Channel;
- // Update last tx done time for the current channel
- txDone.Channel = Channel;
- txDone.Joined = IsLoRaMacNetworkJoined;
- txDone.LastTxDoneTime = curTime;
- RegionSetBandTxDone( LoRaMacRegion, &txDone );
+ txDone.LastTxDoneTime = TxDoneParams.CurTime;
+ RegionSetBandTxDone( MacCtx.NvmCtx->Region, &txDone );
// Update Aggregated last tx done time
- AggregatedLastTxDoneTime = curTime;
+ MacCtx.NvmCtx->LastTxDoneTime = TxDoneParams.CurTime;
- if( NodeAckRequested == false )
+ if( MacCtx.NodeAckRequested == false )
{
- McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_OK;
- ChannelsNbRepCounter++;
+ MacCtx.McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_OK;
}
}
static void PrepareRxDoneAbort( void )
{
- LoRaMacState |= LORAMAC_RX_ABORT;
+ MacCtx.MacState |= LORAMAC_RX_ABORT;
- if( NodeAckRequested )
+ if( MacCtx.NodeAckRequested == true )
{
- OnAckTimeoutTimerEvent( );
+ OnAckTimeoutTimerEvent( NULL );
}
- LoRaMacFlags.Bits.McpsInd = 1;
- LoRaMacFlags.Bits.MacDone = 1;
+ MacCtx.MacFlags.Bits.McpsInd = 1;
+ MacCtx.MacFlags.Bits.MacDone = 1;
- // Trig OnMacCheckTimerEvent call as soon as possible
- TimerSetValue( &MacStateCheckTimer, 1 );
- TimerStart( &MacStateCheckTimer );
+ UpdateRxSlotIdleState( );
}
-static void OnRadioRxDone( uint8_t *payload, uint32_t timestamp, uint16_t size, int16_t rssi, int8_t snr, uint8_t sf )
+static void ProcessRadioRxDone( void )
{
LoRaMacHeader_t macHdr;
- LoRaMacFrameCtrl_t fCtrl;
ApplyCFListParams_t applyCFList;
GetPhyParams_t getPhy;
PhyParam_t phyParam;
+ LoRaMacCryptoStatus_t macCryptoStatus = LORAMAC_CRYPTO_ERROR;
- uint8_t pktHeaderLen = 0;
- uint32_t address = 0;
- uint8_t appPayloadStartIndex = 0;
- uint8_t port = 0xFF;
- uint8_t frameLen = 0;
- uint32_t mic = 0;
- uint32_t micRx = 0;
-
- uint16_t sequenceCounter = 0;
- uint16_t sequenceCounterPrev = 0;
- uint16_t sequenceCounterDiff = 0;
- uint32_t downLinkCounter = 0;
+ LoRaMacMessageData_t macMsgData;
+ LoRaMacMessageJoinAccept_t macMsgJoinAccept;
+ uint8_t *payload = RxDoneParams.Payload;
+ uint16_t size = RxDoneParams.Size;
+ int16_t rssi = RxDoneParams.Rssi;
+ int8_t snr = RxDoneParams.Snr;
- MulticastParams_t *curMulticastParams = NULL;
- uint8_t *nwkSKey = LoRaMacNwkSKey;
- uint8_t *appSKey = LoRaMacAppSKey;
+ uint8_t pktHeaderLen = 0;
+ uint32_t downLinkCounter = 0;
+ uint32_t address = MacCtx.NvmCtx->DevAddr;
uint8_t multicast = 0;
-
- bool isMicOk = false;
-
- McpsConfirm.AckReceived = false;
- McpsIndication.TimeStamp = timestamp;
- McpsIndication.Rssi = rssi;
- McpsIndication.Snr = snr;
- McpsIndication.RxSlot = RxSlot;
- McpsIndication.Port = 0;
- McpsIndication.Multicast = 0;
- McpsIndication.FramePending = 0;
- McpsIndication.Buffer = NULL;
- McpsIndication.BufferSize = 0;
- McpsIndication.RxData = false;
- McpsIndication.AckReceived = false;
- McpsIndication.DownLinkCounter = 0;
- McpsIndication.McpsIndication = MCPS_UNCONFIRMED;
-
+ AddressIdentifier_t addrID = UNICAST_DEV_ADDR;
+ FCntIdentifier_t fCntID;
+
+ MacCtx.McpsConfirm.AckReceived = false;
+ MacCtx.McpsIndication.Rssi = rssi;
+ MacCtx.McpsIndication.Snr = snr;
+ MacCtx.McpsIndication.RxSlot = MacCtx.RxSlot;
+ MacCtx.McpsIndication.Port = 0;
+ MacCtx.McpsIndication.Multicast = 0;
+ MacCtx.McpsIndication.FramePending = 0;
+ MacCtx.McpsIndication.Buffer = NULL;
+ MacCtx.McpsIndication.BufferSize = 0;
+ MacCtx.McpsIndication.RxData = false;
+ MacCtx.McpsIndication.AckReceived = false;
+ MacCtx.McpsIndication.DownLinkCounter = 0;
+ MacCtx.McpsIndication.McpsIndication = MCPS_UNCONFIRMED;
+ MacCtx.McpsIndication.DevAddress = 0;
+ MacCtx.McpsIndication.DeviceTimeAnsReceived = false;
+
+ // Pycom: Setting TimeStamp
+ MacCtx.McpsIndication.TimeStamp = RxDoneParams.LastRxDone;
Radio.Sleep( );
- TimerStop( &RxWindowTimer2 );
+ TimerStop( &MacCtx.RxWindowTimer2 );
+
+ // This function must be called even if we are not in class b mode yet.
+ if( LoRaMacClassBRxBeacon( payload, size ) == true )
+ {
+ MacCtx.MlmeIndication.BeaconInfo.Rssi = rssi;
+ MacCtx.MlmeIndication.BeaconInfo.Snr = snr;
+ return;
+ }
+ // Check if we expect a ping or a multicast slot.
+ if( MacCtx.NvmCtx->DeviceClass == CLASS_B )
+ {
+ if( LoRaMacClassBIsPingExpected( ) == true )
+ {
+ LoRaMacClassBSetPingSlotState( PINGSLOT_STATE_CALC_PING_OFFSET );
+ LoRaMacClassBPingSlotTimerEvent( NULL );
+ MacCtx.McpsIndication.RxSlot = RX_SLOT_WIN_CLASS_B_PING_SLOT;
+ }
+ else if( LoRaMacClassBIsMulticastExpected( ) == true )
+ {
+ LoRaMacClassBSetMulticastSlotState( PINGSLOT_STATE_CALC_PING_OFFSET );
+ LoRaMacClassBMulticastSlotTimerEvent( NULL );
+ MacCtx.McpsIndication.RxSlot = RX_SLOT_WIN_CLASS_B_MULTICAST_SLOT;
+ }
+ }
macHdr.Value = payload[pktHeaderLen++];
switch( macHdr.Bits.MType )
{
case FRAME_TYPE_JOIN_ACCEPT:
- if( IsLoRaMacNetworkJoined == true )
+ macMsgJoinAccept.Buffer = payload;
+ macMsgJoinAccept.BufSize = size;
+
+ // Abort in case if the device isn't joined yet and no rejoin request is ongoing.
+ if( MacCtx.NvmCtx->NetworkActivation != ACTIVATION_TYPE_NONE )
{
- McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_ERROR;
+ MacCtx.McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_ERROR;
PrepareRxDoneAbort( );
return;
}
- LoRaMacJoinDecrypt( payload + 1, size - 1, LoRaMacAppKey, LoRaMacRxPayload + 1 );
-
- LoRaMacRxPayload[0] = macHdr.Value;
-
- LoRaMacJoinComputeMic( LoRaMacRxPayload, size - LORAMAC_MFR_LEN, LoRaMacAppKey, &mic );
+ macCryptoStatus = LoRaMacCryptoHandleJoinAccept( JOIN_REQ, SecureElementGetJoinEui( ), &macMsgJoinAccept );
- micRx |= ( uint32_t )LoRaMacRxPayload[size - LORAMAC_MFR_LEN];
- micRx |= ( ( uint32_t )LoRaMacRxPayload[size - LORAMAC_MFR_LEN + 1] << 8 );
- micRx |= ( ( uint32_t )LoRaMacRxPayload[size - LORAMAC_MFR_LEN + 2] << 16 );
- micRx |= ( ( uint32_t )LoRaMacRxPayload[size - LORAMAC_MFR_LEN + 3] << 24 );
-
- if( micRx == mic )
+ if( LORAMAC_CRYPTO_SUCCESS == macCryptoStatus )
{
- LoRaMacJoinComputeSKeys( LoRaMacAppKey, LoRaMacRxPayload + 1, LoRaMacDevNonce, LoRaMacNwkSKey, LoRaMacAppSKey );
-
- LoRaMacNetID = ( uint32_t )LoRaMacRxPayload[4];
- LoRaMacNetID |= ( ( uint32_t )LoRaMacRxPayload[5] << 8 );
- LoRaMacNetID |= ( ( uint32_t )LoRaMacRxPayload[6] << 16 );
+ // Network ID
+ MacCtx.NvmCtx->NetID = ( uint32_t ) macMsgJoinAccept.NetID[0];
+ MacCtx.NvmCtx->NetID |= ( ( uint32_t ) macMsgJoinAccept.NetID[1] << 8 );
+ MacCtx.NvmCtx->NetID |= ( ( uint32_t ) macMsgJoinAccept.NetID[2] << 16 );
- LoRaMacDevAddr = ( uint32_t )LoRaMacRxPayload[7];
- LoRaMacDevAddr |= ( ( uint32_t )LoRaMacRxPayload[8] << 8 );
- LoRaMacDevAddr |= ( ( uint32_t )LoRaMacRxPayload[9] << 16 );
- LoRaMacDevAddr |= ( ( uint32_t )LoRaMacRxPayload[10] << 24 );
+ // Device Address
+ MacCtx.NvmCtx->DevAddr = macMsgJoinAccept.DevAddr;
// DLSettings
- LoRaMacParams.Rx1DrOffset = ( LoRaMacRxPayload[11] >> 4 ) & 0x07;
- LoRaMacParams.Rx2Channel.Datarate = LoRaMacRxPayload[11] & 0x0F;
+ MacCtx.NvmCtx->MacParams.Rx1DrOffset = macMsgJoinAccept.DLSettings.Bits.RX1DRoffset;
+ MacCtx.NvmCtx->MacParams.Rx2Channel.Datarate = macMsgJoinAccept.DLSettings.Bits.RX2DataRate;
+ MacCtx.NvmCtx->MacParams.RxCChannel.Datarate = macMsgJoinAccept.DLSettings.Bits.RX2DataRate;
// RxDelay
- LoRaMacParams.ReceiveDelay1 = ( LoRaMacRxPayload[12] & 0x0F );
- if( LoRaMacParams.ReceiveDelay1 == 0 )
+ MacCtx.NvmCtx->MacParams.ReceiveDelay1 = macMsgJoinAccept.RxDelay;
+ if( MacCtx.NvmCtx->MacParams.ReceiveDelay1 == 0 )
{
- LoRaMacParams.ReceiveDelay1 = 1;
+ MacCtx.NvmCtx->MacParams.ReceiveDelay1 = 1;
}
- LoRaMacParams.ReceiveDelay1 *= 1000;
- LoRaMacParams.ReceiveDelay2 = LoRaMacParams.ReceiveDelay1 + 1000;
+ MacCtx.NvmCtx->MacParams.ReceiveDelay1 *= 1000;
+ MacCtx.NvmCtx->MacParams.ReceiveDelay2 = MacCtx.NvmCtx->MacParams.ReceiveDelay1 + 1000;
+
+ MacCtx.NvmCtx->Version.Fields.Minor = 0;
// Apply CF list
- applyCFList.Payload = &LoRaMacRxPayload[13];
+ applyCFList.Payload = macMsgJoinAccept.CFList;
// Size of the regular payload is 12. Plus 1 byte MHDR and 4 bytes MIC
applyCFList.Size = size - 17;
- RegionApplyCFList( LoRaMacRegion, &applyCFList );
+ RegionApplyCFList( MacCtx.NvmCtx->Region, &applyCFList );
+
+ MacCtx.NvmCtx->NetworkActivation = ACTIVATION_TYPE_OTAA;
- MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_OK;
- IsLoRaMacNetworkJoined = true;
+ // MLME handling
+ if( LoRaMacConfirmQueueIsCmdActive( MLME_JOIN ) == true )
+ {
+ LoRaMacConfirmQueueSetStatus( LORAMAC_EVENT_INFO_STATUS_OK, MLME_JOIN );
+ }
}
else
{
- MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_JOIN_FAIL;
+ // MLME handling
+ if( LoRaMacConfirmQueueIsCmdActive( MLME_JOIN ) == true )
+ {
+ LoRaMacConfirmQueueSetStatus( LORAMAC_EVENT_INFO_STATUS_JOIN_FAIL, MLME_JOIN );
+ }
}
break;
case FRAME_TYPE_DATA_CONFIRMED_DOWN:
+ MacCtx.McpsIndication.McpsIndication = MCPS_CONFIRMED;
+ // Intentional fall through
case FRAME_TYPE_DATA_UNCONFIRMED_DOWN:
+ // Check if the received payload size is valid
+ getPhy.UplinkDwellTime = MacCtx.NvmCtx->MacParams.DownlinkDwellTime;
+ getPhy.Datarate = MacCtx.McpsIndication.RxDatarate;
+ getPhy.Attribute = PHY_MAX_PAYLOAD;
+
+ // Get the maximum payload length
+ if( MacCtx.NvmCtx->RepeaterSupport == true )
+ {
+ getPhy.Attribute = PHY_MAX_PAYLOAD_REPEATER;
+ }
+ phyParam = RegionGetPhyParam( MacCtx.NvmCtx->Region, &getPhy );
+ if( MAX( 0, ( int16_t )( ( int16_t ) size - ( int16_t ) LORA_MAC_FRMPAYLOAD_OVERHEAD ) ) > ( int16_t )phyParam.Value )
{
- // Check if the received payload size is valid
- getPhy.UplinkDwellTime = LoRaMacParams.DownlinkDwellTime;
- getPhy.Datarate = McpsIndication.RxDatarate;
- getPhy.Attribute = PHY_MAX_PAYLOAD;
+ MacCtx.McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_ERROR;
+ PrepareRxDoneAbort( );
+ return;
+ }
+ macMsgData.Buffer = payload;
+ macMsgData.BufSize = size;
+ macMsgData.FRMPayload = MacCtx.RxPayload;
+ macMsgData.FRMPayloadSize = LORAMAC_PHY_MAXPAYLOAD;
- // Get the maximum payload length
- if( RepeaterSupport == true )
- {
- getPhy.Attribute = PHY_MAX_PAYLOAD_REPEATER;
- }
- phyParam = RegionGetPhyParam( LoRaMacRegion, &getPhy );
- if( MAX( 0, ( int16_t )( ( int16_t )size - ( int16_t )LORA_MAC_FRMPAYLOAD_OVERHEAD ) ) > phyParam.Value )
- {
- McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_ERROR;
- PrepareRxDoneAbort( );
- return;
- }
+ if( LORAMAC_PARSER_SUCCESS != LoRaMacParserData( &macMsgData ) )
+ {
+ MacCtx.McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_ERROR;
+ PrepareRxDoneAbort( );
+ return;
+ }
+
+ // Store device address
+ MacCtx.McpsIndication.DevAddress = macMsgData.FHDR.DevAddr;
- address = payload[pktHeaderLen++];
- address |= ( (uint32_t)payload[pktHeaderLen++] << 8 );
- address |= ( (uint32_t)payload[pktHeaderLen++] << 16 );
- address |= ( (uint32_t)payload[pktHeaderLen++] << 24 );
+ FType_t fType;
+ if( LORAMAC_STATUS_OK != DetermineFrameType( &macMsgData, &fType ) )
+ {
+ MacCtx.McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_ERROR;
+ PrepareRxDoneAbort( );
+ return;
+ }
- if( address != LoRaMacDevAddr )
+ //Check if it is a multicast message
+ multicast = 0;
+ downLinkCounter = 0;
+ for( uint8_t i = 0; i < LORAMAC_MAX_MC_CTX; i++ )
+ {
+ if( ( MacCtx.NvmCtx->MulticastChannelList[i].ChannelParams.Address == macMsgData.FHDR.DevAddr ) &&
+ ( MacCtx.NvmCtx->MulticastChannelList[i].ChannelParams.IsEnabled == true ) )
{
- curMulticastParams = MulticastChannels;
- while( curMulticastParams != NULL )
- {
- if( address == curMulticastParams->Address )
- {
- multicast = 1;
- nwkSKey = curMulticastParams->NwkSKey;
- appSKey = curMulticastParams->AppSKey;
- downLinkCounter = curMulticastParams->DownLinkCounter;
- break;
- }
- curMulticastParams = curMulticastParams->Next;
- }
- if( multicast == 0 )
+ multicast = 1;
+ addrID = MacCtx.NvmCtx->MulticastChannelList[i].ChannelParams.GroupID;
+ downLinkCounter = *( MacCtx.NvmCtx->MulticastChannelList[i].DownLinkCounter );
+ address = MacCtx.NvmCtx->MulticastChannelList[i].ChannelParams.Address;
+ if( MacCtx.NvmCtx->DeviceClass == CLASS_C )
{
- // We are not the destination of this frame.
- McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_ADDRESS_FAIL;
- PrepareRxDoneAbort( );
- return;
+ MacCtx.McpsIndication.RxSlot = RX_SLOT_WIN_CLASS_C_MULTICAST;
}
+ break;
}
- else
- {
- multicast = 0;
- nwkSKey = LoRaMacNwkSKey;
- appSKey = LoRaMacAppSKey;
- downLinkCounter = DownLinkCounter;
- }
-
- fCtrl.Value = payload[pktHeaderLen++];
-
- sequenceCounter = ( uint16_t )payload[pktHeaderLen++];
- sequenceCounter |= ( uint16_t )payload[pktHeaderLen++] << 8;
-
- appPayloadStartIndex = 8 + fCtrl.Bits.FOptsLen;
-
- micRx |= ( uint32_t )payload[size - LORAMAC_MFR_LEN];
- micRx |= ( ( uint32_t )payload[size - LORAMAC_MFR_LEN + 1] << 8 );
- micRx |= ( ( uint32_t )payload[size - LORAMAC_MFR_LEN + 2] << 16 );
- micRx |= ( ( uint32_t )payload[size - LORAMAC_MFR_LEN + 3] << 24 );
+ }
- sequenceCounterPrev = ( uint16_t )downLinkCounter;
- sequenceCounterDiff = ( sequenceCounter - sequenceCounterPrev );
+ // Get maximum allowed counter difference
+ getPhy.Attribute = PHY_MAX_FCNT_GAP;
+ phyParam = RegionGetPhyParam( MacCtx.NvmCtx->Region, &getPhy );
- if( sequenceCounterDiff < ( 1 << 15 ) )
+ // Get downlink frame counter value
+ macCryptoStatus = GetFCntDown( addrID, fType, &macMsgData, MacCtx.NvmCtx->Version, phyParam.Value, &fCntID, &downLinkCounter );
+ if( macCryptoStatus != LORAMAC_CRYPTO_SUCCESS )
+ {
+ if( macCryptoStatus == LORAMAC_CRYPTO_FAIL_FCNT_DUPLICATED )
{
- downLinkCounter += sequenceCounterDiff;
- LoRaMacComputeMic( payload, size - LORAMAC_MFR_LEN, nwkSKey, address, DOWN_LINK, downLinkCounter, &mic );
- if( micRx == mic )
+ // Catch the case of repeated downlink frame counter
+ MacCtx.McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_DOWNLINK_REPEATED;
+ if( ( MacCtx.NvmCtx->Version.Fields.Minor == 0 ) && ( macHdr.Bits.MType == FRAME_TYPE_DATA_CONFIRMED_DOWN ) && ( MacCtx.NvmCtx->LastRxMic == macMsgData.MIC ) )
{
- isMicOk = true;
+ MacCtx.NvmCtx->SrvAckRequested = true;
}
}
+ else if( macCryptoStatus == LORAMAC_CRYPTO_FAIL_MAX_GAP_FCNT )
+ {
+ // Lost too many frames
+ MacCtx.McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_DOWNLINK_TOO_MANY_FRAMES_LOSS;
+ }
else
{
- // check for sequence roll-over
- uint32_t downLinkCounterTmp = downLinkCounter + 0x10000 + ( int16_t )sequenceCounterDiff;
- LoRaMacComputeMic( payload, size - LORAMAC_MFR_LEN, nwkSKey, address, DOWN_LINK, downLinkCounterTmp, &mic );
- if( micRx == mic )
- {
- isMicOk = true;
- downLinkCounter = downLinkCounterTmp;
- }
+ // Other errors
+ MacCtx.McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_ERROR;
}
+ MacCtx.McpsIndication.DownLinkCounter = downLinkCounter;
+ PrepareRxDoneAbort( );
+ return;
+ }
- // Check for a the maximum allowed counter difference
- getPhy.Attribute = PHY_MAX_FCNT_GAP;
- phyParam = RegionGetPhyParam( LoRaMacRegion, &getPhy );
- if( sequenceCounterDiff >= phyParam.Value )
+ macCryptoStatus = LoRaMacCryptoUnsecureMessage( addrID, address, fCntID, downLinkCounter, &macMsgData );
+ if( macCryptoStatus != LORAMAC_CRYPTO_SUCCESS )
+ {
+ if( macCryptoStatus == LORAMAC_CRYPTO_FAIL_ADDRESS )
{
- McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_DOWNLINK_TOO_MANY_FRAMES_LOSS;
- McpsIndication.DownLinkCounter = downLinkCounter;
- PrepareRxDoneAbort( );
- return;
+ // We are not the destination of this frame.
+ MacCtx.McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_ADDRESS_FAIL;
}
-
- if( isMicOk == true )
+ else
{
- McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_OK;
- McpsIndication.Multicast = multicast;
- McpsIndication.FramePending = fCtrl.Bits.FPending;
- McpsIndication.Buffer = NULL;
- McpsIndication.BufferSize = 0;
- McpsIndication.DownLinkCounter = downLinkCounter;
-
- McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_OK;
-
- AdrAckCounter = 0;
- MacCommandsBufferToRepeatIndex = 0;
-
- // Update 32 bits downlink counter
- if( multicast == 1 )
- {
- McpsIndication.McpsIndication = MCPS_MULTICAST;
-
- if( ( curMulticastParams->DownLinkCounter == downLinkCounter ) &&
- ( curMulticastParams->DownLinkCounter != 0 ) )
- {
- McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_DOWNLINK_REPEATED;
- McpsIndication.DownLinkCounter = downLinkCounter;
- PrepareRxDoneAbort( );
- return;
- }
- curMulticastParams->DownLinkCounter = downLinkCounter;
- }
- else
- {
- if( macHdr.Bits.MType == FRAME_TYPE_DATA_CONFIRMED_DOWN )
- {
- SrvAckRequested = true;
- McpsIndication.McpsIndication = MCPS_CONFIRMED;
-
- if( ( DownLinkCounter == downLinkCounter ) &&
- ( DownLinkCounter != 0 ) )
- {
- // Duplicated confirmed downlink. Skip indication.
- // In this case, the MAC layer shall accept the MAC commands
- // which are included in the downlink retransmission.
- // It should not provide the same frame to the application
- // layer again. The MAC layer accepts the acknowledgement.
- LoRaMacFlags.Bits.McpsIndSkip = 1;
- }
- }
- else
- {
- SrvAckRequested = false;
- McpsIndication.McpsIndication = MCPS_UNCONFIRMED;
-
- if( ( DownLinkCounter == downLinkCounter ) &&
- ( DownLinkCounter != 0 ) )
- {
- McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_DOWNLINK_REPEATED;
- McpsIndication.DownLinkCounter = downLinkCounter;
- PrepareRxDoneAbort( );
- return;
- }
- }
- DownLinkCounter = downLinkCounter;
- }
+ // MIC calculation fail
+ MacCtx.McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_MIC_FAIL;
+ }
+ PrepareRxDoneAbort( );
+ return;
+ }
- // This must be done before parsing the payload and the MAC commands.
- // We need to reset the MacCommandsBufferIndex here, since we need
- // to take retransmissions and repetitions into account. Error cases
- // will be handled in function OnMacStateCheckTimerEvent.
- if( McpsConfirm.McpsRequest == MCPS_CONFIRMED )
- {
- if( fCtrl.Bits.Ack == 1 )
- {// Reset MacCommandsBufferIndex when we have received an ACK.
- MacCommandsBufferIndex = 0;
- // Update acknowledgement information
- McpsConfirm.AckReceived = fCtrl.Bits.Ack;
- McpsIndication.AckReceived = fCtrl.Bits.Ack;
- }
- }
- else
- {// Reset the variable if we have received any valid frame.
- MacCommandsBufferIndex = 0;
- }
+ // Frame is valid
+ MacCtx.McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_OK;
+ MacCtx.McpsIndication.Multicast = multicast;
+ MacCtx.McpsIndication.FramePending = macMsgData.FHDR.FCtrl.Bits.FPending;
+ MacCtx.McpsIndication.Buffer = NULL;
+ MacCtx.McpsIndication.BufferSize = 0;
+ MacCtx.McpsIndication.DownLinkCounter = downLinkCounter;
+ MacCtx.McpsIndication.AckReceived = macMsgData.FHDR.FCtrl.Bits.Ack;
+
+ MacCtx.McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_OK;
+ MacCtx.McpsConfirm.AckReceived = macMsgData.FHDR.FCtrl.Bits.Ack;
+
+ // Reset ADR ACK Counter only, when RX1 or RX2 slot
+ if( ( MacCtx.McpsIndication.RxSlot == RX_SLOT_WIN_1 ) ||
+ ( MacCtx.McpsIndication.RxSlot == RX_SLOT_WIN_2 ) )
+ {
+ MacCtx.NvmCtx->AdrAckCounter = 0;
+ }
- // Process payload and MAC commands
- if( ( ( size - 4 ) - appPayloadStartIndex ) > 0 )
- {
- port = payload[appPayloadStartIndex++];
- frameLen = ( size - 4 ) - appPayloadStartIndex;
-
- McpsIndication.Port = port;
-
- if( port == 0 )
- {
- // Only allow frames which do not have fOpts
- if( fCtrl.Bits.FOptsLen == 0 )
- {
- LoRaMacPayloadDecrypt( payload + appPayloadStartIndex,
- frameLen,
- nwkSKey,
- address,
- DOWN_LINK,
- downLinkCounter,
- LoRaMacRxPayload );
-
- // Decode frame payload MAC commands
- ProcessMacCommands( LoRaMacRxPayload, 0, frameLen, snr );
- }
- else
- {
- LoRaMacFlags.Bits.McpsIndSkip = 1;
- // This is not a valid frame. Drop it and reset the ACK bits
- McpsConfirm.AckReceived = false;
- McpsIndication.AckReceived = false;
- }
- }
- else
- {
- if( fCtrl.Bits.FOptsLen > 0 )
- {
- // Decode Options field MAC commands. Omit the fPort.
- ProcessMacCommands( payload, 8, appPayloadStartIndex - 1, snr );
- }
-
- LoRaMacPayloadDecrypt( payload + appPayloadStartIndex,
- frameLen,
- appSKey,
- address,
- DOWN_LINK,
- downLinkCounter,
- LoRaMacRxPayload );
-
- McpsIndication.Buffer = LoRaMacRxPayload;
- McpsIndication.BufferSize = frameLen;
- McpsIndication.RxData = true;
- }
- }
- else
+ // MCPS Indication and ack requested handling
+ if( multicast == 1 )
+ {
+ MacCtx.McpsIndication.McpsIndication = MCPS_MULTICAST;
+ }
+ else
+ {
+ if( macHdr.Bits.MType == FRAME_TYPE_DATA_CONFIRMED_DOWN )
+ {
+ MacCtx.NvmCtx->SrvAckRequested = true;
+ if( MacCtx.NvmCtx->Version.Fields.Minor == 0 )
{
- if( fCtrl.Bits.FOptsLen > 0 )
- {
- // Decode Options field MAC commands
- ProcessMacCommands( payload, 8, appPayloadStartIndex, snr );
- }
+ MacCtx.NvmCtx->LastRxMic = macMsgData.MIC;
}
-
- // Provide always an indication, skip the callback to the user application,
- // in case of a confirmed downlink retransmission.
- LoRaMacFlags.Bits.McpsInd = 1;
+ MacCtx.McpsIndication.McpsIndication = MCPS_CONFIRMED;
}
else
{
- McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_MIC_FAIL;
+ MacCtx.NvmCtx->SrvAckRequested = false;
+ MacCtx.McpsIndication.McpsIndication = MCPS_UNCONFIRMED;
+ }
+ }
- PrepareRxDoneAbort( );
- return;
+ RemoveMacCommands( MacCtx.McpsIndication.RxSlot, macMsgData.FHDR.FCtrl, MacCtx.McpsConfirm.McpsRequest );
+
+ switch( fType )
+ {
+ case FRAME_TYPE_A:
+ { /* +----------+------+-------+--------------+
+ * | FOptsLen | Fopt | FPort | FRMPayload |
+ * +----------+------+-------+--------------+
+ * | > 0 | X | > 0 | X |
+ * +----------+------+-------+--------------+
+ */
+
+ // Decode MAC commands in FOpts field
+ ProcessMacCommands( macMsgData.FHDR.FOpts, 0, macMsgData.FHDR.FCtrl.Bits.FOptsLen, snr, MacCtx.McpsIndication.RxSlot );
+ MacCtx.McpsIndication.Port = macMsgData.FPort;
+ MacCtx.McpsIndication.Buffer = macMsgData.FRMPayload;
+ MacCtx.McpsIndication.BufferSize = macMsgData.FRMPayloadSize;
+ MacCtx.McpsIndication.RxData = true;
+ break;
+ }
+ case FRAME_TYPE_B:
+ { /* +----------+------+-------+--------------+
+ * | FOptsLen | Fopt | FPort | FRMPayload |
+ * +----------+------+-------+--------------+
+ * | > 0 | X | - | - |
+ * +----------+------+-------+--------------+
+ */
+
+ // Decode MAC commands in FOpts field
+ ProcessMacCommands( macMsgData.FHDR.FOpts, 0, macMsgData.FHDR.FCtrl.Bits.FOptsLen, snr, MacCtx.McpsIndication.RxSlot );
+ MacCtx.McpsIndication.Port = macMsgData.FPort;
+ break;
+ }
+ case FRAME_TYPE_C:
+ { /* +----------+------+-------+--------------+
+ * | FOptsLen | Fopt | FPort | FRMPayload |
+ * +----------+------+-------+--------------+
+ * | = 0 | - | = 0 | MAC commands |
+ * +----------+------+-------+--------------+
+ */
+
+ // Decode MAC commands in FRMPayload
+ ProcessMacCommands( macMsgData.FRMPayload, 0, macMsgData.FRMPayloadSize, snr, MacCtx.McpsIndication.RxSlot );
+ MacCtx.McpsIndication.Port = macMsgData.FPort;
+ break;
+ }
+ case FRAME_TYPE_D:
+ { /* +----------+------+-------+--------------+
+ * | FOptsLen | Fopt | FPort | FRMPayload |
+ * +----------+------+-------+--------------+
+ * | = 0 | - | > 0 | X |
+ * +----------+------+-------+--------------+
+ */
+
+ // No MAC commands just application payload
+ MacCtx.McpsIndication.Port = macMsgData.FPort;
+ MacCtx.McpsIndication.Buffer = macMsgData.FRMPayload;
+ MacCtx.McpsIndication.BufferSize = macMsgData.FRMPayloadSize;
+ MacCtx.McpsIndication.RxData = true;
+ break;
}
+ default:
+ MacCtx.McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_ERROR;
+ PrepareRxDoneAbort( );
+ break;
}
+
+ // Provide always an indication, skip the callback to the user application,
+ // in case of a confirmed downlink retransmission.
+ MacCtx.MacFlags.Bits.McpsInd = 1;
+
break;
case FRAME_TYPE_PROPRIETARY:
- {
- memcpy1( LoRaMacRxPayload, &payload[pktHeaderLen], size );
+ memcpy1( MacCtx.RxPayload, &payload[pktHeaderLen], size - pktHeaderLen );
- McpsIndication.McpsIndication = MCPS_PROPRIETARY;
- McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_OK;
- McpsIndication.Buffer = LoRaMacRxPayload;
- McpsIndication.BufferSize = size - pktHeaderLen;
+ MacCtx.McpsIndication.McpsIndication = MCPS_PROPRIETARY;
+ MacCtx.McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_OK;
+ MacCtx.McpsIndication.Buffer = MacCtx.RxPayload;
+ MacCtx.McpsIndication.BufferSize = size - pktHeaderLen;
- LoRaMacFlags.Bits.McpsInd = 1;
- break;
- }
+ MacCtx.MacFlags.Bits.McpsInd = 1;
+ break;
default:
- McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_ERROR;
+ MacCtx.McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_ERROR;
PrepareRxDoneAbort( );
break;
}
// Verify if we need to disable the AckTimeoutTimer
- CheckToDisableAckTimeout( NodeAckRequested, LoRaMacDeviceClass, McpsConfirm.AckReceived,
- AckTimeoutRetriesCounter, AckTimeoutRetries );
-
- if( AckTimeoutTimer.IsRunning == false )
- {// Procedure is completed when the AckTimeoutTimer is not running anymore
- LoRaMacFlags.Bits.MacDone = 1;
-
- // Trig OnMacCheckTimerEvent call as soon as possible
- TimerSetValue( &MacStateCheckTimer, 1 );
- TimerStart( &MacStateCheckTimer );
+ if( MacCtx.NodeAckRequested == true )
+ {
+ if( MacCtx.McpsConfirm.AckReceived == true )
+ {
+ OnAckTimeoutTimerEvent( NULL );
+ }
}
+ else
+ {
+ if( MacCtx.NvmCtx->DeviceClass == CLASS_C )
+ {
+ OnAckTimeoutTimerEvent( NULL );
+ }
+ }
+ MacCtx.MacFlags.Bits.MacDone = 1;
+
+ UpdateRxSlotIdleState( );
}
-static void OnRadioTxTimeout( void )
+static void ProcessRadioTxTimeout( void )
{
- if( LoRaMacDeviceClass != CLASS_C )
+ if( MacCtx.NvmCtx->DeviceClass != CLASS_C )
{
Radio.Sleep( );
}
- else
+ UpdateRxSlotIdleState( );
+
+ MacCtx.McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT;
+ LoRaMacConfirmQueueSetStatusCmn( LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT );
+ if( MacCtx.NodeAckRequested == true )
{
- OpenContinuousRx2Window( );
+ MacCtx.AckTimeoutRetry = true;
}
-
- McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT;
- MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT;
- LoRaMacFlags.Bits.MacDone = 1;
+ MacCtx.MacFlags.Bits.MacDone = 1;
}
-static void OnRadioRxError( void )
+static void HandleRadioRxErrorTimeout( LoRaMacEventInfoStatus_t rx1EventInfoStatus, LoRaMacEventInfoStatus_t rx2EventInfoStatus )
{
- if( LoRaMacDeviceClass != CLASS_C )
+ bool classBRx = false;
+
+ if( MacCtx.NvmCtx->DeviceClass != CLASS_C )
{
Radio.Sleep( );
}
- if( RxSlot == 0 )
+ if( LoRaMacClassBIsBeaconExpected( ) == true )
{
- if( NodeAckRequested == true )
+ LoRaMacClassBSetBeaconState( BEACON_STATE_TIMEOUT );
+ LoRaMacClassBBeaconTimerEvent( NULL );
+ classBRx = true;
+ }
+ if( MacCtx.NvmCtx->DeviceClass == CLASS_B )
+ {
+ if( LoRaMacClassBIsPingExpected( ) == true )
{
- McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_RX1_ERROR;
+ LoRaMacClassBSetPingSlotState( PINGSLOT_STATE_CALC_PING_OFFSET );
+ LoRaMacClassBPingSlotTimerEvent( NULL );
+ classBRx = true;
}
- MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_RX1_ERROR;
-
- if( TimerGetElapsedTime( AggregatedLastTxDoneTime ) >= RxWindow2Delay + 50)
+ if( LoRaMacClassBIsMulticastExpected( ) == true )
{
- LoRaMacFlags.Bits.MacDone = 1;
+ LoRaMacClassBSetMulticastSlotState( PINGSLOT_STATE_CALC_PING_OFFSET );
+ LoRaMacClassBMulticastSlotTimerEvent( NULL );
+ classBRx = true;
}
}
- else
+
+ if( classBRx == false )
{
- if( NodeAckRequested == true )
+ if( MacCtx.RxSlot == RX_SLOT_WIN_1 )
{
- McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_RX2_ERROR;
- }
- MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_RX2_ERROR;
- LoRaMacFlags.Bits.MacDone = 1;
- }
+ if( MacCtx.NodeAckRequested == true )
+ {
+ MacCtx.McpsConfirm.Status = rx1EventInfoStatus;
+ }
+ LoRaMacConfirmQueueSetStatusCmn( rx1EventInfoStatus );
- if( LoRaMacDeviceClass == CLASS_C )
- {
- OpenContinuousRx2Window( );
- }
-}
+ if( TimerGetElapsedTime( MacCtx.NvmCtx->LastTxDoneTime ) >= MacCtx.RxWindow2Delay )
+ {
+ TimerStop( &MacCtx.RxWindowTimer2 );
+ MacCtx.MacFlags.Bits.MacDone = 1;
+ }
+ }
+ else
+ {
+ if( MacCtx.NodeAckRequested == true )
+ {
+ MacCtx.McpsConfirm.Status = rx2EventInfoStatus;
+ }
+ LoRaMacConfirmQueueSetStatusCmn( rx2EventInfoStatus );
-static void OnRadioRxTimeout( void )
-{
- if( LoRaMacDeviceClass != CLASS_C )
- {
- Radio.Sleep( );
- }
- else
- {
- OnRxWindow2TimerEvent( );
+ if( MacCtx.NvmCtx->DeviceClass != CLASS_C )
+ {
+ MacCtx.MacFlags.Bits.MacDone = 1;
+ }
+ }
}
- if( RxSlot == 0 )
+ UpdateRxSlotIdleState( );
+}
+
+static void ProcessRadioRxError( void )
+{
+ HandleRadioRxErrorTimeout( LORAMAC_EVENT_INFO_STATUS_RX1_ERROR, LORAMAC_EVENT_INFO_STATUS_RX2_ERROR );
+}
+
+static void ProcessRadioRxTimeout( void )
+{
+ HandleRadioRxErrorTimeout( LORAMAC_EVENT_INFO_STATUS_RX1_TIMEOUT, LORAMAC_EVENT_INFO_STATUS_RX2_TIMEOUT );
+}
+
+static void LoRaMacHandleIrqEvents( void )
+{
+ LoRaMacRadioEvents_t events;
+
+ CRITICAL_SECTION_BEGIN( );
+ events = LoRaMacRadioEvents;
+ LoRaMacRadioEvents.Value = 0;
+ CRITICAL_SECTION_END( );
+
+ if( events.Value != 0 )
{
- if( NodeAckRequested == true )
+ if( events.Events.TxDone == 1 )
{
- McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_RX1_TIMEOUT;
+ ProcessRadioTxDone( );
}
- MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_RX1_TIMEOUT;
-
- if( TimerGetElapsedTime( AggregatedLastTxDoneTime ) >= RxWindow2Delay + 50)
+ if( events.Events.RxDone == 1 )
{
- LoRaMacFlags.Bits.MacDone = 1;
+ ProcessRadioRxDone( );
}
- }
- else
- {
- if( NodeAckRequested == true )
+ if( events.Events.TxTimeout == 1 )
{
- McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_RX2_TIMEOUT;
+ ProcessRadioTxTimeout( );
}
- MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_RX2_TIMEOUT;
-
- if( LoRaMacDeviceClass != CLASS_C )
+ if( events.Events.RxError == 1 )
+ {
+ ProcessRadioRxError( );
+ }
+ if( events.Events.RxTimeout == 1 )
{
- LoRaMacFlags.Bits.MacDone = 1;
+ ProcessRadioRxTimeout( );
}
}
+}
- if( LoRaMacDeviceClass == CLASS_C )
+bool LoRaMacIsBusy( void )
+{
+ if( ( MacCtx.MacState == LORAMAC_IDLE ) &&
+ ( MacCtx.AllowRequests == LORAMAC_REQUEST_HANDLING_ON ) )
{
- OpenContinuousRx2Window( );
+ return false;
}
+ return true;
}
-static void OnMacStateCheckTimerEvent( void )
+static void LoRaMacEnableRequests( LoRaMacRequestHandling_t requestState )
{
- GetPhyParams_t getPhy;
- PhyParam_t phyParam;
- bool txTimeout = false;
+ MacCtx.AllowRequests = requestState;
+}
- TimerStop( &MacStateCheckTimer );
+static void LoRaMacHandleRequestEvents( void )
+{
+ // Handle events
+ LoRaMacFlags_t reqEvents = MacCtx.MacFlags;
- if( LoRaMacFlags.Bits.MacDone == 1 )
+ if( MacCtx.MacState == LORAMAC_IDLE )
{
- if( ( LoRaMacState & LORAMAC_RX_ABORT ) == LORAMAC_RX_ABORT )
+ // Update event bits
+ if( MacCtx.MacFlags.Bits.McpsReq == 1 )
{
- LoRaMacState &= ~LORAMAC_RX_ABORT;
- LoRaMacState &= ~LORAMAC_TX_RUNNING;
+ MacCtx.MacFlags.Bits.McpsReq = 0;
}
- if( ( LoRaMacFlags.Bits.MlmeReq == 1 ) || ( ( LoRaMacFlags.Bits.McpsReq == 1 ) ) )
+ if( MacCtx.MacFlags.Bits.MlmeReq == 1 )
{
- if( ( McpsConfirm.Status == LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT ) ||
- ( MlmeConfirm.Status == LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT ) )
- {
- // Stop transmit cycle due to tx timeout.
- LoRaMacState &= ~LORAMAC_TX_RUNNING;
- MacCommandsBufferIndex = 0;
- McpsConfirm.NbRetries = AckTimeoutRetriesCounter;
- McpsConfirm.AckReceived = false;
- McpsConfirm.TxTimeOnAir = 0;
- txTimeout = true;
- }
+ MacCtx.MacFlags.Bits.MlmeReq = 0;
}
- if( ( NodeAckRequested == false ) && ( txTimeout == false ) )
+ // Allow requests again
+ LoRaMacEnableRequests( LORAMAC_REQUEST_HANDLING_ON );
+
+ // Handle callbacks
+ if( reqEvents.Bits.McpsReq == 1 )
{
- if( ( LoRaMacFlags.Bits.MlmeReq == 1 ) || ( ( LoRaMacFlags.Bits.McpsReq == 1 ) ) )
- {
- if( ( LoRaMacFlags.Bits.MlmeReq == 1 ) && ( MlmeConfirm.MlmeRequest == MLME_JOIN ) )
- {// Procedure for the join request
- MlmeConfirm.NbRetries = JoinRequestTrials;
+ MacCtx.MacPrimitives->MacMcpsConfirm( &MacCtx.McpsConfirm );
+ }
- if( MlmeConfirm.Status == LORAMAC_EVENT_INFO_STATUS_OK )
- {// Node joined successfully
- UpLinkCounter = 0;
- ChannelsNbRepCounter = 0;
- LoRaMacState &= ~LORAMAC_TX_RUNNING;
- }
- else
- {
- // Pycom: Do not resend join requests
-
- // if( JoinRequestTrials >= MaxJoinRequestTrials )
- // {
- LoRaMacState &= ~LORAMAC_TX_RUNNING;
- // }
- // else
- // {
- // LoRaMacFlags.Bits.MacDone = 0;
- // // Sends the same frame again
- // OnTxDelayedTimerEvent( );
- // }
- }
- }
- else
- {// Procedure for all other frames
- if( ( ChannelsNbRepCounter >= LoRaMacParams.ChannelsNbRep ) || ( LoRaMacFlags.Bits.McpsInd == 1 ) )
- {
- if( LoRaMacFlags.Bits.McpsInd == 0 )
- { // Maximum repetitions without downlink. Reset MacCommandsBufferIndex. Increase ADR Ack counter.
- // Only process the case when the MAC did not receive a downlink.
- MacCommandsBufferIndex = 0;
- AdrAckCounter++;
- }
+ if( reqEvents.Bits.MlmeReq == 1 )
+ {
+ LoRaMacConfirmQueueHandleCb( &MacCtx.MlmeConfirm );
+ if( LoRaMacConfirmQueueGetCnt( ) > 0 )
+ {
+ MacCtx.MacFlags.Bits.MlmeReq = 1;
+ }
+ }
- ChannelsNbRepCounter = 0;
+ // Start beaconing again
+ LoRaMacClassBResumeBeaconing( );
- if( IsUpLinkCounterFixed == false )
- {
- UpLinkCounter++;
- }
+ // Procedure done. Reset variables.
+ MacCtx.MacFlags.Bits.MacDone = 0;
+ }
+}
- LoRaMacState &= ~LORAMAC_TX_RUNNING;
- }
- else
- {
- LoRaMacFlags.Bits.MacDone = 0;
- // Sends the same frame again
- OnTxDelayedTimerEvent( );
- }
- }
- }
+static void LoRaMacHandleScheduleUplinkEvent( void )
+{
+ // Handle events
+ if( MacCtx.MacState == LORAMAC_IDLE )
+ {
+ // Verify if sticky MAC commands are pending or not
+ bool isStickyMacCommandPending = false;
+ LoRaMacCommandsStickyCmdsPending( &isStickyMacCommandPending );
+ if( isStickyMacCommandPending == true )
+ {// Setup MLME indication
+ SetMlmeScheduleUplinkIndication( );
}
+ }
+}
- if( LoRaMacFlags.Bits.McpsInd == 1 )
- {// Procedure if we received a frame
- if( ( McpsConfirm.AckReceived == true ) || ( AckTimeoutRetriesCounter > AckTimeoutRetries ) )
- {
- AckTimeoutRetry = false;
- NodeAckRequested = false;
- if( IsUpLinkCounterFixed == false )
- {
- UpLinkCounter++;
- }
- McpsConfirm.NbRetries = AckTimeoutRetriesCounter;
+static void LoRaMacHandleIndicationEvents( void )
+{
+ // Handle MLME indication
+ if( MacCtx.MacFlags.Bits.MlmeInd == 1 )
+ {
+ MacCtx.MacFlags.Bits.MlmeInd = 0;
+ MacCtx.MacPrimitives->MacMlmeIndication( &MacCtx.MlmeIndication );
+ }
- LoRaMacState &= ~LORAMAC_TX_RUNNING;
- }
- }
+ if( MacCtx.MacFlags.Bits.MlmeSchedUplinkInd == 1 )
+ {
+ MlmeIndication_t schduleUplinkIndication;
+ schduleUplinkIndication.MlmeIndication = MLME_SCHEDULE_UPLINK;
+ schduleUplinkIndication.Status = LORAMAC_EVENT_INFO_STATUS_OK;
+
+ MacCtx.MacPrimitives->MacMlmeIndication( &schduleUplinkIndication );
+ MacCtx.MacFlags.Bits.MlmeSchedUplinkInd = 0;
+ }
+
+ // Handle MCPS indication
+ if( MacCtx.MacFlags.Bits.McpsInd == 1 )
+ {
+ MacCtx.MacFlags.Bits.McpsInd = 0;
+ MacCtx.MacPrimitives->MacMcpsIndication( &MacCtx.McpsIndication );
+ }
+}
- if( ( AckTimeoutRetry == true ) && ( ( LoRaMacState & LORAMAC_TX_DELAYED ) == 0 ) )
- {// Retransmissions procedure for confirmed uplinks
- AckTimeoutRetry = false;
- if( ( AckTimeoutRetriesCounter < AckTimeoutRetries ) && ( AckTimeoutRetriesCounter <= MAX_ACK_RETRIES ) )
+static void LoRaMacHandleMcpsRequest( void )
+{
+ // Handle MCPS uplinks
+ if( MacCtx.MacFlags.Bits.McpsReq == 1 )
+ {
+ bool stopRetransmission = false;
+ bool waitForRetransmission = false;
+
+ if( ( MacCtx.McpsConfirm.McpsRequest == MCPS_UNCONFIRMED ) ||
+ ( MacCtx.McpsConfirm.McpsRequest == MCPS_PROPRIETARY ) )
+ {
+ stopRetransmission = CheckRetransUnconfirmedUplink( );
+ }
+ else if( MacCtx.McpsConfirm.McpsRequest == MCPS_CONFIRMED )
+ {
+ if( MacCtx.AckTimeoutRetry == true )
{
- AckTimeoutRetriesCounter++;
+ stopRetransmission = CheckRetransConfirmedUplink( );
- if( ( AckTimeoutRetriesCounter % 2 ) == 1 )
- {
- getPhy.Attribute = PHY_NEXT_LOWER_TX_DR;
- getPhy.UplinkDwellTime = LoRaMacParams.UplinkDwellTime;
- getPhy.Datarate = LoRaMacParams.ChannelsDatarate;
- phyParam = RegionGetPhyParam( LoRaMacRegion, &getPhy );
- LoRaMacParams.ChannelsDatarate = phyParam.Value;
- }
- // Try to send the frame again
- if( ScheduleTx( ) == LORAMAC_STATUS_OK )
+ if( MacCtx.NvmCtx->Version.Fields.Minor == 0 )
{
- LoRaMacFlags.Bits.MacDone = 0;
- }
- else
- {
- // The DR is not applicable for the payload size
- McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_TX_DR_PAYLOAD_SIZE_ERROR;
-
- MacCommandsBufferIndex = 0;
- LoRaMacState &= ~LORAMAC_TX_RUNNING;
- NodeAckRequested = false;
- McpsConfirm.AckReceived = false;
- McpsConfirm.NbRetries = AckTimeoutRetriesCounter;
- McpsConfirm.Datarate = LoRaMacParams.ChannelsDatarate;
- if( IsUpLinkCounterFixed == false )
+ if( stopRetransmission == false )
+ {
+ AckTimeoutRetriesProcess( );
+ }
+ else
{
- UpLinkCounter++;
+ AckTimeoutRetriesFinalize( );
}
}
}
else
{
- RegionInitDefaults( LoRaMacRegion, INIT_TYPE_RESTORE );
-
- LoRaMacState &= ~LORAMAC_TX_RUNNING;
-
- MacCommandsBufferIndex = 0;
- NodeAckRequested = false;
- McpsConfirm.AckReceived = false;
- McpsConfirm.NbRetries = AckTimeoutRetriesCounter;
- if( IsUpLinkCounterFixed == false )
- {
- UpLinkCounter++;
- }
+ waitForRetransmission = true;
}
}
- }
- // Handle reception for Class B and Class C
- if( ( LoRaMacState & LORAMAC_RX ) == LORAMAC_RX )
- {
- LoRaMacState &= ~LORAMAC_RX;
- }
- if( LoRaMacFlags.Bits.McpsInd == 1 )
- {
- if( LoRaMacDeviceClass == CLASS_C )
- {// Activate RX2 window for Class C
- OnRxWindow2TimerEvent( );
+ if( stopRetransmission == true )
+ {// Stop retransmission
+ TimerStop( &MacCtx.TxDelayedTimer );
+ MacCtx.MacState &= ~LORAMAC_TX_DELAYED;
+ StopRetransmission( );
}
- if( LoRaMacFlags.Bits.McpsIndSkip == 0 )
- {
- LoRaMacPrimitives->MacMcpsIndication( &McpsIndication );
+ else if( waitForRetransmission == false )
+ {// Arrange further retransmission
+ MacCtx.MacFlags.Bits.MacDone = 0;
+ // Reset the state of the AckTimeout
+ MacCtx.AckTimeoutRetry = false;
+ // Sends the same frame again
+ OnTxDelayedTimerEvent( NULL );
}
- LoRaMacFlags.Bits.McpsIndSkip = 0;
- LoRaMacFlags.Bits.McpsInd = 0;
}
+}
- if( LoRaMacState == LORAMAC_IDLE )
+static void LoRaMacHandleMlmeRequest( void )
+{
+ // Handle join request
+ if( MacCtx.MacFlags.Bits.MlmeReq == 1 )
{
- if( LoRaMacFlags.Bits.McpsReq == 1 )
+ if( ( LoRaMacConfirmQueueIsCmdActive( MLME_JOIN ) == true ) )
{
- LoRaMacPrimitives->MacMcpsConfirm( &McpsConfirm );
- LoRaMacFlags.Bits.McpsReq = 0;
+ if( LoRaMacConfirmQueueGetStatus( MLME_JOIN ) == LORAMAC_EVENT_INFO_STATUS_OK )
+ {// Node joined successfully
+ MacCtx.ChannelsNbTransCounter = 0;
+ }
+ MacCtx.MacState &= ~LORAMAC_TX_RUNNING;
}
-
- if( LoRaMacFlags.Bits.MlmeReq == 1 )
+ else if( ( LoRaMacConfirmQueueIsCmdActive( MLME_TXCW ) == true ) ||
+ ( LoRaMacConfirmQueueIsCmdActive( MLME_TXCW_1 ) == true ) )
{
- LoRaMacPrimitives->MacMlmeConfirm( &MlmeConfirm );
- LoRaMacFlags.Bits.MlmeReq = 0;
- }
-
- // Verify if sticky MAC commands are pending or not
- if( IsStickyMacCommandPending( ) == true )
- {// Setup MLME indication
- SetMlmeScheduleUplinkIndication( );
+ MacCtx.MacState &= ~LORAMAC_TX_RUNNING;
}
-
- // Procedure done. Reset variables.
- LoRaMacFlags.Bits.MacDone = 0;
- }
- else
- {
- // Operation not finished restart timer
- TimerSetValue( &MacStateCheckTimer, MAC_STATE_CHECK_TIMEOUT );
- TimerStart( &MacStateCheckTimer );
}
+}
- // Handle MCPS indication
- if( LoRaMacFlags.Bits.McpsInd == 1 )
+static uint8_t LoRaMacCheckForBeaconAcquisition( void )
+{
+ if( ( LoRaMacConfirmQueueIsCmdActive( MLME_BEACON_ACQUISITION ) == true ) &&
+ ( MacCtx.MacFlags.Bits.McpsReq == 0 ) )
{
- LoRaMacFlags.Bits.McpsInd = 0;
- if( LoRaMacDeviceClass == CLASS_C )
- {// Activate RX2 window for Class C
- OpenContinuousRx2Window( );
- }
- if( LoRaMacFlags.Bits.McpsIndSkip == 0 )
+ if( MacCtx.MacFlags.Bits.MlmeReq == 1 )
{
- LoRaMacPrimitives->MacMcpsIndication( &McpsIndication );
+ MacCtx.MacState &= ~LORAMAC_TX_RUNNING;
+ return 0x01;
}
- LoRaMacFlags.Bits.McpsIndSkip = 0;
}
+ return 0x00;
+}
- // Handle MLME indication
- if( LoRaMacFlags.Bits.MlmeInd == 1 )
+static void LoRaMacCheckForRxAbort( void )
+{
+ // A error occurs during receiving
+ if( ( MacCtx.MacState & LORAMAC_RX_ABORT ) == LORAMAC_RX_ABORT )
{
- LoRaMacFlags.Bits.MlmeInd = 0;
- LoRaMacPrimitives->MacMlmeIndication( &MlmeIndication );
+ MacCtx.MacState &= ~LORAMAC_RX_ABORT;
+ MacCtx.MacState &= ~LORAMAC_TX_RUNNING;
}
}
-static void OnTxDelayedTimerEvent( void )
+
+void LoRaMacProcess( void )
{
- LoRaMacHeader_t macHdr;
- LoRaMacFrameCtrl_t fCtrl;
- AlternateDrParams_t altDr;
+ uint8_t noTx = false;
- TimerStop( &TxDelayedTimer );
- LoRaMacState &= ~LORAMAC_TX_DELAYED;
+ LoRaMacHandleIrqEvents( );
+ LoRaMacClassBProcess( );
- if( ( LoRaMacFlags.Bits.MlmeReq == 1 ) && ( MlmeConfirm.MlmeRequest == MLME_JOIN ) )
+ // MAC proceeded a state and is ready to check
+ if( MacCtx.MacFlags.Bits.MacDone == 1 )
{
- ResetMacParameters( );
-
- altDr.NbTrials = JoinRequestTrials + 1;
- LoRaMacParams.ChannelsDatarate = RegionAlternateDr( LoRaMacRegion, &altDr );
+ LoRaMacEnableRequests( LORAMAC_REQUEST_HANDLING_OFF );
+ LoRaMacCheckForRxAbort( );
- macHdr.Value = 0;
- macHdr.Bits.MType = FRAME_TYPE_JOIN_REQ;
-
- fCtrl.Value = 0;
- fCtrl.Bits.Adr = AdrCtrlOn;
+ // An error occurs during transmitting
+ if( IsRequestPending( ) > 0 )
+ {
+ noTx |= LoRaMacCheckForBeaconAcquisition( );
+ }
- /* In case of join request retransmissions, the stack must prepare
- * the frame again, because the network server keeps track of the random
- * LoRaMacDevNonce values to prevent reply attacks. */
- PrepareFrame( &macHdr, &fCtrl, 0, NULL, 0 );
+ if( noTx == 0x00 )
+ {
+ LoRaMacHandleMlmeRequest( );
+ LoRaMacHandleMcpsRequest( );
+ }
+ LoRaMacHandleRequestEvents( );
+ LoRaMacHandleScheduleUplinkEvent( );
+ LoRaMacEnableRequests( LORAMAC_REQUEST_HANDLING_ON );
+ }
+ LoRaMacHandleIndicationEvents( );
+ if( MacCtx.RxSlot == RX_SLOT_WIN_CLASS_C )
+ {
+ OpenContinuousRxCWindow( );
}
-
- ScheduleTx( );
}
-static void OnRxWindow1TimerEvent( void )
+static void OnTxDelayedTimerEvent( void* context )
{
- TimerStop( &RxWindowTimer1 );
- RxSlot = 0;
+ TimerStop( &MacCtx.TxDelayedTimer );
+ MacCtx.MacState &= ~LORAMAC_TX_DELAYED;
- RxWindow1Config.Channel = Channel;
- RxWindow1Config.DrOffset = LoRaMacParams.Rx1DrOffset;
- RxWindow1Config.DownlinkDwellTime = LoRaMacParams.DownlinkDwellTime;
- RxWindow1Config.RepeaterSupport = RepeaterSupport;
- RxWindow1Config.RxContinuous = false;
- RxWindow1Config.Window = RxSlot;
-
- if( LoRaMacDeviceClass == CLASS_C )
+ // Schedule frame, allow delayed frame transmissions
+ switch( ScheduleTx( true ) )
{
- Radio.Standby( );
+ case LORAMAC_STATUS_OK:
+ case LORAMAC_STATUS_DUTYCYCLE_RESTRICTED:
+ {
+ break;
+ }
+ default:
+ {
+ // Stop retransmission attempt
+ MacCtx.McpsConfirm.Datarate = MacCtx.NvmCtx->MacParams.ChannelsDatarate;
+ MacCtx.McpsConfirm.NbRetries = MacCtx.AckTimeoutRetriesCounter;
+ MacCtx.McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_TX_DR_PAYLOAD_SIZE_ERROR;
+ LoRaMacConfirmQueueSetStatusCmn( LORAMAC_EVENT_INFO_STATUS_TX_DR_PAYLOAD_SIZE_ERROR );
+ StopRetransmission( );
+ break;
+ }
}
+}
- RegionRxConfig( LoRaMacRegion, &RxWindow1Config, ( int8_t* )&McpsIndication.RxDatarate );
- RxWindowSetup( RxWindow1Config.RxContinuous, LoRaMacParams.MaxRxWindow );
+static void OnRxWindow1TimerEvent( void* context )
+{
+ MacCtx.RxWindow1Config.Channel = MacCtx.Channel;
+ MacCtx.RxWindow1Config.DrOffset = MacCtx.NvmCtx->MacParams.Rx1DrOffset;
+ MacCtx.RxWindow1Config.DownlinkDwellTime = MacCtx.NvmCtx->MacParams.DownlinkDwellTime;
+ MacCtx.RxWindow1Config.RepeaterSupport = MacCtx.NvmCtx->RepeaterSupport;
+ MacCtx.RxWindow1Config.RxContinuous = false;
+ MacCtx.RxWindow1Config.RxSlot = RX_SLOT_WIN_1;
+
+ RxWindowSetup( &MacCtx.RxWindowTimer1, &MacCtx.RxWindow1Config );
}
-static void OnRxWindow2TimerEvent( void )
+static void OnRxWindow2TimerEvent( void* context )
{
- TimerStop( &RxWindowTimer2 );
+ // Check if we are processing Rx1 window.
+ // If yes, we don't setup the Rx2 window.
+ if( MacCtx.RxSlot == RX_SLOT_WIN_1 )
+ {
+ return;
+ }
+ MacCtx.RxWindow2Config.Channel = MacCtx.Channel;
+ MacCtx.RxWindow2Config.Frequency = MacCtx.NvmCtx->MacParams.Rx2Channel.Frequency;
+ MacCtx.RxWindow2Config.DownlinkDwellTime = MacCtx.NvmCtx->MacParams.DownlinkDwellTime;
+ MacCtx.RxWindow2Config.RepeaterSupport = MacCtx.NvmCtx->RepeaterSupport;
+ MacCtx.RxWindow2Config.RxContinuous = false;
+ MacCtx.RxWindow2Config.RxSlot = RX_SLOT_WIN_2;
+
+ RxWindowSetup( &MacCtx.RxWindowTimer2, &MacCtx.RxWindow2Config );
+}
- RxWindow2Config.Channel = Channel;
- RxWindow2Config.Frequency = LoRaMacParams.Rx2Channel.Frequency;
- RxWindow2Config.DownlinkDwellTime = LoRaMacParams.DownlinkDwellTime;
- RxWindow2Config.RepeaterSupport = RepeaterSupport;
- RxWindow2Config.Window = 1;
+static void OnAckTimeoutTimerEvent( void* context )
+{
+ TimerStop( &MacCtx.AckTimeoutTimer );
- if( LoRaMacDeviceClass != CLASS_C )
+ if( MacCtx.NodeAckRequested == true )
{
- RxWindow2Config.RxContinuous = false;
+ MacCtx.AckTimeoutRetry = true;
}
- else
+ if( MacCtx.NvmCtx->DeviceClass == CLASS_C )
{
- RxWindow2Config.RxContinuous = true;
- if (NetworkActivation == ACTIVATION_TYPE_ABP){
- RxWindow2Config.Datarate = McpsIndication.RxDatarate;
- }
+ MacCtx.MacFlags.Bits.MacDone = 1;
}
-
- if( RegionRxConfig( LoRaMacRegion, &RxWindow2Config, ( int8_t* )&McpsIndication.RxDatarate ) == true )
+ if( ( MacCtx.MacCallbacks != NULL ) && ( MacCtx.MacCallbacks->MacProcessNotify != NULL ) )
{
- RxWindowSetup( RxWindow2Config.RxContinuous, LoRaMacParams.MaxRxWindow );
- RxSlot = RxWindow2Config.Window;
+ MacCtx.MacCallbacks->MacProcessNotify( );
}
}
-static void CheckToDisableAckTimeout( bool nodeAckRequested, DeviceClass_t devClass, bool ackReceived,
- uint8_t ackTimeoutRetriesCounter, uint8_t ackTimeoutRetries )
+static LoRaMacCryptoStatus_t GetFCntDown( AddressIdentifier_t addrID, FType_t fType, LoRaMacMessageData_t* macMsg, Version_t lrWanVersion,
+ uint16_t maxFCntGap, FCntIdentifier_t* fCntID, uint32_t* currentDown )
{
- // There are three cases where we need to stop the AckTimeoutTimer:
- if( nodeAckRequested == false )
+ if( ( macMsg == NULL ) || ( fCntID == NULL ) ||
+ ( currentDown == NULL ) )
{
- if( devClass == CLASS_C )
- {// FIRST CASE
- // We have performed an unconfirmed uplink in class c mode
- // and have received a downlink in RX1 or RX2.
- TimerStop( &AckTimeoutTimer );
- }
+ return LORAMAC_CRYPTO_ERROR_NPE;
}
- else
+
+ // Determine the frame counter identifier and choose counter from FCntList
+ switch( addrID )
{
- if( ackReceived == 1 )
- {// SECOND CASE
- // We have performed a confirmed uplink and have received a
- // downlink with a valid ACK.
- TimerStop( &AckTimeoutTimer );
- }
- else
- {// THIRD CASE
- if( ackTimeoutRetriesCounter > ackTimeoutRetries )
+ case UNICAST_DEV_ADDR:
+ if( lrWanVersion.Fields.Minor == 1 )
{
- // We have performed a confirmed uplink and have not
- // received a downlink with a valid ACK. In this case
- // we need to verify if the maximum retries have been
- // elapsed. If so, stop the timer.
- TimerStop( &AckTimeoutTimer );
+ if( ( fType == FRAME_TYPE_A ) || ( fType == FRAME_TYPE_D ) )
+ {
+ *fCntID = A_FCNT_DOWN;
+ }
+ else
+ {
+ *fCntID = N_FCNT_DOWN;
+ }
}
- }
+ else
+ { // For LoRaWAN 1.0.X
+ *fCntID = FCNT_DOWN;
+ }
+ break;
+ case MULTICAST_0_ADDR:
+ *fCntID = MC_FCNT_DOWN_0;
+ break;
+ case MULTICAST_1_ADDR:
+ *fCntID = MC_FCNT_DOWN_1;
+ break;
+ case MULTICAST_2_ADDR:
+ *fCntID = MC_FCNT_DOWN_2;
+ break;
+ case MULTICAST_3_ADDR:
+ *fCntID = MC_FCNT_DOWN_3;
+ break;
+ default:
+ return LORAMAC_CRYPTO_FAIL_FCNT_ID;
}
+
+ return LoRaMacCryptoGetFCntDown( *fCntID, maxFCntGap, macMsg->FHDR.FCnt, currentDown );
}
-static void OnAckTimeoutTimerEvent( void )
+static LoRaMacStatus_t SwitchClass( DeviceClass_t deviceClass )
{
- TimerStop( &AckTimeoutTimer );
+ LoRaMacStatus_t status = LORAMAC_STATUS_PARAMETER_INVALID;
- if( NodeAckRequested == true )
- {
- AckTimeoutRetry = true;
- LoRaMacState &= ~LORAMAC_ACK_REQ;
- }
- if( LoRaMacDeviceClass == CLASS_C )
+ switch( MacCtx.NvmCtx->DeviceClass )
{
- LoRaMacFlags.Bits.MacDone = 1;
- }
-}
+ case CLASS_A:
+ {
+ if( deviceClass == CLASS_A )
+ {
+ // Revert back RxC parameters
+ MacCtx.NvmCtx->MacParams.RxCChannel = MacCtx.NvmCtx->MacParams.Rx2Channel;
+ }
+ if( deviceClass == CLASS_B )
+ {
+ status = LoRaMacClassBSwitchClass( deviceClass );
+ if( status == LORAMAC_STATUS_OK )
+ {
+ MacCtx.NvmCtx->DeviceClass = deviceClass;
+ }
+ }
-static void RxWindowSetup( bool rxContinuous, uint32_t maxRxWindow )
-{
- if( rxContinuous == false )
- {
- Radio.Rx( maxRxWindow );
- }
- else
- {
- Radio.Rx( 0 ); // Continuous mode
+ if( deviceClass == CLASS_C )
+ {
+ MacCtx.NvmCtx->DeviceClass = deviceClass;
+
+ MacCtx.RxWindowCConfig = MacCtx.RxWindow2Config;
+ MacCtx.RxWindowCConfig.RxSlot = RX_SLOT_WIN_CLASS_C;
+
+ for( int8_t i = 0; i < LORAMAC_MAX_MC_CTX; i++ )
+ {
+ if( MacCtx.NvmCtx->MulticastChannelList[i].ChannelParams.IsEnabled == true )
+ // TODO: Check multicast channel device class.
+ {
+ MacCtx.NvmCtx->MacParams.RxCChannel.Frequency = MacCtx.NvmCtx->MulticastChannelList[i].ChannelParams.RxParams.ClassC.Frequency;
+ MacCtx.NvmCtx->MacParams.RxCChannel.Datarate = MacCtx.NvmCtx->MulticastChannelList[i].ChannelParams.RxParams.ClassC.Datarate;
+
+ MacCtx.RxWindowCConfig.Channel = MacCtx.Channel;
+ MacCtx.RxWindowCConfig.Frequency = MacCtx.NvmCtx->MacParams.RxCChannel.Frequency;
+ MacCtx.RxWindowCConfig.DownlinkDwellTime = MacCtx.NvmCtx->MacParams.DownlinkDwellTime;
+ MacCtx.RxWindowCConfig.RepeaterSupport = MacCtx.NvmCtx->RepeaterSupport;
+ MacCtx.RxWindowCConfig.RxSlot = RX_SLOT_WIN_CLASS_C_MULTICAST;
+ MacCtx.RxWindowCConfig.RxContinuous = true;
+ break;
+ }
+ }
+
+ // Set the NodeAckRequested indicator to default
+ MacCtx.NodeAckRequested = false;
+ // Set the radio into sleep mode in case we are still in RX mode
+ Radio.Sleep( );
+
+ OpenContinuousRxCWindow( );
+
+ status = LORAMAC_STATUS_OK;
+ }
+ break;
+ }
+ case CLASS_B:
+ {
+ status = LoRaMacClassBSwitchClass( deviceClass );
+ if( status == LORAMAC_STATUS_OK )
+ {
+ MacCtx.NvmCtx->DeviceClass = deviceClass;
+ }
+ break;
+ }
+ case CLASS_C:
+ {
+ if( deviceClass == CLASS_A )
+ {
+ MacCtx.NvmCtx->DeviceClass = deviceClass;
+
+ // Set the radio into sleep to setup a defined state
+ Radio.Sleep( );
+
+ status = LORAMAC_STATUS_OK;
+ }
+ break;
+ }
}
+
+ return status;
}
-bool ValidatePayloadLength( uint8_t lenN, int8_t datarate, uint8_t fOptsLen )
+static uint8_t GetMaxAppPayloadWithoutFOptsLength( int8_t datarate )
{
GetPhyParams_t getPhy;
PhyParam_t phyParam;
- uint16_t maxN = 0;
- uint16_t payloadSize = 0;
// Setup PHY request
- getPhy.UplinkDwellTime = LoRaMacParams.UplinkDwellTime;
+ getPhy.UplinkDwellTime = MacCtx.NvmCtx->MacParams.UplinkDwellTime;
getPhy.Datarate = datarate;
getPhy.Attribute = PHY_MAX_PAYLOAD;
// Get the maximum payload length
- if( RepeaterSupport == true )
+ if( MacCtx.NvmCtx->RepeaterSupport == true )
{
getPhy.Attribute = PHY_MAX_PAYLOAD_REPEATER;
}
- phyParam = RegionGetPhyParam( LoRaMacRegion, &getPhy );
- maxN = phyParam.Value;
+ phyParam = RegionGetPhyParam( MacCtx.NvmCtx->Region, &getPhy );
+
+ return phyParam.Value;
+}
+
+bool ValidatePayloadLength( uint8_t lenN, int8_t datarate, uint8_t fOptsLen )
+{
+ uint16_t maxN = 0;
+ uint16_t payloadSize = 0;
+
+ maxN = GetMaxAppPayloadWithoutFOptsLength( datarate );
// Calculate the resulting payload size
payloadSize = ( lenN + fOptsLen );
@@ -1633,350 +1930,306 @@ bool ValidatePayloadLength( uint8_t lenN, int8_t datarate, uint8_t fOptsLen )
return false;
}
-static bool IsStickyMacCommandPending( void )
-{
- if( MacCommandsBufferToRepeatIndex > 0 )
- {
- // Sticky MAC commands pending
- return true;
- }
- return false;
-}
-
static void SetMlmeScheduleUplinkIndication( void )
{
- MlmeIndication.MlmeIndication = MLME_SCHEDULE_UPLINK;
- LoRaMacFlags.Bits.MlmeInd = 1;
+ MacCtx.MacFlags.Bits.MlmeSchedUplinkInd = 1;
}
-static LoRaMacStatus_t AddMacCommand( uint8_t cmd, uint8_t p1, uint8_t p2 )
+static void ProcessMacCommands( uint8_t *payload, uint8_t macIndex, uint8_t commandsSize, int8_t snr, LoRaMacRxSlot_t rxSlot )
{
- LoRaMacStatus_t status = LORAMAC_STATUS_BUSY;
- // The maximum buffer length must take MAC commands to re-send into account.
- uint8_t bufLen = LORA_MAC_COMMAND_MAX_LENGTH - MacCommandsBufferToRepeatIndex;
+ uint8_t status = 0;
+ bool adrBlockFound = false;
+ uint8_t macCmdPayload[2] = { 0x00, 0x00 };
- switch( cmd )
+ while( macIndex < commandsSize )
{
- case MOTE_MAC_LINK_CHECK_REQ:
- if( MacCommandsBufferIndex < bufLen )
+ // Decode Frame MAC commands
+ switch( payload[macIndex++] )
+ {
+ case SRV_MAC_LINK_CHECK_ANS:
{
- MacCommandsBuffer[MacCommandsBufferIndex++] = cmd;
- // No payload for this command
- status = LORAMAC_STATUS_OK;
- }
- break;
- case MOTE_MAC_LINK_ADR_ANS:
- if( MacCommandsBufferIndex < ( bufLen - 1 ) )
- {
- MacCommandsBuffer[MacCommandsBufferIndex++] = cmd;
- // Margin
- MacCommandsBuffer[MacCommandsBufferIndex++] = p1;
- status = LORAMAC_STATUS_OK;
- }
- break;
- case MOTE_MAC_DUTY_CYCLE_ANS:
- if( MacCommandsBufferIndex < bufLen )
- {
- MacCommandsBuffer[MacCommandsBufferIndex++] = cmd;
- // No payload for this answer
- status = LORAMAC_STATUS_OK;
- }
- break;
- case MOTE_MAC_RX_PARAM_SETUP_ANS:
- if( MacCommandsBufferIndex < ( bufLen - 1 ) )
- {
- MacCommandsBuffer[MacCommandsBufferIndex++] = cmd;
- // Status: Datarate ACK, Channel ACK
- MacCommandsBuffer[MacCommandsBufferIndex++] = p1;
- // This is a sticky MAC command answer. Setup indication
- SetMlmeScheduleUplinkIndication( );
- status = LORAMAC_STATUS_OK;
- }
- break;
- case MOTE_MAC_DEV_STATUS_ANS:
- if( MacCommandsBufferIndex < ( bufLen - 2 ) )
- {
- MacCommandsBuffer[MacCommandsBufferIndex++] = cmd;
- // 1st byte Battery
- // 2nd byte Margin
- MacCommandsBuffer[MacCommandsBufferIndex++] = p1;
- MacCommandsBuffer[MacCommandsBufferIndex++] = p2;
- status = LORAMAC_STATUS_OK;
- }
- break;
- case MOTE_MAC_NEW_CHANNEL_ANS:
- if( MacCommandsBufferIndex < ( bufLen - 1 ) )
- {
- MacCommandsBuffer[MacCommandsBufferIndex++] = cmd;
- // Status: Datarate range OK, Channel frequency OK
- MacCommandsBuffer[MacCommandsBufferIndex++] = p1;
- status = LORAMAC_STATUS_OK;
- }
- break;
- case MOTE_MAC_RX_TIMING_SETUP_ANS:
- if( MacCommandsBufferIndex < bufLen )
- {
- MacCommandsBuffer[MacCommandsBufferIndex++] = cmd;
- // No payload for this answer
- // This is a sticky MAC command answer. Setup indication
- SetMlmeScheduleUplinkIndication( );
- status = LORAMAC_STATUS_OK;
- }
- break;
- case MOTE_MAC_TX_PARAM_SETUP_ANS:
- if( MacCommandsBufferIndex < bufLen )
- {
- MacCommandsBuffer[MacCommandsBufferIndex++] = cmd;
- // No payload for this answer
- status = LORAMAC_STATUS_OK;
- }
- break;
- case MOTE_MAC_DL_CHANNEL_ANS:
- if( MacCommandsBufferIndex < bufLen )
- {
- MacCommandsBuffer[MacCommandsBufferIndex++] = cmd;
- // Status: Uplink frequency exists, Channel frequency OK
- MacCommandsBuffer[MacCommandsBufferIndex++] = p1;
-
- // This is a sticky MAC command answer. Setup indication
- SetMlmeScheduleUplinkIndication( );
-
- status = LORAMAC_STATUS_OK;
- }
- break;
- default:
- return LORAMAC_STATUS_SERVICE_UNKNOWN;
- }
- if( status == LORAMAC_STATUS_OK )
- {
- MacCommandsInNextTx = true;
- }
- return status;
-}
-
-static uint8_t ParseMacCommandsToRepeat( uint8_t* cmdBufIn, uint8_t length, uint8_t* cmdBufOut )
-{
- uint8_t i = 0;
- uint8_t cmdCount = 0;
-
- if( ( cmdBufIn == NULL ) || ( cmdBufOut == NULL ) )
- {
- return 0;
- }
-
- for( i = 0; i < length; i++ )
- {
- switch( cmdBufIn[i] )
- {
- // STICKY
- case MOTE_MAC_DL_CHANNEL_ANS:
- case MOTE_MAC_RX_PARAM_SETUP_ANS:
- { // 1 byte payload
- cmdBufOut[cmdCount++] = cmdBufIn[i++];
- cmdBufOut[cmdCount++] = cmdBufIn[i];
- break;
- }
- case MOTE_MAC_RX_TIMING_SETUP_ANS:
- { // 0 byte payload
- cmdBufOut[cmdCount++] = cmdBufIn[i];
- break;
- }
- // NON-STICKY
- case MOTE_MAC_DEV_STATUS_ANS:
- { // 2 bytes payload
- i += 2;
- break;
- }
- case MOTE_MAC_LINK_ADR_ANS:
- case MOTE_MAC_NEW_CHANNEL_ANS:
- { // 1 byte payload
- i++;
- break;
- }
- case MOTE_MAC_TX_PARAM_SETUP_ANS:
- case MOTE_MAC_DUTY_CYCLE_ANS:
- case MOTE_MAC_LINK_CHECK_REQ:
- { // 0 byte payload
+ if( LoRaMacConfirmQueueIsCmdActive( MLME_LINK_CHECK ) == true )
+ {
+ LoRaMacConfirmQueueSetStatus( LORAMAC_EVENT_INFO_STATUS_OK, MLME_LINK_CHECK );
+ MacCtx.MlmeConfirm.DemodMargin = payload[macIndex++];
+ MacCtx.MlmeConfirm.NbGateways = payload[macIndex++];
+ }
break;
}
- default:
- break;
- }
- }
-
- return cmdCount;
-}
-
-static void ProcessMacCommands( uint8_t *payload, uint8_t macIndex, uint8_t commandsSize, uint8_t snr )
-{
- uint8_t status = 0;
-
- while( macIndex < commandsSize )
- {
- // Decode Frame MAC commands
- switch( payload[macIndex++] )
- {
- case SRV_MAC_LINK_CHECK_ANS:
- MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_OK;
- MlmeConfirm.DemodMargin = payload[macIndex++];
- MlmeConfirm.NbGateways = payload[macIndex++];
- break;
case SRV_MAC_LINK_ADR_REQ:
+ {
+ LinkAdrReqParams_t linkAdrReq;
+ int8_t linkAdrDatarate = DR_0;
+ int8_t linkAdrTxPower = TX_POWER_0;
+ uint8_t linkAdrNbRep = 0;
+ uint8_t linkAdrNbBytesParsed = 0;
+
+ if( adrBlockFound == false )
{
- LinkAdrReqParams_t linkAdrReq;
- int8_t linkAdrDatarate = DR_0;
- int8_t linkAdrTxPower = TX_POWER_0;
- uint8_t linkAdrNbRep = 0;
- uint8_t linkAdrNbBytesParsed = 0;
+ adrBlockFound = true;
// Fill parameter structure
linkAdrReq.Payload = &payload[macIndex - 1];
linkAdrReq.PayloadSize = commandsSize - ( macIndex - 1 );
- linkAdrReq.AdrEnabled = AdrCtrlOn;
- linkAdrReq.UplinkDwellTime = LoRaMacParams.UplinkDwellTime;
- linkAdrReq.CurrentDatarate = LoRaMacParams.ChannelsDatarate;
- linkAdrReq.CurrentTxPower = LoRaMacParams.ChannelsTxPower;
- linkAdrReq.CurrentNbRep = LoRaMacParams.ChannelsNbRep;
+ linkAdrReq.AdrEnabled = MacCtx.NvmCtx->AdrCtrlOn;
+ linkAdrReq.UplinkDwellTime = MacCtx.NvmCtx->MacParams.UplinkDwellTime;
+ linkAdrReq.CurrentDatarate = MacCtx.NvmCtx->MacParams.ChannelsDatarate;
+ linkAdrReq.CurrentTxPower = MacCtx.NvmCtx->MacParams.ChannelsTxPower;
+ linkAdrReq.CurrentNbRep = MacCtx.NvmCtx->MacParams.ChannelsNbTrans;
+ linkAdrReq.Version = MacCtx.NvmCtx->Version;
// Process the ADR requests
- status = RegionLinkAdrReq( LoRaMacRegion, &linkAdrReq, &linkAdrDatarate,
+ status = RegionLinkAdrReq( MacCtx.NvmCtx->Region, &linkAdrReq, &linkAdrDatarate,
&linkAdrTxPower, &linkAdrNbRep, &linkAdrNbBytesParsed );
if( ( status & 0x07 ) == 0x07 )
{
- LoRaMacParams.ChannelsDatarate = linkAdrDatarate;
- LoRaMacParams.ChannelsTxPower = linkAdrTxPower;
- LoRaMacParams.ChannelsNbRep = linkAdrNbRep;
+ MacCtx.NvmCtx->MacParams.ChannelsDatarate = linkAdrDatarate;
+ MacCtx.NvmCtx->MacParams.ChannelsTxPower = linkAdrTxPower;
+ MacCtx.NvmCtx->MacParams.ChannelsNbTrans = linkAdrNbRep;
}
// Add the answers to the buffer
for( uint8_t i = 0; i < ( linkAdrNbBytesParsed / 5 ); i++ )
{
- AddMacCommand( MOTE_MAC_LINK_ADR_ANS, status, 0 );
+ LoRaMacCommandsAddCmd( MOTE_MAC_LINK_ADR_ANS, &status, 1 );
}
// Update MAC index
macIndex += linkAdrNbBytesParsed - 1;
}
break;
+ }
case SRV_MAC_DUTY_CYCLE_REQ:
- MaxDCycle = payload[macIndex++];
- AggregatedDCycle = 1 << MaxDCycle;
- AddMacCommand( MOTE_MAC_DUTY_CYCLE_ANS, 0, 0 );
+ {
+ MacCtx.NvmCtx->MaxDCycle = payload[macIndex++] & 0x0F;
+ MacCtx.NvmCtx->AggregatedDCycle = 1 << MacCtx.NvmCtx->MaxDCycle;
+ LoRaMacCommandsAddCmd( MOTE_MAC_DUTY_CYCLE_ANS, macCmdPayload, 0 );
break;
+ }
case SRV_MAC_RX_PARAM_SETUP_REQ:
- {
- RxParamSetupReqParams_t rxParamSetupReq;
- status = 0x07;
+ {
+ RxParamSetupReqParams_t rxParamSetupReq;
+ status = 0x07;
- rxParamSetupReq.DrOffset = ( payload[macIndex] >> 4 ) & 0x07;
- rxParamSetupReq.Datarate = payload[macIndex] & 0x0F;
- macIndex++;
+ rxParamSetupReq.DrOffset = ( payload[macIndex] >> 4 ) & 0x07;
+ rxParamSetupReq.Datarate = payload[macIndex] & 0x0F;
+ macIndex++;
- rxParamSetupReq.Frequency = ( uint32_t )payload[macIndex++];
- rxParamSetupReq.Frequency |= ( uint32_t )payload[macIndex++] << 8;
- rxParamSetupReq.Frequency |= ( uint32_t )payload[macIndex++] << 16;
- rxParamSetupReq.Frequency *= 100;
+ rxParamSetupReq.Frequency = ( uint32_t ) payload[macIndex++];
+ rxParamSetupReq.Frequency |= ( uint32_t ) payload[macIndex++] << 8;
+ rxParamSetupReq.Frequency |= ( uint32_t ) payload[macIndex++] << 16;
+ rxParamSetupReq.Frequency *= 100;
- // Perform request on region
- status = RegionRxParamSetupReq( LoRaMacRegion, &rxParamSetupReq );
+ // Perform request on region
+ status = RegionRxParamSetupReq( MacCtx.NvmCtx->Region, &rxParamSetupReq );
- if( ( status & 0x07 ) == 0x07 )
- {
- LoRaMacParams.Rx2Channel.Datarate = rxParamSetupReq.Datarate;
- LoRaMacParams.Rx2Channel.Frequency = rxParamSetupReq.Frequency;
- LoRaMacParams.Rx1DrOffset = rxParamSetupReq.DrOffset;
- }
- AddMacCommand( MOTE_MAC_RX_PARAM_SETUP_ANS, status, 0 );
+ if( ( status & 0x07 ) == 0x07 )
+ {
+ MacCtx.NvmCtx->MacParams.Rx2Channel.Datarate = rxParamSetupReq.Datarate;
+ MacCtx.NvmCtx->MacParams.RxCChannel.Datarate = rxParamSetupReq.Datarate;
+ MacCtx.NvmCtx->MacParams.Rx2Channel.Frequency = rxParamSetupReq.Frequency;
+ MacCtx.NvmCtx->MacParams.RxCChannel.Frequency = rxParamSetupReq.Frequency;
+ MacCtx.NvmCtx->MacParams.Rx1DrOffset = rxParamSetupReq.DrOffset;
}
+ macCmdPayload[0] = status;
+ LoRaMacCommandsAddCmd( MOTE_MAC_RX_PARAM_SETUP_ANS, macCmdPayload, 1 );
+ // Setup indication to inform the application
+ SetMlmeScheduleUplinkIndication( );
break;
+ }
case SRV_MAC_DEV_STATUS_REQ:
+ {
+ uint8_t batteryLevel = BAT_LEVEL_NO_MEASURE;
+ if( ( MacCtx.MacCallbacks != NULL ) && ( MacCtx.MacCallbacks->GetBatteryLevel != NULL ) )
{
- uint8_t batteryLevel = BAT_LEVEL_NO_MEASURE;
- if( ( LoRaMacCallbacks != NULL ) && ( LoRaMacCallbacks->GetBatteryLevel != NULL ) )
- {
- batteryLevel = LoRaMacCallbacks->GetBatteryLevel( );
- }
- AddMacCommand( MOTE_MAC_DEV_STATUS_ANS, batteryLevel, snr );
- break;
+ batteryLevel = MacCtx.MacCallbacks->GetBatteryLevel( );
}
+ macCmdPayload[0] = batteryLevel;
+ macCmdPayload[1] = ( uint8_t )( snr & 0x3F );
+ LoRaMacCommandsAddCmd( MOTE_MAC_DEV_STATUS_ANS, macCmdPayload, 2 );
+ break;
+ }
case SRV_MAC_NEW_CHANNEL_REQ:
- {
- NewChannelReqParams_t newChannelReq;
- ChannelParams_t chParam;
- status = 0x03;
+ {
+ NewChannelReqParams_t newChannelReq;
+ ChannelParams_t chParam;
+ status = 0x03;
- newChannelReq.ChannelId = payload[macIndex++];
- newChannelReq.NewChannel = &chParam;
+ newChannelReq.ChannelId = payload[macIndex++];
+ newChannelReq.NewChannel = &chParam;
- chParam.Frequency = ( uint32_t )payload[macIndex++];
- chParam.Frequency |= ( uint32_t )payload[macIndex++] << 8;
- chParam.Frequency |= ( uint32_t )payload[macIndex++] << 16;
- chParam.Frequency *= 100;
- chParam.Rx1Frequency = 0;
- chParam.DrRange.Value = payload[macIndex++];
+ chParam.Frequency = ( uint32_t ) payload[macIndex++];
+ chParam.Frequency |= ( uint32_t ) payload[macIndex++] << 8;
+ chParam.Frequency |= ( uint32_t ) payload[macIndex++] << 16;
+ chParam.Frequency *= 100;
+ chParam.Rx1Frequency = 0;
+ chParam.DrRange.Value = payload[macIndex++];
- status = RegionNewChannelReq( LoRaMacRegion, &newChannelReq );
+ status = RegionNewChannelReq( MacCtx.NvmCtx->Region, &newChannelReq );
- AddMacCommand( MOTE_MAC_NEW_CHANNEL_ANS, status, 0 );
- }
+ macCmdPayload[0] = status;
+ LoRaMacCommandsAddCmd( MOTE_MAC_NEW_CHANNEL_ANS, macCmdPayload, 1 );
break;
+ }
case SRV_MAC_RX_TIMING_SETUP_REQ:
- {
- uint8_t delay = payload[macIndex++] & 0x0F;
+ {
+ uint8_t delay = payload[macIndex++] & 0x0F;
- if( delay == 0 )
- {
- delay++;
- }
- LoRaMacParams.ReceiveDelay1 = delay * 1000;
- LoRaMacParams.ReceiveDelay2 = LoRaMacParams.ReceiveDelay1 + 1000;
- AddMacCommand( MOTE_MAC_RX_TIMING_SETUP_ANS, 0, 0 );
+ if( delay == 0 )
+ {
+ delay++;
}
+ MacCtx.NvmCtx->MacParams.ReceiveDelay1 = delay * 1000;
+ MacCtx.NvmCtx->MacParams.ReceiveDelay2 = MacCtx.NvmCtx->MacParams.ReceiveDelay1 + 1000;
+ LoRaMacCommandsAddCmd( MOTE_MAC_RX_TIMING_SETUP_ANS, macCmdPayload, 0 );
+ // Setup indication to inform the application
+ SetMlmeScheduleUplinkIndication( );
break;
+ }
case SRV_MAC_TX_PARAM_SETUP_REQ:
- {
- TxParamSetupReqParams_t txParamSetupReq;
- uint8_t eirpDwellTime = payload[macIndex++];
+ {
+ TxParamSetupReqParams_t txParamSetupReq;
+ GetPhyParams_t getPhy;
+ PhyParam_t phyParam;
+ uint8_t eirpDwellTime = payload[macIndex++];
- txParamSetupReq.UplinkDwellTime = 0;
- txParamSetupReq.DownlinkDwellTime = 0;
+ txParamSetupReq.UplinkDwellTime = 0;
+ txParamSetupReq.DownlinkDwellTime = 0;
- if( ( eirpDwellTime & 0x20 ) == 0x20 )
- {
- txParamSetupReq.DownlinkDwellTime = 1;
- }
- if( ( eirpDwellTime & 0x10 ) == 0x10 )
- {
- txParamSetupReq.UplinkDwellTime = 1;
- }
- txParamSetupReq.MaxEirp = eirpDwellTime & 0x0F;
+ if( ( eirpDwellTime & 0x20 ) == 0x20 )
+ {
+ txParamSetupReq.DownlinkDwellTime = 1;
+ }
+ if( ( eirpDwellTime & 0x10 ) == 0x10 )
+ {
+ txParamSetupReq.UplinkDwellTime = 1;
+ }
+ txParamSetupReq.MaxEirp = eirpDwellTime & 0x0F;
- // Check the status for correctness
- if( RegionTxParamSetupReq( LoRaMacRegion, &txParamSetupReq ) != -1 )
- {
- // Accept command
- LoRaMacParams.UplinkDwellTime = txParamSetupReq.UplinkDwellTime;
- LoRaMacParams.DownlinkDwellTime = txParamSetupReq.DownlinkDwellTime;
- LoRaMacParams.MaxEirp = LoRaMacMaxEirpTable[txParamSetupReq.MaxEirp];
- // Add command response
- AddMacCommand( MOTE_MAC_TX_PARAM_SETUP_ANS, 0, 0 );
- }
+ // Check the status for correctness
+ if( RegionTxParamSetupReq( MacCtx.NvmCtx->Region, &txParamSetupReq ) != -1 )
+ {
+ // Accept command
+ MacCtx.NvmCtx->MacParams.UplinkDwellTime = txParamSetupReq.UplinkDwellTime;
+ MacCtx.NvmCtx->MacParams.DownlinkDwellTime = txParamSetupReq.DownlinkDwellTime;
+ MacCtx.NvmCtx->MacParams.MaxEirp = LoRaMacMaxEirpTable[txParamSetupReq.MaxEirp];
+ // Update the datarate in case of the new configuration limits it
+ getPhy.Attribute = PHY_MIN_TX_DR;
+ getPhy.UplinkDwellTime = MacCtx.NvmCtx->MacParams.UplinkDwellTime;
+ phyParam = RegionGetPhyParam( MacCtx.NvmCtx->Region, &getPhy );
+ MacCtx.NvmCtx->MacParams.ChannelsDatarate = MAX( MacCtx.NvmCtx->MacParams.ChannelsDatarate, ( int8_t )phyParam.Value );
+
+ // Add command response
+ LoRaMacCommandsAddCmd( MOTE_MAC_TX_PARAM_SETUP_ANS, macCmdPayload, 0 );
}
break;
+ }
case SRV_MAC_DL_CHANNEL_REQ:
+ {
+ DlChannelReqParams_t dlChannelReq;
+ status = 0x03;
+
+ dlChannelReq.ChannelId = payload[macIndex++];
+ dlChannelReq.Rx1Frequency = ( uint32_t ) payload[macIndex++];
+ dlChannelReq.Rx1Frequency |= ( uint32_t ) payload[macIndex++] << 8;
+ dlChannelReq.Rx1Frequency |= ( uint32_t ) payload[macIndex++] << 16;
+ dlChannelReq.Rx1Frequency *= 100;
+
+ status = RegionDlChannelReq( MacCtx.NvmCtx->Region, &dlChannelReq );
+ macCmdPayload[0] = status;
+ LoRaMacCommandsAddCmd( MOTE_MAC_DL_CHANNEL_ANS, macCmdPayload, 1 );
+ // Setup indication to inform the application
+ SetMlmeScheduleUplinkIndication( );
+ break;
+ }
+ case SRV_MAC_DEVICE_TIME_ANS:
+ {
+ SysTime_t gpsEpochTime = { 0 };
+ SysTime_t sysTime = { 0 };
+ SysTime_t sysTimeCurrent = { 0 };
+
+ gpsEpochTime.Seconds = ( uint32_t )payload[macIndex++];
+ gpsEpochTime.Seconds |= ( uint32_t )payload[macIndex++] << 8;
+ gpsEpochTime.Seconds |= ( uint32_t )payload[macIndex++] << 16;
+ gpsEpochTime.Seconds |= ( uint32_t )payload[macIndex++] << 24;
+ gpsEpochTime.SubSeconds = payload[macIndex++];
+
+ // Convert the fractional second received in ms
+ // round( pow( 0.5, 8.0 ) * 1000 ) = 3.90625
+ gpsEpochTime.SubSeconds = ( int16_t )( ( ( int32_t )gpsEpochTime.SubSeconds * 1000 ) >> 8 );
+
+ // Copy received GPS Epoch time into system time
+ sysTime = gpsEpochTime;
+ // Add Unix to Gps epcoh offset. The system time is based on Unix time.
+ sysTime.Seconds += UNIX_GPS_EPOCH_OFFSET;
+
+ // Compensate time difference between Tx Done time and now
+ sysTimeCurrent = SysTimeGet( );
+ sysTime = SysTimeAdd( sysTimeCurrent, SysTimeSub( sysTime, MacCtx.LastTxSysTime ) );
+
+ // Apply the new system time.
+ SysTimeSet( sysTime );
+ LoRaMacClassBDeviceTimeAns( );
+ MacCtx.McpsIndication.DeviceTimeAnsReceived = true;
+ break;
+ }
+ case SRV_MAC_PING_SLOT_INFO_ANS:
+ {
+ // According to the specification, it is not allowed to process this answer in
+ // a ping or multicast slot
+ if( ( MacCtx.RxSlot != RX_SLOT_WIN_CLASS_B_PING_SLOT ) && ( MacCtx.RxSlot != RX_SLOT_WIN_CLASS_B_MULTICAST_SLOT ) )
{
- DlChannelReqParams_t dlChannelReq;
- status = 0x03;
+ LoRaMacClassBPingSlotInfoAns( );
+ }
+ break;
+ }
+ case SRV_MAC_PING_SLOT_CHANNEL_REQ:
+ {
+ uint8_t status = 0x03;
+ uint32_t frequency = 0;
+ uint8_t datarate;
+
+ frequency = ( uint32_t )payload[macIndex++];
+ frequency |= ( uint32_t )payload[macIndex++] << 8;
+ frequency |= ( uint32_t )payload[macIndex++] << 16;
+ frequency *= 100;
+ datarate = payload[macIndex++] & 0x0F;
+
+ status = LoRaMacClassBPingSlotChannelReq( datarate, frequency );
+ macCmdPayload[0] = status;
+ LoRaMacCommandsAddCmd( MOTE_MAC_PING_SLOT_FREQ_ANS, macCmdPayload, 1 );
+ break;
+ }
+ case SRV_MAC_BEACON_TIMING_ANS:
+ {
+ uint16_t beaconTimingDelay = 0;
+ uint8_t beaconTimingChannel = 0;
- dlChannelReq.ChannelId = payload[macIndex++];
- dlChannelReq.Rx1Frequency = ( uint32_t )payload[macIndex++];
- dlChannelReq.Rx1Frequency |= ( uint32_t )payload[macIndex++] << 8;
- dlChannelReq.Rx1Frequency |= ( uint32_t )payload[macIndex++] << 16;
- dlChannelReq.Rx1Frequency *= 100;
+ beaconTimingDelay = ( uint16_t )payload[macIndex++];
+ beaconTimingDelay |= ( uint16_t )payload[macIndex++] << 8;
+ beaconTimingChannel = payload[macIndex++];
+
+ LoRaMacClassBBeaconTimingAns( beaconTimingDelay, beaconTimingChannel, RxDoneParams.LastRxDone );
+ break;
+ }
+ case SRV_MAC_BEACON_FREQ_REQ:
+ {
+ uint32_t frequency = 0;
- status = RegionDlChannelReq( LoRaMacRegion, &dlChannelReq );
+ frequency = ( uint32_t )payload[macIndex++];
+ frequency |= ( uint32_t )payload[macIndex++] << 8;
+ frequency |= ( uint32_t )payload[macIndex++] << 16;
+ frequency *= 100;
- AddMacCommand( MOTE_MAC_DL_CHANNEL_ANS, status, 0 );
+ if( LoRaMacClassBBeaconFreqReq( frequency ) == true )
+ {
+ macCmdPayload[0] = 1;
+ }
+ else
+ {
+ macCmdPayload[0] = 0;
+ }
+ LoRaMacCommandsAddCmd( MOTE_MAC_BEACON_FREQ_ANS, macCmdPayload, 1 );
}
break;
default:
@@ -1986,354 +2239,537 @@ static void ProcessMacCommands( uint8_t *payload, uint8_t macIndex, uint8_t comm
}
}
-LoRaMacStatus_t Send( LoRaMacHeader_t *macHdr, uint8_t fPort, void *fBuffer, uint16_t fBufferSize )
+LoRaMacStatus_t Send( LoRaMacHeader_t* macHdr, uint8_t fPort, void* fBuffer, uint16_t fBufferSize )
{
LoRaMacFrameCtrl_t fCtrl;
LoRaMacStatus_t status = LORAMAC_STATUS_PARAMETER_INVALID;
+ int8_t datarate = MacCtx.NvmCtx->MacParams.ChannelsDatarate;
+ int8_t txPower = MacCtx.NvmCtx->MacParams.ChannelsTxPower;
+ uint32_t adrAckCounter = MacCtx.NvmCtx->AdrAckCounter;
+ CalcNextAdrParams_t adrNext;
+
+ // Check if we are joined
+ if( MacCtx.NvmCtx->NetworkActivation == ACTIVATION_TYPE_NONE )
+ {
+ return LORAMAC_STATUS_NO_NETWORK_JOINED;
+ }
+ if( MacCtx.NvmCtx->MaxDCycle == 0 )
+ {
+ MacCtx.NvmCtx->AggregatedTimeOff = 0;
+ }
fCtrl.Value = 0;
fCtrl.Bits.FOptsLen = 0;
- fCtrl.Bits.FPending = 0;
- fCtrl.Bits.Ack = false;
- fCtrl.Bits.AdrAckReq = false;
- fCtrl.Bits.Adr = AdrCtrlOn;
+ fCtrl.Bits.Adr = MacCtx.NvmCtx->AdrCtrlOn;
+
+ // Check class b
+ if( MacCtx.NvmCtx->DeviceClass == CLASS_B )
+ {
+ fCtrl.Bits.FPending = 1;
+ }
+ else
+ {
+ fCtrl.Bits.FPending = 0;
+ }
+
+ // Check server ack
+ if( MacCtx.NvmCtx->SrvAckRequested == true )
+ {
+ fCtrl.Bits.Ack = 1;
+ }
+
+ // ADR next request
+ adrNext.Version = MacCtx.NvmCtx->Version;
+ adrNext.UpdateChanMask = true;
+ adrNext.AdrEnabled = fCtrl.Bits.Adr;
+ adrNext.AdrAckCounter = MacCtx.NvmCtx->AdrAckCounter;
+ adrNext.AdrAckLimit = MacCtx.AdrAckLimit;
+ adrNext.AdrAckDelay = MacCtx.AdrAckDelay;
+ adrNext.Datarate = MacCtx.NvmCtx->MacParams.ChannelsDatarate;
+ adrNext.TxPower = MacCtx.NvmCtx->MacParams.ChannelsTxPower;
+ adrNext.UplinkDwellTime = MacCtx.NvmCtx->MacParams.UplinkDwellTime;
+ adrNext.Region = MacCtx.NvmCtx->Region;
+
+ fCtrl.Bits.AdrAckReq = LoRaMacAdrCalcNext( &adrNext, &MacCtx.NvmCtx->MacParams.ChannelsDatarate,
+ &MacCtx.NvmCtx->MacParams.ChannelsTxPower, &adrAckCounter );
// Prepare the frame
status = PrepareFrame( macHdr, &fCtrl, fPort, fBuffer, fBufferSize );
// Validate status
+ if( ( status == LORAMAC_STATUS_OK ) || ( status == LORAMAC_STATUS_SKIPPED_APP_DATA ) )
+ {
+ // Schedule frame, do not allow delayed transmissions
+ status = ScheduleTx( false );
+ }
+
+ // Post processing
if( status != LORAMAC_STATUS_OK )
{
- return status;
+ // Bad case - restore
+ // Store local variables
+ MacCtx.NvmCtx->MacParams.ChannelsDatarate = datarate;
+ MacCtx.NvmCtx->MacParams.ChannelsTxPower = txPower;
}
+ else
+ {
+ // Good case
+ MacCtx.NvmCtx->SrvAckRequested = false;
+ MacCtx.NvmCtx->AdrAckCounter = adrAckCounter;
+ // Remove all none sticky MAC commands
+ if( LoRaMacCommandsRemoveNoneStickyCmds( ) != LORAMAC_COMMANDS_SUCCESS )
+ {
+ return LORAMAC_STATUS_MAC_COMMAD_ERROR;
+ }
+ }
+ return status;
+}
+
+LoRaMacStatus_t SendReJoinReq( JoinReqIdentifier_t joinReqType )
+{
+ LoRaMacStatus_t status = LORAMAC_STATUS_OK;
+ LoRaMacHeader_t macHdr;
+ macHdr.Value = 0;
+ bool allowDelayedTx = true;
+
+ // Setup join/rejoin message
+ switch( joinReqType )
+ {
+ case JOIN_REQ:
+ {
+ SwitchClass( CLASS_A );
+
+ MacCtx.TxMsg.Type = LORAMAC_MSG_TYPE_JOIN_REQUEST;
+ MacCtx.TxMsg.Message.JoinReq.Buffer = MacCtx.PktBuffer;
+ MacCtx.TxMsg.Message.JoinReq.BufSize = LORAMAC_PHY_MAXPAYLOAD;
- // Reset confirm parameters
- McpsConfirm.NbRetries = 0;
- McpsConfirm.AckReceived = false;
- McpsConfirm.UpLinkCounter = UpLinkCounter;
+ macHdr.Bits.MType = FRAME_TYPE_JOIN_REQ;
+ MacCtx.TxMsg.Message.JoinReq.MHDR.Value = macHdr.Value;
- status = ScheduleTx( );
+ memcpy1( MacCtx.TxMsg.Message.JoinReq.JoinEUI, SecureElementGetJoinEui( ), LORAMAC_JOIN_EUI_FIELD_SIZE );
+ memcpy1( MacCtx.TxMsg.Message.JoinReq.DevEUI, SecureElementGetDevEui( ), LORAMAC_DEV_EUI_FIELD_SIZE );
+
+ allowDelayedTx = false;
+
+ break;
+ }
+ default:
+ status = LORAMAC_STATUS_SERVICE_UNKNOWN;
+ break;
+ }
+ // Schedule frame
+ status = ScheduleTx( allowDelayedTx );
return status;
}
-static LoRaMacStatus_t ScheduleTx( void )
+static LoRaMacStatus_t CheckForClassBCollision( void )
{
- TimerTime_t dutyCycleTimeOff = 0;
- NextChanParams_t nextChan;
+ if( LoRaMacClassBIsBeaconExpected( ) == true )
+ {
+ return LORAMAC_STATUS_BUSY_BEACON_RESERVED_TIME;
+ }
- // Check if the device is off
- if( MaxDCycle == 255 )
+ if( MacCtx.NvmCtx->DeviceClass == CLASS_B )
{
- return LORAMAC_STATUS_DEVICE_OFF;
+ if( LoRaMacClassBIsPingExpected( ) == true )
+ {
+ return LORAMAC_STATUS_BUSY_PING_SLOT_WINDOW_TIME;
+ }
+ else if( LoRaMacClassBIsMulticastExpected( ) == true )
+ {
+ return LORAMAC_STATUS_BUSY_PING_SLOT_WINDOW_TIME;
+ }
}
- if( MaxDCycle == 0 )
+ return LORAMAC_STATUS_OK;
+}
+
+static LoRaMacStatus_t ScheduleTx( bool allowDelayedTx )
+{
+ LoRaMacStatus_t status = LORAMAC_STATUS_PARAMETER_INVALID;
+ TimerTime_t dutyCycleTimeOff = 0;
+ NextChanParams_t nextChan;
+ size_t macCmdsSize = 0;
+
+ // Check class b collisions
+ status = CheckForClassBCollision( );
+
+ if( status != LORAMAC_STATUS_OK )
{
- AggregatedTimeOff = 0;
+ return status;
}
- // Update Backoff
- CalculateBackOff( LastTxChannel );
+ // Update back-off
+ CalculateBackOff( MacCtx.NvmCtx->LastTxChannel );
- nextChan.AggrTimeOff = AggregatedTimeOff;
- nextChan.Datarate = LoRaMacParams.ChannelsDatarate;
- nextChan.DutyCycleEnabled = DutyCycleOn;
- nextChan.Joined = IsLoRaMacNetworkJoined;
- nextChan.LastAggrTx = AggregatedLastTxDoneTime;
+ nextChan.AggrTimeOff = MacCtx.NvmCtx->AggregatedTimeOff;
+ nextChan.Datarate = MacCtx.NvmCtx->MacParams.ChannelsDatarate;
+ nextChan.DutyCycleEnabled = MacCtx.NvmCtx->DutyCycleOn;
+ if( MacCtx.NvmCtx->NetworkActivation == ACTIVATION_TYPE_NONE )
+ {
+ nextChan.Joined = false;
+ }
+ else
+ {
+ nextChan.Joined = true;
+ }
+ nextChan.LastAggrTx = MacCtx.NvmCtx->LastTxDoneTime;
// Select channel
- while( RegionNextChannel( LoRaMacRegion, &nextChan, &Channel, &dutyCycleTimeOff, &AggregatedTimeOff ) == false )
+ status = RegionNextChannel( MacCtx.NvmCtx->Region, &nextChan, &MacCtx.Channel, &dutyCycleTimeOff, &MacCtx.NvmCtx->AggregatedTimeOff );
+
+ if( status != LORAMAC_STATUS_OK )
{
- // Set the default datarate
- LoRaMacParams.ChannelsDatarate = LoRaMacParamsDefaults.ChannelsDatarate;
- // Update datarate in the function parameters
- nextChan.Datarate = LoRaMacParams.ChannelsDatarate;
+ if( ( status == LORAMAC_STATUS_DUTYCYCLE_RESTRICTED ) &&
+ ( allowDelayedTx == true ) )
+ {
+ // Allow delayed transmissions. We have to allow it in case
+ // the MAC must retransmit a frame with the frame repetitions
+ if( dutyCycleTimeOff != 0 )
+ {// Send later - prepare timer
+ MacCtx.MacState |= LORAMAC_TX_DELAYED;
+ TimerSetValue( &MacCtx.TxDelayedTimer, dutyCycleTimeOff );
+ TimerStart( &MacCtx.TxDelayedTimer );
+ }
+ return LORAMAC_STATUS_OK;
+ }
+ else
+ {// State where the MAC cannot send a frame
+ return status;
+ }
}
// Compute Rx1 windows parameters
- RegionComputeRxWindowParameters( LoRaMacRegion,
- RegionApplyDrOffset( LoRaMacRegion, LoRaMacParams.DownlinkDwellTime, LoRaMacParams.ChannelsDatarate, LoRaMacParams.Rx1DrOffset ),
- LoRaMacParams.MinRxSymbols,
- LoRaMacParams.SystemMaxRxError,
- &RxWindow1Config );
+ RegionComputeRxWindowParameters( MacCtx.NvmCtx->Region,
+ RegionApplyDrOffset( MacCtx.NvmCtx->Region, MacCtx.NvmCtx->MacParams.DownlinkDwellTime, MacCtx.NvmCtx->MacParams.ChannelsDatarate, MacCtx.NvmCtx->MacParams.Rx1DrOffset ),
+ MacCtx.NvmCtx->MacParams.MinRxSymbols,
+ MacCtx.NvmCtx->MacParams.SystemMaxRxError,
+ &MacCtx.RxWindow1Config );
+
// Compute Rx2 windows parameters
- RegionComputeRxWindowParameters( LoRaMacRegion,
- LoRaMacParams.Rx2Channel.Datarate,
- LoRaMacParams.MinRxSymbols,
- LoRaMacParams.SystemMaxRxError,
- &RxWindow2Config );
+ RegionComputeRxWindowParameters( MacCtx.NvmCtx->Region,
+ MacCtx.NvmCtx->MacParams.Rx2Channel.Datarate,
+ MacCtx.NvmCtx->MacParams.MinRxSymbols,
+ MacCtx.NvmCtx->MacParams.SystemMaxRxError,
+ &MacCtx.RxWindow2Config );
- if( IsLoRaMacNetworkJoined == false )
+ if( MacCtx.NvmCtx->NetworkActivation == ACTIVATION_TYPE_NONE )
{
- RxWindow1Delay = LoRaMacParams.JoinAcceptDelay1 + RxWindow1Config.WindowOffset - 2;
- RxWindow2Delay = LoRaMacParams.JoinAcceptDelay2 + RxWindow2Config.WindowOffset - 3;
+ MacCtx.RxWindow1Delay = MacCtx.NvmCtx->MacParams.JoinAcceptDelay1 + MacCtx.RxWindow1Config.WindowOffset;
+ MacCtx.RxWindow2Delay = MacCtx.NvmCtx->MacParams.JoinAcceptDelay2 + MacCtx.RxWindow2Config.WindowOffset;
}
else
{
- if( ValidatePayloadLength( LoRaMacTxPayloadLen, LoRaMacParams.ChannelsDatarate, MacCommandsBufferIndex ) == false )
+ if( LoRaMacCommandsGetSizeSerializedCmds( &macCmdsSize ) != LORAMAC_COMMANDS_SUCCESS )
+ {
+ return LORAMAC_STATUS_MAC_COMMAD_ERROR;
+ }
+
+ if( ValidatePayloadLength( MacCtx.AppDataSize, MacCtx.NvmCtx->MacParams.ChannelsDatarate, macCmdsSize ) == false )
{
return LORAMAC_STATUS_LENGTH_ERROR;
}
- RxWindow1Delay = LoRaMacParams.ReceiveDelay1 + RxWindow1Config.WindowOffset - 1;
- RxWindow2Delay = LoRaMacParams.ReceiveDelay2 + RxWindow2Config.WindowOffset - 2;
+ MacCtx.RxWindow1Delay = MacCtx.NvmCtx->MacParams.ReceiveDelay1 + MacCtx.RxWindow1Config.WindowOffset;
+ MacCtx.RxWindow2Delay = MacCtx.NvmCtx->MacParams.ReceiveDelay2 + MacCtx.RxWindow2Config.WindowOffset;
}
- // Schedule transmission of frame
- if( dutyCycleTimeOff == 0 )
+ // Secure frame
+ LoRaMacStatus_t retval = SecureFrame( MacCtx.NvmCtx->MacParams.ChannelsDatarate, MacCtx.Channel );
+ if( retval != LORAMAC_STATUS_OK )
{
- // Try to send now
- return SendFrameOnChannel( Channel );
+ return retval;
}
- else
+
+ // Try to send now
+ return SendFrameOnChannel( MacCtx.Channel );
+}
+
+static LoRaMacStatus_t SecureFrame( uint8_t txDr, uint8_t txCh )
+{
+ LoRaMacCryptoStatus_t macCryptoStatus = LORAMAC_CRYPTO_ERROR;
+ uint32_t fCntUp = 0;
+
+ switch( MacCtx.TxMsg.Type )
{
- // Send later - prepare timer
- LoRaMacState |= LORAMAC_TX_DELAYED;
- TimerSetValue( &TxDelayedTimer, dutyCycleTimeOff );
- TimerStart( &TxDelayedTimer );
+ case LORAMAC_MSG_TYPE_JOIN_REQUEST:
+ macCryptoStatus = LoRaMacCryptoPrepareJoinRequest( &MacCtx.TxMsg.Message.JoinReq );
+ if( LORAMAC_CRYPTO_SUCCESS != macCryptoStatus )
+ {
+ return LORAMAC_STATUS_CRYPTO_ERROR;
+ }
+ MacCtx.PktBufferLen = MacCtx.TxMsg.Message.JoinReq.BufSize;
+ break;
+ case LORAMAC_MSG_TYPE_DATA:
- return LORAMAC_STATUS_OK;
+ if( LORAMAC_CRYPTO_SUCCESS != LoRaMacCryptoGetFCntUp( &fCntUp ) )
+ {
+ return LORAMAC_STATUS_FCNT_HANDLER_ERROR;
+ }
+
+ if( ( MacCtx.ChannelsNbTransCounter >= 1 ) || ( MacCtx.AckTimeoutRetriesCounter > 1 ) )
+ {
+ fCntUp -= 1;
+ }
+
+ macCryptoStatus = LoRaMacCryptoSecureMessage( fCntUp, txDr, txCh, &MacCtx.TxMsg.Message.Data );
+ if( LORAMAC_CRYPTO_SUCCESS != macCryptoStatus )
+ {
+ return LORAMAC_STATUS_CRYPTO_ERROR;
+ }
+ MacCtx.PktBufferLen = MacCtx.TxMsg.Message.Data.BufSize;
+ break;
+ case LORAMAC_MSG_TYPE_JOIN_ACCEPT:
+ case LORAMAC_MSG_TYPE_UNDEF:
+ default:
+ return LORAMAC_STATUS_PARAMETER_INVALID;
}
+ return LORAMAC_STATUS_OK;
}
static void CalculateBackOff( uint8_t channel )
{
CalcBackOffParams_t calcBackOff;
- calcBackOff.Joined = IsLoRaMacNetworkJoined;
- calcBackOff.DutyCycleEnabled = DutyCycleOn;
+ if( MacCtx.NvmCtx->NetworkActivation == ACTIVATION_TYPE_NONE )
+ {
+ calcBackOff.Joined = false;
+ }
+ else
+ {
+ calcBackOff.Joined = true;
+ }
+ calcBackOff.DutyCycleEnabled = MacCtx.NvmCtx->DutyCycleOn;
calcBackOff.Channel = channel;
- calcBackOff.ElapsedTime = TimerGetElapsedTime( LoRaMacInitializationTime );
- calcBackOff.TxTimeOnAir = TxTimeOnAir;
- calcBackOff.LastTxIsJoinRequest = LastTxIsJoinRequest;
+ calcBackOff.ElapsedTime = SysTimeSub( SysTimeGetMcuTime( ), MacCtx.NvmCtx->InitializationTime );
+ calcBackOff.TxTimeOnAir = MacCtx.TxTimeOnAir;
+ calcBackOff.LastTxIsJoinRequest = false;
+ if( ( MacCtx.MacFlags.Bits.MlmeReq == 1 ) && ( LoRaMacConfirmQueueIsCmdActive( MLME_JOIN ) == true ) )
+ {
+ calcBackOff.LastTxIsJoinRequest = true;
+ }
// Update regional back-off
- RegionCalcBackOff( LoRaMacRegion, &calcBackOff );
+ RegionCalcBackOff( MacCtx.NvmCtx->Region, &calcBackOff );
- // Update aggregated time-off
- AggregatedTimeOff = AggregatedTimeOff + ( TxTimeOnAir * AggregatedDCycle - TxTimeOnAir );
+ // Update aggregated time-off. This must be an assignment and no incremental
+ // update as we do only calculate the time-off based on the last transmission
+ MacCtx.NvmCtx->AggregatedTimeOff = ( MacCtx.TxTimeOnAir * MacCtx.NvmCtx->AggregatedDCycle - MacCtx.TxTimeOnAir );
}
-static void ResetMacParameters( void )
+static void RemoveMacCommands( LoRaMacRxSlot_t rxSlot, LoRaMacFrameCtrl_t fCtrl, Mcps_t request )
{
- IsLoRaMacNetworkJoined = false;
+ if( rxSlot == RX_SLOT_WIN_1 || rxSlot == RX_SLOT_WIN_2 )
+ {
+ // Remove all sticky MAC commands answers since we can assume
+ // that they have been received by the server.
+ if( request == MCPS_CONFIRMED )
+ {
+ if( fCtrl.Bits.Ack == 1 )
+ { // For confirmed uplinks only if we have received an ACK.
+ LoRaMacCommandsRemoveStickyAnsCmds( );
+ }
+ }
+ else
+ {
+ LoRaMacCommandsRemoveStickyAnsCmds( );
+ }
+ }
+}
- // Counters
- UpLinkCounter = 0;
- DownLinkCounter = 0;
- AdrAckCounter = 0;
- ChannelsNbRepCounter = 0;
+static void ResetMacParameters( void )
+{
+ MacCtx.NvmCtx->NetworkActivation = ACTIVATION_TYPE_NONE;
- AckTimeoutRetries = 1;
- AckTimeoutRetriesCounter = 1;
- AckTimeoutRetry = false;
+ // ADR counter
+ MacCtx.NvmCtx->AdrAckCounter = 0;
- MaxDCycle = 0;
- AggregatedDCycle = 1;
+ MacCtx.ChannelsNbTransCounter = 0;
+ MacCtx.AckTimeoutRetries = 1;
+ MacCtx.AckTimeoutRetriesCounter = 1;
+ MacCtx.AckTimeoutRetry = false;
- MacCommandsBufferIndex = 0;
- MacCommandsBufferToRepeatIndex = 0;
+ MacCtx.NvmCtx->MaxDCycle = 0;
+ MacCtx.NvmCtx->AggregatedDCycle = 1;
- IsRxWindowsEnabled = true;
+ MacCtx.NvmCtx->MacParams.ChannelsTxPower = MacCtx.NvmCtx->MacParamsDefaults.ChannelsTxPower;
+ MacCtx.NvmCtx->MacParams.ChannelsDatarate = MacCtx.NvmCtx->MacParamsDefaults.ChannelsDatarate;
+ MacCtx.NvmCtx->MacParams.Rx1DrOffset = MacCtx.NvmCtx->MacParamsDefaults.Rx1DrOffset;
+ MacCtx.NvmCtx->MacParams.Rx2Channel = MacCtx.NvmCtx->MacParamsDefaults.Rx2Channel;
+ MacCtx.NvmCtx->MacParams.RxCChannel = MacCtx.NvmCtx->MacParamsDefaults.RxCChannel;
+ MacCtx.NvmCtx->MacParams.UplinkDwellTime = MacCtx.NvmCtx->MacParamsDefaults.UplinkDwellTime;
+ MacCtx.NvmCtx->MacParams.DownlinkDwellTime = MacCtx.NvmCtx->MacParamsDefaults.DownlinkDwellTime;
+ MacCtx.NvmCtx->MacParams.MaxEirp = MacCtx.NvmCtx->MacParamsDefaults.MaxEirp;
+ MacCtx.NvmCtx->MacParams.AntennaGain = MacCtx.NvmCtx->MacParamsDefaults.AntennaGain;
- LoRaMacParams.ChannelsTxPower = LoRaMacParamsDefaults.ChannelsTxPower;
- LoRaMacParams.ChannelsDatarate = LoRaMacParamsDefaults.ChannelsDatarate;
- LoRaMacParams.Rx1DrOffset = LoRaMacParamsDefaults.Rx1DrOffset;
- LoRaMacParams.Rx2Channel = LoRaMacParamsDefaults.Rx2Channel;
- LoRaMacParams.UplinkDwellTime = LoRaMacParamsDefaults.UplinkDwellTime;
- LoRaMacParams.DownlinkDwellTime = LoRaMacParamsDefaults.DownlinkDwellTime;
- LoRaMacParams.MaxEirp = LoRaMacParamsDefaults.MaxEirp;
- LoRaMacParams.AntennaGain = LoRaMacParamsDefaults.AntennaGain;
+ MacCtx.NodeAckRequested = false;
+ MacCtx.NvmCtx->SrvAckRequested = false;
- NodeAckRequested = false;
- SrvAckRequested = false;
- MacCommandsInNextTx = false;
+ // Pycom: Not resetting the Default Regions since we might have manually updated them before Join and this would reset the changes
+ // // Reset to application defaults
+ // InitDefaultsParams_t params;
+ // params.Type = INIT_TYPE_RESTORE_DEFAULT_CHANNELS;
+ // params.NvmCtx = NULL;
- // Reset Multicast downlink counters
- MulticastParams_t *cur = MulticastChannels;
- while( cur != NULL )
- {
- cur->DownLinkCounter = 0;
- cur = cur->Next;
- }
+ // RegionInitDefaults( MacCtx.NvmCtx->Region, ¶ms );
// Initialize channel index.
- Channel = 0;
- LastTxChannel = Channel;
+ MacCtx.Channel = 0;
+ MacCtx.NvmCtx->LastTxChannel = MacCtx.Channel;
+
+ // Initialize Rx2 config parameters.
+ MacCtx.RxWindow2Config.Channel = MacCtx.Channel;
+ MacCtx.RxWindow2Config.Frequency = MacCtx.NvmCtx->MacParams.Rx2Channel.Frequency;
+ MacCtx.RxWindow2Config.DownlinkDwellTime = MacCtx.NvmCtx->MacParams.DownlinkDwellTime;
+ MacCtx.RxWindow2Config.RepeaterSupport = MacCtx.NvmCtx->RepeaterSupport;
+ MacCtx.RxWindow2Config.RxContinuous = false;
+ MacCtx.RxWindow2Config.RxSlot = RX_SLOT_WIN_2;
+
+ // Initialize RxC config parameters.
+ MacCtx.RxWindowCConfig = MacCtx.RxWindow2Config;
+ MacCtx.RxWindowCConfig.RxContinuous = true;
+ MacCtx.RxWindowCConfig.RxSlot = RX_SLOT_WIN_CLASS_C;
+
}
-static bool IsFPortAllowed( uint8_t fPort )
+/*!
+ * \brief Initializes and opens the reception window
+ *
+ * \param [IN] rxTimer Window timer to be topped.
+ * \param [IN] rxConfig Window parameters to be setup
+ */
+static void RxWindowSetup( TimerEvent_t* rxTimer, RxConfigParams_t* rxConfig )
{
- if( fPort > 224 )
+ TimerStop( rxTimer );
+
+ // Ensure the radio is Idle
+ Radio.Standby( );
+
+ if( RegionRxConfig( MacCtx.NvmCtx->Region, rxConfig, ( int8_t* )&MacCtx.McpsIndication.RxDatarate ) == true )
{
- return false;
+ Radio.Rx( MacCtx.NvmCtx->MacParams.MaxRxWindow );
+ MacCtx.RxSlot = rxConfig->RxSlot;
}
- return true;
}
-static void OpenContinuousRx2Window( void )
+static void OpenContinuousRxCWindow( void )
{
- OnRxWindow2TimerEvent( );
- RxSlot = 2;
+ // Compute RxC windows parameters
+ RegionComputeRxWindowParameters( MacCtx.NvmCtx->Region,
+ MacCtx.NvmCtx->MacParams.RxCChannel.Datarate,
+ MacCtx.NvmCtx->MacParams.MinRxSymbols,
+ MacCtx.NvmCtx->MacParams.SystemMaxRxError,
+ &MacCtx.RxWindowCConfig );
+
+ MacCtx.RxWindowCConfig.RxSlot = RX_SLOT_WIN_CLASS_C;
+ // Setup continuous listening
+ MacCtx.RxWindowCConfig.RxContinuous = true;
+
+ // At this point the Radio should be idle.
+ // Thus, there is no need to set the radio in standby mode.
+ if( RegionRxConfig( MacCtx.NvmCtx->Region, &MacCtx.RxWindowCConfig, ( int8_t* )&MacCtx.McpsIndication.RxDatarate ) == true )
+ {
+ Radio.Rx( 0 ); // Continuous mode
+ MacCtx.RxSlot = MacCtx.RxWindowCConfig.RxSlot;
+ }
}
-LoRaMacStatus_t PrepareFrame( LoRaMacHeader_t *macHdr, LoRaMacFrameCtrl_t *fCtrl, uint8_t fPort, void *fBuffer, uint16_t fBufferSize )
+LoRaMacStatus_t PrepareFrame( LoRaMacHeader_t* macHdr, LoRaMacFrameCtrl_t* fCtrl, uint8_t fPort, void* fBuffer, uint16_t fBufferSize )
{
- AdrNextParams_t adrNext;
- uint16_t i;
- uint8_t pktHeaderLen = 0;
- uint32_t mic = 0;
- const void* payload = fBuffer;
- uint8_t framePort = fPort;
-
- LoRaMacBufferPktLen = 0;
-
- NodeAckRequested = false;
+ MacCtx.PktBufferLen = 0;
+ MacCtx.NodeAckRequested = false;
+ uint32_t fCntUp = 0;
+ size_t macCmdsSize = 0;
+ uint8_t availableSize = 0;
if( fBuffer == NULL )
{
fBufferSize = 0;
}
- LoRaMacTxPayloadLen = fBufferSize;
-
- LoRaMacBuffer[pktHeaderLen++] = macHdr->Value;
+ memcpy1( MacCtx.AppData, ( uint8_t* ) fBuffer, fBufferSize );
+ MacCtx.AppDataSize = fBufferSize;
+ MacCtx.PktBuffer[0] = macHdr->Value;
switch( macHdr->Bits.MType )
{
- case FRAME_TYPE_JOIN_REQ:
- LoRaMacBufferPktLen = pktHeaderLen;
-
- memcpyr( LoRaMacBuffer + LoRaMacBufferPktLen, LoRaMacAppEui, 8 );
- LoRaMacBufferPktLen += 8;
- memcpyr( LoRaMacBuffer + LoRaMacBufferPktLen, LoRaMacDevEui, 8 );
- LoRaMacBufferPktLen += 8;
-
- LoRaMacDevNonce = Radio.Random( );
-
- LoRaMacBuffer[LoRaMacBufferPktLen++] = LoRaMacDevNonce & 0xFF;
- LoRaMacBuffer[LoRaMacBufferPktLen++] = ( LoRaMacDevNonce >> 8 ) & 0xFF;
-
- LoRaMacJoinComputeMic( LoRaMacBuffer, LoRaMacBufferPktLen & 0xFF, LoRaMacAppKey, &mic );
-
- LoRaMacBuffer[LoRaMacBufferPktLen++] = mic & 0xFF;
- LoRaMacBuffer[LoRaMacBufferPktLen++] = ( mic >> 8 ) & 0xFF;
- LoRaMacBuffer[LoRaMacBufferPktLen++] = ( mic >> 16 ) & 0xFF;
- LoRaMacBuffer[LoRaMacBufferPktLen++] = ( mic >> 24 ) & 0xFF;
-
- break;
case FRAME_TYPE_DATA_CONFIRMED_UP:
- NodeAckRequested = true;
- //Intentional fallthrough
+ MacCtx.NodeAckRequested = true;
+ // Intentional fall through
case FRAME_TYPE_DATA_UNCONFIRMED_UP:
- if( IsLoRaMacNetworkJoined == false )
+ MacCtx.TxMsg.Type = LORAMAC_MSG_TYPE_DATA;
+ MacCtx.TxMsg.Message.Data.Buffer = MacCtx.PktBuffer;
+ MacCtx.TxMsg.Message.Data.BufSize = LORAMAC_PHY_MAXPAYLOAD;
+ MacCtx.TxMsg.Message.Data.MHDR.Value = macHdr->Value;
+ MacCtx.TxMsg.Message.Data.FPort = fPort;
+ MacCtx.TxMsg.Message.Data.FHDR.DevAddr = MacCtx.NvmCtx->DevAddr;
+ MacCtx.TxMsg.Message.Data.FHDR.FCtrl.Value = fCtrl->Value;
+ MacCtx.TxMsg.Message.Data.FRMPayloadSize = MacCtx.AppDataSize;
+ MacCtx.TxMsg.Message.Data.FRMPayload = MacCtx.AppData;
+
+ if( LORAMAC_CRYPTO_SUCCESS != LoRaMacCryptoGetFCntUp( &fCntUp ) )
{
- return LORAMAC_STATUS_NO_NETWORK_JOINED; // No network has been joined yet
+ return LORAMAC_STATUS_FCNT_HANDLER_ERROR;
}
+ MacCtx.TxMsg.Message.Data.FHDR.FCnt = ( uint16_t )fCntUp;
- // Adr next request
- adrNext.UpdateChanMask = true;
- adrNext.AdrEnabled = fCtrl->Bits.Adr;
- adrNext.AdrAckCounter = AdrAckCounter;
- adrNext.Datarate = LoRaMacParams.ChannelsDatarate;
- adrNext.TxPower = LoRaMacParams.ChannelsTxPower;
- adrNext.UplinkDwellTime = LoRaMacParams.UplinkDwellTime;
+ // Reset confirm parameters
+ MacCtx.McpsConfirm.NbRetries = 0;
+ MacCtx.McpsConfirm.AckReceived = false;
+ MacCtx.McpsConfirm.UpLinkCounter = fCntUp;
- fCtrl->Bits.AdrAckReq = RegionAdrNext( LoRaMacRegion, &adrNext,
- &LoRaMacParams.ChannelsDatarate, &LoRaMacParams.ChannelsTxPower, &AdrAckCounter );
-
- if( SrvAckRequested == true )
+ // Handle the MAC commands if there are any available
+ if( LoRaMacCommandsGetSizeSerializedCmds( &macCmdsSize ) != LORAMAC_COMMANDS_SUCCESS )
{
- SrvAckRequested = false;
- fCtrl->Bits.Ack = 1;
+ return LORAMAC_STATUS_MAC_COMMAD_ERROR;
}
- LoRaMacBuffer[pktHeaderLen++] = ( LoRaMacDevAddr ) & 0xFF;
- LoRaMacBuffer[pktHeaderLen++] = ( LoRaMacDevAddr >> 8 ) & 0xFF;
- LoRaMacBuffer[pktHeaderLen++] = ( LoRaMacDevAddr >> 16 ) & 0xFF;
- LoRaMacBuffer[pktHeaderLen++] = ( LoRaMacDevAddr >> 24 ) & 0xFF;
-
- LoRaMacBuffer[pktHeaderLen++] = fCtrl->Value;
-
- LoRaMacBuffer[pktHeaderLen++] = UpLinkCounter & 0xFF;
- LoRaMacBuffer[pktHeaderLen++] = ( UpLinkCounter >> 8 ) & 0xFF;
-
- // Copy the MAC commands which must be re-send into the MAC command buffer
- memcpy1( &MacCommandsBuffer[MacCommandsBufferIndex], MacCommandsBufferToRepeat, MacCommandsBufferToRepeatIndex );
- MacCommandsBufferIndex += MacCommandsBufferToRepeatIndex;
-
- if( ( payload != NULL ) && ( LoRaMacTxPayloadLen > 0 ) )
+ if( macCmdsSize > 0 )
{
- if( MacCommandsInNextTx == true )
+ availableSize = GetMaxAppPayloadWithoutFOptsLength( MacCtx.NvmCtx->MacParams.ChannelsDatarate );
+
+ // There is application payload available and the MAC commands fit into FOpts field.
+ if( ( MacCtx.AppDataSize > 0 ) && ( macCmdsSize <= LORA_MAC_COMMAND_MAX_FOPTS_LENGTH ) )
{
- if( MacCommandsBufferIndex <= LORA_MAC_COMMAND_MAX_FOPTS_LENGTH )
- {
- fCtrl->Bits.FOptsLen += MacCommandsBufferIndex;
-
- // Update FCtrl field with new value of OptionsLength
- LoRaMacBuffer[0x05] = fCtrl->Value;
- for( i = 0; i < MacCommandsBufferIndex; i++ )
- {
- LoRaMacBuffer[pktHeaderLen++] = MacCommandsBuffer[i];
- }
- }
- else
+ if( LoRaMacCommandsSerializeCmds( LORA_MAC_COMMAND_MAX_FOPTS_LENGTH, &macCmdsSize, MacCtx.TxMsg.Message.Data.FHDR.FOpts ) != LORAMAC_COMMANDS_SUCCESS )
{
- LoRaMacTxPayloadLen = MacCommandsBufferIndex;
- payload = MacCommandsBuffer;
- framePort = 0;
+ return LORAMAC_STATUS_MAC_COMMAD_ERROR;
}
+ fCtrl->Bits.FOptsLen = macCmdsSize;
+ // Update FCtrl field with new value of FOptionsLength
+ MacCtx.TxMsg.Message.Data.FHDR.FCtrl.Value = fCtrl->Value;
}
- }
- else
- {
- if( ( MacCommandsBufferIndex > 0 ) && ( MacCommandsInNextTx == true ) )
+ // There is application payload available but the MAC commands does NOT fit into FOpts field.
+ else if( ( MacCtx.AppDataSize > 0 ) && ( macCmdsSize > LORA_MAC_COMMAND_MAX_FOPTS_LENGTH ) )
{
- LoRaMacTxPayloadLen = MacCommandsBufferIndex;
- payload = MacCommandsBuffer;
- framePort = 0;
- }
- }
- MacCommandsInNextTx = false;
- // Store MAC commands which must be re-send in case the device does not receive a downlink anymore
- MacCommandsBufferToRepeatIndex = ParseMacCommandsToRepeat( MacCommandsBuffer, MacCommandsBufferIndex, MacCommandsBufferToRepeat );
- if( MacCommandsBufferToRepeatIndex > 0 )
- {
- MacCommandsInNextTx = true;
- }
- if( ( payload != NULL ) && ( LoRaMacTxPayloadLen > 0 ) )
- {
- LoRaMacBuffer[pktHeaderLen++] = framePort;
-
- if( framePort == 0 )
- {
- // Reset buffer index as the mac commands are being sent on port 0
- MacCommandsBufferIndex = 0;
- LoRaMacPayloadEncrypt( (uint8_t* ) payload, LoRaMacTxPayloadLen, LoRaMacNwkSKey, LoRaMacDevAddr, UP_LINK, UpLinkCounter, &LoRaMacBuffer[pktHeaderLen] );
+ if( LoRaMacCommandsSerializeCmds( availableSize, &macCmdsSize, MacCtx.NvmCtx->MacCommandsBuffer ) != LORAMAC_COMMANDS_SUCCESS )
+ {
+ return LORAMAC_STATUS_MAC_COMMAD_ERROR;
+ }
+ return LORAMAC_STATUS_SKIPPED_APP_DATA;
}
+ // No application payload available therefore add all mac commands to the FRMPayload.
else
{
- LoRaMacPayloadEncrypt( (uint8_t* ) payload, LoRaMacTxPayloadLen, LoRaMacAppSKey, LoRaMacDevAddr, UP_LINK, UpLinkCounter, &LoRaMacBuffer[pktHeaderLen] );
+ if( LoRaMacCommandsSerializeCmds( availableSize, &macCmdsSize, MacCtx.NvmCtx->MacCommandsBuffer ) != LORAMAC_COMMANDS_SUCCESS )
+ {
+ return LORAMAC_STATUS_MAC_COMMAD_ERROR;
+ }
+ // Force FPort to be zero
+ MacCtx.TxMsg.Message.Data.FPort = 0;
+
+ MacCtx.TxMsg.Message.Data.FRMPayload = MacCtx.NvmCtx->MacCommandsBuffer;
+ MacCtx.TxMsg.Message.Data.FRMPayloadSize = macCmdsSize;
}
}
- LoRaMacBufferPktLen = pktHeaderLen + LoRaMacTxPayloadLen;
-
- LoRaMacComputeMic( LoRaMacBuffer, LoRaMacBufferPktLen, LoRaMacNwkSKey, LoRaMacDevAddr, UP_LINK, UpLinkCounter, &mic );
-
- LoRaMacBuffer[LoRaMacBufferPktLen + 0] = mic & 0xFF;
- LoRaMacBuffer[LoRaMacBufferPktLen + 1] = ( mic >> 8 ) & 0xFF;
- LoRaMacBuffer[LoRaMacBufferPktLen + 2] = ( mic >> 16 ) & 0xFF;
- LoRaMacBuffer[LoRaMacBufferPktLen + 3] = ( mic >> 24 ) & 0xFF;
-
- LoRaMacBufferPktLen += LORAMAC_MFR_LEN;
break;
case FRAME_TYPE_PROPRIETARY:
- if( ( fBuffer != NULL ) && ( LoRaMacTxPayloadLen > 0 ) )
+ if( ( fBuffer != NULL ) && ( MacCtx.AppDataSize > 0 ) )
{
- memcpy1( LoRaMacBuffer + pktHeaderLen, ( uint8_t* ) fBuffer, LoRaMacTxPayloadLen );
- LoRaMacBufferPktLen = pktHeaderLen + LoRaMacTxPayloadLen;
+ memcpy1( MacCtx.PktBuffer + LORAMAC_MHDR_FIELD_SIZE, ( uint8_t* ) fBuffer, MacCtx.AppDataSize );
+ MacCtx.PktBufferLen = LORAMAC_MHDR_FIELD_SIZE + MacCtx.AppDataSize;
}
break;
default:
@@ -2349,37 +2785,51 @@ LoRaMacStatus_t SendFrameOnChannel( uint8_t channel )
int8_t txPower = 0;
txConfig.Channel = channel;
- txConfig.Datarate = LoRaMacParams.ChannelsDatarate;
- txConfig.TxPower = LoRaMacParams.ChannelsTxPower;
- txConfig.MaxEirp = LoRaMacParams.MaxEirp;
- txConfig.AntennaGain = LoRaMacParams.AntennaGain;
- txConfig.PktLen = LoRaMacBufferPktLen;
-
- RegionTxConfig( LoRaMacRegion, &txConfig, &txPower, &TxTimeOnAir );
-
- MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_ERROR;
- McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_ERROR;
- McpsConfirm.Datarate = LoRaMacParams.ChannelsDatarate;
- McpsConfirm.TxPower = txPower;
- McpsConfirm.UpLinkFrequency = Radio.GetChannel();
-
+ txConfig.Datarate = MacCtx.NvmCtx->MacParams.ChannelsDatarate;
+ txConfig.TxPower = MacCtx.NvmCtx->MacParams.ChannelsTxPower;
+ txConfig.MaxEirp = MacCtx.NvmCtx->MacParams.MaxEirp;
+ txConfig.AntennaGain = MacCtx.NvmCtx->MacParams.AntennaGain;
+ txConfig.PktLen = MacCtx.PktBufferLen;
+
+ RegionTxConfig( MacCtx.NvmCtx->Region, &txConfig, &txPower, &MacCtx.TxTimeOnAir );
+
+ MacCtx.McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_ERROR;
+ MacCtx.McpsConfirm.Datarate = MacCtx.NvmCtx->MacParams.ChannelsDatarate;
+ MacCtx.McpsConfirm.TxPower = txPower;
+ MacCtx.McpsConfirm.Channel = channel;
+
// Store the time on air
- McpsConfirm.TxTimeOnAir = TxTimeOnAir;
- MlmeConfirm.TxTimeOnAir = TxTimeOnAir;
+ MacCtx.McpsConfirm.TxTimeOnAir = MacCtx.TxTimeOnAir;
+ MacCtx.MlmeConfirm.TxTimeOnAir = MacCtx.TxTimeOnAir;
+
+ if( LoRaMacClassBIsBeaconModeActive( ) == true )
+ {
+ // Currently, the Time-On-Air can only be computed when the radio is configured with
+ // the TX configuration
+ TimerTime_t collisionTime = LoRaMacClassBIsUplinkCollision( MacCtx.TxTimeOnAir );
- // Starts the MAC layer status check timer
- TimerSetValue( &MacStateCheckTimer, MAC_STATE_CHECK_TIMEOUT );
- TimerStart( &MacStateCheckTimer );
+ if( collisionTime > 0 )
+ {
+ return LORAMAC_STATUS_BUSY_UPLINK_COLLISION;
+ }
+ }
- if( IsLoRaMacNetworkJoined == false )
+ if( MacCtx.NvmCtx->DeviceClass == CLASS_B )
{
- JoinRequestTrials++;
+ // Stop slots for class b
+ LoRaMacClassBStopRxSlots( );
}
- // Send now
- Radio.Send( LoRaMacBuffer, LoRaMacBufferPktLen );
+ LoRaMacClassBHaltBeaconing( );
- LoRaMacState |= LORAMAC_TX_RUNNING;
+ MacCtx.MacState |= LORAMAC_TX_RUNNING;
+ if( MacCtx.NodeAckRequested == false )
+ {
+ MacCtx.ChannelsNbTransCounter++;
+ }
+
+ // Send now
+ Radio.Send( MacCtx.PktBuffer, MacCtx.PktBufferLen );
return LORAMAC_STATUS_OK;
}
@@ -2388,20 +2838,16 @@ LoRaMacStatus_t SetTxContinuousWave( uint16_t timeout )
{
ContinuousWaveParams_t continuousWave;
- continuousWave.Channel = Channel;
- continuousWave.Datarate = LoRaMacParams.ChannelsDatarate;
- continuousWave.TxPower = LoRaMacParams.ChannelsTxPower;
- continuousWave.MaxEirp = LoRaMacParams.MaxEirp;
- continuousWave.AntennaGain = LoRaMacParams.AntennaGain;
+ continuousWave.Channel = MacCtx.Channel;
+ continuousWave.Datarate = MacCtx.NvmCtx->MacParams.ChannelsDatarate;
+ continuousWave.TxPower = MacCtx.NvmCtx->MacParams.ChannelsTxPower;
+ continuousWave.MaxEirp = MacCtx.NvmCtx->MacParams.MaxEirp;
+ continuousWave.AntennaGain = MacCtx.NvmCtx->MacParams.AntennaGain;
continuousWave.Timeout = timeout;
- RegionSetContinuousWave( LoRaMacRegion, &continuousWave );
+ RegionSetContinuousWave( MacCtx.NvmCtx->Region, &continuousWave );
- // Starts the MAC layer status check timer
- TimerSetValue( &MacStateCheckTimer, MAC_STATE_CHECK_TIMEOUT );
- TimerStart( &MacStateCheckTimer );
-
- LoRaMacState |= LORAMAC_TX_RUNNING;
+ MacCtx.MacState |= LORAMAC_TX_RUNNING;
return LORAMAC_STATUS_OK;
}
@@ -2410,21 +2856,297 @@ LoRaMacStatus_t SetTxContinuousWave1( uint16_t timeout, uint32_t frequency, uint
{
Radio.SetTxContinuousWave( frequency, power, timeout );
- // Starts the MAC layer status check timer
- TimerSetValue( &MacStateCheckTimer, MAC_STATE_CHECK_TIMEOUT );
- TimerStart( &MacStateCheckTimer );
+ MacCtx.MacState |= LORAMAC_TX_RUNNING;
+
+ return LORAMAC_STATUS_OK;
+}
+
+LoRaMacCtxs_t* GetCtxs( void )
+{
+ Contexts.MacNvmCtx = &NvmMacCtx;
+ Contexts.MacNvmCtxSize = sizeof( NvmMacCtx );
+ Contexts.CryptoNvmCtx = LoRaMacCryptoGetNvmCtx( &Contexts.CryptoNvmCtxSize );
+ GetNvmCtxParams_t params ={ 0 };
+ Contexts.RegionNvmCtx = RegionGetNvmCtx( MacCtx.NvmCtx->Region, ¶ms );
+ Contexts.RegionNvmCtxSize = params.nvmCtxSize;
+ Contexts.SecureElementNvmCtx = SecureElementGetNvmCtx( &Contexts.SecureElementNvmCtxSize );
+ Contexts.CommandsNvmCtx = LoRaMacCommandsGetNvmCtx( &Contexts.CommandsNvmCtxSize );
+ Contexts.ClassBNvmCtx = LoRaMacClassBGetNvmCtx( &Contexts.ClassBNvmCtxSize );
+ Contexts.ConfirmQueueNvmCtx = LoRaMacConfirmQueueGetNvmCtx( &Contexts.ConfirmQueueNvmCtxSize );
+ return &Contexts;
+}
+
+LoRaMacStatus_t RestoreCtxs( LoRaMacCtxs_t* contexts )
+{
+ if( contexts == NULL )
+ {
+ return LORAMAC_STATUS_PARAMETER_INVALID;
+ }
+ if( MacCtx.MacState != LORAMAC_STOPPED )
+ {
+ return LORAMAC_STATUS_BUSY;
+ }
+
+ if( contexts->MacNvmCtx != NULL )
+ {
+ memcpy1( ( uint8_t* ) &NvmMacCtx, ( uint8_t* ) contexts->MacNvmCtx, contexts->MacNvmCtxSize );
+ }
+
+ InitDefaultsParams_t params;
+ params.Type = INIT_TYPE_RESTORE_CTX;
+ params.NvmCtx = contexts->RegionNvmCtx;
+ RegionInitDefaults( MacCtx.NvmCtx->Region, ¶ms );
+
+ // Initialize RxC config parameters.
+ MacCtx.RxWindowCConfig.Channel = MacCtx.Channel;
+ MacCtx.RxWindowCConfig.Frequency = MacCtx.NvmCtx->MacParams.RxCChannel.Frequency;
+ MacCtx.RxWindowCConfig.DownlinkDwellTime = MacCtx.NvmCtx->MacParams.DownlinkDwellTime;
+ MacCtx.RxWindowCConfig.RepeaterSupport = MacCtx.NvmCtx->RepeaterSupport;
+ MacCtx.RxWindowCConfig.RxContinuous = true;
+ MacCtx.RxWindowCConfig.RxSlot = RX_SLOT_WIN_CLASS_C;
- LoRaMacState |= LORAMAC_TX_RUNNING;
+ if( SecureElementRestoreNvmCtx( contexts->SecureElementNvmCtx ) != SECURE_ELEMENT_SUCCESS )
+ {
+ return LORAMAC_STATUS_CRYPTO_ERROR;
+ }
+
+ if( LoRaMacCryptoRestoreNvmCtx( contexts->CryptoNvmCtx ) != LORAMAC_CRYPTO_SUCCESS )
+ {
+ return LORAMAC_STATUS_CRYPTO_ERROR;
+ }
+
+ if( LoRaMacCommandsRestoreNvmCtx( contexts->CommandsNvmCtx ) != LORAMAC_COMMANDS_SUCCESS )
+ {
+ return LORAMAC_STATUS_MAC_COMMAD_ERROR;
+ }
+
+ if( LoRaMacClassBRestoreNvmCtx( contexts->ClassBNvmCtx ) != true )
+ {
+ return LORAMAC_STATUS_CLASS_B_ERROR;
+ }
+
+ if( LoRaMacConfirmQueueRestoreNvmCtx( contexts->ConfirmQueueNvmCtx ) != true )
+ {
+ return LORAMAC_STATUS_CONFIRM_QUEUE_ERROR;
+ }
+
+ return LORAMAC_STATUS_OK;
+}
+
+LoRaMacStatus_t DetermineFrameType( LoRaMacMessageData_t* macMsg, FType_t* fType )
+{
+ if( ( macMsg == NULL ) || ( fType == NULL ) )
+ {
+ return LORAMAC_STATUS_PARAMETER_INVALID;
+ }
+
+ /* The LoRaWAN specification allows several possible configurations how data up/down frames are built up.
+ * In sake of clearness the following naming is applied. Please keep in mind that this is
+ * implementation specific since there is no definition in the LoRaWAN specification included.
+ *
+ * X -> Field is available
+ * - -> Field is not available
+ *
+ * +-------+ +----------+------+-------+--------------+
+ * | FType | | FOptsLen | Fopt | FPort | FRMPayload |
+ * +-------+ +----------+------+-------+--------------+
+ * | A | | > 0 | X | > 0 | X |
+ * +-------+ +----------+------+-------+--------------+
+ * | B | | >= 0 | X/- | - | - |
+ * +-------+ +----------+------+-------+--------------+
+ * | C | | = 0 | - | = 0 | MAC commands |
+ * +-------+ +----------+------+-------+--------------+
+ * | D | | = 0 | - | > 0 | X |
+ * +-------+ +----------+------+-------+--------------+
+ */
+
+ if( ( macMsg->FHDR.FCtrl.Bits.FOptsLen > 0 ) && ( macMsg->FPort > 0 ) )
+ {
+ *fType = FRAME_TYPE_A;
+ }
+ else if( macMsg->FRMPayloadSize == 0 )
+ {
+ *fType = FRAME_TYPE_B;
+ }
+ else if( ( macMsg->FHDR.FCtrl.Bits.FOptsLen == 0 ) && ( macMsg->FPort == 0 ) )
+ {
+ *fType = FRAME_TYPE_C;
+ }
+ else if( ( macMsg->FHDR.FCtrl.Bits.FOptsLen == 0 ) && ( macMsg->FPort > 0 ) )
+ {
+ *fType = FRAME_TYPE_D;
+ }
+ else
+ {
+ // Should never happen.
+ return LORAMAC_STATUS_ERROR;
+ }
return LORAMAC_STATUS_OK;
}
-LoRaMacStatus_t LoRaMacInitialization( LoRaMacPrimitives_t *primitives, LoRaMacCallback_t *callbacks, LoRaMacRegion_t region )
+static bool CheckRetransUnconfirmedUplink( void )
+{
+ // Unconfirmed uplink, when all retransmissions are done.
+ if( MacCtx.ChannelsNbTransCounter >=
+ MacCtx.NvmCtx->MacParams.ChannelsNbTrans )
+ {
+ return true;
+ }
+ else if( MacCtx.MacFlags.Bits.McpsInd == 1 )
+ {
+ // For Class A stop in each case
+ if( MacCtx.NvmCtx->DeviceClass == CLASS_A )
+ {
+ return true;
+ }
+ else
+ {// For Class B & C stop only if the frame was received in RX1 window
+ if( MacCtx.McpsIndication.RxSlot == RX_SLOT_WIN_1 )
+ {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+static bool CheckRetransConfirmedUplink( void )
+{
+ // Confirmed uplink, when all retransmissions ( tries to get a ack ) are done.
+ if( MacCtx.AckTimeoutRetriesCounter >=
+ MacCtx.AckTimeoutRetries )
+ {
+ return true;
+ }
+ else if( MacCtx.MacFlags.Bits.McpsInd == 1 )
+ {
+ if( MacCtx.McpsConfirm.AckReceived == true )
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+static bool StopRetransmission( void )
+{
+ if( ( MacCtx.MacFlags.Bits.McpsInd == 0 ) ||
+ ( ( MacCtx.McpsIndication.RxSlot != RX_SLOT_WIN_1 ) &&
+ ( MacCtx.McpsIndication.RxSlot != RX_SLOT_WIN_2 ) ) )
+ { // Maximum repetitions without downlink. Increase ADR Ack counter.
+ // Only process the case when the MAC did not receive a downlink.
+ if( MacCtx.NvmCtx->AdrCtrlOn == true )
+ {
+ MacCtx.NvmCtx->AdrAckCounter++;
+ }
+ }
+
+ MacCtx.ChannelsNbTransCounter = 0;
+ MacCtx.NodeAckRequested = false;
+ MacCtx.AckTimeoutRetry = false;
+ MacCtx.MacState &= ~LORAMAC_TX_RUNNING;
+
+ return true;
+}
+
+static void AckTimeoutRetriesProcess( void )
+{
+ if( MacCtx.AckTimeoutRetriesCounter < MacCtx.AckTimeoutRetries )
+ {
+ MacCtx.AckTimeoutRetriesCounter++;
+ if( ( MacCtx.AckTimeoutRetriesCounter % 2 ) == 1 )
+ {
+ GetPhyParams_t getPhy;
+ PhyParam_t phyParam;
+
+ getPhy.Attribute = PHY_NEXT_LOWER_TX_DR;
+ getPhy.UplinkDwellTime = MacCtx.NvmCtx->MacParams.UplinkDwellTime;
+ getPhy.Datarate = MacCtx.NvmCtx->MacParams.ChannelsDatarate;
+ phyParam = RegionGetPhyParam( MacCtx.NvmCtx->Region, &getPhy );
+ MacCtx.NvmCtx->MacParams.ChannelsDatarate = phyParam.Value;
+ }
+ }
+}
+
+static void AckTimeoutRetriesFinalize( void )
+{
+ if( MacCtx.McpsConfirm.AckReceived == false )
+ {
+ InitDefaultsParams_t params;
+ params.Type = INIT_TYPE_RESTORE_DEFAULT_CHANNELS;
+ params.NvmCtx = Contexts.RegionNvmCtx;
+ RegionInitDefaults( MacCtx.NvmCtx->Region, ¶ms );
+
+ MacCtx.NodeAckRequested = false;
+ MacCtx.McpsConfirm.AckReceived = false;
+ }
+ MacCtx.McpsConfirm.NbRetries = MacCtx.AckTimeoutRetriesCounter;
+}
+
+static void CallNvmCtxCallback( LoRaMacNvmCtxModule_t module )
+{
+ if( ( MacCtx.MacCallbacks != NULL ) && ( MacCtx.MacCallbacks->NvmContextChange != NULL ) )
+ {
+ MacCtx.MacCallbacks->NvmContextChange( module );
+ }
+}
+
+static void EventMacNvmCtxChanged( void )
+{
+ CallNvmCtxCallback( LORAMAC_NVMCTXMODULE_MAC );
+}
+
+static void EventRegionNvmCtxChanged( void )
+{
+ CallNvmCtxCallback( LORAMAC_NVMCTXMODULE_REGION );
+}
+
+static void EventCryptoNvmCtxChanged( void )
+{
+ CallNvmCtxCallback( LORAMAC_NVMCTXMODULE_CRYPTO );
+}
+
+static void EventSecureElementNvmCtxChanged( void )
+{
+ CallNvmCtxCallback( LORAMAC_NVMCTXMODULE_SECURE_ELEMENT );
+}
+
+static void EventCommandsNvmCtxChanged( void )
+{
+ CallNvmCtxCallback( LORAMAC_NVMCTXMODULE_COMMANDS );
+}
+
+static void EventClassBNvmCtxChanged( void )
+{
+ CallNvmCtxCallback( LORAMAC_NVMCTXMODULE_CLASS_B );
+}
+
+static void EventConfirmQueueNvmCtxChanged( void )
+{
+ CallNvmCtxCallback( LORAMAC_NVMCTXMODULE_CONFIRM_QUEUE );
+}
+
+static uint8_t IsRequestPending( void )
+{
+ if( ( MacCtx.MacFlags.Bits.MlmeReq == 1 ) ||
+ ( MacCtx.MacFlags.Bits.McpsReq == 1 ) )
+ {
+ return 1;
+ }
+ return 0;
+}
+
+
+LoRaMacStatus_t LoRaMacInitialization( LoRaMacPrimitives_t* primitives, LoRaMacCallback_t* callbacks, LoRaMacRegion_t region )
{
GetPhyParams_t getPhy;
PhyParam_t phyParam;
+ LoRaMacClassBCallback_t classBCallbacks;
+ LoRaMacClassBParams_t classBParams;
- if( primitives == NULL )
+ if( ( primitives == NULL ) ||
+ ( callbacks == NULL ) )
{
return LORAMAC_STATUS_PARAMETER_INVALID;
}
@@ -2442,143 +3164,232 @@ LoRaMacStatus_t LoRaMacInitialization( LoRaMacPrimitives_t *primitives, LoRaMacC
return LORAMAC_STATUS_REGION_NOT_SUPPORTED;
}
- LoRaMacPrimitives = primitives;
- LoRaMacCallbacks = callbacks;
- LoRaMacRegion = region;
+ // Confirm queue reset
+ LoRaMacConfirmQueueInit( primitives, EventConfirmQueueNvmCtxChanged );
- LoRaMacFlags.Value = 0;
+ // Initialize the module context with zeros
+ memset1( ( uint8_t* ) &NvmMacCtx, 0x00, sizeof( LoRaMacNvmCtx_t ) );
+ memset1( ( uint8_t* ) &MacCtx, 0x00, sizeof( LoRaMacCtx_t ) );
+ MacCtx.NvmCtx = &NvmMacCtx;
- LoRaMacDeviceClass = CLASS_A;
- LoRaMacState = LORAMAC_IDLE;
- NetworkActivation = ACTIVATION_TYPE_NONE;
+ // Set non zero variables to its default value
+ MacCtx.AckTimeoutRetriesCounter = 1;
+ MacCtx.AckTimeoutRetries = 1;
+ MacCtx.NvmCtx->Region = region;
+ MacCtx.NvmCtx->DeviceClass = CLASS_A;
+ MacCtx.NvmCtx->RepeaterSupport = false;
- JoinRequestTrials = 0;
- MaxJoinRequestTrials = 1;
- RepeaterSupport = false;
-
- // Reset duty cycle times
- AggregatedLastTxDoneTime = 0;
- AggregatedTimeOff = 0;
+ Version_t lrWanVersion;
+ lrWanVersion.Fields.Major = 1;
+ lrWanVersion.Fields.Minor = 0;
+ lrWanVersion.Fields.Revision = 3;
+ lrWanVersion.Fields.Rfu = 0;
+ MacCtx.NvmCtx->Version = lrWanVersion;
// Reset to defaults
getPhy.Attribute = PHY_DUTY_CYCLE;
- phyParam = RegionGetPhyParam( LoRaMacRegion, &getPhy );
- DutyCycleOn = ( bool ) phyParam.Value;
+ phyParam = RegionGetPhyParam( MacCtx.NvmCtx->Region, &getPhy );
+ MacCtx.NvmCtx->DutyCycleOn = ( bool ) phyParam.Value;
getPhy.Attribute = PHY_DEF_TX_POWER;
- phyParam = RegionGetPhyParam( LoRaMacRegion, &getPhy );
- LoRaMacParamsDefaults.ChannelsTxPower = phyParam.Value;
+ phyParam = RegionGetPhyParam( MacCtx.NvmCtx->Region, &getPhy );
+ MacCtx.NvmCtx->MacParamsDefaults.ChannelsTxPower = phyParam.Value;
getPhy.Attribute = PHY_DEF_TX_DR;
- phyParam = RegionGetPhyParam( LoRaMacRegion, &getPhy );
- LoRaMacParamsDefaults.ChannelsDatarate = phyParam.Value;
+ phyParam = RegionGetPhyParam( MacCtx.NvmCtx->Region, &getPhy );
+ MacCtx.NvmCtx->MacParamsDefaults.ChannelsDatarate = phyParam.Value;
getPhy.Attribute = PHY_MAX_RX_WINDOW;
- phyParam = RegionGetPhyParam( LoRaMacRegion, &getPhy );
- LoRaMacParamsDefaults.MaxRxWindow = phyParam.Value;
+ phyParam = RegionGetPhyParam( MacCtx.NvmCtx->Region, &getPhy );
+ MacCtx.NvmCtx->MacParamsDefaults.MaxRxWindow = phyParam.Value;
getPhy.Attribute = PHY_RECEIVE_DELAY1;
- phyParam = RegionGetPhyParam( LoRaMacRegion, &getPhy );
- LoRaMacParamsDefaults.ReceiveDelay1 = phyParam.Value;
+ phyParam = RegionGetPhyParam( MacCtx.NvmCtx->Region, &getPhy );
+ MacCtx.NvmCtx->MacParamsDefaults.ReceiveDelay1 = phyParam.Value;
getPhy.Attribute = PHY_RECEIVE_DELAY2;
- phyParam = RegionGetPhyParam( LoRaMacRegion, &getPhy );
- LoRaMacParamsDefaults.ReceiveDelay2 = phyParam.Value;
+ phyParam = RegionGetPhyParam( MacCtx.NvmCtx->Region, &getPhy );
+ MacCtx.NvmCtx->MacParamsDefaults.ReceiveDelay2 = phyParam.Value;
getPhy.Attribute = PHY_JOIN_ACCEPT_DELAY1;
- phyParam = RegionGetPhyParam( LoRaMacRegion, &getPhy );
- LoRaMacParamsDefaults.JoinAcceptDelay1 = phyParam.Value;
+ phyParam = RegionGetPhyParam( MacCtx.NvmCtx->Region, &getPhy );
+ MacCtx.NvmCtx->MacParamsDefaults.JoinAcceptDelay1 = phyParam.Value;
getPhy.Attribute = PHY_JOIN_ACCEPT_DELAY2;
- phyParam = RegionGetPhyParam( LoRaMacRegion, &getPhy );
- LoRaMacParamsDefaults.JoinAcceptDelay2 = phyParam.Value;
+ phyParam = RegionGetPhyParam( MacCtx.NvmCtx->Region, &getPhy );
+ MacCtx.NvmCtx->MacParamsDefaults.JoinAcceptDelay2 = phyParam.Value;
getPhy.Attribute = PHY_DEF_DR1_OFFSET;
- phyParam = RegionGetPhyParam( LoRaMacRegion, &getPhy );
- LoRaMacParamsDefaults.Rx1DrOffset = phyParam.Value;
+ phyParam = RegionGetPhyParam( MacCtx.NvmCtx->Region, &getPhy );
+ MacCtx.NvmCtx->MacParamsDefaults.Rx1DrOffset = phyParam.Value;
getPhy.Attribute = PHY_DEF_RX2_FREQUENCY;
- phyParam = RegionGetPhyParam( LoRaMacRegion, &getPhy );
- LoRaMacParamsDefaults.Rx2Channel.Frequency = phyParam.Value;
+ phyParam = RegionGetPhyParam( MacCtx.NvmCtx->Region, &getPhy );
+ MacCtx.NvmCtx->MacParamsDefaults.Rx2Channel.Frequency = phyParam.Value;
+ MacCtx.NvmCtx->MacParamsDefaults.RxCChannel.Frequency = phyParam.Value;
getPhy.Attribute = PHY_DEF_RX2_DR;
- phyParam = RegionGetPhyParam( LoRaMacRegion, &getPhy );
- LoRaMacParamsDefaults.Rx2Channel.Datarate = phyParam.Value;
+ phyParam = RegionGetPhyParam( MacCtx.NvmCtx->Region, &getPhy );
+ MacCtx.NvmCtx->MacParamsDefaults.Rx2Channel.Datarate = phyParam.Value;
+ MacCtx.NvmCtx->MacParamsDefaults.RxCChannel.Datarate = phyParam.Value;
getPhy.Attribute = PHY_DEF_UPLINK_DWELL_TIME;
- phyParam = RegionGetPhyParam( LoRaMacRegion, &getPhy );
- LoRaMacParamsDefaults.UplinkDwellTime = phyParam.Value;
+ phyParam = RegionGetPhyParam( MacCtx.NvmCtx->Region, &getPhy );
+ MacCtx.NvmCtx->MacParamsDefaults.UplinkDwellTime = phyParam.Value;
getPhy.Attribute = PHY_DEF_DOWNLINK_DWELL_TIME;
- phyParam = RegionGetPhyParam( LoRaMacRegion, &getPhy );
- LoRaMacParamsDefaults.DownlinkDwellTime = phyParam.Value;
+ phyParam = RegionGetPhyParam( MacCtx.NvmCtx->Region, &getPhy );
+ MacCtx.NvmCtx->MacParamsDefaults.DownlinkDwellTime = phyParam.Value;
getPhy.Attribute = PHY_DEF_MAX_EIRP;
- phyParam = RegionGetPhyParam( LoRaMacRegion, &getPhy );
- LoRaMacParamsDefaults.MaxEirp = phyParam.fValue;
+ phyParam = RegionGetPhyParam( MacCtx.NvmCtx->Region, &getPhy );
+ MacCtx.NvmCtx->MacParamsDefaults.MaxEirp = phyParam.fValue;
getPhy.Attribute = PHY_DEF_ANTENNA_GAIN;
- phyParam = RegionGetPhyParam( LoRaMacRegion, &getPhy );
- LoRaMacParamsDefaults.AntennaGain = phyParam.fValue;
+ phyParam = RegionGetPhyParam( MacCtx.NvmCtx->Region, &getPhy );
+ MacCtx.NvmCtx->MacParamsDefaults.AntennaGain = phyParam.fValue;
- RegionInitDefaults( LoRaMacRegion, INIT_TYPE_INIT );
+ getPhy.Attribute = PHY_DEF_ADR_ACK_LIMIT;
+ phyParam = RegionGetPhyParam( MacCtx.NvmCtx->Region, &getPhy );
+ MacCtx.AdrAckLimit = phyParam.Value;
+
+ getPhy.Attribute = PHY_DEF_ADR_ACK_DELAY;
+ phyParam = RegionGetPhyParam( MacCtx.NvmCtx->Region, &getPhy );
+ MacCtx.AdrAckDelay = phyParam.Value;
// Init parameters which are not set in function ResetMacParameters
- LoRaMacParamsDefaults.ChannelsNbRep = 1;
- LoRaMacParamsDefaults.SystemMaxRxError = 10;
- LoRaMacParamsDefaults.MinRxSymbols = 6;
-
- LoRaMacParams.SystemMaxRxError = LoRaMacParamsDefaults.SystemMaxRxError;
- LoRaMacParams.MinRxSymbols = LoRaMacParamsDefaults.MinRxSymbols;
- LoRaMacParams.MaxRxWindow = LoRaMacParamsDefaults.MaxRxWindow;
- LoRaMacParams.ReceiveDelay1 = LoRaMacParamsDefaults.ReceiveDelay1;
- LoRaMacParams.ReceiveDelay2 = LoRaMacParamsDefaults.ReceiveDelay2;
- LoRaMacParams.JoinAcceptDelay1 = LoRaMacParamsDefaults.JoinAcceptDelay1;
- LoRaMacParams.JoinAcceptDelay2 = LoRaMacParamsDefaults.JoinAcceptDelay2;
- LoRaMacParams.ChannelsNbRep = LoRaMacParamsDefaults.ChannelsNbRep;
+ MacCtx.NvmCtx->MacParamsDefaults.ChannelsNbTrans = 1;
+ MacCtx.NvmCtx->MacParamsDefaults.SystemMaxRxError = 10;
+ MacCtx.NvmCtx->MacParamsDefaults.MinRxSymbols = 6;
+
+ MacCtx.NvmCtx->MacParams.SystemMaxRxError = MacCtx.NvmCtx->MacParamsDefaults.SystemMaxRxError;
+ MacCtx.NvmCtx->MacParams.MinRxSymbols = MacCtx.NvmCtx->MacParamsDefaults.MinRxSymbols;
+ MacCtx.NvmCtx->MacParams.MaxRxWindow = MacCtx.NvmCtx->MacParamsDefaults.MaxRxWindow;
+ MacCtx.NvmCtx->MacParams.ReceiveDelay1 = MacCtx.NvmCtx->MacParamsDefaults.ReceiveDelay1;
+ MacCtx.NvmCtx->MacParams.ReceiveDelay2 = MacCtx.NvmCtx->MacParamsDefaults.ReceiveDelay2;
+ MacCtx.NvmCtx->MacParams.JoinAcceptDelay1 = MacCtx.NvmCtx->MacParamsDefaults.JoinAcceptDelay1;
+ MacCtx.NvmCtx->MacParams.JoinAcceptDelay2 = MacCtx.NvmCtx->MacParamsDefaults.JoinAcceptDelay2;
+ MacCtx.NvmCtx->MacParams.ChannelsNbTrans = MacCtx.NvmCtx->MacParamsDefaults.ChannelsNbTrans;
ResetMacParameters( );
- // Initialize timers
- TimerInit( &MacStateCheckTimer, OnMacStateCheckTimerEvent );
- TimerSetValue( &MacStateCheckTimer, MAC_STATE_CHECK_TIMEOUT );
+ MacCtx.NvmCtx->PublicNetwork = true;
+
+ MacCtx.MacPrimitives = primitives;
+ MacCtx.MacCallbacks = callbacks;
+ MacCtx.MacFlags.Value = 0;
+ MacCtx.MacState = LORAMAC_STOPPED;
+
+ // Reset duty cycle times
+ MacCtx.NvmCtx->LastTxDoneTime = 0;
+ MacCtx.NvmCtx->AggregatedTimeOff = 0;
- TimerInit( &TxDelayedTimer, OnTxDelayedTimerEvent );
- TimerInit( &RxWindowTimer1, OnRxWindow1TimerEvent );
- TimerInit( &RxWindowTimer2, OnRxWindow2TimerEvent );
- TimerInit( &AckTimeoutTimer, OnAckTimeoutTimerEvent );
- //TimerInit( &RadioTxDoneClassCTimer, OnRxWindow2TimerEvent );
- //TimerSetValue( &RadioTxDoneClassCTimer, 1 );
+ // Initialize timers
+ TimerInit( &MacCtx.TxDelayedTimer, OnTxDelayedTimerEvent );
+ TimerInit( &MacCtx.RxWindowTimer1, OnRxWindow1TimerEvent );
+ TimerInit( &MacCtx.RxWindowTimer2, OnRxWindow2TimerEvent );
+ TimerInit( &MacCtx.AckTimeoutTimer, OnAckTimeoutTimerEvent );
// Store the current initialization time
- LoRaMacInitializationTime = TimerGetCurrentTime( );
+ MacCtx.NvmCtx->InitializationTime = SysTimeGetMcuTime( );
// Initialize Radio driver
- RadioEvents.TxDone = OnRadioTxDone;
- RadioEvents.RxDone = OnRadioRxDone;
- RadioEvents.RxError = OnRadioRxError;
- RadioEvents.TxTimeout = OnRadioTxTimeout;
- RadioEvents.RxTimeout = OnRadioRxTimeout;
- Radio.Init( &RadioEvents );
+ MacCtx.RadioEvents.TxDone = OnRadioTxDone;
+ MacCtx.RadioEvents.RxDone = OnRadioRxDone;
+ MacCtx.RadioEvents.RxError = OnRadioRxError;
+ MacCtx.RadioEvents.TxTimeout = OnRadioTxTimeout;
+ MacCtx.RadioEvents.RxTimeout = OnRadioRxTimeout;
+ Radio.Init( &MacCtx.RadioEvents );
+
+ InitDefaultsParams_t params;
+ params.Type = INIT_TYPE_INIT;
+ params.NvmCtx = NULL;
+ RegionInitDefaults( MacCtx.NvmCtx->Region, ¶ms );
+
+ // Initialize the Secure Element driver
+ if( SecureElementInit( EventSecureElementNvmCtxChanged ) != SECURE_ELEMENT_SUCCESS )
+ {
+ return LORAMAC_STATUS_CRYPTO_ERROR;
+ }
+
+ // Initialize Crypto module
+ if( LoRaMacCryptoInit( EventCryptoNvmCtxChanged ) != LORAMAC_CRYPTO_SUCCESS )
+ {
+ return LORAMAC_STATUS_CRYPTO_ERROR;
+ }
+
+ // Initialize MAC commands module
+ if( LoRaMacCommandsInit( EventCommandsNvmCtxChanged ) != LORAMAC_COMMANDS_SUCCESS )
+ {
+ return LORAMAC_STATUS_MAC_COMMAD_ERROR;
+ }
+
+ // Set multicast downlink counter reference
+ if( LoRaMacCryptoSetMulticastReference( MacCtx.NvmCtx->MulticastChannelList ) != LORAMAC_CRYPTO_SUCCESS )
+ {
+ return LORAMAC_STATUS_CRYPTO_ERROR;
+ }
// Random seed initialization
srand1( Radio.Random( ) );
- PublicNetwork = true;
- Radio.SetPublicNetwork( PublicNetwork );
+ Radio.SetPublicNetwork( MacCtx.NvmCtx->PublicNetwork );
Radio.Sleep( );
+ // Initialize class b
+ // Apply callback
+ classBCallbacks.GetTemperatureLevel = NULL;
+ classBCallbacks.MacProcessNotify = NULL;
+ if( callbacks != NULL )
+ {
+ classBCallbacks.GetTemperatureLevel = callbacks->GetTemperatureLevel;
+ classBCallbacks.MacProcessNotify = callbacks->MacProcessNotify;
+ }
+
+ // Must all be static. Don't use local references.
+ classBParams.MlmeIndication = &MacCtx.MlmeIndication;
+ classBParams.McpsIndication = &MacCtx.McpsIndication;
+ classBParams.MlmeConfirm = &MacCtx.MlmeConfirm;
+ classBParams.LoRaMacFlags = &MacCtx.MacFlags;
+ classBParams.LoRaMacDevAddr = &MacCtx.NvmCtx->DevAddr;
+ classBParams.LoRaMacRegion = &MacCtx.NvmCtx->Region;
+ classBParams.LoRaMacParams = &MacCtx.NvmCtx->MacParams;
+ classBParams.MulticastChannels = &MacCtx.NvmCtx->MulticastChannelList[0];
+
+ LoRaMacClassBInit( &classBParams, &classBCallbacks, &EventClassBNvmCtxChanged );
+
+ LoRaMacEnableRequests( LORAMAC_REQUEST_HANDLING_ON );
+
+ return LORAMAC_STATUS_OK;
+}
+
+LoRaMacStatus_t LoRaMacStart( void )
+{
+ MacCtx.MacState = LORAMAC_IDLE;
return LORAMAC_STATUS_OK;
}
+LoRaMacStatus_t LoRaMacStop( void )
+{
+ if( LoRaMacIsBusy( ) == false )
+ {
+ MacCtx.MacState = LORAMAC_STOPPED;
+ return LORAMAC_STATUS_OK;
+ }
+ else if( MacCtx.MacState == LORAMAC_STOPPED )
+ {
+ return LORAMAC_STATUS_OK;
+ }
+ return LORAMAC_STATUS_BUSY;
+}
+
LoRaMacStatus_t LoRaMacQueryTxPossible( uint8_t size, LoRaMacTxInfo_t* txInfo )
{
- AdrNextParams_t adrNext;
- GetPhyParams_t getPhy;
- PhyParam_t phyParam;
- int8_t datarate = LoRaMacParamsDefaults.ChannelsDatarate;
- int8_t txPower = LoRaMacParamsDefaults.ChannelsTxPower;
- uint8_t fOptLen = MacCommandsBufferIndex + MacCommandsBufferToRepeatIndex;
+ CalcNextAdrParams_t adrNext;
+ uint32_t adrAckCounter = MacCtx.NvmCtx->AdrAckCounter;
+ int8_t datarate = MacCtx.NvmCtx->MacParamsDefaults.ChannelsDatarate;
+ int8_t txPower = MacCtx.NvmCtx->MacParamsDefaults.ChannelsTxPower;
+ size_t macCmdsSize = 0;
if( txInfo == NULL )
{
@@ -2586,54 +3397,51 @@ LoRaMacStatus_t LoRaMacQueryTxPossible( uint8_t size, LoRaMacTxInfo_t* txInfo )
}
// Setup ADR request
+ adrNext.Version = MacCtx.NvmCtx->Version;
adrNext.UpdateChanMask = false;
- adrNext.AdrEnabled = AdrCtrlOn;
- adrNext.AdrAckCounter = AdrAckCounter;
- adrNext.Datarate = LoRaMacParams.ChannelsDatarate;
- adrNext.TxPower = LoRaMacParams.ChannelsTxPower;
- adrNext.UplinkDwellTime = LoRaMacParams.UplinkDwellTime;
+ adrNext.AdrEnabled = MacCtx.NvmCtx->AdrCtrlOn;
+ adrNext.AdrAckCounter = MacCtx.NvmCtx->AdrAckCounter;
+ adrNext.AdrAckLimit = MacCtx.AdrAckLimit;
+ adrNext.AdrAckDelay = MacCtx.AdrAckDelay;
+ adrNext.Datarate = MacCtx.NvmCtx->MacParams.ChannelsDatarate;
+ adrNext.TxPower = MacCtx.NvmCtx->MacParams.ChannelsTxPower;
+ adrNext.UplinkDwellTime = MacCtx.NvmCtx->MacParams.UplinkDwellTime;
+ adrNext.Region = MacCtx.NvmCtx->Region;
// We call the function for information purposes only. We don't want to
// apply the datarate, the tx power and the ADR ack counter.
- RegionAdrNext( LoRaMacRegion, &adrNext, &datarate, &txPower, &AdrAckCounter );
+ LoRaMacAdrCalcNext( &adrNext, &datarate, &txPower, &adrAckCounter );
- // Setup PHY request
- getPhy.UplinkDwellTime = LoRaMacParams.UplinkDwellTime;
- getPhy.Datarate = datarate;
- getPhy.Attribute = PHY_MAX_PAYLOAD;
+ txInfo->CurrentPossiblePayloadSize = GetMaxAppPayloadWithoutFOptsLength( datarate );
- // Change request in case repeater is supported
- if( RepeaterSupport == true )
+ if( LoRaMacCommandsGetSizeSerializedCmds( &macCmdsSize ) != LORAMAC_COMMANDS_SUCCESS )
{
- getPhy.Attribute = PHY_MAX_PAYLOAD_REPEATER;
+ return LORAMAC_STATUS_MAC_COMMAD_ERROR;
}
- phyParam = RegionGetPhyParam( LoRaMacRegion, &getPhy );
- txInfo->CurrentPayloadSize = phyParam.Value;
- // Verify if the fOpts fit into the maximum payload
- if( txInfo->CurrentPayloadSize >= fOptLen )
+ // Verify if the MAC commands fit into the FOpts and into the maximum payload.
+ if( ( LORA_MAC_COMMAND_MAX_FOPTS_LENGTH >= macCmdsSize ) && ( txInfo->CurrentPossiblePayloadSize >= macCmdsSize ) )
{
- txInfo->MaxPossiblePayload = txInfo->CurrentPayloadSize - fOptLen;
- }
- else
- {
- txInfo->MaxPossiblePayload = txInfo->CurrentPayloadSize;
- // The fOpts don't fit into the maximum payload. Omit the MAC commands to
- // ensure that another uplink is possible.
- fOptLen = 0;
- MacCommandsBufferIndex = 0;
- MacCommandsBufferToRepeatIndex = 0;
- }
+ txInfo->MaxPossibleApplicationDataSize = txInfo->CurrentPossiblePayloadSize - macCmdsSize;
- // Verify if the fOpts and the payload fit into the maximum payload
- if( ValidatePayloadLength( size, datarate, fOptLen ) == false )
+ // Verify if the application data together with MAC command fit into the maximum payload.
+ if( txInfo->CurrentPossiblePayloadSize >= ( macCmdsSize + size ) )
+ {
+ return LORAMAC_STATUS_OK;
+ }
+ else
+ {
+ return LORAMAC_STATUS_LENGTH_ERROR;
+ }
+ }
+ else
{
+ txInfo->MaxPossibleApplicationDataSize = 0;
return LORAMAC_STATUS_LENGTH_ERROR;
}
- return LORAMAC_STATUS_OK;
}
-LoRaMacStatus_t LoRaMacMibGetRequestConfirm( MibRequestConfirm_t *mibGet )
+LoRaMacStatus_t LoRaMacMibGetRequestConfirm( MibRequestConfirm_t* mibGet )
{
LoRaMacStatus_t status = LORAMAC_STATUS_OK;
GetPhyParams_t getPhy;
@@ -2648,76 +3456,81 @@ LoRaMacStatus_t LoRaMacMibGetRequestConfirm( MibRequestConfirm_t *mibGet )
{
case MIB_DEVICE_CLASS:
{
- mibGet->Param.Class = LoRaMacDeviceClass;
+ mibGet->Param.Class = MacCtx.NvmCtx->DeviceClass;
break;
}
case MIB_NETWORK_ACTIVATION:
{
- mibGet->Param.NetworkActivation = NetworkActivation;
+ mibGet->Param.NetworkActivation = MacCtx.NvmCtx->NetworkActivation;
break;
}
- case MIB_NETWORK_JOINED:
+ case MIB_DEV_EUI:
{
- mibGet->Param.IsNetworkJoined = IsLoRaMacNetworkJoined;
+ mibGet->Param.DevEui = SecureElementGetDevEui( );
break;
}
- case MIB_ADR:
- {
- mibGet->Param.AdrEnable = AdrCtrlOn;
- break;
- }
- case MIB_NET_ID:
+ case MIB_JOIN_EUI:
{
- mibGet->Param.NetID = LoRaMacNetID;
+ mibGet->Param.JoinEui = SecureElementGetJoinEui( );
break;
}
- case MIB_DEV_ADDR:
+ case MIB_ADR:
{
- mibGet->Param.DevAddr = LoRaMacDevAddr;
+ mibGet->Param.AdrEnable = MacCtx.NvmCtx->AdrCtrlOn;
break;
}
- case MIB_NWK_SKEY:
+ case MIB_NET_ID:
{
- mibGet->Param.NwkSKey = LoRaMacNwkSKey;
+ mibGet->Param.NetID = MacCtx.NvmCtx->NetID;
break;
}
- case MIB_APP_SKEY:
+ case MIB_DEV_ADDR:
{
- mibGet->Param.AppSKey = LoRaMacAppSKey;
+ mibGet->Param.DevAddr = MacCtx.NvmCtx->DevAddr;
break;
}
case MIB_PUBLIC_NETWORK:
{
- mibGet->Param.EnablePublicNetwork = PublicNetwork;
+ mibGet->Param.EnablePublicNetwork = MacCtx.NvmCtx->PublicNetwork;
break;
}
case MIB_REPEATER_SUPPORT:
{
- mibGet->Param.EnableRepeaterSupport = RepeaterSupport;
+ mibGet->Param.EnableRepeaterSupport = MacCtx.NvmCtx->RepeaterSupport;
break;
}
case MIB_CHANNELS:
{
getPhy.Attribute = PHY_CHANNELS;
- phyParam = RegionGetPhyParam( LoRaMacRegion, &getPhy );
+ phyParam = RegionGetPhyParam( MacCtx.NvmCtx->Region, &getPhy );
mibGet->Param.ChannelList = phyParam.Channels;
break;
}
case MIB_RX2_CHANNEL:
{
- mibGet->Param.Rx2Channel = LoRaMacParams.Rx2Channel;
+ mibGet->Param.Rx2Channel = MacCtx.NvmCtx->MacParams.Rx2Channel;
break;
}
case MIB_RX2_DEFAULT_CHANNEL:
{
- mibGet->Param.Rx2Channel = LoRaMacParamsDefaults.Rx2Channel;
+ mibGet->Param.Rx2Channel = MacCtx.NvmCtx->MacParamsDefaults.Rx2Channel;
+ break;
+ }
+ case MIB_RXC_CHANNEL:
+ {
+ mibGet->Param.RxCChannel = MacCtx.NvmCtx->MacParams.RxCChannel;
+ break;
+ }
+ case MIB_RXC_DEFAULT_CHANNEL:
+ {
+ mibGet->Param.RxCChannel = MacCtx.NvmCtx->MacParamsDefaults.RxCChannel;
break;
}
case MIB_CHANNELS_DEFAULT_MASK:
{
getPhy.Attribute = PHY_CHANNELS_DEFAULT_MASK;
- phyParam = RegionGetPhyParam( LoRaMacRegion, &getPhy );
+ phyParam = RegionGetPhyParam( MacCtx.NvmCtx->Region, &getPhy );
mibGet->Param.ChannelsDefaultMask = phyParam.ChannelsMask;
break;
@@ -2725,100 +3538,96 @@ LoRaMacStatus_t LoRaMacMibGetRequestConfirm( MibRequestConfirm_t *mibGet )
case MIB_CHANNELS_MASK:
{
getPhy.Attribute = PHY_CHANNELS_MASK;
- phyParam = RegionGetPhyParam( LoRaMacRegion, &getPhy );
+ phyParam = RegionGetPhyParam( MacCtx.NvmCtx->Region, &getPhy );
mibGet->Param.ChannelsMask = phyParam.ChannelsMask;
break;
}
- case MIB_CHANNELS_NB_REP:
+ case MIB_CHANNELS_NB_TRANS:
{
- mibGet->Param.ChannelNbRep = LoRaMacParams.ChannelsNbRep;
+ mibGet->Param.ChannelsNbTrans = MacCtx.NvmCtx->MacParams.ChannelsNbTrans;
break;
}
case MIB_MAX_RX_WINDOW_DURATION:
{
- mibGet->Param.MaxRxWindow = LoRaMacParams.MaxRxWindow;
+ mibGet->Param.MaxRxWindow = MacCtx.NvmCtx->MacParams.MaxRxWindow;
break;
}
case MIB_RECEIVE_DELAY_1:
{
- mibGet->Param.ReceiveDelay1 = LoRaMacParams.ReceiveDelay1;
+ mibGet->Param.ReceiveDelay1 = MacCtx.NvmCtx->MacParams.ReceiveDelay1;
break;
}
case MIB_RECEIVE_DELAY_2:
{
- mibGet->Param.ReceiveDelay2 = LoRaMacParams.ReceiveDelay2;
+ mibGet->Param.ReceiveDelay2 = MacCtx.NvmCtx->MacParams.ReceiveDelay2;
break;
}
case MIB_JOIN_ACCEPT_DELAY_1:
{
- mibGet->Param.JoinAcceptDelay1 = LoRaMacParams.JoinAcceptDelay1;
+ mibGet->Param.JoinAcceptDelay1 = MacCtx.NvmCtx->MacParams.JoinAcceptDelay1;
break;
}
case MIB_JOIN_ACCEPT_DELAY_2:
{
- mibGet->Param.JoinAcceptDelay2 = LoRaMacParams.JoinAcceptDelay2;
+ mibGet->Param.JoinAcceptDelay2 = MacCtx.NvmCtx->MacParams.JoinAcceptDelay2;
break;
}
case MIB_CHANNELS_DEFAULT_DATARATE:
{
- mibGet->Param.ChannelsDefaultDatarate = LoRaMacParamsDefaults.ChannelsDatarate;
+ mibGet->Param.ChannelsDefaultDatarate = MacCtx.NvmCtx->MacParamsDefaults.ChannelsDatarate;
break;
}
case MIB_CHANNELS_DATARATE:
{
- mibGet->Param.ChannelsDatarate = LoRaMacParams.ChannelsDatarate;
+ mibGet->Param.ChannelsDatarate = MacCtx.NvmCtx->MacParams.ChannelsDatarate;
break;
}
case MIB_CHANNELS_DEFAULT_TX_POWER:
{
- mibGet->Param.ChannelsDefaultTxPower = LoRaMacParamsDefaults.ChannelsTxPower;
+ mibGet->Param.ChannelsDefaultTxPower = MacCtx.NvmCtx->MacParamsDefaults.ChannelsTxPower;
break;
}
case MIB_CHANNELS_TX_POWER:
{
- mibGet->Param.ChannelsTxPower = LoRaMacParams.ChannelsTxPower;
+ mibGet->Param.ChannelsTxPower = MacCtx.NvmCtx->MacParams.ChannelsTxPower;
break;
}
- case MIB_UPLINK_COUNTER:
+ case MIB_SYSTEM_MAX_RX_ERROR:
{
- mibGet->Param.UpLinkCounter = UpLinkCounter;
+ mibGet->Param.SystemMaxRxError = MacCtx.NvmCtx->MacParams.SystemMaxRxError;
break;
}
- case MIB_DOWNLINK_COUNTER:
+ case MIB_MIN_RX_SYMBOLS:
{
- mibGet->Param.DownLinkCounter = DownLinkCounter;
+ mibGet->Param.MinRxSymbols = MacCtx.NvmCtx->MacParams.MinRxSymbols;
break;
}
- case MIB_MULTICAST_CHANNEL:
+ case MIB_ANTENNA_GAIN:
{
- mibGet->Param.MulticastList = MulticastChannels;
+ mibGet->Param.AntennaGain = MacCtx.NvmCtx->MacParams.AntennaGain;
break;
}
- case MIB_SYSTEM_MAX_RX_ERROR:
+ case MIB_NVM_CTXS:
{
- mibGet->Param.SystemMaxRxError = LoRaMacParams.SystemMaxRxError;
+ mibGet->Param.Contexts = GetCtxs( );
break;
}
- case MIB_MIN_RX_SYMBOLS:
+ case MIB_DEFAULT_ANTENNA_GAIN:
{
- mibGet->Param.MinRxSymbols = LoRaMacParams.MinRxSymbols;
+ mibGet->Param.DefaultAntennaGain = MacCtx.NvmCtx->MacParamsDefaults.AntennaGain;
break;
}
- case MIB_ANTENNA_GAIN:
+ default:
{
- mibGet->Param.AntennaGain = LoRaMacParams.AntennaGain;
+ status = LoRaMacClassBMibGetRequestConfirm( mibGet );
break;
}
- default:
- status = LORAMAC_STATUS_SERVICE_UNKNOWN;
- break;
}
-
return status;
}
-LoRaMacStatus_t LoRaMacMibSetRequestConfirm( MibRequestConfirm_t *mibSet )
+LoRaMacStatus_t LoRaMacMibSetRequestConfirm( MibRequestConfirm_t* mibSet )
{
LoRaMacStatus_t status = LORAMAC_STATUS_OK;
ChanMaskSetParams_t chanMaskSet;
@@ -2828,7 +3637,7 @@ LoRaMacStatus_t LoRaMacMibSetRequestConfirm( MibRequestConfirm_t *mibSet )
{
return LORAMAC_STATUS_PARAMETER_INVALID;
}
- if( ( LoRaMacState & LORAMAC_TX_RUNNING ) == LORAMAC_TX_RUNNING )
+ if( ( MacCtx.MacState & LORAMAC_TX_RUNNING ) == LORAMAC_TX_RUNNING )
{
return LORAMAC_STATUS_BUSY;
}
@@ -2837,34 +3646,375 @@ LoRaMacStatus_t LoRaMacMibSetRequestConfirm( MibRequestConfirm_t *mibSet )
{
case MIB_DEVICE_CLASS:
{
- LoRaMacDeviceClass = mibSet->Param.Class;
- switch( LoRaMacDeviceClass )
+ status = SwitchClass( mibSet->Param.Class );
+ break;
+ }
+ case MIB_NETWORK_ACTIVATION:
+ {
+ if( mibSet->Param.NetworkActivation != ACTIVATION_TYPE_OTAA )
{
- case CLASS_A:
+ MacCtx.NvmCtx->NetworkActivation = mibSet->Param.NetworkActivation;
+ }
+ else
+ { // Do not allow to set ACTIVATION_TYPE_OTAA since the MAC will set it automatically after a successful join process.
+ status = LORAMAC_STATUS_PARAMETER_INVALID;
+ }
+ break;
+ }
+ case MIB_DEV_EUI:
+ {
+ if( SecureElementSetDevEui( mibSet->Param.DevEui ) != SECURE_ELEMENT_SUCCESS )
+ {
+ status = LORAMAC_STATUS_PARAMETER_INVALID;
+ }
+ break;
+ }
+ case MIB_JOIN_EUI:
+ {
+ if( SecureElementSetJoinEui( mibSet->Param.JoinEui ) != SECURE_ELEMENT_SUCCESS )
+ {
+ status = LORAMAC_STATUS_PARAMETER_INVALID;
+ }
+ break;
+ }
+ case MIB_ADR:
+ {
+ MacCtx.NvmCtx->AdrCtrlOn = mibSet->Param.AdrEnable;
+ break;
+ }
+ case MIB_NET_ID:
+ {
+ MacCtx.NvmCtx->NetID = mibSet->Param.NetID;
+ break;
+ }
+ case MIB_DEV_ADDR:
+ {
+ MacCtx.NvmCtx->DevAddr = mibSet->Param.DevAddr;
+ break;
+ }
+ case MIB_GEN_APP_KEY:
+ {
+ if( mibSet->Param.GenAppKey != NULL )
+ {
+ if( LORAMAC_CRYPTO_SUCCESS != LoRaMacCryptoSetKey( GEN_APP_KEY, mibSet->Param.GenAppKey ) )
{
- // Set the radio into sleep to setup a defined state
- Radio.Sleep( );
- break;
+ return LORAMAC_STATUS_CRYPTO_ERROR;
}
- case CLASS_B:
+ }
+ else
+ {
+ status = LORAMAC_STATUS_PARAMETER_INVALID;
+ }
+ break;
+ }
+ case MIB_APP_KEY:
+ {
+ if( mibSet->Param.AppKey != NULL )
+ {
+ if( LORAMAC_CRYPTO_SUCCESS != LoRaMacCryptoSetKey( APP_KEY, mibSet->Param.AppKey ) )
{
- break;
+ return LORAMAC_STATUS_CRYPTO_ERROR;
}
- case CLASS_C:
+ }
+ else
+ {
+ status = LORAMAC_STATUS_PARAMETER_INVALID;
+ }
+ break;
+ }
+ case MIB_NWK_KEY:
+ {
+ if( mibSet->Param.NwkKey != NULL )
+ {
+ if( LORAMAC_CRYPTO_SUCCESS != LoRaMacCryptoSetKey( NWK_KEY, mibSet->Param.NwkKey ) )
{
- // Set the NodeAckRequested indicator to default
- NodeAckRequested = false;
- OnRxWindow2TimerEvent( );
- break;
+ return LORAMAC_STATUS_CRYPTO_ERROR;
+ }
+ }
+ else
+ {
+ status = LORAMAC_STATUS_PARAMETER_INVALID;
+ }
+ break;
+ }
+ case MIB_J_S_INT_KEY:
+ {
+ if( mibSet->Param.JSIntKey != NULL )
+ {
+ if( LORAMAC_CRYPTO_SUCCESS != LoRaMacCryptoSetKey( J_S_INT_KEY, mibSet->Param.JSIntKey ) )
+ {
+ return LORAMAC_STATUS_CRYPTO_ERROR;
+ }
+ }
+ else
+ {
+ status = LORAMAC_STATUS_PARAMETER_INVALID;
+ }
+ break;
+ }
+ case MIB_J_S_ENC_KEY:
+ {
+ if( mibSet->Param.JSEncKey != NULL )
+ {
+ if( LORAMAC_CRYPTO_SUCCESS != LoRaMacCryptoSetKey( J_S_ENC_KEY, mibSet->Param.JSEncKey ) )
+ {
+ return LORAMAC_STATUS_CRYPTO_ERROR;
+ }
+ }
+ else
+ {
+ status = LORAMAC_STATUS_PARAMETER_INVALID;
+ }
+ break;
+ }
+ case MIB_F_NWK_S_INT_KEY:
+ {
+ if( mibSet->Param.FNwkSIntKey != NULL )
+ {
+ if( LORAMAC_CRYPTO_SUCCESS != LoRaMacCryptoSetKey( F_NWK_S_INT_KEY, mibSet->Param.FNwkSIntKey ) )
+ {
+ return LORAMAC_STATUS_CRYPTO_ERROR;
+ }
+ }
+ else
+ {
+ status = LORAMAC_STATUS_PARAMETER_INVALID;
+ }
+ break;
+ }
+ case MIB_S_NWK_S_INT_KEY:
+ {
+ if( mibSet->Param.SNwkSIntKey != NULL )
+ {
+ if( LORAMAC_CRYPTO_SUCCESS != LoRaMacCryptoSetKey( S_NWK_S_INT_KEY, mibSet->Param.SNwkSIntKey ) )
+ {
+ return LORAMAC_STATUS_CRYPTO_ERROR;
+ }
+ }
+ else
+ {
+ status = LORAMAC_STATUS_PARAMETER_INVALID;
+ }
+ break;
+ }
+ case MIB_NWK_S_ENC_KEY:
+ {
+ if( mibSet->Param.NwkSEncKey != NULL )
+ {
+ if( LORAMAC_CRYPTO_SUCCESS != LoRaMacCryptoSetKey( NWK_S_ENC_KEY, mibSet->Param.NwkSEncKey ) )
+ {
+ return LORAMAC_STATUS_CRYPTO_ERROR;
+ }
+ }
+ else
+ {
+ status = LORAMAC_STATUS_PARAMETER_INVALID;
+ }
+ break;
+ }
+ case MIB_APP_S_KEY:
+ {
+ if( mibSet->Param.AppSKey != NULL )
+ {
+ if( LORAMAC_CRYPTO_SUCCESS != LoRaMacCryptoSetKey( APP_S_KEY, mibSet->Param.AppSKey ) )
+ {
+ return LORAMAC_STATUS_CRYPTO_ERROR;
+ }
+ }
+ else
+ {
+ status = LORAMAC_STATUS_PARAMETER_INVALID;
+ }
+ break;
+ }
+ case MIB_MC_KE_KEY:
+ {
+ if( mibSet->Param.McKEKey != NULL )
+ {
+ if( LORAMAC_CRYPTO_SUCCESS != LoRaMacCryptoSetKey( MC_KE_KEY, mibSet->Param.McKEKey ) )
+ {
+ return LORAMAC_STATUS_CRYPTO_ERROR;
+ }
+ }
+ else
+ {
+ status = LORAMAC_STATUS_PARAMETER_INVALID;
+ }
+ break;
+ }
+ case MIB_MC_KEY_0:
+ {
+ if( mibSet->Param.McKey0 != NULL )
+ {
+ if( LORAMAC_CRYPTO_SUCCESS != LoRaMacCryptoSetKey( MC_KEY_0, mibSet->Param.McKey0 ) )
+ {
+ return LORAMAC_STATUS_CRYPTO_ERROR;
+ }
+ }
+ else
+ {
+ status = LORAMAC_STATUS_PARAMETER_INVALID;
+ }
+ break;
+ }
+ case MIB_MC_APP_S_KEY_0:
+ {
+ if( mibSet->Param.McAppSKey0 != NULL )
+ {
+ if( LORAMAC_CRYPTO_SUCCESS != LoRaMacCryptoSetKey( MC_APP_S_KEY_0, mibSet->Param.McAppSKey0 ) )
+ {
+ return LORAMAC_STATUS_CRYPTO_ERROR;
+ }
+ }
+ else
+ {
+ status = LORAMAC_STATUS_PARAMETER_INVALID;
+ }
+ break;
+ }
+ case MIB_MC_NWK_S_KEY_0:
+ {
+ if( mibSet->Param.McNwkSKey0 != NULL )
+ {
+ if( LORAMAC_CRYPTO_SUCCESS != LoRaMacCryptoSetKey( MC_NWK_S_KEY_0, mibSet->Param.McNwkSKey0 ) )
+ {
+ return LORAMAC_STATUS_CRYPTO_ERROR;
+ }
+ }
+ else
+ {
+ status = LORAMAC_STATUS_PARAMETER_INVALID;
+ }
+ break;
+ }
+ case MIB_MC_KEY_1:
+ {
+ if( mibSet->Param.McKey1 != NULL )
+ {
+ if( LORAMAC_CRYPTO_SUCCESS != LoRaMacCryptoSetKey( MC_KEY_1, mibSet->Param.McKey1 ) )
+ {
+ return LORAMAC_STATUS_CRYPTO_ERROR;
+ }
+ }
+ else
+ {
+ status = LORAMAC_STATUS_PARAMETER_INVALID;
+ }
+ break;
+ }
+ case MIB_MC_APP_S_KEY_1:
+ {
+ if( mibSet->Param.McAppSKey1 != NULL )
+ {
+ if( LORAMAC_CRYPTO_SUCCESS != LoRaMacCryptoSetKey( MC_APP_S_KEY_1, mibSet->Param.McAppSKey1 ) )
+ {
+ return LORAMAC_STATUS_CRYPTO_ERROR;
+ }
+ }
+ else
+ {
+ status = LORAMAC_STATUS_PARAMETER_INVALID;
+ }
+ break;
+ }
+ case MIB_MC_NWK_S_KEY_1:
+ {
+ if( mibSet->Param.McNwkSKey1 != NULL )
+ {
+ if( LORAMAC_CRYPTO_SUCCESS != LoRaMacCryptoSetKey( MC_NWK_S_KEY_1, mibSet->Param.McNwkSKey1 ) )
+ {
+ return LORAMAC_STATUS_CRYPTO_ERROR;
+ }
+ }
+ else
+ {
+ status = LORAMAC_STATUS_PARAMETER_INVALID;
+ }
+ break;
+ }
+ case MIB_MC_KEY_2:
+ {
+ if( mibSet->Param.McKey2 != NULL )
+ {
+ if( LORAMAC_CRYPTO_SUCCESS != LoRaMacCryptoSetKey( MC_KEY_2, mibSet->Param.McKey2 ) )
+ {
+ return LORAMAC_STATUS_CRYPTO_ERROR;
+ }
+ }
+ else
+ {
+ status = LORAMAC_STATUS_PARAMETER_INVALID;
+ }
+ break;
+ }
+ case MIB_MC_APP_S_KEY_2:
+ {
+ if( mibSet->Param.McAppSKey2 != NULL )
+ {
+ if( LORAMAC_CRYPTO_SUCCESS != LoRaMacCryptoSetKey( MC_APP_S_KEY_2, mibSet->Param.McAppSKey2 ) )
+ {
+ return LORAMAC_STATUS_CRYPTO_ERROR;
+ }
+ }
+ else
+ {
+ status = LORAMAC_STATUS_PARAMETER_INVALID;
+ }
+ break;
+ }
+ case MIB_MC_NWK_S_KEY_2:
+ {
+ if( mibSet->Param.McNwkSKey2 != NULL )
+ {
+ if( LORAMAC_CRYPTO_SUCCESS != LoRaMacCryptoSetKey( MC_NWK_S_KEY_2, mibSet->Param.McNwkSKey2 ) )
+ {
+ return LORAMAC_STATUS_CRYPTO_ERROR;
+ }
+ }
+ else
+ {
+ status = LORAMAC_STATUS_PARAMETER_INVALID;
+ }
+ break;
+ }
+ case MIB_MC_KEY_3:
+ {
+ if( mibSet->Param.McKey3 != NULL )
+ {
+ if( LORAMAC_CRYPTO_SUCCESS != LoRaMacCryptoSetKey( MC_KEY_3, mibSet->Param.McKey3 ) )
+ {
+ return LORAMAC_STATUS_CRYPTO_ERROR;
+ }
+ }
+ else
+ {
+ status = LORAMAC_STATUS_PARAMETER_INVALID;
+ }
+ break;
+ }
+ case MIB_MC_APP_S_KEY_3:
+ {
+ if( mibSet->Param.McAppSKey3 != NULL )
+ {
+ if( LORAMAC_CRYPTO_SUCCESS != LoRaMacCryptoSetKey( MC_APP_S_KEY_3, mibSet->Param.McAppSKey3 ) )
+ {
+ return LORAMAC_STATUS_CRYPTO_ERROR;
}
}
+ else
+ {
+ status = LORAMAC_STATUS_PARAMETER_INVALID;
+ }
break;
}
- case MIB_NETWORK_ACTIVATION:
+ case MIB_MC_NWK_S_KEY_3:
{
- if( mibSet->Param.NetworkActivation != ACTIVATION_TYPE_OTAA )
+ if( mibSet->Param.McNwkSKey3 != NULL )
{
- NetworkActivation = mibSet->Param.NetworkActivation;
+ if( LORAMAC_CRYPTO_SUCCESS != LoRaMacCryptoSetKey( MC_NWK_S_KEY_3, mibSet->Param.McNwkSKey3 ) )
+ {
+ return LORAMAC_STATUS_CRYPTO_ERROR;
+ }
}
else
{
@@ -2872,32 +4022,25 @@ LoRaMacStatus_t LoRaMacMibSetRequestConfirm( MibRequestConfirm_t *mibSet )
}
break;
}
- case MIB_NETWORK_JOINED:
- {
- IsLoRaMacNetworkJoined = mibSet->Param.IsNetworkJoined;
- break;
- }
- case MIB_ADR:
- {
- AdrCtrlOn = mibSet->Param.AdrEnable;
- break;
- }
- case MIB_NET_ID:
+ case MIB_PUBLIC_NETWORK:
{
- LoRaMacNetID = mibSet->Param.NetID;
+ MacCtx.NvmCtx->PublicNetwork = mibSet->Param.EnablePublicNetwork;
+ Radio.SetPublicNetwork( MacCtx.NvmCtx->PublicNetwork );
break;
}
- case MIB_DEV_ADDR:
+ case MIB_REPEATER_SUPPORT:
{
- LoRaMacDevAddr = mibSet->Param.DevAddr;
+ MacCtx.NvmCtx->RepeaterSupport = mibSet->Param.EnableRepeaterSupport;
break;
}
- case MIB_NWK_SKEY:
+ case MIB_RX2_CHANNEL:
{
- if( mibSet->Param.NwkSKey != NULL )
+ verify.DatarateParams.Datarate = mibSet->Param.Rx2Channel.Datarate;
+ verify.DatarateParams.DownlinkDwellTime = MacCtx.NvmCtx->MacParams.DownlinkDwellTime;
+
+ if( RegionVerify( MacCtx.NvmCtx->Region, &verify, PHY_RX_DR ) == true )
{
- memcpy1( LoRaMacNwkSKey, mibSet->Param.NwkSKey,
- sizeof( LoRaMacNwkSKey ) );
+ MacCtx.NvmCtx->MacParams.Rx2Channel = mibSet->Param.Rx2Channel;
}
else
{
@@ -2905,12 +4048,14 @@ LoRaMacStatus_t LoRaMacMibSetRequestConfirm( MibRequestConfirm_t *mibSet )
}
break;
}
- case MIB_APP_SKEY:
+ case MIB_RX2_DEFAULT_CHANNEL:
{
- if( mibSet->Param.AppSKey != NULL )
+ verify.DatarateParams.Datarate = mibSet->Param.Rx2Channel.Datarate;
+ verify.DatarateParams.DownlinkDwellTime = MacCtx.NvmCtx->MacParams.DownlinkDwellTime;
+
+ if( RegionVerify( MacCtx.NvmCtx->Region, &verify, PHY_RX_DR ) == true )
{
- memcpy1( LoRaMacAppSKey, mibSet->Param.AppSKey,
- sizeof( LoRaMacAppSKey ) );
+ MacCtx.NvmCtx->MacParamsDefaults.Rx2Channel = mibSet->Param.Rx2DefaultChannel;
}
else
{
@@ -2918,51 +4063,24 @@ LoRaMacStatus_t LoRaMacMibSetRequestConfirm( MibRequestConfirm_t *mibSet )
}
break;
}
- case MIB_PUBLIC_NETWORK:
- {
- PublicNetwork = mibSet->Param.EnablePublicNetwork;
- Radio.SetPublicNetwork( PublicNetwork );
- break;
- }
- case MIB_REPEATER_SUPPORT:
- {
- RepeaterSupport = mibSet->Param.EnableRepeaterSupport;
- break;
- }
- case MIB_RX2_CHANNEL:
+ case MIB_RXC_CHANNEL:
{
- verify.DatarateParams.Datarate = mibSet->Param.Rx2Channel.Datarate;
- verify.DatarateParams.DownlinkDwellTime = LoRaMacParams.DownlinkDwellTime;
+ verify.DatarateParams.Datarate = mibSet->Param.RxCChannel.Datarate;
+ verify.DatarateParams.DownlinkDwellTime = MacCtx.NvmCtx->MacParams.DownlinkDwellTime;
- if( RegionVerify( LoRaMacRegion, &verify, PHY_RX_DR ) == true )
+ if( RegionVerify( MacCtx.NvmCtx->Region, &verify, PHY_RX_DR ) == true )
{
- LoRaMacParams.Rx2Channel = mibSet->Param.Rx2Channel;
+ MacCtx.NvmCtx->MacParams.RxCChannel = mibSet->Param.RxCChannel;
- if( ( LoRaMacDeviceClass == CLASS_C ) && ( IsLoRaMacNetworkJoined == true ) )
+ if( ( MacCtx.NvmCtx->DeviceClass == CLASS_C ) && ( MacCtx.NvmCtx->NetworkActivation != ACTIVATION_TYPE_NONE ) )
{
- // Compute Rx2 windows parameters
- RegionComputeRxWindowParameters( LoRaMacRegion,
- LoRaMacParams.Rx2Channel.Datarate,
- LoRaMacParams.MinRxSymbols,
- LoRaMacParams.SystemMaxRxError,
- &RxWindow2Config );
-
- RxWindow2Config.Channel = Channel;
- RxWindow2Config.Frequency = LoRaMacParams.Rx2Channel.Frequency;
- RxWindow2Config.DownlinkDwellTime = LoRaMacParams.DownlinkDwellTime;
- RxWindow2Config.RepeaterSupport = RepeaterSupport;
- RxWindow2Config.Window = 1;
- RxWindow2Config.RxContinuous = true;
-
- if( RegionRxConfig( LoRaMacRegion, &RxWindow2Config, ( int8_t* )&McpsIndication.RxDatarate ) == true )
- {
- RxWindowSetup( RxWindow2Config.RxContinuous, LoRaMacParams.MaxRxWindow );
- RxSlot = RxWindow2Config.Window;
- }
- else
- {
- status = LORAMAC_STATUS_PARAMETER_INVALID;
- }
+ // We can only compute the RX window parameters directly, if we are already
+ // in class c mode and joined. We cannot setup an RX window in case of any other
+ // class type.
+ // Set the radio into sleep mode in case we are still in RX mode
+ Radio.Sleep( );
+
+ OpenContinuousRxCWindow( );
}
}
else
@@ -2971,14 +4089,14 @@ LoRaMacStatus_t LoRaMacMibSetRequestConfirm( MibRequestConfirm_t *mibSet )
}
break;
}
- case MIB_RX2_DEFAULT_CHANNEL:
+ case MIB_RXC_DEFAULT_CHANNEL:
{
- verify.DatarateParams.Datarate = mibSet->Param.Rx2Channel.Datarate;
- verify.DatarateParams.DownlinkDwellTime = LoRaMacParams.DownlinkDwellTime;
+ verify.DatarateParams.Datarate = mibSet->Param.RxCChannel.Datarate;
+ verify.DatarateParams.DownlinkDwellTime = MacCtx.NvmCtx->MacParams.DownlinkDwellTime;
- if( RegionVerify( LoRaMacRegion, &verify, PHY_RX_DR ) == true )
+ if( RegionVerify( MacCtx.NvmCtx->Region, &verify, PHY_RX_DR ) == true )
{
- LoRaMacParamsDefaults.Rx2Channel = mibSet->Param.Rx2DefaultChannel;
+ MacCtx.NvmCtx->MacParamsDefaults.RxCChannel = mibSet->Param.RxCDefaultChannel;
}
else
{
@@ -2988,10 +4106,10 @@ LoRaMacStatus_t LoRaMacMibSetRequestConfirm( MibRequestConfirm_t *mibSet )
}
case MIB_CHANNELS_DEFAULT_MASK:
{
- chanMaskSet.ChannelsMaskIn = mibSet->Param.ChannelsMask;
+ chanMaskSet.ChannelsMaskIn = mibSet->Param.ChannelsDefaultMask;
chanMaskSet.ChannelsMaskType = CHANNELS_DEFAULT_MASK;
- if( RegionChanMaskSet( LoRaMacRegion, &chanMaskSet ) == false )
+ if( RegionChanMaskSet( MacCtx.NvmCtx->Region, &chanMaskSet ) == false )
{
status = LORAMAC_STATUS_PARAMETER_INVALID;
}
@@ -3002,18 +4120,18 @@ LoRaMacStatus_t LoRaMacMibSetRequestConfirm( MibRequestConfirm_t *mibSet )
chanMaskSet.ChannelsMaskIn = mibSet->Param.ChannelsMask;
chanMaskSet.ChannelsMaskType = CHANNELS_MASK;
- if( RegionChanMaskSet( LoRaMacRegion, &chanMaskSet ) == false )
+ if( RegionChanMaskSet( MacCtx.NvmCtx->Region, &chanMaskSet ) == false )
{
status = LORAMAC_STATUS_PARAMETER_INVALID;
}
break;
}
- case MIB_CHANNELS_NB_REP:
+ case MIB_CHANNELS_NB_TRANS:
{
- if( ( mibSet->Param.ChannelNbRep >= 1 ) &&
- ( mibSet->Param.ChannelNbRep <= 15 ) )
+ if( ( mibSet->Param.ChannelsNbTrans >= 1 ) &&
+ ( mibSet->Param.ChannelsNbTrans <= 15 ) )
{
- LoRaMacParams.ChannelsNbRep = mibSet->Param.ChannelNbRep;
+ MacCtx.NvmCtx->MacParams.ChannelsNbTrans = mibSet->Param.ChannelsNbTrans;
}
else
{
@@ -3023,36 +4141,36 @@ LoRaMacStatus_t LoRaMacMibSetRequestConfirm( MibRequestConfirm_t *mibSet )
}
case MIB_MAX_RX_WINDOW_DURATION:
{
- LoRaMacParams.MaxRxWindow = mibSet->Param.MaxRxWindow;
+ MacCtx.NvmCtx->MacParams.MaxRxWindow = mibSet->Param.MaxRxWindow;
break;
}
case MIB_RECEIVE_DELAY_1:
{
- LoRaMacParams.ReceiveDelay1 = mibSet->Param.ReceiveDelay1;
+ MacCtx.NvmCtx->MacParams.ReceiveDelay1 = mibSet->Param.ReceiveDelay1;
break;
}
case MIB_RECEIVE_DELAY_2:
{
- LoRaMacParams.ReceiveDelay2 = mibSet->Param.ReceiveDelay2;
+ MacCtx.NvmCtx->MacParams.ReceiveDelay2 = mibSet->Param.ReceiveDelay2;
break;
}
case MIB_JOIN_ACCEPT_DELAY_1:
{
- LoRaMacParams.JoinAcceptDelay1 = mibSet->Param.JoinAcceptDelay1;
+ MacCtx.NvmCtx->MacParams.JoinAcceptDelay1 = mibSet->Param.JoinAcceptDelay1;
break;
}
case MIB_JOIN_ACCEPT_DELAY_2:
{
- LoRaMacParams.JoinAcceptDelay2 = mibSet->Param.JoinAcceptDelay2;
+ MacCtx.NvmCtx->MacParams.JoinAcceptDelay2 = mibSet->Param.JoinAcceptDelay2;
break;
}
case MIB_CHANNELS_DEFAULT_DATARATE:
{
verify.DatarateParams.Datarate = mibSet->Param.ChannelsDefaultDatarate;
- if( RegionVerify( LoRaMacRegion, &verify, PHY_DEF_TX_DR ) == true )
+ if( RegionVerify( MacCtx.NvmCtx->Region, &verify, PHY_DEF_TX_DR ) == true )
{
- LoRaMacParamsDefaults.ChannelsDatarate = verify.DatarateParams.Datarate;
+ MacCtx.NvmCtx->MacParamsDefaults.ChannelsDatarate = verify.DatarateParams.Datarate;
}
else
{
@@ -3063,10 +4181,11 @@ LoRaMacStatus_t LoRaMacMibSetRequestConfirm( MibRequestConfirm_t *mibSet )
case MIB_CHANNELS_DATARATE:
{
verify.DatarateParams.Datarate = mibSet->Param.ChannelsDatarate;
+ verify.DatarateParams.UplinkDwellTime = MacCtx.NvmCtx->MacParams.UplinkDwellTime;
- if( RegionVerify( LoRaMacRegion, &verify, PHY_TX_DR ) == true )
+ if( RegionVerify( MacCtx.NvmCtx->Region, &verify, PHY_TX_DR ) == true )
{
- LoRaMacParams.ChannelsDatarate = verify.DatarateParams.Datarate;
+ MacCtx.NvmCtx->MacParams.ChannelsDatarate = verify.DatarateParams.Datarate;
}
else
{
@@ -3078,9 +4197,9 @@ LoRaMacStatus_t LoRaMacMibSetRequestConfirm( MibRequestConfirm_t *mibSet )
{
verify.TxPower = mibSet->Param.ChannelsDefaultTxPower;
- if( RegionVerify( LoRaMacRegion, &verify, PHY_DEF_TX_POWER ) == true )
+ if( RegionVerify( MacCtx.NvmCtx->Region, &verify, PHY_DEF_TX_POWER ) == true )
{
- LoRaMacParamsDefaults.ChannelsTxPower = verify.TxPower;
+ MacCtx.NvmCtx->MacParamsDefaults.ChannelsTxPower = verify.TxPower;
}
else
{
@@ -3092,9 +4211,9 @@ LoRaMacStatus_t LoRaMacMibSetRequestConfirm( MibRequestConfirm_t *mibSet )
{
verify.TxPower = mibSet->Param.ChannelsTxPower;
- if( RegionVerify( LoRaMacRegion, &verify, PHY_TX_POWER ) == true )
+ if( RegionVerify( MacCtx.NvmCtx->Region, &verify, PHY_TX_POWER ) == true )
{
- LoRaMacParams.ChannelsTxPower = verify.TxPower;
+ MacCtx.NvmCtx->MacParams.ChannelsTxPower = verify.TxPower;
}
else
{
@@ -3102,36 +4221,63 @@ LoRaMacStatus_t LoRaMacMibSetRequestConfirm( MibRequestConfirm_t *mibSet )
}
break;
}
- case MIB_UPLINK_COUNTER:
+ case MIB_SYSTEM_MAX_RX_ERROR:
{
- UpLinkCounter = mibSet->Param.UpLinkCounter;
+ MacCtx.NvmCtx->MacParams.SystemMaxRxError = MacCtx.NvmCtx->MacParamsDefaults.SystemMaxRxError = mibSet->Param.SystemMaxRxError;
break;
}
- case MIB_DOWNLINK_COUNTER:
+ case MIB_MIN_RX_SYMBOLS:
{
- DownLinkCounter = mibSet->Param.DownLinkCounter;
+ MacCtx.NvmCtx->MacParams.MinRxSymbols = MacCtx.NvmCtx->MacParamsDefaults.MinRxSymbols = mibSet->Param.MinRxSymbols;
break;
}
- case MIB_SYSTEM_MAX_RX_ERROR:
+ case MIB_ANTENNA_GAIN:
{
- LoRaMacParams.SystemMaxRxError = LoRaMacParamsDefaults.SystemMaxRxError = mibSet->Param.SystemMaxRxError;
+ MacCtx.NvmCtx->MacParams.AntennaGain = mibSet->Param.AntennaGain;
break;
}
- case MIB_MIN_RX_SYMBOLS:
+ case MIB_DEFAULT_ANTENNA_GAIN:
{
- LoRaMacParams.MinRxSymbols = LoRaMacParamsDefaults.MinRxSymbols = mibSet->Param.MinRxSymbols;
+ MacCtx.NvmCtx->MacParamsDefaults.AntennaGain = mibSet->Param.DefaultAntennaGain;
break;
}
- case MIB_ANTENNA_GAIN:
+ case MIB_NVM_CTXS:
+ {
+ if( mibSet->Param.Contexts != 0 )
+ {
+ status = RestoreCtxs( mibSet->Param.Contexts );
+ }
+ else
+ {
+ status = LORAMAC_STATUS_PARAMETER_INVALID;
+ }
+ break;
+ }
+ case MIB_ABP_LORAWAN_VERSION:
{
- LoRaMacParams.AntennaGain = mibSet->Param.AntennaGain;
+ if( mibSet->Param.AbpLrWanVersion.Fields.Minor <= 1 )
+ {
+ MacCtx.NvmCtx->Version = mibSet->Param.AbpLrWanVersion;
+
+ if( LORAMAC_CRYPTO_SUCCESS != LoRaMacCryptoSetLrWanVersion( mibSet->Param.AbpLrWanVersion ) )
+ {
+ return LORAMAC_STATUS_CRYPTO_ERROR;
+ }
+ }
+ else
+ {
+ status = LORAMAC_STATUS_PARAMETER_INVALID;
+ }
break;
}
default:
- status = LORAMAC_STATUS_SERVICE_UNKNOWN;
+ {
+ status = LoRaMacMibClassBSetRequestConfirm( mibSet );
break;
+ }
}
-
+ EventRegionNvmCtxChanged( );
+ EventMacNvmCtxChanged( );
return status;
}
@@ -3140,28 +4286,9 @@ LoRaMacStatus_t LoRaMacChannelAdd( uint8_t id, ChannelParams_t params )
ChannelAddParams_t channelAdd;
// Validate if the MAC is in a correct state
- if( ( LoRaMacState & LORAMAC_TX_RUNNING ) == LORAMAC_TX_RUNNING )
- {
- if( ( LoRaMacState & LORAMAC_TX_CONFIG ) != LORAMAC_TX_CONFIG )
- {
- return LORAMAC_STATUS_BUSY;
- }
- }
-
- channelAdd.NewChannel = ¶ms;
- channelAdd.ChannelId = id;
-
- return RegionChannelAdd( LoRaMacRegion, &channelAdd );
-}
-
-LoRaMacStatus_t LoRaMacChannelManualAdd( uint8_t id, ChannelParams_t params )
-{
- ChannelAddParams_t channelAdd;
-
- // Validate if the MAC is in a correct state
- if( ( LoRaMacState & LORAMAC_TX_RUNNING ) == LORAMAC_TX_RUNNING )
+ if( ( MacCtx.MacState & LORAMAC_TX_RUNNING ) == LORAMAC_TX_RUNNING )
{
- if( ( LoRaMacState & LORAMAC_TX_CONFIG ) != LORAMAC_TX_CONFIG )
+ if( ( MacCtx.MacState & LORAMAC_TX_CONFIG ) != LORAMAC_TX_CONFIG )
{
return LORAMAC_STATUS_BUSY;
}
@@ -3170,16 +4297,17 @@ LoRaMacStatus_t LoRaMacChannelManualAdd( uint8_t id, ChannelParams_t params )
channelAdd.NewChannel = ¶ms;
channelAdd.ChannelId = id;
- return RegionChannelManualAdd( LoRaMacRegion, &channelAdd );
+ EventRegionNvmCtxChanged( );
+ return RegionChannelAdd( MacCtx.NvmCtx->Region, &channelAdd );
}
LoRaMacStatus_t LoRaMacChannelRemove( uint8_t id )
{
ChannelRemoveParams_t channelRemove;
- if( ( LoRaMacState & LORAMAC_TX_RUNNING ) == LORAMAC_TX_RUNNING )
+ if( ( MacCtx.MacState & LORAMAC_TX_RUNNING ) == LORAMAC_TX_RUNNING )
{
- if( ( LoRaMacState & LORAMAC_TX_CONFIG ) != LORAMAC_TX_CONFIG )
+ if( ( MacCtx.MacState & LORAMAC_TX_CONFIG ) != LORAMAC_TX_CONFIG )
{
return LORAMAC_STATUS_BUSY;
}
@@ -3187,237 +4315,310 @@ LoRaMacStatus_t LoRaMacChannelRemove( uint8_t id )
channelRemove.ChannelId = id;
- if( RegionChannelsRemove( LoRaMacRegion, &channelRemove ) == false )
+ if( RegionChannelsRemove( MacCtx.NvmCtx->Region, &channelRemove ) == false )
{
return LORAMAC_STATUS_PARAMETER_INVALID;
}
+
+ EventRegionNvmCtxChanged( );
return LORAMAC_STATUS_OK;
}
-LoRaMacStatus_t LoRaMacChannelManualRemove( uint8_t id )
+LoRaMacStatus_t LoRaMacMcChannelSetup( McChannelParams_t *channel )
{
- ChannelRemoveParams_t channelRemove;
+ if( ( MacCtx.MacState & LORAMAC_TX_RUNNING ) == LORAMAC_TX_RUNNING )
+ {
+ return LORAMAC_STATUS_BUSY;
+ }
- if( ( LoRaMacState & LORAMAC_TX_RUNNING ) == LORAMAC_TX_RUNNING )
+ if( channel->GroupID >= LORAMAC_MAX_MC_CTX )
{
- if( ( LoRaMacState & LORAMAC_TX_CONFIG ) != LORAMAC_TX_CONFIG )
- {
- return LORAMAC_STATUS_BUSY;
- }
+ return LORAMAC_STATUS_MC_GROUP_UNDEFINED;
}
- channelRemove.ChannelId = id;
+ MacCtx.NvmCtx->MulticastChannelList[channel->GroupID].ChannelParams = *channel;
- if( RegionChannelsManualRemove( LoRaMacRegion, &channelRemove ) == false )
+ const KeyIdentifier_t mcKeys[LORAMAC_MAX_MC_CTX] = { MC_KEY_0, MC_KEY_1, MC_KEY_2, MC_KEY_3 };
+ if( LoRaMacCryptoSetKey( mcKeys[channel->GroupID], channel->McKeyE ) != LORAMAC_CRYPTO_SUCCESS )
{
- return LORAMAC_STATUS_PARAMETER_INVALID;
+ return LORAMAC_STATUS_CRYPTO_ERROR;
}
- return LORAMAC_STATUS_OK;
-}
-LoRaMacStatus_t LoRaMacMulticastChannelLink( MulticastParams_t *channelParam )
-{
- if( channelParam == NULL )
+ if( LoRaMacCryptoDeriveMcSessionKeyPair( channel->GroupID, channel->Address ) != LORAMAC_CRYPTO_SUCCESS )
{
- return LORAMAC_STATUS_PARAMETER_INVALID;
+ return LORAMAC_STATUS_CRYPTO_ERROR;
}
- if( ( LoRaMacState & LORAMAC_TX_RUNNING ) == LORAMAC_TX_RUNNING )
+
+ if( channel->Class == CLASS_B )
{
- return LORAMAC_STATUS_BUSY;
+ // Calculate class b parameters
+ LoRaMacClassBSetMulticastPeriodicity( &MacCtx.NvmCtx->MulticastChannelList[channel->GroupID] );
}
- // Reset downlink counter
- channelParam->DownLinkCounter = 0;
+ // Reset multicast channel downlink counter to initial value.
+ *MacCtx.NvmCtx->MulticastChannelList[channel->GroupID].DownLinkCounter = FCNT_DOWN_INITAL_VALUE;
- if( MulticastChannels == NULL )
+ EventMacNvmCtxChanged( );
+ EventRegionNvmCtxChanged( );
+ return LORAMAC_STATUS_OK;
+}
+
+LoRaMacStatus_t LoRaMacMcChannelDelete( AddressIdentifier_t groupID )
+{
+ if( ( MacCtx.MacState & LORAMAC_TX_RUNNING ) == LORAMAC_TX_RUNNING )
{
- // New node is the fist element
- MulticastChannels = channelParam;
+ return LORAMAC_STATUS_BUSY;
}
- else
- {
- MulticastParams_t *cur = MulticastChannels;
- // Search the last node in the list
- while( cur->Next != NULL )
- {
- cur = cur->Next;
- }
- // This function always finds the last node
- cur->Next = channelParam;
+ if( ( groupID >= LORAMAC_MAX_MC_CTX ) ||
+ ( MacCtx.NvmCtx->MulticastChannelList[groupID].ChannelParams.IsEnabled == false ) )
+ {
+ return LORAMAC_STATUS_MC_GROUP_UNDEFINED;
}
+ McChannelParams_t channel;
+
+ // Set all channel fields with 0
+ memset1( ( uint8_t* )&channel, 0, sizeof( McChannelParams_t ) );
+
+ MacCtx.NvmCtx->MulticastChannelList[groupID].ChannelParams = channel;
+
+ EventMacNvmCtxChanged( );
+ EventRegionNvmCtxChanged( );
return LORAMAC_STATUS_OK;
}
-MulticastParams_t * LoRaMacMulticastGetChannel(uint32_t multicastAddr)
+uint8_t LoRaMacMcChannelGetGroupId( uint32_t mcAddress )
{
- MulticastParams_t *cur = MulticastChannels;
-
- while (cur != NULL)
+ for( uint8_t i = 0; i < LORAMAC_MAX_MC_CTX; i++ )
{
- if (cur->Address == multicastAddr) {
- return cur;
+ if( mcAddress == MacCtx.NvmCtx->MulticastChannelList[i].ChannelParams.Address )
+ {
+ return i;
}
- cur = cur->Next;
}
-
- return NULL;
+ return 0xFF;
}
-LoRaMacStatus_t LoRaMacMulticastChannelUnlink( MulticastParams_t *channelParam )
+LoRaMacStatus_t LoRaMacMcChannelSetupRxParams( AddressIdentifier_t groupID, McRxParams_t *rxParams, uint8_t *status )
{
- if( channelParam == NULL )
+ *status = 0x1C + ( groupID & 0x03 );
+
+ if( ( MacCtx.MacState & LORAMAC_TX_RUNNING ) == LORAMAC_TX_RUNNING )
+ {
+ return LORAMAC_STATUS_BUSY;
+ }
+
+ DeviceClass_t devClass = MacCtx.NvmCtx->MulticastChannelList[groupID].ChannelParams.Class;
+ if( ( devClass == CLASS_A ) || ( devClass > CLASS_C ) )
{
return LORAMAC_STATUS_PARAMETER_INVALID;
}
- if( ( LoRaMacState & LORAMAC_TX_RUNNING ) == LORAMAC_TX_RUNNING )
+
+ if( ( groupID >= LORAMAC_MAX_MC_CTX ) ||
+ ( MacCtx.NvmCtx->MulticastChannelList[groupID].ChannelParams.IsEnabled == false ) )
{
- return LORAMAC_STATUS_BUSY;
+ return LORAMAC_STATUS_MC_GROUP_UNDEFINED;
}
+ *status &= 0x0F; // groupID OK
- if( MulticastChannels != NULL )
+ VerifyParams_t verify;
+ // Check datarate
+ if( devClass == CLASS_B )
{
- if( MulticastChannels == channelParam )
- {
- // First element
- MulticastChannels = channelParam->Next;
- }
- else
- {
- MulticastParams_t *cur = MulticastChannels;
+ verify.DatarateParams.Datarate = rxParams->ClassB.Datarate;
+ }
+ else
+ {
+ verify.DatarateParams.Datarate = rxParams->ClassC.Datarate;
+ }
+ verify.DatarateParams.DownlinkDwellTime = MacCtx.NvmCtx->MacParams.DownlinkDwellTime;
- // Search the node in the list
- while( cur->Next && cur->Next != channelParam )
- {
- cur = cur->Next;
- }
- // If we found the node, remove it
- if( cur->Next )
- {
- cur->Next = channelParam->Next;
- }
- }
- channelParam->Next = NULL;
+ if( RegionVerify( MacCtx.NvmCtx->Region, &verify, PHY_RX_DR ) == true )
+ {
+ *status &= 0xFB; // datarate OK
+ }
+
+ // Check frequency
+ if( devClass == CLASS_B )
+ {
+ verify.Frequency = rxParams->ClassB.Frequency;
+ }
+ else
+ {
+ verify.Frequency = rxParams->ClassC.Frequency;
+ }
+ if( RegionVerify( MacCtx.NvmCtx->Region, &verify, PHY_FREQUENCY ) == true )
+ {
+ *status &= 0xF7; // frequency OK
}
+ if( *status == ( groupID & 0x03 ) )
+ {
+ // Apply parameters
+ MacCtx.NvmCtx->MulticastChannelList[groupID].ChannelParams.RxParams = *rxParams;
+ }
+
+ EventMacNvmCtxChanged( );
+ EventRegionNvmCtxChanged( );
return LORAMAC_STATUS_OK;
}
-LoRaMacStatus_t LoRaMacMlmeRequest( MlmeReq_t *mlmeRequest )
+LoRaMacStatus_t LoRaMacMlmeRequest( MlmeReq_t* mlmeRequest )
{
LoRaMacStatus_t status = LORAMAC_STATUS_SERVICE_UNKNOWN;
- LoRaMacHeader_t macHdr;
- AlternateDrParams_t altDr;
- VerifyParams_t verify;
- GetPhyParams_t getPhy;
- PhyParam_t phyParam;
+ MlmeConfirmQueue_t queueElement;
+ uint8_t macCmdPayload[2] = { 0x00, 0x00 };
if( mlmeRequest == NULL )
{
return LORAMAC_STATUS_PARAMETER_INVALID;
}
- if( ( LoRaMacState & LORAMAC_TX_RUNNING ) == LORAMAC_TX_RUNNING )
+ if( LoRaMacIsBusy( ) == true )
+ {
+ return LORAMAC_STATUS_BUSY;
+ }
+ if( LoRaMacConfirmQueueIsFull( ) == true )
{
return LORAMAC_STATUS_BUSY;
}
- memset1( ( uint8_t* ) &MlmeConfirm, 0, sizeof( MlmeConfirm ) );
+ if( LoRaMacConfirmQueueGetCnt( ) == 0 )
+ {
+ memset1( ( uint8_t* ) &MacCtx.MlmeConfirm, 0, sizeof( MacCtx.MlmeConfirm ) );
+ }
+ MacCtx.MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_ERROR;
- MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_ERROR;
+ MacCtx.MacFlags.Bits.MlmeReq = 1;
+ queueElement.Request = mlmeRequest->Type;
+ queueElement.Status = LORAMAC_EVENT_INFO_STATUS_ERROR;
+ queueElement.RestrictCommonReadyToHandle = false;
switch( mlmeRequest->Type )
{
case MLME_JOIN:
{
- if( ( LoRaMacState & LORAMAC_TX_DELAYED ) == LORAMAC_TX_DELAYED )
+ if( ( MacCtx.MacState & LORAMAC_TX_DELAYED ) == LORAMAC_TX_DELAYED )
{
return LORAMAC_STATUS_BUSY;
}
- if( ( mlmeRequest->Req.Join.DevEui == NULL ) ||
- ( mlmeRequest->Req.Join.AppEui == NULL ) ||
- ( mlmeRequest->Req.Join.AppKey == NULL ) ||
- ( mlmeRequest->Req.Join.NbTrials == 0 ) )
- {
- return LORAMAC_STATUS_PARAMETER_INVALID;
- }
-
- // Verify the parameter NbTrials for the join procedure
- verify.NbJoinTrials = mlmeRequest->Req.Join.NbTrials;
-
- if( RegionVerify( LoRaMacRegion, &verify, PHY_NB_JOIN_TRIALS ) == false )
- {
- // Value not supported, get default
- getPhy.Attribute = PHY_DEF_NB_JOIN_TRIALS;
- phyParam = RegionGetPhyParam( LoRaMacRegion, &getPhy );
- mlmeRequest->Req.Join.NbTrials = ( uint8_t ) phyParam.Value;
- }
-
- LoRaMacFlags.Bits.MlmeReq = 1;
- MlmeConfirm.MlmeRequest = mlmeRequest->Type;
-
- LoRaMacDevEui = mlmeRequest->Req.Join.DevEui;
- LoRaMacAppEui = mlmeRequest->Req.Join.AppEui;
- LoRaMacAppKey = mlmeRequest->Req.Join.AppKey;
- MaxJoinRequestTrials = mlmeRequest->Req.Join.NbTrials;
-
- // Reset variable JoinRequestTrials
- JoinRequestTrials = 0;
-
- // Setup header information
- macHdr.Value = 0;
- macHdr.Bits.MType = FRAME_TYPE_JOIN_REQ;
-
ResetMacParameters( );
- altDr.NbTrials = JoinRequestTrials + 1;
+ // Pycom: Add Join DR selection as and when the region permits. Probably not required because AlternateDR() now just returns CurrentDR in the current version
+ // RegionForceJoinDataRate( LoRaMacRegion, mlmeRequest->Req.Join.DR, &altDr );
- // Pycom: Add Join DR selection as and when the region permits
- RegionForceJoinDataRate( LoRaMacRegion, mlmeRequest->Req.Join.DR, &altDr );
+ MacCtx.NvmCtx->MacParams.ChannelsDatarate = RegionAlternateDr( MacCtx.NvmCtx->Region, mlmeRequest->Req.Join.Datarate, ALTERNATE_DR );
- LoRaMacParams.ChannelsDatarate = RegionAlternateDr( LoRaMacRegion, &altDr );
+ queueElement.Status = LORAMAC_EVENT_INFO_STATUS_JOIN_FAIL;
- status = Send( &macHdr, 0, NULL, 0 );
+ status = SendReJoinReq( JOIN_REQ );
+
+ if( status != LORAMAC_STATUS_OK )
+ {
+ // Revert back the previous datarate ( mainly used for US915 like regions )
+ MacCtx.NvmCtx->MacParams.ChannelsDatarate = RegionAlternateDr( MacCtx.NvmCtx->Region, mlmeRequest->Req.Join.Datarate, ALTERNATE_DR_RESTORE );
+ }
break;
}
case MLME_LINK_CHECK:
{
- LoRaMacFlags.Bits.MlmeReq = 1;
// LoRaMac will send this command piggy-pack
- MlmeConfirm.MlmeRequest = mlmeRequest->Type;
-
- status = AddMacCommand( MOTE_MAC_LINK_CHECK_REQ, 0, 0 );
+ status = LORAMAC_STATUS_OK;
+ if( LoRaMacCommandsAddCmd( MOTE_MAC_LINK_CHECK_REQ, macCmdPayload, 0 ) != LORAMAC_COMMANDS_SUCCESS )
+ {
+ status = LORAMAC_STATUS_MAC_COMMAD_ERROR;
+ }
break;
}
case MLME_TXCW:
{
- MlmeConfirm.MlmeRequest = mlmeRequest->Type;
- LoRaMacFlags.Bits.MlmeReq = 1;
status = SetTxContinuousWave( mlmeRequest->Req.TxCw.Timeout );
break;
}
case MLME_TXCW_1:
{
- MlmeConfirm.MlmeRequest = mlmeRequest->Type;
- LoRaMacFlags.Bits.MlmeReq = 1;
+
status = SetTxContinuousWave1( mlmeRequest->Req.TxCw.Timeout, mlmeRequest->Req.TxCw.Frequency, mlmeRequest->Req.TxCw.Power );
break;
}
+ case MLME_DEVICE_TIME:
+ {
+ // LoRaMac will send this command piggy-pack
+ status = LORAMAC_STATUS_OK;
+ if( LoRaMacCommandsAddCmd( MOTE_MAC_DEVICE_TIME_REQ, macCmdPayload, 0 ) != LORAMAC_COMMANDS_SUCCESS )
+ {
+ status = LORAMAC_STATUS_MAC_COMMAD_ERROR;
+ }
+ break;
+ }
+ case MLME_PING_SLOT_INFO:
+ {
+ if( MacCtx.NvmCtx->DeviceClass == CLASS_A )
+ {
+ uint8_t value = mlmeRequest->Req.PingSlotInfo.PingSlot.Value;
+
+ // LoRaMac will send this command piggy-pack
+ LoRaMacClassBSetPingSlotInfo( mlmeRequest->Req.PingSlotInfo.PingSlot.Fields.Periodicity );
+ macCmdPayload[0] = value;
+ status = LORAMAC_STATUS_OK;
+ if( LoRaMacCommandsAddCmd( MOTE_MAC_PING_SLOT_INFO_REQ, macCmdPayload, 1 ) != LORAMAC_COMMANDS_SUCCESS )
+ {
+ status = LORAMAC_STATUS_MAC_COMMAD_ERROR;
+ }
+ }
+ break;
+ }
+ case MLME_BEACON_TIMING:
+ {
+ // LoRaMac will send this command piggy-pack
+ status = LORAMAC_STATUS_OK;
+ if( LoRaMacCommandsAddCmd( MOTE_MAC_BEACON_TIMING_REQ, macCmdPayload, 0 ) != LORAMAC_COMMANDS_SUCCESS )
+ {
+ status = LORAMAC_STATUS_MAC_COMMAD_ERROR;
+ }
+ break;
+ }
+ case MLME_BEACON_ACQUISITION:
+ {
+ // Apply the request
+ queueElement.RestrictCommonReadyToHandle = true;
+
+ if( LoRaMacClassBIsAcquisitionInProgress( ) == false )
+ {
+ // Start class B algorithm
+ LoRaMacClassBSetBeaconState( BEACON_STATE_ACQUISITION );
+ LoRaMacClassBBeaconTimerEvent( NULL );
+
+ status = LORAMAC_STATUS_OK;
+ }
+ else
+ {
+ status = LORAMAC_STATUS_BUSY;
+ }
+ break;
+ }
default:
break;
}
if( status != LORAMAC_STATUS_OK )
{
- NodeAckRequested = false;
- LoRaMacFlags.Bits.MlmeReq = 0;
+ if( LoRaMacConfirmQueueGetCnt( ) == 0 )
+ {
+ MacCtx.NodeAckRequested = false;
+ MacCtx.MacFlags.Bits.MlmeReq = 0;
+ }
+ }
+ else
+ {
+ LoRaMacConfirmQueueAdd( &queueElement );
+ EventMacNvmCtxChanged( );
}
-
return status;
}
-LoRaMacStatus_t LoRaMacMcpsRequest( McpsReq_t *mcpsRequest )
+LoRaMacStatus_t LoRaMacMcpsRequest( McpsReq_t* mcpsRequest )
{
GetPhyParams_t getPhy;
PhyParam_t phyParam;
@@ -3425,34 +4626,33 @@ LoRaMacStatus_t LoRaMacMcpsRequest( McpsReq_t *mcpsRequest )
LoRaMacHeader_t macHdr;
VerifyParams_t verify;
uint8_t fPort = 0;
- void *fBuffer;
+ void* fBuffer;
uint16_t fBufferSize;
- int8_t datarate;
+ int8_t datarate = DR_0;
bool readyToSend = false;
if( mcpsRequest == NULL )
{
return LORAMAC_STATUS_PARAMETER_INVALID;
}
- if( ( ( LoRaMacState & LORAMAC_TX_RUNNING ) == LORAMAC_TX_RUNNING ) ||
- ( ( LoRaMacState & LORAMAC_TX_DELAYED ) == LORAMAC_TX_DELAYED ) )
+ if( LoRaMacIsBusy( ) == true )
{
return LORAMAC_STATUS_BUSY;
}
macHdr.Value = 0;
- memset1 ( ( uint8_t* ) &McpsConfirm, 0, sizeof( McpsConfirm ) );
- McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_ERROR;
+ memset1( ( uint8_t* ) &MacCtx.McpsConfirm, 0, sizeof( MacCtx.McpsConfirm ) );
+ MacCtx.McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_ERROR;
// AckTimeoutRetriesCounter must be reset every time a new request (unconfirmed or confirmed) is performed.
- AckTimeoutRetriesCounter = 1;
+ MacCtx.AckTimeoutRetriesCounter = 1;
switch( mcpsRequest->Type )
{
case MCPS_UNCONFIRMED:
{
readyToSend = true;
- AckTimeoutRetries = 1;
+ MacCtx.AckTimeoutRetries = 1;
macHdr.Bits.MType = FRAME_TYPE_DATA_UNCONFIRMED_UP;
fPort = mcpsRequest->Req.Unconfirmed.fPort;
@@ -3464,7 +4664,7 @@ LoRaMacStatus_t LoRaMacMcpsRequest( McpsReq_t *mcpsRequest )
case MCPS_CONFIRMED:
{
readyToSend = true;
- AckTimeoutRetries = mcpsRequest->Req.Confirmed.NbTrials;
+ MacCtx.AckTimeoutRetries = MIN( mcpsRequest->Req.Confirmed.NbTrials, MAX_ACK_RETRIES );
macHdr.Bits.MType = FRAME_TYPE_DATA_CONFIRMED_UP;
fPort = mcpsRequest->Req.Confirmed.fPort;
@@ -3476,7 +4676,7 @@ LoRaMacStatus_t LoRaMacMcpsRequest( McpsReq_t *mcpsRequest )
case MCPS_PROPRIETARY:
{
readyToSend = true;
- AckTimeoutRetries = 1;
+ MacCtx.AckTimeoutRetries = 1;
macHdr.Bits.MType = FRAME_TYPE_PROPRIETARY;
fBuffer = mcpsRequest->Req.Proprietary.fBuffer;
@@ -3488,30 +4688,24 @@ LoRaMacStatus_t LoRaMacMcpsRequest( McpsReq_t *mcpsRequest )
break;
}
- // Filter fPorts
- if( IsFPortAllowed( fPort ) == false )
- {
- return LORAMAC_STATUS_PARAMETER_INVALID;
- }
-
// Get the minimum possible datarate
getPhy.Attribute = PHY_MIN_TX_DR;
- getPhy.UplinkDwellTime = LoRaMacParams.UplinkDwellTime;
- phyParam = RegionGetPhyParam( LoRaMacRegion, &getPhy );
+ getPhy.UplinkDwellTime = MacCtx.NvmCtx->MacParams.UplinkDwellTime;
+ phyParam = RegionGetPhyParam( MacCtx.NvmCtx->Region, &getPhy );
// Apply the minimum possible datarate.
// Some regions have limitations for the minimum datarate.
- datarate = MAX( datarate, phyParam.Value );
+ datarate = MAX( datarate, ( int8_t )phyParam.Value );
if( readyToSend == true )
{
- if( AdrCtrlOn == false )
+ if( MacCtx.NvmCtx->AdrCtrlOn == false )
{
verify.DatarateParams.Datarate = datarate;
- verify.DatarateParams.UplinkDwellTime = LoRaMacParams.UplinkDwellTime;
+ verify.DatarateParams.UplinkDwellTime = MacCtx.NvmCtx->MacParams.UplinkDwellTime;
- if( RegionVerify( LoRaMacRegion, &verify, PHY_TX_DR ) == true )
+ if( RegionVerify( MacCtx.NvmCtx->Region, &verify, PHY_TX_DR ) == true )
{
- LoRaMacParams.ChannelsDatarate = verify.DatarateParams.Datarate;
+ MacCtx.NvmCtx->MacParams.ChannelsDatarate = verify.DatarateParams.Datarate;
}
else
{
@@ -3522,125 +4716,59 @@ LoRaMacStatus_t LoRaMacMcpsRequest( McpsReq_t *mcpsRequest )
status = Send( &macHdr, fPort, fBuffer, fBufferSize );
if( status == LORAMAC_STATUS_OK )
{
- McpsConfirm.McpsRequest = mcpsRequest->Type;
- LoRaMacFlags.Bits.McpsReq = 1;
+ MacCtx.McpsConfirm.McpsRequest = mcpsRequest->Type;
+ MacCtx.MacFlags.Bits.McpsReq = 1;
}
else
{
- NodeAckRequested = false;
+ MacCtx.NodeAckRequested = false;
}
}
+ EventMacNvmCtxChanged( );
return status;
}
-void LoRaMacTestRxWindowsOn( bool enable )
-{
- IsRxWindowsEnabled = enable;
-}
-
-void LoRaMacTestSetMic( uint16_t txPacketCounter )
-{
- UpLinkCounter = txPacketCounter;
- IsUpLinkCounterFixed = true;
-}
-
void LoRaMacTestSetDutyCycleOn( bool enable )
{
VerifyParams_t verify;
verify.DutyCycle = enable;
- if( RegionVerify( LoRaMacRegion, &verify, PHY_DUTY_CYCLE ) == true )
+ if( RegionVerify( MacCtx.NvmCtx->Region, &verify, PHY_DUTY_CYCLE ) == true )
{
- DutyCycleOn = enable;
+ MacCtx.NvmCtx->DutyCycleOn = enable;
}
}
-void LoRaMacTestSetChannel( uint8_t channel )
-{
- Channel = channel;
-}
-
-void LoRaMacNvsSave( void )
-{
- ChannelParams_t *channels;
- uint16_t *channelmask;
- uint32_t size;
-
- modlora_nvs_set_blob(E_LORA_NVS_ELE_MAC_PARAMS, &LoRaMacParams, sizeof(LoRaMacParams));
- RegionGetChannels(LoRaMacRegion, &channels, &size);
- modlora_nvs_set_blob(E_LORA_NVS_ELE_CHANNELS, channels, size);
-
- if (RegionGetChannelMask(LoRaMacRegion, &channelmask, &size)) {
- modlora_nvs_set_blob(E_LORA_NVS_ELE_CHANNELMASK, channelmask, size);
- }
-
- if (RegionGetChannelMaskRemaining(LoRaMacRegion, &channelmask, &size)) {
- modlora_nvs_set_blob(E_LORA_NVS_ELE_CHANNELMASK_REMAINING, channelmask, size);
- }
-
- modlora_nvs_set_uint(E_LORA_NVS_ELE_ACK_REQ, SrvAckRequested);
-
- modlora_nvs_set_uint(E_LORA_NVS_MAC_NXT_TX, MacCommandsInNextTx);
- modlora_nvs_set_uint(E_LORA_NVS_MAC_CMD_BUF_IDX, MacCommandsBufferIndex);
- modlora_nvs_set_uint(E_LORA_NVS_MAC_CMD_BUF_RPT_IDX, MacCommandsBufferToRepeatIndex);
-
- modlora_nvs_set_blob(E_LORA_NVS_ELE_MAC_BUF, MacCommandsBuffer, sizeof(MacCommandsBuffer));
- modlora_nvs_set_blob(E_LORA_NVS_ELE_MAC_RPT_BUF, MacCommandsBufferToRepeat, sizeof(MacCommandsBufferToRepeat));
- modlora_nvs_set_uint(E_LORA_NVS_ELE_DWLINK, DownLinkCounter);
- modlora_nvs_set_uint(E_LORA_NVS_ELE_UPLINK, UpLinkCounter);
- modlora_nvs_set_blob(E_LORA_NVS_ELE_NWSKEY, LoRaMacNwkSKey, sizeof(LoRaMacNwkSKey));
- modlora_nvs_set_blob(E_LORA_NVS_ELE_APPSKEY, LoRaMacAppSKey, sizeof(LoRaMacAppSKey));
- modlora_nvs_set_uint(E_LORA_NVS_ELE_NET_ID, LoRaMacNetID);
- modlora_nvs_set_uint(E_LORA_NVS_ELE_DEVADDR, LoRaMacDevAddr);
- modlora_nvs_set_uint(E_LORA_NVS_ELE_ADR_ACKS, AdrAckCounter);
-}
-
-void LoRaMacGetChannelList(ChannelParams_t **channels, uint32_t *size) {
- RegionGetChannels(LoRaMacRegion, channels, size);
-}
-
-bool LoRaMacGetChannelsMask(uint16_t **channelmask, uint32_t *size) {
- return RegionGetChannelMask(LoRaMacRegion, channelmask, size);
-}
-
-bool LoRaMacGetChannelsMaskRemaining(uint16_t **channelmask, uint32_t *size) {
- return RegionGetChannelMaskRemaining(LoRaMacRegion, channelmask, size);
-}
-LoRaMacParams_t * LoRaMacGetMacParams(void) {
- return &LoRaMacParams;
-}
-bool * LoRaMacGetSrvAckRequested(void) {
- return &SrvAckRequested;
-}
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+//////////////////////// PYCOM FUNCTION DEFINITIONS ///////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
-bool * LoRaMacGetMacCmdNextTx(void) {
- return &MacCommandsInNextTx;
-}
+void LoRaMacNvsSave( void )
+{
+ void *modCtx = NULL;
+ void *secElemCtx = NULL;
-uint8_t * LoRaMacGetMacCmdBufferIndex(void) {
- return &MacCommandsBufferIndex;
-}
+ size_t size;
+ GetNvmCtxParams_t params;
-uint8_t * LoRaMacGetMacCmdBufferRepeatIndex(void) {
- return &MacCommandsBufferToRepeatIndex;
-}
+ modlora_nvs_set_blob(E_LORA_NVS_ELE_LORAMAC_CTX, &NvmMacCtx, sizeof(NvmMacCtx));
-uint8_t * LoRaMacGetMacCmdBuffer(void) {
- return MacCommandsBuffer;
-}
+ modCtx = RegionGetNvmCtx(NvmMacCtx.Region, ¶ms);
+ modlora_nvs_set_blob(E_LORA_NVS_ELE_REGION_CTX, &modCtx, params.nvmCtxSize);
-uint8_t * LoRaMacGetMacCmdBufferRepeat(void) {
- return MacCommandsBufferToRepeat;
-}
+ modCtx = LoRaMacCommandsGetNvmCtx( &size );
+ modlora_nvs_set_blob(E_LORA_NVS_ELE_MAC_CMD_CTX, &modCtx, size);
-uint32_t * LoRaMacGetAdrAckCounter(void) {
- return &AdrAckCounter;
+ modCtx = SecureElementGetNvmCtx( &size );
+ modlora_nvs_set_blob(E_LORA_NVS_ELE_SEC_ELEM_CTX, &secElemCtx, size);
}
diff --git a/lib/lora/mac/LoRaMac.h b/lib/lora/mac/LoRaMac.h
index 2a77564b10..d9471361e3 100644
--- a/lib/lora/mac/LoRaMac.h
+++ b/lib/lora/mac/LoRaMac.h
@@ -12,7 +12,7 @@
* \____ \| ___ | (_ _) ___ |/ ___) _ \
* _____) ) ____| | | || |_| ____( (___| | | |
* (______/|_____)_|_|_| \__)_____)\____)_| |_|
- * (C)2013 Semtech
+ * (C)2013-2017 Semtech
*
* ___ _____ _ ___ _ _____ ___ ___ ___ ___
* / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
@@ -28,29 +28,22 @@
*
* \author Daniel Jaeckle ( STACKFORCE )
*
+ * \author Johannes Bruder ( STACKFORCE )
+ *
* \defgroup LORAMAC LoRa MAC layer implementation
* This module specifies the API implementation of the LoRaMAC layer.
* This is a placeholder for a detailed description of the LoRaMac
* layer and the supported features.
* \{
*
- * \example classA/LoRaMote/main.c
- * LoRaWAN class A application example for the LoRaMote.
- *
- * \example classB/LoRaMote/main.c
- * LoRaWAN class B application example for the LoRaMote.
- *
- * \example classC/LoRaMote/main.c
- * LoRaWAN class C application example for the LoRaMote.
- *
- * \example classA/MoteII/main.c
- * LoRaWAN class A application example for the MoteII.
+ * \example classA/B-L072Z-LRWAN1/main.c
+ * LoRaWAN class A application example for the B-L072Z-LRWAN1.
*
- * \example classB/MoteII/main.c
- * LoRaWAN class B application example for the MoteII.
+ * \example classB/B-L072Z-LRWAN1/main.c
+ * LoRaWAN class B application example for the B-L072Z-LRWAN1.
*
- * \example classC/MoteII/main.c
- * LoRaWAN class C application example for the MoteII.
+ * \example classC/B-L072Z-LRWAN1/main.c
+ * LoRaWAN class C application example for the B-L072Z-LRWAN1.
*
* \example classA/NAMote72/main.c
* LoRaWAN class A application example for the NAMote72.
@@ -61,31 +54,85 @@
* \example classC/NAMote72/main.c
* LoRaWAN class C application example for the NAMote72.
*
- * \example classA/SensorNode/main.c
- * LoRaWAN class A application example for the SensorNode.
+ * \example classA/NucleoL073/main.c
+ * LoRaWAN class A application example for the NucleoL073.
+ *
+ * \example classB/NucleoL073/main.c
+ * LoRaWAN class B application example for the NucleoL073.
+ *
+ * \example classC/NucleoL073/main.c
+ * LoRaWAN class C application example for the NucleoL073.
+ *
+ * \example classA/NucleoL152/main.c
+ * LoRaWAN class A application example for the NucleoL152.
+ *
+ * \example classB/NucleoL152/main.c
+ * LoRaWAN class B application example for the NucleoL152.
+ *
+ * \example classC/NucleoL152/main.c
+ * LoRaWAN class C application example for the NucleoL152.
+ *
+ * \example classA/NucleoL476/main.c
+ * LoRaWAN class A application example for the NucleoL476.
+ *
+ * \example classB/NucleoL476/main.c
+ * LoRaWAN class B application example for the NucleoL476.
+ *
+ * \example classC/NucleoL476/main.c
+ * LoRaWAN class C application example for the NucleoL476.
+ *
+ * \example classA/SAML21/main.c
+ * LoRaWAN class A application example for the SAML21.
+ *
+ * \example classB/SAML21/main.c
+ * LoRaWAN class B application example for the SAML21.
+ *
+ * \example classC/SAML21/main.c
+ * LoRaWAN class C application example for the SAML21.
+ *
+ * \example classA/SKiM880B/main.c
+ * LoRaWAN class A application example for the SKiM880B.
*
- * \example classB/SensorNode/main.c
- * LoRaWAN class B application example for the SensorNode.
+ * \example classB/SKiM880B/main.c
+ * LoRaWAN class B application example for the SKiM880B.
*
- * \example classC/SensorNode/main.c
- * LoRaWAN class C application example for the SensorNode.
+ * \example classC/SKiM880B/main.c
+ * LoRaWAN class C application example for the SKiM880B.
*
- * \example classA/SK-iM880A/main.c
- * LoRaWAN class A application example for the SK-iM880A.
+ * \example classA/SKiM881AXL/main.c
+ * LoRaWAN class A application example for the SKiM881AXL.
*
- * \example classB/SK-iM880A/main.c
- * LoRaWAN class B application example for the SK-iM880A.
+ * \example classB/SKiM881AXL/main.c
+ * LoRaWAN class B application example for the SKiM881AXL.
+ *
+ * \example classC/SKiM881AXL/main.c
+ * LoRaWAN class C application example for the SKiM881AXL.
+ *
+ * \example classA/SKiM980A/main.c
+ * LoRaWAN class A application example for the SKiM980A.
+ *
+ * \example classB/SKiM980A/main.c
+ * LoRaWAN class B application example for the SKiM980A.
+ *
+ * \example classC/SKiM980A/main.c
+ * LoRaWAN class C application example for the SKiM980A.
*
- * \example classC/SK-iM880A/main.c
- * LoRaWAN class C application example for the SK-iM880A.
*/
#ifndef __LORAMAC_H__
#define __LORAMAC_H__
-/*!
- * Check the Mac layer state every MAC_STATE_CHECK_TIMEOUT in ms
- */
-#define MAC_STATE_CHECK_TIMEOUT 1000
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include
+#include
+#include "utilities.h"
+#include "../system/timer.h"
+#include "../system/systime.h"
+#include "radio.h"
+#include "LoRaMacTypes.h"
/*!
* Maximum number of times the MAC layer tries to get an acknowledge.
@@ -108,6 +155,11 @@
*/
#define LORAMAC_MFR_LEN 4
+/*!
+ * LoRaMac MLME-Confirm queue length
+ */
+#define LORA_MAC_MLME_CONFIRM_QUEUE_LEN 5
+
/*!
* FRMPayload overhead to be used when setting the Radio.SetMaxPayloadLength
* in RxWindowSetup function.
@@ -116,31 +168,14 @@
#define LORA_MAC_FRMPAYLOAD_OVERHEAD 13 // MHDR(1) + FHDR(7) + Port(1) + MIC(4)
/*!
- * LoRaWAN devices classes definition
- *
- * LoRaWAN Specification V1.0.2, chapter 2.1
+ * Maximum number of multicast context
*/
-typedef enum eDeviceClass
-{
- /*!
- * LoRaWAN device class A
- *
- * LoRaWAN Specification V1.0.2, chapter 3
- */
- CLASS_A,
- /*!
- * LoRaWAN device class B
- *
- * LoRaWAN Specification V1.0.2, chapter 8
- */
- CLASS_B,
- /*!
- * LoRaWAN device class C
- *
- * LoRaWAN Specification V1.0.2, chapter 17
- */
- CLASS_C,
-}DeviceClass_t;
+#define LORAMAC_MAX_MC_CTX 4
+
+/*!
+ * Start value for multicast keys enumeration
+ */
+#define LORAMAC_CRYPTO_MULTICAST_KEYS 127
/*!
* End-Device activation type
@@ -175,7 +210,7 @@ typedef union uDrRange
*/
struct sFields
{
- /*!
+ /*!
* Minimum data rate
*
* LoRaWAN Regional Parameters V1.0.2rB
@@ -194,33 +229,6 @@ typedef union uDrRange
}Fields;
}DrRange_t;
-/*!
- * LoRaMAC band parameters definition
- */
-typedef struct sBand
-{
- /*!
- * Duty cycle
- */
- uint16_t DCycle;
- /*!
- * Maximum Tx power
- */
- int8_t TxMaxPower;
- /*!
- * Time stamp of the last JoinReq Tx frame.
- */
- TimerTime_t LastJoinTxDoneTime;
- /*!
- * Time stamp of the last Tx frame
- */
- TimerTime_t LastTxDoneTime;
- /*!
- * Holds the time where the device is off
- */
- TimerTime_t TimeOff;
-}Band_t;
-
/*!
* LoRaMAC channel definition
*/
@@ -245,9 +253,9 @@ typedef struct sChannelParams
}ChannelParams_t;
/*!
- * LoRaMAC receive window 2 channel parameters
+ * LoRaMAC receive window channel parameters
*/
-typedef struct sRx2ChannelParams
+typedef struct sRxChannelParams
{
/*!
* Frequency in Hz
@@ -261,332 +269,260 @@ typedef struct sRx2ChannelParams
* The allowed ranges are region specific. Please refer to \ref DR_0 to \ref DR_15 for details.
*/
uint8_t Datarate;
-}Rx2ChannelParams_t;
+}RxChannelParams_t;
/*!
- * Global MAC layer parameters
+ * LoRaMAC receive window enumeration
*/
-typedef struct sLoRaMacParams
+typedef enum eLoRaMacRxSlot
{
/*!
- * Channels TX power
- */
- int8_t ChannelsTxPower;
- /*!
- * Channels data rate
- */
- int8_t ChannelsDatarate;
- /*!
- * System overall timing error in milliseconds.
- * [-SystemMaxRxError : +SystemMaxRxError]
- * Default: +/-10 ms
- */
- uint32_t SystemMaxRxError;
- /*!
- * Minimum required number of symbols to detect an Rx frame
- * Default: 6 symbols
- */
- uint8_t MinRxSymbols;
- /*!
- * LoRaMac maximum time a reception window stays open
- */
- uint32_t MaxRxWindow;
- /*!
- * Receive delay 1
- */
- uint32_t ReceiveDelay1;
- /*!
- * Receive delay 2
- */
- uint32_t ReceiveDelay2;
- /*!
- * Join accept delay 1
- */
- uint32_t JoinAcceptDelay1;
- /*!
- * Join accept delay 1
- */
- uint32_t JoinAcceptDelay2;
- /*!
- * Number of uplink messages repetitions [1:15] (unconfirmed messages only)
+ * LoRaMAC receive window 1
*/
- uint8_t ChannelsNbRep;
+ RX_SLOT_WIN_1,
/*!
- * Datarate offset between uplink and downlink on first window
+ * LoRaMAC receive window 2
*/
- uint8_t Rx1DrOffset;
+ RX_SLOT_WIN_2,
/*!
- * LoRaMAC 2nd reception window settings
+ * LoRaMAC receive window 2 for class c - continuous listening
*/
- Rx2ChannelParams_t Rx2Channel;
+ RX_SLOT_WIN_CLASS_C,
/*!
- * Uplink dwell time configuration. 0: No limit, 1: 400ms
+ * LoRaMAC class c multicast downlink
*/
- uint8_t UplinkDwellTime;
+ RX_SLOT_WIN_CLASS_C_MULTICAST,
/*!
- * Downlink dwell time configuration. 0: No limit, 1: 400ms
+ * LoRaMAC class b ping slot window
*/
- uint8_t DownlinkDwellTime;
+ RX_SLOT_WIN_CLASS_B_PING_SLOT,
/*!
- * Maximum possible EIRP
+ * LoRaMAC class b multicast slot window
*/
- float MaxEirp;
+ RX_SLOT_WIN_CLASS_B_MULTICAST_SLOT,
/*!
- * Antenna gain of the node
+ * LoRaMAC no active receive window
*/
- float AntennaGain;
-}LoRaMacParams_t;
+ RX_SLOT_NONE,
+}LoRaMacRxSlot_t;
/*!
- * LoRaMAC multicast channel parameter
+ * LoRaMAC structure to hold internal context pointers and its lengths
*/
-typedef struct sMulticastParams
+typedef struct sLoRaMacCtxs
{
/*!
- * Address
+ * \brief Pointer to Mac context
*/
- uint32_t Address;
+ void* MacNvmCtx;
/*!
- * Network session key
+ * \brief Size of Mac context
*/
- uint8_t NwkSKey[16];
+ size_t MacNvmCtxSize;
/*!
- * Application session key
+ * \brief Pointer to region context
*/
- uint8_t AppSKey[16];
+ void* RegionNvmCtx;
/*!
- * Downlink counter
+ * \brief Size of region context
*/
- uint32_t DownLinkCounter;
+ size_t RegionNvmCtxSize;
/*!
- * Reference pointer to the next multicast channel parameters in the list
+ * \brief Pointer to crypto module context
*/
- struct sMulticastParams *Next;
-}MulticastParams_t;
-
-/*!
- * LoRaMAC frame types
- *
- * LoRaWAN Specification V1.0.2, chapter 4.2.1, table 1
- */
-typedef enum eLoRaMacFrameType
-{
+ void* CryptoNvmCtx;
/*!
- * LoRaMAC join request frame
+ * \brief Size of crypto module context
*/
- FRAME_TYPE_JOIN_REQ = 0x00,
+ size_t CryptoNvmCtxSize;
/*!
- * LoRaMAC join accept frame
+ * \brief Pointer to secure element driver context
*/
- FRAME_TYPE_JOIN_ACCEPT = 0x01,
+ void* SecureElementNvmCtx;
/*!
- * LoRaMAC unconfirmed up-link frame
+ * \brief Size of secure element driver context
*/
- FRAME_TYPE_DATA_UNCONFIRMED_UP = 0x02,
+ size_t SecureElementNvmCtxSize;
/*!
- * LoRaMAC unconfirmed down-link frame
+ * \brief Pointer to MAC commands module context
*/
- FRAME_TYPE_DATA_UNCONFIRMED_DOWN = 0x03,
+ void* CommandsNvmCtx;
/*!
- * LoRaMAC confirmed up-link frame
+ * \brief Size of MAC commands module context
*/
- FRAME_TYPE_DATA_CONFIRMED_UP = 0x04,
+ size_t CommandsNvmCtxSize;
/*!
- * LoRaMAC confirmed down-link frame
+ * \brief Pointer to Class B module context
*/
- FRAME_TYPE_DATA_CONFIRMED_DOWN = 0x05,
+ void* ClassBNvmCtx;
/*!
- * LoRaMAC RFU frame
+ * \brief Size of MAC Class B module context
*/
- FRAME_TYPE_RFU = 0x06,
+ size_t ClassBNvmCtxSize;
/*!
- * LoRaMAC proprietary frame
+ * \brief Pointer to MLME Confirm queue module context
*/
- FRAME_TYPE_PROPRIETARY = 0x07,
-}LoRaMacFrameType_t;
+ void* ConfirmQueueNvmCtx;
+ /*!
+ * \brief Size of MLME Confirm queue module context
+ */
+ size_t ConfirmQueueNvmCtxSize;
+}LoRaMacCtxs_t;
/*!
- * LoRaMAC mote MAC commands
- *
- * LoRaWAN Specification V1.0.2, chapter 5, table 4
+ * Global MAC layer parameters
*/
-typedef enum eLoRaMacMoteCmd
+typedef struct sLoRaMacParams
{
/*!
- * LinkCheckReq
- */
- MOTE_MAC_LINK_CHECK_REQ = 0x02,
- /*!
- * LinkADRAns
- */
- MOTE_MAC_LINK_ADR_ANS = 0x03,
- /*!
- * DutyCycleAns
- */
- MOTE_MAC_DUTY_CYCLE_ANS = 0x04,
- /*!
- * RXParamSetupAns
- */
- MOTE_MAC_RX_PARAM_SETUP_ANS = 0x05,
- /*!
- * DevStatusAns
+ * Channels TX power
*/
- MOTE_MAC_DEV_STATUS_ANS = 0x06,
+ int8_t ChannelsTxPower;
/*!
- * NewChannelAns
+ * Channels data rate
*/
- MOTE_MAC_NEW_CHANNEL_ANS = 0x07,
+ int8_t ChannelsDatarate;
/*!
- * RXTimingSetupAns
+ * System overall timing error in milliseconds.
+ * [-SystemMaxRxError : +SystemMaxRxError]
+ * Default: +/-10 ms
*/
- MOTE_MAC_RX_TIMING_SETUP_ANS = 0x08,
+ uint32_t SystemMaxRxError;
/*!
- * TXParamSetupAns
+ * Minimum required number of symbols to detect an Rx frame
+ * Default: 6 symbols
*/
- MOTE_MAC_TX_PARAM_SETUP_ANS = 0x09,
+ uint8_t MinRxSymbols;
/*!
- * DlChannelAns
+ * LoRaMac maximum time a reception window stays open
*/
- MOTE_MAC_DL_CHANNEL_ANS = 0x0A
-}LoRaMacMoteCmd_t;
-
-/*!
- * LoRaMAC server MAC commands
- *
- * LoRaWAN Specification V1.0.2 chapter 5, table 4
- */
-typedef enum eLoRaMacSrvCmd
-{
+ uint32_t MaxRxWindow;
/*!
- * LinkCheckAns
+ * Receive delay 1
*/
- SRV_MAC_LINK_CHECK_ANS = 0x02,
+ uint32_t ReceiveDelay1;
/*!
- * LinkADRReq
+ * Receive delay 2
*/
- SRV_MAC_LINK_ADR_REQ = 0x03,
+ uint32_t ReceiveDelay2;
/*!
- * DutyCycleReq
+ * Join accept delay 1
*/
- SRV_MAC_DUTY_CYCLE_REQ = 0x04,
+ uint32_t JoinAcceptDelay1;
/*!
- * RXParamSetupReq
+ * Join accept delay 1
*/
- SRV_MAC_RX_PARAM_SETUP_REQ = 0x05,
+ uint32_t JoinAcceptDelay2;
/*!
- * DevStatusReq
+ * Number of uplink messages repetitions [1:15] (unconfirmed messages only)
*/
- SRV_MAC_DEV_STATUS_REQ = 0x06,
+ uint8_t ChannelsNbTrans;
/*!
- * NewChannelReq
+ * Datarate offset between uplink and downlink on first window
*/
- SRV_MAC_NEW_CHANNEL_REQ = 0x07,
+ uint8_t Rx1DrOffset;
/*!
- * RXTimingSetupReq
+ * LoRaMAC 2nd reception window settings
*/
- SRV_MAC_RX_TIMING_SETUP_REQ = 0x08,
+ RxChannelParams_t Rx2Channel;
/*!
- * NewChannelReq
+ * LoRaMAC continuous reception window settings
*/
- SRV_MAC_TX_PARAM_SETUP_REQ = 0x09,
+ RxChannelParams_t RxCChannel;
/*!
- * DlChannelReq
+ * Uplink dwell time configuration. 0: No limit, 1: 400ms
*/
- SRV_MAC_DL_CHANNEL_REQ = 0x0A,
-}LoRaMacSrvCmd_t;
-
-/*!
- * LoRaMAC Battery level indicator
- */
-typedef enum eLoRaMacBatteryLevel
-{
+ uint8_t UplinkDwellTime;
/*!
- * External power source
+ * Downlink dwell time configuration. 0: No limit, 1: 400ms
*/
- BAT_LEVEL_EXT_SRC = 0x00,
+ uint8_t DownlinkDwellTime;
/*!
- * Battery level empty
+ * Maximum possible EIRP
*/
- BAT_LEVEL_EMPTY = 0x01,
+ float MaxEirp;
/*!
- * Battery level full
+ * Antenna gain of the node
*/
- BAT_LEVEL_FULL = 0xFE,
+ float AntennaGain;
/*!
- * Battery level - no measurement available
+ * Indicates if the node supports repeaters
*/
- BAT_LEVEL_NO_MEASURE = 0xFF,
-}LoRaMacBatteryLevel_t;
+ bool RepeaterSupport;
+}LoRaMacParams_t;
/*!
- * LoRaMAC header field definition (MHDR field)
+ * LoRaMAC data structure for a PingSlotInfoReq \ref MLME_PING_SLOT_INFO
*
- * LoRaWAN Specification V1.0.2, chapter 4.2
+ * LoRaWAN Specification
*/
-typedef union uLoRaMacHeader
+typedef union uPingSlotInfo
{
/*!
- * Byte-access to the bits
+ * Parameter for byte access
*/
uint8_t Value;
/*!
- * Structure containing single access to header bits
+ * Structure containing the parameters for the PingSlotInfoReq
*/
- struct sHdrBits
+ struct sInfoFields
{
/*!
- * Major version
+ * Periodicity = 0: ping slot every second
+ * Periodicity = 7: ping slot every 128 seconds
*/
- uint8_t Major : 2;
+ uint8_t Periodicity : 3;
/*!
* RFU
*/
- uint8_t RFU : 3;
- /*!
- * Message type
- */
- uint8_t MType : 3;
- }Bits;
-}LoRaMacHeader_t;
+ uint8_t RFU : 5;
+ }Fields;
+}PingSlotInfo_t;
/*!
- * LoRaMAC frame control field definition (FCtrl)
+ * LoRaMAC data structure for the \ref MLME_BEACON MLME-Indication
*
- * LoRaWAN Specification V1.0.2, chapter 4.3.1
+ * LoRaWAN Specification
*/
-typedef union uLoRaMacFrameCtrl
+typedef struct sBeaconInfo
{
/*!
- * Byte-access to the bits
+ * Timestamp in seconds since 00:00:00, Sunday 6th of January 1980
+ * (start of the GPS epoch) modulo 2^32
*/
- uint8_t Value;
+ SysTime_t Time;
/*!
- * Structure containing single access to bits
+ * Frequency
+ */
+ uint32_t Frequency;
+ /*!
+ * Datarate
+ */
+ uint8_t Datarate;
+ /*!
+ * RSSI
+ */
+ int16_t Rssi;
+ /*!
+ * SNR
*/
- struct sCtrlBits
+ int8_t Snr;
+ /*!
+ * Data structure for the gateway specific part. The
+ * content of the values may differ for each gateway
+ */
+ struct sGwSpecific
{
/*!
- * Frame options length
- */
- uint8_t FOptsLen : 4;
- /*!
- * Frame pending bit
+ * Info descriptor - can differ for each gateway
*/
- uint8_t FPending : 1;
+ uint8_t InfoDesc;
/*!
- * Message acknowledge bit
+ * Info - can differ for each gateway
*/
- uint8_t Ack : 1;
- /*!
- * ADR acknowledgment request bit
- */
- uint8_t AdrAckReq : 1;
- /*!
- * ADR control in frame header
- */
- uint8_t Adr : 1;
- }Bits;
-}LoRaMacFrameCtrl_t;
+ uint8_t Info[6];
+ }GwSpecific;
+}BeaconInfo_t;
/*!
* Enumeration containing the status of the operation of a MAC service
@@ -645,9 +581,25 @@ typedef enum eLoRaMacEventInfoStatus
*/
LORAMAC_EVENT_INFO_STATUS_ADDRESS_FAIL,
/*!
- * message integrity check failure
+ * Message integrity check failure
*/
LORAMAC_EVENT_INFO_STATUS_MIC_FAIL,
+ /*!
+ * ToDo
+ */
+ LORAMAC_EVENT_INFO_STATUS_MULTICAST_FAIL,
+ /*!
+ * ToDo
+ */
+ LORAMAC_EVENT_INFO_STATUS_BEACON_LOCKED,
+ /*!
+ * ToDo
+ */
+ LORAMAC_EVENT_INFO_STATUS_BEACON_LOST,
+ /*!
+ * ToDo
+ */
+ LORAMAC_EVENT_INFO_STATUS_BEACON_NOT_FOUND,
}LoRaMacEventInfoStatus_t;
/*!
@@ -667,27 +619,27 @@ typedef union eLoRaMacFlags_t
/*!
* MCPS-Req pending
*/
- uint8_t McpsReq : 1;
+ uint8_t McpsReq : 1;
/*!
* MCPS-Ind pending
*/
- uint8_t McpsInd : 1;
- /*!
- * MCPS-Ind pending. Skip indication to the application layer
- */
- uint8_t McpsIndSkip : 1;
+ uint8_t McpsInd : 1;
/*!
* MLME-Req pending
*/
- uint8_t MlmeReq : 1;
+ uint8_t MlmeReq : 1;
/*!
* MLME-Ind pending
*/
- uint8_t MlmeInd : 1;
+ uint8_t MlmeInd : 1;
+ /*!
+ * MLME-Ind to schedule an uplink pending
+ */
+ uint8_t MlmeSchedUplinkInd : 1;
/*!
* MAC cycle done
*/
- uint8_t MacDone : 1;
+ uint8_t MacDone : 1;
}Bits;
}LoRaMacFlags_t;
@@ -749,7 +701,7 @@ typedef struct sMcpsReqUnconfirmed
/*!
* Pointer to the buffer of the frame payload
*/
- void *fBuffer;
+ void* fBuffer;
/*!
* Size of the frame payload
*/
@@ -775,7 +727,7 @@ typedef struct sMcpsReqConfirmed
/*!
* Pointer to the buffer of the frame payload
*/
- void *fBuffer;
+ void* fBuffer;
/*!
* Size of the frame payload
*/
@@ -815,7 +767,7 @@ typedef struct sMcpsReqProprietary
/*!
* Pointer to the buffer of the frame payload
*/
- void *fBuffer;
+ void* fBuffer;
/*!
* Size of the frame payload
*/
@@ -894,9 +846,9 @@ typedef struct sMcpsConfirm
*/
uint32_t UpLinkCounter;
/*!
- * The uplink frequency related to the frame
+ * The uplink channel related to the frame
*/
- uint32_t UpLinkFrequency;
+ uint32_t Channel;
}McpsConfirm_t;
/*!
@@ -912,6 +864,7 @@ typedef struct sMcpsIndication
* Status of the operation
*/
LoRaMacEventInfoStatus_t Status;
+ // Pycom: Added TimeStamp
/*!
* Downlink timestamp
*/
@@ -935,7 +888,7 @@ typedef struct sMcpsIndication
/*!
* Pointer to the received data stream
*/
- uint8_t *Buffer;
+ uint8_t* Buffer;
/*!
* Size of the received data stream
*/
@@ -951,13 +904,11 @@ typedef struct sMcpsIndication
/*!
* Snr of the received packet
*/
- uint8_t Snr;
+ int8_t Snr;
/*!
* Receive window
- *
- * [0: Rx window 1, 1: Rx window 2]
*/
- uint8_t RxSlot;
+ LoRaMacRxSlot_t RxSlot;
/*!
* Set if an acknowledgement was received
*/
@@ -966,6 +917,14 @@ typedef struct sMcpsIndication
* The downlink counter value for the received frame
*/
uint32_t DownLinkCounter;
+ /*!
+ * The device address of the frame
+ */
+ uint32_t DevAddress;
+ /*!
+ * Set if a DeviceTimeAns MAC command was received.
+ */
+ bool DeviceTimeAnsReceived;
}McpsIndication_t;
/*!
@@ -974,11 +933,14 @@ typedef struct sMcpsIndication
* \details The following table list the primitives which are supported by the
* specific MAC management service:
*
- * Name | Request | Indication | Response | Confirm
- * --------------------- | :-----: | :--------: | :------: | :-----:
- * \ref MLME_JOIN | YES | NO | NO | YES
- * \ref MLME_LINK_CHECK | YES | NO | NO | YES
- * \ref MLME_TXCW | YES | NO | NO | YES
+ * Name | Request | Indication | Response | Confirm
+ * ---------------------------- | :-----: | :--------: | :------: | :-----:
+ * \ref MLME_JOIN | YES | NO | NO | YES
+ * \ref MLME_LINK_CHECK | YES | NO | NO | YES
+ * \ref MLME_TXCW | YES | NO | NO | YES
+ * \ref MLME_SCHEDULE_UPLINK | NO | YES | NO | NO
+ * \ref MLME_DERIVE_MC_KE_KEY | YES | NO | NO | YES
+ * \ref MLME_DERIVE_MC_KEY_PAIR | YES | NO | NO | YES
*
* The following table provides links to the function implementations of the
* related MLME primitives.
@@ -987,6 +949,7 @@ typedef struct sMcpsIndication
* ---------------- | :---------------------:
* MLME-Request | \ref LoRaMacMlmeRequest
* MLME-Confirm | MacMlmeConfirm in \ref LoRaMacPrimitives_t
+ * MLME-Indication | MacMlmeIndication in \ref LoRaMacPrimitives_t
*/
typedef enum eMlme
{
@@ -996,6 +959,18 @@ typedef enum eMlme
* LoRaWAN Specification V1.0.2, chapter 6.2
*/
MLME_JOIN,
+ /*!
+ * Initiates sending a ReJoin-request type 0
+ *
+ * LoRaWAN Specification V1.1.0, chapter 6.2.4.1
+ */
+ MLME_REJOIN_0,
+ /*!
+ * Initiates sending a ReJoin-request type 1
+ *
+ * LoRaWAN Specification V1.1.0, chapter 6.2.4.2
+ */
+ MLME_REJOIN_1,
/*!
* LinkCheckReq - Connectivity validation
*
@@ -1018,40 +993,66 @@ typedef enum eMlme
* Indicates that the application shall perform an uplink as
* soon as possible.
*/
- MLME_SCHEDULE_UPLINK
-}Mlme_t;
-
-/*!
- * LoRaMAC MLME-Request for the join service
- */
-typedef struct sMlmeReqJoin
-{
+ MLME_SCHEDULE_UPLINK,
+ /*!
+ * Derives the McKEKey from the AppKey or NwkKey.
+ */
+ MLME_DERIVE_MC_KE_KEY,
+ /*!
+ * Derives a Multicast group key pair ( McAppSKey, McNwkSKey ) from McKey
+ */
+ MLME_DERIVE_MC_KEY_PAIR,
/*!
- * Globally unique end-device identifier
+ * Initiates a DeviceTimeReq
*
- * LoRaWAN Specification V1.0.2, chapter 6.2.1
+ * LoRaWAN end-device certification
*/
- uint8_t *DevEui;
+ MLME_DEVICE_TIME,
/*!
- * Application identifier
+ * The MAC uses this MLME primitive to indicate a beacon reception
+ * status.
*
- * LoRaWAN Specification V1.0.2, chapter 6.1.2
+ * LoRaWAN end-device certification
*/
- uint8_t *AppEui;
+ MLME_BEACON,
/*!
- * AES-128 application key
+ * Initiate a beacon acquisition. The MAC will search for a beacon.
+ * It will search for XX_BEACON_INTERVAL milliseconds.
*
- * LoRaWAN Specification V1.0.2, chapter 6.2.2
+ * LoRaWAN end-device certification
*/
- uint8_t *AppKey;
+ MLME_BEACON_ACQUISITION,
/*!
- * Number of trials for the join request.
+ * Initiates a PingSlotInfoReq
+ *
+ * LoRaWAN end-device certification
*/
- uint8_t NbTrials;
+ MLME_PING_SLOT_INFO,
+ /*!
+ * Initiates a BeaconTimingReq
+ *
+ * LoRaWAN end-device certification
+ */
+ MLME_BEACON_TIMING,
+ /*!
+ * Primitive which indicates that the beacon has been lost
+ *
+ * \remark The upper layer is required to switch the device class to ClassA
+ *
+ * LoRaWAN end-device certification
+ */
+ MLME_BEACON_LOST,
+}Mlme_t;
+
+/*!
+ * LoRaMAC MLME-Request for the join service
+ */
+typedef struct sMlmeReqJoin
+{
/*!
- * To support initial data rate selection for the Join Request
+ * Datarate used for join request.
*/
- uint8_t DR;
+ uint8_t Datarate;
}MlmeReqJoin_t;
/*!
@@ -1073,6 +1074,44 @@ typedef struct sMlmeReqTxCw
uint8_t Power;
}MlmeReqTxCw_t;
+/*!
+ * LoRaMAC MLME-Request for the ping slot info service
+ */
+typedef struct sMlmeReqPingSlotInfo
+{
+ PingSlotInfo_t PingSlot;
+}MlmeReqPingSlotInfo_t;
+
+/*!
+ * LoRaMAC MLME-Request to derive the McKEKey from the AppKey or NwkKey
+ */
+typedef struct sMlmeReqDeriveMcKEKey
+{
+ /*!
+ * Key identifier of the root key to use to perform the derivation ( NwkKey or AppKey )
+ */
+ KeyIdentifier_t KeyID;
+ /*!
+ * Nonce value ( nonce <= 15)
+ */
+ uint16_t Nonce;
+ /*!
+ * DevEUI Value
+ */
+ uint8_t* DevEUI;
+}MlmeReqDeriveMcKEKey_t;
+
+/*!
+ * LoRaMAC MLME-Request to derive a Multicast group key pair ( McAppSKey, McNwkSKey ) from McKey
+ */
+typedef struct sMlmeReqDeriveMcSessionKeyPair
+{
+ /*!
+ * Address identifier to select the multicast group
+ */
+ AddressIdentifier_t GroupID;
+}MlmeReqDeriveMcSessionKeyPair_t;
+
/*!
* LoRaMAC MLME-Request structure
*/
@@ -1096,6 +1135,18 @@ typedef struct sMlmeReq
* MLME-Request parameters for Tx continuous mode request
*/
MlmeReqTxCw_t TxCw;
+ /*!
+ * MLME-Request parameters for a ping slot info request
+ */
+ MlmeReqPingSlotInfo_t PingSlotInfo;
+ /*!
+ * MLME-Request to derive the McKEKey from the AppKey or NwkKey
+ */
+ MlmeReqDeriveMcKEKey_t DeriveMcKEKey;
+ /*!
+ * MLME-Request to derive a Multicast group key pair ( McAppSKey, McNwkSKey ) from McKey
+ */
+ MlmeReqDeriveMcSessionKeyPair_t DeriveMcSessionKeyPair;
}Req;
}MlmeReq_t;
@@ -1129,6 +1180,15 @@ typedef struct sMlmeConfirm
* Provides the number of retransmissions
*/
uint8_t NbRetries;
+ /*!
+ * The delay which we have received through the
+ * BeaconTimingAns
+ */
+ TimerTime_t BeaconTimingDelay;
+ /*!
+ * The channel of the next beacon
+ */
+ uint8_t BeaconTimingChannel;
}MlmeConfirm_t;
/*!
@@ -1140,6 +1200,15 @@ typedef struct sMlmeIndication
* MLME-Indication type
*/
Mlme_t MlmeIndication;
+ /*!
+ * Status of the operation
+ */
+ LoRaMacEventInfoStatus_t Status;
+ /*!
+ * Beacon information. Only valid for \ref MLME_BEACON,
+ * status \ref LORAMAC_EVENT_INFO_STATUS_BEACON_LOCKED
+ */
+ BeaconInfo_t BeaconInfo;
}MlmeIndication_t;
/*!
@@ -1147,38 +1216,74 @@ typedef struct sMlmeIndication
*
* The following table lists the MIB parameters and the related attributes:
*
- * Attribute | Get | Set
- * --------------------------------- | :-: | :-:
- * \ref MIB_DEVICE_CLASS | YES | YES
- * \ref MIB_NETWORK_ACTIVATION | YES | YES
- * \ref MIB_NETWORK_JOINED | YES | YES
- * \ref MIB_ADR | YES | YES
- * \ref MIB_NET_ID | YES | YES
- * \ref MIB_DEV_ADDR | YES | YES
- * \ref MIB_NWK_SKEY | YES | YES
- * \ref MIB_APP_SKEY | YES | YES
- * \ref MIB_PUBLIC_NETWORK | YES | YES
- * \ref MIB_REPEATER_SUPPORT | YES | YES
- * \ref MIB_CHANNELS | YES | NO
- * \ref MIB_RX2_CHANNEL | YES | YES
- * \ref MIB_CHANNELS_MASK | YES | YES
- * \ref MIB_CHANNELS_DEFAULT_MASK | YES | YES
- * \ref MIB_CHANNELS_NB_REP | YES | YES
- * \ref MIB_MAX_RX_WINDOW_DURATION | YES | YES
- * \ref MIB_RECEIVE_DELAY_1 | YES | YES
- * \ref MIB_RECEIVE_DELAY_2 | YES | YES
- * \ref MIB_JOIN_ACCEPT_DELAY_1 | YES | YES
- * \ref MIB_JOIN_ACCEPT_DELAY_2 | YES | YES
- * \ref MIB_CHANNELS_DATARATE | YES | YES
- * \ref MIB_CHANNELS_DEFAULT_DATARATE| YES | YES
- * \ref MIB_CHANNELS_TX_POWER | YES | YES
- * \ref MIB_CHANNELS_DEFAULT_TX_POWER| YES | YES
- * \ref MIB_UPLINK_COUNTER | YES | YES
- * \ref MIB_DOWNLINK_COUNTER | YES | YES
- * \ref MIB_MULTICAST_CHANNEL | YES | NO
- * \ref MIB_SYSTEM_MAX_RX_ERROR | YES | YES
- * \ref MIB_MIN_RX_SYMBOLS | YES | YES
- * \ref MIB_ANTENNA_GAIN | YES | YES
+ * Attribute | Get | Set
+ * ----------------------------------------------| :-: | :-:
+ * \ref MIB_DEVICE_CLASS | YES | YES
+ * \ref MIB_NETWORK_ACTIVATION | YES | YES
+ * \ref MIB_DEV_EUI | YES | YES
+ * \ref MIB_JOIN_EUI | YES | YES
+ * \ref MIB_ADR | YES | YES
+ * \ref MIB_NET_ID | YES | YES
+ * \ref MIB_DEV_ADDR | YES | YES
+ * \ref MIB_GEN_APP_KEY | NO | YES
+ * \ref MIB_APP_KEY | NO | YES
+ * \ref MIB_NWK_KEY | NO | YES
+ * \ref MIB_J_S_INT_KEY | NO | YES
+ * \ref MIB_J_S_ENC_KEY | NO | YES
+ * \ref MIB_F_NWK_S_INT_KEY | NO | YES
+ * \ref MIB_S_NWK_S_INT_KEY | NO | YES
+ * \ref MIB_NWK_S_ENC_KEY | NO | YES
+ * \ref MIB_APP_S_KEY | NO | YES
+ * \ref MIB_MC_KE_KEY | NO | YES
+ * \ref MIB_MC_KEY_0 | NO | YES
+ * \ref MIB_MC_APP_S_KEY_0 | NO | YES
+ * \ref MIB_MC_NWK_S_KEY_0 | NO | YES
+ * \ref MIB_MC_KEY_1 | NO | YES
+ * \ref MIB_MC_APP_S_KEY_1 | NO | YES
+ * \ref MIB_MC_NWK_S_KEY_1 | NO | YES
+ * \ref MIB_MC_KEY_2 | NO | YES
+ * \ref MIB_MC_APP_S_KEY_2 | NO | YES
+ * \ref MIB_MC_NWK_S_KEY_2 | NO | YES
+ * \ref MIB_MC_KEY_3 | NO | YES
+ * \ref MIB_MC_APP_S_KEY_3 | NO | YES
+ * \ref MIB_MC_NWK_S_KEY_3 | NO | YES
+ * \ref MIB_PUBLIC_NETWORK | YES | YES
+ * \ref MIB_REPEATER_SUPPORT | YES | YES
+ * \ref MIB_CHANNELS | YES | NO
+ * \ref MIB_RX2_CHANNEL | YES | YES
+ * \ref MIB_RX2_DFAULT_CHANNEL | YES | YES
+ * \ref MIB_RXC_CHANNEL | YES | YES
+ * \ref MIB_RXC_DFAULT_CHANNEL | YES | YES
+ * \ref MIB_CHANNELS_MASK | YES | YES
+ * \ref MIB_CHANNELS_DEFAULT_MASK | YES | YES
+ * \ref MIB_CHANNELS_NB_TRANS | YES | YES
+ * \ref MIB_MAX_RX_WINDOW_DURATION | YES | YES
+ * \ref MIB_RECEIVE_DELAY_1 | YES | YES
+ * \ref MIB_RECEIVE_DELAY_2 | YES | YES
+ * \ref MIB_JOIN_ACCEPT_DELAY_1 | YES | YES
+ * \ref MIB_JOIN_ACCEPT_DELAY_2 | YES | YES
+ * \ref MIB_CHANNELS_DATARATE | YES | YES
+ * \ref MIB_CHANNELS_DEFAULT_DATARATE | YES | YES
+ * \ref MIB_CHANNELS_TX_POWER | YES | YES
+ * \ref MIB_CHANNELS_DEFAULT_TX_POWER | YES | YES
+ * \ref MIB_SYSTEM_MAX_RX_ERROR | YES | YES
+ * \ref MIB_MIN_RX_SYMBOLS | YES | YES
+ * \ref MIB_BEACON_INTERVAL | YES | YES
+ * \ref MIB_BEACON_RESERVED | YES | YES
+ * \ref MIB_BEACON_GUARD | YES | YES
+ * \ref MIB_BEACON_WINDOW | YES | YES
+ * \ref MIB_BEACON_WINDOW_SLOTS | YES | YES
+ * \ref MIB_PING_SLOT_WINDOW | YES | YES
+ * \ref MIB_BEACON_SYMBOL_TO_DEFAULT | YES | YES
+ * \ref MIB_BEACON_SYMBOL_TO_EXPANSION_MAX | YES | YES
+ * \ref MIB_PING_SLOT_SYMBOL_TO_EXPANSION_MAX | YES | YES
+ * \ref MIB_BEACON_SYMBOL_TO_EXPANSION_FACTOR | YES | YES
+ * \ref MIB_PING_SLOT_SYMBOL_TO_EXPANSION_FACTOR | YES | YES
+ * \ref MIB_MAX_BEACON_LESS_PERIOD | YES | YES
+ * \ref MIB_ANTENNA_GAIN | YES | YES
+ * \ref MIB_DEFAULT_ANTENNA_GAIN | YES | YES
+ * \ref MIB_NVM_CTXS | YES | YES
+ * \ref MIB_ABP_LORAWAN_VERSION | YES | YES
*
* The following table provides links to the function implementations of the
* related MIB primitives:
@@ -1203,11 +1308,17 @@ typedef enum eMib
*/
MIB_NETWORK_ACTIVATION,
/*!
- * LoRaWAN Network joined attribute
+ * LoRaWAN device EUI
*
* LoRaWAN Specification V1.0.2
*/
- MIB_NETWORK_JOINED,
+ MIB_DEV_EUI,
+ /*!
+ * LoRaWAN join EUI
+ *
+ * LoRaWAN Specification V1.0.2
+ */
+ MIB_JOIN_EUI,
/*!
* Adaptive data rate
*
@@ -1229,17 +1340,137 @@ typedef enum eMib
*/
MIB_DEV_ADDR,
/*!
- * Network session key
+ * Application root key - 1.0.x devices only.
+ *
+ * LoRaWAN Remote Multicast Setup v1.0.0 Specification, chapter 4.3
+ */
+ MIB_GEN_APP_KEY,
+ /*!
+ * Application root key
+ *
+ * LoRaWAN Specification V1.1.0, chapter 6.1.1.3
+ */
+ MIB_APP_KEY,
+ /*!
+ * Network root key
+ *
+ * LoRaWAN Specification V1.1.0, chapter 6.1.1.3
+ */
+ MIB_NWK_KEY,
+ /*!
+ * Join session integrity key
+ *
+ * LoRaWAN Specification V1.1.0, chapter 6.1.1.4
+ */
+ MIB_J_S_INT_KEY,
+ /*!
+ * Join session encryption key
*
- * LoRaWAN Specification V1.0.2, chapter 6.1.3
+ * LoRaWAN Specification V1.1.0, chapter 6.1.1.4
*/
- MIB_NWK_SKEY,
+ MIB_J_S_ENC_KEY,
+ /*!
+ * Forwarding Network session integrity key
+ *
+ * LoRaWAN Specification V1.1.0, chapter 6.1.2.2
+ */
+ MIB_F_NWK_S_INT_KEY,
+ /*!
+ * Serving Network session integrity key
+ *
+ * LoRaWAN Specification V1.1.0, chapter 6.1.2.3
+ */
+ MIB_S_NWK_S_INT_KEY,
+ /*!
+ * Network session encryption key
+ *
+ * LoRaWAN Specification V1.1.0, chapter 6.1.2.4
+ */
+ MIB_NWK_S_ENC_KEY,
/*!
* Application session key
*
- * LoRaWAN Specification V1.0.2, chapter 6.1.4
+ * LoRaWAN Specification V1.1.0, chapter 6.1.1.3
+ */
+ MIB_APP_S_KEY,
+ /*!
+ * Multicast key encryption key
+ *
+ * LoRaWAN - Secure element specification v1
+ */
+ MIB_MC_KE_KEY,
+ /*!
+ * Multicast root key index 0
+ *
+ * LoRaWAN - Secure element specification v1
+ */
+ MIB_MC_KEY_0,
+ /*!
+ * Multicast Application session key index 0
+ *
+ * LoRaWAN - Secure element specification v1
+ */
+ MIB_MC_APP_S_KEY_0,
+ /*!
+ * Multicast Network session key index 0
+ *
+ * LoRaWAN - Secure element specification v1
+ */
+ MIB_MC_NWK_S_KEY_0,
+ /*!
+ * Multicast root key index 1
+ *
+ * LoRaWAN - Secure element specification v1
+ */
+ MIB_MC_KEY_1,
+ /*!
+ * Multicast Application session key index 1
+ *
+ * LoRaWAN - Secure element specification v1
+ */
+ MIB_MC_APP_S_KEY_1,
+ /*!
+ * Multicast Network session key index 1
+ *
+ * LoRaWAN - Secure element specification v1
+ */
+ MIB_MC_NWK_S_KEY_1,
+ /*!
+ * Multicast root key index 2
+ *
+ * LoRaWAN - Secure element specification v1
+ */
+ MIB_MC_KEY_2,
+ /*!
+ * Multicast Application session key index 2
+ *
+ * LoRaWAN - Secure element specification v1
+ */
+ MIB_MC_APP_S_KEY_2,
+ /*!
+ * Multicast Network session key index 2
+ *
+ * LoRaWAN - Secure element specification v1
+ */
+ MIB_MC_NWK_S_KEY_2,
+ /*!
+ * Multicast root key index 3
+ *
+ * LoRaWAN - Secure element specification v1
+ */
+ MIB_MC_KEY_3,
+ /*!
+ * Multicast Application session key index 3
+ *
+ * LoRaWAN - Secure element specification v1
+ */
+ MIB_MC_APP_S_KEY_3,
+ /*!
+ * Multicast Network session key index 3
+ *
+ * LoRaWAN - Secure element specification v1
*/
- MIB_APP_SKEY,
+ MIB_MC_NWK_S_KEY_3,
/*!
* Set the network type to public or private
*
@@ -1276,6 +1507,18 @@ typedef enum eMib
* LoRaWAN Specification V1.0.2, chapter 3.3.2
*/
MIB_RX2_DEFAULT_CHANNEL,
+ /*!
+ * Set receive window C channel
+ *
+ * LoRaWAN Specification V1.0.2, chapter 3.3.1
+ */
+ MIB_RXC_CHANNEL,
+ /*!
+ * Set receive window C channel
+ *
+ * LoRaWAN Specification V1.0.2, chapter 3.3.2
+ */
+ MIB_RXC_DEFAULT_CHANNEL,
/*!
* LoRaWAN channels mask
*
@@ -1293,7 +1536,7 @@ typedef enum eMib
*
* LoRaWAN Specification V1.0.2, chapter 5.2
*/
- MIB_CHANNELS_NB_REP,
+ MIB_CHANNELS_NB_TRANS,
/*!
* Maximum receive window duration in [ms]
*
@@ -1357,25 +1600,7 @@ typedef enum eMib
*/
MIB_CHANNELS_DEFAULT_TX_POWER,
/*!
- * LoRaWAN Up-link counter
- *
- * LoRaWAN Specification V1.0.2, chapter 4.3.1.5
- */
- MIB_UPLINK_COUNTER,
- /*!
- * LoRaWAN Down-link counter
- *
- * LoRaWAN Specification V1.0.2, chapter 4.3.1.5
- */
- MIB_DOWNLINK_COUNTER,
- /*!
- * Multicast channels. A get request will return a pointer to the first
- * entry of the multicast channel linked list. If the pointer is equal to
- * NULL, the list is empty.
- */
- MIB_MULTICAST_CHANNEL,
- /*!
- * System overall timing error in milliseconds.
+ * System overall timing error in milliseconds.
* [-SystemMaxRxError : +SystemMaxRxError]
* Default: +/-10 ms
*/
@@ -1390,8 +1615,89 @@ typedef enum eMib
* The antenna gain is used to calculate the TX power of the node.
* The formula is:
* radioTxPower = ( int8_t )floor( maxEirp - antennaGain )
+ *
+ * \remark The antenna gain value is referenced to the isotropic antenna.
+ * The value is in dBi.
+ * MIB_ANTENNA_GAIN[dBi] = measuredAntennaGain[dBd] + 2.15
+ */
+ MIB_ANTENNA_GAIN,
+ /*!
+ * Default antenna gain of the node. Default value is region specific.
+ * The antenna gain is used to calculate the TX power of the node.
+ * The formula is:
+ * radioTxPower = ( int8_t )floor( maxEirp - antennaGain )
+ *
+ * \remark The antenna gain value is referenced to the isotropic antenna.
+ * The value is in dBi.
+ * MIB_DEFAULT_ANTENNA_GAIN[dBi] = measuredAntennaGain[dBd] + 2.15
+ */
+ MIB_DEFAULT_ANTENNA_GAIN,
+ /*!
+ * Structure holding pointers to internal contexts and its size
+ */
+ MIB_NVM_CTXS,
+ /*!
+ * LoRaWAN MAC layer operating version when activated by ABP.
+ */
+ MIB_ABP_LORAWAN_VERSION,
+ /*!
+ * Beacon interval in ms
+ */
+ MIB_BEACON_INTERVAL,
+ /*!
+ * Beacon reserved time in ms
+ */
+ MIB_BEACON_RESERVED,
+ /*!
+ * Beacon guard time in ms
+ */
+ MIB_BEACON_GUARD,
+ /*!
+ * Beacon window time in ms
+ */
+ MIB_BEACON_WINDOW,
+ /*!
+ * Beacon window time in number of slots
+ */
+ MIB_BEACON_WINDOW_SLOTS,
+ /*!
+ * Ping slot length time in ms
+ */
+ MIB_PING_SLOT_WINDOW,
+ /*!
+ * Default symbol timeout for beacons and ping slot windows
+ */
+ MIB_BEACON_SYMBOL_TO_DEFAULT,
+ /*!
+ * Maximum symbol timeout for beacons
+ */
+ MIB_BEACON_SYMBOL_TO_EXPANSION_MAX,
+ /*!
+ * Maximum symbol timeout for ping slots
+ */
+ MIB_PING_SLOT_SYMBOL_TO_EXPANSION_MAX,
+ /*!
+ * Symbol expansion value for beacon windows in case of beacon
+ * loss in symbols
+ */
+ MIB_BEACON_SYMBOL_TO_EXPANSION_FACTOR,
+ /*!
+ * Symbol expansion value for ping slot windows in case of beacon
+ * loss in symbols
+ */
+ MIB_PING_SLOT_SYMBOL_TO_EXPANSION_FACTOR,
+ /*!
+ * Maximum allowed beacon less time in ms
+ */
+ MIB_MAX_BEACON_LESS_PERIOD,
+ /*!
+ * Ping slot data rate
+ *
+ * LoRaWAN Regional Parameters V1.0.2rB
+ *
+ * The allowed ranges are region specific. Please refer to \ref DR_0 to \ref DR_15 for details.
*/
- MIB_ANTENNA_GAIN
+ MIB_PING_SLOT_DATARATE,
}Mib_t;
/*!
@@ -1412,11 +1718,17 @@ typedef union uMibParam
*/
ActivationType_t NetworkActivation;
/*!
- * LoRaWAN network joined attribute
+ * LoRaWAN device class
+ *
+ * Related MIB type: \ref MIB_DEV_EUI
+ */
+ uint8_t* DevEui;
+ /*!
+ * LoRaWAN device class
*
- * Related MIB type: \ref MIB_NETWORK_JOINED
+ * Related MIB type: \ref MIB_JOIN_EUI
*/
- bool IsNetworkJoined;
+ uint8_t* JoinEui;
/*!
* Activation state of ADR
*
@@ -1436,17 +1748,137 @@ typedef union uMibParam
*/
uint32_t DevAddr;
/*!
- * Network session key
+ * Application root key - 1.0.x device only
+ *
+ * Related MIB type: \ref MIB_GEN_APP_KEY
+ */
+ uint8_t* GenAppKey;
+ /*!
+ * Application root key
+ *
+ * Related MIB type: \ref MIB_APP_KEY
+ */
+ uint8_t* AppKey;
+ /*!
+ * Network root key
+ *
+ * Related MIB type: \ref MIB_NWK_KEY
+ */
+ uint8_t* NwkKey;
+ /*!
+ * Join session integrity key
+ *
+ * Related MIB type: \ref MIB_J_S_INT_KEY
+ */
+ uint8_t* JSIntKey;
+ /*!
+ * Join session encryption key
+ *
+ * Related MIB type: \ref MIB_J_S_ENC_KEY
+ */
+ uint8_t* JSEncKey;
+ /*!
+ * Forwarding Network session integrity key
*
- * Related MIB type: \ref MIB_NWK_SKEY
+ * Related MIB type: \ref MIB_F_NWK_S_INT_KEY
*/
- uint8_t *NwkSKey;
+ uint8_t* FNwkSIntKey;
+ /*!
+ * Serving Network session integrity key
+ *
+ * Related MIB type: \ref MIB_S_NWK_S_INT_KEY
+ */
+ uint8_t* SNwkSIntKey;
+ /*!
+ * Network session encryption key
+ *
+ * Related MIB type: \ref MIB_NWK_S_ENC_KEY
+ */
+ uint8_t* NwkSEncKey;
/*!
* Application session key
*
- * Related MIB type: \ref MIB_APP_SKEY
+ * Related MIB type: \ref MIB_APP_S_KEY
+ */
+ uint8_t* AppSKey;
+ /*!
+ * Multicast key encryption key
+ *
+ * Related MIB type: \ref MIB_MC_KE_KEY
*/
- uint8_t *AppSKey;
+ uint8_t* McKEKey;
+ /*!
+ * Multicast root key index 0
+ *
+ * Related MIB type: \ref MIB_MC_KEY_0
+ */
+ uint8_t* McKey0;
+ /*!
+ * Multicast Application session key index 0
+ *
+ * Related MIB type: \ref MIB_MC_APP_S_KEY_0
+ */
+ uint8_t* McAppSKey0;
+ /*!
+ * Multicast Network session key index 0
+ *
+ * Related MIB type: \ref MIB_MC_NWK_S_KEY_0
+ */
+ uint8_t* McNwkSKey0;
+ /*!
+ * Multicast root key index 0
+ *
+ * Related MIB type: \ref MIB_MC_KEY_0
+ */
+ uint8_t* McKey1;
+ /*!
+ * Multicast Application session key index 1
+ *
+ * Related MIB type: \ref MIB_MC_APP_S_KEY_1
+ */
+ uint8_t* McAppSKey1;
+ /*!
+ * Multicast Network session key index 1
+ *
+ * Related MIB type: \ref MIB_MC_NWK_S_KEY_1
+ */
+ uint8_t* McNwkSKey1;
+ /*!
+ * Multicast root key index 2
+ *
+ * Related MIB type: \ref MIB_MC_KEY_2
+ */
+ uint8_t* McKey2;
+ /*!
+ * Multicast Application session key index 2
+ *
+ * Related MIB type: \ref MIB_MC_APP_S_KEY_2
+ */
+ uint8_t* McAppSKey2;
+ /*!
+ * Multicast Network session key index 2
+ *
+ * Related MIB type: \ref MIB_MC_NWK_S_KEY_2
+ */
+ uint8_t* McNwkSKey2;
+ /*!
+ * Multicast root key index 2
+ *
+ * Related MIB type: \ref MIB_MC_KEY_2
+ */
+ uint8_t* McKey3;
+ /*!
+ * Multicast Application session key index 2
+ *
+ * Related MIB type: \ref MIB_MC_APP_S_KEY_2
+ */
+ uint8_t* McAppSKey3;
+ /*!
+ * Multicast Network session key index 2
+ *
+ * Related MIB type: \ref MIB_MC_NWK_S_KEY_2
+ */
+ uint8_t* McNwkSKey3;
/*!
* Enable or disable a public network
*
@@ -1465,18 +1897,30 @@ typedef union uMibParam
* Related MIB type: \ref MIB_CHANNELS
*/
ChannelParams_t* ChannelList;
- /*!
+ /*!
* Channel for the receive window 2
*
* Related MIB type: \ref MIB_RX2_CHANNEL
*/
- Rx2ChannelParams_t Rx2Channel;
- /*!
+ RxChannelParams_t Rx2Channel;
+ /*!
* Channel for the receive window 2
*
* Related MIB type: \ref MIB_RX2_DEFAULT_CHANNEL
*/
- Rx2ChannelParams_t Rx2DefaultChannel;
+ RxChannelParams_t Rx2DefaultChannel;
+ /*!
+ * Channel for the receive window C
+ *
+ * Related MIB type: \ref MIB_RXC_CHANNEL
+ */
+ RxChannelParams_t RxCChannel;
+ /*!
+ * Channel for the receive window C
+ *
+ * Related MIB type: \ref MIB_RXC_DEFAULT_CHANNEL
+ */
+ RxChannelParams_t RxCDefaultChannel;
/*!
* Channel mask
*
@@ -1492,9 +1936,9 @@ typedef union uMibParam
/*!
* Number of frame repetitions
*
- * Related MIB type: \ref MIB_CHANNELS_NB_REP
+ * Related MIB type: \ref MIB_CHANNELS_NB_TRANS
*/
- uint8_t ChannelNbRep;
+ uint8_t ChannelsNbTrans;
/*!
* Maximum receive window duration
*
@@ -1550,25 +1994,13 @@ typedef union uMibParam
*/
int8_t ChannelsTxPower;
/*!
- * LoRaWAN Up-link counter
- *
- * Related MIB type: \ref MIB_UPLINK_COUNTER
- */
- uint32_t UpLinkCounter;
- /*!
- * LoRaWAN Down-link counter
- *
- * Related MIB type: \ref MIB_DOWNLINK_COUNTER
- */
- uint32_t DownLinkCounter;
- /*!
- * Multicast channel
+ * Multicast channels
*
* Related MIB type: \ref MIB_MULTICAST_CHANNEL
*/
- MulticastParams_t* MulticastList;
+ McChannelParams_t MulticastChannel;
/*!
- * System overall timing error in milliseconds.
+ * System overall timing error in milliseconds.
*
* Related MIB type: \ref MIB_SYSTEM_MAX_RX_ERROR
*/
@@ -1585,6 +2017,104 @@ typedef union uMibParam
* Related MIB type: \ref MIB_ANTENNA_GAIN
*/
float AntennaGain;
+ /*!
+ * Default antenna gain
+ *
+ * Related MIB type: \ref MIB_DEFAULT_ANTENNA_GAIN
+ */
+ float DefaultAntennaGain;
+ /*!
+ * Structure holding pointers to internal non-volatile contexts and its lengths.
+ *
+ * Related MIB type: \ref MIB_NVM_CTXS
+ */
+ LoRaMacCtxs_t* Contexts;
+ /*
+ * LoRaWAN MAC layer operating version when activated by ABP.
+ *
+ * Related MIB type: \ref MIB_ABP_LORAWAN_VERSION
+ */
+ Version_t AbpLrWanVersion;
+ /*!
+ * Beacon interval in ms
+ *
+ * Related MIB type: \ref MIB_BEACON_INTERVAL
+ */
+ uint32_t BeaconInterval;
+ /*!
+ * Beacon reserved time in ms
+ *
+ * Related MIB type: \ref MIB_BEACON_RESERVED
+ */
+ uint32_t BeaconReserved;
+ /*!
+ * Beacon guard time in ms
+ *
+ * Related MIB type: \ref MIB_BEACON_GUARD
+ */
+ uint32_t BeaconGuard;
+ /*!
+ * Beacon window time in ms
+ *
+ * Related MIB type: \ref MIB_BEACON_WINDOW
+ */
+ uint32_t BeaconWindow;
+ /*!
+ * Beacon window time in number of slots
+ *
+ * Related MIB type: \ref MIB_BEACON_WINDOW_SLOTS
+ */
+ uint32_t BeaconWindowSlots;
+ /*!
+ * Ping slot length time in ms
+ *
+ * Related MIB type: \ref MIB_PING_SLOT_WINDOW
+ */
+ uint32_t PingSlotWindow;
+ /*!
+ * Default symbol timeout for beacons and ping slot windows
+ *
+ * Related MIB type: \ref MIB_BEACON_SYMBOL_TO_DEFAULT
+ */
+ uint32_t BeaconSymbolToDefault;
+ /*!
+ * Maximum symbol timeout for beacons
+ *
+ * Related MIB type: \ref MIB_BEACON_SYMBOL_TO_EXPANSION_MAX
+ */
+ uint32_t BeaconSymbolToExpansionMax;
+ /*!
+ * Maximum symbol timeout for ping slots
+ *
+ * Related MIB type: \ref MIB_PING_SLOT_SYMBOL_TO_EXPANSION_MAX
+ */
+ uint32_t PingSlotSymbolToExpansionMax;
+ /*!
+ * Symbol expansion value for beacon windows in case of beacon
+ * loss in symbols
+ *
+ * Related MIB type: \ref MIB_BEACON_SYMBOL_TO_EXPANSION_FACTOR
+ */
+ uint32_t BeaconSymbolToExpansionFactor;
+ /*!
+ * Symbol expansion value for ping slot windows in case of beacon
+ * loss in symbols
+ *
+ * Related MIB type: \ref MIB_PING_SLOT_SYMBOL_TO_EXPANSION_FACTOR
+ */
+ uint32_t PingSlotSymbolToExpansionFactor;
+ /*!
+ * Maximum allowed beacon less time in ms
+ *
+ * Related MIB type: \ref MIB_MAX_BEACON_LESS_PERIOD
+ */
+ uint32_t MaxBeaconLessPeriod;
+ /*!
+ * Ping slots data rate
+ *
+ * Related MIB type: \ref MIB_PING_SLOT_DATARATE
+ */
+ int8_t PingSlotDatarate;
}MibParam_t;
/*!
@@ -1609,13 +2139,14 @@ typedef struct eMibRequestConfirm
typedef struct sLoRaMacTxInfo
{
/*!
- * Defines the size of the applicative payload which can be processed
+ * Size of the application data payload which can be transmitted.
*/
- uint8_t MaxPossiblePayload;
+ uint8_t MaxPossibleApplicationDataSize;
/*!
- * The current payload size, dependent on the current datarate
+ * The current maximum possible payload size without MAC commands
+ * which is dependent on the current datarate.
*/
- uint8_t CurrentPayloadSize;
+ uint8_t CurrentPossiblePayloadSize;
}LoRaMacTxInfo_t;
/*!
@@ -1659,15 +2190,68 @@ typedef enum eLoRaMacStatus
* Service not started - payload length error
*/
LORAMAC_STATUS_LENGTH_ERROR,
- /*!
- * Service not started - the device is switched off
- */
- LORAMAC_STATUS_DEVICE_OFF,
/*!
* Service not started - the specified region is not supported
* or not activated with preprocessor definitions.
*/
- LORAMAC_STATUS_REGION_NOT_SUPPORTED
+ LORAMAC_STATUS_REGION_NOT_SUPPORTED,
+ /*!
+ * The application data was not transmitted
+ * because prioritized pending MAC commands had to be sent.
+ */
+ LORAMAC_STATUS_SKIPPED_APP_DATA,
+ /*!
+ * ToDo
+ */
+ LORAMAC_STATUS_DUTYCYCLE_RESTRICTED,
+ /*!
+ *
+ */
+ LORAMAC_STATUS_NO_CHANNEL_FOUND,
+ /*!
+ *
+ */
+ LORAMAC_STATUS_NO_FREE_CHANNEL_FOUND,
+ /*!
+ * ToDo
+ */
+ LORAMAC_STATUS_BUSY_BEACON_RESERVED_TIME,
+ /*!
+ * ToDo
+ */
+ LORAMAC_STATUS_BUSY_PING_SLOT_WINDOW_TIME,
+ /*!
+ * ToDo
+ */
+ LORAMAC_STATUS_BUSY_UPLINK_COLLISION,
+ /*!
+ * An error in the cryptographic module is occurred
+ */
+ LORAMAC_STATUS_CRYPTO_ERROR,
+ /*!
+ * An error in the frame counter handler module is occurred
+ */
+ LORAMAC_STATUS_FCNT_HANDLER_ERROR,
+ /*!
+ * An error in the MAC command module is occurred
+ */
+ LORAMAC_STATUS_MAC_COMMAD_ERROR,
+ /*!
+ * An error in the Class B module is occurred
+ */
+ LORAMAC_STATUS_CLASS_B_ERROR,
+ /*!
+ * An error in the Confirm Queue module is occurred
+ */
+ LORAMAC_STATUS_CONFIRM_QUEUE_ERROR,
+ /*!
+ * The multicast group doesn't exist
+ */
+ LORAMAC_STATUS_MC_GROUP_UNDEFINED,
+ /*!
+ * Undefined error occurred
+ */
+ LORAMAC_STATUS_ERROR
}LoRaMacStatus_t;
/*!
@@ -1712,15 +2296,46 @@ typedef enum eLoRaMacRegion_t
*/
LORAMAC_REGION_US915,
/*!
- * North american band on 915MHz with a maximum of 16 channels
+ * Russia band on 864MHz
*/
- LORAMAC_REGION_US915_HYBRID,
+ LORAMAC_REGION_RU864,
+}LoRaMacRegion_t;
+/*!
+ * Enumeration of modules which have a context
+ */
+typedef enum LoRaMacNvmCtxModule_e
+{
/*!
- * Invalid region
+ * Context for the MAC
*/
- LORAMAC_REGION_MAX
-}LoRaMacRegion_t;
+ LORAMAC_NVMCTXMODULE_MAC,
+ /*!
+ * Context for the regions
+ */
+ LORAMAC_NVMCTXMODULE_REGION,
+ /*!
+ * Context for the crypto module
+ */
+ LORAMAC_NVMCTXMODULE_CRYPTO,
+ /*!
+ * Context for the secure element
+ */
+ LORAMAC_NVMCTXMODULE_SECURE_ELEMENT,
+ /*!
+ * Context for the command queue
+ */
+ LORAMAC_NVMCTXMODULE_COMMANDS,
+ /*!
+ * Context for class b
+ */
+ LORAMAC_NVMCTXMODULE_CLASS_B,
+ /*!
+ * Context for the confirm queue
+ */
+ LORAMAC_NVMCTXMODULE_CONFIRM_QUEUE,
+}LoRaMacNvmCtxModule_t;
+
/*!
* LoRaMAC events structure
@@ -1733,25 +2348,25 @@ typedef struct sLoRaMacPrimitives
*
* \param [OUT] MCPS-Confirm parameters
*/
- void ( *MacMcpsConfirm )( McpsConfirm_t *McpsConfirm );
+ void ( *MacMcpsConfirm )( McpsConfirm_t* McpsConfirm );
/*!
* \brief MCPS-Indication primitive
*
* \param [OUT] MCPS-Indication parameters
*/
- void ( *MacMcpsIndication )( McpsIndication_t *McpsIndication );
+ void ( *MacMcpsIndication )( McpsIndication_t* McpsIndication );
/*!
* \brief MLME-Confirm primitive
*
* \param [OUT] MLME-Confirm parameters
*/
- void ( *MacMlmeConfirm )( MlmeConfirm_t *MlmeConfirm );
+ void ( *MacMlmeConfirm )( MlmeConfirm_t* MlmeConfirm );
/*!
* \brief MLME-Indication primitive
*
* \param [OUT] MLME-Indication parameters
*/
- void ( *MacMlmeIndication )( MlmeIndication_t *MlmeIndication );
+ void ( *MacMlmeIndication )( MlmeIndication_t* MlmeIndication );
}LoRaMacPrimitives_t;
/*!
@@ -1768,15 +2383,33 @@ typedef struct sLoRaMacCallback
* to measure the battery level]
*/
uint8_t ( *GetBatteryLevel )( void );
+ /*!
+ * \brief Measures the temperature level
+ *
+ * \retval Temperature level
+ */
+ float ( *GetTemperatureLevel )( void );
+ /*!
+ * \brief Will be called when an attribute has changed in one of the context.
+ *
+ * \param Context that changed
+ */
+ void ( *NvmContextChange )( LoRaMacNvmCtxModule_t module );
+ /*!
+ *\brief Will be called each time a Radio IRQ is handled by the MAC
+ * layer.
+ *
+ *\warning Runs in a IRQ context. Should only change variables state.
+ */
+ void ( *MacProcessNotify )( void );
}LoRaMacCallback_t;
+
/*!
* LoRaMAC Max EIRP (dBm) table
*/
static const uint8_t LoRaMacMaxEirpTable[] = { 8, 10, 12, 13, 14, 16, 18, 20, 21, 24, 26, 27, 29, 30, 33, 36 };
-
-
/*!
* \brief LoRaMAC layer initialization
*
@@ -1788,10 +2421,10 @@ static const uint8_t LoRaMacMaxEirpTable[] = { 8, 10, 12, 13, 14, 16, 18, 20, 21
* \param [IN] primitives - Pointer to a structure defining the LoRaMAC
* event functions. Refer to \ref LoRaMacPrimitives_t.
*
- * \param [IN] events - Pointer to a structure defining the LoRaMAC
- * callback functions. Refer to \ref LoRaMacCallback_t.
+ * \param [IN] callbacks - Pointer to a structure defining the LoRaMAC
+ * callback functions. Refer to \ref LoRaMacCallback_t.
*
- * \param [IN] region - The region to start.
+ * \param [IN] region - The region to start.
*
* \retval LoRaMacStatus_t Status of the operation. Possible returns are:
* returns are:
@@ -1799,14 +2432,46 @@ static const uint8_t LoRaMacMaxEirpTable[] = { 8, 10, 12, 13, 14, 16, 18, 20, 21
* \ref LORAMAC_STATUS_PARAMETER_INVALID,
* \ref LORAMAC_STATUS_REGION_NOT_SUPPORTED.
*/
-LoRaMacStatus_t LoRaMacInitialization( LoRaMacPrimitives_t *primitives, LoRaMacCallback_t *callbacks, LoRaMacRegion_t region );
+LoRaMacStatus_t LoRaMacInitialization( LoRaMacPrimitives_t* primitives, LoRaMacCallback_t* callbacks, LoRaMacRegion_t region );
+
+/*!
+ * \brief Starts LoRaMAC layer
+ *
+ * \retval LoRaMacStatus_t Status of the operation. Possible returns are:
+ * returns are:
+ * \ref LORAMAC_STATUS_OK,
+ */
+LoRaMacStatus_t LoRaMacStart( void );
+
+/*!
+ * \brief Stops LoRaMAC layer
+ *
+ * \retval LoRaMacStatus_t Status of the operation. Possible returns are:
+ * returns are:
+ * \ref LORAMAC_STATUS_OK,
+ */
+LoRaMacStatus_t LoRaMacStop( void );
+
+/*!
+ * \brief Returns a value indicating if the MAC layer is busy or not.
+ *
+ * \retval isBusy Mac layer is busy.
+ */
+bool LoRaMacIsBusy( void );
+
+/*!
+ * Processes the LoRaMac events.
+ *
+ * \remark This function must be called in the main loop.
+ */
+void LoRaMacProcess( void );
/*!
* \brief Queries the LoRaMAC if it is possible to send the next frame with
- * a given payload size. The LoRaMAC takes scheduled MAC commands into
- * account and reports, when the frame can be send or not.
+ * a given application data payload size. The LoRaMAC takes scheduled
+ * MAC commands into account and reports, when the frame can be send or not.
*
- * \param [IN] size - Size of applicative payload to be send next
+ * \param [IN] size - Size of application data payload to be send next
*
* \param [OUT] txInfo - The structure \ref LoRaMacTxInfo_t contains
* information about the actual maximum payload possible
@@ -1816,11 +2481,13 @@ LoRaMacStatus_t LoRaMacInitialization( LoRaMacPrimitives_t *primitives, LoRaMacC
*
* \retval LoRaMacStatus_t Status of the operation. When the parameters are
* not valid, the function returns \ref LORAMAC_STATUS_PARAMETER_INVALID.
- * In case of a length error caused by the applicative payload in combination
+ * In case of a length error caused by the application data payload in combination
* with the MAC commands, the function returns \ref LORAMAC_STATUS_LENGTH_ERROR.
- * Please note that if the size of the MAC commands which are in the queue do
- * not fit into the payload size on the related datarate, the LoRaMAC will
- * omit the MAC commands.
+ * In this case its recommended to send a frame without application data to flush
+ * the MAC commands. Otherwise the LoRaMAC will prioritize the MAC commands and
+ * if needed it will skip the application data. Please note that if MAC commands do
+ * not fit at all into the payload size on the related datarate, the LoRaMAC will
+ * automatically clip the MAC commands.
* In case the query is valid, and the LoRaMAC is able to send the frame,
* the function returns \ref LORAMAC_STATUS_OK.
*/
@@ -1859,44 +2526,60 @@ LoRaMacStatus_t LoRaMacChannelAdd( uint8_t id, ChannelParams_t params );
LoRaMacStatus_t LoRaMacChannelRemove( uint8_t id );
/*!
- * \brief LoRaMAC multicast channel link service
+ * \brief LoRaMAC multicast channel setup service
*
- * \details Links a multicast channel into the linked list.
+ * \details Sets up a multicast channel.
*
- * \param [IN] channelParam - Multicast channel parameters to link.
+ * \param [IN] channel - Multicast channel to set.
*
* \retval LoRaMacStatus_t Status of the operation. Possible returns are:
* \ref LORAMAC_STATUS_OK,
* \ref LORAMAC_STATUS_BUSY,
- * \ref LORAMAC_STATUS_PARAMETER_INVALID.
+ * \ref LORAMAC_STATUS_PARAMETER_INVALID,
+ * \ref LORAMAC_STATUS_MC_GROUP_UNDEFINED.
*/
-LoRaMacStatus_t LoRaMacMulticastChannelLink( MulticastParams_t *channelParam );
+LoRaMacStatus_t LoRaMacMcChannelSetup( McChannelParams_t *channel );
/*!
- * \brief LoRaMAC multicast channel unlink service
+ * \brief LoRaMAC multicast channel removal service
*
- * \details Unlinks a multicast channel from the linked list.
+ * \details Removes/Disables a multicast channel.
*
- * \param [IN] channelParam - Multicast channel parameters to unlink.
+ * \param [IN] groupID - Multicast channel ID to be removed/disabled
*
* \retval LoRaMacStatus_t Status of the operation. Possible returns are:
* \ref LORAMAC_STATUS_OK,
* \ref LORAMAC_STATUS_BUSY,
- * \ref LORAMAC_STATUS_PARAMETER_INVALID.
+ * \ref LORAMAC_STATUS_MC_GROUP_UNDEFINED.
*/
-LoRaMacStatus_t LoRaMacMulticastChannelUnlink( MulticastParams_t *channelParam );
+LoRaMacStatus_t LoRaMacMcChannelDelete( AddressIdentifier_t groupID );
/*!
- * \brief LoRaMAC multicast get channel
+ * \brief LoRaMAC multicast channel get groupId from MC address.
*
- * \details Gets the specified multicast channel from the linked list.
+ * \param [IN] mcAddress - Multicast address to be checked
*
- * \param [IN] multicastAddr - Address of the Multicast channel.
- *
- * \retval MulticastParams_t * Pointer to the multicast channel.
+ * \retval groupID Multicast channel ID associated to the address.
+ * Returns 0xFF if the address isn't found.
*/
+uint8_t LoRaMacMcChannelGetGroupId( uint32_t mcAddress );
-MulticastParams_t * LoRaMacMulticastGetChannel(uint32_t multicastAddr);
+/*!
+ * \brief LoRaMAC multicast channel Rx parameters setup service
+ *
+ * \details Sets up a multicast channel reception parameters.
+ *
+ * \param [IN] groupID - Multicast channel ID
+ * \param [IN] rxParams - Reception parameters
+ * \param [OUT] status - Status mask [UNDEF_ID | FREQ_ERR | DR_ERR | GROUP_ID]
+ *
+ * \retval LoRaMacStatus_t Status of the operation. Possible returns are:
+ * \ref LORAMAC_STATUS_OK,
+ * \ref LORAMAC_STATUS_BUSY,
+ * \ref LORAMAC_STATUS_PARAMETER_INVALID,
+ * \ref LORAMAC_STATUS_MC_GROUP_UNDEFINED.
+ */
+LoRaMacStatus_t LoRaMacMcChannelSetupRxParams( AddressIdentifier_t groupID, McRxParams_t *rxParams, uint8_t *status );
/*!
* \brief LoRaMAC MIB-Get
@@ -1924,7 +2607,7 @@ MulticastParams_t * LoRaMacMulticastGetChannel(uint32_t multicastAddr);
* \ref LORAMAC_STATUS_SERVICE_UNKNOWN,
* \ref LORAMAC_STATUS_PARAMETER_INVALID.
*/
-LoRaMacStatus_t LoRaMacMibGetRequestConfirm( MibRequestConfirm_t *mibGet );
+LoRaMacStatus_t LoRaMacMibGetRequestConfirm( MibRequestConfirm_t* mibGet );
/*!
* \brief LoRaMAC MIB-Set
@@ -1955,35 +2638,22 @@ LoRaMacStatus_t LoRaMacMibGetRequestConfirm( MibRequestConfirm_t *mibGet );
* \ref LORAMAC_STATUS_SERVICE_UNKNOWN,
* \ref LORAMAC_STATUS_PARAMETER_INVALID.
*/
-LoRaMacStatus_t LoRaMacMibSetRequestConfirm( MibRequestConfirm_t *mibSet );
+LoRaMacStatus_t LoRaMacMibSetRequestConfirm( MibRequestConfirm_t* mibSet );
/*!
* \brief LoRaMAC MLME-Request
*
* \details The Mac layer management entity handles management services. The
* following code-snippet shows how to use the API to perform a
- * network join request.
+ * network join request. Please note that for a join request, the
+ * DevEUI and the JoinEUI must be set previously via the MIB. Please
+ * also refer to the sample implementations.
*
* \code
- * static uint8_t DevEui[] =
- * {
- * 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
- * };
- * static uint8_t AppEui[] =
- * {
- * 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
- * };
- * static uint8_t AppKey[] =
- * {
- * 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,
- * 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C
- * };
*
* MlmeReq_t mlmeReq;
* mlmeReq.Type = MLME_JOIN;
- * mlmeReq.Req.Join.DevEui = DevEui;
- * mlmeReq.Req.Join.AppEui = AppEui;
- * mlmeReq.Req.Join.AppKey = AppKey;
+ * mlmeReq.Req.Join.Datarate = LORAWAN_DEFAULT_DATARATE;
*
* if( LoRaMacMlmeRequest( &mlmeReq ) == LORAMAC_STATUS_OK )
* {
@@ -2000,9 +2670,8 @@ LoRaMacStatus_t LoRaMacMibSetRequestConfirm( MibRequestConfirm_t *mibSet );
* \ref LORAMAC_STATUS_PARAMETER_INVALID,
* \ref LORAMAC_STATUS_NO_NETWORK_JOINED,
* \ref LORAMAC_STATUS_LENGTH_ERROR,
- * \ref LORAMAC_STATUS_DEVICE_OFF.
*/
-LoRaMacStatus_t LoRaMacMlmeRequest( MlmeReq_t *mlmeRequest );
+LoRaMacStatus_t LoRaMacMlmeRequest( MlmeReq_t* mlmeRequest );
/*!
* \brief LoRaMAC MCPS-Request
@@ -2035,9 +2704,20 @@ LoRaMacStatus_t LoRaMacMlmeRequest( MlmeReq_t *mlmeRequest );
* \ref LORAMAC_STATUS_PARAMETER_INVALID,
* \ref LORAMAC_STATUS_NO_NETWORK_JOINED,
* \ref LORAMAC_STATUS_LENGTH_ERROR,
- * \ref LORAMAC_STATUS_DEVICE_OFF.
*/
-LoRaMacStatus_t LoRaMacMcpsRequest( McpsReq_t *mcpsRequest );
+LoRaMacStatus_t LoRaMacMcpsRequest( McpsReq_t* mcpsRequest );
+
+/*!
+ * Automatically add the Region.h file at the end of LoRaMac.h file.
+ * This is required because Region.h uses definitions from LoRaMac.h
+ */
+#include "region/Region.h"
+
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+//////////////////////// PYCOM FUNCTION DECLARATIONS //////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
/*!
* \brief Validates if the payload fits into the frame, taking the datarate
@@ -2055,34 +2735,15 @@ LoRaMacStatus_t LoRaMacMcpsRequest( McpsReq_t *mcpsRequest );
* \retval [false: payload does not fit into the frame, true: payload fits into
* the frame]
*/
+// Pycom: This function declaration was moved to header to be used outside LoRaMac
bool ValidatePayloadLength( uint8_t lenN, int8_t datarate, uint8_t fOptsLen );
void LoRaMacNvsSave( void );
-void LoRaMacGetChannelList(ChannelParams_t **channels, uint32_t *size);
-
-bool LoRaMacGetChannelsMask(uint16_t **channelmask, uint32_t *size);
-
-bool LoRaMacGetChannelsMaskRemaining(uint16_t **channelmask, uint32_t *size);
-
-LoRaMacParams_t * LoRaMacGetMacParams(void);
-
-bool * LoRaMacGetSrvAckRequested(void);
-
-bool * LoRaMacGetMacCmdNextTx(void);
-
-uint8_t * LoRaMacGetMacCmdBufferIndex(void);
-
-uint8_t * LoRaMacGetMacCmdBufferRepeatIndex(void);
-
-uint8_t * LoRaMacGetMacCmdBuffer(void);
-
-uint8_t * LoRaMacGetMacCmdBufferRepeat(void);
-
-uint8_t * LoRaMacGetMacCmdBufferRepeat(void);
-
-uint32_t * LoRaMacGetAdrAckCounter(void);
-
/*! \} defgroup LORAMAC */
+#ifdef __cplusplus
+}
+#endif
+
#endif // __LORAMAC_H__
diff --git a/lib/lora/mac/LoRaMacAdr.c b/lib/lora/mac/LoRaMacAdr.c
new file mode 100644
index 0000000000..5d0a3e0135
--- /dev/null
+++ b/lib/lora/mac/LoRaMacAdr.c
@@ -0,0 +1,130 @@
+/*!
+ * \file LoRaMacAdr.c
+ *
+ * \brief LoRa MAC ADR implementation
+ *
+ * \copyright Revised BSD License, see section \ref LICENSE.
+ *
+ * \code
+ * ______ _
+ * / _____) _ | |
+ * ( (____ _____ ____ _| |_ _____ ____| |__
+ * \____ \| ___ | (_ _) ___ |/ ___) _ \
+ * _____) ) ____| | | || |_| ____( (___| | | |
+ * (______/|_____)_|_|_| \__)_____)\____)_| |_|
+ * (C)2013-2017 Semtech
+ *
+ * ___ _____ _ ___ _ _____ ___ ___ ___ ___
+ * / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
+ * \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
+ * |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
+ * embedded.connectivity.solutions===============
+ *
+ * \endcode
+ *
+ * \author Miguel Luis ( Semtech )
+ *
+ * \author Gregory Cristian ( Semtech )
+ *
+ * \author Daniel Jaeckle ( STACKFORCE )
+ *
+ * \author Johannes Bruder ( STACKFORCE )
+ */
+
+#include "region/Region.h"
+#include "LoRaMacAdr.h"
+
+static bool CalcNextV10X( CalcNextAdrParams_t* adrNext, int8_t* drOut, int8_t* txPowOut, uint32_t* adrAckCounter )
+{
+ bool adrAckReq = false;
+ int8_t datarate = adrNext->Datarate;
+ int8_t txPower = adrNext->TxPower;
+ int8_t minTxDatarate;
+ GetPhyParams_t getPhy;
+ PhyParam_t phyParam;
+
+ // Report back the adr ack counter
+ *adrAckCounter = adrNext->AdrAckCounter;
+
+ if( adrNext->AdrEnabled == true )
+ {
+ // Query minimum TX Datarate
+ getPhy.Attribute = PHY_MIN_TX_DR;
+ getPhy.UplinkDwellTime = adrNext->UplinkDwellTime;
+ phyParam = RegionGetPhyParam( adrNext->Region, &getPhy );
+ minTxDatarate = phyParam.Value;
+ datarate = MAX( datarate, minTxDatarate );
+
+ if( datarate == minTxDatarate )
+ {
+ *adrAckCounter = 0;
+ adrAckReq = false;
+ }
+ else
+ {
+ if( adrNext->AdrAckCounter >= adrNext->AdrAckLimit )
+ {
+ adrAckReq = true;
+ }
+ else
+ {
+ adrAckReq = false;
+ }
+ if( adrNext->AdrAckCounter >= ( adrNext->AdrAckLimit + adrNext->AdrAckDelay ) )
+ {
+ // Set TX Power to maximum
+ getPhy.Attribute = PHY_MAX_TX_POWER;
+ phyParam = RegionGetPhyParam( adrNext->Region, &getPhy );
+ txPower = phyParam.Value;
+
+ if( ( adrNext->AdrAckCounter % adrNext->AdrAckDelay ) == 1 )
+ {
+ // Decrease the datarate
+ getPhy.Attribute = PHY_NEXT_LOWER_TX_DR;
+ getPhy.Datarate = datarate;
+ getPhy.UplinkDwellTime = adrNext->UplinkDwellTime;
+ phyParam = RegionGetPhyParam( adrNext->Region, &getPhy );
+ datarate = phyParam.Value;
+
+ if( datarate == minTxDatarate )
+ {
+ // We must set adrAckReq to false as soon as we reach the lowest datarate
+ adrAckReq = false;
+ if( adrNext->UpdateChanMask == true )
+ {
+ InitDefaultsParams_t params;
+ params.Type = INIT_TYPE_RESTORE_DEFAULT_CHANNELS;
+ RegionInitDefaults( adrNext->Region, ¶ms );
+ }
+ }
+ }
+ }
+ }
+ }
+
+ *drOut = datarate;
+ *txPowOut = txPower;
+ return adrAckReq;
+}
+
+/*!
+ * \brief Calculates the next datarate to set, when ADR is on or off.
+ *
+ * \param [IN] adrNext Pointer to the function parameters.
+ *
+ * \param [OUT] drOut The calculated datarate for the next TX.
+ *
+ * \param [OUT] txPowOut The TX power for the next TX.
+ *
+ * \param [OUT] adrAckCounter The calculated ADR acknowledgement counter.
+ *
+ * \retval Returns true, if an ADR request should be performed.
+ */
+bool LoRaMacAdrCalcNext( CalcNextAdrParams_t* adrNext, int8_t* drOut, int8_t* txPowOut, uint32_t* adrAckCounter )
+{
+ if( adrNext->Version.Fields.Minor == 0 )
+ {
+ return CalcNextV10X( adrNext, drOut, txPowOut, adrAckCounter );
+ }
+ return false;
+}
diff --git a/lib/lora/mac/LoRaMacAdr.h b/lib/lora/mac/LoRaMacAdr.h
new file mode 100644
index 0000000000..4e0ea87fcc
--- /dev/null
+++ b/lib/lora/mac/LoRaMacAdr.h
@@ -0,0 +1,113 @@
+/*!
+ * \file LoRaMacAdr.h
+ *
+ * \brief LoRa MAC ADR implementation
+ *
+ * \copyright Revised BSD License, see section \ref LICENSE.
+ *
+ * \code
+ * ______ _
+ * / _____) _ | |
+ * ( (____ _____ ____ _| |_ _____ ____| |__
+ * \____ \| ___ | (_ _) ___ |/ ___) _ \
+ * _____) ) ____| | | || |_| ____( (___| | | |
+ * (______/|_____)_|_|_| \__)_____)\____)_| |_|
+ * (C)2013-2017 Semtech
+ *
+ * ___ _____ _ ___ _ _____ ___ ___ ___ ___
+ * / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
+ * \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
+ * |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
+ * embedded.connectivity.solutions===============
+ *
+ * \endcode
+ *
+ * \author Miguel Luis ( Semtech )
+ *
+ * \author Gregory Cristian ( Semtech )
+ *
+ * \author Daniel Jaeckle ( STACKFORCE )
+ *
+ * \author Johannes Bruder ( STACKFORCE )
+ *
+ * \defgroup LORAMACADR LoRa MAC ADR implementation
+ * Implementation of the ADR algorithm for LoRa.
+ * \{
+ */
+#ifndef __LORAMACADR_H__
+#define __LORAMACADR_H__
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/*! \} defgroup LORAMACADR */
+
+/*
+ * Parameter structure for the function CalcNextAdr.
+ */
+typedef struct sCalcNextAdrParams
+{
+ /*!
+ * LoRaWAN Minor Version 1.X
+ */
+ Version_t Version;
+ /*!
+ * Set to true, if the function should update the channels mask.
+ */
+ bool UpdateChanMask;
+ /*!
+ * Set to true, if ADR is enabled.
+ */
+ bool AdrEnabled;
+ /*!
+ * ADR ack counter.
+ */
+ uint32_t AdrAckCounter;
+ /*!
+ * ADR Ack limit
+ */
+ uint16_t AdrAckLimit;
+ /*!
+ * ADR Ack delay
+ */
+ uint16_t AdrAckDelay;
+ /*!
+ * Datarate used currently.
+ */
+ int8_t Datarate;
+ /*!
+ * TX power used currently.
+ */
+ int8_t TxPower;
+ /*!
+ * UplinkDwellTime
+ */
+ uint8_t UplinkDwellTime;
+ /*!
+ * Region
+ */
+ LoRaMacRegion_t Region;
+}CalcNextAdrParams_t;
+
+/*!
+ * \brief Calculates the next datarate to set, when ADR is on or off.
+ *
+ * \param [IN] adrNext Pointer to the function parameters.
+ *
+ * \param [OUT] drOut The calculated datarate for the next TX.
+ *
+ * \param [OUT] txPowOut The TX power for the next TX.
+ *
+ * \param [OUT] adrAckCounter The calculated ADR acknowledgement counter.
+ *
+ * \retval Returns true, if an ADR request should be performed.
+ */
+bool LoRaMacAdrCalcNext( CalcNextAdrParams_t* adrNext, int8_t* drOut, int8_t* txPowOut, uint32_t* adrAckCounter );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // __LORAMACADR_H__
diff --git a/lib/lora/mac/LoRaMacClassB.c b/lib/lora/mac/LoRaMacClassB.c
new file mode 100644
index 0000000000..b04be9fbd5
--- /dev/null
+++ b/lib/lora/mac/LoRaMacClassB.c
@@ -0,0 +1,1767 @@
+/*
+ / _____) _ | |
+( (____ _____ ____ _| |_ _____ ____| |__
+ \____ \| ___ | (_ _) ___ |/ ___) _ \
+ _____) ) ____| | | || |_| ____( (___| | | |
+(______/|_____)_|_|_| \__)_____)\____)_| |_|
+ (C)2013 Semtech
+ ___ _____ _ ___ _ _____ ___ ___ ___ ___
+/ __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
+\__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
+|___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
+embedded.connectivity.solutions===============
+
+Description: LoRa MAC Class B layer implementation
+
+License: Revised BSD License, see LICENSE.TXT file include in the project
+
+Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jaeckle ( STACKFORCE )
+*/
+#include
+#include "utilities.h"
+#include "secure-element.h"
+#include "LoRaMac.h"
+#include "LoRaMacClassB.h"
+#include "LoRaMacClassBConfig.h"
+#include "LoRaMacCrypto.h"
+#include "LoRaMacConfirmQueue.h"
+
+#ifdef LORAMAC_CLASSB_ENABLED
+
+
+/*
+ * LoRaMac Class B Context structure for NVM parameters
+ * related to ping slots
+ */
+typedef struct sLoRaMacClassBPingSlotNvmCtx
+{
+ struct sPingSlotCtrlNvm
+ {
+ /*!
+ * Set when the server assigned a ping slot to the node
+ */
+ uint8_t Assigned : 1;
+ /*!
+ * Set when a custom frequency is used
+ */
+ uint8_t CustomFreq : 1;
+ }Ctrl;
+ /*!
+ * Number of ping slots
+ */
+ uint8_t PingNb;
+ /*!
+ * Period of the ping slots
+ */
+ uint16_t PingPeriod;
+ /*!
+ * Reception frequency of the ping slot windows
+ */
+ uint32_t Frequency;
+ /*!
+ * Datarate of the ping slot
+ */
+ int8_t Datarate;
+} LoRaMacClassBPingSlotNvmCtx_t;
+
+/*
+ * LoRaMac Class B Context structure for NVM parameters
+ * related to beaconing
+ */
+typedef struct sLoRaMacClassBBeaconNvmCtx
+{
+ struct sBeaconCtrlNvm
+ {
+ /*!
+ * Set if the node has a custom frequency for beaconing and ping slots
+ */
+ uint8_t CustomFreq : 1;
+ }Ctrl;
+ /*!
+ * Beacon reception frequency
+ */
+ uint32_t Frequency;
+} LoRaMacClassBBeaconNvmCtx_t;
+
+/*
+ * LoRaMac Class B Context structure
+ */
+typedef struct sLoRaMacClassBNvmCtx
+{
+ /*!
+ * Class B ping slot context
+ */
+ LoRaMacClassBPingSlotNvmCtx_t PingSlotCtx;
+ /*!
+ * Class B beacon context
+ */
+ LoRaMacClassBBeaconNvmCtx_t BeaconCtx;
+} LoRaMacClassBNvmCtx_t;
+
+/*
+ * LoRaMac Class B Context structure
+ */
+typedef struct sLoRaMacClassBCtx
+{
+ /*!
+ * Class B ping slot context
+ */
+ PingSlotContext_t PingSlotCtx;
+ /*!
+ * Class B beacon context
+ */
+ BeaconContext_t BeaconCtx;
+ /*!
+ * State of the beaconing mechanism
+ */
+ BeaconState_t BeaconState;
+ /*!
+ * State of the ping slot mechanism
+ */
+ PingSlotState_t PingSlotState;
+ /*!
+ * State of the multicast slot mechanism
+ */
+ PingSlotState_t MulticastSlotState;
+ /*!
+ * Timer for CLASS B beacon acquisition and tracking.
+ */
+ TimerEvent_t BeaconTimer;
+ /*!
+ * Timer for CLASS B ping slot timer.
+ */
+ TimerEvent_t PingSlotTimer;
+ /*!
+ * Timer for CLASS B multicast ping slot timer.
+ */
+ TimerEvent_t MulticastSlotTimer;
+ /*!
+ * Container for the callbacks related to class b.
+ */
+ LoRaMacClassBCallback_t LoRaMacClassBCallbacks;
+ /*!
+ * Data structure which holds the parameters which needs to be set
+ * in class b operation.
+ */
+ LoRaMacClassBParams_t LoRaMacClassBParams;
+ /*
+ * Callback function to notify the upper layer about context change
+ */
+ LoRaMacClassBNvmEvent LoRaMacClassBNvmEvent;
+ /*!
+ * Non-volatile module context.
+ */
+ LoRaMacClassBNvmCtx_t* NvmCtx;
+} LoRaMacClassBCtx_t;
+
+/*!
+ * Defines the LoRaMac radio events status
+ */
+typedef union uLoRaMacClassBEvents
+{
+ uint32_t Value;
+ struct sEvents
+ {
+ uint32_t Beacon : 1;
+ uint32_t PingSlot : 1;
+ uint32_t MulticastSlot : 1;
+ }Events;
+}LoRaMacClassBEvents_t;
+
+LoRaMacClassBEvents_t LoRaMacClassBEvents = { .Value = 0 };
+
+/*
+ * Non-volatile module context.
+ */
+static LoRaMacClassBNvmCtx_t NvmCtx;
+
+/*
+ * Module context.
+ */
+static LoRaMacClassBCtx_t Ctx;
+
+/*!
+ * Computes the Ping Offset
+ *
+ * \param [IN] beaconTime - Time of the recent received beacon
+ * \param [IN] address - Frame address
+ * \param [IN] pingPeriod - Ping period of the node
+ * \param [OUT] pingOffset - Pseudo random ping offset
+ */
+static void ComputePingOffset( uint64_t beaconTime, uint32_t address, uint16_t pingPeriod, uint16_t *pingOffset )
+{
+ uint8_t buffer[16];
+ uint8_t cipher[16];
+ uint32_t result = 0;
+ /* Refer to chapter 15.2 of the LoRaWAN specification v1.1. The beacon time
+ * GPS time in seconds modulo 2^32
+ */
+ uint32_t time = ( beaconTime % ( ( ( uint64_t ) 1 ) << 32 ) );
+
+ memset1( buffer, 0, 16 );
+ memset1( cipher, 0, 16 );
+
+ buffer[0] = ( time ) & 0xFF;
+ buffer[1] = ( time >> 8 ) & 0xFF;
+ buffer[2] = ( time >> 16 ) & 0xFF;
+ buffer[3] = ( time >> 24 ) & 0xFF;
+
+ buffer[4] = ( address ) & 0xFF;
+ buffer[5] = ( address >> 8 ) & 0xFF;
+ buffer[6] = ( address >> 16 ) & 0xFF;
+ buffer[7] = ( address >> 24 ) & 0xFF;
+
+ SecureElementAesEncrypt( buffer, 16, SLOT_RAND_ZERO_KEY, cipher );
+
+ result = ( ( ( uint32_t ) cipher[0] ) + ( ( ( uint32_t ) cipher[1] ) * 256 ) );
+
+ *pingOffset = ( uint16_t )( result % pingPeriod );
+}
+
+/*!
+ * \brief Calculates the downlink frequency for a given channel.
+ *
+ * \param [IN] channel The channel according to the channel plan.
+ *
+ * \retval The downlink frequency
+ */
+static uint32_t CalcDownlinkFrequency( uint8_t channel )
+{
+ GetPhyParams_t getPhy;
+ PhyParam_t phyParam;
+ uint32_t frequency = 0;
+ uint32_t stepwidth = 0;
+
+ getPhy.Attribute = PHY_BEACON_CHANNEL_FREQ;
+ phyParam = RegionGetPhyParam( *Ctx.LoRaMacClassBParams.LoRaMacRegion, &getPhy );
+ frequency = phyParam.Value;
+
+ getPhy.Attribute = PHY_BEACON_CHANNEL_STEPWIDTH;
+ phyParam = RegionGetPhyParam( *Ctx.LoRaMacClassBParams.LoRaMacRegion, &getPhy );
+ stepwidth = phyParam.Value;
+
+ // Calculate the frequency
+ return frequency + ( channel * stepwidth );
+}
+
+/*!
+ * \brief Calculates the downlink channel for the beacon and for
+ * ping slot downlinks.
+ *
+ * \param [IN] devAddr The address of the device
+ *
+ * \param [IN] beaconTime The beacon time of the beacon.
+ *
+ * \param [IN] beaconInterval The beacon interval
+ *
+ * \retval The downlink channel
+ */
+static uint32_t CalcDownlinkChannelAndFrequency( uint32_t devAddr, TimerTime_t beaconTime, TimerTime_t beaconInterval )
+{
+ GetPhyParams_t getPhy;
+ PhyParam_t phyParam;
+ uint32_t channel = 0;
+ uint8_t nbChannels = 0;
+ uint32_t frequency = 0;
+
+ getPhy.Attribute = PHY_BEACON_NB_CHANNELS;
+ phyParam = RegionGetPhyParam( *Ctx.LoRaMacClassBParams.LoRaMacRegion, &getPhy );
+ nbChannels = (uint8_t) phyParam.Value;
+
+ if( nbChannels > 1 )
+ {
+ // Calculate the channel for the next downlink
+ channel = devAddr + ( beaconTime / ( beaconInterval / 1000 ) );
+ channel = channel % nbChannels;
+ }
+
+ // Calculate the frequency for the next downlink
+ frequency = CalcDownlinkFrequency( channel );
+
+ // Calculate the frequency for the next downlink
+ return frequency;
+}
+
+/*!
+ * \brief Calculates the correct frequency and opens up the beacon reception window.
+ *
+ * \param [IN] rxTime The reception time which should be setup
+ *
+ * \param [IN] activateDefaultChannel Set to true, if the function shall setup the default channel
+ */
+static void RxBeaconSetup( TimerTime_t rxTime, bool activateDefaultChannel )
+{
+ RxBeaconSetup_t rxBeaconSetup;
+ uint32_t frequency = 0;
+ RxConfigParams_t beaconRxConfig;
+ GetPhyParams_t getPhy;
+ PhyParam_t phyParam;
+ uint16_t windowTimeout = Ctx.BeaconCtx.SymbolTimeout;
+
+ if( activateDefaultChannel == true )
+ {
+ // This is the default frequency in case we don't know when the next
+ // beacon will be transmitted. We select channel 0 as default.
+ frequency = CalcDownlinkFrequency( 0 );
+ }
+ else
+ {
+ // This is the frequency according to the channel plan
+ frequency = CalcDownlinkChannelAndFrequency( 0, Ctx.BeaconCtx.BeaconTime.Seconds + ( CLASSB_BEACON_INTERVAL / 1000 ),
+ CLASSB_BEACON_INTERVAL );
+ }
+
+ if( Ctx.NvmCtx->BeaconCtx.Ctrl.CustomFreq == 1 )
+ {
+ // Set the frequency from the BeaconFreqReq
+ frequency = Ctx.NvmCtx->BeaconCtx.Frequency;
+ }
+
+ if( Ctx.BeaconCtx.Ctrl.BeaconChannelSet == 1 )
+ {
+ // Set the frequency which was provided by BeaconTimingAns MAC command
+ Ctx.BeaconCtx.Ctrl.BeaconChannelSet = 0;
+ frequency = CalcDownlinkFrequency( Ctx.BeaconCtx.BeaconTimingChannel );
+ }
+
+ if( ( Ctx.BeaconCtx.Ctrl.BeaconAcquired == 1 ) || ( Ctx.BeaconCtx.Ctrl.AcquisitionPending == 1 ) )
+ {
+ // Apply the symbol timeout only if we have acquired the beacon
+ // Otherwise, take the window enlargement into account
+ // Read beacon datarate
+ getPhy.Attribute = PHY_BEACON_CHANNEL_DR;
+ phyParam = RegionGetPhyParam( *Ctx.LoRaMacClassBParams.LoRaMacRegion, &getPhy );
+
+ // Calculate downlink symbols
+ RegionComputeRxWindowParameters( *Ctx.LoRaMacClassBParams.LoRaMacRegion,
+ ( int8_t )phyParam.Value, // datarate
+ Ctx.LoRaMacClassBParams.LoRaMacParams->MinRxSymbols,
+ Ctx.LoRaMacClassBParams.LoRaMacParams->SystemMaxRxError,
+ &beaconRxConfig );
+ windowTimeout = beaconRxConfig.WindowTimeout;
+ }
+
+ rxBeaconSetup.SymbolTimeout = windowTimeout;
+ rxBeaconSetup.RxTime = rxTime;
+ rxBeaconSetup.Frequency = frequency;
+
+ RegionRxBeaconSetup( *Ctx.LoRaMacClassBParams.LoRaMacRegion, &rxBeaconSetup, &Ctx.LoRaMacClassBParams.McpsIndication->RxDatarate );
+
+ Ctx.LoRaMacClassBParams.MlmeIndication->BeaconInfo.Frequency = frequency;
+ Ctx.LoRaMacClassBParams.MlmeIndication->BeaconInfo.Datarate = Ctx.LoRaMacClassBParams.McpsIndication->RxDatarate;
+}
+
+/*!
+ * \brief Calculates the next ping slot time.
+ *
+ * \param [IN] slotOffset The ping slot offset
+ * \param [IN] pingPeriod The ping period
+ * \param [OUT] timeOffset Time offset of the next slot, based on current time
+ *
+ * \retval [true: ping slot found, false: no ping slot found]
+ */
+static bool CalcNextSlotTime( uint16_t slotOffset, uint16_t pingPeriod, uint16_t pingNb, TimerTime_t* timeOffset )
+{
+ uint8_t currentPingSlot = 0;
+ TimerTime_t slotTime = 0;
+ TimerTime_t currentTime = TimerGetCurrentTime( );
+
+ // Calculate the point in time of the last beacon even if we missed it
+ slotTime = ( ( currentTime - SysTimeToMs( Ctx.BeaconCtx.LastBeaconRx ) ) % CLASSB_BEACON_INTERVAL );
+ slotTime = currentTime - slotTime;
+
+ // Add the reserved time and the ping offset
+ slotTime += CLASSB_BEACON_RESERVED;
+ slotTime += slotOffset * CLASSB_PING_SLOT_WINDOW;
+
+ if( slotTime < currentTime )
+ {
+ currentPingSlot = ( ( currentTime - slotTime ) /
+ ( pingPeriod * CLASSB_PING_SLOT_WINDOW ) ) + 1;
+ slotTime += ( ( TimerTime_t )( currentPingSlot * pingPeriod ) *
+ CLASSB_PING_SLOT_WINDOW );
+ }
+
+ if( currentPingSlot < pingNb )
+ {
+ if( slotTime <= ( SysTimeToMs( Ctx.BeaconCtx.NextBeaconRx ) - CLASSB_BEACON_GUARD - CLASSB_PING_SLOT_WINDOW ) )
+ {
+ // Calculate the relative ping slot time
+ slotTime -= currentTime;
+ slotTime -= Radio.GetWakeupTime( );
+ slotTime = TimerTempCompensation( slotTime, Ctx.BeaconCtx.Temperature );
+ *timeOffset = slotTime;
+ return true;
+ }
+ }
+ return false;
+}
+
+/*!
+ * \brief Calculates CRC's of the beacon frame
+ *
+ * \param [IN] buffer Pointer to the data
+ * \param [IN] length Length of the data
+ *
+ * \retval CRC
+ */
+static uint16_t BeaconCrc( uint8_t *buffer, uint16_t length )
+{
+ // The CRC calculation follows CCITT
+ const uint16_t polynom = 0x1021;
+ // CRC initial value
+ uint16_t crc = 0x0000;
+
+ if( buffer == NULL )
+ {
+ return 0;
+ }
+
+ for( uint16_t i = 0; i < length; ++i )
+ {
+ crc ^= ( uint16_t ) buffer[i] << 8;
+ for( uint16_t j = 0; j < 8; ++j )
+ {
+ crc = ( crc & 0x8000 ) ? ( crc << 1 ) ^ polynom : ( crc << 1 );
+ }
+ }
+
+ return crc;
+}
+
+static void GetTemperatureLevel( LoRaMacClassBCallback_t *callbacks, BeaconContext_t *beaconCtx )
+{
+ // Measure temperature, if available
+ if( ( callbacks != NULL ) && ( callbacks->GetTemperatureLevel != NULL ) )
+ {
+ beaconCtx->Temperature = callbacks->GetTemperatureLevel( );
+ }
+}
+
+static void InitClassB( void )
+{
+ GetPhyParams_t getPhy;
+ PhyParam_t phyParam;
+
+ // Init events
+ LoRaMacClassBEvents.Value = 0;
+
+ // Init variables to default
+ memset1( ( uint8_t* ) &NvmCtx, 0, sizeof( LoRaMacClassBNvmCtx_t ) );
+ memset1( ( uint8_t* ) &Ctx.PingSlotCtx, 0, sizeof( PingSlotContext_t ) );
+ memset1( ( uint8_t* ) &Ctx.BeaconCtx, 0, sizeof( BeaconContext_t ) );
+
+ // Setup default temperature
+ Ctx.BeaconCtx.Temperature = 25.0;
+ GetTemperatureLevel( &Ctx.LoRaMacClassBCallbacks, &Ctx.BeaconCtx );
+
+ // Setup default ping slot datarate
+ getPhy.Attribute = PHY_PING_SLOT_CHANNEL_DR;
+ phyParam = RegionGetPhyParam( *Ctx.LoRaMacClassBParams.LoRaMacRegion, &getPhy );
+ Ctx.NvmCtx->PingSlotCtx.Datarate = (int8_t)( phyParam.Value );
+
+ // Setup default states
+ Ctx.BeaconState = BEACON_STATE_ACQUISITION;
+ Ctx.PingSlotState = PINGSLOT_STATE_CALC_PING_OFFSET;
+ Ctx.MulticastSlotState = PINGSLOT_STATE_CALC_PING_OFFSET;
+}
+
+static void InitClassBDefaults( void )
+{
+ // This function shall reset the Class B settings to default,
+ // but should keep important configurations
+ LoRaMacClassBBeaconNvmCtx_t beaconCtx = Ctx.NvmCtx->BeaconCtx;
+ LoRaMacClassBPingSlotNvmCtx_t pingSlotCtx = Ctx.NvmCtx->PingSlotCtx;
+
+ InitClassB( );
+
+ // Parameters from BeaconFreqReq
+ Ctx.NvmCtx->BeaconCtx.Frequency = beaconCtx.Frequency;
+ Ctx.NvmCtx->BeaconCtx.Ctrl.CustomFreq = beaconCtx.Ctrl.CustomFreq;
+
+ // Parameters from PingSlotChannelReq
+ Ctx.NvmCtx->PingSlotCtx.Ctrl.CustomFreq = pingSlotCtx.Ctrl.CustomFreq;
+ Ctx.NvmCtx->PingSlotCtx.Frequency = pingSlotCtx.Frequency;
+ Ctx.NvmCtx->PingSlotCtx.Datarate = pingSlotCtx.Datarate;
+}
+
+static void EnlargeWindowTimeout( void )
+{
+ // Update beacon movement
+ Ctx.BeaconCtx.BeaconWindowMovement *= CLASSB_WINDOW_MOVE_EXPANSION_FACTOR;
+ if( Ctx.BeaconCtx.BeaconWindowMovement > CLASSB_WINDOW_MOVE_EXPANSION_MAX )
+ {
+ Ctx.BeaconCtx.BeaconWindowMovement = CLASSB_WINDOW_MOVE_EXPANSION_MAX;
+ }
+ // Update symbol timeout
+ Ctx.BeaconCtx.SymbolTimeout *= CLASSB_BEACON_SYMBOL_TO_EXPANSION_FACTOR;
+ if( Ctx.BeaconCtx.SymbolTimeout > CLASSB_BEACON_SYMBOL_TO_EXPANSION_MAX )
+ {
+ Ctx.BeaconCtx.SymbolTimeout = CLASSB_BEACON_SYMBOL_TO_EXPANSION_MAX;
+ }
+ Ctx.PingSlotCtx.SymbolTimeout *= CLASSB_BEACON_SYMBOL_TO_EXPANSION_FACTOR;
+ if( Ctx.PingSlotCtx.SymbolTimeout > CLASSB_PING_SLOT_SYMBOL_TO_EXPANSION_MAX )
+ {
+ Ctx.PingSlotCtx.SymbolTimeout = CLASSB_PING_SLOT_SYMBOL_TO_EXPANSION_MAX;
+ }
+}
+
+static void ResetWindowTimeout( void )
+{
+ Ctx.BeaconCtx.SymbolTimeout = CLASSB_BEACON_SYMBOL_TO_DEFAULT;
+ Ctx.PingSlotCtx.SymbolTimeout = CLASSB_BEACON_SYMBOL_TO_DEFAULT;
+ Ctx.BeaconCtx.BeaconWindowMovement = CLASSB_WINDOW_MOVE_DEFAULT;
+}
+
+static TimerTime_t CalcDelayForNextBeacon( TimerTime_t currentTime, TimerTime_t lastBeaconRx )
+{
+ TimerTime_t nextBeaconRxTime = 0;
+
+ // Calculate the point in time of the next beacon
+ nextBeaconRxTime = ( ( currentTime - lastBeaconRx ) % CLASSB_BEACON_INTERVAL );
+ return ( CLASSB_BEACON_INTERVAL - nextBeaconRxTime );
+}
+
+static void IndicateBeaconStatus( LoRaMacEventInfoStatus_t status )
+{
+ if( Ctx.BeaconCtx.Ctrl.ResumeBeaconing == 0 )
+ {
+ Ctx.LoRaMacClassBParams.MlmeIndication->MlmeIndication = MLME_BEACON;
+ Ctx.LoRaMacClassBParams.MlmeIndication->Status = status;
+ Ctx.LoRaMacClassBParams.LoRaMacFlags->Bits.MlmeInd = 1;
+
+ Ctx.LoRaMacClassBParams.LoRaMacFlags->Bits.MacDone = 1;
+ }
+ Ctx.BeaconCtx.Ctrl.ResumeBeaconing = 0;
+}
+
+static TimerTime_t ApplyGuardTime( TimerTime_t beaconEventTime )
+{
+ TimerTime_t timeGuard = beaconEventTime;
+
+ if( timeGuard > CLASSB_BEACON_GUARD )
+ {
+ timeGuard -= CLASSB_BEACON_GUARD;
+ }
+ return timeGuard;
+}
+
+static TimerTime_t UpdateBeaconState( LoRaMacEventInfoStatus_t status,
+ TimerTime_t windowMovement, TimerTime_t currentTime )
+
+{
+ TimerTime_t beaconEventTime = 0;
+
+ // Calculate the next beacon RX time
+ beaconEventTime = CalcDelayForNextBeacon( currentTime, SysTimeToMs( Ctx.BeaconCtx.LastBeaconRx ) );
+ Ctx.BeaconCtx.NextBeaconRx = SysTimeFromMs( currentTime + beaconEventTime );
+
+ // Take temperature compensation into account
+ beaconEventTime = TimerTempCompensation( beaconEventTime, Ctx.BeaconCtx.Temperature );
+
+ // Move the window
+ if( beaconEventTime > windowMovement )
+ {
+ beaconEventTime -= windowMovement;
+ }
+ Ctx.BeaconCtx.NextBeaconRxAdjusted = currentTime + beaconEventTime;
+
+ // Start the RX slot state machine for ping and multicast slots
+ LoRaMacClassBStartRxSlots( );
+
+ // Setup an MLME_BEACON indication to inform the upper layer
+ IndicateBeaconStatus( status );
+
+ // Apply guard time
+ return ApplyGuardTime( beaconEventTime );
+}
+
+static uint8_t CalcPingNb( uint16_t periodicity )
+{
+ return 128 / ( 1 << periodicity );
+}
+
+static uint16_t CalcPingPeriod( uint8_t pingNb )
+{
+ return CLASSB_BEACON_WINDOW_SLOTS / pingNb;
+}
+
+/*
+ * Dummy callback in case if the user provides NULL function pointer
+ */
+static void NvmContextChange( void )
+{
+ if( Ctx.LoRaMacClassBNvmEvent != NULL )
+ {
+ Ctx.LoRaMacClassBNvmEvent( );
+ }
+}
+
+#endif // LORAMAC_CLASSB_ENABLED
+
+void LoRaMacClassBInit( LoRaMacClassBParams_t *classBParams, LoRaMacClassBCallback_t *callbacks, LoRaMacClassBNvmEvent classBNvmCtxChanged )
+{
+#ifdef LORAMAC_CLASSB_ENABLED
+ // Store callbacks
+ Ctx.LoRaMacClassBCallbacks = *callbacks;
+
+ // Store parameter pointers
+ Ctx.LoRaMacClassBParams = *classBParams;
+
+ // Assign non-volatile context
+ Ctx.NvmCtx = &NvmCtx;
+
+ // Assign callback
+ Ctx.LoRaMacClassBNvmEvent = classBNvmCtxChanged;
+
+ // Initialize timers
+ TimerInit( &Ctx.BeaconTimer, LoRaMacClassBBeaconTimerEvent );
+ TimerInit( &Ctx.PingSlotTimer, LoRaMacClassBPingSlotTimerEvent );
+ TimerInit( &Ctx.MulticastSlotTimer, LoRaMacClassBMulticastSlotTimerEvent );
+
+ InitClassB( );
+#endif // LORAMAC_CLASSB_ENABLED
+}
+
+bool LoRaMacClassBRestoreNvmCtx( void* classBNvmCtx )
+{
+#ifdef LORAMAC_CLASSB_ENABLED
+ // Restore module context
+ if( classBNvmCtx != NULL )
+ {
+ memcpy1( ( uint8_t* ) &NvmCtx, ( uint8_t* ) classBNvmCtx, sizeof( NvmCtx ) );
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+#else
+ return true;
+#endif // LORAMAC_CLASSB_ENABLED
+}
+
+void* LoRaMacClassBGetNvmCtx( size_t* classBNvmCtxSize )
+{
+#ifdef LORAMAC_CLASSB_ENABLED
+ *classBNvmCtxSize = sizeof( NvmCtx );
+ return &NvmCtx;
+#else
+ *classBNvmCtxSize = 0;
+ return NULL;
+#endif // LORAMAC_CLASSB_ENABLED
+}
+
+void LoRaMacClassBSetBeaconState( BeaconState_t beaconState )
+{
+#ifdef LORAMAC_CLASSB_ENABLED
+ if( beaconState == BEACON_STATE_ACQUISITION )
+ {
+ // If the MAC has received a time reference for the beacon,
+ // apply the state BEACON_STATE_ACQUISITION_BY_TIME.
+ if( ( Ctx.BeaconCtx.Ctrl.BeaconDelaySet == 1 ) &&
+ ( LoRaMacClassBIsAcquisitionPending( ) == false ) )
+ {
+ Ctx.BeaconState = BEACON_STATE_ACQUISITION_BY_TIME;
+ }
+ else
+ {
+ Ctx.BeaconState = beaconState;
+ }
+ }
+ else
+ {
+ if( ( Ctx.BeaconState != BEACON_STATE_ACQUISITION ) &&
+ ( Ctx.BeaconState != BEACON_STATE_ACQUISITION_BY_TIME ) )
+ {
+ Ctx.BeaconState = beaconState;
+ }
+ }
+#endif // LORAMAC_CLASSB_ENABLED
+}
+
+void LoRaMacClassBSetPingSlotState( PingSlotState_t pingSlotState )
+{
+#ifdef LORAMAC_CLASSB_ENABLED
+ Ctx.PingSlotState = pingSlotState;
+#endif // LORAMAC_CLASSB_ENABLED
+}
+
+void LoRaMacClassBSetMulticastSlotState( PingSlotState_t multicastSlotState )
+{
+#ifdef LORAMAC_CLASSB_ENABLED
+ Ctx.MulticastSlotState = multicastSlotState;
+#endif // LORAMAC_CLASSB_ENABLED
+}
+
+bool LoRaMacClassBIsAcquisitionInProgress( void )
+{
+#ifdef LORAMAC_CLASSB_ENABLED
+ if( Ctx.BeaconState == BEACON_STATE_ACQUISITION_BY_TIME )
+ {
+ // In this case the acquisition is in progress, as the MAC has
+ // a time reference for the next beacon RX.
+ return true;
+ }
+ if( LoRaMacClassBIsAcquisitionPending( ) == true )
+ {
+ // In this case the acquisition is in progress, as the MAC
+ // searches for a beacon.
+ return true;
+ }
+ return false;
+#else
+ return false;
+#endif // LORAMAC_CLASSB_ENABLED
+}
+
+void LoRaMacClassBBeaconTimerEvent( void* context )
+{
+#ifdef LORAMAC_CLASSB_ENABLED
+ Ctx.BeaconCtx.TimeStamp = TimerGetCurrentTime( );
+ TimerStop( &Ctx.BeaconTimer );
+ LoRaMacClassBEvents.Events.Beacon = 1;
+
+ if( Ctx.LoRaMacClassBCallbacks.MacProcessNotify != NULL )
+ {
+ Ctx.LoRaMacClassBCallbacks.MacProcessNotify( );
+ }
+#endif // LORAMAC_CLASSB_ENABLED
+}
+
+#ifdef LORAMAC_CLASSB_ENABLED
+static void LoRaMacClassBProcessBeacon( void )
+{
+ bool activateTimer = false;
+ TimerTime_t beaconEventTime = 1;
+ TimerTime_t currentTime = Ctx.BeaconCtx.TimeStamp;
+
+ // Beacon state machine
+ switch( Ctx.BeaconState )
+ {
+ case BEACON_STATE_ACQUISITION_BY_TIME:
+ {
+ activateTimer = true;
+
+ if( Ctx.BeaconCtx.Ctrl.AcquisitionPending == 1 )
+ {
+ Radio.Sleep();
+ Ctx.BeaconState = BEACON_STATE_LOST;
+ }
+ else
+ {
+ // Default symbol timeouts
+ ResetWindowTimeout( );
+
+ if( Ctx.BeaconCtx.Ctrl.BeaconDelaySet == 1 )
+ {
+ if( Ctx.BeaconCtx.BeaconTimingDelay > 0 )
+ {
+ if( SysTimeToMs( Ctx.BeaconCtx.NextBeaconRx ) > currentTime )
+ {
+ beaconEventTime = TimerTempCompensation( SysTimeToMs( Ctx.BeaconCtx.NextBeaconRx ) - currentTime, Ctx.BeaconCtx.Temperature );
+ }
+ else
+ {
+ // Reset status provides by BeaconTimingAns
+ Ctx.BeaconCtx.Ctrl.BeaconDelaySet = 0;
+ Ctx.BeaconCtx.Ctrl.BeaconChannelSet = 0;
+ Ctx.BeaconState = BEACON_STATE_ACQUISITION;
+ }
+ Ctx.BeaconCtx.BeaconTimingDelay = 0;
+ }
+ else
+ {
+ activateTimer = false;
+
+ // Reset status provides by BeaconTimingAns
+ Ctx.BeaconCtx.Ctrl.BeaconDelaySet = 0;
+ // Set the node into acquisition mode
+ Ctx.BeaconCtx.Ctrl.AcquisitionPending = 1;
+
+ // Don't use the default channel. We know on which
+ // channel the next beacon will be transmitted
+ RxBeaconSetup( CLASSB_BEACON_RESERVED, false );
+ }
+ }
+ else
+ {
+ Ctx.BeaconCtx.NextBeaconRx.Seconds = 0;
+ Ctx.BeaconCtx.NextBeaconRx.SubSeconds = 0;
+ Ctx.BeaconCtx.BeaconTimingDelay = 0;
+
+ Ctx.BeaconState = BEACON_STATE_ACQUISITION;
+ }
+ }
+ break;
+ }
+ case BEACON_STATE_ACQUISITION:
+ {
+ activateTimer = true;
+
+ if( Ctx.BeaconCtx.Ctrl.AcquisitionPending == 1 )
+ {
+ Radio.Sleep();
+ Ctx.BeaconState = BEACON_STATE_LOST;
+ }
+ else
+ {
+ // Default symbol timeouts
+ ResetWindowTimeout( );
+
+ Ctx.BeaconCtx.Ctrl.AcquisitionPending = 1;
+ beaconEventTime = CLASSB_BEACON_INTERVAL;
+
+ // Start the beacon acquisition. When the MAC has received a beacon in function
+ // RxBeacon successfully, the next state is BEACON_STATE_LOCKED. If the MAC does not
+ // find a beacon, the state machine will stay in state BEACON_STATE_ACQUISITION.
+ // This state detects that a acquisition was pending previously and will change the next
+ // state to BEACON_STATE_LOST.
+ RxBeaconSetup( 0, true );
+ }
+ break;
+ }
+ case BEACON_STATE_TIMEOUT:
+ {
+ // We have to update the beacon time, since we missed a beacon
+ Ctx.BeaconCtx.BeaconTime.Seconds += ( CLASSB_BEACON_INTERVAL / 1000 );
+ Ctx.BeaconCtx.BeaconTime.SubSeconds = 0;
+
+ // Enlarge window timeouts to increase the chance to receive the next beacon
+ EnlargeWindowTimeout( );
+
+ // Setup next state
+ Ctx.BeaconState = BEACON_STATE_REACQUISITION;
+ }
+ // Intentional fall through
+ case BEACON_STATE_REACQUISITION:
+ {
+ activateTimer = true;
+
+ // The beacon is no longer acquired
+ Ctx.BeaconCtx.Ctrl.BeaconAcquired = 0;
+
+ // Verify if the maximum beacon less period has been elapsed
+ if( ( currentTime - SysTimeToMs( Ctx.BeaconCtx.LastBeaconRx ) ) > CLASSB_MAX_BEACON_LESS_PERIOD )
+ {
+ Ctx.BeaconState = BEACON_STATE_LOST;
+ }
+ else
+ {
+ // Handle beacon miss
+ beaconEventTime = UpdateBeaconState( LORAMAC_EVENT_INFO_STATUS_BEACON_LOST,
+ Ctx.BeaconCtx.BeaconWindowMovement, currentTime );
+
+ // Setup next state
+ Ctx.BeaconState = BEACON_STATE_IDLE;
+ }
+ break;
+ }
+ case BEACON_STATE_LOCKED:
+ {
+ activateTimer = true;
+
+ // We have received a beacon. Acquisition is no longer pending.
+ Ctx.BeaconCtx.Ctrl.AcquisitionPending = 0;
+
+ // Handle beacon reception
+ beaconEventTime = UpdateBeaconState( LORAMAC_EVENT_INFO_STATUS_BEACON_LOCKED,
+ 0, currentTime );
+
+ // Setup the MLME confirm for the MLME_BEACON_ACQUISITION
+ if( Ctx.LoRaMacClassBParams.LoRaMacFlags->Bits.MlmeReq == 1 )
+ {
+ if( LoRaMacConfirmQueueIsCmdActive( MLME_BEACON_ACQUISITION ) == true )
+ {
+ LoRaMacConfirmQueueSetStatus( LORAMAC_EVENT_INFO_STATUS_OK, MLME_BEACON_ACQUISITION );
+ Ctx.LoRaMacClassBParams.MlmeConfirm->TxTimeOnAir = 0;
+ }
+ }
+
+ // Setup next state
+ Ctx.BeaconState = BEACON_STATE_IDLE;
+ break;
+ }
+ case BEACON_STATE_IDLE:
+ {
+ activateTimer = true;
+ GetTemperatureLevel( &Ctx.LoRaMacClassBCallbacks, &Ctx.BeaconCtx );
+ beaconEventTime = Ctx.BeaconCtx.NextBeaconRxAdjusted - Radio.GetWakeupTime( );
+ currentTime = TimerGetCurrentTime( );
+
+ if( beaconEventTime > currentTime )
+ {
+ Ctx.BeaconState = BEACON_STATE_GUARD;
+ beaconEventTime -= currentTime;
+ beaconEventTime = TimerTempCompensation( beaconEventTime, Ctx.BeaconCtx.Temperature );
+ }
+ else
+ {
+ Ctx.BeaconState = BEACON_STATE_REACQUISITION;
+ beaconEventTime = 1;
+ }
+ break;
+ }
+ case BEACON_STATE_GUARD:
+ {
+ Ctx.BeaconState = BEACON_STATE_RX;
+
+ // Stop slot timers
+ LoRaMacClassBStopRxSlots( );
+
+ // Don't use the default channel. We know on which
+ // channel the next beacon will be transmitted
+ RxBeaconSetup( CLASSB_BEACON_RESERVED, false );
+ break;
+ }
+ case BEACON_STATE_LOST:
+ {
+ // Handle events
+ if( Ctx.LoRaMacClassBParams.LoRaMacFlags->Bits.MlmeReq == 1 )
+ {
+ if( LoRaMacConfirmQueueIsCmdActive( MLME_BEACON_ACQUISITION ) == true )
+ {
+ LoRaMacConfirmQueueSetStatus( LORAMAC_EVENT_INFO_STATUS_BEACON_NOT_FOUND, MLME_BEACON_ACQUISITION );
+ }
+ }
+ else
+ {
+ Ctx.LoRaMacClassBParams.MlmeIndication->MlmeIndication = MLME_BEACON_LOST;
+ Ctx.LoRaMacClassBParams.MlmeIndication->Status = LORAMAC_EVENT_INFO_STATUS_OK;
+ Ctx.LoRaMacClassBParams.LoRaMacFlags->Bits.MlmeInd = 1;
+ }
+
+ // Stop slot timers
+ LoRaMacClassBStopRxSlots( );
+
+ // Initialize default state for class b
+ InitClassBDefaults( );
+
+ Ctx.LoRaMacClassBParams.LoRaMacFlags->Bits.MacDone = 1;
+
+ break;
+ }
+ default:
+ {
+ Ctx.BeaconState = BEACON_STATE_ACQUISITION;
+ break;
+ }
+ }
+
+ if( activateTimer == true )
+ {
+ TimerSetValue( &Ctx.BeaconTimer, beaconEventTime );
+ TimerStart( &Ctx.BeaconTimer );
+ }
+}
+#endif // LORAMAC_CLASSB_ENABLED
+
+void LoRaMacClassBPingSlotTimerEvent( void* context )
+{
+#ifdef LORAMAC_CLASSB_ENABLED
+ LoRaMacClassBEvents.Events.PingSlot = 1;
+
+ if( Ctx.LoRaMacClassBCallbacks.MacProcessNotify != NULL )
+ {
+ Ctx.LoRaMacClassBCallbacks.MacProcessNotify( );
+ }
+#endif // LORAMAC_CLASSB_ENABLED
+}
+
+#ifdef LORAMAC_CLASSB_ENABLED
+static void LoRaMacClassBProcessPingSlot( void )
+{
+ static RxConfigParams_t pingSlotRxConfig;
+ TimerTime_t pingSlotTime = 0;
+
+ switch( Ctx.PingSlotState )
+ {
+ case PINGSLOT_STATE_CALC_PING_OFFSET:
+ {
+ ComputePingOffset( Ctx.BeaconCtx.BeaconTime.Seconds,
+ *Ctx.LoRaMacClassBParams.LoRaMacDevAddr,
+ Ctx.NvmCtx->PingSlotCtx.PingPeriod,
+ &( Ctx.PingSlotCtx.PingOffset ) );
+ Ctx.PingSlotState = PINGSLOT_STATE_SET_TIMER;
+ }
+ // Intentional fall through
+ case PINGSLOT_STATE_SET_TIMER:
+ {
+ if( CalcNextSlotTime( Ctx.PingSlotCtx.PingOffset, Ctx.NvmCtx->PingSlotCtx.PingPeriod, Ctx.NvmCtx->PingSlotCtx.PingNb, &pingSlotTime ) == true )
+ {
+ if( Ctx.BeaconCtx.Ctrl.BeaconAcquired == 1 )
+ {
+ // Compute the symbol timeout. Apply it only, if the beacon is acquired
+ // Otherwise, take the enlargement of the symbols into account.
+ RegionComputeRxWindowParameters( *Ctx.LoRaMacClassBParams.LoRaMacRegion,
+ Ctx.NvmCtx->PingSlotCtx.Datarate,
+ Ctx.LoRaMacClassBParams.LoRaMacParams->MinRxSymbols,
+ Ctx.LoRaMacClassBParams.LoRaMacParams->SystemMaxRxError,
+ &pingSlotRxConfig );
+ Ctx.PingSlotCtx.SymbolTimeout = pingSlotRxConfig.WindowTimeout;
+
+ if( ( int32_t )pingSlotTime > pingSlotRxConfig.WindowOffset )
+ {// Apply the window offset
+ pingSlotTime += pingSlotRxConfig.WindowOffset;
+ }
+ }
+
+ // Start the timer if the ping slot time is in range
+ Ctx.PingSlotState = PINGSLOT_STATE_IDLE;
+ TimerSetValue( &Ctx.PingSlotTimer, pingSlotTime );
+ TimerStart( &Ctx.PingSlotTimer );
+ }
+ break;
+ }
+ case PINGSLOT_STATE_IDLE:
+ {
+ uint32_t frequency = Ctx.NvmCtx->PingSlotCtx.Frequency;
+
+ // Apply a custom frequency if the following bit is set
+ if( Ctx.NvmCtx->PingSlotCtx.Ctrl.CustomFreq == 0 )
+ {
+ // Restore floor plan
+ frequency = CalcDownlinkChannelAndFrequency( *Ctx.LoRaMacClassBParams.LoRaMacDevAddr, Ctx.BeaconCtx.BeaconTime.Seconds, CLASSB_BEACON_INTERVAL );
+ }
+
+ // Open the ping slot window only, if there is no multicast ping slot
+ // open. Multicast ping slots have always priority
+ if( Ctx.MulticastSlotState != PINGSLOT_STATE_RX )
+ {
+ Ctx.PingSlotState = PINGSLOT_STATE_RX;
+
+ pingSlotRxConfig.Datarate = Ctx.NvmCtx->PingSlotCtx.Datarate;
+ pingSlotRxConfig.DownlinkDwellTime = Ctx.LoRaMacClassBParams.LoRaMacParams->DownlinkDwellTime;
+ pingSlotRxConfig.RepeaterSupport = Ctx.LoRaMacClassBParams.LoRaMacParams->RepeaterSupport;
+ pingSlotRxConfig.Frequency = frequency;
+ pingSlotRxConfig.RxContinuous = false;
+ pingSlotRxConfig.RxSlot = RX_SLOT_WIN_CLASS_B_PING_SLOT;
+
+ RegionRxConfig( *Ctx.LoRaMacClassBParams.LoRaMacRegion, &pingSlotRxConfig, ( int8_t* )&Ctx.LoRaMacClassBParams.McpsIndication->RxDatarate );
+
+ if( pingSlotRxConfig.RxContinuous == false )
+ {
+ Radio.Rx( Ctx.LoRaMacClassBParams.LoRaMacParams->MaxRxWindow );
+ }
+ else
+ {
+ Radio.Rx( 0 ); // Continuous mode
+ }
+ }
+ else
+ {
+ // Multicast slots have priority. Skip Rx
+ Ctx.PingSlotState = PINGSLOT_STATE_CALC_PING_OFFSET;
+ TimerSetValue( &Ctx.PingSlotTimer, CLASSB_PING_SLOT_WINDOW );
+ TimerStart( &Ctx.PingSlotTimer );
+ }
+ break;
+ }
+ default:
+ {
+ Ctx.PingSlotState = PINGSLOT_STATE_CALC_PING_OFFSET;
+ break;
+ }
+ }
+}
+#endif // LORAMAC_CLASSB_ENABLED
+
+void LoRaMacClassBMulticastSlotTimerEvent( void* context )
+{
+#ifdef LORAMAC_CLASSB_ENABLED
+ LoRaMacClassBEvents.Events.MulticastSlot = 1;
+
+ if( Ctx.LoRaMacClassBCallbacks.MacProcessNotify != NULL )
+ {
+ Ctx.LoRaMacClassBCallbacks.MacProcessNotify( );
+ }
+#endif // LORAMAC_CLASSB_ENABLED
+}
+
+#ifdef LORAMAC_CLASSB_ENABLED
+static void LoRaMacClassBProcessMulticastSlot( void )
+{
+ static RxConfigParams_t multicastSlotRxConfig;
+ TimerTime_t multicastSlotTime = 0;
+ TimerTime_t slotTime = 0;
+ MulticastCtx_t *cur = Ctx.LoRaMacClassBParams.MulticastChannels;
+
+
+ if( cur == NULL )
+ {
+ return;
+ }
+
+ if( Ctx.MulticastSlotState == PINGSLOT_STATE_RX )
+ {
+ // A multicast slot is already open
+ return;
+ }
+
+ switch( Ctx.MulticastSlotState )
+ {
+ case PINGSLOT_STATE_CALC_PING_OFFSET:
+ {
+ // Compute all offsets for every multicast slots
+ for( uint8_t i = 0; i < 4; i++ )
+ {
+ ComputePingOffset( Ctx.BeaconCtx.BeaconTime.Seconds,
+ cur->ChannelParams.Address,
+ cur->PingPeriod,
+ &( cur->PingOffset ) );
+ cur++;
+ }
+ Ctx.MulticastSlotState = PINGSLOT_STATE_SET_TIMER;
+ }
+ // Intentional fall through
+ case PINGSLOT_STATE_SET_TIMER:
+ {
+ cur = Ctx.LoRaMacClassBParams.MulticastChannels;
+ Ctx.PingSlotCtx.NextMulticastChannel = NULL;
+
+ for( uint8_t i = 0; i < 4; i++ )
+ {
+ // Calculate the next slot time for every multicast slot
+ if( CalcNextSlotTime( cur->PingOffset, cur->PingPeriod, cur->PingNb, &slotTime ) == true )
+ {
+ if( ( multicastSlotTime == 0 ) || ( multicastSlotTime > slotTime ) )
+ {
+ // Update the slot time and the next multicast channel
+ multicastSlotTime = slotTime;
+ Ctx.PingSlotCtx.NextMulticastChannel = cur;
+ }
+ }
+ cur++;
+ }
+
+ // Schedule the next multicast slot
+ if( Ctx.PingSlotCtx.NextMulticastChannel != NULL )
+ {
+ if( Ctx.BeaconCtx.Ctrl.BeaconAcquired == 1 )
+ {
+ RegionComputeRxWindowParameters( *Ctx.LoRaMacClassBParams.LoRaMacRegion,
+ Ctx.NvmCtx->PingSlotCtx.Datarate,
+ Ctx.LoRaMacClassBParams.LoRaMacParams->MinRxSymbols,
+ Ctx.LoRaMacClassBParams.LoRaMacParams->SystemMaxRxError,
+ &multicastSlotRxConfig );
+ Ctx.PingSlotCtx.SymbolTimeout = multicastSlotRxConfig.WindowTimeout;
+ }
+
+ if( ( int32_t )multicastSlotTime > multicastSlotRxConfig.WindowOffset )
+ {// Apply the window offset
+ multicastSlotTime += multicastSlotRxConfig.WindowOffset;
+ }
+
+ // Start the timer if the ping slot time is in range
+ Ctx.MulticastSlotState = PINGSLOT_STATE_IDLE;
+ TimerSetValue( &Ctx.MulticastSlotTimer, multicastSlotTime );
+ TimerStart( &Ctx.MulticastSlotTimer );
+ }
+ break;
+ }
+ case PINGSLOT_STATE_IDLE:
+ {
+ uint32_t frequency = 0;
+
+ // Verify if the multicast channel is valid
+ if( Ctx.PingSlotCtx.NextMulticastChannel == NULL )
+ {
+ Ctx.MulticastSlotState = PINGSLOT_STATE_CALC_PING_OFFSET;
+ TimerSetValue( &Ctx.MulticastSlotTimer, 1 );
+ TimerStart( &Ctx.MulticastSlotTimer );
+ break;
+ }
+
+ // Apply frequency
+ frequency = Ctx.PingSlotCtx.NextMulticastChannel->ChannelParams.RxParams.ClassB.Frequency;
+
+ // Restore the floor plan frequency if there is no individual frequency assigned
+ if( frequency == 0 )
+ {
+ // Restore floor plan
+ frequency = CalcDownlinkChannelAndFrequency( Ctx.PingSlotCtx.NextMulticastChannel->ChannelParams.Address, Ctx.BeaconCtx.BeaconTime.Seconds, CLASSB_BEACON_INTERVAL );
+ }
+
+ Ctx.MulticastSlotState = PINGSLOT_STATE_RX;
+
+ multicastSlotRxConfig.Datarate = Ctx.PingSlotCtx.NextMulticastChannel->ChannelParams.RxParams.ClassB.Datarate;
+ multicastSlotRxConfig.DownlinkDwellTime = Ctx.LoRaMacClassBParams.LoRaMacParams->DownlinkDwellTime;
+ multicastSlotRxConfig.RepeaterSupport = Ctx.LoRaMacClassBParams.LoRaMacParams->RepeaterSupport;
+ multicastSlotRxConfig.Frequency = frequency;
+ multicastSlotRxConfig.RxContinuous = false;
+ multicastSlotRxConfig.RxSlot = RX_SLOT_WIN_CLASS_B_MULTICAST_SLOT;
+
+ RegionRxConfig( *Ctx.LoRaMacClassBParams.LoRaMacRegion, &multicastSlotRxConfig, ( int8_t* )&Ctx.LoRaMacClassBParams.McpsIndication->RxDatarate );
+
+ if( Ctx.PingSlotState == PINGSLOT_STATE_RX )
+ {
+ // Close ping slot window, if necessary. Multicast slots have priority
+ Radio.Standby( );
+ Ctx.PingSlotState = PINGSLOT_STATE_CALC_PING_OFFSET;
+ TimerSetValue( &Ctx.PingSlotTimer, CLASSB_PING_SLOT_WINDOW );
+ TimerStart( &Ctx.PingSlotTimer );
+ }
+
+ if( multicastSlotRxConfig.RxContinuous == false )
+ {
+ Radio.Rx( Ctx.LoRaMacClassBParams.LoRaMacParams->MaxRxWindow );
+ }
+ else
+ {
+ Radio.Rx( 0 ); // Continuous mode
+ }
+ break;
+ }
+ default:
+ {
+ Ctx.MulticastSlotState = PINGSLOT_STATE_CALC_PING_OFFSET;
+ break;
+ }
+ }
+}
+#endif // LORAMAC_CLASSB_ENABLED
+
+bool LoRaMacClassBRxBeacon( uint8_t *payload, uint16_t size )
+{
+#ifdef LORAMAC_CLASSB_ENABLED
+ GetPhyParams_t getPhy;
+ PhyParam_t phyParam;
+ bool beaconProcessed = false;
+ uint16_t crc0 = 0;
+ uint16_t crc1 = 0;
+ uint16_t beaconCrc0 = 0;
+ uint16_t beaconCrc1 = 0;
+
+ getPhy.Attribute = PHY_BEACON_FORMAT;
+ phyParam = RegionGetPhyParam( *Ctx.LoRaMacClassBParams.LoRaMacRegion, &getPhy );
+
+ // Verify if we are in the state where we expect a beacon
+ if( ( Ctx.BeaconState == BEACON_STATE_RX ) || ( Ctx.BeaconCtx.Ctrl.AcquisitionPending == 1 ) )
+ {
+ if( size == phyParam.BeaconFormat.BeaconSize )
+ {
+ // A beacon frame is defined as:
+ // Bytes: | x | 4 | 2 | 7 | y | 2 |
+ // |------|------|------|------------|------|------|
+ // Field: | RFU1 | Time | CRC1 | GwSpecific | RFU2 | CRC2 |
+ //
+ // Field RFU1 and RFU2 have variable sizes. It depends on the region specific implementation
+
+ // Read CRC1 field from the frame
+ beaconCrc0 = ( ( uint16_t )payload[phyParam.BeaconFormat.Rfu1Size + 4] ) & 0x00FF;
+ beaconCrc0 |= ( ( uint16_t )payload[phyParam.BeaconFormat.Rfu1Size + 4 + 1] << 8 ) & 0xFF00;
+ crc0 = BeaconCrc( payload, phyParam.BeaconFormat.Rfu1Size + 4 );
+
+ // Validate the first crc of the beacon frame
+ if( crc0 == beaconCrc0 )
+ {
+ // Read Time field from the frame
+ Ctx.BeaconCtx.BeaconTime.Seconds = ( ( uint32_t )payload[phyParam.BeaconFormat.Rfu1Size] ) & 0x000000FF;
+ Ctx.BeaconCtx.BeaconTime.Seconds |= ( ( uint32_t )( payload[phyParam.BeaconFormat.Rfu1Size + 1] << 8 ) ) & 0x0000FF00;
+ Ctx.BeaconCtx.BeaconTime.Seconds |= ( ( uint32_t )( payload[phyParam.BeaconFormat.Rfu1Size + 2] << 16 ) ) & 0x00FF0000;
+ Ctx.BeaconCtx.BeaconTime.Seconds |= ( ( uint32_t )( payload[phyParam.BeaconFormat.Rfu1Size + 3] << 24 ) ) & 0xFF000000;
+ Ctx.BeaconCtx.BeaconTime.SubSeconds = 0;
+ Ctx.LoRaMacClassBParams.MlmeIndication->BeaconInfo.Time = Ctx.BeaconCtx.BeaconTime;
+ beaconProcessed = true;
+ }
+
+ // Read CRC2 field from the frame
+ beaconCrc1 = ( ( uint16_t )payload[phyParam.BeaconFormat.Rfu1Size + 4 + 2 + 7 + phyParam.BeaconFormat.Rfu2Size] ) & 0x00FF;
+ beaconCrc1 |= ( ( uint16_t )payload[phyParam.BeaconFormat.Rfu1Size + 4 + 2 + 7 + phyParam.BeaconFormat.Rfu2Size + 1] << 8 ) & 0xFF00;
+ crc1 = BeaconCrc( &payload[phyParam.BeaconFormat.Rfu1Size + 4 + 2], 7 + phyParam.BeaconFormat.Rfu2Size );
+
+ // Validate the second crc of the beacon frame
+ if( crc1 == beaconCrc1 )
+ {
+ // Read GwSpecific field from the frame
+ // The GwSpecific field contains 1 byte InfoDesc and 6 bytes Info
+ Ctx.LoRaMacClassBParams.MlmeIndication->BeaconInfo.GwSpecific.InfoDesc = payload[phyParam.BeaconFormat.Rfu1Size + 4 + 2];
+ memcpy1( Ctx.LoRaMacClassBParams.MlmeIndication->BeaconInfo.GwSpecific.Info, &payload[phyParam.BeaconFormat.Rfu1Size + 4 + 2 + 1], 6 );
+ }
+
+ // Reset beacon variables, if one of the crc is valid
+ if( beaconProcessed == true )
+ {
+ TimerTime_t time = Radio.TimeOnAir( MODEM_LORA, size );
+ SysTime_t timeOnAir;
+ timeOnAir.Seconds = time / 1000;
+ timeOnAir.SubSeconds = time - timeOnAir.Seconds * 1000;
+
+ Ctx.BeaconCtx.LastBeaconRx = Ctx.BeaconCtx.BeaconTime;
+ Ctx.BeaconCtx.LastBeaconRx.Seconds += UNIX_GPS_EPOCH_OFFSET;
+
+ // Update system time.
+ SysTimeSet( SysTimeAdd( Ctx.BeaconCtx.LastBeaconRx, timeOnAir ) );
+
+ Ctx.BeaconCtx.Ctrl.BeaconAcquired = 1;
+ Ctx.BeaconCtx.Ctrl.BeaconMode = 1;
+ ResetWindowTimeout( );
+ Ctx.BeaconState = BEACON_STATE_LOCKED;
+
+ LoRaMacClassBBeaconTimerEvent( NULL );
+ }
+ }
+
+ if( Ctx.BeaconState == BEACON_STATE_RX )
+ {
+ Ctx.BeaconState = BEACON_STATE_TIMEOUT;
+ LoRaMacClassBBeaconTimerEvent( NULL );
+ }
+ // When the MAC listens for a beacon, it is not allowed to process any other
+ // downlink except the beacon frame itself. The reason for this is that no valid downlink window is open.
+ // If it receives a frame which is
+ // 1. not a beacon or
+ // 2. a beacon with a crc fail
+ // the MAC shall ignore the frame completely. Thus, the function must always return true, even if no
+ // valid beacon has been received.
+ beaconProcessed = true;
+ }
+ return beaconProcessed;
+#else
+ return false;
+#endif // LORAMAC_CLASSB_ENABLED
+}
+
+bool LoRaMacClassBIsBeaconExpected( void )
+{
+#ifdef LORAMAC_CLASSB_ENABLED
+ if( ( Ctx.BeaconCtx.Ctrl.AcquisitionPending == 1 ) ||
+ ( Ctx.BeaconState == BEACON_STATE_RX ) )
+ {
+ return true;
+ }
+ return false;
+#else
+ return false;
+#endif // LORAMAC_CLASSB_ENABLED
+}
+
+bool LoRaMacClassBIsPingExpected( void )
+{
+#ifdef LORAMAC_CLASSB_ENABLED
+ if( Ctx.PingSlotState == PINGSLOT_STATE_RX )
+ {
+ return true;
+ }
+ return false;
+#else
+ return false;
+#endif // LORAMAC_CLASSB_ENABLED
+}
+
+bool LoRaMacClassBIsMulticastExpected( void )
+{
+#ifdef LORAMAC_CLASSB_ENABLED
+ if( Ctx.MulticastSlotState == PINGSLOT_STATE_RX )
+ {
+ return true;
+ }
+ return false;
+#else
+ return false;
+#endif // LORAMAC_CLASSB_ENABLED
+}
+
+bool LoRaMacClassBIsAcquisitionPending( void )
+{
+#ifdef LORAMAC_CLASSB_ENABLED
+ if( Ctx.BeaconCtx.Ctrl.AcquisitionPending == 1 )
+ {
+ return true;
+ }
+ return false;
+#else
+ return false;
+#endif // LORAMAC_CLASSB_ENABLED
+}
+
+bool LoRaMacClassBIsBeaconModeActive( void )
+{
+#ifdef LORAMAC_CLASSB_ENABLED
+ if( ( Ctx.BeaconCtx.Ctrl.BeaconMode == 1 ) ||
+ ( Ctx.BeaconState == BEACON_STATE_ACQUISITION_BY_TIME ) )
+ {
+ return true;
+ }
+ return false;
+#else
+ return false;
+#endif // LORAMAC_CLASSB_ENABLED
+}
+
+void LoRaMacClassBSetPingSlotInfo( uint8_t periodicity )
+{
+#ifdef LORAMAC_CLASSB_ENABLED
+ Ctx.NvmCtx->PingSlotCtx.PingNb = CalcPingNb( periodicity );
+ Ctx.NvmCtx->PingSlotCtx.PingPeriod = CalcPingPeriod( Ctx.NvmCtx->PingSlotCtx.PingNb );
+ NvmContextChange( );
+#endif // LORAMAC_CLASSB_ENABLED
+}
+
+void LoRaMacClassBHaltBeaconing( void )
+{
+#ifdef LORAMAC_CLASSB_ENABLED
+ if( Ctx.BeaconCtx.Ctrl.BeaconMode == 1 )
+ {
+ if( ( Ctx.BeaconState == BEACON_STATE_TIMEOUT ) ||
+ ( Ctx.BeaconState == BEACON_STATE_LOST ) )
+ {
+ // Update the state machine before halt
+ LoRaMacClassBBeaconTimerEvent( NULL );
+ }
+
+ CRITICAL_SECTION_BEGIN( );
+ LoRaMacClassBEvents.Events.Beacon = 0;
+ CRITICAL_SECTION_END( );
+
+ // Halt ping slot state machine
+ TimerStop( &Ctx.BeaconTimer );
+
+ // Halt beacon state machine
+ Ctx.BeaconState = BEACON_STATE_HALT;
+
+ // Halt ping and multicast slot state machines
+ LoRaMacClassBStopRxSlots( );
+ }
+#endif // LORAMAC_CLASSB_ENABLED
+}
+
+void LoRaMacClassBResumeBeaconing( void )
+{
+#ifdef LORAMAC_CLASSB_ENABLED
+ if( Ctx.BeaconState == BEACON_STATE_HALT )
+ {
+ Ctx.BeaconCtx.Ctrl.ResumeBeaconing = 1;
+
+ // Set default state
+ Ctx.BeaconState = BEACON_STATE_LOCKED;
+
+ if( Ctx.BeaconCtx.Ctrl.BeaconAcquired == 0 )
+ {
+ // Set the default state for beacon less operation
+ Ctx.BeaconState = BEACON_STATE_REACQUISITION;
+ }
+
+ LoRaMacClassBBeaconTimerEvent( NULL );
+ }
+#endif // LORAMAC_CLASSB_ENABLED
+}
+
+LoRaMacStatus_t LoRaMacClassBSwitchClass( DeviceClass_t nextClass )
+{
+#ifdef LORAMAC_CLASSB_ENABLED
+ if( nextClass == CLASS_B )
+ {// Switch to from class a to class b
+ if( ( Ctx.BeaconCtx.Ctrl.BeaconMode == 1 ) && ( Ctx.NvmCtx->PingSlotCtx.Ctrl.Assigned == 1 ) )
+ {
+ return LORAMAC_STATUS_OK;
+ }
+ }
+ if( nextClass == CLASS_A )
+ {// Switch from class b to class a
+ LoRaMacClassBHaltBeaconing( );
+
+ // Initialize default state for class b
+ InitClassBDefaults( );
+
+ return LORAMAC_STATUS_OK;
+ }
+ return LORAMAC_STATUS_SERVICE_UNKNOWN;
+#else
+ return LORAMAC_STATUS_SERVICE_UNKNOWN;
+#endif // LORAMAC_CLASSB_ENABLED
+}
+
+LoRaMacStatus_t LoRaMacClassBMibGetRequestConfirm( MibRequestConfirm_t *mibGet )
+{
+#ifdef LORAMAC_CLASSB_ENABLED
+ LoRaMacStatus_t status;
+
+ switch( mibGet->Type )
+ {
+ case MIB_PING_SLOT_DATARATE:
+ {
+ mibGet->Param.PingSlotDatarate = Ctx.NvmCtx->PingSlotCtx.Datarate;
+ break;
+ }
+ default:
+ {
+ status = LORAMAC_STATUS_SERVICE_UNKNOWN;
+ break;
+ }
+ }
+ return status;
+#else
+ return LORAMAC_STATUS_SERVICE_UNKNOWN;
+#endif // LORAMAC_CLASSB_ENABLED
+}
+
+LoRaMacStatus_t LoRaMacMibClassBSetRequestConfirm( MibRequestConfirm_t *mibSet )
+{
+#ifdef LORAMAC_CLASSB_ENABLED
+ LoRaMacStatus_t status;
+
+ switch( mibSet->Type )
+ {
+ case MIB_PING_SLOT_DATARATE:
+ {
+ Ctx.NvmCtx->PingSlotCtx.Datarate = mibSet->Param.PingSlotDatarate;
+ NvmContextChange( );
+ break;
+ }
+ default:
+ {
+ status = LORAMAC_STATUS_SERVICE_UNKNOWN;
+ break;
+ }
+ }
+ return status;
+#else
+ return LORAMAC_STATUS_SERVICE_UNKNOWN;
+#endif // LORAMAC_CLASSB_ENABLED
+}
+
+void LoRaMacClassBPingSlotInfoAns( void )
+{
+#ifdef LORAMAC_CLASSB_ENABLED
+ if( LoRaMacConfirmQueueIsCmdActive( MLME_PING_SLOT_INFO ) == true )
+ {
+ LoRaMacConfirmQueueSetStatus( LORAMAC_EVENT_INFO_STATUS_OK, MLME_PING_SLOT_INFO );
+ Ctx.NvmCtx->PingSlotCtx.Ctrl.Assigned = 1;
+ NvmContextChange( );
+ }
+#endif // LORAMAC_CLASSB_ENABLED
+}
+
+uint8_t LoRaMacClassBPingSlotChannelReq( uint8_t datarate, uint32_t frequency )
+{
+#ifdef LORAMAC_CLASSB_ENABLED
+ uint8_t status = 0x03;
+ VerifyParams_t verify;
+ bool isCustomFreq = false;
+
+ if( frequency != 0 )
+ {
+ isCustomFreq = true;
+ verify.Frequency = frequency;
+ if( RegionVerify( *Ctx.LoRaMacClassBParams.LoRaMacRegion, &verify, PHY_FREQUENCY ) == false )
+ {
+ status &= 0xFE; // Channel frequency KO
+ }
+ }
+
+ verify.DatarateParams.Datarate = datarate;
+ verify.DatarateParams.DownlinkDwellTime = Ctx.LoRaMacClassBParams.LoRaMacParams->DownlinkDwellTime;
+
+ if( RegionVerify( *Ctx.LoRaMacClassBParams.LoRaMacRegion, &verify, PHY_RX_DR ) == false )
+ {
+ status &= 0xFD; // Datarate range KO
+ }
+
+ if( status == 0x03 )
+ {
+ if( isCustomFreq == true )
+ {
+ Ctx.NvmCtx->PingSlotCtx.Ctrl.CustomFreq = 1;
+ Ctx.NvmCtx->PingSlotCtx.Frequency = frequency;
+ }
+ else
+ {
+ Ctx.NvmCtx->PingSlotCtx.Ctrl.CustomFreq = 0;
+ Ctx.NvmCtx->PingSlotCtx.Frequency = 0;
+ }
+ Ctx.NvmCtx->PingSlotCtx.Datarate = datarate;
+ NvmContextChange( );
+ }
+
+ return status;
+#else
+ return 0;
+#endif // LORAMAC_CLASSB_ENABLED
+}
+
+void LoRaMacClassBBeaconTimingAns( uint16_t beaconTimingDelay, uint8_t beaconTimingChannel, TimerTime_t lastRxDone )
+{
+#ifdef LORAMAC_CLASSB_ENABLED
+ Ctx.BeaconCtx.BeaconTimingDelay = ( CLASSB_BEACON_DELAY_BEACON_TIMING_ANS * beaconTimingDelay );
+ Ctx.BeaconCtx.BeaconTimingChannel = beaconTimingChannel;
+
+ if( LoRaMacConfirmQueueIsCmdActive( MLME_BEACON_TIMING ) == true )
+ {
+ if( Ctx.BeaconCtx.BeaconTimingDelay > CLASSB_BEACON_INTERVAL )
+ {
+ // We missed the beacon already
+ Ctx.BeaconCtx.BeaconTimingDelay = 0;
+ Ctx.BeaconCtx.BeaconTimingChannel = 0;
+ LoRaMacConfirmQueueSetStatus( LORAMAC_EVENT_INFO_STATUS_BEACON_NOT_FOUND, MLME_BEACON_TIMING );
+ }
+ else
+ {
+ Ctx.BeaconCtx.Ctrl.BeaconDelaySet = 1;
+ Ctx.BeaconCtx.Ctrl.BeaconChannelSet = 1;
+ Ctx.BeaconCtx.NextBeaconRx = SysTimeFromMs( lastRxDone + Ctx.BeaconCtx.BeaconTimingDelay );
+ LoRaMacConfirmQueueSetStatus( LORAMAC_EVENT_INFO_STATUS_OK, MLME_BEACON_TIMING );
+ }
+
+ Ctx.LoRaMacClassBParams.MlmeConfirm->BeaconTimingDelay = Ctx.BeaconCtx.BeaconTimingDelay;
+ Ctx.LoRaMacClassBParams.MlmeConfirm->BeaconTimingChannel = Ctx.BeaconCtx.BeaconTimingChannel;
+ }
+#endif // LORAMAC_CLASSB_ENABLED
+}
+
+void LoRaMacClassBDeviceTimeAns( void )
+{
+#ifdef LORAMAC_CLASSB_ENABLED
+
+ SysTime_t nextBeacon = SysTimeGet( );
+ uint32_t currentTimeMs = SysTimeToMs( nextBeacon );
+
+ nextBeacon.Seconds = nextBeacon.Seconds + ( 128 - ( nextBeacon.Seconds % 128 ) );
+ nextBeacon.SubSeconds = 0;
+
+ Ctx.BeaconCtx.NextBeaconRx = nextBeacon;
+ Ctx.BeaconCtx.LastBeaconRx = SysTimeSub( Ctx.BeaconCtx.NextBeaconRx, ( SysTime_t ){ .Seconds = CLASSB_BEACON_INTERVAL / 1000, .SubSeconds = 0 } );
+
+ if( LoRaMacConfirmQueueIsCmdActive( MLME_DEVICE_TIME ) == true )
+ {
+ if( currentTimeMs > SysTimeToMs( Ctx.BeaconCtx.NextBeaconRx ) )
+ {
+ // We missed the beacon already
+ Ctx.BeaconCtx.LastBeaconRx.Seconds = 0;
+ Ctx.BeaconCtx.LastBeaconRx.SubSeconds = 0;
+ Ctx.BeaconCtx.NextBeaconRx.Seconds = 0;
+ Ctx.BeaconCtx.NextBeaconRx.SubSeconds = 0;
+ LoRaMacConfirmQueueSetStatus( LORAMAC_EVENT_INFO_STATUS_BEACON_NOT_FOUND, MLME_DEVICE_TIME );
+ }
+ else
+ {
+ Ctx.BeaconCtx.Ctrl.BeaconDelaySet = 1;
+ Ctx.BeaconCtx.BeaconTimingDelay = SysTimeToMs( Ctx.BeaconCtx.NextBeaconRx ) - currentTimeMs;
+ Ctx.BeaconCtx.BeaconTime.Seconds = nextBeacon.Seconds - UNIX_GPS_EPOCH_OFFSET - 128;
+ Ctx.BeaconCtx.BeaconTime.SubSeconds = 0;
+ LoRaMacConfirmQueueSetStatus( LORAMAC_EVENT_INFO_STATUS_OK, MLME_DEVICE_TIME );
+ }
+ }
+#endif // LORAMAC_CLASSB_ENABLED
+}
+
+bool LoRaMacClassBBeaconFreqReq( uint32_t frequency )
+{
+#ifdef LORAMAC_CLASSB_ENABLED
+ VerifyParams_t verify;
+
+ if( frequency != 0 )
+ {
+ verify.Frequency = frequency;
+
+ if( RegionVerify( *Ctx.LoRaMacClassBParams.LoRaMacRegion, &verify, PHY_FREQUENCY ) == true )
+ {
+ Ctx.NvmCtx->BeaconCtx.Ctrl.CustomFreq = 1;
+ Ctx.NvmCtx->BeaconCtx.Frequency = frequency;
+ NvmContextChange( );
+ return true;
+ }
+ }
+ else
+ {
+ Ctx.NvmCtx->BeaconCtx.Ctrl.CustomFreq = 0;
+ NvmContextChange( );
+ return true;
+ }
+ return false;
+#else
+ return false;
+#endif // LORAMAC_CLASSB_ENABLED
+}
+
+TimerTime_t LoRaMacClassBIsUplinkCollision( TimerTime_t txTimeOnAir )
+{
+#ifdef LORAMAC_CLASSB_ENABLED
+ TimerTime_t currentTime = TimerGetCurrentTime( );
+ TimerTime_t beaconReserved = 0;
+ TimerTime_t nextBeacon = SysTimeToMs( Ctx.BeaconCtx.NextBeaconRx );
+
+ beaconReserved = nextBeacon -
+ CLASSB_BEACON_GUARD -
+ Ctx.LoRaMacClassBParams.LoRaMacParams->ReceiveDelay1 -
+ Ctx.LoRaMacClassBParams.LoRaMacParams->ReceiveDelay2 -
+ txTimeOnAir;
+
+ // Check if the next beacon will be received during the next uplink.
+ if( ( currentTime >= beaconReserved ) && ( currentTime < ( nextBeacon + CLASSB_BEACON_RESERVED ) ) )
+ {// Next beacon will be sent during the next uplink.
+ return CLASSB_BEACON_RESERVED;
+ }
+ return 0;
+#else
+ return 0;
+#endif // LORAMAC_CLASSB_ENABLED
+}
+
+void LoRaMacClassBStopRxSlots( void )
+{
+#ifdef LORAMAC_CLASSB_ENABLED
+ TimerStop( &Ctx.PingSlotTimer );
+ TimerStop( &Ctx.MulticastSlotTimer );
+
+ CRITICAL_SECTION_BEGIN( );
+ LoRaMacClassBEvents.Events.PingSlot = 0;
+ LoRaMacClassBEvents.Events.MulticastSlot = 0;
+ CRITICAL_SECTION_END( );
+#endif // LORAMAC_CLASSB_ENABLED
+}
+
+void LoRaMacClassBStartRxSlots( void )
+{
+#ifdef LORAMAC_CLASSB_ENABLED
+ if( Ctx.NvmCtx->PingSlotCtx.Ctrl.Assigned == 1 )
+ {
+ Ctx.PingSlotState = PINGSLOT_STATE_CALC_PING_OFFSET;
+ TimerSetValue( &Ctx.PingSlotTimer, 1 );
+ TimerStart( &Ctx.PingSlotTimer );
+
+ Ctx.MulticastSlotState = PINGSLOT_STATE_CALC_PING_OFFSET;
+ TimerSetValue( &Ctx.MulticastSlotTimer, 1 );
+ TimerStart( &Ctx.MulticastSlotTimer );
+ }
+#endif // LORAMAC_CLASSB_ENABLED
+}
+
+void LoRaMacClassBSetMulticastPeriodicity( MulticastCtx_t* multicastChannel )
+{
+#ifdef LORAMAC_CLASSB_ENABLED
+ if( multicastChannel != NULL )
+ {
+ multicastChannel->PingNb = CalcPingNb( multicastChannel->ChannelParams.RxParams.ClassB.Periodicity );
+ multicastChannel->PingPeriod = CalcPingPeriod( multicastChannel->PingNb );
+ }
+#endif // LORAMAC_CLASSB_ENABLED
+}
+
+void LoRaMacClassBProcess( void )
+{
+#ifdef LORAMAC_CLASSB_ENABLED
+ LoRaMacClassBEvents_t events;
+
+ CRITICAL_SECTION_BEGIN( );
+ events = LoRaMacClassBEvents;
+ LoRaMacClassBEvents.Value = 0;
+ CRITICAL_SECTION_END( );
+
+ if( events.Value != 0 )
+ {
+ if( events.Events.Beacon == 1 )
+ {
+ LoRaMacClassBProcessBeacon( );
+ }
+ if( events.Events.PingSlot == 1 )
+ {
+ LoRaMacClassBProcessPingSlot( );
+ }
+ if( events.Events.MulticastSlot == 1 )
+ {
+ LoRaMacClassBProcessMulticastSlot( );
+ }
+ }
+#endif // LORAMAC_CLASSB_ENABLED
+}
diff --git a/lib/lora/mac/LoRaMacClassB.h b/lib/lora/mac/LoRaMacClassB.h
new file mode 100644
index 0000000000..ccde35b34f
--- /dev/null
+++ b/lib/lora/mac/LoRaMacClassB.h
@@ -0,0 +1,539 @@
+/*!
+ * \file LoRaMacClassB.h
+ *
+ * \brief LoRa MAC Class B layer implementation
+ *
+ * \copyright Revised BSD License, see section \ref LICENSE.
+ *
+ * \code
+ * ______ _
+ * / _____) _ | |
+ * ( (____ _____ ____ _| |_ _____ ____| |__
+ * \____ \| ___ | (_ _) ___ |/ ___) _ \
+ * _____) ) ____| | | || |_| ____( (___| | | |
+ * (______/|_____)_|_|_| \__)_____)\____)_| |_|
+ * (C)2013 Semtech
+ *
+ * ___ _____ _ ___ _ _____ ___ ___ ___ ___
+ * / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
+ * \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
+ * |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
+ * embedded.connectivity.solutions===============
+ *
+ * \endcode
+ *
+ * \author Miguel Luis ( Semtech )
+ *
+ * \author Gregory Cristian ( Semtech )
+ *
+ * \author Daniel Jaeckle ( STACKFORCE )
+ *
+ * \defgroup LORAMACCLASSB LoRa MAC Class B layer implementation
+ * This module specifies the API implementation of the LoRaMAC Class B layer.
+ * This is a placeholder for a detailed description of the LoRaMac
+ * layer and the supported features.
+ * \{
+ */
+#ifndef __LORAMACCLASSB_H__
+#define __LORAMACCLASSB_H__
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include "../system/systime.h"
+#include "LoRaMacTypes.h"
+
+/*!
+ * States of the class B beacon acquisition and tracking
+ */
+typedef enum eBeaconState
+{
+ /*!
+ * Initial state to acquire the beacon
+ */
+ BEACON_STATE_ACQUISITION,
+ /*!
+ * Beacon acquisition state when a time reference is available
+ */
+ BEACON_STATE_ACQUISITION_BY_TIME,
+ /*!
+ * Handles the state when the beacon reception fails
+ */
+ BEACON_STATE_TIMEOUT,
+ /*!
+ * Handles the state when the beacon was missed due to an uplink
+ */
+ BEACON_STATE_BEACON_MISSED,
+ /*!
+ * Reacquisition state which applies the algorithm to enlarge the reception
+ * windows
+ */
+ BEACON_STATE_REACQUISITION,
+ /*!
+ * The node has locked a beacon successfully
+ */
+ BEACON_STATE_LOCKED,
+ /*!
+ * The beacon state machine is stopped due to operations with higher priority
+ */
+ BEACON_STATE_HALT,
+ /*!
+ * The node currently operates in the beacon window and is idle. In this
+ * state, the temperature measurement takes place
+ */
+ BEACON_STATE_IDLE,
+ /*!
+ * The node operates in the guard time of class B
+ */
+ BEACON_STATE_GUARD,
+ /*!
+ * The node is in receive mode to lock a beacon
+ */
+ BEACON_STATE_RX,
+ /*!
+ * The nodes switches the device class
+ */
+ BEACON_STATE_LOST,
+}BeaconState_t;
+
+/*!
+ * States of the class B ping slot mechanism
+ */
+typedef enum ePingSlotState
+{
+ /*!
+ * Calculation of the ping slot offset
+ */
+ PINGSLOT_STATE_CALC_PING_OFFSET,
+ /*!
+ * State to set the timer to open the next ping slot
+ */
+ PINGSLOT_STATE_SET_TIMER,
+ /*!
+ * The node is in idle state
+ */
+ PINGSLOT_STATE_IDLE,
+ /*!
+ * The node opens up a ping slot window
+ */
+ PINGSLOT_STATE_RX,
+}PingSlotState_t;
+
+/*!
+ * Class B ping slot context structure
+ */
+typedef struct sPingSlotContext
+{
+
+ /*!
+ * Ping slot length time in ms
+ */
+ uint32_t PingSlotWindow;
+ /*!
+ * Ping offset
+ */
+ uint16_t PingOffset;
+ /*!
+ * Current symbol timeout. The node enlarges this variable in case of beacon
+ * loss.
+ */
+ uint16_t SymbolTimeout;
+ /*!
+ * The multicast channel which will be enabled next.
+ */
+ MulticastCtx_t *NextMulticastChannel;
+}PingSlotContext_t;
+
+
+/*!
+ * Class B beacon context structure
+ */
+typedef struct sBeaconContext
+{
+ struct sBeaconCtrl
+ {
+ /*!
+ * Set if the node receives beacons
+ */
+ uint8_t BeaconMode : 1;
+ /*!
+ * Set if the node has acquired the beacon
+ */
+ uint8_t BeaconAcquired : 1;
+ /*!
+ * Set if a beacon delay was set for the beacon acquisition
+ */
+ uint8_t BeaconDelaySet : 1;
+ /*!
+ * Set if a beacon channel was set for the beacon acquisition
+ */
+ uint8_t BeaconChannelSet : 1;
+ /*!
+ * Set if beacon acquisition is pending
+ */
+ uint8_t AcquisitionPending : 1;
+ /*!
+ * Set if the beacon state machine will be resumed
+ */
+ uint8_t ResumeBeaconing : 1;
+ }Ctrl;
+
+ /*!
+ * Current temperature
+ */
+ float Temperature;
+ /*!
+ * Beacon time received with the beacon frame
+ */
+ SysTime_t BeaconTime;
+ /*!
+ * Time when the last beacon was received
+ */
+ SysTime_t LastBeaconRx;
+ /*!
+ * Time when the next beacon will be received
+ */
+ SysTime_t NextBeaconRx;
+ /*!
+ * This is the time where the RX window will be opened.
+ * Its base is NextBeaconRx with temperature compensations
+ * and RX window movement.
+ */
+ TimerTime_t NextBeaconRxAdjusted;
+ /*!
+ * Current symbol timeout. The node enlarges this variable in case of beacon
+ * loss.
+ */
+ uint16_t SymbolTimeout;
+ /*!
+ * Specifies how much time the beacon window will be moved.
+ */
+ TimerTime_t BeaconWindowMovement;
+ /*!
+ * Beacon timing channel for next beacon
+ */
+ uint8_t BeaconTimingChannel;
+ /*!
+ * Delay for next beacon in ms
+ */
+ TimerTime_t BeaconTimingDelay;
+ TimerTime_t TimeStamp;
+}BeaconContext_t;
+
+/*!
+ * Data structure which contains the callbacks
+ */
+typedef struct sLoRaMacClassBCallback
+{
+ /*!
+ * \brief Measures the temperature level
+ *
+ * \retval Temperature level
+ */
+ float ( *GetTemperatureLevel )( void );
+ /*!
+ *\brief Will be called each time a Radio IRQ is handled by the MAC
+ * layer.
+ *
+ *\warning Runs in a IRQ context. Should only change variables state.
+ */
+ void ( *MacProcessNotify )( void );
+}LoRaMacClassBCallback_t;
+
+/*!
+ * Data structure which pointers to the properties LoRaMAC
+ */
+typedef struct sLoRaMacClassBParams
+{
+ /*!
+ * Pointer to the MlmeIndication structure
+ */
+ MlmeIndication_t *MlmeIndication;
+ /*!
+ * Pointer to the McpsIndication structure
+ */
+ McpsIndication_t *McpsIndication;
+ /*!
+ * Pointer to the MlmeConfirm structure
+ */
+ MlmeConfirm_t *MlmeConfirm;
+ /*!
+ * Pointer to the LoRaMacFlags structure
+ */
+ LoRaMacFlags_t *LoRaMacFlags;
+ /*!
+ * Pointer to the LoRaMac device address
+ */
+ uint32_t *LoRaMacDevAddr;
+ /*!
+ * Pointer to the LoRaMac region definition
+ */
+ LoRaMacRegion_t *LoRaMacRegion;
+ /*!
+ * Pointer to the LoRaMacParams structure
+ */
+ LoRaMacParams_t *LoRaMacParams;
+ /*!
+ * Pointer to the multicast channel list
+ */
+ MulticastCtx_t *MulticastChannels;
+}LoRaMacClassBParams_t;
+
+/*!
+ * Signature of callback function to be called by this module when the
+ * non-volatile needs to be saved.
+ */
+typedef void ( *LoRaMacClassBNvmEvent )( void );
+
+/*!
+ * \brief Initialize LoRaWAN Class B
+ *
+ * \param [IN] classBParams Information and feedback parameter
+ * \param [IN] callbacks Contains the callback which the Class B implementation needs
+ * \param [IN] callback function which will be called when the non-volatile context needs to be saved.
+ */
+void LoRaMacClassBInit( LoRaMacClassBParams_t *classBParams, LoRaMacClassBCallback_t *callbacks, LoRaMacClassBNvmEvent classBNvmCtxChanged );
+
+/*!
+ * Restores the internal non-volatile context from passed pointer.
+ *
+ * \param [IN] classBNvmCtx - Pointer to non-volatile class B module context to be restored.
+ *
+ * \retval - Status of the operation
+ */
+bool LoRaMacClassBRestoreNvmCtx( void* classBNvmCtx );
+
+/*!
+ * Returns a pointer to the internal non-volatile context.
+ *
+ * \param [IN] classBNvmCtxSize - Size of the module non-volatile context
+ *
+ * \retval - Points to a structure where the module store its non-volatile context
+ */
+void* LoRaMacClassBGetNvmCtx( size_t* classBNvmCtxSize );
+
+/*!
+ * \brief Set the state of the beacon state machine
+ *
+ * \param [IN] beaconState Beacon state.
+ */
+void LoRaMacClassBSetBeaconState( BeaconState_t beaconState );
+
+/*!
+ * \brief Set the state of the ping slot state machine
+ *
+ * \param [IN] pingSlotState Ping slot state.
+ */
+void LoRaMacClassBSetPingSlotState( PingSlotState_t pingSlotState );
+
+/*!
+ * \brief Set the state of the multicast slot state machine
+ *
+ * \param [IN] pingSlotState multicast slot state.
+ */
+void LoRaMacClassBSetMulticastSlotState( PingSlotState_t multicastSlotState );
+
+/*!
+ * \brief Verifies if an acquisition procedure is in progress
+ *
+ * \retval [true, if the acquisition is in progress; false, if not]
+ */
+bool LoRaMacClassBIsAcquisitionInProgress( void );
+
+/*!
+ * \brief State machine of the Class B for beaconing
+ */
+void LoRaMacClassBBeaconTimerEvent( void* context );
+
+/*!
+ * \brief State machine of the Class B for ping slots
+ */
+void LoRaMacClassBPingSlotTimerEvent( void* context );
+
+/*!
+ * \brief State machine of the Class B for multicast slots
+ */
+void LoRaMacClassBMulticastSlotTimerEvent( void* context );
+
+/*!
+ * \brief Receives and decodes the beacon frame
+ *
+ * \param [IN] payload Pointer to the payload
+ * \param [IN] size Size of the payload
+ * \retval [true, if the node has received a beacon; false, if not]
+ */
+bool LoRaMacClassBRxBeacon( uint8_t *payload, uint16_t size );
+
+/*!
+ * \brief The function validates, if the node expects a beacon
+ * at the current time.
+ *
+ * \retval [true, if the node expects a beacon; false, if not]
+ */
+bool LoRaMacClassBIsBeaconExpected( void );
+
+/*!
+ * \brief The function validates, if the node expects a ping slot
+ * at the current time.
+ *
+ * \retval [true, if the node expects a ping slot; false, if not]
+ */
+bool LoRaMacClassBIsPingExpected( void );
+
+/*!
+ * \brief The function validates, if the node expects a multicast slot
+ * at the current time.
+ *
+ * \retval [true, if the node expects a multicast slot; false, if not]
+ */
+bool LoRaMacClassBIsMulticastExpected( void );
+
+/*!
+ * \brief Verifies if the acquisition pending bit is set
+ *
+ * \retval [true, if the bit is set; false, if not]
+ */
+bool LoRaMacClassBIsAcquisitionPending( void );
+
+/*!
+ * \brief Verifies if the beacon mode active bit is set
+ *
+ * \retval [true, if the bit is set; false, if not]
+ */
+bool LoRaMacClassBIsBeaconModeActive( void );
+
+/*!
+ * \brief Stops the beacon and ping slot operation
+ */
+void LoRaMacClassBHaltBeaconing( void );
+
+/*!
+ * \brief Resumes the beacon and ping slot operation
+ */
+void LoRaMacClassBResumeBeaconing( void );
+
+/*!
+ * \brief Sets the periodicity of the ping slots
+ *
+ * \param [IN] periodicity Periodicity
+ */
+void LoRaMacClassBSetPingSlotInfo( uint8_t periodicity );
+
+/*!
+ * \brief Switches the device class
+ *
+ * \param [IN] nextClass Device class to switch to
+ *
+ * \retval LoRaMacStatus_t Status of the operation.
+ */
+LoRaMacStatus_t LoRaMacClassBSwitchClass( DeviceClass_t nextClass );
+
+/*!
+ * \brief LoRaMAC ClassB MIB-Get
+ *
+ * \details The mac information base service to get attributes of the LoRaMac
+ * Class B layer.
+ *
+ * \param [IN] mibRequest - MIB-GET-Request to perform. Refer to \ref MibRequestConfirm_t.
+ *
+ * \retval LoRaMacStatus_t Status of the operation. Possible returns are:
+ * \ref LORAMAC_STATUS_OK,
+ * \ref LORAMAC_STATUS_SERVICE_UNKNOWN,
+ * \ref LORAMAC_STATUS_PARAMETER_INVALID.
+ */
+LoRaMacStatus_t LoRaMacClassBMibGetRequestConfirm( MibRequestConfirm_t *mibGet );
+
+/*!
+ * \brief LoRaMAC Class B MIB-Set
+ *
+ * \details The mac information base service to set attributes of the LoRaMac
+ * Class B layer.
+ *
+ * \param [IN] mibRequest - MIB-SET-Request to perform. Refer to \ref MibRequestConfirm_t.
+ *
+ * \retval LoRaMacStatus_t Status of the operation. Possible returns are:
+ * \ref LORAMAC_STATUS_OK,
+ * \ref LORAMAC_STATUS_BUSY,
+ * \ref LORAMAC_STATUS_SERVICE_UNKNOWN,
+ * \ref LORAMAC_STATUS_PARAMETER_INVALID.
+ */
+LoRaMacStatus_t LoRaMacMibClassBSetRequestConfirm( MibRequestConfirm_t *mibSet );
+
+/*!
+ * \brief This function handles the PING_SLOT_FREQ_ANS
+ */
+void LoRaMacClassBPingSlotInfoAns( void );
+
+/*!
+ * \brief This function handles the PING_SLOT_CHANNEL_REQ
+ *
+ * \param [IN] datarate Device class to switch to
+ * \param [IN] frequency Device class to switch to
+ *
+ * \retval Status for the MAC answer.
+ */
+uint8_t LoRaMacClassBPingSlotChannelReq( uint8_t datarate, uint32_t frequency );
+
+/*!
+ * \brief This function handles the BEACON_TIMING_ANS
+ *
+ * \param [IN] beaconTimingDelay The beacon timing delay
+ * \param [IN] beaconTimingChannel The beacon timing channel
+ * \param [IN] lastRxDone The time of the last frame reception
+ */
+void LoRaMacClassBBeaconTimingAns( uint16_t beaconTimingDelay, uint8_t beaconTimingChannel, TimerTime_t lastRxDone );
+
+/*!
+ * \brief This function handles the ClassB DEVICE_TIME_ANS
+ */
+void LoRaMacClassBDeviceTimeAns( void );
+
+/*!
+ * \brief This function handles the BEACON_FREQ_REQ
+ *
+ * \param [IN] frequency Frequency to set
+ *
+ * \retval [true, if MAC shall send an answer; false, if not]
+ */
+bool LoRaMacClassBBeaconFreqReq( uint32_t frequency );
+
+/*!
+ * \brief Queries the ping slot window time
+ *
+ * \param [IN] txTimeOnAir TX time on air for the next uplink
+ *
+ * \retval Returns the time the uplink should be delayed
+ */
+TimerTime_t LoRaMacClassBIsUplinkCollision( TimerTime_t txTimeOnAir );
+
+/*!
+ * \brief Stops the timers for the RX slots. This includes the
+ * timers for ping and multicast slots.
+ */
+void LoRaMacClassBStopRxSlots( void );
+
+/*!
+ * \brief Starts the timers for the RX slots. This includes the
+ * timers for ping and multicast slots.
+ */
+void LoRaMacClassBStartRxSlots( void );
+
+/*!
+ * \brief Starts the timers for the RX slots. This includes the
+ * timers for ping and multicast slots.
+ *
+ * \param [IN] periodicity Downlink periodicity
+ *
+ * \param [IN] multicastChannel Related multicast channel
+ */
+void LoRaMacClassBSetMulticastPeriodicity( MulticastCtx_t* multicastChannel );
+
+void LoRaMacClassBProcess( void );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // __LORAMACCLASSB_H__
diff --git a/lib/lora/mac/LoRaMacClassBConfig.h b/lib/lora/mac/LoRaMacClassBConfig.h
new file mode 100644
index 0000000000..3c231affa2
--- /dev/null
+++ b/lib/lora/mac/LoRaMacClassBConfig.h
@@ -0,0 +1,124 @@
+/*!
+ * \file LoRaMacClassBConfig.h
+ *
+ * \brief LoRa MAC Class B configuration
+ *
+ * \copyright Revised BSD License, see section \ref LICENSE.
+ *
+ * \code
+ * ______ _
+ * / _____) _ | |
+ * ( (____ _____ ____ _| |_ _____ ____| |__
+ * \____ \| ___ | (_ _) ___ |/ ___) _ \
+ * _____) ) ____| | | || |_| ____( (___| | | |
+ * (______/|_____)_|_|_| \__)_____)\____)_| |_|
+ * (C)2013 Semtech
+ *
+ * ___ _____ _ ___ _ _____ ___ ___ ___ ___
+ * / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
+ * \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
+ * |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
+ * embedded.connectivity.solutions===============
+ *
+ * \endcode
+ *
+ * \author Miguel Luis ( Semtech )
+ *
+ * \author Gregory Cristian ( Semtech )
+ *
+ * \author Daniel Jaeckle ( STACKFORCE )
+ *
+ * \defgroup LORAMACCLASSB LoRa MAC Class B configuration
+ * This header file contains parameters to configure the class b operation.
+ * By default, all parameters are set according to the specification.
+ * \{
+ */
+#ifndef __LORAMACCLASSBCONFIG_H__
+#define __LORAMACCLASSBCONFIG_H__
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/*!
+ * Defines the beacon interval in ms
+ */
+#define CLASSB_BEACON_INTERVAL 128000
+
+/*!
+ * Beacon reserved time in ms
+ */
+#define CLASSB_BEACON_RESERVED 2120
+
+/*!
+ * Beacon guard time in ms
+ */
+#define CLASSB_BEACON_GUARD 3000
+
+/*!
+ * Beacon window time in ms
+ */
+#define CLASSB_BEACON_WINDOW 122880
+
+/*!
+ * Beacon window time in numer of slots
+ */
+#define CLASSB_BEACON_WINDOW_SLOTS 4096
+
+/*!
+ * Ping slot length time in ms
+ */
+#define CLASSB_PING_SLOT_WINDOW 30
+
+/*!
+ * Maximum allowed beacon less time in ms
+ */
+#define CLASSB_MAX_BEACON_LESS_PERIOD 7200000
+
+/*!
+ * Delay time for the BeaconTimingAns in ms
+ */
+#define CLASSB_BEACON_DELAY_BEACON_TIMING_ANS 30
+
+/*!
+ * Default symbol timeout for beacons and ping slot windows
+ */
+#define CLASSB_BEACON_SYMBOL_TO_DEFAULT 8
+
+/*!
+ * Maximum symbol timeout for beacons
+ */
+#define CLASSB_BEACON_SYMBOL_TO_EXPANSION_MAX 255
+
+/*!
+ * Maximum symbol timeout for ping slots
+ */
+#define CLASSB_PING_SLOT_SYMBOL_TO_EXPANSION_MAX 30
+
+/*!
+ * Symbol expansion value for beacon windows in case of beacon
+ * loss in symbols
+ */
+#define CLASSB_BEACON_SYMBOL_TO_EXPANSION_FACTOR 2
+
+/*!
+ * Defines the default window movement time
+ */
+#define CLASSB_WINDOW_MOVE_DEFAULT 2
+
+/*!
+ * Defines the maximum time for the beacon movement
+ */
+#define CLASSB_WINDOW_MOVE_EXPANSION_MAX 256
+
+/*!
+ * Defines the expansion factor for the beacon movement
+ */
+#define CLASSB_WINDOW_MOVE_EXPANSION_FACTOR 2
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // __LORAMACCLASSBCONFIG_H__
diff --git a/lib/lora/mac/LoRaMacCommands.c b/lib/lora/mac/LoRaMacCommands.c
new file mode 100644
index 0000000000..b516136aa7
--- /dev/null
+++ b/lib/lora/mac/LoRaMacCommands.c
@@ -0,0 +1,548 @@
+/*
+ / _____) _ | |
+( (____ _____ ____ _| |_ _____ ____| |__
+ \____ \| ___ | (_ _) ___ |/ ___) _ \
+ _____) ) ____| | | || |_| ____( (___| | | |
+(______/|_____)_|_|_| \__)_____)\____)_| |_|
+ (C)2013 Semtech
+ ___ _____ _ ___ _ _____ ___ ___ ___ ___
+/ __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
+\__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
+|___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
+embedded.connectivity.solutions===============
+
+Description: LoRa MAC commands
+
+License: Revised BSD License, see LICENSE.TXT file include in the project
+
+Maintainer: Miguel Luis ( Semtech ), Daniel Jaeckle ( STACKFORCE ), Johannes Bruder ( STACKFORCE )
+*/
+#include
+
+#include "utilities.h"
+#include "LoRaMacCommands.h"
+#include "LoRaMacConfirmQueue.h"
+
+/*!
+ * Number of MAC Command slots
+ */
+#define NUM_OF_MAC_COMMANDS 15
+
+/*!
+ * Size of the CID field of MAC commands
+ */
+#define CID_FIELD_SIZE 1
+
+/*!
+ * Mac Commands list structure
+ */
+typedef struct sMacCommandsList
+{
+ /*
+ * First element of MAC command list.
+ */
+ MacCommand_t* First;
+ /*
+ * Last element of MAC command list.
+ */
+ MacCommand_t* Last;
+} MacCommandsList_t;
+
+/*!
+ * LoRaMac Commands Context structure
+ */
+typedef struct sLoRaMacCommandsCtx
+{
+ /*
+ * List of MAC command elements
+ */
+ MacCommandsList_t MacCommandList;
+ /*
+ * Buffer to store MAC command elements
+ */
+ MacCommand_t MacCommandSlots[NUM_OF_MAC_COMMANDS];
+ /*
+ * Size of all MAC commands serialized as buffer
+ */
+ size_t SerializedCmdsSize;
+} LoRaMacCommandsCtx_t;
+
+/*!
+ * Callback function to notify the upper layer about context change
+ */
+static LoRaMacCommandsNvmEvent CommandsNvmCtxChanged;
+
+/*!
+ * Non-volatile module context.
+ */
+static LoRaMacCommandsCtx_t NvmCtx;
+
+/* Memory management functions */
+
+/*!
+ * \brief Determines if a MAC command slot is free
+ *
+ * \param[IN] slot - Slot to check
+ * \retval - Status of the operation
+ */
+static bool IsSlotFree( const MacCommand_t* slot )
+{
+ uint8_t* mem = ( uint8_t* )slot;
+
+ for( uint16_t size = 0; size < sizeof( MacCommand_t ); size++ )
+ {
+ if( mem[size] != 0x00 )
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+/*!
+ * \brief Allocates a new MAC command memory slot
+ *
+ * \retval - Pointer to slot
+ */
+static MacCommand_t* MallocNewMacCommandSlot( void )
+{
+ uint8_t itr = 0;
+
+ while( IsSlotFree( ( const MacCommand_t* )&NvmCtx.MacCommandSlots[itr] ) == false )
+ {
+ itr++;
+ if( itr == NUM_OF_MAC_COMMANDS )
+ {
+ return NULL;
+ }
+ }
+
+ return &NvmCtx.MacCommandSlots[itr];
+}
+
+/*!
+ * \brief Free memory slot
+ *
+ * \param[IN] slot - Slot to free
+ *
+ * \retval - Status of the operation
+ */
+static bool FreeMacCommandSlot( MacCommand_t* slot )
+{
+ if( slot == NULL )
+ {
+ return false;
+ }
+
+ memset1( ( uint8_t* )slot, 0x00, sizeof( MacCommand_t ) );
+
+ return true;
+}
+
+/* Linked list functions */
+
+/*!
+ * \brief Initialize list
+ *
+ * \param[IN] list - List that shall be initialized
+ * \retval - Status of the operation
+ */
+static bool LinkedListInit( MacCommandsList_t* list )
+{
+ if( list == NULL )
+ {
+ return false;
+ }
+
+ list->First = NULL;
+ list->Last = NULL;
+
+ return true;
+}
+
+/*!
+ * \brief Add an element to the list
+ *
+ * \param[IN] list - List where the element shall be added.
+ * \param[IN] element - Element to add
+ * \retval - Status of the operation
+ */
+static bool LinkedListAdd( MacCommandsList_t* list, MacCommand_t* element )
+{
+ if( ( list == NULL ) || ( element == NULL ) )
+ {
+ return false;
+ }
+
+ // Check if this is the first entry to enter the list.
+ if( list->First == NULL )
+ {
+ list->First = element;
+ }
+
+ // Check if the last entry exists and update its next point.
+ if( list->Last )
+ {
+ list->Last->Next = element;
+ }
+
+ // Update the next point of this entry.
+ element->Next = NULL;
+
+ // Update the last entry of the list.
+ list->Last = element;
+
+ return true;
+}
+
+/*!
+ * \brief Return the previous element in the list.
+ *
+ * \param[IN] list - List
+ * \param[IN] element - Element where the previous element shall be searched
+ * \retval - Status of the operation
+ */
+static MacCommand_t* LinkedListGetPrevious( MacCommandsList_t* list, MacCommand_t* element )
+{
+ if( ( list == NULL ) || ( element == NULL ) )
+ {
+ return NULL;
+ }
+
+ MacCommand_t* curElement;
+
+ // Start at the head of the list
+ curElement = list->First;
+
+ // When current element is the first of the list, there's no previous element so we can return NULL immediately.
+ if( element != curElement )
+ {
+ // Loop through all elements until the end is reached or the next of current is the current element.
+ while( ( curElement != NULL ) && ( curElement->Next != element ) )
+ {
+ curElement = curElement->Next;
+ }
+ }
+ else
+ {
+ curElement = NULL;
+ }
+
+ return curElement;
+}
+
+/*!
+ * \brief Remove an element from the list
+ *
+ * \param[IN] list - List where the element shall be removed from.
+ * \param[IN] element - Element to remove
+ * \retval - Status of the operation
+ */
+static bool LinkedListRemove( MacCommandsList_t* list, MacCommand_t* element )
+{
+ if( ( list == NULL ) || ( element == NULL ) )
+ {
+ return false;
+ }
+
+ MacCommand_t* PrevElement = LinkedListGetPrevious( list, element );
+
+ if( list->First == element )
+ {
+ list->First = element->Next;
+ }
+
+ if( list->Last == element )
+ {
+ list->Last = PrevElement;
+ }
+
+ if( PrevElement != NULL )
+ {
+ PrevElement->Next = element->Next;
+ }
+
+ element->Next = NULL;
+
+ return true;
+}
+
+/*
+ * \brief Determines if a MAC command is sticky or not
+ *
+ * \param[IN] cid - MAC command identifier
+ *
+ * \retval - Status of the operation
+ */
+static bool IsSticky( uint8_t cid )
+{
+ switch( cid )
+ {
+ case MOTE_MAC_DL_CHANNEL_ANS:
+ case MOTE_MAC_RX_PARAM_SETUP_ANS:
+ case MOTE_MAC_RX_TIMING_SETUP_ANS:
+ return true;
+ default:
+ return false;
+ }
+}
+
+/*
+ * \brief Wrapper function for the NvmCtx
+ */
+static void NvmCtxCallback( void )
+{
+ if( CommandsNvmCtxChanged != NULL )
+ {
+ CommandsNvmCtxChanged( );
+ }
+}
+
+LoRaMacCommandStatus_t LoRaMacCommandsInit( LoRaMacCommandsNvmEvent commandsNvmCtxChanged )
+{
+ // Initialize with default
+ memset1( ( uint8_t* )&NvmCtx, 0, sizeof( NvmCtx ) );
+
+ LinkedListInit( &NvmCtx.MacCommandList );
+
+ // Assign callback
+ CommandsNvmCtxChanged = commandsNvmCtxChanged;
+
+ return LORAMAC_COMMANDS_SUCCESS;
+}
+
+LoRaMacCommandStatus_t LoRaMacCommandsRestoreNvmCtx( void* commandsNvmCtx )
+{
+ // Restore module context
+ if( commandsNvmCtx != NULL )
+ {
+ memcpy1( ( uint8_t* )&NvmCtx, ( uint8_t* )commandsNvmCtx, sizeof( NvmCtx ) );
+ return LORAMAC_COMMANDS_SUCCESS;
+ }
+ else
+ {
+ return LORAMAC_COMMANDS_ERROR_NPE;
+ }
+}
+
+void* LoRaMacCommandsGetNvmCtx( size_t* commandsNvmCtxSize )
+{
+ *commandsNvmCtxSize = sizeof( NvmCtx );
+ return &NvmCtx;
+}
+
+LoRaMacCommandStatus_t LoRaMacCommandsAddCmd( uint8_t cid, uint8_t* payload, size_t payloadSize )
+{
+ if( payload == NULL )
+ {
+ return LORAMAC_COMMANDS_ERROR_NPE;
+ }
+ MacCommand_t* newCmd;
+
+ // Allocate a memory slot
+ newCmd = MallocNewMacCommandSlot( );
+
+ if( newCmd == 0 )
+ {
+ return LORAMAC_COMMANDS_ERROR_MEMORY;
+ }
+
+ // Add it to the list of Mac commands
+ if( LinkedListAdd( &NvmCtx.MacCommandList, newCmd ) == false )
+ {
+ return LORAMAC_COMMANDS_ERROR;
+ }
+
+ // Set Values
+ newCmd->CID = cid;
+ newCmd->PayloadSize = payloadSize;
+ memcpy1( ( uint8_t* )newCmd->Payload, payload, payloadSize );
+ newCmd->IsSticky = IsSticky( cid );
+
+ NvmCtx.SerializedCmdsSize += ( CID_FIELD_SIZE + payloadSize );
+
+ NvmCtxCallback( );
+
+ return LORAMAC_COMMANDS_SUCCESS;
+}
+
+LoRaMacCommandStatus_t LoRaMacCommandsRemoveCmd( MacCommand_t* macCmd )
+{
+ if( macCmd == NULL )
+ {
+ return LORAMAC_COMMANDS_ERROR_NPE;
+ }
+
+ // Remove the Mac command element from MacCommandList
+ if( LinkedListRemove( &NvmCtx.MacCommandList, macCmd ) == false )
+ {
+ return LORAMAC_COMMANDS_ERROR_CMD_NOT_FOUND;
+ }
+
+ NvmCtx.SerializedCmdsSize -= ( CID_FIELD_SIZE + macCmd->PayloadSize );
+
+ // Free the MacCommand Slot
+ if( FreeMacCommandSlot( macCmd ) == false )
+ {
+ return LORAMAC_COMMANDS_ERROR;
+ }
+
+ NvmCtxCallback( );
+
+ return LORAMAC_COMMANDS_SUCCESS;
+}
+
+LoRaMacCommandStatus_t LoRaMacCommandsGetCmd( uint8_t cid, MacCommand_t** macCmd )
+{
+ MacCommand_t* curElement;
+
+ // Start at the head of the list
+ curElement = NvmCtx.MacCommandList.First;
+
+ // Loop through all elements until we find the element with the given CID
+ while( ( curElement != NULL ) && ( curElement->CID != cid ) )
+ {
+ curElement = curElement->Next;
+ }
+
+ // Update the pointer anyway
+ *macCmd = curElement;
+
+ // Handle error in case if we reached the end without finding it.
+ if( curElement == NULL )
+ {
+ return LORAMAC_COMMANDS_ERROR_CMD_NOT_FOUND;
+ }
+ return LORAMAC_COMMANDS_SUCCESS;
+}
+
+LoRaMacCommandStatus_t LoRaMacCommandsRemoveNoneStickyCmds( void )
+{
+ MacCommand_t* curElement;
+ MacCommand_t* nexElement;
+
+ // Start at the head of the list
+ curElement = NvmCtx.MacCommandList.First;
+
+ // Loop through all elements
+ while( curElement != NULL )
+ {
+ if( curElement->IsSticky == false )
+ {
+ nexElement = curElement->Next;
+ LoRaMacCommandsRemoveCmd( curElement );
+ curElement = nexElement;
+ }
+ else
+ {
+ curElement = curElement->Next;
+ }
+ }
+
+ NvmCtxCallback( );
+
+ return LORAMAC_COMMANDS_SUCCESS;
+}
+
+LoRaMacCommandStatus_t LoRaMacCommandsRemoveStickyAnsCmds( void )
+{
+ MacCommand_t* curElement;
+ MacCommand_t* nexElement;
+
+ // Start at the head of the list
+ curElement = NvmCtx.MacCommandList.First;
+
+ // Loop through all elements
+ while( curElement != NULL )
+ {
+ nexElement = curElement->Next;
+ if( IsSticky( curElement->CID ) == true )
+ {
+ LoRaMacCommandsRemoveCmd( curElement );
+ }
+ curElement = nexElement;
+ }
+
+ NvmCtxCallback( );
+
+ return LORAMAC_COMMANDS_SUCCESS;
+}
+
+LoRaMacCommandStatus_t LoRaMacCommandsGetSizeSerializedCmds( size_t* size )
+{
+ if( size == NULL )
+ {
+ return LORAMAC_COMMANDS_ERROR_NPE;
+ }
+ *size = NvmCtx.SerializedCmdsSize;
+ return LORAMAC_COMMANDS_SUCCESS;
+}
+
+LoRaMacCommandStatus_t LoRaMacCommandsSerializeCmds( size_t availableSize, size_t* effectiveSize, uint8_t* buffer )
+{
+ MacCommand_t* curElement = NvmCtx.MacCommandList.First;
+ MacCommand_t* nextElement;
+ uint8_t itr = 0;
+
+ if( ( buffer == NULL ) || ( effectiveSize == NULL ) )
+ {
+ return LORAMAC_COMMANDS_ERROR_NPE;
+ }
+
+ // Loop through all elements which fits into the buffer
+ while( curElement != NULL )
+ {
+ // If the next MAC command still fits into the buffer, add it.
+ if( ( availableSize - itr ) >= ( CID_FIELD_SIZE + curElement->PayloadSize ) )
+ {
+ buffer[itr++] = curElement->CID;
+ memcpy1( &buffer[itr], curElement->Payload, curElement->PayloadSize );
+ itr += curElement->PayloadSize;
+ }
+ else
+ {
+ break;
+ }
+ curElement = curElement->Next;
+ }
+
+ // Remove all commands which do not fit into the buffer
+ while( curElement != NULL )
+ {
+ // Store the next element before removing the current one
+ nextElement = curElement->Next;
+ LoRaMacCommandsRemoveCmd( curElement );
+ curElement = nextElement;
+ }
+
+ // Fetch the effective size of the mac commands
+ LoRaMacCommandsGetSizeSerializedCmds( effectiveSize );
+
+ return LORAMAC_COMMANDS_SUCCESS;
+}
+
+LoRaMacCommandStatus_t LoRaMacCommandsStickyCmdsPending( bool* cmdsPending )
+{
+ if( cmdsPending == NULL )
+ {
+ return LORAMAC_COMMANDS_ERROR_NPE;
+ }
+ MacCommand_t* curElement;
+ curElement = NvmCtx.MacCommandList.First;
+
+ *cmdsPending = false;
+
+ // Loop through all elements
+ while( curElement != NULL )
+ {
+ if( curElement->IsSticky == true )
+ {
+ // Found one sticky MAC command
+ *cmdsPending = true;
+ return LORAMAC_COMMANDS_SUCCESS;
+ }
+ curElement = curElement->Next;
+ }
+
+ return LORAMAC_COMMANDS_SUCCESS;
+}
diff --git a/lib/lora/mac/LoRaMacCommands.h b/lib/lora/mac/LoRaMacCommands.h
new file mode 100644
index 0000000000..ca147fd2ad
--- /dev/null
+++ b/lib/lora/mac/LoRaMacCommands.h
@@ -0,0 +1,227 @@
+/*!
+ * \file LoRaMacCommands.h
+ *
+ * \brief LoRa MAC commands
+ *
+ * \copyright Revised BSD License, see section \ref LICENSE.
+ *
+ * \code
+ * ______ _
+ * / _____) _ | |
+ * ( (____ _____ ____ _| |_ _____ ____| |__
+ * \____ \| ___ | (_ _) ___ |/ ___) _ \
+ * _____) ) ____| | | || |_| ____( (___| | | |
+ * (______/|_____)_|_|_| \__)_____)\____)_| |_|
+ * (C)2013 Semtech
+ *
+ * ___ _____ _ ___ _ _____ ___ ___ ___ ___
+ * / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
+ * \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
+ * |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
+ * embedded.connectivity.solutions===============
+ *
+ * \endcode
+ *
+ * \author Miguel Luis ( Semtech )
+ *
+ * \author Daniel Jaeckle ( STACKFORCE )
+ *
+ * \author Johannes Bruder ( STACKFORCE )
+ *
+ * addtogroup LORAMAC
+ * \{
+ *
+ */
+#ifndef __LORAMAC_COMMANDS_H__
+#define __LORAMAC_COMMANDS_H__
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include
+#include
+#include "LoRaMacTypes.h"
+
+
+/*
+ * Number of MAC Command slots
+ */
+#define LORAMAC_COMMADS_MAX_NUM_OF_PARAMS 2
+
+/*!
+ * LoRaWAN MAC Command element
+ */
+typedef struct sMacCommand MacCommand_t;
+
+struct sMacCommand
+{
+ /*!
+ * The pointer to the next MAC Command element in the list
+ */
+ MacCommand_t* Next;
+ /*!
+ * MAC command identifier
+ */
+ uint8_t CID;
+ /*!
+ * MAC command payload
+ */
+ uint8_t Payload[LORAMAC_COMMADS_MAX_NUM_OF_PARAMS];
+ /*!
+ * Size of MAC command payload
+ */
+ size_t PayloadSize;
+ /*!
+ * Indicates if it's a sticky MAC command
+ */
+ bool IsSticky;
+};
+
+/*!
+ * LoRaMac Commands Status
+ */
+typedef enum eLoRaMacCommandsStatus
+{
+ /*!
+ * No error occurred
+ */
+ LORAMAC_COMMANDS_SUCCESS = 0,
+ /*!
+ * Null pointer exception
+ */
+ LORAMAC_COMMANDS_ERROR_NPE,
+ /*!
+ * There is no memory left to add a further MAC command
+ */
+ LORAMAC_COMMANDS_ERROR_MEMORY,
+ /*!
+ * MAC command not found.
+ */
+ LORAMAC_COMMANDS_ERROR_CMD_NOT_FOUND,
+ /*!
+ * Unknown or corrupted command error occurred.
+ */
+ LORAMAC_COMMANDS_ERROR_UNKNOWN_CMD,
+ /*!
+ * Undefined Error occurred
+ */
+ LORAMAC_COMMANDS_ERROR,
+}LoRaMacCommandStatus_t;
+
+/*!
+ * Signature of callback function to be called by this module when the
+ * non-volatile needs to be saved.
+ */
+typedef void ( *LoRaMacCommandsNvmEvent )( void );
+
+/*!
+ * \brief Initialization of LoRaMac MAC commands module
+ *
+ * \param[IN] commandsNvmCtxChanged - Callback function which will be called when the
+ * non-volatile context needs to be saved.
+ *
+ * \retval - Status of the operation
+ */
+LoRaMacCommandStatus_t LoRaMacCommandsInit( LoRaMacCommandsNvmEvent commandsNvmCtxChanged );
+
+/*!
+ * Restores the internal non-volatile context from passed pointer.
+ *
+ * \param[IN] commandsNvmCtx - Pointer to non-volatile MAC commands module context to be restored.
+ *
+ * \retval - Status of the operation
+ */
+LoRaMacCommandStatus_t LoRaMacCommandsRestoreNvmCtx( void* commandsNvmCtx );
+
+/*!
+ * Returns a pointer to the internal non-volatile context.
+ *
+ * \param[IN] commandsNvmCtxSize - Size of the module non-volatile context
+ *
+ * \retval - Points to a structure where the module store its non-volatile context
+ */
+void* LoRaMacCommandsGetNvmCtx( size_t* commandsNvmCtxSize );
+
+/*!
+ * \brief Adds a new MAC command to be sent.
+ *
+ * \param[IN] cid - MAC command identifier
+ * \param[IN] payload - MAC command payload containing parameters
+ * \param[IN] payloadSize - Size of MAC command payload
+ *
+ * \retval - Status of the operation
+ */
+LoRaMacCommandStatus_t LoRaMacCommandsAddCmd( uint8_t cid, uint8_t* payload, size_t payloadSize );
+
+/*!
+ * \brief Remove a MAC command.
+ *
+ * \param[OUT] cmd - MAC command
+ *
+ * \retval - Status of the operation
+ */
+LoRaMacCommandStatus_t LoRaMacCommandsRemoveCmd( MacCommand_t* macCmd );
+
+/*!
+ * \brief Get the MAC command with corresponding CID.
+ *
+ * \param[IN] cid - MAC command identifier
+ * \param[OUT] cmd - MAC command
+ *
+ * \retval - Status of the operation
+ */
+LoRaMacCommandStatus_t LoRaMacCommandsGetCmd( uint8_t cid, MacCommand_t** macCmd );
+
+/*!
+ * \brief Remove all none sticky MAC commands.
+ *
+ * \retval - Status of the operation
+ */
+LoRaMacCommandStatus_t LoRaMacCommandsRemoveNoneStickyCmds( void );
+
+/*!
+ * \brief Remove all sticky answer MAC commands.
+ *
+ * \retval - Status of the operation
+ */
+LoRaMacCommandStatus_t LoRaMacCommandsRemoveStickyAnsCmds( void );
+
+/*!
+ * \brief Get size of all MAC commands serialized as buffer
+ *
+ * \param[out] size - Available size of memory for MAC commands
+ *
+ * \retval - Status of the operation
+ */
+LoRaMacCommandStatus_t LoRaMacCommandsGetSizeSerializedCmds( size_t* size );
+
+/*!
+ * \brief Get as many as possible MAC commands serialized
+ *
+ * \param[IN] availableSize - Available size of memory for MAC commands
+ * \param[out] effectiveSize - Size of memory which was effectively used for serializing.
+ * \param[out] buffer - Destination data buffer
+ *
+ * \retval - Status of the operation
+ */
+LoRaMacCommandStatus_t LoRaMacCommandsSerializeCmds( size_t availableSize, size_t* effectiveSize, uint8_t* buffer );
+
+/*!
+ * \brief Determines if there are sticky MAC commands pending.
+ *
+ * \param[IN] cmdsPending - Indicates if there are sticky MAC commands in the queue.
+ *
+ * \retval - Status of the operation
+ */
+LoRaMacCommandStatus_t LoRaMacCommandsStickyCmdsPending( bool* cmdsPending );
+
+/*! \} addtogroup LORAMAC */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // __LORAMAC_COMMANDS_H__
+
diff --git a/lib/lora/mac/LoRaMacConfirmQueue.c b/lib/lora/mac/LoRaMacConfirmQueue.c
new file mode 100644
index 0000000000..11698448bc
--- /dev/null
+++ b/lib/lora/mac/LoRaMacConfirmQueue.c
@@ -0,0 +1,344 @@
+/*
+ / _____) _ | |
+( (____ _____ ____ _| |_ _____ ____| |__
+ \____ \| ___ | (_ _) ___ |/ ___) _ \
+ _____) ) ____| | | || |_| ____( (___| | | |
+(______/|_____)_|_|_| \__)_____)\____)_| |_|
+ (C)2013 Semtech
+ ___ _____ _ ___ _ _____ ___ ___ ___ ___
+/ __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
+\__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
+|___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
+embedded.connectivity.solutions===============
+
+Description: LoRa MAC confirm queue implementation
+
+License: Revised BSD License, see LICENSE.TXT file include in the project
+
+Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jaeckle ( STACKFORCE )
+*/
+#include
+#include
+#include
+
+#include "timer.h"
+#include "utilities.h"
+#include "LoRaMac.h"
+#include "LoRaMacConfirmQueue.h"
+
+
+/*
+ * LoRaMac Confirm Queue Context NVM structure
+ */
+typedef struct sLoRaMacConfirmQueueNvmCtx
+{
+ /*!
+ * MlmeConfirm queue data structure
+ */
+ MlmeConfirmQueue_t MlmeConfirmQueue[LORA_MAC_MLME_CONFIRM_QUEUE_LEN];
+ /*!
+ * Counts the number of MlmeConfirms to process
+ */
+ uint8_t MlmeConfirmQueueCnt;
+ /*!
+ * Variable which holds a common status
+ */
+ LoRaMacEventInfoStatus_t CommonStatus;
+} LoRaMacConfirmQueueNvmCtx_t;
+
+/*
+ * LoRaMac Confirm Queue Context structure
+ */
+typedef struct sLoRaMacConfirmQueueCtx
+{
+ /*!
+ * LoRaMac callback function primitives
+ */
+ LoRaMacPrimitives_t* Primitives;
+ /*!
+ * Pointer to the first element of the ring buffer
+ */
+ MlmeConfirmQueue_t* BufferStart;
+ /*!
+ * Pointer to the last element of the ring buffer
+ */
+ MlmeConfirmQueue_t* BufferEnd;
+ /*
+ * Callback function to notify the upper layer about context change
+ */
+ LoRaMacConfirmQueueNvmEvent LoRaMacConfirmQueueNvmEvent;
+ /*!
+ * Non-volatile module context.
+ */
+ LoRaMacConfirmQueueNvmCtx_t* ConfirmQueueNvmCtx;
+} LoRaMacConfirmQueueCtx_t;
+
+/*
+ * Non-volatile module context.
+ */
+static LoRaMacConfirmQueueNvmCtx_t ConfirmQueueNvmCtx;
+
+/*
+ * Module context.
+ */
+static LoRaMacConfirmQueueCtx_t ConfirmQueueCtx;
+
+static MlmeConfirmQueue_t* IncreaseBufferPointer( MlmeConfirmQueue_t* bufferPointer )
+{
+ if( bufferPointer == &ConfirmQueueCtx.ConfirmQueueNvmCtx->MlmeConfirmQueue[LORA_MAC_MLME_CONFIRM_QUEUE_LEN - 1] )
+ {
+ // Reset to the first element
+ bufferPointer = ConfirmQueueCtx.ConfirmQueueNvmCtx->MlmeConfirmQueue;
+ }
+ else
+ {
+ // Increase
+ bufferPointer++;
+ }
+ return bufferPointer;
+}
+
+static MlmeConfirmQueue_t* DecreaseBufferPointer( MlmeConfirmQueue_t* bufferPointer )
+{
+ if( bufferPointer == ConfirmQueueCtx.ConfirmQueueNvmCtx->MlmeConfirmQueue )
+ {
+ // Reset to the last element
+ bufferPointer = &ConfirmQueueCtx.ConfirmQueueNvmCtx->MlmeConfirmQueue[LORA_MAC_MLME_CONFIRM_QUEUE_LEN - 1];
+ }
+ else
+ {
+ bufferPointer--;
+ }
+ return bufferPointer;
+}
+
+static MlmeConfirmQueue_t* GetElement( Mlme_t request, MlmeConfirmQueue_t* bufferStart, MlmeConfirmQueue_t* bufferEnd )
+{
+ MlmeConfirmQueue_t* element = bufferStart;
+
+ while( element != bufferEnd )
+ {
+ if( element->Request == request )
+ {
+ // We have found the element
+ return element;
+ }
+ else
+ {
+ element = IncreaseBufferPointer( element );
+ }
+ }
+ return NULL;
+}
+
+void LoRaMacConfirmQueueInit( LoRaMacPrimitives_t* primitives, LoRaMacConfirmQueueNvmEvent confirmQueueNvmCtxChanged )
+{
+ ConfirmQueueCtx.Primitives = primitives;
+
+ // Assign nvm context
+ ConfirmQueueCtx.ConfirmQueueNvmCtx = &ConfirmQueueNvmCtx;
+
+ // Init counter
+ ConfirmQueueCtx.ConfirmQueueNvmCtx->MlmeConfirmQueueCnt = 0;
+
+ // Init buffer
+ ConfirmQueueCtx.BufferStart = ConfirmQueueCtx.ConfirmQueueNvmCtx->MlmeConfirmQueue;
+ ConfirmQueueCtx.BufferEnd = ConfirmQueueCtx.ConfirmQueueNvmCtx->MlmeConfirmQueue;
+
+ memset1( ( uint8_t* )ConfirmQueueCtx.ConfirmQueueNvmCtx->MlmeConfirmQueue, 0xFF, sizeof( ConfirmQueueCtx.ConfirmQueueNvmCtx->MlmeConfirmQueue ) );
+
+ // Common status
+ ConfirmQueueCtx.ConfirmQueueNvmCtx->CommonStatus = LORAMAC_EVENT_INFO_STATUS_ERROR;
+
+ // Assign callback
+ ConfirmQueueCtx.LoRaMacConfirmQueueNvmEvent = confirmQueueNvmCtxChanged;
+}
+
+bool LoRaMacConfirmQueueRestoreNvmCtx( void* confirmQueueNvmCtx )
+{
+ // Restore module context
+ if( confirmQueueNvmCtx != NULL )
+ {
+ memcpy1( ( uint8_t* )&ConfirmQueueNvmCtx, ( uint8_t* ) confirmQueueNvmCtx, sizeof( ConfirmQueueNvmCtx ) );
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+void* LoRaMacConfirmQueueGetNvmCtx( size_t* confirmQueueNvmCtxSize )
+{
+ *confirmQueueNvmCtxSize = sizeof( ConfirmQueueNvmCtx );
+ return &ConfirmQueueNvmCtx;
+}
+
+bool LoRaMacConfirmQueueAdd( MlmeConfirmQueue_t* mlmeConfirm )
+{
+ if( ConfirmQueueCtx.ConfirmQueueNvmCtx->MlmeConfirmQueueCnt >= LORA_MAC_MLME_CONFIRM_QUEUE_LEN )
+ {
+ // Protect the buffer against overwrites
+ return false;
+ }
+
+ // Add the element to the ring buffer
+ ConfirmQueueCtx.BufferEnd->Request = mlmeConfirm->Request;
+ ConfirmQueueCtx.BufferEnd->Status = mlmeConfirm->Status;
+ ConfirmQueueCtx.BufferEnd->RestrictCommonReadyToHandle = mlmeConfirm->RestrictCommonReadyToHandle;
+ ConfirmQueueCtx.BufferEnd->ReadyToHandle = false;
+ // Increase counter
+ ConfirmQueueCtx.ConfirmQueueNvmCtx->MlmeConfirmQueueCnt++;
+ // Update end pointer
+ ConfirmQueueCtx.BufferEnd = IncreaseBufferPointer( ConfirmQueueCtx.BufferEnd );
+
+ return true;
+}
+
+bool LoRaMacConfirmQueueRemoveLast( void )
+{
+ if( ConfirmQueueCtx.ConfirmQueueNvmCtx->MlmeConfirmQueueCnt == 0 )
+ {
+ return false;
+ }
+
+ // Increase counter
+ ConfirmQueueCtx.ConfirmQueueNvmCtx->MlmeConfirmQueueCnt--;
+ // Update start pointer
+ ConfirmQueueCtx.BufferEnd = DecreaseBufferPointer( ConfirmQueueCtx.BufferEnd );
+
+ return true;
+}
+
+bool LoRaMacConfirmQueueRemoveFirst( void )
+{
+ if( ConfirmQueueCtx.ConfirmQueueNvmCtx->MlmeConfirmQueueCnt == 0 )
+ {
+ return false;
+ }
+
+ // Increase counter
+ ConfirmQueueCtx.ConfirmQueueNvmCtx->MlmeConfirmQueueCnt--;
+ // Update start pointer
+ ConfirmQueueCtx.BufferStart = IncreaseBufferPointer( ConfirmQueueCtx.BufferStart );
+
+ return true;
+}
+
+void LoRaMacConfirmQueueSetStatus( LoRaMacEventInfoStatus_t status, Mlme_t request )
+{
+ MlmeConfirmQueue_t* element = NULL;
+
+ if( ConfirmQueueCtx.ConfirmQueueNvmCtx->MlmeConfirmQueueCnt > 0 )
+ {
+ element = GetElement( request, ConfirmQueueCtx.BufferStart, ConfirmQueueCtx.BufferEnd );
+ if( element != NULL )
+ {
+ element->Status = status;
+ element->ReadyToHandle = true;
+ }
+ }
+}
+
+LoRaMacEventInfoStatus_t LoRaMacConfirmQueueGetStatus( Mlme_t request )
+{
+ MlmeConfirmQueue_t* element = NULL;
+
+ if( ConfirmQueueCtx.ConfirmQueueNvmCtx->MlmeConfirmQueueCnt > 0 )
+ {
+ element = GetElement( request, ConfirmQueueCtx.BufferStart, ConfirmQueueCtx.BufferEnd );
+ if( element != NULL )
+ {
+ return element->Status;
+ }
+ }
+ return LORAMAC_EVENT_INFO_STATUS_ERROR;
+}
+
+void LoRaMacConfirmQueueSetStatusCmn( LoRaMacEventInfoStatus_t status )
+{
+ MlmeConfirmQueue_t* element = ConfirmQueueCtx.BufferStart;
+
+ ConfirmQueueCtx.ConfirmQueueNvmCtx->CommonStatus = status;
+
+ if( ConfirmQueueCtx.ConfirmQueueNvmCtx->MlmeConfirmQueueCnt > 0 )
+ {
+ do
+ {
+ element->Status = status;
+ // Set the status if it is allowed to set it with a call to
+ // LoRaMacConfirmQueueSetStatusCmn.
+ if( element->RestrictCommonReadyToHandle == false )
+ {
+ element->ReadyToHandle = true;
+ }
+ element = IncreaseBufferPointer( element );
+ }while( element != ConfirmQueueCtx.BufferEnd );
+ }
+}
+
+LoRaMacEventInfoStatus_t LoRaMacConfirmQueueGetStatusCmn( void )
+{
+ return ConfirmQueueCtx.ConfirmQueueNvmCtx->CommonStatus;
+}
+
+bool LoRaMacConfirmQueueIsCmdActive( Mlme_t request )
+{
+ if( GetElement( request, ConfirmQueueCtx.BufferStart, ConfirmQueueCtx.BufferEnd ) != NULL )
+ {
+ return true;
+ }
+ return false;
+}
+
+void LoRaMacConfirmQueueHandleCb( MlmeConfirm_t* mlmeConfirm )
+{
+ uint8_t nbElements = ConfirmQueueCtx.ConfirmQueueNvmCtx->MlmeConfirmQueueCnt;
+ bool readyToHandle = false;
+ MlmeConfirmQueue_t mlmeConfirmToStore;
+
+ for( uint8_t i = 0; i < nbElements; i++ )
+ {
+ mlmeConfirm->MlmeRequest = ConfirmQueueCtx.BufferStart->Request;
+ mlmeConfirm->Status = ConfirmQueueCtx.BufferStart->Status;
+ readyToHandle = ConfirmQueueCtx.BufferStart->ReadyToHandle;
+
+ if( readyToHandle == true )
+ {
+ ConfirmQueueCtx.Primitives->MacMlmeConfirm( mlmeConfirm );
+ }
+ else
+ {
+ // The request is not processed yet. Store the state.
+ mlmeConfirmToStore.Request = ConfirmQueueCtx.BufferStart->Request;
+ mlmeConfirmToStore.Status = ConfirmQueueCtx.BufferStart->Status;
+ mlmeConfirmToStore.RestrictCommonReadyToHandle = ConfirmQueueCtx.BufferStart->RestrictCommonReadyToHandle;
+ }
+
+ // Increase the pointer afterwards to prevent overwrites
+ LoRaMacConfirmQueueRemoveFirst( );
+
+ if( readyToHandle == false )
+ {
+ // Add a request which has not been finished again to the queue
+ LoRaMacConfirmQueueAdd( &mlmeConfirmToStore );
+ }
+ }
+}
+
+uint8_t LoRaMacConfirmQueueGetCnt( void )
+{
+ return ConfirmQueueCtx.ConfirmQueueNvmCtx->MlmeConfirmQueueCnt;
+}
+
+bool LoRaMacConfirmQueueIsFull( void )
+{
+ if( ConfirmQueueCtx.ConfirmQueueNvmCtx->MlmeConfirmQueueCnt >= LORA_MAC_MLME_CONFIRM_QUEUE_LEN )
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
diff --git a/lib/lora/mac/LoRaMacConfirmQueue.h b/lib/lora/mac/LoRaMacConfirmQueue.h
new file mode 100644
index 0000000000..b572be4f40
--- /dev/null
+++ b/lib/lora/mac/LoRaMacConfirmQueue.h
@@ -0,0 +1,204 @@
+/*!
+ * \file LoRaMacConfirmQueue.h
+ *
+ * \brief LoRa MAC confirm queue implementation
+ *
+ * \copyright Revised BSD License, see section \ref LICENSE.
+ *
+ * \code
+ * ______ _
+ * / _____) _ | |
+ * ( (____ _____ ____ _| |_ _____ ____| |__
+ * \____ \| ___ | (_ _) ___ |/ ___) _ \
+ * _____) ) ____| | | || |_| ____( (___| | | |
+ * (______/|_____)_|_|_| \__)_____)\____)_| |_|
+ * (C)2013 Semtech
+ *
+ * ___ _____ _ ___ _ _____ ___ ___ ___ ___
+ * / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
+ * \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
+ * |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
+ * embedded.connectivity.solutions===============
+ *
+ * \endcode
+ *
+ * \author Miguel Luis ( Semtech )
+ *
+ * \author Gregory Cristian ( Semtech )
+ *
+ * \author Daniel Jaeckle ( STACKFORCE )
+ *
+ * \defgroup LORAMACCONFIRMQUEUE LoRa MAC confirm queue implementation
+ * This module specifies the API implementation of the LoRaMAC confirm queue.
+ * The confirm queue is implemented with as a ring buffer. The number of
+ * elements can be defined with \ref LORA_MAC_MLME_CONFIRM_QUEUE_LEN. The
+ * current implementation does not support multiple elements of the same
+ * Mlme_t type.
+ * \{
+ */
+#ifndef __LORAMAC_CONFIRMQUEUE_H__
+#define __LORAMAC_CONFIRMQUEUE_H__
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include
+#include
+
+#include "LoRaMac.h"
+
+/*!
+ * LoRaMac MLME-Confirm queue length
+ */
+#define LORA_MAC_MLME_CONFIRM_QUEUE_LEN 5
+
+/*!
+ * Structure to hold multiple MLME request confirm data
+ */
+typedef struct sMlmeConfirmQueue
+{
+ /*!
+ * Holds the previously performed MLME-Request
+ */
+ Mlme_t Request;
+ /*!
+ * Status of the operation
+ */
+ LoRaMacEventInfoStatus_t Status;
+ /*!
+ * Set to true, if the request is ready to be handled
+ */
+ bool ReadyToHandle;
+ /*!
+ * Set to true, if it is not permitted to set the ReadyToHandle variable
+ * with a function call to LoRaMacConfirmQueueSetStatusCmn.
+ */
+ bool RestrictCommonReadyToHandle;
+}MlmeConfirmQueue_t;
+
+/*!
+ * Signature of callback function to be called by this module when the
+ * non-volatile needs to be saved.
+ */
+typedef void ( *LoRaMacConfirmQueueNvmEvent )( void );
+
+/*!
+ * \brief Initializes the confirm queue
+ *
+ * \param [IN] primitives - Pointer to the LoRaMac primitives.
+ *
+ * \param [IN] confirmQueueNvmCtxChanged - Callback function which will be called when the
+ * non-volatile context needs to be saved.
+ */
+void LoRaMacConfirmQueueInit( LoRaMacPrimitives_t* primitives, LoRaMacConfirmQueueNvmEvent confirmQueueNvmCtxChanged );
+
+/*!
+ * Restores the internal non-volatile context from passed pointer.
+ *
+ * \param [IN] confirmQueueNvmCtx - Pointer to non-volatile class B module context to be restored.
+ *
+ * \retval [true - operation was successful, false - operation failed]
+ */
+bool LoRaMacConfirmQueueRestoreNvmCtx( void* confirmQueueNvmCtx );
+
+/*!
+ * Returns a pointer to the internal non-volatile context.
+ *
+ * \param [IN] confirmQueueNvmCtxSize - Size of the module non-volatile context
+ *
+ * \retval - Points to a structure where the module store its non-volatile context
+ */
+void* LoRaMacConfirmQueueGetNvmCtx( size_t* confirmQueueNvmCtxSize );
+
+/*!
+ * \brief Adds an element to the confirm queue.
+ *
+ * \param [IN] mlmeConfirm - Pointer to the element to add.
+ *
+ * \retval [true - operation was successful, false - operation failed]
+ */
+bool LoRaMacConfirmQueueAdd( MlmeConfirmQueue_t* mlmeConfirm );
+
+/*!
+ * \brief Removes the last element which was added into the queue.
+ *
+ * \retval [true - operation was successful, false - operation failed]
+ */
+bool LoRaMacConfirmQueueRemoveLast( void );
+
+/*!
+ * \brief Removes the first element which was added to the confirm queue.
+ *
+ * \retval [true - operation was successful, false - operation failed]
+ */
+bool LoRaMacConfirmQueueRemoveFirst( void );
+
+/*!
+ * \brief Sets the status of an element.
+ *
+ * \param [IN] status - The status to set.
+ *
+ * \param [IN] request - The related request to set the status.
+ */
+void LoRaMacConfirmQueueSetStatus( LoRaMacEventInfoStatus_t status, Mlme_t request );
+
+/*!
+ * \brief Gets the status of an element.
+ *
+ * \param [IN] request - The request to query the status.
+ *
+ * \retval The status of the related MlmeRequest.
+ */
+LoRaMacEventInfoStatus_t LoRaMacConfirmQueueGetStatus( Mlme_t request );
+
+/*!
+ * \brief Sets a common status for all elements in the queue.
+ *
+ * \param [IN] status - The status to set.
+ */
+void LoRaMacConfirmQueueSetStatusCmn( LoRaMacEventInfoStatus_t status );
+
+/*!
+ * \brief Gets the common status of all elements.
+ *
+ * \retval The common status of all elements.
+ */
+LoRaMacEventInfoStatus_t LoRaMacConfirmQueueGetStatusCmn( void );
+
+/*!
+ * \brief Verifies if a request is in the queue and active.
+ *
+ * \param [IN] request - The request to verify.
+ *
+ * \retval [true - element is in the queue, false - element is not in the queue].
+ */
+bool LoRaMacConfirmQueueIsCmdActive( Mlme_t request );
+
+/*!
+ * \brief Handles all callbacks of active requests
+ *
+ * \param [IN] mlmeConfirm - Pointer to the generic mlmeConfirm structure.
+ */
+void LoRaMacConfirmQueueHandleCb( MlmeConfirm_t* mlmeConfirm );
+
+/*!
+ * \brief Query number of elements in the queue.
+ *
+ * \retval Number of elements.
+ */
+uint8_t LoRaMacConfirmQueueGetCnt( void );
+
+/*!
+ * \brief Verify if the confirm queue is full.
+ *
+ * \retval [true - queue is full, false - queue is not full].
+ */
+bool LoRaMacConfirmQueueIsFull( void );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // __LORAMAC_CONFIRMQUEUE_H__
diff --git a/lib/lora/mac/LoRaMacCrypto.c b/lib/lora/mac/LoRaMacCrypto.c
index 38420762ae..2e2d22c6f8 100644
--- a/lib/lora/mac/LoRaMacCrypto.c
+++ b/lib/lora/mac/LoRaMacCrypto.c
@@ -1,202 +1,1693 @@
-/*
- / _____) _ | |
-( (____ _____ ____ _| |_ _____ ____| |__
- \____ \| ___ | (_ _) ___ |/ ___) _ \
- _____) ) ____| | | || |_| ____( (___| | | |
-(______/|_____)_|_|_| \__)_____)\____)_| |_|
- (C)2013 Semtech
- ___ _____ _ ___ _ _____ ___ ___ ___ ___
-/ __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
-\__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
-|___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
-embedded.connectivity.solutions===============
-
-Description: LoRa MAC layer implementation
-
-License: Revised BSD License, see LICENSE.TXT file include in the project
-
-Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jaeckle ( STACKFORCE )
-*/
+/*!
+ * \file LoRaMacCrypto.c
+ *
+ * \brief LoRa MAC layer cryptography implementation
+ *
+ * \copyright Revised BSD License, see section \ref LICENSE.
+ *
+ * \code
+ * ______ _
+ * / _____) _ | |
+ * ( (____ _____ ____ _| |_ _____ ____| |__
+ * \____ \| ___ | (_ _) ___ |/ ___) _ \
+ * _____) ) ____| | | || |_| ____( (___| | | |
+ * (______/|_____)_|_|_| \__)_____)\____)_| |_|
+ * (C)2013-2017 Semtech
+ *
+ * ___ _____ _ ___ _ _____ ___ ___ ___ ___
+ * / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
+ * \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
+ * |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
+ * embedded.connectivity.solutions===============
+ *
+ * \endcode
+ *
+ * \author Miguel Luis ( Semtech )
+ *
+ * \author Gregory Cristian ( Semtech )
+ *
+ * \author Daniel Jaeckle ( STACKFORCE )
+ *
+ * \author Johannes Bruder ( STACKFORCE )
+ */
+#include
#include
#include
-#include "utilities.h"
-#include "lora/system/crypto/aes.h"
-#include "lora/system/crypto/cmac.h"
+#include "utilities.h"
+#include "secure-element.h"
+#include "LoRaMacParser.h"
+#include "LoRaMacSerializer.h"
#include "LoRaMacCrypto.h"
/*!
- * CMAC/AES Message Integrity Code (MIC) Block B0 size
+ * Indicates if LoRaWAN 1.1.x crypto scheme is enabled
*/
-#define LORAMAC_MIC_BLOCK_B0_SIZE 16
+#define USE_LRWAN_1_1_X_CRYPTO 0
/*!
- * MIC field computation initial data
+ * Indicates if a random devnonce must be used or not
*/
-static uint8_t MicBlockB0[] = { 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
- };
+#define USE_RANDOM_DEV_NONCE 1
-/*!
- * Contains the computed MIC field.
- *
- * \remark Only the 4 first bytes are used
+/*
+ * Frame direction definition for uplink communications
*/
-static uint8_t Mic[16];
+#define UPLINK 0
-/*!
- * Encryption aBlock and sBlock
+/*
+ * Frame direction definition for downlink communications
*/
-static uint8_t aBlock[] = { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
- };
-static uint8_t sBlock[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
- };
+#define DOWNLINK 1
-/*!
- * AES computation context variable
+/*
+ * CMAC/AES Message Integrity Code (MIC) Block B0 size
*/
-static aes_context AesContext;
+#define MIC_BLOCK_BX_SIZE 16
-/*!
- * CMAC computation context variable
+/*
+ * Size of JoinReqType is field for integrity check
*/
-static AES_CMAC_CTX AesCmacCtx[1];
+#define JOIN_REQ_TYPE_SIZE 1
-/*!
- * \brief Computes the LoRaMAC frame MIC field
- *
- * \param [IN] buffer Data buffer
- * \param [IN] size Data buffer size
- * \param [IN] key AES key to be used
- * \param [IN] address Frame address
- * \param [IN] dir Frame direction [0: uplink, 1: downlink]
- * \param [IN] sequenceCounter Frame sequence counter
- * \param [OUT] mic Computed MIC field
+/*
+ * Size of DevNonce is field for integrity check
*/
-void LoRaMacComputeMic( const uint8_t *buffer, uint16_t size, const uint8_t *key, uint32_t address, uint8_t dir, uint32_t sequenceCounter, uint32_t *mic )
-{
- MicBlockB0[5] = dir;
+#define DEV_NONCE_SIZE 2
- MicBlockB0[6] = ( address ) & 0xFF;
- MicBlockB0[7] = ( address >> 8 ) & 0xFF;
- MicBlockB0[8] = ( address >> 16 ) & 0xFF;
- MicBlockB0[9] = ( address >> 24 ) & 0xFF;
+/*
+ * Number of security context entries
+ */
+#define NUM_OF_SEC_CTX 5
+
+/*
+ * Size of the module context
+ */
+#define CRYPTO_CTX_SIZE sizeof( LoRaMacCryptoCtx_t )
+
+/*
+ * Size of the module non volatile context
+ */
+#define CRYPTO_NVM_CTX_SIZE sizeof( LoRaMacCryptoNvmCtx_t )
- MicBlockB0[10] = ( sequenceCounter ) & 0xFF;
- MicBlockB0[11] = ( sequenceCounter >> 8 ) & 0xFF;
- MicBlockB0[12] = ( sequenceCounter >> 16 ) & 0xFF;
- MicBlockB0[13] = ( sequenceCounter >> 24 ) & 0xFF;
+/*
+ * Maximum size of the message that can be handled by the crypto operations
+ */
+#define CRYPTO_MAXMESSAGE_SIZE 256
+
+/*
+ * Maximum size of the buffer for crypto operations
+ */
+#define CRYPTO_BUFFER_SIZE CRYPTO_MAXMESSAGE_SIZE + MIC_BLOCK_BX_SIZE
- MicBlockB0[15] = size & 0xFF;
+/*
+ * MIC computaion offset
+ */
+#define CRYPTO_MIC_COMPUTATION_OFFSET JOIN_REQ_TYPE_SIZE + LORAMAC_JOIN_EUI_FIELD_SIZE + DEV_NONCE_SIZE + LORAMAC_MHDR_FIELD_SIZE
- AES_CMAC_Init( AesCmacCtx );
+/*!
+ * LoRaWAN Frame counter list.
+ */
+typedef struct sFCntList
+{
+ /*!
+ * Uplink frame counter which is incremented with each uplink.
+ */
+ uint32_t FCntUp;
+ /*!
+ * Network downlink frame counter which is incremented with each downlink on FPort 0
+ * or when the FPort field is missing.
+ */
+ uint32_t NFCntDown;
+ /*!
+ * Application downlink frame counter which is incremented with each downlink
+ * on a port different than 0.
+ */
+ uint32_t AFCntDown;
+ /*!
+ * In case if the device is connected to a LoRaWAN 1.0 Server,
+ * this counter is used for every kind of downlink frame.
+ */
+ uint32_t FCntDown;
+ /*!
+ * Multicast downlink counter for index 0
+ */
+ uint32_t McFCntDown0;
+ /*!
+ * Multicast downlink counter for index 1
+ */
+ uint32_t McFCntDown1;
+ /*!
+ * Multicast downlink counter for index 2
+ */
+ uint32_t McFCntDown2;
+ /*!
+ * Multicast downlink counter for index 3
+ */
+ uint32_t McFCntDown3;
+}FCntList_t;
- AES_CMAC_SetKey( AesCmacCtx, key );
+/*
+ * LoRaMac Crypto Non Volatile Context structure
+ */
+typedef struct sLoRaMacCryptoNvmCtx
+{
+ /*
+ * Stores the information if the device is connected to a LoRaWAN network
+ * server with prior to 1.1.0 implementation.
+ */
+ Version_t LrWanVersion;
+ /*
+ * Device nonce is a counter starting at 0 when the device is initially
+ * powered up and incremented with every JoinRequest.
+ */
+ uint16_t DevNonce;
+ /*
+ * JoinNonce is a device specific counter value (that never repeats itself)
+ * provided by the join server and incremented with every JoinAccept message.
+ */
+ uint32_t JoinNonce;
+ /*
+ * Frame counter list
+ */
+ FCntList_t FCntList;
+ /*
+ * RJcount1 is a counter incremented with every Rejoin request Type 1 frame transmitted.
+ */
+ uint16_t RJcount1;
+ /*
+ * LastDownFCnt stores the information which frame counter was used to unsecure the last frame.
+ * This information is needed to compute ConfFCnt in B1 block for the MIC.
+ */
+ uint32_t* LastDownFCnt;
+}LoRaMacCryptoNvmCtx_t;
- AES_CMAC_Update( AesCmacCtx, MicBlockB0, LORAMAC_MIC_BLOCK_B0_SIZE );
+/*
+ * LoRaMac Crypto Context structure
+ */
+typedef struct sLoRaMacCryptoCtx
+{
+ /*
+ * RJcount0 is a counter incremented with every Type 0 or 2 Rejoin frame transmitted.
+ */
+ uint16_t RJcount0;
+ /*
+ * Non volatile module context structure
+ */
+ LoRaMacCryptoNvmCtx_t* NvmCtx;
+ /*
+ * Callback function to notify the upper layer about context change
+ */
+ LoRaMacCryptoNvmEvent EventCryptoNvmCtxChanged;
+}LoRaMacCryptoCtx_t;
- AES_CMAC_Update( AesCmacCtx, buffer, size & 0xFF );
+/*
+ * Key-Address item
+ */
+typedef struct sKeyAddr
+{
+ /*
+ * Address identifier
+ */
+ AddressIdentifier_t AddrID;
+ /*
+ * Application session key
+ */
+ KeyIdentifier_t AppSkey;
+ /*
+ * Network session key
+ */
+ KeyIdentifier_t NwkSkey;
+ /*
+ * Rootkey (Multicast only)
+ */
+ KeyIdentifier_t RootKey;
+}KeyAddr_t;
- AES_CMAC_Final( Mic, AesCmacCtx );
+/*
+ *Crypto module context.
+ */
+static LoRaMacCryptoCtx_t CryptoCtx;
- *mic = ( uint32_t )( ( uint32_t )Mic[3] << 24 | ( uint32_t )Mic[2] << 16 | ( uint32_t )Mic[1] << 8 | ( uint32_t )Mic[0] );
-}
+/*
+ * Non volatile module context.
+ */
+static LoRaMacCryptoNvmCtx_t NvmCryptoCtx;
-void LoRaMacPayloadEncrypt( const uint8_t *buffer, uint16_t size, const uint8_t *key, uint32_t address, uint8_t dir, uint32_t sequenceCounter, uint8_t *encBuffer )
+/*
+ * Key-Address list
+ */
+static KeyAddr_t KeyAddrList[NUM_OF_SEC_CTX] =
+ {
+ { MULTICAST_0_ADDR, MC_APP_S_KEY_0, MC_NWK_S_KEY_0, MC_KEY_0 },
+ { MULTICAST_1_ADDR, MC_APP_S_KEY_1, MC_NWK_S_KEY_1, MC_KEY_1 },
+ { MULTICAST_2_ADDR, MC_APP_S_KEY_2, MC_NWK_S_KEY_2, MC_KEY_2 },
+ { MULTICAST_3_ADDR, MC_APP_S_KEY_3, MC_NWK_S_KEY_3, MC_KEY_3 },
+ { UNICAST_DEV_ADDR, APP_S_KEY, S_NWK_S_INT_KEY, NO_KEY }
+ };
+
+/*
+ * Local functions
+ */
+
+/*
+ * Encrypts the payload
+ *
+ * \param[IN] keyID - Key identifier
+ * \param[IN] address - Address
+ * \param[IN] dir - Frame direction ( Uplink or Downlink )
+ * \param[IN] frameCounter - Frame counter
+ * \param[IN] size - Size of data
+ * \param[IN/OUT] buffer - Data buffer
+ * \retval - Status of the operation
+ */
+static LoRaMacCryptoStatus_t PayloadEncrypt( uint8_t* buffer, int16_t size, KeyIdentifier_t keyID, uint32_t address, uint8_t dir, uint32_t frameCounter )
{
- uint16_t i;
+ if( buffer == 0 )
+ {
+ return LORAMAC_CRYPTO_ERROR_NPE;
+ }
+
uint8_t bufferIndex = 0;
uint16_t ctr = 1;
+ uint8_t sBlock[16] = { 0 };
+ uint8_t aBlock[16] = { 0 };
- memset1( AesContext.ksch, '\0', 240 );
- aes_set_key_lora( key, 16, &AesContext );
+ aBlock[0] = 0x01;
aBlock[5] = dir;
- aBlock[6] = ( address ) & 0xFF;
+ aBlock[6] = address & 0xFF;
aBlock[7] = ( address >> 8 ) & 0xFF;
aBlock[8] = ( address >> 16 ) & 0xFF;
aBlock[9] = ( address >> 24 ) & 0xFF;
- aBlock[10] = ( sequenceCounter ) & 0xFF;
- aBlock[11] = ( sequenceCounter >> 8 ) & 0xFF;
- aBlock[12] = ( sequenceCounter >> 16 ) & 0xFF;
- aBlock[13] = ( sequenceCounter >> 24 ) & 0xFF;
+ aBlock[10] = frameCounter & 0xFF;
+ aBlock[11] = ( frameCounter >> 8 ) & 0xFF;
+ aBlock[12] = ( frameCounter >> 16 ) & 0xFF;
+ aBlock[13] = ( frameCounter >> 24 ) & 0xFF;
- while( size >= 16 )
+ while( size > 0 )
{
- aBlock[15] = ( ( ctr ) & 0xFF );
+ aBlock[15] = ctr & 0xFF;
ctr++;
- aes_encrypt_lora( aBlock, sBlock, &AesContext );
- for( i = 0; i < 16; i++ )
+ if( SecureElementAesEncrypt( aBlock, 16, keyID, sBlock ) != SECURE_ELEMENT_SUCCESS )
+ {
+ return LORAMAC_CRYPTO_ERROR_SECURE_ELEMENT_FUNC;
+ }
+
+ for( uint8_t i = 0; i < ( ( size > 16 ) ? 16 : size ); i++ )
{
- encBuffer[bufferIndex + i] = buffer[bufferIndex + i] ^ sBlock[i];
+ buffer[bufferIndex + i] = buffer[bufferIndex + i] ^ sBlock[i];
}
size -= 16;
bufferIndex += 16;
}
+ return LORAMAC_CRYPTO_SUCCESS;
+}
+
+#if( USE_LRWAN_1_1_X_CRYPTO == 1 )
+/*
+ * Encrypts the FOpts
+ *
+ * \param[IN] address - Address
+ * \param[IN] dir - Frame direction ( Uplink or Downlink )
+ * \param[IN] fCntID - Frame counter identifier
+ * \param[IN] frameCounter - Frame counter
+ * \param[IN] size - Size of data
+ * \param[IN/OUT] buffer - Data buffer
+ * \retval - Status of the operation
+ */
+static LoRaMacCryptoStatus_t FOptsEncrypt( uint16_t size, uint32_t address, uint8_t dir, FCntIdentifier_t fCntID, uint32_t frameCounter, uint8_t* buffer )
+{
+ if( buffer == 0 )
+ {
+ return LORAMAC_CRYPTO_ERROR_NPE;
+ }
+
+ uint8_t bufferIndex = 0;
+ uint8_t sBlock[16] = { 0 };
+ uint8_t aBlock[16] = { 0 };
+
+ aBlock[0] = 0x01;
+
+ if( CryptoCtx.NvmCtx->LrWanVersion.Value > 0x01010000 )
+ {
+ // Introduced in LoRaWAN 1.1.1 specification
+ switch( fCntID )
+ {
+ case FCNT_UP:
+ {
+ aBlock[4] = 0x01;
+ break;
+ }
+ case N_FCNT_DOWN:
+ {
+ aBlock[4] = 0x01;
+ break;
+ }
+ case A_FCNT_DOWN:
+ {
+ aBlock[4] = 0x02;
+ break;
+ }
+ default:
+ return LORAMAC_CRYPTO_FAIL_PARAM;
+ }
+ }
+
+ aBlock[5] = dir;
+
+ aBlock[6] = address & 0xFF;
+ aBlock[7] = ( address >> 8 ) & 0xFF;
+ aBlock[8] = ( address >> 16 ) & 0xFF;
+ aBlock[9] = ( address >> 24 ) & 0xFF;
+
+ aBlock[10] = frameCounter & 0xFF;
+ aBlock[11] = ( frameCounter >> 8 ) & 0xFF;
+ aBlock[12] = ( frameCounter >> 16 ) & 0xFF;
+ aBlock[13] = ( frameCounter >> 24 ) & 0xFF;
+
+ if( CryptoCtx.NvmCtx->LrWanVersion.Value > 0x01010000 )
+ {
+ // Introduced in LoRaWAN 1.1.1 specification
+ aBlock[15] = 0x01;
+ }
+
if( size > 0 )
{
- aBlock[15] = ( ( ctr ) & 0xFF );
- aes_encrypt_lora( aBlock, sBlock, &AesContext );
- for( i = 0; i < size; i++ )
+ if( SecureElementAesEncrypt( aBlock, 16, NWK_S_ENC_KEY, sBlock ) != SECURE_ELEMENT_SUCCESS )
+ {
+ return LORAMAC_CRYPTO_ERROR_SECURE_ELEMENT_FUNC;
+ }
+ for( uint8_t i = 0; i < size; i++ )
{
- encBuffer[bufferIndex + i] = buffer[bufferIndex + i] ^ sBlock[i];
+ buffer[bufferIndex + i] = buffer[bufferIndex + i] ^ sBlock[i];
}
}
+
+ return LORAMAC_CRYPTO_SUCCESS;
+}
+#endif
+
+/*
+ * Prepares B0 block for cmac computation.
+ *
+ * \param[IN] msgLen - Length of message
+ * \param[IN] keyID - Key identifier
+ * \param[IN] isAck - True if it is a acknowledge frame ( Sets ConfFCnt in B0 block )
+ * \param[IN] devAddr - Device address
+ * \param[IN] dir - Frame direction ( Uplink:0, Downlink:1 )
+ * \param[IN] fCnt - Frame counter
+ * \param[IN/OUT] b0 - B0 block
+ * \retval - Status of the operation
+ */
+static LoRaMacCryptoStatus_t PrepareB0( uint16_t msgLen, KeyIdentifier_t keyID, bool isAck, uint8_t dir, uint32_t devAddr, uint32_t fCnt, uint8_t* b0 )
+{
+ if( b0 == 0 )
+ {
+ return LORAMAC_CRYPTO_ERROR_NPE;
+ }
+
+ b0[0] = 0x49;
+
+ if( ( isAck == true ) && ( dir == DOWNLINK ) )
+ {
+ // confFCnt contains the frame counter value modulo 2^16 of the "confirmed" uplink or downlink frame that is being acknowledged
+ uint16_t confFCnt = 0;
+
+ confFCnt = ( uint16_t )( CryptoCtx.NvmCtx->FCntList.FCntUp % 65536 );
+
+ b0[1] = confFCnt & 0xFF;
+ b0[2] = ( confFCnt >> 8 ) & 0xFF;
+ }
+ else
+ {
+ b0[1] = 0x00;
+ b0[2] = 0x00;
+ }
+
+ b0[3] = 0x00;
+ b0[4] = 0x00;
+
+ b0[5] = dir;
+
+ b0[6] = devAddr & 0xFF;
+ b0[7] = ( devAddr >> 8 ) & 0xFF;
+ b0[8] = ( devAddr >> 16 ) & 0xFF;
+ b0[9] = ( devAddr >> 24 ) & 0xFF;
+
+ b0[10] = fCnt & 0xFF;
+ b0[11] = ( fCnt >> 8 ) & 0xFF;
+ b0[12] = ( fCnt >> 16 ) & 0xFF;
+ b0[13] = ( fCnt >> 24 ) & 0xFF;
+
+ b0[14] = 0x00;
+
+ b0[15] = msgLen & 0xFF;
+
+ return LORAMAC_CRYPTO_SUCCESS;
+}
+
+/*
+ * Computes cmac with adding B0 block in front.
+ *
+ * cmac = aes128_cmac(keyID, B0 | msg)
+ *
+ * \param[IN] msg - Message to compute the integrity code
+ * \param[IN] len - Length of message
+ * \param[IN] keyID - Key identifier
+ * \param[IN] isAck - True if it is a acknowledge frame ( Sets ConfFCnt in B0 block )
+ * \param[IN] devAddr - Device address
+ * \param[IN] dir - Frame direction ( Uplink:0, Downlink:1 )
+ * \param[IN] fCnt - Frame counter
+ * \param[OUT] cmac - Computed cmac
+ * \retval - Status of the operation
+ */
+static LoRaMacCryptoStatus_t ComputeCmacB0( uint8_t* msg, uint16_t len, KeyIdentifier_t keyID, bool isAck, uint8_t dir, uint32_t devAddr, uint32_t fCnt, uint32_t* cmac )
+{
+ if( ( msg == 0 ) || ( cmac == 0 ) )
+ {
+ return LORAMAC_CRYPTO_ERROR_NPE;
+ }
+ if( len > CRYPTO_MAXMESSAGE_SIZE )
+ {
+ return LORAMAC_CRYPTO_ERROR_BUF_SIZE;
+ }
+
+ uint8_t micBuff[MIC_BLOCK_BX_SIZE];
+
+ // Initialize the first Block
+ PrepareB0( len, keyID, isAck, dir, devAddr, fCnt, micBuff );
+
+ if( SecureElementComputeAesCmac( micBuff, msg, len, keyID, cmac ) != SECURE_ELEMENT_SUCCESS )
+ {
+ return LORAMAC_CRYPTO_ERROR_SECURE_ELEMENT_FUNC;
+ }
+ return LORAMAC_CRYPTO_SUCCESS;
+}
+
+/*!
+ * Verifies cmac with adding B0 block in front.
+ *
+ * \param[IN] msg - Message to compute the integrity code
+ * \param[IN] len - Length of message
+ * \param[IN] keyID - Key identifier
+ * \param[IN] isAck - True if it is a acknowledge frame ( Sets ConfFCnt in B0 block )
+ * \param[IN] devAddr - Device address
+ * \param[IN] dir - Frame direction ( Uplink:0, Downlink:1 )
+ * \param[IN] fCnt - Frame counter
+ * \param[in] expectedCmac - Expected cmac
+ * \retval - Status of the operation
+ */
+static LoRaMacCryptoStatus_t VerifyCmacB0( uint8_t* msg, uint16_t len, KeyIdentifier_t keyID, bool isAck, uint8_t dir, uint32_t devAddr, uint32_t fCnt, uint32_t expectedCmac )
+{
+ if( msg == 0 )
+ {
+ return LORAMAC_CRYPTO_ERROR_NPE;
+ }
+ if( len > CRYPTO_MAXMESSAGE_SIZE )
+ {
+ return LORAMAC_CRYPTO_ERROR_BUF_SIZE;
+ }
+
+ uint8_t micBuff[CRYPTO_BUFFER_SIZE];
+ memset1( micBuff, 0, CRYPTO_BUFFER_SIZE );
+
+ // Initialize the first Block
+ PrepareB0( len, keyID, isAck, dir, devAddr, fCnt, micBuff );
+
+ // Copy the given data to the mic computation buffer
+ memcpy1( ( micBuff + MIC_BLOCK_BX_SIZE ), msg, len );
+
+ SecureElementStatus_t retval = SECURE_ELEMENT_ERROR;
+ retval = SecureElementVerifyAesCmac( micBuff, ( len + MIC_BLOCK_BX_SIZE ), expectedCmac, keyID );
+
+ if( retval == SECURE_ELEMENT_SUCCESS )
+ {
+ return LORAMAC_CRYPTO_SUCCESS;
+ }
+ else if( retval == SECURE_ELEMENT_FAIL_CMAC )
+ {
+ return LORAMAC_CRYPTO_FAIL_MIC;
+ }
+
+ return LORAMAC_CRYPTO_ERROR_SECURE_ELEMENT_FUNC;
+}
+
+#if( USE_LRWAN_1_1_X_CRYPTO == 1 )
+/*
+ * Prpares B1 block for cmac computation.
+ *
+ * \param[IN] msgLen - Length of message
+ * \param[IN] keyID - Key identifier
+ * \param[IN] isAck - True if it is a acknowledge frame ( Sets ConfFCnt in B0 block )
+ * \param[IN] txDr - Data rate used for the transmission
+ * \param[IN] txCh - Index of the channel used for the transmission
+ * \param[IN] devAddr - Device address
+ * \param[IN] fCntUp - Frame counter
+ * \param[IN/OUT] b0 - B0 block
+ * \retval - Status of the operation
+ */
+static LoRaMacCryptoStatus_t PrepareB1( uint16_t msgLen, KeyIdentifier_t keyID, bool isAck, uint8_t txDr, uint8_t txCh, uint32_t devAddr, uint32_t fCntUp, uint8_t* b1 )
+{
+ if( b1 == 0 )
+ {
+ return LORAMAC_CRYPTO_ERROR_NPE;
+ }
+
+ b1[0] = 0x49;
+
+ if( isAck == true )
+ {
+ // confFCnt contains the frame counter value modulo 2^16 of the "confirmed" uplink frame that is being acknowledged
+ uint16_t confFCnt = ( uint16_t )( *CryptoCtx.NvmCtx->LastDownFCnt % 65536 );
+ b1[1] = confFCnt & 0xFF;
+ b1[2] = ( confFCnt >> 8 ) & 0xFF;
+ }
+ else
+ {
+ b1[1] = 0x00;
+ b1[2] = 0x00;
+ }
+
+ b1[3] = txDr;
+ b1[4] = txCh;
+ b1[5] = UPLINK; // dir = Uplink
+
+ b1[6] = devAddr & 0xFF;
+ b1[7] = ( devAddr >> 8 ) & 0xFF;
+ b1[8] = ( devAddr >> 16 ) & 0xFF;
+ b1[9] = ( devAddr >> 24 ) & 0xFF;
+
+ b1[10] = fCntUp & 0xFF;
+ b1[11] = ( fCntUp >> 8 ) & 0xFF;
+ b1[12] = ( fCntUp >> 16 ) & 0xFF;
+ b1[13] = ( fCntUp >> 24 ) & 0xFF;
+
+ b1[14] = 0x00;
+
+ b1[15] = msgLen & 0xFF;
+
+ return LORAMAC_CRYPTO_SUCCESS;
+}
+
+/*
+ * Computes cmac with adding B1 block in front ( only for Uplink frames LoRaWAN 1.1 )
+ *
+ * cmac = aes128_cmac(keyID, B1 | msg)
+ *
+ * \param[IN] msg - Message to calculate the Integrity code
+ * \param[IN] len - Length of message
+ * \param[IN] keyID - Key identifier
+ * \param[IN] isAck - True if it is a acknowledge frame ( Sets ConfFCnt in B0 block )
+ * \param[IN] txDr - Data rate used for the transmission
+ * \param[IN] txCh - Index of the channel used for the transmission
+ * \param[IN] devAddr - Device address
+ * \param[IN] fCntUp - Uplink Frame counter
+ * \param[OUT] cmac - Computed cmac
+ * \retval - Status of the operation
+ */
+static LoRaMacCryptoStatus_t ComputeCmacB1( uint8_t* msg, uint16_t len, KeyIdentifier_t keyID, bool isAck, uint8_t txDr, uint8_t txCh, uint32_t devAddr, uint32_t fCntUp, uint32_t* cmac )
+{
+ if( ( msg == 0 ) || ( cmac == 0 ) )
+ {
+ return LORAMAC_CRYPTO_ERROR_NPE;
+ }
+ if( len > CRYPTO_MAXMESSAGE_SIZE )
+ {
+ return LORAMAC_CRYPTO_ERROR_BUF_SIZE;
+ }
+
+ uint8_t micBuff[MIC_BLOCK_BX_SIZE];
+
+ // Initialize the first Block
+ PrepareB1( len, keyID, isAck, txDr, txCh, devAddr, fCntUp, micBuff );
+
+ if( SecureElementComputeAesCmac( micBuff, msg, len, keyID, cmac ) != SECURE_ELEMENT_SUCCESS )
+ {
+ return LORAMAC_CRYPTO_ERROR_SECURE_ELEMENT_FUNC;
+ }
+ return LORAMAC_CRYPTO_SUCCESS;
}
+#endif
-void LoRaMacPayloadDecrypt( const uint8_t *buffer, uint16_t size, const uint8_t *key, uint32_t address, uint8_t dir, uint32_t sequenceCounter, uint8_t *decBuffer )
+/*
+ * Gets security item from list.
+ *
+ * \param[IN] addrID - Address identifier
+ * \param[OUT] keyItem - Key item reference
+ * \retval - Status of the operation
+ */
+static LoRaMacCryptoStatus_t GetKeyAddrItem( AddressIdentifier_t addrID, KeyAddr_t** item )
{
- LoRaMacPayloadEncrypt( buffer, size, key, address, dir, sequenceCounter, decBuffer );
+ for( uint8_t i = 0; i < NUM_OF_SEC_CTX; i++ )
+ {
+ if( KeyAddrList[i].AddrID == addrID )
+ {
+ *item = &( KeyAddrList[i] );
+ return LORAMAC_CRYPTO_SUCCESS;
+ }
+ }
+ return LORAMAC_CRYPTO_ERROR_INVALID_ADDR_ID;
}
-void LoRaMacJoinComputeMic( const uint8_t *buffer, uint16_t size, const uint8_t *key, uint32_t *mic )
+/*
+ * Derives a session key as of LoRaWAN versions prior to 1.1.0
+ *
+ * \param[IN] keyID - Key Identifier for the key to be calculated
+ * \param[IN] joinNonce - Sever nonce
+ * \param[IN] netID - Network Identifier
+ * \param[IN] deviceNonce - Device nonce
+ * \retval - Status of the operation
+ */
+static LoRaMacCryptoStatus_t DeriveSessionKey10x( KeyIdentifier_t keyID, uint8_t* joinNonce, uint8_t* netID, uint8_t* devNonce )
{
- AES_CMAC_Init( AesCmacCtx );
+ if( ( joinNonce == 0 ) || ( netID == 0 ) || ( devNonce == 0 ) )
+ {
+ return LORAMAC_CRYPTO_ERROR_NPE;
+ }
+
+ uint8_t compBase[16] = { 0 };
- AES_CMAC_SetKey( AesCmacCtx, key );
+ switch( keyID )
+ {
+ case F_NWK_S_INT_KEY:
+ case S_NWK_S_INT_KEY:
+ case NWK_S_ENC_KEY:
+ compBase[0] = 0x01;
+ break;
+ case APP_S_KEY:
+ compBase[0] = 0x02;
+ break;
+ default:
+ return LORAMAC_CRYPTO_ERROR_INVALID_KEY_ID;
+ }
- AES_CMAC_Update( AesCmacCtx, buffer, size & 0xFF );
+ memcpy1( compBase + 1, joinNonce, 3 );
+ memcpy1( compBase + 4, netID, 3 );
+ memcpy1( compBase + 7, devNonce, 2 );
- AES_CMAC_Final( Mic, AesCmacCtx );
+ if( SecureElementDeriveAndStoreKey( CryptoCtx.NvmCtx->LrWanVersion, compBase, NWK_KEY, keyID ) != SECURE_ELEMENT_SUCCESS )
+ {
+ return LORAMAC_CRYPTO_ERROR_SECURE_ELEMENT_FUNC;
+ }
- *mic = ( uint32_t )( ( uint32_t )Mic[3] << 24 | ( uint32_t )Mic[2] << 16 | ( uint32_t )Mic[1] << 8 | ( uint32_t )Mic[0] );
+ return LORAMAC_CRYPTO_SUCCESS;
}
-void LoRaMacJoinDecrypt( const uint8_t *buffer, uint16_t size, const uint8_t *key, uint8_t *decBuffer )
+#if( USE_LRWAN_1_1_X_CRYPTO == 1 )
+/*
+ * Derives a session key as of LoRaWAN 1.1.0
+ *
+ * \param[IN] keyID - Key Identifier for the key to be calculated
+ * \param[IN] joinNonce - Sever nonce
+ * \param[IN] joinEUI - Join Server EUI
+ * \param[IN] deviceNonce - Device nonce
+ * \retval - Status of the operation
+ */
+static LoRaMacCryptoStatus_t DeriveSessionKey11x( KeyIdentifier_t keyID, uint8_t* joinNonce, uint8_t* joinEUI, uint8_t* devNonce )
{
- memset1( AesContext.ksch, '\0', 240 );
- aes_set_key_lora( key, 16, &AesContext );
- aes_encrypt_lora( buffer, decBuffer, &AesContext );
- // Check if optional CFList is included
- if( size >= 16 )
+ if( ( joinNonce == 0 ) || ( joinEUI == 0 ) || ( devNonce == 0 ) )
+ {
+ return LORAMAC_CRYPTO_ERROR_NPE;
+ }
+
+ uint8_t compBase[16] = { 0 };
+ KeyIdentifier_t rootKeyId = NWK_KEY;
+
+ switch( keyID )
+ {
+ case F_NWK_S_INT_KEY:
+ compBase[0] = 0x01;
+ break;
+ case S_NWK_S_INT_KEY:
+ compBase[0] = 0x03;
+ break;
+ case NWK_S_ENC_KEY:
+ compBase[0] = 0x04;
+ break;
+ case APP_S_KEY:
+ rootKeyId = APP_KEY;
+ compBase[0] = 0x02;
+ break;
+ default:
+ return LORAMAC_CRYPTO_ERROR_INVALID_KEY_ID;
+ }
+
+ memcpy1( compBase + 1, joinNonce, 3 );
+ memcpyr( compBase + 4, joinEUI, 8 );
+ memcpy1( compBase + 12, devNonce, 2 );
+
+ if( SecureElementDeriveAndStoreKey( CryptoCtx.NvmCtx->LrWanVersion, compBase, rootKeyId, keyID ) != SECURE_ELEMENT_SUCCESS )
{
- aes_encrypt_lora( buffer + 16, decBuffer + 16, &AesContext );
+ return LORAMAC_CRYPTO_ERROR_SECURE_ELEMENT_FUNC;
}
+
+ return LORAMAC_CRYPTO_SUCCESS;
}
-void LoRaMacJoinComputeSKeys( const uint8_t *key, const uint8_t *appNonce, uint16_t devNonce, uint8_t *nwkSKey, uint8_t *appSKey )
+/*
+ * Derives a life time session key (JSIntKey or JSEncKey) as of LoRaWAN 1.1.0
+ *
+ * \param[IN] keyID - Key Identifier for the key to be calculated
+ * \param[IN] devEUI - Device EUI
+ * \retval - Status of the operation
+ */
+static LoRaMacCryptoStatus_t DeriveLifeTimeSessionKey( KeyIdentifier_t keyID, uint8_t* devEUI )
{
- uint8_t nonce[16];
- uint8_t *pDevNonce = ( uint8_t * )&devNonce;
+ if( devEUI == 0 )
+ {
+ return LORAMAC_CRYPTO_ERROR_NPE;
+ }
+
+ uint8_t compBase[16] = { 0 };
- memset1( AesContext.ksch, '\0', 240 );
- aes_set_key_lora( key, 16, &AesContext );
+ switch( keyID )
+ {
+ case J_S_INT_KEY:
+ compBase[0] = 0x06;
+ break;
+ case J_S_ENC_KEY:
+ compBase[0] = 0x05;
+ break;
+ default:
+ return LORAMAC_CRYPTO_ERROR_INVALID_KEY_ID;
+ }
+
+ memcpyr( compBase + 1, devEUI, 8 );
+
+ if( SecureElementDeriveAndStoreKey( CryptoCtx.NvmCtx->LrWanVersion, compBase, NWK_KEY, keyID ) != SECURE_ELEMENT_SUCCESS )
+ {
+ return LORAMAC_CRYPTO_ERROR_SECURE_ELEMENT_FUNC;
+ }
+
+ return LORAMAC_CRYPTO_SUCCESS;
+}
+#endif
- memset1( nonce, 0, sizeof( nonce ) );
- nonce[0] = 0x01;
- memcpy1( nonce + 1, appNonce, 6 );
- memcpy1( nonce + 7, pDevNonce, 2 );
- aes_encrypt_lora( nonce, nwkSKey, &AesContext );
+/*
+ * Gets the last received frame counter
+ *
+ * \param[IN] fCntID - Frame counter identifier
+ * \param[IN] lastDown - Last downlink counter value
+ *
+ * \retval - Status of the operation
+ */
+static LoRaMacCryptoStatus_t GetLastFcntDown( FCntIdentifier_t fCntID, uint32_t* lastDown )
+{
+ if( lastDown == NULL )
+ {
+ return LORAMAC_CRYPTO_ERROR_NPE;
+ }
+ switch( fCntID )
+ {
+ case N_FCNT_DOWN:
+ *lastDown = CryptoCtx.NvmCtx->FCntList.NFCntDown;
+ CryptoCtx.NvmCtx->LastDownFCnt = &CryptoCtx.NvmCtx->FCntList.NFCntDown;
+ break;
+ case A_FCNT_DOWN:
+ *lastDown = CryptoCtx.NvmCtx->FCntList.AFCntDown;
+ CryptoCtx.NvmCtx->LastDownFCnt = &CryptoCtx.NvmCtx->FCntList.AFCntDown;
+ break;
+ case FCNT_DOWN:
+ *lastDown = CryptoCtx.NvmCtx->FCntList.FCntDown;
+ CryptoCtx.NvmCtx->LastDownFCnt = &CryptoCtx.NvmCtx->FCntList.FCntDown;
+ break;
+ case MC_FCNT_DOWN_0:
+ *lastDown = CryptoCtx.NvmCtx->FCntList.McFCntDown0;
+ break;
+ case MC_FCNT_DOWN_1:
+ *lastDown = CryptoCtx.NvmCtx->FCntList.McFCntDown1;
+ break;
+ case MC_FCNT_DOWN_2:
+ *lastDown = CryptoCtx.NvmCtx->FCntList.McFCntDown2;
+ break;
+ case MC_FCNT_DOWN_3:
+ *lastDown = CryptoCtx.NvmCtx->FCntList.McFCntDown3;
+ break;
+ default:
+ return LORAMAC_CRYPTO_FAIL_FCNT_ID;
+ }
+ return LORAMAC_CRYPTO_SUCCESS;
+}
+
+/*
+ * Checks the downlink counter value
+ *
+ * \param[IN] fCntID - Frame counter identifier
+ * \param[IN] currentDown - Current downlink counter value
+ *
+ * \retval - Status of the operation
+ */
+static bool CheckFCntDown( FCntIdentifier_t fCntID, uint32_t currentDown )
+{
+ uint32_t lastDown = 0;
+ if( GetLastFcntDown( fCntID, &lastDown ) != LORAMAC_CRYPTO_SUCCESS )
+ {
+ return false;
+ }
+ if( ( currentDown > lastDown ) ||
+ // For LoRaWAN 1.0.X only. Allow downlink frames of 0
+ ( lastDown == FCNT_DOWN_INITAL_VALUE ) )
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+/*!
+ * Updates the reference downlink counter
+ *
+ * \param[IN] fCntID - Frame counter identifier
+ * \param[IN] currentDown - Current downlink counter value
+ *
+ * \retval - Status of the operation
+ */
+static void UpdateFCntDown( FCntIdentifier_t fCntID, uint32_t currentDown )
+{
+ switch( fCntID )
+ {
+ case N_FCNT_DOWN:
+ CryptoCtx.NvmCtx->FCntList.NFCntDown = currentDown;
+ break;
+ case A_FCNT_DOWN:
+ CryptoCtx.NvmCtx->FCntList.AFCntDown = currentDown;
+ break;
+ case FCNT_DOWN:
+ CryptoCtx.NvmCtx->FCntList.FCntDown = currentDown;
+ break;
+ case MC_FCNT_DOWN_0:
+ CryptoCtx.NvmCtx->FCntList.McFCntDown0 = currentDown;
+ break;
+ case MC_FCNT_DOWN_1:
+ CryptoCtx.NvmCtx->FCntList.McFCntDown1 = currentDown;
+ break;
+ case MC_FCNT_DOWN_2:
+ CryptoCtx.NvmCtx->FCntList.McFCntDown2 = currentDown;
+ break;
+ case MC_FCNT_DOWN_3:
+ CryptoCtx.NvmCtx->FCntList.McFCntDown3 = currentDown;
+ break;
+ default:
+ break;
+ }
+ CryptoCtx.EventCryptoNvmCtxChanged( );
+}
+
+/*!
+ * Resets the frame counters
+ */
+static void ResetFCnts( void )
+{
+
+ CryptoCtx.NvmCtx->FCntList.FCntUp = 0;
+ CryptoCtx.NvmCtx->FCntList.NFCntDown = FCNT_DOWN_INITAL_VALUE;
+ CryptoCtx.NvmCtx->FCntList.AFCntDown = FCNT_DOWN_INITAL_VALUE;
+ CryptoCtx.NvmCtx->FCntList.FCntDown = FCNT_DOWN_INITAL_VALUE;
+ CryptoCtx.NvmCtx->LastDownFCnt = &CryptoCtx.NvmCtx->FCntList.FCntDown;
+
+ CryptoCtx.NvmCtx->FCntList.McFCntDown0 = FCNT_DOWN_INITAL_VALUE;
+ CryptoCtx.NvmCtx->FCntList.McFCntDown1 = FCNT_DOWN_INITAL_VALUE;
+ CryptoCtx.NvmCtx->FCntList.McFCntDown2 = FCNT_DOWN_INITAL_VALUE;
+ CryptoCtx.NvmCtx->FCntList.McFCntDown3 = FCNT_DOWN_INITAL_VALUE;
+
+ CryptoCtx.EventCryptoNvmCtxChanged( );
+}
+
+/*
+ * Dummy callback in case if the user provides NULL function pointer
+ */
+static void DummyCB( void )
+{
+ return;
+}
+
+/*
+ * API functions
+ */
+
+LoRaMacCryptoStatus_t LoRaMacCryptoInit( LoRaMacCryptoNvmEvent cryptoNvmCtxChanged )
+{
+ // Assign non volatile context
+ CryptoCtx.NvmCtx = &NvmCryptoCtx;
+
+ // Assign callback
+ if( cryptoNvmCtxChanged != 0 )
+ {
+ CryptoCtx.EventCryptoNvmCtxChanged = cryptoNvmCtxChanged;
+ }
+ else
+ {
+ CryptoCtx.EventCryptoNvmCtxChanged = DummyCB;
+ }
+
+ // Initialize with default
+ memset1( (uint8_t*) CryptoCtx.NvmCtx, 0, sizeof( LoRaMacCryptoNvmCtx_t ) );
+
+ // Set default LoRaWAN version
+ CryptoCtx.NvmCtx->LrWanVersion.Fields.Major = 1;
+ CryptoCtx.NvmCtx->LrWanVersion.Fields.Minor = 1;
+ CryptoCtx.NvmCtx->LrWanVersion.Fields.Revision = 1;
+ CryptoCtx.NvmCtx->LrWanVersion.Fields.Rfu = 0;
+
+ // Reset frame counters
+ ResetFCnts( );
+
+ return LORAMAC_CRYPTO_SUCCESS;
+}
+
+LoRaMacCryptoStatus_t LoRaMacCryptoSetLrWanVersion( Version_t version )
+{
+ CryptoCtx.NvmCtx->LrWanVersion = version;
+ return LORAMAC_CRYPTO_SUCCESS;
+}
+
+LoRaMacCryptoStatus_t LoRaMacCryptoRestoreNvmCtx( void* cryptoNvmCtx )
+{
+ // Restore module context
+ if( cryptoNvmCtx != 0 )
+ {
+ memcpy1( ( uint8_t* ) &NvmCryptoCtx, ( uint8_t* ) cryptoNvmCtx, CRYPTO_NVM_CTX_SIZE );
+ return LORAMAC_CRYPTO_SUCCESS;
+ }
+ else
+ {
+ return LORAMAC_CRYPTO_ERROR_NPE;
+ }
+}
+
+void* LoRaMacCryptoGetNvmCtx( size_t* cryptoNvmCtxSize )
+{
+ *cryptoNvmCtxSize = CRYPTO_NVM_CTX_SIZE;
+ return &NvmCryptoCtx;
+}
+
+LoRaMacCryptoStatus_t LoRaMacCryptoGetFCntUp( uint32_t* currentUp )
+{
+ if( currentUp == NULL )
+ {
+ return LORAMAC_CRYPTO_ERROR_NPE;
+ }
+
+ *currentUp = CryptoCtx.NvmCtx->FCntList.FCntUp + 1;
+
+ return LORAMAC_CRYPTO_SUCCESS;
+}
+
+LoRaMacCryptoStatus_t LoRaMacCryptoGetFCntDown( FCntIdentifier_t fCntID, uint16_t maxFCntGap, uint32_t frameFcnt, uint32_t* currentDown )
+{
+ uint32_t lastDown = 0;
+ int32_t fCntDiff = 0;
+ LoRaMacCryptoStatus_t cryptoStatus = LORAMAC_CRYPTO_ERROR;
+
+ if( currentDown == NULL )
+ {
+ return LORAMAC_CRYPTO_ERROR_NPE;
+ }
+
+ cryptoStatus = GetLastFcntDown( fCntID, &lastDown );
+ if( cryptoStatus != LORAMAC_CRYPTO_SUCCESS )
+ {
+ return cryptoStatus;
+ }
+
+ // For LoRaWAN 1.0.X only, allow downlink frames of 0
+ if( lastDown == FCNT_DOWN_INITAL_VALUE )
+ {
+ *currentDown = frameFcnt;
+ }
+ else
+ {
+ // Add difference, consider roll-over
+ fCntDiff = ( int32_t )( ( int64_t )frameFcnt - ( int64_t )( lastDown & 0x0000FFFF ) );
+
+ if( fCntDiff > 0 )
+ { // Positive difference
+ *currentDown = lastDown + fCntDiff;
+ }
+ else if( fCntDiff == 0 )
+ { // Duplicate FCnt value, keep the current value.
+ *currentDown = lastDown;
+ return LORAMAC_CRYPTO_FAIL_FCNT_DUPLICATED;
+ }
+ else
+ { // Negative difference, assume a roll-over of one uint16_t
+ *currentDown = ( lastDown & 0xFFFF0000 ) + 0x10000 + frameFcnt;
+ }
+ }
+
+
+ // For LoRaWAN 1.0.X only, check maxFCntGap
+ if( CryptoCtx.NvmCtx->LrWanVersion.Fields.Minor == 0 )
+ {
+ if( ( ( int64_t )*currentDown - ( int64_t )lastDown ) >= maxFCntGap )
+ {
+ return LORAMAC_CRYPTO_FAIL_MAX_GAP_FCNT;
+ }
+ }
+
+ return LORAMAC_CRYPTO_SUCCESS;
+}
+
+LoRaMacCryptoStatus_t LoRaMacCryptoSetMulticastReference( MulticastCtx_t* multicastList )
+{
+ if( multicastList == NULL )
+ {
+ return LORAMAC_CRYPTO_ERROR_NPE;
+ }
+
+ multicastList[0].DownLinkCounter = &CryptoCtx.NvmCtx->FCntList.McFCntDown0;
+ multicastList[1].DownLinkCounter = &CryptoCtx.NvmCtx->FCntList.McFCntDown1;
+ multicastList[2].DownLinkCounter = &CryptoCtx.NvmCtx->FCntList.McFCntDown2;
+ multicastList[3].DownLinkCounter = &CryptoCtx.NvmCtx->FCntList.McFCntDown3;
+
+ return LORAMAC_CRYPTO_SUCCESS;
+}
+
+LoRaMacCryptoStatus_t LoRaMacCryptoSetKey( KeyIdentifier_t keyID, uint8_t* key )
+{
+ if( SecureElementSetKey( keyID, key ) != SECURE_ELEMENT_SUCCESS )
+ {
+ return LORAMAC_CRYPTO_ERROR_SECURE_ELEMENT_FUNC;
+ }
+ if( ( keyID == GEN_APP_KEY ) || ( keyID == APP_KEY ) )
+ {
+ // Derive lifetime keys
+ if( LoRaMacCryptoDeriveMcRootKey( keyID ) != LORAMAC_CRYPTO_SUCCESS )
+ {
+ return LORAMAC_CRYPTO_ERROR_SECURE_ELEMENT_FUNC;
+ }
+ if( LoRaMacCryptoDeriveMcKEKey( MC_ROOT_KEY ) != LORAMAC_CRYPTO_SUCCESS )
+ {
+ return LORAMAC_CRYPTO_ERROR_SECURE_ELEMENT_FUNC;
+ }
+ }
+ return LORAMAC_CRYPTO_SUCCESS;
+}
+
+LoRaMacCryptoStatus_t LoRaMacCryptoPrepareJoinRequest( LoRaMacMessageJoinRequest_t* macMsg )
+{
+ if( macMsg == 0 )
+ {
+ return LORAMAC_CRYPTO_ERROR_NPE;
+ }
+ KeyIdentifier_t micComputationKeyID = NWK_KEY;
+
+ // Add device nonce
+#if ( USE_RANDOM_DEV_NONCE == 1 )
+ uint32_t devNonce = 0;
+ SecureElementRandomNumber( &devNonce );
+ CryptoCtx.NvmCtx->DevNonce = devNonce;
+#else
+ CryptoCtx.NvmCtx->DevNonce++;
+#endif
+ CryptoCtx.EventCryptoNvmCtxChanged( );
+ macMsg->DevNonce = CryptoCtx.NvmCtx->DevNonce;
+
+#if( USE_LRWAN_1_1_X_CRYPTO == 1 )
+ // Derive lifetime session keys
+ if( DeriveLifeTimeSessionKey( J_S_INT_KEY, macMsg->DevEUI ) != LORAMAC_CRYPTO_SUCCESS )
+ {
+ return LORAMAC_CRYPTO_ERROR;
+ }
+ if( DeriveLifeTimeSessionKey( J_S_ENC_KEY, macMsg->DevEUI ) != LORAMAC_CRYPTO_SUCCESS )
+ {
+ return LORAMAC_CRYPTO_ERROR;
+ }
+#endif
+
+ // Serialize message
+ if( LoRaMacSerializerJoinRequest( macMsg ) != LORAMAC_SERIALIZER_SUCCESS )
+ {
+ return LORAMAC_CRYPTO_ERROR_SERIALIZER;
+ }
+
+ // Compute mic
+ if( SecureElementComputeAesCmac( NULL, macMsg->Buffer, ( LORAMAC_JOIN_REQ_MSG_SIZE - LORAMAC_MIC_FIELD_SIZE ), micComputationKeyID, &macMsg->MIC ) != SECURE_ELEMENT_SUCCESS )
+ {
+ return LORAMAC_CRYPTO_ERROR_SECURE_ELEMENT_FUNC;
+ }
+
+ // Reserialize message to add the MIC
+ if( LoRaMacSerializerJoinRequest( macMsg ) != LORAMAC_SERIALIZER_SUCCESS )
+ {
+ return LORAMAC_CRYPTO_ERROR_SERIALIZER;
+ }
+
+ return LORAMAC_CRYPTO_SUCCESS;
+}
+
+LoRaMacCryptoStatus_t LoRaMacCryptoPrepareReJoinType1( LoRaMacMessageReJoinType1_t* macMsg )
+{
+ if( macMsg == 0 )
+ {
+ return LORAMAC_CRYPTO_ERROR_NPE;
+ }
+
+ // Check for RJcount1 overflow
+ if( CryptoCtx.NvmCtx->RJcount1 == 65535 )
+ {
+ return LORAMAC_CRYPTO_ERROR_RJCOUNT1_OVERFLOW;
+ }
+
+ // Serialize message
+ if( LoRaMacSerializerReJoinType1( macMsg ) != LORAMAC_SERIALIZER_SUCCESS )
+ {
+ return LORAMAC_CRYPTO_ERROR_SERIALIZER;
+ }
+
+ // Compute mic
+ // cmac = aes128_cmac(JSIntKey, MHDR | RejoinType | JoinEUI| DevEUI | RJcount1)
+ if( SecureElementComputeAesCmac( NULL, macMsg->Buffer, ( LORAMAC_RE_JOIN_1_MSG_SIZE - LORAMAC_MIC_FIELD_SIZE ), J_S_INT_KEY, &macMsg->MIC ) != SECURE_ELEMENT_SUCCESS )
+ {
+ return LORAMAC_CRYPTO_ERROR_SECURE_ELEMENT_FUNC;
+ }
+
+ // Reserialize message to add the MIC
+ if( LoRaMacSerializerReJoinType1( macMsg ) != LORAMAC_SERIALIZER_SUCCESS )
+ {
+ return LORAMAC_CRYPTO_ERROR_SERIALIZER;
+ }
+
+ // Increment RJcount1
+ CryptoCtx.NvmCtx->RJcount1++;
+ CryptoCtx.EventCryptoNvmCtxChanged( );
+
+ return LORAMAC_CRYPTO_SUCCESS;
+}
+
+LoRaMacCryptoStatus_t LoRaMacCryptoPrepareReJoinType0or2( LoRaMacMessageReJoinType0or2_t* macMsg )
+{
+ if( macMsg == 0 )
+ {
+ return LORAMAC_CRYPTO_ERROR_NPE;
+ }
+
+ // Check for RJcount0 overflow
+ if( CryptoCtx.RJcount0 == 65535 )
+ {
+ return LORAMAC_CRYPTO_FAIL_RJCOUNT0_OVERFLOW;
+ }
+
+ // Serialize message
+ if( LoRaMacSerializerReJoinType0or2( macMsg ) != LORAMAC_SERIALIZER_SUCCESS )
+ {
+ return LORAMAC_CRYPTO_ERROR_SERIALIZER;
+ }
+
+ // Compute mic
+ // cmac = aes128_cmac(SNwkSIntKey, MHDR | Rejoin Type | NetID | DevEUI | RJcount0)
+ if( SecureElementComputeAesCmac( NULL, macMsg->Buffer, ( LORAMAC_RE_JOIN_0_2_MSG_SIZE - LORAMAC_MIC_FIELD_SIZE ), S_NWK_S_INT_KEY, &macMsg->MIC ) != SECURE_ELEMENT_SUCCESS )
+ {
+ return LORAMAC_CRYPTO_ERROR_SECURE_ELEMENT_FUNC;
+ }
+
+ // Reserialize message to add the MIC
+ if( LoRaMacSerializerReJoinType0or2( macMsg ) != LORAMAC_SERIALIZER_SUCCESS )
+ {
+ return LORAMAC_CRYPTO_ERROR_SERIALIZER;
+ }
+
+ // Increment RJcount0
+ CryptoCtx.RJcount0++;
+
+ return LORAMAC_CRYPTO_SUCCESS;
+}
+
+LoRaMacCryptoStatus_t LoRaMacCryptoHandleJoinAccept( JoinReqIdentifier_t joinReqType, uint8_t* joinEUI, LoRaMacMessageJoinAccept_t* macMsg )
+{
+ if( ( macMsg == 0 ) || ( joinEUI == 0 ) )
+ {
+ return LORAMAC_CRYPTO_ERROR_NPE;
+ }
+
+ LoRaMacCryptoStatus_t retval = LORAMAC_CRYPTO_ERROR;
+ KeyIdentifier_t micComputationKeyID;
+ KeyIdentifier_t encryptionKeyID;
+ uint8_t micComputationOffset = 0;
+#if( USE_LRWAN_1_1_X_CRYPTO == 1 )
+ uint8_t* devNonceForKeyDerivation = ( uint8_t* ) &CryptoCtx.NvmCtx->DevNonce;
+#endif
+
+ // Determine decryption key and DevNonce for key derivation
+ if( joinReqType == JOIN_REQ )
+ {
+ encryptionKeyID = NWK_KEY;
+ micComputationOffset = CRYPTO_MIC_COMPUTATION_OFFSET;
+ }
+#if( USE_LRWAN_1_1_X_CRYPTO == 1 )
+ else
+ {
+ encryptionKeyID = J_S_ENC_KEY;
+
+ // If Join-accept is a reply to a rejoin, the RJcount(0 or 1) replaces DevNonce in the key derivation process.
+ if( ( joinReqType == REJOIN_REQ_0 ) || ( joinReqType == REJOIN_REQ_2 ) )
+ {
+ devNonceForKeyDerivation = ( uint8_t* ) &CryptoCtx.RJcount0;
+ }
+ else
+ {
+ devNonceForKeyDerivation = ( uint8_t* ) &CryptoCtx.NvmCtx->RJcount1;
+ }
+ }
+#endif
+ // Decrypt header, skip MHDR
+ uint8_t procBuffer[CRYPTO_MAXMESSAGE_SIZE + CRYPTO_MIC_COMPUTATION_OFFSET];
+ memset1( procBuffer, 0, ( macMsg->BufSize + micComputationOffset ) );
+
+ if( SecureElementAesEncrypt( macMsg->Buffer + LORAMAC_MHDR_FIELD_SIZE, ( macMsg->BufSize - LORAMAC_MHDR_FIELD_SIZE ), encryptionKeyID, ( procBuffer + micComputationOffset ) ) != SECURE_ELEMENT_SUCCESS )
+ {
+ return LORAMAC_CRYPTO_ERROR_SECURE_ELEMENT_FUNC;
+ }
+ // Copy the result to an offset location to keep space for additional information which have to be added in case of 1.1 and later
+ memcpy1( macMsg->Buffer + LORAMAC_MHDR_FIELD_SIZE, ( procBuffer + micComputationOffset ), ( macMsg->BufSize - LORAMAC_MHDR_FIELD_SIZE ) );
+
+ // Parse the message
+ if( LoRaMacParserJoinAccept( macMsg ) != LORAMAC_PARSER_SUCCESS )
+ {
+ return LORAMAC_CRYPTO_ERROR_PARSER;
+ }
+
+ // Is it a LoRaWAN 1.1.0 or later ?
+ if( macMsg->DLSettings.Bits.OptNeg == 1 )
+ {
+ CryptoCtx.NvmCtx->LrWanVersion.Fields.Minor = 1;
+ micComputationKeyID = J_S_INT_KEY;
+ }
+ else
+ {
+ CryptoCtx.NvmCtx->LrWanVersion.Fields.Minor = 0;
+ micComputationKeyID = NWK_KEY;
+ }
+
+ // Verify mic
+ if( CryptoCtx.NvmCtx->LrWanVersion.Fields.Minor == 0 )
+ {
+ // For legacy mode :
+ // cmac = aes128_cmac(NwkKey, MHDR | JoinNonce | NetID | DevAddr | DLSettings | RxDelay | CFList | CFListType)
+ if( SecureElementVerifyAesCmac( macMsg->Buffer, ( macMsg->BufSize - LORAMAC_MIC_FIELD_SIZE ), macMsg->MIC, micComputationKeyID ) != SECURE_ELEMENT_SUCCESS )
+ {
+ return LORAMAC_CRYPTO_ERROR_SECURE_ELEMENT_FUNC;
+ }
+ }
+ else
+ {
+ // For 1.1 and later:
+ // cmac = aes128_cmac(JSIntKey, JoinReqType | JoinEUI | DevNonce | MHDR | JoinNonce | NetID | DevAddr | DLSettings | RxDelay | CFList | CFListType)
+
+ // Prepare the msg for integrity check (adding JoinReqType, JoinEUI and DevNonce)
+ uint16_t bufItr = 0;
+ procBuffer[bufItr++] = ( uint8_t ) joinReqType;
+
+ memcpyr( &procBuffer[bufItr], joinEUI, LORAMAC_JOIN_EUI_FIELD_SIZE );
+ bufItr += LORAMAC_JOIN_EUI_FIELD_SIZE;
+
+ procBuffer[bufItr++] = CryptoCtx.NvmCtx->DevNonce & 0xFF;
+ procBuffer[bufItr++] = ( CryptoCtx.NvmCtx->DevNonce >> 8 ) & 0xFF;
+
+ procBuffer[bufItr++] = macMsg->MHDR.Value;
+
+ if( SecureElementVerifyAesCmac( procBuffer, ( macMsg->BufSize + micComputationOffset - LORAMAC_MHDR_FIELD_SIZE - LORAMAC_MIC_FIELD_SIZE ), macMsg->MIC, micComputationKeyID ) != SECURE_ELEMENT_SUCCESS )
+ {
+ return LORAMAC_CRYPTO_ERROR_SECURE_ELEMENT_FUNC;
+ }
+
+ // Check if the JoinNonce is greater as the previous one
+ uint32_t currentJoinNonce = 0;
+ currentJoinNonce = ( uint32_t ) macMsg->JoinNonce[0];
+ currentJoinNonce |= ( ( uint32_t ) macMsg->JoinNonce[1] << 8 );
+ currentJoinNonce |= ( ( uint32_t ) macMsg->JoinNonce[2] << 16 );
+
+ if( currentJoinNonce > CryptoCtx.NvmCtx->JoinNonce )
+ {
+ CryptoCtx.NvmCtx->JoinNonce = currentJoinNonce;
+ CryptoCtx.EventCryptoNvmCtxChanged( );
+ }
+ else
+ {
+ return LORAMAC_CRYPTO_FAIL_JOIN_NONCE;
+ }
+ }
+
+ // Derive session keys
+#if( USE_LRWAN_1_1_X_CRYPTO == 1 )
+ if( CryptoCtx.NvmCtx->LrWanVersion.Fields.Minor == 1 )
+ {
+ // Derive lifetime keys
+ retval = LoRaMacCryptoDeriveMcRootKey( APP_KEY );
+ if( retval != LORAMAC_CRYPTO_SUCCESS )
+ {
+ return retval;
+ }
+
+ retval = LoRaMacCryptoDeriveMcKEKey( MC_ROOT_KEY );
+ if( retval != LORAMAC_CRYPTO_SUCCESS )
+ {
+ return retval;
+ }
+
+ retval = DeriveSessionKey11x( F_NWK_S_INT_KEY, macMsg->JoinNonce, joinEUI, devNonceForKeyDerivation );
+ if( retval != LORAMAC_CRYPTO_SUCCESS )
+ {
+ return retval;
+ }
+
+ retval = DeriveSessionKey11x( S_NWK_S_INT_KEY, macMsg->JoinNonce, joinEUI, devNonceForKeyDerivation );
+ if( retval != LORAMAC_CRYPTO_SUCCESS )
+ {
+ return retval;
+ }
+
+ retval = DeriveSessionKey11x( NWK_S_ENC_KEY, macMsg->JoinNonce, joinEUI, devNonceForKeyDerivation );
+ if( retval != LORAMAC_CRYPTO_SUCCESS )
+ {
+ return retval;
+ }
+
+ retval = DeriveSessionKey11x( APP_S_KEY, macMsg->JoinNonce, joinEUI, devNonceForKeyDerivation );
+ if( retval != LORAMAC_CRYPTO_SUCCESS )
+ {
+ return retval;
+ }
+ }
+ else
+#endif
+ {
+ // prior LoRaWAN 1.1.0
+ retval = LoRaMacCryptoDeriveMcRootKey( GEN_APP_KEY );
+ if( retval != LORAMAC_CRYPTO_SUCCESS )
+ {
+ return retval;
+ }
+
+ retval = LoRaMacCryptoDeriveMcKEKey( MC_ROOT_KEY );
+ if( retval != LORAMAC_CRYPTO_SUCCESS )
+ {
+ return retval;
+ }
+
+ retval = DeriveSessionKey10x( APP_S_KEY, macMsg->JoinNonce, macMsg->NetID, ( uint8_t* ) &CryptoCtx.NvmCtx->DevNonce );
+ if( retval != LORAMAC_CRYPTO_SUCCESS )
+ {
+ return retval;
+ }
+
+ retval = DeriveSessionKey10x( NWK_S_ENC_KEY, macMsg->JoinNonce, macMsg->NetID, ( uint8_t* ) &CryptoCtx.NvmCtx->DevNonce );
+ if( retval != LORAMAC_CRYPTO_SUCCESS )
+ {
+ return retval;
+ }
+
+ retval = DeriveSessionKey10x( F_NWK_S_INT_KEY, macMsg->JoinNonce, macMsg->NetID, ( uint8_t* ) &CryptoCtx.NvmCtx->DevNonce );
+ if( retval != LORAMAC_CRYPTO_SUCCESS )
+ {
+ return retval;
+ }
+
+ retval = DeriveSessionKey10x( S_NWK_S_INT_KEY, macMsg->JoinNonce, macMsg->NetID, ( uint8_t* ) &CryptoCtx.NvmCtx->DevNonce );
+ if( retval != LORAMAC_CRYPTO_SUCCESS )
+ {
+ return retval;
+ }
+ }
+
+ // Join-Accept is successfully processed, reset frame counters
+ CryptoCtx.RJcount0 = 0;
+ CryptoCtx.NvmCtx->FCntList.FCntUp = 0;
+ CryptoCtx.NvmCtx->FCntList.FCntDown = FCNT_DOWN_INITAL_VALUE;
+ CryptoCtx.NvmCtx->FCntList.NFCntDown = FCNT_DOWN_INITAL_VALUE;
+ CryptoCtx.NvmCtx->FCntList.AFCntDown = FCNT_DOWN_INITAL_VALUE;
+ CryptoCtx.EventCryptoNvmCtxChanged( );
+
+ return LORAMAC_CRYPTO_SUCCESS;
+}
+
+LoRaMacCryptoStatus_t LoRaMacCryptoSecureMessage( uint32_t fCntUp, uint8_t txDr, uint8_t txCh, LoRaMacMessageData_t* macMsg )
+{
+ LoRaMacCryptoStatus_t retval = LORAMAC_CRYPTO_ERROR;
+ KeyIdentifier_t payloadDecryptionKeyID = APP_S_KEY;
+
+ if( macMsg == NULL )
+ {
+ return LORAMAC_CRYPTO_ERROR_NPE;
+ }
+
+ if( fCntUp < CryptoCtx.NvmCtx->FCntList.FCntUp )
+ {
+ return LORAMAC_CRYPTO_FAIL_FCNT_SMALLER;
+ }
+
+ // Encrypt payload
+ if( macMsg->FPort == 0 )
+ {
+ // Use network session key
+ payloadDecryptionKeyID = NWK_S_ENC_KEY;
+ }
+
+ if( fCntUp > CryptoCtx.NvmCtx->FCntList.FCntUp )
+ {
+ retval = PayloadEncrypt( macMsg->FRMPayload, macMsg->FRMPayloadSize, payloadDecryptionKeyID, macMsg->FHDR.DevAddr, UPLINK, fCntUp );
+ if( retval != LORAMAC_CRYPTO_SUCCESS )
+ {
+ return retval;
+ }
+
+#if( USE_LRWAN_1_1_X_CRYPTO == 1 )
+ if( CryptoCtx.NvmCtx->LrWanVersion.Fields.Minor == 1 )
+ {
+ // Encrypt FOpts
+ retval = FOptsEncrypt( macMsg->FHDR.FCtrl.Bits.FOptsLen, macMsg->FHDR.DevAddr, UPLINK, FCNT_UP, fCntUp, macMsg->FHDR.FOpts );
+ if( retval != LORAMAC_CRYPTO_SUCCESS )
+ {
+ return retval;
+ }
+ }
+#endif
+ }
+ CryptoCtx.NvmCtx->FCntList.FCntUp = fCntUp;
+ CryptoCtx.EventCryptoNvmCtxChanged( );
+
+ // Serialize message
+ if( LoRaMacSerializerData( macMsg ) != LORAMAC_SERIALIZER_SUCCESS )
+ {
+ return LORAMAC_CRYPTO_ERROR_SERIALIZER;
+ }
+
+ // Compute mic
+#if( USE_LRWAN_1_1_X_CRYPTO == 1 )
+ if( CryptoCtx.NvmCtx->LrWanVersion.Fields.Minor == 1 )
+ {
+ uint32_t cmacS = 0;
+ uint32_t cmacF = 0;
+
+ // cmacS = aes128_cmac(SNwkSIntKey, B1 | msg)
+ retval = ComputeCmacB1( macMsg->Buffer, ( macMsg->BufSize - LORAMAC_MIC_FIELD_SIZE ), S_NWK_S_INT_KEY, macMsg->FHDR.FCtrl.Bits.Ack, txDr, txCh, macMsg->FHDR.DevAddr, fCntUp, &cmacS );
+ if( retval != LORAMAC_CRYPTO_SUCCESS )
+ {
+ return retval;
+ }
+ //cmacF = aes128_cmac(FNwkSIntKey, B0 | msg)
+ retval = ComputeCmacB0( macMsg->Buffer, ( macMsg->BufSize - LORAMAC_MIC_FIELD_SIZE ), F_NWK_S_INT_KEY, macMsg->FHDR.FCtrl.Bits.Ack, UPLINK, macMsg->FHDR.DevAddr, fCntUp, &cmacF );
+ if( retval != LORAMAC_CRYPTO_SUCCESS )
+ {
+ return retval;
+ }
+ // MIC = cmacS[0..1] | cmacF[0..1]
+ macMsg->MIC = ( ( cmacF << 16 ) & 0xFFFF0000 ) | ( cmacS & 0x0000FFFF );
+ }
+ else
+#endif
+ {
+ // MIC = cmacF[0..3]
+ // The IsAck parameter is every time false since the ConfFCnt field is not used in legacy mode.
+ retval = ComputeCmacB0( macMsg->Buffer, ( macMsg->BufSize - LORAMAC_MIC_FIELD_SIZE ), NWK_S_ENC_KEY, false, UPLINK, macMsg->FHDR.DevAddr, fCntUp, &macMsg->MIC );
+ if( retval != LORAMAC_CRYPTO_SUCCESS )
+ {
+ return retval;
+ }
+ }
+
+ // Re-serialize message to add the MIC
+ if( LoRaMacSerializerData( macMsg ) != LORAMAC_SERIALIZER_SUCCESS )
+ {
+ return LORAMAC_CRYPTO_ERROR_SERIALIZER;
+ }
+
+ return LORAMAC_CRYPTO_SUCCESS;
+}
+
+LoRaMacCryptoStatus_t LoRaMacCryptoUnsecureMessage( AddressIdentifier_t addrID, uint32_t address, FCntIdentifier_t fCntID, uint32_t fCntDown, LoRaMacMessageData_t* macMsg )
+{
+ if( macMsg == 0 )
+ {
+ return LORAMAC_CRYPTO_ERROR_NPE;
+ }
+
+ if( CheckFCntDown( fCntID, fCntDown ) == false )
+ {
+ return LORAMAC_CRYPTO_FAIL_FCNT_SMALLER;
+ }
+
+ LoRaMacCryptoStatus_t retval = LORAMAC_CRYPTO_ERROR;
+ KeyIdentifier_t payloadDecryptionKeyID = APP_S_KEY;
+ KeyIdentifier_t micComputationKeyID = S_NWK_S_INT_KEY;
+ KeyAddr_t* curItem;
+
+ // Parse the message
+ if( LoRaMacParserData( macMsg ) != LORAMAC_PARSER_SUCCESS )
+ {
+ return LORAMAC_CRYPTO_ERROR_PARSER;
+ }
+
+ // Determine current security context
+ retval = GetKeyAddrItem( addrID, &curItem );
+ if( retval != LORAMAC_CRYPTO_SUCCESS )
+ {
+ return retval;
+ }
+
+ payloadDecryptionKeyID = curItem->AppSkey;
+ micComputationKeyID = curItem->NwkSkey;
+
+ // Check if it is our address
+ if( address != macMsg->FHDR.DevAddr )
+ {
+ return LORAMAC_CRYPTO_FAIL_ADDRESS;
+ }
+
+ // Compute mic
+ bool isAck = macMsg->FHDR.FCtrl.Bits.Ack;
+ if( CryptoCtx.NvmCtx->LrWanVersion.Fields.Minor == 0 )
+ {
+ // In legacy mode the IsAck parameter is forced to be false since the ConfFCnt field is not used.
+ isAck = false;
+ }
+
+ // Verify mic
+ retval = VerifyCmacB0( macMsg->Buffer, ( macMsg->BufSize - LORAMAC_MIC_FIELD_SIZE ), micComputationKeyID, isAck, DOWNLINK, address, fCntDown, macMsg->MIC );
+ if( retval != LORAMAC_CRYPTO_SUCCESS )
+ {
+ return retval;
+ }
+
+ // Decrypt payload
+ if( macMsg->FPort == 0 )
+ {
+ // Use network session encryption key
+ payloadDecryptionKeyID = NWK_S_ENC_KEY;
+ }
+ retval = PayloadEncrypt( macMsg->FRMPayload, macMsg->FRMPayloadSize, payloadDecryptionKeyID, address, DOWNLINK, fCntDown );
+ if( retval != LORAMAC_CRYPTO_SUCCESS )
+ {
+ return retval;
+ }
+
+#if( USE_LRWAN_1_1_X_CRYPTO == 1 )
+ if( CryptoCtx.NvmCtx->LrWanVersion.Fields.Minor == 1 )
+ {
+ // Decrypt FOpts
+ retval = FOptsEncrypt( macMsg->FHDR.FCtrl.Bits.FOptsLen, address, DOWNLINK, fCntID, fCntDown, macMsg->FHDR.FOpts );
+ if( retval != LORAMAC_CRYPTO_SUCCESS )
+ {
+ return retval;
+ }
+ }
+#endif
+
+ UpdateFCntDown( fCntID, fCntDown );
+
+ return LORAMAC_CRYPTO_SUCCESS;
+}
+
+LoRaMacCryptoStatus_t LoRaMacCryptoDeriveMcRootKey( KeyIdentifier_t keyID )
+{
+ // Prevent other keys than GenAppKey for LoRaWAN 1.0.x or AppKey for LoRaWAN 1.1 or later
+ if( ( ( keyID == APP_KEY ) && ( CryptoCtx.NvmCtx->LrWanVersion.Fields.Minor == 0 ) ) ||
+ ( ( keyID == GEN_APP_KEY ) && ( CryptoCtx.NvmCtx->LrWanVersion.Fields.Minor == 1 ) ) )
+ {
+ return LORAMAC_CRYPTO_ERROR_INVALID_KEY_ID;
+ }
+ uint8_t compBase[16] = { 0 };
+
+ if( CryptoCtx.NvmCtx->LrWanVersion.Fields.Minor == 1 )
+ {
+ compBase[0] = 0x20;
+ }
+ if( SecureElementDeriveAndStoreKey( CryptoCtx.NvmCtx->LrWanVersion, compBase, keyID, MC_ROOT_KEY ) != SECURE_ELEMENT_SUCCESS )
+ {
+ return LORAMAC_CRYPTO_ERROR_SECURE_ELEMENT_FUNC;
+ }
+
+ return LORAMAC_CRYPTO_SUCCESS;
+}
+
+LoRaMacCryptoStatus_t LoRaMacCryptoDeriveMcKEKey( KeyIdentifier_t keyID )
+{
+ // Prevent other keys than McRootKey
+ if( keyID != MC_ROOT_KEY )
+ {
+ return LORAMAC_CRYPTO_ERROR_INVALID_KEY_ID;
+ }
+ uint8_t compBase[16] = { 0 };
+
+ if( SecureElementDeriveAndStoreKey( CryptoCtx.NvmCtx->LrWanVersion, compBase, keyID, MC_KE_KEY ) != SECURE_ELEMENT_SUCCESS )
+ {
+ return LORAMAC_CRYPTO_ERROR_SECURE_ELEMENT_FUNC;
+ }
+
+ return LORAMAC_CRYPTO_SUCCESS;
+}
+
+LoRaMacCryptoStatus_t LoRaMacCryptoDeriveMcSessionKeyPair( AddressIdentifier_t addrID, uint32_t mcAddr )
+{
+ if( mcAddr == 0 )
+ {
+ return LORAMAC_CRYPTO_ERROR_NPE;
+ }
+
+ LoRaMacCryptoStatus_t retval = LORAMAC_CRYPTO_ERROR;
+
+ // Determine current security context
+ KeyAddr_t* curItem;
+ retval = GetKeyAddrItem( addrID, &curItem );
+ if( retval != LORAMAC_CRYPTO_SUCCESS )
+ {
+ return retval;
+ }
+
+ //McAppSKey = aes128_encrypt(McKey, 0x01 | McAddr | pad16)
+ //McNwkSKey = aes128_encrypt(McKey, 0x02 | McAddr | pad16)
+
+ uint8_t compBaseAppS[16] = { 0 };
+ uint8_t compBaseNwkS[16] = { 0 };
+
+ compBaseAppS[0] = 0x01;
+ compBaseAppS[1] = mcAddr & 0xFF;
+ compBaseAppS[2] = ( mcAddr >> 8 ) & 0xFF;
+ compBaseAppS[3] = ( mcAddr >> 16 ) & 0xFF;
+ compBaseAppS[4] = ( mcAddr >> 24 ) & 0xFF;
+
+ compBaseNwkS[0] = 0x02;
+ compBaseNwkS[1] = mcAddr & 0xFF;
+ compBaseNwkS[2] = ( mcAddr >> 8 ) & 0xFF;
+ compBaseNwkS[3] = ( mcAddr >> 16 ) & 0xFF;
+ compBaseNwkS[4] = ( mcAddr >> 24 ) & 0xFF;
+
+ if( SecureElementDeriveAndStoreKey( CryptoCtx.NvmCtx->LrWanVersion, compBaseAppS, curItem->RootKey, curItem->AppSkey ) != SECURE_ELEMENT_SUCCESS )
+ {
+ return LORAMAC_CRYPTO_ERROR_SECURE_ELEMENT_FUNC;
+ }
+
+ if( SecureElementDeriveAndStoreKey( CryptoCtx.NvmCtx->LrWanVersion, compBaseNwkS, curItem->RootKey, curItem->NwkSkey ) != SECURE_ELEMENT_SUCCESS )
+ {
+ return LORAMAC_CRYPTO_ERROR_SECURE_ELEMENT_FUNC;
+ }
- memset1( nonce, 0, sizeof( nonce ) );
- nonce[0] = 0x02;
- memcpy1( nonce + 1, appNonce, 6 );
- memcpy1( nonce + 7, pDevNonce, 2 );
- aes_encrypt_lora( nonce, appSKey, &AesContext );
+ return LORAMAC_CRYPTO_SUCCESS;
}
diff --git a/lib/lora/mac/LoRaMacCrypto.h b/lib/lora/mac/LoRaMacCrypto.h
index 89eade7675..5289a4fbd2 100644
--- a/lib/lora/mac/LoRaMacCrypto.h
+++ b/lib/lora/mac/LoRaMacCrypto.h
@@ -1,7 +1,7 @@
/*!
* \file LoRaMacCrypto.h
*
- * \brief LoRa MAC layer cryptography implementation
+ * \brief LoRa MAC layer cryptographic functionality implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
@@ -12,7 +12,7 @@
* \____ \| ___ | (_ _) ___ |/ ___) _ \
* _____) ) ____| | | || |_| ____( (___| | | |
* (______/|_____)_|_|_| \__)_____)\____)_| |_|
- * (C)2013 Semtech
+ * (C)2013-2017 Semtech
*
* ___ _____ _ ___ _ _____ ___ ___ ___ ___
* / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
@@ -28,84 +28,302 @@
*
* \author Daniel Jaeckle ( STACKFORCE )
*
- * \defgroup LORAMAC_CRYPTO LoRa MAC layer cryptography implementation
- * This module covers the implementation of cryptographic functions
- * of the LoRaMAC layer.
+ * \author Johannes Bruder ( STACKFORCE )
+ *
+ * addtogroup LORAMAC
* \{
+ *
*/
#ifndef __LORAMAC_CRYPTO_H__
#define __LORAMAC_CRYPTO_H__
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include
+#include
+#include
+#include "utilities.h"
+#include "LoRaMacTypes.h"
+#include "LoRaMacMessageTypes.h"
+
+/*
+ * Initial value of the frame counters
+ */
+#define FCNT_DOWN_INITAL_VALUE 0xFFFFFFFF
+
+/*!
+ * LoRaMac Cryto Status
+ */
+typedef enum eLoRaMacCryptoStatus
+{
+ /*!
+ * No error occurred
+ */
+ LORAMAC_CRYPTO_SUCCESS = 0,
+ /*!
+ * MIC does not match
+ */
+ LORAMAC_CRYPTO_FAIL_MIC,
+ /*!
+ * Address does not match
+ */
+ LORAMAC_CRYPTO_FAIL_ADDRESS,
+ /*!
+ * JoinNonce was not greater than previous one.
+ */
+ LORAMAC_CRYPTO_FAIL_JOIN_NONCE,
+ /*!
+ * RJcount0 reached 2^16-1
+ */
+ LORAMAC_CRYPTO_FAIL_RJCOUNT0_OVERFLOW,
+ /*!
+ * FCNT_ID is not supported
+ */
+ LORAMAC_CRYPTO_FAIL_FCNT_ID,
+ /*!
+ * FCntUp/Down check failed (new FCnt is smaller than previous one)
+ */
+ LORAMAC_CRYPTO_FAIL_FCNT_SMALLER,
+ /*!
+ * FCntUp/Down check failed (duplicated)
+ */
+ LORAMAC_CRYPTO_FAIL_FCNT_DUPLICATED,
+ /*!
+ * MAX_GAP_FCNT check failed
+ */
+ LORAMAC_CRYPTO_FAIL_MAX_GAP_FCNT,
+ /*!
+ * Not allowed parameter value
+ */
+ LORAMAC_CRYPTO_FAIL_PARAM,
+ /*!
+ * Null pointer exception
+ */
+ LORAMAC_CRYPTO_ERROR_NPE,
+ /*!
+ * Invalid key identifier exception
+ */
+ LORAMAC_CRYPTO_ERROR_INVALID_KEY_ID,
+ /*!
+ * Invalid address identifier exception
+ */
+ LORAMAC_CRYPTO_ERROR_INVALID_ADDR_ID,
+ /*!
+ * Invalid LoRaWAN specification version
+ */
+ LORAMAC_CRYPTO_ERROR_INVALID_VERSION,
+ /*!
+ * Incompatible buffer size
+ */
+ LORAMAC_CRYPTO_ERROR_BUF_SIZE,
+ /*!
+ * The secure element reports an error
+ */
+ LORAMAC_CRYPTO_ERROR_SECURE_ELEMENT_FUNC,
+ /*!
+ * Error from parser reported
+ */
+ LORAMAC_CRYPTO_ERROR_PARSER,
+ /*!
+ * Error from serializer reported
+ */
+ LORAMAC_CRYPTO_ERROR_SERIALIZER,
+ /*!
+ * RJcount1 reached 2^16-1 which should never happen
+ */
+ LORAMAC_CRYPTO_ERROR_RJCOUNT1_OVERFLOW,
+ /*!
+ * Undefined Error occurred
+ */
+ LORAMAC_CRYPTO_ERROR,
+}LoRaMacCryptoStatus_t;
+
+/*!
+ * Signature of callback function to be called by the LoRaMac Crypto module when the
+ * non-volatile context have to be stored. It is also possible to save the entire
+ * crypto module context.
+ *
+ */
+typedef void ( *LoRaMacCryptoNvmEvent )( void );
+
+/*!
+ * Initialization of LoRaMac Crypto module
+ * It sets initial values of volatile variables and assigns the non-volatile context.
+ *
+ * \param[IN] cryptoNvmCtxChanged - Callback function which will be called when the
+ * non-volatile context have to be stored.
+ * \retval - Status of the operation
+ */
+LoRaMacCryptoStatus_t LoRaMacCryptoInit( LoRaMacCryptoNvmEvent cryptoNvmCtxChanged );
+
+/*!
+ * Sets the LoRaWAN specification version to be used.
+ *
+ * \warning This function should be used for ABP only. In case of OTA the version will be set automatically.
+ *
+ * \param[IN] version - LoRaWAN specification version to be used.
+ *
+ * \retval - Status of the operation
+ */
+LoRaMacCryptoStatus_t LoRaMacCryptoSetLrWanVersion( Version_t version );
+
+/*!
+ * Restores the internal nvm context from passed pointer.
+ *
+ * \param[IN] cryptoNmvCtx - Pointer to non-volatile crypto module context to be restored.
+ * \retval - Status of the operation
+ */
+LoRaMacCryptoStatus_t LoRaMacCryptoRestoreNvmCtx( void* cryptoNvmCtx );
+
+/*!
+ * Returns a pointer to the internal non-volatile context.
+ *
+ * \param[IN] cryptoNvmCtxSize - Size of the module non-volatile context
+ * \retval - Points to a structure where the module store its non-volatile context
+ */
+void* LoRaMacCryptoGetNvmCtx( size_t* cryptoNvmCtxSize );
+
+/*!
+ * Returns updated fCntID downlink counter value.
+ *
+ * \param[IN] fCntID - Frame counter identifier
+ * \param[IN] maxFcntGap - Maximum allowed frame counter difference (only necessary for L2 LW1.0.x)
+ * \param[IN] frameFcnt - Received frame counter (used to update current counter value)
+ * \param[OUT] currentDown - Current downlink counter value
+ * \retval - Status of the operation
+ */
+LoRaMacCryptoStatus_t LoRaMacCryptoGetFCntDown( FCntIdentifier_t fCntID, uint16_t maxFCntGap, uint32_t frameFcnt, uint32_t* currentDown );
+
+/*!
+ * Returns updated fCntUp uplink counter value.
+ *
+ * \param[IN] currentUp - Uplink counter value
+ * \retval - Status of the operation
+ */
+LoRaMacCryptoStatus_t LoRaMacCryptoGetFCntUp( uint32_t* currentUp );
+
+/*!
+ * Provides multicast context.
+ *
+ * \param[IN] multicastList - Pointer to the multicast context list
+ *
+ * \retval - Status of the operation
+ */
+LoRaMacCryptoStatus_t LoRaMacCryptoSetMulticastReference( MulticastCtx_t* multicastList );
+
+/*!
+ * Sets a key
+ *
+ * \param[IN] keyID - Key identifier
+ * \param[IN] key - Key value (16 byte), if its a multicast key it must be encrypted with McKEKey
+ * \retval - Status of the operation
+ */
+LoRaMacCryptoStatus_t LoRaMacCryptoSetKey( KeyIdentifier_t keyID, uint8_t* key );
+
+/*!
+ * Prepares the join-request message.
+ * It computes the mic and add it to the message.
+ *
+ * \param[IN/OUT] macMsg - Join-request message object
+ * \retval - Status of the operation
+ */
+LoRaMacCryptoStatus_t LoRaMacCryptoPrepareJoinRequest( LoRaMacMessageJoinRequest_t* macMsg );
+
+/*!
+ * Prepares a rejoin-request type 1 message.
+ * It computes the mic and add it to the message.
+ *
+ * \param[IN/OUT] macMsg - Rejoin message object
+ * \retval - Status of the operation
+ */
+LoRaMacCryptoStatus_t LoRaMacCryptoPrepareReJoinType1( LoRaMacMessageReJoinType1_t* macMsg );
+
+/*!
+ * Prepares a rejoin-request type 0 or 2 message.
+ * It computes the mic and add it to the message.
+ *
+ * \param[IN/OUT] macMsg - Rejoin message object
+ * \retval - Status of the operation
+ */
+LoRaMacCryptoStatus_t LoRaMacCryptoPrepareReJoinType0or2( LoRaMacMessageReJoinType0or2_t* macMsg );
+
/*!
- * Computes the LoRaMAC frame MIC field
+ * Handles the join-accept message.
+ * It decrypts the message, verifies the MIC and if successful derives the session keys.
*
- * \param [IN] buffer - Data buffer
- * \param [IN] size - Data buffer size
- * \param [IN] key - AES key to be used
- * \param [IN] address - Frame address
- * \param [IN] dir - Frame direction [0: uplink, 1: downlink]
- * \param [IN] sequenceCounter - Frame sequence counter
- * \param [OUT] mic - Computed MIC field
+ * \param[IN] joinReqType - Type of last join-request or rejoin which triggered the join-accept response
+ * \param[IN] joinEUI - Join server EUI (8 byte)
+ * \param[IN/OUT] macMsg - Join-accept message object
+ * \retval - Status of the operation
*/
-void LoRaMacComputeMic( const uint8_t *buffer, uint16_t size, const uint8_t *key, uint32_t address, uint8_t dir, uint32_t sequenceCounter, uint32_t *mic );
+LoRaMacCryptoStatus_t LoRaMacCryptoHandleJoinAccept( JoinReqIdentifier_t joinReqType, uint8_t* joinEUI, LoRaMacMessageJoinAccept_t* macMsg );
/*!
- * Computes the LoRaMAC payload encryption
+ * Secures a message (encryption + integrity).
*
- * \param [IN] buffer - Data buffer
- * \param [IN] size - Data buffer size
- * \param [IN] key - AES key to be used
- * \param [IN] address - Frame address
- * \param [IN] dir - Frame direction [0: uplink, 1: downlink]
- * \param [IN] sequenceCounter - Frame sequence counter
- * \param [OUT] encBuffer - Encrypted buffer
+ * \param[IN] fCntUp - Uplink sequence counter
+ * \param[IN] txDr - Data rate used for the transmission
+ * \param[IN] txCh - Index of the channel used for the transmission
+ * \param[IN/OUT] macMsg - Data message object
+ * \retval - Status of the operation
*/
-void LoRaMacPayloadEncrypt( const uint8_t *buffer, uint16_t size, const uint8_t *key, uint32_t address, uint8_t dir, uint32_t sequenceCounter, uint8_t *encBuffer );
+LoRaMacCryptoStatus_t LoRaMacCryptoSecureMessage( uint32_t fCntUp, uint8_t txDr, uint8_t txCh, LoRaMacMessageData_t* macMsg );
/*!
- * Computes the LoRaMAC payload decryption
+ * Unsecures a message (decryption + integrity verification).
*
- * \param [IN] buffer - Data buffer
- * \param [IN] size - Data buffer size
- * \param [IN] key - AES key to be used
- * \param [IN] address - Frame address
- * \param [IN] dir - Frame direction [0: uplink, 1: downlink]
- * \param [IN] sequenceCounter - Frame sequence counter
- * \param [OUT] decBuffer - Decrypted buffer
+ * \param[IN] addrID - Address identifier
+ * \param[IN] address - Address
+ * \param[IN] fCntID - Frame counter identifier
+ * \param[IN] fCntDown - Downlink sequence counter
+ * \param[IN/OUT] macMsg - Data message object
+ * \retval - Status of the operation
*/
-void LoRaMacPayloadDecrypt( const uint8_t *buffer, uint16_t size, const uint8_t *key, uint32_t address, uint8_t dir, uint32_t sequenceCounter, uint8_t *decBuffer );
+LoRaMacCryptoStatus_t LoRaMacCryptoUnsecureMessage( AddressIdentifier_t addrID, uint32_t address, FCntIdentifier_t fCntID, uint32_t fCntDown, LoRaMacMessageData_t* macMsg );
/*!
- * Computes the LoRaMAC Join Request frame MIC field
+ * Derives the McRootKey from the GenAppKey or AppKey.
+ *
+ * 1.0.x
+ * McRootKey = aes128_encrypt(GenAppKey , 0x00 | pad16)
*
- * \param [IN] buffer - Data buffer
- * \param [IN] size - Data buffer size
- * \param [IN] key - AES key to be used
- * \param [OUT] mic - Computed MIC field
+ * 1.1.x
+ * McRootKey = aes128_encrypt(AppKey , 0x20 | pad16)
+ *
+ * \param[IN] keyID - Key identifier of the root key to use to perform the derivation ( GenAppKey or AppKey )
+ * \retval - Status of the operation
*/
-void LoRaMacJoinComputeMic( const uint8_t *buffer, uint16_t size, const uint8_t *key, uint32_t *mic );
+LoRaMacCryptoStatus_t LoRaMacCryptoDeriveMcRootKey( KeyIdentifier_t keyID );
/*!
- * Computes the LoRaMAC join frame decryption
+ * Derives the McKEKey from the McRootKey.
+ *
+ * McKEKey = aes128_encrypt(McRootKey , 0x00 | pad16)
*
- * \param [IN] buffer - Data buffer
- * \param [IN] size - Data buffer size
- * \param [IN] key - AES key to be used
- * \param [OUT] decBuffer - Decrypted buffer
+ * \param[IN] keyID - Key identifier of the root key to use to perform the derivation ( McRootKey )
+ * \retval - Status of the operation
*/
-void LoRaMacJoinDecrypt( const uint8_t *buffer, uint16_t size, const uint8_t *key, uint8_t *decBuffer );
+LoRaMacCryptoStatus_t LoRaMacCryptoDeriveMcKEKey( KeyIdentifier_t keyID );
/*!
- * Computes the LoRaMAC join frame decryption
+ * Derives a Multicast group key pair ( McAppSKey, McNwkSKey ) from McKey
*
- * \param [IN] key - AES key to be used
- * \param [IN] appNonce - Application nonce
- * \param [IN] devNonce - Device nonce
- * \param [OUT] nwkSKey - Network session key
- * \param [OUT] appSKey - Application session key
+ * McAppSKey = aes128_encrypt(McKey, 0x01 | McAddr | pad16)
+ * McNwkSKey = aes128_encrypt(McKey, 0x02 | McAddr | pad16)
+ *
+ * \param[IN] addrID - Address identifier to select the multicast group
+ * \param[IN] mcAddr - Multicast group address (4 bytes)
+ * \retval - Status of the operation
*/
-void LoRaMacJoinComputeSKeys( const uint8_t *key, const uint8_t *appNonce, uint16_t devNonce, uint8_t *nwkSKey, uint8_t *appSKey );
+LoRaMacCryptoStatus_t LoRaMacCryptoDeriveMcSessionKeyPair( AddressIdentifier_t addrID, uint32_t mcAddr );
+
+/*! \} addtogroup LORAMAC */
-/*! \} defgroup LORAMAC */
+#ifdef __cplusplus
+}
+#endif
#endif // __LORAMAC_CRYPTO_H__
diff --git a/lib/lora/mac/LoRaMacHeaderTypes.h b/lib/lora/mac/LoRaMacHeaderTypes.h
new file mode 100644
index 0000000000..02bd9ea0a2
--- /dev/null
+++ b/lib/lora/mac/LoRaMacHeaderTypes.h
@@ -0,0 +1,195 @@
+/*!
+ * \file LoRaMacHeaderTypes.h
+ *
+ * \brief LoRa MAC layer header type definitions
+ *
+ * \copyright Revised BSD License, see section \ref LICENSE.
+ *
+ * \code
+ * ______ _
+ * / _____) _ | |
+ * ( (____ _____ ____ _| |_ _____ ____| |__
+ * \____ \| ___ | (_ _) ___ |/ ___) _ \
+ * _____) ) ____| | | || |_| ____( (___| | | |
+ * (______/|_____)_|_|_| \__)_____)\____)_| |_|
+ * (C)2013 Semtech
+ *
+ * ___ _____ _ ___ _ _____ ___ ___ ___ ___
+ * / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
+ * \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
+ * |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
+ * embedded.connectivity.solutions===============
+ *
+ * \endcode
+ *
+ * \author Miguel Luis ( Semtech )
+ *
+ * \author Gregory Cristian ( Semtech )
+ *
+ * \author Daniel Jaeckle ( STACKFORCE )
+ *
+ * \author Johannes Bruder ( STACKFORCE )
+ *
+ * addtogroup LORAMAC
+ * \{
+ *
+ */
+#ifndef __LORAMAC_HEADER_TYPES_H__
+#define __LORAMAC_HEADER_TYPES_H__
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include
+
+/*! Frame header (FHDR) maximum field size */
+#define LORAMAC_FHDR_MAX_FIELD_SIZE 22
+
+/*! FHDR Device address field size */
+#define LORAMAC_FHDR_DEV_ADD_FIELD_SIZE 4
+
+/*! FHDR Frame control field size */
+#define LORAMAC_FHDR_F_CTRL_FIELD_SIZE 1
+
+/*! FHDR Frame control field size */
+#define LORAMAC_FHDR_F_CNT_FIELD_SIZE 2
+
+/*! FOpts maximum field size */
+#define LORAMAC_FHDR_F_OPTS_MAX_FIELD_SIZE 15
+
+
+/*!
+ * LoRaMAC field definition of DLSettings
+ *
+ * LoRaWAN Specification V1.0.2, chapter 5.4
+ */
+typedef union uLoRaMacDLSettings
+{
+ /*!
+ * Byte-access to the bits
+ */
+ uint8_t Value;
+ /*!
+ * Structure containing single access to header bits
+ */
+ struct sDLSettingsBits
+ {
+ /*!
+ * Data rate of a downlink using the second receive window
+ */
+ uint8_t RX2DataRate : 4;
+ /*!
+ * Offset between up and downlink datarate of first reception slot
+ */
+ uint8_t RX1DRoffset : 3;
+ /*!
+ * Indicates network server LoRaWAN implementation version 1.1 or later.
+ */
+ uint8_t OptNeg : 1;
+ }Bits;
+}LoRaMacDLSettings_t;
+
+/*!
+ * LoRaMAC header field definition (MHDR field)
+ *
+ * LoRaWAN Specification V1.0.2, chapter 4.2
+ */
+typedef union uLoRaMacHeader
+{
+ /*!
+ * Byte-access to the bits
+ */
+ uint8_t Value;
+ /*!
+ * Structure containing single access to header bits
+ */
+ struct sMacHeaderBits
+ {
+ /*!
+ * Major version
+ */
+ uint8_t Major : 2;
+ /*!
+ * RFU
+ */
+ uint8_t RFU : 3;
+ /*!
+ * Message type
+ */
+ uint8_t MType : 3;
+ }Bits;
+}LoRaMacHeader_t;
+
+/*!
+ * LoRaMAC frame control field definition (FCtrl)
+ *
+ * LoRaWAN Specification V1.0.2, chapter 4.3.1
+ */
+typedef union uLoRaMacFrameCtrl
+{
+ /*!
+ * Byte-access to the bits
+ */
+ uint8_t Value;
+ /*!
+ * Structure containing single access to bits
+ */
+ struct sCtrlBits
+ {
+ /*!
+ * Frame options length
+ */
+ uint8_t FOptsLen : 4;
+ /*!
+ * Frame pending bit
+ */
+ uint8_t FPending : 1;
+ /*!
+ * Message acknowledge bit
+ */
+ uint8_t Ack : 1;
+ /*!
+ * ADR acknowledgment request bit
+ */
+ uint8_t AdrAckReq : 1;
+ /*!
+ * ADR control in frame header
+ */
+ uint8_t Adr : 1;
+ }Bits;
+}LoRaMacFrameCtrl_t;
+
+/*!
+ * LoRaMac Frame header (FHDR)
+ *
+ * LoRaWAN Specification V1.0.2, chapter 4.3.1
+ */
+typedef struct sLoRaMacFrameHeader
+{
+ /*!
+ * Device address
+ */
+ uint32_t DevAddr;
+ /*!
+ * Frame control field
+ */
+ LoRaMacFrameCtrl_t FCtrl;
+ /*!
+ * Frame counter
+ */
+ uint16_t FCnt;
+ /*!
+ * FOpts field may transport MAC commands (opt. 0-15 Bytes)
+ */
+ uint8_t FOpts[LORAMAC_FHDR_F_OPTS_MAX_FIELD_SIZE];
+}LoRaMacFrameHeader_t;
+
+/*! \} addtogroup LORAMAC */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // __LORAMAC_HEADER_TYPES_H__
diff --git a/lib/lora/mac/LoRaMacMessageTypes.h b/lib/lora/mac/LoRaMacMessageTypes.h
new file mode 100644
index 0000000000..415d431b12
--- /dev/null
+++ b/lib/lora/mac/LoRaMacMessageTypes.h
@@ -0,0 +1,336 @@
+/*!
+ * \file LoRaMacMessageTypes.h
+ *
+ * \brief LoRa MAC layer message type definitions
+ *
+ * \copyright Revised BSD License, see section \ref LICENSE.
+ *
+ * \code
+ * ______ _
+ * / _____) _ | |
+ * ( (____ _____ ____ _| |_ _____ ____| |__
+ * \____ \| ___ | (_ _) ___ |/ ___) _ \
+ * _____) ) ____| | | || |_| ____( (___| | | |
+ * (______/|_____)_|_|_| \__)_____)\____)_| |_|
+ * (C)2013 Semtech
+ *
+ * ___ _____ _ ___ _ _____ ___ ___ ___ ___
+ * / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
+ * \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
+ * |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
+ * embedded.connectivity.solutions===============
+ *
+ * \endcode
+ *
+ * \author Miguel Luis ( Semtech )
+ *
+ * \author Gregory Cristian ( Semtech )
+ *
+ * \author Daniel Jaeckle ( STACKFORCE )
+ *
+ * \author Johannes Bruder ( STACKFORCE )
+ *
+ * addtogroup LORAMAC
+ * \{
+ *
+ */
+#ifndef __LORAMAC_MESSAGE_TYPES_H__
+#define __LORAMAC_MESSAGE_TYPES_H__
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include
+#include "LoRaMacHeaderTypes.h"
+
+
+/*! MAC header field size */
+#define LORAMAC_MHDR_FIELD_SIZE 1
+
+/*! Join EUI field size */
+#define LORAMAC_JOIN_EUI_FIELD_SIZE 8
+
+/*! Device EUI field size */
+#define LORAMAC_DEV_EUI_FIELD_SIZE 8
+
+/*! Join-server nonce field size */
+#define LORAMAC_JOIN_NONCE_FIELD_SIZE 3
+
+/*! Network ID field size */
+#define LORAMAC_NET_ID_FIELD_SIZE 3
+
+/*! Port field size */
+#define LORAMAC_F_PORT_FIELD_SIZE 1
+
+/*! CFList field size */
+#define LORAMAC_C_FLIST_FIELD_SIZE 16
+
+/*! MIC field size */
+#define LORAMAC_MIC_FIELD_SIZE 4
+
+/*! Join-request message size */
+#define LORAMAC_JOIN_REQ_MSG_SIZE 23
+
+/*! ReJoin-request type 1 message size */
+#define LORAMAC_RE_JOIN_1_MSG_SIZE 24
+
+/*! ReJoin-request type 0 or 2 message size */
+#define LORAMAC_RE_JOIN_0_2_MSG_SIZE 19
+
+/*!
+ * LoRaMac type for Join-request message
+ */
+typedef struct sLoRaMacMessageJoinRequest
+{
+ /*!
+ * Serialized message buffer
+ */
+ uint8_t* Buffer;
+ /*!
+ * Size of serialized message buffer
+ */
+ uint8_t BufSize;
+ /*!
+ * MAC header
+ */
+ LoRaMacHeader_t MHDR;
+ /*!
+ * Join EUI
+ */
+ uint8_t JoinEUI[LORAMAC_JOIN_EUI_FIELD_SIZE];
+ /*!
+ * Device EUI
+ */
+ uint8_t DevEUI[LORAMAC_DEV_EUI_FIELD_SIZE];
+ /*!
+ * Device Nonce
+ */
+ uint16_t DevNonce;
+ /*!
+ * Message integrity code (MIC)
+ */
+ uint32_t MIC;
+}LoRaMacMessageJoinRequest_t;
+
+/*!
+ * LoRaMac type for rejoin-request type 1 message
+ */
+typedef struct sLoRaMacMessageReJoinType1
+{
+ /*!
+ * Serialized message buffer
+ */
+ uint8_t* Buffer;
+ /*!
+ * Size of serialized message buffer
+ */
+ uint8_t BufSize;
+ /*!
+ * MAC header
+ */
+ LoRaMacHeader_t MHDR;
+ /*!
+ * Rejoin-request type ( 1 )
+ */
+ uint8_t ReJoinType;
+ /*!
+ * Join EUI
+ */
+ uint8_t JoinEUI[LORAMAC_JOIN_EUI_FIELD_SIZE];
+ /*!
+ * Device EUI
+ */
+ uint8_t DevEUI[LORAMAC_DEV_EUI_FIELD_SIZE];
+ /*!
+ * ReJoin Type 1 counter
+ */
+ uint16_t RJcount1;
+ /*!
+ * Message integrity code (MIC)
+ */
+ uint32_t MIC;
+}LoRaMacMessageReJoinType1_t;
+
+/*!
+ * LoRaMac type for rejoin-request type 0 or 2 message
+ */
+typedef struct sLoRaMacMessageReJoinType0or2
+{
+ /*!
+ * Serialized message buffer
+ */
+ uint8_t* Buffer;
+ /*!
+ * Size of serialized message buffer
+ */
+ uint8_t BufSize;
+ /*!
+ * MAC header
+ */
+ LoRaMacHeader_t MHDR;
+ /*!
+ * Rejoin-request type ( 0 or 2 )
+ */
+ uint8_t ReJoinType;
+ /*!
+ * Network ID ( 3 bytes )
+ */
+ uint8_t NetID[LORAMAC_NET_ID_FIELD_SIZE];
+ /*!
+ * Device EUI
+ */
+ uint8_t DevEUI[LORAMAC_DEV_EUI_FIELD_SIZE];
+ /*!
+ * ReJoin Type 0 and 2 frame counter
+ */
+ uint16_t RJcount0;
+ /*!
+ * Message integrity code (MIC)
+ */
+ uint32_t MIC;
+}LoRaMacMessageReJoinType0or2_t;
+
+/*!
+ * LoRaMac type for Join-accept message
+ */
+typedef struct sLoRaMacMessageJoinAccept
+{
+ /*!
+ * Serialized message buffer
+ */
+ uint8_t* Buffer;
+ /*!
+ * Size of serialized message buffer
+ */
+ uint8_t BufSize;
+ /*!
+ * MAC header
+ */
+ LoRaMacHeader_t MHDR;
+ /*!
+ * Server Nonce ( 3 bytes )
+ */
+ uint8_t JoinNonce[LORAMAC_JOIN_NONCE_FIELD_SIZE];
+ /*!
+ * Network ID ( 3 bytes )
+ */
+ uint8_t NetID[LORAMAC_NET_ID_FIELD_SIZE];
+ /*!
+ * Device address
+ */
+ uint32_t DevAddr;
+ /*!
+ * Device address
+ */
+ LoRaMacDLSettings_t DLSettings;
+ /*!
+ * Delay between TX and RX
+ */
+ uint8_t RxDelay;
+ /*!
+ * List of channel frequencies (opt.)
+ */
+ uint8_t CFList[16];
+ /*!
+ * Message integrity code (MIC)
+ */
+ uint32_t MIC;
+}LoRaMacMessageJoinAccept_t;
+
+
+/*!
+ * LoRaMac type for Data MAC messages
+ * (Unconfirmed Data Up, Confirmed Data Up, Unconfirmed Data Down, Confirmed Data Down)
+ */
+typedef struct sLoRaMacMessageData
+{
+ /*!
+ * Serialized message buffer
+ */
+ uint8_t* Buffer;
+ /*!
+ * Size of serialized message buffer
+ */
+ uint8_t BufSize;
+ /*!
+ * MAC header
+ */
+ LoRaMacHeader_t MHDR;
+ /*!
+ * Frame header (FHDR)
+ */
+ LoRaMacFrameHeader_t FHDR;
+ /*!
+ * Port field (opt.)
+ */
+ uint8_t FPort;
+ /*!
+ * Frame payload may contain MAC commands or data (opt.)
+ */
+ uint8_t* FRMPayload;
+ /*!
+ * Size of frame payload (not included in LoRaMac messages)
+ */
+ uint8_t FRMPayloadSize;
+ /*!
+ * Message integrity code (MIC)
+ */
+ uint32_t MIC;
+}LoRaMacMessageData_t;
+
+/*!
+ * LoRaMac message type enumerator
+ */
+typedef enum eLoRaMacMessageType
+{
+ /*!
+ * Join-request message
+ */
+ LORAMAC_MSG_TYPE_JOIN_REQUEST,
+ /*!
+ * Rejoin-request type 1 message
+ */
+ LORAMAC_MSG_TYPE_RE_JOIN_1,
+ /*!
+ * Rejoin-request type 1 message
+ */
+ LORAMAC_MSG_TYPE_RE_JOIN_0_2,
+ /*!
+ * Join-accept message
+ */
+ LORAMAC_MSG_TYPE_JOIN_ACCEPT,
+ /*!
+ * Data MAC messages
+ */
+ LORAMAC_MSG_TYPE_DATA,
+ /*!
+ * Undefined message type
+ */
+ LORAMAC_MSG_TYPE_UNDEF,
+}LoRaMacMessageType_t;
+
+/*!
+ * LoRaMac general message type
+ */
+typedef struct sLoRaMacMessage
+{
+ LoRaMacMessageType_t Type;
+ union uMessage
+ {
+ LoRaMacMessageJoinRequest_t JoinReq;
+ LoRaMacMessageReJoinType1_t ReJoin1;
+ LoRaMacMessageReJoinType0or2_t ReJoin0or2;
+ LoRaMacMessageJoinAccept_t JoinAccept;
+ LoRaMacMessageData_t Data;
+ }Message;
+}LoRaMacMessage_t;
+
+/*! \} addtogroup LORAMAC */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // __LORAMAC_MESSAGE_TYPES_H__
diff --git a/lib/lora/mac/LoRaMacParser.c b/lib/lora/mac/LoRaMacParser.c
new file mode 100644
index 0000000000..6f29d06dd6
--- /dev/null
+++ b/lib/lora/mac/LoRaMacParser.c
@@ -0,0 +1,118 @@
+/*
+ / _____) _ | |
+( (____ _____ ____ _| |_ _____ ____| |__
+ \____ \| ___ | (_ _) ___ |/ ___) _ \
+ _____) ) ____| | | || |_| ____( (___| | | |
+(______/|_____)_|_|_| \__)_____)\____)_| |_|
+ (C)2013 Semtech
+ ___ _____ _ ___ _ _____ ___ ___ ___ ___
+/ __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
+\__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
+|___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
+embedded.connectivity.solutions===============
+
+Description: LoRa MAC layer message parser functionality implementation
+
+License: Revised BSD License, see LICENSE.TXT file include in the project
+
+Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ),
+ Daniel Jaeckle ( STACKFORCE ), Johannes Bruder ( STACKFORCE )
+*/
+#include "LoRaMacParser.h"
+#include "utilities.h"
+
+LoRaMacParserStatus_t LoRaMacParserJoinAccept( LoRaMacMessageJoinAccept_t* macMsg )
+{
+ if( ( macMsg == 0 ) || ( macMsg->Buffer == 0 ) )
+ {
+ return LORAMAC_PARSER_ERROR_NPE;
+ }
+
+ uint16_t bufItr = 0;
+
+ macMsg->MHDR.Value = macMsg->Buffer[bufItr++];
+
+ memcpy1( macMsg->JoinNonce, &macMsg->Buffer[bufItr], 3 );
+ bufItr = bufItr + 3;
+
+ memcpy1( macMsg->NetID, &macMsg->Buffer[bufItr], 3 );
+ bufItr = bufItr + 3;
+
+ macMsg->DevAddr = ( uint32_t ) macMsg->Buffer[bufItr++];
+ macMsg->DevAddr |= ( ( uint32_t ) macMsg->Buffer[bufItr++] << 8 );
+ macMsg->DevAddr |= ( ( uint32_t ) macMsg->Buffer[bufItr++] << 16 );
+ macMsg->DevAddr |= ( ( uint32_t ) macMsg->Buffer[bufItr++] << 24 );
+
+ macMsg->DLSettings.Value = macMsg->Buffer[bufItr++];
+
+ macMsg->RxDelay = macMsg->Buffer[bufItr++];
+
+ if( ( macMsg->BufSize - LORAMAC_MIC_FIELD_SIZE - bufItr ) == LORAMAC_C_FLIST_FIELD_SIZE )
+ {
+ memcpy1( macMsg->CFList, &macMsg->Buffer[bufItr], LORAMAC_C_FLIST_FIELD_SIZE );
+ bufItr = bufItr + LORAMAC_C_FLIST_FIELD_SIZE;
+ }
+ else if( ( macMsg->BufSize - LORAMAC_MIC_FIELD_SIZE - bufItr ) > 0 )
+ {
+ return LORAMAC_PARSER_FAIL;
+ }
+
+ macMsg->MIC = ( uint32_t ) macMsg->Buffer[bufItr++];
+ macMsg->MIC |= ( ( uint32_t ) macMsg->Buffer[bufItr++] << 8 );
+ macMsg->MIC |= ( ( uint32_t ) macMsg->Buffer[bufItr++] << 16 );
+ macMsg->MIC |= ( ( uint32_t ) macMsg->Buffer[bufItr++] << 24 );
+
+ return LORAMAC_PARSER_SUCCESS;
+}
+
+LoRaMacParserStatus_t LoRaMacParserData( LoRaMacMessageData_t* macMsg )
+{
+ if( ( macMsg == 0 ) || ( macMsg->Buffer == 0 ) )
+ {
+ return LORAMAC_PARSER_ERROR_NPE;
+ }
+
+ uint16_t bufItr = 0;
+
+ macMsg->MHDR.Value = macMsg->Buffer[bufItr++];
+
+ macMsg->FHDR.DevAddr = macMsg->Buffer[bufItr++];
+ macMsg->FHDR.DevAddr |= ( ( uint32_t ) macMsg->Buffer[bufItr++] << 8 );
+ macMsg->FHDR.DevAddr |= ( ( uint32_t ) macMsg->Buffer[bufItr++] << 16 );
+ macMsg->FHDR.DevAddr |= ( ( uint32_t ) macMsg->Buffer[bufItr++] << 24 );
+
+ macMsg->FHDR.FCtrl.Value = macMsg->Buffer[bufItr++];
+
+ macMsg->FHDR.FCnt = macMsg->Buffer[bufItr++];
+ macMsg->FHDR.FCnt |= macMsg->Buffer[bufItr++] << 8;
+
+ if( macMsg->FHDR.FCtrl.Bits.FOptsLen <= 15 )
+ {
+ memcpy1( macMsg->FHDR.FOpts, &macMsg->Buffer[bufItr], macMsg->FHDR.FCtrl.Bits.FOptsLen );
+ bufItr = bufItr + macMsg->FHDR.FCtrl.Bits.FOptsLen;
+ }
+ else
+ {
+ return LORAMAC_PARSER_FAIL;
+ }
+
+ // Initialize anyway with zero.
+ macMsg->FPort = 0;
+ macMsg->FRMPayloadSize = 0;
+
+ if( ( macMsg->BufSize - bufItr - LORAMAC_MIC_FIELD_SIZE ) > 0 )
+ {
+ macMsg->FPort = macMsg->Buffer[bufItr++];
+
+ macMsg->FRMPayloadSize = ( macMsg->BufSize - bufItr - LORAMAC_MIC_FIELD_SIZE );
+ memcpy1( macMsg->FRMPayload, &macMsg->Buffer[bufItr], macMsg->FRMPayloadSize );
+ bufItr = bufItr + macMsg->FRMPayloadSize;
+ }
+
+ macMsg->MIC = ( uint32_t ) macMsg->Buffer[( macMsg->BufSize - LORAMAC_MIC_FIELD_SIZE )];
+ macMsg->MIC |= ( ( uint32_t ) macMsg->Buffer[( macMsg->BufSize - LORAMAC_MIC_FIELD_SIZE ) + 1] << 8 );
+ macMsg->MIC |= ( ( uint32_t ) macMsg->Buffer[( macMsg->BufSize - LORAMAC_MIC_FIELD_SIZE ) + 2] << 16 );
+ macMsg->MIC |= ( ( uint32_t ) macMsg->Buffer[( macMsg->BufSize - LORAMAC_MIC_FIELD_SIZE ) + 3] << 24 );
+
+ return LORAMAC_PARSER_SUCCESS;
+}
diff --git a/lib/lora/mac/LoRaMacParser.h b/lib/lora/mac/LoRaMacParser.h
new file mode 100644
index 0000000000..e9a0a22c99
--- /dev/null
+++ b/lib/lora/mac/LoRaMacParser.h
@@ -0,0 +1,95 @@
+/*!
+ * \file LoRaMacParser.h
+ *
+ * \brief LoRa MAC layer message parser functionality implementation
+ *
+ * \copyright Revised BSD License, see section \ref LICENSE.
+ *
+ * \code
+ * ______ _
+ * / _____) _ | |
+ * ( (____ _____ ____ _| |_ _____ ____| |__
+ * \____ \| ___ | (_ _) ___ |/ ___) _ \
+ * _____) ) ____| | | || |_| ____( (___| | | |
+ * (______/|_____)_|_|_| \__)_____)\____)_| |_|
+ * (C)2013 Semtech
+ *
+ * ___ _____ _ ___ _ _____ ___ ___ ___ ___
+ * / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
+ * \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
+ * |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
+ * embedded.connectivity.solutions===============
+ *
+ * \endcode
+ *
+ * \author Miguel Luis ( Semtech )
+ *
+ * \author Gregory Cristian ( Semtech )
+ *
+ * \author Daniel Jaeckle ( STACKFORCE )
+ *
+ * \author Johannes Bruder ( STACKFORCE )
+ *
+ * addtogroup LORAMAC
+ * \{
+ *
+ */
+#ifndef __LORAMAC_PARSER_H__
+#define __LORAMAC_PARSER_H__
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include
+#include "LoRaMacMessageTypes.h"
+
+/*!
+ * LoRaMac Parser Status
+ */
+typedef enum eLoRaMacParserStatus
+{
+ /*!
+ * No error occurred
+ */
+ LORAMAC_PARSER_SUCCESS = 0,
+ /*!
+ * Failure during parsing occurred
+ */
+ LORAMAC_PARSER_FAIL,
+ /*!
+ * Null pointer exception
+ */
+ LORAMAC_PARSER_ERROR_NPE,
+ /*!
+ * Undefined Error occurred
+ */
+ LORAMAC_PARSER_ERROR,
+}LoRaMacParserStatus_t;
+
+
+/*!
+ * Parse a serialized join-accept message and fills the structured object.
+ *
+ * \param[IN/OUT] macMsg - Join-accept message object
+ * \retval - Status of the operation
+ */
+LoRaMacParserStatus_t LoRaMacParserJoinAccept( LoRaMacMessageJoinAccept_t *macMsg );
+
+/*!
+ * Parse a serialized data message and fills the structured object.
+ *
+ * \param[IN/OUT] macMsg - Data message object
+ * \retval - Status of the operation
+ */
+LoRaMacParserStatus_t LoRaMacParserData( LoRaMacMessageData_t *macMsg );
+
+/*! \} addtogroup LORAMAC */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // __LORAMAC_PARSER_H__
+
diff --git a/lib/lora/mac/LoRaMacSerializer.c b/lib/lora/mac/LoRaMacSerializer.c
new file mode 100644
index 0000000000..261cfb2f48
--- /dev/null
+++ b/lib/lora/mac/LoRaMacSerializer.c
@@ -0,0 +1,183 @@
+/*
+ / _____) _ | |
+( (____ _____ ____ _| |_ _____ ____| |__
+ \____ \| ___ | (_ _) ___ |/ ___) _ \
+ _____) ) ____| | | || |_| ____( (___| | | |
+(______/|_____)_|_|_| \__)_____)\____)_| |_|
+ (C)2013 Semtech
+ ___ _____ _ ___ _ _____ ___ ___ ___ ___
+/ __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
+\__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
+|___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
+embedded.connectivity.solutions===============
+
+Description: LoRa MAC layer message serializer functionality implementation
+
+License: Revised BSD License, see LICENSE.TXT file include in the project
+
+Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ),
+ Daniel Jaeckle ( STACKFORCE ), Johannes Bruder ( STACKFORCE )
+*/
+#include "LoRaMacSerializer.h"
+#include "utilities.h"
+
+LoRaMacSerializerStatus_t LoRaMacSerializerJoinRequest( LoRaMacMessageJoinRequest_t* macMsg )
+{
+ if( ( macMsg == 0 ) || ( macMsg->Buffer == 0 ) )
+ {
+ return LORAMAC_SERIALIZER_ERROR_NPE;
+ }
+
+ uint16_t bufItr = 0;
+
+ // Check macMsg->BufSize
+ if( macMsg->BufSize < LORAMAC_JOIN_REQ_MSG_SIZE )
+ {
+ return LORAMAC_SERIALIZER_ERROR_BUF_SIZE;
+ }
+
+ macMsg->Buffer[bufItr++] = macMsg->MHDR.Value;
+
+ memcpyr( &macMsg->Buffer[bufItr], macMsg->JoinEUI, LORAMAC_JOIN_EUI_FIELD_SIZE );
+ bufItr += LORAMAC_JOIN_EUI_FIELD_SIZE;
+
+ memcpyr( &macMsg->Buffer[bufItr], macMsg->DevEUI, LORAMAC_DEV_EUI_FIELD_SIZE );
+ bufItr += LORAMAC_DEV_EUI_FIELD_SIZE;
+
+ macMsg->Buffer[bufItr++] = macMsg->DevNonce & 0xFF;
+ macMsg->Buffer[bufItr++] = ( macMsg->DevNonce >> 8 ) & 0xFF;
+
+ macMsg->Buffer[bufItr++] = macMsg->MIC & 0xFF;
+ macMsg->Buffer[bufItr++] = ( macMsg->MIC >> 8 ) & 0xFF;
+ macMsg->Buffer[bufItr++] = ( macMsg->MIC >> 16 ) & 0xFF;
+ macMsg->Buffer[bufItr++] = ( macMsg->MIC >> 24 ) & 0xFF;
+
+ macMsg->BufSize = bufItr;
+
+ return LORAMAC_SERIALIZER_SUCCESS;
+}
+
+LoRaMacSerializerStatus_t LoRaMacSerializerReJoinType1( LoRaMacMessageReJoinType1_t* macMsg )
+{
+ if( ( macMsg == 0 ) || ( macMsg->Buffer == 0 ) )
+ {
+ return LORAMAC_SERIALIZER_ERROR_NPE;
+ }
+
+ uint16_t bufItr = 0;
+
+ // Check macMsg->BufSize
+ if( macMsg->BufSize < LORAMAC_RE_JOIN_1_MSG_SIZE )
+ {
+ return LORAMAC_SERIALIZER_ERROR_BUF_SIZE;
+ }
+
+ macMsg->Buffer[bufItr++] = macMsg->MHDR.Value;
+
+ macMsg->Buffer[bufItr++] = macMsg->ReJoinType;
+
+ memcpyr( &macMsg->Buffer[bufItr], macMsg->JoinEUI, LORAMAC_JOIN_EUI_FIELD_SIZE );
+ bufItr += LORAMAC_JOIN_EUI_FIELD_SIZE;
+
+ memcpyr( &macMsg->Buffer[bufItr], macMsg->DevEUI, LORAMAC_DEV_EUI_FIELD_SIZE );
+ bufItr += LORAMAC_DEV_EUI_FIELD_SIZE;
+
+ macMsg->Buffer[bufItr++] = macMsg->RJcount1 & 0xFF;
+ macMsg->Buffer[bufItr++] = ( macMsg->RJcount1 >> 8 ) & 0xFF;
+
+ return LORAMAC_SERIALIZER_SUCCESS;
+}
+
+LoRaMacSerializerStatus_t LoRaMacSerializerReJoinType0or2( LoRaMacMessageReJoinType0or2_t* macMsg )
+{
+ if( ( macMsg == 0 ) || ( macMsg->Buffer == 0 ) )
+ {
+ return LORAMAC_SERIALIZER_ERROR_NPE;
+ }
+
+ uint16_t bufItr = 0;
+
+ // Check macMsg->BufSize
+ if( macMsg->BufSize < LORAMAC_RE_JOIN_0_2_MSG_SIZE )
+ {
+ return LORAMAC_SERIALIZER_ERROR_BUF_SIZE;
+ }
+
+ macMsg->Buffer[bufItr++] = macMsg->MHDR.Value;
+
+ macMsg->Buffer[bufItr++] = macMsg->ReJoinType;
+
+ memcpy1( &macMsg->Buffer[bufItr], macMsg->NetID, LORAMAC_NET_ID_FIELD_SIZE );
+ bufItr += LORAMAC_NET_ID_FIELD_SIZE;
+
+ memcpyr( &macMsg->Buffer[bufItr], macMsg->DevEUI, LORAMAC_DEV_EUI_FIELD_SIZE );
+ bufItr += LORAMAC_DEV_EUI_FIELD_SIZE;
+
+ macMsg->Buffer[bufItr++] = macMsg->RJcount0 & 0xFF;
+ macMsg->Buffer[bufItr++] = ( macMsg->RJcount0 >> 8 ) & 0xFF;
+
+ return LORAMAC_SERIALIZER_SUCCESS;
+}
+
+LoRaMacSerializerStatus_t LoRaMacSerializerData( LoRaMacMessageData_t* macMsg )
+{
+ if( ( macMsg == 0 ) || ( macMsg->Buffer == 0 ) )
+ {
+ return LORAMAC_SERIALIZER_ERROR_NPE;
+ }
+
+ uint16_t bufItr = 0;
+
+ // Check macMsg->BufSize
+ uint16_t computedBufSize = LORAMAC_MHDR_FIELD_SIZE
+ + LORAMAC_FHDR_DEV_ADD_FIELD_SIZE
+ + LORAMAC_FHDR_F_CTRL_FIELD_SIZE
+ + LORAMAC_FHDR_F_CNT_FIELD_SIZE;
+
+ computedBufSize += macMsg->FHDR.FCtrl.Bits.FOptsLen;
+
+ if( macMsg->FRMPayloadSize > 0 )
+ {
+ computedBufSize += LORAMAC_F_PORT_FIELD_SIZE;
+ }
+
+ computedBufSize += macMsg->FRMPayloadSize;
+ computedBufSize += LORAMAC_MIC_FIELD_SIZE;
+
+ if( macMsg->BufSize < computedBufSize )
+ {
+ return LORAMAC_SERIALIZER_ERROR_BUF_SIZE;
+ }
+
+ macMsg->Buffer[bufItr++] = macMsg->MHDR.Value;
+
+ macMsg->Buffer[bufItr++] = ( macMsg->FHDR.DevAddr ) & 0xFF;
+ macMsg->Buffer[bufItr++] = ( macMsg->FHDR.DevAddr >> 8 ) & 0xFF;
+ macMsg->Buffer[bufItr++] = ( macMsg->FHDR.DevAddr >> 16 ) & 0xFF;
+ macMsg->Buffer[bufItr++] = ( macMsg->FHDR.DevAddr >> 24 ) & 0xFF;
+
+ macMsg->Buffer[bufItr++] = macMsg->FHDR.FCtrl.Value;
+
+ macMsg->Buffer[bufItr++] = macMsg->FHDR.FCnt & 0xFF;
+ macMsg->Buffer[bufItr++] = ( macMsg->FHDR.FCnt >> 8 ) & 0xFF;
+
+ memcpy1( &macMsg->Buffer[bufItr], macMsg->FHDR.FOpts, macMsg->FHDR.FCtrl.Bits.FOptsLen );
+ bufItr = bufItr + macMsg->FHDR.FCtrl.Bits.FOptsLen;
+
+ if( macMsg->FRMPayloadSize > 0 )
+ {
+ macMsg->Buffer[bufItr++] = macMsg->FPort;
+ }
+
+ memcpy1( &macMsg->Buffer[bufItr], macMsg->FRMPayload, macMsg->FRMPayloadSize );
+ bufItr = bufItr + macMsg->FRMPayloadSize;
+
+ macMsg->Buffer[bufItr++] = macMsg->MIC & 0xFF;
+ macMsg->Buffer[bufItr++] = ( macMsg->MIC >> 8 ) & 0xFF;
+ macMsg->Buffer[bufItr++] = ( macMsg->MIC >> 16 ) & 0xFF;
+ macMsg->Buffer[bufItr++] = ( macMsg->MIC >> 24 ) & 0xFF;
+
+ macMsg->BufSize = bufItr;
+
+ return LORAMAC_SERIALIZER_SUCCESS;
+}
diff --git a/lib/lora/mac/LoRaMacSerializer.h b/lib/lora/mac/LoRaMacSerializer.h
new file mode 100644
index 0000000000..8588062ab0
--- /dev/null
+++ b/lib/lora/mac/LoRaMacSerializer.h
@@ -0,0 +1,110 @@
+/*!
+ * \file LoRaMacSerializer.h
+ *
+ * \brief LoRa MAC layer message serializer functionality implementation
+ *
+ * \copyright Revised BSD License, see section \ref LICENSE.
+ *
+ * \code
+ * ______ _
+ * / _____) _ | |
+ * ( (____ _____ ____ _| |_ _____ ____| |__
+ * \____ \| ___ | (_ _) ___ |/ ___) _ \
+ * _____) ) ____| | | || |_| ____( (___| | | |
+ * (______/|_____)_|_|_| \__)_____)\____)_| |_|
+ * (C)2013 Semtech
+ *
+ * ___ _____ _ ___ _ _____ ___ ___ ___ ___
+ * / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
+ * \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
+ * |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
+ * embedded.connectivity.solutions===============
+ *
+ * \endcode
+ *
+ * \author Miguel Luis ( Semtech )
+ *
+ * \author Gregory Cristian ( Semtech )
+ *
+ * \author Daniel Jaeckle ( STACKFORCE )
+ *
+ * \author Johannes Bruder ( STACKFORCE )
+ *
+ * addtogroup LORAMAC
+ * \{
+ *
+ */
+#ifndef __LORAMAC_SERIALIZER_H__
+#define __LORAMAC_SERIALIZER_H__
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+#include
+#include "LoRaMacMessageTypes.h"
+
+
+/*!
+ * LoRaMac Serializer Status
+ */
+typedef enum eLoRaMacSerializerStatus
+{
+ /*!
+ * No error occurred
+ */
+ LORAMAC_SERIALIZER_SUCCESS = 0,
+ /*!
+ * Null pointer exception
+ */
+ LORAMAC_SERIALIZER_ERROR_NPE,
+ /*!
+ * Incompatible buffer size
+ */
+ LORAMAC_SERIALIZER_ERROR_BUF_SIZE,
+ /*!
+ * Undefined Error occurred
+ */
+ LORAMAC_SERIALIZER_ERROR,
+}LoRaMacSerializerStatus_t;
+
+/*!
+ * Creates serialized MAC message of structured object.
+ *
+ * \param[IN/OUT] macMsg - Join-request message object
+ * \retval - Status of the operation
+ */
+LoRaMacSerializerStatus_t LoRaMacSerializerJoinRequest( LoRaMacMessageJoinRequest_t* macMsg );
+
+/*!
+ * Creates serialized MAC message of structured object.
+ *
+ * \param[IN/OUT] macMsg - Join-request message object
+ * \retval - Status of the operation
+ */
+LoRaMacSerializerStatus_t LoRaMacSerializerReJoinType1( LoRaMacMessageReJoinType1_t* macMsg );
+
+/*!
+ * Creates serialized MAC message of structured object.
+ *
+ * \param[IN/OUT] macMsg - Join-request message object
+ * \retval - Status of the operation
+ */
+LoRaMacSerializerStatus_t LoRaMacSerializerReJoinType0or2( LoRaMacMessageReJoinType0or2_t* macMsg );
+
+/*!
+ * Creates serialized MAC message of structured object.
+ *
+ * \param[IN/OUT] macMsg - Data message object
+ * \retval - Status of the operation
+ */
+LoRaMacSerializerStatus_t LoRaMacSerializerData( LoRaMacMessageData_t* macMsg );
+
+/*! \} addtogroup LORAMAC */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // __LORAMAC_SERIALIZER_H__
+
diff --git a/lib/lora/mac/LoRaMacTest.h b/lib/lora/mac/LoRaMacTest.h
index 454201849f..57f49683cd 100644
--- a/lib/lora/mac/LoRaMacTest.h
+++ b/lib/lora/mac/LoRaMacTest.h
@@ -12,7 +12,7 @@
* \____ \| ___ | (_ _) ___ |/ ___) _ \
* _____) ) ____| | | || |_| ____( (___| | | |
* (______/|_____)_|_|_| \__)_____)\____)_| |_|
- * (C)2013 Semtech
+ * (C)2013-2017 Semtech
*
* ___ _____ _ ___ _ _____ ___ ___ ___ ___
* / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
@@ -36,25 +36,10 @@
#ifndef __LORAMACTEST_H__
#define __LORAMACTEST_H__
-/*!
- * \brief Enabled or disables the reception windows
- *
- * \details This is a test function. It shall be used for testing purposes only.
- * Changing this attribute may lead to a non-conformance LoRaMac operation.
- *
- * \param [IN] enable - Enabled or disables the reception windows
- */
-void LoRaMacTestRxWindowsOn( bool enable );
-
-/*!
- * \brief Enables the MIC field test
- *
- * \details This is a test function. It shall be used for testing purposes only.
- * Changing this attribute may lead to a non-conformance LoRaMac operation.
- *
- * \param [IN] txPacketCounter - Fixed Tx packet counter value
- */
-void LoRaMacTestSetMic( uint16_t txPacketCounter );
+#ifdef __cplusplus
+extern "C"
+{
+#endif
/*!
* \brief Enabled or disables the duty cycle
@@ -66,16 +51,10 @@ void LoRaMacTestSetMic( uint16_t txPacketCounter );
*/
void LoRaMacTestSetDutyCycleOn( bool enable );
-/*!
- * \brief Sets the channel index
- *
- * \details This is a test function. It shall be used for testing purposes only.
- * Changing this attribute may lead to a non-conformance LoRaMac operation.
- *
- * \param [IN] channel - Channel index
- */
-void LoRaMacTestSetChannel( uint8_t channel );
-
/*! \} defgroup LORAMACTEST */
+#ifdef __cplusplus
+}
+#endif
+
#endif // __LORAMACTEST_H__
diff --git a/lib/lora/mac/LoRaMacTypes.h b/lib/lora/mac/LoRaMacTypes.h
new file mode 100644
index 0000000000..d5d5436b2d
--- /dev/null
+++ b/lib/lora/mac/LoRaMacTypes.h
@@ -0,0 +1,653 @@
+/*!
+ * \file LoRaMacTypes.h
+ *
+ * \brief LoRa MAC layer internal types definition. Please do not include in application sources.
+ *
+ * \copyright Revised BSD License, see section \ref LICENSE.
+ *
+ * \code
+ * ______ _
+ * / _____) _ | |
+ * ( (____ _____ ____ _| |_ _____ ____| |__
+ * \____ \| ___ | (_ _) ___ |/ ___) _ \
+ * _____) ) ____| | | || |_| ____( (___| | | |
+ * (______/|_____)_|_|_| \__)_____)\____)_| |_|
+ * (C)2013 Semtech
+ *
+ * ___ _____ _ ___ _ _____ ___ ___ ___ ___
+ * / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
+ * \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
+ * |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
+ * embedded.connectivity.solutions===============
+ *
+ * \endcode
+ *
+ * \author Miguel Luis ( Semtech )
+ *
+ * \author Daniel Jaeckle ( STACKFORCE )
+ *
+ * \author Johannes Bruder ( STACKFORCE )
+ *
+ * addtogroup LORAMAC
+ * \{
+ *
+ */
+#ifndef __LORAMAC_TYPES_H__
+#define __LORAMAC_TYPES_H__
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include
+#include
+#include "timer.h"
+#include "timer-board.h"
+
+/*!
+ * Start value for unicast keys enumeration
+ */
+#define LORAMAC_CRYPTO_UNICAST_KEYS 0
+
+/*!
+ * Start value for multicast keys enumeration
+ */
+#define LORAMAC_CRYPTO_MULTICAST_KEYS 127
+
+/*!
+ * LoRaWAN devices classes definition
+ *
+ * LoRaWAN Specification V1.0.2, chapter 2.1
+ */
+typedef enum DeviceClass_e
+{
+ /*!
+ * LoRaWAN device class A
+ *
+ * LoRaWAN Specification V1.0.2, chapter 3
+ */
+ CLASS_A = 0x00,
+ /*!
+ * LoRaWAN device class B
+ *
+ * LoRaWAN Specification V1.0.2, chapter 8
+ */
+ CLASS_B = 0x01,
+ /*!
+ * LoRaWAN device class C
+ *
+ * LoRaWAN Specification V1.0.2, chapter 17
+ */
+ CLASS_C = 0x02,
+}DeviceClass_t;
+
+/*!
+ * LoRaWAN Frame type enumeration to differ between the possible data up/down frame configurations.
+ *
+ * Note: The naming is implementation specific since there is no definition
+ * in the LoRaWAN specification included.
+ */
+typedef enum eFType
+{
+ /*!
+ * Frame type A
+ *
+ * FOptsLen > 0, Fopt present, FPort > 0, FRMPayload present
+ */
+ FRAME_TYPE_A,
+ /*!
+ * Frame type B
+ *
+ * FOptsLen > 0, Fopt present, FPort not present, FRMPayload not present
+ */
+ FRAME_TYPE_B,
+ /*!
+ * Frame type C
+ *
+ * FOptsLen = 0, Fopt not present, FPort = 0 , FRMPayload containing MAC commands
+ */
+ FRAME_TYPE_C,
+ /*!
+ * Frame type D
+ *
+ * FOptsLen = 0, Fopt not present, FPort > 0 , FRMPayload present
+ */
+ FRAME_TYPE_D,
+}FType_t;
+
+/*!
+ * LoRaWAN Frame counter identifier.
+ */
+typedef enum eFCntIdentifier
+{
+ /*!
+ * Uplink frame counter which is incremented with each uplink.
+ */
+ FCNT_UP = 0,
+ /*!
+ * Network downlink frame counter which is incremented with each downlink on FPort 0
+ * or when the FPort field is missing.
+ */
+ N_FCNT_DOWN,
+ /*!
+ * Application downlink frame counter which is incremented with each downlink
+ * on a port different than 0.
+ */
+ A_FCNT_DOWN,
+ /*!
+ * In case if the device is connected to a LoRaWAN 1.0 Server,
+ * this counter is used for every kind of downlink frame.
+ */
+ FCNT_DOWN,
+ /*!
+ * Multicast downlink counter for index 0
+ */
+ MC_FCNT_DOWN_0,
+ /*!
+ * Multicast downlink counter for index 1
+ */
+ MC_FCNT_DOWN_1,
+ /*!
+ * Multicast downlink counter for index 2
+ */
+ MC_FCNT_DOWN_2,
+ /*!
+ * Multicast downlink counter for index 3
+ */
+ MC_FCNT_DOWN_3,
+}FCntIdentifier_t;
+
+/*!
+ * LoRaMac Key identifier
+ */
+typedef enum eKeyIdentifier
+{
+ /*!
+ * Application root key
+ */
+ APP_KEY = 0,
+ /*!
+ * Application root key
+ * Used to derive McRootKey for 1.0.x devices
+ */
+ GEN_APP_KEY,
+ /*!
+ * Network root key
+ */
+ NWK_KEY,
+ /*!
+ * Join session integrity key
+ */
+ J_S_INT_KEY,
+ /*!
+ * Join session encryption key
+ */
+ J_S_ENC_KEY,
+ /*!
+ * Forwarding Network session integrity key
+ */
+ F_NWK_S_INT_KEY,
+ /*!
+ * Serving Network session integrity key
+ */
+ S_NWK_S_INT_KEY,
+ /*!
+ * Network session encryption key
+ */
+ NWK_S_ENC_KEY,
+ /*!
+ * Application session key
+ */
+ APP_S_KEY,
+ /*!
+ * Multicast root key
+ */
+ MC_ROOT_KEY,
+ /*!
+ * Multicast key encryption key
+ */
+ MC_KE_KEY = LORAMAC_CRYPTO_MULTICAST_KEYS,
+ /*!
+ * Multicast root key index 0
+ */
+ MC_KEY_0,
+ /*!
+ * Multicast Application session key index 0
+ */
+ MC_APP_S_KEY_0,
+ /*!
+ * Multicast Network session key index 0
+ */
+ MC_NWK_S_KEY_0,
+ /*!
+ * Multicast root key index 1
+ */
+ MC_KEY_1,
+ /*!
+ * Multicast Application session key index 1
+ */
+ MC_APP_S_KEY_1,
+ /*!
+ * Multicast Network session key index 1
+ */
+ MC_NWK_S_KEY_1,
+ /*!
+ * Multicast root key index 2
+ */
+ MC_KEY_2,
+ /*!
+ * Multicast Application session key index 2
+ */
+ MC_APP_S_KEY_2,
+ /*!
+ * Multicast Network session key index 2
+ */
+ MC_NWK_S_KEY_2,
+ /*!
+ * Multicast root key index 3
+ */
+ MC_KEY_3,
+ /*!
+ * Multicast Application session key index 3
+ */
+ MC_APP_S_KEY_3,
+ /*!
+ * Multicast Network session key index 3
+ */
+ MC_NWK_S_KEY_3,
+ /*!
+ * Zero key for slot randomization in class B
+ */
+ SLOT_RAND_ZERO_KEY,
+ /*!
+ * No Key
+ */
+ NO_KEY,
+}KeyIdentifier_t;
+
+/*!
+ * LoRaMac Crypto address identifier
+ */
+typedef enum eAddressIdentifier
+{
+ /*!
+ * Multicast Address for index 0
+ */
+ MULTICAST_0_ADDR = 0,
+ /*!
+ * Multicast Address for index 1
+ */
+ MULTICAST_1_ADDR = 1,
+ /*!
+ * Multicast Address for index 2
+ */
+ MULTICAST_2_ADDR = 2,
+ /*!
+ * Multicast Address for index 3
+ */
+ MULTICAST_3_ADDR = 3,
+ /*!
+ * Unicast End-device address
+ */
+ UNICAST_DEV_ADDR = 4,
+}AddressIdentifier_t;
+
+/*
+ * Multicast Rx window parameters
+ */
+typedef union uMcRxParams
+{
+ struct
+ {
+ /*!
+ * Reception frequency of the ping slot windows
+ */
+ uint32_t Frequency;
+ /*!
+ * Datarate of the ping slot
+ */
+ int8_t Datarate;
+ /*!
+ * This parameter is necessary for class B operation. It defines the
+ * periodicity of the multicast downlink slots
+ */
+ uint16_t Periodicity;
+ }ClassB;
+ struct
+ {
+ /*!
+ * Reception frequency of the ping slot windows
+ */
+ uint32_t Frequency;
+ /*!
+ * Datarate of the ping slot
+ */
+ int8_t Datarate;
+ }ClassC;
+}McRxParams_t;
+
+/*!
+ * Multicast channel
+ */
+typedef struct sMcChannelParams
+{
+ /*!
+ * Multicats channel LoRaWAN class B or C
+ */
+ DeviceClass_t Class;
+ /*!
+ * True if the entry is active
+ */
+ bool IsEnabled;
+ /*
+ * Address identifier
+ */
+ AddressIdentifier_t GroupID;
+ /*!
+ * Address
+ */
+ uint32_t Address;
+ /*!
+ * Encrypted multicast key
+ */
+ uint8_t *McKeyE;
+ /*!
+ * Minimum multicast frame counter value
+ */
+ uint32_t FCountMin;
+ /*!
+ * Maximum multicast frame counter value
+ */
+ uint32_t FCountMax;
+ /*!
+ * Multicast reception parameters
+ */
+ McRxParams_t RxParams;
+}McChannelParams_t;
+
+/*!
+ * Multicast context
+ */
+typedef struct sMulticastCtx
+{
+ /*!
+ * Multicast channel parameters
+ */
+ McChannelParams_t ChannelParams;
+ /*!
+ * Downlink counter
+ */
+ uint32_t* DownLinkCounter;
+ /*
+ * Following parameters are only used for ClassB multicast channels
+ */
+ /*!
+ * Number of multicast slots. The variable can be
+ * calculated as follows:
+ * PingNb = 128 / ( 1 << periodicity ), where
+ * 0 <= periodicity <= 7
+ */
+ uint8_t PingNb;
+ /*!
+ * Period of the multicast slots. The variable can be
+ * calculated as follows:
+ * PingPeriod = 4096 / PingNb
+ */
+ uint16_t PingPeriod;
+ /*!
+ * Ping offset of the multicast channel for Class B
+ */
+ uint16_t PingOffset;
+}MulticastCtx_t;
+
+/*!
+ * LoRaMac join-request / rejoin type identifier
+ */
+typedef enum eJoinReqIdentifier
+{
+ /*!
+ * Rejoin type 0
+ */
+ REJOIN_REQ_0 = 0x00,
+ /*!
+ * Rejoin type 1
+ */
+ REJOIN_REQ_1 = 0x01,
+ /*!
+ * Rejoin type 2
+ */
+ REJOIN_REQ_2 = 0x02,
+ /*!
+ * Join-request
+ */
+ JOIN_REQ = 0xFF,
+}JoinReqIdentifier_t;
+
+/*!
+ * LoRaMAC mote MAC commands
+ *
+ * LoRaWAN Specification V1.1.0, chapter 5, table 4
+ */
+typedef enum eLoRaMacMoteCmd
+{
+ /*!
+ * LinkCheckReq
+ */
+ MOTE_MAC_LINK_CHECK_REQ = 0x02,
+ /*!
+ * LinkADRAns
+ */
+ MOTE_MAC_LINK_ADR_ANS = 0x03,
+ /*!
+ * DutyCycleAns
+ */
+ MOTE_MAC_DUTY_CYCLE_ANS = 0x04,
+ /*!
+ * RXParamSetupAns
+ */
+ MOTE_MAC_RX_PARAM_SETUP_ANS = 0x05,
+ /*!
+ * DevStatusAns
+ */
+ MOTE_MAC_DEV_STATUS_ANS = 0x06,
+ /*!
+ * NewChannelAns
+ */
+ MOTE_MAC_NEW_CHANNEL_ANS = 0x07,
+ /*!
+ * RXTimingSetupAns
+ */
+ MOTE_MAC_RX_TIMING_SETUP_ANS = 0x08,
+ /*!
+ * TXParamSetupAns
+ */
+ MOTE_MAC_TX_PARAM_SETUP_ANS = 0x09,
+ /*!
+ * DlChannelAns
+ */
+ MOTE_MAC_DL_CHANNEL_ANS = 0x0A,
+ /*!
+ * DeviceTimeReq
+ */
+ MOTE_MAC_DEVICE_TIME_REQ = 0x0D,
+ /*!
+ * PingSlotInfoReq
+ */
+ MOTE_MAC_PING_SLOT_INFO_REQ = 0x10,
+ /*!
+ * PingSlotFreqAns
+ */
+ MOTE_MAC_PING_SLOT_FREQ_ANS = 0x11,
+ /*!
+ * BeaconTimingReq
+ */
+ MOTE_MAC_BEACON_TIMING_REQ = 0x12,
+ /*!
+ * BeaconFreqAns
+ */
+ MOTE_MAC_BEACON_FREQ_ANS = 0x13,
+}LoRaMacMoteCmd_t;
+
+/*!
+ * LoRaMAC server MAC commands
+ *
+ * LoRaWAN Specification V1.1.0 chapter 5, table 4
+ */
+typedef enum eLoRaMacSrvCmd
+{
+ /*!
+ * ResetInd
+ */
+ SRV_MAC_RESET_CONF = 0x01,
+ /*!
+ * LinkCheckAns
+ */
+ SRV_MAC_LINK_CHECK_ANS = 0x02,
+ /*!
+ * LinkADRReq
+ */
+ SRV_MAC_LINK_ADR_REQ = 0x03,
+ /*!
+ * DutyCycleReq
+ */
+ SRV_MAC_DUTY_CYCLE_REQ = 0x04,
+ /*!
+ * RXParamSetupReq
+ */
+ SRV_MAC_RX_PARAM_SETUP_REQ = 0x05,
+ /*!
+ * DevStatusReq
+ */
+ SRV_MAC_DEV_STATUS_REQ = 0x06,
+ /*!
+ * NewChannelReq
+ */
+ SRV_MAC_NEW_CHANNEL_REQ = 0x07,
+ /*!
+ * RXTimingSetupReq
+ */
+ SRV_MAC_RX_TIMING_SETUP_REQ = 0x08,
+ /*!
+ * NewChannelReq
+ */
+ SRV_MAC_TX_PARAM_SETUP_REQ = 0x09,
+ /*!
+ * DlChannelReq
+ */
+ SRV_MAC_DL_CHANNEL_REQ = 0x0A,
+ /*!
+ * DeviceTimeAns
+ */
+ SRV_MAC_DEVICE_TIME_ANS = 0x0D,
+ /*!
+ * PingSlotInfoAns
+ */
+ SRV_MAC_PING_SLOT_INFO_ANS = 0x10,
+ /*!
+ * PingSlotChannelReq
+ */
+ SRV_MAC_PING_SLOT_CHANNEL_REQ = 0x11,
+ /*!
+ * BeaconTimingAns
+ */
+ SRV_MAC_BEACON_TIMING_ANS = 0x12,
+ /*!
+ * BeaconFreqReq
+ */
+ SRV_MAC_BEACON_FREQ_REQ = 0x13,
+}LoRaMacSrvCmd_t;
+
+/*!
+ * LoRaMAC band parameters definition
+ */
+typedef struct sBand
+{
+ /*!
+ * Duty cycle
+ */
+ uint16_t DCycle;
+ /*!
+ * Maximum Tx power
+ */
+ int8_t TxMaxPower;
+ /*!
+ * Time stamp of the last JoinReq Tx frame.
+ */
+ TimerTime_t LastJoinTxDoneTime;
+ /*!
+ * Time stamp of the last Tx frame
+ */
+ TimerTime_t LastTxDoneTime;
+ /*!
+ * Holds the time where the device is off
+ */
+ TimerTime_t TimeOff;
+}Band_t;
+
+/*!
+ * LoRaMAC frame types
+ *
+ * LoRaWAN Specification V1.0.2, chapter 4.2.1, table 1
+ */
+typedef enum eLoRaMacFrameType
+{
+ /*!
+ * LoRaMAC join request frame
+ */
+ FRAME_TYPE_JOIN_REQ = 0x00,
+ /*!
+ * LoRaMAC join accept frame
+ */
+ FRAME_TYPE_JOIN_ACCEPT = 0x01,
+ /*!
+ * LoRaMAC unconfirmed up-link frame
+ */
+ FRAME_TYPE_DATA_UNCONFIRMED_UP = 0x02,
+ /*!
+ * LoRaMAC unconfirmed down-link frame
+ */
+ FRAME_TYPE_DATA_UNCONFIRMED_DOWN = 0x03,
+ /*!
+ * LoRaMAC confirmed up-link frame
+ */
+ FRAME_TYPE_DATA_CONFIRMED_UP = 0x04,
+ /*!
+ * LoRaMAC confirmed down-link frame
+ */
+ FRAME_TYPE_DATA_CONFIRMED_DOWN = 0x05,
+ /*!
+ * LoRaMAC proprietary frame
+ */
+ FRAME_TYPE_PROPRIETARY = 0x07,
+}LoRaMacFrameType_t;
+
+/*!
+ * LoRaMAC Battery level indicator
+ */
+typedef enum eLoRaMacBatteryLevel
+{
+ /*!
+ * External power source
+ */
+ BAT_LEVEL_EXT_SRC = 0x00,
+ /*!
+ * Battery level empty
+ */
+ BAT_LEVEL_EMPTY = 0x01,
+ /*!
+ * Battery level full
+ */
+ BAT_LEVEL_FULL = 0xFE,
+ /*!
+ * Battery level - no measurement available
+ */
+ BAT_LEVEL_NO_MEASURE = 0xFF,
+}LoRaMacBatteryLevel_t;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // __LORAMAC_TYPES_H__
+
diff --git a/lib/lora/mac/region/Region.c b/lib/lora/mac/region/Region.c
index 3d61b9b4d2..a1296e4fed 100644
--- a/lib/lora/mac/region/Region.c
+++ b/lib/lora/mac/region/Region.c
@@ -1,75 +1,74 @@
-/*
- / _____) _ | |
-( (____ _____ ____ _| |_ _____ ____| |__
- \____ \| ___ | (_ _) ___ |/ ___) _ \
- _____) ) ____| | | || |_| ____( (___| | | |
-(______/|_____)_|_|_| \__)_____)\____)_| |_|
- (C)2013 Semtech
- ___ _____ _ ___ _ _____ ___ ___ ___ ___
-/ __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
-\__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
-|___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
-embedded.connectivity.solutions===============
-
-Description: LoRa MAC region implementation
-
-License: Revised BSD License, see LICENSE.TXT file include in the project
-
-Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jaeckle ( STACKFORCE )
-*/
-#include
-#include
-#include
-
-#include "lora/system/timer.h"
-#include "lora/mac/LoRaMac.h"
-#include "esp_attr.h"
-
-
-// Regional includes
-#include "Region.h"
-
+/*!
+ * \file Region.c
+ *
+ * \brief Region implementation.
+ *
+ * \copyright Revised BSD License, see section \ref LICENSE.
+ *
+ * \code
+ * ______ _
+ * / _____) _ | |
+ * ( (____ _____ ____ _| |_ _____ ____| |__
+ * \____ \| ___ | (_ _) ___ |/ ___) _ \
+ * _____) ) ____| | | || |_| ____( (___| | | |
+ * (______/|_____)_|_|_| \__)_____)\____)_| |_|
+ * (C)2013-2017 Semtech
+ *
+ * ___ _____ _ ___ _ _____ ___ ___ ___ ___
+ * / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
+ * \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
+ * |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
+ * embedded.connectivity.solutions===============
+ *
+ * \endcode
+ *
+ * \author Miguel Luis ( Semtech )
+ *
+ * \author Gregory Cristian ( Semtech )
+ *
+ * \author Daniel Jaeckle ( STACKFORCE )
+ */
+#include "../LoRaMac.h"
// Setup regions
#ifdef REGION_AS923
#include "RegionAS923.h"
-#define AS923_IS_ACTIVE( ) else if(region == LORAMAC_REGION_AS923) { return true; }
-#define AS923_GET_PHY_PARAM( ) else if(region == LORAMAC_REGION_AS923) { return RegionAS923GetPhyParam( getPhy ); }
-#define AS923_SET_BAND_TX_DONE( ) else if(region == LORAMAC_REGION_AS923) { RegionAS923SetBandTxDone( txDone );}
-#define AS923_INIT_DEFAULTS( ) else if(region == LORAMAC_REGION_AS923) { RegionAS923InitDefaults( type );}
-#define AS923_VERIFY( ) else if(region == LORAMAC_REGION_AS923) { return RegionAS923Verify( verify, phyAttribute ); }
-#define AS923_APPLY_CF_LIST( ) else if(region == LORAMAC_REGION_AS923) { RegionAS923ApplyCFList( applyCFList );}
-#define AS923_CHAN_MASK_SET( ) else if(region == LORAMAC_REGION_AS923) { return RegionAS923ChanMaskSet( chanMaskSet ); }
-#define AS923_ADR_NEXT( ) else if(region == LORAMAC_REGION_AS923) { return RegionAS923AdrNext( adrNext, drOut, txPowOut, adrAckCounter ); }
-#define AS923_COMPUTE_RX_WINDOW_PARAMETERS( ) else if(region == LORAMAC_REGION_AS923) { RegionAS923ComputeRxWindowParameters( datarate, minRxSymbols, rxError, rxConfigParams );}
-#define AS923_RX_CONFIG( ) else if(region == LORAMAC_REGION_AS923) { return RegionAS923RxConfig( rxConfig, datarate ); }
-#define AS923_TX_CONFIG( ) else if(region == LORAMAC_REGION_AS923) { return RegionAS923TxConfig( txConfig, txPower, txTimeOnAir ); }
-#define AS923_LINK_ADR_REQ( ) else if(region == LORAMAC_REGION_AS923) { return RegionAS923LinkAdrReq( linkAdrReq, drOut, txPowOut, nbRepOut, nbBytesParsed ); }
-#define AS923_RX_PARAM_SETUP_REQ( ) else if(region == LORAMAC_REGION_AS923) { return RegionAS923RxParamSetupReq( rxParamSetupReq ); }
-#define AS923_NEW_CHANNEL_REQ( ) else if(region == LORAMAC_REGION_AS923) { return RegionAS923NewChannelReq( newChannelReq ); }
-#define AS923_TX_PARAM_SETUP_REQ( ) else if(region == LORAMAC_REGION_AS923) { return RegionAS923TxParamSetupReq( txParamSetupReq ); }
-#define AS923_DL_CHANNEL_REQ( ) else if(region == LORAMAC_REGION_AS923) { return RegionAS923DlChannelReq( dlChannelReq ); }
-#define AS923_ALTERNATE_DR( ) else if(region == LORAMAC_REGION_AS923) { return RegionAS923AlternateDr( alternateDr ); }
-#define AS923_CALC_BACKOFF( ) else if(region == LORAMAC_REGION_AS923) { RegionAS923CalcBackOff( calcBackOff );}
-#define AS923_NEXT_CHANNEL( ) else if(region == LORAMAC_REGION_AS923) { return RegionAS923NextChannel( nextChanParams, channel, time, aggregatedTimeOff ); }
-#define AS923_CHANNEL_ADD( ) else if(region == LORAMAC_REGION_AS923) { return RegionAS923ChannelAdd( channelAdd ); }
-#define AS923_CHANNEL_REMOVE( ) else if(region == LORAMAC_REGION_AS923) { return RegionAS923ChannelsRemove( channelRemove ); }
-#define AS923_CHANNEL_MANUAL_ADD( ) else if(region == LORAMAC_REGION_AS923) { return RegionAS923ChannelManualAdd( channelAdd ); }
-#define AS923_CHANNEL_MANUAL_REMOVE( ) else if(region == LORAMAC_REGION_AS923) { return RegionAS923ChannelsRemove( channelRemove ); }
-#define AS923_SET_CONTINUOUS_WAVE( ) else if(region == LORAMAC_REGION_AS923) { RegionAS923SetContinuousWave( continuousWave );}
-#define AS923_APPLY_DR_OFFSET( ) else if(region == LORAMAC_REGION_AS923) { return RegionAS923ApplyDrOffset( downlinkDwellTime, dr, drOffset ); }
-#define AS923_GET_CHANNELS( ) else if(region == LORAMAC_REGION_AS923) { return RegionAS923GetChannels( channels, size ); }
-#define AS923_GET_CHANNEL_MASK( ) else if(region == LORAMAC_REGION_AS923) { return RegionAS923GetChannelMask( channelmask, size ); }
-#define AS923_FORCE_JOIN_DATARATE( ) else if(region == LORAMAC_REGION_AS923) { return RegionAS923ForceJoinDataRate( joinDr, alternateDr ); }
+#define AS923_CASE case LORAMAC_REGION_AS923:
+#define AS923_IS_ACTIVE( ) AS923_CASE { return true; }
+#define AS923_GET_PHY_PARAM( ) AS923_CASE { return RegionAS923GetPhyParam( getPhy ); }
+#define AS923_SET_BAND_TX_DONE( ) AS923_CASE { RegionAS923SetBandTxDone( txDone ); break; }
+#define AS923_INIT_DEFAULTS( ) AS923_CASE { RegionAS923InitDefaults( params ); break; }
+#define AS923_GET_NVM_CTX( ) AS923_CASE { return RegionAS923GetNvmCtx( params ); }
+#define AS923_VERIFY( ) AS923_CASE { return RegionAS923Verify( verify, phyAttribute ); }
+#define AS923_APPLY_CF_LIST( ) AS923_CASE { RegionAS923ApplyCFList( applyCFList ); break; }
+#define AS923_CHAN_MASK_SET( ) AS923_CASE { return RegionAS923ChanMaskSet( chanMaskSet ); }
+#define AS923_COMPUTE_RX_WINDOW_PARAMETERS( ) AS923_CASE { RegionAS923ComputeRxWindowParameters( datarate, minRxSymbols, rxError, rxConfigParams ); break; }
+#define AS923_RX_CONFIG( ) AS923_CASE { return RegionAS923RxConfig( rxConfig, datarate ); }
+#define AS923_TX_CONFIG( ) AS923_CASE { return RegionAS923TxConfig( txConfig, txPower, txTimeOnAir ); }
+#define AS923_LINK_ADR_REQ( ) AS923_CASE { return RegionAS923LinkAdrReq( linkAdrReq, drOut, txPowOut, nbRepOut, nbBytesParsed ); }
+#define AS923_RX_PARAM_SETUP_REQ( ) AS923_CASE { return RegionAS923RxParamSetupReq( rxParamSetupReq ); }
+#define AS923_NEW_CHANNEL_REQ( ) AS923_CASE { return RegionAS923NewChannelReq( newChannelReq ); }
+#define AS923_TX_PARAM_SETUP_REQ( ) AS923_CASE { return RegionAS923TxParamSetupReq( txParamSetupReq ); }
+#define AS923_DL_CHANNEL_REQ( ) AS923_CASE { return RegionAS923DlChannelReq( dlChannelReq ); }
+#define AS923_ALTERNATE_DR( ) AS923_CASE { return RegionAS923AlternateDr( currentDr, type ); }
+#define AS923_CALC_BACKOFF( ) AS923_CASE { RegionAS923CalcBackOff( calcBackOff ); break; }
+#define AS923_NEXT_CHANNEL( ) AS923_CASE { return RegionAS923NextChannel( nextChanParams, channel, time, aggregatedTimeOff ); }
+#define AS923_CHANNEL_ADD( ) AS923_CASE { return RegionAS923ChannelAdd( channelAdd ); }
+#define AS923_CHANNEL_REMOVE( ) AS923_CASE { return RegionAS923ChannelsRemove( channelRemove ); }
+#define AS923_SET_CONTINUOUS_WAVE( ) AS923_CASE { RegionAS923SetContinuousWave( continuousWave ); break; }
+#define AS923_APPLY_DR_OFFSET( ) AS923_CASE { return RegionAS923ApplyDrOffset( downlinkDwellTime, dr, drOffset ); }
+#define AS923_RX_BEACON_SETUP( ) AS923_CASE { RegionAS923RxBeaconSetup( rxBeaconSetup, outDr ); break; }
+#define AS923_CHANNEL_MANUAL_ADD( ) AS923_CASE { return RegionAS923ChannelManualAdd( channelAdd ); }
+#define AS923_CHANNEL_MANUAL_REMOVE( ) AS923_CASE { return RegionAS923ChannelsRemove( channelRemove ); }
#else
#define AS923_IS_ACTIVE( )
#define AS923_GET_PHY_PARAM( )
#define AS923_SET_BAND_TX_DONE( )
#define AS923_INIT_DEFAULTS( )
+#define AS923_GET_NVM_CTX( )
#define AS923_VERIFY( )
#define AS923_APPLY_CF_LIST( )
#define AS923_CHAN_MASK_SET( )
-#define AS923_ADR_NEXT( )
#define AS923_COMPUTE_RX_WINDOW_PARAMETERS( )
#define AS923_RX_CONFIG( )
#define AS923_TX_CONFIG( )
@@ -83,55 +82,51 @@ Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jae
#define AS923_NEXT_CHANNEL( )
#define AS923_CHANNEL_ADD( )
#define AS923_CHANNEL_REMOVE( )
-#define AS923_CHANNEL_MANUAL_ADD( )
-#define AS923_CHANNEL_MANUAL_REMOVE( )
#define AS923_SET_CONTINUOUS_WAVE( )
#define AS923_APPLY_DR_OFFSET( )
-#define AS923_GET_CHANNELS( )
-#define AS923_GET_CHANNEL_MASK( )
-#define AS923_FORCE_JOIN_DATARATE( )
+#define AS923_RX_BEACON_SETUP( )
+#define AS923_CHANNEL_MANUAL_ADD( )
+#define AS923_CHANNEL_MANUAL_REMOVE( )
#endif
#ifdef REGION_AU915
#include "RegionAU915.h"
-#define AU915_IS_ACTIVE( ) else if(region == LORAMAC_REGION_AU915) { return true; }
-#define AU915_GET_PHY_PARAM( ) else if(region == LORAMAC_REGION_AU915) { return RegionAU915GetPhyParam( getPhy ); }
-#define AU915_SET_BAND_TX_DONE( ) else if(region == LORAMAC_REGION_AU915) { RegionAU915SetBandTxDone( txDone );}
-#define AU915_INIT_DEFAULTS( ) else if(region == LORAMAC_REGION_AU915) { RegionAU915InitDefaults( type );}
-#define AU915_VERIFY( ) else if(region == LORAMAC_REGION_AU915) { return RegionAU915Verify( verify, phyAttribute ); }
-#define AU915_APPLY_CF_LIST( ) else if(region == LORAMAC_REGION_AU915) { RegionAU915ApplyCFList( applyCFList );}
-#define AU915_CHAN_MASK_SET( ) else if(region == LORAMAC_REGION_AU915) { return RegionAU915ChanMaskSet( chanMaskSet ); }
-#define AU915_ADR_NEXT( ) else if(region == LORAMAC_REGION_AU915) { return RegionAU915AdrNext( adrNext, drOut, txPowOut, adrAckCounter ); }
-#define AU915_COMPUTE_RX_WINDOW_PARAMETERS( ) else if(region == LORAMAC_REGION_AU915) { RegionAU915ComputeRxWindowParameters( datarate, minRxSymbols, rxError, rxConfigParams );}
-#define AU915_RX_CONFIG( ) else if(region == LORAMAC_REGION_AU915) { return RegionAU915RxConfig( rxConfig, datarate ); }
-#define AU915_TX_CONFIG( ) else if(region == LORAMAC_REGION_AU915) { return RegionAU915TxConfig( txConfig, txPower, txTimeOnAir ); }
-#define AU915_LINK_ADR_REQ( ) else if(region == LORAMAC_REGION_AU915) { return RegionAU915LinkAdrReq( linkAdrReq, drOut, txPowOut, nbRepOut, nbBytesParsed ); }
-#define AU915_RX_PARAM_SETUP_REQ( ) else if(region == LORAMAC_REGION_AU915) { return RegionAU915RxParamSetupReq( rxParamSetupReq ); }
-#define AU915_NEW_CHANNEL_REQ( ) else if(region == LORAMAC_REGION_AU915) { return RegionAU915NewChannelReq( newChannelReq ); }
-#define AU915_TX_PARAM_SETUP_REQ( ) else if(region == LORAMAC_REGION_AU915) { return RegionAU915TxParamSetupReq( txParamSetupReq ); }
-#define AU915_DL_CHANNEL_REQ( ) else if(region == LORAMAC_REGION_AU915) { return RegionAU915DlChannelReq( dlChannelReq ); }
-#define AU915_ALTERNATE_DR( ) else if(region == LORAMAC_REGION_AU915) { return RegionAU915AlternateDr( alternateDr ); }
-#define AU915_CALC_BACKOFF( ) else if(region == LORAMAC_REGION_AU915) { RegionAU915CalcBackOff( calcBackOff );}
-#define AU915_NEXT_CHANNEL( ) else if(region == LORAMAC_REGION_AU915) { return RegionAU915NextChannel( nextChanParams, channel, time, aggregatedTimeOff ); }
-#define AU915_CHANNEL_ADD( ) else if(region == LORAMAC_REGION_AU915) { return RegionAU915ChannelAdd( channelAdd ); }
-#define AU915_CHANNEL_REMOVE( ) else if(region == LORAMAC_REGION_AU915) { return RegionAU915ChannelsRemove( channelRemove ); }
-#define AU915_CHANNEL_MANUAL_ADD( ) else if(region == LORAMAC_REGION_AU915) { return RegionAU915ChannelManualAdd( channelAdd ); }
-#define AU915_CHANNEL_MANUAL_REMOVE( ) else if(region == LORAMAC_REGION_AU915) { return RegionAU915ChannelsManualRemove( channelRemove ); }
-#define AU915_SET_CONTINUOUS_WAVE( ) else if(region == LORAMAC_REGION_AU915) { RegionAU915SetContinuousWave( continuousWave );}
-#define AU915_APPLY_DR_OFFSET( ) else if(region == LORAMAC_REGION_AU915) { return RegionAU915ApplyDrOffset( downlinkDwellTime, dr, drOffset ); }
-#define AU915_GET_CHANNELS( ) else if(region == LORAMAC_REGION_AU915) { return RegionAU915GetChannels( channels, size ); }
-#define AU915_GET_CHANNEL_MASK( ) else if(region == LORAMAC_REGION_AU915) { return RegionAU915GetChannelMask( channelmask, size ); }
-#define AU915_GET_CHANNEL_MASK_REMAINING( ) else if(region == LORAMAC_REGION_AU915) { return RegionAU915GetChannelMaskRemaining( channelmask, size ); }
-#define AU915_FORCE_JOIN_DATARATE( ) else if(region == LORAMAC_REGION_AU915) { return RegionAU915ForceJoinDataRate( joinDr, alternateDr ); }
+#define AU915_CASE case LORAMAC_REGION_AU915:
+#define AU915_IS_ACTIVE( ) AU915_CASE { return true; }
+#define AU915_GET_PHY_PARAM( ) AU915_CASE { return RegionAU915GetPhyParam( getPhy ); }
+#define AU915_SET_BAND_TX_DONE( ) AU915_CASE { RegionAU915SetBandTxDone( txDone ); break; }
+#define AU915_INIT_DEFAULTS( ) AU915_CASE { RegionAU915InitDefaults( params ); break; }
+#define AU915_GET_NVM_CTX( ) AU915_CASE { return RegionAU915GetNvmCtx( params ); }
+#define AU915_VERIFY( ) AU915_CASE { return RegionAU915Verify( verify, phyAttribute ); }
+#define AU915_APPLY_CF_LIST( ) AU915_CASE { RegionAU915ApplyCFList( applyCFList ); break; }
+#define AU915_CHAN_MASK_SET( ) AU915_CASE { return RegionAU915ChanMaskSet( chanMaskSet ); }
+#define AU915_COMPUTE_RX_WINDOW_PARAMETERS( ) AU915_CASE { RegionAU915ComputeRxWindowParameters( datarate, minRxSymbols, rxError, rxConfigParams ); break; }
+#define AU915_RX_CONFIG( ) AU915_CASE { return RegionAU915RxConfig( rxConfig, datarate ); }
+#define AU915_TX_CONFIG( ) AU915_CASE { return RegionAU915TxConfig( txConfig, txPower, txTimeOnAir ); }
+#define AU915_LINK_ADR_REQ( ) AU915_CASE { return RegionAU915LinkAdrReq( linkAdrReq, drOut, txPowOut, nbRepOut, nbBytesParsed ); }
+#define AU915_RX_PARAM_SETUP_REQ( ) AU915_CASE { return RegionAU915RxParamSetupReq( rxParamSetupReq ); }
+#define AU915_NEW_CHANNEL_REQ( ) AU915_CASE { return RegionAU915NewChannelReq( newChannelReq ); }
+#define AU915_TX_PARAM_SETUP_REQ( ) AU915_CASE { return RegionAU915TxParamSetupReq( txParamSetupReq ); }
+#define AU915_DL_CHANNEL_REQ( ) AU915_CASE { return RegionAU915DlChannelReq( dlChannelReq ); }
+#define AU915_ALTERNATE_DR( ) AU915_CASE { return RegionAU915AlternateDr( currentDr, type ); }
+#define AU915_CALC_BACKOFF( ) AU915_CASE { RegionAU915CalcBackOff( calcBackOff ); break; }
+#define AU915_NEXT_CHANNEL( ) AU915_CASE { return RegionAU915NextChannel( nextChanParams, channel, time, aggregatedTimeOff ); }
+#define AU915_CHANNEL_ADD( ) AU915_CASE { return RegionAU915ChannelAdd( channelAdd ); }
+#define AU915_CHANNEL_REMOVE( ) AU915_CASE { return RegionAU915ChannelsRemove( channelRemove ); }
+#define AU915_SET_CONTINUOUS_WAVE( ) AU915_CASE { RegionAU915SetContinuousWave( continuousWave ); break; }
+#define AU915_APPLY_DR_OFFSET( ) AU915_CASE { return RegionAU915ApplyDrOffset( downlinkDwellTime, dr, drOffset ); }
+#define AU915_RX_BEACON_SETUP( ) AU915_CASE { RegionAU915RxBeaconSetup( rxBeaconSetup, outDr ); break; }
+#define AU915_CHANNEL_MANUAL_ADD( ) AU915_CASE { return RegionAU915ChannelManualAdd( channelAdd ); }
+#define AU915_CHANNEL_MANUAL_REMOVE( ) AU915_CASE { return RegionAU915ChannelsManualRemove( channelRemove ); }
#else
#define AU915_IS_ACTIVE( )
#define AU915_GET_PHY_PARAM( )
#define AU915_SET_BAND_TX_DONE( )
#define AU915_INIT_DEFAULTS( )
+#define AU915_GET_NVM_CTX( )
#define AU915_VERIFY( )
#define AU915_APPLY_CF_LIST( )
#define AU915_CHAN_MASK_SET( )
-#define AU915_ADR_NEXT( )
#define AU915_COMPUTE_RX_WINDOW_PARAMETERS( )
#define AU915_RX_CONFIG( )
#define AU915_TX_CONFIG( )
@@ -145,53 +140,52 @@ Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jae
#define AU915_NEXT_CHANNEL( )
#define AU915_CHANNEL_ADD( )
#define AU915_CHANNEL_REMOVE( )
-#define AU915_CHANNEL_MANUAL_ADD( )
-#define AU915_CHANNEL_MANUAL_REMOVE( )
#define AU915_SET_CONTINUOUS_WAVE( )
#define AU915_APPLY_DR_OFFSET( )
-#define AU915_GET_CHANNELS( )
-#define AU915_GET_CHANNEL_MASK( )
-#define AU915_GET_CHANNEL_MASK_REMAINING( )
-#define AU915_FORCE_JOIN_DATARATE( )
+#define AU915_RX_BEACON_SETUP( )
+#define AU915_CHANNEL_MANUAL_ADD( )
+#define AU915_CHANNEL_MANUAL_REMOVE( )
+
#endif
#ifdef REGION_CN470
#include "RegionCN470.h"
-#define CN470_IS_ACTIVE( ) else if(region == LORAMAC_REGION_CN470) { return true; }
-#define CN470_GET_PHY_PARAM( ) else if(region == LORAMAC_REGION_CN470) { return RegionCN470GetPhyParam( getPhy ); }
-#define CN470_SET_BAND_TX_DONE( ) else if(region == LORAMAC_REGION_CN470) { RegionCN470SetBandTxDone( txDone );}
-#define CN470_INIT_DEFAULTS( ) else if(region == LORAMAC_REGION_CN470) { RegionCN470InitDefaults( type );}
-#define CN470_VERIFY( ) else if(region == LORAMAC_REGION_CN470) { return RegionCN470Verify( verify, phyAttribute ); }
-#define CN470_APPLY_CF_LIST( ) else if(region == LORAMAC_REGION_CN470) { RegionCN470ApplyCFList( applyCFList );}
-#define CN470_CHAN_MASK_SET( ) else if(region == LORAMAC_REGION_CN470) { return RegionCN470ChanMaskSet( chanMaskSet ); }
-#define CN470_ADR_NEXT( ) else if(region == LORAMAC_REGION_CN470) { return RegionCN470AdrNext( adrNext, drOut, txPowOut, adrAckCounter ); }
-#define CN470_COMPUTE_RX_WINDOW_PARAMETERS( ) else if(region == LORAMAC_REGION_CN470) { RegionCN470ComputeRxWindowParameters( datarate, minRxSymbols, rxError, rxConfigParams );}
-#define CN470_RX_CONFIG( ) else if(region == LORAMAC_REGION_CN470) { return RegionCN470RxConfig( rxConfig, datarate ); }
-#define CN470_TX_CONFIG( ) else if(region == LORAMAC_REGION_CN470) { return RegionCN470TxConfig( txConfig, txPower, txTimeOnAir ); }
-#define CN470_LINK_ADR_REQ( ) else if(region == LORAMAC_REGION_CN470) { return RegionCN470LinkAdrReq( linkAdrReq, drOut, txPowOut, nbRepOut, nbBytesParsed ); }
-#define CN470_RX_PARAM_SETUP_REQ( ) else if(region == LORAMAC_REGION_CN470) { return RegionCN470RxParamSetupReq( rxParamSetupReq ); }
-#define CN470_NEW_CHANNEL_REQ( ) else if(region == LORAMAC_REGION_CN470) { return RegionCN470NewChannelReq( newChannelReq ); }
-#define CN470_TX_PARAM_SETUP_REQ( ) else if(region == LORAMAC_REGION_CN470) { return RegionCN470TxParamSetupReq( txParamSetupReq ); }
-#define CN470_DL_CHANNEL_REQ( ) else if(region == LORAMAC_REGION_CN470) { return RegionCN470DlChannelReq( dlChannelReq ); }
-#define CN470_ALTERNATE_DR( ) else if(region == LORAMAC_REGION_CN470) { return RegionCN470AlternateDr( alternateDr ); }
-#define CN470_CALC_BACKOFF( ) else if(region == LORAMAC_REGION_CN470) { RegionCN470CalcBackOff( calcBackOff );}
-#define CN470_NEXT_CHANNEL( ) else if(region == LORAMAC_REGION_CN470) { return RegionCN470NextChannel( nextChanParams, channel, time, aggregatedTimeOff ); }
-#define CN470_CHANNEL_ADD( ) else if(region == LORAMAC_REGION_CN470) { return RegionCN470ChannelAdd( channelAdd ); }
-#define CN470_CHANNEL_REMOVE( ) else if(region == LORAMAC_REGION_CN470) { return RegionCN470ChannelsRemove( channelRemove ); }
-#define CN470_CHANNEL_MANUAL_ADD( ) else if(region == LORAMAC_REGION_CN470) { return RegionCN470ChannelManualAdd( channelAdd ); }
-#define CN470_CHANNEL_MANUAL_REMOVE( ) else if(region == LORAMAC_REGION_CN470) { return RegionCN470ChannelsRemove( channelRemove ); }
-#define CN470_SET_CONTINUOUS_WAVE( ) else if(region == LORAMAC_REGION_CN470) { RegionCN470SetContinuousWave( continuousWave );}
-#define CN470_APPLY_DR_OFFSET( ) else if(region == LORAMAC_REGION_CN470) { return RegionCN470ApplyDrOffset( downlinkDwellTime, dr, drOffset ); }
-#define CN470_FORCE_JOIN_DATARATE( ) else if(region == LORAMAC_REGION_CN470) { return RegionCN470ForceJoinDataRate( joinDr, alternateDr ); }
+#define CN470_CASE case LORAMAC_REGION_CN470:
+#define CN470_IS_ACTIVE( ) CN470_CASE { return true; }
+#define CN470_GET_PHY_PARAM( ) CN470_CASE { return RegionCN470GetPhyParam( getPhy ); }
+#define CN470_SET_BAND_TX_DONE( ) CN470_CASE { RegionCN470SetBandTxDone( txDone ); break; }
+#define CN470_INIT_DEFAULTS( ) CN470_CASE { RegionCN470InitDefaults( params ); break; }
+#define CN470_GET_NVM_CTX( ) CN470_CASE { return RegionCN470GetNvmCtx( params ); }
+#define CN470_VERIFY( ) CN470_CASE { return RegionCN470Verify( verify, phyAttribute ); }
+#define CN470_APPLY_CF_LIST( ) CN470_CASE { RegionCN470ApplyCFList( applyCFList ); break; }
+#define CN470_CHAN_MASK_SET( ) CN470_CASE { return RegionCN470ChanMaskSet( chanMaskSet ); }
+#define CN470_COMPUTE_RX_WINDOW_PARAMETERS( ) CN470_CASE { RegionCN470ComputeRxWindowParameters( datarate, minRxSymbols, rxError, rxConfigParams ); break; }
+#define CN470_RX_CONFIG( ) CN470_CASE { return RegionCN470RxConfig( rxConfig, datarate ); }
+#define CN470_TX_CONFIG( ) CN470_CASE { return RegionCN470TxConfig( txConfig, txPower, txTimeOnAir ); }
+#define CN470_LINK_ADR_REQ( ) CN470_CASE { return RegionCN470LinkAdrReq( linkAdrReq, drOut, txPowOut, nbRepOut, nbBytesParsed ); }
+#define CN470_RX_PARAM_SETUP_REQ( ) CN470_CASE { return RegionCN470RxParamSetupReq( rxParamSetupReq ); }
+#define CN470_NEW_CHANNEL_REQ( ) CN470_CASE { return RegionCN470NewChannelReq( newChannelReq ); }
+#define CN470_TX_PARAM_SETUP_REQ( ) CN470_CASE { return RegionCN470TxParamSetupReq( txParamSetupReq ); }
+#define CN470_DL_CHANNEL_REQ( ) CN470_CASE { return RegionCN470DlChannelReq( dlChannelReq ); }
+#define CN470_ALTERNATE_DR( ) CN470_CASE { return RegionCN470AlternateDr( currentDr, type ); }
+#define CN470_CALC_BACKOFF( ) CN470_CASE { RegionCN470CalcBackOff( calcBackOff ); break; }
+#define CN470_NEXT_CHANNEL( ) CN470_CASE { return RegionCN470NextChannel( nextChanParams, channel, time, aggregatedTimeOff ); }
+#define CN470_CHANNEL_ADD( ) CN470_CASE { return RegionCN470ChannelAdd( channelAdd ); }
+#define CN470_CHANNEL_REMOVE( ) CN470_CASE { return RegionCN470ChannelsRemove( channelRemove ); }
+#define CN470_SET_CONTINUOUS_WAVE( ) CN470_CASE { RegionCN470SetContinuousWave( continuousWave ); break; }
+#define CN470_APPLY_DR_OFFSET( ) CN470_CASE { return RegionCN470ApplyDrOffset( downlinkDwellTime, dr, drOffset ); }
+#define CN470_RX_BEACON_SETUP( ) CN470_CASE { RegionCN470RxBeaconSetup( rxBeaconSetup, outDr ); break; }
+#define CN470_CHANNEL_MANUAL_ADD( ) CN470_CASE { return RegionCN470ChannelManualAdd( channelAdd ); }
+#define CN470_CHANNEL_MANUAL_REMOVE( ) CN470_CASE { return RegionCN470ChannelsRemove( channelRemove ); }
#else
#define CN470_IS_ACTIVE( )
#define CN470_GET_PHY_PARAM( )
#define CN470_SET_BAND_TX_DONE( )
#define CN470_INIT_DEFAULTS( )
+#define CN470_GET_NVM_CTX( )
#define CN470_VERIFY( )
#define CN470_APPLY_CF_LIST( )
#define CN470_CHAN_MASK_SET( )
-#define CN470_ADR_NEXT( )
#define CN470_COMPUTE_RX_WINDOW_PARAMETERS( )
#define CN470_RX_CONFIG( )
#define CN470_TX_CONFIG( )
@@ -205,47 +199,51 @@ Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jae
#define CN470_NEXT_CHANNEL( )
#define CN470_CHANNEL_ADD( )
#define CN470_CHANNEL_REMOVE( )
-#define CN470_CHANNEL_MANUAL_ADD( )
-#define CN470_CHANNEL_MANUAL_REMOVE( )
#define CN470_SET_CONTINUOUS_WAVE( )
#define CN470_APPLY_DR_OFFSET( )
-#define CN470_FORCE_JOIN_DATARATE( )
+#define CN470_RX_BEACON_SETUP( )
+#define CN470_CHANNEL_MANUAL_ADD( )
+#define CN470_CHANNEL_MANUAL_REMOVE( )
#endif
#ifdef REGION_CN779
#include "RegionCN779.h"
-#define CN779_IS_ACTIVE( ) else if(region == LORAMAC_REGION_CN779) { return true; }
-#define CN779_GET_PHY_PARAM( ) else if(region == LORAMAC_REGION_CN779) { return RegionCN779GetPhyParam( getPhy ); }
-#define CN779_SET_BAND_TX_DONE( ) else if(region == LORAMAC_REGION_CN779) { RegionCN779SetBandTxDone( txDone );}
-#define CN779_INIT_DEFAULTS( ) else if(region == LORAMAC_REGION_CN779) { RegionCN779InitDefaults( type );}
-#define CN779_VERIFY( ) else if(region == LORAMAC_REGION_CN779) { return RegionCN779Verify( verify, phyAttribute ); }
-#define CN779_APPLY_CF_LIST( ) else if(region == LORAMAC_REGION_CN779) { RegionCN779ApplyCFList( applyCFList );}
-#define CN779_CHAN_MASK_SET( ) else if(region == LORAMAC_REGION_CN779) { return RegionCN779ChanMaskSet( chanMaskSet ); }
-#define CN779_ADR_NEXT( ) else if(region == LORAMAC_REGION_CN779) { return RegionCN779AdrNext( adrNext, drOut, txPowOut, adrAckCounter ); }
-#define CN779_COMPUTE_RX_WINDOW_PARAMETERS( ) else if(region == LORAMAC_REGION_CN779) { RegionCN779ComputeRxWindowParameters( datarate, minRxSymbols, rxError, rxConfigParams );}
-#define CN779_RX_CONFIG( ) else if(region == LORAMAC_REGION_CN779) { return RegionCN779RxConfig( rxConfig, datarate ); }
-#define CN779_TX_CONFIG( ) else if(region == LORAMAC_REGION_CN779) { return RegionCN779TxConfig( txConfig, txPower, txTimeOnAir ); }
-#define CN779_LINK_ADR_REQ( ) else if(region == LORAMAC_REGION_CN779) { return RegionCN779LinkAdrReq( linkAdrReq, drOut, txPowOut, nbRepOut, nbBytesParsed ); }
-#define CN779_RX_PARAM_SETUP_REQ( ) else if(region == LORAMAC_REGION_CN779) { return RegionCN779RxParamSetupReq( rxParamSetupReq ); }
-#define CN779_NEW_CHANNEL_REQ( ) else if(region == LORAMAC_REGION_CN779) { return RegionCN779NewChannelReq( newChannelReq ); }
-#define CN779_TX_PARAM_SETUP_REQ( ) else if(region == LORAMAC_REGION_CN779) { return RegionCN779TxParamSetupReq( txParamSetupReq ); }
-#define CN779_DL_CHANNEL_REQ( ) else if(region == LORAMAC_REGION_CN779) { return RegionCN779DlChannelReq( dlChannelReq ); }
-#define CN779_ALTERNATE_DR( ) else if(region == LORAMAC_REGION_CN779) { return RegionCN779AlternateDr( alternateDr ); }
-#define CN779_CALC_BACKOFF( ) else if(region == LORAMAC_REGION_CN779) { RegionCN779CalcBackOff( calcBackOff );}
-#define CN779_NEXT_CHANNEL( ) else if(region == LORAMAC_REGION_CN779) { return RegionCN779NextChannel( nextChanParams, channel, time, aggregatedTimeOff ); }
-#define CN779_CHANNEL_ADD( ) else if(region == LORAMAC_REGION_CN779) { return RegionCN779ChannelAdd( channelAdd ); }
-#define CN779_CHANNEL_REMOVE( ) else if(region == LORAMAC_REGION_CN779) { return RegionCN779ChannelsRemove( channelRemove ); }
-#define CN779_SET_CONTINUOUS_WAVE( ) else if(region == LORAMAC_REGION_CN779) { RegionCN779SetContinuousWave( continuousWave );}
-#define CN779_APPLY_DR_OFFSET( ) else if(region == LORAMAC_REGION_CN779) { return RegionCN779ApplyDrOffset( downlinkDwellTime, dr, drOffset ); }
+#define CN779_CASE case LORAMAC_REGION_CN779:
+#define CN779_IS_ACTIVE( ) CN779_CASE { return true; }
+#define CN779_GET_PHY_PARAM( ) CN779_CASE { return RegionCN779GetPhyParam( getPhy ); }
+#define CN779_SET_BAND_TX_DONE( ) CN779_CASE { RegionCN779SetBandTxDone( txDone ); break; }
+#define CN779_INIT_DEFAULTS( ) CN779_CASE { RegionCN779InitDefaults( params ); break; }
+#define CN779_GET_NVM_CTX( ) CN779_CASE { return RegionCN779GetNvmCtx( params ); }
+#define CN779_VERIFY( ) CN779_CASE { return RegionCN779Verify( verify, phyAttribute ); }
+#define CN779_APPLY_CF_LIST( ) CN779_CASE { RegionCN779ApplyCFList( applyCFList ); break; }
+#define CN779_CHAN_MASK_SET( ) CN779_CASE { return RegionCN779ChanMaskSet( chanMaskSet ); }
+#define CN779_COMPUTE_RX_WINDOW_PARAMETERS( ) CN779_CASE { RegionCN779ComputeRxWindowParameters( datarate, minRxSymbols, rxError, rxConfigParams ); break; }
+#define CN779_RX_CONFIG( ) CN779_CASE { return RegionCN779RxConfig( rxConfig, datarate ); }
+#define CN779_TX_CONFIG( ) CN779_CASE { return RegionCN779TxConfig( txConfig, txPower, txTimeOnAir ); }
+#define CN779_LINK_ADR_REQ( ) CN779_CASE { return RegionCN779LinkAdrReq( linkAdrReq, drOut, txPowOut, nbRepOut, nbBytesParsed ); }
+#define CN779_RX_PARAM_SETUP_REQ( ) CN779_CASE { return RegionCN779RxParamSetupReq( rxParamSetupReq ); }
+#define CN779_NEW_CHANNEL_REQ( ) CN779_CASE { return RegionCN779NewChannelReq( newChannelReq ); }
+#define CN779_TX_PARAM_SETUP_REQ( ) CN779_CASE { return RegionCN779TxParamSetupReq( txParamSetupReq ); }
+#define CN779_DL_CHANNEL_REQ( ) CN779_CASE { return RegionCN779DlChannelReq( dlChannelReq ); }
+#define CN779_ALTERNATE_DR( ) CN779_CASE { return RegionCN779AlternateDr( currentDr, type ); }
+#define CN779_CALC_BACKOFF( ) CN779_CASE { RegionCN779CalcBackOff( calcBackOff ); break; }
+#define CN779_NEXT_CHANNEL( ) CN779_CASE { return RegionCN779NextChannel( nextChanParams, channel, time, aggregatedTimeOff ); }
+#define CN779_CHANNEL_ADD( ) CN779_CASE { return RegionCN779ChannelAdd( channelAdd ); }
+#define CN779_CHANNEL_REMOVE( ) CN779_CASE { return RegionCN779ChannelsRemove( channelRemove ); }
+#define CN779_SET_CONTINUOUS_WAVE( ) CN779_CASE { RegionCN779SetContinuousWave( continuousWave ); break; }
+#define CN779_APPLY_DR_OFFSET( ) CN779_CASE { return RegionCN779ApplyDrOffset( downlinkDwellTime, dr, drOffset ); }
+#define CN779_RX_BEACON_SETUP( ) CN779_CASE { RegionCN779RxBeaconSetup( rxBeaconSetup, outDr ); break; }
+#define CN779_CHANNEL_MANUAL_ADD( ) CN779_CASE { return RegionCN779ChannelManualAdd( channelAdd ); }
+#define CN779_CHANNEL_MANUAL_REMOVE( ) CN779_CASE { return RegionCN779ChannelsRemove( channelRemove ); }
#else
#define CN779_IS_ACTIVE( )
#define CN779_GET_PHY_PARAM( )
#define CN779_SET_BAND_TX_DONE( )
#define CN779_INIT_DEFAULTS( )
+#define CN779_GET_NVM_CTX( )
#define CN779_VERIFY( )
#define CN779_APPLY_CF_LIST( )
#define CN779_CHAN_MASK_SET( )
-#define CN779_ADR_NEXT( )
#define CN779_COMPUTE_RX_WINDOW_PARAMETERS( )
#define CN779_RX_CONFIG( )
#define CN779_TX_CONFIG( )
@@ -261,45 +259,49 @@ Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jae
#define CN779_CHANNEL_REMOVE( )
#define CN779_SET_CONTINUOUS_WAVE( )
#define CN779_APPLY_DR_OFFSET( )
+#define CN779_RX_BEACON_SETUP( )
+#define CN779_CHANNEL_MANUAL_ADD( )
+#define CN779_CHANNEL_MANUAL_REMOVE( )
#endif
#ifdef REGION_EU433
#include "RegionEU433.h"
-#define EU433_IS_ACTIVE( ) else if(region == LORAMAC_REGION_EU433) { return true; }
-#define EU433_GET_PHY_PARAM( ) else if(region == LORAMAC_REGION_EU433) { return RegionEU433GetPhyParam( getPhy ); }
-#define EU433_SET_BAND_TX_DONE( ) else if(region == LORAMAC_REGION_EU433) { RegionEU433SetBandTxDone( txDone );}
-#define EU433_INIT_DEFAULTS( ) else if(region == LORAMAC_REGION_EU433) { RegionEU433InitDefaults( type );}
-#define EU433_VERIFY( ) else if(region == LORAMAC_REGION_EU433) { return RegionEU433Verify( verify, phyAttribute ); }
-#define EU433_APPLY_CF_LIST( ) else if(region == LORAMAC_REGION_EU433) { RegionEU433ApplyCFList( applyCFList );}
-#define EU433_CHAN_MASK_SET( ) else if(region == LORAMAC_REGION_EU433) { return RegionEU433ChanMaskSet( chanMaskSet ); }
-#define EU433_ADR_NEXT( ) else if(region == LORAMAC_REGION_EU433) { return RegionEU433AdrNext( adrNext, drOut, txPowOut, adrAckCounter ); }
-#define EU433_COMPUTE_RX_WINDOW_PARAMETERS( ) else if(region == LORAMAC_REGION_EU433) { RegionEU433ComputeRxWindowParameters( datarate, minRxSymbols, rxError, rxConfigParams );}
-#define EU433_RX_CONFIG( ) else if(region == LORAMAC_REGION_EU433) { return RegionEU433RxConfig( rxConfig, datarate ); }
-#define EU433_TX_CONFIG( ) else if(region == LORAMAC_REGION_EU433) { return RegionEU433TxConfig( txConfig, txPower, txTimeOnAir ); }
-#define EU433_LINK_ADR_REQ( ) else if(region == LORAMAC_REGION_EU433) { return RegionEU433LinkAdrReq( linkAdrReq, drOut, txPowOut, nbRepOut, nbBytesParsed ); }
-#define EU433_RX_PARAM_SETUP_REQ( ) else if(region == LORAMAC_REGION_EU433) { return RegionEU433RxParamSetupReq( rxParamSetupReq ); }
-#define EU433_NEW_CHANNEL_REQ( ) else if(region == LORAMAC_REGION_EU433) { return RegionEU433NewChannelReq( newChannelReq ); }
-#define EU433_TX_PARAM_SETUP_REQ( ) else if(region == LORAMAC_REGION_EU433) { return RegionEU433TxParamSetupReq( txParamSetupReq ); }
-#define EU433_DL_CHANNEL_REQ( ) else if(region == LORAMAC_REGION_EU433) { return RegionEU433DlChannelReq( dlChannelReq ); }
-#define EU433_ALTERNATE_DR( ) else if(region == LORAMAC_REGION_EU433) { return RegionEU433AlternateDr( alternateDr ); }
-#define EU433_CALC_BACKOFF( ) else if(region == LORAMAC_REGION_EU433) { RegionEU433CalcBackOff( calcBackOff );}
-#define EU433_NEXT_CHANNEL( ) else if(region == LORAMAC_REGION_EU433) { return RegionEU433NextChannel( nextChanParams, channel, time, aggregatedTimeOff ); }
-#define EU433_CHANNEL_ADD( ) else if(region == LORAMAC_REGION_EU433) { return RegionEU433ChannelAdd( channelAdd ); }
-#define EU433_CHANNEL_REMOVE( ) else if(region == LORAMAC_REGION_EU433) { return RegionEU433ChannelsRemove( channelRemove ); }
+#define EU433_CASE case LORAMAC_REGION_EU433:
+#define EU433_IS_ACTIVE( ) EU433_CASE { return true; }
+#define EU433_GET_PHY_PARAM( ) EU433_CASE { return RegionEU433GetPhyParam( getPhy ); }
+#define EU433_SET_BAND_TX_DONE( ) EU433_CASE { RegionEU433SetBandTxDone( txDone ); break; }
+#define EU433_INIT_DEFAULTS( ) EU433_CASE { RegionEU433InitDefaults( params ); break; }
+#define EU433_GET_NVM_CTX( ) EU433_CASE { return RegionEU433GetNvmCtx( params ); }
+#define EU433_VERIFY( ) EU433_CASE { return RegionEU433Verify( verify, phyAttribute ); }
+#define EU433_APPLY_CF_LIST( ) EU433_CASE { RegionEU433ApplyCFList( applyCFList ); break; }
+#define EU433_CHAN_MASK_SET( ) EU433_CASE { return RegionEU433ChanMaskSet( chanMaskSet ); }
+#define EU433_COMPUTE_RX_WINDOW_PARAMETERS( ) EU433_CASE { RegionEU433ComputeRxWindowParameters( datarate, minRxSymbols, rxError, rxConfigParams ); break; }
+#define EU433_RX_CONFIG( ) EU433_CASE { return RegionEU433RxConfig( rxConfig, datarate ); }
+#define EU433_TX_CONFIG( ) EU433_CASE { return RegionEU433TxConfig( txConfig, txPower, txTimeOnAir ); }
+#define EU433_LINK_ADR_REQ( ) EU433_CASE { return RegionEU433LinkAdrReq( linkAdrReq, drOut, txPowOut, nbRepOut, nbBytesParsed ); }
+#define EU433_RX_PARAM_SETUP_REQ( ) EU433_CASE { return RegionEU433RxParamSetupReq( rxParamSetupReq ); }
+#define EU433_NEW_CHANNEL_REQ( ) EU433_CASE { return RegionEU433NewChannelReq( newChannelReq ); }
+#define EU433_TX_PARAM_SETUP_REQ( ) EU433_CASE { return RegionEU433TxParamSetupReq( txParamSetupReq ); }
+#define EU433_DL_CHANNEL_REQ( ) EU433_CASE { return RegionEU433DlChannelReq( dlChannelReq ); }
+#define EU433_ALTERNATE_DR( ) EU433_CASE { return RegionEU433AlternateDr( currentDr, type ); }
+#define EU433_CALC_BACKOFF( ) EU433_CASE { RegionEU433CalcBackOff( calcBackOff ); break; }
+#define EU433_NEXT_CHANNEL( ) EU433_CASE { return RegionEU433NextChannel( nextChanParams, channel, time, aggregatedTimeOff ); }
+#define EU433_CHANNEL_ADD( ) EU433_CASE { return RegionEU433ChannelAdd( channelAdd ); }
+#define EU433_CHANNEL_REMOVE( ) EU433_CASE { return RegionEU433ChannelsRemove( channelRemove ); }
+#define EU433_SET_CONTINUOUS_WAVE( ) EU433_CASE { RegionEU433SetContinuousWave( continuousWave ); break; }
+#define EU433_APPLY_DR_OFFSET( ) EU433_CASE { return RegionEU433ApplyDrOffset( downlinkDwellTime, dr, drOffset ); }
+#define EU433_RX_BEACON_SETUP( ) EU433_CASE { RegionEU433RxBeaconSetup( rxBeaconSetup, outDr ); break; }
#define EU433_CHANNEL_MANUAL_ADD( ) EU433_CASE { return RegionEU433ChannelManualAdd( channelAdd ); }
-#define EU433_CHANNEL_MANUAL_REMOVE( ) EU433_CASE { return RegionEU433ChannelsRemove( channelRemove ); }
-#define EU433_SET_CONTINUOUS_WAVE( ) else if(region == LORAMAC_REGION_EU433) { RegionEU433SetContinuousWave( continuousWave );}
-#define EU433_APPLY_DR_OFFSET( ) else if(region == LORAMAC_REGION_EU433) { return RegionEU433ApplyDrOffset( downlinkDwellTime, dr, drOffset ); }
-#define EU433_FORCE_JOIN_DATARATE( ) EU433_CASE { return RegionEU433ForceJoinDataRate( joinDr, alternateDr ); }
+#define EU433_CHANNEL_MANUAL_REMOVE( ) EU433_CASE { return RegionEU433ChannelsRemove( channelRemove ); }
#else
#define EU433_IS_ACTIVE( )
#define EU433_GET_PHY_PARAM( )
#define EU433_SET_BAND_TX_DONE( )
#define EU433_INIT_DEFAULTS( )
+#define EU433_GET_NVM_CTX( )
#define EU433_VERIFY( )
#define EU433_APPLY_CF_LIST( )
#define EU433_CHAN_MASK_SET( )
-#define EU433_ADR_NEXT( )
#define EU433_COMPUTE_RX_WINDOW_PARAMETERS( )
#define EU433_RX_CONFIG( )
#define EU433_TX_CONFIG( )
@@ -313,52 +315,51 @@ Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jae
#define EU433_NEXT_CHANNEL( )
#define EU433_CHANNEL_ADD( )
#define EU433_CHANNEL_REMOVE( )
-#define EU433_CHANNEL_MANUAL_ADD( )
-#define EU433_CHANNEL_MANUAL_REMOVE( )
#define EU433_SET_CONTINUOUS_WAVE( )
#define EU433_APPLY_DR_OFFSET( )
-#define EU433_FORCE_JOIN_DATARATE( )
+#define EU433_RX_BEACON_SETUP( )
+#define EU433_CHANNEL_MANUAL_ADD( )
+#define EU433_CHANNEL_MANUAL_REMOVE( )
#endif
#ifdef REGION_EU868
#include "RegionEU868.h"
-#define EU868_IS_ACTIVE( ) else if(region == LORAMAC_REGION_EU868) { return true; }
-#define EU868_GET_PHY_PARAM( ) else if(region == LORAMAC_REGION_EU868) { return RegionEU868GetPhyParam( getPhy ); }
-#define EU868_SET_BAND_TX_DONE( ) else if(region == LORAMAC_REGION_EU868) { RegionEU868SetBandTxDone( txDone );}
-#define EU868_INIT_DEFAULTS( ) else if(region == LORAMAC_REGION_EU868) { RegionEU868InitDefaults( type );}
-#define EU868_VERIFY( ) else if(region == LORAMAC_REGION_EU868) { return RegionEU868Verify( verify, phyAttribute ); }
-#define EU868_APPLY_CF_LIST( ) else if(region == LORAMAC_REGION_EU868) { RegionEU868ApplyCFList( applyCFList );}
-#define EU868_CHAN_MASK_SET( ) else if(region == LORAMAC_REGION_EU868) { return RegionEU868ChanMaskSet( chanMaskSet ); }
-#define EU868_ADR_NEXT( ) else if(region == LORAMAC_REGION_EU868) { return RegionEU868AdrNext( adrNext, drOut, txPowOut, adrAckCounter ); }
-#define EU868_COMPUTE_RX_WINDOW_PARAMETERS( ) else if(region == LORAMAC_REGION_EU868) { RegionEU868ComputeRxWindowParameters( datarate, minRxSymbols, rxError, rxConfigParams );}
-#define EU868_RX_CONFIG( ) else if(region == LORAMAC_REGION_EU868) { return RegionEU868RxConfig( rxConfig, datarate ); }
-#define EU868_TX_CONFIG( ) else if(region == LORAMAC_REGION_EU868) { return RegionEU868TxConfig( txConfig, txPower, txTimeOnAir ); }
-#define EU868_LINK_ADR_REQ( ) else if(region == LORAMAC_REGION_EU868) { return RegionEU868LinkAdrReq( linkAdrReq, drOut, txPowOut, nbRepOut, nbBytesParsed ); }
-#define EU868_RX_PARAM_SETUP_REQ( ) else if(region == LORAMAC_REGION_EU868) { return RegionEU868RxParamSetupReq( rxParamSetupReq ); }
-#define EU868_NEW_CHANNEL_REQ( ) else if(region == LORAMAC_REGION_EU868) { return RegionEU868NewChannelReq( newChannelReq ); }
-#define EU868_TX_PARAM_SETUP_REQ( ) else if(region == LORAMAC_REGION_EU868) { return RegionEU868TxParamSetupReq( txParamSetupReq ); }
-#define EU868_DL_CHANNEL_REQ( ) else if(region == LORAMAC_REGION_EU868) { return RegionEU868DlChannelReq( dlChannelReq ); }
-#define EU868_ALTERNATE_DR( ) else if(region == LORAMAC_REGION_EU868) { return RegionEU868AlternateDr( alternateDr ); }
-#define EU868_CALC_BACKOFF( ) else if(region == LORAMAC_REGION_EU868) { RegionEU868CalcBackOff( calcBackOff );}
-#define EU868_NEXT_CHANNEL( ) else if(region == LORAMAC_REGION_EU868) { return RegionEU868NextChannel( nextChanParams, channel, time, aggregatedTimeOff ); }
-#define EU868_CHANNEL_ADD( ) else if(region == LORAMAC_REGION_EU868) { return RegionEU868ChannelAdd( channelAdd ); }
-#define EU868_CHANNEL_REMOVE( ) else if(region == LORAMAC_REGION_EU868) { return RegionEU868ChannelsRemove( channelRemove ); }
-#define EU868_CHANNEL_MANUAL_ADD( ) else if(region == LORAMAC_REGION_EU868) { return RegionEU868ChannelManualAdd( channelAdd ); }
-#define EU868_CHANNEL_MANUAL_REMOVE( ) else if(region == LORAMAC_REGION_EU868) { return RegionEU868ChannelsRemove( channelRemove ); }
-#define EU868_SET_CONTINUOUS_WAVE( ) else if(region == LORAMAC_REGION_EU868) { RegionEU868SetContinuousWave( continuousWave );}
-#define EU868_APPLY_DR_OFFSET( ) else if(region == LORAMAC_REGION_EU868) { return RegionEU868ApplyDrOffset( downlinkDwellTime, dr, drOffset ); }
-#define EU868_GET_CHANNELS( ) else if(region == LORAMAC_REGION_EU868) { return RegionEU868GetChannels( channels, size ); }
-#define EU868_GET_CHANNEL_MASK( ) else if(region == LORAMAC_REGION_EU868) { return RegionEU868GetChannelMask( channelmask, size ); }
-#define EU868_FORCE_JOIN_DATARATE( ) else if(region == LORAMAC_REGION_EU868) { return RegionEU868ForceJoinDataRate( joinDr, alternateDr ); }
+#define EU868_CASE case LORAMAC_REGION_EU868:
+#define EU868_IS_ACTIVE( ) EU868_CASE { return true; }
+#define EU868_GET_PHY_PARAM( ) EU868_CASE { return RegionEU868GetPhyParam( getPhy ); }
+#define EU868_SET_BAND_TX_DONE( ) EU868_CASE { RegionEU868SetBandTxDone( txDone ); break; }
+#define EU868_INIT_DEFAULTS( ) EU868_CASE { RegionEU868InitDefaults( params ); break; }
+#define EU868_GET_NVM_CTX( ) EU868_CASE { return RegionEU868GetNvmCtx( params ); }
+#define EU868_VERIFY( ) EU868_CASE { return RegionEU868Verify( verify, phyAttribute ); }
+#define EU868_APPLY_CF_LIST( ) EU868_CASE { RegionEU868ApplyCFList( applyCFList ); break; }
+#define EU868_CHAN_MASK_SET( ) EU868_CASE { return RegionEU868ChanMaskSet( chanMaskSet ); }
+#define EU868_COMPUTE_RX_WINDOW_PARAMETERS( ) EU868_CASE { RegionEU868ComputeRxWindowParameters( datarate, minRxSymbols, rxError, rxConfigParams ); break; }
+#define EU868_RX_CONFIG( ) EU868_CASE { return RegionEU868RxConfig( rxConfig, datarate ); }
+#define EU868_TX_CONFIG( ) EU868_CASE { return RegionEU868TxConfig( txConfig, txPower, txTimeOnAir ); }
+#define EU868_LINK_ADR_REQ( ) EU868_CASE { return RegionEU868LinkAdrReq( linkAdrReq, drOut, txPowOut, nbRepOut, nbBytesParsed ); }
+#define EU868_RX_PARAM_SETUP_REQ( ) EU868_CASE { return RegionEU868RxParamSetupReq( rxParamSetupReq ); }
+#define EU868_NEW_CHANNEL_REQ( ) EU868_CASE { return RegionEU868NewChannelReq( newChannelReq ); }
+#define EU868_TX_PARAM_SETUP_REQ( ) EU868_CASE { return RegionEU868TxParamSetupReq( txParamSetupReq ); }
+#define EU868_DL_CHANNEL_REQ( ) EU868_CASE { return RegionEU868DlChannelReq( dlChannelReq ); }
+#define EU868_ALTERNATE_DR( ) EU868_CASE { return RegionEU868AlternateDr( currentDr, type ); }
+#define EU868_CALC_BACKOFF( ) EU868_CASE { RegionEU868CalcBackOff( calcBackOff ); break; }
+#define EU868_NEXT_CHANNEL( ) EU868_CASE { return RegionEU868NextChannel( nextChanParams, channel, time, aggregatedTimeOff ); }
+#define EU868_CHANNEL_ADD( ) EU868_CASE { return RegionEU868ChannelAdd( channelAdd ); }
+#define EU868_CHANNEL_REMOVE( ) EU868_CASE { return RegionEU868ChannelsRemove( channelRemove ); }
+#define EU868_SET_CONTINUOUS_WAVE( ) EU868_CASE { RegionEU868SetContinuousWave( continuousWave ); break; }
+#define EU868_APPLY_DR_OFFSET( ) EU868_CASE { return RegionEU868ApplyDrOffset( downlinkDwellTime, dr, drOffset ); }
+#define EU868_RX_BEACON_SETUP( ) EU868_CASE { RegionEU868RxBeaconSetup( rxBeaconSetup, outDr ); break; }
+#define EU868_CHANNEL_MANUAL_ADD( ) EU868_CASE { return RegionEU868ChannelManualAdd( channelAdd ); }
+#define EU868_CHANNEL_MANUAL_REMOVE( ) EU868_CASE { return RegionEU868ChannelsRemove( channelRemove ); }
#else
#define EU868_IS_ACTIVE( )
#define EU868_GET_PHY_PARAM( )
#define EU868_SET_BAND_TX_DONE( )
#define EU868_INIT_DEFAULTS( )
+#define EU868_GET_NVM_CTX( )
#define EU868_VERIFY( )
#define EU868_APPLY_CF_LIST( )
#define EU868_CHAN_MASK_SET( )
-#define EU868_ADR_NEXT( )
#define EU868_COMPUTE_RX_WINDOW_PARAMETERS( )
#define EU868_RX_CONFIG( )
#define EU868_TX_CONFIG( )
@@ -372,49 +373,51 @@ Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jae
#define EU868_NEXT_CHANNEL( )
#define EU868_CHANNEL_ADD( )
#define EU868_CHANNEL_REMOVE( )
-#define EU868_CHANNEL_MANUAL_ADD( )
-#define EU868_CHANNEL_MANUAL_REMOVE( )
#define EU868_SET_CONTINUOUS_WAVE( )
#define EU868_APPLY_DR_OFFSET( )
-#define EU868_GET_CHANNELS( )
-#define EU868_GET_CHANNEL_MASK( )
-#define EU868_FORCE_JOIN_DATARATE( )
+#define EU868_RX_BEACON_SETUP( )
+#define EU868_CHANNEL_MANUAL_ADD( )
+#define EU868_CHANNEL_MANUAL_REMOVE( )
#endif
#ifdef REGION_KR920
#include "RegionKR920.h"
-#define KR920_IS_ACTIVE( ) else if(region == LORAMAC_REGION_KR920) { return true; }
-#define KR920_GET_PHY_PARAM( ) else if(region == LORAMAC_REGION_KR920) { return RegionKR920GetPhyParam( getPhy ); }
-#define KR920_SET_BAND_TX_DONE( ) else if(region == LORAMAC_REGION_KR920) { RegionKR920SetBandTxDone( txDone );}
-#define KR920_INIT_DEFAULTS( ) else if(region == LORAMAC_REGION_KR920) { RegionKR920InitDefaults( type );}
-#define KR920_VERIFY( ) else if(region == LORAMAC_REGION_KR920) { return RegionKR920Verify( verify, phyAttribute ); }
-#define KR920_APPLY_CF_LIST( ) else if(region == LORAMAC_REGION_KR920) { RegionKR920ApplyCFList( applyCFList );}
-#define KR920_CHAN_MASK_SET( ) else if(region == LORAMAC_REGION_KR920) { return RegionKR920ChanMaskSet( chanMaskSet ); }
-#define KR920_ADR_NEXT( ) else if(region == LORAMAC_REGION_KR920) { return RegionKR920AdrNext( adrNext, drOut, txPowOut, adrAckCounter ); }
-#define KR920_COMPUTE_RX_WINDOW_PARAMETERS( ) else if(region == LORAMAC_REGION_KR920) { RegionKR920ComputeRxWindowParameters( datarate, minRxSymbols, rxError, rxConfigParams );}
-#define KR920_RX_CONFIG( ) else if(region == LORAMAC_REGION_KR920) { return RegionKR920RxConfig( rxConfig, datarate ); }
-#define KR920_TX_CONFIG( ) else if(region == LORAMAC_REGION_KR920) { return RegionKR920TxConfig( txConfig, txPower, txTimeOnAir ); }
-#define KR920_LINK_ADR_REQ( ) else if(region == LORAMAC_REGION_KR920) { return RegionKR920LinkAdrReq( linkAdrReq, drOut, txPowOut, nbRepOut, nbBytesParsed ); }
-#define KR920_RX_PARAM_SETUP_REQ( ) else if(region == LORAMAC_REGION_KR920) { return RegionKR920RxParamSetupReq( rxParamSetupReq ); }
-#define KR920_NEW_CHANNEL_REQ( ) else if(region == LORAMAC_REGION_KR920) { return RegionKR920NewChannelReq( newChannelReq ); }
-#define KR920_TX_PARAM_SETUP_REQ( ) else if(region == LORAMAC_REGION_KR920) { return RegionKR920TxParamSetupReq( txParamSetupReq ); }
-#define KR920_DL_CHANNEL_REQ( ) else if(region == LORAMAC_REGION_KR920) { return RegionKR920DlChannelReq( dlChannelReq ); }
-#define KR920_ALTERNATE_DR( ) else if(region == LORAMAC_REGION_KR920) { return RegionKR920AlternateDr( alternateDr ); }
-#define KR920_CALC_BACKOFF( ) else if(region == LORAMAC_REGION_KR920) { RegionKR920CalcBackOff( calcBackOff );}
-#define KR920_NEXT_CHANNEL( ) else if(region == LORAMAC_REGION_KR920) { return RegionKR920NextChannel( nextChanParams, channel, time, aggregatedTimeOff ); }
-#define KR920_CHANNEL_ADD( ) else if(region == LORAMAC_REGION_KR920) { return RegionKR920ChannelAdd( channelAdd ); }
-#define KR920_CHANNEL_REMOVE( ) else if(region == LORAMAC_REGION_KR920) { return RegionKR920ChannelsRemove( channelRemove ); }
-#define KR920_SET_CONTINUOUS_WAVE( ) else if(region == LORAMAC_REGION_KR920) { RegionKR920SetContinuousWave( continuousWave );}
-#define KR920_APPLY_DR_OFFSET( ) else if(region == LORAMAC_REGION_KR920) { return RegionKR920ApplyDrOffset( downlinkDwellTime, dr, drOffset ); }
+#define KR920_CASE case LORAMAC_REGION_KR920:
+#define KR920_IS_ACTIVE( ) KR920_CASE { return true; }
+#define KR920_GET_PHY_PARAM( ) KR920_CASE { return RegionKR920GetPhyParam( getPhy ); }
+#define KR920_SET_BAND_TX_DONE( ) KR920_CASE { RegionKR920SetBandTxDone( txDone ); break; }
+#define KR920_INIT_DEFAULTS( ) KR920_CASE { RegionKR920InitDefaults( params ); break; }
+#define KR920_GET_NVM_CTX( ) KR920_CASE { return RegionKR920GetNvmCtx( params ); }
+#define KR920_VERIFY( ) KR920_CASE { return RegionKR920Verify( verify, phyAttribute ); }
+#define KR920_APPLY_CF_LIST( ) KR920_CASE { RegionKR920ApplyCFList( applyCFList ); break; }
+#define KR920_CHAN_MASK_SET( ) KR920_CASE { return RegionKR920ChanMaskSet( chanMaskSet ); }
+#define KR920_COMPUTE_RX_WINDOW_PARAMETERS( ) KR920_CASE { RegionKR920ComputeRxWindowParameters( datarate, minRxSymbols, rxError, rxConfigParams ); break; }
+#define KR920_RX_CONFIG( ) KR920_CASE { return RegionKR920RxConfig( rxConfig, datarate ); }
+#define KR920_TX_CONFIG( ) KR920_CASE { return RegionKR920TxConfig( txConfig, txPower, txTimeOnAir ); }
+#define KR920_LINK_ADR_REQ( ) KR920_CASE { return RegionKR920LinkAdrReq( linkAdrReq, drOut, txPowOut, nbRepOut, nbBytesParsed ); }
+#define KR920_RX_PARAM_SETUP_REQ( ) KR920_CASE { return RegionKR920RxParamSetupReq( rxParamSetupReq ); }
+#define KR920_NEW_CHANNEL_REQ( ) KR920_CASE { return RegionKR920NewChannelReq( newChannelReq ); }
+#define KR920_TX_PARAM_SETUP_REQ( ) KR920_CASE { return RegionKR920TxParamSetupReq( txParamSetupReq ); }
+#define KR920_DL_CHANNEL_REQ( ) KR920_CASE { return RegionKR920DlChannelReq( dlChannelReq ); }
+#define KR920_ALTERNATE_DR( ) KR920_CASE { return RegionKR920AlternateDr( currentDr, type ); }
+#define KR920_CALC_BACKOFF( ) KR920_CASE { RegionKR920CalcBackOff( calcBackOff ); break; }
+#define KR920_NEXT_CHANNEL( ) KR920_CASE { return RegionKR920NextChannel( nextChanParams, channel, time, aggregatedTimeOff ); }
+#define KR920_CHANNEL_ADD( ) KR920_CASE { return RegionKR920ChannelAdd( channelAdd ); }
+#define KR920_CHANNEL_REMOVE( ) KR920_CASE { return RegionKR920ChannelsRemove( channelRemove ); }
+#define KR920_SET_CONTINUOUS_WAVE( ) KR920_CASE { RegionKR920SetContinuousWave( continuousWave ); break; }
+#define KR920_APPLY_DR_OFFSET( ) KR920_CASE { return RegionKR920ApplyDrOffset( downlinkDwellTime, dr, drOffset ); }
+#define KR920_RX_BEACON_SETUP( ) KR920_CASE { RegionKR920RxBeaconSetup( rxBeaconSetup, outDr ); break; }
+#define KR920_CHANNEL_MANUAL_ADD( ) KR920_CASE { return RegionKR920ChannelManualAdd( channelAdd ); }
+#define KR920_CHANNEL_MANUAL_REMOVE( ) KR920_CASE { return RegionKR920ChannelsRemove( channelRemove ); }
#else
#define KR920_IS_ACTIVE( )
#define KR920_GET_PHY_PARAM( )
#define KR920_SET_BAND_TX_DONE( )
#define KR920_INIT_DEFAULTS( )
+#define KR920_GET_NVM_CTX( )
#define KR920_VERIFY( )
#define KR920_APPLY_CF_LIST( )
#define KR920_CHAN_MASK_SET( )
-#define KR920_ADR_NEXT( )
#define KR920_COMPUTE_RX_WINDOW_PARAMETERS( )
#define KR920_RX_CONFIG( )
#define KR920_TX_CONFIG( )
@@ -430,47 +433,49 @@ Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jae
#define KR920_CHANNEL_REMOVE( )
#define KR920_SET_CONTINUOUS_WAVE( )
#define KR920_APPLY_DR_OFFSET( )
+#define KR920_RX_BEACON_SETUP( )
+#define KR920_CHANNEL_MANUAL_ADD( )
+#define KR920_CHANNEL_MANUAL_REMOVE( )
#endif
#ifdef REGION_IN865
#include "RegionIN865.h"
-#define IN865_IS_ACTIVE( ) else if(region == LORAMAC_REGION_IN865) { return true; }
-#define IN865_GET_PHY_PARAM( ) else if(region == LORAMAC_REGION_IN865) { return RegionIN865GetPhyParam( getPhy ); }
-#define IN865_SET_BAND_TX_DONE( ) else if(region == LORAMAC_REGION_IN865) { RegionIN865SetBandTxDone( txDone );}
-#define IN865_INIT_DEFAULTS( ) else if(region == LORAMAC_REGION_IN865) { RegionIN865InitDefaults( type );}
-#define IN865_VERIFY( ) else if(region == LORAMAC_REGION_IN865) { return RegionIN865Verify( verify, phyAttribute ); }
-#define IN865_APPLY_CF_LIST( ) else if(region == LORAMAC_REGION_IN865) { RegionIN865ApplyCFList( applyCFList );}
-#define IN865_CHAN_MASK_SET( ) else if(region == LORAMAC_REGION_IN865) { return RegionIN865ChanMaskSet( chanMaskSet ); }
-#define IN865_ADR_NEXT( ) else if(region == LORAMAC_REGION_IN865) { return RegionIN865AdrNext( adrNext, drOut, txPowOut, adrAckCounter ); }
-#define IN865_COMPUTE_RX_WINDOW_PARAMETERS( ) else if(region == LORAMAC_REGION_IN865) { RegionIN865ComputeRxWindowParameters( datarate, minRxSymbols, rxError, rxConfigParams );}
-#define IN865_RX_CONFIG( ) else if(region == LORAMAC_REGION_IN865) { return RegionIN865RxConfig( rxConfig, datarate ); }
-#define IN865_TX_CONFIG( ) else if(region == LORAMAC_REGION_IN865) { return RegionIN865TxConfig( txConfig, txPower, txTimeOnAir ); }
-#define IN865_LINK_ADR_REQ( ) else if(region == LORAMAC_REGION_IN865) { return RegionIN865LinkAdrReq( linkAdrReq, drOut, txPowOut, nbRepOut, nbBytesParsed ); }
-#define IN865_RX_PARAM_SETUP_REQ( ) else if(region == LORAMAC_REGION_IN865) { return RegionIN865RxParamSetupReq( rxParamSetupReq ); }
-#define IN865_NEW_CHANNEL_REQ( ) else if(region == LORAMAC_REGION_IN865) { return RegionIN865NewChannelReq( newChannelReq ); }
-#define IN865_TX_PARAM_SETUP_REQ( ) else if(region == LORAMAC_REGION_IN865) { return RegionIN865TxParamSetupReq( txParamSetupReq ); }
-#define IN865_DL_CHANNEL_REQ( ) else if(region == LORAMAC_REGION_IN865) { return RegionIN865DlChannelReq( dlChannelReq ); }
-#define IN865_ALTERNATE_DR( ) else if(region == LORAMAC_REGION_IN865) { return RegionIN865AlternateDr( alternateDr ); }
-#define IN865_CALC_BACKOFF( ) else if(region == LORAMAC_REGION_IN865) { RegionIN865CalcBackOff( calcBackOff );}
-#define IN865_NEXT_CHANNEL( ) else if(region == LORAMAC_REGION_IN865) { return RegionIN865NextChannel( nextChanParams, channel, time, aggregatedTimeOff ); }
-#define IN865_CHANNEL_ADD( ) else if(region == LORAMAC_REGION_IN865) { return RegionIN865ChannelAdd( channelAdd ); }
-#define IN865_CHANNEL_REMOVE( ) else if(region == LORAMAC_REGION_IN865) { return RegionIN865ChannelsRemove( channelRemove ); }
-#define IN865_CHANNEL_MANUAL_ADD( ) else if(region == LORAMAC_REGION_IN865) { return RegionIN865ChannelManualAdd( channelAdd ); }
-#define IN865_CHANNEL_MANUAL_REMOVE( ) else if(region == LORAMAC_REGION_IN865) { return RegionIN865ChannelsRemove( channelRemove ); }
-#define IN865_SET_CONTINUOUS_WAVE( ) else if(region == LORAMAC_REGION_IN865) { RegionIN865SetContinuousWave( continuousWave );}
-#define IN865_APPLY_DR_OFFSET( ) else if(region == LORAMAC_REGION_IN865) { return RegionIN865ApplyDrOffset( downlinkDwellTime, dr, drOffset ); }
-#define IN865_GET_CHANNELS( ) else if(region == LORAMAC_REGION_IN865) { return RegionIN865GetChannels( channels, size ); }
-#define IN865_GET_CHANNEL_MASK( ) else if(region == LORAMAC_REGION_IN865) { return RegionIN865GetChannelMask( channelmask, size ); }
-#define IN865_FORCE_JOIN_DATARATE( ) else if(region == LORAMAC_REGION_IN865) { return RegionIN865ForceJoinDataRate( joinDr, alternateDr ); }
+#define IN865_CASE case LORAMAC_REGION_IN865:
+#define IN865_IS_ACTIVE( ) IN865_CASE { return true; }
+#define IN865_GET_PHY_PARAM( ) IN865_CASE { return RegionIN865GetPhyParam( getPhy ); }
+#define IN865_SET_BAND_TX_DONE( ) IN865_CASE { RegionIN865SetBandTxDone( txDone ); break; }
+#define IN865_INIT_DEFAULTS( ) IN865_CASE { RegionIN865InitDefaults( params ); break; }
+#define IN865_GET_NVM_CTX( ) IN865_CASE { return RegionIN865GetNvmCtx( params ); }
+#define IN865_VERIFY( ) IN865_CASE { return RegionIN865Verify( verify, phyAttribute ); }
+#define IN865_APPLY_CF_LIST( ) IN865_CASE { RegionIN865ApplyCFList( applyCFList ); break; }
+#define IN865_CHAN_MASK_SET( ) IN865_CASE { return RegionIN865ChanMaskSet( chanMaskSet ); }
+#define IN865_COMPUTE_RX_WINDOW_PARAMETERS( ) IN865_CASE { RegionIN865ComputeRxWindowParameters( datarate, minRxSymbols, rxError, rxConfigParams ); break; }
+#define IN865_RX_CONFIG( ) IN865_CASE { return RegionIN865RxConfig( rxConfig, datarate ); }
+#define IN865_TX_CONFIG( ) IN865_CASE { return RegionIN865TxConfig( txConfig, txPower, txTimeOnAir ); }
+#define IN865_LINK_ADR_REQ( ) IN865_CASE { return RegionIN865LinkAdrReq( linkAdrReq, drOut, txPowOut, nbRepOut, nbBytesParsed ); }
+#define IN865_RX_PARAM_SETUP_REQ( ) IN865_CASE { return RegionIN865RxParamSetupReq( rxParamSetupReq ); }
+#define IN865_NEW_CHANNEL_REQ( ) IN865_CASE { return RegionIN865NewChannelReq( newChannelReq ); }
+#define IN865_TX_PARAM_SETUP_REQ( ) IN865_CASE { return RegionIN865TxParamSetupReq( txParamSetupReq ); }
+#define IN865_DL_CHANNEL_REQ( ) IN865_CASE { return RegionIN865DlChannelReq( dlChannelReq ); }
+#define IN865_ALTERNATE_DR( ) IN865_CASE { return RegionIN865AlternateDr( currentDr, type ); }
+#define IN865_CALC_BACKOFF( ) IN865_CASE { RegionIN865CalcBackOff( calcBackOff ); break; }
+#define IN865_NEXT_CHANNEL( ) IN865_CASE { return RegionIN865NextChannel( nextChanParams, channel, time, aggregatedTimeOff ); }
+#define IN865_CHANNEL_ADD( ) IN865_CASE { return RegionIN865ChannelAdd( channelAdd ); }
+#define IN865_CHANNEL_REMOVE( ) IN865_CASE { return RegionIN865ChannelsRemove( channelRemove ); }
+#define IN865_SET_CONTINUOUS_WAVE( ) IN865_CASE { RegionIN865SetContinuousWave( continuousWave ); break; }
+#define IN865_APPLY_DR_OFFSET( ) IN865_CASE { return RegionIN865ApplyDrOffset( downlinkDwellTime, dr, drOffset ); }
+#define IN865_RX_BEACON_SETUP( ) IN865_CASE { RegionIN865RxBeaconSetup( rxBeaconSetup, outDr ); break; }
+#define IN865_CHANNEL_MANUAL_ADD( ) IN865_CASE { return RegionIN865ChannelManualAdd( channelAdd ); }
+#define IN865_CHANNEL_MANUAL_REMOVE( ) IN865_CASE { return RegionIN865ChannelsRemove( channelRemove ); }
#else
#define IN865_IS_ACTIVE( )
#define IN865_GET_PHY_PARAM( )
#define IN865_SET_BAND_TX_DONE( )
#define IN865_INIT_DEFAULTS( )
+#define IN865_GET_NVM_CTX( )
#define IN865_VERIFY( )
#define IN865_APPLY_CF_LIST( )
#define IN865_CHAN_MASK_SET( )
-#define IN865_ADR_NEXT( )
#define IN865_COMPUTE_RX_WINDOW_PARAMETERS( )
#define IN865_RX_CONFIG( )
#define IN865_TX_CONFIG( )
@@ -484,55 +489,51 @@ Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jae
#define IN865_NEXT_CHANNEL( )
#define IN865_CHANNEL_ADD( )
#define IN865_CHANNEL_REMOVE( )
-#define IN865_CHANNEL_MANUAL_ADD( )
-#define IN865_CHANNEL_MANUAL_REMOVE( )
#define IN865_SET_CONTINUOUS_WAVE( )
#define IN865_APPLY_DR_OFFSET( )
-#define IN865_GET_CHANNELS( )
-#define IN865_GET_CHANNEL_MASK( )
-#define IN865_FORCE_JOIN_DATARATE( )
+#define IN865_RX_BEACON_SETUP( )
+#define IN865_CHANNEL_MANUAL_ADD( )
+#define IN865_CHANNEL_MANUAL_REMOVE( )
#endif
#ifdef REGION_US915
#include "RegionUS915.h"
-#define US915_IS_ACTIVE( ) else if(region == LORAMAC_REGION_US915) { return true; }
-#define US915_GET_PHY_PARAM( ) else if(region == LORAMAC_REGION_US915) { return RegionUS915GetPhyParam( getPhy ); }
-#define US915_SET_BAND_TX_DONE( ) else if(region == LORAMAC_REGION_US915) { RegionUS915SetBandTxDone( txDone );}
-#define US915_INIT_DEFAULTS( ) else if(region == LORAMAC_REGION_US915) { RegionUS915InitDefaults( type );}
-#define US915_VERIFY( ) else if(region == LORAMAC_REGION_US915) { return RegionUS915Verify( verify, phyAttribute ); }
-#define US915_APPLY_CF_LIST( ) else if(region == LORAMAC_REGION_US915) { RegionUS915ApplyCFList( applyCFList );}
-#define US915_CHAN_MASK_SET( ) else if(region == LORAMAC_REGION_US915) { return RegionUS915ChanMaskSet( chanMaskSet ); }
-#define US915_ADR_NEXT( ) else if(region == LORAMAC_REGION_US915) { return RegionUS915AdrNext( adrNext, drOut, txPowOut, adrAckCounter ); }
-#define US915_COMPUTE_RX_WINDOW_PARAMETERS( ) else if(region == LORAMAC_REGION_US915) { RegionUS915ComputeRxWindowParameters( datarate, minRxSymbols, rxError, rxConfigParams );}
-#define US915_RX_CONFIG( ) else if(region == LORAMAC_REGION_US915) { return RegionUS915RxConfig( rxConfig, datarate ); }
-#define US915_TX_CONFIG( ) else if(region == LORAMAC_REGION_US915) { return RegionUS915TxConfig( txConfig, txPower, txTimeOnAir ); }
-#define US915_LINK_ADR_REQ( ) else if(region == LORAMAC_REGION_US915) { return RegionUS915LinkAdrReq( linkAdrReq, drOut, txPowOut, nbRepOut, nbBytesParsed ); }
-#define US915_RX_PARAM_SETUP_REQ( ) else if(region == LORAMAC_REGION_US915) { return RegionUS915RxParamSetupReq( rxParamSetupReq ); }
-#define US915_NEW_CHANNEL_REQ( ) else if(region == LORAMAC_REGION_US915) { return RegionUS915NewChannelReq( newChannelReq ); }
-#define US915_TX_PARAM_SETUP_REQ( ) else if(region == LORAMAC_REGION_US915) { return RegionUS915TxParamSetupReq( txParamSetupReq ); }
-#define US915_DL_CHANNEL_REQ( ) else if(region == LORAMAC_REGION_US915) { return RegionUS915DlChannelReq( dlChannelReq ); }
-#define US915_ALTERNATE_DR( ) else if(region == LORAMAC_REGION_US915) { return RegionUS915AlternateDr( alternateDr ); }
-#define US915_CALC_BACKOFF( ) else if(region == LORAMAC_REGION_US915) { RegionUS915CalcBackOff( calcBackOff );}
-#define US915_NEXT_CHANNEL( ) else if(region == LORAMAC_REGION_US915) { return RegionUS915NextChannel( nextChanParams, channel, time, aggregatedTimeOff ); }
-#define US915_CHANNEL_ADD( ) else if(region == LORAMAC_REGION_US915) { return RegionUS915ChannelAdd( channelAdd ); }
-#define US915_CHANNEL_REMOVE( ) else if(region == LORAMAC_REGION_US915) { return RegionUS915ChannelsRemove( channelRemove ); }
-#define US915_CHANNEL_MANUAL_ADD( ) else if(region == LORAMAC_REGION_US915) { return RegionUS915ChannelManualAdd( channelAdd ); }
-#define US915_CHANNEL_MANUAL_REMOVE( ) else if(region == LORAMAC_REGION_US915) { return RegionUS915ChannelsManualRemove( channelRemove ); }
-#define US915_SET_CONTINUOUS_WAVE( ) else if(region == LORAMAC_REGION_US915) { RegionUS915SetContinuousWave( continuousWave );}
-#define US915_APPLY_DR_OFFSET( ) else if(region == LORAMAC_REGION_US915) { return RegionUS915ApplyDrOffset( downlinkDwellTime, dr, drOffset ); }
-#define US915_GET_CHANNELS( ) else if(region == LORAMAC_REGION_US915) { return RegionUS915GetChannels( channels, size ); }
-#define US915_GET_CHANNEL_MASK( ) else if(region == LORAMAC_REGION_US915) { return RegionUS915GetChannelMask( channelmask, size ); }
-#define US915_GET_CHANNEL_MASK_REMAINING( ) else if(region == LORAMAC_REGION_US915) { return RegionUS915GetChannelMaskRemaining( channelmask, size ); }
-#define US915_FORCE_JOIN_DATARATE( ) else if(region == LORAMAC_REGION_US915) { return RegionUS915ForceJoinDataRate( joinDr, alternateDr ); }
+#define US915_CASE case LORAMAC_REGION_US915:
+#define US915_IS_ACTIVE( ) US915_CASE { return true; }
+#define US915_GET_PHY_PARAM( ) US915_CASE { return RegionUS915GetPhyParam( getPhy ); }
+#define US915_SET_BAND_TX_DONE( ) US915_CASE { RegionUS915SetBandTxDone( txDone ); break; }
+#define US915_INIT_DEFAULTS( ) US915_CASE { RegionUS915InitDefaults( params ); break; }
+#define US915_GET_NVM_CTX( ) US915_CASE { return RegionUS915GetNvmCtx( params ); }
+#define US915_VERIFY( ) US915_CASE { return RegionUS915Verify( verify, phyAttribute ); }
+#define US915_APPLY_CF_LIST( ) US915_CASE { RegionUS915ApplyCFList( applyCFList ); break; }
+#define US915_CHAN_MASK_SET( ) US915_CASE { return RegionUS915ChanMaskSet( chanMaskSet ); }
+#define US915_COMPUTE_RX_WINDOW_PARAMETERS( ) US915_CASE { RegionUS915ComputeRxWindowParameters( datarate, minRxSymbols, rxError, rxConfigParams ); break; }
+#define US915_RX_CONFIG( ) US915_CASE { return RegionUS915RxConfig( rxConfig, datarate ); }
+#define US915_TX_CONFIG( ) US915_CASE { return RegionUS915TxConfig( txConfig, txPower, txTimeOnAir ); }
+#define US915_LINK_ADR_REQ( ) US915_CASE { return RegionUS915LinkAdrReq( linkAdrReq, drOut, txPowOut, nbRepOut, nbBytesParsed ); }
+#define US915_RX_PARAM_SETUP_REQ( ) US915_CASE { return RegionUS915RxParamSetupReq( rxParamSetupReq ); }
+#define US915_NEW_CHANNEL_REQ( ) US915_CASE { return RegionUS915NewChannelReq( newChannelReq ); }
+#define US915_TX_PARAM_SETUP_REQ( ) US915_CASE { return RegionUS915TxParamSetupReq( txParamSetupReq ); }
+#define US915_DL_CHANNEL_REQ( ) US915_CASE { return RegionUS915DlChannelReq( dlChannelReq ); }
+#define US915_ALTERNATE_DR( ) US915_CASE { return RegionUS915AlternateDr( currentDr, type ); }
+#define US915_CALC_BACKOFF( ) US915_CASE { RegionUS915CalcBackOff( calcBackOff ); break; }
+#define US915_NEXT_CHANNEL( ) US915_CASE { return RegionUS915NextChannel( nextChanParams, channel, time, aggregatedTimeOff ); }
+#define US915_CHANNEL_ADD( ) US915_CASE { return RegionUS915ChannelAdd( channelAdd ); }
+#define US915_CHANNEL_REMOVE( ) US915_CASE { return RegionUS915ChannelsRemove( channelRemove ); }
+#define US915_SET_CONTINUOUS_WAVE( ) US915_CASE { RegionUS915SetContinuousWave( continuousWave ); break; }
+#define US915_APPLY_DR_OFFSET( ) US915_CASE { return RegionUS915ApplyDrOffset( downlinkDwellTime, dr, drOffset ); }
+#define US915_RX_BEACON_SETUP( ) US915_CASE { RegionUS915RxBeaconSetup( rxBeaconSetup, outDr ); break; }
+#define US915_CHANNEL_MANUAL_ADD( ) US915_CASE { return RegionUS915ChannelManualAdd( channelAdd ); }
+#define US915_CHANNEL_MANUAL_REMOVE( ) US915_CASE { return RegionUS915ChannelsManualRemove( channelRemove ); }
#else
#define US915_IS_ACTIVE( )
#define US915_GET_PHY_PARAM( )
#define US915_SET_BAND_TX_DONE( )
#define US915_INIT_DEFAULTS( )
+#define US915_GET_NVM_CTX( )
#define US915_VERIFY( )
#define US915_APPLY_CF_LIST( )
#define US915_CHAN_MASK_SET( )
-#define US915_ADR_NEXT( )
#define US915_COMPUTE_RX_WINDOW_PARAMETERS( )
#define US915_RX_CONFIG( )
#define US915_TX_CONFIG( )
@@ -546,645 +547,636 @@ Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jae
#define US915_NEXT_CHANNEL( )
#define US915_CHANNEL_ADD( )
#define US915_CHANNEL_REMOVE( )
-#define US915_CHANNEL_MANUAL_ADD( )
-#define US915_CHANNEL_MANUAL_REMOVE( )
#define US915_SET_CONTINUOUS_WAVE( )
#define US915_APPLY_DR_OFFSET( )
-#define US915_GET_CHANNELS( )
-#define US915_GET_CHANNEL_MASK( )
-#define US915_GET_CHANNEL_MASK_REMAINING( )
-#define US915_FORCE_JOIN_DATARATE( )
+#define US915_RX_BEACON_SETUP( )
+#define US915_CHANNEL_MANUAL_ADD( )
+#define US915_CHANNEL_MANUAL_REMOVE( )
#endif
-#ifdef REGION_US915_HYBRID
-#include "RegionUS915-Hybrid.h"
-#define US915_HYBRID_IS_ACTIVE( ) else if(region == LORAMAC_REGION_US915_HYBRID) { return true; }
-#define US915_HYBRID_GET_PHY_PARAM( ) else if(region == LORAMAC_REGION_US915_HYBRID) { return RegionUS915HybridGetPhyParam( getPhy ); }
-#define US915_HYBRID_SET_BAND_TX_DONE( ) else if(region == LORAMAC_REGION_US915_HYBRID) { RegionUS915HybridSetBandTxDone( txDone );}
-#define US915_HYBRID_INIT_DEFAULTS( ) else if(region == LORAMAC_REGION_US915_HYBRID) { RegionUS915HybridInitDefaults( type );}
-#define US915_HYBRID_VERIFY( ) else if(region == LORAMAC_REGION_US915_HYBRID) { return RegionUS915HybridVerify( verify, phyAttribute ); }
-#define US915_HYBRID_APPLY_CF_LIST( ) else if(region == LORAMAC_REGION_US915_HYBRID) { RegionUS915HybridApplyCFList( applyCFList );}
-#define US915_HYBRID_CHAN_MASK_SET( ) else if(region == LORAMAC_REGION_US915_HYBRID) { return RegionUS915HybridChanMaskSet( chanMaskSet ); }
-#define US915_HYBRID_ADR_NEXT( ) else if(region == LORAMAC_REGION_US915_HYBRID) { return RegionUS915HybridAdrNext( adrNext, drOut, txPowOut, adrAckCounter ); }
-#define US915_HYBRID_COMPUTE_RX_WINDOW_PARAMETERS( ) else if(region == LORAMAC_REGION_US915_HYBRID) { RegionUS915HybridComputeRxWindowParameters( datarate, minRxSymbols, rxError, rxConfigParams );}
-#define US915_HYBRID_RX_CONFIG( ) else if(region == LORAMAC_REGION_US915_HYBRID) { return RegionUS915HybridRxConfig( rxConfig, datarate ); }
-#define US915_HYBRID_TX_CONFIG( ) else if(region == LORAMAC_REGION_US915_HYBRID) { return RegionUS915HybridTxConfig( txConfig, txPower, txTimeOnAir ); }
-#define US915_HYBRID_LINK_ADR_REQ( ) else if(region == LORAMAC_REGION_US915_HYBRID) { return RegionUS915HybridLinkAdrReq( linkAdrReq, drOut, txPowOut, nbRepOut, nbBytesParsed ); }
-#define US915_HYBRID_RX_PARAM_SETUP_REQ( ) else if(region == LORAMAC_REGION_US915_HYBRID) { return RegionUS915HybridRxParamSetupReq( rxParamSetupReq ); }
-#define US915_HYBRID_NEW_CHANNEL_REQ( ) else if(region == LORAMAC_REGION_US915_HYBRID) { return RegionUS915HybridNewChannelReq( newChannelReq ); }
-#define US915_HYBRID_TX_PARAM_SETUP_REQ( ) else if(region == LORAMAC_REGION_US915_HYBRID) { return RegionUS915HybridTxParamSetupReq( txParamSetupReq ); }
-#define US915_HYBRID_DL_CHANNEL_REQ( ) else if(region == LORAMAC_REGION_US915_HYBRID) { return RegionUS915HybridDlChannelReq( dlChannelReq ); }
-#define US915_HYBRID_ALTERNATE_DR( ) else if(region == LORAMAC_REGION_US915_HYBRID) { return RegionUS915HybridAlternateDr( alternateDr ); }
-#define US915_HYBRID_CALC_BACKOFF( ) else if(region == LORAMAC_REGION_US915_HYBRID) { RegionUS915HybridCalcBackOff( calcBackOff );}
-#define US915_HYBRID_NEXT_CHANNEL( ) else if(region == LORAMAC_REGION_US915_HYBRID) { return RegionUS915HybridNextChannel( nextChanParams, channel, time, aggregatedTimeOff ); }
-#define US915_HYBRID_CHANNEL_ADD( ) else if(region == LORAMAC_REGION_US915_HYBRID) { return RegionUS915HybridChannelAdd( channelAdd ); }
-#define US915_HYBRID_CHANNEL_REMOVE( ) else if(region == LORAMAC_REGION_US915_HYBRID) { return RegionUS915HybridChannelsRemove( channelRemove ); }
-#define US915_HYBRID_CHANNEL_MANUAL_ADD( ) else if(region == LORAMAC_REGION_US915_HYBRID) { return RegionUS915HybridChannelManualAdd( channelAdd ); }
-#define US915_HYBRID_CHANNEL_MANUAL_REMOVE( ) else if(region == LORAMAC_REGION_US915_HYBRID) { return RegionUS915HybridChannelsManualRemove( channelRemove ); }
-#define US915_HYBRID_SET_CONTINUOUS_WAVE( ) else if(region == LORAMAC_REGION_US915_HYBRID) { RegionUS915HybridSetContinuousWave( continuousWave );}
-#define US915_HYBRID_APPLY_DR_OFFSET( ) else if(region == LORAMAC_REGION_US915_HYBRID) { return RegionUS915HybridApplyDrOffset( downlinkDwellTime, dr, drOffset ); }
-#define US915_HYBRID_GET_CHANNELS( ) else if(region == LORAMAC_REGION_US915_HYBRID) { return RegionUS915HybridGetChannels( channels, size ); }
-#define US915_HYBRID_GET_CHANNEL_MASK( ) else if(region == LORAMAC_REGION_US915_HYBRID) { return RegionUS915HybridGetChannelMask( channelmask, size ); }
-#define US915_HYBRID_GET_CHANNEL_MASK_REMAINING( ) else if(region == LORAMAC_REGION_US915_HYBRID) { return RegionUS915HybridGetChannelMaskRemaining( channelmask, size ); }
-#define US915_HYBRID_FORCE_JOIN_DATARATE( ) else if(region == LORAMAC_REGION_US915_HYBRID) { return RegionUS915HybridForceJoinDataRate( joinDr, alternateDr ); }
+#ifdef REGION_RU864
+#include "RegionRU864.h"
+#define RU864_CASE case LORAMAC_REGION_RU864:
+#define RU864_IS_ACTIVE( ) RU864_CASE { return true; }
+#define RU864_GET_PHY_PARAM( ) RU864_CASE { return RegionRU864GetPhyParam( getPhy ); }
+#define RU864_SET_BAND_TX_DONE( ) RU864_CASE { RegionRU864SetBandTxDone( txDone ); break; }
+#define RU864_INIT_DEFAULTS( ) RU864_CASE { RegionRU864InitDefaults( params ); break; }
+#define RU864_GET_NVM_CTX( ) RU864_CASE { return RegionRU864GetNvmCtx( params ); }
+#define RU864_VERIFY( ) RU864_CASE { return RegionRU864Verify( verify, phyAttribute ); }
+#define RU864_APPLY_CF_LIST( ) RU864_CASE { RegionRU864ApplyCFList( applyCFList ); break; }
+#define RU864_CHAN_MASK_SET( ) RU864_CASE { return RegionRU864ChanMaskSet( chanMaskSet ); }
+#define RU864_COMPUTE_RX_WINDOW_PARAMETERS( ) RU864_CASE { RegionRU864ComputeRxWindowParameters( datarate, minRxSymbols, rxError, rxConfigParams ); break; }
+#define RU864_RX_CONFIG( ) RU864_CASE { return RegionRU864RxConfig( rxConfig, datarate ); }
+#define RU864_TX_CONFIG( ) RU864_CASE { return RegionRU864TxConfig( txConfig, txPower, txTimeOnAir ); }
+#define RU864_LINK_ADR_REQ( ) RU864_CASE { return RegionRU864LinkAdrReq( linkAdrReq, drOut, txPowOut, nbRepOut, nbBytesParsed ); }
+#define RU864_RX_PARAM_SETUP_REQ( ) RU864_CASE { return RegionRU864RxParamSetupReq( rxParamSetupReq ); }
+#define RU864_NEW_CHANNEL_REQ( ) RU864_CASE { return RegionRU864NewChannelReq( newChannelReq ); }
+#define RU864_TX_PARAM_SETUP_REQ( ) RU864_CASE { return RegionRU864TxParamSetupReq( txParamSetupReq ); }
+#define RU864_DL_CHANNEL_REQ( ) RU864_CASE { return RegionRU864DlChannelReq( dlChannelReq ); }
+#define RU864_ALTERNATE_DR( ) RU864_CASE { return RegionRU864AlternateDr( currentDr, type ); }
+#define RU864_CALC_BACKOFF( ) RU864_CASE { RegionRU864CalcBackOff( calcBackOff ); break; }
+#define RU864_NEXT_CHANNEL( ) RU864_CASE { return RegionRU864NextChannel( nextChanParams, channel, time, aggregatedTimeOff ); }
+#define RU864_CHANNEL_ADD( ) RU864_CASE { return RegionRU864ChannelAdd( channelAdd ); }
+#define RU864_CHANNEL_REMOVE( ) RU864_CASE { return RegionRU864ChannelsRemove( channelRemove ); }
+#define RU864_SET_CONTINUOUS_WAVE( ) RU864_CASE { RegionRU864SetContinuousWave( continuousWave ); break; }
+#define RU864_APPLY_DR_OFFSET( ) RU864_CASE { return RegionRU864ApplyDrOffset( downlinkDwellTime, dr, drOffset ); }
+#define RU864_RX_BEACON_SETUP( ) RU864_CASE { RegionRU864RxBeaconSetup( rxBeaconSetup, outDr ); break; }
+#define RU864_CHANNEL_MANUAL_ADD( ) RU864_CASE { return RegionRU864ChannelManualAdd( channelAdd ); }
+#define RU864_CHANNEL_MANUAL_REMOVE( ) RU864_CASE { return RegionRU864ChannelsRemove( channelRemove ); }
#else
-#define US915_HYBRID_IS_ACTIVE( )
-#define US915_HYBRID_GET_PHY_PARAM( )
-#define US915_HYBRID_SET_BAND_TX_DONE( )
-#define US915_HYBRID_INIT_DEFAULTS( )
-#define US915_HYBRID_VERIFY( )
-#define US915_HYBRID_APPLY_CF_LIST( )
-#define US915_HYBRID_CHAN_MASK_SET( )
-#define US915_HYBRID_ADR_NEXT( )
-#define US915_HYBRID_COMPUTE_RX_WINDOW_PARAMETERS( )
-#define US915_HYBRID_RX_CONFIG( )
-#define US915_HYBRID_TX_CONFIG( )
-#define US915_HYBRID_LINK_ADR_REQ( )
-#define US915_HYBRID_RX_PARAM_SETUP_REQ( )
-#define US915_HYBRID_NEW_CHANNEL_REQ( )
-#define US915_HYBRID_TX_PARAM_SETUP_REQ( )
-#define US915_HYBRID_DL_CHANNEL_REQ( )
-#define US915_HYBRID_ALTERNATE_DR( )
-#define US915_HYBRID_CALC_BACKOFF( )
-#define US915_HYBRID_NEXT_CHANNEL( )
-#define US915_HYBRID_CHANNEL_ADD( )
-#define US915_HYBRID_CHANNEL_REMOVE( )
-#define US915_HYBRID_CHANNEL_MANUAL_ADD( )
-#define US915_HYBRID_CHANNEL_MANUAL_REMOVE( )
-#define US915_HYBRID_SET_CONTINUOUS_WAVE( )
-#define US915_HYBRID_APPLY_DR_OFFSET( )
-#define US915_HYBRID_GET_CHANNELS( )
-#define US915_HYBRID_GET_CHANNEL_MASK( )
-#define US915_HYBRID_GET_CHANNEL_MASK_REMAINING( )
-#define US915_HYBRID_FORCE_JOIN_DATARATE( )
+#define RU864_IS_ACTIVE( )
+#define RU864_GET_PHY_PARAM( )
+#define RU864_SET_BAND_TX_DONE( )
+#define RU864_INIT_DEFAULTS( )
+#define RU864_GET_NVM_CTX( )
+#define RU864_VERIFY( )
+#define RU864_APPLY_CF_LIST( )
+#define RU864_CHAN_MASK_SET( )
+#define RU864_COMPUTE_RX_WINDOW_PARAMETERS( )
+#define RU864_RX_CONFIG( )
+#define RU864_TX_CONFIG( )
+#define RU864_LINK_ADR_REQ( )
+#define RU864_RX_PARAM_SETUP_REQ( )
+#define RU864_NEW_CHANNEL_REQ( )
+#define RU864_TX_PARAM_SETUP_REQ( )
+#define RU864_DL_CHANNEL_REQ( )
+#define RU864_ALTERNATE_DR( )
+#define RU864_CALC_BACKOFF( )
+#define RU864_NEXT_CHANNEL( )
+#define RU864_CHANNEL_ADD( )
+#define RU864_CHANNEL_REMOVE( )
+#define RU864_SET_CONTINUOUS_WAVE( )
+#define RU864_APPLY_DR_OFFSET( )
+#define RU864_RX_BEACON_SETUP( )
+#define RU864_CHANNEL_MANUAL_ADD( )
+#define RU864_CHANNEL_MANUAL_REMOVE( )
#endif
bool RegionIsActive( LoRaMacRegion_t region )
{
- if(region >= LORAMAC_REGION_MAX) {
- return false;
- }
- AS923_IS_ACTIVE( )
- AU915_IS_ACTIVE( )
- CN470_IS_ACTIVE( )
- CN779_IS_ACTIVE( )
- EU433_IS_ACTIVE( )
- EU868_IS_ACTIVE( )
- KR920_IS_ACTIVE( )
- IN865_IS_ACTIVE( )
- US915_IS_ACTIVE( )
- US915_HYBRID_IS_ACTIVE( )
- else {
- return false;
+ switch( region )
+ {
+ AS923_IS_ACTIVE( );
+ AU915_IS_ACTIVE( );
+ CN470_IS_ACTIVE( );
+ CN779_IS_ACTIVE( );
+ EU433_IS_ACTIVE( );
+ EU868_IS_ACTIVE( );
+ KR920_IS_ACTIVE( );
+ IN865_IS_ACTIVE( );
+ US915_IS_ACTIVE( );
+ RU864_IS_ACTIVE( );
+ default:
+ {
+ return false;
+ }
}
}
-IRAM_ATTR PhyParam_t RegionGetPhyParam( LoRaMacRegion_t region, GetPhyParams_t* getPhy )
+PhyParam_t RegionGetPhyParam( LoRaMacRegion_t region, GetPhyParams_t* getPhy )
{
PhyParam_t phyParam = { 0 };
-
- if(region >= LORAMAC_REGION_MAX) {
- return phyParam;
- }
- AS923_GET_PHY_PARAM( )
- AU915_GET_PHY_PARAM( )
- CN470_GET_PHY_PARAM( )
- CN779_GET_PHY_PARAM( )
- EU433_GET_PHY_PARAM( )
- EU868_GET_PHY_PARAM( )
- KR920_GET_PHY_PARAM( )
- IN865_GET_PHY_PARAM( )
- US915_GET_PHY_PARAM( )
- US915_HYBRID_GET_PHY_PARAM( )
- else {
- return phyParam;
+ switch( region )
+ {
+ AS923_GET_PHY_PARAM( );
+ AU915_GET_PHY_PARAM( );
+ CN470_GET_PHY_PARAM( );
+ CN779_GET_PHY_PARAM( );
+ EU433_GET_PHY_PARAM( );
+ EU868_GET_PHY_PARAM( );
+ KR920_GET_PHY_PARAM( );
+ IN865_GET_PHY_PARAM( );
+ US915_GET_PHY_PARAM( );
+ RU864_GET_PHY_PARAM( );
+ default:
+ {
+ return phyParam;
+ }
}
}
-IRAM_ATTR void RegionSetBandTxDone( LoRaMacRegion_t region, SetBandTxDoneParams_t* txDone )
+void RegionSetBandTxDone( LoRaMacRegion_t region, SetBandTxDoneParams_t* txDone )
{
- if(region >= LORAMAC_REGION_MAX) {
- return;
+ switch( region )
+ {
+ AS923_SET_BAND_TX_DONE( );
+ AU915_SET_BAND_TX_DONE( );
+ CN470_SET_BAND_TX_DONE( );
+ CN779_SET_BAND_TX_DONE( );
+ EU433_SET_BAND_TX_DONE( );
+ EU868_SET_BAND_TX_DONE( );
+ KR920_SET_BAND_TX_DONE( );
+ IN865_SET_BAND_TX_DONE( );
+ US915_SET_BAND_TX_DONE( );
+ RU864_SET_BAND_TX_DONE( );
+ default:
+ {
+ return;
+ }
}
- AS923_SET_BAND_TX_DONE( )
- AU915_SET_BAND_TX_DONE( )
- CN470_SET_BAND_TX_DONE( )
- CN779_SET_BAND_TX_DONE( )
- EU433_SET_BAND_TX_DONE( )
- EU868_SET_BAND_TX_DONE( )
- KR920_SET_BAND_TX_DONE( )
- IN865_SET_BAND_TX_DONE( )
- US915_SET_BAND_TX_DONE( )
- US915_HYBRID_SET_BAND_TX_DONE( )
}
-void RegionInitDefaults( LoRaMacRegion_t region, InitType_t type )
+void RegionInitDefaults( LoRaMacRegion_t region, InitDefaultsParams_t* params )
{
-
- if(region >= LORAMAC_REGION_MAX) {
- return;
+ switch( region )
+ {
+ AS923_INIT_DEFAULTS( );
+ AU915_INIT_DEFAULTS( );
+ CN470_INIT_DEFAULTS( );
+ CN779_INIT_DEFAULTS( );
+ EU433_INIT_DEFAULTS( );
+ EU868_INIT_DEFAULTS( );
+ KR920_INIT_DEFAULTS( );
+ IN865_INIT_DEFAULTS( );
+ US915_INIT_DEFAULTS( );
+ RU864_INIT_DEFAULTS( );
+ default:
+ {
+ break;
+ }
}
- AS923_INIT_DEFAULTS( )
- AU915_INIT_DEFAULTS( )
- CN470_INIT_DEFAULTS( )
- CN779_INIT_DEFAULTS( )
- EU433_INIT_DEFAULTS( )
- EU868_INIT_DEFAULTS( )
- KR920_INIT_DEFAULTS( )
- IN865_INIT_DEFAULTS( )
- US915_INIT_DEFAULTS( )
- US915_HYBRID_INIT_DEFAULTS( )
}
-bool RegionVerify( LoRaMacRegion_t region, VerifyParams_t* verify, PhyAttribute_t phyAttribute )
+void* RegionGetNvmCtx( LoRaMacRegion_t region, GetNvmCtxParams_t* params )
{
-
- if(region >= LORAMAC_REGION_MAX) {
- return false;
- }
- AS923_VERIFY( )
- AU915_VERIFY( )
- CN470_VERIFY( )
- CN779_VERIFY( )
- EU433_VERIFY( )
- EU868_VERIFY( )
- KR920_VERIFY( )
- IN865_VERIFY( )
- US915_VERIFY( )
- US915_HYBRID_VERIFY( )
- else {
- return false;
+ switch( region )
+ {
+ AS923_GET_NVM_CTX( );
+ AU915_GET_NVM_CTX( );
+ CN470_GET_NVM_CTX( );
+ CN779_GET_NVM_CTX( );
+ EU433_GET_NVM_CTX( );
+ EU868_GET_NVM_CTX( );
+ KR920_GET_NVM_CTX( );
+ IN865_GET_NVM_CTX( );
+ US915_GET_NVM_CTX( );
+ RU864_GET_NVM_CTX( );
+ default:
+ {
+ return 0;
+ }
}
}
-void RegionApplyCFList( LoRaMacRegion_t region, ApplyCFListParams_t* applyCFList )
+bool RegionVerify( LoRaMacRegion_t region, VerifyParams_t* verify, PhyAttribute_t phyAttribute )
{
-
- if(region >= LORAMAC_REGION_MAX) {
- return;
+ switch( region )
+ {
+ AS923_VERIFY( );
+ AU915_VERIFY( );
+ CN470_VERIFY( );
+ CN779_VERIFY( );
+ EU433_VERIFY( );
+ EU868_VERIFY( );
+ KR920_VERIFY( );
+ IN865_VERIFY( );
+ US915_VERIFY( );
+ RU864_VERIFY( );
+ default:
+ {
+ return false;
+ }
}
- AS923_APPLY_CF_LIST( )
- AU915_APPLY_CF_LIST( )
- CN470_APPLY_CF_LIST( )
- CN779_APPLY_CF_LIST( )
- EU433_APPLY_CF_LIST( )
- EU868_APPLY_CF_LIST( )
- KR920_APPLY_CF_LIST( )
- IN865_APPLY_CF_LIST( )
- US915_APPLY_CF_LIST( )
- US915_HYBRID_APPLY_CF_LIST( )
}
-bool RegionChanMaskSet( LoRaMacRegion_t region, ChanMaskSetParams_t* chanMaskSet )
+void RegionApplyCFList( LoRaMacRegion_t region, ApplyCFListParams_t* applyCFList )
{
-
- if(region >= LORAMAC_REGION_MAX) {
- return false;
- }
- AS923_CHAN_MASK_SET( )
- AU915_CHAN_MASK_SET( )
- CN470_CHAN_MASK_SET( )
- CN779_CHAN_MASK_SET( )
- EU433_CHAN_MASK_SET( )
- EU868_CHAN_MASK_SET( )
- KR920_CHAN_MASK_SET( )
- IN865_CHAN_MASK_SET( )
- US915_CHAN_MASK_SET( )
- US915_HYBRID_CHAN_MASK_SET( )
- else {
- return false;
+ switch( region )
+ {
+ AS923_APPLY_CF_LIST( );
+ AU915_APPLY_CF_LIST( );
+ CN470_APPLY_CF_LIST( );
+ CN779_APPLY_CF_LIST( );
+ EU433_APPLY_CF_LIST( );
+ EU868_APPLY_CF_LIST( );
+ KR920_APPLY_CF_LIST( );
+ IN865_APPLY_CF_LIST( );
+ US915_APPLY_CF_LIST( );
+ RU864_APPLY_CF_LIST( );
+ default:
+ {
+ break;
+ }
}
}
-bool RegionAdrNext( LoRaMacRegion_t region, AdrNextParams_t* adrNext, int8_t* drOut, int8_t* txPowOut, uint32_t* adrAckCounter )
+bool RegionChanMaskSet( LoRaMacRegion_t region, ChanMaskSetParams_t* chanMaskSet )
{
-
- if(region >= LORAMAC_REGION_MAX) {
- return false;
- }
- AS923_ADR_NEXT( )
- AU915_ADR_NEXT( )
- CN470_ADR_NEXT( )
- CN779_ADR_NEXT( )
- EU433_ADR_NEXT( )
- EU868_ADR_NEXT( )
- KR920_ADR_NEXT( )
- IN865_ADR_NEXT( )
- US915_ADR_NEXT( )
- US915_HYBRID_ADR_NEXT( )
- else {
- return false;
+ switch( region )
+ {
+ AS923_CHAN_MASK_SET( );
+ AU915_CHAN_MASK_SET( );
+ CN470_CHAN_MASK_SET( );
+ CN779_CHAN_MASK_SET( );
+ EU433_CHAN_MASK_SET( );
+ EU868_CHAN_MASK_SET( );
+ KR920_CHAN_MASK_SET( );
+ IN865_CHAN_MASK_SET( );
+ US915_CHAN_MASK_SET( );
+ RU864_CHAN_MASK_SET( );
+ default:
+ {
+ return false;
+ }
}
}
void RegionComputeRxWindowParameters( LoRaMacRegion_t region, int8_t datarate, uint8_t minRxSymbols, uint32_t rxError, RxConfigParams_t *rxConfigParams )
{
-
- if(region >= LORAMAC_REGION_MAX) {
- return;
+ switch( region )
+ {
+ AS923_COMPUTE_RX_WINDOW_PARAMETERS( );
+ AU915_COMPUTE_RX_WINDOW_PARAMETERS( );
+ CN470_COMPUTE_RX_WINDOW_PARAMETERS( );
+ CN779_COMPUTE_RX_WINDOW_PARAMETERS( );
+ EU433_COMPUTE_RX_WINDOW_PARAMETERS( );
+ EU868_COMPUTE_RX_WINDOW_PARAMETERS( );
+ KR920_COMPUTE_RX_WINDOW_PARAMETERS( );
+ IN865_COMPUTE_RX_WINDOW_PARAMETERS( );
+ US915_COMPUTE_RX_WINDOW_PARAMETERS( );
+ RU864_COMPUTE_RX_WINDOW_PARAMETERS( );
+ default:
+ {
+ break;
+ }
}
- AS923_COMPUTE_RX_WINDOW_PARAMETERS( )
- AU915_COMPUTE_RX_WINDOW_PARAMETERS( )
- CN470_COMPUTE_RX_WINDOW_PARAMETERS( )
- CN779_COMPUTE_RX_WINDOW_PARAMETERS( )
- EU433_COMPUTE_RX_WINDOW_PARAMETERS( )
- EU868_COMPUTE_RX_WINDOW_PARAMETERS( )
- KR920_COMPUTE_RX_WINDOW_PARAMETERS( )
- IN865_COMPUTE_RX_WINDOW_PARAMETERS( )
- US915_COMPUTE_RX_WINDOW_PARAMETERS( )
- US915_HYBRID_COMPUTE_RX_WINDOW_PARAMETERS( )
}
bool RegionRxConfig( LoRaMacRegion_t region, RxConfigParams_t* rxConfig, int8_t* datarate )
{
-
- if(region >= LORAMAC_REGION_MAX) {
- return false;
- }
- AS923_RX_CONFIG( )
- AU915_RX_CONFIG( )
- CN470_RX_CONFIG( )
- CN779_RX_CONFIG( )
- EU433_RX_CONFIG( )
- EU868_RX_CONFIG( )
- KR920_RX_CONFIG( )
- IN865_RX_CONFIG( )
- US915_RX_CONFIG( )
- US915_HYBRID_RX_CONFIG( )
- else {
- return false;
+ switch( region )
+ {
+ AS923_RX_CONFIG( );
+ AU915_RX_CONFIG( );
+ CN470_RX_CONFIG( );
+ CN779_RX_CONFIG( );
+ EU433_RX_CONFIG( );
+ EU868_RX_CONFIG( );
+ KR920_RX_CONFIG( );
+ IN865_RX_CONFIG( );
+ US915_RX_CONFIG( );
+ RU864_RX_CONFIG( );
+ default:
+ {
+ return false;
+ }
}
}
bool RegionTxConfig( LoRaMacRegion_t region, TxConfigParams_t* txConfig, int8_t* txPower, TimerTime_t* txTimeOnAir )
{
-
- if(region >= LORAMAC_REGION_MAX) {
- return false;
- }
- AS923_TX_CONFIG( )
- AU915_TX_CONFIG( )
- CN470_TX_CONFIG( )
- CN779_TX_CONFIG( )
- EU433_TX_CONFIG( )
- EU868_TX_CONFIG( )
- KR920_TX_CONFIG( )
- IN865_TX_CONFIG( )
- US915_TX_CONFIG( )
- US915_HYBRID_TX_CONFIG( )
- else {
- return false;
+ switch( region )
+ {
+ AS923_TX_CONFIG( );
+ AU915_TX_CONFIG( );
+ CN470_TX_CONFIG( );
+ CN779_TX_CONFIG( );
+ EU433_TX_CONFIG( );
+ EU868_TX_CONFIG( );
+ KR920_TX_CONFIG( );
+ IN865_TX_CONFIG( );
+ US915_TX_CONFIG( );
+ RU864_TX_CONFIG( );
+ default:
+ {
+ return false;
+ }
}
}
uint8_t RegionLinkAdrReq( LoRaMacRegion_t region, LinkAdrReqParams_t* linkAdrReq, int8_t* drOut, int8_t* txPowOut, uint8_t* nbRepOut, uint8_t* nbBytesParsed )
{
-
- if(region >= LORAMAC_REGION_MAX) {
- return 0;
- }
- AS923_LINK_ADR_REQ( )
- AU915_LINK_ADR_REQ( )
- CN470_LINK_ADR_REQ( )
- CN779_LINK_ADR_REQ( )
- EU433_LINK_ADR_REQ( )
- EU868_LINK_ADR_REQ( )
- KR920_LINK_ADR_REQ( )
- IN865_LINK_ADR_REQ( )
- US915_LINK_ADR_REQ( )
- US915_HYBRID_LINK_ADR_REQ( )
- else {
- return 0;
+ switch( region )
+ {
+ AS923_LINK_ADR_REQ( );
+ AU915_LINK_ADR_REQ( );
+ CN470_LINK_ADR_REQ( );
+ CN779_LINK_ADR_REQ( );
+ EU433_LINK_ADR_REQ( );
+ EU868_LINK_ADR_REQ( );
+ KR920_LINK_ADR_REQ( );
+ IN865_LINK_ADR_REQ( );
+ US915_LINK_ADR_REQ( );
+ RU864_LINK_ADR_REQ( );
+ default:
+ {
+ return 0;
+ }
}
}
uint8_t RegionRxParamSetupReq( LoRaMacRegion_t region, RxParamSetupReqParams_t* rxParamSetupReq )
{
-
- if(region >= LORAMAC_REGION_MAX) {
- return 0;
- }
- AS923_RX_PARAM_SETUP_REQ( )
- AU915_RX_PARAM_SETUP_REQ( )
- CN470_RX_PARAM_SETUP_REQ( )
- CN779_RX_PARAM_SETUP_REQ( )
- EU433_RX_PARAM_SETUP_REQ( )
- EU868_RX_PARAM_SETUP_REQ( )
- KR920_RX_PARAM_SETUP_REQ( )
- IN865_RX_PARAM_SETUP_REQ( )
- US915_RX_PARAM_SETUP_REQ( )
- US915_HYBRID_RX_PARAM_SETUP_REQ( )
- else {
- return 0;
+ switch( region )
+ {
+ AS923_RX_PARAM_SETUP_REQ( );
+ AU915_RX_PARAM_SETUP_REQ( );
+ CN470_RX_PARAM_SETUP_REQ( );
+ CN779_RX_PARAM_SETUP_REQ( );
+ EU433_RX_PARAM_SETUP_REQ( );
+ EU868_RX_PARAM_SETUP_REQ( );
+ KR920_RX_PARAM_SETUP_REQ( );
+ IN865_RX_PARAM_SETUP_REQ( );
+ US915_RX_PARAM_SETUP_REQ( );
+ RU864_RX_PARAM_SETUP_REQ( );
+ default:
+ {
+ return 0;
+ }
}
}
uint8_t RegionNewChannelReq( LoRaMacRegion_t region, NewChannelReqParams_t* newChannelReq )
{
-
- if(region >= LORAMAC_REGION_MAX) {
- return 0;
- }
- AS923_NEW_CHANNEL_REQ( )
- AU915_NEW_CHANNEL_REQ( )
- CN470_NEW_CHANNEL_REQ( )
- CN779_NEW_CHANNEL_REQ( )
- EU433_NEW_CHANNEL_REQ( )
- EU868_NEW_CHANNEL_REQ( )
- KR920_NEW_CHANNEL_REQ( )
- IN865_NEW_CHANNEL_REQ( )
- US915_NEW_CHANNEL_REQ( )
- US915_HYBRID_NEW_CHANNEL_REQ( )
- else {
- return 0;
+ switch( region )
+ {
+ AS923_NEW_CHANNEL_REQ( );
+ AU915_NEW_CHANNEL_REQ( );
+ CN470_NEW_CHANNEL_REQ( );
+ CN779_NEW_CHANNEL_REQ( );
+ EU433_NEW_CHANNEL_REQ( );
+ EU868_NEW_CHANNEL_REQ( );
+ KR920_NEW_CHANNEL_REQ( );
+ IN865_NEW_CHANNEL_REQ( );
+ US915_NEW_CHANNEL_REQ( );
+ RU864_NEW_CHANNEL_REQ( );
+ default:
+ {
+ return 0;
+ }
}
}
int8_t RegionTxParamSetupReq( LoRaMacRegion_t region, TxParamSetupReqParams_t* txParamSetupReq )
{
-
- if(region >= LORAMAC_REGION_MAX) {
- return 0;
- }
- AS923_TX_PARAM_SETUP_REQ( )
- AU915_TX_PARAM_SETUP_REQ( )
- CN470_TX_PARAM_SETUP_REQ( )
- CN779_TX_PARAM_SETUP_REQ( )
- EU433_TX_PARAM_SETUP_REQ( )
- EU868_TX_PARAM_SETUP_REQ( )
- KR920_TX_PARAM_SETUP_REQ( )
- IN865_TX_PARAM_SETUP_REQ( )
- US915_TX_PARAM_SETUP_REQ( )
- US915_HYBRID_TX_PARAM_SETUP_REQ( )
- else {
- return 0;
+ switch( region )
+ {
+ AS923_TX_PARAM_SETUP_REQ( );
+ AU915_TX_PARAM_SETUP_REQ( );
+ CN470_TX_PARAM_SETUP_REQ( );
+ CN779_TX_PARAM_SETUP_REQ( );
+ EU433_TX_PARAM_SETUP_REQ( );
+ EU868_TX_PARAM_SETUP_REQ( );
+ KR920_TX_PARAM_SETUP_REQ( );
+ IN865_TX_PARAM_SETUP_REQ( );
+ US915_TX_PARAM_SETUP_REQ( );
+ RU864_TX_PARAM_SETUP_REQ( );
+ default:
+ {
+ return 0;
+ }
}
}
uint8_t RegionDlChannelReq( LoRaMacRegion_t region, DlChannelReqParams_t* dlChannelReq )
{
-
- if(region >= LORAMAC_REGION_MAX) {
- return 0;
- }
- AS923_DL_CHANNEL_REQ( )
- AU915_DL_CHANNEL_REQ( )
- CN470_DL_CHANNEL_REQ( )
- CN779_DL_CHANNEL_REQ( )
- EU433_DL_CHANNEL_REQ( )
- EU868_DL_CHANNEL_REQ( )
- KR920_DL_CHANNEL_REQ( )
- IN865_DL_CHANNEL_REQ( )
- US915_DL_CHANNEL_REQ( )
- US915_HYBRID_DL_CHANNEL_REQ( )
- else {
- return 0;
+ switch( region )
+ {
+ AS923_DL_CHANNEL_REQ( );
+ AU915_DL_CHANNEL_REQ( );
+ CN470_DL_CHANNEL_REQ( );
+ CN779_DL_CHANNEL_REQ( );
+ EU433_DL_CHANNEL_REQ( );
+ EU868_DL_CHANNEL_REQ( );
+ KR920_DL_CHANNEL_REQ( );
+ IN865_DL_CHANNEL_REQ( );
+ US915_DL_CHANNEL_REQ( );
+ RU864_DL_CHANNEL_REQ( );
+ default:
+ {
+ return 0;
+ }
}
}
-int8_t RegionAlternateDr( LoRaMacRegion_t region, AlternateDrParams_t* alternateDr )
+int8_t RegionAlternateDr( LoRaMacRegion_t region, int8_t currentDr, AlternateDrType_t type )
{
-
- if(region >= LORAMAC_REGION_MAX) {
- return 0;
- }
- AS923_ALTERNATE_DR( )
- AU915_ALTERNATE_DR( )
- CN470_ALTERNATE_DR( )
- CN779_ALTERNATE_DR( )
- EU433_ALTERNATE_DR( )
- EU868_ALTERNATE_DR( )
- KR920_ALTERNATE_DR( )
- IN865_ALTERNATE_DR( )
- US915_ALTERNATE_DR( )
- US915_HYBRID_ALTERNATE_DR( )
- else {
- return 0;
+ switch( region )
+ {
+ AS923_ALTERNATE_DR( );
+ AU915_ALTERNATE_DR( );
+ CN470_ALTERNATE_DR( );
+ CN779_ALTERNATE_DR( );
+ EU433_ALTERNATE_DR( );
+ EU868_ALTERNATE_DR( );
+ KR920_ALTERNATE_DR( );
+ IN865_ALTERNATE_DR( );
+ US915_ALTERNATE_DR( );
+ RU864_ALTERNATE_DR( );
+ default:
+ {
+ return 0;
+ }
}
}
void RegionCalcBackOff( LoRaMacRegion_t region, CalcBackOffParams_t* calcBackOff )
{
-
- if(region >= LORAMAC_REGION_MAX) {
- return;
+ switch( region )
+ {
+ AS923_CALC_BACKOFF( );
+ AU915_CALC_BACKOFF( );
+ CN470_CALC_BACKOFF( );
+ CN779_CALC_BACKOFF( );
+ EU433_CALC_BACKOFF( );
+ EU868_CALC_BACKOFF( );
+ KR920_CALC_BACKOFF( );
+ IN865_CALC_BACKOFF( );
+ US915_CALC_BACKOFF( );
+ RU864_CALC_BACKOFF( );
+ default:
+ {
+ break;
+ }
}
- AS923_CALC_BACKOFF( )
- AU915_CALC_BACKOFF( )
- CN470_CALC_BACKOFF( )
- CN779_CALC_BACKOFF( )
- EU433_CALC_BACKOFF( )
- EU868_CALC_BACKOFF( )
- KR920_CALC_BACKOFF( )
- IN865_CALC_BACKOFF( )
- US915_CALC_BACKOFF( )
- US915_HYBRID_CALC_BACKOFF( )
}
-bool RegionNextChannel( LoRaMacRegion_t region, NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff )
+LoRaMacStatus_t RegionNextChannel( LoRaMacRegion_t region, NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff )
{
-
- if(region >= LORAMAC_REGION_MAX) {
- return false;
- }
- AS923_NEXT_CHANNEL( )
- AU915_NEXT_CHANNEL( )
- CN470_NEXT_CHANNEL( )
- CN779_NEXT_CHANNEL( )
- EU433_NEXT_CHANNEL( )
- EU868_NEXT_CHANNEL( )
- KR920_NEXT_CHANNEL( )
- IN865_NEXT_CHANNEL( )
- US915_NEXT_CHANNEL( )
- US915_HYBRID_NEXT_CHANNEL( )
- else {
- return false;
+ switch( region )
+ {
+ AS923_NEXT_CHANNEL( );
+ AU915_NEXT_CHANNEL( );
+ CN470_NEXT_CHANNEL( );
+ CN779_NEXT_CHANNEL( );
+ EU433_NEXT_CHANNEL( );
+ EU868_NEXT_CHANNEL( );
+ KR920_NEXT_CHANNEL( );
+ IN865_NEXT_CHANNEL( );
+ US915_NEXT_CHANNEL( );
+ RU864_NEXT_CHANNEL( );
+ default:
+ {
+ return LORAMAC_STATUS_REGION_NOT_SUPPORTED;
+ }
}
}
LoRaMacStatus_t RegionChannelAdd( LoRaMacRegion_t region, ChannelAddParams_t* channelAdd )
{
-
- if(region >= LORAMAC_REGION_MAX) {
- return LORAMAC_STATUS_PARAMETER_INVALID;
- }
- AS923_CHANNEL_ADD( )
- AU915_CHANNEL_ADD( )
- CN470_CHANNEL_ADD( )
- CN779_CHANNEL_ADD( )
- EU433_CHANNEL_ADD( )
- EU868_CHANNEL_ADD( )
- KR920_CHANNEL_ADD( )
- IN865_CHANNEL_ADD( )
- US915_CHANNEL_ADD( )
- US915_HYBRID_CHANNEL_ADD( )
- else {
- return LORAMAC_STATUS_PARAMETER_INVALID;
- }
-}
-
-LoRaMacStatus_t RegionChannelManualAdd( LoRaMacRegion_t region, ChannelAddParams_t* channelAdd )
-{
-
- if(region >= LORAMAC_REGION_MAX) {
- return LORAMAC_STATUS_PARAMETER_INVALID;
- }
- AS923_CHANNEL_MANUAL_ADD( )
- AU915_CHANNEL_MANUAL_ADD( )
- EU868_CHANNEL_MANUAL_ADD( )
- US915_CHANNEL_MANUAL_ADD( )
- CN470_CHANNEL_MANUAL_ADD( )
- IN865_CHANNEL_MANUAL_ADD( )
- US915_HYBRID_CHANNEL_MANUAL_ADD( )
- else {
- return LORAMAC_STATUS_PARAMETER_INVALID;
+ switch( region )
+ {
+ AS923_CHANNEL_ADD( );
+ AU915_CHANNEL_ADD( );
+ CN470_CHANNEL_ADD( );
+ CN779_CHANNEL_ADD( );
+ EU433_CHANNEL_ADD( );
+ EU868_CHANNEL_ADD( );
+ KR920_CHANNEL_ADD( );
+ IN865_CHANNEL_ADD( );
+ US915_CHANNEL_ADD( );
+ RU864_CHANNEL_ADD( );
+ default:
+ {
+ return LORAMAC_STATUS_PARAMETER_INVALID;
+ }
}
}
bool RegionChannelsRemove( LoRaMacRegion_t region, ChannelRemoveParams_t* channelRemove )
{
-
- if(region >= LORAMAC_REGION_MAX) {
- return false;
- }
- AS923_CHANNEL_REMOVE( )
- AU915_CHANNEL_REMOVE( )
- CN470_CHANNEL_REMOVE( )
- CN779_CHANNEL_REMOVE( )
- EU433_CHANNEL_REMOVE( )
- EU868_CHANNEL_REMOVE( )
- KR920_CHANNEL_REMOVE( )
- IN865_CHANNEL_REMOVE( )
- US915_CHANNEL_REMOVE( )
- US915_HYBRID_CHANNEL_REMOVE( )
- else {
- return false;
- }
-}
-
-bool RegionChannelsManualRemove( LoRaMacRegion_t region, ChannelRemoveParams_t* channelRemove )
-{
-
- if(region >= LORAMAC_REGION_MAX) {
- return false;
- }
- AS923_CHANNEL_MANUAL_REMOVE( )
- AU915_CHANNEL_MANUAL_REMOVE( )
- EU868_CHANNEL_MANUAL_REMOVE( )
- US915_CHANNEL_MANUAL_REMOVE( )
- CN470_CHANNEL_MANUAL_REMOVE( )
- IN865_CHANNEL_MANUAL_REMOVE( )
- US915_HYBRID_CHANNEL_MANUAL_REMOVE( )
- US915_HYBRID_CHANNEL_REMOVE( )
- else {
- return false;
+ switch( region )
+ {
+ AS923_CHANNEL_REMOVE( );
+ AU915_CHANNEL_REMOVE( );
+ CN470_CHANNEL_REMOVE( );
+ CN779_CHANNEL_REMOVE( );
+ EU433_CHANNEL_REMOVE( );
+ EU868_CHANNEL_REMOVE( );
+ KR920_CHANNEL_REMOVE( );
+ IN865_CHANNEL_REMOVE( );
+ US915_CHANNEL_REMOVE( );
+ RU864_CHANNEL_REMOVE( );
+ default:
+ {
+ return false;
+ }
}
}
void RegionSetContinuousWave( LoRaMacRegion_t region, ContinuousWaveParams_t* continuousWave )
{
-
- if(region >= LORAMAC_REGION_MAX) {
- return;
+ switch( region )
+ {
+ AS923_SET_CONTINUOUS_WAVE( );
+ AU915_SET_CONTINUOUS_WAVE( );
+ CN470_SET_CONTINUOUS_WAVE( );
+ CN779_SET_CONTINUOUS_WAVE( );
+ EU433_SET_CONTINUOUS_WAVE( );
+ EU868_SET_CONTINUOUS_WAVE( );
+ KR920_SET_CONTINUOUS_WAVE( );
+ IN865_SET_CONTINUOUS_WAVE( );
+ US915_SET_CONTINUOUS_WAVE( );
+ RU864_SET_CONTINUOUS_WAVE( );
+ default:
+ {
+ break;
+ }
}
- AS923_SET_CONTINUOUS_WAVE( )
- AU915_SET_CONTINUOUS_WAVE( )
- CN470_SET_CONTINUOUS_WAVE( )
- CN779_SET_CONTINUOUS_WAVE( )
- EU433_SET_CONTINUOUS_WAVE( )
- EU868_SET_CONTINUOUS_WAVE( )
- KR920_SET_CONTINUOUS_WAVE( )
- IN865_SET_CONTINUOUS_WAVE( )
- US915_SET_CONTINUOUS_WAVE( )
- US915_HYBRID_SET_CONTINUOUS_WAVE( )
}
uint8_t RegionApplyDrOffset( LoRaMacRegion_t region, uint8_t downlinkDwellTime, int8_t dr, int8_t drOffset )
{
-
- if(region >= LORAMAC_REGION_MAX) {
- return dr;
- }
- AS923_APPLY_DR_OFFSET( )
- AU915_APPLY_DR_OFFSET( )
- CN470_APPLY_DR_OFFSET( )
- CN779_APPLY_DR_OFFSET( )
- EU433_APPLY_DR_OFFSET( )
- EU868_APPLY_DR_OFFSET( )
- KR920_APPLY_DR_OFFSET( )
- IN865_APPLY_DR_OFFSET( )
- US915_APPLY_DR_OFFSET( )
- US915_HYBRID_APPLY_DR_OFFSET( )
- US915_HYBRID_CHANNEL_REMOVE( )
- else {
- return dr;
+ switch( region )
+ {
+ AS923_APPLY_DR_OFFSET( );
+ AU915_APPLY_DR_OFFSET( );
+ CN470_APPLY_DR_OFFSET( );
+ CN779_APPLY_DR_OFFSET( );
+ EU433_APPLY_DR_OFFSET( );
+ EU868_APPLY_DR_OFFSET( );
+ KR920_APPLY_DR_OFFSET( );
+ IN865_APPLY_DR_OFFSET( );
+ US915_APPLY_DR_OFFSET( );
+ RU864_APPLY_DR_OFFSET( );
+ default:
+ {
+ return dr;
+ }
}
}
-bool RegionGetChannels( LoRaMacRegion_t region, ChannelParams_t** channels, uint32_t *size )
+void RegionRxBeaconSetup( LoRaMacRegion_t region, RxBeaconSetup_t* rxBeaconSetup, uint8_t* outDr )
{
-
- if(region >= LORAMAC_REGION_MAX) {
- return false;
- }
- AS923_GET_CHANNELS( )
- AU915_GET_CHANNELS( )
- EU868_GET_CHANNELS( )
- IN865_GET_CHANNELS( )
- US915_GET_CHANNELS( )
- US915_HYBRID_GET_CHANNELS( )
- US915_HYBRID_CHANNEL_REMOVE( )
- else {
- return false;
- }
-}
-
-bool RegionGetChannelMask(LoRaMacRegion_t region, uint16_t **channelmask, uint32_t *size ) {
-
- if(region >= LORAMAC_REGION_MAX) {
- return false;
- }
- AS923_GET_CHANNEL_MASK( )
- AU915_GET_CHANNEL_MASK( )
- EU868_GET_CHANNEL_MASK( )
- IN865_GET_CHANNEL_MASK( )
- US915_GET_CHANNEL_MASK( )
- US915_HYBRID_GET_CHANNEL_MASK( )
- US915_HYBRID_CHANNEL_REMOVE( )
- else {
- return false;
+ switch( region )
+ {
+ AS923_RX_BEACON_SETUP( );
+ AU915_RX_BEACON_SETUP( );
+ CN470_RX_BEACON_SETUP( );
+ CN779_RX_BEACON_SETUP( );
+ EU433_RX_BEACON_SETUP( );
+ EU868_RX_BEACON_SETUP( );
+ KR920_RX_BEACON_SETUP( );
+ IN865_RX_BEACON_SETUP( );
+ US915_RX_BEACON_SETUP( );
+ RU864_RX_BEACON_SETUP( );
+ default:
+ {
+ break;
+ }
}
}
-bool RegionGetChannelMaskRemaining(LoRaMacRegion_t region, uint16_t **channelmask, uint32_t *size ) {
-
- if(region >= LORAMAC_REGION_MAX) {
- return false;
- }
- AU915_GET_CHANNEL_MASK_REMAINING( )
- US915_GET_CHANNEL_MASK_REMAINING( )
- US915_HYBRID_GET_CHANNEL_MASK_REMAINING( )
- US915_HYBRID_CHANNEL_REMOVE( )
- else {
- return false;
+////////////////////////////////////// PYCOM FUNCTIONS //////////////////////////////////////
+LoRaMacStatus_t RegionChannelManualAdd( LoRaMacRegion_t region, ChannelAddParams_t* channelAdd )
+{
+ switch( region )
+ {
+ AS923_CHANNEL_MANUAL_ADD( )
+ AU915_CHANNEL_MANUAL_ADD( )
+ EU868_CHANNEL_MANUAL_ADD( )
+ US915_CHANNEL_MANUAL_ADD( )
+ CN470_CHANNEL_MANUAL_ADD( )
+ IN865_CHANNEL_MANUAL_ADD( )
+ EU433_CHANNEL_MANUAL_ADD( )
+ CN779_CHANNEL_MANUAL_ADD( )
+ RU864_CHANNEL_MANUAL_ADD( )
+ KR920_CHANNEL_MANUAL_ADD( )
+
+ default:
+ {
+ return LORAMAC_STATUS_PARAMETER_INVALID;
+ }
}
}
-bool RegionForceJoinDataRate( LoRaMacRegion_t region, int8_t joinDr, AlternateDrParams_t* alternateDr )
+bool RegionChannelsManualRemove( LoRaMacRegion_t region, ChannelRemoveParams_t* channelRemove )
{
- if(region >= LORAMAC_REGION_MAX) {
- return false;
- }
- AS923_FORCE_JOIN_DATARATE( )
- AU915_FORCE_JOIN_DATARATE( )
- EU868_FORCE_JOIN_DATARATE( )
- US915_FORCE_JOIN_DATARATE( )
- CN470_FORCE_JOIN_DATARATE( )
- IN865_FORCE_JOIN_DATARATE( )
- US915_HYBRID_FORCE_JOIN_DATARATE( )
- US915_HYBRID_CHANNEL_REMOVE( )
- else {
- return false;
+ switch( region )
+ {
+ AS923_CHANNEL_MANUAL_REMOVE( )
+ AU915_CHANNEL_MANUAL_REMOVE( )
+ EU868_CHANNEL_MANUAL_REMOVE( )
+ US915_CHANNEL_MANUAL_REMOVE( )
+ CN470_CHANNEL_MANUAL_REMOVE( )
+ IN865_CHANNEL_MANUAL_REMOVE( )
+ EU433_CHANNEL_MANUAL_REMOVE( )
+ CN779_CHANNEL_MANUAL_REMOVE( )
+ RU864_CHANNEL_MANUAL_REMOVE( )
+ KR920_CHANNEL_MANUAL_REMOVE( )
+ default:
+ {
+ return false;
+ }
}
}
+// bool RegionForceJoinDataRate( LoRaMacRegion_t region, int8_t joinDr, AlternateDrParams_t* alternateDr )
+// {
+
+// if(region > LORAMAC_REGION_RU864) {
+// return false;
+// }
+// AS923_FORCE_JOIN_DATARATE( )
+// AU915_FORCE_JOIN_DATARATE( )
+// EU868_FORCE_JOIN_DATARATE( )
+// US915_FORCE_JOIN_DATARATE( )
+// CN470_FORCE_JOIN_DATARATE( )
+// IN865_FORCE_JOIN_DATARATE( )
+// US915_HYBRID_FORCE_JOIN_DATARATE( )
+// US915_HYBRID_CHANNEL_REMOVE( )
+// else {
+// return false;
+// }
+// return true;
+// }
diff --git a/lib/lora/mac/region/Region.h b/lib/lora/mac/region/Region.h
index 641f6af810..387fc38a48 100644
--- a/lib/lora/mac/region/Region.h
+++ b/lib/lora/mac/region/Region.h
@@ -12,7 +12,7 @@
* \____ \| ___ | (_ _) ___ |/ ___) _ \
* _____) ) ____| | | || |_| ____( (___| | | |
* (______/|_____)_|_|_| \__)_____)\____)_| |_|
- * (C)2013 Semtech
+ * (C)2013-2017 Semtech
*
* ___ _____ _ ___ _ _____ ___ ___ ___ ___
* / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
@@ -45,15 +45,23 @@
* - #define REGION_KR920
* - #define REGION_IN865
* - #define REGION_US915
- * - #define REGION_US915_HYBRID
+ * - #define REGION_RU864
*
* \{
*/
#ifndef __REGION_H__
#define __REGION_H__
+#ifdef __cplusplus
+extern "C"
+{
+#endif
-
+#include
+#include
+#include "utilities.h"
+#include "../LoRaMac.h"
+#include "timer.h"
/*!
* Macro to compute bit of a channel index.
@@ -72,7 +80,7 @@
* IN865 | SF12 - BW125
* KR920 | SF12 - BW125
* US915 | SF10 - BW125
- * US915_HYBRID | SF10 - BW125
+ * RU864 | SF12 - BW125
*/
#define DR_0 0
@@ -88,7 +96,7 @@
* IN865 | SF11 - BW125
* KR920 | SF11 - BW125
* US915 | SF9 - BW125
- * US915_HYBRID | SF9 - BW125
+ * RU864 | SF11 - BW125
*/
#define DR_1 1
@@ -104,7 +112,7 @@
* IN865 | SF10 - BW125
* KR920 | SF10 - BW125
* US915 | SF8 - BW125
- * US915_HYBRID | SF8 - BW125
+ * RU864 | SF10 - BW125
*/
#define DR_2 2
@@ -120,7 +128,7 @@
* IN865 | SF9 - BW125
* KR920 | SF9 - BW125
* US915 | SF7 - BW125
- * US915_HYBRID | SF7 - BW125
+ * RU864 | SF9 - BW125
*/
#define DR_3 3
@@ -136,7 +144,7 @@
* IN865 | SF8 - BW125
* KR920 | SF8 - BW125
* US915 | SF8 - BW500
- * US915_HYBRID | SF8 - BW500
+ * RU864 | SF8 - BW125
*/
#define DR_4 4
@@ -152,7 +160,7 @@
* IN865 | SF7 - BW125
* KR920 | SF7 - BW125
* US915 | RFU
- * US915_HYBRID | RFU
+ * RU864 | SF7 - BW125
*/
#define DR_5 5
@@ -168,7 +176,7 @@
* IN865 | SF7 - BW250
* KR920 | RFU
* US915 | RFU
- * US915_HYBRID | RFU
+ * RU864 | SF7 - BW250
*/
#define DR_6 6
@@ -184,7 +192,7 @@
* IN865 | FSK
* KR920 | RFU
* US915 | RFU
- * US915_HYBRID | RFU
+ * RU864 | FSK
*/
#define DR_7 7
@@ -200,7 +208,7 @@
* IN865 | RFU
* KR920 | RFU
* US915 | SF12 - BW500
- * US915_HYBRID | SF12 - BW500
+ * RU864 | RFU
*/
#define DR_8 8
@@ -216,7 +224,7 @@
* IN865 | RFU
* KR920 | RFU
* US915 | SF11 - BW500
- * US915_HYBRID | SF11 - BW500
+ * RU864 | RFU
*/
#define DR_9 9
@@ -232,7 +240,7 @@
* IN865 | RFU
* KR920 | RFU
* US915 | SF10 - BW500
- * US915_HYBRID | SF10 - BW500
+ * RU864 | RFU
*/
#define DR_10 10
@@ -248,7 +256,7 @@
* IN865 | RFU
* KR920 | RFU
* US915 | SF9 - BW500
- * US915_HYBRID | SF9 - BW500
+ * RU864 | RFU
*/
#define DR_11 11
@@ -264,7 +272,7 @@
* IN865 | RFU
* KR920 | RFU
* US915 | SF8 - BW500
- * US915_HYBRID | SF8 - BW500
+ * RU864 | RFU
*/
#define DR_12 12
@@ -280,7 +288,7 @@
* IN865 | RFU
* KR920 | RFU
* US915 | SF7 - BW500
- * US915_HYBRID | SF7 - BW500
+ * RU864 | RFU
*/
#define DR_13 13
@@ -296,7 +304,7 @@
* IN865 | RFU
* KR920 | RFU
* US915 | RFU
- * US915_HYBRID | RFU
+ * RU864 | RFU
*/
#define DR_14 14
@@ -312,7 +320,7 @@
* IN865 | RFU
* KR920 | RFU
* US915 | RFU
- * US915_HYBRID | RFU
+ * RU864 | RFU
*/
#define DR_15 15
@@ -330,7 +338,7 @@
* IN865 | Max EIRP
* KR920 | Max EIRP
* US915 | Max ERP
- * US915_HYBRID | Max ERP
+ * RU864 | Max EIRP
*/
#define TX_POWER_0 0
@@ -346,7 +354,7 @@
* IN865 | Max EIRP - 2
* KR920 | Max EIRP - 2
* US915 | Max ERP - 2
- * US915_HYBRID | Max ERP - 2
+ * RU864 | Max EIRP - 2
*/
#define TX_POWER_1 1
@@ -362,7 +370,7 @@
* IN865 | Max EIRP - 4
* KR920 | Max EIRP - 4
* US915 | Max ERP - 4
- * US915_HYBRID | Max ERP - 4
+ * RU864 | Max EIRP - 4
*/
#define TX_POWER_2 2
@@ -378,7 +386,7 @@
* IN865 | Max EIRP - 6
* KR920 | Max EIRP - 6
* US915 | Max ERP - 6
- * US915_HYBRID | Max ERP - 6
+ * RU864 | Max EIRP - 6
*/
#define TX_POWER_3 3
@@ -394,7 +402,7 @@
* IN865 | Max EIRP - 8
* KR920 | Max EIRP - 8
* US915 | Max ERP - 8
- * US915_HYBRID | Max ERP - 8
+ * RU864 | Max EIRP - 8
*/
#define TX_POWER_4 4
@@ -410,7 +418,7 @@
* IN865 | Max EIRP - 10
* KR920 | Max EIRP - 10
* US915 | Max ERP - 10
- * US915_HYBRID | Max ERP - 10
+ * RU864 | Max EIRP - 10
*/
#define TX_POWER_5 5
@@ -426,7 +434,7 @@
* IN865 | Max EIRP - 12
* KR920 | Max EIRP - 12
* US915 | Max ERP - 12
- * US915_HYBRID | Max ERP - 12
+ * RU864 | Max EIRP - 12
*/
#define TX_POWER_6 6
@@ -442,7 +450,7 @@
* IN865 | Max EIRP - 14
* KR920 | Max EIRP - 14
* US915 | Max ERP - 14
- * US915_HYBRID | Max ERP - 14
+ * RU864 | Max EIRP - 14
*/
#define TX_POWER_7 7
@@ -458,7 +466,7 @@
* IN865 | Max EIRP - 16
* KR920 | -
* US915 | Max ERP - 16
- * US915_HYBRID | Max ERP -16
+ * RU864 | -
*/
#define TX_POWER_8 8
@@ -473,8 +481,8 @@
* EU868 | -
* IN865 | Max EIRP - 18
* KR920 | -
- * US915 | Max ERP - 16
- * US915_HYBRID | Max ERP - 16
+ * US915 | Max ERP - 18
+ * RU864 | -
*/
#define TX_POWER_9 9
@@ -489,28 +497,72 @@
* EU868 | -
* IN865 | Max EIRP - 20
* KR920 | -
- * US915 | Max ERP - 10
- * US915_HYBRID | Max ERP - 10
+ * US915 | Max ERP - 20
+ * RU864 | -
*/
#define TX_POWER_10 10
/*!
- * RFU
+ * Region | dBM
+ * ------------ | :-----:
+ * AS923 | -
+ * AU915 | Max EIRP - 22
+ * CN470 | -
+ * CN779 | -
+ * EU433 | -
+ * EU868 | -
+ * IN865 | -
+ * KR920 | -
+ * US915 | Max ERP - 22
+ * RU864 | -
*/
#define TX_POWER_11 11
/*!
- * RFU
+ * Region | dBM
+ * ------------ | :-----:
+ * AS923 | -
+ * AU915 | Max EIRP - 24
+ * CN470 | -
+ * CN779 | -
+ * EU433 | -
+ * EU868 | -
+ * IN865 | -
+ * KR920 | -
+ * US915 | Max ERP - 24
+ * RU864 | -
*/
#define TX_POWER_12 12
/*!
- * RFU
+ * Region | dBM
+ * ------------ | :-----:
+ * AS923 | -
+ * AU915 | Max EIRP - 26
+ * CN470 | -
+ * CN779 | -
+ * EU433 | -
+ * EU868 | -
+ * IN865 | -
+ * KR920 | -
+ * US915 | Max ERP - 26
+ * RU864 | -
*/
#define TX_POWER_13 13
/*!
- * RFU
+ * Region | dBM
+ * ------------ | :-----:
+ * AS923 | -
+ * AU915 | Max EIRP - 28
+ * CN470 | -
+ * CN779 | -
+ * EU433 | -
+ * EU868 | -
+ * IN865 | -
+ * KR920 | -
+ * US915 | Max ERP - 28
+ * RU864 | -
*/
#define TX_POWER_14 14
@@ -526,6 +578,11 @@
*/
typedef enum ePhyAttribute
{
+ /*!
+ * Frequency. It is available
+ * to perform a verification with RegionVerify().
+ */
+ PHY_FREQUENCY,
/*!
* Minimum RX datarate.
*/
@@ -544,6 +601,8 @@ typedef enum ePhyAttribute
PHY_MAX_TX_DR,
/*!
* TX datarate.
+ * This is a parameter which can't be queried. It is available
+ * to perform a verification with RegionVerify().
*/
PHY_TX_DR,
/*!
@@ -551,17 +610,31 @@ typedef enum ePhyAttribute
*/
PHY_DEF_TX_DR,
/*!
- * RX datarate.
+ * RX datarate. It is available
+ * to perform a verification with RegionVerify().
*/
PHY_RX_DR,
/*!
- * TX power.
+ * Maximum TX power.
+ */
+ PHY_MAX_TX_POWER,
+ /*!
+ * TX power. It is available
+ * to perform a verification with RegionVerify().
*/
PHY_TX_POWER,
/*!
* Default TX power.
*/
PHY_DEF_TX_POWER,
+ /*!
+ * Default ADR_ACK_LIMIT value.
+ */
+ PHY_DEF_ADR_ACK_LIMIT,
+ /*!
+ * Default ADR_ACK_DELAY value.
+ */
+ PHY_DEF_ADR_ACK_DELAY,
/*!
* Maximum payload possible.
*/
@@ -647,17 +720,87 @@ typedef enum ePhyAttribute
*/
PHY_DEF_ANTENNA_GAIN,
/*!
- * Value for the number of join trials.
+ * Next lower datarate.
+ */
+ PHY_NEXT_LOWER_TX_DR,
+ /*!
+ * Beacon interval in ms.
*/
- PHY_NB_JOIN_TRIALS,
+ PHY_BEACON_INTERVAL,
/*!
- * Default value for the number of join trials.
+ * Beacon reserved time in ms.
*/
- PHY_DEF_NB_JOIN_TRIALS,
+ PHY_BEACON_RESERVED,
/*!
- * Next lower datarate.
+ * Beacon guard time in ms.
+ */
+ PHY_BEACON_GUARD,
+ /*!
+ * Beacon window time in ms.
+ */
+ PHY_BEACON_WINDOW,
+ /*!
+ * Beacon window time in numer of slots.
+ */
+ PHY_BEACON_WINDOW_SLOTS,
+ /*!
+ * Ping slot length time in ms.
+ */
+ PHY_PING_SLOT_WINDOW,
+ /*!
+ * Default symbol timeout for beacons and ping slot windows.
+ */
+ PHY_BEACON_SYMBOL_TO_DEFAULT,
+ /*!
+ * Maximum symbol timeout for beacons.
+ */
+ PHY_BEACON_SYMBOL_TO_EXPANSION_MAX,
+ /*!
+ * Maximum symbol timeout for ping slots.
+ */
+ PHY_PING_SLOT_SYMBOL_TO_EXPANSION_MAX,
+ /*!
+ * Symbol expansion value for beacon windows in case of beacon
+ * loss in symbols.
+ */
+ PHY_BEACON_SYMBOL_TO_EXPANSION_FACTOR,
+ /*!
+ * Symbol expansion value for ping slot windows in case of beacon
+ * loss in symbols.
+ */
+ PHY_PING_SLOT_SYMBOL_TO_EXPANSION_FACTOR,
+ /*!
+ * Maximum allowed beacon less time in ms.
+ */
+ PHY_MAX_BEACON_LESS_PERIOD,
+ /*!
+ * Delay time for the BeaconTimingAns in ms.
+ */
+ PHY_BEACON_DELAY_BEACON_TIMING_ANS,
+ /*!
+ * Beacon channel frequency.
+ */
+ PHY_BEACON_CHANNEL_FREQ,
+ /*!
+ * The format of the beacon.
+ */
+ PHY_BEACON_FORMAT,
+ /*!
+ * The beacon channel datarate.
*/
- PHY_NEXT_LOWER_TX_DR
+ PHY_BEACON_CHANNEL_DR,
+ /*!
+ * The frequency stepwidth between the beacon channels.
+ */
+ PHY_BEACON_CHANNEL_STEPWIDTH,
+ /*!
+ * The number of channels for the beacon reception.
+ */
+ PHY_BEACON_NB_CHANNELS,
+ /*!
+ * The datarate of a ping slot channel.
+ */
+ PHY_PING_SLOT_CHANNEL_DR
}PhyAttribute_t;
/*!
@@ -666,13 +809,18 @@ typedef enum ePhyAttribute
typedef enum eInitType
{
/*!
- * Performs an initialization and overwrites all existing data.
+ * Initializes the region specific data to defaults, according to the
+ * LoRaWAN specification.
*/
INIT_TYPE_INIT,
/*!
- * Restores default channels only.
+ * Restores default channels defined by the LoRaWAN specification only.
*/
- INIT_TYPE_RESTORE
+ INIT_TYPE_RESTORE_DEFAULT_CHANNELS,
+ /*!
+ * Restores internal context from passed pointer.
+ */
+ INIT_TYPE_RESTORE_CTX
}InitType_t;
typedef enum eChannelsMask
@@ -687,6 +835,25 @@ typedef enum eChannelsMask
CHANNELS_DEFAULT_MASK
}ChannelsMask_t;
+/*!
+ * Structure containing the beacon format
+ */
+typedef struct sBeaconFormat
+{
+ /*!
+ * Size of the beacon
+ */
+ uint8_t BeaconSize;
+ /*!
+ * Size of the RFU 1 data field
+ */
+ uint8_t Rfu1Size;
+ /*!
+ * Size of the RFU 2 data field
+ */
+ uint8_t Rfu2Size;
+}BeaconFormat_t;
+
/*!
* Union for the structure uGetPhyParams
*/
@@ -708,6 +875,10 @@ typedef union uPhyParam
* Pointer to the channels.
*/
ChannelParams_t* Channels;
+ /*!
+ * Beacon format
+ */
+ BeaconFormat_t BeaconFormat;
}PhyParam_t;
/*!
@@ -726,13 +897,15 @@ typedef struct sGetPhyParams
*/
int8_t Datarate;
/*!
- * Uplink dwell time.
+ * Uplink dwell time. This parameter must be set to query:
+ * PHY_MAX_PAYLOAD, PHY_MAX_PAYLOAD_REPEATER, PHY_MIN_TX_DR.
* The parameter is needed for the following queries:
* PHY_MIN_TX_DR, PHY_MAX_PAYLOAD, PHY_MAX_PAYLOAD_REPEATER, PHY_NEXT_LOWER_TX_DR.
*/
uint8_t UplinkDwellTime;
/*!
- * Downlink dwell time.
+ * Downlink dwell time. This parameter must be set to query:
+ * PHY_MAX_PAYLOAD, PHY_MAX_PAYLOAD_REPEATER, PHY_MIN_RX_DR.
* The parameter is needed for the following queries:
* PHY_MIN_RX_DR, PHY_MAX_PAYLOAD, PHY_MAX_PAYLOAD_REPEATER.
*/
@@ -758,11 +931,42 @@ typedef struct sSetBandTxDoneParams
TimerTime_t LastTxDoneTime;
}SetBandTxDoneParams_t;
+/*!
+ * Parameter structure for the function RegionInitDefaults.
+ */
+typedef struct sInitDefaultsParams
+{
+ /*!
+ * Pointer to region module context to be restored.
+ */
+ void* NvmCtx;
+ /*!
+ * Sets the initialization type.
+ */
+ InitType_t Type;
+}InitDefaultsParams_t;
+
+/*!
+ * Parameter structure for the function RegionGetNvmCtx.
+ */
+typedef struct sGetNvmCtxParams
+{
+ /*!
+ * Size of module context.
+ */
+ size_t nvmCtxSize;
+}GetNvmCtxParams_t;
+
+
/*!
* Parameter structure for the function RegionVerify.
*/
typedef union uVerifyParams
{
+ /*!
+ * Channel frequency to verify
+ */
+ uint32_t Frequency;
/*!
* TX power to verify.
*/
@@ -771,10 +975,6 @@ typedef union uVerifyParams
* Set to true, if the duty cycle is enabled, otherwise false.
*/
bool DutyCycle;
- /*!
- * The number of join trials.
- */
- uint8_t NbJoinTrials;
/*!
* Datarate to verify.
*/
@@ -825,37 +1025,6 @@ typedef struct sChanMaskSetParams
ChannelsMask_t ChannelsMaskType;
}ChanMaskSetParams_t;
-/*!
- * Parameter structure for the function RegionAdrNext.
- */
-typedef struct sAdrNextParams
-{
- /*!
- * Set to true, if the function should update the channels mask.
- */
- bool UpdateChanMask;
- /*!
- * Set to true, if ADR is enabled.
- */
- bool AdrEnabled;
- /*!
- * ADR ack counter.
- */
- uint32_t AdrAckCounter;
- /*!
- * Datarate used currently.
- */
- int8_t Datarate;
- /*!
- * TX power used currently.
- */
- int8_t TxPower;
- /*!
- * UplinkDwellTime
- */
- uint8_t UplinkDwellTime;
-}AdrNextParams_t;
-
/*!
* Parameter structure for the function RegionRxConfig.
*/
@@ -902,9 +1071,9 @@ typedef struct sRxConfigParams
*/
bool RxContinuous;
/*!
- * Sets the RX window. 0: RX window 1, 1: RX window 2.
+ * Sets the RX window.
*/
- bool Window;
+ LoRaMacRxSlot_t RxSlot;
}RxConfigParams_t;
/*!
@@ -943,6 +1112,10 @@ typedef struct sTxConfigParams
*/
typedef struct sLinkAdrReqParams
{
+ /*!
+ * Current LoRaWAN Version
+ */
+ Version_t Version;
/*!
* Pointer to the payload which contains the MAC commands.
*/
@@ -1042,15 +1215,19 @@ typedef struct sDlChannelReqParams
}DlChannelReqParams_t;
/*!
- * Parameter structure for the function RegionAlternateDr.
+ * Enumeration of alternation type
*/
-typedef struct sAlternateDrParams
+typedef enum eAlternateDrType
{
/*!
- * Number of trials.
+ * Type to use for an alternation
+ */
+ ALTERNATE_DR,
+ /*!
+ * Type to use to restore one alternation
*/
- uint16_t NbTrials;
-}AlternateDrParams_t;
+ ALTERNATE_DR_RESTORE
+}AlternateDrType_t;
/*!
* Parameter structure for the function RegionCalcBackOff.
@@ -1076,7 +1253,7 @@ typedef struct sCalcBackOffParams
/*!
* Elapsed time since the start of the node.
*/
- TimerTime_t ElapsedTime;
+ SysTime_t ElapsedTime;
/*!
* Time-on-air of the last transmission.
*/
@@ -1167,6 +1344,25 @@ typedef struct sContinuousWaveParams
uint16_t Timeout;
}ContinuousWaveParams_t;
+/*!
+ * Parameter structure for the function RegionRxBeaconSetup
+ */
+typedef struct sRxBeaconSetupParams
+{
+ /*!
+ * Symbol timeout.
+ */
+ uint16_t SymbolTimeout;
+ /*!
+ * Receive time.
+ */
+ uint32_t RxTime;
+ /*!
+ * The frequency to setup.
+ */
+ uint32_t Frequency;
+}RxBeaconSetup_t;
+
/*!
@@ -1204,9 +1400,20 @@ void RegionSetBandTxDone( LoRaMacRegion_t region, SetBandTxDoneParams_t* txDone
*
* \param [IN] region LoRaWAN region.
*
- * \param [IN] type Sets the initialization type.
+ * \param [IN] params Pointer to the function parameters.
+ */
+void RegionInitDefaults( LoRaMacRegion_t region, InitDefaultsParams_t* params );
+
+/*!
+ * \brief Returns a pointer to the internal context and its size.
+ *
+ * \param [IN] region LoRaWAN region.
+ *
+ * \param [IN] params Pointer to the function parameters.
+ *
+ * \retval Points to a structure where the module store its non-volatile context.
*/
-void RegionInitDefaults( LoRaMacRegion_t region, InitType_t type );
+void* RegionGetNvmCtx( LoRaMacRegion_t region, GetNvmCtxParams_t* params );
/*!
* \brief Verifies a parameter.
@@ -1242,23 +1449,6 @@ void RegionApplyCFList( LoRaMacRegion_t region, ApplyCFListParams_t* applyCFList
*/
bool RegionChanMaskSet( LoRaMacRegion_t region, ChanMaskSetParams_t* chanMaskSet );
-/*!
- * \brief Calculates the next datarate to set, when ADR is on or off.
- *
- * \param [IN] region LoRaWAN region.
- *
- * \param [IN] adrNext Pointer to the function parameters.
- *
- * \param [OUT] drOut The calculated datarate for the next TX.
- *
- * \param [OUT] txPowOut The TX power for the next TX.
- *
- * \param [OUT] adrAckCounter The calculated ADR acknowledgement counter.
- *
- * \retval Returns true, if an ADR request should be performed.
- */
-bool RegionAdrNext( LoRaMacRegion_t region, AdrNextParams_t* adrNext, int8_t* drOut, int8_t* txPowOut, uint32_t* adrAckCounter );
-
/*!
* \brief Configuration of the RX windows.
*
@@ -1276,9 +1466,9 @@ bool RegionRxConfig( LoRaMacRegion_t region, RxConfigParams_t* rxConfig, int8_t*
* Rx window precise timing
*
* For more details please consult the following document, chapter 3.1.2.
- * http://www.semtech.com/images/datasheet/SX1272_settings_for_LoRaWAN_v2.0.pdf
+ * https://www.semtech.com/uploads/documents/SX1272_settings_for_LoRaWAN_v2.0.pdf
* or
- * http://www.semtech.com/images/datasheet/SX1276_settings_for_LoRaWAN_v2.0.pdf
+ * https://www.semtech.com/uploads/documents/SX1276_settings_for_LoRaWAN_v2.0.pdf
*
* Downlink start: T = Tx + 1s (+/- 20 us)
* |
@@ -1412,11 +1602,13 @@ uint8_t RegionDlChannelReq( LoRaMacRegion_t region, DlChannelReqParams_t* dlChan
*
* \param [IN] region LoRaWAN region.
*
- * \param [IN] alternateDr Pointer to the function parameters.
+ * \param [IN] currentDr Current datarate.
+ *
+ * \param [IN] type Alternation type.
*
* \retval Datarate to apply.
*/
-int8_t RegionAlternateDr( LoRaMacRegion_t region, AlternateDrParams_t* alternateDr );
+int8_t RegionAlternateDr( LoRaMacRegion_t region, int8_t currentDr, AlternateDrType_t type );
/*!
* \brief Calculates the back-off time.
@@ -1441,7 +1633,7 @@ void RegionCalcBackOff( LoRaMacRegion_t region, CalcBackOffParams_t* calcBackOff
*
* \retval Function status [1: OK, 0: Unable to find a channel on the current datarate].
*/
-bool RegionNextChannel( LoRaMacRegion_t region, NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff );
+LoRaMacStatus_t RegionNextChannel( LoRaMacRegion_t region, NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff );
/*!
* \brief Adds a channel.
@@ -1489,14 +1681,41 @@ void RegionSetContinuousWave( LoRaMacRegion_t region, ContinuousWaveParams_t* co
*/
uint8_t RegionApplyDrOffset( LoRaMacRegion_t region, uint8_t downlinkDwellTime, int8_t dr, int8_t drOffset );
+/*!
+ * \brief Sets the radio into beacon reception mode
+ *
+ * \param [IN] rxBeaconSetup Pointer to the function parameters
+ *
+ * \param [out] outDr Datarate used to receive the beacon
+ */
+void RegionRxBeaconSetup( LoRaMacRegion_t region, RxBeaconSetup_t* rxBeaconSetup, uint8_t* outDr );
+
+////////////////////////////////////// PYCOM FUNCTIONS //////////////////////////////////////
bool RegionGetChannels( LoRaMacRegion_t region, ChannelParams_t** channels, uint32_t *size);
bool RegionGetChannelMask(LoRaMacRegion_t region, uint16_t **channelmask, uint32_t *size );
bool RegionGetChannelMaskRemaining(LoRaMacRegion_t region, uint16_t **channelmask, uint32_t *size );
-bool RegionForceJoinDataRate( LoRaMacRegion_t region, int8_t joinDr, AlternateDrParams_t* alternateDr );
+
+// /*!
+// * Parameter structure for the function RegionAlternateDr.
+// */
+// typedef struct sAlternateDrParams
+// {
+// /*!
+// * Number of trials.
+// */
+// uint16_t NbTrials;
+// }AlternateDrParams_t;
+
+// bool RegionForceJoinDataRate( LoRaMacRegion_t region, int8_t joinDr, AlternateDrParams_t* alternateDr );
+
/*! \} defgroup REGION */
+#ifdef __cplusplus
+}
+#endif
+
#endif // __REGION_H__
diff --git a/lib/lora/mac/region/RegionAS923.c b/lib/lora/mac/region/RegionAS923.c
index bfc36038d9..573276ca3b 100644
--- a/lib/lora/mac/region/RegionAS923.c
+++ b/lib/lora/mac/region/RegionAS923.c
@@ -1,63 +1,70 @@
-/*
- / _____) _ | |
-( (____ _____ ____ _| |_ _____ ____| |__
- \____ \| ___ | (_ _) ___ |/ ___) _ \
- _____) ) ____| | | || |_| ____( (___| | | |
-(______/|_____)_|_|_| \__)_____)\____)_| |_|
- (C)2013 Semtech
- ___ _____ _ ___ _ _____ ___ ___ ___ ___
-/ __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
-\__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
-|___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
-embedded.connectivity.solutions===============
-
-Description: LoRa MAC region AS923 implementation
-
-License: Revised BSD License, see LICENSE.TXT file include in the project
-
-Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jaeckle ( STACKFORCE )
+/*!
+ * \file RegionAS923.c
+ *
+ * \brief Region implementation for AS923
+ *
+ * \copyright Revised BSD License, see section \ref LICENSE.
+ *
+ * \code
+ * ______ _
+ * / _____) _ | |
+ * ( (____ _____ ____ _| |_ _____ ____| |__
+ * \____ \| ___ | (_ _) ___ |/ ___) _ \
+ * _____) ) ____| | | || |_| ____( (___| | | |
+ * (______/|_____)_|_|_| \__)_____)\____)_| |_|
+ * (C)2013-2017 Semtech
+ *
+ * ___ _____ _ ___ _ _____ ___ ___ ___ ___
+ * / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
+ * \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
+ * |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
+ * embedded.connectivity.solutions===============
+ *
+ * \endcode
+ *
+ * \author Miguel Luis ( Semtech )
+ *
+ * \author Gregory Cristian ( Semtech )
+ *
+ * \author Daniel Jaeckle ( STACKFORCE )
*/
-#include
#include
-#include
-#include
-
-#include "board.h"
-#include "lora/mac/LoRaMac.h"
-#include "esp_attr.h"
#include "utilities.h"
-#include "Region.h"
#include "RegionCommon.h"
#include "RegionAS923.h"
// Definitions
#define CHANNELS_MASK_SIZE 1
-// Global attributes
/*!
- * LoRaMAC channels
+ * Region specific context
*/
-static ChannelParams_t Channels[AS923_MAX_NB_CHANNELS];
-
-/*!
- * LoRaMac bands
- */
-static Band_t Bands[AS923_MAX_NB_BANDS] =
+typedef struct sRegionAS923NvmCtx
{
- AS923_BAND0
-};
+ /*!
+ * LoRaMAC channels
+ */
+ ChannelParams_t Channels[ AS923_MAX_NB_CHANNELS ];
+ /*!
+ * LoRaMac bands
+ */
+ Band_t Bands[ AS923_MAX_NB_BANDS ];
+ /*!
+ * LoRaMac channels mask
+ */
+ uint16_t ChannelsMask[ CHANNELS_MASK_SIZE ];
+ /*!
+ * LoRaMac channels default mask
+ */
+ uint16_t ChannelsDefaultMask[ CHANNELS_MASK_SIZE ];
+}RegionAS923NvmCtx_t;
-/*!
- * LoRaMac channels mask
- */
-static uint16_t ChannelsMask[CHANNELS_MASK_SIZE];
-
-/*!
- * LoRaMac channels default mask
+/*
+ * Non-volatile module context.
*/
-static uint16_t ChannelsDefaultMask[CHANNELS_MASK_SIZE];
+static RegionAS923NvmCtx_t NvmCtx;
// Static functions
static int8_t GetNextLowerTxDr( int8_t dr, int8_t minDr )
@@ -99,7 +106,7 @@ static int8_t LimitTxPower( int8_t txPower, int8_t maxBandTxPower, int8_t datara
return txPowerResult;
}
-static bool VerifyTxFreq( uint32_t freq )
+static bool VerifyRfFreq( uint32_t freq )
{
// Check radio driver support
if( Radio.CheckRfFrequency( freq ) == false )
@@ -202,11 +209,26 @@ PhyParam_t RegionAS923GetPhyParam( GetPhyParams_t* getPhy )
}
break;
}
+ case PHY_MAX_TX_POWER:
+ {
+ phyParam.Value = AS923_MAX_TX_POWER;
+ break;
+ }
case PHY_DEF_TX_POWER:
{
phyParam.Value = AS923_DEFAULT_TX_POWER;
break;
}
+ case PHY_DEF_ADR_ACK_LIMIT:
+ {
+ phyParam.Value = AS923_ADR_ACK_LIMIT;
+ break;
+ }
+ case PHY_DEF_ADR_ACK_DELAY:
+ {
+ phyParam.Value = AS923_ADR_ACK_DELAY;
+ break;
+ }
case PHY_MAX_PAYLOAD:
{
if( getPhy->UplinkDwellTime == 0 )
@@ -288,12 +310,12 @@ PhyParam_t RegionAS923GetPhyParam( GetPhyParams_t* getPhy )
}
case PHY_CHANNELS_MASK:
{
- phyParam.ChannelsMask = ChannelsMask;
+ phyParam.ChannelsMask = NvmCtx.ChannelsMask;
break;
}
case PHY_CHANNELS_DEFAULT_MASK:
{
- phyParam.ChannelsMask = ChannelsDefaultMask;
+ phyParam.ChannelsMask = NvmCtx.ChannelsDefaultMask;
break;
}
case PHY_MAX_NB_CHANNELS:
@@ -303,7 +325,7 @@ PhyParam_t RegionAS923GetPhyParam( GetPhyParams_t* getPhy )
}
case PHY_CHANNELS:
{
- phyParam.Channels = Channels;
+ phyParam.Channels = NvmCtx.Channels;
break;
}
case PHY_DEF_UPLINK_DWELL_TIME:
@@ -326,10 +348,26 @@ PhyParam_t RegionAS923GetPhyParam( GetPhyParams_t* getPhy )
phyParam.fValue = AS923_DEFAULT_ANTENNA_GAIN;
break;
}
- case PHY_NB_JOIN_TRIALS:
- case PHY_DEF_NB_JOIN_TRIALS:
+ case PHY_BEACON_CHANNEL_FREQ:
+ {
+ phyParam.Value = AS923_BEACON_CHANNEL_FREQ;
+ break;
+ }
+ case PHY_BEACON_FORMAT:
+ {
+ phyParam.BeaconFormat.BeaconSize = AS923_BEACON_SIZE;
+ phyParam.BeaconFormat.Rfu1Size = AS923_RFU1_SIZE;
+ phyParam.BeaconFormat.Rfu2Size = AS923_RFU2_SIZE;
+ break;
+ }
+ case PHY_BEACON_CHANNEL_DR:
{
- phyParam.Value = 1;
+ phyParam.Value = AS923_BEACON_CHANNEL_DR;
+ break;
+ }
+ case PHY_PING_SLOT_CHANNEL_DR:
+ {
+ phyParam.Value = AS923_PING_SLOT_CHANNEL_DR;
break;
}
default:
@@ -341,31 +379,51 @@ PhyParam_t RegionAS923GetPhyParam( GetPhyParams_t* getPhy )
return phyParam;
}
-IRAM_ATTR void RegionAS923SetBandTxDone( SetBandTxDoneParams_t* txDone )
+void RegionAS923SetBandTxDone( SetBandTxDoneParams_t* txDone )
{
- RegionCommonSetBandTxDone( txDone->Joined, &Bands[Channels[txDone->Channel].Band], txDone->LastTxDoneTime );
+ RegionCommonSetBandTxDone( txDone->Joined, &NvmCtx.Bands[NvmCtx.Channels[txDone->Channel].Band], txDone->LastTxDoneTime );
}
-void RegionAS923InitDefaults( InitType_t type )
+void RegionAS923InitDefaults( InitDefaultsParams_t* params )
{
- switch( type )
+ Band_t bands[AS923_MAX_NB_BANDS] =
+ {
+ AS923_BAND0
+ };
+
+ switch( params->Type )
{
case INIT_TYPE_INIT:
{
+ // Initialize bands
+ memcpy1( ( uint8_t* )NvmCtx.Bands, ( uint8_t* )bands, sizeof( Band_t ) * AS923_MAX_NB_BANDS );
+
// Channels
- Channels[0] = ( ChannelParams_t ) AS923_LC1;
- Channels[1] = ( ChannelParams_t ) AS923_LC2;
+ NvmCtx.Channels[0] = ( ChannelParams_t ) AS923_LC1;
+ NvmCtx.Channels[1] = ( ChannelParams_t ) AS923_LC2;
// Initialize the channels default mask
- ChannelsDefaultMask[0] = LC( 1 ) + LC( 2 );
+ NvmCtx.ChannelsDefaultMask[0] = LC( 1 ) + LC( 2 );
// Update the channels mask
- RegionCommonChanMaskCopy( ChannelsMask, ChannelsDefaultMask, 1 );
+ RegionCommonChanMaskCopy( NvmCtx.ChannelsMask, NvmCtx.ChannelsDefaultMask, 1 );
break;
}
- case INIT_TYPE_RESTORE:
+ case INIT_TYPE_RESTORE_CTX:
+ {
+ if( params->NvmCtx != 0 )
+ {
+ memcpy1( (uint8_t*) &NvmCtx, (uint8_t*) params->NvmCtx, sizeof( NvmCtx ) );
+ }
+ break;
+ }
+ case INIT_TYPE_RESTORE_DEFAULT_CHANNELS:
{
// Restore channels default mask
- ChannelsMask[0] |= ChannelsDefaultMask[0];
+ NvmCtx.ChannelsMask[0] |= NvmCtx.ChannelsDefaultMask[0];
+
+ // Channels
+ NvmCtx.Channels[0] = ( ChannelParams_t ) AS923_LC1;
+ NvmCtx.Channels[1] = ( ChannelParams_t ) AS923_LC2;
break;
}
default:
@@ -375,10 +433,20 @@ void RegionAS923InitDefaults( InitType_t type )
}
}
+void* RegionAS923GetNvmCtx( GetNvmCtxParams_t* params )
+{
+ params->nvmCtxSize = sizeof( RegionAS923NvmCtx_t );
+ return &NvmCtx;
+}
+
bool RegionAS923Verify( VerifyParams_t* verify, PhyAttribute_t phyAttribute )
{
switch( phyAttribute )
{
+ case PHY_FREQUENCY:
+ {
+ return VerifyRfFreq( verify->Frequency );
+ }
case PHY_TX_DR:
{
if( verify->DatarateParams.UplinkDwellTime == 0 )
@@ -415,10 +483,6 @@ bool RegionAS923Verify( VerifyParams_t* verify, PhyAttribute_t phyAttribute )
{
return AS923_DUTY_CYCLE_ENABLED;
}
- case PHY_NB_JOIN_TRIALS:
- {
- return true;
- }
default:
return false;
}
@@ -439,6 +503,12 @@ void RegionAS923ApplyCFList( ApplyCFListParams_t* applyCFList )
return;
}
+ // Last byte CFListType must be 0 to indicate the CFList contains a list of frequencies
+ if( applyCFList->Payload[15] != 0 )
+ {
+ return;
+ }
+
// Last byte is RFU, don't take it into account
for( uint8_t i = 0, chanIdx = AS923_NUMB_DEFAULT_CHANNELS; chanIdx < AS923_MAX_NB_CHANNELS; i+=3, chanIdx++ )
{
@@ -483,12 +553,12 @@ bool RegionAS923ChanMaskSet( ChanMaskSetParams_t* chanMaskSet )
{
case CHANNELS_MASK:
{
- RegionCommonChanMaskCopy( ChannelsMask, chanMaskSet->ChannelsMaskIn, 1 );
+ RegionCommonChanMaskCopy( NvmCtx.ChannelsMask, chanMaskSet->ChannelsMaskIn, 1 );
break;
}
case CHANNELS_DEFAULT_MASK:
{
- RegionCommonChanMaskCopy( ChannelsDefaultMask, chanMaskSet->ChannelsMaskIn, 1 );
+ RegionCommonChanMaskCopy( NvmCtx.ChannelsDefaultMask, chanMaskSet->ChannelsMaskIn, 1 );
break;
}
default:
@@ -497,76 +567,6 @@ bool RegionAS923ChanMaskSet( ChanMaskSetParams_t* chanMaskSet )
return true;
}
-bool RegionAS923AdrNext( AdrNextParams_t* adrNext, int8_t* drOut, int8_t* txPowOut, uint32_t* adrAckCounter )
-{
- bool adrAckReq = false;
- int8_t datarate = adrNext->Datarate;
- int8_t minTxDatarate = 0;
- int8_t txPower = adrNext->TxPower;
- GetPhyParams_t getPhy;
- PhyParam_t phyParam;
-
- // Get the minimum possible datarate
- getPhy.Attribute = PHY_MIN_TX_DR;
- getPhy.UplinkDwellTime = adrNext->UplinkDwellTime;
- phyParam = RegionAS923GetPhyParam( &getPhy );
- minTxDatarate = phyParam.Value;
-
- // Report back the adr ack counter
- *adrAckCounter = adrNext->AdrAckCounter;
-
- // Apply the minimum possible datarate.
- datarate = MAX( datarate, minTxDatarate );
-
- if( adrNext->AdrEnabled == true )
- {
- if( datarate == minTxDatarate )
- {
- *adrAckCounter = 0;
- adrAckReq = false;
- }
- else
- {
- if( adrNext->AdrAckCounter >= AS923_ADR_ACK_LIMIT )
- {
- adrAckReq = true;
- txPower = AS923_MAX_TX_POWER;
- }
- else
- {
- adrAckReq = false;
- }
- if( adrNext->AdrAckCounter >= ( AS923_ADR_ACK_LIMIT + AS923_ADR_ACK_DELAY ) )
- {
- if( ( adrNext->AdrAckCounter % AS923_ADR_ACK_DELAY ) == 1 )
- {
- // Decrease the datarate
- getPhy.Attribute = PHY_NEXT_LOWER_TX_DR;
- getPhy.Datarate = datarate;
- getPhy.UplinkDwellTime = adrNext->UplinkDwellTime;
- phyParam = RegionAS923GetPhyParam( &getPhy );
- datarate = phyParam.Value;
-
- if( datarate == minTxDatarate )
- {
- // We must set adrAckReq to false as soon as we reach the lowest datarate
- adrAckReq = false;
- if( adrNext->UpdateChanMask == true )
- {
- // Re-enable default channels
- ChannelsMask[0] |= LC( 1 ) + LC( 2 );
- }
- }
- }
- }
- }
- }
-
- *drOut = datarate;
- *txPowOut = txPower;
- return adrAckReq;
-}
-
void RegionAS923ComputeRxWindowParameters( int8_t datarate, uint8_t minRxSymbols, uint32_t rxError, RxConfigParams_t *rxConfigParams )
{
double tSymbol = 0.0;
@@ -584,8 +584,7 @@ void RegionAS923ComputeRxWindowParameters( int8_t datarate, uint8_t minRxSymbols
tSymbol = RegionCommonComputeSymbolTimeLoRa( DataratesAS923[rxConfigParams->Datarate], BandwidthsAS923[rxConfigParams->Datarate] );
}
- RegionCommonComputeRxWindowParameters( tSymbol, minRxSymbols, rxError, RADIO_WAKEUP_TIME, &rxConfigParams->WindowTimeout, &rxConfigParams->WindowOffset );
- rxConfigParams->WindowTimeout = rxConfigParams->WindowTimeout * 3;
+ RegionCommonComputeRxWindowParameters( tSymbol, minRxSymbols, rxError, Radio.GetWakeupTime( ), &rxConfigParams->WindowTimeout, &rxConfigParams->WindowOffset );
}
bool RegionAS923RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate )
@@ -601,14 +600,14 @@ bool RegionAS923RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate )
return false;
}
- if( rxConfig->Window == 0 )
+ if( rxConfig->RxSlot == RX_SLOT_WIN_1 )
{
// Apply window 1 frequency
- frequency = Channels[rxConfig->Channel].Frequency;
+ frequency = NvmCtx.Channels[rxConfig->Channel].Frequency;
// Apply the alternative RX 1 window frequency, if it is available
- if( Channels[rxConfig->Channel].Rx1Frequency != 0 )
+ if( NvmCtx.Channels[rxConfig->Channel].Rx1Frequency != 0 )
{
- frequency = Channels[rxConfig->Channel].Rx1Frequency;
+ frequency = NvmCtx.Channels[rxConfig->Channel].Rx1Frequency;
}
}
@@ -649,7 +648,7 @@ bool RegionAS923TxConfig( TxConfigParams_t* txConfig, int8_t* txPower, TimerTime
{
RadioModems_t modem;
int8_t phyDr = DataratesAS923[txConfig->Datarate];
- int8_t txPowerLimited = LimitTxPower( txConfig->TxPower, Bands[Channels[txConfig->Channel].Band].TxMaxPower, txConfig->Datarate, ChannelsMask );
+ int8_t txPowerLimited = LimitTxPower( txConfig->TxPower, NvmCtx.Bands[NvmCtx.Channels[txConfig->Channel].Band].TxMaxPower, txConfig->Datarate, NvmCtx.ChannelsMask );
uint32_t bandwidth = GetBandwidth( txConfig->Datarate );
int8_t phyTxPower = 0;
@@ -657,17 +656,17 @@ bool RegionAS923TxConfig( TxConfigParams_t* txConfig, int8_t* txPower, TimerTime
phyTxPower = RegionCommonComputeTxPower( txPowerLimited, txConfig->MaxEirp, txConfig->AntennaGain );
// Setup the radio frequency
- Radio.SetChannel( Channels[txConfig->Channel].Frequency );
+ Radio.SetChannel( NvmCtx.Channels[txConfig->Channel].Frequency );
if( txConfig->Datarate == DR_7 )
{ // High Speed FSK channel
modem = MODEM_FSK;
- Radio.SetTxConfig( modem, phyTxPower, 25000, bandwidth, phyDr * 1000, 0, 5, false, true, 0, 0, false, 3000 );
+ Radio.SetTxConfig( modem, phyTxPower, 25000, bandwidth, phyDr * 1000, 0, 5, false, true, 0, 0, false, 4000 );
}
else
{
modem = MODEM_LORA;
- Radio.SetTxConfig( modem, phyTxPower, 0, bandwidth, phyDr, 1, 8, false, true, 0, 0, false, 3000 );
+ Radio.SetTxConfig( modem, phyTxPower, 0, bandwidth, phyDr, 1, 8, false, true, 0, 0, false, 4000 );
}
// Setup maximum payload lenght of the radio driver
@@ -724,7 +723,7 @@ uint8_t RegionAS923LinkAdrReq( LinkAdrReqParams_t* linkAdrReq, int8_t* drOut, in
{
if( linkAdrParams.ChMaskCtrl == 6 )
{
- if( Channels[i].Frequency != 0 )
+ if( NvmCtx.Channels[i].Frequency != 0 )
{
chMask |= 1 << i;
}
@@ -732,7 +731,7 @@ uint8_t RegionAS923LinkAdrReq( LinkAdrReqParams_t* linkAdrReq, int8_t* drOut, in
else
{
if( ( ( chMask & ( 1 << i ) ) != 0 ) &&
- ( Channels[i].Frequency == 0 ) )
+ ( NvmCtx.Channels[i].Frequency == 0 ) )
{// Trying to enable an undefined channel
status &= 0xFE; // Channel mask KO
}
@@ -758,9 +757,10 @@ uint8_t RegionAS923LinkAdrReq( LinkAdrReqParams_t* linkAdrReq, int8_t* drOut, in
linkAdrVerifyParams.ChannelsMask = &chMask;
linkAdrVerifyParams.MinDatarate = ( int8_t )phyParam.Value;
linkAdrVerifyParams.MaxDatarate = AS923_TX_MAX_DATARATE;
- linkAdrVerifyParams.Channels = Channels;
+ linkAdrVerifyParams.Channels = NvmCtx.Channels;
linkAdrVerifyParams.MinTxPower = AS923_MIN_TX_POWER;
linkAdrVerifyParams.MaxTxPower = AS923_MAX_TX_POWER;
+ linkAdrVerifyParams.Version = linkAdrReq->Version;
// Verify the parameters and update, if necessary
status = RegionCommonLinkAdrReqVerifyParams( &linkAdrVerifyParams, &linkAdrParams.Datarate, &linkAdrParams.TxPower, &linkAdrParams.NbRep );
@@ -769,9 +769,9 @@ uint8_t RegionAS923LinkAdrReq( LinkAdrReqParams_t* linkAdrReq, int8_t* drOut, in
if( status == 0x07 )
{
// Set the channels mask to a default value
- memset( ChannelsMask, 0, sizeof( ChannelsMask ) );
+ memset1( ( uint8_t* ) NvmCtx.ChannelsMask, 0, sizeof( NvmCtx.ChannelsMask ) );
// Update the channels mask
- ChannelsMask[0] = chMask;
+ NvmCtx.ChannelsMask[0] = chMask;
}
// Update status variables
@@ -788,7 +788,7 @@ uint8_t RegionAS923RxParamSetupReq( RxParamSetupReqParams_t* rxParamSetupReq )
uint8_t status = 0x07;
// Verify radio frequency
- if( Radio.CheckRfFrequency( rxParamSetupReq->Frequency ) == false )
+ if( VerifyRfFreq( rxParamSetupReq->Frequency ) == false )
{
status &= 0xFE; // Channel frequency KO
}
@@ -872,13 +872,13 @@ uint8_t RegionAS923DlChannelReq( DlChannelReqParams_t* dlChannelReq )
uint8_t status = 0x03;
// Verify if the frequency is supported
- if( VerifyTxFreq( dlChannelReq->Rx1Frequency ) == false )
+ if( VerifyRfFreq( dlChannelReq->Rx1Frequency ) == false )
{
status &= 0xFE;
}
// Verify if an uplink frequency exists
- if( Channels[dlChannelReq->ChannelId].Frequency == 0 )
+ if( NvmCtx.Channels[dlChannelReq->ChannelId].Frequency == 0 )
{
status &= 0xFD;
}
@@ -886,13 +886,13 @@ uint8_t RegionAS923DlChannelReq( DlChannelReqParams_t* dlChannelReq )
// Apply Rx1 frequency, if the status is OK
if( status == 0x03 )
{
- Channels[dlChannelReq->ChannelId].Rx1Frequency = dlChannelReq->Rx1Frequency;
+ NvmCtx.Channels[dlChannelReq->ChannelId].Rx1Frequency = dlChannelReq->Rx1Frequency;
}
return status;
}
-int8_t RegionAS923AlternateDr( AlternateDrParams_t* alternateDr )
+int8_t RegionAS923AlternateDr( int8_t currentDr, AlternateDrType_t type )
{
// Only AS923_DWELL_LIMIT_DATARATE is supported
return AS923_DWELL_LIMIT_DATARATE;
@@ -902,8 +902,8 @@ void RegionAS923CalcBackOff( CalcBackOffParams_t* calcBackOff )
{
RegionCommonCalcBackOffParams_t calcBackOffParams;
- calcBackOffParams.Channels = Channels;
- calcBackOffParams.Bands = Bands;
+ calcBackOffParams.Channels = NvmCtx.Channels;
+ calcBackOffParams.Bands = NvmCtx.Bands;
calcBackOffParams.LastTxIsJoinRequest = calcBackOff->LastTxIsJoinRequest;
calcBackOffParams.Joined = calcBackOff->Joined;
calcBackOffParams.DutyCycleEnabled = calcBackOff->DutyCycleEnabled;
@@ -914,7 +914,7 @@ void RegionAS923CalcBackOff( CalcBackOffParams_t* calcBackOff )
RegionCommonCalcBackOff( &calcBackOffParams );
}
-bool RegionAS923NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff )
+LoRaMacStatus_t RegionAS923NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff )
{
uint8_t channelNext = 0;
uint8_t nbEnabledChannels = 0;
@@ -922,28 +922,29 @@ bool RegionAS923NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel,
uint8_t enabledChannels[AS923_MAX_NB_CHANNELS] = { 0 };
TimerTime_t nextTxDelay = 0;
- if( RegionCommonCountChannels( ChannelsMask, 0, 1 ) == 0 )
+ if( RegionCommonCountChannels( NvmCtx.ChannelsMask, 0, 1 ) == 0 )
{ // Reactivate default channels
- ChannelsMask[0] |= LC( 1 ) + LC( 2 );
+ NvmCtx.ChannelsMask[0] |= LC( 1 ) + LC( 2 );
}
- if( nextChanParams->AggrTimeOff <= TimerGetElapsedTime( nextChanParams->LastAggrTx ) )
+ TimerTime_t elapsed = TimerGetElapsedTime( nextChanParams->LastAggrTx );
+ if( ( nextChanParams->LastAggrTx == 0 ) || ( nextChanParams->AggrTimeOff <= elapsed ) )
{
// Reset Aggregated time off
*aggregatedTimeOff = 0;
// Update bands Time OFF
- nextTxDelay = RegionCommonUpdateBandTimeOff( nextChanParams->Joined, nextChanParams->DutyCycleEnabled, Bands, AS923_MAX_NB_BANDS );
+ nextTxDelay = RegionCommonUpdateBandTimeOff( nextChanParams->Joined, nextChanParams->DutyCycleEnabled, NvmCtx.Bands, AS923_MAX_NB_BANDS );
// Search how many channels are enabled
nbEnabledChannels = CountNbOfEnabledChannels( nextChanParams->Joined, nextChanParams->Datarate,
- ChannelsMask, Channels,
- Bands, enabledChannels, &delayTx );
+ NvmCtx.ChannelsMask, NvmCtx.Channels,
+ NvmCtx.Bands, enabledChannels, &delayTx );
}
else
{
delayTx++;
- nextTxDelay = nextChanParams->AggrTimeOff - TimerGetElapsedTime( nextChanParams->LastAggrTx );
+ nextTxDelay = nextChanParams->AggrTimeOff - elapsed;
}
if( nbEnabledChannels > 0 )
@@ -955,15 +956,15 @@ bool RegionAS923NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel,
// Perform carrier sense for AS923_CARRIER_SENSE_TIME
// If the channel is free, we can stop the LBT mechanism
- if( Radio.IsChannelFree( MODEM_LORA, Channels[channelNext].Frequency, AS923_RSSI_FREE_TH, AS923_CARRIER_SENSE_TIME ) == true )
+ if( Radio.IsChannelFree( MODEM_LORA, NvmCtx.Channels[channelNext].Frequency, AS923_RSSI_FREE_TH, AS923_CARRIER_SENSE_TIME ) == true )
{
// Free channel found
*channel = channelNext;
*time = 0;
- return true;
+ return LORAMAC_STATUS_OK;
}
}
- return false;
+ return LORAMAC_STATUS_NO_FREE_CHANNEL_FOUND;
}
else
{
@@ -971,22 +972,26 @@ bool RegionAS923NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel,
{
// Delay transmission due to AggregatedTimeOff or to a band time off
*time = nextTxDelay;
- return true;
+ return LORAMAC_STATUS_DUTYCYCLE_RESTRICTED;
}
// Datarate not supported by any channel, restore defaults
- ChannelsMask[0] |= LC( 1 ) + LC( 2 );
+ NvmCtx.ChannelsMask[0] |= LC( 1 ) + LC( 2 );
*time = 0;
- return false;
+ return LORAMAC_STATUS_NO_CHANNEL_FOUND;
}
}
LoRaMacStatus_t RegionAS923ChannelAdd( ChannelAddParams_t* channelAdd )
{
- uint8_t band = 0;
bool drInvalid = false;
bool freqInvalid = false;
uint8_t id = channelAdd->ChannelId;
+ if( id < AS923_NUMB_DEFAULT_CHANNELS )
+ {
+ return LORAMAC_STATUS_FREQ_AND_DR_INVALID;
+ }
+
if( id >= AS923_MAX_NB_CHANNELS )
{
return LORAMAC_STATUS_PARAMETER_INVALID;
@@ -1006,30 +1011,10 @@ LoRaMacStatus_t RegionAS923ChannelAdd( ChannelAddParams_t* channelAdd )
drInvalid = true;
}
- // Default channels don't accept all values
- if( id < AS923_NUMB_DEFAULT_CHANNELS )
- {
- // Validate the datarate range for min: must be DR_0
- if( channelAdd->NewChannel->DrRange.Fields.Min > DR_0 )
- {
- drInvalid = true;
- }
- // Validate the datarate range for max: must be DR_5 <= Max <= TX_MAX_DATARATE
- if( RegionCommonValueInRange( channelAdd->NewChannel->DrRange.Fields.Max, DR_5, AS923_TX_MAX_DATARATE ) == false )
- {
- drInvalid = true;
- }
- // We are not allowed to change the frequency
- if( channelAdd->NewChannel->Frequency != Channels[id].Frequency )
- {
- freqInvalid = true;
- }
- }
-
// Check frequency
if( freqInvalid == false )
{
- if( VerifyTxFreq( channelAdd->NewChannel->Frequency ) == false )
+ if( VerifyRfFreq( channelAdd->NewChannel->Frequency ) == false )
{
freqInvalid = true;
}
@@ -1049,12 +1034,72 @@ LoRaMacStatus_t RegionAS923ChannelAdd( ChannelAddParams_t* channelAdd )
return LORAMAC_STATUS_FREQUENCY_INVALID;
}
- memcpy( &(Channels[id]), channelAdd->NewChannel, sizeof( Channels[id] ) );
- Channels[id].Band = band;
- ChannelsMask[0] |= ( 1 << id );
+ memcpy1( ( uint8_t* ) &(NvmCtx.Channels[id]), ( uint8_t* ) channelAdd->NewChannel, sizeof( NvmCtx.Channels[id] ) );
+ NvmCtx.Channels[id].Band = 0;
+ NvmCtx.ChannelsMask[0] |= ( 1 << id );
return LORAMAC_STATUS_OK;
}
+bool RegionAS923ChannelsRemove( ChannelRemoveParams_t* channelRemove )
+{
+ uint8_t id = channelRemove->ChannelId;
+
+ if( id < AS923_NUMB_DEFAULT_CHANNELS )
+ {
+ return false;
+ }
+
+ // Remove the channel from the list of channels
+ NvmCtx.Channels[id] = ( ChannelParams_t ){ 0, 0, { 0 }, 0 };
+
+ return RegionCommonChanDisable( NvmCtx.ChannelsMask, id, AS923_MAX_NB_CHANNELS );
+}
+
+void RegionAS923SetContinuousWave( ContinuousWaveParams_t* continuousWave )
+{
+ int8_t txPowerLimited = LimitTxPower( continuousWave->TxPower, NvmCtx.Bands[NvmCtx.Channels[continuousWave->Channel].Band].TxMaxPower, continuousWave->Datarate, NvmCtx.ChannelsMask );
+ int8_t phyTxPower = 0;
+ uint32_t frequency = NvmCtx.Channels[continuousWave->Channel].Frequency;
+
+ // Calculate physical TX power
+ phyTxPower = RegionCommonComputeTxPower( txPowerLimited, continuousWave->MaxEirp, continuousWave->AntennaGain );
+
+ Radio.SetTxContinuousWave( frequency, phyTxPower, continuousWave->Timeout );
+}
+
+uint8_t RegionAS923ApplyDrOffset( uint8_t downlinkDwellTime, int8_t dr, int8_t drOffset )
+{
+ // Initialize minDr for a downlink dwell time configuration of 0
+ int8_t minDr = DR_0;
+
+ // Update the minDR for a downlink dwell time configuration of 1
+ if( downlinkDwellTime == 1 )
+ {
+ minDr = AS923_DWELL_LIMIT_DATARATE;
+ }
+
+ // Apply offset formula
+ return MIN( DR_5, MAX( minDr, dr - EffectiveRx1DrOffsetAS923[drOffset] ) );
+}
+
+void RegionAS923RxBeaconSetup( RxBeaconSetup_t* rxBeaconSetup, uint8_t* outDr )
+{
+ RegionCommonRxBeaconSetupParams_t regionCommonRxBeaconSetup;
+
+ regionCommonRxBeaconSetup.Datarates = DataratesAS923;
+ regionCommonRxBeaconSetup.Frequency = rxBeaconSetup->Frequency;
+ regionCommonRxBeaconSetup.BeaconSize = AS923_BEACON_SIZE;
+ regionCommonRxBeaconSetup.BeaconDatarate = AS923_BEACON_CHANNEL_DR;
+ regionCommonRxBeaconSetup.BeaconChannelBW = AS923_BEACON_CHANNEL_BW;
+ regionCommonRxBeaconSetup.RxTime = rxBeaconSetup->RxTime;
+ regionCommonRxBeaconSetup.SymbolTimeout = rxBeaconSetup->SymbolTimeout;
+
+ RegionCommonRxBeaconSetup( ®ionCommonRxBeaconSetup );
+
+ // Store downlink datarate
+ *outDr = AS923_BEACON_CHANNEL_DR;
+}
+
LoRaMacStatus_t RegionAS923ChannelManualAdd( ChannelAddParams_t* channelAdd )
{
uint8_t band = 0;
@@ -1099,7 +1144,7 @@ LoRaMacStatus_t RegionAS923ChannelManualAdd( ChannelAddParams_t* channelAdd )
// Check frequency
if( freqInvalid == false )
{
- if( VerifyTxFreq( channelAdd->NewChannel->Frequency ) == false )
+ if( VerifyRfFreq( channelAdd->NewChannel->Frequency ) == false )
{
freqInvalid = true;
}
@@ -1119,70 +1164,8 @@ LoRaMacStatus_t RegionAS923ChannelManualAdd( ChannelAddParams_t* channelAdd )
return LORAMAC_STATUS_FREQUENCY_INVALID;
}
- memcpy( &(Channels[id]), channelAdd->NewChannel, sizeof( Channels[id] ) );
- Channels[id].Band = band;
- ChannelsMask[0] |= ( 1 << id );
+ memcpy( &(NvmCtx.Channels[id]), channelAdd->NewChannel, sizeof( NvmCtx.Channels[id] ) );
+ NvmCtx.Channels[id].Band = band;
+ NvmCtx.ChannelsMask[0] |= ( 1 << id );
return LORAMAC_STATUS_OK;
}
-
-bool RegionAS923ChannelsRemove( ChannelRemoveParams_t* channelRemove )
-{
- uint8_t id = channelRemove->ChannelId;
-
- if( id < AS923_NUMB_DEFAULT_CHANNELS )
- {
- return false;
- }
-
- // Remove the channel from the list of channels
- Channels[id] = ( ChannelParams_t ){ 0, 0, { 0 }, 0 };
-
- return RegionCommonChanDisable( ChannelsMask, id, AS923_MAX_NB_CHANNELS );
-}
-
-void RegionAS923SetContinuousWave( ContinuousWaveParams_t* continuousWave )
-{
- int8_t txPowerLimited = LimitTxPower( continuousWave->TxPower, Bands[Channels[continuousWave->Channel].Band].TxMaxPower, continuousWave->Datarate, ChannelsMask );
- int8_t phyTxPower = 0;
- uint32_t frequency = Channels[continuousWave->Channel].Frequency;
-
- // Calculate physical TX power
- phyTxPower = RegionCommonComputeTxPower( txPowerLimited, continuousWave->MaxEirp, continuousWave->AntennaGain );
-
- Radio.SetTxContinuousWave( frequency, phyTxPower, continuousWave->Timeout );
-}
-
-uint8_t RegionAS923ApplyDrOffset( uint8_t downlinkDwellTime, int8_t dr, int8_t drOffset )
-{
- // Initialize minDr for a downlink dwell time configuration of 0
- int8_t minDr = DR_0;
-
- // Update the minDR for a downlink dwell time configuration of 1
- if( downlinkDwellTime == 1 )
- {
- minDr = AS923_DWELL_LIMIT_DATARATE;
- }
-
- // Apply offset formula
- return MIN( DR_5, MAX( minDr, dr - EffectiveRx1DrOffsetAS923[drOffset] ) );
-}
-
-bool RegionAS923GetChannels( ChannelParams_t** channels, uint32_t *size )
-{
- *channels = Channels;
- *size = sizeof(Channels);
- return true;
-}
-
-bool RegionAS923GetChannelMask( uint16_t** channelmask, uint32_t *size )
-{
- *channelmask = ChannelsMask;
- *size = sizeof(ChannelsMask);
- return true;
-}
-
-bool RegionAS923ForceJoinDataRate( int8_t joinDr, AlternateDrParams_t* alternateDr )
-{
- // Only AS923_DWELL_LIMIT_DATARATE is supported
- return true;
-}
diff --git a/lib/lora/mac/region/RegionAS923.h b/lib/lora/mac/region/RegionAS923.h
index fff368cfbe..9051594dad 100644
--- a/lib/lora/mac/region/RegionAS923.h
+++ b/lib/lora/mac/region/RegionAS923.h
@@ -12,7 +12,7 @@
* \____ \| ___ | (_ _) ___ |/ ___) _ \
* _____) ) ____| | | || |_| ____( (___| | | |
* (______/|_____)_|_|_| \__)_____)\____)_| |_|
- * (C)2013 Semtech
+ * (C)2013-2017 Semtech
*
* ___ _____ _ ___ _ _____ ___ ___ ___ ___
* / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
@@ -28,6 +28,8 @@
*
* \author Daniel Jaeckle ( STACKFORCE )
*
+ * \author Johannes Bruder ( STACKFORCE )
+ *
* \defgroup REGIONAS923 Region AS923
* Implementation according to LoRaWAN Specification v1.0.2.
* \{
@@ -35,6 +37,13 @@
#ifndef __REGION_AS923_H__
#define __REGION_AS923_H__
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include "Region.h"
+
/*!
* LoRaMac maximum number of channels
*/
@@ -58,7 +67,7 @@
/*!
* Maximal datarate that can be used by the node
*/
-#define AS923_TX_MAX_DATARATE DR_6
+#define AS923_TX_MAX_DATARATE DR_7
/*!
* Minimal datarate that can be used by the node
@@ -68,7 +77,7 @@
/*!
* Maximal datarate that can be used by the node
*/
-#define AS923_RX_MAX_DATARATE DR_6
+#define AS923_RX_MAX_DATARATE DR_7
/*!
* Default datarate used by the node
@@ -200,6 +209,44 @@
*/
#define AS923_RX_WND_2_DR DR_2
+/*
+ * CLASS B
+ */
+/*!
+ * Beacon frequency
+ */
+#define AS923_BEACON_CHANNEL_FREQ 923400000
+
+/*!
+ * Payload size of a beacon frame
+ */
+#define AS923_BEACON_SIZE 17
+
+/*!
+ * Size of RFU 1 field
+ */
+#define AS923_RFU1_SIZE 2
+
+/*!
+ * Size of RFU 2 field
+ */
+#define AS923_RFU2_SIZE 0
+
+/*!
+ * Datarate of the beacon channel
+ */
+#define AS923_BEACON_CHANNEL_DR DR_3
+
+/*!
+ * Bandwith of the beacon channel
+ */
+#define AS923_BEACON_CHANNEL_BW 0
+
+/*!
+ * Ping slot channel datarate
+ */
+#define AS923_PING_SLOT_CHANNEL_DR DR_3
+
/*!
* Maximum number of bands
*/
@@ -207,9 +254,9 @@
/*!
* Band 0 definition
- * { DutyCycle, TxMaxPower, LastTxDoneTime, TimeOff }
+ * { DutyCycle, TxMaxPower, LastJoinTxDoneTime, LastTxDoneTime, TimeOff }
*/
-#define AS923_BAND0 { 100, AS923_MAX_TX_POWER, 0, 0 } // 1.0 %
+#define AS923_BAND0 { 100, AS923_MAX_TX_POWER, 0, 0, 0 } // 1.0 %
/*!
* LoRaMac default channel 1
@@ -299,7 +346,16 @@ void RegionAS923SetBandTxDone( SetBandTxDoneParams_t* txDone );
*
* \param [IN] type Sets the initialization type.
*/
-void RegionAS923InitDefaults( InitType_t type );
+void RegionAS923InitDefaults( InitDefaultsParams_t* params );
+
+/*!
+ * \brief Returns a pointer to the internal context and its size.
+ *
+ * \param [OUT] params Pointer to the function parameters.
+ *
+ * \retval Points to a structure where the module store its non-volatile context.
+ */
+void* RegionAS923GetNvmCtx( GetNvmCtxParams_t* params );
/*!
* \brief Verifies a parameter.
@@ -329,21 +385,6 @@ void RegionAS923ApplyCFList( ApplyCFListParams_t* applyCFList );
*/
bool RegionAS923ChanMaskSet( ChanMaskSetParams_t* chanMaskSet );
-/*!
- * \brief Calculates the next datarate to set, when ADR is on or off.
- *
- * \param [IN] adrNext Pointer to the function parameters.
- *
- * \param [OUT] drOut The calculated datarate for the next TX.
- *
- * \param [OUT] txPowOut The TX power for the next TX.
- *
- * \param [OUT] adrAckCounter The calculated ADR acknowledgement counter.
- *
- * \retval Returns true, if an ADR request should be performed.
- */
-bool RegionAS923AdrNext( AdrNextParams_t* adrNext, int8_t* drOut, int8_t* txPowOut, uint32_t* adrAckCounter );
-
/*!
* Computes the Rx window timeout and offset.
*
@@ -433,11 +474,11 @@ uint8_t RegionAS923DlChannelReq( DlChannelReqParams_t* dlChannelReq );
/*!
* \brief Alternates the datarate of the channel for the join request.
*
- * \param [IN] alternateDr Pointer to the function parameters.
+ * \param [IN] currentDr Current datarate.
*
* \retval Datarate to apply.
*/
-int8_t RegionAS923AlternateDr( AlternateDrParams_t* alternateDr );
+int8_t RegionAS923AlternateDr( int8_t currentDr, AlternateDrType_t type );
/*!
* \brief Calculates the back-off time.
@@ -458,7 +499,7 @@ void RegionAS923CalcBackOff( CalcBackOffParams_t* calcBackOff );
*
* \retval Function status [1: OK, 0: Unable to find a channel on the current datarate]
*/
-bool RegionAS923NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff );
+LoRaMacStatus_t RegionAS923NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff );
/*!
* \brief Adds a channel.
@@ -499,12 +540,17 @@ void RegionAS923SetContinuousWave( ContinuousWaveParams_t* continuousWave );
*/
uint8_t RegionAS923ApplyDrOffset( uint8_t downlinkDwellTime, int8_t dr, int8_t drOffset );
-bool RegionAS923GetChannels( ChannelParams_t** channels, uint32_t *size );
-
-bool RegionAS923GetChannelMask( uint16_t** channelmask, uint32_t *size );
-
-bool RegionAS923ForceJoinDataRate( int8_t joinDr, AlternateDrParams_t* alternateDr );
+/*!
+ * \brief Sets the radio into beacon reception mode
+ *
+ * \param [IN] rxBeaconSetup Pointer to the function parameters
+ */
+ void RegionAS923RxBeaconSetup( RxBeaconSetup_t* rxBeaconSetup, uint8_t* outDr );
/*! \} defgroup REGIONAS923 */
+#ifdef __cplusplus
+}
+#endif
+
#endif // __REGION_AS923_H__
diff --git a/lib/lora/mac/region/RegionAU915.c b/lib/lora/mac/region/RegionAU915.c
index e1a63135cb..ed03c38325 100644
--- a/lib/lora/mac/region/RegionAU915.c
+++ b/lib/lora/mac/region/RegionAU915.c
@@ -1,31 +1,35 @@
-/*
- / _____) _ | |
-( (____ _____ ____ _| |_ _____ ____| |__
- \____ \| ___ | (_ _) ___ |/ ___) _ \
- _____) ) ____| | | || |_| ____( (___| | | |
-(______/|_____)_|_|_| \__)_____)\____)_| |_|
- (C)2013 Semtech
- ___ _____ _ ___ _ _____ ___ ___ ___ ___
-/ __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
-\__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
-|___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
-embedded.connectivity.solutions===============
-
-Description: LoRa MAC region AU915 implementation
-
-License: Revised BSD License, see LICENSE.TXT file include in the project
-
-Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jaeckle ( STACKFORCE )
+/*!
+ * \file RegionAU915.c
+ *
+ * \brief Region implementation for AU915
+ *
+ * \copyright Revised BSD License, see section \ref LICENSE.
+ *
+ * \code
+ * ______ _
+ * / _____) _ | |
+ * ( (____ _____ ____ _| |_ _____ ____| |__
+ * \____ \| ___ | (_ _) ___ |/ ___) _ \
+ * _____) ) ____| | | || |_| ____( (___| | | |
+ * (______/|_____)_|_|_| \__)_____)\____)_| |_|
+ * (C)2013-2017 Semtech
+ *
+ * ___ _____ _ ___ _ _____ ___ ___ ___ ___
+ * / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
+ * \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
+ * |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
+ * embedded.connectivity.solutions===============
+ *
+ * \endcode
+ *
+ * \author Miguel Luis ( Semtech )
+ *
+ * \author Gregory Cristian ( Semtech )
+ *
+ * \author Daniel Jaeckle ( STACKFORCE )
*/
-#include
-#include
-#include
-#include
-
-#include "board.h"
-#include "lora/mac/LoRaMac.h"
-#include "esp_attr.h"
+#include
#include "utilities.h"
#include "Region.h"
@@ -35,34 +39,40 @@ Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jae
// Definitions
#define CHANNELS_MASK_SIZE 6
-// Global attributes
-/*!
- * LoRaMAC channels
- */
-static ChannelParams_t Channels[AU915_MAX_NB_CHANNELS];
+// A mask to select only valid 500KHz channels
+#define CHANNELS_MASK_500KHZ_MASK 0x00FF
/*!
- * LoRaMac bands
+ * Region specific context
*/
-static Band_t Bands[AU915_MAX_NB_BANDS] =
+typedef struct sRegionAU915NvmCtx
{
- AU915_BAND0
-};
-
-/*!
- * LoRaMac channels mask
- */
-static uint16_t ChannelsMask[CHANNELS_MASK_SIZE];
-
-/*!
- * LoRaMac channels remaining
- */
-static uint16_t ChannelsMaskRemaining[CHANNELS_MASK_SIZE];
+ /*!
+ * LoRaMAC channels
+ */
+ ChannelParams_t Channels[ AU915_MAX_NB_CHANNELS ];
+ /*!
+ * LoRaMac bands
+ */
+ Band_t Bands[ AU915_MAX_NB_BANDS ];
+ /*!
+ * LoRaMac channels mask
+ */
+ uint16_t ChannelsMask[ CHANNELS_MASK_SIZE ];
+ /*!
+ * LoRaMac channels remaining
+ */
+ uint16_t ChannelsMaskRemaining[CHANNELS_MASK_SIZE];
+ /*!
+ * LoRaMac channels default mask
+ */
+ uint16_t ChannelsDefaultMask[ CHANNELS_MASK_SIZE ];
+}RegionAU915NvmCtx_t;
-/*!
- * LoRaMac channels default mask
+/*
+ * Non-volatile module context.
*/
-static uint16_t ChannelsDefaultMask[CHANNELS_MASK_SIZE];
+static RegionAU915NvmCtx_t NvmCtx;
// Static functions
static int8_t GetNextLowerTxDr( int8_t dr, int8_t minDr )
@@ -73,6 +83,10 @@ static int8_t GetNextLowerTxDr( int8_t dr, int8_t minDr )
{
nextLowerDr = minDr;
}
+ else if( dr == DR_8 )
+ { // DR_7 is not allowed
+ nextLowerDr = DR_6;
+ }
else
{
nextLowerDr = dr - 1;
@@ -104,6 +118,31 @@ static int8_t LimitTxPower( int8_t txPower, int8_t maxBandTxPower, int8_t datara
return txPowerResult;
}
+static bool VerifyRfFreq( uint32_t freq )
+{
+ // Check radio driver support
+ if( Radio.CheckRfFrequency( freq ) == false )
+ {
+ return false;
+ }
+
+ // Rx frequencies
+ if( ( freq < AU915_FIRST_RX1_CHANNEL ) ||
+ ( freq > AU915_LAST_RX1_CHANNEL ) ||
+ ( ( ( freq - ( uint32_t ) AU915_FIRST_RX1_CHANNEL ) % ( uint32_t ) AU915_STEPWIDTH_RX1_CHANNEL ) != 0 ) )
+ {
+ return false;
+ }
+
+ // Tx frequencies for 125kHz
+ // Also includes the range for 500kHz channels
+ if( ( freq < 915200000 ) || ( freq > 927800000 ) )
+ {
+ return false;
+ }
+ return true;
+}
+
static uint8_t CountNbOfEnabledChannels( uint8_t datarate, uint16_t* channelsMask, ChannelParams_t* channels, Band_t* bands, uint8_t* enabledChannels, uint8_t* delayTx )
{
uint8_t nbEnabledChannels = 0;
@@ -146,12 +185,26 @@ PhyParam_t RegionAU915GetPhyParam( GetPhyParams_t* getPhy )
{
case PHY_MIN_RX_DR:
{
- phyParam.Value = AU915_RX_MIN_DATARATE;
+ if( getPhy->DownlinkDwellTime == 0)
+ {
+ phyParam.Value = AU915_RX_MIN_DATARATE;
+ }
+ else
+ {
+ phyParam.Value = AU915_DWELL_LIMIT_DATARATE;
+ }
break;
}
case PHY_MIN_TX_DR:
{
- phyParam.Value = AU915_TX_MIN_DATARATE;
+ if( getPhy->UplinkDwellTime == 0)
+ {
+ phyParam.Value = AU915_TX_MIN_DATARATE;
+ }
+ else
+ {
+ phyParam.Value = AU915_DWELL_LIMIT_DATARATE;
+ }
break;
}
case PHY_DEF_TX_DR:
@@ -161,7 +214,19 @@ PhyParam_t RegionAU915GetPhyParam( GetPhyParams_t* getPhy )
}
case PHY_NEXT_LOWER_TX_DR:
{
- phyParam.Value = GetNextLowerTxDr( getPhy->Datarate, AU915_TX_MIN_DATARATE );
+ if( getPhy->UplinkDwellTime == 0)
+ {
+ phyParam.Value = GetNextLowerTxDr( getPhy->Datarate, AU915_TX_MIN_DATARATE );
+ }
+ else
+ {
+ phyParam.Value = GetNextLowerTxDr( getPhy->Datarate, AU915_DWELL_LIMIT_DATARATE );
+ }
+ break;
+ }
+ case PHY_MAX_TX_POWER:
+ {
+ phyParam.Value = AU915_MAX_TX_POWER;
break;
}
case PHY_DEF_TX_POWER:
@@ -169,14 +234,38 @@ PhyParam_t RegionAU915GetPhyParam( GetPhyParams_t* getPhy )
phyParam.Value = AU915_DEFAULT_TX_POWER;
break;
}
+ case PHY_DEF_ADR_ACK_LIMIT:
+ {
+ phyParam.Value = AU915_ADR_ACK_LIMIT;
+ break;
+ }
+ case PHY_DEF_ADR_ACK_DELAY:
+ {
+ phyParam.Value = AU915_ADR_ACK_DELAY;
+ break;
+ }
case PHY_MAX_PAYLOAD:
{
- phyParam.Value = MaxPayloadOfDatarateAU915[getPhy->Datarate];
+ if( getPhy->UplinkDwellTime == 0 )
+ {
+ phyParam.Value = MaxPayloadOfDatarateDwell0AU915[getPhy->Datarate];
+ }
+ else
+ {
+ phyParam.Value = MaxPayloadOfDatarateDwell1AU915[getPhy->Datarate];
+ }
break;
}
case PHY_MAX_PAYLOAD_REPEATER:
{
- phyParam.Value = MaxPayloadOfDatarateRepeaterAU915[getPhy->Datarate];
+ if( getPhy->UplinkDwellTime == 0)
+ {
+ phyParam.Value = MaxPayloadOfDatarateRepeaterDwell0AU915[getPhy->Datarate];
+ }
+ else
+ {
+ phyParam.Value = MaxPayloadOfDatarateRepeaterDwell1AU915[getPhy->Datarate];
+ }
break;
}
case PHY_DUTY_CYCLE:
@@ -236,12 +325,12 @@ PhyParam_t RegionAU915GetPhyParam( GetPhyParams_t* getPhy )
}
case PHY_CHANNELS_MASK:
{
- phyParam.ChannelsMask = ChannelsMask;
+ phyParam.ChannelsMask = NvmCtx.ChannelsMask;
break;
}
case PHY_CHANNELS_DEFAULT_MASK:
{
- phyParam.ChannelsMask = ChannelsDefaultMask;
+ phyParam.ChannelsMask = NvmCtx.ChannelsDefaultMask;
break;
}
case PHY_MAX_NB_CHANNELS:
@@ -251,13 +340,17 @@ PhyParam_t RegionAU915GetPhyParam( GetPhyParams_t* getPhy )
}
case PHY_CHANNELS:
{
- phyParam.Channels = Channels;
+ phyParam.Channels = NvmCtx.Channels;
break;
}
case PHY_DEF_UPLINK_DWELL_TIME:
+ {
+ phyParam.Value = AU915_DEFAULT_UPLINK_DWELL_TIME;
+ break;
+ }
case PHY_DEF_DOWNLINK_DWELL_TIME:
{
- phyParam.Value = 0;
+ phyParam.Value = AU915_DEFAULT_DOWNLINK_DWELL_TIME;
break;
}
case PHY_DEF_MAX_EIRP:
@@ -270,10 +363,31 @@ PhyParam_t RegionAU915GetPhyParam( GetPhyParams_t* getPhy )
phyParam.fValue = AU915_DEFAULT_ANTENNA_GAIN;
break;
}
- case PHY_NB_JOIN_TRIALS:
- case PHY_DEF_NB_JOIN_TRIALS:
+ case PHY_BEACON_FORMAT:
+ {
+ phyParam.BeaconFormat.BeaconSize = AU915_BEACON_SIZE;
+ phyParam.BeaconFormat.Rfu1Size = AU915_RFU1_SIZE;
+ phyParam.BeaconFormat.Rfu2Size = AU915_RFU2_SIZE;
+ break;
+ }
+ case PHY_BEACON_CHANNEL_DR:
+ {
+ phyParam.Value = AU915_BEACON_CHANNEL_DR;
+ break;
+ }
+ case PHY_BEACON_CHANNEL_STEPWIDTH:
+ {
+ phyParam.Value = AU915_BEACON_CHANNEL_STEPWIDTH;
+ break;
+ }
+ case PHY_BEACON_NB_CHANNELS:
{
- phyParam.Value = 2;
+ phyParam.Value = AU915_BEACON_NB_CHANNELS;
+ break;
+ }
+ case PHY_PING_SLOT_CHANNEL_DR:
+ {
+ phyParam.Value = AU915_PING_SLOT_CHANNEL_DR;
break;
}
default:
@@ -285,56 +399,72 @@ PhyParam_t RegionAU915GetPhyParam( GetPhyParams_t* getPhy )
return phyParam;
}
-IRAM_ATTR void RegionAU915SetBandTxDone( SetBandTxDoneParams_t* txDone )
+void RegionAU915SetBandTxDone( SetBandTxDoneParams_t* txDone )
{
- RegionCommonSetBandTxDone( txDone->Joined, &Bands[Channels[txDone->Channel].Band], txDone->LastTxDoneTime );
+ RegionCommonSetBandTxDone( txDone->Joined, &NvmCtx.Bands[NvmCtx.Channels[txDone->Channel].Band], txDone->LastTxDoneTime );
}
-void RegionAU915InitDefaults( InitType_t type )
+void RegionAU915InitDefaults( InitDefaultsParams_t* params )
{
- switch( type )
+ Band_t bands[AU915_MAX_NB_BANDS] =
+ {
+ AU915_BAND0
+ };
+
+ switch( params->Type )
{
case INIT_TYPE_INIT:
{
+ // Initialize bands
+ memcpy1( ( uint8_t* )NvmCtx.Bands, ( uint8_t* )bands, sizeof( Band_t ) * AU915_MAX_NB_BANDS );
+
// Channels
// 125 kHz channels
for( uint8_t i = 0; i < AU915_MAX_NB_CHANNELS - 8; i++ )
{
- Channels[i].Frequency = 915200000 + i * 200000;
- Channels[i].DrRange.Value = ( DR_5 << 4 ) | DR_0;
- Channels[i].Band = 0;
+ NvmCtx.Channels[i].Frequency = 915200000 + i * 200000;
+ NvmCtx.Channels[i].DrRange.Value = ( DR_5 << 4 ) | DR_0;
+ NvmCtx.Channels[i].Band = 0;
}
// 500 kHz channels
for( uint8_t i = AU915_MAX_NB_CHANNELS - 8; i < AU915_MAX_NB_CHANNELS; i++ )
{
- Channels[i].Frequency = 915900000 + ( i - ( AU915_MAX_NB_CHANNELS - 8 ) ) * 1600000;
- Channels[i].DrRange.Value = ( DR_6 << 4 ) | DR_6;
- Channels[i].Band = 0;
+ NvmCtx.Channels[i].Frequency = 915900000 + ( i - ( AU915_MAX_NB_CHANNELS - 8 ) ) * 1600000;
+ NvmCtx.Channels[i].DrRange.Value = ( DR_6 << 4 ) | DR_6;
+ NvmCtx.Channels[i].Band = 0;
}
// Initialize channels default mask
- ChannelsDefaultMask[0] = 0xFFFF;
- ChannelsDefaultMask[1] = 0xFFFF;
- ChannelsDefaultMask[2] = 0xFFFF;
- ChannelsDefaultMask[3] = 0xFFFF;
- ChannelsDefaultMask[4] = 0x00FF;
- ChannelsDefaultMask[5] = 0x0000;
+ NvmCtx.ChannelsDefaultMask[0] = 0xFFFF;
+ NvmCtx.ChannelsDefaultMask[1] = 0xFFFF;
+ NvmCtx.ChannelsDefaultMask[2] = 0xFFFF;
+ NvmCtx.ChannelsDefaultMask[3] = 0xFFFF;
+ NvmCtx.ChannelsDefaultMask[4] = 0x00FF;
+ NvmCtx.ChannelsDefaultMask[5] = 0x0000;
// Copy channels default mask
- RegionCommonChanMaskCopy( ChannelsMask, ChannelsDefaultMask, 6 );
+ RegionCommonChanMaskCopy( NvmCtx.ChannelsMask, NvmCtx.ChannelsDefaultMask, 6 );
// Copy into channels mask remaining
- RegionCommonChanMaskCopy( ChannelsMaskRemaining, ChannelsMask, 6 );
+ RegionCommonChanMaskCopy( NvmCtx.ChannelsMaskRemaining, NvmCtx.ChannelsMask, 6 );
break;
}
- case INIT_TYPE_RESTORE:
+ case INIT_TYPE_RESTORE_CTX:
+ {
+ if( params->NvmCtx != 0 )
+ {
+ memcpy1( (uint8_t*) &NvmCtx, (uint8_t*) params->NvmCtx, sizeof( NvmCtx ) );
+ }
+ break;
+ }
+ case INIT_TYPE_RESTORE_DEFAULT_CHANNELS:
{
// Copy channels default mask
- RegionCommonChanMaskCopy( ChannelsMask, ChannelsDefaultMask, 6 );
+ RegionCommonChanMaskCopy( NvmCtx.ChannelsMask, NvmCtx.ChannelsDefaultMask, 6 );
for( uint8_t i = 0; i < 6; i++ )
{ // Copy-And the channels mask
- ChannelsMaskRemaining[i] &= ChannelsMask[i];
+ NvmCtx.ChannelsMaskRemaining[i] &= NvmCtx.ChannelsMask[i];
}
break;
}
@@ -345,18 +475,42 @@ void RegionAU915InitDefaults( InitType_t type )
}
}
+void* RegionAU915GetNvmCtx( GetNvmCtxParams_t* params )
+{
+ params->nvmCtxSize = sizeof( RegionAU915NvmCtx_t );
+ return &NvmCtx;
+}
+
bool RegionAU915Verify( VerifyParams_t* verify, PhyAttribute_t phyAttribute )
{
switch( phyAttribute )
{
+ case PHY_FREQUENCY:
+ {
+ return VerifyRfFreq( verify->Frequency );
+ }
case PHY_TX_DR:
case PHY_DEF_TX_DR:
{
- return RegionCommonValueInRange( verify->DatarateParams.Datarate, AU915_TX_MIN_DATARATE, AU915_TX_MAX_DATARATE );
+ if( verify->DatarateParams.UplinkDwellTime == 0 )
+ {
+ return RegionCommonValueInRange( verify->DatarateParams.Datarate, AU915_TX_MIN_DATARATE, AU915_TX_MAX_DATARATE );
+ }
+ else
+ {
+ return RegionCommonValueInRange( verify->DatarateParams.Datarate, AU915_DWELL_LIMIT_DATARATE, AU915_TX_MAX_DATARATE );
+ }
}
case PHY_RX_DR:
{
- return RegionCommonValueInRange( verify->DatarateParams.Datarate, AU915_RX_MIN_DATARATE, AU915_RX_MAX_DATARATE );
+ if( verify->DatarateParams.UplinkDwellTime == 0 )
+ {
+ return RegionCommonValueInRange( verify->DatarateParams.Datarate, AU915_RX_MIN_DATARATE, AU915_RX_MAX_DATARATE );
+ }
+ else
+ {
+ return RegionCommonValueInRange( verify->DatarateParams.Datarate, AU915_DWELL_LIMIT_DATARATE, AU915_RX_MAX_DATARATE );
+ }
}
case PHY_DEF_TX_POWER:
case PHY_TX_POWER:
@@ -368,53 +522,59 @@ bool RegionAU915Verify( VerifyParams_t* verify, PhyAttribute_t phyAttribute )
{
return AU915_DUTY_CYCLE_ENABLED;
}
- case PHY_NB_JOIN_TRIALS:
- {
- if( verify->NbJoinTrials < 2 )
- {
- return false;
- }
- break;
- }
default:
return false;
}
- return true;
}
void RegionAU915ApplyCFList( ApplyCFListParams_t* applyCFList )
{
- return;
-}
+ // Size of the optional CF list must be 16 byte
+ if( applyCFList->Size != 16 )
+ {
+ return;
+ }
-bool RegionAU915ChanMaskSet( ChanMaskSetParams_t* chanMaskSet )
-{
- uint8_t nbChannels = RegionCommonCountChannels( chanMaskSet->ChannelsMaskIn, 0, 4 );
+ // Last byte CFListType must be 0x01 to indicate the CFList contains a series of ChMask fields
+ if( applyCFList->Payload[15] != 0x01 )
+ {
+ return;
+ }
- // Check the number of active channels
- // According to ACMA regulation, we require at least 20 125KHz channels, if
- // the node shall utilize 125KHz channels.
- if( ( nbChannels < 20 ) &&
- ( nbChannels > 0 ) )
+ // ChMask0 - ChMask4 must be set (every ChMask has 16 bit)
+ for( uint8_t chMaskItr = 0, cntPayload = 0; chMaskItr <= 4; chMaskItr++, cntPayload+=2 )
{
- return false;
+ NvmCtx.ChannelsMask[chMaskItr] = (uint16_t) (0x00FF & applyCFList->Payload[cntPayload]);
+ NvmCtx.ChannelsMask[chMaskItr] |= (uint16_t) (applyCFList->Payload[cntPayload+1] << 8);
+ if( chMaskItr == 4 )
+ {
+ NvmCtx.ChannelsMask[chMaskItr] = NvmCtx.ChannelsMask[chMaskItr] & CHANNELS_MASK_500KHZ_MASK;
+ }
+ // Set the channel mask to the remaining
+ NvmCtx.ChannelsMaskRemaining[chMaskItr] &= NvmCtx.ChannelsMask[chMaskItr];
}
+}
+bool RegionAU915ChanMaskSet( ChanMaskSetParams_t* chanMaskSet )
+{
switch( chanMaskSet->ChannelsMaskType )
{
case CHANNELS_MASK:
{
- RegionCommonChanMaskCopy( ChannelsMask, chanMaskSet->ChannelsMaskIn, 6 );
+ RegionCommonChanMaskCopy( NvmCtx.ChannelsMask, chanMaskSet->ChannelsMaskIn, 6 );
+
+ NvmCtx.ChannelsDefaultMask[4] = NvmCtx.ChannelsDefaultMask[4] & CHANNELS_MASK_500KHZ_MASK;
+ NvmCtx.ChannelsDefaultMask[5] = 0x0000;
for( uint8_t i = 0; i < 6; i++ )
{ // Copy-And the channels mask
- ChannelsMaskRemaining[i] &= ChannelsMask[i];
+ NvmCtx.ChannelsMaskRemaining[i] &= NvmCtx.ChannelsMask[i];
}
break;
}
case CHANNELS_DEFAULT_MASK:
{
- RegionCommonChanMaskCopy( ChannelsDefaultMask, chanMaskSet->ChannelsMaskIn, 6 );
+ RegionCommonChanMaskCopy( NvmCtx.ChannelsDefaultMask, chanMaskSet->ChannelsMaskIn, 6 );
break;
}
default:
@@ -423,83 +583,17 @@ bool RegionAU915ChanMaskSet( ChanMaskSetParams_t* chanMaskSet )
return true;
}
-bool RegionAU915AdrNext( AdrNextParams_t* adrNext, int8_t* drOut, int8_t* txPowOut, uint32_t* adrAckCounter )
-{
- bool adrAckReq = false;
- int8_t datarate = adrNext->Datarate;
- int8_t txPower = adrNext->TxPower;
- GetPhyParams_t getPhy;
- PhyParam_t phyParam;
-
- // Report back the adr ack counter
- *adrAckCounter = adrNext->AdrAckCounter;
-
- if( adrNext->AdrEnabled == true )
- {
- if( datarate == AU915_TX_MIN_DATARATE )
- {
- *adrAckCounter = 0;
- adrAckReq = false;
- }
- else
- {
- if( adrNext->AdrAckCounter >= AU915_ADR_ACK_LIMIT )
- {
- adrAckReq = true;
- txPower = AU915_MAX_TX_POWER;
- }
- else
- {
- adrAckReq = false;
- }
- if( adrNext->AdrAckCounter >= ( AU915_ADR_ACK_LIMIT + AU915_ADR_ACK_DELAY ) )
- {
- if( ( adrNext->AdrAckCounter % AU915_ADR_ACK_DELAY ) == 1 )
- {
- // Decrease the datarate
- getPhy.Attribute = PHY_NEXT_LOWER_TX_DR;
- getPhy.Datarate = datarate;
- getPhy.UplinkDwellTime = adrNext->UplinkDwellTime;
- phyParam = RegionAU915GetPhyParam( &getPhy );
- datarate = phyParam.Value;
-
- if( datarate == AU915_TX_MIN_DATARATE )
- {
- // We must set adrAckReq to false as soon as we reach the lowest datarate
- adrAckReq = false;
- if( adrNext->UpdateChanMask == true )
- {
- // Re-enable default channels
- ChannelsMask[0] = 0xFFFF;
- ChannelsMask[1] = 0xFFFF;
- ChannelsMask[2] = 0xFFFF;
- ChannelsMask[3] = 0xFFFF;
- ChannelsMask[4] = 0x00FF;
- ChannelsMask[5] = 0x0000;
- }
- }
- }
- }
- }
- }
-
- *drOut = datarate;
- *txPowOut = txPower;
- return adrAckReq;
-}
-
void RegionAU915ComputeRxWindowParameters( int8_t datarate, uint8_t minRxSymbols, uint32_t rxError, RxConfigParams_t *rxConfigParams )
-{
+{printf("RegionAU915ComputeRxWindowParameters\n");
double tSymbol = 0.0;
// Get the datarate, perform a boundary check
rxConfigParams->Datarate = MIN( datarate, AU915_RX_MAX_DATARATE );
rxConfigParams->Bandwidth = GetBandwidth( rxConfigParams->Datarate );
-
+printf("DR: %d, BW: %d\n", rxConfigParams->Datarate, rxConfigParams->Bandwidth);
tSymbol = RegionCommonComputeSymbolTimeLoRa( DataratesAU915[rxConfigParams->Datarate], BandwidthsAU915[rxConfigParams->Datarate] );
-
- RegionCommonComputeRxWindowParameters( tSymbol, minRxSymbols, rxError, RADIO_WAKEUP_TIME, &rxConfigParams->WindowTimeout, &rxConfigParams->WindowOffset );
- rxConfigParams->WindowTimeout = rxConfigParams->WindowTimeout * 3;
+printf("tSymbol: %f\n", tSymbol);
+ RegionCommonComputeRxWindowParameters( tSymbol, minRxSymbols, rxError, Radio.GetWakeupTime( ), &rxConfigParams->WindowTimeout, &rxConfigParams->WindowOffset );
}
bool RegionAU915RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate )
@@ -514,7 +608,7 @@ bool RegionAU915RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate )
return false;
}
- if( rxConfig->Window == 0 )
+ if( rxConfig->RxSlot == RX_SLOT_WIN_1 )
{
// Apply window 1 frequency
frequency = AU915_FIRST_RX1_CHANNEL + ( rxConfig->Channel % 8 ) * AU915_STEPWIDTH_RX1_CHANNEL;
@@ -530,11 +624,11 @@ bool RegionAU915RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate )
if( rxConfig->RepeaterSupport == true )
{
- maxPayload = MaxPayloadOfDatarateRepeaterAU915[dr];
+ maxPayload = MaxPayloadOfDatarateRepeaterDwell0AU915[dr];
}
else
{
- maxPayload = MaxPayloadOfDatarateAU915[dr];
+ maxPayload = MaxPayloadOfDatarateDwell0AU915[dr];
}
Radio.SetMaxPayloadLength( MODEM_LORA, maxPayload + LORA_MAC_FRMPAYLOAD_OVERHEAD );
@@ -545,7 +639,7 @@ bool RegionAU915RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate )
bool RegionAU915TxConfig( TxConfigParams_t* txConfig, int8_t* txPower, TimerTime_t* txTimeOnAir )
{
int8_t phyDr = DataratesAU915[txConfig->Datarate];
- int8_t txPowerLimited = LimitTxPower( txConfig->TxPower, Bands[Channels[txConfig->Channel].Band].TxMaxPower, txConfig->Datarate, ChannelsMask );
+ int8_t txPowerLimited = LimitTxPower( txConfig->TxPower, NvmCtx.Bands[NvmCtx.Channels[txConfig->Channel].Band].TxMaxPower, txConfig->Datarate, NvmCtx.ChannelsMask );
uint32_t bandwidth = GetBandwidth( txConfig->Datarate );
int8_t phyTxPower = 0;
@@ -553,9 +647,9 @@ bool RegionAU915TxConfig( TxConfigParams_t* txConfig, int8_t* txPower, TimerTime
phyTxPower = RegionCommonComputeTxPower( txPowerLimited, txConfig->MaxEirp, txConfig->AntennaGain );
// Setup the radio frequency
- Radio.SetChannel( Channels[txConfig->Channel].Frequency );
+ Radio.SetChannel( NvmCtx.Channels[txConfig->Channel].Frequency );
- Radio.SetTxConfig( MODEM_LORA, phyTxPower, 0, bandwidth, phyDr, 1, 8, false, true, 0, 0, false, 3000 );
+ Radio.SetTxConfig( MODEM_LORA, phyTxPower, 0, bandwidth, phyDr, 1, 8, false, true, 0, 0, false, 4000 );
// Setup maximum payload lenght of the radio driver
Radio.SetMaxPayloadLength( MODEM_LORA, txConfig->PktLen );
@@ -578,7 +672,7 @@ uint8_t RegionAU915LinkAdrReq( LinkAdrReqParams_t* linkAdrReq, int8_t* drOut, in
RegionCommonLinkAdrReqVerifyParams_t linkAdrVerifyParams;
// Initialize local copy of channels mask
- RegionCommonChanMaskCopy( channelsMask, ChannelsMask, 6 );
+ RegionCommonChanMaskCopy( channelsMask, NvmCtx.ChannelsMask, 6 );
while( bytesProcessed < linkAdrReq->PayloadSize )
{
@@ -601,7 +695,7 @@ uint8_t RegionAU915LinkAdrReq( LinkAdrReqParams_t* linkAdrReq, int8_t* drOut, in
channelsMask[2] = 0xFFFF;
channelsMask[3] = 0xFFFF;
// Apply chMask to channels 64 to 71
- channelsMask[4] = linkAdrParams.ChMask;
+ channelsMask[4] = linkAdrParams.ChMask & CHANNELS_MASK_500KHZ_MASK;
}
else if( linkAdrParams.ChMaskCtrl == 7 )
{
@@ -611,12 +705,61 @@ uint8_t RegionAU915LinkAdrReq( LinkAdrReqParams_t* linkAdrReq, int8_t* drOut, in
channelsMask[2] = 0x0000;
channelsMask[3] = 0x0000;
// Apply chMask to channels 64 to 71
- channelsMask[4] = linkAdrParams.ChMask;
+ channelsMask[4] = linkAdrParams.ChMask & CHANNELS_MASK_500KHZ_MASK;
}
else if( linkAdrParams.ChMaskCtrl == 5 )
{
- // RFU
- status &= 0xFE; // Channel mask KO
+ // Start value for comparision
+ uint8_t bitMask = 1;
+
+ // cntChannelMask for channelsMask[0] until channelsMask[3]
+ uint8_t cntChannelMask = 0;
+
+ // i will be 1, 2, 3, ..., 7
+ for( uint8_t i = 0; i <= 7; i++ )
+ {
+ // 8 MSBs of ChMask are RFU
+ // Checking if the ChMask is set, then true
+ if( ( ( linkAdrParams.ChMask & 0x00FF ) & ( bitMask << i ) ) != 0 )
+ {
+ if( ( i % 2 ) == 0 )
+ {
+ // Enable a bank of 8 125kHz channels, 8 LSBs
+ channelsMask[cntChannelMask] |= 0x00FF;
+ // Enable the corresponding 500kHz channel
+ channelsMask[4] |= ( bitMask << i );
+ }
+ else
+ {
+ // Enable a bank of 8 125kHz channels, 8 MSBs
+ channelsMask[cntChannelMask] |= 0xFF00;
+ // Enable the corresponding 500kHz channel
+ channelsMask[4] |= ( bitMask << i );
+ // cntChannelMask increment for uneven i
+ cntChannelMask++;
+ }
+ }
+ // ChMask is not set
+ else
+ {
+ if( ( i % 2 ) == 0 )
+ {
+ // Disable a bank of 8 125kHz channels, 8 LSBs
+ channelsMask[cntChannelMask] &= 0xFF00;
+ // Disable the corresponding 500kHz channel
+ channelsMask[4] &= ~( bitMask << i );
+ }
+ else
+ {
+ // Enable a bank of 8 125kHz channels, 8 MSBs
+ channelsMask[cntChannelMask] &= 0x00FF;
+ // Disable the corresponding 500kHz channel
+ channelsMask[4] &= ~( bitMask << i );
+ // cntChannelMask increment for uneven i
+ cntChannelMask++;
+ }
+ }
+ }
}
else
{
@@ -647,9 +790,10 @@ uint8_t RegionAU915LinkAdrReq( LinkAdrReqParams_t* linkAdrReq, int8_t* drOut, in
linkAdrVerifyParams.ChannelsMask = channelsMask;
linkAdrVerifyParams.MinDatarate = ( int8_t )phyParam.Value;
linkAdrVerifyParams.MaxDatarate = AU915_TX_MAX_DATARATE;
- linkAdrVerifyParams.Channels = Channels;
+ linkAdrVerifyParams.Channels = NvmCtx.Channels;
linkAdrVerifyParams.MinTxPower = AU915_MIN_TX_POWER;
linkAdrVerifyParams.MaxTxPower = AU915_MAX_TX_POWER;
+ linkAdrVerifyParams.Version = linkAdrReq->Version;
// Verify the parameters and update, if necessary
status = RegionCommonLinkAdrReqVerifyParams( &linkAdrVerifyParams, &linkAdrParams.Datarate, &linkAdrParams.TxPower, &linkAdrParams.NbRep );
@@ -658,14 +802,14 @@ uint8_t RegionAU915LinkAdrReq( LinkAdrReqParams_t* linkAdrReq, int8_t* drOut, in
if( status == 0x07 )
{
// Copy Mask
- RegionCommonChanMaskCopy( ChannelsMask, channelsMask, 6 );
-
- ChannelsMaskRemaining[0] &= ChannelsMask[0];
- ChannelsMaskRemaining[1] &= ChannelsMask[1];
- ChannelsMaskRemaining[2] &= ChannelsMask[2];
- ChannelsMaskRemaining[3] &= ChannelsMask[3];
- ChannelsMaskRemaining[4] = ChannelsMask[4];
- ChannelsMaskRemaining[5] = ChannelsMask[5];
+ RegionCommonChanMaskCopy( NvmCtx.ChannelsMask, channelsMask, 6 );
+
+ NvmCtx.ChannelsMaskRemaining[0] &= NvmCtx.ChannelsMask[0];
+ NvmCtx.ChannelsMaskRemaining[1] &= NvmCtx.ChannelsMask[1];
+ NvmCtx.ChannelsMaskRemaining[2] &= NvmCtx.ChannelsMask[2];
+ NvmCtx.ChannelsMaskRemaining[3] &= NvmCtx.ChannelsMask[3];
+ NvmCtx.ChannelsMaskRemaining[4] = NvmCtx.ChannelsMask[4];
+ NvmCtx.ChannelsMaskRemaining[5] = NvmCtx.ChannelsMask[5];
}
// Update status variables
@@ -680,13 +824,9 @@ uint8_t RegionAU915LinkAdrReq( LinkAdrReqParams_t* linkAdrReq, int8_t* drOut, in
uint8_t RegionAU915RxParamSetupReq( RxParamSetupReqParams_t* rxParamSetupReq )
{
uint8_t status = 0x07;
- uint32_t freq = rxParamSetupReq->Frequency;
// Verify radio frequency
- if( ( Radio.CheckRfFrequency( freq ) == false ) ||
- ( freq < AU915_FIRST_RX1_CHANNEL ) ||
- ( freq > AU915_LAST_RX1_CHANNEL ) ||
- ( ( ( freq - ( uint32_t ) AU915_FIRST_RX1_CHANNEL ) % ( uint32_t ) AU915_STEPWIDTH_RX1_CHANNEL ) != 0 ) )
+ if( VerifyRfFreq( rxParamSetupReq->Frequency ) == false )
{
status &= 0xFE; // Channel frequency KO
}
@@ -719,7 +859,8 @@ uint8_t RegionAU915NewChannelReq( NewChannelReqParams_t* newChannelReq )
int8_t RegionAU915TxParamSetupReq( TxParamSetupReqParams_t* txParamSetupReq )
{
- return -1;
+ // Accept the request
+ return 0;
}
uint8_t RegionAU915DlChannelReq( DlChannelReqParams_t* dlChannelReq )
@@ -727,30 +868,31 @@ uint8_t RegionAU915DlChannelReq( DlChannelReqParams_t* dlChannelReq )
return 0;
}
-int8_t RegionAU915AlternateDr( AlternateDrParams_t* alternateDr )
+int8_t RegionAU915AlternateDr( int8_t currentDr, AlternateDrType_t type )
{
- int8_t datarate = 0;
+ static int8_t trialsCount = 0;
// Re-enable 500 kHz default channels
- ChannelsMask[4] = 0x00FF;
+ NvmCtx.ChannelsMask[4] = CHANNELS_MASK_500KHZ_MASK;
- if( ( alternateDr->NbTrials & 0x01 ) == 0x01 )
+ if( ( trialsCount & 0x01 ) == 0x01 )
{
- datarate = DR_6;
+ currentDr = DR_6;
}
else
{
- datarate = DR_0;
+ currentDr = DR_2;
}
- return datarate;
+ trialsCount++;
+ return currentDr;
}
void RegionAU915CalcBackOff( CalcBackOffParams_t* calcBackOff )
{
RegionCommonCalcBackOffParams_t calcBackOffParams;
- calcBackOffParams.Channels = Channels;
- calcBackOffParams.Bands = Bands;
+ calcBackOffParams.Channels = NvmCtx.Channels;
+ calcBackOffParams.Bands = NvmCtx.Bands;
calcBackOffParams.LastTxIsJoinRequest = calcBackOff->LastTxIsJoinRequest;
calcBackOffParams.Joined = calcBackOff->Joined;
calcBackOffParams.DutyCycleEnabled = calcBackOff->DutyCycleEnabled;
@@ -761,7 +903,7 @@ void RegionAU915CalcBackOff( CalcBackOffParams_t* calcBackOff )
RegionCommonCalcBackOff( &calcBackOffParams );
}
-bool RegionAU915NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff )
+LoRaMacStatus_t RegionAU915NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff )
{
uint8_t nbEnabledChannels = 0;
uint8_t delayTx = 0;
@@ -769,36 +911,37 @@ bool RegionAU915NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel,
TimerTime_t nextTxDelay = 0;
// Count 125kHz channels
- if( RegionCommonCountChannels( ChannelsMaskRemaining, 0, 4 ) == 0 )
+ if( RegionCommonCountChannels( NvmCtx.ChannelsMaskRemaining, 0, 4 ) == 0 )
{ // Reactivate default channels
- RegionCommonChanMaskCopy( ChannelsMaskRemaining, ChannelsMask, 4 );
+ RegionCommonChanMaskCopy( NvmCtx.ChannelsMaskRemaining, NvmCtx.ChannelsMask, 4 );
}
// Check other channels
if( nextChanParams->Datarate >= DR_6 )
{
- if( ( ChannelsMaskRemaining[4] & 0x00FF ) == 0 )
+ if( ( NvmCtx.ChannelsMaskRemaining[4] & CHANNELS_MASK_500KHZ_MASK ) == 0 )
{
- ChannelsMaskRemaining[4] = ChannelsMask[4];
+ NvmCtx.ChannelsMaskRemaining[4] = NvmCtx.ChannelsMask[4];
}
}
- if( nextChanParams->AggrTimeOff <= TimerGetElapsedTime( nextChanParams->LastAggrTx ) )
+ TimerTime_t elapsed = TimerGetElapsedTime( nextChanParams->LastAggrTx );
+ if( ( nextChanParams->LastAggrTx == 0 ) || ( nextChanParams->AggrTimeOff <= elapsed ) )
{
// Reset Aggregated time off
*aggregatedTimeOff = 0;
// Update bands Time OFF
- nextTxDelay = RegionCommonUpdateBandTimeOff( nextChanParams->Joined, nextChanParams->DutyCycleEnabled, Bands, AU915_MAX_NB_BANDS );
+ nextTxDelay = RegionCommonUpdateBandTimeOff( nextChanParams->Joined, nextChanParams->DutyCycleEnabled, NvmCtx.Bands, AU915_MAX_NB_BANDS );
// Search how many channels are enabled
nbEnabledChannels = CountNbOfEnabledChannels( nextChanParams->Datarate,
- ChannelsMaskRemaining, Channels,
- Bands, enabledChannels, &delayTx );
+ NvmCtx.ChannelsMaskRemaining, NvmCtx.Channels,
+ NvmCtx.Bands, enabledChannels, &delayTx );
}
else
{
delayTx++;
- nextTxDelay = nextChanParams->AggrTimeOff - TimerGetElapsedTime( nextChanParams->LastAggrTx );
+ nextTxDelay = nextChanParams->AggrTimeOff - elapsed;
}
if( nbEnabledChannels > 0 )
@@ -806,10 +949,10 @@ bool RegionAU915NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel,
// We found a valid channel
*channel = enabledChannels[randr( 0, nbEnabledChannels - 1 )];
// Disable the channel in the mask
- RegionCommonChanDisable( ChannelsMaskRemaining, *channel, AU915_MAX_NB_CHANNELS - 8 );
+ RegionCommonChanDisable( NvmCtx.ChannelsMaskRemaining, *channel, AU915_MAX_NB_CHANNELS - 8 );
*time = 0;
- return true;
+ return LORAMAC_STATUS_OK;
}
else
{
@@ -817,11 +960,11 @@ bool RegionAU915NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel,
{
// Delay transmission due to AggregatedTimeOff or to a band time off
*time = nextTxDelay;
- return true;
+ return LORAMAC_STATUS_DUTYCYCLE_RESTRICTED;
}
// Datarate not supported by any channel
*time = 0;
- return false;
+ return LORAMAC_STATUS_NO_CHANNEL_FOUND;
}
}
@@ -830,6 +973,59 @@ LoRaMacStatus_t RegionAU915ChannelAdd( ChannelAddParams_t* channelAdd )
return LORAMAC_STATUS_PARAMETER_INVALID;
}
+bool RegionAU915ChannelsRemove( ChannelRemoveParams_t* channelRemove )
+{
+ return LORAMAC_STATUS_PARAMETER_INVALID;
+}
+
+void RegionAU915SetContinuousWave( ContinuousWaveParams_t* continuousWave )
+{
+ int8_t txPowerLimited = LimitTxPower( continuousWave->TxPower, NvmCtx.Bands[NvmCtx.Channels[continuousWave->Channel].Band].TxMaxPower, continuousWave->Datarate, NvmCtx.ChannelsMask );
+ int8_t phyTxPower = 0;
+ uint32_t frequency = NvmCtx.Channels[continuousWave->Channel].Frequency;
+
+ // Calculate physical TX power
+ phyTxPower = RegionCommonComputeTxPower( txPowerLimited, continuousWave->MaxEirp, continuousWave->AntennaGain );
+
+ Radio.SetTxContinuousWave( frequency, phyTxPower, continuousWave->Timeout );
+}
+
+uint8_t RegionAU915ApplyDrOffset( uint8_t downlinkDwellTime, int8_t dr, int8_t drOffset )
+{
+ int8_t datarate = DatarateOffsetsAU915[dr][drOffset];
+
+ if( datarate < 0 )
+ {
+ if( downlinkDwellTime == 0 )
+ {
+ datarate = AU915_TX_MIN_DATARATE;
+ }
+ else
+ {
+ datarate = AU915_DWELL_LIMIT_DATARATE;
+ }
+ }
+ return datarate;
+}
+
+void RegionAU915RxBeaconSetup( RxBeaconSetup_t* rxBeaconSetup, uint8_t* outDr )
+{
+ RegionCommonRxBeaconSetupParams_t regionCommonRxBeaconSetup;
+
+ regionCommonRxBeaconSetup.Datarates = DataratesAU915;
+ regionCommonRxBeaconSetup.Frequency = rxBeaconSetup->Frequency;
+ regionCommonRxBeaconSetup.BeaconSize = AU915_BEACON_SIZE;
+ regionCommonRxBeaconSetup.BeaconDatarate = AU915_BEACON_CHANNEL_DR;
+ regionCommonRxBeaconSetup.BeaconChannelBW = AU915_BEACON_CHANNEL_BW;
+ regionCommonRxBeaconSetup.RxTime = rxBeaconSetup->RxTime;
+ regionCommonRxBeaconSetup.SymbolTimeout = rxBeaconSetup->SymbolTimeout;
+
+ RegionCommonRxBeaconSetup( ®ionCommonRxBeaconSetup );
+
+ // Store downlink datarate
+ *outDr = AU915_BEACON_CHANNEL_DR;
+}
+
LoRaMacStatus_t RegionAU915ChannelManualAdd( ChannelAddParams_t* channelAdd )
{
uint8_t band = 0;
@@ -873,88 +1069,30 @@ LoRaMacStatus_t RegionAU915ChannelManualAdd( ChannelAddParams_t* channelAdd )
return LORAMAC_STATUS_FREQUENCY_INVALID;
}
- memcpy( &(Channels[id]), channelAdd->NewChannel, sizeof( Channels[id] ) );
- Channels[id].Band = band;
- ChannelsMask[ (id / 16) ] |= (1 << (id % 16));
+ memcpy( &(NvmCtx.Channels[id]), channelAdd->NewChannel, sizeof( NvmCtx.Channels[id] ) );
+ NvmCtx.Channels[id].Band = band;
+ NvmCtx.ChannelsMask[ (id / 16) ] |= (1 << (id % 16));
// activate the channel in the remaining ones
- ChannelsMaskRemaining[id / 16] |= ChannelsMask[id / 16];
+ NvmCtx.ChannelsMaskRemaining[id / 16] |= NvmCtx.ChannelsMask[id / 16];
return LORAMAC_STATUS_OK;
}
-bool RegionAU915ChannelsRemove( ChannelRemoveParams_t* channelAdd )
-{
- return false;
-}
-
bool RegionAU915ChannelsManualRemove( ChannelRemoveParams_t* channelRemove )
{
uint8_t id = channelRemove->ChannelId;
// Disable the channel as it doesn't exist anymore
- if ( !RegionCommonChanDisable( ChannelsMask, id, AU915_MAX_NB_CHANNELS ) ) {
+ if ( !RegionCommonChanDisable( NvmCtx.ChannelsMask, id, AU915_MAX_NB_CHANNELS ) ) {
return false;
}
// Remove the channel from the list of channels
- Channels[id] = ( ChannelParams_t ){ 0, 0, { 0 }, 0 };
+ NvmCtx.Channels[id] = ( ChannelParams_t ){ 0, 0, { 0 }, 0 };
// Set the channel mask remaining accordingly
- ChannelsMaskRemaining[id / 16] &= ChannelsMask[id / 16];
-
- return true;
-}
-
-void RegionAU915SetContinuousWave( ContinuousWaveParams_t* continuousWave )
-{
- int8_t txPowerLimited = LimitTxPower( continuousWave->TxPower, Bands[Channels[continuousWave->Channel].Band].TxMaxPower, continuousWave->Datarate, ChannelsMask );
- int8_t phyTxPower = 0;
- uint32_t frequency = Channels[continuousWave->Channel].Frequency;
-
- // Calculate physical TX power
- phyTxPower = RegionCommonComputeTxPower( txPowerLimited, continuousWave->MaxEirp, continuousWave->AntennaGain );
-
- Radio.SetTxContinuousWave( frequency, phyTxPower, continuousWave->Timeout );
-}
+ NvmCtx.ChannelsMaskRemaining[id / 16] &= NvmCtx.ChannelsMask[id / 16];
-uint8_t RegionAU915ApplyDrOffset( uint8_t downlinkDwellTime, int8_t dr, int8_t drOffset )
-{
- int8_t datarate = DatarateOffsetsAU915[dr][drOffset];
-
- if( datarate < 0 )
- {
- datarate = DR_0;
- }
- return datarate;
-}
-
-bool RegionAU915GetChannels( ChannelParams_t** channels, uint32_t *size )
-{
- *channels = Channels;
- *size = sizeof(Channels);
- return true;
-}
-
-bool RegionAU915GetChannelMask( uint16_t** channelmask, uint32_t *size )
-{
- *channelmask = ChannelsMask;
- *size = sizeof(ChannelsMask);
return true;
}
-bool RegionAU915GetChannelMaskRemaining( uint16_t** channelmask, uint32_t *size )
-{
- *channelmask = ChannelsMaskRemaining;
- *size = sizeof(ChannelsMaskRemaining);
- return true;
-}
-
-bool RegionAU915ForceJoinDataRate( int8_t joinDr, AlternateDrParams_t* alternateDr )
-{
- if (joinDr == DR_6) {
- alternateDr->NbTrials = 1;
- } else {
- alternateDr->NbTrials = 0;
- }
- return true;
-}
diff --git a/lib/lora/mac/region/RegionAU915.h b/lib/lora/mac/region/RegionAU915.h
index da482a9447..7367f7f593 100644
--- a/lib/lora/mac/region/RegionAU915.h
+++ b/lib/lora/mac/region/RegionAU915.h
@@ -12,7 +12,7 @@
* \____ \| ___ | (_ _) ___ |/ ___) _ \
* _____) ) ____| | | || |_| ____( (___| | | |
* (______/|_____)_|_|_| \__)_____)\____)_| |_|
- * (C)2013 Semtech
+ * (C)2013-2017 Semtech
*
* ___ _____ _ ___ _ _____ ___ ___ ___ ___
* / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
@@ -28,6 +28,8 @@
*
* \author Daniel Jaeckle ( STACKFORCE )
*
+ * \author Johannes Bruder ( STACKFORCE )
+ *
* \defgroup REGIONAU915 Region AU915
* Implementation according to LoRaWAN Specification v1.0.2.
* \{
@@ -35,6 +37,13 @@
#ifndef __REGION_AU915_H__
#define __REGION_AU915_H__
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include "Region.h"
+
/*!
* LoRaMac maximum number of channels
*/
@@ -48,7 +57,7 @@
/*!
* Maximal datarate that can be used by the node
*/
-#define AU915_TX_MAX_DATARATE DR_6
+#define AU915_TX_MAX_DATARATE DR_13
/*!
* Minimal datarate that can be used by the node
@@ -63,7 +72,13 @@
/*!
* Default datarate used by the node
*/
-#define AU915_DEFAULT_DATARATE DR_0
+#define AU915_DEFAULT_DATARATE DR_2
+
+/*!
+ * The minimum datarate which is used when the
+ * dwell time is limited.
+ */
+#define AU915_DWELL_LIMIT_DATARATE DR_2
/*!
* Minimal Rx1 receive datarate offset
@@ -83,7 +98,7 @@
/*!
* Minimal Tx output power that can be used by the node
*/
-#define AU915_MIN_TX_POWER TX_POWER_10
+#define AU915_MIN_TX_POWER TX_POWER_14
/*!
* Maximal Tx output power that can be used by the node
@@ -95,6 +110,16 @@
*/
#define AU915_DEFAULT_TX_POWER TX_POWER_0
+/*!
+ * Default uplink dwell time configuration
+ */
+#define AU915_DEFAULT_UPLINK_DWELL_TIME 1
+
+/*!
+ * Default downlink dwell time configuration
+ */
+#define AU915_DEFAULT_DOWNLINK_DWELL_TIME 0
+
/*!
* Default Max EIRP
*/
@@ -170,16 +195,64 @@
*/
#define AU915_RX_WND_2_DR DR_8
+/*
+ * CLASS B
+ */
+/*!
+ * Beacon frequency
+ */
+#define AU915_BEACON_CHANNEL_FREQ 923300000
+
+/*!
+ * Beacon frequency channel stepwidth
+ */
+#define AU915_BEACON_CHANNEL_STEPWIDTH 600000
+
+/*!
+ * Number of possible beacon channels
+ */
+#define AU915_BEACON_NB_CHANNELS 8
+
+/*!
+ * Payload size of a beacon frame
+ */
+#define AU915_BEACON_SIZE 19
+
+/*!
+ * Size of RFU 1 field
+ */
+#define AU915_RFU1_SIZE 3
+
+/*!
+ * Size of RFU 2 field
+ */
+#define AU915_RFU2_SIZE 1
+
+/*!
+ * Datarate of the beacon channel
+ */
+#define AU915_BEACON_CHANNEL_DR DR_10
+
+/*!
+ * Bandwith of the beacon channel
+ */
+#define AU915_BEACON_CHANNEL_BW 2
+
+/*!
+ * Ping slot channel datarate
+ */
+#define AU915_PING_SLOT_CHANNEL_DR DR_10
+
/*!
* LoRaMac maximum number of bands
*/
-#define AU915_MAX_NB_BANDS 1
+#define AU915_MAX_NB_BANDS 1
/*!
* Band 0 definition
- * { DutyCycle, TxMaxPower, LastTxDoneTime, TimeOff }
+ * { DutyCycle, TxMaxPower, LastJoinTxDoneTime, LastTxDoneTime, TimeOff }
*/
-#define AU915_BAND0 { 1, AU915_MAX_TX_POWER, 0, 0 } // 100.0 %
+#define AU915_BAND0 { 1, AU915_MAX_TX_POWER, 0, 0, 0 } // 100.0 %
/*!
* Defines the first channel for RX window 1 for US band
@@ -222,13 +295,29 @@ static const int8_t DatarateOffsetsAU915[7][6] =
/*!
* Maximum payload with respect to the datarate index. Cannot operate with repeater.
+ * The table is valid for the dwell time configuration of 0 for uplinks.
*/
-static const uint8_t MaxPayloadOfDatarateAU915[] = { 51, 51, 51, 115, 242, 242, 242, 0, 53, 129, 242, 242, 242, 242, 0, 0 };
+static const uint8_t MaxPayloadOfDatarateDwell0AU915[] = { 51, 51, 51, 115, 242, 242, 242, 0, 53, 129, 242, 242, 242, 242 };
/*!
* Maximum payload with respect to the datarate index. Can operate with repeater.
+ * The table is valid for the dwell time configuration of 0 for uplinks. The table provides
+ * repeater support.
*/
-static const uint8_t MaxPayloadOfDatarateRepeaterAU915[] = { 51, 51, 51, 115, 222, 222, 222, 0, 33, 109, 222, 222, 222, 222, 0, 0 };
+static const uint8_t MaxPayloadOfDatarateRepeaterDwell0AU915[] = { 51, 51, 51, 115, 222, 222, 222, 0, 33, 109, 222, 222, 222, 222 };
+
+/*!
+ * Maximum payload with respect to the datarate index. Cannot operate with repeater.
+ * The table is valid for the dwell time configuration of 1 for uplinks.
+ */
+static const uint8_t MaxPayloadOfDatarateDwell1AU915[] = { 0, 0, 11, 53, 125, 242, 242, 0, 53, 129, 242, 242, 242, 242 };
+
+/*!
+ * Maximum payload with respect to the datarate index. Can operate with repeater.
+ * The table is valid for the dwell time configuration of 1 for uplinks. The table provides
+ * repeater support.
+ */
+static const uint8_t MaxPayloadOfDatarateRepeaterDwell1AU915[] = { 0, 0, 11, 53, 125, 242, 242, 0, 33, 109, 222, 222, 222, 222 };
/*!
* \brief The function gets a value of a specific phy attribute.
@@ -251,7 +340,16 @@ void RegionAU915SetBandTxDone( SetBandTxDoneParams_t* txDone );
*
* \param [IN] type Sets the initialization type.
*/
-void RegionAU915InitDefaults( InitType_t type );
+void RegionAU915InitDefaults( InitDefaultsParams_t* params );
+
+/*!
+ * \brief Returns a pointer to the internal context and its size.
+ *
+ * \param [OUT] params Pointer to the function parameters.
+ *
+ * \retval Points to a structure where the module store its non-volatile context.
+ */
+void* RegionAU915GetNvmCtx( GetNvmCtxParams_t* params );
/*!
* \brief Verifies a parameter.
@@ -281,21 +379,6 @@ void RegionAU915ApplyCFList( ApplyCFListParams_t* applyCFList );
*/
bool RegionAU915ChanMaskSet( ChanMaskSetParams_t* chanMaskSet );
-/*!
- * \brief Calculates the next datarate to set, when ADR is on or off.
- *
- * \param [IN] adrNext Pointer to the function parameters.
- *
- * \param [OUT] drOut The calculated datarate for the next TX.
- *
- * \param [OUT] txPowOut The TX power for the next TX.
- *
- * \param [OUT] adrAckCounter The calculated ADR acknowledgement counter.
- *
- * \retval Returns true, if an ADR request should be performed.
- */
-bool RegionAU915AdrNext( AdrNextParams_t* adrNext, int8_t* drOut, int8_t* txPowOut, uint32_t* adrAckCounter );
-
/*!
* Computes the Rx window timeout and offset.
*
@@ -385,11 +468,11 @@ uint8_t RegionAU915DlChannelReq( DlChannelReqParams_t* dlChannelReq );
/*!
* \brief Alternates the datarate of the channel for the join request.
*
- * \param [IN] alternateDr Pointer to the function parameters.
+ * \param [IN] currentDr Current datarate.
*
* \retval Datarate to apply.
*/
-int8_t RegionAU915AlternateDr( AlternateDrParams_t* alternateDr );
+int8_t RegionAU915AlternateDr( int8_t currentDr, AlternateDrType_t type );
/*!
* \brief Calculates the back-off time.
@@ -410,7 +493,7 @@ void RegionAU915CalcBackOff( CalcBackOffParams_t* calcBackOff );
*
* \retval Function status [1: OK, 0: Unable to find a channel on the current datarate]
*/
-bool RegionAU915NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff );
+LoRaMacStatus_t RegionAU915NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff );
/*!
* \brief Adds a channel.
@@ -452,14 +535,17 @@ void RegionAU915SetContinuousWave( ContinuousWaveParams_t* continuousWave );
*/
uint8_t RegionAU915ApplyDrOffset( uint8_t downlinkDwellTime, int8_t dr, int8_t drOffset );
-bool RegionAU915GetChannels( ChannelParams_t** channels, uint32_t *size );
-
-bool RegionAU915GetChannelMask( uint16_t** channelmask, uint32_t *size );
-
-bool RegionAU915GetChannelMaskRemaining( uint16_t** channelmask, uint32_t *size );
-
-bool RegionAU915ForceJoinDataRate( int8_t joinDr, AlternateDrParams_t* alternateDr );
+/*!
+ * \brief Sets the radio into beacon reception mode
+ *
+ * \param [IN] rxBeaconSetup Pointer to the function parameters
+ */
+ void RegionAU915RxBeaconSetup( RxBeaconSetup_t* rxBeaconSetup, uint8_t* outDr );
/*! \} defgroup REGIONAU915 */
+#ifdef __cplusplus
+}
+#endif
+
#endif // __REGION_AU915_H__
diff --git a/lib/lora/mac/region/RegionCN470.c b/lib/lora/mac/region/RegionCN470.c
index 929646c504..eb31143f3e 100644
--- a/lib/lora/mac/region/RegionCN470.c
+++ b/lib/lora/mac/region/RegionCN470.c
@@ -1,63 +1,70 @@
-/*
- / _____) _ | |
-( (____ _____ ____ _| |_ _____ ____| |__
- \____ \| ___ | (_ _) ___ |/ ___) _ \
- _____) ) ____| | | || |_| ____( (___| | | |
-(______/|_____)_|_|_| \__)_____)\____)_| |_|
- (C)2013 Semtech
- ___ _____ _ ___ _ _____ ___ ___ ___ ___
-/ __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
-\__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
-|___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
-embedded.connectivity.solutions===============
-
-Description: LoRa MAC region CN470 implementation
-
-License: Revised BSD License, see LICENSE.TXT file include in the project
-
-Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jaeckle ( STACKFORCE )
+/*!
+ * \file RegionCN470.c
+ *
+ * \brief Region implementation for CN470
+ *
+ * \copyright Revised BSD License, see section \ref LICENSE.
+ *
+ * \code
+ * ______ _
+ * / _____) _ | |
+ * ( (____ _____ ____ _| |_ _____ ____| |__
+ * \____ \| ___ | (_ _) ___ |/ ___) _ \
+ * _____) ) ____| | | || |_| ____( (___| | | |
+ * (______/|_____)_|_|_| \__)_____)\____)_| |_|
+ * (C)2013-2017 Semtech
+ *
+ * ___ _____ _ ___ _ _____ ___ ___ ___ ___
+ * / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
+ * \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
+ * |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
+ * embedded.connectivity.solutions===============
+ *
+ * \endcode
+ *
+ * \author Miguel Luis ( Semtech )
+ *
+ * \author Gregory Cristian ( Semtech )
+ *
+ * \author Daniel Jaeckle ( STACKFORCE )
*/
-#include
#include
-#include
-#include
-
-#include "board.h"
-#include "lora/mac/LoRaMac.h"
-#include "esp_attr.h"
#include "utilities.h"
-#include "Region.h"
#include "RegionCommon.h"
#include "RegionCN470.h"
// Definitions
#define CHANNELS_MASK_SIZE 6
-// Global attributes
-/*!
- * LoRaMAC channels
- */
-static ChannelParams_t Channels[CN470_MAX_NB_CHANNELS];
-
/*!
- * LoRaMac bands
+ * Region specific context
*/
-static Band_t Bands[CN470_MAX_NB_BANDS] =
+typedef struct sRegionCN470NvmCtx
{
- CN470_BAND0
-};
+ /*!
+ * LoRaMAC channels
+ */
+ ChannelParams_t Channels[ CN470_MAX_NB_CHANNELS ];
+ /*!
+ * LoRaMac bands
+ */
+ Band_t Bands[ CN470_MAX_NB_BANDS ];
+ /*!
+ * LoRaMac channels mask
+ */
+ uint16_t ChannelsMask[ CHANNELS_MASK_SIZE ];
+ /*!
+ * LoRaMac channels default mask
+ */
+ uint16_t ChannelsDefaultMask[ CHANNELS_MASK_SIZE ];
+}RegionCN470NvmCtx_t;
-/*!
- * LoRaMac channels mask
- */
-static uint16_t ChannelsMask[CHANNELS_MASK_SIZE];
-
-/*!
- * LoRaMac channels default mask
+/*
+ * Non-volatile module context.
*/
-static uint16_t ChannelsDefaultMask[CHANNELS_MASK_SIZE];
+static RegionCN470NvmCtx_t NvmCtx;
// Static functions
static int8_t GetNextLowerTxDr( int8_t dr, int8_t minDr )
@@ -99,6 +106,30 @@ static int8_t LimitTxPower( int8_t txPower, int8_t maxBandTxPower, int8_t datara
return txPowerResult;
}
+static bool VerifyRfFreq( uint32_t freq )
+{
+ // Check radio driver support
+ if( Radio.CheckRfFrequency( freq ) == false )
+ {
+ return false;
+ }
+
+ // Rx frequencies
+ if( ( freq < CN470_FIRST_RX1_CHANNEL ) ||
+ ( freq > CN470_LAST_RX1_CHANNEL ) ||
+ ( ( ( freq - ( uint32_t ) CN470_FIRST_RX1_CHANNEL ) % ( uint32_t ) CN470_STEPWIDTH_RX1_CHANNEL ) != 0 ) )
+ {
+ return false;
+ }
+
+ // Test for frequency range - take RX and TX freqencies into account
+ if( ( freq < 470300000 ) || ( freq > 509700000 ) )
+ {
+ return false;
+ }
+ return true;
+}
+
static uint8_t CountNbOfEnabledChannels( uint8_t datarate, uint16_t* channelsMask, ChannelParams_t* channels, Band_t* bands, uint8_t* enabledChannels, uint8_t* delayTx )
{
uint8_t nbEnabledChannels = 0;
@@ -159,11 +190,26 @@ PhyParam_t RegionCN470GetPhyParam( GetPhyParams_t* getPhy )
phyParam.Value = GetNextLowerTxDr( getPhy->Datarate, CN470_TX_MIN_DATARATE );
break;
}
+ case PHY_MAX_TX_POWER:
+ {
+ phyParam.Value = CN470_MAX_TX_POWER;
+ break;
+ }
case PHY_DEF_TX_POWER:
{
phyParam.Value = CN470_DEFAULT_TX_POWER;
break;
}
+ case PHY_DEF_ADR_ACK_LIMIT:
+ {
+ phyParam.Value = CN470_ADR_ACK_LIMIT;
+ break;
+ }
+ case PHY_DEF_ADR_ACK_DELAY:
+ {
+ phyParam.Value = CN470_ADR_ACK_DELAY;
+ break;
+ }
case PHY_MAX_PAYLOAD:
{
phyParam.Value = MaxPayloadOfDatarateCN470[getPhy->Datarate];
@@ -231,12 +277,12 @@ PhyParam_t RegionCN470GetPhyParam( GetPhyParams_t* getPhy )
}
case PHY_CHANNELS_MASK:
{
- phyParam.ChannelsMask = ChannelsMask;
+ phyParam.ChannelsMask = NvmCtx.ChannelsMask;
break;
}
case PHY_CHANNELS_DEFAULT_MASK:
{
- phyParam.ChannelsMask = ChannelsDefaultMask;
+ phyParam.ChannelsMask = NvmCtx.ChannelsDefaultMask;
break;
}
case PHY_MAX_NB_CHANNELS:
@@ -246,7 +292,7 @@ PhyParam_t RegionCN470GetPhyParam( GetPhyParams_t* getPhy )
}
case PHY_CHANNELS:
{
- phyParam.Channels = Channels;
+ phyParam.Channels = NvmCtx.Channels;
break;
}
case PHY_DEF_UPLINK_DWELL_TIME:
@@ -265,10 +311,31 @@ PhyParam_t RegionCN470GetPhyParam( GetPhyParams_t* getPhy )
phyParam.fValue = CN470_DEFAULT_ANTENNA_GAIN;
break;
}
- case PHY_NB_JOIN_TRIALS:
- case PHY_DEF_NB_JOIN_TRIALS:
+ case PHY_BEACON_FORMAT:
{
- phyParam.Value = 48;
+ phyParam.BeaconFormat.BeaconSize = CN470_BEACON_SIZE;
+ phyParam.BeaconFormat.Rfu1Size = CN470_RFU1_SIZE;
+ phyParam.BeaconFormat.Rfu2Size = CN470_RFU2_SIZE;
+ break;
+ }
+ case PHY_BEACON_CHANNEL_DR:
+ {
+ phyParam.Value = CN470_BEACON_CHANNEL_DR;
+ break;
+ }
+ case PHY_BEACON_CHANNEL_STEPWIDTH:
+ {
+ phyParam.Value = CN470_BEACON_CHANNEL_STEPWIDTH;
+ break;
+ }
+ case PHY_BEACON_NB_CHANNELS:
+ {
+ phyParam.Value = CN470_BEACON_NB_CHANNELS;
+ break;
+ }
+ case PHY_PING_SLOT_CHANNEL_DR:
+ {
+ phyParam.Value = CN470_PING_SLOT_CHANNEL_DR;
break;
}
default:
@@ -280,42 +347,58 @@ PhyParam_t RegionCN470GetPhyParam( GetPhyParams_t* getPhy )
return phyParam;
}
-IRAM_ATTR void RegionCN470SetBandTxDone( SetBandTxDoneParams_t* txDone )
+void RegionCN470SetBandTxDone( SetBandTxDoneParams_t* txDone )
{
- RegionCommonSetBandTxDone( txDone->Joined, &Bands[Channels[txDone->Channel].Band], txDone->LastTxDoneTime );
+ RegionCommonSetBandTxDone( txDone->Joined, &NvmCtx.Bands[NvmCtx.Channels[txDone->Channel].Band], txDone->LastTxDoneTime );
}
-void RegionCN470InitDefaults( InitType_t type )
+void RegionCN470InitDefaults( InitDefaultsParams_t* params )
{
- switch( type )
+ Band_t bands[CN470_MAX_NB_BANDS] =
+ {
+ CN470_BAND0
+ };
+
+ switch( params->Type )
{
case INIT_TYPE_INIT:
{
+ // Initialize bands
+ memcpy1( ( uint8_t* )NvmCtx.Bands, ( uint8_t* )bands, sizeof( Band_t ) * CN470_MAX_NB_BANDS );
+
// Channels
// 125 kHz channels
for( uint8_t i = 0; i < CN470_MAX_NB_CHANNELS; i++ )
{
- Channels[i].Frequency = 470300000 + i * 200000;
- Channels[i].DrRange.Value = ( DR_5 << 4 ) | DR_0;
- Channels[i].Band = 0;
+ NvmCtx.Channels[i].Frequency = 470300000 + i * 200000;
+ NvmCtx.Channels[i].DrRange.Value = ( DR_5 << 4 ) | DR_0;
+ NvmCtx.Channels[i].Band = 0;
}
// Initialize the channels default mask
- ChannelsDefaultMask[0] = 0xFFFF;
- ChannelsDefaultMask[1] = 0xFFFF;
- ChannelsDefaultMask[2] = 0xFFFF;
- ChannelsDefaultMask[3] = 0xFFFF;
- ChannelsDefaultMask[4] = 0xFFFF;
- ChannelsDefaultMask[5] = 0xFFFF;
+ NvmCtx.ChannelsDefaultMask[0] = 0xFFFF;
+ NvmCtx.ChannelsDefaultMask[1] = 0xFFFF;
+ NvmCtx.ChannelsDefaultMask[2] = 0xFFFF;
+ NvmCtx.ChannelsDefaultMask[3] = 0xFFFF;
+ NvmCtx.ChannelsDefaultMask[4] = 0xFFFF;
+ NvmCtx.ChannelsDefaultMask[5] = 0xFFFF;
// Update the channels mask
- RegionCommonChanMaskCopy( ChannelsMask, ChannelsDefaultMask, 6 );
+ RegionCommonChanMaskCopy( NvmCtx.ChannelsMask, NvmCtx.ChannelsDefaultMask, 6 );
+ break;
+ }
+ case INIT_TYPE_RESTORE_CTX:
+ {
+ if( params->NvmCtx != 0 )
+ {
+ memcpy1( (uint8_t*) &NvmCtx, (uint8_t*) params->NvmCtx, sizeof( NvmCtx ) );
+ }
break;
}
- case INIT_TYPE_RESTORE:
+ case INIT_TYPE_RESTORE_DEFAULT_CHANNELS:
{
// Restore channels default mask
- RegionCommonChanMaskCopy( ChannelsMask, ChannelsDefaultMask, 6 );
+ RegionCommonChanMaskCopy( NvmCtx.ChannelsMask, NvmCtx.ChannelsDefaultMask, 6 );
break;
}
default:
@@ -325,10 +408,20 @@ void RegionCN470InitDefaults( InitType_t type )
}
}
+void* RegionCN470GetNvmCtx( GetNvmCtxParams_t* params )
+{
+ params->nvmCtxSize = sizeof( RegionCN470NvmCtx_t );
+ return &NvmCtx;
+}
+
bool RegionCN470Verify( VerifyParams_t* verify, PhyAttribute_t phyAttribute )
{
switch( phyAttribute )
{
+ case PHY_FREQUENCY:
+ {
+ return VerifyRfFreq( verify->Frequency );
+ }
case PHY_TX_DR:
case PHY_DEF_TX_DR:
{
@@ -348,23 +441,31 @@ bool RegionCN470Verify( VerifyParams_t* verify, PhyAttribute_t phyAttribute )
{
return CN470_DUTY_CYCLE_ENABLED;
}
- case PHY_NB_JOIN_TRIALS:
- {
- if( verify->NbJoinTrials < 48 )
- {
- return false;
- }
- break;
- }
default:
return false;
}
- return true;
}
void RegionCN470ApplyCFList( ApplyCFListParams_t* applyCFList )
{
- return;
+ // Size of the optional CF list must be 16 byte
+ if( applyCFList->Size != 16 )
+ {
+ return;
+ }
+
+ // Last byte CFListType must be 0x01 to indicate the CFList contains a series of ChMask fields
+ if( applyCFList->Payload[15] != 0x01 )
+ {
+ return;
+ }
+
+ // ChMask0 - ChMask5 must be set (every ChMask has 16 bit)
+ for( uint8_t chMaskItr = 0, cntPayload = 0; chMaskItr <= 5; chMaskItr++, cntPayload+=2 )
+ {
+ NvmCtx.ChannelsMask[chMaskItr] = (uint16_t) (0x00FF & applyCFList->Payload[cntPayload]);
+ NvmCtx.ChannelsMask[chMaskItr] |= (uint16_t) (applyCFList->Payload[cntPayload+1] << 8);
+ }
}
bool RegionCN470ChanMaskSet( ChanMaskSetParams_t* chanMaskSet )
@@ -373,12 +474,12 @@ bool RegionCN470ChanMaskSet( ChanMaskSetParams_t* chanMaskSet )
{
case CHANNELS_MASK:
{
- RegionCommonChanMaskCopy( ChannelsMask, chanMaskSet->ChannelsMaskIn, 6 );
+ RegionCommonChanMaskCopy( NvmCtx.ChannelsMask, chanMaskSet->ChannelsMaskIn, 6 );
break;
}
case CHANNELS_DEFAULT_MASK:
{
- RegionCommonChanMaskCopy( ChannelsDefaultMask, chanMaskSet->ChannelsMaskIn, 6 );
+ RegionCommonChanMaskCopy( NvmCtx.ChannelsDefaultMask, chanMaskSet->ChannelsMaskIn, 6 );
break;
}
default:
@@ -387,71 +488,6 @@ bool RegionCN470ChanMaskSet( ChanMaskSetParams_t* chanMaskSet )
return true;
}
-bool RegionCN470AdrNext( AdrNextParams_t* adrNext, int8_t* drOut, int8_t* txPowOut, uint32_t* adrAckCounter )
-{
- bool adrAckReq = false;
- int8_t datarate = adrNext->Datarate;
- int8_t txPower = adrNext->TxPower;
- GetPhyParams_t getPhy;
- PhyParam_t phyParam;
-
- // Report back the adr ack counter
- *adrAckCounter = adrNext->AdrAckCounter;
-
- if( adrNext->AdrEnabled == true )
- {
- if( datarate == CN470_TX_MIN_DATARATE )
- {
- *adrAckCounter = 0;
- adrAckReq = false;
- }
- else
- {
- if( adrNext->AdrAckCounter >= CN470_ADR_ACK_LIMIT )
- {
- adrAckReq = true;
- txPower = CN470_MAX_TX_POWER;
- }
- else
- {
- adrAckReq = false;
- }
- if( adrNext->AdrAckCounter >= ( CN470_ADR_ACK_LIMIT + CN470_ADR_ACK_DELAY ) )
- {
- if( ( adrNext->AdrAckCounter % CN470_ADR_ACK_DELAY ) == 1 )
- {
- // Decrease the datarate
- getPhy.Attribute = PHY_NEXT_LOWER_TX_DR;
- getPhy.Datarate = datarate;
- getPhy.UplinkDwellTime = adrNext->UplinkDwellTime;
- phyParam = RegionCN470GetPhyParam( &getPhy );
- datarate = phyParam.Value;
-
- if( datarate == CN470_TX_MIN_DATARATE )
- {
- // We must set adrAckReq to false as soon as we reach the lowest datarate
- adrAckReq = false;
- if( adrNext->UpdateChanMask == true )
- {
- // Re-enable default channels
- ChannelsMask[0] = 0xFFFF;
- ChannelsMask[1] = 0xFFFF;
- ChannelsMask[2] = 0xFFFF;
- ChannelsMask[3] = 0xFFFF;
- ChannelsMask[4] = 0xFFFF;
- ChannelsMask[5] = 0xFFFF;
- }
- }
- }
- }
- }
- }
-
- *drOut = datarate;
- *txPowOut = txPower;
- return adrAckReq;
-}
-
void RegionCN470ComputeRxWindowParameters( int8_t datarate, uint8_t minRxSymbols, uint32_t rxError, RxConfigParams_t *rxConfigParams )
{
double tSymbol = 0.0;
@@ -462,7 +498,7 @@ void RegionCN470ComputeRxWindowParameters( int8_t datarate, uint8_t minRxSymbols
tSymbol = RegionCommonComputeSymbolTimeLoRa( DataratesCN470[rxConfigParams->Datarate], BandwidthsCN470[rxConfigParams->Datarate] );
- RegionCommonComputeRxWindowParameters( tSymbol, minRxSymbols, rxError, RADIO_WAKEUP_TIME, &rxConfigParams->WindowTimeout, &rxConfigParams->WindowOffset );
+ RegionCommonComputeRxWindowParameters( tSymbol, minRxSymbols, rxError, Radio.GetWakeupTime( ), &rxConfigParams->WindowTimeout, &rxConfigParams->WindowOffset );
}
bool RegionCN470RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate )
@@ -477,7 +513,7 @@ bool RegionCN470RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate )
return false;
}
- if( rxConfig->Window == 0 )
+ if( rxConfig->RxSlot == RX_SLOT_WIN_1 )
{
// Apply window 1 frequency
frequency = CN470_FIRST_RX1_CHANNEL + ( rxConfig->Channel % 48 ) * CN470_STEPWIDTH_RX1_CHANNEL;
@@ -508,16 +544,16 @@ bool RegionCN470RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate )
bool RegionCN470TxConfig( TxConfigParams_t* txConfig, int8_t* txPower, TimerTime_t* txTimeOnAir )
{
int8_t phyDr = DataratesCN470[txConfig->Datarate];
- int8_t txPowerLimited = LimitTxPower( txConfig->TxPower, Bands[Channels[txConfig->Channel].Band].TxMaxPower, txConfig->Datarate, ChannelsMask );
+ int8_t txPowerLimited = LimitTxPower( txConfig->TxPower, NvmCtx.Bands[NvmCtx.Channels[txConfig->Channel].Band].TxMaxPower, txConfig->Datarate, NvmCtx.ChannelsMask );
int8_t phyTxPower = 0;
// Calculate physical TX power
phyTxPower = RegionCommonComputeTxPower( txPowerLimited, txConfig->MaxEirp, txConfig->AntennaGain );
// Setup the radio frequency
- Radio.SetChannel( Channels[txConfig->Channel].Frequency );
+ Radio.SetChannel( NvmCtx.Channels[txConfig->Channel].Frequency );
- Radio.SetTxConfig( MODEM_LORA, phyTxPower, 0, 0, phyDr, 1, 8, false, true, 0, 0, false, 3000 );
+ Radio.SetTxConfig( MODEM_LORA, phyTxPower, 0, 0, phyDr, 1, 8, false, true, 0, 0, false, 4000 );
// Setup maximum payload lenght of the radio driver
Radio.SetMaxPayloadLength( MODEM_LORA, txConfig->PktLen );
// Get the time-on-air of the next tx frame
@@ -539,7 +575,7 @@ uint8_t RegionCN470LinkAdrReq( LinkAdrReqParams_t* linkAdrReq, int8_t* drOut, in
RegionCommonLinkAdrReqVerifyParams_t linkAdrVerifyParams;
// Initialize local copy of channels mask
- RegionCommonChanMaskCopy( channelsMask, ChannelsMask, 6 );
+ RegionCommonChanMaskCopy( channelsMask, NvmCtx.ChannelsMask, 6 );
while( bytesProcessed < linkAdrReq->PayloadSize )
{
@@ -574,7 +610,7 @@ uint8_t RegionCN470LinkAdrReq( LinkAdrReqParams_t* linkAdrReq, int8_t* drOut, in
for( uint8_t i = 0; i < 16; i++ )
{
if( ( ( linkAdrParams.ChMask & ( 1 << i ) ) != 0 ) &&
- ( Channels[linkAdrParams.ChMaskCtrl * 16 + i].Frequency == 0 ) )
+ ( NvmCtx.Channels[linkAdrParams.ChMaskCtrl * 16 + i].Frequency == 0 ) )
{// Trying to enable an undefined channel
status &= 0xFE; // Channel mask KO
}
@@ -600,9 +636,10 @@ uint8_t RegionCN470LinkAdrReq( LinkAdrReqParams_t* linkAdrReq, int8_t* drOut, in
linkAdrVerifyParams.ChannelsMask = channelsMask;
linkAdrVerifyParams.MinDatarate = ( int8_t )phyParam.Value;
linkAdrVerifyParams.MaxDatarate = CN470_TX_MAX_DATARATE;
- linkAdrVerifyParams.Channels = Channels;
+ linkAdrVerifyParams.Channels = NvmCtx.Channels;
linkAdrVerifyParams.MinTxPower = CN470_MIN_TX_POWER;
linkAdrVerifyParams.MaxTxPower = CN470_MAX_TX_POWER;
+ linkAdrVerifyParams.Version = linkAdrReq->Version;
// Verify the parameters and update, if necessary
status = RegionCommonLinkAdrReqVerifyParams( &linkAdrVerifyParams, &linkAdrParams.Datarate, &linkAdrParams.TxPower, &linkAdrParams.NbRep );
@@ -611,7 +648,7 @@ uint8_t RegionCN470LinkAdrReq( LinkAdrReqParams_t* linkAdrReq, int8_t* drOut, in
if( status == 0x07 )
{
// Copy Mask
- RegionCommonChanMaskCopy( ChannelsMask, channelsMask, 6 );
+ RegionCommonChanMaskCopy( NvmCtx.ChannelsMask, channelsMask, 6 );
}
// Update status variables
@@ -626,13 +663,9 @@ uint8_t RegionCN470LinkAdrReq( LinkAdrReqParams_t* linkAdrReq, int8_t* drOut, in
uint8_t RegionCN470RxParamSetupReq( RxParamSetupReqParams_t* rxParamSetupReq )
{
uint8_t status = 0x07;
- uint32_t freq = rxParamSetupReq->Frequency;
// Verify radio frequency
- if( ( Radio.CheckRfFrequency( freq ) == false ) ||
- ( freq < CN470_FIRST_RX1_CHANNEL ) ||
- ( freq > CN470_LAST_RX1_CHANNEL ) ||
- ( ( ( freq - ( uint32_t ) CN470_FIRST_RX1_CHANNEL ) % ( uint32_t ) CN470_STEPWIDTH_RX1_CHANNEL ) != 0 ) )
+ if( VerifyRfFreq( rxParamSetupReq->Frequency ) == false )
{
status &= 0xFE; // Channel frequency KO
}
@@ -668,43 +701,17 @@ uint8_t RegionCN470DlChannelReq( DlChannelReqParams_t* dlChannelReq )
return 0;
}
-int8_t RegionCN470AlternateDr( AlternateDrParams_t* alternateDr )
+int8_t RegionCN470AlternateDr( int8_t currentDr, AlternateDrType_t type )
{
- int8_t datarate = 0;
-
- if( ( alternateDr->NbTrials % 48 ) == 0 )
- {
- datarate = DR_0;
- }
- else if( ( alternateDr->NbTrials % 32 ) == 0 )
- {
- datarate = DR_1;
- }
- else if( ( alternateDr->NbTrials % 24 ) == 0 )
- {
- datarate = DR_2;
- }
- else if( ( alternateDr->NbTrials % 16 ) == 0 )
- {
- datarate = DR_3;
- }
- else if( ( alternateDr->NbTrials % 8 ) == 0 )
- {
- datarate = DR_4;
- }
- else
- {
- datarate = DR_5;
- }
- return datarate;
+ return currentDr;
}
void RegionCN470CalcBackOff( CalcBackOffParams_t* calcBackOff )
{
RegionCommonCalcBackOffParams_t calcBackOffParams;
- calcBackOffParams.Channels = Channels;
- calcBackOffParams.Bands = Bands;
+ calcBackOffParams.Channels = NvmCtx.Channels;
+ calcBackOffParams.Bands = NvmCtx.Bands;
calcBackOffParams.LastTxIsJoinRequest = calcBackOff->LastTxIsJoinRequest;
calcBackOffParams.Joined = calcBackOff->Joined;
calcBackOffParams.DutyCycleEnabled = calcBackOff->DutyCycleEnabled;
@@ -715,7 +722,7 @@ void RegionCN470CalcBackOff( CalcBackOffParams_t* calcBackOff )
RegionCommonCalcBackOff( &calcBackOffParams );
}
-bool RegionCN470NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff )
+LoRaMacStatus_t RegionCN470NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff )
{
uint8_t nbEnabledChannels = 0;
uint8_t delayTx = 0;
@@ -723,32 +730,34 @@ bool RegionCN470NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel,
TimerTime_t nextTxDelay = 0;
// Count 125kHz channels
- if( RegionCommonCountChannels( ChannelsMask, 0, 6 ) == 0 )
+ if( RegionCommonCountChannels( NvmCtx.ChannelsMask, 0, 6 ) == 0 )
{ // Reactivate default channels
- ChannelsMask[0] = 0xFFFF;
- ChannelsMask[1] = 0xFFFF;
- ChannelsMask[2] = 0xFFFF;
- ChannelsMask[3] = 0xFFFF;
- ChannelsMask[4] = 0xFFFF;
- ChannelsMask[5] = 0xFFFF;
+ NvmCtx.ChannelsMask[0] = 0xFFFF;
+ NvmCtx.ChannelsMask[1] = 0xFFFF;
+ NvmCtx.ChannelsMask[2] = 0xFFFF;
+ NvmCtx.ChannelsMask[3] = 0xFFFF;
+ NvmCtx.ChannelsMask[4] = 0xFFFF;
+ NvmCtx.ChannelsMask[5] = 0xFFFF;
}
- if( nextChanParams->AggrTimeOff <= TimerGetElapsedTime( nextChanParams->LastAggrTx ) )
+ TimerTime_t elapsed = TimerGetElapsedTime( nextChanParams->LastAggrTx );
+ if( ( nextChanParams->LastAggrTx == 0 ) || ( nextChanParams->AggrTimeOff <= elapsed ) )
{
// Reset Aggregated time off
*aggregatedTimeOff = 0;
// Update bands Time OFF
- nextTxDelay = RegionCommonUpdateBandTimeOff( nextChanParams->Joined, nextChanParams->DutyCycleEnabled, Bands, CN470_MAX_NB_BANDS );
+ nextTxDelay = RegionCommonUpdateBandTimeOff( nextChanParams->Joined, nextChanParams->DutyCycleEnabled, NvmCtx.Bands, CN470_MAX_NB_BANDS );
+
// Search how many channels are enabled
nbEnabledChannels = CountNbOfEnabledChannels( nextChanParams->Datarate,
- ChannelsMask, Channels,
- Bands, enabledChannels, &delayTx );
+ NvmCtx.ChannelsMask, NvmCtx.Channels,
+ NvmCtx.Bands, enabledChannels, &delayTx );
}
else
{
delayTx++;
- nextTxDelay = nextChanParams->AggrTimeOff - TimerGetElapsedTime( nextChanParams->LastAggrTx );
+ nextTxDelay = nextChanParams->AggrTimeOff - elapsed;
}
if( nbEnabledChannels > 0 )
@@ -757,7 +766,7 @@ bool RegionCN470NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel,
*channel = enabledChannels[randr( 0, nbEnabledChannels - 1 )];
*time = 0;
- return true;
+ return LORAMAC_STATUS_OK;
}
else
{
@@ -765,11 +774,11 @@ bool RegionCN470NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel,
{
// Delay transmission due to AggregatedTimeOff or to a band time off
*time = nextTxDelay;
- return true;
+ return LORAMAC_STATUS_DUTYCYCLE_RESTRICTED;
}
// Datarate not supported by any channel
*time = 0;
- return false;
+ return LORAMAC_STATUS_NO_CHANNEL_FOUND;
}
}
@@ -785,9 +794,9 @@ bool RegionCN470ChannelsRemove( ChannelRemoveParams_t* channelRemove )
void RegionCN470SetContinuousWave( ContinuousWaveParams_t* continuousWave )
{
- int8_t txPowerLimited = LimitTxPower( continuousWave->TxPower, Bands[Channels[continuousWave->Channel].Band].TxMaxPower, continuousWave->Datarate, ChannelsMask );
+ int8_t txPowerLimited = LimitTxPower( continuousWave->TxPower, NvmCtx.Bands[NvmCtx.Channels[continuousWave->Channel].Band].TxMaxPower, continuousWave->Datarate, NvmCtx.ChannelsMask );
int8_t phyTxPower = 0;
- uint32_t frequency = Channels[continuousWave->Channel].Frequency;
+ uint32_t frequency = NvmCtx.Channels[continuousWave->Channel].Frequency;
// Calculate physical TX power
phyTxPower = RegionCommonComputeTxPower( txPowerLimited, continuousWave->MaxEirp, continuousWave->AntennaGain );
@@ -795,6 +804,35 @@ void RegionCN470SetContinuousWave( ContinuousWaveParams_t* continuousWave )
Radio.SetTxContinuousWave( frequency, phyTxPower, continuousWave->Timeout );
}
+uint8_t RegionCN470ApplyDrOffset( uint8_t downlinkDwellTime, int8_t dr, int8_t drOffset )
+{
+ int8_t datarate = dr - drOffset;
+
+ if( datarate < 0 )
+ {
+ datarate = DR_0;
+ }
+ return datarate;
+}
+
+void RegionCN470RxBeaconSetup( RxBeaconSetup_t* rxBeaconSetup, uint8_t* outDr )
+{
+ RegionCommonRxBeaconSetupParams_t regionCommonRxBeaconSetup;
+
+ regionCommonRxBeaconSetup.Datarates = DataratesCN470;
+ regionCommonRxBeaconSetup.Frequency = rxBeaconSetup->Frequency;
+ regionCommonRxBeaconSetup.BeaconSize = CN470_BEACON_SIZE;
+ regionCommonRxBeaconSetup.BeaconDatarate = CN470_BEACON_CHANNEL_DR;
+ regionCommonRxBeaconSetup.BeaconChannelBW = CN470_BEACON_CHANNEL_BW;
+ regionCommonRxBeaconSetup.RxTime = rxBeaconSetup->RxTime;
+ regionCommonRxBeaconSetup.SymbolTimeout = rxBeaconSetup->SymbolTimeout;
+
+ RegionCommonRxBeaconSetup( ®ionCommonRxBeaconSetup );
+
+ // Store downlink datarate
+ *outDr = CN470_BEACON_CHANNEL_DR;
+}
+
LoRaMacStatus_t RegionCN470ChannelManualAdd( ChannelAddParams_t* channelAdd )
{
uint8_t band = 0;
@@ -838,29 +876,10 @@ LoRaMacStatus_t RegionCN470ChannelManualAdd( ChannelAddParams_t* channelAdd )
return LORAMAC_STATUS_FREQUENCY_INVALID;
}
- memcpy( &(Channels[id]), channelAdd->NewChannel, sizeof( Channels[id] ) );
- Channels[id].Band = band;
- ChannelsMask[ (id / 16) ] |= (1 << (id % 16));
+ memcpy( &(NvmCtx.Channels[id]), channelAdd->NewChannel, sizeof( NvmCtx.Channels[id] ) );
+ NvmCtx.Channels[id].Band = band;
+ NvmCtx.ChannelsMask[ (id / 16) ] |= (1 << (id % 16));
return LORAMAC_STATUS_OK;
}
-uint8_t RegionCN470ApplyDrOffset( uint8_t downlinkDwellTime, int8_t dr, int8_t drOffset )
-{
- int8_t datarate = dr - drOffset;
-
- if( datarate < 0 )
- {
- datarate = DR_0;
- }
- return datarate;
-}
-
-bool RegionCN470ForceJoinDataRate( int8_t joinDr, AlternateDrParams_t* alternateDr )
-{
- uint8_t DRToCounter[6] = { 48, 32, 24, 16, 8, 1 };
- if (joinDr < sizeof(DRToCounter)) {
- alternateDr->NbTrials = DRToCounter[joinDr];
- }
- return true;
-}
diff --git a/lib/lora/mac/region/RegionCN470.h b/lib/lora/mac/region/RegionCN470.h
index cfc1d93e87..2a4f7432a0 100644
--- a/lib/lora/mac/region/RegionCN470.h
+++ b/lib/lora/mac/region/RegionCN470.h
@@ -12,7 +12,7 @@
* \____ \| ___ | (_ _) ___ |/ ___) _ \
* _____) ) ____| | | || |_| ____( (___| | | |
* (______/|_____)_|_|_| \__)_____)\____)_| |_|
- * (C)2013 Semtech
+ * (C)2013-2017 Semtech
*
* ___ _____ _ ___ _ _____ ___ ___ ___ ___
* / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
@@ -28,6 +28,8 @@
*
* \author Daniel Jaeckle ( STACKFORCE )
*
+ * \author Johannes Bruder ( STACKFORCE )
+ *
* \defgroup REGIONCN470 Region CN470
* Implementation according to LoRaWAN Specification v1.0.2.
* \{
@@ -35,6 +37,13 @@
#ifndef __REGION_CN470_H__
#define __REGION_CN470_H__
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include "Region.h"
+
/*!
* LoRaMac maximum number of channels
*/
@@ -170,16 +179,64 @@
*/
#define CN470_RX_WND_2_DR DR_0
+/*
+ * CLASS B
+ */
+/*!
+ * Beacon frequency
+ */
+#define CN470_BEACON_CHANNEL_FREQ 508300000
+
+/*!
+ * Beacon frequency channel stepwidth
+ */
+#define CN470_BEACON_CHANNEL_STEPWIDTH 200000
+
+/*!
+ * Number of possible beacon channels
+ */
+#define CN470_BEACON_NB_CHANNELS 8
+
+/*!
+ * Payload size of a beacon frame
+ */
+#define CN470_BEACON_SIZE 19
+
+/*!
+ * Size of RFU 1 field
+ */
+#define CN470_RFU1_SIZE 3
+
+/*!
+ * Size of RFU 2 field
+ */
+#define CN470_RFU2_SIZE 1
+
+/*!
+ * Datarate of the beacon channel
+ */
+#define CN470_BEACON_CHANNEL_DR DR_2
+
+/*!
+ * Bandwith of the beacon channel
+ */
+#define CN470_BEACON_CHANNEL_BW 0
+
+/*!
+ * Ping slot channel datarate
+ */
+#define CN470_PING_SLOT_CHANNEL_DR DR_2
+
/*!
* LoRaMac maximum number of bands
*/
-#define CN470_MAX_NB_BANDS 1
+#define CN470_MAX_NB_BANDS 1
/*!
* Band 0 definition
- * { DutyCycle, TxMaxPower, LastTxDoneTime, TimeOff }
+ * { DutyCycle, TxMaxPower, LastJoinTxDoneTime, LastTxDoneTime, TimeOff }
*/
-#define CN470_BAND0 { 1, CN470_MAX_TX_POWER, 0, 0 } // 100.0 %
+#define CN470_BAND0 { 1, CN470_MAX_TX_POWER, 0, 0, 0 } // 100.0 %
/*!
* Defines the first channel for RX window 1 for CN470 band
@@ -209,7 +266,7 @@ static const uint32_t BandwidthsCN470[] = { 125000, 125000, 125000, 125000, 1250
/*!
* Maximum payload with respect to the datarate index. Cannot operate with repeater.
*/
-static const uint8_t MaxPayloadOfDatarateCN470[] = { 51, 51, 51, 115, 222, 222 };
+static const uint8_t MaxPayloadOfDatarateCN470[] = { 51, 51, 51, 115, 242, 242 };
/*!
* Maximum payload with respect to the datarate index. Can operate with repeater.
@@ -237,7 +294,16 @@ void RegionCN470SetBandTxDone( SetBandTxDoneParams_t* txDone );
*
* \param [IN] type Sets the initialization type.
*/
-void RegionCN470InitDefaults( InitType_t type );
+void RegionCN470InitDefaults( InitDefaultsParams_t* params );
+
+/*!
+ * \brief Returns a pointer to the internal context and its size.
+ *
+ * \param [OUT] params Pointer to the function parameters.
+ *
+ * \retval Points to a structure where the module store its non-volatile context.
+ */
+void* RegionCN470GetNvmCtx( GetNvmCtxParams_t* params );
/*!
* \brief Verifies a parameter.
@@ -267,21 +333,6 @@ void RegionCN470ApplyCFList( ApplyCFListParams_t* applyCFList );
*/
bool RegionCN470ChanMaskSet( ChanMaskSetParams_t* chanMaskSet );
-/*!
- * \brief Calculates the next datarate to set, when ADR is on or off.
- *
- * \param [IN] adrNext Pointer to the function parameters.
- *
- * \param [OUT] drOut The calculated datarate for the next TX.
- *
- * \param [OUT] txPowOut The TX power for the next TX.
- *
- * \param [OUT] adrAckCounter The calculated ADR acknowledgement counter.
- *
- * \retval Returns true, if an ADR request should be performed.
- */
-bool RegionCN470AdrNext( AdrNextParams_t* adrNext, int8_t* drOut, int8_t* txPowOut, uint32_t* adrAckCounter );
-
/*!
* Computes the Rx window timeout and offset.
*
@@ -371,11 +422,11 @@ uint8_t RegionCN470DlChannelReq( DlChannelReqParams_t* dlChannelReq );
/*!
* \brief Alternates the datarate of the channel for the join request.
*
- * \param [IN] alternateDr Pointer to the function parameters.
+ * \param [IN] currentDr Current datarate.
*
* \retval Datarate to apply.
*/
-int8_t RegionCN470AlternateDr( AlternateDrParams_t* alternateDr );
+int8_t RegionCN470AlternateDr( int8_t currentDr, AlternateDrType_t type );
/*!
* \brief Calculates the back-off time.
@@ -396,7 +447,7 @@ void RegionCN470CalcBackOff( CalcBackOffParams_t* calcBackOff );
*
* \retval Function status [1: OK, 0: Unable to find a channel on the current datarate]
*/
-bool RegionCN470NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff );
+LoRaMacStatus_t RegionCN470NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff );
/*!
* \brief Adds a channel.
@@ -406,6 +457,7 @@ bool RegionCN470NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel,
* \retval Status of the operation.
*/
LoRaMacStatus_t RegionCN470ChannelAdd( ChannelAddParams_t* channelAdd );
+LoRaMacStatus_t RegionCN470ChannelManualAdd( ChannelAddParams_t* channelAdd );
/*!
* \brief Removes a channel.
@@ -436,10 +488,17 @@ void RegionCN470SetContinuousWave( ContinuousWaveParams_t* continuousWave );
*/
uint8_t RegionCN470ApplyDrOffset( uint8_t downlinkDwellTime, int8_t dr, int8_t drOffset );
+/*!
+ * \brief Sets the radio into beacon reception mode
+ *
+ * \param [IN] rxBeaconSetup Pointer to the function parameters
+ */
+ void RegionCN470RxBeaconSetup( RxBeaconSetup_t* rxBeaconSetup, uint8_t* outDr );
+
/*! \} defgroup REGIONCN470 */
-bool RegionCN470ForceJoinDataRate( int8_t joinDr, AlternateDrParams_t* alternateDr );
-LoRaMacStatus_t RegionCN470ChannelManualAdd( ChannelAddParams_t* channelAdd );
-bool RegionCN470ChannelsRemove( ChannelRemoveParams_t* channelRemove );
+#ifdef __cplusplus
+}
+#endif
#endif // __REGION_CN470_H__
diff --git a/lib/lora/mac/region/RegionCN779.c b/lib/lora/mac/region/RegionCN779.c
index 5b785fe140..fed87bdd16 100644
--- a/lib/lora/mac/region/RegionCN779.c
+++ b/lib/lora/mac/region/RegionCN779.c
@@ -1,63 +1,68 @@
-/*
- / _____) _ | |
-( (____ _____ ____ _| |_ _____ ____| |__
- \____ \| ___ | (_ _) ___ |/ ___) _ \
- _____) ) ____| | | || |_| ____( (___| | | |
-(______/|_____)_|_|_| \__)_____)\____)_| |_|
- (C)2013 Semtech
- ___ _____ _ ___ _ _____ ___ ___ ___ ___
-/ __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
-\__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
-|___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
-embedded.connectivity.solutions===============
-
-Description: LoRa MAC region CN779 implementation
-
-License: Revised BSD License, see LICENSE.TXT file include in the project
-
-Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jaeckle ( STACKFORCE )
+/*!
+ * \file RegionCN779.c
+ *
+ * \brief Region implementation for CN779
+ *
+ * \copyright Revised BSD License, see section \ref LICENSE.
+ *
+ * \code
+ * ______ _
+ * / _____) _ | |
+ * ( (____ _____ ____ _| |_ _____ ____| |__
+ * \____ \| ___ | (_ _) ___ |/ ___) _ \
+ * _____) ) ____| | | || |_| ____( (___| | | |
+ * (______/|_____)_|_|_| \__)_____)\____)_| |_|
+ * (C)2013-2017 Semtech
+ *
+ * ___ _____ _ ___ _ _____ ___ ___ ___ ___
+ * / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
+ * \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
+ * |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
+ * embedded.connectivity.solutions===============
+ *
+ * \endcode
+ *
+ * \author Miguel Luis ( Semtech )
+ *
+ * \author Gregory Cristian ( Semtech )
+ *
+ * \author Daniel Jaeckle ( STACKFORCE )
*/
-#include
-#include
-#include
-#include
-
-#include "board.h"
-#include "LoRaMac.h"
-#include "esp_attr.h"
-
#include "utilities.h"
-#include "Region.h"
#include "RegionCommon.h"
#include "RegionCN779.h"
// Definitions
#define CHANNELS_MASK_SIZE 1
-// Global attributes
/*!
- * LoRaMAC channels
+ * Region specific context
*/
-static ChannelParams_t Channels[CN779_MAX_NB_CHANNELS];
-
-/*!
- * LoRaMac bands
- */
-static Band_t Bands[CN779_MAX_NB_BANDS] =
+typedef struct sRegionCN779NvmCtx
{
- CN779_BAND0
-};
+ /*!
+ * LoRaMAC channels
+ */
+ ChannelParams_t Channels[ CN779_MAX_NB_CHANNELS ];
+ /*!
+ * LoRaMac bands
+ */
+ Band_t Bands[ CN779_MAX_NB_BANDS ];
+ /*!
+ * LoRaMac channels mask
+ */
+ uint16_t ChannelsMask[ CHANNELS_MASK_SIZE ];
+ /*!
+ * LoRaMac channels default mask
+ */
+ uint16_t ChannelsDefaultMask[ CHANNELS_MASK_SIZE ];
+}RegionCN779NvmCtx_t;
-/*!
- * LoRaMac channels mask
- */
-static uint16_t ChannelsMask[CHANNELS_MASK_SIZE];
-
-/*!
- * LoRaMac channels default mask
+/*
+ * Non-volatile module context.
*/
-static uint16_t ChannelsDefaultMask[CHANNELS_MASK_SIZE];
+static RegionCN779NvmCtx_t NvmCtx;
// Static functions
static int8_t GetNextLowerTxDr( int8_t dr, int8_t minDr )
@@ -99,7 +104,7 @@ static int8_t LimitTxPower( int8_t txPower, int8_t maxBandTxPower, int8_t datara
return txPowerResult;
}
-static bool VerifyTxFreq( uint32_t freq )
+static bool VerifyRfFreq( uint32_t freq )
{
// Check radio driver support
if( Radio.CheckRfFrequency( freq ) == false )
@@ -181,11 +186,26 @@ PhyParam_t RegionCN779GetPhyParam( GetPhyParams_t* getPhy )
phyParam.Value = GetNextLowerTxDr( getPhy->Datarate, CN779_TX_MIN_DATARATE );
break;
}
+ case PHY_MAX_TX_POWER:
+ {
+ phyParam.Value = CN779_MAX_TX_POWER;
+ break;
+ }
case PHY_DEF_TX_POWER:
{
phyParam.Value = CN779_DEFAULT_TX_POWER;
break;
}
+ case PHY_DEF_ADR_ACK_LIMIT:
+ {
+ phyParam.Value = CN779_ADR_ACK_LIMIT;
+ break;
+ }
+ case PHY_DEF_ADR_ACK_DELAY:
+ {
+ phyParam.Value = CN779_ADR_ACK_DELAY;
+ break;
+ }
case PHY_MAX_PAYLOAD:
{
phyParam.Value = MaxPayloadOfDatarateCN779[getPhy->Datarate];
@@ -253,12 +273,12 @@ PhyParam_t RegionCN779GetPhyParam( GetPhyParams_t* getPhy )
}
case PHY_CHANNELS_MASK:
{
- phyParam.ChannelsMask = ChannelsMask;
+ phyParam.ChannelsMask = NvmCtx.ChannelsMask;
break;
}
case PHY_CHANNELS_DEFAULT_MASK:
{
- phyParam.ChannelsMask = ChannelsDefaultMask;
+ phyParam.ChannelsMask = NvmCtx.ChannelsDefaultMask;
break;
}
case PHY_MAX_NB_CHANNELS:
@@ -268,7 +288,7 @@ PhyParam_t RegionCN779GetPhyParam( GetPhyParams_t* getPhy )
}
case PHY_CHANNELS:
{
- phyParam.Channels = Channels;
+ phyParam.Channels = NvmCtx.Channels;
break;
}
case PHY_DEF_UPLINK_DWELL_TIME:
@@ -287,10 +307,26 @@ PhyParam_t RegionCN779GetPhyParam( GetPhyParams_t* getPhy )
phyParam.fValue = CN779_DEFAULT_ANTENNA_GAIN;
break;
}
- case PHY_NB_JOIN_TRIALS:
- case PHY_DEF_NB_JOIN_TRIALS:
+ case PHY_BEACON_CHANNEL_FREQ:
{
- phyParam.Value = 48;
+ phyParam.Value = CN779_BEACON_CHANNEL_FREQ;
+ break;
+ }
+ case PHY_BEACON_FORMAT:
+ {
+ phyParam.BeaconFormat.BeaconSize = CN779_BEACON_SIZE;
+ phyParam.BeaconFormat.Rfu1Size = CN779_RFU1_SIZE;
+ phyParam.BeaconFormat.Rfu2Size = CN779_RFU2_SIZE;
+ break;
+ }
+ case PHY_BEACON_CHANNEL_DR:
+ {
+ phyParam.Value = CN779_BEACON_CHANNEL_DR;
+ break;
+ }
+ case PHY_PING_SLOT_CHANNEL_DR:
+ {
+ phyParam.Value = CN779_PING_SLOT_CHANNEL_DR;
break;
}
default:
@@ -302,32 +338,53 @@ PhyParam_t RegionCN779GetPhyParam( GetPhyParams_t* getPhy )
return phyParam;
}
-IRAM_ATTR void RegionCN779SetBandTxDone( SetBandTxDoneParams_t* txDone )
+void RegionCN779SetBandTxDone( SetBandTxDoneParams_t* txDone )
{
- RegionCommonSetBandTxDone( txDone->Joined, &Bands[Channels[txDone->Channel].Band], txDone->LastTxDoneTime );
+ RegionCommonSetBandTxDone( txDone->Joined, &NvmCtx.Bands[NvmCtx.Channels[txDone->Channel].Band], txDone->LastTxDoneTime );
}
-void RegionCN779InitDefaults( InitType_t type )
+void RegionCN779InitDefaults( InitDefaultsParams_t* params )
{
- switch( type )
+ Band_t bands[CN779_MAX_NB_BANDS] =
+ {
+ CN779_BAND0
+ };
+
+ switch( params->Type )
{
case INIT_TYPE_INIT:
{
+ // Initialize bands
+ memcpy1( ( uint8_t* )NvmCtx.Bands, ( uint8_t* )bands, sizeof( Band_t ) * CN779_MAX_NB_BANDS );
+
// Channels
- Channels[0] = ( ChannelParams_t ) CN779_LC1;
- Channels[1] = ( ChannelParams_t ) CN779_LC2;
- Channels[2] = ( ChannelParams_t ) CN779_LC3;
+ NvmCtx.Channels[0] = ( ChannelParams_t ) CN779_LC1;
+ NvmCtx.Channels[1] = ( ChannelParams_t ) CN779_LC2;
+ NvmCtx.Channels[2] = ( ChannelParams_t ) CN779_LC3;
// Initialize the channels default mask
- ChannelsDefaultMask[0] = LC( 1 ) + LC( 2 ) + LC( 3 );
+ NvmCtx.ChannelsDefaultMask[0] = LC( 1 ) + LC( 2 ) + LC( 3 );
// Update the channels mask
- RegionCommonChanMaskCopy( ChannelsMask, ChannelsDefaultMask, 1 );
+ RegionCommonChanMaskCopy( NvmCtx.ChannelsMask, NvmCtx.ChannelsDefaultMask, 1 );
+ break;
+ }
+ case INIT_TYPE_RESTORE_CTX:
+ {
+ if( params->NvmCtx != 0 )
+ {
+ memcpy1( (uint8_t*) &NvmCtx, (uint8_t*) params->NvmCtx, sizeof( NvmCtx ) );
+ }
break;
}
- case INIT_TYPE_RESTORE:
+ case INIT_TYPE_RESTORE_DEFAULT_CHANNELS:
{
// Restore channels default mask
- ChannelsMask[0] |= ChannelsDefaultMask[0];
+ NvmCtx.ChannelsMask[0] |= NvmCtx.ChannelsDefaultMask[0];
+
+ // Channels
+ NvmCtx.Channels[0] = ( ChannelParams_t ) CN779_LC1;
+ NvmCtx.Channels[1] = ( ChannelParams_t ) CN779_LC2;
+ NvmCtx.Channels[2] = ( ChannelParams_t ) CN779_LC3;
break;
}
default:
@@ -337,10 +394,20 @@ void RegionCN779InitDefaults( InitType_t type )
}
}
+void* RegionCN779GetNvmCtx( GetNvmCtxParams_t* params )
+{
+ params->nvmCtxSize = sizeof( RegionCN779NvmCtx_t );
+ return &NvmCtx;
+}
+
bool RegionCN779Verify( VerifyParams_t* verify, PhyAttribute_t phyAttribute )
{
switch( phyAttribute )
{
+ case PHY_FREQUENCY:
+ {
+ return VerifyRfFreq( verify->Frequency );
+ }
case PHY_TX_DR:
{
return RegionCommonValueInRange( verify->DatarateParams.Datarate, CN779_TX_MIN_DATARATE, CN779_TX_MAX_DATARATE );
@@ -363,18 +430,9 @@ bool RegionCN779Verify( VerifyParams_t* verify, PhyAttribute_t phyAttribute )
{
return CN779_DUTY_CYCLE_ENABLED;
}
- case PHY_NB_JOIN_TRIALS:
- {
- if( verify->NbJoinTrials < 48 )
- {
- return false;
- }
- break;
- }
default:
return false;
}
- return true;
}
void RegionCN779ApplyCFList( ApplyCFListParams_t* applyCFList )
@@ -392,6 +450,12 @@ void RegionCN779ApplyCFList( ApplyCFListParams_t* applyCFList )
return;
}
+ // Last byte CFListType must be 0 to indicate the CFList contains a list of frequencies
+ if( applyCFList->Payload[15] != 0 )
+ {
+ return;
+ }
+
// Last byte is RFU, don't take it into account
for( uint8_t i = 0, chanIdx = CN779_NUMB_DEFAULT_CHANNELS; chanIdx < CN779_MAX_NB_CHANNELS; i+=3, chanIdx++ )
{
@@ -436,12 +500,12 @@ bool RegionCN779ChanMaskSet( ChanMaskSetParams_t* chanMaskSet )
{
case CHANNELS_MASK:
{
- RegionCommonChanMaskCopy( ChannelsMask, chanMaskSet->ChannelsMaskIn, 1 );
+ RegionCommonChanMaskCopy( NvmCtx.ChannelsMask, chanMaskSet->ChannelsMaskIn, 1 );
break;
}
case CHANNELS_DEFAULT_MASK:
{
- RegionCommonChanMaskCopy( ChannelsDefaultMask, chanMaskSet->ChannelsMaskIn, 1 );
+ RegionCommonChanMaskCopy( NvmCtx.ChannelsDefaultMask, chanMaskSet->ChannelsMaskIn, 1 );
break;
}
default:
@@ -450,66 +514,6 @@ bool RegionCN779ChanMaskSet( ChanMaskSetParams_t* chanMaskSet )
return true;
}
-bool RegionCN779AdrNext( AdrNextParams_t* adrNext, int8_t* drOut, int8_t* txPowOut, uint32_t* adrAckCounter )
-{
- bool adrAckReq = false;
- int8_t datarate = adrNext->Datarate;
- int8_t txPower = adrNext->TxPower;
- GetPhyParams_t getPhy;
- PhyParam_t phyParam;
-
- // Report back the adr ack counter
- *adrAckCounter = adrNext->AdrAckCounter;
-
- if( adrNext->AdrEnabled == true )
- {
- if( datarate == CN779_TX_MIN_DATARATE )
- {
- *adrAckCounter = 0;
- adrAckReq = false;
- }
- else
- {
- if( adrNext->AdrAckCounter >= CN779_ADR_ACK_LIMIT )
- {
- adrAckReq = true;
- txPower = CN779_MAX_TX_POWER;
- }
- else
- {
- adrAckReq = false;
- }
- if( adrNext->AdrAckCounter >= ( CN779_ADR_ACK_LIMIT + CN779_ADR_ACK_DELAY ) )
- {
- if( ( adrNext->AdrAckCounter % CN779_ADR_ACK_DELAY ) == 1 )
- {
- // Decrease the datarate
- getPhy.Attribute = PHY_NEXT_LOWER_TX_DR;
- getPhy.Datarate = datarate;
- getPhy.UplinkDwellTime = adrNext->UplinkDwellTime;
- phyParam = RegionCN779GetPhyParam( &getPhy );
- datarate = phyParam.Value;
-
- if( datarate == CN779_TX_MIN_DATARATE )
- {
- // We must set adrAckReq to false as soon as we reach the lowest datarate
- adrAckReq = false;
- if( adrNext->UpdateChanMask == true )
- {
- // Re-enable default channels
- ChannelsMask[0] |= LC( 1 ) + LC( 2 ) + LC( 3 );
- }
- }
- }
- }
- }
- }
-
- *drOut = datarate;
- *txPowOut = txPower;
- return adrAckReq;
-}
-
void RegionCN779ComputeRxWindowParameters( int8_t datarate, uint8_t minRxSymbols, uint32_t rxError, RxConfigParams_t *rxConfigParams )
{
double tSymbol = 0.0;
@@ -527,7 +531,7 @@ void RegionCN779ComputeRxWindowParameters( int8_t datarate, uint8_t minRxSymbols
tSymbol = RegionCommonComputeSymbolTimeLoRa( DataratesCN779[rxConfigParams->Datarate], BandwidthsCN779[rxConfigParams->Datarate] );
}
- RegionCommonComputeRxWindowParameters( tSymbol, minRxSymbols, rxError, RADIO_WAKEUP_TIME, &rxConfigParams->WindowTimeout, &rxConfigParams->WindowOffset );
+ RegionCommonComputeRxWindowParameters( tSymbol, minRxSymbols, rxError, Radio.GetWakeupTime( ), &rxConfigParams->WindowTimeout, &rxConfigParams->WindowOffset );
}
bool RegionCN779RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate )
@@ -543,14 +547,14 @@ bool RegionCN779RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate )
return false;
}
- if( rxConfig->Window == 0 )
+ if( rxConfig->RxSlot == RX_SLOT_WIN_1 )
{
// Apply window 1 frequency
- frequency = Channels[rxConfig->Channel].Frequency;
+ frequency = NvmCtx.Channels[rxConfig->Channel].Frequency;
// Apply the alternative RX 1 window frequency, if it is available
- if( Channels[rxConfig->Channel].Rx1Frequency != 0 )
+ if( NvmCtx.Channels[rxConfig->Channel].Rx1Frequency != 0 )
{
- frequency = Channels[rxConfig->Channel].Rx1Frequency;
+ frequency = NvmCtx.Channels[rxConfig->Channel].Rx1Frequency;
}
}
@@ -589,7 +593,7 @@ bool RegionCN779TxConfig( TxConfigParams_t* txConfig, int8_t* txPower, TimerTime
{
RadioModems_t modem;
int8_t phyDr = DataratesCN779[txConfig->Datarate];
- int8_t txPowerLimited = LimitTxPower( txConfig->TxPower, Bands[Channels[txConfig->Channel].Band].TxMaxPower, txConfig->Datarate, ChannelsMask );
+ int8_t txPowerLimited = LimitTxPower( txConfig->TxPower, NvmCtx.Bands[NvmCtx.Channels[txConfig->Channel].Band].TxMaxPower, txConfig->Datarate, NvmCtx.ChannelsMask );
uint32_t bandwidth = GetBandwidth( txConfig->Datarate );
int8_t phyTxPower = 0;
@@ -597,17 +601,17 @@ bool RegionCN779TxConfig( TxConfigParams_t* txConfig, int8_t* txPower, TimerTime
phyTxPower = RegionCommonComputeTxPower( txPowerLimited, txConfig->MaxEirp, txConfig->AntennaGain );
// Setup the radio frequency
- Radio.SetChannel( Channels[txConfig->Channel].Frequency );
+ Radio.SetChannel( NvmCtx.Channels[txConfig->Channel].Frequency );
if( txConfig->Datarate == DR_7 )
{ // High Speed FSK channel
modem = MODEM_FSK;
- Radio.SetTxConfig( modem, phyTxPower, 25000, bandwidth, phyDr * 1000, 0, 5, false, true, 0, 0, false, 3000 );
+ Radio.SetTxConfig( modem, phyTxPower, 25000, bandwidth, phyDr * 1000, 0, 5, false, true, 0, 0, false, 4000 );
}
else
{
modem = MODEM_LORA;
- Radio.SetTxConfig( modem, phyTxPower, 0, bandwidth, phyDr, 1, 8, false, true, 0, 0, false, 3000 );
+ Radio.SetTxConfig( modem, phyTxPower, 0, bandwidth, phyDr, 1, 8, false, true, 0, 0, false, 4000 );
}
// Setup maximum payload lenght of the radio driver
@@ -664,7 +668,7 @@ uint8_t RegionCN779LinkAdrReq( LinkAdrReqParams_t* linkAdrReq, int8_t* drOut, in
{
if( linkAdrParams.ChMaskCtrl == 6 )
{
- if( Channels[i].Frequency != 0 )
+ if( NvmCtx.Channels[i].Frequency != 0 )
{
chMask |= 1 << i;
}
@@ -672,7 +676,7 @@ uint8_t RegionCN779LinkAdrReq( LinkAdrReqParams_t* linkAdrReq, int8_t* drOut, in
else
{
if( ( ( chMask & ( 1 << i ) ) != 0 ) &&
- ( Channels[i].Frequency == 0 ) )
+ ( NvmCtx.Channels[i].Frequency == 0 ) )
{// Trying to enable an undefined channel
status &= 0xFE; // Channel mask KO
}
@@ -698,9 +702,10 @@ uint8_t RegionCN779LinkAdrReq( LinkAdrReqParams_t* linkAdrReq, int8_t* drOut, in
linkAdrVerifyParams.ChannelsMask = &chMask;
linkAdrVerifyParams.MinDatarate = ( int8_t )phyParam.Value;
linkAdrVerifyParams.MaxDatarate = CN779_TX_MAX_DATARATE;
- linkAdrVerifyParams.Channels = Channels;
+ linkAdrVerifyParams.Channels = NvmCtx.Channels;
linkAdrVerifyParams.MinTxPower = CN779_MIN_TX_POWER;
linkAdrVerifyParams.MaxTxPower = CN779_MAX_TX_POWER;
+ linkAdrVerifyParams.Version = linkAdrReq->Version;
// Verify the parameters and update, if necessary
status = RegionCommonLinkAdrReqVerifyParams( &linkAdrVerifyParams, &linkAdrParams.Datarate, &linkAdrParams.TxPower, &linkAdrParams.NbRep );
@@ -709,9 +714,9 @@ uint8_t RegionCN779LinkAdrReq( LinkAdrReqParams_t* linkAdrReq, int8_t* drOut, in
if( status == 0x07 )
{
// Set the channels mask to a default value
- memset( ChannelsMask, 0, sizeof( ChannelsMask ) );
+ memset1( ( uint8_t* ) NvmCtx.ChannelsMask, 0, sizeof( NvmCtx.ChannelsMask ) );
// Update the channels mask
- ChannelsMask[0] = chMask;
+ NvmCtx.ChannelsMask[0] = chMask;
}
// Update status variables
@@ -728,7 +733,7 @@ uint8_t RegionCN779RxParamSetupReq( RxParamSetupReqParams_t* rxParamSetupReq )
uint8_t status = 0x07;
// Verify radio frequency
- if( Radio.CheckRfFrequency( rxParamSetupReq->Frequency ) == false )
+ if( VerifyRfFreq( rxParamSetupReq->Frequency ) == false )
{
status &= 0xFE; // Channel frequency KO
}
@@ -811,13 +816,13 @@ uint8_t RegionCN779DlChannelReq( DlChannelReqParams_t* dlChannelReq )
uint8_t status = 0x03;
// Verify if the frequency is supported
- if( VerifyTxFreq( dlChannelReq->Rx1Frequency ) == false )
+ if( VerifyRfFreq( dlChannelReq->Rx1Frequency ) == false )
{
status &= 0xFE;
}
// Verify if an uplink frequency exists
- if( Channels[dlChannelReq->ChannelId].Frequency == 0 )
+ if( NvmCtx.Channels[dlChannelReq->ChannelId].Frequency == 0 )
{
status &= 0xFD;
}
@@ -825,49 +830,23 @@ uint8_t RegionCN779DlChannelReq( DlChannelReqParams_t* dlChannelReq )
// Apply Rx1 frequency, if the status is OK
if( status == 0x03 )
{
- Channels[dlChannelReq->ChannelId].Rx1Frequency = dlChannelReq->Rx1Frequency;
+ NvmCtx.Channels[dlChannelReq->ChannelId].Rx1Frequency = dlChannelReq->Rx1Frequency;
}
return status;
}
-int8_t RegionCN779AlternateDr( AlternateDrParams_t* alternateDr )
+int8_t RegionCN779AlternateDr( int8_t currentDr, AlternateDrType_t type )
{
- int8_t datarate = 0;
-
- if( ( alternateDr->NbTrials % 48 ) == 0 )
- {
- datarate = DR_0;
- }
- else if( ( alternateDr->NbTrials % 32 ) == 0 )
- {
- datarate = DR_1;
- }
- else if( ( alternateDr->NbTrials % 24 ) == 0 )
- {
- datarate = DR_2;
- }
- else if( ( alternateDr->NbTrials % 16 ) == 0 )
- {
- datarate = DR_3;
- }
- else if( ( alternateDr->NbTrials % 8 ) == 0 )
- {
- datarate = DR_4;
- }
- else
- {
- datarate = DR_5;
- }
- return datarate;
+ return currentDr;
}
void RegionCN779CalcBackOff( CalcBackOffParams_t* calcBackOff )
{
RegionCommonCalcBackOffParams_t calcBackOffParams;
- calcBackOffParams.Channels = Channels;
- calcBackOffParams.Bands = Bands;
+ calcBackOffParams.Channels = NvmCtx.Channels;
+ calcBackOffParams.Bands = NvmCtx.Bands;
calcBackOffParams.LastTxIsJoinRequest = calcBackOff->LastTxIsJoinRequest;
calcBackOffParams.Joined = calcBackOff->Joined;
calcBackOffParams.DutyCycleEnabled = calcBackOff->DutyCycleEnabled;
@@ -878,35 +857,36 @@ void RegionCN779CalcBackOff( CalcBackOffParams_t* calcBackOff )
RegionCommonCalcBackOff( &calcBackOffParams );
}
-bool RegionCN779NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff )
+LoRaMacStatus_t RegionCN779NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff )
{
uint8_t nbEnabledChannels = 0;
uint8_t delayTx = 0;
uint8_t enabledChannels[CN779_MAX_NB_CHANNELS] = { 0 };
TimerTime_t nextTxDelay = 0;
- if( RegionCommonCountChannels( ChannelsMask, 0, 1 ) == 0 )
+ if( RegionCommonCountChannels( NvmCtx.ChannelsMask, 0, 1 ) == 0 )
{ // Reactivate default channels
- ChannelsMask[0] |= LC( 1 ) + LC( 2 ) + LC( 3 );
+ NvmCtx.ChannelsMask[0] |= LC( 1 ) + LC( 2 ) + LC( 3 );
}
- if( nextChanParams->AggrTimeOff <= TimerGetElapsedTime( nextChanParams->LastAggrTx ) )
+ TimerTime_t elapsed = TimerGetElapsedTime( nextChanParams->LastAggrTx );
+ if( ( nextChanParams->LastAggrTx == 0 ) || ( nextChanParams->AggrTimeOff <= elapsed ) )
{
// Reset Aggregated time off
*aggregatedTimeOff = 0;
// Update bands Time OFF
- nextTxDelay = RegionCommonUpdateBandTimeOff( nextChanParams->Joined, nextChanParams->DutyCycleEnabled, Bands, CN779_MAX_NB_BANDS );
+ nextTxDelay = RegionCommonUpdateBandTimeOff( nextChanParams->Joined, nextChanParams->DutyCycleEnabled, NvmCtx.Bands, CN779_MAX_NB_BANDS );
// Search how many channels are enabled
nbEnabledChannels = CountNbOfEnabledChannels( nextChanParams->Joined, nextChanParams->Datarate,
- ChannelsMask, Channels,
- Bands, enabledChannels, &delayTx );
+ NvmCtx.ChannelsMask, NvmCtx.Channels,
+ NvmCtx.Bands, enabledChannels, &delayTx );
}
else
{
delayTx++;
- nextTxDelay = nextChanParams->AggrTimeOff - TimerGetElapsedTime( nextChanParams->LastAggrTx );
+ nextTxDelay = nextChanParams->AggrTimeOff - elapsed;
}
if( nbEnabledChannels > 0 )
@@ -915,7 +895,7 @@ bool RegionCN779NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel,
*channel = enabledChannels[randr( 0, nbEnabledChannels - 1 )];
*time = 0;
- return true;
+ return LORAMAC_STATUS_OK;
}
else
{
@@ -923,22 +903,26 @@ bool RegionCN779NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel,
{
// Delay transmission due to AggregatedTimeOff or to a band time off
*time = nextTxDelay;
- return true;
+ return LORAMAC_STATUS_DUTYCYCLE_RESTRICTED;
}
// Datarate not supported by any channel, restore defaults
- ChannelsMask[0] |= LC( 1 ) + LC( 2 ) + LC( 3 );
+ NvmCtx.ChannelsMask[0] |= LC( 1 ) + LC( 2 ) + LC( 3 );
*time = 0;
- return false;
+ return LORAMAC_STATUS_NO_CHANNEL_FOUND;
}
}
LoRaMacStatus_t RegionCN779ChannelAdd( ChannelAddParams_t* channelAdd )
{
- uint8_t band = 0;
bool drInvalid = false;
bool freqInvalid = false;
uint8_t id = channelAdd->ChannelId;
+ if( id < CN779_NUMB_DEFAULT_CHANNELS )
+ {
+ return LORAMAC_STATUS_FREQ_AND_DR_INVALID;
+ }
+
if( id >= CN779_MAX_NB_CHANNELS )
{
return LORAMAC_STATUS_PARAMETER_INVALID;
@@ -958,30 +942,10 @@ LoRaMacStatus_t RegionCN779ChannelAdd( ChannelAddParams_t* channelAdd )
drInvalid = true;
}
- // Default channels don't accept all values
- if( id < CN779_NUMB_DEFAULT_CHANNELS )
- {
- // Validate the datarate range for min: must be DR_0
- if( channelAdd->NewChannel->DrRange.Fields.Min > DR_0 )
- {
- drInvalid = true;
- }
- // Validate the datarate range for max: must be DR_5 <= Max <= TX_MAX_DATARATE
- if( RegionCommonValueInRange( channelAdd->NewChannel->DrRange.Fields.Max, DR_5, CN779_TX_MAX_DATARATE ) == false )
- {
- drInvalid = true;
- }
- // We are not allowed to change the frequency
- if( channelAdd->NewChannel->Frequency != Channels[id].Frequency )
- {
- freqInvalid = true;
- }
- }
-
// Check frequency
if( freqInvalid == false )
{
- if( VerifyTxFreq( channelAdd->NewChannel->Frequency ) == false )
+ if( VerifyRfFreq( channelAdd->NewChannel->Frequency ) == false )
{
freqInvalid = true;
}
@@ -1001,9 +965,9 @@ LoRaMacStatus_t RegionCN779ChannelAdd( ChannelAddParams_t* channelAdd )
return LORAMAC_STATUS_FREQUENCY_INVALID;
}
- memcpy( &(Channels[id]), channelAdd->NewChannel, sizeof( Channels[id] ) );
- Channels[id].Band = band;
- ChannelsMask[0] |= ( 1 << id );
+ memcpy1( ( uint8_t* ) &(NvmCtx.Channels[id]), ( uint8_t* ) channelAdd->NewChannel, sizeof( NvmCtx.Channels[id] ) );
+ NvmCtx.Channels[id].Band = 0;
+ NvmCtx.ChannelsMask[0] |= ( 1 << id );
return LORAMAC_STATUS_OK;
}
@@ -1017,16 +981,16 @@ bool RegionCN779ChannelsRemove( ChannelRemoveParams_t* channelRemove )
}
// Remove the channel from the list of channels
- Channels[id] = ( ChannelParams_t ){ 0, 0, { 0 }, 0 };
+ NvmCtx.Channels[id] = ( ChannelParams_t ){ 0, 0, { 0 }, 0 };
- return RegionCommonChanDisable( ChannelsMask, id, CN779_MAX_NB_CHANNELS );
+ return RegionCommonChanDisable( NvmCtx.ChannelsMask, id, CN779_MAX_NB_CHANNELS );
}
void RegionCN779SetContinuousWave( ContinuousWaveParams_t* continuousWave )
{
- int8_t txPowerLimited = LimitTxPower( continuousWave->TxPower, Bands[Channels[continuousWave->Channel].Band].TxMaxPower, continuousWave->Datarate, ChannelsMask );
+ int8_t txPowerLimited = LimitTxPower( continuousWave->TxPower, NvmCtx.Bands[NvmCtx.Channels[continuousWave->Channel].Band].TxMaxPower, continuousWave->Datarate, NvmCtx.ChannelsMask );
int8_t phyTxPower = 0;
- uint32_t frequency = Channels[continuousWave->Channel].Frequency;
+ uint32_t frequency = NvmCtx.Channels[continuousWave->Channel].Frequency;
// Calculate physical TX power
phyTxPower = RegionCommonComputeTxPower( txPowerLimited, continuousWave->MaxEirp, continuousWave->AntennaGain );
@@ -1044,3 +1008,75 @@ uint8_t RegionCN779ApplyDrOffset( uint8_t downlinkDwellTime, int8_t dr, int8_t d
}
return datarate;
}
+
+void RegionCN779RxBeaconSetup( RxBeaconSetup_t* rxBeaconSetup, uint8_t* outDr )
+{
+ RegionCommonRxBeaconSetupParams_t regionCommonRxBeaconSetup;
+
+ regionCommonRxBeaconSetup.Datarates = DataratesCN779;
+ regionCommonRxBeaconSetup.Frequency = rxBeaconSetup->Frequency;
+ regionCommonRxBeaconSetup.BeaconSize = CN779_BEACON_SIZE;
+ regionCommonRxBeaconSetup.BeaconDatarate = CN779_BEACON_CHANNEL_DR;
+ regionCommonRxBeaconSetup.BeaconChannelBW = CN779_BEACON_CHANNEL_BW;
+ regionCommonRxBeaconSetup.RxTime = rxBeaconSetup->RxTime;
+ regionCommonRxBeaconSetup.SymbolTimeout = rxBeaconSetup->SymbolTimeout;
+
+ RegionCommonRxBeaconSetup( ®ionCommonRxBeaconSetup );
+
+ // Store downlink datarate
+ *outDr = CN779_BEACON_CHANNEL_DR;
+}
+
+LoRaMacStatus_t RegionCN779ChannelManualAdd( ChannelAddParams_t* channelAdd )
+{
+ bool drInvalid = false;
+ bool freqInvalid = false;
+ uint8_t id = channelAdd->ChannelId;
+
+ if( id >= CN779_MAX_NB_CHANNELS )
+ {
+ return LORAMAC_STATUS_PARAMETER_INVALID;
+ }
+
+ // Validate the datarate range
+ if( RegionCommonValueInRange( channelAdd->NewChannel->DrRange.Fields.Min, CN779_TX_MIN_DATARATE, CN779_TX_MAX_DATARATE ) == false )
+ {
+ drInvalid = true;
+ }
+ if( RegionCommonValueInRange( channelAdd->NewChannel->DrRange.Fields.Max, CN779_TX_MIN_DATARATE, CN779_TX_MAX_DATARATE ) == false )
+ {
+ drInvalid = true;
+ }
+ if( channelAdd->NewChannel->DrRange.Fields.Min > channelAdd->NewChannel->DrRange.Fields.Max )
+ {
+ drInvalid = true;
+ }
+
+ // Check frequency
+ if( freqInvalid == false )
+ {
+ if( VerifyRfFreq( channelAdd->NewChannel->Frequency ) == false )
+ {
+ freqInvalid = true;
+ }
+ }
+
+ // Check status
+ if( ( drInvalid == true ) && ( freqInvalid == true ) )
+ {
+ return LORAMAC_STATUS_FREQ_AND_DR_INVALID;
+ }
+ if( drInvalid == true )
+ {
+ return LORAMAC_STATUS_DATARATE_INVALID;
+ }
+ if( freqInvalid == true )
+ {
+ return LORAMAC_STATUS_FREQUENCY_INVALID;
+ }
+
+ memcpy1( ( uint8_t* ) &(NvmCtx.Channels[id]), ( uint8_t* ) channelAdd->NewChannel, sizeof( NvmCtx.Channels[id] ) );
+ NvmCtx.Channels[id].Band = 0;
+ NvmCtx.ChannelsMask[0] |= ( 1 << id );
+ return LORAMAC_STATUS_OK;
+}
diff --git a/lib/lora/mac/region/RegionCN779.h b/lib/lora/mac/region/RegionCN779.h
index 1d1d8bfa98..458b9d9303 100644
--- a/lib/lora/mac/region/RegionCN779.h
+++ b/lib/lora/mac/region/RegionCN779.h
@@ -12,7 +12,7 @@
* \____ \| ___ | (_ _) ___ |/ ___) _ \
* _____) ) ____| | | || |_| ____( (___| | | |
* (______/|_____)_|_|_| \__)_____)\____)_| |_|
- * (C)2013 Semtech
+ * (C)2013-2017 Semtech
*
* ___ _____ _ ___ _ _____ ___ ___ ___ ___
* / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
@@ -28,6 +28,8 @@
*
* \author Daniel Jaeckle ( STACKFORCE )
*
+ * \author Johannes Bruder ( STACKFORCE )
+ *
* \defgroup REGIONCN779 Region CN779
* Implementation according to LoRaWAN Specification v1.0.2.
* \{
@@ -35,6 +37,13 @@
#ifndef __REGION_CN779_H__
#define __REGION_CN779_H__
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include "Region.h"
+
/*!
* LoRaMac maximum number of channels
*/
@@ -187,6 +196,44 @@
*/
#define CN779_RX_WND_2_DR DR_0
+/*
+ * CLASS B
+ */
+/*!
+ * Beacon frequency
+ */
+#define CN779_BEACON_CHANNEL_FREQ 785000000
+
+/*!
+ * Payload size of a beacon frame
+ */
+#define CN779_BEACON_SIZE 17
+
+/*!
+ * Size of RFU 1 field
+ */
+#define CN779_RFU1_SIZE 2
+
+/*!
+ * Size of RFU 2 field
+ */
+#define CN779_RFU2_SIZE 0
+
+/*!
+ * Datarate of the beacon channel
+ */
+#define CN779_BEACON_CHANNEL_DR DR_3
+
+/*!
+ * Bandwith of the beacon channel
+ */
+#define CN779_BEACON_CHANNEL_BW 0
+
+/*!
+ * Ping slot channel datarate
+ */
+#define CN779_PING_SLOT_CHANNEL_DR DR_3
+
/*!
* LoRaMac maximum number of bands
*/
@@ -194,9 +241,9 @@
/*!
* Band 0 definition
- * { DutyCycle, TxMaxPower, LastTxDoneTime, TimeOff }
+ * { DutyCycle, TxMaxPower, LastJoinTxDoneTime, LastTxDoneTime, TimeOff }
*/
-#define CN779_BAND0 { 100, CN779_MAX_TX_POWER, 0, 0 } // 1.0 %
+#define CN779_BAND0 { 100, CN779_MAX_TX_POWER, 0, 0, 0 } // 1.0 %
/*!
* LoRaMac default channel 1
@@ -261,7 +308,16 @@ void RegionCN779SetBandTxDone( SetBandTxDoneParams_t* txDone );
*
* \param [IN] type Sets the initialization type.
*/
-void RegionCN779InitDefaults( InitType_t type );
+void RegionCN779InitDefaults( InitDefaultsParams_t* params );
+
+/*!
+ * \brief Returns a pointer to the internal context and its size.
+ *
+ * \param [OUT] params Pointer to the function parameters.
+ *
+ * \retval Points to a structure where the module store its non-volatile context.
+ */
+void* RegionCN779GetNvmCtx( GetNvmCtxParams_t* params );
/*!
* \brief Verifies a parameter.
@@ -291,21 +347,6 @@ void RegionCN779ApplyCFList( ApplyCFListParams_t* applyCFList );
*/
bool RegionCN779ChanMaskSet( ChanMaskSetParams_t* chanMaskSet );
-/*!
- * \brief Calculates the next datarate to set, when ADR is on or off.
- *
- * \param [IN] adrNext Pointer to the function parameters.
- *
- * \param [OUT] drOut The calculated datarate for the next TX.
- *
- * \param [OUT] txPowOut The TX power for the next TX.
- *
- * \param [OUT] adrAckCounter The calculated ADR acknowledgement counter.
- *
- * \retval Returns true, if an ADR request should be performed.
- */
-bool RegionCN779AdrNext( AdrNextParams_t* adrNext, int8_t* drOut, int8_t* txPowOut, uint32_t* adrAckCounter );
-
/*!
* Computes the Rx window timeout and offset.
*
@@ -395,11 +436,11 @@ uint8_t RegionCN779DlChannelReq( DlChannelReqParams_t* dlChannelReq );
/*!
* \brief Alternates the datarate of the channel for the join request.
*
- * \param [IN] alternateDr Pointer to the function parameters.
+ * \param [IN] currentDr Current datarate.
*
* \retval Datarate to apply.
*/
-int8_t RegionCN779AlternateDr( AlternateDrParams_t* alternateDr );
+int8_t RegionCN779AlternateDr( int8_t currentDr, AlternateDrType_t type );
/*!
* \brief Calculates the back-off time.
@@ -420,7 +461,7 @@ void RegionCN779CalcBackOff( CalcBackOffParams_t* calcBackOff );
*
* \retval Function status [1: OK, 0: Unable to find a channel on the current datarate]
*/
-bool RegionCN779NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff );
+LoRaMacStatus_t RegionCN779NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff );
/*!
* \brief Adds a channel.
@@ -430,6 +471,7 @@ bool RegionCN779NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel,
* \retval Status of the operation.
*/
LoRaMacStatus_t RegionCN779ChannelAdd( ChannelAddParams_t* channelAdd );
+LoRaMacStatus_t RegionCN779ChannelManualAdd( ChannelAddParams_t* channelAdd );
/*!
* \brief Removes a channel.
@@ -460,6 +502,17 @@ void RegionCN779SetContinuousWave( ContinuousWaveParams_t* continuousWave );
*/
uint8_t RegionCN779ApplyDrOffset( uint8_t downlinkDwellTime, int8_t dr, int8_t drOffset );
+/*!
+ * \brief Sets the radio into beacon reception mode
+ *
+ * \param [IN] rxBeaconSetup Pointer to the function parameters
+ */
+ void RegionCN779RxBeaconSetup( RxBeaconSetup_t* rxBeaconSetup, uint8_t* outDr );
+
/*! \} defgroup REGIONCN779 */
+#ifdef __cplusplus
+}
+#endif
+
#endif // __REGION_CN779_H__
diff --git a/lib/lora/mac/region/RegionCommon.c b/lib/lora/mac/region/RegionCommon.c
index 6b209c2e4a..4b3b677926 100644
--- a/lib/lora/mac/region/RegionCommon.c
+++ b/lib/lora/mac/region/RegionCommon.c
@@ -1,42 +1,49 @@
-/*
- / _____) _ | |
-( (____ _____ ____ _| |_ _____ ____| |__
- \____ \| ___ | (_ _) ___ |/ ___) _ \
- _____) ) ____| | | || |_| ____( (___| | | |
-(______/|_____)_|_|_| \__)_____)\____)_| |_|
- (C)2013 Semtech
- ___ _____ _ ___ _ _____ ___ ___ ___ ___
-/ __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
-\__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
-|___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
-embedded.connectivity.solutions===============
-
-Description: LoRa MAC common region implementation
-
-License: Revised BSD License, see LICENSE.TXT file include in the project
-
-Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jaeckle ( STACKFORCE )
-*/
+/*!
+ * \file RegionCommon.c
+ *
+ * \brief LoRa MAC common region implementation
+ *
+ * \copyright Revised BSD License, see section \ref LICENSE.
+ *
+ * \code
+ * ______ _
+ * / _____) _ | |
+ * ( (____ _____ ____ _| |_ _____ ____| |__
+ * \____ \| ___ | (_ _) ___ |/ ___) _ \
+ * _____) ) ____| | | || |_| ____( (___| | | |
+ * (______/|_____)_|_|_| \__)_____)\____)_| |_|
+ * (C)2013-2017 Semtech
+ *
+ * ___ _____ _ ___ _ _____ ___ ___ ___ ___
+ * / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
+ * \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
+ * |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
+ * embedded.connectivity.solutions===============
+ *
+ * \endcode
+ *
+ * \author Miguel Luis ( Semtech )
+ *
+ * \author Gregory Cristian ( Semtech )
+ *
+ * \author Daniel Jaeckle ( STACKFORCE )
+ */
#include
#include
#include
#include
-
+#include "radio.h"
#include "lora/system/timer.h"
#include "utilities.h"
#include "lora/mac/LoRaMac.h"
#include "RegionCommon.h"
#include "esp_attr.h"
-
-
#define BACKOFF_DC_1_HOUR 100
#define BACKOFF_DC_10_HOURS 1000
#define BACKOFF_DC_24_HOURS 10000
-
-
static uint8_t CountChannels( uint16_t mask, uint8_t nbBits )
{
uint8_t nbActiveBits = 0;
@@ -51,17 +58,15 @@ static uint8_t CountChannels( uint16_t mask, uint8_t nbBits )
return nbActiveBits;
}
-
-
-uint16_t RegionCommonGetJoinDc( TimerTime_t elapsedTime )
+uint16_t RegionCommonGetJoinDc( SysTime_t elapsedTime )
{
uint16_t dutyCycle = 0;
- if( elapsedTime < 3600000 )
+ if( elapsedTime.Seconds < 3600 )
{
dutyCycle = BACKOFF_DC_1_HOUR;
}
- else if( elapsedTime < ( 3600000 + 36000000 ) )
+ else if( elapsedTime.Seconds < ( 3600 + 36000 ) )
{
dutyCycle = BACKOFF_DC_10_HOURS;
}
@@ -149,7 +154,7 @@ void RegionCommonChanMaskCopy( uint16_t* channelsMaskDest, uint16_t* channelsMas
}
}
-IRAM_ATTR void RegionCommonSetBandTxDone( bool joined, Band_t* band, TimerTime_t lastTxDone )
+void RegionCommonSetBandTxDone( bool joined, Band_t* band, TimerTime_t lastTxDone )
{
if( joined == true )
{
@@ -164,15 +169,17 @@ IRAM_ATTR void RegionCommonSetBandTxDone( bool joined, Band_t* band, TimerTime_t
TimerTime_t RegionCommonUpdateBandTimeOff( bool joined, bool dutyCycle, Band_t* bands, uint8_t nbBands )
{
- TimerTime_t nextTxDelay = ( TimerTime_t )( -1 );
+ TimerTime_t nextTxDelay = TIMERTIME_T_MAX;
// Update bands Time OFF
for( uint8_t i = 0; i < nbBands; i++ )
{
if( joined == false )
{
- uint32_t txDoneTime = MAX( TimerGetElapsedTime( bands[i].LastJoinTxDoneTime ),
- ( dutyCycle == true ) ? TimerGetElapsedTime( bands[i].LastTxDoneTime ) : 0 );
+ TimerTime_t elapsedJoin = TimerGetElapsedTime( bands[i].LastJoinTxDoneTime );
+ TimerTime_t elapsedTx = TimerGetElapsedTime( bands[i].LastTxDoneTime );
+ TimerTime_t txDoneTime = MAX( elapsedJoin,
+ ( dutyCycle == true ) ? elapsedTx : 0 );
if( bands[i].TimeOff <= txDoneTime )
{
@@ -187,14 +194,14 @@ TimerTime_t RegionCommonUpdateBandTimeOff( bool joined, bool dutyCycle, Band_t*
{
if( dutyCycle == true )
{
- if( bands[i].TimeOff <= TimerGetElapsedTime( bands[i].LastTxDoneTime ) )
+ TimerTime_t elapsed = TimerGetElapsedTime( bands[i].LastTxDoneTime );
+ if( bands[i].TimeOff <= elapsed )
{
bands[i].TimeOff = 0;
}
if( bands[i].TimeOff != 0 )
{
- nextTxDelay = MIN( bands[i].TimeOff - TimerGetElapsedTime( bands[i].LastTxDoneTime ),
- nextTxDelay );
+ nextTxDelay = MIN( bands[i].TimeOff - elapsed, nextTxDelay );
}
}
else
@@ -204,7 +211,8 @@ TimerTime_t RegionCommonUpdateBandTimeOff( bool joined, bool dutyCycle, Band_t*
}
}
}
- return nextTxDelay;
+
+ return ( nextTxDelay == TIMERTIME_T_MAX ) ? 0 : nextTxDelay;
}
uint8_t RegionCommonParseLinkAdrReq( uint8_t* payload, RegionCommonLinkAdrParams_t* linkAdrParams )
@@ -241,16 +249,10 @@ uint8_t RegionCommonLinkAdrReqVerifyParams( RegionCommonLinkAdrReqVerifyParams_t
// Handle the case when ADR is off.
if( verifyParams->AdrEnabled == false )
{
- // When ADR is off, we are allowed to change the channels mask and the NbRep,
- // if the datarate and the TX power of the LinkAdrReq are set to 0x0F.
- if( ( verifyParams->Datarate != 0x0F ) || ( verifyParams->TxPower != 0x0F ) )
- {
- status = 0;
- nbRepetitions = verifyParams->CurrentNbRep;
- }
- // Get the current datarate and tx power
- datarate = verifyParams->CurrentDatarate;
- txPower = verifyParams->CurrentTxPower;
+ // When ADR is off, we are allowed to change the channels mask
+ nbRepetitions = verifyParams->CurrentNbRep;
+ datarate = verifyParams->CurrentDatarate;
+ txPower = verifyParams->CurrentTxPower;
}
if( status != 0 )
@@ -281,8 +283,8 @@ uint8_t RegionCommonLinkAdrReqVerifyParams( RegionCommonLinkAdrReqVerifyParams_t
if( status == 0x07 )
{
if( nbRepetitions == 0 )
- { // Keep the current one
- nbRepetitions = verifyParams->CurrentNbRep;
+ { // Restore the default value according to the LoRaWAN specification
+ nbRepetitions = 1;
}
}
@@ -361,3 +363,32 @@ void RegionCommonCalcBackOff( RegionCommonCalcBackOffParams_t* calcBackOffParams
}
}
}
+
+
+void RegionCommonRxBeaconSetup( RegionCommonRxBeaconSetupParams_t* rxBeaconSetupParams )
+{
+ bool rxContinuous = true;
+ uint8_t datarate;
+
+ // Set the radio into sleep mode
+ Radio.Sleep( );
+
+ // Setup frequency and payload length
+ Radio.SetChannel( rxBeaconSetupParams->Frequency );
+ Radio.SetMaxPayloadLength( MODEM_LORA, rxBeaconSetupParams->BeaconSize );
+
+ // Check the RX continuous mode
+ if( rxBeaconSetupParams->RxTime != 0 )
+ {
+ rxContinuous = false;
+ }
+
+ // Get region specific datarate
+ datarate = rxBeaconSetupParams->Datarates[rxBeaconSetupParams->BeaconDatarate];
+
+ // Setup radio
+ Radio.SetRxConfig( MODEM_LORA, rxBeaconSetupParams->BeaconChannelBW, datarate,
+ 1, 0, 10, rxBeaconSetupParams->SymbolTimeout, true, rxBeaconSetupParams->BeaconSize, false, 0, 0, false, rxContinuous );
+
+ Radio.Rx( rxBeaconSetupParams->RxTime );
+}
diff --git a/lib/lora/mac/region/RegionCommon.h b/lib/lora/mac/region/RegionCommon.h
index 2d387c4991..c74f388401 100644
--- a/lib/lora/mac/region/RegionCommon.h
+++ b/lib/lora/mac/region/RegionCommon.h
@@ -12,7 +12,7 @@
* \____ \| ___ | (_ _) ___ |/ ___) _ \
* _____) ) ____| | | || |_| ____( (___| | | |
* (______/|_____)_|_|_| \__)_____)\____)_| |_|
- * (C)2013 Semtech
+ * (C)2013-2017 Semtech
*
* ___ _____ _ ___ _ _____ ___ ___ ___ ___
* / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
@@ -28,6 +28,8 @@
*
* \author Daniel Jaeckle ( STACKFORCE )
*
+ * \author Johannes Bruder ( STACKFORCE )
+ *
* \defgroup REGIONCOMMON Common region implementation
* Region independent implementations which are common to all regions.
* \{
@@ -35,6 +37,14 @@
#ifndef __REGIONCOMMON_H__
#define __REGIONCOMMON_H__
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include "../LoRaMacTypes.h"
+#include "Region.h"
+
typedef struct sRegionCommonLinkAdrParams
{
/*!
@@ -61,6 +71,10 @@ typedef struct sRegionCommonLinkAdrParams
typedef struct sRegionCommonLinkAdrReqVerifyParams
{
+ /*!
+ * LoRaWAN specification Version
+ */
+ Version_t Version;
/*!
* The current status of the AdrLinkRequest.
*/
@@ -152,13 +166,45 @@ typedef struct sRegionCommonCalcBackOffParams
/*!
* The elapsed time since initialization.
*/
- TimerTime_t ElapsedTime;
+ SysTime_t ElapsedTime;
/*!
* The time on air of the last Tx frame.
*/
TimerTime_t TxTimeOnAir;
}RegionCommonCalcBackOffParams_t;
+typedef struct sRegionCommonRxBeaconSetupParams
+{
+ /*!
+ * A pointer to the available datarates.
+ */
+ const uint8_t* Datarates;
+ /*!
+ * Frequency
+ */
+ uint32_t Frequency;
+ /*!
+ * The size of the beacon frame.
+ */
+ uint8_t BeaconSize;
+ /*!
+ * The datarate of the beacon.
+ */
+ uint8_t BeaconDatarate;
+ /*!
+ * The channel bandwidth of the beacon.
+ */
+ uint8_t BeaconChannelBW;
+ /*!
+ * The RX time.
+ */
+ uint32_t RxTime;
+ /*!
+ * The symbol timeout of the RX procedure.
+ */
+ uint16_t SymbolTimeout;
+}RegionCommonRxBeaconSetupParams_t;
+
/*!
* \brief Calculates the join duty cycle.
* This is a generic function and valid for all regions.
@@ -167,7 +213,7 @@ typedef struct sRegionCommonCalcBackOffParams
*
* \retval Duty cycle restriction.
*/
-uint16_t RegionCommonGetJoinDc( TimerTime_t elapsedTime );
+uint16_t RegionCommonGetJoinDc( SysTime_t elapsedTime );
/*!
* \brief Verifies, if a value is in a given range.
@@ -344,12 +390,16 @@ void RegionCommonComputeRxWindowParameters( double tSymbol, uint8_t minRxSymbols
/*!
* \brief Computes the txPower, based on the max EIRP and the antenna gain.
+ *
+ * \remark US915 region uses a conducted power as input value for maxEirp.
+ * Thus, the antennaGain parameter must be set to 0.
*
* \param [IN] txPower TX power index.
*
* \param [IN] maxEirp Maximum EIRP.
*
- * \param [IN] antennaGain Antenna gain.
+ * \param [IN] antennaGain Antenna gain. Referenced to the isotropic antenna.
+ * Value is in dBi. ( antennaGain[dBi] = measuredAntennaGain[dBd] + 2.15 )
*
* \retval Returns the physical TX power.
*/
@@ -362,6 +412,17 @@ int8_t RegionCommonComputeTxPower( int8_t txPowerIndex, float maxEirp, float ant
*/
void RegionCommonCalcBackOff( RegionCommonCalcBackOffParams_t* calcBackOffParams );
+/*!
+ * \brief Sets up the radio into RX beacon mode.
+ *
+ * \param [IN] rxBeaconSetupParams A pointer to the input parameters.
+ */
+void RegionCommonRxBeaconSetup( RegionCommonRxBeaconSetupParams_t* rxBeaconSetupParams );
+
/*! \} defgroup REGIONCOMMON */
+#ifdef __cplusplus
+}
+#endif
+
#endif // __REGIONCOMMON_H__
diff --git a/lib/lora/mac/region/RegionEU433.c b/lib/lora/mac/region/RegionEU433.c
index 71c023afa2..f1d86d623a 100644
--- a/lib/lora/mac/region/RegionEU433.c
+++ b/lib/lora/mac/region/RegionEU433.c
@@ -1,63 +1,68 @@
-/*
- / _____) _ | |
-( (____ _____ ____ _| |_ _____ ____| |__
- \____ \| ___ | (_ _) ___ |/ ___) _ \
- _____) ) ____| | | || |_| ____( (___| | | |
-(______/|_____)_|_|_| \__)_____)\____)_| |_|
- (C)2013 Semtech
- ___ _____ _ ___ _ _____ ___ ___ ___ ___
-/ __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
-\__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
-|___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
-embedded.connectivity.solutions===============
-
-Description: LoRa MAC region EU433 implementation
-
-License: Revised BSD License, see LICENSE.TXT file include in the project
-
-Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jaeckle ( STACKFORCE )
+/*!
+ * \file RegionEU433.c
+ *
+ * \brief Region implementation for EU433
+ *
+ * \copyright Revised BSD License, see section \ref LICENSE.
+ *
+ * \code
+ * ______ _
+ * / _____) _ | |
+ * ( (____ _____ ____ _| |_ _____ ____| |__
+ * \____ \| ___ | (_ _) ___ |/ ___) _ \
+ * _____) ) ____| | | || |_| ____( (___| | | |
+ * (______/|_____)_|_|_| \__)_____)\____)_| |_|
+ * (C)2013-2017 Semtech
+ *
+ * ___ _____ _ ___ _ _____ ___ ___ ___ ___
+ * / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
+ * \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
+ * |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
+ * embedded.connectivity.solutions===============
+ *
+ * \endcode
+ *
+ * \author Miguel Luis ( Semtech )
+ *
+ * \author Gregory Cristian ( Semtech )
+ *
+ * \author Daniel Jaeckle ( STACKFORCE )
*/
-#include
-#include
-#include
-#include
-
-#include "board.h"
-#include "lora/mac/LoRaMac.h"
-#include "esp_attr.h"
-
#include "utilities.h"
-#include "Region.h"
#include "RegionCommon.h"
#include "RegionEU433.h"
// Definitions
#define CHANNELS_MASK_SIZE 1
-// Global attributes
-/*!
- * LoRaMAC channels
- */
-static ChannelParams_t Channels[EU433_MAX_NB_CHANNELS];
-
/*!
- * LoRaMac bands
+ * Region specific context
*/
-static Band_t Bands[EU433_MAX_NB_BANDS] =
+typedef struct sRegionEU433NvmCtx
{
- EU433_BAND0
-};
+ /*!
+ * LoRaMAC channels
+ */
+ ChannelParams_t Channels[ EU433_MAX_NB_CHANNELS ];
+ /*!
+ * LoRaMac bands
+ */
+ Band_t Bands[ EU433_MAX_NB_BANDS ];
+ /*!
+ * LoRaMac channels mask
+ */
+ uint16_t ChannelsMask[ CHANNELS_MASK_SIZE ];
+ /*!
+ * LoRaMac channels default mask
+ */
+ uint16_t ChannelsDefaultMask[ CHANNELS_MASK_SIZE ];
+}RegionEU433NvmCtx_t;
-/*!
- * LoRaMac channels mask
- */
-static uint16_t ChannelsMask[CHANNELS_MASK_SIZE];
-
-/*!
- * LoRaMac channels default mask
+/*
+ * Non-volatile module context.
*/
-static uint16_t ChannelsDefaultMask[CHANNELS_MASK_SIZE];
+static RegionEU433NvmCtx_t NvmCtx;
// Static functions
static int8_t GetNextLowerTxDr( int8_t dr, int8_t minDr )
@@ -99,7 +104,7 @@ static int8_t LimitTxPower( int8_t txPower, int8_t maxBandTxPower, int8_t datara
return txPowerResult;
}
-static bool VerifyTxFreq( uint32_t freq )
+static bool VerifyRfFreq( uint32_t freq )
{
// Check radio driver support
if( Radio.CheckRfFrequency( freq ) == false )
@@ -181,11 +186,26 @@ PhyParam_t RegionEU433GetPhyParam( GetPhyParams_t* getPhy )
phyParam.Value = GetNextLowerTxDr( getPhy->Datarate, EU433_TX_MIN_DATARATE );
break;
}
+ case PHY_MAX_TX_POWER:
+ {
+ phyParam.Value = EU433_MAX_TX_POWER;
+ break;
+ }
case PHY_DEF_TX_POWER:
{
phyParam.Value = EU433_DEFAULT_TX_POWER;
break;
}
+ case PHY_DEF_ADR_ACK_LIMIT:
+ {
+ phyParam.Value = EU433_ADR_ACK_LIMIT;
+ break;
+ }
+ case PHY_DEF_ADR_ACK_DELAY:
+ {
+ phyParam.Value = EU433_ADR_ACK_DELAY;
+ break;
+ }
case PHY_MAX_PAYLOAD:
{
phyParam.Value = MaxPayloadOfDatarateEU433[getPhy->Datarate];
@@ -253,12 +273,12 @@ PhyParam_t RegionEU433GetPhyParam( GetPhyParams_t* getPhy )
}
case PHY_CHANNELS_MASK:
{
- phyParam.ChannelsMask = ChannelsMask;
+ phyParam.ChannelsMask = NvmCtx.ChannelsMask;
break;
}
case PHY_CHANNELS_DEFAULT_MASK:
{
- phyParam.ChannelsMask = ChannelsDefaultMask;
+ phyParam.ChannelsMask = NvmCtx.ChannelsDefaultMask;
break;
}
case PHY_MAX_NB_CHANNELS:
@@ -268,7 +288,7 @@ PhyParam_t RegionEU433GetPhyParam( GetPhyParams_t* getPhy )
}
case PHY_CHANNELS:
{
- phyParam.Channels = Channels;
+ phyParam.Channels = NvmCtx.Channels;
break;
}
case PHY_DEF_UPLINK_DWELL_TIME:
@@ -287,10 +307,26 @@ PhyParam_t RegionEU433GetPhyParam( GetPhyParams_t* getPhy )
phyParam.fValue = EU433_DEFAULT_ANTENNA_GAIN;
break;
}
- case PHY_NB_JOIN_TRIALS:
- case PHY_DEF_NB_JOIN_TRIALS:
+ case PHY_BEACON_CHANNEL_FREQ:
+ {
+ phyParam.Value = EU433_BEACON_CHANNEL_FREQ;
+ break;
+ }
+ case PHY_BEACON_FORMAT:
+ {
+ phyParam.BeaconFormat.BeaconSize = EU433_BEACON_SIZE;
+ phyParam.BeaconFormat.Rfu1Size = EU433_RFU1_SIZE;
+ phyParam.BeaconFormat.Rfu2Size = EU433_RFU2_SIZE;
+ break;
+ }
+ case PHY_BEACON_CHANNEL_DR:
{
- phyParam.Value = 48;
+ phyParam.Value = EU433_BEACON_CHANNEL_DR;
+ break;
+ }
+ case PHY_PING_SLOT_CHANNEL_DR:
+ {
+ phyParam.Value = EU433_PING_SLOT_CHANNEL_DR;
break;
}
default:
@@ -302,32 +338,53 @@ PhyParam_t RegionEU433GetPhyParam( GetPhyParams_t* getPhy )
return phyParam;
}
-IRAM_ATTR void RegionEU433SetBandTxDone( SetBandTxDoneParams_t* txDone )
+void RegionEU433SetBandTxDone( SetBandTxDoneParams_t* txDone )
{
- RegionCommonSetBandTxDone( txDone->Joined, &Bands[Channels[txDone->Channel].Band], txDone->LastTxDoneTime );
+ RegionCommonSetBandTxDone( txDone->Joined, &NvmCtx.Bands[NvmCtx.Channels[txDone->Channel].Band], txDone->LastTxDoneTime );
}
-void RegionEU433InitDefaults( InitType_t type )
+void RegionEU433InitDefaults( InitDefaultsParams_t* params )
{
- switch( type )
+ Band_t bands[EU433_MAX_NB_BANDS] =
+ {
+ EU433_BAND0
+ };
+
+ switch( params->Type )
{
case INIT_TYPE_INIT:
{
+ // Initialize bands
+ memcpy1( ( uint8_t* )NvmCtx.Bands, ( uint8_t* )bands, sizeof( Band_t ) * EU433_MAX_NB_BANDS );
+
// Channels
- Channels[0] = ( ChannelParams_t ) EU433_LC1;
- Channels[1] = ( ChannelParams_t ) EU433_LC2;
- Channels[2] = ( ChannelParams_t ) EU433_LC3;
+ NvmCtx.Channels[0] = ( ChannelParams_t ) EU433_LC1;
+ NvmCtx.Channels[1] = ( ChannelParams_t ) EU433_LC2;
+ NvmCtx.Channels[2] = ( ChannelParams_t ) EU433_LC3;
// Initialize the channels default mask
- ChannelsDefaultMask[0] = LC( 1 ) + LC( 2 ) + LC( 3 );
+ NvmCtx.ChannelsDefaultMask[0] = LC( 1 ) + LC( 2 ) + LC( 3 );
// Update the channels mask
- RegionCommonChanMaskCopy( ChannelsMask, ChannelsDefaultMask, 1 );
+ RegionCommonChanMaskCopy( NvmCtx.ChannelsMask, NvmCtx.ChannelsDefaultMask, 1 );
+ break;
+ }
+ case INIT_TYPE_RESTORE_CTX:
+ {
+ if( params->NvmCtx != 0 )
+ {
+ memcpy1( (uint8_t*) &NvmCtx, (uint8_t*) params->NvmCtx, sizeof( NvmCtx ) );
+ }
break;
}
- case INIT_TYPE_RESTORE:
+ case INIT_TYPE_RESTORE_DEFAULT_CHANNELS:
{
// Restore channels default mask
- ChannelsMask[0] |= ChannelsDefaultMask[0];
+ NvmCtx.ChannelsMask[0] |= NvmCtx.ChannelsDefaultMask[0];
+
+ // Channels
+ NvmCtx.Channels[0] = ( ChannelParams_t ) EU433_LC1;
+ NvmCtx.Channels[1] = ( ChannelParams_t ) EU433_LC2;
+ NvmCtx.Channels[2] = ( ChannelParams_t ) EU433_LC3;
break;
}
default:
@@ -337,10 +394,20 @@ void RegionEU433InitDefaults( InitType_t type )
}
}
+void* RegionEU433GetNvmCtx( GetNvmCtxParams_t* params )
+{
+ params->nvmCtxSize = sizeof( RegionEU433NvmCtx_t );
+ return &NvmCtx;
+}
+
bool RegionEU433Verify( VerifyParams_t* verify, PhyAttribute_t phyAttribute )
{
switch( phyAttribute )
{
+ case PHY_FREQUENCY:
+ {
+ return VerifyRfFreq( verify->Frequency );
+ }
case PHY_TX_DR:
{
return RegionCommonValueInRange( verify->DatarateParams.Datarate, EU433_TX_MIN_DATARATE, EU433_TX_MAX_DATARATE );
@@ -363,18 +430,9 @@ bool RegionEU433Verify( VerifyParams_t* verify, PhyAttribute_t phyAttribute )
{
return EU433_DUTY_CYCLE_ENABLED;
}
- case PHY_NB_JOIN_TRIALS:
- {
- if( verify->NbJoinTrials < 48 )
- {
- return false;
- }
- break;
- }
default:
return false;
}
- return true;
}
void RegionEU433ApplyCFList( ApplyCFListParams_t* applyCFList )
@@ -392,6 +450,12 @@ void RegionEU433ApplyCFList( ApplyCFListParams_t* applyCFList )
return;
}
+ // Last byte CFListType must be 0 to indicate the CFList contains a list of frequencies
+ if( applyCFList->Payload[15] != 0 )
+ {
+ return;
+ }
+
// Last byte is RFU, don't take it into account
for( uint8_t i = 0, chanIdx = EU433_NUMB_DEFAULT_CHANNELS; chanIdx < EU433_MAX_NB_CHANNELS; i+=3, chanIdx++ )
{
@@ -436,12 +500,12 @@ bool RegionEU433ChanMaskSet( ChanMaskSetParams_t* chanMaskSet )
{
case CHANNELS_MASK:
{
- RegionCommonChanMaskCopy( ChannelsMask, chanMaskSet->ChannelsMaskIn, 1 );
+ RegionCommonChanMaskCopy( NvmCtx.ChannelsMask, chanMaskSet->ChannelsMaskIn, 1 );
break;
}
case CHANNELS_DEFAULT_MASK:
{
- RegionCommonChanMaskCopy( ChannelsDefaultMask, chanMaskSet->ChannelsMaskIn, 1 );
+ RegionCommonChanMaskCopy( NvmCtx.ChannelsDefaultMask, chanMaskSet->ChannelsMaskIn, 1 );
break;
}
default:
@@ -450,66 +514,6 @@ bool RegionEU433ChanMaskSet( ChanMaskSetParams_t* chanMaskSet )
return true;
}
-bool RegionEU433AdrNext( AdrNextParams_t* adrNext, int8_t* drOut, int8_t* txPowOut, uint32_t* adrAckCounter )
-{
- bool adrAckReq = false;
- int8_t datarate = adrNext->Datarate;
- int8_t txPower = adrNext->TxPower;
- GetPhyParams_t getPhy;
- PhyParam_t phyParam;
-
- // Report back the adr ack counter
- *adrAckCounter = adrNext->AdrAckCounter;
-
- if( adrNext->AdrEnabled == true )
- {
- if( datarate == EU433_TX_MIN_DATARATE )
- {
- *adrAckCounter = 0;
- adrAckReq = false;
- }
- else
- {
- if( adrNext->AdrAckCounter >= EU433_ADR_ACK_LIMIT )
- {
- adrAckReq = true;
- txPower = EU433_MAX_TX_POWER;
- }
- else
- {
- adrAckReq = false;
- }
- if( adrNext->AdrAckCounter >= ( EU433_ADR_ACK_LIMIT + EU433_ADR_ACK_DELAY ) )
- {
- if( ( adrNext->AdrAckCounter % EU433_ADR_ACK_DELAY ) == 1 )
- {
- // Decrease the datarate
- getPhy.Attribute = PHY_NEXT_LOWER_TX_DR;
- getPhy.Datarate = datarate;
- getPhy.UplinkDwellTime = adrNext->UplinkDwellTime;
- phyParam = RegionEU433GetPhyParam( &getPhy );
- datarate = phyParam.Value;
-
- if( datarate == EU433_TX_MIN_DATARATE )
- {
- // We must set adrAckReq to false as soon as we reach the lowest datarate
- adrAckReq = false;
- if( adrNext->UpdateChanMask == true )
- {
- // Re-enable default channels
- ChannelsMask[0] |= LC( 1 ) + LC( 2 ) + LC( 3 );
- }
- }
- }
- }
- }
- }
-
- *drOut = datarate;
- *txPowOut = txPower;
- return adrAckReq;
-}
-
void RegionEU433ComputeRxWindowParameters( int8_t datarate, uint8_t minRxSymbols, uint32_t rxError, RxConfigParams_t *rxConfigParams )
{
double tSymbol = 0.0;
@@ -527,7 +531,7 @@ void RegionEU433ComputeRxWindowParameters( int8_t datarate, uint8_t minRxSymbols
tSymbol = RegionCommonComputeSymbolTimeLoRa( DataratesEU433[rxConfigParams->Datarate], BandwidthsEU433[rxConfigParams->Datarate] );
}
- RegionCommonComputeRxWindowParameters( tSymbol, minRxSymbols, rxError, RADIO_WAKEUP_TIME, &rxConfigParams->WindowTimeout, &rxConfigParams->WindowOffset );
+ RegionCommonComputeRxWindowParameters( tSymbol, minRxSymbols, rxError, Radio.GetWakeupTime( ), &rxConfigParams->WindowTimeout, &rxConfigParams->WindowOffset );
}
bool RegionEU433RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate )
@@ -543,14 +547,14 @@ bool RegionEU433RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate )
return false;
}
- if( rxConfig->Window == 0 )
+ if( rxConfig->RxSlot == RX_SLOT_WIN_1 )
{
// Apply window 1 frequency
- frequency = Channels[rxConfig->Channel].Frequency;
+ frequency = NvmCtx.Channels[rxConfig->Channel].Frequency;
// Apply the alternative RX 1 window frequency, if it is available
- if( Channels[rxConfig->Channel].Rx1Frequency != 0 )
+ if( NvmCtx.Channels[rxConfig->Channel].Rx1Frequency != 0 )
{
- frequency = Channels[rxConfig->Channel].Rx1Frequency;
+ frequency = NvmCtx.Channels[rxConfig->Channel].Rx1Frequency;
}
}
@@ -589,7 +593,7 @@ bool RegionEU433TxConfig( TxConfigParams_t* txConfig, int8_t* txPower, TimerTime
{
RadioModems_t modem;
int8_t phyDr = DataratesEU433[txConfig->Datarate];
- int8_t txPowerLimited = LimitTxPower( txConfig->TxPower, Bands[Channels[txConfig->Channel].Band].TxMaxPower, txConfig->Datarate, ChannelsMask );
+ int8_t txPowerLimited = LimitTxPower( txConfig->TxPower, NvmCtx.Bands[NvmCtx.Channels[txConfig->Channel].Band].TxMaxPower, txConfig->Datarate, NvmCtx.ChannelsMask );
uint32_t bandwidth = GetBandwidth( txConfig->Datarate );
int8_t phyTxPower = 0;
@@ -597,17 +601,17 @@ bool RegionEU433TxConfig( TxConfigParams_t* txConfig, int8_t* txPower, TimerTime
phyTxPower = RegionCommonComputeTxPower( txPowerLimited, txConfig->MaxEirp, txConfig->AntennaGain );
// Setup the radio frequency
- Radio.SetChannel( Channels[txConfig->Channel].Frequency );
+ Radio.SetChannel( NvmCtx.Channels[txConfig->Channel].Frequency );
if( txConfig->Datarate == DR_7 )
{ // High Speed FSK channel
modem = MODEM_FSK;
- Radio.SetTxConfig( modem, phyTxPower, 25000, bandwidth, phyDr * 1000, 0, 5, false, true, 0, 0, false, 3000 );
+ Radio.SetTxConfig( modem, phyTxPower, 25000, bandwidth, phyDr * 1000, 0, 5, false, true, 0, 0, false, 4000 );
}
else
{
modem = MODEM_LORA;
- Radio.SetTxConfig( modem, phyTxPower, 0, bandwidth, phyDr, 1, 8, false, true, 0, 0, false, 3000 );
+ Radio.SetTxConfig( modem, phyTxPower, 0, bandwidth, phyDr, 1, 8, false, true, 0, 0, false, 4000 );
}
// Setup maximum payload lenght of the radio driver
@@ -664,7 +668,7 @@ uint8_t RegionEU433LinkAdrReq( LinkAdrReqParams_t* linkAdrReq, int8_t* drOut, in
{
if( linkAdrParams.ChMaskCtrl == 6 )
{
- if( Channels[i].Frequency != 0 )
+ if( NvmCtx.Channels[i].Frequency != 0 )
{
chMask |= 1 << i;
}
@@ -672,7 +676,7 @@ uint8_t RegionEU433LinkAdrReq( LinkAdrReqParams_t* linkAdrReq, int8_t* drOut, in
else
{
if( ( ( chMask & ( 1 << i ) ) != 0 ) &&
- ( Channels[i].Frequency == 0 ) )
+ ( NvmCtx.Channels[i].Frequency == 0 ) )
{// Trying to enable an undefined channel
status &= 0xFE; // Channel mask KO
}
@@ -698,9 +702,10 @@ uint8_t RegionEU433LinkAdrReq( LinkAdrReqParams_t* linkAdrReq, int8_t* drOut, in
linkAdrVerifyParams.ChannelsMask = &chMask;
linkAdrVerifyParams.MinDatarate = ( int8_t )phyParam.Value;
linkAdrVerifyParams.MaxDatarate = EU433_TX_MAX_DATARATE;
- linkAdrVerifyParams.Channels = Channels;
+ linkAdrVerifyParams.Channels = NvmCtx.Channels;
linkAdrVerifyParams.MinTxPower = EU433_MIN_TX_POWER;
linkAdrVerifyParams.MaxTxPower = EU433_MAX_TX_POWER;
+ linkAdrVerifyParams.Version = linkAdrReq->Version;
// Verify the parameters and update, if necessary
status = RegionCommonLinkAdrReqVerifyParams( &linkAdrVerifyParams, &linkAdrParams.Datarate, &linkAdrParams.TxPower, &linkAdrParams.NbRep );
@@ -709,9 +714,9 @@ uint8_t RegionEU433LinkAdrReq( LinkAdrReqParams_t* linkAdrReq, int8_t* drOut, in
if( status == 0x07 )
{
// Set the channels mask to a default value
- memset( ChannelsMask, 0, sizeof( ChannelsMask ) );
+ memset1( ( uint8_t* ) NvmCtx.ChannelsMask, 0, sizeof( NvmCtx.ChannelsMask ) );
// Update the channels mask
- ChannelsMask[0] = chMask;
+ NvmCtx.ChannelsMask[0] = chMask;
}
// Update status variables
@@ -728,7 +733,7 @@ uint8_t RegionEU433RxParamSetupReq( RxParamSetupReqParams_t* rxParamSetupReq )
uint8_t status = 0x07;
// Verify radio frequency
- if( Radio.CheckRfFrequency( rxParamSetupReq->Frequency ) == false )
+ if( VerifyRfFreq( rxParamSetupReq->Frequency ) == false )
{
status &= 0xFE; // Channel frequency KO
}
@@ -811,13 +816,13 @@ uint8_t RegionEU433DlChannelReq( DlChannelReqParams_t* dlChannelReq )
uint8_t status = 0x03;
// Verify if the frequency is supported
- if( VerifyTxFreq( dlChannelReq->Rx1Frequency ) == false )
+ if( VerifyRfFreq( dlChannelReq->Rx1Frequency ) == false )
{
status &= 0xFE;
}
// Verify if an uplink frequency exists
- if( Channels[dlChannelReq->ChannelId].Frequency == 0 )
+ if( NvmCtx.Channels[dlChannelReq->ChannelId].Frequency == 0 )
{
status &= 0xFD;
}
@@ -825,49 +830,23 @@ uint8_t RegionEU433DlChannelReq( DlChannelReqParams_t* dlChannelReq )
// Apply Rx1 frequency, if the status is OK
if( status == 0x03 )
{
- Channels[dlChannelReq->ChannelId].Rx1Frequency = dlChannelReq->Rx1Frequency;
+ NvmCtx.Channels[dlChannelReq->ChannelId].Rx1Frequency = dlChannelReq->Rx1Frequency;
}
return status;
}
-int8_t RegionEU433AlternateDr( AlternateDrParams_t* alternateDr )
+int8_t RegionEU433AlternateDr( int8_t currentDr, AlternateDrType_t type )
{
- int8_t datarate = 0;
-
- if( ( alternateDr->NbTrials % 48 ) == 0 )
- {
- datarate = DR_0;
- }
- else if( ( alternateDr->NbTrials % 32 ) == 0 )
- {
- datarate = DR_1;
- }
- else if( ( alternateDr->NbTrials % 24 ) == 0 )
- {
- datarate = DR_2;
- }
- else if( ( alternateDr->NbTrials % 16 ) == 0 )
- {
- datarate = DR_3;
- }
- else if( ( alternateDr->NbTrials % 8 ) == 0 )
- {
- datarate = DR_4;
- }
- else
- {
- datarate = DR_5;
- }
- return datarate;
+ return currentDr;
}
void RegionEU433CalcBackOff( CalcBackOffParams_t* calcBackOff )
{
RegionCommonCalcBackOffParams_t calcBackOffParams;
- calcBackOffParams.Channels = Channels;
- calcBackOffParams.Bands = Bands;
+ calcBackOffParams.Channels = NvmCtx.Channels;
+ calcBackOffParams.Bands = NvmCtx.Bands;
calcBackOffParams.LastTxIsJoinRequest = calcBackOff->LastTxIsJoinRequest;
calcBackOffParams.Joined = calcBackOff->Joined;
calcBackOffParams.DutyCycleEnabled = calcBackOff->DutyCycleEnabled;
@@ -878,35 +857,36 @@ void RegionEU433CalcBackOff( CalcBackOffParams_t* calcBackOff )
RegionCommonCalcBackOff( &calcBackOffParams );
}
-bool RegionEU433NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff )
+LoRaMacStatus_t RegionEU433NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff )
{
uint8_t nbEnabledChannels = 0;
uint8_t delayTx = 0;
uint8_t enabledChannels[EU433_MAX_NB_CHANNELS] = { 0 };
TimerTime_t nextTxDelay = 0;
- if( RegionCommonCountChannels( ChannelsMask, 0, 1 ) == 0 )
+ if( RegionCommonCountChannels( NvmCtx.ChannelsMask, 0, 1 ) == 0 )
{ // Reactivate default channels
- ChannelsMask[0] |= LC( 1 ) + LC( 2 ) + LC( 3 );
+ NvmCtx.ChannelsMask[0] |= LC( 1 ) + LC( 2 ) + LC( 3 );
}
- if( nextChanParams->AggrTimeOff <= TimerGetElapsedTime( nextChanParams->LastAggrTx ) )
+ TimerTime_t elapsed = TimerGetElapsedTime( nextChanParams->LastAggrTx );
+ if( ( nextChanParams->LastAggrTx == 0 ) || ( nextChanParams->AggrTimeOff <= elapsed ) )
{
// Reset Aggregated time off
*aggregatedTimeOff = 0;
// Update bands Time OFF
- nextTxDelay = RegionCommonUpdateBandTimeOff( nextChanParams->Joined, nextChanParams->DutyCycleEnabled, Bands, EU433_MAX_NB_BANDS );
+ nextTxDelay = RegionCommonUpdateBandTimeOff( nextChanParams->Joined, nextChanParams->DutyCycleEnabled, NvmCtx.Bands, EU433_MAX_NB_BANDS );
// Search how many channels are enabled
nbEnabledChannels = CountNbOfEnabledChannels( nextChanParams->Joined, nextChanParams->Datarate,
- ChannelsMask, Channels,
- Bands, enabledChannels, &delayTx );
+ NvmCtx.ChannelsMask, NvmCtx.Channels,
+ NvmCtx.Bands, enabledChannels, &delayTx );
}
else
{
delayTx++;
- nextTxDelay = nextChanParams->AggrTimeOff - TimerGetElapsedTime( nextChanParams->LastAggrTx );
+ nextTxDelay = nextChanParams->AggrTimeOff - elapsed;
}
if( nbEnabledChannels > 0 )
@@ -915,7 +895,7 @@ bool RegionEU433NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel,
*channel = enabledChannels[randr( 0, nbEnabledChannels - 1 )];
*time = 0;
- return true;
+ return LORAMAC_STATUS_OK;
}
else
{
@@ -923,22 +903,26 @@ bool RegionEU433NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel,
{
// Delay transmission due to AggregatedTimeOff or to a band time off
*time = nextTxDelay;
- return true;
+ return LORAMAC_STATUS_DUTYCYCLE_RESTRICTED;
}
// Datarate not supported by any channel, restore defaults
- ChannelsMask[0] |= LC( 1 ) + LC( 2 ) + LC( 3 );
+ NvmCtx.ChannelsMask[0] |= LC( 1 ) + LC( 2 ) + LC( 3 );
*time = 0;
- return false;
+ return LORAMAC_STATUS_NO_CHANNEL_FOUND;
}
}
LoRaMacStatus_t RegionEU433ChannelAdd( ChannelAddParams_t* channelAdd )
{
- uint8_t band = 0;
bool drInvalid = false;
bool freqInvalid = false;
uint8_t id = channelAdd->ChannelId;
+ if( id < EU433_NUMB_DEFAULT_CHANNELS )
+ {
+ return LORAMAC_STATUS_FREQ_AND_DR_INVALID;
+ }
+
if( id >= EU433_MAX_NB_CHANNELS )
{
return LORAMAC_STATUS_PARAMETER_INVALID;
@@ -958,30 +942,10 @@ LoRaMacStatus_t RegionEU433ChannelAdd( ChannelAddParams_t* channelAdd )
drInvalid = true;
}
- // Default channels don't accept all values
- if( id < EU433_NUMB_DEFAULT_CHANNELS )
- {
- // Validate the datarate range for min: must be DR_0
- if( channelAdd->NewChannel->DrRange.Fields.Min > DR_0 )
- {
- drInvalid = true;
- }
- // Validate the datarate range for max: must be DR_5 <= Max <= TX_MAX_DATARATE
- if( RegionCommonValueInRange( channelAdd->NewChannel->DrRange.Fields.Max, DR_5, EU433_TX_MAX_DATARATE ) == false )
- {
- drInvalid = true;
- }
- // We are not allowed to change the frequency
- if( channelAdd->NewChannel->Frequency != Channels[id].Frequency )
- {
- freqInvalid = true;
- }
- }
-
// Check frequency
if( freqInvalid == false )
{
- if( VerifyTxFreq( channelAdd->NewChannel->Frequency ) == false )
+ if( VerifyRfFreq( channelAdd->NewChannel->Frequency ) == false )
{
freqInvalid = true;
}
@@ -1001,15 +965,70 @@ LoRaMacStatus_t RegionEU433ChannelAdd( ChannelAddParams_t* channelAdd )
return LORAMAC_STATUS_FREQUENCY_INVALID;
}
- memcpy( &(Channels[id]), channelAdd->NewChannel, sizeof( Channels[id] ) );
- Channels[id].Band = band;
- ChannelsMask[0] |= ( 1 << id );
+ memcpy1( ( uint8_t* ) &(NvmCtx.Channels[id]), ( uint8_t* ) channelAdd->NewChannel, sizeof( NvmCtx.Channels[id] ) );
+ NvmCtx.Channels[id].Band = 0;
+ NvmCtx.ChannelsMask[0] |= ( 1 << id );
return LORAMAC_STATUS_OK;
}
+bool RegionEU433ChannelsRemove( ChannelRemoveParams_t* channelRemove )
+{
+ uint8_t id = channelRemove->ChannelId;
+
+ if( id < EU433_NUMB_DEFAULT_CHANNELS )
+ {
+ return false;
+ }
+
+ // Remove the channel from the list of channels
+ NvmCtx.Channels[id] = ( ChannelParams_t ){ 0, 0, { 0 }, 0 };
+
+ return RegionCommonChanDisable( NvmCtx.ChannelsMask, id, EU433_MAX_NB_CHANNELS );
+}
+
+void RegionEU433SetContinuousWave( ContinuousWaveParams_t* continuousWave )
+{
+ int8_t txPowerLimited = LimitTxPower( continuousWave->TxPower, NvmCtx.Bands[NvmCtx.Channels[continuousWave->Channel].Band].TxMaxPower, continuousWave->Datarate, NvmCtx.ChannelsMask );
+ int8_t phyTxPower = 0;
+ uint32_t frequency = NvmCtx.Channels[continuousWave->Channel].Frequency;
+
+ // Calculate physical TX power
+ phyTxPower = RegionCommonComputeTxPower( txPowerLimited, continuousWave->MaxEirp, continuousWave->AntennaGain );
+
+ Radio.SetTxContinuousWave( frequency, phyTxPower, continuousWave->Timeout );
+}
+
+uint8_t RegionEU433ApplyDrOffset( uint8_t downlinkDwellTime, int8_t dr, int8_t drOffset )
+{
+ int8_t datarate = dr - drOffset;
+
+ if( datarate < 0 )
+ {
+ datarate = DR_0;
+ }
+ return datarate;
+}
+
+void RegionEU433RxBeaconSetup( RxBeaconSetup_t* rxBeaconSetup, uint8_t* outDr )
+{
+ RegionCommonRxBeaconSetupParams_t regionCommonRxBeaconSetup;
+
+ regionCommonRxBeaconSetup.Datarates = DataratesEU433;
+ regionCommonRxBeaconSetup.Frequency = rxBeaconSetup->Frequency;
+ regionCommonRxBeaconSetup.BeaconSize = EU433_BEACON_SIZE;
+ regionCommonRxBeaconSetup.BeaconDatarate = EU433_BEACON_CHANNEL_DR;
+ regionCommonRxBeaconSetup.BeaconChannelBW = EU433_BEACON_CHANNEL_BW;
+ regionCommonRxBeaconSetup.RxTime = rxBeaconSetup->RxTime;
+ regionCommonRxBeaconSetup.SymbolTimeout = rxBeaconSetup->SymbolTimeout;
+
+ RegionCommonRxBeaconSetup( ®ionCommonRxBeaconSetup );
+
+ // Store downlink datarate
+ *outDr = EU433_BEACON_CHANNEL_DR;
+}
+
LoRaMacStatus_t RegionEU433ChannelManualAdd( ChannelAddParams_t* channelAdd )
{
- uint8_t band = 0;
bool drInvalid = false;
bool freqInvalid = false;
uint8_t id = channelAdd->ChannelId;
@@ -1033,25 +1052,10 @@ LoRaMacStatus_t RegionEU433ChannelManualAdd( ChannelAddParams_t* channelAdd )
drInvalid = true;
}
- // Default channels don't accept all values
- if( id < EU433_NUMB_DEFAULT_CHANNELS )
- {
- // Validate the datarate range for min: must be DR_0
- if( channelAdd->NewChannel->DrRange.Fields.Min > DR_0 )
- {
- drInvalid = true;
- }
- // Validate the datarate range for max: must be DR_5 <= Max <= TX_MAX_DATARATE
- if( RegionCommonValueInRange( channelAdd->NewChannel->DrRange.Fields.Max, DR_5, EU433_TX_MAX_DATARATE ) == false )
- {
- drInvalid = true;
- }
- }
-
// Check frequency
if( freqInvalid == false )
{
- if( VerifyTxFreq( channelAdd->NewChannel->Frequency ) == false )
+ if( VerifyRfFreq( channelAdd->NewChannel->Frequency ) == false )
{
freqInvalid = true;
}
@@ -1071,55 +1075,8 @@ LoRaMacStatus_t RegionEU433ChannelManualAdd( ChannelAddParams_t* channelAdd )
return LORAMAC_STATUS_FREQUENCY_INVALID;
}
- memcpy( &(Channels[id]), channelAdd->NewChannel, sizeof( Channels[id] ) );
- Channels[id].Band = band;
- ChannelsMask[0] |= ( 1 << id );
+ memcpy1( ( uint8_t* ) &(NvmCtx.Channels[id]), ( uint8_t* ) channelAdd->NewChannel, sizeof( NvmCtx.Channels[id] ) );
+ NvmCtx.Channels[id].Band = 0;
+ NvmCtx.ChannelsMask[0] |= ( 1 << id );
return LORAMAC_STATUS_OK;
}
-
-bool RegionEU433ChannelsRemove( ChannelRemoveParams_t* channelRemove )
-{
- uint8_t id = channelRemove->ChannelId;
-
- if( id < EU433_NUMB_DEFAULT_CHANNELS )
- {
- return false;
- }
-
- // Remove the channel from the list of channels
- Channels[id] = ( ChannelParams_t ){ 0, 0, { 0 }, 0 };
-
- return RegionCommonChanDisable( ChannelsMask, id, EU433_MAX_NB_CHANNELS );
-}
-
-void RegionEU433SetContinuousWave( ContinuousWaveParams_t* continuousWave )
-{
- int8_t txPowerLimited = LimitTxPower( continuousWave->TxPower, Bands[Channels[continuousWave->Channel].Band].TxMaxPower, continuousWave->Datarate, ChannelsMask );
- int8_t phyTxPower = 0;
- uint32_t frequency = Channels[continuousWave->Channel].Frequency;
-
- // Calculate physical TX power
- phyTxPower = RegionCommonComputeTxPower( txPowerLimited, continuousWave->MaxEirp, continuousWave->AntennaGain );
-
- Radio.SetTxContinuousWave( frequency, phyTxPower, continuousWave->Timeout );
-}
-
-uint8_t RegionEU433ApplyDrOffset( uint8_t downlinkDwellTime, int8_t dr, int8_t drOffset )
-{
- int8_t datarate = dr - drOffset;
-
- if( datarate < 0 )
- {
- datarate = DR_0;
- }
- return datarate;
-}
-
-bool RegionEU433ForceJoinDataRate( int8_t joinDr, AlternateDrParams_t* alternateDr )
-{
- uint8_t DRToCounter[6] = { 48, 32, 24, 16, 8, 1 };
- if (joinDr < sizeof(DRToCounter)) {
- alternateDr->NbTrials = DRToCounter[joinDr];
- }
- return true;
-}
diff --git a/lib/lora/mac/region/RegionEU433.h b/lib/lora/mac/region/RegionEU433.h
index a66a0da4a1..d4de35e7ff 100644
--- a/lib/lora/mac/region/RegionEU433.h
+++ b/lib/lora/mac/region/RegionEU433.h
@@ -12,7 +12,7 @@
* \____ \| ___ | (_ _) ___ |/ ___) _ \
* _____) ) ____| | | || |_| ____( (___| | | |
* (______/|_____)_|_|_| \__)_____)\____)_| |_|
- * (C)2013 Semtech
+ * (C)2013-2017 Semtech
*
* ___ _____ _ ___ _ _____ ___ ___ ___ ___
* / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
@@ -28,6 +28,8 @@
*
* \author Daniel Jaeckle ( STACKFORCE )
*
+ * \author Johannes Bruder ( STACKFORCE )
+ *
* \defgroup REGIONEU433 Region EU433
* Implementation according to LoRaWAN Specification v1.0.2.
* \{
@@ -35,6 +37,13 @@
#ifndef __REGION_EU433_H__
#define __REGION_EU433_H__
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include "Region.h"
+
/*!
* LoRaMac maximum number of channels
*/
@@ -192,11 +201,49 @@
*/
#define EU433_MAX_NB_BANDS 1
+/*
+ * CLASS B
+ */
+/*!
+ * Beacon frequency
+ */
+#define EU433_BEACON_CHANNEL_FREQ 434665000
+
+/*!
+ * Payload size of a beacon frame
+ */
+#define EU433_BEACON_SIZE 17
+
+/*!
+ * Size of RFU 1 field
+ */
+#define EU433_RFU1_SIZE 2
+
+/*!
+ * Size of RFU 2 field
+ */
+#define EU433_RFU2_SIZE 0
+
+/*!
+ * Datarate of the beacon channel
+ */
+#define EU433_BEACON_CHANNEL_DR DR_3
+
+/*!
+ * Bandwith of the beacon channel
+ */
+#define EU433_BEACON_CHANNEL_BW 0
+
+/*!
+ * Ping slot channel datarate
+ */
+#define EU433_PING_SLOT_CHANNEL_DR DR_3
+
/*!
* Band 0 definition
- * { DutyCycle, TxMaxPower, LastTxDoneTime, TimeOff }
+ * { DutyCycle, TxMaxPower, LastJoinTxDoneTime, LastTxDoneTime, TimeOff }
*/
-#define EU433_BAND0 { 100, EU433_MAX_TX_POWER, 0, 0 } // 1.0 %
+#define EU433_BAND0 { 100, EU433_MAX_TX_POWER, 0, 0, 0 } // 1.0 %
/*!
* LoRaMac default channel 1
@@ -262,7 +309,16 @@ void RegionEU433SetBandTxDone( SetBandTxDoneParams_t* txDone );
*
* \param [IN] type Sets the initialization type.
*/
-void RegionEU433InitDefaults( InitType_t type );
+void RegionEU433InitDefaults( InitDefaultsParams_t* params );
+
+/*!
+ * \brief Returns a pointer to the internal context and its size.
+ *
+ * \param [OUT] params Pointer to the function parameters.
+ *
+ * \retval Points to a structure where the module store its non-volatile context.
+ */
+void* RegionEU433GetNvmCtx( GetNvmCtxParams_t* params );
/*!
* \brief Verifies a parameter.
@@ -292,21 +348,6 @@ void RegionEU433ApplyCFList( ApplyCFListParams_t* applyCFList );
*/
bool RegionEU433ChanMaskSet( ChanMaskSetParams_t* chanMaskSet );
-/*!
- * \brief Calculates the next datarate to set, when ADR is on or off.
- *
- * \param [IN] adrNext Pointer to the function parameters.
- *
- * \param [OUT] drOut The calculated datarate for the next TX.
- *
- * \param [OUT] txPowOut The TX power for the next TX.
- *
- * \param [OUT] adrAckCounter The calculated ADR acknowledgement counter.
- *
- * \retval Returns true, if an ADR request should be performed.
- */
-bool RegionEU433AdrNext( AdrNextParams_t* adrNext, int8_t* drOut, int8_t* txPowOut, uint32_t* adrAckCounter );
-
/*!
* Computes the Rx window timeout and offset.
*
@@ -396,11 +437,11 @@ uint8_t RegionEU433DlChannelReq( DlChannelReqParams_t* dlChannelReq );
/*!
* \brief Alternates the datarate of the channel for the join request.
*
- * \param [IN] alternateDr Pointer to the function parameters.
+ * \param [IN] currentDr Current datarate.
*
* \retval Datarate to apply.
*/
-int8_t RegionEU433AlternateDr( AlternateDrParams_t* alternateDr );
+int8_t RegionEU433AlternateDr( int8_t currentDr, AlternateDrType_t type );
/*!
* \brief Calculates the back-off time.
@@ -421,7 +462,7 @@ void RegionEU433CalcBackOff( CalcBackOffParams_t* calcBackOff );
*
* \retval Function status [1: OK, 0: Unable to find a channel on the current datarate]
*/
-bool RegionEU433NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff );
+LoRaMacStatus_t RegionEU433NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff );
/*!
* \brief Adds a channel.
@@ -431,6 +472,7 @@ bool RegionEU433NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel,
* \retval Status of the operation.
*/
LoRaMacStatus_t RegionEU433ChannelAdd( ChannelAddParams_t* channelAdd );
+LoRaMacStatus_t RegionEU433ChannelManualAdd( ChannelAddParams_t* channelAdd );
/*!
* \brief Removes a channel.
@@ -441,15 +483,6 @@ LoRaMacStatus_t RegionEU433ChannelAdd( ChannelAddParams_t* channelAdd );
*/
bool RegionEU433ChannelsRemove( ChannelRemoveParams_t* channelRemove );
-/*!
- * \brief Adds a channel manually.
- *
- * \param [IN] channelAdd Pointer to the function parameters.
- *
- * \retval Status of the operation.
- */
-LoRaMacStatus_t RegionEU433ChannelManualAdd( ChannelAddParams_t* channelAdd );
-
/*!
* \brief Sets the radio into continuous wave mode.
*
@@ -470,8 +503,17 @@ void RegionEU433SetContinuousWave( ContinuousWaveParams_t* continuousWave );
*/
uint8_t RegionEU433ApplyDrOffset( uint8_t downlinkDwellTime, int8_t dr, int8_t drOffset );
-bool RegionCN470ForceJoinDataRate( int8_t joinDr, AlternateDrParams_t *alternateDr );
+/*!
+ * \brief Sets the radio into beacon reception mode
+ *
+ * \param [IN] rxBeaconSetup Pointer to the function parameters
+ */
+ void RegionEU433RxBeaconSetup( RxBeaconSetup_t* rxBeaconSetup, uint8_t* outDr );
/*! \} defgroup REGIONEU433 */
+#ifdef __cplusplus
+}
+#endif
+
#endif // __REGION_EU433_H__
diff --git a/lib/lora/mac/region/RegionEU868.c b/lib/lora/mac/region/RegionEU868.c
index da31e1805f..5f9ff29263 100644
--- a/lib/lora/mac/region/RegionEU868.c
+++ b/lib/lora/mac/region/RegionEU868.c
@@ -1,31 +1,34 @@
-/*
- / _____) _ | |
-( (____ _____ ____ _| |_ _____ ____| |__
- \____ \| ___ | (_ _) ___ |/ ___) _ \
- _____) ) ____| | | || |_| ____( (___| | | |
-(______/|_____)_|_|_| \__)_____)\____)_| |_|
- (C)2013 Semtech
- ___ _____ _ ___ _ _____ ___ ___ ___ ___
-/ __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
-\__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
-|___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
-embedded.connectivity.solutions===============
-
-Description: LoRa MAC region EU868 implementation
-
-License: Revised BSD License, see LICENSE.TXT file include in the project
-
-Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jaeckle ( STACKFORCE )
+/*!
+ * \file RegionEU868.c
+ *
+ * \brief Region implementation for EU868
+ *
+ * \copyright Revised BSD License, see section \ref LICENSE.
+ *
+ * \code
+ * ______ _
+ * / _____) _ | |
+ * ( (____ _____ ____ _| |_ _____ ____| |__
+ * \____ \| ___ | (_ _) ___ |/ ___) _ \
+ * _____) ) ____| | | || |_| ____( (___| | | |
+ * (______/|_____)_|_|_| \__)_____)\____)_| |_|
+ * (C)2013-2017 Semtech
+ *
+ * ___ _____ _ ___ _ _____ ___ ___ ___ ___
+ * / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
+ * \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
+ * |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
+ * embedded.connectivity.solutions===============
+ *
+ * \endcode
+ *
+ * \author Miguel Luis ( Semtech )
+ *
+ * \author Gregory Cristian ( Semtech )
+ *
+ * \author Daniel Jaeckle ( STACKFORCE )
*/
-#include
#include
-#include
-#include
-
-#include "board.h"
-#include "lora/mac/LoRaMac.h"
-#include "esp_attr.h"
-
#include "utilities.h"
#include "Region.h"
@@ -35,33 +38,33 @@ Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jae
// Definitions
#define CHANNELS_MASK_SIZE 1
-// Global attributes
/*!
- * LoRaMAC channels
+ * Region specific context
*/
-static ChannelParams_t Channels[EU868_MAX_NB_CHANNELS];
-
-/*!
- * LoRaMac bands
- */
-static Band_t Bands[EU868_MAX_NB_BANDS] =
+typedef struct sRegionEU868NvmCtx
{
- EU868_BAND0,
- EU868_BAND1,
- EU868_BAND2,
- EU868_BAND3,
- EU868_BAND4,
-};
+ /*!
+ * LoRaMAC channels
+ */
+ ChannelParams_t Channels[ EU868_MAX_NB_CHANNELS ];
+ /*!
+ * LoRaMac bands
+ */
+ Band_t Bands[ EU868_MAX_NB_BANDS ];
+ /*!
+ * LoRaMac channels mask
+ */
+ uint16_t ChannelsMask[ CHANNELS_MASK_SIZE ];
+ /*!
+ * LoRaMac channels default mask
+ */
+ uint16_t ChannelsDefaultMask[ CHANNELS_MASK_SIZE ];
+}RegionEU868NvmCtx_t;
-/*!
- * LoRaMac channels mask
- */
-static uint16_t ChannelsMask[CHANNELS_MASK_SIZE];
-
-/*!
- * LoRaMac channels default mask
+/*
+ * Non-volatile module context.
*/
-static uint16_t ChannelsDefaultMask[CHANNELS_MASK_SIZE];
+static RegionEU868NvmCtx_t NvmCtx;
// Static functions
static int8_t GetNextLowerTxDr( int8_t dr, int8_t minDr )
@@ -103,7 +106,7 @@ static int8_t LimitTxPower( int8_t txPower, int8_t maxBandTxPower, int8_t datara
return txPowerResult;
}
-static bool VerifyTxFreq( uint32_t freq, uint8_t *band )
+static bool VerifyRfFreq( uint32_t freq, uint8_t *band )
{
// Check radio driver support
if( Radio.CheckRfFrequency( freq ) == false )
@@ -126,7 +129,7 @@ static bool VerifyTxFreq( uint32_t freq, uint8_t *band )
}
else if( ( freq >= 868700000 ) && ( freq <= 869200000 ) )
{
- *band = 2;
+ *band = 5;
}
else if( ( freq >= 869400000 ) && ( freq <= 869650000 ) )
{
@@ -184,7 +187,7 @@ static uint8_t CountNbOfEnabledChannels( bool joined, uint8_t datarate, uint16_t
return nbEnabledChannels;
}
-IRAM_ATTR PhyParam_t RegionEU868GetPhyParam( GetPhyParams_t* getPhy )
+PhyParam_t RegionEU868GetPhyParam( GetPhyParams_t* getPhy )
{
PhyParam_t phyParam = { 0 };
@@ -210,11 +213,26 @@ IRAM_ATTR PhyParam_t RegionEU868GetPhyParam( GetPhyParams_t* getPhy )
phyParam.Value = GetNextLowerTxDr( getPhy->Datarate, EU868_TX_MIN_DATARATE );
break;
}
+ case PHY_MAX_TX_POWER:
+ {
+ phyParam.Value = EU868_MAX_TX_POWER;
+ break;
+ }
case PHY_DEF_TX_POWER:
{
phyParam.Value = EU868_DEFAULT_TX_POWER;
break;
}
+ case PHY_DEF_ADR_ACK_LIMIT:
+ {
+ phyParam.Value = EU868_ADR_ACK_LIMIT;
+ break;
+ }
+ case PHY_DEF_ADR_ACK_DELAY:
+ {
+ phyParam.Value = EU868_ADR_ACK_DELAY;
+ break;
+ }
case PHY_MAX_PAYLOAD:
{
phyParam.Value = MaxPayloadOfDatarateEU868[getPhy->Datarate];
@@ -282,12 +300,12 @@ IRAM_ATTR PhyParam_t RegionEU868GetPhyParam( GetPhyParams_t* getPhy )
}
case PHY_CHANNELS_MASK:
{
- phyParam.ChannelsMask = ChannelsMask;
+ phyParam.ChannelsMask = NvmCtx.ChannelsMask;
break;
}
case PHY_CHANNELS_DEFAULT_MASK:
{
- phyParam.ChannelsMask = ChannelsDefaultMask;
+ phyParam.ChannelsMask = NvmCtx.ChannelsDefaultMask;
break;
}
case PHY_MAX_NB_CHANNELS:
@@ -297,7 +315,7 @@ IRAM_ATTR PhyParam_t RegionEU868GetPhyParam( GetPhyParams_t* getPhy )
}
case PHY_CHANNELS:
{
- phyParam.Channels = Channels;
+ phyParam.Channels = NvmCtx.Channels;
break;
}
case PHY_DEF_UPLINK_DWELL_TIME:
@@ -316,10 +334,26 @@ IRAM_ATTR PhyParam_t RegionEU868GetPhyParam( GetPhyParams_t* getPhy )
phyParam.fValue = EU868_DEFAULT_ANTENNA_GAIN;
break;
}
- case PHY_NB_JOIN_TRIALS:
- case PHY_DEF_NB_JOIN_TRIALS:
+ case PHY_BEACON_CHANNEL_FREQ:
+ {
+ phyParam.Value = EU868_BEACON_CHANNEL_FREQ;
+ break;
+ }
+ case PHY_BEACON_FORMAT:
{
- phyParam.Value = 48;
+ phyParam.BeaconFormat.BeaconSize = EU868_BEACON_SIZE;
+ phyParam.BeaconFormat.Rfu1Size = EU868_RFU1_SIZE;
+ phyParam.BeaconFormat.Rfu2Size = EU868_RFU2_SIZE;
+ break;
+ }
+ case PHY_BEACON_CHANNEL_DR:
+ {
+ phyParam.Value = EU868_BEACON_CHANNEL_DR;
+ break;
+ }
+ case PHY_PING_SLOT_CHANNEL_DR:
+ {
+ phyParam.Value = EU868_PING_SLOT_CHANNEL_DR;
break;
}
default:
@@ -331,32 +365,58 @@ IRAM_ATTR PhyParam_t RegionEU868GetPhyParam( GetPhyParams_t* getPhy )
return phyParam;
}
-IRAM_ATTR void RegionEU868SetBandTxDone( SetBandTxDoneParams_t* txDone )
+void RegionEU868SetBandTxDone( SetBandTxDoneParams_t* txDone )
{
- RegionCommonSetBandTxDone( txDone->Joined, &Bands[Channels[txDone->Channel].Band], txDone->LastTxDoneTime );
+ RegionCommonSetBandTxDone( txDone->Joined, &NvmCtx.Bands[NvmCtx.Channels[txDone->Channel].Band], txDone->LastTxDoneTime );
}
-void RegionEU868InitDefaults( InitType_t type )
+void RegionEU868InitDefaults( InitDefaultsParams_t* params )
{
- switch( type )
+ Band_t bands[EU868_MAX_NB_BANDS] =
+ {
+ EU868_BAND0,
+ EU868_BAND1,
+ EU868_BAND2,
+ EU868_BAND3,
+ EU868_BAND4,
+ EU868_BAND5,
+ };
+
+ switch( params->Type )
{
case INIT_TYPE_INIT:
{
+ // Initialize bands
+ memcpy1( ( uint8_t* )NvmCtx.Bands, ( uint8_t* )bands, sizeof( Band_t ) * EU868_MAX_NB_BANDS );
+
// Channels
- Channels[0] = ( ChannelParams_t ) EU868_LC1;
- Channels[1] = ( ChannelParams_t ) EU868_LC2;
- Channels[2] = ( ChannelParams_t ) EU868_LC3;
+ NvmCtx.Channels[0] = ( ChannelParams_t ) EU868_LC1;
+ NvmCtx.Channels[1] = ( ChannelParams_t ) EU868_LC2;
+ NvmCtx.Channels[2] = ( ChannelParams_t ) EU868_LC3;
// Initialize the channels default mask
- ChannelsDefaultMask[0] = LC( 1 ) + LC( 2 ) + LC( 3 );
+ NvmCtx.ChannelsDefaultMask[0] = LC( 1 ) + LC( 2 ) + LC( 3 );
// Update the channels mask
- RegionCommonChanMaskCopy( ChannelsMask, ChannelsDefaultMask, 1 );
+ RegionCommonChanMaskCopy( NvmCtx.ChannelsMask, NvmCtx.ChannelsDefaultMask, 1 );
break;
}
- case INIT_TYPE_RESTORE:
+ case INIT_TYPE_RESTORE_CTX:
+ {
+ if( params->NvmCtx != 0 )
+ {
+ memcpy1( (uint8_t*) &NvmCtx, (uint8_t*) params->NvmCtx, sizeof( NvmCtx ) );
+ }
+ break;
+ }
+ case INIT_TYPE_RESTORE_DEFAULT_CHANNELS:
{
// Restore channels default mask
- ChannelsMask[0] |= ChannelsDefaultMask[0];
+ NvmCtx.ChannelsMask[0] |= NvmCtx.ChannelsDefaultMask[0];
+
+ // Channels
+ NvmCtx.Channels[0] = ( ChannelParams_t ) EU868_LC1;
+ NvmCtx.Channels[1] = ( ChannelParams_t ) EU868_LC2;
+ NvmCtx.Channels[2] = ( ChannelParams_t ) EU868_LC3;
break;
}
default:
@@ -366,10 +426,21 @@ void RegionEU868InitDefaults( InitType_t type )
}
}
+void* RegionEU868GetNvmCtx( GetNvmCtxParams_t* params )
+{
+ params->nvmCtxSize = sizeof( RegionEU868NvmCtx_t );
+ return &NvmCtx;
+}
+
bool RegionEU868Verify( VerifyParams_t* verify, PhyAttribute_t phyAttribute )
{
switch( phyAttribute )
{
+ case PHY_FREQUENCY:
+ {
+ uint8_t band = 0;
+ return VerifyRfFreq( verify->Frequency, &band );
+ }
case PHY_TX_DR:
{
return RegionCommonValueInRange( verify->DatarateParams.Datarate, EU868_TX_MIN_DATARATE, EU868_TX_MAX_DATARATE );
@@ -392,18 +463,9 @@ bool RegionEU868Verify( VerifyParams_t* verify, PhyAttribute_t phyAttribute )
{
return EU868_DUTY_CYCLE_ENABLED;
}
- case PHY_NB_JOIN_TRIALS:
- {
- if( verify->NbJoinTrials < 48 )
- {
- return false;
- }
- break;
- }
default:
return false;
}
- return true;
}
void RegionEU868ApplyCFList( ApplyCFListParams_t* applyCFList )
@@ -421,6 +483,12 @@ void RegionEU868ApplyCFList( ApplyCFListParams_t* applyCFList )
return;
}
+ // Last byte CFListType must be 0 to indicate the CFList contains a list of frequencies
+ if( applyCFList->Payload[15] != 0 )
+ {
+ return;
+ }
+
// Last byte is RFU, don't take it into account
for( uint8_t i = 0, chanIdx = EU868_NUMB_DEFAULT_CHANNELS; chanIdx < EU868_MAX_NB_CHANNELS; i+=3, chanIdx++ )
{
@@ -465,12 +533,12 @@ bool RegionEU868ChanMaskSet( ChanMaskSetParams_t* chanMaskSet )
{
case CHANNELS_MASK:
{
- RegionCommonChanMaskCopy( ChannelsMask, chanMaskSet->ChannelsMaskIn, 1 );
+ RegionCommonChanMaskCopy( NvmCtx.ChannelsMask, chanMaskSet->ChannelsMaskIn, 1 );
break;
}
case CHANNELS_DEFAULT_MASK:
{
- RegionCommonChanMaskCopy( ChannelsDefaultMask, chanMaskSet->ChannelsMaskIn, 1 );
+ RegionCommonChanMaskCopy( NvmCtx.ChannelsDefaultMask, chanMaskSet->ChannelsMaskIn, 1 );
break;
}
default:
@@ -479,66 +547,6 @@ bool RegionEU868ChanMaskSet( ChanMaskSetParams_t* chanMaskSet )
return true;
}
-bool RegionEU868AdrNext( AdrNextParams_t* adrNext, int8_t* drOut, int8_t* txPowOut, uint32_t* adrAckCounter )
-{
- bool adrAckReq = false;
- int8_t datarate = adrNext->Datarate;
- int8_t txPower = adrNext->TxPower;
- GetPhyParams_t getPhy;
- PhyParam_t phyParam;
-
- // Report back the adr ack counter
- *adrAckCounter = adrNext->AdrAckCounter;
-
- if( adrNext->AdrEnabled == true )
- {
- if( datarate == EU868_TX_MIN_DATARATE )
- {
- *adrAckCounter = 0;
- adrAckReq = false;
- }
- else
- {
- if( adrNext->AdrAckCounter >= EU868_ADR_ACK_LIMIT )
- {
- adrAckReq = true;
- txPower = EU868_MAX_TX_POWER;
- }
- else
- {
- adrAckReq = false;
- }
- if( adrNext->AdrAckCounter >= ( EU868_ADR_ACK_LIMIT + EU868_ADR_ACK_DELAY ) )
- {
- if( ( adrNext->AdrAckCounter % EU868_ADR_ACK_DELAY ) == 1 )
- {
- // Decrease the datarate
- getPhy.Attribute = PHY_NEXT_LOWER_TX_DR;
- getPhy.Datarate = datarate;
- getPhy.UplinkDwellTime = adrNext->UplinkDwellTime;
- phyParam = RegionEU868GetPhyParam( &getPhy );
- datarate = phyParam.Value;
-
- if( datarate == EU868_TX_MIN_DATARATE )
- {
- // We must set adrAckReq to false as soon as we reach the lowest datarate
- adrAckReq = false;
- if( adrNext->UpdateChanMask == true )
- {
- // Re-enable default channels
- ChannelsMask[0] |= LC( 1 ) + LC( 2 ) + LC( 3 );
- }
- }
- }
- }
- }
- }
-
- *drOut = datarate;
- *txPowOut = txPower;
- return adrAckReq;
-}
-
void RegionEU868ComputeRxWindowParameters( int8_t datarate, uint8_t minRxSymbols, uint32_t rxError, RxConfigParams_t *rxConfigParams )
{
double tSymbol = 0.0;
@@ -556,8 +564,7 @@ void RegionEU868ComputeRxWindowParameters( int8_t datarate, uint8_t minRxSymbols
tSymbol = RegionCommonComputeSymbolTimeLoRa( DataratesEU868[rxConfigParams->Datarate], BandwidthsEU868[rxConfigParams->Datarate] );
}
- RegionCommonComputeRxWindowParameters( tSymbol, minRxSymbols, rxError, RADIO_WAKEUP_TIME, &rxConfigParams->WindowTimeout, &rxConfigParams->WindowOffset );
- rxConfigParams->WindowTimeout = rxConfigParams->WindowTimeout * 3;
+ RegionCommonComputeRxWindowParameters( tSymbol, minRxSymbols, rxError, Radio.GetWakeupTime( ), &rxConfigParams->WindowTimeout, &rxConfigParams->WindowOffset );
}
bool RegionEU868RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate )
@@ -573,14 +580,14 @@ bool RegionEU868RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate )
return false;
}
- if( rxConfig->Window == 0 )
+ if( rxConfig->RxSlot == RX_SLOT_WIN_1 )
{
// Apply window 1 frequency
- frequency = Channels[rxConfig->Channel].Frequency;
+ frequency = NvmCtx.Channels[rxConfig->Channel].Frequency;
// Apply the alternative RX 1 window frequency, if it is available
- if( Channels[rxConfig->Channel].Rx1Frequency != 0 )
+ if( NvmCtx.Channels[rxConfig->Channel].Rx1Frequency != 0 )
{
- frequency = Channels[rxConfig->Channel].Rx1Frequency;
+ frequency = NvmCtx.Channels[rxConfig->Channel].Rx1Frequency;
}
}
@@ -620,7 +627,7 @@ bool RegionEU868TxConfig( TxConfigParams_t* txConfig, int8_t* txPower, TimerTime
{
RadioModems_t modem;
int8_t phyDr = DataratesEU868[txConfig->Datarate];
- int8_t txPowerLimited = LimitTxPower( txConfig->TxPower, Bands[Channels[txConfig->Channel].Band].TxMaxPower, txConfig->Datarate, ChannelsMask );
+ int8_t txPowerLimited = LimitTxPower( txConfig->TxPower, NvmCtx.Bands[NvmCtx.Channels[txConfig->Channel].Band].TxMaxPower, txConfig->Datarate, NvmCtx.ChannelsMask );
uint32_t bandwidth = GetBandwidth( txConfig->Datarate );
int8_t phyTxPower = 0;
@@ -628,17 +635,17 @@ bool RegionEU868TxConfig( TxConfigParams_t* txConfig, int8_t* txPower, TimerTime
phyTxPower = RegionCommonComputeTxPower( txPowerLimited, txConfig->MaxEirp, txConfig->AntennaGain );
// Setup the radio frequency
- Radio.SetChannel( Channels[txConfig->Channel].Frequency );
+ Radio.SetChannel( NvmCtx.Channels[txConfig->Channel].Frequency );
if( txConfig->Datarate == DR_7 )
{ // High Speed FSK channel
modem = MODEM_FSK;
- Radio.SetTxConfig( modem, phyTxPower, 25000, bandwidth, phyDr * 1000, 0, 5, false, true, 0, 0, false, 3000 );
+ Radio.SetTxConfig( modem, phyTxPower, 25000, bandwidth, phyDr * 1000, 0, 5, false, true, 0, 0, false, 4000 );
}
else
{
modem = MODEM_LORA;
- Radio.SetTxConfig( modem, phyTxPower, 0, bandwidth, phyDr, 1, 8, false, true, 0, 0, false, 3000 );
+ Radio.SetTxConfig( modem, phyTxPower, 0, bandwidth, phyDr, 1, 8, false, true, 0, 0, false, 4000 );
}
// Setup maximum payload lenght of the radio driver
@@ -695,7 +702,7 @@ uint8_t RegionEU868LinkAdrReq( LinkAdrReqParams_t* linkAdrReq, int8_t* drOut, in
{
if( linkAdrParams.ChMaskCtrl == 6 )
{
- if( Channels[i].Frequency != 0 )
+ if( NvmCtx.Channels[i].Frequency != 0 )
{
chMask |= 1 << i;
}
@@ -703,7 +710,7 @@ uint8_t RegionEU868LinkAdrReq( LinkAdrReqParams_t* linkAdrReq, int8_t* drOut, in
else
{
if( ( ( chMask & ( 1 << i ) ) != 0 ) &&
- ( Channels[i].Frequency == 0 ) )
+ ( NvmCtx.Channels[i].Frequency == 0 ) )
{// Trying to enable an undefined channel
status &= 0xFE; // Channel mask KO
}
@@ -729,9 +736,10 @@ uint8_t RegionEU868LinkAdrReq( LinkAdrReqParams_t* linkAdrReq, int8_t* drOut, in
linkAdrVerifyParams.ChannelsMask = &chMask;
linkAdrVerifyParams.MinDatarate = ( int8_t )phyParam.Value;
linkAdrVerifyParams.MaxDatarate = EU868_TX_MAX_DATARATE;
- linkAdrVerifyParams.Channels = Channels;
+ linkAdrVerifyParams.Channels = NvmCtx.Channels;
linkAdrVerifyParams.MinTxPower = EU868_MIN_TX_POWER;
linkAdrVerifyParams.MaxTxPower = EU868_MAX_TX_POWER;
+ linkAdrVerifyParams.Version = linkAdrReq->Version;
// Verify the parameters and update, if necessary
status = RegionCommonLinkAdrReqVerifyParams( &linkAdrVerifyParams, &linkAdrParams.Datarate, &linkAdrParams.TxPower, &linkAdrParams.NbRep );
@@ -740,9 +748,9 @@ uint8_t RegionEU868LinkAdrReq( LinkAdrReqParams_t* linkAdrReq, int8_t* drOut, in
if( status == 0x07 )
{
// Set the channels mask to a default value
- memset( ChannelsMask, 0, sizeof( ChannelsMask ) );
+ memset1( ( uint8_t* ) NvmCtx.ChannelsMask, 0, sizeof( NvmCtx.ChannelsMask ) );
// Update the channels mask
- ChannelsMask[0] = chMask;
+ NvmCtx.ChannelsMask[0] = chMask;
}
// Update status variables
@@ -757,9 +765,10 @@ uint8_t RegionEU868LinkAdrReq( LinkAdrReqParams_t* linkAdrReq, int8_t* drOut, in
uint8_t RegionEU868RxParamSetupReq( RxParamSetupReqParams_t* rxParamSetupReq )
{
uint8_t status = 0x07;
+ uint8_t band = 0;
// Verify radio frequency
- if( Radio.CheckRfFrequency( rxParamSetupReq->Frequency ) == false )
+ if( VerifyRfFreq( rxParamSetupReq->Frequency, &band ) == false )
{
status &= 0xFE; // Channel frequency KO
}
@@ -843,13 +852,13 @@ uint8_t RegionEU868DlChannelReq( DlChannelReqParams_t* dlChannelReq )
uint8_t band = 0;
// Verify if the frequency is supported
- if( VerifyTxFreq( dlChannelReq->Rx1Frequency, &band ) == false )
+ if( VerifyRfFreq( dlChannelReq->Rx1Frequency, &band ) == false )
{
status &= 0xFE;
}
// Verify if an uplink frequency exists
- if( Channels[dlChannelReq->ChannelId].Frequency == 0 )
+ if( NvmCtx.Channels[dlChannelReq->ChannelId].Frequency == 0 )
{
status &= 0xFD;
}
@@ -857,49 +866,23 @@ uint8_t RegionEU868DlChannelReq( DlChannelReqParams_t* dlChannelReq )
// Apply Rx1 frequency, if the status is OK
if( status == 0x03 )
{
- Channels[dlChannelReq->ChannelId].Rx1Frequency = dlChannelReq->Rx1Frequency;
+ NvmCtx.Channels[dlChannelReq->ChannelId].Rx1Frequency = dlChannelReq->Rx1Frequency;
}
return status;
}
-int8_t RegionEU868AlternateDr( AlternateDrParams_t* alternateDr )
+int8_t RegionEU868AlternateDr( int8_t currentDr, AlternateDrType_t type )
{
- int8_t datarate = 0;
-
- if( ( alternateDr->NbTrials % 48 ) == 0 )
- {
- datarate = DR_0;
- }
- else if( ( alternateDr->NbTrials % 32 ) == 0 )
- {
- datarate = DR_1;
- }
- else if( ( alternateDr->NbTrials % 24 ) == 0 )
- {
- datarate = DR_2;
- }
- else if( ( alternateDr->NbTrials % 16 ) == 0 )
- {
- datarate = DR_3;
- }
- else if( ( alternateDr->NbTrials % 8 ) == 0 )
- {
- datarate = DR_4;
- }
- else
- {
- datarate = DR_5;
- }
- return datarate;
+ return currentDr;
}
void RegionEU868CalcBackOff( CalcBackOffParams_t* calcBackOff )
{
RegionCommonCalcBackOffParams_t calcBackOffParams;
- calcBackOffParams.Channels = Channels;
- calcBackOffParams.Bands = Bands;
+ calcBackOffParams.Channels = NvmCtx.Channels;
+ calcBackOffParams.Bands = NvmCtx.Bands;
calcBackOffParams.LastTxIsJoinRequest = calcBackOff->LastTxIsJoinRequest;
calcBackOffParams.Joined = calcBackOff->Joined;
calcBackOffParams.DutyCycleEnabled = calcBackOff->DutyCycleEnabled;
@@ -910,35 +893,36 @@ void RegionEU868CalcBackOff( CalcBackOffParams_t* calcBackOff )
RegionCommonCalcBackOff( &calcBackOffParams );
}
-bool RegionEU868NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff )
+LoRaMacStatus_t RegionEU868NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff )
{
uint8_t nbEnabledChannels = 0;
uint8_t delayTx = 0;
uint8_t enabledChannels[EU868_MAX_NB_CHANNELS] = { 0 };
TimerTime_t nextTxDelay = 0;
- if( RegionCommonCountChannels( ChannelsMask, 0, 1 ) == 0 )
+ if( RegionCommonCountChannels( NvmCtx.ChannelsMask, 0, 1 ) == 0 )
{ // Reactivate default channels
- ChannelsMask[0] |= LC( 1 ) + LC( 2 ) + LC( 3 );
+ NvmCtx.ChannelsMask[0] |= LC( 1 ) + LC( 2 ) + LC( 3 );
}
- if( nextChanParams->AggrTimeOff <= TimerGetElapsedTime( nextChanParams->LastAggrTx ) )
+ TimerTime_t elapsed = TimerGetElapsedTime( nextChanParams->LastAggrTx );
+ if( ( nextChanParams->LastAggrTx == 0 ) || ( nextChanParams->AggrTimeOff <= elapsed ) )
{
// Reset Aggregated time off
*aggregatedTimeOff = 0;
// Update bands Time OFF
- nextTxDelay = RegionCommonUpdateBandTimeOff( nextChanParams->Joined, nextChanParams->DutyCycleEnabled, Bands, EU868_MAX_NB_BANDS );
+ nextTxDelay = RegionCommonUpdateBandTimeOff( nextChanParams->Joined, nextChanParams->DutyCycleEnabled, NvmCtx.Bands, EU868_MAX_NB_BANDS );
// Search how many channels are enabled
nbEnabledChannels = CountNbOfEnabledChannels( nextChanParams->Joined, nextChanParams->Datarate,
- ChannelsMask, Channels,
- Bands, enabledChannels, &delayTx );
+ NvmCtx.ChannelsMask, NvmCtx.Channels,
+ NvmCtx.Bands, enabledChannels, &delayTx );
}
else
{
delayTx++;
- nextTxDelay = nextChanParams->AggrTimeOff - TimerGetElapsedTime( nextChanParams->LastAggrTx );
+ nextTxDelay = nextChanParams->AggrTimeOff - elapsed;
}
if( nbEnabledChannels > 0 )
@@ -947,7 +931,7 @@ bool RegionEU868NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel,
*channel = enabledChannels[randr( 0, nbEnabledChannels - 1 )];
*time = 0;
- return true;
+ return LORAMAC_STATUS_OK;
}
else
{
@@ -955,12 +939,12 @@ bool RegionEU868NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel,
{
// Delay transmission due to AggregatedTimeOff or to a band time off
*time = nextTxDelay;
- return true;
+ return LORAMAC_STATUS_DUTYCYCLE_RESTRICTED;
}
// Datarate not supported by any channel, restore defaults
- ChannelsMask[0] |= LC( 1 ) + LC( 2 ) + LC( 3 );
+ NvmCtx.ChannelsMask[0] |= LC( 1 ) + LC( 2 ) + LC( 3 );
*time = 0;
- return false;
+ return LORAMAC_STATUS_NO_CHANNEL_FOUND;
}
}
@@ -971,6 +955,11 @@ LoRaMacStatus_t RegionEU868ChannelAdd( ChannelAddParams_t* channelAdd )
bool freqInvalid = false;
uint8_t id = channelAdd->ChannelId;
+ if( id < EU868_NUMB_DEFAULT_CHANNELS )
+ {
+ return LORAMAC_STATUS_FREQ_AND_DR_INVALID;
+ }
+
if( id >= EU868_MAX_NB_CHANNELS )
{
return LORAMAC_STATUS_PARAMETER_INVALID;
@@ -990,30 +979,10 @@ LoRaMacStatus_t RegionEU868ChannelAdd( ChannelAddParams_t* channelAdd )
drInvalid = true;
}
- // Default channels don't accept all values
- if( id < EU868_NUMB_DEFAULT_CHANNELS )
- {
- // Validate the datarate range for min: must be DR_0
- if( channelAdd->NewChannel->DrRange.Fields.Min > DR_0 )
- {
- drInvalid = true;
- }
- // Validate the datarate range for max: must be DR_5 <= Max <= TX_MAX_DATARATE
- if( RegionCommonValueInRange( channelAdd->NewChannel->DrRange.Fields.Max, DR_5, EU868_TX_MAX_DATARATE ) == false )
- {
- drInvalid = true;
- }
- // We are not allowed to change the frequency
- if( channelAdd->NewChannel->Frequency != Channels[id].Frequency )
- {
- freqInvalid = true;
- }
- }
-
// Check frequency
if( freqInvalid == false )
{
- if( VerifyTxFreq( channelAdd->NewChannel->Frequency, &band ) == false )
+ if( VerifyRfFreq( channelAdd->NewChannel->Frequency, &band ) == false )
{
freqInvalid = true;
}
@@ -1033,9 +1002,9 @@ LoRaMacStatus_t RegionEU868ChannelAdd( ChannelAddParams_t* channelAdd )
return LORAMAC_STATUS_FREQUENCY_INVALID;
}
- memcpy( &(Channels[id]), channelAdd->NewChannel, sizeof( Channels[id] ) );
- Channels[id].Band = band;
- ChannelsMask[0] |= ( 1 << id );
+ memcpy1( ( uint8_t* ) &(NvmCtx.Channels[id]), ( uint8_t* ) channelAdd->NewChannel, sizeof( NvmCtx.Channels[id] ) );
+ NvmCtx.Channels[id].Band = band;
+ NvmCtx.ChannelsMask[0] |= ( 1 << id );
return LORAMAC_STATUS_OK;
}
@@ -1081,7 +1050,7 @@ LoRaMacStatus_t RegionEU868ChannelManualAdd( ChannelAddParams_t* channelAdd )
}
// Check frequency
- if( VerifyTxFreq( channelAdd->NewChannel->Frequency, &band ) == false )
+ if( VerifyRfFreq( channelAdd->NewChannel->Frequency, &band ) == false )
{
freqInvalid = true;
}
@@ -1100,9 +1069,10 @@ LoRaMacStatus_t RegionEU868ChannelManualAdd( ChannelAddParams_t* channelAdd )
return LORAMAC_STATUS_FREQUENCY_INVALID;
}
- memcpy( &(Channels[id]), channelAdd->NewChannel, sizeof( Channels[id] ) );
- Channels[id].Band = band;
- ChannelsMask[0] |= ( 1 << id );
+ memcpy( &(NvmCtx.Channels[id]), channelAdd->NewChannel, sizeof( NvmCtx.Channels[id] ) );
+ NvmCtx.Channels[id].Band = band;
+ NvmCtx.ChannelsMask[0] |= ( 1 << id );
+
return LORAMAC_STATUS_OK;
}
@@ -1116,16 +1086,16 @@ bool RegionEU868ChannelsRemove( ChannelRemoveParams_t* channelRemove )
}
// Remove the channel from the list of channels
- Channels[id] = ( ChannelParams_t ){ 0, 0, { 0 }, 0 };
+ NvmCtx.Channels[id] = ( ChannelParams_t ){ 0, 0, { 0 }, 0 };
- return RegionCommonChanDisable( ChannelsMask, id, EU868_MAX_NB_CHANNELS );
+ return RegionCommonChanDisable( NvmCtx.ChannelsMask, id, EU868_MAX_NB_CHANNELS );
}
void RegionEU868SetContinuousWave( ContinuousWaveParams_t* continuousWave )
{
- int8_t txPowerLimited = LimitTxPower( continuousWave->TxPower, Bands[Channels[continuousWave->Channel].Band].TxMaxPower, continuousWave->Datarate, ChannelsMask );
+ int8_t txPowerLimited = LimitTxPower( continuousWave->TxPower, NvmCtx.Bands[NvmCtx.Channels[continuousWave->Channel].Band].TxMaxPower, continuousWave->Datarate, NvmCtx.ChannelsMask );
int8_t phyTxPower = 0;
- uint32_t frequency = Channels[continuousWave->Channel].Frequency;
+ uint32_t frequency = NvmCtx.Channels[continuousWave->Channel].Frequency;
// Calculate physical TX power
phyTxPower = RegionCommonComputeTxPower( txPowerLimited, continuousWave->MaxEirp, continuousWave->AntennaGain );
@@ -1144,25 +1114,20 @@ uint8_t RegionEU868ApplyDrOffset( uint8_t downlinkDwellTime, int8_t dr, int8_t d
return datarate;
}
-bool RegionEU868GetChannels( ChannelParams_t** channels, uint32_t *size )
+void RegionEU868RxBeaconSetup( RxBeaconSetup_t* rxBeaconSetup, uint8_t* outDr )
{
- *channels = Channels;
- *size = sizeof(Channels);
- return true;
-}
+ RegionCommonRxBeaconSetupParams_t regionCommonRxBeaconSetup;
-bool RegionEU868GetChannelMask( uint16_t** channelmask, uint32_t *size )
-{
- *channelmask = ChannelsMask;
- *size = sizeof(ChannelsMask);
- return true;
-}
+ regionCommonRxBeaconSetup.Datarates = DataratesEU868;
+ regionCommonRxBeaconSetup.Frequency = rxBeaconSetup->Frequency;
+ regionCommonRxBeaconSetup.BeaconSize = EU868_BEACON_SIZE;
+ regionCommonRxBeaconSetup.BeaconDatarate = EU868_BEACON_CHANNEL_DR;
+ regionCommonRxBeaconSetup.BeaconChannelBW = EU868_BEACON_CHANNEL_BW;
+ regionCommonRxBeaconSetup.RxTime = rxBeaconSetup->RxTime;
+ regionCommonRxBeaconSetup.SymbolTimeout = rxBeaconSetup->SymbolTimeout;
-bool RegionEU868ForceJoinDataRate( int8_t joinDr, AlternateDrParams_t* alternateDr )
-{
- uint8_t DRToCounter[6] = { 48, 32, 24, 16, 8, 1 };
- if (joinDr < sizeof(DRToCounter)) {
- alternateDr->NbTrials = DRToCounter[joinDr];
- }
- return true;
+ RegionCommonRxBeaconSetup( ®ionCommonRxBeaconSetup );
+
+ // Store downlink datarate
+ *outDr = EU868_BEACON_CHANNEL_DR;
}
diff --git a/lib/lora/mac/region/RegionEU868.h b/lib/lora/mac/region/RegionEU868.h
index 4691e42663..4475d2aff0 100644
--- a/lib/lora/mac/region/RegionEU868.h
+++ b/lib/lora/mac/region/RegionEU868.h
@@ -12,7 +12,7 @@
* \____ \| ___ | (_ _) ___ |/ ___) _ \
* _____) ) ____| | | || |_| ____( (___| | | |
* (______/|_____)_|_|_| \__)_____)\____)_| |_|
- * (C)2013 Semtech
+ * (C)2013-2017 Semtech
*
* ___ _____ _ ___ _ _____ ___ ___ ___ ___
* / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
@@ -28,6 +28,8 @@
*
* \author Daniel Jaeckle ( STACKFORCE )
*
+ * \author Johannes Bruder ( STACKFORCE )
+ *
* \defgroup REGIONEU868 Region EU868
* Implementation according to LoRaWAN Specification v1.0.2.
* \{
@@ -35,6 +37,13 @@
#ifndef __REGION_EU868_H__
#define __REGION_EU868_H__
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include "Region.h"
+
/*!
* LoRaMac maximum number of channels
*/
@@ -58,7 +67,7 @@
/*!
* Maximal datarate that can be used by the node
*/
-#define EU868_TX_MAX_DATARATE DR_6
+#define EU868_TX_MAX_DATARATE DR_7
/*!
* Minimal datarate that can be used by the node
@@ -68,7 +77,7 @@
/*!
* Maximal datarate that can be used by the node
*/
-#define EU868_RX_MAX_DATARATE DR_6
+#define EU868_RX_MAX_DATARATE DR_7
/*!
* Default datarate used by the node
@@ -184,40 +193,84 @@
*/
#define EU868_RX_WND_2_DR DR_0
+/*
+ * CLASS B
+ */
+/*!
+ * Beacon frequency
+ */
+#define EU868_BEACON_CHANNEL_FREQ 869525000
+
+/*!
+ * Payload size of a beacon frame
+ */
+#define EU868_BEACON_SIZE 17
+
+/*!
+ * Size of RFU 1 field
+ */
+#define EU868_RFU1_SIZE 2
+
+/*!
+ * Size of RFU 2 field
+ */
+#define EU868_RFU2_SIZE 0
+
+/*!
+ * Datarate of the beacon channel
+ */
+#define EU868_BEACON_CHANNEL_DR DR_3
+
+/*!
+ * Bandwith of the beacon channel
+ */
+#define EU868_BEACON_CHANNEL_BW 0
+
+/*!
+ * Ping slot channel datarate
+ */
+#define EU868_PING_SLOT_CHANNEL_DR DR_3
+
/*!
* Maximum number of bands
*/
-#define EU868_MAX_NB_BANDS 5
+#define EU868_MAX_NB_BANDS 6
/*!
* Band 0 definition
- * { DutyCycle, TxMaxPower, LastTxDoneTime, TimeOff }
+ * { DutyCycle, TxMaxPower, LastJoinTxDoneTime, LastTxDoneTime, TimeOff }
*/
-#define EU868_BAND0 { 100 , EU868_MAX_TX_POWER, 0, 0 } // 1.0 %
+#define EU868_BAND0 { 100 , EU868_MAX_TX_POWER, 0, 0, 0 } // 1.0 %
/*!
* Band 1 definition
- * { DutyCycle, TxMaxPower, LastTxDoneTime, TimeOff }
+ * { DutyCycle, TxMaxPower, LastJoinTxDoneTime, LastTxDoneTime, TimeOff }
*/
-#define EU868_BAND1 { 100 , EU868_MAX_TX_POWER, 0, 0 } // 1.0 %
+#define EU868_BAND1 { 100 , EU868_MAX_TX_POWER, 0, 0, 0 } // 1.0 %
/*!
* Band 2 definition
- * Band = { DutyCycle, TxMaxPower, LastTxDoneTime, TimeOff }
+ * Band = { DutyCycle, TxMaxPower, LastJoinTxDoneTime, LastTxDoneTime, TimeOff }
*/
-#define EU868_BAND2 { 1000, EU868_MAX_TX_POWER, 0, 0 } // 0.1 %
+#define EU868_BAND2 { 1000, EU868_MAX_TX_POWER, 0, 0, 0 } // 0.1 %
/*!
- * Band 2 definition
- * Band = { DutyCycle, TxMaxPower, LastTxDoneTime, TimeOff }
+ * Band 3 definition
+ * Band = { DutyCycle, TxMaxPower, LastJoinTxDoneTime, LastTxDoneTime, TimeOff }
*/
-#define EU868_BAND3 { 10 , EU868_MAX_TX_POWER, 0, 0 } // 10.0 %
+#define EU868_BAND3 { 10 , EU868_MAX_TX_POWER, 0, 0, 0 } // 10.0 %
/*!
- * Band 2 definition
- * Band = { DutyCycle, TxMaxPower, LastTxDoneTime, TimeOff }
+ * Band 4 definition
+ * Band = { DutyCycle, TxMaxPower, LastJoinTxDoneTime, LastTxDoneTime, TimeOff }
*/
-#define EU868_BAND4 { 100 , EU868_MAX_TX_POWER, 0, 0 } // 1.0 %
+#define EU868_BAND4 { 100 , EU868_MAX_TX_POWER, 0, 0, 0 } // 1.0 %
+
+/*!
+ * Band 5 definition
+ * Band = { DutyCycle, TxMaxPower, LastJoinTxDoneTime, LastTxDoneTime, TimeOff }
+ */
+#define EU868_BAND5 { 1000, EU868_MAX_TX_POWER, 0, 0, 0 } // 0.1 %
/*!
* LoRaMac default channel 1
@@ -283,7 +336,16 @@ void RegionEU868SetBandTxDone( SetBandTxDoneParams_t* txDone );
*
* \param [IN] type Sets the initialization type.
*/
-void RegionEU868InitDefaults( InitType_t type );
+void RegionEU868InitDefaults( InitDefaultsParams_t* params );
+
+/*!
+ * \brief Returns a pointer to the internal context and its size.
+ *
+ * \param [OUT] params Pointer to the function parameters.
+ *
+ * \retval Points to a structure where the module store its non-volatile context.
+ */
+void* RegionEU868GetNvmCtx( GetNvmCtxParams_t* params );
/*!
* \brief Verifies a parameter.
@@ -313,21 +375,6 @@ void RegionEU868ApplyCFList( ApplyCFListParams_t* applyCFList );
*/
bool RegionEU868ChanMaskSet( ChanMaskSetParams_t* chanMaskSet );
-/*!
- * \brief Calculates the next datarate to set, when ADR is on or off.
- *
- * \param [IN] adrNext Pointer to the function parameters.
- *
- * \param [OUT] drOut The calculated datarate for the next TX.
- *
- * \param [OUT] txPowOut The TX power for the next TX.
- *
- * \param [OUT] adrAckCounter The calculated ADR acknowledgement counter.
- *
- * \retval Returns true, if an ADR request should be performed.
- */
-bool RegionEU868AdrNext( AdrNextParams_t* adrNext, int8_t* drOut, int8_t* txPowOut, uint32_t* adrAckCounter );
-
/*!
* Computes the Rx window timeout and offset.
*
@@ -417,11 +464,11 @@ uint8_t RegionEU868DlChannelReq( DlChannelReqParams_t* dlChannelReq );
/*!
* \brief Alternates the datarate of the channel for the join request.
*
- * \param [IN] alternateDr Pointer to the function parameters.
+ * \param [IN] currentDr Current datarate.
*
* \retval Datarate to apply.
*/
-int8_t RegionEU868AlternateDr( AlternateDrParams_t* alternateDr );
+int8_t RegionEU868AlternateDr( int8_t currentDr, AlternateDrType_t type );
/*!
* \brief Calculates the back-off time.
@@ -442,7 +489,7 @@ void RegionEU868CalcBackOff( CalcBackOffParams_t* calcBackOff );
*
* \retval Function status [1: OK, 0: Unable to find a channel on the current datarate]
*/
-bool RegionEU868NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff );
+LoRaMacStatus_t RegionEU868NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff );
/*!
* \brief Adds a channel.
@@ -483,12 +530,17 @@ void RegionEU868SetContinuousWave( ContinuousWaveParams_t* continuousWave );
*/
uint8_t RegionEU868ApplyDrOffset( uint8_t downlinkDwellTime, int8_t dr, int8_t drOffset );
-bool RegionEU868GetChannels( ChannelParams_t** channels, uint32_t *size );
-
-bool RegionEU868GetChannelMask( uint16_t** channelmask, uint32_t *size );
-
-bool RegionEU868ForceJoinDataRate( int8_t joinDr, AlternateDrParams_t* alternateDr );
+/*!
+ * \brief Sets the radio into beacon reception mode
+ *
+ * \param [IN] rxBeaconSetup Pointer to the function parameters
+ */
+void RegionEU868RxBeaconSetup( RxBeaconSetup_t* rxBeaconSetup, uint8_t* outDr );
/*! \} defgroup REGIONEU868 */
+#ifdef __cplusplus
+}
+#endif
+
#endif // __REGION_EU868_H__
diff --git a/lib/lora/mac/region/RegionIN865.c b/lib/lora/mac/region/RegionIN865.c
index bf85248ac5..8d8b586165 100644
--- a/lib/lora/mac/region/RegionIN865.c
+++ b/lib/lora/mac/region/RegionIN865.c
@@ -1,63 +1,70 @@
-/*
- / _____) _ | |
-( (____ _____ ____ _| |_ _____ ____| |__
- \____ \| ___ | (_ _) ___ |/ ___) _ \
- _____) ) ____| | | || |_| ____( (___| | | |
-(______/|_____)_|_|_| \__)_____)\____)_| |_|
- (C)2013 Semtech
- ___ _____ _ ___ _ _____ ___ ___ ___ ___
-/ __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
-\__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
-|___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
-embedded.connectivity.solutions===============
-
-Description: LoRa MAC region IN865 implementation
-
-License: Revised BSD License, see LICENSE.TXT file include in the project
-
-Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jaeckle ( STACKFORCE )
+/*!
+ * \file RegionIN865.c
+ *
+ * \brief Region implementation for IN865
+ *
+ * \copyright Revised BSD License, see section \ref LICENSE.
+ *
+ * \code
+ * ______ _
+ * / _____) _ | |
+ * ( (____ _____ ____ _| |_ _____ ____| |__
+ * \____ \| ___ | (_ _) ___ |/ ___) _ \
+ * _____) ) ____| | | || |_| ____( (___| | | |
+ * (______/|_____)_|_|_| \__)_____)\____)_| |_|
+ * (C)2013-2017 Semtech
+ *
+ * ___ _____ _ ___ _ _____ ___ ___ ___ ___
+ * / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
+ * \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
+ * |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
+ * embedded.connectivity.solutions===============
+ *
+ * \endcode
+ *
+ * \author Miguel Luis ( Semtech )
+ *
+ * \author Gregory Cristian ( Semtech )
+ *
+ * \author Daniel Jaeckle ( STACKFORCE )
*/
-#include
#include
-#include
-#include
-
-#include "board.h"
-#include "lora/mac/LoRaMac.h"
-#include "esp_attr.h"
#include "utilities.h"
-#include "Region.h"
#include "RegionCommon.h"
#include "RegionIN865.h"
// Definitions
#define CHANNELS_MASK_SIZE 1
-// Global attributes
/*!
- * LoRaMAC channels
+ * Region specific context
*/
-static ChannelParams_t Channels[IN865_MAX_NB_CHANNELS];
-
-/*!
- * LoRaMac bands
- */
-static Band_t Bands[IN865_MAX_NB_BANDS] =
+typedef struct sRegionIN865NvmCtx
{
- IN865_BAND0
-};
-
-/*!
- * LoRaMac channels mask
- */
-static uint16_t ChannelsMask[CHANNELS_MASK_SIZE];
+ /*!
+ * LoRaMAC channels
+ */
+ ChannelParams_t Channels[ IN865_MAX_NB_CHANNELS ];
+ /*!
+ * LoRaMac bands
+ */
+ Band_t Bands[ IN865_MAX_NB_BANDS ];
+ /*!
+ * LoRaMac channels mask
+ */
+ uint16_t ChannelsMask[ CHANNELS_MASK_SIZE ];
+ /*!
+ * LoRaMac channels default mask
+ */
+ uint16_t ChannelsDefaultMask[ CHANNELS_MASK_SIZE ];
+}RegionIN865NvmCtx_t;
-/*!
- * LoRaMac channels default mask
+/*
+ * Non-volatile module context.
*/
-static uint16_t ChannelsDefaultMask[CHANNELS_MASK_SIZE];
+static RegionIN865NvmCtx_t NvmCtx;
// Static functions
static int8_t GetNextLowerTxDr( int8_t dr, int8_t minDr )
@@ -103,7 +110,7 @@ static int8_t LimitTxPower( int8_t txPower, int8_t maxBandTxPower, int8_t datara
return txPowerResult;
}
-static bool VerifyTxFreq( uint32_t freq, uint8_t *band )
+static bool VerifyRfFreq( uint32_t freq )
{
// Check radio driver support
if( Radio.CheckRfFrequency( freq ) == false )
@@ -185,11 +192,26 @@ PhyParam_t RegionIN865GetPhyParam( GetPhyParams_t* getPhy )
phyParam.Value = GetNextLowerTxDr( getPhy->Datarate, IN865_TX_MIN_DATARATE );
break;
}
+ case PHY_MAX_TX_POWER:
+ {
+ phyParam.Value = IN865_MAX_TX_POWER;
+ break;
+ }
case PHY_DEF_TX_POWER:
{
phyParam.Value = IN865_DEFAULT_TX_POWER;
break;
}
+ case PHY_DEF_ADR_ACK_LIMIT:
+ {
+ phyParam.Value = IN865_ADR_ACK_LIMIT;
+ break;
+ }
+ case PHY_DEF_ADR_ACK_DELAY:
+ {
+ phyParam.Value = IN865_ADR_ACK_DELAY;
+ break;
+ }
case PHY_MAX_PAYLOAD:
{
phyParam.Value = MaxPayloadOfDatarateIN865[getPhy->Datarate];
@@ -257,12 +279,12 @@ PhyParam_t RegionIN865GetPhyParam( GetPhyParams_t* getPhy )
}
case PHY_CHANNELS_MASK:
{
- phyParam.ChannelsMask = ChannelsMask;
+ phyParam.ChannelsMask = NvmCtx.ChannelsMask;
break;
}
case PHY_CHANNELS_DEFAULT_MASK:
{
- phyParam.ChannelsMask = ChannelsDefaultMask;
+ phyParam.ChannelsMask = NvmCtx.ChannelsDefaultMask;
break;
}
case PHY_MAX_NB_CHANNELS:
@@ -272,7 +294,7 @@ PhyParam_t RegionIN865GetPhyParam( GetPhyParams_t* getPhy )
}
case PHY_CHANNELS:
{
- phyParam.Channels = Channels;
+ phyParam.Channels = NvmCtx.Channels;
break;
}
case PHY_DEF_UPLINK_DWELL_TIME:
@@ -291,10 +313,26 @@ PhyParam_t RegionIN865GetPhyParam( GetPhyParams_t* getPhy )
phyParam.fValue = IN865_DEFAULT_ANTENNA_GAIN;
break;
}
- case PHY_NB_JOIN_TRIALS:
- case PHY_DEF_NB_JOIN_TRIALS:
+ case PHY_BEACON_CHANNEL_FREQ:
+ {
+ phyParam.Value = IN865_BEACON_CHANNEL_FREQ;
+ break;
+ }
+ case PHY_BEACON_FORMAT:
+ {
+ phyParam.BeaconFormat.BeaconSize = IN865_BEACON_SIZE;
+ phyParam.BeaconFormat.Rfu1Size = IN865_RFU1_SIZE;
+ phyParam.BeaconFormat.Rfu2Size = IN865_RFU2_SIZE;
+ break;
+ }
+ case PHY_BEACON_CHANNEL_DR:
+ {
+ phyParam.Value = IN865_BEACON_CHANNEL_DR;
+ break;
+ }
+ case PHY_PING_SLOT_CHANNEL_DR:
{
- phyParam.Value = 48;
+ phyParam.Value = IN865_PING_SLOT_CHANNEL_DR;
break;
}
default:
@@ -306,32 +344,53 @@ PhyParam_t RegionIN865GetPhyParam( GetPhyParams_t* getPhy )
return phyParam;
}
-IRAM_ATTR void RegionIN865SetBandTxDone( SetBandTxDoneParams_t* txDone )
+void RegionIN865SetBandTxDone( SetBandTxDoneParams_t* txDone )
{
- RegionCommonSetBandTxDone( txDone->Joined, &Bands[Channels[txDone->Channel].Band], txDone->LastTxDoneTime );
+ RegionCommonSetBandTxDone( txDone->Joined, &NvmCtx.Bands[NvmCtx.Channels[txDone->Channel].Band], txDone->LastTxDoneTime );
}
-void RegionIN865InitDefaults( InitType_t type )
+void RegionIN865InitDefaults( InitDefaultsParams_t* params )
{
- switch( type )
+ Band_t bands[IN865_MAX_NB_BANDS] =
+ {
+ IN865_BAND0
+ };
+
+ switch( params->Type )
{
case INIT_TYPE_INIT:
{
+ // Initialize bands
+ memcpy1( ( uint8_t* )NvmCtx.Bands, ( uint8_t* )bands, sizeof( Band_t ) * IN865_MAX_NB_BANDS );
+
// Channels
- Channels[0] = ( ChannelParams_t ) IN865_LC1;
- Channels[1] = ( ChannelParams_t ) IN865_LC2;
- Channels[2] = ( ChannelParams_t ) IN865_LC3;
+ NvmCtx.Channels[0] = ( ChannelParams_t ) IN865_LC1;
+ NvmCtx.Channels[1] = ( ChannelParams_t ) IN865_LC2;
+ NvmCtx.Channels[2] = ( ChannelParams_t ) IN865_LC3;
// Initialize the channels default mask
- ChannelsDefaultMask[0] = LC( 1 ) + LC( 2 ) + LC( 3 );
+ NvmCtx.ChannelsDefaultMask[0] = LC( 1 ) + LC( 2 ) + LC( 3 );
// Update the channels mask
- RegionCommonChanMaskCopy( ChannelsMask, ChannelsDefaultMask, 1 );
+ RegionCommonChanMaskCopy( NvmCtx.ChannelsMask, NvmCtx.ChannelsDefaultMask, 1 );
+ break;
+ }
+ case INIT_TYPE_RESTORE_CTX:
+ {
+ if( params->NvmCtx != 0 )
+ {
+ memcpy1( (uint8_t*) &NvmCtx, (uint8_t*) params->NvmCtx, sizeof( NvmCtx ) );
+ }
break;
}
- case INIT_TYPE_RESTORE:
+ case INIT_TYPE_RESTORE_DEFAULT_CHANNELS:
{
// Restore channels default mask
- ChannelsMask[0] |= ChannelsDefaultMask[0];
+ NvmCtx.ChannelsMask[0] |= NvmCtx.ChannelsDefaultMask[0];
+
+ // Channels
+ NvmCtx.Channels[0] = ( ChannelParams_t ) IN865_LC1;
+ NvmCtx.Channels[1] = ( ChannelParams_t ) IN865_LC2;
+ NvmCtx.Channels[2] = ( ChannelParams_t ) IN865_LC3;
break;
}
default:
@@ -341,13 +400,30 @@ void RegionIN865InitDefaults( InitType_t type )
}
}
+void* RegionIN865GetNvmCtx( GetNvmCtxParams_t* params )
+{
+ params->nvmCtxSize = sizeof( RegionIN865NvmCtx_t );
+ return &NvmCtx;
+}
+
bool RegionIN865Verify( VerifyParams_t* verify, PhyAttribute_t phyAttribute )
{
switch( phyAttribute )
{
+ case PHY_FREQUENCY:
+ {
+ return VerifyRfFreq( verify->Frequency );
+ }
case PHY_TX_DR:
{
- return RegionCommonValueInRange( verify->DatarateParams.Datarate, IN865_TX_MIN_DATARATE, IN865_TX_MAX_DATARATE );
+ if( verify->DatarateParams.Datarate == DR_6 )
+ {// DR_6 is not supported by this region
+ return false;
+ }
+ else
+ {
+ return RegionCommonValueInRange( verify->DatarateParams.Datarate, IN865_TX_MIN_DATARATE, IN865_TX_MAX_DATARATE );
+ }
}
case PHY_DEF_TX_DR:
{
@@ -355,7 +431,14 @@ bool RegionIN865Verify( VerifyParams_t* verify, PhyAttribute_t phyAttribute )
}
case PHY_RX_DR:
{
- return RegionCommonValueInRange( verify->DatarateParams.Datarate, IN865_RX_MIN_DATARATE, IN865_RX_MAX_DATARATE );
+ if( verify->DatarateParams.Datarate == DR_6 )
+ {// DR_6 is not supported by this region
+ return false;
+ }
+ else
+ {
+ return RegionCommonValueInRange( verify->DatarateParams.Datarate, IN865_RX_MIN_DATARATE, IN865_RX_MAX_DATARATE );
+ }
}
case PHY_DEF_TX_POWER:
case PHY_TX_POWER:
@@ -367,18 +450,9 @@ bool RegionIN865Verify( VerifyParams_t* verify, PhyAttribute_t phyAttribute )
{
return IN865_DUTY_CYCLE_ENABLED;
}
- case PHY_NB_JOIN_TRIALS:
- {
- if( verify->NbJoinTrials < 48 )
- {
- return false;
- }
- break;
- }
default:
return false;
}
- return true;
}
void RegionIN865ApplyCFList( ApplyCFListParams_t* applyCFList )
@@ -396,6 +470,12 @@ void RegionIN865ApplyCFList( ApplyCFListParams_t* applyCFList )
return;
}
+ // Last byte CFListType must be 0 to indicate the CFList contains a list of frequencies
+ if( applyCFList->Payload[15] != 0 )
+ {
+ return;
+ }
+
// Last byte is RFU, don't take it into account
for( uint8_t i = 0, chanIdx = IN865_NUMB_DEFAULT_CHANNELS; chanIdx < IN865_MAX_NB_CHANNELS; i+=3, chanIdx++ )
{
@@ -440,12 +520,12 @@ bool RegionIN865ChanMaskSet( ChanMaskSetParams_t* chanMaskSet )
{
case CHANNELS_MASK:
{
- RegionCommonChanMaskCopy( ChannelsMask, chanMaskSet->ChannelsMaskIn, 1 );
+ RegionCommonChanMaskCopy( NvmCtx.ChannelsMask, chanMaskSet->ChannelsMaskIn, 1 );
break;
}
case CHANNELS_DEFAULT_MASK:
{
- RegionCommonChanMaskCopy( ChannelsDefaultMask, chanMaskSet->ChannelsMaskIn, 1 );
+ RegionCommonChanMaskCopy( NvmCtx.ChannelsDefaultMask, chanMaskSet->ChannelsMaskIn, 1 );
break;
}
default:
@@ -454,66 +534,6 @@ bool RegionIN865ChanMaskSet( ChanMaskSetParams_t* chanMaskSet )
return true;
}
-bool RegionIN865AdrNext( AdrNextParams_t* adrNext, int8_t* drOut, int8_t* txPowOut, uint32_t* adrAckCounter )
-{
- bool adrAckReq = false;
- int8_t datarate = adrNext->Datarate;
- int8_t txPower = adrNext->TxPower;
- GetPhyParams_t getPhy;
- PhyParam_t phyParam;
-
- // Report back the adr ack counter
- *adrAckCounter = adrNext->AdrAckCounter;
-
- if( adrNext->AdrEnabled == true )
- {
- if( datarate == IN865_TX_MIN_DATARATE )
- {
- *adrAckCounter = 0;
- adrAckReq = false;
- }
- else
- {
- if( adrNext->AdrAckCounter >= IN865_ADR_ACK_LIMIT )
- {
- adrAckReq = true;
- txPower = IN865_MAX_TX_POWER;
- }
- else
- {
- adrAckReq = false;
- }
- if( adrNext->AdrAckCounter >= ( IN865_ADR_ACK_LIMIT + IN865_ADR_ACK_DELAY ) )
- {
- if( ( adrNext->AdrAckCounter % IN865_ADR_ACK_DELAY ) == 1 )
- {
- // Decrease the datarate
- getPhy.Attribute = PHY_NEXT_LOWER_TX_DR;
- getPhy.Datarate = datarate;
- getPhy.UplinkDwellTime = adrNext->UplinkDwellTime;
- phyParam = RegionIN865GetPhyParam( &getPhy );
- datarate = phyParam.Value;
-
- if( datarate == IN865_TX_MIN_DATARATE )
- {
- // We must set adrAckReq to false as soon as we reach the lowest datarate
- adrAckReq = false;
- if( adrNext->UpdateChanMask == true )
- {
- // Re-enable default channels
- ChannelsMask[0] |= LC( 1 ) + LC( 2 ) + LC( 3 );
- }
- }
- }
- }
- }
- }
-
- *drOut = datarate;
- *txPowOut = txPower;
- return adrAckReq;
-}
-
void RegionIN865ComputeRxWindowParameters( int8_t datarate, uint8_t minRxSymbols, uint32_t rxError, RxConfigParams_t *rxConfigParams )
{
double tSymbol = 0.0;
@@ -531,7 +551,7 @@ void RegionIN865ComputeRxWindowParameters( int8_t datarate, uint8_t minRxSymbols
tSymbol = RegionCommonComputeSymbolTimeLoRa( DataratesIN865[rxConfigParams->Datarate], BandwidthsIN865[rxConfigParams->Datarate] );
}
- RegionCommonComputeRxWindowParameters( tSymbol, minRxSymbols, rxError, RADIO_WAKEUP_TIME, &rxConfigParams->WindowTimeout, &rxConfigParams->WindowOffset );
+ RegionCommonComputeRxWindowParameters( tSymbol, minRxSymbols, rxError, Radio.GetWakeupTime( ), &rxConfigParams->WindowTimeout, &rxConfigParams->WindowOffset );
}
bool RegionIN865RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate )
@@ -547,14 +567,14 @@ bool RegionIN865RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate )
return false;
}
- if( rxConfig->Window == 0 )
+ if( rxConfig->RxSlot == RX_SLOT_WIN_1 )
{
// Apply window 1 frequency
- frequency = Channels[rxConfig->Channel].Frequency;
+ frequency = NvmCtx.Channels[rxConfig->Channel].Frequency;
// Apply the alternative RX 1 window frequency, if it is available
- if( Channels[rxConfig->Channel].Rx1Frequency != 0 )
+ if( NvmCtx.Channels[rxConfig->Channel].Rx1Frequency != 0 )
{
- frequency = Channels[rxConfig->Channel].Rx1Frequency;
+ frequency = NvmCtx.Channels[rxConfig->Channel].Rx1Frequency;
}
}
@@ -593,7 +613,7 @@ bool RegionIN865TxConfig( TxConfigParams_t* txConfig, int8_t* txPower, TimerTime
{
RadioModems_t modem;
int8_t phyDr = DataratesIN865[txConfig->Datarate];
- int8_t txPowerLimited = LimitTxPower( txConfig->TxPower, Bands[Channels[txConfig->Channel].Band].TxMaxPower, txConfig->Datarate, ChannelsMask );
+ int8_t txPowerLimited = LimitTxPower( txConfig->TxPower, NvmCtx.Bands[NvmCtx.Channels[txConfig->Channel].Band].TxMaxPower, txConfig->Datarate, NvmCtx.ChannelsMask );
uint32_t bandwidth = GetBandwidth( txConfig->Datarate );
int8_t phyTxPower = 0;
@@ -601,17 +621,17 @@ bool RegionIN865TxConfig( TxConfigParams_t* txConfig, int8_t* txPower, TimerTime
phyTxPower = RegionCommonComputeTxPower( txPowerLimited, txConfig->MaxEirp, txConfig->AntennaGain );
// Setup the radio frequency
- Radio.SetChannel( Channels[txConfig->Channel].Frequency );
+ Radio.SetChannel( NvmCtx.Channels[txConfig->Channel].Frequency );
if( txConfig->Datarate == DR_7 )
{ // High Speed FSK channel
modem = MODEM_FSK;
- Radio.SetTxConfig( modem, phyTxPower, 25000, bandwidth, phyDr * 1000, 0, 5, false, true, 0, 0, false, 3000 );
+ Radio.SetTxConfig( modem, phyTxPower, 25000, bandwidth, phyDr * 1000, 0, 5, false, true, 0, 0, false, 4000 );
}
else
{
modem = MODEM_LORA;
- Radio.SetTxConfig( modem, phyTxPower, 0, bandwidth, phyDr, 1, 8, false, true, 0, 0, false, 3000 );
+ Radio.SetTxConfig( modem, phyTxPower, 0, bandwidth, phyDr, 1, 8, false, true, 0, 0, false, 4000 );
}
// Setup maximum payload lenght of the radio driver
@@ -668,7 +688,7 @@ uint8_t RegionIN865LinkAdrReq( LinkAdrReqParams_t* linkAdrReq, int8_t* drOut, in
{
if( linkAdrParams.ChMaskCtrl == 6 )
{
- if( Channels[i].Frequency != 0 )
+ if( NvmCtx.Channels[i].Frequency != 0 )
{
chMask |= 1 << i;
}
@@ -676,7 +696,7 @@ uint8_t RegionIN865LinkAdrReq( LinkAdrReqParams_t* linkAdrReq, int8_t* drOut, in
else
{
if( ( ( chMask & ( 1 << i ) ) != 0 ) &&
- ( Channels[i].Frequency == 0 ) )
+ ( NvmCtx.Channels[i].Frequency == 0 ) )
{// Trying to enable an undefined channel
status &= 0xFE; // Channel mask KO
}
@@ -685,37 +705,45 @@ uint8_t RegionIN865LinkAdrReq( LinkAdrReqParams_t* linkAdrReq, int8_t* drOut, in
}
}
- // Get the minimum possible datarate
- getPhy.Attribute = PHY_MIN_TX_DR;
- getPhy.UplinkDwellTime = linkAdrReq->UplinkDwellTime;
- phyParam = RegionIN865GetPhyParam( &getPhy );
-
- linkAdrVerifyParams.Status = status;
- linkAdrVerifyParams.AdrEnabled = linkAdrReq->AdrEnabled;
- linkAdrVerifyParams.Datarate = linkAdrParams.Datarate;
- linkAdrVerifyParams.TxPower = linkAdrParams.TxPower;
- linkAdrVerifyParams.NbRep = linkAdrParams.NbRep;
- linkAdrVerifyParams.CurrentDatarate = linkAdrReq->CurrentDatarate;
- linkAdrVerifyParams.CurrentTxPower = linkAdrReq->CurrentTxPower;
- linkAdrVerifyParams.CurrentNbRep = linkAdrReq->CurrentNbRep;
- linkAdrVerifyParams.NbChannels = IN865_MAX_NB_CHANNELS;
- linkAdrVerifyParams.ChannelsMask = &chMask;
- linkAdrVerifyParams.MinDatarate = ( int8_t )phyParam.Value;
- linkAdrVerifyParams.MaxDatarate = IN865_TX_MAX_DATARATE;
- linkAdrVerifyParams.Channels = Channels;
- linkAdrVerifyParams.MinTxPower = IN865_MIN_TX_POWER;
- linkAdrVerifyParams.MaxTxPower = IN865_MAX_TX_POWER;
-
- // Verify the parameters and update, if necessary
- status = RegionCommonLinkAdrReqVerifyParams( &linkAdrVerifyParams, &linkAdrParams.Datarate, &linkAdrParams.TxPower, &linkAdrParams.NbRep );
+ if( linkAdrParams.Datarate != DR_6 )
+ {
+ // Get the minimum possible datarate
+ getPhy.Attribute = PHY_MIN_TX_DR;
+ getPhy.UplinkDwellTime = linkAdrReq->UplinkDwellTime;
+ phyParam = RegionIN865GetPhyParam( &getPhy );
+
+ linkAdrVerifyParams.Status = status;
+ linkAdrVerifyParams.AdrEnabled = linkAdrReq->AdrEnabled;
+ linkAdrVerifyParams.Datarate = linkAdrParams.Datarate;
+ linkAdrVerifyParams.TxPower = linkAdrParams.TxPower;
+ linkAdrVerifyParams.NbRep = linkAdrParams.NbRep;
+ linkAdrVerifyParams.CurrentDatarate = linkAdrReq->CurrentDatarate;
+ linkAdrVerifyParams.CurrentTxPower = linkAdrReq->CurrentTxPower;
+ linkAdrVerifyParams.CurrentNbRep = linkAdrReq->CurrentNbRep;
+ linkAdrVerifyParams.NbChannels = IN865_MAX_NB_CHANNELS;
+ linkAdrVerifyParams.ChannelsMask = &chMask;
+ linkAdrVerifyParams.MinDatarate = ( int8_t )phyParam.Value;
+ linkAdrVerifyParams.MaxDatarate = IN865_TX_MAX_DATARATE;
+ linkAdrVerifyParams.Channels = NvmCtx.Channels;
+ linkAdrVerifyParams.MinTxPower = IN865_MIN_TX_POWER;
+ linkAdrVerifyParams.MaxTxPower = IN865_MAX_TX_POWER;
+ linkAdrVerifyParams.Version = linkAdrReq->Version;
+
+ // Verify the parameters and update, if necessary
+ status = RegionCommonLinkAdrReqVerifyParams( &linkAdrVerifyParams, &linkAdrParams.Datarate, &linkAdrParams.TxPower, &linkAdrParams.NbRep );
+ }
+ else
+ {// DR_6 is not supported by this region
+ status &= 0xFD; // Datarate KO
+ }
// Update channelsMask if everything is correct
if( status == 0x07 )
{
// Set the channels mask to a default value
- memset( ChannelsMask, 0, sizeof( ChannelsMask ) );
+ memset1( ( uint8_t* ) NvmCtx.ChannelsMask, 0, sizeof( NvmCtx.ChannelsMask ) );
// Update the channels mask
- ChannelsMask[0] = chMask;
+ NvmCtx.ChannelsMask[0] = chMask;
}
// Update status variables
@@ -732,7 +760,7 @@ uint8_t RegionIN865RxParamSetupReq( RxParamSetupReqParams_t* rxParamSetupReq )
uint8_t status = 0x07;
// Verify radio frequency
- if( Radio.CheckRfFrequency( rxParamSetupReq->Frequency ) == false )
+ if( VerifyRfFreq( rxParamSetupReq->Frequency ) == false )
{
status &= 0xFE; // Channel frequency KO
}
@@ -813,16 +841,15 @@ int8_t RegionIN865TxParamSetupReq( TxParamSetupReqParams_t* txParamSetupReq )
uint8_t RegionIN865DlChannelReq( DlChannelReqParams_t* dlChannelReq )
{
uint8_t status = 0x03;
- uint8_t band = 0;
// Verify if the frequency is supported
- if( VerifyTxFreq( dlChannelReq->Rx1Frequency, &band ) == false )
+ if( VerifyRfFreq( dlChannelReq->Rx1Frequency ) == false )
{
status &= 0xFE;
}
// Verify if an uplink frequency exists
- if( Channels[dlChannelReq->ChannelId].Frequency == 0 )
+ if( NvmCtx.Channels[dlChannelReq->ChannelId].Frequency == 0 )
{
status &= 0xFD;
}
@@ -830,49 +857,23 @@ uint8_t RegionIN865DlChannelReq( DlChannelReqParams_t* dlChannelReq )
// Apply Rx1 frequency, if the status is OK
if( status == 0x03 )
{
- Channels[dlChannelReq->ChannelId].Rx1Frequency = dlChannelReq->Rx1Frequency;
+ NvmCtx.Channels[dlChannelReq->ChannelId].Rx1Frequency = dlChannelReq->Rx1Frequency;
}
return status;
}
-int8_t RegionIN865AlternateDr( AlternateDrParams_t* alternateDr )
+int8_t RegionIN865AlternateDr( int8_t currentDr, AlternateDrType_t type )
{
- int8_t datarate = 0;
-
- if( ( alternateDr->NbTrials % 48 ) == 0 )
- {
- datarate = DR_0;
- }
- else if( ( alternateDr->NbTrials % 32 ) == 0 )
- {
- datarate = DR_1;
- }
- else if( ( alternateDr->NbTrials % 24 ) == 0 )
- {
- datarate = DR_2;
- }
- else if( ( alternateDr->NbTrials % 16 ) == 0 )
- {
- datarate = DR_3;
- }
- else if( ( alternateDr->NbTrials % 8 ) == 0 )
- {
- datarate = DR_4;
- }
- else
- {
- datarate = DR_5;
- }
- return datarate;
+ return currentDr;
}
void RegionIN865CalcBackOff( CalcBackOffParams_t* calcBackOff )
{
RegionCommonCalcBackOffParams_t calcBackOffParams;
- calcBackOffParams.Channels = Channels;
- calcBackOffParams.Bands = Bands;
+ calcBackOffParams.Channels = NvmCtx.Channels;
+ calcBackOffParams.Bands = NvmCtx.Bands;
calcBackOffParams.LastTxIsJoinRequest = calcBackOff->LastTxIsJoinRequest;
calcBackOffParams.Joined = calcBackOff->Joined;
calcBackOffParams.DutyCycleEnabled = calcBackOff->DutyCycleEnabled;
@@ -883,35 +884,36 @@ void RegionIN865CalcBackOff( CalcBackOffParams_t* calcBackOff )
RegionCommonCalcBackOff( &calcBackOffParams );
}
-bool RegionIN865NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff )
+LoRaMacStatus_t RegionIN865NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff )
{
uint8_t nbEnabledChannels = 0;
uint8_t delayTx = 0;
uint8_t enabledChannels[IN865_MAX_NB_CHANNELS] = { 0 };
TimerTime_t nextTxDelay = 0;
- if( RegionCommonCountChannels( ChannelsMask, 0, 1 ) == 0 )
+ if( RegionCommonCountChannels( NvmCtx.ChannelsMask, 0, 1 ) == 0 )
{ // Reactivate default channels
- ChannelsMask[0] |= LC( 1 ) + LC( 2 ) + LC( 3 );
+ NvmCtx.ChannelsMask[0] |= LC( 1 ) + LC( 2 ) + LC( 3 );
}
- if( nextChanParams->AggrTimeOff <= TimerGetElapsedTime( nextChanParams->LastAggrTx ) )
+ TimerTime_t elapsed = TimerGetElapsedTime( nextChanParams->LastAggrTx );
+ if( ( nextChanParams->LastAggrTx == 0 ) || ( nextChanParams->AggrTimeOff <= elapsed ) )
{
// Reset Aggregated time off
*aggregatedTimeOff = 0;
// Update bands Time OFF
- nextTxDelay = RegionCommonUpdateBandTimeOff( nextChanParams->Joined, nextChanParams->DutyCycleEnabled, Bands, IN865_MAX_NB_BANDS );
+ nextTxDelay = RegionCommonUpdateBandTimeOff( nextChanParams->Joined, nextChanParams->DutyCycleEnabled, NvmCtx.Bands, IN865_MAX_NB_BANDS );
// Search how many channels are enabled
nbEnabledChannels = CountNbOfEnabledChannels( nextChanParams->Joined, nextChanParams->Datarate,
- ChannelsMask, Channels,
- Bands, enabledChannels, &delayTx );
+ NvmCtx.ChannelsMask, NvmCtx.Channels,
+ NvmCtx.Bands, enabledChannels, &delayTx );
}
else
{
delayTx++;
- nextTxDelay = nextChanParams->AggrTimeOff - TimerGetElapsedTime( nextChanParams->LastAggrTx );
+ nextTxDelay = nextChanParams->AggrTimeOff - elapsed;
}
if( nbEnabledChannels > 0 )
@@ -920,7 +922,7 @@ bool RegionIN865NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel,
*channel = enabledChannels[randr( 0, nbEnabledChannels - 1 )];
*time = 0;
- return true;
+ return LORAMAC_STATUS_OK;
}
else
{
@@ -928,22 +930,26 @@ bool RegionIN865NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel,
{
// Delay transmission due to AggregatedTimeOff or to a band time off
*time = nextTxDelay;
- return true;
+ return LORAMAC_STATUS_DUTYCYCLE_RESTRICTED;
}
// Datarate not supported by any channel, restore defaults
- ChannelsMask[0] |= LC( 1 ) + LC( 2 ) + LC( 3 );
+ NvmCtx.ChannelsMask[0] |= LC( 1 ) + LC( 2 ) + LC( 3 );
*time = 0;
- return false;
+ return LORAMAC_STATUS_NO_CHANNEL_FOUND;
}
}
LoRaMacStatus_t RegionIN865ChannelAdd( ChannelAddParams_t* channelAdd )
{
- uint8_t band = 0;
bool drInvalid = false;
bool freqInvalid = false;
uint8_t id = channelAdd->ChannelId;
+ if( id < IN865_NUMB_DEFAULT_CHANNELS )
+ {
+ return LORAMAC_STATUS_FREQ_AND_DR_INVALID;
+ }
+
if( id >= IN865_MAX_NB_CHANNELS )
{
return LORAMAC_STATUS_PARAMETER_INVALID;
@@ -963,30 +969,10 @@ LoRaMacStatus_t RegionIN865ChannelAdd( ChannelAddParams_t* channelAdd )
drInvalid = true;
}
- // Default channels don't accept all values
- if( id < IN865_NUMB_DEFAULT_CHANNELS )
- {
- // Validate the datarate range for min: must be DR_0
- if( channelAdd->NewChannel->DrRange.Fields.Min > DR_0 )
- {
- drInvalid = true;
- }
- // Validate the datarate range for max: must be DR_5 <= Max <= TX_MAX_DATARATE
- if( RegionCommonValueInRange( channelAdd->NewChannel->DrRange.Fields.Max, DR_5, IN865_TX_MAX_DATARATE ) == false )
- {
- drInvalid = true;
- }
- // We are not allowed to change the frequency
- if( channelAdd->NewChannel->Frequency != Channels[id].Frequency )
- {
- freqInvalid = true;
- }
- }
-
// Check frequency
if( freqInvalid == false )
{
- if( VerifyTxFreq( channelAdd->NewChannel->Frequency, &band ) == false )
+ if( VerifyRfFreq( channelAdd->NewChannel->Frequency ) == false )
{
freqInvalid = true;
}
@@ -1006,12 +992,63 @@ LoRaMacStatus_t RegionIN865ChannelAdd( ChannelAddParams_t* channelAdd )
return LORAMAC_STATUS_FREQUENCY_INVALID;
}
- memcpy( &(Channels[id]), channelAdd->NewChannel, sizeof( Channels[id] ) );
- Channels[id].Band = band;
- ChannelsMask[0] |= ( 1 << id );
+ memcpy1( ( uint8_t* ) &(NvmCtx.Channels[id]), ( uint8_t* ) channelAdd->NewChannel, sizeof( NvmCtx.Channels[id] ) );
+ NvmCtx.Channels[id].Band = 0;
+ NvmCtx.ChannelsMask[0] |= ( 1 << id );
return LORAMAC_STATUS_OK;
}
+bool RegionIN865ChannelsRemove( ChannelRemoveParams_t* channelRemove )
+{
+ uint8_t id = channelRemove->ChannelId;
+
+ if( id < IN865_NUMB_DEFAULT_CHANNELS )
+ {
+ return false;
+ }
+
+ // Remove the channel from the list of channels
+ NvmCtx.Channels[id] = ( ChannelParams_t ){ 0, 0, { 0 }, 0 };
+
+ return RegionCommonChanDisable( NvmCtx.ChannelsMask, id, IN865_MAX_NB_CHANNELS );
+}
+
+void RegionIN865SetContinuousWave( ContinuousWaveParams_t* continuousWave )
+{
+ int8_t txPowerLimited = LimitTxPower( continuousWave->TxPower, NvmCtx.Bands[NvmCtx.Channels[continuousWave->Channel].Band].TxMaxPower, continuousWave->Datarate, NvmCtx.ChannelsMask );
+ int8_t phyTxPower = 0;
+ uint32_t frequency = NvmCtx.Channels[continuousWave->Channel].Frequency;
+
+ // Calculate physical TX power
+ phyTxPower = RegionCommonComputeTxPower( txPowerLimited, continuousWave->MaxEirp, continuousWave->AntennaGain );
+
+ Radio.SetTxContinuousWave( frequency, phyTxPower, continuousWave->Timeout );
+}
+
+uint8_t RegionIN865ApplyDrOffset( uint8_t downlinkDwellTime, int8_t dr, int8_t drOffset )
+{
+ // Apply offset formula
+ return MIN( DR_5, MAX( DR_0, dr - EffectiveRx1DrOffsetIN865[drOffset] ) );
+}
+
+void RegionIN865RxBeaconSetup( RxBeaconSetup_t* rxBeaconSetup, uint8_t* outDr )
+{
+ RegionCommonRxBeaconSetupParams_t regionCommonRxBeaconSetup;
+
+ regionCommonRxBeaconSetup.Datarates = DataratesIN865;
+ regionCommonRxBeaconSetup.Frequency = rxBeaconSetup->Frequency;
+ regionCommonRxBeaconSetup.BeaconSize = IN865_BEACON_SIZE;
+ regionCommonRxBeaconSetup.BeaconDatarate = IN865_BEACON_CHANNEL_DR;
+ regionCommonRxBeaconSetup.BeaconChannelBW = IN865_BEACON_CHANNEL_BW;
+ regionCommonRxBeaconSetup.RxTime = rxBeaconSetup->RxTime;
+ regionCommonRxBeaconSetup.SymbolTimeout = rxBeaconSetup->SymbolTimeout;
+
+ RegionCommonRxBeaconSetup( ®ionCommonRxBeaconSetup );
+
+ // Store downlink datarate
+ *outDr = IN865_BEACON_CHANNEL_DR;
+}
+
LoRaMacStatus_t RegionIN865ChannelManualAdd( ChannelAddParams_t* channelAdd )
{
uint8_t band = 0;
@@ -1054,7 +1091,7 @@ LoRaMacStatus_t RegionIN865ChannelManualAdd( ChannelAddParams_t* channelAdd )
}
// Check frequency
- if( VerifyTxFreq( channelAdd->NewChannel->Frequency, &band ) == false )
+ if( VerifyRfFreq( channelAdd->NewChannel->Frequency ) == false )
{
freqInvalid = true;
}
@@ -1073,64 +1110,8 @@ LoRaMacStatus_t RegionIN865ChannelManualAdd( ChannelAddParams_t* channelAdd )
return LORAMAC_STATUS_FREQUENCY_INVALID;
}
- memcpy( &(Channels[id]), channelAdd->NewChannel, sizeof( Channels[id] ) );
- Channels[id].Band = band;
- ChannelsMask[0] |= ( 1 << id );
+ memcpy( &(NvmCtx.Channels[id]), channelAdd->NewChannel, sizeof( NvmCtx.Channels[id] ) );
+ NvmCtx.Channels[id].Band = band;
+ NvmCtx.ChannelsMask[0] |= ( 1 << id );
return LORAMAC_STATUS_OK;
}
-
-bool RegionIN865ChannelsRemove( ChannelRemoveParams_t* channelRemove )
-{
- uint8_t id = channelRemove->ChannelId;
-
- if( id < IN865_NUMB_DEFAULT_CHANNELS )
- {
- return false;
- }
-
- // Remove the channel from the list of channels
- Channels[id] = ( ChannelParams_t ){ 0, 0, { 0 }, 0 };
-
- return RegionCommonChanDisable( ChannelsMask, id, IN865_MAX_NB_CHANNELS );
-}
-
-void RegionIN865SetContinuousWave( ContinuousWaveParams_t* continuousWave )
-{
- int8_t txPowerLimited = LimitTxPower( continuousWave->TxPower, Bands[Channels[continuousWave->Channel].Band].TxMaxPower, continuousWave->Datarate, ChannelsMask );
- int8_t phyTxPower = 0;
- uint32_t frequency = Channels[continuousWave->Channel].Frequency;
-
- // Calculate physical TX power
- phyTxPower = RegionCommonComputeTxPower( txPowerLimited, continuousWave->MaxEirp, continuousWave->AntennaGain );
-
- Radio.SetTxContinuousWave( frequency, phyTxPower, continuousWave->Timeout );
-}
-
-uint8_t RegionIN865ApplyDrOffset( uint8_t downlinkDwellTime, int8_t dr, int8_t drOffset )
-{
- // Apply offset formula
- return MIN( DR_5, MAX( DR_0, dr - EffectiveRx1DrOffsetIN865[drOffset] ) );
-}
-
-bool RegionIN865GetChannels( ChannelParams_t** channels, uint32_t *size )
-{
- *channels = Channels;
- *size = sizeof(Channels);
- return true;
-}
-
-bool RegionIN865GetChannelMask( uint16_t** channelmask, uint32_t *size )
-{
- *channelmask = ChannelsMask;
- *size = sizeof(ChannelsMask);
- return true;
-}
-
-bool RegionIN865ForceJoinDataRate( int8_t joinDr, AlternateDrParams_t* alternateDr )
-{
- uint8_t DRToCounter[6] = { 48, 32, 24, 16, 8, 1 };
- if (joinDr < sizeof(DRToCounter)) {
- alternateDr->NbTrials = DRToCounter[joinDr];
- }
- return true;
-}
diff --git a/lib/lora/mac/region/RegionIN865.h b/lib/lora/mac/region/RegionIN865.h
index f3837cda4f..6edfd7c6ae 100644
--- a/lib/lora/mac/region/RegionIN865.h
+++ b/lib/lora/mac/region/RegionIN865.h
@@ -12,7 +12,7 @@
* \____ \| ___ | (_ _) ___ |/ ___) _ \
* _____) ) ____| | | || |_| ____( (___| | | |
* (______/|_____)_|_|_| \__)_____)\____)_| |_|
- * (C)2013 Semtech
+ * (C)2013-2017 Semtech
*
* ___ _____ _ ___ _ _____ ___ ___ ___ ___
* / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
@@ -28,6 +28,8 @@
*
* \author Daniel Jaeckle ( STACKFORCE )
*
+ * \author Johannes Bruder ( STACKFORCE )
+ *
* \defgroup REGIONIN865 Region IN865
* Implementation according to LoRaWAN Specification v1.0.2.
* \{
@@ -35,6 +37,13 @@
#ifndef __REGION_IN865_H__
#define __REGION_IN865_H__
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include "Region.h"
+
/*!
* LoRaMac maximum number of channels
*/
@@ -184,6 +193,44 @@
*/
#define IN865_RX_WND_2_DR DR_2
+/*
+ * CLASS B
+ */
+/*!
+ * Beacon frequency
+ */
+#define IN865_BEACON_CHANNEL_FREQ 866550000
+
+/*!
+ * Payload size of a beacon frame
+ */
+#define IN865_BEACON_SIZE 19
+
+/*!
+ * Size of RFU 1 field
+ */
+#define IN865_RFU1_SIZE 1
+
+/*!
+ * Size of RFU 2 field
+ */
+#define IN865_RFU2_SIZE 3
+
+/*!
+ * Datarate of the beacon channel
+ */
+#define IN865_BEACON_CHANNEL_DR DR_4
+
+/*!
+ * Bandwith of the beacon channel
+ */
+#define IN865_BEACON_CHANNEL_BW 0
+
+/*!
+ * Ping slot channel datarate
+ */
+#define IN865_PING_SLOT_CHANNEL_DR DR_4
+
/*!
* Maximum number of bands
*/
@@ -191,9 +238,9 @@
/*!
* Band 0 definition
- * { DutyCycle, TxMaxPower, LastTxDoneTime, TimeOff }
+ * { DutyCycle, TxMaxPower, LastJoinTxDoneTime, LastTxDoneTime, TimeOff }
*/
-#define IN865_BAND0 { 1 , IN865_MAX_TX_POWER, 0, 0 } // 100.0 %
+#define IN865_BAND0 { 1 , IN865_MAX_TX_POWER, 0, 0, 0 } // 100.0 %
/*!
* LoRaMac default channel 1
@@ -264,7 +311,16 @@ void RegionIN865SetBandTxDone( SetBandTxDoneParams_t* txDone );
*
* \param [IN] type Sets the initialization type.
*/
-void RegionIN865InitDefaults( InitType_t type );
+void RegionIN865InitDefaults( InitDefaultsParams_t* params );
+
+/*!
+ * \brief Returns a pointer to the internal context and its size.
+ *
+ * \param [OUT] params Pointer to the function parameters.
+ *
+ * \retval Points to a structure where the module store its non-volatile context.
+ */
+void* RegionIN865GetNvmCtx( GetNvmCtxParams_t* params );
/*!
* \brief Verifies a parameter.
@@ -294,21 +350,6 @@ void RegionIN865ApplyCFList( ApplyCFListParams_t* applyCFList );
*/
bool RegionIN865ChanMaskSet( ChanMaskSetParams_t* chanMaskSet );
-/*!
- * \brief Calculates the next datarate to set, when ADR is on or off.
- *
- * \param [IN] adrNext Pointer to the function parameters.
- *
- * \param [OUT] drOut The calculated datarate for the next TX.
- *
- * \param [OUT] txPowOut The TX power for the next TX.
- *
- * \param [OUT] adrAckCounter The calculated ADR acknowledgement counter.
- *
- * \retval Returns true, if an ADR request should be performed.
- */
-bool RegionIN865AdrNext( AdrNextParams_t* adrNext, int8_t* drOut, int8_t* txPowOut, uint32_t* adrAckCounter );
-
/*!
* Computes the Rx window timeout and offset.
*
@@ -398,11 +439,11 @@ uint8_t RegionIN865DlChannelReq( DlChannelReqParams_t* dlChannelReq );
/*!
* \brief Alternates the datarate of the channel for the join request.
*
- * \param [IN] alternateDr Pointer to the function parameters.
+ * \param [IN] currentDr Current datarate.
*
* \retval Datarate to apply.
*/
-int8_t RegionIN865AlternateDr( AlternateDrParams_t* alternateDr );
+int8_t RegionIN865AlternateDr( int8_t currentDr, AlternateDrType_t type );
/*!
* \brief Calculates the back-off time.
@@ -423,7 +464,7 @@ void RegionIN865CalcBackOff( CalcBackOffParams_t* calcBackOff );
*
* \retval Function status [1: OK, 0: Unable to find a channel on the current datarate]
*/
-bool RegionIN865NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff );
+LoRaMacStatus_t RegionIN865NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff );
/*!
* \brief Adds a channel.
@@ -433,6 +474,7 @@ bool RegionIN865NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel,
* \retval Status of the operation.
*/
LoRaMacStatus_t RegionIN865ChannelAdd( ChannelAddParams_t* channelAdd );
+LoRaMacStatus_t RegionIN865ChannelManualAdd( ChannelAddParams_t* channelAdd );
/*!
* \brief Removes a channel.
@@ -463,16 +505,17 @@ void RegionIN865SetContinuousWave( ContinuousWaveParams_t* continuousWave );
*/
uint8_t RegionIN865ApplyDrOffset( uint8_t downlinkDwellTime, int8_t dr, int8_t drOffset );
-bool RegionIN865ForceJoinDataRate( int8_t joinDr, AlternateDrParams_t* alternateDr );
-
-LoRaMacStatus_t RegionIN865ChannelManualAdd( ChannelAddParams_t* channelAdd );
-
-bool RegionIN865ChannelsRemove( ChannelRemoveParams_t* channelRemove );
-
-bool RegionIN865GetChannels( ChannelParams_t** channels, uint32_t *size );
-
-bool RegionIN865GetChannelMask( uint16_t** channelmask, uint32_t *size );
+/*!
+ * \brief Sets the radio into beacon reception mode
+ *
+ * \param [IN] rxBeaconSetup Pointer to the function parameters
+ */
+ void RegionIN865RxBeaconSetup( RxBeaconSetup_t* rxBeaconSetup, uint8_t* outDr );
/*! \} defgroup REGIONIN865 */
+#ifdef __cplusplus
+}
+#endif
+
#endif // __REGION_IN865_H__
diff --git a/lib/lora/mac/region/RegionKR920.c b/lib/lora/mac/region/RegionKR920.c
index 8377efee3e..5f36c155e4 100644
--- a/lib/lora/mac/region/RegionKR920.c
+++ b/lib/lora/mac/region/RegionKR920.c
@@ -1,63 +1,68 @@
-/*
- / _____) _ | |
-( (____ _____ ____ _| |_ _____ ____| |__
- \____ \| ___ | (_ _) ___ |/ ___) _ \
- _____) ) ____| | | || |_| ____( (___| | | |
-(______/|_____)_|_|_| \__)_____)\____)_| |_|
- (C)2013 Semtech
- ___ _____ _ ___ _ _____ ___ ___ ___ ___
-/ __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
-\__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
-|___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
-embedded.connectivity.solutions===============
-
-Description: LoRa MAC region KR920 implementation
-
-License: Revised BSD License, see LICENSE.TXT file include in the project
-
-Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jaeckle ( STACKFORCE )
+/*!
+ * \file RegionKR920.c
+ *
+ * \brief Region implementation for KR920
+ *
+ * \copyright Revised BSD License, see section \ref LICENSE.
+ *
+ * \code
+ * ______ _
+ * / _____) _ | |
+ * ( (____ _____ ____ _| |_ _____ ____| |__
+ * \____ \| ___ | (_ _) ___ |/ ___) _ \
+ * _____) ) ____| | | || |_| ____( (___| | | |
+ * (______/|_____)_|_|_| \__)_____)\____)_| |_|
+ * (C)2013-2017 Semtech
+ *
+ * ___ _____ _ ___ _ _____ ___ ___ ___ ___
+ * / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
+ * \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
+ * |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
+ * embedded.connectivity.solutions===============
+ *
+ * \endcode
+ *
+ * \author Miguel Luis ( Semtech )
+ *
+ * \author Gregory Cristian ( Semtech )
+ *
+ * \author Daniel Jaeckle ( STACKFORCE )
*/
-#include
-#include
-#include
-#include
-
-#include "board.h"
-#include "LoRaMac.h"
-#include "esp_attr.h"
-
#include "utilities.h"
-#include "Region.h"
#include "RegionCommon.h"
#include "RegionKR920.h"
// Definitions
#define CHANNELS_MASK_SIZE 1
-// Global attributes
/*!
- * LoRaMAC channels
+ * Region specific context
*/
-static ChannelParams_t Channels[KR920_MAX_NB_CHANNELS];
-
-/*!
- * LoRaMac bands
- */
-static Band_t Bands[KR920_MAX_NB_BANDS] =
+typedef struct sRegionKR920NvmCtx
{
- KR920_BAND0
-};
+ /*!
+ * LoRaMAC channels
+ */
+ ChannelParams_t Channels[ KR920_MAX_NB_CHANNELS ];
+ /*!
+ * LoRaMac bands
+ */
+ Band_t Bands[ KR920_MAX_NB_BANDS ];
+ /*!
+ * LoRaMac channels mask
+ */
+ uint16_t ChannelsMask[ CHANNELS_MASK_SIZE ];
+ /*!
+ * LoRaMac channels default mask
+ */
+ uint16_t ChannelsDefaultMask[ CHANNELS_MASK_SIZE ];
+}RegionKR920NvmCtx_t;
-/*!
- * LoRaMac channels mask
- */
-static uint16_t ChannelsMask[CHANNELS_MASK_SIZE];
-
-/*!
- * LoRaMac channels default mask
+/*
+ * Non-volatile module context.
*/
-static uint16_t ChannelsDefaultMask[CHANNELS_MASK_SIZE];
+static RegionKR920NvmCtx_t NvmCtx;
// Static functions
static int8_t GetNextLowerTxDr( int8_t dr, int8_t minDr )
@@ -109,7 +114,7 @@ static int8_t LimitTxPower( int8_t txPower, int8_t maxBandTxPower, int8_t datara
return txPowerResult;
}
-static bool VerifyTxFreq( uint32_t freq )
+static bool VerifyRfFreq( uint32_t freq )
{
uint32_t tmpFreq = freq;
@@ -200,11 +205,26 @@ PhyParam_t RegionKR920GetPhyParam( GetPhyParams_t* getPhy )
phyParam.Value = GetNextLowerTxDr( getPhy->Datarate, KR920_TX_MIN_DATARATE );
break;
}
+ case PHY_MAX_TX_POWER:
+ {
+ phyParam.Value = KR920_MAX_TX_POWER;
+ break;
+ }
case PHY_DEF_TX_POWER:
{
phyParam.Value = KR920_DEFAULT_TX_POWER;
break;
}
+ case PHY_DEF_ADR_ACK_LIMIT:
+ {
+ phyParam.Value = KR920_ADR_ACK_LIMIT;
+ break;
+ }
+ case PHY_DEF_ADR_ACK_DELAY:
+ {
+ phyParam.Value = KR920_ADR_ACK_DELAY;
+ break;
+ }
case PHY_MAX_PAYLOAD:
{
phyParam.Value = MaxPayloadOfDatarateKR920[getPhy->Datarate];
@@ -272,12 +292,12 @@ PhyParam_t RegionKR920GetPhyParam( GetPhyParams_t* getPhy )
}
case PHY_CHANNELS_MASK:
{
- phyParam.ChannelsMask = ChannelsMask;
+ phyParam.ChannelsMask = NvmCtx.ChannelsMask;
break;
}
case PHY_CHANNELS_DEFAULT_MASK:
{
- phyParam.ChannelsMask = ChannelsDefaultMask;
+ phyParam.ChannelsMask = NvmCtx.ChannelsDefaultMask;
break;
}
case PHY_MAX_NB_CHANNELS:
@@ -287,7 +307,7 @@ PhyParam_t RegionKR920GetPhyParam( GetPhyParams_t* getPhy )
}
case PHY_CHANNELS:
{
- phyParam.Channels = Channels;
+ phyParam.Channels = NvmCtx.Channels;
break;
}
case PHY_DEF_UPLINK_DWELL_TIME:
@@ -310,10 +330,26 @@ PhyParam_t RegionKR920GetPhyParam( GetPhyParams_t* getPhy )
phyParam.fValue = KR920_DEFAULT_ANTENNA_GAIN;
break;
}
- case PHY_NB_JOIN_TRIALS:
- case PHY_DEF_NB_JOIN_TRIALS:
+ case PHY_BEACON_CHANNEL_FREQ:
{
- phyParam.Value = 48;
+ phyParam.Value = KR920_BEACON_CHANNEL_FREQ;
+ break;
+ }
+ case PHY_BEACON_FORMAT:
+ {
+ phyParam.BeaconFormat.BeaconSize = KR920_BEACON_SIZE;
+ phyParam.BeaconFormat.Rfu1Size = KR920_RFU1_SIZE;
+ phyParam.BeaconFormat.Rfu2Size = KR920_RFU2_SIZE;
+ break;
+ }
+ case PHY_BEACON_CHANNEL_DR:
+ {
+ phyParam.Value = KR920_BEACON_CHANNEL_DR;
+ break;
+ }
+ case PHY_PING_SLOT_CHANNEL_DR:
+ {
+ phyParam.Value = KR920_PING_SLOT_CHANNEL_DR;
break;
}
default:
@@ -325,32 +361,53 @@ PhyParam_t RegionKR920GetPhyParam( GetPhyParams_t* getPhy )
return phyParam;
}
-IRAM_ATTR void RegionKR920SetBandTxDone( SetBandTxDoneParams_t* txDone )
+void RegionKR920SetBandTxDone( SetBandTxDoneParams_t* txDone )
{
- RegionCommonSetBandTxDone( txDone->Joined, &Bands[Channels[txDone->Channel].Band], txDone->LastTxDoneTime );
+ RegionCommonSetBandTxDone( txDone->Joined, &NvmCtx.Bands[NvmCtx.Channels[txDone->Channel].Band], txDone->LastTxDoneTime );
}
-void RegionKR920InitDefaults( InitType_t type )
+void RegionKR920InitDefaults( InitDefaultsParams_t* params )
{
- switch( type )
+ Band_t bands[KR920_MAX_NB_BANDS] =
+ {
+ KR920_BAND0
+ };
+
+ switch( params->Type )
{
case INIT_TYPE_INIT:
{
+ // Initialize bands
+ memcpy1( ( uint8_t* )NvmCtx.Bands, ( uint8_t* )bands, sizeof( Band_t ) * KR920_MAX_NB_BANDS );
+
// Channels
- Channels[0] = ( ChannelParams_t ) KR920_LC1;
- Channels[1] = ( ChannelParams_t ) KR920_LC2;
- Channels[2] = ( ChannelParams_t ) KR920_LC3;
+ NvmCtx.Channels[0] = ( ChannelParams_t ) KR920_LC1;
+ NvmCtx.Channels[1] = ( ChannelParams_t ) KR920_LC2;
+ NvmCtx.Channels[2] = ( ChannelParams_t ) KR920_LC3;
// Initialize the channels default mask
- ChannelsDefaultMask[0] = LC( 1 ) + LC( 2 ) + LC( 3 );
+ NvmCtx.ChannelsDefaultMask[0] = LC( 1 ) + LC( 2 ) + LC( 3 );
// Update the channels mask
- RegionCommonChanMaskCopy( ChannelsMask, ChannelsDefaultMask, 1 );
+ RegionCommonChanMaskCopy( NvmCtx.ChannelsMask, NvmCtx.ChannelsDefaultMask, 1 );
+ break;
+ }
+ case INIT_TYPE_RESTORE_CTX:
+ {
+ if( params->NvmCtx != 0 )
+ {
+ memcpy1( (uint8_t*) &NvmCtx, (uint8_t*) params->NvmCtx, sizeof( NvmCtx ) );
+ }
break;
}
- case INIT_TYPE_RESTORE:
+ case INIT_TYPE_RESTORE_DEFAULT_CHANNELS:
{
// Restore channels default mask
- ChannelsMask[0] |= ChannelsDefaultMask[0];
+ NvmCtx.ChannelsMask[0] |= NvmCtx.ChannelsDefaultMask[0];
+
+ // Channels
+ NvmCtx.Channels[0] = ( ChannelParams_t ) KR920_LC1;
+ NvmCtx.Channels[1] = ( ChannelParams_t ) KR920_LC2;
+ NvmCtx.Channels[2] = ( ChannelParams_t ) KR920_LC3;
break;
}
default:
@@ -360,10 +417,20 @@ void RegionKR920InitDefaults( InitType_t type )
}
}
+void* RegionKR920GetNvmCtx( GetNvmCtxParams_t* params )
+{
+ params->nvmCtxSize = sizeof( RegionKR920NvmCtx_t );
+ return &NvmCtx;
+}
+
bool RegionKR920Verify( VerifyParams_t* verify, PhyAttribute_t phyAttribute )
{
switch( phyAttribute )
{
+ case PHY_FREQUENCY:
+ {
+ return VerifyRfFreq( verify->Frequency );
+ }
case PHY_TX_DR:
{
return RegionCommonValueInRange( verify->DatarateParams.Datarate, KR920_TX_MIN_DATARATE, KR920_TX_MAX_DATARATE );
@@ -386,18 +453,9 @@ bool RegionKR920Verify( VerifyParams_t* verify, PhyAttribute_t phyAttribute )
{
return KR920_DUTY_CYCLE_ENABLED;
}
- case PHY_NB_JOIN_TRIALS:
- {
- if( verify->NbJoinTrials < 48 )
- {
- return false;
- }
- break;
- }
default:
return false;
}
- return true;
}
void RegionKR920ApplyCFList( ApplyCFListParams_t* applyCFList )
@@ -415,6 +473,12 @@ void RegionKR920ApplyCFList( ApplyCFListParams_t* applyCFList )
return;
}
+ // Last byte CFListType must be 0 to indicate the CFList contains a list of frequencies
+ if( applyCFList->Payload[15] != 0 )
+ {
+ return;
+ }
+
// Last byte is RFU, don't take it into account
for( uint8_t i = 0, chanIdx = KR920_NUMB_DEFAULT_CHANNELS; chanIdx < KR920_MAX_NB_CHANNELS; i+=3, chanIdx++ )
{
@@ -459,12 +523,12 @@ bool RegionKR920ChanMaskSet( ChanMaskSetParams_t* chanMaskSet )
{
case CHANNELS_MASK:
{
- RegionCommonChanMaskCopy( ChannelsMask, chanMaskSet->ChannelsMaskIn, 1 );
+ RegionCommonChanMaskCopy( NvmCtx.ChannelsMask, chanMaskSet->ChannelsMaskIn, 1 );
break;
}
case CHANNELS_DEFAULT_MASK:
{
- RegionCommonChanMaskCopy( ChannelsDefaultMask, chanMaskSet->ChannelsMaskIn, 1 );
+ RegionCommonChanMaskCopy( NvmCtx.ChannelsDefaultMask, chanMaskSet->ChannelsMaskIn, 1 );
break;
}
default:
@@ -473,66 +537,6 @@ bool RegionKR920ChanMaskSet( ChanMaskSetParams_t* chanMaskSet )
return true;
}
-bool RegionKR920AdrNext( AdrNextParams_t* adrNext, int8_t* drOut, int8_t* txPowOut, uint32_t* adrAckCounter )
-{
- bool adrAckReq = false;
- int8_t datarate = adrNext->Datarate;
- int8_t txPower = adrNext->TxPower;
- GetPhyParams_t getPhy;
- PhyParam_t phyParam;
-
- // Report back the adr ack counter
- *adrAckCounter = adrNext->AdrAckCounter;
-
- if( adrNext->AdrEnabled == true )
- {
- if( datarate == KR920_TX_MIN_DATARATE )
- {
- *adrAckCounter = 0;
- adrAckReq = false;
- }
- else
- {
- if( adrNext->AdrAckCounter >= KR920_ADR_ACK_LIMIT )
- {
- adrAckReq = true;
- txPower = KR920_MAX_TX_POWER;
- }
- else
- {
- adrAckReq = false;
- }
- if( adrNext->AdrAckCounter >= ( KR920_ADR_ACK_LIMIT + KR920_ADR_ACK_DELAY ) )
- {
- if( ( adrNext->AdrAckCounter % KR920_ADR_ACK_DELAY ) == 1 )
- {
- // Decrease the datarate
- getPhy.Attribute = PHY_NEXT_LOWER_TX_DR;
- getPhy.Datarate = datarate;
- getPhy.UplinkDwellTime = adrNext->UplinkDwellTime;
- phyParam = RegionKR920GetPhyParam( &getPhy );
- datarate = phyParam.Value;
-
- if( datarate == KR920_TX_MIN_DATARATE )
- {
- // We must set adrAckReq to false as soon as we reach the lowest datarate
- adrAckReq = false;
- if( adrNext->UpdateChanMask == true )
- {
- // Re-enable default channels
- ChannelsMask[0] |= LC( 1 ) + LC( 2 ) + LC( 3 );
- }
- }
- }
- }
- }
- }
-
- *drOut = datarate;
- *txPowOut = txPower;
- return adrAckReq;
-}
-
void RegionKR920ComputeRxWindowParameters( int8_t datarate, uint8_t minRxSymbols, uint32_t rxError, RxConfigParams_t *rxConfigParams )
{
double tSymbol = 0.0;
@@ -543,7 +547,7 @@ void RegionKR920ComputeRxWindowParameters( int8_t datarate, uint8_t minRxSymbols
tSymbol = RegionCommonComputeSymbolTimeLoRa( DataratesKR920[rxConfigParams->Datarate], BandwidthsKR920[rxConfigParams->Datarate] );
- RegionCommonComputeRxWindowParameters( tSymbol, minRxSymbols, rxError, RADIO_WAKEUP_TIME, &rxConfigParams->WindowTimeout, &rxConfigParams->WindowOffset );
+ RegionCommonComputeRxWindowParameters( tSymbol, minRxSymbols, rxError, Radio.GetWakeupTime( ), &rxConfigParams->WindowTimeout, &rxConfigParams->WindowOffset );
}
bool RegionKR920RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate )
@@ -558,14 +562,14 @@ bool RegionKR920RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate )
return false;
}
- if( rxConfig->Window == 0 )
+ if( rxConfig->RxSlot == RX_SLOT_WIN_1 )
{
// Apply window 1 frequency
- frequency = Channels[rxConfig->Channel].Frequency;
+ frequency = NvmCtx.Channels[rxConfig->Channel].Frequency;
// Apply the alternative RX 1 window frequency, if it is available
- if( Channels[rxConfig->Channel].Rx1Frequency != 0 )
+ if( NvmCtx.Channels[rxConfig->Channel].Rx1Frequency != 0 )
{
- frequency = Channels[rxConfig->Channel].Rx1Frequency;
+ frequency = NvmCtx.Channels[rxConfig->Channel].Rx1Frequency;
}
}
@@ -586,9 +590,9 @@ bool RegionKR920RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate )
bool RegionKR920TxConfig( TxConfigParams_t* txConfig, int8_t* txPower, TimerTime_t* txTimeOnAir )
{
int8_t phyDr = DataratesKR920[txConfig->Datarate];
- int8_t txPowerLimited = LimitTxPower( txConfig->TxPower, Bands[Channels[txConfig->Channel].Band].TxMaxPower, txConfig->Datarate, ChannelsMask );
+ int8_t txPowerLimited = LimitTxPower( txConfig->TxPower, NvmCtx.Bands[NvmCtx.Channels[txConfig->Channel].Band].TxMaxPower, txConfig->Datarate, NvmCtx.ChannelsMask );
uint32_t bandwidth = GetBandwidth( txConfig->Datarate );
- float maxEIRP = GetMaxEIRP( Channels[txConfig->Channel].Frequency );
+ float maxEIRP = GetMaxEIRP( NvmCtx.Channels[txConfig->Channel].Frequency );
int8_t phyTxPower = 0;
// Take the minimum between the maxEIRP and txConfig->MaxEirp.
@@ -599,9 +603,9 @@ bool RegionKR920TxConfig( TxConfigParams_t* txConfig, int8_t* txPower, TimerTime
phyTxPower = RegionCommonComputeTxPower( txPowerLimited, maxEIRP, txConfig->AntennaGain );
// Setup the radio frequency
- Radio.SetChannel( Channels[txConfig->Channel].Frequency );
+ Radio.SetChannel( NvmCtx.Channels[txConfig->Channel].Frequency );
- Radio.SetTxConfig( MODEM_LORA, phyTxPower, 0, bandwidth, phyDr, 1, 8, false, true, 0, 0, false, 3000 );
+ Radio.SetTxConfig( MODEM_LORA, phyTxPower, 0, bandwidth, phyDr, 1, 8, false, true, 0, 0, false, 4000 );
// Setup maximum payload lenght of the radio driver
Radio.SetMaxPayloadLength( MODEM_LORA, txConfig->PktLen );
@@ -657,7 +661,7 @@ uint8_t RegionKR920LinkAdrReq( LinkAdrReqParams_t* linkAdrReq, int8_t* drOut, in
{
if( linkAdrParams.ChMaskCtrl == 6 )
{
- if( Channels[i].Frequency != 0 )
+ if( NvmCtx.Channels[i].Frequency != 0 )
{
chMask |= 1 << i;
}
@@ -665,7 +669,7 @@ uint8_t RegionKR920LinkAdrReq( LinkAdrReqParams_t* linkAdrReq, int8_t* drOut, in
else
{
if( ( ( chMask & ( 1 << i ) ) != 0 ) &&
- ( Channels[i].Frequency == 0 ) )
+ ( NvmCtx.Channels[i].Frequency == 0 ) )
{// Trying to enable an undefined channel
status &= 0xFE; // Channel mask KO
}
@@ -691,9 +695,10 @@ uint8_t RegionKR920LinkAdrReq( LinkAdrReqParams_t* linkAdrReq, int8_t* drOut, in
linkAdrVerifyParams.ChannelsMask = &chMask;
linkAdrVerifyParams.MinDatarate = ( int8_t )phyParam.Value;
linkAdrVerifyParams.MaxDatarate = KR920_TX_MAX_DATARATE;
- linkAdrVerifyParams.Channels = Channels;
+ linkAdrVerifyParams.Channels = NvmCtx.Channels;
linkAdrVerifyParams.MinTxPower = KR920_MIN_TX_POWER;
linkAdrVerifyParams.MaxTxPower = KR920_MAX_TX_POWER;
+ linkAdrVerifyParams.Version = linkAdrReq->Version;
// Verify the parameters and update, if necessary
status = RegionCommonLinkAdrReqVerifyParams( &linkAdrVerifyParams, &linkAdrParams.Datarate, &linkAdrParams.TxPower, &linkAdrParams.NbRep );
@@ -702,9 +707,9 @@ uint8_t RegionKR920LinkAdrReq( LinkAdrReqParams_t* linkAdrReq, int8_t* drOut, in
if( status == 0x07 )
{
// Set the channels mask to a default value
- memset( ChannelsMask, 0, sizeof( ChannelsMask ) );
+ memset1( ( uint8_t* ) NvmCtx.ChannelsMask, 0, sizeof( NvmCtx.ChannelsMask ) );
// Update the channels mask
- ChannelsMask[0] = chMask;
+ NvmCtx.ChannelsMask[0] = chMask;
}
// Update status variables
@@ -721,7 +726,7 @@ uint8_t RegionKR920RxParamSetupReq( RxParamSetupReqParams_t* rxParamSetupReq )
uint8_t status = 0x07;
// Verify radio frequency
- if( Radio.CheckRfFrequency( rxParamSetupReq->Frequency ) == false )
+ if( VerifyRfFreq( rxParamSetupReq->Frequency ) == false )
{
status &= 0xFE; // Channel frequency KO
}
@@ -804,13 +809,13 @@ uint8_t RegionKR920DlChannelReq( DlChannelReqParams_t* dlChannelReq )
uint8_t status = 0x03;
// Verify if the frequency is supported
- if( VerifyTxFreq( dlChannelReq->Rx1Frequency ) == false )
+ if( VerifyRfFreq( dlChannelReq->Rx1Frequency ) == false )
{
status &= 0xFE;
}
// Verify if an uplink frequency exists
- if( Channels[dlChannelReq->ChannelId].Frequency == 0 )
+ if( NvmCtx.Channels[dlChannelReq->ChannelId].Frequency == 0 )
{
status &= 0xFD;
}
@@ -818,49 +823,23 @@ uint8_t RegionKR920DlChannelReq( DlChannelReqParams_t* dlChannelReq )
// Apply Rx1 frequency, if the status is OK
if( status == 0x03 )
{
- Channels[dlChannelReq->ChannelId].Rx1Frequency = dlChannelReq->Rx1Frequency;
+ NvmCtx.Channels[dlChannelReq->ChannelId].Rx1Frequency = dlChannelReq->Rx1Frequency;
}
return status;
}
-int8_t RegionKR920AlternateDr( AlternateDrParams_t* alternateDr )
+int8_t RegionKR920AlternateDr( int8_t currentDr, AlternateDrType_t type )
{
- int8_t datarate = 0;
-
- if( ( alternateDr->NbTrials % 48 ) == 0 )
- {
- datarate = DR_0;
- }
- else if( ( alternateDr->NbTrials % 32 ) == 0 )
- {
- datarate = DR_1;
- }
- else if( ( alternateDr->NbTrials % 24 ) == 0 )
- {
- datarate = DR_2;
- }
- else if( ( alternateDr->NbTrials % 16 ) == 0 )
- {
- datarate = DR_3;
- }
- else if( ( alternateDr->NbTrials % 8 ) == 0 )
- {
- datarate = DR_4;
- }
- else
- {
- datarate = DR_5;
- }
- return datarate;
+ return currentDr;
}
void RegionKR920CalcBackOff( CalcBackOffParams_t* calcBackOff )
{
RegionCommonCalcBackOffParams_t calcBackOffParams;
- calcBackOffParams.Channels = Channels;
- calcBackOffParams.Bands = Bands;
+ calcBackOffParams.Channels = NvmCtx.Channels;
+ calcBackOffParams.Bands = NvmCtx.Bands;
calcBackOffParams.LastTxIsJoinRequest = calcBackOff->LastTxIsJoinRequest;
calcBackOffParams.Joined = calcBackOff->Joined;
calcBackOffParams.DutyCycleEnabled = calcBackOff->DutyCycleEnabled;
@@ -871,7 +850,7 @@ void RegionKR920CalcBackOff( CalcBackOffParams_t* calcBackOff )
RegionCommonCalcBackOff( &calcBackOffParams );
}
-bool RegionKR920NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff )
+LoRaMacStatus_t RegionKR920NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff )
{
uint8_t channelNext = 0;
uint8_t nbEnabledChannels = 0;
@@ -879,28 +858,29 @@ bool RegionKR920NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel,
uint8_t enabledChannels[KR920_MAX_NB_CHANNELS] = { 0 };
TimerTime_t nextTxDelay = 0;
- if( RegionCommonCountChannels( ChannelsMask, 0, 1 ) == 0 )
+ if( RegionCommonCountChannels( NvmCtx.ChannelsMask, 0, 1 ) == 0 )
{ // Reactivate default channels
- ChannelsMask[0] |= LC( 1 ) + LC( 2 ) + LC( 3 );
+ NvmCtx.ChannelsMask[0] |= LC( 1 ) + LC( 2 ) + LC( 3 );
}
- if( nextChanParams->AggrTimeOff <= TimerGetElapsedTime( nextChanParams->LastAggrTx ) )
+ TimerTime_t elapsed = TimerGetElapsedTime( nextChanParams->LastAggrTx );
+ if( ( nextChanParams->LastAggrTx == 0 ) || ( nextChanParams->AggrTimeOff <= elapsed ) )
{
// Reset Aggregated time off
*aggregatedTimeOff = 0;
// Update bands Time OFF
- nextTxDelay = RegionCommonUpdateBandTimeOff( nextChanParams->Joined, nextChanParams->DutyCycleEnabled, Bands, KR920_MAX_NB_BANDS );
+ nextTxDelay = RegionCommonUpdateBandTimeOff( nextChanParams->Joined, nextChanParams->DutyCycleEnabled, NvmCtx.Bands, KR920_MAX_NB_BANDS );
// Search how many channels are enabled
nbEnabledChannels = CountNbOfEnabledChannels( nextChanParams->Joined, nextChanParams->Datarate,
- ChannelsMask, Channels,
- Bands, enabledChannels, &delayTx );
+ NvmCtx.ChannelsMask, NvmCtx.Channels,
+ NvmCtx.Bands, enabledChannels, &delayTx );
}
else
{
delayTx++;
- nextTxDelay = nextChanParams->AggrTimeOff - TimerGetElapsedTime( nextChanParams->LastAggrTx );
+ nextTxDelay = nextChanParams->AggrTimeOff - elapsed;
}
if( nbEnabledChannels > 0 )
@@ -912,15 +892,15 @@ bool RegionKR920NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel,
// Perform carrier sense for KR920_CARRIER_SENSE_TIME
// If the channel is free, we can stop the LBT mechanism
- if( Radio.IsChannelFree( MODEM_LORA, Channels[channelNext].Frequency, KR920_RSSI_FREE_TH, KR920_CARRIER_SENSE_TIME ) == true )
+ if( Radio.IsChannelFree( MODEM_LORA, NvmCtx.Channels[channelNext].Frequency, KR920_RSSI_FREE_TH, KR920_CARRIER_SENSE_TIME ) == true )
{
// Free channel found
*channel = channelNext;
*time = 0;
- return true;
+ return LORAMAC_STATUS_OK;
}
}
- return false;
+ return LORAMAC_STATUS_NO_FREE_CHANNEL_FOUND;
}
else
{
@@ -928,22 +908,26 @@ bool RegionKR920NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel,
{
// Delay transmission due to AggregatedTimeOff or to a band time off
*time = nextTxDelay;
- return true;
+ return LORAMAC_STATUS_DUTYCYCLE_RESTRICTED;
}
// Datarate not supported by any channel, restore defaults
- ChannelsMask[0] |= LC( 1 ) + LC( 2 ) + LC( 3 );
+ NvmCtx.ChannelsMask[0] |= LC( 1 ) + LC( 2 ) + LC( 3 );
*time = 0;
- return false;
+ return LORAMAC_STATUS_NO_CHANNEL_FOUND;
}
}
LoRaMacStatus_t RegionKR920ChannelAdd( ChannelAddParams_t* channelAdd )
{
- uint8_t band = 0;
bool drInvalid = false;
bool freqInvalid = false;
uint8_t id = channelAdd->ChannelId;
+ if( id < KR920_NUMB_DEFAULT_CHANNELS )
+ {
+ return LORAMAC_STATUS_FREQ_AND_DR_INVALID;
+ }
+
if( id >= KR920_MAX_NB_CHANNELS )
{
return LORAMAC_STATUS_PARAMETER_INVALID;
@@ -963,21 +947,10 @@ LoRaMacStatus_t RegionKR920ChannelAdd( ChannelAddParams_t* channelAdd )
drInvalid = true;
}
- // Default channels don't accept all values
- if( id < KR920_NUMB_DEFAULT_CHANNELS )
- {
- // All datarates are supported
- // We are not allowed to change the frequency
- if( channelAdd->NewChannel->Frequency != Channels[id].Frequency )
- {
- freqInvalid = true;
- }
- }
-
// Check frequency
if( freqInvalid == false )
{
- if( VerifyTxFreq( channelAdd->NewChannel->Frequency ) == false )
+ if( VerifyRfFreq( channelAdd->NewChannel->Frequency ) == false )
{
freqInvalid = true;
}
@@ -997,9 +970,9 @@ LoRaMacStatus_t RegionKR920ChannelAdd( ChannelAddParams_t* channelAdd )
return LORAMAC_STATUS_FREQUENCY_INVALID;
}
- memcpy( &(Channels[id]), channelAdd->NewChannel, sizeof( Channels[id] ) );
- Channels[id].Band = band;
- ChannelsMask[0] |= ( 1 << id );
+ memcpy1( ( uint8_t* ) &(NvmCtx.Channels[id]), ( uint8_t* ) channelAdd->NewChannel, sizeof( NvmCtx.Channels[id] ) );
+ NvmCtx.Channels[id].Band = 0;
+ NvmCtx.ChannelsMask[0] |= ( 1 << id );
return LORAMAC_STATUS_OK;
}
@@ -1013,17 +986,17 @@ bool RegionKR920ChannelsRemove( ChannelRemoveParams_t* channelRemove )
}
// Remove the channel from the list of channels
- Channels[id] = ( ChannelParams_t ){ 0, 0, { 0 }, 0 };
+ NvmCtx.Channels[id] = ( ChannelParams_t ){ 0, 0, { 0 }, 0 };
- return RegionCommonChanDisable( ChannelsMask, id, KR920_MAX_NB_CHANNELS );
+ return RegionCommonChanDisable( NvmCtx.ChannelsMask, id, KR920_MAX_NB_CHANNELS );
}
void RegionKR920SetContinuousWave( ContinuousWaveParams_t* continuousWave )
{
- int8_t txPowerLimited = LimitTxPower( continuousWave->TxPower, Bands[Channels[continuousWave->Channel].Band].TxMaxPower, continuousWave->Datarate, ChannelsMask );
- float maxEIRP = GetMaxEIRP( Channels[continuousWave->Channel].Frequency );
+ int8_t txPowerLimited = LimitTxPower( continuousWave->TxPower, NvmCtx.Bands[NvmCtx.Channels[continuousWave->Channel].Band].TxMaxPower, continuousWave->Datarate, NvmCtx.ChannelsMask );
+ float maxEIRP = GetMaxEIRP( NvmCtx.Channels[continuousWave->Channel].Frequency );
int8_t phyTxPower = 0;
- uint32_t frequency = Channels[continuousWave->Channel].Frequency;
+ uint32_t frequency = NvmCtx.Channels[continuousWave->Channel].Frequency;
// Take the minimum between the maxEIRP and continuousWave->MaxEirp.
// The value of continuousWave->MaxEirp could have changed during runtime, e.g. due to a MAC command.
@@ -1045,3 +1018,75 @@ uint8_t RegionKR920ApplyDrOffset( uint8_t downlinkDwellTime, int8_t dr, int8_t d
}
return datarate;
}
+
+void RegionKR920RxBeaconSetup( RxBeaconSetup_t* rxBeaconSetup, uint8_t* outDr )
+{
+ RegionCommonRxBeaconSetupParams_t regionCommonRxBeaconSetup;
+
+ regionCommonRxBeaconSetup.Datarates = DataratesKR920;
+ regionCommonRxBeaconSetup.Frequency = rxBeaconSetup->Frequency;
+ regionCommonRxBeaconSetup.BeaconSize = KR920_BEACON_SIZE;
+ regionCommonRxBeaconSetup.BeaconDatarate = KR920_BEACON_CHANNEL_DR;
+ regionCommonRxBeaconSetup.BeaconChannelBW = KR920_BEACON_CHANNEL_BW;
+ regionCommonRxBeaconSetup.RxTime = rxBeaconSetup->RxTime;
+ regionCommonRxBeaconSetup.SymbolTimeout = rxBeaconSetup->SymbolTimeout;
+
+ RegionCommonRxBeaconSetup( ®ionCommonRxBeaconSetup );
+
+ // Store downlink datarate
+ *outDr = KR920_BEACON_CHANNEL_DR;
+}
+
+LoRaMacStatus_t RegionKR920ChannelManualAdd( ChannelAddParams_t* channelAdd )
+{
+ bool drInvalid = false;
+ bool freqInvalid = false;
+ uint8_t id = channelAdd->ChannelId;
+
+ if( id >= KR920_MAX_NB_CHANNELS )
+ {
+ return LORAMAC_STATUS_PARAMETER_INVALID;
+ }
+
+ // Validate the datarate range
+ if( RegionCommonValueInRange( channelAdd->NewChannel->DrRange.Fields.Min, KR920_TX_MIN_DATARATE, KR920_TX_MAX_DATARATE ) == false )
+ {
+ drInvalid = true;
+ }
+ if( RegionCommonValueInRange( channelAdd->NewChannel->DrRange.Fields.Max, KR920_TX_MIN_DATARATE, KR920_TX_MAX_DATARATE ) == false )
+ {
+ drInvalid = true;
+ }
+ if( channelAdd->NewChannel->DrRange.Fields.Min > channelAdd->NewChannel->DrRange.Fields.Max )
+ {
+ drInvalid = true;
+ }
+
+ // Check frequency
+ if( freqInvalid == false )
+ {
+ if( VerifyRfFreq( channelAdd->NewChannel->Frequency ) == false )
+ {
+ freqInvalid = true;
+ }
+ }
+
+ // Check status
+ if( ( drInvalid == true ) && ( freqInvalid == true ) )
+ {
+ return LORAMAC_STATUS_FREQ_AND_DR_INVALID;
+ }
+ if( drInvalid == true )
+ {
+ return LORAMAC_STATUS_DATARATE_INVALID;
+ }
+ if( freqInvalid == true )
+ {
+ return LORAMAC_STATUS_FREQUENCY_INVALID;
+ }
+
+ memcpy1( ( uint8_t* ) &(NvmCtx.Channels[id]), ( uint8_t* ) channelAdd->NewChannel, sizeof( NvmCtx.Channels[id] ) );
+ NvmCtx.Channels[id].Band = 0;
+ NvmCtx.ChannelsMask[0] |= ( 1 << id );
+ return LORAMAC_STATUS_OK;
+}
diff --git a/lib/lora/mac/region/RegionKR920.h b/lib/lora/mac/region/RegionKR920.h
index 1c1cadf755..52c90e873a 100644
--- a/lib/lora/mac/region/RegionKR920.h
+++ b/lib/lora/mac/region/RegionKR920.h
@@ -12,7 +12,7 @@
* \____ \| ___ | (_ _) ___ |/ ___) _ \
* _____) ) ____| | | || |_| ____( (___| | | |
* (______/|_____)_|_|_| \__)_____)\____)_| |_|
- * (C)2013 Semtech
+ * (C)2013-2017 Semtech
*
* ___ _____ _ ___ _ _____ ___ ___ ___ ___
* / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
@@ -28,6 +28,8 @@
*
* \author Daniel Jaeckle ( STACKFORCE )
*
+ * \author Johannes Bruder ( STACKFORCE )
+ *
* \defgroup REGIONKR920 Region KR920
* Implementation according to LoRaWAN Specification v1.0.2.
* \{
@@ -35,6 +37,13 @@
#ifndef __REGION_KR920_H__
#define __REGION_KR920_H__
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include "Region.h"
+
/*!
* LoRaMac maximum number of channels
*/
@@ -189,6 +198,44 @@
*/
#define KR920_RX_WND_2_DR DR_0
+/*
+ * CLASS B
+ */
+/*!
+ * Beacon frequency
+ */
+#define KR920_BEACON_CHANNEL_FREQ 923100000
+
+/*!
+ * Payload size of a beacon frame
+ */
+#define KR920_BEACON_SIZE 17
+
+/*!
+ * Size of RFU 1 field
+ */
+#define KR920_RFU1_SIZE 2
+
+/*!
+ * Size of RFU 2 field
+ */
+#define KR920_RFU2_SIZE 0
+
+/*!
+ * Datarate of the beacon channel
+ */
+#define KR920_BEACON_CHANNEL_DR DR_3
+
+/*!
+ * Bandwith of the beacon channel
+ */
+#define KR920_BEACON_CHANNEL_BW 0
+
+/*!
+ * Ping slot channel datarate
+ */
+#define KR920_PING_SLOT_CHANNEL_DR DR_3
+
/*!
* Maximum number of bands
*/
@@ -196,9 +243,9 @@
/*!
* Band 0 definition
- * { DutyCycle, TxMaxPower, LastTxDoneTime, TimeOff }
+ * { DutyCycle, TxMaxPower, LastJoinTxDoneTime, LastTxDoneTime, TimeOff }
*/
-#define KR920_BAND0 { 1 , KR920_MAX_TX_POWER, 0, 0 } // 100.0 %
+#define KR920_BAND0 { 1 , KR920_MAX_TX_POWER, 0, 0, 0 } // 100.0 %
/*!
* LoRaMac default channel 1
@@ -274,7 +321,16 @@ void RegionKR920SetBandTxDone( SetBandTxDoneParams_t* txDone );
*
* \param [IN] type Sets the initialization type.
*/
-void RegionKR920InitDefaults( InitType_t type );
+void RegionKR920InitDefaults( InitDefaultsParams_t* params );
+
+/*!
+ * \brief Returns a pointer to the internal context and its size.
+ *
+ * \param [OUT] params Pointer to the function parameters.
+ *
+ * \retval Points to a structure where the module store its non-volatile context.
+ */
+void* RegionKR920GetNvmCtx( GetNvmCtxParams_t* params );
/*!
* \brief Verifies a parameter.
@@ -304,21 +360,6 @@ void RegionKR920ApplyCFList( ApplyCFListParams_t* applyCFList );
*/
bool RegionKR920ChanMaskSet( ChanMaskSetParams_t* chanMaskSet );
-/*!
- * \brief Calculates the next datarate to set, when ADR is on or off.
- *
- * \param [IN] adrNext Pointer to the function parameters.
- *
- * \param [OUT] drOut The calculated datarate for the next TX.
- *
- * \param [OUT] txPowOut The TX power for the next TX.
- *
- * \param [OUT] adrAckCounter The calculated ADR acknowledgement counter.
- *
- * \retval Returns true, if an ADR request should be performed.
- */
-bool RegionKR920AdrNext( AdrNextParams_t* adrNext, int8_t* drOut, int8_t* txPowOut, uint32_t* adrAckCounter );
-
/*!
* Computes the Rx window timeout and offset.
*
@@ -408,11 +449,11 @@ uint8_t RegionKR920DlChannelReq( DlChannelReqParams_t* dlChannelReq );
/*!
* \brief Alternates the datarate of the channel for the join request.
*
- * \param [IN] alternateDr Pointer to the function parameters.
+ * \param [IN] currentDr current datarate.
*
* \retval Datarate to apply.
*/
-int8_t RegionKR920AlternateDr( AlternateDrParams_t* alternateDr );
+int8_t RegionKR920AlternateDr( int8_t currentDr, AlternateDrType_t type );
/*!
* \brief Calculates the back-off time.
@@ -433,7 +474,7 @@ void RegionKR920CalcBackOff( CalcBackOffParams_t* calcBackOff );
*
* \retval Function status [1: OK, 0: Unable to find a channel on the current datarate]
*/
-bool RegionKR920NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff );
+LoRaMacStatus_t RegionKR920NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff );
/*!
* \brief Adds a channel.
@@ -443,6 +484,7 @@ bool RegionKR920NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel,
* \retval Status of the operation.
*/
LoRaMacStatus_t RegionKR920ChannelAdd( ChannelAddParams_t* channelAdd );
+LoRaMacStatus_t RegionKR920ChannelManualAdd( ChannelAddParams_t* channelAdd );
/*!
* \brief Removes a channel.
@@ -473,6 +515,17 @@ void RegionKR920SetContinuousWave( ContinuousWaveParams_t* continuousWave );
*/
uint8_t RegionKR920ApplyDrOffset( uint8_t downlinkDwellTime, int8_t dr, int8_t drOffset );
+/*!
+ * \brief Sets the radio into beacon reception mode
+ *
+ * \param [IN] rxBeaconSetup Pointer to the function parameters
+ */
+ void RegionKR920RxBeaconSetup( RxBeaconSetup_t* rxBeaconSetup, uint8_t* outDr );
+
/*! \} defgroup REGIONKR920 */
+#ifdef __cplusplus
+}
+#endif
+
#endif // __REGION_KR920_H__
diff --git a/lib/lora/mac/region/RegionRU864.c b/lib/lora/mac/region/RegionRU864.c
new file mode 100644
index 0000000000..fee872842c
--- /dev/null
+++ b/lib/lora/mac/region/RegionRU864.c
@@ -0,0 +1,1077 @@
+/*!
+ * \file RegionRU864.c
+ *
+ * \brief Region implementation for RU864
+ *
+ * \copyright Revised BSD License, see section \ref LICENSE.
+ *
+ * \code
+ * ______ _
+ * / _____) _ | |
+ * ( (____ _____ ____ _| |_ _____ ____| |__
+ * \____ \| ___ | (_ _) ___ |/ ___) _ \
+ * _____) ) ____| | | || |_| ____( (___| | | |
+ * (______/|_____)_|_|_| \__)_____)\____)_| |_|
+ * (C)2013-2017 Semtech
+ *
+ * ___ _____ _ ___ _ _____ ___ ___ ___ ___
+ * / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
+ * \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
+ * |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
+ * embedded.connectivity.solutions===============
+ *
+ * \endcode
+ *
+ * \author Miguel Luis ( Semtech )
+ *
+ * \author Gregory Cristian ( Semtech )
+ *
+ * \author Daniel Jaeckle ( STACKFORCE )
+*/
+#include "utilities.h"
+
+#include "RegionCommon.h"
+#include "RegionRU864.h"
+
+// Definitions
+#define CHANNELS_MASK_SIZE 1
+
+/*!
+ * Region specific context
+ */
+typedef struct sRegionRU864NvmCtx
+{
+ /*!
+ * LoRaMAC channels
+ */
+ ChannelParams_t Channels[ RU864_MAX_NB_CHANNELS ];
+ /*!
+ * LoRaMac bands
+ */
+ Band_t Bands[ RU864_MAX_NB_BANDS ];
+ /*!
+ * LoRaMac channels mask
+ */
+ uint16_t ChannelsMask[ CHANNELS_MASK_SIZE ];
+ /*!
+ * LoRaMac channels default mask
+ */
+ uint16_t ChannelsDefaultMask[ CHANNELS_MASK_SIZE ];
+}RegionRU864NvmCtx_t;
+
+/*
+ * Non-volatile module context.
+ */
+static RegionRU864NvmCtx_t NvmCtx;
+
+// Static functions
+static int8_t GetNextLowerTxDr( int8_t dr, int8_t minDr )
+{
+ uint8_t nextLowerDr = 0;
+
+ if( dr == minDr )
+ {
+ nextLowerDr = minDr;
+ }
+ else
+ {
+ nextLowerDr = dr - 1;
+ }
+ return nextLowerDr;
+}
+
+static uint32_t GetBandwidth( uint32_t drIndex )
+{
+ switch( BandwidthsRU864[drIndex] )
+ {
+ default:
+ case 125000:
+ return 0;
+ case 250000:
+ return 1;
+ case 500000:
+ return 2;
+ }
+}
+
+static int8_t LimitTxPower( int8_t txPower, int8_t maxBandTxPower, int8_t datarate, uint16_t* channelsMask )
+{
+ int8_t txPowerResult = txPower;
+
+ // Limit tx power to the band max
+ txPowerResult = MAX( txPower, maxBandTxPower );
+
+ return txPowerResult;
+}
+
+static bool VerifyRfFreq( uint32_t freq )
+{
+ // Check radio driver support
+ if( Radio.CheckRfFrequency( freq ) == false )
+ {
+ return false;
+ }
+
+ // Check frequency bands
+ if( ( freq < 864000000 ) || ( freq > 870000000 ) )
+ {
+ return false;
+ }
+ return true;
+}
+
+static uint8_t CountNbOfEnabledChannels( bool joined, uint8_t datarate, uint16_t* channelsMask, ChannelParams_t* channels, Band_t* bands, uint8_t* enabledChannels, uint8_t* delayTx )
+{
+ uint8_t nbEnabledChannels = 0;
+ uint8_t delayTransmission = 0;
+
+ for( uint8_t i = 0, k = 0; i < RU864_MAX_NB_CHANNELS; i += 16, k++ )
+ {
+ for( uint8_t j = 0; j < MIN( RU864_MAX_NB_CHANNELS, 16 ); j++ )
+ {
+ if( ( channelsMask[k] & ( 1 << j ) ) != 0 )
+ {
+ if( channels[i + j].Frequency == 0 )
+ { // Check if the channel is enabled
+ continue;
+ }
+ if( joined == false )
+ {
+ if( ( RU864_JOIN_CHANNELS & ( 1 << j ) ) == 0 )
+ {
+ continue;
+ }
+ }
+ if( RegionCommonValueInRange( datarate, channels[i + j].DrRange.Fields.Min,
+ channels[i + j].DrRange.Fields.Max ) == false )
+ { // Check if the current channel selection supports the given datarate
+ continue;
+ }
+ if( bands[channels[i + j].Band].TimeOff > 0 )
+ { // Check if the band is available for transmission
+ delayTransmission++;
+ continue;
+ }
+ enabledChannels[nbEnabledChannels++] = i + j;
+ }
+ }
+ }
+
+ *delayTx = delayTransmission;
+ return nbEnabledChannels;
+}
+
+PhyParam_t RegionRU864GetPhyParam( GetPhyParams_t* getPhy )
+{
+ PhyParam_t phyParam = { 0 };
+
+ switch( getPhy->Attribute )
+ {
+ case PHY_MIN_RX_DR:
+ {
+ phyParam.Value = RU864_RX_MIN_DATARATE;
+ break;
+ }
+ case PHY_MIN_TX_DR:
+ {
+ phyParam.Value = RU864_TX_MIN_DATARATE;
+ break;
+ }
+ case PHY_DEF_TX_DR:
+ {
+ phyParam.Value = RU864_DEFAULT_DATARATE;
+ break;
+ }
+ case PHY_NEXT_LOWER_TX_DR:
+ {
+ phyParam.Value = GetNextLowerTxDr( getPhy->Datarate, RU864_TX_MIN_DATARATE );
+ break;
+ }
+ case PHY_MAX_TX_POWER:
+ {
+ phyParam.Value = RU864_MAX_TX_POWER;
+ break;
+ }
+ case PHY_DEF_TX_POWER:
+ {
+ phyParam.Value = RU864_DEFAULT_TX_POWER;
+ break;
+ }
+ case PHY_DEF_ADR_ACK_LIMIT:
+ {
+ phyParam.Value = RU864_ADR_ACK_LIMIT;
+ break;
+ }
+ case PHY_DEF_ADR_ACK_DELAY:
+ {
+ phyParam.Value = RU864_ADR_ACK_DELAY;
+ break;
+ }
+ case PHY_MAX_PAYLOAD:
+ {
+ phyParam.Value = MaxPayloadOfDatarateRU864[getPhy->Datarate];
+ break;
+ }
+ case PHY_MAX_PAYLOAD_REPEATER:
+ {
+ phyParam.Value = MaxPayloadOfDatarateRepeaterRU864[getPhy->Datarate];
+ break;
+ }
+ case PHY_DUTY_CYCLE:
+ {
+ phyParam.Value = RU864_DUTY_CYCLE_ENABLED;
+ break;
+ }
+ case PHY_MAX_RX_WINDOW:
+ {
+ phyParam.Value = RU864_MAX_RX_WINDOW;
+ break;
+ }
+ case PHY_RECEIVE_DELAY1:
+ {
+ phyParam.Value = RU864_RECEIVE_DELAY1;
+ break;
+ }
+ case PHY_RECEIVE_DELAY2:
+ {
+ phyParam.Value = RU864_RECEIVE_DELAY2;
+ break;
+ }
+ case PHY_JOIN_ACCEPT_DELAY1:
+ {
+ phyParam.Value = RU864_JOIN_ACCEPT_DELAY1;
+ break;
+ }
+ case PHY_JOIN_ACCEPT_DELAY2:
+ {
+ phyParam.Value = RU864_JOIN_ACCEPT_DELAY2;
+ break;
+ }
+ case PHY_MAX_FCNT_GAP:
+ {
+ phyParam.Value = RU864_MAX_FCNT_GAP;
+ break;
+ }
+ case PHY_ACK_TIMEOUT:
+ {
+ phyParam.Value = ( RU864_ACKTIMEOUT + randr( -RU864_ACK_TIMEOUT_RND, RU864_ACK_TIMEOUT_RND ) );
+ break;
+ }
+ case PHY_DEF_DR1_OFFSET:
+ {
+ phyParam.Value = RU864_DEFAULT_RX1_DR_OFFSET;
+ break;
+ }
+ case PHY_DEF_RX2_FREQUENCY:
+ {
+ phyParam.Value = RU864_RX_WND_2_FREQ;
+ break;
+ }
+ case PHY_DEF_RX2_DR:
+ {
+ phyParam.Value = RU864_RX_WND_2_DR;
+ break;
+ }
+ case PHY_CHANNELS_MASK:
+ {
+ phyParam.ChannelsMask = NvmCtx.ChannelsMask;
+ break;
+ }
+ case PHY_CHANNELS_DEFAULT_MASK:
+ {
+ phyParam.ChannelsMask = NvmCtx.ChannelsDefaultMask;
+ break;
+ }
+ case PHY_MAX_NB_CHANNELS:
+ {
+ phyParam.Value = RU864_MAX_NB_CHANNELS;
+ break;
+ }
+ case PHY_CHANNELS:
+ {
+ phyParam.Channels = NvmCtx.Channels;
+ break;
+ }
+ case PHY_DEF_UPLINK_DWELL_TIME:
+ case PHY_DEF_DOWNLINK_DWELL_TIME:
+ {
+ phyParam.Value = 0;
+ break;
+ }
+ case PHY_DEF_MAX_EIRP:
+ {
+ phyParam.fValue = RU864_DEFAULT_MAX_EIRP;
+ break;
+ }
+ case PHY_DEF_ANTENNA_GAIN:
+ {
+ phyParam.fValue = RU864_DEFAULT_ANTENNA_GAIN;
+ break;
+ }
+ case PHY_BEACON_CHANNEL_FREQ:
+ {
+ phyParam.Value = RU864_BEACON_CHANNEL_FREQ;
+ break;
+ }
+ case PHY_BEACON_FORMAT:
+ {
+ phyParam.BeaconFormat.BeaconSize = RU864_BEACON_SIZE;
+ phyParam.BeaconFormat.Rfu1Size = RU864_RFU1_SIZE;
+ phyParam.BeaconFormat.Rfu2Size = RU864_RFU2_SIZE;
+ break;
+ }
+ case PHY_BEACON_CHANNEL_DR:
+ {
+ phyParam.Value = RU864_BEACON_CHANNEL_DR;
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+
+ return phyParam;
+}
+
+void RegionRU864SetBandTxDone( SetBandTxDoneParams_t* txDone )
+{
+ RegionCommonSetBandTxDone( txDone->Joined, &NvmCtx.Bands[NvmCtx.Channels[txDone->Channel].Band], txDone->LastTxDoneTime );
+}
+
+void RegionRU864InitDefaults( InitDefaultsParams_t* params )
+{
+ Band_t bands[RU864_MAX_NB_BANDS] =
+ {
+ RU864_BAND0
+ };
+
+ switch( params->Type )
+ {
+ case INIT_TYPE_INIT:
+ {
+ // Initialize bands
+ memcpy1( ( uint8_t* )NvmCtx.Bands, ( uint8_t* )bands, sizeof( Band_t ) * RU864_MAX_NB_BANDS );
+
+ // Channels
+ NvmCtx.Channels[0] = ( ChannelParams_t ) RU864_LC1;
+ NvmCtx.Channels[1] = ( ChannelParams_t ) RU864_LC2;
+
+ // Initialize the channels default mask
+ NvmCtx.ChannelsDefaultMask[0] = LC( 1 ) + LC( 2 );
+ // Update the channels mask
+ RegionCommonChanMaskCopy( NvmCtx.ChannelsMask, NvmCtx.ChannelsDefaultMask, 1 );
+ break;
+ }
+ case INIT_TYPE_RESTORE_CTX:
+ {
+ if( params->NvmCtx != 0 )
+ {
+ memcpy1( (uint8_t*) &NvmCtx, (uint8_t*) params->NvmCtx, sizeof( NvmCtx ) );
+ }
+ break;
+ }
+ case INIT_TYPE_RESTORE_DEFAULT_CHANNELS:
+ {
+ // Restore channels default mask
+ NvmCtx.ChannelsMask[0] |= NvmCtx.ChannelsDefaultMask[0];
+
+ // Channels
+ NvmCtx.Channels[0] = ( ChannelParams_t ) RU864_LC1;
+ NvmCtx.Channels[1] = ( ChannelParams_t ) RU864_LC2;
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+}
+
+void* RegionRU864GetNvmCtx( GetNvmCtxParams_t* params )
+{
+ params->nvmCtxSize = sizeof( RegionRU864NvmCtx_t );
+ return &NvmCtx;
+}
+
+bool RegionRU864Verify( VerifyParams_t* verify, PhyAttribute_t phyAttribute )
+{
+ switch( phyAttribute )
+ {
+ case PHY_FREQUENCY:
+ {
+ return VerifyRfFreq( verify->Frequency );
+ }
+ case PHY_TX_DR:
+ {
+ return RegionCommonValueInRange( verify->DatarateParams.Datarate, RU864_TX_MIN_DATARATE, RU864_TX_MAX_DATARATE );
+ }
+ case PHY_DEF_TX_DR:
+ {
+ return RegionCommonValueInRange( verify->DatarateParams.Datarate, DR_0, DR_5 );
+ }
+ case PHY_RX_DR:
+ {
+ return RegionCommonValueInRange( verify->DatarateParams.Datarate, RU864_RX_MIN_DATARATE, RU864_RX_MAX_DATARATE );
+ }
+ case PHY_DEF_TX_POWER:
+ case PHY_TX_POWER:
+ {
+ // Remark: switched min and max!
+ return RegionCommonValueInRange( verify->TxPower, RU864_MAX_TX_POWER, RU864_MIN_TX_POWER );
+ }
+ case PHY_DUTY_CYCLE:
+ {
+ return RU864_DUTY_CYCLE_ENABLED;
+ }
+ default:
+ return false;
+ }
+}
+
+void RegionRU864ApplyCFList( ApplyCFListParams_t* applyCFList )
+{
+ ChannelParams_t newChannel;
+ ChannelAddParams_t channelAdd;
+ ChannelRemoveParams_t channelRemove;
+
+ // Setup default datarate range
+ newChannel.DrRange.Value = ( DR_5 << 4 ) | DR_0;
+
+ // Size of the optional CF list
+ if( applyCFList->Size != 16 )
+ {
+ return;
+ }
+
+ // Last byte CFListType must be 0 to indicate the CFList contains a list of frequencies
+ if( applyCFList->Payload[15] != 0 )
+ {
+ return;
+ }
+
+ // Last byte is RFU, don't take it into account
+ for( uint8_t i = 0, chanIdx = RU864_NUMB_DEFAULT_CHANNELS; chanIdx < RU864_MAX_NB_CHANNELS; i+=3, chanIdx++ )
+ {
+ if( chanIdx < ( RU864_NUMB_CHANNELS_CF_LIST + RU864_NUMB_DEFAULT_CHANNELS ) )
+ {
+ // Channel frequency
+ newChannel.Frequency = (uint32_t) applyCFList->Payload[i];
+ newChannel.Frequency |= ( (uint32_t) applyCFList->Payload[i + 1] << 8 );
+ newChannel.Frequency |= ( (uint32_t) applyCFList->Payload[i + 2] << 16 );
+ newChannel.Frequency *= 100;
+
+ // Initialize alternative frequency to 0
+ newChannel.Rx1Frequency = 0;
+ }
+ else
+ {
+ newChannel.Frequency = 0;
+ newChannel.DrRange.Value = 0;
+ newChannel.Rx1Frequency = 0;
+ }
+
+ if( newChannel.Frequency != 0 )
+ {
+ channelAdd.NewChannel = &newChannel;
+ channelAdd.ChannelId = chanIdx;
+
+ // Try to add all channels
+ RegionRU864ChannelAdd( &channelAdd );
+ }
+ else
+ {
+ channelRemove.ChannelId = chanIdx;
+
+ RegionRU864ChannelsRemove( &channelRemove );
+ }
+ }
+}
+
+bool RegionRU864ChanMaskSet( ChanMaskSetParams_t* chanMaskSet )
+{
+ switch( chanMaskSet->ChannelsMaskType )
+ {
+ case CHANNELS_MASK:
+ {
+ RegionCommonChanMaskCopy( NvmCtx.ChannelsMask, chanMaskSet->ChannelsMaskIn, 1 );
+ break;
+ }
+ case CHANNELS_DEFAULT_MASK:
+ {
+ RegionCommonChanMaskCopy( NvmCtx.ChannelsDefaultMask, chanMaskSet->ChannelsMaskIn, 1 );
+ break;
+ }
+ default:
+ return false;
+ }
+ return true;
+}
+
+void RegionRU864ComputeRxWindowParameters( int8_t datarate, uint8_t minRxSymbols, uint32_t rxError, RxConfigParams_t *rxConfigParams )
+{
+ double tSymbol = 0.0;
+
+ // Get the datarate, perform a boundary check
+ rxConfigParams->Datarate = MIN( datarate, RU864_RX_MAX_DATARATE );
+ rxConfigParams->Bandwidth = GetBandwidth( rxConfigParams->Datarate );
+
+ if( rxConfigParams->Datarate == DR_7 )
+ { // FSK
+ tSymbol = RegionCommonComputeSymbolTimeFsk( DataratesRU864[rxConfigParams->Datarate] );
+ }
+ else
+ { // LoRa
+ tSymbol = RegionCommonComputeSymbolTimeLoRa( DataratesRU864[rxConfigParams->Datarate], BandwidthsRU864[rxConfigParams->Datarate] );
+ }
+
+ RegionCommonComputeRxWindowParameters( tSymbol, minRxSymbols, rxError, Radio.GetWakeupTime( ), &rxConfigParams->WindowTimeout, &rxConfigParams->WindowOffset );
+}
+
+bool RegionRU864RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate )
+{
+ RadioModems_t modem;
+ int8_t dr = rxConfig->Datarate;
+ uint8_t maxPayload = 0;
+ int8_t phyDr = 0;
+ uint32_t frequency = rxConfig->Frequency;
+
+ if( Radio.GetStatus( ) != RF_IDLE )
+ {
+ return false;
+ }
+
+ if( rxConfig->RxSlot == RX_SLOT_WIN_1 )
+ {
+ // Apply window 1 frequency
+ frequency = NvmCtx.Channels[rxConfig->Channel].Frequency;
+ // Apply the alternative RX 1 window frequency, if it is available
+ if( NvmCtx.Channels[rxConfig->Channel].Rx1Frequency != 0 )
+ {
+ frequency = NvmCtx.Channels[rxConfig->Channel].Rx1Frequency;
+ }
+ }
+
+ // Read the physical datarate from the datarates table
+ phyDr = DataratesRU864[dr];
+
+ Radio.SetChannel( frequency );
+
+ // Radio configuration
+ if( dr == DR_7 )
+ {
+ modem = MODEM_FSK;
+ Radio.SetRxConfig( modem, 50000, phyDr * 1000, 0, 83333, 5, rxConfig->WindowTimeout, false, 0, true, 0, 0, false, rxConfig->RxContinuous );
+ }
+ else
+ {
+ modem = MODEM_LORA;
+ Radio.SetRxConfig( modem, rxConfig->Bandwidth, phyDr, 1, 0, 8, rxConfig->WindowTimeout, false, 0, false, 0, 0, true, rxConfig->RxContinuous );
+ }
+
+ if( rxConfig->RepeaterSupport == true )
+ {
+ maxPayload = MaxPayloadOfDatarateRepeaterRU864[dr];
+ }
+ else
+ {
+ maxPayload = MaxPayloadOfDatarateRU864[dr];
+ }
+
+ Radio.SetMaxPayloadLength( modem, maxPayload + LORA_MAC_FRMPAYLOAD_OVERHEAD );
+
+ *datarate = (uint8_t) dr;
+ return true;
+}
+
+bool RegionRU864TxConfig( TxConfigParams_t* txConfig, int8_t* txPower, TimerTime_t* txTimeOnAir )
+{
+ RadioModems_t modem;
+ int8_t phyDr = DataratesRU864[txConfig->Datarate];
+ int8_t txPowerLimited = LimitTxPower( txConfig->TxPower, NvmCtx.Bands[NvmCtx.Channels[txConfig->Channel].Band].TxMaxPower, txConfig->Datarate, NvmCtx.ChannelsMask );
+ uint32_t bandwidth = GetBandwidth( txConfig->Datarate );
+ int8_t phyTxPower = 0;
+
+ // Calculate physical TX power
+ phyTxPower = RegionCommonComputeTxPower( txPowerLimited, txConfig->MaxEirp, txConfig->AntennaGain );
+
+ // Setup the radio frequency
+ Radio.SetChannel( NvmCtx.Channels[txConfig->Channel].Frequency );
+
+ if( txConfig->Datarate == DR_7 )
+ { // High Speed FSK channel
+ modem = MODEM_FSK;
+ Radio.SetTxConfig( modem, phyTxPower, 25000, bandwidth, phyDr * 1000, 0, 5, false, true, 0, 0, false, 4000 );
+ }
+ else
+ {
+ modem = MODEM_LORA;
+ Radio.SetTxConfig( modem, phyTxPower, 0, bandwidth, phyDr, 1, 8, false, true, 0, 0, false, 4000 );
+ }
+
+ // Setup maximum payload lenght of the radio driver
+ Radio.SetMaxPayloadLength( modem, txConfig->PktLen );
+ // Get the time-on-air of the next tx frame
+ *txTimeOnAir = Radio.TimeOnAir( modem, txConfig->PktLen );
+
+ *txPower = txPowerLimited;
+ return true;
+}
+
+uint8_t RegionRU864LinkAdrReq( LinkAdrReqParams_t* linkAdrReq, int8_t* drOut, int8_t* txPowOut, uint8_t* nbRepOut, uint8_t* nbBytesParsed )
+{
+ uint8_t status = 0x07;
+ RegionCommonLinkAdrParams_t linkAdrParams;
+ uint8_t nextIndex = 0;
+ uint8_t bytesProcessed = 0;
+ uint16_t chMask = 0;
+ GetPhyParams_t getPhy;
+ PhyParam_t phyParam;
+ RegionCommonLinkAdrReqVerifyParams_t linkAdrVerifyParams;
+
+ while( bytesProcessed < linkAdrReq->PayloadSize )
+ {
+ // Get ADR request parameters
+ nextIndex = RegionCommonParseLinkAdrReq( &( linkAdrReq->Payload[bytesProcessed] ), &linkAdrParams );
+
+ if( nextIndex == 0 )
+ break; // break loop, since no more request has been found
+
+ // Update bytes processed
+ bytesProcessed += nextIndex;
+
+ // Revert status, as we only check the last ADR request for the channel mask KO
+ status = 0x07;
+
+ // Setup temporary channels mask
+ chMask = linkAdrParams.ChMask;
+
+ // Verify channels mask
+ if( ( linkAdrParams.ChMaskCtrl == 0 ) && ( chMask == 0 ) )
+ {
+ status &= 0xFE; // Channel mask KO
+ }
+ else if( ( ( linkAdrParams.ChMaskCtrl >= 1 ) && ( linkAdrParams.ChMaskCtrl <= 5 )) ||
+ ( linkAdrParams.ChMaskCtrl >= 7 ) )
+ {
+ // RFU
+ status &= 0xFE; // Channel mask KO
+ }
+ else
+ {
+ for( uint8_t i = 0; i < RU864_MAX_NB_CHANNELS; i++ )
+ {
+ if( linkAdrParams.ChMaskCtrl == 6 )
+ {
+ if( NvmCtx.Channels[i].Frequency != 0 )
+ {
+ chMask |= 1 << i;
+ }
+ }
+ else
+ {
+ if( ( ( chMask & ( 1 << i ) ) != 0 ) &&
+ ( NvmCtx.Channels[i].Frequency == 0 ) )
+ {// Trying to enable an undefined channel
+ status &= 0xFE; // Channel mask KO
+ }
+ }
+ }
+ }
+ }
+
+ // Get the minimum possible datarate
+ getPhy.Attribute = PHY_MIN_TX_DR;
+ getPhy.UplinkDwellTime = linkAdrReq->UplinkDwellTime;
+ phyParam = RegionRU864GetPhyParam( &getPhy );
+
+ linkAdrVerifyParams.Status = status;
+ linkAdrVerifyParams.AdrEnabled = linkAdrReq->AdrEnabled;
+ linkAdrVerifyParams.Datarate = linkAdrParams.Datarate;
+ linkAdrVerifyParams.TxPower = linkAdrParams.TxPower;
+ linkAdrVerifyParams.NbRep = linkAdrParams.NbRep;
+ linkAdrVerifyParams.CurrentDatarate = linkAdrReq->CurrentDatarate;
+ linkAdrVerifyParams.CurrentTxPower = linkAdrReq->CurrentTxPower;
+ linkAdrVerifyParams.CurrentNbRep = linkAdrReq->CurrentNbRep;
+ linkAdrVerifyParams.NbChannels = RU864_MAX_NB_CHANNELS;
+ linkAdrVerifyParams.ChannelsMask = &chMask;
+ linkAdrVerifyParams.MinDatarate = ( int8_t )phyParam.Value;
+ linkAdrVerifyParams.MaxDatarate = RU864_TX_MAX_DATARATE;
+ linkAdrVerifyParams.Channels = NvmCtx.Channels;
+ linkAdrVerifyParams.MinTxPower = RU864_MIN_TX_POWER;
+ linkAdrVerifyParams.MaxTxPower = RU864_MAX_TX_POWER;
+ linkAdrVerifyParams.Version = linkAdrReq->Version;
+
+ // Verify the parameters and update, if necessary
+ status = RegionCommonLinkAdrReqVerifyParams( &linkAdrVerifyParams, &linkAdrParams.Datarate, &linkAdrParams.TxPower, &linkAdrParams.NbRep );
+
+ // Update channelsMask if everything is correct
+ if( status == 0x07 )
+ {
+ // Set the channels mask to a default value
+ memset1( ( uint8_t* ) NvmCtx.ChannelsMask, 0, sizeof( NvmCtx.ChannelsMask ) );
+ // Update the channels mask
+ NvmCtx.ChannelsMask[0] = chMask;
+ }
+
+ // Update status variables
+ *drOut = linkAdrParams.Datarate;
+ *txPowOut = linkAdrParams.TxPower;
+ *nbRepOut = linkAdrParams.NbRep;
+ *nbBytesParsed = bytesProcessed;
+
+ return status;
+}
+
+uint8_t RegionRU864RxParamSetupReq( RxParamSetupReqParams_t* rxParamSetupReq )
+{
+ uint8_t status = 0x07;
+
+ // Verify radio frequency
+ if( VerifyRfFreq( rxParamSetupReq->Frequency ) == false )
+ {
+ status &= 0xFE; // Channel frequency KO
+ }
+
+ // Verify datarate
+ if( RegionCommonValueInRange( rxParamSetupReq->Datarate, RU864_RX_MIN_DATARATE, RU864_RX_MAX_DATARATE ) == false )
+ {
+ status &= 0xFD; // Datarate KO
+ }
+
+ // Verify datarate offset
+ if( RegionCommonValueInRange( rxParamSetupReq->DrOffset, RU864_MIN_RX1_DR_OFFSET, RU864_MAX_RX1_DR_OFFSET ) == false )
+ {
+ status &= 0xFB; // Rx1DrOffset range KO
+ }
+
+ return status;
+}
+
+uint8_t RegionRU864NewChannelReq( NewChannelReqParams_t* newChannelReq )
+{
+ uint8_t status = 0x03;
+ ChannelAddParams_t channelAdd;
+ ChannelRemoveParams_t channelRemove;
+
+ if( newChannelReq->NewChannel->Frequency == 0 )
+ {
+ channelRemove.ChannelId = newChannelReq->ChannelId;
+
+ // Remove
+ if( RegionRU864ChannelsRemove( &channelRemove ) == false )
+ {
+ status &= 0xFC;
+ }
+ }
+ else
+ {
+ channelAdd.NewChannel = newChannelReq->NewChannel;
+ channelAdd.ChannelId = newChannelReq->ChannelId;
+
+ switch( RegionRU864ChannelAdd( &channelAdd ) )
+ {
+ case LORAMAC_STATUS_OK:
+ {
+ break;
+ }
+ case LORAMAC_STATUS_FREQUENCY_INVALID:
+ {
+ status &= 0xFE;
+ break;
+ }
+ case LORAMAC_STATUS_DATARATE_INVALID:
+ {
+ status &= 0xFD;
+ break;
+ }
+ case LORAMAC_STATUS_FREQ_AND_DR_INVALID:
+ {
+ status &= 0xFC;
+ break;
+ }
+ default:
+ {
+ status &= 0xFC;
+ break;
+ }
+ }
+ }
+
+ return status;
+}
+
+int8_t RegionRU864TxParamSetupReq( TxParamSetupReqParams_t* txParamSetupReq )
+{
+ return -1;
+}
+
+uint8_t RegionRU864DlChannelReq( DlChannelReqParams_t* dlChannelReq )
+{
+ uint8_t status = 0x03;
+
+ // Verify if the frequency is supported
+ if( VerifyRfFreq( dlChannelReq->Rx1Frequency ) == false )
+ {
+ status &= 0xFE;
+ }
+
+ // Verify if an uplink frequency exists
+ if( NvmCtx.Channels[dlChannelReq->ChannelId].Frequency == 0 )
+ {
+ status &= 0xFD;
+ }
+
+ // Apply Rx1 frequency, if the status is OK
+ if( status == 0x03 )
+ {
+ NvmCtx.Channels[dlChannelReq->ChannelId].Rx1Frequency = dlChannelReq->Rx1Frequency;
+ }
+
+ return status;
+}
+
+int8_t RegionRU864AlternateDr( int8_t currentDr, AlternateDrType_t type )
+{
+ return currentDr;
+}
+
+void RegionRU864CalcBackOff( CalcBackOffParams_t* calcBackOff )
+{
+ RegionCommonCalcBackOffParams_t calcBackOffParams;
+
+ calcBackOffParams.Channels = NvmCtx.Channels;
+ calcBackOffParams.Bands = NvmCtx.Bands;
+ calcBackOffParams.LastTxIsJoinRequest = calcBackOff->LastTxIsJoinRequest;
+ calcBackOffParams.Joined = calcBackOff->Joined;
+ calcBackOffParams.DutyCycleEnabled = calcBackOff->DutyCycleEnabled;
+ calcBackOffParams.Channel = calcBackOff->Channel;
+ calcBackOffParams.ElapsedTime = calcBackOff->ElapsedTime;
+ calcBackOffParams.TxTimeOnAir = calcBackOff->TxTimeOnAir;
+
+ RegionCommonCalcBackOff( &calcBackOffParams );
+}
+
+LoRaMacStatus_t RegionRU864NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff )
+{
+ uint8_t nbEnabledChannels = 0;
+ uint8_t delayTx = 0;
+ uint8_t enabledChannels[RU864_MAX_NB_CHANNELS] = { 0 };
+ TimerTime_t nextTxDelay = 0;
+
+ if( RegionCommonCountChannels( NvmCtx.ChannelsMask, 0, 1 ) == 0 )
+ { // Reactivate default channels
+ NvmCtx.ChannelsMask[0] |= LC( 1 ) + LC( 2 );
+ }
+
+ TimerTime_t elapsed = TimerGetElapsedTime( nextChanParams->LastAggrTx );
+ if( ( nextChanParams->LastAggrTx == 0 ) || ( nextChanParams->AggrTimeOff <= elapsed ) )
+ {
+ // Reset Aggregated time off
+ *aggregatedTimeOff = 0;
+
+ // Update bands Time OFF
+ nextTxDelay = RegionCommonUpdateBandTimeOff( nextChanParams->Joined, nextChanParams->DutyCycleEnabled, NvmCtx.Bands, RU864_MAX_NB_BANDS );
+
+ // Search how many channels are enabled
+ nbEnabledChannels = CountNbOfEnabledChannels( nextChanParams->Joined, nextChanParams->Datarate,
+ NvmCtx.ChannelsMask, NvmCtx.Channels,
+ NvmCtx.Bands, enabledChannels, &delayTx );
+ }
+ else
+ {
+ delayTx++;
+ nextTxDelay = nextChanParams->AggrTimeOff - elapsed;
+ }
+
+ if( nbEnabledChannels > 0 )
+ {
+ // We found a valid channel
+ *channel = enabledChannels[randr( 0, nbEnabledChannels - 1 )];
+
+ *time = 0;
+ return LORAMAC_STATUS_OK;
+ }
+ else
+ {
+ if( delayTx > 0 )
+ {
+ // Delay transmission due to AggregatedTimeOff or to a band time off
+ *time = nextTxDelay;
+ return LORAMAC_STATUS_DUTYCYCLE_RESTRICTED;
+ }
+ // Datarate not supported by any channel, restore defaults
+ NvmCtx.ChannelsMask[0] |= LC( 1 ) + LC( 2 );
+ *time = 0;
+ return LORAMAC_STATUS_NO_CHANNEL_FOUND;
+ }
+}
+
+LoRaMacStatus_t RegionRU864ChannelAdd( ChannelAddParams_t* channelAdd )
+{
+ bool drInvalid = false;
+ bool freqInvalid = false;
+ uint8_t id = channelAdd->ChannelId;
+
+ if( id < RU864_NUMB_DEFAULT_CHANNELS )
+ {
+ return LORAMAC_STATUS_FREQ_AND_DR_INVALID;
+ }
+
+ if( id >= RU864_MAX_NB_CHANNELS )
+ {
+ return LORAMAC_STATUS_PARAMETER_INVALID;
+ }
+
+ // Validate the datarate range
+ if( RegionCommonValueInRange( channelAdd->NewChannel->DrRange.Fields.Min, RU864_TX_MIN_DATARATE, RU864_TX_MAX_DATARATE ) == false )
+ {
+ drInvalid = true;
+ }
+ if( RegionCommonValueInRange( channelAdd->NewChannel->DrRange.Fields.Max, RU864_TX_MIN_DATARATE, RU864_TX_MAX_DATARATE ) == false )
+ {
+ drInvalid = true;
+ }
+ if( channelAdd->NewChannel->DrRange.Fields.Min > channelAdd->NewChannel->DrRange.Fields.Max )
+ {
+ drInvalid = true;
+ }
+
+ // Check frequency
+ if( freqInvalid == false )
+ {
+ if( VerifyRfFreq( channelAdd->NewChannel->Frequency ) == false )
+ {
+ freqInvalid = true;
+ }
+ }
+
+ // Check status
+ if( ( drInvalid == true ) && ( freqInvalid == true ) )
+ {
+ return LORAMAC_STATUS_FREQ_AND_DR_INVALID;
+ }
+ if( drInvalid == true )
+ {
+ return LORAMAC_STATUS_DATARATE_INVALID;
+ }
+ if( freqInvalid == true )
+ {
+ return LORAMAC_STATUS_FREQUENCY_INVALID;
+ }
+
+ memcpy1( ( uint8_t* ) &(NvmCtx.Channels[id]), ( uint8_t* ) channelAdd->NewChannel, sizeof( NvmCtx.Channels[id] ) );
+ NvmCtx.Channels[id].Band = 0;
+ NvmCtx.ChannelsMask[0] |= ( 1 << id );
+ return LORAMAC_STATUS_OK;
+}
+
+bool RegionRU864ChannelsRemove( ChannelRemoveParams_t* channelRemove )
+{
+ uint8_t id = channelRemove->ChannelId;
+
+ if( id < RU864_NUMB_DEFAULT_CHANNELS )
+ {
+ return false;
+ }
+
+ // Remove the channel from the list of channels
+ NvmCtx.Channels[id] = ( ChannelParams_t ){ 0, 0, { 0 }, 0 };
+
+ return RegionCommonChanDisable( NvmCtx.ChannelsMask, id, RU864_MAX_NB_CHANNELS );
+}
+
+void RegionRU864SetContinuousWave( ContinuousWaveParams_t* continuousWave )
+{
+ int8_t txPowerLimited = LimitTxPower( continuousWave->TxPower, NvmCtx.Bands[NvmCtx.Channels[continuousWave->Channel].Band].TxMaxPower, continuousWave->Datarate, NvmCtx.ChannelsMask );
+ int8_t phyTxPower = 0;
+ uint32_t frequency = NvmCtx.Channels[continuousWave->Channel].Frequency;
+
+ // Calculate physical TX power
+ phyTxPower = RegionCommonComputeTxPower( txPowerLimited, continuousWave->MaxEirp, continuousWave->AntennaGain );
+
+ Radio.SetTxContinuousWave( frequency, phyTxPower, continuousWave->Timeout );
+}
+
+uint8_t RegionRU864ApplyDrOffset( uint8_t downlinkDwellTime, int8_t dr, int8_t drOffset )
+{
+ int8_t datarate = dr - drOffset;
+
+ if( datarate < 0 )
+ {
+ datarate = DR_0;
+ }
+ return datarate;
+}
+
+void RegionRU864RxBeaconSetup( RxBeaconSetup_t* rxBeaconSetup, uint8_t* outDr )
+{
+ RegionCommonRxBeaconSetupParams_t regionCommonRxBeaconSetup;
+
+ regionCommonRxBeaconSetup.Datarates = DataratesRU864;
+ regionCommonRxBeaconSetup.Frequency = rxBeaconSetup->Frequency;
+ regionCommonRxBeaconSetup.BeaconSize = RU864_BEACON_SIZE;
+ regionCommonRxBeaconSetup.BeaconDatarate = RU864_BEACON_CHANNEL_DR;
+ regionCommonRxBeaconSetup.BeaconChannelBW = RU864_BEACON_CHANNEL_BW;
+ regionCommonRxBeaconSetup.RxTime = rxBeaconSetup->RxTime;
+ regionCommonRxBeaconSetup.SymbolTimeout = rxBeaconSetup->SymbolTimeout;
+
+ RegionCommonRxBeaconSetup( ®ionCommonRxBeaconSetup );
+
+ // Store downlink datarate
+ *outDr = RU864_BEACON_CHANNEL_DR;
+}
+
+LoRaMacStatus_t RegionRU864ChannelManualAdd( ChannelAddParams_t* channelAdd )
+{
+ bool drInvalid = false;
+ bool freqInvalid = false;
+ uint8_t id = channelAdd->ChannelId;
+
+ if( id >= RU864_MAX_NB_CHANNELS )
+ {
+ return LORAMAC_STATUS_PARAMETER_INVALID;
+ }
+
+ // Validate the datarate range
+ if( RegionCommonValueInRange( channelAdd->NewChannel->DrRange.Fields.Min, RU864_TX_MIN_DATARATE, RU864_TX_MAX_DATARATE ) == false )
+ {
+ drInvalid = true;
+ }
+ if( RegionCommonValueInRange( channelAdd->NewChannel->DrRange.Fields.Max, RU864_TX_MIN_DATARATE, RU864_TX_MAX_DATARATE ) == false )
+ {
+ drInvalid = true;
+ }
+ if( channelAdd->NewChannel->DrRange.Fields.Min > channelAdd->NewChannel->DrRange.Fields.Max )
+ {
+ drInvalid = true;
+ }
+
+ // Check frequency
+ if( freqInvalid == false )
+ {
+ if( VerifyRfFreq( channelAdd->NewChannel->Frequency ) == false )
+ {
+ freqInvalid = true;
+ }
+ }
+
+ // Check status
+ if( ( drInvalid == true ) && ( freqInvalid == true ) )
+ {
+ return LORAMAC_STATUS_FREQ_AND_DR_INVALID;
+ }
+ if( drInvalid == true )
+ {
+ return LORAMAC_STATUS_DATARATE_INVALID;
+ }
+ if( freqInvalid == true )
+ {
+ return LORAMAC_STATUS_FREQUENCY_INVALID;
+ }
+
+ memcpy1( ( uint8_t* ) &(NvmCtx.Channels[id]), ( uint8_t* ) channelAdd->NewChannel, sizeof( NvmCtx.Channels[id] ) );
+ NvmCtx.Channels[id].Band = 0;
+ NvmCtx.ChannelsMask[0] |= ( 1 << id );
+ return LORAMAC_STATUS_OK;
+}
diff --git a/lib/lora/mac/region/RegionRU864.h b/lib/lora/mac/region/RegionRU864.h
new file mode 100644
index 0000000000..b70800d076
--- /dev/null
+++ b/lib/lora/mac/region/RegionRU864.h
@@ -0,0 +1,504 @@
+/*!
+ * \file RegionRU864.h
+ *
+ * \brief Region definition for RU864
+ *
+ * \copyright Revised BSD License, see section \ref LICENSE.
+ *
+ * \code
+ * ______ _
+ * / _____) _ | |
+ * ( (____ _____ ____ _| |_ _____ ____| |__
+ * \____ \| ___ | (_ _) ___ |/ ___) _ \
+ * _____) ) ____| | | || |_| ____( (___| | | |
+ * (______/|_____)_|_|_| \__)_____)\____)_| |_|
+ * (C)2013-2017 Semtech
+ *
+ * ___ _____ _ ___ _ _____ ___ ___ ___ ___
+ * / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
+ * \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
+ * |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
+ * embedded.connectivity.solutions===============
+ *
+ * \endcode
+ *
+ * \author Miguel Luis ( Semtech )
+ *
+ * \author Gregory Cristian ( Semtech )
+ *
+ * \author Daniel Jaeckle ( STACKFORCE )
+ *
+ * \defgroup REGIONRU864 Region RU864
+ * Implementation according to LoRaWAN Specification v1.0.2.
+ * \{
+ */
+#ifndef __REGION_RU864_H__
+#define __REGION_RU864_H__
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include "../LoRaMac.h"
+
+/*!
+ * LoRaMac maximum number of channels
+ */
+#define RU864_MAX_NB_CHANNELS 8
+
+/*!
+ * Number of default channels
+ */
+#define RU864_NUMB_DEFAULT_CHANNELS 2
+
+/*!
+ * Number of channels to apply for the CF list
+ */
+#define RU864_NUMB_CHANNELS_CF_LIST 5
+
+/*!
+ * Minimal datarate that can be used by the node
+ */
+#define RU864_TX_MIN_DATARATE DR_0
+
+/*!
+ * Maximal datarate that can be used by the node
+ */
+#define RU864_TX_MAX_DATARATE DR_7
+
+/*!
+ * Minimal datarate that can be used by the node
+ */
+#define RU864_RX_MIN_DATARATE DR_0
+
+/*!
+ * Maximal datarate that can be used by the node
+ */
+#define RU864_RX_MAX_DATARATE DR_7
+
+/*!
+ * Default datarate used by the node
+ */
+#define RU864_DEFAULT_DATARATE DR_0
+
+/*!
+ * Minimal Rx1 receive datarate offset
+ */
+#define RU864_MIN_RX1_DR_OFFSET 0
+
+/*!
+ * Maximal Rx1 receive datarate offset
+ */
+#define RU864_MAX_RX1_DR_OFFSET 5
+
+/*!
+ * Default Rx1 receive datarate offset
+ */
+#define RU864_DEFAULT_RX1_DR_OFFSET 0
+
+/*!
+ * Minimal Tx output power that can be used by the node
+ */
+#define RU864_MIN_TX_POWER TX_POWER_7
+
+/*!
+ * Maximal Tx output power that can be used by the node
+ */
+#define RU864_MAX_TX_POWER TX_POWER_0
+
+/*!
+ * Default Tx output power used by the node
+ */
+#define RU864_DEFAULT_TX_POWER TX_POWER_0
+
+/*!
+ * Default Max EIRP
+ */
+#define RU864_DEFAULT_MAX_EIRP 16.0f
+
+/*!
+ * Default antenna gain
+ */
+#define RU864_DEFAULT_ANTENNA_GAIN 2.15f
+
+/*!
+ * ADR Ack limit
+ */
+#define RU864_ADR_ACK_LIMIT 64
+
+/*!
+ * ADR Ack delay
+ */
+#define RU864_ADR_ACK_DELAY 32
+
+/*!
+ * Enabled or disabled the duty cycle
+ */
+#define RU864_DUTY_CYCLE_ENABLED 1
+
+/*!
+ * Maximum RX window duration
+ */
+#define RU864_MAX_RX_WINDOW 3000 //TODO
+
+/*!
+ * Receive delay 1
+ */
+#define RU864_RECEIVE_DELAY1 1000
+
+/*!
+ * Receive delay 2
+ */
+#define RU864_RECEIVE_DELAY2 2000
+
+/*!
+ * Join accept delay 1
+ */
+#define RU864_JOIN_ACCEPT_DELAY1 5000
+
+/*!
+ * Join accept delay 2
+ */
+#define RU864_JOIN_ACCEPT_DELAY2 6000
+
+/*!
+ * Maximum frame counter gap
+ */
+#define RU864_MAX_FCNT_GAP 16384
+
+/*!
+ * Ack timeout
+ */
+#define RU864_ACKTIMEOUT 2000
+
+/*!
+ * Random ack timeout limits
+ */
+#define RU864_ACK_TIMEOUT_RND 1000
+
+#if ( RU864_DEFAULT_DATARATE > DR_5 )
+#error "A default DR higher than DR_5 may lead to connectivity loss."
+#endif
+
+/*!
+ * Second reception window channel frequency definition.
+ */
+#define RU864_RX_WND_2_FREQ 869100000
+
+/*!
+ * Second reception window channel datarate definition.
+ */
+#define RU864_RX_WND_2_DR DR_0
+
+/*
+ * CLASS B
+ */
+/*!
+ * Beacon frequency
+ */
+#define RU864_BEACON_CHANNEL_FREQ 869100000
+
+/*!
+ * Payload size of a beacon frame
+ */
+#define RU864_BEACON_SIZE 17
+
+/*!
+ * Size of RFU 1 field
+ */
+#define RU864_RFU1_SIZE 2
+
+/*!
+ * Size of RFU 2 field
+ */
+#define RU864_RFU2_SIZE 0
+
+/*!
+ * Datarate of the beacon channel
+ */
+#define RU864_BEACON_CHANNEL_DR DR_3
+
+/*!
+ * Bandwith of the beacon channel (Index of BandwidthsRU864[])
+ */
+#define RU864_BEACON_CHANNEL_BW 0
+
+/*!
+ * Maximum number of bands
+ */
+#define RU864_MAX_NB_BANDS 1
+
+/*!
+ * Band 0 definition
+ * { DutyCycle, TxMaxPower, LastJoinTxDoneTime, LastTxDoneTime, TimeOff }
+ */
+#define RU864_BAND0 { 100 , RU864_MAX_TX_POWER, 0, 0, 0 } // 1.0 %
+
+/*!
+ * LoRaMac default channel 1
+ * Channel = { Frequency [Hz], RX1 Frequency [Hz], { ( ( DrMax << 4 ) | DrMin ) }, Band }
+ */
+#define RU864_LC1 { 868900000, 0, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 }
+
+/*!
+ * LoRaMac default channel 2
+ * Channel = { Frequency [Hz], RX1 Frequency [Hz], { ( ( DrMax << 4 ) | DrMin ) }, Band }
+ */
+#define RU864_LC2 { 869100000, 0, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 }
+
+
+/*!
+ * LoRaMac channels which are allowed for the join procedure
+ */
+#define RU864_JOIN_CHANNELS ( uint16_t )( LC( 1 ) | LC( 2 ) )
+
+/*!
+ * Data rates table definition
+ */
+static const uint8_t DataratesRU864[] = { 12, 11, 10, 9, 8, 7, 7, 50 };
+
+/*!
+ * Bandwidths table definition in Hz
+ */
+static const uint32_t BandwidthsRU864[] = { 125000, 125000, 125000, 125000, 125000, 125000, 250000, 0 };
+
+/*!
+ * Maximum payload with respect to the datarate index. Cannot operate with repeater.
+ */
+static const uint8_t MaxPayloadOfDatarateRU864[] = { 51, 51, 51, 115, 242, 242, 242, 242 };
+
+/*!
+ * Maximum payload with respect to the datarate index. Can operate with repeater.
+ */
+static const uint8_t MaxPayloadOfDatarateRepeaterRU864[] = { 51, 51, 51, 115, 222, 222, 222, 222 };
+
+/*!
+ * \brief The function gets a value of a specific phy attribute.
+ *
+ * \param [IN] getPhy Pointer to the function parameters.
+ *
+ * \retval Returns a structure containing the PHY parameter.
+ */
+PhyParam_t RegionRU864GetPhyParam( GetPhyParams_t* getPhy );
+
+/*!
+ * \brief Updates the last TX done parameters of the current channel.
+ *
+ * \param [IN] txDone Pointer to the function parameters.
+ */
+void RegionRU864SetBandTxDone( SetBandTxDoneParams_t* txDone );
+
+/*!
+ * \brief Initializes the channels masks and the channels.
+ *
+ * \param [IN] type Sets the initialization type.
+ */
+void RegionRU864InitDefaults( InitDefaultsParams_t* params );
+
+/*!
+ * \brief Returns a pointer to the internal context and its size.
+ *
+ * \param [OUT] params Pointer to the function parameters.
+ *
+ * \retval Points to a structure where the module store its non-volatile context.
+ */
+void* RegionRU864GetNvmCtx( GetNvmCtxParams_t* params );
+
+/*!
+ * \brief Verifies a parameter.
+ *
+ * \param [IN] verify Pointer to the function parameters.
+ *
+ * \param [IN] type Sets the initialization type.
+ *
+ * \retval Returns true, if the parameter is valid.
+ */
+bool RegionRU864Verify( VerifyParams_t* verify, PhyAttribute_t phyAttribute );
+
+/*!
+ * \brief The function parses the input buffer and sets up the channels of the
+ * CF list.
+ *
+ * \param [IN] applyCFList Pointer to the function parameters.
+ */
+void RegionRU864ApplyCFList( ApplyCFListParams_t* applyCFList );
+
+/*!
+ * \brief Sets a channels mask.
+ *
+ * \param [IN] chanMaskSet Pointer to the function parameters.
+ *
+ * \retval Returns true, if the channels mask could be set.
+ */
+bool RegionRU864ChanMaskSet( ChanMaskSetParams_t* chanMaskSet );
+
+/*!
+ * Computes the Rx window timeout and offset.
+ *
+ * \param [IN] datarate Rx window datarate index to be used
+ *
+ * \param [IN] minRxSymbols Minimum required number of symbols to detect an Rx frame.
+ *
+ * \param [IN] rxError System maximum timing error of the receiver. In milliseconds
+ * The receiver will turn on in a [-rxError : +rxError] ms
+ * interval around RxOffset
+ *
+ * \param [OUT]rxConfigParams Returns updated WindowTimeout and WindowOffset fields.
+ */
+void RegionRU864ComputeRxWindowParameters( int8_t datarate, uint8_t minRxSymbols, uint32_t rxError, RxConfigParams_t *rxConfigParams );
+
+/*!
+ * \brief Configuration of the RX windows.
+ *
+ * \param [IN] rxConfig Pointer to the function parameters.
+ *
+ * \param [OUT] datarate The datarate index which was set.
+ *
+ * \retval Returns true, if the configuration was applied successfully.
+ */
+bool RegionRU864RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate );
+
+/*!
+ * \brief TX configuration.
+ *
+ * \param [IN] txConfig Pointer to the function parameters.
+ *
+ * \param [OUT] txPower The tx power index which was set.
+ *
+ * \param [OUT] txTimeOnAir The time-on-air of the frame.
+ *
+ * \retval Returns true, if the configuration was applied successfully.
+ */
+bool RegionRU864TxConfig( TxConfigParams_t* txConfig, int8_t* txPower, TimerTime_t* txTimeOnAir );
+
+/*!
+ * \brief The function processes a Link ADR Request.
+ *
+ * \param [IN] linkAdrReq Pointer to the function parameters.
+ *
+ * \retval Returns the status of the operation, according to the LoRaMAC specification.
+ */
+uint8_t RegionRU864LinkAdrReq( LinkAdrReqParams_t* linkAdrReq, int8_t* drOut, int8_t* txPowOut, uint8_t* nbRepOut, uint8_t* nbBytesParsed );
+
+/*!
+ * \brief The function processes a RX Parameter Setup Request.
+ *
+ * \param [IN] rxParamSetupReq Pointer to the function parameters.
+ *
+ * \retval Returns the status of the operation, according to the LoRaMAC specification.
+ */
+uint8_t RegionRU864RxParamSetupReq( RxParamSetupReqParams_t* rxParamSetupReq );
+
+/*!
+ * \brief The function processes a Channel Request.
+ *
+ * \param [IN] newChannelReq Pointer to the function parameters.
+ *
+ * \retval Returns the status of the operation, according to the LoRaMAC specification.
+ */
+uint8_t RegionRU864NewChannelReq( NewChannelReqParams_t* newChannelReq );
+
+/*!
+ * \brief The function processes a TX ParamSetup Request.
+ *
+ * \param [IN] txParamSetupReq Pointer to the function parameters.
+ *
+ * \retval Returns the status of the operation, according to the LoRaMAC specification.
+ * Returns -1, if the functionality is not implemented. In this case, the end node
+ * shall not process the command.
+ */
+int8_t RegionRU864TxParamSetupReq( TxParamSetupReqParams_t* txParamSetupReq );
+
+/*!
+ * \brief The function processes a DlChannel Request.
+ *
+ * \param [IN] dlChannelReq Pointer to the function parameters.
+ *
+ * \retval Returns the status of the operation, according to the LoRaMAC specification.
+ */
+uint8_t RegionRU864DlChannelReq( DlChannelReqParams_t* dlChannelReq );
+
+/*!
+ * \brief Alternates the datarate of the channel for the join request.
+ *
+ * \param [IN] currentDr Current datarate.
+ *
+ * \retval Datarate to apply.
+ */
+int8_t RegionRU864AlternateDr( int8_t currentDr, AlternateDrType_t type );
+
+/*!
+ * \brief Calculates the back-off time.
+ *
+ * \param [IN] calcBackOff Pointer to the function parameters.
+ */
+void RegionRU864CalcBackOff( CalcBackOffParams_t* calcBackOff );
+
+/*!
+ * \brief Searches and set the next random available channel
+ *
+ * \param [OUT] channel Next channel to use for TX.
+ *
+ * \param [OUT] time Time to wait for the next transmission according to the duty
+ * cycle.
+ *
+ * \param [OUT] aggregatedTimeOff Updates the aggregated time off.
+ *
+ * \retval Function status [1: OK, 0: Unable to find a channel on the current datarate]
+ */
+LoRaMacStatus_t RegionRU864NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff );
+
+/*!
+ * \brief Adds a channel.
+ *
+ * \param [IN] channelAdd Pointer to the function parameters.
+ *
+ * \retval Status of the operation.
+ */
+LoRaMacStatus_t RegionRU864ChannelAdd( ChannelAddParams_t* channelAdd );
+LoRaMacStatus_t RegionRU864ChannelManualAdd( ChannelAddParams_t* channelAdd );
+
+/*!
+ * \brief Removes a channel.
+ *
+ * \param [IN] channelRemove Pointer to the function parameters.
+ *
+ * \retval Returns true, if the channel was removed successfully.
+ */
+bool RegionRU864ChannelsRemove( ChannelRemoveParams_t* channelRemove );
+
+/*!
+ * \brief Sets the radio into continuous wave mode.
+ *
+ * \param [IN] continuousWave Pointer to the function parameters.
+ */
+void RegionRU864SetContinuousWave( ContinuousWaveParams_t* continuousWave );
+
+/*!
+ * \brief Computes new datarate according to the given offset
+ *
+ * \param [IN] downlinkDwellTime Downlink dwell time configuration. 0: No limit, 1: 400ms
+ *
+ * \param [IN] dr Current datarate
+ *
+ * \param [IN] drOffset Offset to be applied
+ *
+ * \retval newDr Computed datarate.
+ */
+uint8_t RegionRU864ApplyDrOffset( uint8_t downlinkDwellTime, int8_t dr, int8_t drOffset );
+
+/*!
+ * \brief Sets the radio into beacon reception mode
+ *
+ * \param [IN] rxBeaconSetup Pointer to the function parameters
+ */
+void RegionRU864RxBeaconSetup( RxBeaconSetup_t* rxBeaconSetup, uint8_t* outDr );
+
+/*! \} defgroup REGIONRU864 */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // __REGION_RU864_H__
diff --git a/lib/lora/mac/region/RegionUS915-Hybrid.c b/lib/lora/mac/region/RegionUS915-Hybrid.c
deleted file mode 100644
index 06ca70dad1..0000000000
--- a/lib/lora/mac/region/RegionUS915-Hybrid.c
+++ /dev/null
@@ -1,1060 +0,0 @@
-/*
- / _____) _ | |
-( (____ _____ ____ _| |_ _____ ____| |__
- \____ \| ___ | (_ _) ___ |/ ___) _ \
- _____) ) ____| | | || |_| ____( (___| | | |
-(______/|_____)_|_|_| \__)_____)\____)_| |_|
- (C)2013 Semtech
- ___ _____ _ ___ _ _____ ___ ___ ___ ___
-/ __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
-\__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
-|___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
-embedded.connectivity.solutions===============
-
-Description: LoRa MAC region US915 Hybrid implementation
-
-License: Revised BSD License, see LICENSE.TXT file include in the project
-
-Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jaeckle ( STACKFORCE )
-*/
-#include
-#include
-#include
-#include
-
-#include "board.h"
-#include "lora/mac/LoRaMac.h"
-#include "esp_attr.h"
-
-#include "utilities.h"
-
-#include "Region.h"
-#include "RegionCommon.h"
-#include "RegionUS915-Hybrid.h"
-
-// Definitions
-#define CHANNELS_MASK_SIZE 6
-
-// Global attributes
-/*!
- * LoRaMAC channels
- */
-static ChannelParams_t Channels[US915_HYBRID_MAX_NB_CHANNELS];
-
-/*!
- * LoRaMac bands
- */
-static Band_t Bands[US915_HYBRID_MAX_NB_BANDS] =
-{
- US915_HYBRID_BAND0
-};
-
-/*!
- * LoRaMac channels mask
- */
-static uint16_t ChannelsMask[CHANNELS_MASK_SIZE];
-
-/*!
- * LoRaMac channels remaining
- */
-static uint16_t ChannelsMaskRemaining[CHANNELS_MASK_SIZE];
-
-/*!
- * LoRaMac channels default mask
- */
-static uint16_t ChannelsDefaultMask[CHANNELS_MASK_SIZE];
-
-// Static functions
-static int8_t GetNextLowerTxDr( int8_t dr, int8_t minDr )
-{
- uint8_t nextLowerDr = 0;
-
- if( dr == minDr )
- {
- nextLowerDr = minDr;
- }
- else
- {
- nextLowerDr = dr - 1;
- }
- return nextLowerDr;
-}
-
-static uint32_t GetBandwidth( uint32_t drIndex )
-{
- switch( BandwidthsUS915_HYBRID[drIndex] )
- {
- default:
- case 125000:
- return 0;
- case 250000:
- return 1;
- case 500000:
- return 2;
- }
-}
-
-static void ReenableChannels( uint16_t mask, uint16_t* channelsMask )
-{
- uint16_t blockMask = mask;
-
- for( uint8_t i = 0, j = 0; i < 4; i++, j += 2 )
- {
- channelsMask[i] = 0;
- if( ( blockMask & ( 1 << j ) ) != 0 )
- {
- channelsMask[i] |= 0x00FF;
- }
- if( ( blockMask & ( 1 << ( j + 1 ) ) ) != 0 )
- {
- channelsMask[i] |= 0xFF00;
- }
- }
- channelsMask[4] = blockMask;
- channelsMask[5] = 0x0000;
-}
-
-static uint8_t CountBits( uint16_t mask, uint8_t nbBits )
-{
- uint8_t nbActiveBits = 0;
-
- for( uint8_t j = 0; j < nbBits; j++ )
- {
- if( ( mask & ( 1 << j ) ) == ( 1 << j ) )
- {
- nbActiveBits++;
- }
- }
- return nbActiveBits;
-}
-
-static int8_t LimitTxPower( int8_t txPower, int8_t maxBandTxPower, int8_t datarate, uint16_t* channelsMask )
-{
- int8_t txPowerResult = txPower;
-
- // Limit tx power to the band max
- txPowerResult = MAX( txPower, maxBandTxPower );
-
- if( datarate == DR_4 )
- {// Limit tx power to max 26dBm
- txPowerResult = MAX( txPower, TX_POWER_2 );
- }
- else
- {
- if( RegionCommonCountChannels( channelsMask, 0, 4 ) < 50 )
- {// Limit tx power to max 21dBm
- txPowerResult = MAX( txPower, TX_POWER_5 );
- }
- }
- return txPowerResult;
-}
-
-static bool ValidateChannelsMask( uint16_t* channelsMask )
-{
- bool chanMaskState = false;
- uint16_t block1 = 0;
- uint16_t block2 = 0;
- uint8_t index = 0;
- uint16_t channelsMaskCpy[6];
-
- // Copy channels mask to not change the input
- for( uint8_t i = 0; i < 4; i++ )
- {
- channelsMaskCpy[i] = channelsMask[i];
- }
-
- for( uint8_t i = 0; i < 4; i++ )
- {
- block1 = channelsMaskCpy[i] & 0x00FF;
- block2 = channelsMaskCpy[i] & 0xFF00;
-
- if( CountBits( block1, 16 ) > 5 )
- {
- channelsMaskCpy[i] &= block1;
- channelsMaskCpy[4] = 1 << ( i * 2 );
- chanMaskState = true;
- index = i;
- break;
- }
- else if( CountBits( block2, 16 ) > 5 )
- {
- channelsMaskCpy[i] &= block2;
- channelsMaskCpy[4] = 1 << ( i * 2 + 1 );
- chanMaskState = true;
- index = i;
- break;
- }
- }
-
- // Do only change the channel mask, if we have found a valid block.
- if( chanMaskState == true )
- {
- // Copy channels mask back again
- for( uint8_t i = 0; i < 4; i++ )
- {
- channelsMask[i] = channelsMaskCpy[i];
-
- if( i != index )
- {
- channelsMask[i] = 0;
- }
- }
- channelsMask[4] = channelsMaskCpy[4];
- }
- return chanMaskState;
-}
-
-static uint8_t CountNbOfEnabledChannels( uint8_t datarate, uint16_t* channelsMask, ChannelParams_t* channels, Band_t* bands, uint8_t* enabledChannels, uint8_t* delayTx )
-{
- uint8_t nbEnabledChannels = 0;
- uint8_t delayTransmission = 0;
-
- for( uint8_t i = 0, k = 0; i < US915_HYBRID_MAX_NB_CHANNELS; i += 16, k++ )
- {
- for( uint8_t j = 0; j < 16; j++ )
- {
- if( ( channelsMask[k] & ( 1 << j ) ) != 0 )
- {
- if( channels[i + j].Frequency == 0 )
- { // Check if the channel is enabled
- continue;
- }
- if( RegionCommonValueInRange( datarate, channels[i + j].DrRange.Fields.Min,
- channels[i + j].DrRange.Fields.Max ) == false )
- { // Check if the current channel selection supports the given datarate
- continue;
- }
- if( bands[channels[i + j].Band].TimeOff > 0 )
- { // Check if the band is available for transmission
- delayTransmission++;
- continue;
- }
- enabledChannels[nbEnabledChannels++] = i + j;
- }
- }
- }
-
- *delayTx = delayTransmission;
- return nbEnabledChannels;
-}
-
-PhyParam_t RegionUS915HybridGetPhyParam( GetPhyParams_t* getPhy )
-{
- PhyParam_t phyParam = { 0 };
-
- switch( getPhy->Attribute )
- {
- case PHY_MIN_RX_DR:
- {
- phyParam.Value = US915_HYBRID_RX_MIN_DATARATE;
- break;
- }
- case PHY_MIN_TX_DR:
- {
- phyParam.Value = US915_HYBRID_TX_MIN_DATARATE;
- break;
- }
- case PHY_DEF_TX_DR:
- {
- phyParam.Value = US915_HYBRID_DEFAULT_DATARATE;
- break;
- }
- case PHY_NEXT_LOWER_TX_DR:
- {
- phyParam.Value = GetNextLowerTxDr( getPhy->Datarate, US915_HYBRID_TX_MIN_DATARATE );
- break;
- }
- case PHY_DEF_TX_POWER:
- {
- phyParam.Value = US915_HYBRID_DEFAULT_TX_POWER;
- break;
- }
- case PHY_MAX_PAYLOAD:
- {
- phyParam.Value = MaxPayloadOfDatarateUS915_HYBRID[getPhy->Datarate];
- break;
- }
- case PHY_MAX_PAYLOAD_REPEATER:
- {
- phyParam.Value = MaxPayloadOfDatarateRepeaterUS915_HYBRID[getPhy->Datarate];
- break;
- }
- case PHY_DUTY_CYCLE:
- {
- phyParam.Value = US915_HYBRID_DUTY_CYCLE_ENABLED;
- break;
- }
- case PHY_MAX_RX_WINDOW:
- {
- phyParam.Value = US915_HYBRID_MAX_RX_WINDOW;
- break;
- }
- case PHY_RECEIVE_DELAY1:
- {
- phyParam.Value = US915_HYBRID_RECEIVE_DELAY1;
- break;
- }
- case PHY_RECEIVE_DELAY2:
- {
- phyParam.Value = US915_HYBRID_RECEIVE_DELAY2;
- break;
- }
- case PHY_JOIN_ACCEPT_DELAY1:
- {
- phyParam.Value = US915_HYBRID_JOIN_ACCEPT_DELAY1;
- break;
- }
- case PHY_JOIN_ACCEPT_DELAY2:
- {
- phyParam.Value = US915_HYBRID_JOIN_ACCEPT_DELAY2;
- break;
- }
- case PHY_MAX_FCNT_GAP:
- {
- phyParam.Value = US915_HYBRID_MAX_FCNT_GAP;
- break;
- }
- case PHY_ACK_TIMEOUT:
- {
- phyParam.Value = ( US915_HYBRID_ACKTIMEOUT + randr( -US915_HYBRID_ACK_TIMEOUT_RND, US915_HYBRID_ACK_TIMEOUT_RND ) );
- break;
- }
- case PHY_DEF_DR1_OFFSET:
- {
- phyParam.Value = US915_HYBRID_DEFAULT_RX1_DR_OFFSET;
- break;
- }
- case PHY_DEF_RX2_FREQUENCY:
- {
- phyParam.Value = US915_HYBRID_RX_WND_2_FREQ;
- break;
- }
- case PHY_DEF_RX2_DR:
- {
- phyParam.Value = US915_HYBRID_RX_WND_2_DR;
- break;
- }
- case PHY_CHANNELS_MASK:
- {
- phyParam.ChannelsMask = ChannelsMask;
- break;
- }
- case PHY_CHANNELS_DEFAULT_MASK:
- {
- phyParam.ChannelsMask = ChannelsDefaultMask;
- break;
- }
- case PHY_MAX_NB_CHANNELS:
- {
- phyParam.Value = US915_HYBRID_MAX_NB_CHANNELS;
- break;
- }
- case PHY_CHANNELS:
- {
- phyParam.Channels = Channels;
- break;
- }
- case PHY_DEF_UPLINK_DWELL_TIME:
- case PHY_DEF_DOWNLINK_DWELL_TIME:
- {
- phyParam.Value = 0;
- break;
- }
- case PHY_DEF_MAX_EIRP:
- case PHY_DEF_ANTENNA_GAIN:
- {
- phyParam.fValue = 0;
- break;
- }
- case PHY_NB_JOIN_TRIALS:
- case PHY_DEF_NB_JOIN_TRIALS:
- {
- phyParam.Value = 2;
- break;
- }
- default:
- {
- break;
- }
- }
-
- return phyParam;
-}
-
-IRAM_ATTR void RegionUS915HybridSetBandTxDone( SetBandTxDoneParams_t* txDone )
-{
- RegionCommonSetBandTxDone( txDone->Joined, &Bands[Channels[txDone->Channel].Band], txDone->LastTxDoneTime );
-}
-
-void RegionUS915HybridInitDefaults( InitType_t type )
-{
- switch( type )
- {
- case INIT_TYPE_INIT:
- {
- // Channels
- // 125 kHz channels
- for( uint8_t i = 0; i < US915_HYBRID_MAX_NB_CHANNELS - 8; i++ )
- {
- Channels[i].Frequency = 902300000 + i * 200000;
- Channels[i].DrRange.Value = ( DR_3 << 4 ) | DR_0;
- Channels[i].Band = 0;
- }
- // 500 kHz channels
- for( uint8_t i = US915_HYBRID_MAX_NB_CHANNELS - 8; i < US915_HYBRID_MAX_NB_CHANNELS; i++ )
- {
- Channels[i].Frequency = 903000000 + ( i - ( US915_HYBRID_MAX_NB_CHANNELS - 8 ) ) * 1600000;
- Channels[i].DrRange.Value = ( DR_4 << 4 ) | DR_4;
- Channels[i].Band = 0;
- }
-
- // ChannelsMask
- ChannelsDefaultMask[0] = 0x00FF;
- ChannelsDefaultMask[1] = 0x0000;
- ChannelsDefaultMask[2] = 0x0000;
- ChannelsDefaultMask[3] = 0x0000;
- ChannelsDefaultMask[4] = 0x0001;
- ChannelsDefaultMask[5] = 0x0000;
-
- // Copy channels default mask
- RegionCommonChanMaskCopy( ChannelsMask, ChannelsDefaultMask, 6 );
-
- // Copy into channels mask remaining
- RegionCommonChanMaskCopy( ChannelsMaskRemaining, ChannelsMask, 6 );
- break;
- }
- case INIT_TYPE_RESTORE:
- {
- ReenableChannels( ChannelsDefaultMask[4], ChannelsMask );
-
- for( uint8_t i = 0; i < 6; i++ )
- { // Copy-And the channels mask
- ChannelsMaskRemaining[i] &= ChannelsMask[i];
- }
- }
- default:
- {
- break;
- }
- }
-}
-
-bool RegionUS915HybridVerify( VerifyParams_t* verify, PhyAttribute_t phyAttribute )
-{
- switch( phyAttribute )
- {
- case PHY_TX_DR:
- {
- return RegionCommonValueInRange( verify->DatarateParams.Datarate, US915_HYBRID_TX_MIN_DATARATE, US915_HYBRID_TX_MAX_DATARATE );
- }
- case PHY_DEF_TX_DR:
- {
- return RegionCommonValueInRange( verify->DatarateParams.Datarate, DR_0, DR_5 );
- }
- case PHY_RX_DR:
- {
- return RegionCommonValueInRange( verify->DatarateParams.Datarate, US915_HYBRID_RX_MIN_DATARATE, US915_HYBRID_RX_MAX_DATARATE );
- }
- case PHY_DEF_TX_POWER:
- case PHY_TX_POWER:
- {
- // Remark: switched min and max!
- return RegionCommonValueInRange( verify->TxPower, US915_HYBRID_MAX_TX_POWER, US915_HYBRID_MIN_TX_POWER );
- }
- case PHY_DUTY_CYCLE:
- {
- return US915_HYBRID_DUTY_CYCLE_ENABLED;
- }
- case PHY_NB_JOIN_TRIALS:
- {
- if( verify->NbJoinTrials < 2 )
- {
- return false;
- }
- break;
- }
- default:
- return false;
- }
- return true;
-}
-
-void RegionUS915HybridApplyCFList( ApplyCFListParams_t* applyCFList )
-{
- return;
-}
-
-bool RegionUS915HybridChanMaskSet( ChanMaskSetParams_t* chanMaskSet )
-{
- uint8_t nbChannels = RegionCommonCountChannels( chanMaskSet->ChannelsMaskIn, 0, 4 );
-
- // Check the number of active channels
- if( ( nbChannels < 2 ) &&
- ( nbChannels > 0 ) )
- {
- return false;
- }
-
- // Validate the channels mask
- if( ValidateChannelsMask( chanMaskSet->ChannelsMaskIn ) == false )
- {
- return false;
- }
-
- switch( chanMaskSet->ChannelsMaskType )
- {
- case CHANNELS_MASK:
- {
- RegionCommonChanMaskCopy( ChannelsMask, chanMaskSet->ChannelsMaskIn, 6 );
-
- for( uint8_t i = 0; i < 6; i++ )
- { // Copy-And the channels mask
- ChannelsMaskRemaining[i] &= ChannelsMask[i];
- }
- break;
- }
- case CHANNELS_DEFAULT_MASK:
- {
- RegionCommonChanMaskCopy( ChannelsDefaultMask, chanMaskSet->ChannelsMaskIn, 6 );
- break;
- }
- default:
- return false;
- }
- return true;
-}
-
-bool RegionUS915HybridAdrNext( AdrNextParams_t* adrNext, int8_t* drOut, int8_t* txPowOut, uint32_t* adrAckCounter )
-{
- bool adrAckReq = false;
- int8_t datarate = adrNext->Datarate;
- int8_t txPower = adrNext->TxPower;
- GetPhyParams_t getPhy;
- PhyParam_t phyParam;
-
- // Report back the adr ack counter
- *adrAckCounter = adrNext->AdrAckCounter;
-
- if( adrNext->AdrEnabled == true )
- {
- if( datarate == US915_HYBRID_TX_MIN_DATARATE )
- {
- *adrAckCounter = 0;
- adrAckReq = false;
- }
- else
- {
- if( adrNext->AdrAckCounter >= US915_HYBRID_ADR_ACK_LIMIT )
- {
- adrAckReq = true;
- txPower = US915_HYBRID_MAX_TX_POWER;
- }
- else
- {
- adrAckReq = false;
- }
- if( adrNext->AdrAckCounter >= ( US915_HYBRID_ADR_ACK_LIMIT + US915_HYBRID_ADR_ACK_DELAY ) )
- {
- if( ( adrNext->AdrAckCounter % US915_HYBRID_ADR_ACK_DELAY ) == 1 )
- {
- // Decrease the datarate
- getPhy.Attribute = PHY_NEXT_LOWER_TX_DR;
- getPhy.Datarate = datarate;
- getPhy.UplinkDwellTime = adrNext->UplinkDwellTime;
- phyParam = RegionUS915HybridGetPhyParam( &getPhy );
- datarate = phyParam.Value;
-
- if( datarate == US915_HYBRID_TX_MIN_DATARATE )
- {
- // We must set adrAckReq to false as soon as we reach the lowest datarate
- adrAckReq = false;
- if( adrNext->UpdateChanMask == true )
- {
- // Re-enable default channels
- ReenableChannels( ChannelsMask[4], ChannelsMask );
- }
- }
- }
- }
- }
- }
-
- *drOut = datarate;
- *txPowOut = txPower;
- return adrAckReq;
-}
-
-void RegionUS915HybridComputeRxWindowParameters( int8_t datarate, uint8_t minRxSymbols, uint32_t rxError, RxConfigParams_t *rxConfigParams )
-{
- double tSymbol = 0.0;
-
- // Get the datarate, perform a boundary check
- rxConfigParams->Datarate = MIN( datarate, US915_HYBRID_RX_MAX_DATARATE );
- rxConfigParams->Bandwidth = GetBandwidth( rxConfigParams->Datarate );
-
- tSymbol = RegionCommonComputeSymbolTimeLoRa( DataratesUS915_HYBRID[rxConfigParams->Datarate], BandwidthsUS915_HYBRID[rxConfigParams->Datarate] );
-
- RegionCommonComputeRxWindowParameters( tSymbol, minRxSymbols, rxError, RADIO_WAKEUP_TIME, &rxConfigParams->WindowTimeout, &rxConfigParams->WindowOffset );
-}
-
-bool RegionUS915HybridRxConfig( RxConfigParams_t* rxConfig, int8_t* datarate )
-{
- int8_t dr = rxConfig->Datarate;
- uint8_t maxPayload = 0;
- int8_t phyDr = 0;
- uint32_t frequency = rxConfig->Frequency;
-
- if( Radio.GetStatus( ) != RF_IDLE )
- {
- return false;
- }
-
- if( rxConfig->Window == 0 )
- {
- // Apply window 1 frequency
- frequency = US915_HYBRID_FIRST_RX1_CHANNEL + ( rxConfig->Channel % 8 ) * US915_HYBRID_STEPWIDTH_RX1_CHANNEL;
- }
-
- // Read the physical datarate from the datarates table
- phyDr = DataratesUS915_HYBRID[dr];
-
- Radio.SetChannel( frequency );
-
- // Radio configuration
- Radio.SetRxConfig( MODEM_LORA, rxConfig->Bandwidth, phyDr, 1, 0, 8, rxConfig->WindowTimeout, false, 0, false, 0, 0, true, rxConfig->RxContinuous );
-
- if( rxConfig->RepeaterSupport == true )
- {
- maxPayload = MaxPayloadOfDatarateRepeaterUS915_HYBRID[dr];
- }
- else
- {
- maxPayload = MaxPayloadOfDatarateUS915_HYBRID[dr];
- }
- Radio.SetMaxPayloadLength( MODEM_LORA, maxPayload + LORA_MAC_FRMPAYLOAD_OVERHEAD );
-
- *datarate = (uint8_t) dr;
- return true;
-}
-
-bool RegionUS915HybridTxConfig( TxConfigParams_t* txConfig, int8_t* txPower, TimerTime_t* txTimeOnAir )
-{
- int8_t phyDr = DataratesUS915_HYBRID[txConfig->Datarate];
- int8_t txPowerLimited = LimitTxPower( txConfig->TxPower, Bands[Channels[txConfig->Channel].Band].TxMaxPower, txConfig->Datarate, ChannelsMask );
- uint32_t bandwidth = GetBandwidth( txConfig->Datarate );
- int8_t phyTxPower = 0;
-
- // Calculate physical TX power
- phyTxPower = RegionCommonComputeTxPower( txPowerLimited, US915_HYBRID_DEFAULT_MAX_ERP, 0 );
-
- // Setup the radio frequency
- Radio.SetChannel( Channels[txConfig->Channel].Frequency );
-
- Radio.SetTxConfig( MODEM_LORA, phyTxPower, 0, bandwidth, phyDr, 1, 8, false, true, 0, 0, false, 3000 );
-
- // Setup maximum payload lenght of the radio driver
- Radio.SetMaxPayloadLength( MODEM_LORA, txConfig->PktLen );
- // Get the time-on-air of the next tx frame
- *txTimeOnAir = Radio.TimeOnAir( MODEM_LORA, txConfig->PktLen );
- *txPower = txPowerLimited;
-
- return true;
-}
-
-uint8_t RegionUS915HybridLinkAdrReq( LinkAdrReqParams_t* linkAdrReq, int8_t* drOut, int8_t* txPowOut, uint8_t* nbRepOut, uint8_t* nbBytesParsed )
-{
- uint8_t status = 0x07;
- RegionCommonLinkAdrParams_t linkAdrParams;
- uint8_t nextIndex = 0;
- uint8_t bytesProcessed = 0;
- uint16_t channelsMask[6] = { 0, 0, 0, 0, 0, 0 };
- GetPhyParams_t getPhy;
- PhyParam_t phyParam;
- RegionCommonLinkAdrReqVerifyParams_t linkAdrVerifyParams;
-
- // Initialize local copy of channels mask
- RegionCommonChanMaskCopy( channelsMask, ChannelsMask, 6 );
-
- while( bytesProcessed < linkAdrReq->PayloadSize )
- {
- nextIndex = RegionCommonParseLinkAdrReq( &( linkAdrReq->Payload[bytesProcessed] ), &linkAdrParams );
-
- if( nextIndex == 0 )
- break; // break loop, since no more request has been found
-
- // Update bytes processed
- bytesProcessed += nextIndex;
-
- // Revert status, as we only check the last ADR request for the channel mask KO
- status = 0x07;
-
- if( linkAdrParams.ChMaskCtrl == 6 )
- {
- // Enable all 125 kHz channels
- channelsMask[0] = 0xFFFF;
- channelsMask[1] = 0xFFFF;
- channelsMask[2] = 0xFFFF;
- channelsMask[3] = 0xFFFF;
- // Apply chMask to channels 64 to 71
- channelsMask[4] = linkAdrParams.ChMask;
- }
- else if( linkAdrParams.ChMaskCtrl == 7 )
- {
- // Disable all 125 kHz channels
- channelsMask[0] = 0x0000;
- channelsMask[1] = 0x0000;
- channelsMask[2] = 0x0000;
- channelsMask[3] = 0x0000;
- // Apply chMask to channels 64 to 71
- channelsMask[4] = linkAdrParams.ChMask;
- }
- else if( linkAdrParams.ChMaskCtrl == 5 )
- {
- // RFU
- status &= 0xFE; // Channel mask KO
- }
- else
- {
- channelsMask[linkAdrParams.ChMaskCtrl] = linkAdrParams.ChMask;
- }
- }
-
- // FCC 15.247 paragraph F mandates to hop on at least 2 125 kHz channels
- if( ( linkAdrParams.Datarate < DR_4 ) && ( RegionCommonCountChannels( channelsMask, 0, 4 ) < 2 ) )
- {
- status &= 0xFE; // Channel mask KO
- }
-
- if( ValidateChannelsMask( channelsMask ) == false )
- {
- status &= 0xFE; // Channel mask KO
- }
-
- // Get the minimum possible datarate
- getPhy.Attribute = PHY_MIN_TX_DR;
- getPhy.UplinkDwellTime = linkAdrReq->UplinkDwellTime;
- phyParam = RegionUS915HybridGetPhyParam( &getPhy );
-
- linkAdrVerifyParams.Status = status;
- linkAdrVerifyParams.AdrEnabled = linkAdrReq->AdrEnabled;
- linkAdrVerifyParams.Datarate = linkAdrParams.Datarate;
- linkAdrVerifyParams.TxPower = linkAdrParams.TxPower;
- linkAdrVerifyParams.NbRep = linkAdrParams.NbRep;
- linkAdrVerifyParams.CurrentDatarate = linkAdrReq->CurrentDatarate;
- linkAdrVerifyParams.CurrentTxPower = linkAdrReq->CurrentTxPower;
- linkAdrVerifyParams.CurrentNbRep = linkAdrReq->CurrentNbRep;
- linkAdrVerifyParams.NbChannels = US915_HYBRID_MAX_NB_CHANNELS;
- linkAdrVerifyParams.ChannelsMask = channelsMask;
- linkAdrVerifyParams.MinDatarate = ( int8_t )phyParam.Value;
- linkAdrVerifyParams.MaxDatarate = US915_HYBRID_TX_MAX_DATARATE;
- linkAdrVerifyParams.Channels = Channels;
- linkAdrVerifyParams.MinTxPower = US915_HYBRID_MIN_TX_POWER;
- linkAdrVerifyParams.MaxTxPower = US915_HYBRID_MAX_TX_POWER;
-
- // Verify the parameters and update, if necessary
- status = RegionCommonLinkAdrReqVerifyParams( &linkAdrVerifyParams, &linkAdrParams.Datarate, &linkAdrParams.TxPower, &linkAdrParams.NbRep );
-
- // Update channelsMask if everything is correct
- if( status == 0x07 )
- {
- // Copy Mask
- RegionCommonChanMaskCopy( ChannelsMask, channelsMask, 6 );
-
- ChannelsMaskRemaining[0] &= ChannelsMask[0];
- ChannelsMaskRemaining[1] &= ChannelsMask[1];
- ChannelsMaskRemaining[2] &= ChannelsMask[2];
- ChannelsMaskRemaining[3] &= ChannelsMask[3];
- ChannelsMaskRemaining[4] = ChannelsMask[4];
- ChannelsMaskRemaining[5] = ChannelsMask[5];
- }
-
- // Update status variables
- *drOut = linkAdrParams.Datarate;
- *txPowOut = linkAdrParams.TxPower;
- *nbRepOut = linkAdrParams.NbRep;
- *nbBytesParsed = bytesProcessed;
-
- return status;
-}
-
-uint8_t RegionUS915HybridRxParamSetupReq( RxParamSetupReqParams_t* rxParamSetupReq )
-{
- uint8_t status = 0x07;
- uint32_t freq = rxParamSetupReq->Frequency;
-
- // Verify radio frequency
- if( ( Radio.CheckRfFrequency( freq ) == false ) ||
- ( freq < US915_HYBRID_FIRST_RX1_CHANNEL ) ||
- ( freq > US915_HYBRID_LAST_RX1_CHANNEL ) ||
- ( ( ( freq - ( uint32_t ) US915_HYBRID_FIRST_RX1_CHANNEL ) % ( uint32_t ) US915_HYBRID_STEPWIDTH_RX1_CHANNEL ) != 0 ) )
- {
- status &= 0xFE; // Channel frequency KO
- }
-
- // Verify datarate
- if( RegionCommonValueInRange( rxParamSetupReq->Datarate, US915_HYBRID_RX_MIN_DATARATE, US915_HYBRID_RX_MAX_DATARATE ) == false )
- {
- status &= 0xFD; // Datarate KO
- }
- if( ( RegionCommonValueInRange( rxParamSetupReq->Datarate, DR_5, DR_7 ) == true ) ||
- ( rxParamSetupReq->Datarate > DR_13 ) )
- {
- status &= 0xFD; // Datarate KO
- }
-
- // Verify datarate offset
- if( RegionCommonValueInRange( rxParamSetupReq->DrOffset, US915_HYBRID_MIN_RX1_DR_OFFSET, US915_HYBRID_MAX_RX1_DR_OFFSET ) == false )
- {
- status &= 0xFB; // Rx1DrOffset range KO
- }
-
- return status;
-}
-
-uint8_t RegionUS915HybridNewChannelReq( NewChannelReqParams_t* newChannelReq )
-{
- // Datarate and frequency KO
- return 0;
-}
-
-int8_t RegionUS915HybridTxParamSetupReq( TxParamSetupReqParams_t* txParamSetupReq )
-{
- return -1;
-}
-
-uint8_t RegionUS915HybridDlChannelReq( DlChannelReqParams_t* dlChannelReq )
-{
- return 0;
-}
-
-int8_t RegionUS915HybridAlternateDr( AlternateDrParams_t* alternateDr )
-{
- int8_t datarate = 0;
-
- // Re-enable 500 kHz default channels
- ReenableChannels( ChannelsMask[4], ChannelsMask );
-
- if( ( alternateDr->NbTrials & 0x01 ) == 0x01 )
- {
- datarate = DR_4;
- }
- else
- {
- datarate = DR_0;
- }
- return datarate;
-}
-
-void RegionUS915HybridCalcBackOff( CalcBackOffParams_t* calcBackOff )
-{
- RegionCommonCalcBackOffParams_t calcBackOffParams;
-
- calcBackOffParams.Channels = Channels;
- calcBackOffParams.Bands = Bands;
- calcBackOffParams.LastTxIsJoinRequest = calcBackOff->LastTxIsJoinRequest;
- calcBackOffParams.Joined = calcBackOff->Joined;
- calcBackOffParams.DutyCycleEnabled = calcBackOff->DutyCycleEnabled;
- calcBackOffParams.Channel = calcBackOff->Channel;
- calcBackOffParams.ElapsedTime = calcBackOff->ElapsedTime;
- calcBackOffParams.TxTimeOnAir = calcBackOff->TxTimeOnAir;
-
- RegionCommonCalcBackOff( &calcBackOffParams );
-}
-
-bool RegionUS915HybridNextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff )
-{
- uint8_t nbEnabledChannels = 0;
- uint8_t delayTx = 0;
- uint8_t enabledChannels[US915_HYBRID_MAX_NB_CHANNELS] = { 0 };
- TimerTime_t nextTxDelay = 0;
-
- // Count 125kHz channels
- if( RegionCommonCountChannels( ChannelsMaskRemaining, 0, 4 ) == 0 )
- { // Reactivate default channels
- RegionCommonChanMaskCopy( ChannelsMaskRemaining, ChannelsMask, 4 );
- }
- // Check other channels
- if( nextChanParams->Datarate >= DR_4 )
- {
- if( ( ChannelsMaskRemaining[4] & 0x00FF ) == 0 )
- {
- ChannelsMaskRemaining[4] = ChannelsMask[4];
- }
- }
-
- if( nextChanParams->AggrTimeOff <= TimerGetElapsedTime( nextChanParams->LastAggrTx ) )
- {
- // Reset Aggregated time off
- *aggregatedTimeOff = 0;
-
- // Update bands Time OFF
- nextTxDelay = RegionCommonUpdateBandTimeOff( nextChanParams->Joined, nextChanParams->DutyCycleEnabled, Bands, US915_HYBRID_MAX_NB_BANDS );
-
- // Search how many channels are enabled
- nbEnabledChannels = CountNbOfEnabledChannels( nextChanParams->Datarate,
- ChannelsMaskRemaining, Channels,
- Bands, enabledChannels, &delayTx );
- }
- else
- {
- delayTx++;
- nextTxDelay = nextChanParams->AggrTimeOff - TimerGetElapsedTime( nextChanParams->LastAggrTx );
- }
-
- if( nbEnabledChannels > 0 )
- {
- // We found a valid channel
- *channel = enabledChannels[randr( 0, nbEnabledChannels - 1 )];
- // Disable the channel in the mask
- RegionCommonChanDisable( ChannelsMaskRemaining, *channel, US915_HYBRID_MAX_NB_CHANNELS - 8 );
-
- *time = 0;
- return true;
- }
- else
- {
- if( delayTx > 0 )
- {
- // Delay transmission due to AggregatedTimeOff or to a band time off
- *time = nextTxDelay;
- return true;
- }
- // Datarate not supported by any channel
- *time = 0;
- return false;
- }
-}
-
-LoRaMacStatus_t RegionUS915HybridChannelAdd( ChannelAddParams_t* channelAdd )
-{
- return LORAMAC_STATUS_PARAMETER_INVALID;
-}
-
-LoRaMacStatus_t RegionUS915HybridChannelManualAdd( ChannelAddParams_t* channelAdd )
-{
- uint8_t band = 0;
- bool drInvalid = false;
- bool freqInvalid = false;
- uint8_t id = channelAdd->ChannelId;
-
- if( id >= US915_HYBRID_MAX_NB_CHANNELS )
- {
- return LORAMAC_STATUS_PARAMETER_INVALID;
- }
-
- // Validate the datarate range for min: must be DR_0
- if( channelAdd->NewChannel->DrRange.Fields.Min > DR_0 )
- {
- drInvalid = true;
- }
- // Validate the datarate range for max: must be <= TX_MAX_DATARATE
- if( channelAdd->NewChannel->DrRange.Fields.Max != US915_HYBRID_TX_MAX_DATARATE )
- {
- drInvalid = true;
- }
-
- // Check frequency
- if( ( channelAdd->NewChannel->Frequency < 902000000 ) || ( channelAdd->NewChannel->Frequency > 928000000 ) )
- {
- freqInvalid = true;
- }
-
- // Check status
- if( ( drInvalid == true ) && ( freqInvalid == true ) )
- {
- return LORAMAC_STATUS_FREQ_AND_DR_INVALID;
- }
- if( drInvalid == true )
- {
- return LORAMAC_STATUS_DATARATE_INVALID;
- }
- if( freqInvalid == true )
- {
- return LORAMAC_STATUS_FREQUENCY_INVALID;
- }
-
- memcpy( &(Channels[id]), channelAdd->NewChannel, sizeof( Channels[id] ) );
- Channels[id].Band = band;
- ChannelsMask[ (id / 16) ] |= (1 << (id % 16));
- // activate the channel in the remaining ones
- ChannelsMaskRemaining[id / 16] |= ChannelsMask[id / 16];
-
- return LORAMAC_STATUS_OK;
-}
-
-bool RegionUS915HybridChannelsRemove( ChannelRemoveParams_t* channelRemove )
-{
- return false;
-}
-
-bool RegionUS915HybridChannelsManualRemove( ChannelRemoveParams_t* channelRemove )
-{
- uint8_t id = channelRemove->ChannelId;
-
- // Disable the channel as it doesn't exist anymore
- if ( !RegionCommonChanDisable( ChannelsMask, id, US915_HYBRID_MAX_NB_CHANNELS ) ) {
- return false;
- }
-
- // Remove the channel from the list of channels
- Channels[id] = ( ChannelParams_t ){ 0, 0, { 0 }, 0 };
-
- // Set the channel mask remaining accordingly
- ChannelsMaskRemaining[id / 16] &= ChannelsMask[id / 16];
-
- return true;
-}
-
-void RegionUS915HybridSetContinuousWave( ContinuousWaveParams_t* continuousWave )
-{
- int8_t txPowerLimited = LimitTxPower( continuousWave->TxPower, Bands[Channels[continuousWave->Channel].Band].TxMaxPower, continuousWave->Datarate, ChannelsMask );
- int8_t phyTxPower = 0;
- uint32_t frequency = Channels[continuousWave->Channel].Frequency;
-
- // Calculate physical TX power
- phyTxPower = RegionCommonComputeTxPower( txPowerLimited, US915_HYBRID_DEFAULT_MAX_ERP, 0 );
-
- Radio.SetTxContinuousWave( frequency, phyTxPower, continuousWave->Timeout );
-}
-
-uint8_t RegionUS915HybridApplyDrOffset( uint8_t downlinkDwellTime, int8_t dr, int8_t drOffset )
-{
- int8_t datarate = DatarateOffsetsUS915_HYBRID[dr][drOffset];
-
- if( datarate < 0 )
- {
- datarate = DR_0;
- }
- return datarate;
-}
-
-bool RegionUS915HybridGetChannels( ChannelParams_t** channels, uint32_t *size )
-{
- *channels = Channels;
- *size = sizeof(Channels);
- return true;
-}
-
-bool RegionUS915HybridGetChannelMask( uint16_t** channelmask, uint32_t *size )
-{
- *channelmask = ChannelsMask;
- *size = sizeof(ChannelsMask);
- return true;
-}
-
-bool RegionUS915HybridGetChannelMaskRemaining( uint16_t** channelmask, uint32_t *size )
-{
- *channelmask = ChannelsMaskRemaining;
- *size = sizeof(ChannelsMaskRemaining);
- return true;
-}
-
-bool RegionUS915HybridForceJoinDataRate( int8_t joinDr, AlternateDrParams_t* alternateDr )
-{
- if (joinDr == DR_4) {
- alternateDr->NbTrials = 1;
- } else {
- alternateDr->NbTrials = 0;
- }
- return true;
-}
diff --git a/lib/lora/mac/region/RegionUS915-Hybrid.h b/lib/lora/mac/region/RegionUS915-Hybrid.h
deleted file mode 100644
index e6d57f8b35..0000000000
--- a/lib/lora/mac/region/RegionUS915-Hybrid.h
+++ /dev/null
@@ -1,458 +0,0 @@
-/*!
- * \file RegionUS915Hybrid-Hybrid.h
- *
- * \brief Region definition for US915
- *
- * \copyright Revised BSD License, see section \ref LICENSE.
- *
- * \code
- * ______ _
- * / _____) _ | |
- * ( (____ _____ ____ _| |_ _____ ____| |__
- * \____ \| ___ | (_ _) ___ |/ ___) _ \
- * _____) ) ____| | | || |_| ____( (___| | | |
- * (______/|_____)_|_|_| \__)_____)\____)_| |_|
- * (C)2013 Semtech
- *
- * ___ _____ _ ___ _ _____ ___ ___ ___ ___
- * / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
- * \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
- * |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
- * embedded.connectivity.solutions===============
- *
- * \endcode
- *
- * \author Miguel Luis ( Semtech )
- *
- * \author Gregory Cristian ( Semtech )
- *
- * \author Daniel Jaeckle ( STACKFORCE )
- *
- * \defgroup REGIONUS915HYB Region US915 in hybrid mode
- * This is a hybrid implementation for US915, supporting 16 uplink channels only.
- * \{
- */
-#ifndef __REGION_US915_HYBRID_H__
-#define __REGION_US915_HYBRID_H__
-
-/*!
- * LoRaMac maximum number of channels
- */
-#define US915_HYBRID_MAX_NB_CHANNELS 72
-
-/*!
- * Minimal datarate that can be used by the node
- */
-#define US915_HYBRID_TX_MIN_DATARATE DR_0
-
-/*!
- * Maximal datarate that can be used by the node
- */
-#define US915_HYBRID_TX_MAX_DATARATE DR_4
-
-/*!
- * Minimal datarate that can be used by the node
- */
-#define US915_HYBRID_RX_MIN_DATARATE DR_8
-
-/*!
- * Maximal datarate that can be used by the node
- */
-#define US915_HYBRID_RX_MAX_DATARATE DR_13
-
-/*!
- * Default datarate used by the node
- */
-#define US915_HYBRID_DEFAULT_DATARATE DR_0
-
-/*!
- * Minimal Rx1 receive datarate offset
- */
-#define US915_HYBRID_MIN_RX1_DR_OFFSET 0
-
-/*!
- * Maximal Rx1 receive datarate offset
- */
-#define US915_HYBRID_MAX_RX1_DR_OFFSET 3
-
-/*!
- * Default Rx1 receive datarate offset
- */
-#define US915_HYBRID_DEFAULT_RX1_DR_OFFSET 0
-
-/*!
- * Minimal Tx output power that can be used by the node
- */
-#define US915_HYBRID_MIN_TX_POWER TX_POWER_10
-
-/*!
- * Maximal Tx output power that can be used by the node
- */
-#define US915_HYBRID_MAX_TX_POWER TX_POWER_0
-
-/*!
- * Default Tx output power used by the node
- */
-#define US915_HYBRID_DEFAULT_TX_POWER TX_POWER_0
-
-/*!
- * Default Max ERP
- */
-#define US915_HYBRID_DEFAULT_MAX_ERP 30.0f
-
-/*!
- * ADR Ack limit
- */
-#define US915_HYBRID_ADR_ACK_LIMIT 64
-
-/*!
- * ADR Ack delay
- */
-#define US915_HYBRID_ADR_ACK_DELAY 32
-
-/*!
- * Enabled or disabled the duty cycle
- */
-#define US915_HYBRID_DUTY_CYCLE_ENABLED 0
-
-/*!
- * Maximum RX window duration
- */
-#define US915_HYBRID_MAX_RX_WINDOW 3000
-
-/*!
- * Receive delay 1
- */
-#define US915_HYBRID_RECEIVE_DELAY1 1000
-
-/*!
- * Receive delay 2
- */
-#define US915_HYBRID_RECEIVE_DELAY2 2000
-
-/*!
- * Join accept delay 1
- */
-#define US915_HYBRID_JOIN_ACCEPT_DELAY1 5000
-
-/*!
- * Join accept delay 2
- */
-#define US915_HYBRID_JOIN_ACCEPT_DELAY2 6000
-
-/*!
- * Maximum frame counter gap
- */
-#define US915_HYBRID_MAX_FCNT_GAP 16384
-
-/*!
- * Ack timeout
- */
-#define US915_HYBRID_ACKTIMEOUT 2000
-
-/*!
- * Random ack timeout limits
- */
-#define US915_HYBRID_ACK_TIMEOUT_RND 1000
-
-/*!
- * Second reception window channel frequency definition.
- */
-#define US915_HYBRID_RX_WND_2_FREQ 923300000
-
-/*!
- * Second reception window channel datarate definition.
- */
-#define US915_HYBRID_RX_WND_2_DR DR_8
-
-/*!
- * LoRaMac maximum number of bands
- */
-#define US915_HYBRID_MAX_NB_BANDS 1
-
-/*!
- * Band 0 definition
- * { DutyCycle, TxMaxPower, LastTxDoneTime, TimeOff }
- */
-#define US915_HYBRID_BAND0 { 1, US915_HYBRID_MAX_TX_POWER, 0, 0 } // 100.0 %
-
-/*!
- * Defines the first channel for RX window 1 for US band
- */
-#define US915_HYBRID_FIRST_RX1_CHANNEL ( (uint32_t) 923300000 )
-
-/*!
- * Defines the last channel for RX window 1 for US band
- */
-#define US915_HYBRID_LAST_RX1_CHANNEL ( (uint32_t) 927500000 )
-
-/*!
- * Defines the step width of the channels for RX window 1
- */
-#define US915_HYBRID_STEPWIDTH_RX1_CHANNEL ( (uint32_t) 600000 )
-
-/*!
- * Data rates table definition
- */
-static const uint8_t DataratesUS915_HYBRID[] = { 10, 9, 8, 7, 8, 0, 0, 0, 12, 11, 10, 9, 8, 7, 0, 0 };
-
-/*!
- * Bandwidths table definition in Hz
- */
-static const uint32_t BandwidthsUS915_HYBRID[] = { 125000, 125000, 125000, 125000, 500000, 0, 0, 0, 500000, 500000, 500000, 500000, 500000, 500000, 0, 0 };
-
-/*!
- * Up/Down link data rates offset definition
- */
-static const int8_t DatarateOffsetsUS915_HYBRID[5][4] =
-{
- { DR_10, DR_9 , DR_8 , DR_8 }, // DR_0
- { DR_11, DR_10, DR_9 , DR_8 }, // DR_1
- { DR_12, DR_11, DR_10, DR_9 }, // DR_2
- { DR_13, DR_12, DR_11, DR_10 }, // DR_3
- { DR_13, DR_13, DR_12, DR_11 }, // DR_4
-};
-
-/*!
- * Maximum payload with respect to the datarate index. Cannot operate with repeater.
- */
-static const uint8_t MaxPayloadOfDatarateUS915_HYBRID[] = { 11, 53, 125, 242, 242, 0, 0, 0, 53, 129, 242, 242, 242, 242, 0, 0 };
-
-/*!
- * Maximum payload with respect to the datarate index. Can operate with repeater.
- */
-static const uint8_t MaxPayloadOfDatarateRepeaterUS915_HYBRID[] = { 11, 53, 125, 242, 242, 0, 0, 0, 33, 109, 222, 222, 222, 222, 0, 0 };
-
-/*!
- * \brief The function gets a value of a specific phy attribute.
- *
- * \param [IN] getPhy Pointer to the function parameters.
- *
- * \retval Returns a structure containing the PHY parameter.
- */
-PhyParam_t RegionUS915HybridGetPhyParam( GetPhyParams_t* getPhy );
-
-/*!
- * \brief Updates the last TX done parameters of the current channel.
- *
- * \param [IN] txDone Pointer to the function parameters.
- */
-void RegionUS915HybridSetBandTxDone( SetBandTxDoneParams_t* txDone );
-
-/*!
- * \brief Initializes the channels masks and the channels.
- *
- * \param [IN] type Sets the initialization type.
- */
-void RegionUS915HybridInitDefaults( InitType_t type );
-
-/*!
- * \brief Verifies a parameter.
- *
- * \param [IN] verify Pointer to the function parameters.
- *
- * \param [IN] type Sets the initialization type.
- *
- * \retval Returns true, if the parameter is valid.
- */
-bool RegionUS915HybridVerify( VerifyParams_t* verify, PhyAttribute_t phyAttribute );
-
-/*!
- * \brief The function parses the input buffer and sets up the channels of the
- * CF list.
- *
- * \param [IN] applyCFList Pointer to the function parameters.
- */
-void RegionUS915HybridApplyCFList( ApplyCFListParams_t* applyCFList );
-
-/*!
- * \brief Sets a channels mask.
- *
- * \param [IN] chanMaskSet Pointer to the function parameters.
- *
- * \retval Returns true, if the channels mask could be set.
- */
-bool RegionUS915HybridChanMaskSet( ChanMaskSetParams_t* chanMaskSet );
-
-/*!
- * \brief Calculates the next datarate to set, when ADR is on or off.
- *
- * \param [IN] adrNext Pointer to the function parameters.
- *
- * \param [OUT] drOut The calculated datarate for the next TX.
- *
- * \param [OUT] txPowOut The TX power for the next TX.
- *
- * \param [OUT] adrAckCounter The calculated ADR acknowledgement counter.
- *
- * \retval Returns true, if an ADR request should be performed.
- */
-bool RegionUS915HybridAdrNext( AdrNextParams_t* adrNext, int8_t* drOut, int8_t* txPowOut, uint32_t* adrAckCounter );
-
-/*!
- * Computes the Rx window timeout and offset.
- *
- * \param [IN] datarate Rx window datarate index to be used
- *
- * \param [IN] minRxSymbols Minimum required number of symbols to detect an Rx frame.
- *
- * \param [IN] rxError System maximum timing error of the receiver. In milliseconds
- * The receiver will turn on in a [-rxError : +rxError] ms
- * interval around RxOffset
- *
- * \param [OUT]rxConfigParams Returns updated WindowTimeout and WindowOffset fields.
- */
-void RegionUS915HybridComputeRxWindowParameters( int8_t datarate, uint8_t minRxSymbols, uint32_t rxError, RxConfigParams_t *rxConfigParams );
-
-/*!
- * \brief Configuration of the RX windows.
- *
- * \param [IN] rxConfig Pointer to the function parameters.
- *
- * \param [OUT] datarate The datarate index which was set.
- *
- * \retval Returns true, if the configuration was applied successfully.
- */
-bool RegionUS915HybridRxConfig( RxConfigParams_t* rxConfig, int8_t* datarate );
-
-/*!
- * \brief TX configuration.
- *
- * \param [IN] txConfig Pointer to the function parameters.
- *
- * \param [OUT] txPower The tx power index which was set.
- *
- * \param [OUT] txTimeOnAir The time-on-air of the frame.
- *
- * \retval Returns true, if the configuration was applied successfully.
- */
-bool RegionUS915HybridTxConfig( TxConfigParams_t* txConfig, int8_t* txPower, TimerTime_t* txTimeOnAir );
-
-/*!
- * \brief The function processes a Link ADR Request.
- *
- * \param [IN] linkAdrReq Pointer to the function parameters.
- *
- * \retval Returns the status of the operation, according to the LoRaMAC specification.
- */
-uint8_t RegionUS915HybridLinkAdrReq( LinkAdrReqParams_t* linkAdrReq, int8_t* drOut, int8_t* txPowOut, uint8_t* nbRepOut, uint8_t* nbBytesParsed );
-
-/*!
- * \brief The function processes a RX Parameter Setup Request.
- *
- * \param [IN] rxParamSetupReq Pointer to the function parameters.
- *
- * \retval Returns the status of the operation, according to the LoRaMAC specification.
- */
-uint8_t RegionUS915HybridRxParamSetupReq( RxParamSetupReqParams_t* rxParamSetupReq );
-
-/*!
- * \brief The function processes a Channel Request.
- *
- * \param [IN] newChannelReq Pointer to the function parameters.
- *
- * \retval Returns the status of the operation, according to the LoRaMAC specification.
- */
-uint8_t RegionUS915HybridNewChannelReq( NewChannelReqParams_t* newChannelReq );
-
-/*!
- * \brief The function processes a TX ParamSetup Request.
- *
- * \param [IN] txParamSetupReq Pointer to the function parameters.
- *
- * \retval Returns the status of the operation, according to the LoRaMAC specification.
- * Returns -1, if the functionality is not implemented. In this case, the end node
- * shall not process the command.
- */
-int8_t RegionUS915HybridTxParamSetupReq( TxParamSetupReqParams_t* txParamSetupReq );
-
-/*!
- * \brief The function processes a DlChannel Request.
- *
- * \param [IN] dlChannelReq Pointer to the function parameters.
- *
- * \retval Returns the status of the operation, according to the LoRaMAC specification.
- */
-uint8_t RegionUS915HybridDlChannelReq( DlChannelReqParams_t* dlChannelReq );
-
-/*!
- * \brief Alternates the datarate of the channel for the join request.
- *
- * \param [IN] alternateDr Pointer to the function parameters.
- *
- * \retval Datarate to apply.
- */
-int8_t RegionUS915HybridAlternateDr( AlternateDrParams_t* alternateDr );
-
-/*!
- * \brief Calculates the back-off time.
- *
- * \param [IN] calcBackOff Pointer to the function parameters.
- */
-void RegionUS915HybridCalcBackOff( CalcBackOffParams_t* calcBackOff );
-
-/*!
- * \brief Searches and set the next random available channel
- *
- * \param [OUT] channel Next channel to use for TX.
- *
- * \param [OUT] time Time to wait for the next transmission according to the duty
- * cycle.
- *
- * \param [OUT] aggregatedTimeOff Updates the aggregated time off.
- *
- * \retval Function status [1: OK, 0: Unable to find a channel on the current datarate]
- */
-bool RegionUS915HybridNextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff );
-
-/*!
- * \brief Adds a channel.
- *
- * \param [IN] channelAdd Pointer to the function parameters.
- *
- * \retval Status of the operation.
- */
-LoRaMacStatus_t RegionUS915HybridChannelAdd( ChannelAddParams_t* channelAdd );
-LoRaMacStatus_t RegionUS915HybridChannelManualAdd( ChannelAddParams_t* channelAdd );
-
-/*!
- * \brief Removes a channel.
- *
- * \param [IN] channelRemove Pointer to the function parameters.
- *
- * \retval Returns true, if the channel was removed successfully.
- */
-bool RegionUS915HybridChannelsRemove( ChannelRemoveParams_t* channelRemove );
-bool RegionUS915HybridChannelsManualRemove( ChannelRemoveParams_t* channelRemove );
-
-/*!
- * \brief Sets the radio into continuous wave mode.
- *
- * \param [IN] continuousWave Pointer to the function parameters.
- */
-void RegionUS915HybridSetContinuousWave( ContinuousWaveParams_t* continuousWave );
-
-/*!
- * \brief Computes new datarate according to the given offset
- *
- * \param [IN] downlinkDwellTime Downlink dwell time configuration. 0: No limit, 1: 400ms
- *
- * \param [IN] dr Current datarate
- *
- * \param [IN] drOffset Offset to be applied
- *
- * \retval newDr Computed datarate.
- */
-uint8_t RegionUS915HybridApplyDrOffset( uint8_t downlinkDwellTime, int8_t dr, int8_t drOffset );
-
-bool RegionUS915HybridGetChannels( ChannelParams_t** channels, uint32_t *size );
-
-bool RegionUS915HybridGetChannelMask( uint16_t** channelmask, uint32_t *size );
-
-bool RegionUS915HybridGetChannelMaskRemaining( uint16_t** channelmask, uint32_t *size );
-
-bool RegionUS915HybridForceJoinDataRate( int8_t joinDr, AlternateDrParams_t* alternateDr );
-
-/*! \} defgroup REGIONUS915HYB */
-
-#endif // __REGION_US915_HYBRID_H__
diff --git a/lib/lora/mac/region/RegionUS915.c b/lib/lora/mac/region/RegionUS915.c
index aa5b8bd91e..3465903a1c 100644
--- a/lib/lora/mac/region/RegionUS915.c
+++ b/lib/lora/mac/region/RegionUS915.c
@@ -1,68 +1,85 @@
-/*
- / _____) _ | |
-( (____ _____ ____ _| |_ _____ ____| |__
- \____ \| ___ | (_ _) ___ |/ ___) _ \
- _____) ) ____| | | || |_| ____( (___| | | |
-(______/|_____)_|_|_| \__)_____)\____)_| |_|
- (C)2013 Semtech
- ___ _____ _ ___ _ _____ ___ ___ ___ ___
-/ __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
-\__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
-|___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
-embedded.connectivity.solutions===============
-
-Description: LoRa MAC region US915 implementation
-
-License: Revised BSD License, see LICENSE.TXT file include in the project
-
-Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jaeckle ( STACKFORCE )
+/*!
+ * \file RegionUS915.c
+ *
+ * \brief Region implementation for US915
+ *
+ * \copyright Revised BSD License, see section \ref LICENSE.
+ *
+ * \code
+ * ______ _
+ * / _____) _ | |
+ * ( (____ _____ ____ _| |_ _____ ____| |__
+ * \____ \| ___ | (_ _) ___ |/ ___) _ \
+ * _____) ) ____| | | || |_| ____( (___| | | |
+ * (______/|_____)_|_|_| \__)_____)\____)_| |_|
+ * (C)2013-2017 Semtech
+ *
+ * ___ _____ _ ___ _ _____ ___ ___ ___ ___
+ * / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
+ * \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
+ * |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
+ * embedded.connectivity.solutions===============
+ *
+ * \endcode
+ *
+ * \author Miguel Luis ( Semtech )
+ *
+ * \author Gregory Cristian ( Semtech )
+ *
+ * \author Daniel Jaeckle ( STACKFORCE )
*/
-#include
#include
-#include
-#include
-
-#include "board.h"
-#include "lora/mac/LoRaMac.h"
-#include "esp_attr.h"
#include "utilities.h"
-#include "Region.h"
#include "RegionCommon.h"
#include "RegionUS915.h"
// Definitions
#define CHANNELS_MASK_SIZE 6
-// Global attributes
-/*!
- * LoRaMAC channels
- */
-static ChannelParams_t Channels[US915_MAX_NB_CHANNELS];
+// A mask to select only valid 500KHz channels
+#define CHANNELS_MASK_500KHZ_MASK 0x00FF
/*!
- * LoRaMac bands
+ * Region specific context
*/
-static Band_t Bands[US915_MAX_NB_BANDS] =
+typedef struct sRegionUS915NvmCtx
{
- US915_BAND0
-};
-
-/*!
- * LoRaMac channels mask
- */
-static uint16_t ChannelsMask[CHANNELS_MASK_SIZE];
-
-/*!
- * LoRaMac channels remaining
- */
-static uint16_t ChannelsMaskRemaining[CHANNELS_MASK_SIZE];
+ /*!
+ * LoRaMAC channels
+ */
+ ChannelParams_t Channels[ US915_MAX_NB_CHANNELS ];
+ /*!
+ * LoRaMac bands
+ */
+ Band_t Bands[ US915_MAX_NB_BANDS ];
+ /*!
+ * LoRaMac channels mask
+ */
+ uint16_t ChannelsMask[ CHANNELS_MASK_SIZE ];
+ /*!
+ * LoRaMac channels remaining
+ */
+ uint16_t ChannelsMaskRemaining[CHANNELS_MASK_SIZE];
+ /*!
+ * LoRaMac channels default mask
+ */
+ uint16_t ChannelsDefaultMask[ CHANNELS_MASK_SIZE ];
+ /*!
+ * Index of current in use 8 bit group (0: bit 0 - 7, 1: bit 8 - 15, ..., 7: bit 56 - 63)
+ */
+ uint8_t JoinChannelGroupsCurrentIndex;
+ /*!
+ * Counter of join trials needed to alternate between DR0 and DR4, see \ref RegionUS915AlternateDr
+ */
+ uint8_t JoinTrialsCounter;
+}RegionUS915NvmCtx_t;
-/*!
- * LoRaMac channels default mask
+/*
+ * Non-volatile module context.
*/
-static uint16_t ChannelsDefaultMask[CHANNELS_MASK_SIZE];
+static RegionUS915NvmCtx_t NvmCtx;
// Static functions
static int8_t GetNextLowerTxDr( int8_t dr, int8_t minDr )
@@ -80,6 +97,106 @@ static int8_t GetNextLowerTxDr( int8_t dr, int8_t minDr )
return nextLowerDr;
}
+/*!
+ * \brief Searches for available 125 kHz channels in the given channel mask.
+ *
+ * \param [IN] channelMaskRemaining The remaining channel mask.
+ *
+ * \param [OUT] findAvailableChannelsIndex List containing the indexes of all available 125 kHz channels.
+ *
+ * \param [OUT] availableChannels Number of available 125 kHz channels.
+ *
+ * \retval Status
+ */
+static LoRaMacStatus_t FindAvailable125kHzChannels( uint8_t* findAvailableChannelsIndex, uint16_t channelMaskRemaining, uint8_t* availableChannels )
+{
+ // Nullpointer check
+ if( findAvailableChannelsIndex == NULL || availableChannels == NULL )
+ {
+ return LORAMAC_STATUS_PARAMETER_INVALID;
+ }
+
+ // Initialize counter
+ *availableChannels = 0;
+ for( uint8_t i = 0; i < 8; i++ )
+ {
+ // Find available channels
+ if( ( channelMaskRemaining & ( 1 << i ) ) != 0 )
+ {
+ // Save available channel index
+ findAvailableChannelsIndex[*availableChannels] = i;
+ // Increment counter of available channels if the current channel is available
+ ( *availableChannels )++;
+ }
+ }
+
+ return LORAMAC_STATUS_OK;
+}
+
+/*!
+ * \brief Computes the next 125kHz channel used for join requests.
+ *
+ * \param [OUT] newChannelIndex Index of available channel.
+ *
+ * \retval Status
+ */
+static LoRaMacStatus_t ComputeNext125kHzJoinChannel( uint8_t* newChannelIndex )
+{
+ uint8_t currentChannelsMaskRemainingIndex;
+ uint16_t channelMaskRemaining;
+ uint8_t findAvailableChannelsIndex[8] = { 0 };
+ uint8_t availableChannels = 0;
+ uint8_t startIndex = NvmCtx.JoinChannelGroupsCurrentIndex;
+
+ // Null pointer check
+ if( newChannelIndex == NULL )
+ {
+ return LORAMAC_STATUS_PARAMETER_INVALID;
+ }
+
+ do {
+ // Current ChannelMaskRemaining, two groups per channel mask. For example Group 0 and 1 (8 bit) are ChannelMaskRemaining 0 (16 bit), etc.
+ currentChannelsMaskRemainingIndex = (uint8_t) startIndex / 2;
+
+ // For even numbers we need the 8 LSBs and for uneven the 8 MSBs
+ if( ( startIndex % 2 ) == 0 )
+ {
+ channelMaskRemaining = ( NvmCtx.ChannelsMaskRemaining[currentChannelsMaskRemainingIndex] & 0x00FF );
+ }
+ else
+ {
+ channelMaskRemaining = ( ( NvmCtx.ChannelsMaskRemaining[currentChannelsMaskRemainingIndex] >> 8 ) & 0x00FF );
+ }
+
+
+ if( FindAvailable125kHzChannels( findAvailableChannelsIndex, channelMaskRemaining, &availableChannels ) == LORAMAC_STATUS_PARAMETER_INVALID )
+ {
+ return LORAMAC_STATUS_PARAMETER_INVALID;
+ }
+
+ if ( availableChannels > 0 )
+ {
+ // Choose randomly a free channel 125kHz
+ *newChannelIndex = ( startIndex * 8 ) + findAvailableChannelsIndex[randr( 0, ( availableChannels - 1 ) )];
+ }
+
+ // Increment start index
+ startIndex++;
+ if ( startIndex > 7 )
+ {
+ startIndex = 0;
+ }
+ } while( ( availableChannels == 0 ) && ( startIndex != NvmCtx.JoinChannelGroupsCurrentIndex ) );
+
+ if ( availableChannels > 0 )
+ {
+ NvmCtx.JoinChannelGroupsCurrentIndex = startIndex;
+ return LORAMAC_STATUS_OK;
+ }
+
+ return LORAMAC_STATUS_PARAMETER_INVALID;
+}
+
static uint32_t GetBandwidth( uint32_t drIndex )
{
switch( BandwidthsUS915[drIndex] )
@@ -115,6 +232,30 @@ static int8_t LimitTxPower( int8_t txPower, int8_t maxBandTxPower, int8_t datara
return txPowerResult;
}
+static bool VerifyRfFreq( uint32_t freq )
+{
+ // Check radio driver support
+ if( Radio.CheckRfFrequency( freq ) == false )
+ {
+ return false;
+ }
+
+ // Rx frequencies
+ if( ( freq < US915_FIRST_RX1_CHANNEL ) ||
+ ( freq > US915_LAST_RX1_CHANNEL ) ||
+ ( ( ( freq - ( uint32_t ) US915_FIRST_RX1_CHANNEL ) % ( uint32_t ) US915_STEPWIDTH_RX1_CHANNEL ) != 0 ) )
+ {
+ return false;
+ }
+
+ // Test for frequency range - take RX and TX freqencies into account
+ if( ( freq < 902300000 ) || ( freq > 927500000 ) )
+ {
+ return false;
+ }
+ return true;
+}
+
static uint8_t CountNbOfEnabledChannels( uint8_t datarate, uint16_t* channelsMask, ChannelParams_t* channels, Band_t* bands, uint8_t* enabledChannels, uint8_t* delayTx )
{
uint8_t nbEnabledChannels = 0;
@@ -175,11 +316,26 @@ PhyParam_t RegionUS915GetPhyParam( GetPhyParams_t* getPhy )
phyParam.Value = GetNextLowerTxDr( getPhy->Datarate, US915_TX_MIN_DATARATE );
break;
}
+ case PHY_MAX_TX_POWER:
+ {
+ phyParam.Value = US915_MAX_TX_POWER;
+ break;
+ }
case PHY_DEF_TX_POWER:
{
phyParam.Value = US915_DEFAULT_TX_POWER;
break;
}
+ case PHY_DEF_ADR_ACK_LIMIT:
+ {
+ phyParam.Value = US915_ADR_ACK_LIMIT;
+ break;
+ }
+ case PHY_DEF_ADR_ACK_DELAY:
+ {
+ phyParam.Value = US915_ADR_ACK_DELAY;
+ break;
+ }
case PHY_MAX_PAYLOAD:
{
phyParam.Value = MaxPayloadOfDatarateUS915[getPhy->Datarate];
@@ -247,12 +403,12 @@ PhyParam_t RegionUS915GetPhyParam( GetPhyParams_t* getPhy )
}
case PHY_CHANNELS_MASK:
{
- phyParam.ChannelsMask = ChannelsMask;
+ phyParam.ChannelsMask = NvmCtx.ChannelsMask;
break;
}
case PHY_CHANNELS_DEFAULT_MASK:
{
- phyParam.ChannelsMask = ChannelsDefaultMask;
+ phyParam.ChannelsMask = NvmCtx.ChannelsDefaultMask;
break;
}
case PHY_MAX_NB_CHANNELS:
@@ -262,7 +418,7 @@ PhyParam_t RegionUS915GetPhyParam( GetPhyParams_t* getPhy )
}
case PHY_CHANNELS:
{
- phyParam.Channels = Channels;
+ phyParam.Channels = NvmCtx.Channels;
break;
}
case PHY_DEF_UPLINK_DWELL_TIME:
@@ -272,15 +428,45 @@ PhyParam_t RegionUS915GetPhyParam( GetPhyParams_t* getPhy )
break;
}
case PHY_DEF_MAX_EIRP:
+ {
+ phyParam.fValue = US915_DEFAULT_MAX_ERP + 2.15;
+ break;
+ }
case PHY_DEF_ANTENNA_GAIN:
{
phyParam.fValue = 0;
break;
}
- case PHY_NB_JOIN_TRIALS:
- case PHY_DEF_NB_JOIN_TRIALS:
+ case PHY_BEACON_CHANNEL_FREQ:
{
- phyParam.Value = 2;
+ phyParam.Value = US915_BEACON_CHANNEL_FREQ;
+ break;
+ }
+ case PHY_BEACON_FORMAT:
+ {
+ phyParam.BeaconFormat.BeaconSize = US915_BEACON_SIZE;
+ phyParam.BeaconFormat.Rfu1Size = US915_RFU1_SIZE;
+ phyParam.BeaconFormat.Rfu2Size = US915_RFU2_SIZE;
+ break;
+ }
+ case PHY_BEACON_CHANNEL_DR:
+ {
+ phyParam.Value = US915_BEACON_CHANNEL_DR;
+ break;
+ }
+ case PHY_BEACON_CHANNEL_STEPWIDTH:
+ {
+ phyParam.Value = US915_BEACON_CHANNEL_STEPWIDTH;
+ break;
+ }
+ case PHY_BEACON_NB_CHANNELS:
+ {
+ phyParam.Value = US915_BEACON_NB_CHANNELS;
+ break;
+ }
+ case PHY_PING_SLOT_CHANNEL_DR:
+ {
+ phyParam.Value = US915_PING_SLOT_CHANNEL_DR;
break;
}
default:
@@ -292,56 +478,78 @@ PhyParam_t RegionUS915GetPhyParam( GetPhyParams_t* getPhy )
return phyParam;
}
-IRAM_ATTR void RegionUS915SetBandTxDone( SetBandTxDoneParams_t* txDone )
+void RegionUS915SetBandTxDone( SetBandTxDoneParams_t* txDone )
{
- RegionCommonSetBandTxDone( txDone->Joined, &Bands[Channels[txDone->Channel].Band], txDone->LastTxDoneTime );
+ RegionCommonSetBandTxDone( txDone->Joined, &NvmCtx.Bands[NvmCtx.Channels[txDone->Channel].Band], txDone->LastTxDoneTime );
}
-void RegionUS915InitDefaults( InitType_t type )
+void RegionUS915InitDefaults( InitDefaultsParams_t* params )
{
- switch( type )
+ Band_t bands[US915_MAX_NB_BANDS] =
+ {
+ US915_BAND0
+ };
+
+ switch( params->Type )
{
case INIT_TYPE_INIT:
{
+ // Initialize bands
+ memcpy1( ( uint8_t* )NvmCtx.Bands, ( uint8_t* )bands, sizeof( Band_t ) * US915_MAX_NB_BANDS );
+
+ // Initialize 8 bit channel groups index
+ NvmCtx.JoinChannelGroupsCurrentIndex = 0;
+
+ // Initialize the join trials counter
+ NvmCtx.JoinTrialsCounter = 0;
+
// Channels
// 125 kHz channels
for( uint8_t i = 0; i < US915_MAX_NB_CHANNELS - 8; i++ )
{
- Channels[i].Frequency = 902300000 + i * 200000;
- Channels[i].DrRange.Value = ( DR_3 << 4 ) | DR_0;
- Channels[i].Band = 0;
+ NvmCtx.Channels[i].Frequency = 902300000 + i * 200000;
+ NvmCtx.Channels[i].DrRange.Value = ( DR_3 << 4 ) | DR_0;
+ NvmCtx.Channels[i].Band = 0;
}
// 500 kHz channels
for( uint8_t i = US915_MAX_NB_CHANNELS - 8; i < US915_MAX_NB_CHANNELS; i++ )
{
- Channels[i].Frequency = 903000000 + ( i - ( US915_MAX_NB_CHANNELS - 8 ) ) * 1600000;
- Channels[i].DrRange.Value = ( DR_4 << 4 ) | DR_4;
- Channels[i].Band = 0;
+ NvmCtx.Channels[i].Frequency = 903000000 + ( i - ( US915_MAX_NB_CHANNELS - 8 ) ) * 1600000;
+ NvmCtx.Channels[i].DrRange.Value = ( DR_4 << 4 ) | DR_4;
+ NvmCtx.Channels[i].Band = 0;
}
// ChannelsMask
- ChannelsDefaultMask[0] = 0xFFFF;
- ChannelsDefaultMask[1] = 0xFFFF;
- ChannelsDefaultMask[2] = 0xFFFF;
- ChannelsDefaultMask[3] = 0xFFFF;
- ChannelsDefaultMask[4] = 0x00FF;
- ChannelsDefaultMask[5] = 0x0000;
+ NvmCtx.ChannelsDefaultMask[0] = 0xFFFF;
+ NvmCtx.ChannelsDefaultMask[1] = 0xFFFF;
+ NvmCtx.ChannelsDefaultMask[2] = 0xFFFF;
+ NvmCtx.ChannelsDefaultMask[3] = 0xFFFF;
+ NvmCtx.ChannelsDefaultMask[4] = 0x00FF;
+ NvmCtx.ChannelsDefaultMask[5] = 0x0000;
// Copy channels default mask
- RegionCommonChanMaskCopy( ChannelsMask, ChannelsDefaultMask, 6 );
+ RegionCommonChanMaskCopy( NvmCtx.ChannelsMask, NvmCtx.ChannelsDefaultMask, 6 );
// Copy into channels mask remaining
- RegionCommonChanMaskCopy( ChannelsMaskRemaining, ChannelsMask, 6 );
+ RegionCommonChanMaskCopy( NvmCtx.ChannelsMaskRemaining, NvmCtx.ChannelsMask, 6 );
break;
}
- case INIT_TYPE_RESTORE:
+ case INIT_TYPE_RESTORE_CTX:
+ {
+ if( params->NvmCtx != 0 )
+ {
+ memcpy1( (uint8_t*) &NvmCtx, (uint8_t*) params->NvmCtx, sizeof( NvmCtx ) );
+ }
+ break;
+ }
+ case INIT_TYPE_RESTORE_DEFAULT_CHANNELS:
{
// Copy channels default mask
- RegionCommonChanMaskCopy( ChannelsMask, ChannelsDefaultMask, 6 );
+ RegionCommonChanMaskCopy( NvmCtx.ChannelsMask, NvmCtx.ChannelsDefaultMask, 6 );
for( uint8_t i = 0; i < 6; i++ )
{ // Copy-And the channels mask
- ChannelsMaskRemaining[i] &= ChannelsMask[i];
+ NvmCtx.ChannelsMaskRemaining[i] &= NvmCtx.ChannelsMask[i];
}
break;
}
@@ -352,10 +560,20 @@ void RegionUS915InitDefaults( InitType_t type )
}
}
+void* RegionUS915GetNvmCtx( GetNvmCtxParams_t* params )
+{
+ params->nvmCtxSize = sizeof( RegionUS915NvmCtx_t );
+ return &NvmCtx;
+}
+
bool RegionUS915Verify( VerifyParams_t* verify, PhyAttribute_t phyAttribute )
{
switch( phyAttribute )
{
+ case PHY_FREQUENCY:
+ {
+ return VerifyRfFreq( verify->Frequency );
+ }
case PHY_TX_DR:
{
return RegionCommonValueInRange( verify->DatarateParams.Datarate, US915_TX_MIN_DATARATE, US915_TX_MAX_DATARATE );
@@ -378,23 +596,37 @@ bool RegionUS915Verify( VerifyParams_t* verify, PhyAttribute_t phyAttribute )
{
return US915_DUTY_CYCLE_ENABLED;
}
- case PHY_NB_JOIN_TRIALS:
- {
- if( verify->NbJoinTrials < 2 )
- {
- return false;
- }
- break;
- }
default:
return false;
}
- return true;
}
void RegionUS915ApplyCFList( ApplyCFListParams_t* applyCFList )
{
- return;
+ // Size of the optional CF list must be 16 byte
+ if( applyCFList->Size != 16 )
+ {
+ return;
+ }
+
+ // Last byte CFListType must be 0x01 to indicate the CFList contains a series of ChMask fields
+ if( applyCFList->Payload[15] != 0x01 )
+ {
+ return;
+ }
+
+ // ChMask0 - ChMask4 must be set (every ChMask has 16 bit)
+ for( uint8_t chMaskItr = 0, cntPayload = 0; chMaskItr <= 4; chMaskItr++, cntPayload+=2 )
+ {
+ NvmCtx.ChannelsMask[chMaskItr] = (uint16_t) (0x00FF & applyCFList->Payload[cntPayload]);
+ NvmCtx.ChannelsMask[chMaskItr] |= (uint16_t) (applyCFList->Payload[cntPayload+1] << 8);
+ if( chMaskItr == 4 )
+ {
+ NvmCtx.ChannelsMask[chMaskItr] = NvmCtx.ChannelsMask[chMaskItr] & CHANNELS_MASK_500KHZ_MASK;
+ }
+ // Set the channel mask to the remaining
+ NvmCtx.ChannelsMaskRemaining[chMaskItr] &= NvmCtx.ChannelsMask[chMaskItr];
+ }
}
bool RegionUS915ChanMaskSet( ChanMaskSetParams_t* chanMaskSet )
@@ -412,17 +644,20 @@ bool RegionUS915ChanMaskSet( ChanMaskSetParams_t* chanMaskSet )
{
case CHANNELS_MASK:
{
- RegionCommonChanMaskCopy( ChannelsMask, chanMaskSet->ChannelsMaskIn, 6 );
+ RegionCommonChanMaskCopy( NvmCtx.ChannelsMask, chanMaskSet->ChannelsMaskIn, CHANNELS_MASK_SIZE );
- for( uint8_t i = 0; i < 6; i++ )
+ NvmCtx.ChannelsDefaultMask[4] = NvmCtx.ChannelsDefaultMask[4] & CHANNELS_MASK_500KHZ_MASK;
+ NvmCtx.ChannelsDefaultMask[5] = 0x0000;
+
+ for( uint8_t i = 0; i < CHANNELS_MASK_SIZE; i++ )
{ // Copy-And the channels mask
- ChannelsMaskRemaining[i] &= ChannelsMask[i];
+ NvmCtx.ChannelsMaskRemaining[i] &= NvmCtx.ChannelsMask[i];
}
break;
}
case CHANNELS_DEFAULT_MASK:
{
- RegionCommonChanMaskCopy( ChannelsDefaultMask, chanMaskSet->ChannelsMaskIn, 6 );
+ RegionCommonChanMaskCopy( NvmCtx.ChannelsDefaultMask, chanMaskSet->ChannelsMaskIn, CHANNELS_MASK_SIZE );
break;
}
default:
@@ -431,71 +666,6 @@ bool RegionUS915ChanMaskSet( ChanMaskSetParams_t* chanMaskSet )
return true;
}
-bool RegionUS915AdrNext( AdrNextParams_t* adrNext, int8_t* drOut, int8_t* txPowOut, uint32_t* adrAckCounter )
-{
- bool adrAckReq = false;
- int8_t datarate = adrNext->Datarate;
- int8_t txPower = adrNext->TxPower;
- GetPhyParams_t getPhy;
- PhyParam_t phyParam;
-
- // Report back the adr ack counter
- *adrAckCounter = adrNext->AdrAckCounter;
-
- if( adrNext->AdrEnabled == true )
- {
- if( datarate == US915_TX_MIN_DATARATE )
- {
- *adrAckCounter = 0;
- adrAckReq = false;
- }
- else
- {
- if( adrNext->AdrAckCounter >= US915_ADR_ACK_LIMIT )
- {
- adrAckReq = true;
- txPower = US915_MAX_TX_POWER;
- }
- else
- {
- adrAckReq = false;
- }
- if( adrNext->AdrAckCounter >= ( US915_ADR_ACK_LIMIT + US915_ADR_ACK_DELAY ) )
- {
- if( ( adrNext->AdrAckCounter % US915_ADR_ACK_DELAY ) == 1 )
- {
- // Decrease the datarate
- getPhy.Attribute = PHY_NEXT_LOWER_TX_DR;
- getPhy.Datarate = datarate;
- getPhy.UplinkDwellTime = adrNext->UplinkDwellTime;
- phyParam = RegionUS915GetPhyParam( &getPhy );
- datarate = phyParam.Value;
-
- if( datarate == US915_TX_MIN_DATARATE )
- {
- // We must set adrAckReq to false as soon as we reach the lowest datarate
- adrAckReq = false;
- if( adrNext->UpdateChanMask == true )
- {
- // Re-enable default channels
- ChannelsMask[0] = 0xFFFF;
- ChannelsMask[1] = 0xFFFF;
- ChannelsMask[2] = 0xFFFF;
- ChannelsMask[3] = 0xFFFF;
- ChannelsMask[4] = 0x00FF;
- ChannelsMask[5] = 0x0000;
- }
- }
- }
- }
- }
- }
-
- *drOut = datarate;
- *txPowOut = txPower;
- return adrAckReq;
-}
-
void RegionUS915ComputeRxWindowParameters( int8_t datarate, uint8_t minRxSymbols, uint32_t rxError, RxConfigParams_t *rxConfigParams )
{
double tSymbol = 0.0;
@@ -506,8 +676,7 @@ void RegionUS915ComputeRxWindowParameters( int8_t datarate, uint8_t minRxSymbols
tSymbol = RegionCommonComputeSymbolTimeLoRa( DataratesUS915[rxConfigParams->Datarate], BandwidthsUS915[rxConfigParams->Datarate] );
- RegionCommonComputeRxWindowParameters( tSymbol, minRxSymbols, rxError, RADIO_WAKEUP_TIME, &rxConfigParams->WindowTimeout, &rxConfigParams->WindowOffset );
- rxConfigParams->WindowTimeout = rxConfigParams->WindowTimeout * 3;
+ RegionCommonComputeRxWindowParameters( tSymbol, minRxSymbols, rxError, Radio.GetWakeupTime( ), &rxConfigParams->WindowTimeout, &rxConfigParams->WindowOffset );
}
bool RegionUS915RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate )
@@ -522,7 +691,7 @@ bool RegionUS915RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate )
return false;
}
- if( rxConfig->Window == 0 )
+ if( rxConfig->RxSlot == RX_SLOT_WIN_1 )
{
// Apply window 1 frequency
frequency = US915_FIRST_RX1_CHANNEL + ( rxConfig->Channel % 8 ) * US915_STEPWIDTH_RX1_CHANNEL;
@@ -553,7 +722,7 @@ bool RegionUS915RxConfig( RxConfigParams_t* rxConfig, int8_t* datarate )
bool RegionUS915TxConfig( TxConfigParams_t* txConfig, int8_t* txPower, TimerTime_t* txTimeOnAir )
{
int8_t phyDr = DataratesUS915[txConfig->Datarate];
- int8_t txPowerLimited = LimitTxPower( txConfig->TxPower, Bands[Channels[txConfig->Channel].Band].TxMaxPower, txConfig->Datarate, ChannelsMask );
+ int8_t txPowerLimited = LimitTxPower( txConfig->TxPower, NvmCtx.Bands[NvmCtx.Channels[txConfig->Channel].Band].TxMaxPower, txConfig->Datarate, NvmCtx.ChannelsMask );
uint32_t bandwidth = GetBandwidth( txConfig->Datarate );
int8_t phyTxPower = 0;
@@ -561,9 +730,9 @@ bool RegionUS915TxConfig( TxConfigParams_t* txConfig, int8_t* txPower, TimerTime
phyTxPower = RegionCommonComputeTxPower( txPowerLimited, US915_DEFAULT_MAX_ERP, 0 );
// Setup the radio frequency
- Radio.SetChannel( Channels[txConfig->Channel].Frequency );
+ Radio.SetChannel( NvmCtx.Channels[txConfig->Channel].Frequency );
- Radio.SetTxConfig( MODEM_LORA, phyTxPower, 0, bandwidth, phyDr, 1, 8, false, true, 0, 0, false, 3000 );
+ Radio.SetTxConfig( MODEM_LORA, phyTxPower, 0, bandwidth, phyDr, 1, 8, false, true, 0, 0, false, 4000 );
// Setup maximum payload lenght of the radio driver
Radio.SetMaxPayloadLength( MODEM_LORA, txConfig->PktLen );
@@ -586,7 +755,7 @@ uint8_t RegionUS915LinkAdrReq( LinkAdrReqParams_t* linkAdrReq, int8_t* drOut, in
RegionCommonLinkAdrReqVerifyParams_t linkAdrVerifyParams;
// Initialize local copy of channels mask
- RegionCommonChanMaskCopy( channelsMask, ChannelsMask, 6 );
+ RegionCommonChanMaskCopy( channelsMask, NvmCtx.ChannelsMask, 6 );
while( bytesProcessed < linkAdrReq->PayloadSize )
{
@@ -609,7 +778,7 @@ uint8_t RegionUS915LinkAdrReq( LinkAdrReqParams_t* linkAdrReq, int8_t* drOut, in
channelsMask[2] = 0xFFFF;
channelsMask[3] = 0xFFFF;
// Apply chMask to channels 64 to 71
- channelsMask[4] = linkAdrParams.ChMask;
+ channelsMask[4] = linkAdrParams.ChMask & CHANNELS_MASK_500KHZ_MASK;
}
else if( linkAdrParams.ChMaskCtrl == 7 )
{
@@ -619,12 +788,61 @@ uint8_t RegionUS915LinkAdrReq( LinkAdrReqParams_t* linkAdrReq, int8_t* drOut, in
channelsMask[2] = 0x0000;
channelsMask[3] = 0x0000;
// Apply chMask to channels 64 to 71
- channelsMask[4] = linkAdrParams.ChMask;
+ channelsMask[4] = linkAdrParams.ChMask & CHANNELS_MASK_500KHZ_MASK;
}
else if( linkAdrParams.ChMaskCtrl == 5 )
{
- // RFU
- status &= 0xFE; // Channel mask KO
+ // Start value for comparision
+ uint8_t bitMask = 1;
+
+ // cntChannelMask for channelsMask[0] until channelsMask[3]
+ uint8_t cntChannelMask = 0;
+
+ // i will be 1, 2, 3, ..., 7
+ for( uint8_t i = 0; i <= 7; i++ )
+ {
+ // 8 MSBs of ChMask are RFU
+ // Checking if the ChMask is set, then true
+ if( ( ( linkAdrParams.ChMask & 0x00FF ) & ( bitMask << i ) ) != 0 )
+ {
+ if( ( i % 2 ) == 0 )
+ {
+ // Enable a bank of 8 125kHz channels, 8 LSBs
+ channelsMask[cntChannelMask] |= 0x00FF;
+ // Enable the corresponding 500kHz channel
+ channelsMask[4] |= ( bitMask << i );
+ }
+ else
+ {
+ // Enable a bank of 8 125kHz channels, 8 MSBs
+ channelsMask[cntChannelMask] |= 0xFF00;
+ // Enable the corresponding 500kHz channel
+ channelsMask[4] |= ( bitMask << i );
+ // cntChannelMask increment for uneven i
+ cntChannelMask++;
+ }
+ }
+ // ChMask is not set
+ else
+ {
+ if( ( i % 2 ) == 0 )
+ {
+ // Disable a bank of 8 125kHz channels, 8 LSBs
+ channelsMask[cntChannelMask] &= 0xFF00;
+ // Disable the corresponding 500kHz channel
+ channelsMask[4] &= ~( bitMask << i );
+ }
+ else
+ {
+ // Enable a bank of 8 125kHz channels, 8 MSBs
+ channelsMask[cntChannelMask] &= 0x00FF;
+ // Disable the corresponding 500kHz channel
+ channelsMask[4] &= ~( bitMask << i );
+ // cntChannelMask increment for uneven i
+ cntChannelMask++;
+ }
+ }
+ }
}
else
{
@@ -655,9 +873,10 @@ uint8_t RegionUS915LinkAdrReq( LinkAdrReqParams_t* linkAdrReq, int8_t* drOut, in
linkAdrVerifyParams.ChannelsMask = channelsMask;
linkAdrVerifyParams.MinDatarate = ( int8_t )phyParam.Value;
linkAdrVerifyParams.MaxDatarate = US915_TX_MAX_DATARATE;
- linkAdrVerifyParams.Channels = Channels;
+ linkAdrVerifyParams.Channels = NvmCtx.Channels;
linkAdrVerifyParams.MinTxPower = US915_MIN_TX_POWER;
linkAdrVerifyParams.MaxTxPower = US915_MAX_TX_POWER;
+ linkAdrVerifyParams.Version = linkAdrReq->Version;
// Verify the parameters and update, if necessary
status = RegionCommonLinkAdrReqVerifyParams( &linkAdrVerifyParams, &linkAdrParams.Datarate, &linkAdrParams.TxPower, &linkAdrParams.NbRep );
@@ -666,14 +885,14 @@ uint8_t RegionUS915LinkAdrReq( LinkAdrReqParams_t* linkAdrReq, int8_t* drOut, in
if( status == 0x07 )
{
// Copy Mask
- RegionCommonChanMaskCopy( ChannelsMask, channelsMask, 6 );
-
- ChannelsMaskRemaining[0] &= ChannelsMask[0];
- ChannelsMaskRemaining[1] &= ChannelsMask[1];
- ChannelsMaskRemaining[2] &= ChannelsMask[2];
- ChannelsMaskRemaining[3] &= ChannelsMask[3];
- ChannelsMaskRemaining[4] = ChannelsMask[4];
- ChannelsMaskRemaining[5] = ChannelsMask[5];
+ RegionCommonChanMaskCopy( NvmCtx.ChannelsMask, channelsMask, 6 );
+
+ NvmCtx.ChannelsMaskRemaining[0] &= NvmCtx.ChannelsMask[0];
+ NvmCtx.ChannelsMaskRemaining[1] &= NvmCtx.ChannelsMask[1];
+ NvmCtx.ChannelsMaskRemaining[2] &= NvmCtx.ChannelsMask[2];
+ NvmCtx.ChannelsMaskRemaining[3] &= NvmCtx.ChannelsMask[3];
+ NvmCtx.ChannelsMaskRemaining[4] = NvmCtx.ChannelsMask[4];
+ NvmCtx.ChannelsMaskRemaining[5] = NvmCtx.ChannelsMask[5];
}
// Update status variables
@@ -688,13 +907,9 @@ uint8_t RegionUS915LinkAdrReq( LinkAdrReqParams_t* linkAdrReq, int8_t* drOut, in
uint8_t RegionUS915RxParamSetupReq( RxParamSetupReqParams_t* rxParamSetupReq )
{
uint8_t status = 0x07;
- uint32_t freq = rxParamSetupReq->Frequency;
// Verify radio frequency
- if( ( Radio.CheckRfFrequency( freq ) == false ) ||
- ( freq < US915_FIRST_RX1_CHANNEL ) ||
- ( freq > US915_LAST_RX1_CHANNEL ) ||
- ( ( ( freq - ( uint32_t ) US915_FIRST_RX1_CHANNEL ) % ( uint32_t ) US915_STEPWIDTH_RX1_CHANNEL ) != 0 ) )
+ if( VerifyRfFreq( rxParamSetupReq->Frequency ) == false )
{
status &= 0xFE; // Channel frequency KO
}
@@ -735,30 +950,37 @@ uint8_t RegionUS915DlChannelReq( DlChannelReqParams_t* dlChannelReq )
return 0;
}
-int8_t RegionUS915AlternateDr( AlternateDrParams_t* alternateDr )
+int8_t RegionUS915AlternateDr( int8_t currentDr, AlternateDrType_t type )
{
- int8_t datarate = 0;
-
- // Re-enable 500 kHz default channels
- ChannelsMask[4] = 0x00FF;
+ // Alternates the data rate according to the channel sequence:
+ // Eight times a 125kHz DR_0 and then one 500kHz DR_4 channel
+ if( type == ALTERNATE_DR )
+ {
+ NvmCtx.JoinTrialsCounter++;
+ }
+ else
+ {
+ NvmCtx.JoinTrialsCounter--;
+ }
- if( ( alternateDr->NbTrials & 0x01 ) == 0x01 )
+ if( NvmCtx.JoinTrialsCounter % 9 == 0 )
{
- datarate = DR_4;
+ // Use DR_4 every 9th times.
+ currentDr = DR_4;
}
else
{
- datarate = DR_0;
+ currentDr = DR_0;
}
- return datarate;
+ return currentDr;
}
void RegionUS915CalcBackOff( CalcBackOffParams_t* calcBackOff )
{
RegionCommonCalcBackOffParams_t calcBackOffParams;
- calcBackOffParams.Channels = Channels;
- calcBackOffParams.Bands = Bands;
+ calcBackOffParams.Channels = NvmCtx.Channels;
+ calcBackOffParams.Bands = NvmCtx.Bands;
calcBackOffParams.LastTxIsJoinRequest = calcBackOff->LastTxIsJoinRequest;
calcBackOffParams.Joined = calcBackOff->Joined;
calcBackOffParams.DutyCycleEnabled = calcBackOff->DutyCycleEnabled;
@@ -769,55 +991,91 @@ void RegionUS915CalcBackOff( CalcBackOffParams_t* calcBackOff )
RegionCommonCalcBackOff( &calcBackOffParams );
}
-bool RegionUS915NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff )
+LoRaMacStatus_t RegionUS915NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff )
{
uint8_t nbEnabledChannels = 0;
uint8_t delayTx = 0;
uint8_t enabledChannels[US915_MAX_NB_CHANNELS] = { 0 };
TimerTime_t nextTxDelay = 0;
+ uint8_t newChannelIndex = 0;
// Count 125kHz channels
- if( RegionCommonCountChannels( ChannelsMaskRemaining, 0, 4 ) == 0 )
+ if( RegionCommonCountChannels( NvmCtx.ChannelsMaskRemaining, 0, 4 ) == 0 )
{ // Reactivate default channels
- RegionCommonChanMaskCopy( ChannelsMaskRemaining, ChannelsMask, 4 );
+ RegionCommonChanMaskCopy( NvmCtx.ChannelsMaskRemaining, NvmCtx.ChannelsMask, 4 );
+
+ NvmCtx.JoinChannelGroupsCurrentIndex = 0;
}
// Check other channels
if( nextChanParams->Datarate >= DR_4 )
{
- if( ( ChannelsMaskRemaining[4] & 0x00FF ) == 0 )
+ if( ( NvmCtx.ChannelsMaskRemaining[4] & CHANNELS_MASK_500KHZ_MASK ) == 0 )
{
- ChannelsMaskRemaining[4] = ChannelsMask[4];
+ NvmCtx.ChannelsMaskRemaining[4] = NvmCtx.ChannelsMask[4];
}
}
- if( nextChanParams->AggrTimeOff <= TimerGetElapsedTime( nextChanParams->LastAggrTx ) )
+ TimerTime_t elapsed = TimerGetElapsedTime( nextChanParams->LastAggrTx );
+ if( ( nextChanParams->LastAggrTx == 0 ) || ( nextChanParams->AggrTimeOff <= elapsed ) )
{
// Reset Aggregated time off
*aggregatedTimeOff = 0;
// Update bands Time OFF
- nextTxDelay = RegionCommonUpdateBandTimeOff( nextChanParams->Joined, nextChanParams->DutyCycleEnabled, Bands, US915_MAX_NB_BANDS );
+ nextTxDelay = RegionCommonUpdateBandTimeOff( nextChanParams->Joined, nextChanParams->DutyCycleEnabled, NvmCtx.Bands, US915_MAX_NB_BANDS );
// Search how many channels are enabled
nbEnabledChannels = CountNbOfEnabledChannels( nextChanParams->Datarate,
- ChannelsMaskRemaining, Channels,
- Bands, enabledChannels, &delayTx );
+ NvmCtx.ChannelsMaskRemaining, NvmCtx.Channels,
+ NvmCtx.Bands, enabledChannels, &delayTx );
}
else
{
delayTx++;
- nextTxDelay = nextChanParams->AggrTimeOff - TimerGetElapsedTime( nextChanParams->LastAggrTx );
+ nextTxDelay = nextChanParams->AggrTimeOff - elapsed;
}
if( nbEnabledChannels > 0 )
{
- // We found a valid channel
- *channel = enabledChannels[randr( 0, nbEnabledChannels - 1 )];
+ if( nextChanParams->Joined == true )
+ {
+ // Choose randomly on of the remaining channels
+ *channel = enabledChannels[randr( 0, nbEnabledChannels - 1 )];
+ }
+ else
+ {
+ // For rapid network acquisition in mixed gateway channel plan environments, the device
+ // follow a random channel selection sequence. It probes alternating one out of a
+ // group of eight 125 kHz channels followed by probing one 500 kHz channel each pass.
+ // Each time a 125 kHz channel will be selected from another group.
+
+ // 125kHz Channels (0 - 63) DR0
+ if( nextChanParams->Datarate == DR_0 )
+ {
+ if( ComputeNext125kHzJoinChannel( &newChannelIndex ) == LORAMAC_STATUS_PARAMETER_INVALID )
+ {
+ return LORAMAC_STATUS_PARAMETER_INVALID;
+ }
+ *channel = newChannelIndex;
+ }
+ // 500kHz Channels (64 - 71) DR4
+ else
+ {
+ // Choose the next available channel
+ uint8_t i = 0;
+ while( ( ( NvmCtx.ChannelsMaskRemaining[4] & CHANNELS_MASK_500KHZ_MASK ) & ( 1 << i ) ) == 0 )
+ {
+ i++;
+ }
+ *channel = 64 + i;
+ }
+ }
+
// Disable the channel in the mask
- RegionCommonChanDisable( ChannelsMaskRemaining, *channel, US915_MAX_NB_CHANNELS - 8 );
+ RegionCommonChanDisable( NvmCtx.ChannelsMaskRemaining, *channel, US915_MAX_NB_CHANNELS );
*time = 0;
- return true;
+ return LORAMAC_STATUS_OK;
}
else
{
@@ -825,11 +1083,11 @@ bool RegionUS915NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel,
{
// Delay transmission due to AggregatedTimeOff or to a band time off
*time = nextTxDelay;
- return true;
+ return LORAMAC_STATUS_DUTYCYCLE_RESTRICTED;
}
// Datarate not supported by any channel
*time = 0;
- return false;
+ return LORAMAC_STATUS_NO_CHANNEL_FOUND;
}
}
@@ -838,6 +1096,52 @@ LoRaMacStatus_t RegionUS915ChannelAdd( ChannelAddParams_t* channelAdd )
return LORAMAC_STATUS_PARAMETER_INVALID;
}
+bool RegionUS915ChannelsRemove( ChannelRemoveParams_t* channelRemove )
+{
+ return LORAMAC_STATUS_PARAMETER_INVALID;
+}
+
+void RegionUS915SetContinuousWave( ContinuousWaveParams_t* continuousWave )
+{
+ int8_t txPowerLimited = LimitTxPower( continuousWave->TxPower, NvmCtx.Bands[NvmCtx.Channels[continuousWave->Channel].Band].TxMaxPower, continuousWave->Datarate, NvmCtx.ChannelsMask );
+ int8_t phyTxPower = 0;
+ uint32_t frequency = NvmCtx.Channels[continuousWave->Channel].Frequency;
+
+ // Calculate physical TX power
+ phyTxPower = RegionCommonComputeTxPower( txPowerLimited, US915_DEFAULT_MAX_ERP, 0 );
+
+ Radio.SetTxContinuousWave( frequency, phyTxPower, continuousWave->Timeout );
+}
+
+uint8_t RegionUS915ApplyDrOffset( uint8_t downlinkDwellTime, int8_t dr, int8_t drOffset )
+{
+ int8_t datarate = DatarateOffsetsUS915[dr][drOffset];
+
+ if( datarate < 0 )
+ {
+ datarate = DR_0;
+ }
+ return datarate;
+}
+
+void RegionUS915RxBeaconSetup( RxBeaconSetup_t* rxBeaconSetup, uint8_t* outDr )
+{
+ RegionCommonRxBeaconSetupParams_t regionCommonRxBeaconSetup;
+
+ regionCommonRxBeaconSetup.Datarates = DataratesUS915;
+ regionCommonRxBeaconSetup.Frequency = rxBeaconSetup->Frequency;
+ regionCommonRxBeaconSetup.BeaconSize = US915_BEACON_SIZE;
+ regionCommonRxBeaconSetup.BeaconDatarate = US915_BEACON_CHANNEL_DR;
+ regionCommonRxBeaconSetup.BeaconChannelBW = US915_BEACON_CHANNEL_BW;
+ regionCommonRxBeaconSetup.RxTime = rxBeaconSetup->RxTime;
+ regionCommonRxBeaconSetup.SymbolTimeout = rxBeaconSetup->SymbolTimeout;
+
+ RegionCommonRxBeaconSetup( ®ionCommonRxBeaconSetup );
+
+ // Store downlink datarate
+ *outDr = US915_BEACON_CHANNEL_DR;
+}
+
LoRaMacStatus_t RegionUS915ChannelManualAdd( ChannelAddParams_t* channelAdd )
{
uint8_t band = 0;
@@ -881,88 +1185,29 @@ LoRaMacStatus_t RegionUS915ChannelManualAdd( ChannelAddParams_t* channelAdd )
return LORAMAC_STATUS_FREQUENCY_INVALID;
}
- memcpy( &(Channels[id]), channelAdd->NewChannel, sizeof( Channels[id] ) );
- Channels[id].Band = band;
- ChannelsMask[ (id / 16) ] |= (1 << (id % 16));
+ memcpy( &(NvmCtx.Channels[id]), channelAdd->NewChannel, sizeof( NvmCtx.Channels[id] ) );
+ NvmCtx.Channels[id].Band = band;
+ NvmCtx.ChannelsMask[ (id / 16) ] |= (1 << (id % 16));
// activate the channel in the remaining ones
- ChannelsMaskRemaining[id / 16] |= ChannelsMask[id / 16];
+ NvmCtx.ChannelsMaskRemaining[id / 16] |= NvmCtx.ChannelsMask[id / 16];
return LORAMAC_STATUS_OK;
}
-bool RegionUS915ChannelsRemove( ChannelRemoveParams_t* channelRemove )
-{
- return false;
-}
-
bool RegionUS915ChannelsManualRemove( ChannelRemoveParams_t* channelRemove )
{
uint8_t id = channelRemove->ChannelId;
// Disable the channel as it doesn't exist anymore
- if ( !RegionCommonChanDisable( ChannelsMask, id, US915_MAX_NB_CHANNELS ) ) {
+ if ( !RegionCommonChanDisable( NvmCtx.ChannelsMask, id, US915_MAX_NB_CHANNELS ) ) {
return false;
}
// Remove the channel from the list of channels
- Channels[id] = ( ChannelParams_t ){ 0, 0, { 0 }, 0 };
+ NvmCtx.Channels[id] = ( ChannelParams_t ){ 0, 0, { 0 }, 0 };
// Set the channel mask remaining accordingly
- ChannelsMaskRemaining[id / 16] &= ChannelsMask[id / 16];
-
- return true;
-}
+ NvmCtx.ChannelsMaskRemaining[id / 16] &= NvmCtx.ChannelsMask[id / 16];
-void RegionUS915SetContinuousWave( ContinuousWaveParams_t* continuousWave )
-{
- int8_t txPowerLimited = LimitTxPower( continuousWave->TxPower, Bands[Channels[continuousWave->Channel].Band].TxMaxPower, continuousWave->Datarate, ChannelsMask );
- int8_t phyTxPower = 0;
- uint32_t frequency = Channels[continuousWave->Channel].Frequency;
-
- // Calculate physical TX power
- phyTxPower = RegionCommonComputeTxPower( txPowerLimited, US915_DEFAULT_MAX_ERP, 0 );
-
- Radio.SetTxContinuousWave( frequency, phyTxPower, continuousWave->Timeout );
-}
-
-uint8_t RegionUS915ApplyDrOffset( uint8_t downlinkDwellTime, int8_t dr, int8_t drOffset )
-{
- int8_t datarate = DatarateOffsetsUS915[dr][drOffset];
-
- if( datarate < 0 )
- {
- datarate = DR_0;
- }
- return datarate;
-}
-
-bool RegionUS915GetChannels( ChannelParams_t** channels, uint32_t *size )
-{
- *channels = Channels;
- *size = sizeof(Channels);
- return true;
-}
-
-bool RegionUS915GetChannelMask( uint16_t** channelmask, uint32_t *size )
-{
- *channelmask = ChannelsMask;
- *size = sizeof(ChannelsMask);
- return true;
-}
-
-bool RegionUS915GetChannelMaskRemaining( uint16_t** channelmask, uint32_t *size )
-{
- *channelmask = ChannelsMaskRemaining;
- *size = sizeof(ChannelsMaskRemaining);
- return true;
-}
-
-bool RegionUS915ForceJoinDataRate( int8_t joinDr, AlternateDrParams_t* alternateDr )
-{
- if (joinDr == DR_4) {
- alternateDr->NbTrials = 1;
- } else {
- alternateDr->NbTrials = 0;
- }
return true;
}
diff --git a/lib/lora/mac/region/RegionUS915.h b/lib/lora/mac/region/RegionUS915.h
index 92cdeefbdc..6166dc15d9 100644
--- a/lib/lora/mac/region/RegionUS915.h
+++ b/lib/lora/mac/region/RegionUS915.h
@@ -12,7 +12,7 @@
* \____ \| ___ | (_ _) ___ |/ ___) _ \
* _____) ) ____| | | || |_| ____( (___| | | |
* (______/|_____)_|_|_| \__)_____)\____)_| |_|
- * (C)2013 Semtech
+ * (C)2013-2017 Semtech
*
* ___ _____ _ ___ _ _____ ___ ___ ___ ___
* / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
@@ -28,6 +28,8 @@
*
* \author Daniel Jaeckle ( STACKFORCE )
*
+ * \author Johannes Bruder ( STACKFORCE )
+ *
* \defgroup REGIONUS915 Region US915
* Implementation according to LoRaWAN Specification v1.0.2.
* \{
@@ -35,6 +37,13 @@
#ifndef __REGION_US915_H__
#define __REGION_US915_H__
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include "Region.h"
+
/*!
* LoRaMac maximum number of channels
*/
@@ -83,7 +92,7 @@
/*!
* Minimal Tx output power that can be used by the node
*/
-#define US915_MIN_TX_POWER TX_POWER_10
+#define US915_MIN_TX_POWER TX_POWER_14
/*!
* Maximal Tx output power that can be used by the node
@@ -165,16 +174,64 @@
*/
#define US915_RX_WND_2_DR DR_8
+/*
+ * CLASS B
+ */
+/*!
+ * Beacon frequency
+ */
+#define US915_BEACON_CHANNEL_FREQ 923300000
+
+/*!
+ * Beacon frequency channel stepwidth
+ */
+#define US915_BEACON_CHANNEL_STEPWIDTH 600000
+
+/*!
+ * Number of possible beacon channels
+ */
+#define US915_BEACON_NB_CHANNELS 8
+
+/*!
+ * Payload size of a beacon frame
+ */
+#define US915_BEACON_SIZE 23
+
+/*!
+ * Size of RFU 1 field
+ */
+#define US915_RFU1_SIZE 5
+
+/*!
+ * Size of RFU 2 field
+ */
+#define US915_RFU2_SIZE 3
+
+/*!
+ * Datarate of the beacon channel
+ */
+#define US915_BEACON_CHANNEL_DR DR_8
+
+/*!
+ * Bandwith of the beacon channel
+ */
+#define US915_BEACON_CHANNEL_BW 2
+
+/*!
+ * Ping slot channel datarate
+ */
+#define US915_PING_SLOT_CHANNEL_DR DR_8
+
/*!
* LoRaMac maximum number of bands
*/
-#define US915_MAX_NB_BANDS 1
+#define US915_MAX_NB_BANDS 1
/*!
* Band 0 definition
- * { DutyCycle, TxMaxPower, LastTxDoneTime, TimeOff }
+ * { DutyCycle, TxMaxPower, LastJoinTxDoneTime, LastTxDoneTime, TimeOff }
*/
-#define US915_BAND0 { 1, US915_MAX_TX_POWER, 0, 0 } // 100.0 %
+#define US915_BAND0 { 1, US915_MAX_TX_POWER, 0, 0, 0 } // 100.0 %
/*!
* Defines the first channel for RX window 1 for US band
@@ -244,7 +301,16 @@ void RegionUS915SetBandTxDone( SetBandTxDoneParams_t* txDone );
*
* \param [IN] type Sets the initialization type.
*/
-void RegionUS915InitDefaults( InitType_t type );
+void RegionUS915InitDefaults( InitDefaultsParams_t* params );
+
+/*!
+ * \brief Returns a pointer to the internal context and its size.
+ *
+ * \param [OUT] params Pointer to the function parameters.
+ *
+ * \retval Points to a structure where the module store its non-volatile context.
+ */
+void* RegionUS915GetNvmCtx( GetNvmCtxParams_t* params );
/*!
* \brief Verifies a parameter.
@@ -274,21 +340,6 @@ void RegionUS915ApplyCFList( ApplyCFListParams_t* applyCFList );
*/
bool RegionUS915ChanMaskSet( ChanMaskSetParams_t* chanMaskSet );
-/*!
- * \brief Calculates the next datarate to set, when ADR is on or off.
- *
- * \param [IN] adrNext Pointer to the function parameters.
- *
- * \param [OUT] drOut The calculated datarate for the next TX.
- *
- * \param [OUT] txPowOut The TX power for the next TX.
- *
- * \param [OUT] adrAckCounter The calculated ADR acknowledgement counter.
- *
- * \retval Returns true, if an ADR request should be performed.
- */
-bool RegionUS915AdrNext( AdrNextParams_t* adrNext, int8_t* drOut, int8_t* txPowOut, uint32_t* adrAckCounter );
-
/*!
* Computes the Rx window timeout and offset.
*
@@ -378,11 +429,13 @@ uint8_t RegionUS915DlChannelReq( DlChannelReqParams_t* dlChannelReq );
/*!
* \brief Alternates the datarate of the channel for the join request.
*
- * \param [IN] alternateDr Pointer to the function parameters.
+ * \param [IN] currentDr Current datarate.
+ *
+ * \param [IN] type Alternation type.
*
* \retval Datarate to apply.
*/
-int8_t RegionUS915AlternateDr( AlternateDrParams_t* alternateDr );
+int8_t RegionUS915AlternateDr( int8_t currentDr, AlternateDrType_t type );
/*!
* \brief Calculates the back-off time.
@@ -403,7 +456,7 @@ void RegionUS915CalcBackOff( CalcBackOffParams_t* calcBackOff );
*
* \retval Function status [1: OK, 0: Unable to find a channel on the current datarate]
*/
-bool RegionUS915NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff );
+LoRaMacStatus_t RegionUS915NextChannel( NextChanParams_t* nextChanParams, uint8_t* channel, TimerTime_t* time, TimerTime_t* aggregatedTimeOff );
/*!
* \brief Adds a channel.
@@ -445,14 +498,17 @@ void RegionUS915SetContinuousWave( ContinuousWaveParams_t* continuousWave );
*/
uint8_t RegionUS915ApplyDrOffset( uint8_t downlinkDwellTime, int8_t dr, int8_t drOffset );
-bool RegionUS915GetChannels( ChannelParams_t** channels, uint32_t *size );
-
-bool RegionUS915GetChannelMask( uint16_t** channelmask, uint32_t *size );
-
-bool RegionUS915GetChannelMaskRemaining( uint16_t** channelmask, uint32_t *size );
-
-bool RegionUS915ForceJoinDataRate( int8_t joinDr, AlternateDrParams_t* alternateDr );
+/*!
+ * \brief Sets the radio into beacon reception mode
+ *
+ * \param [IN] rxBeaconSetup Pointer to the function parameters
+ */
+ void RegionUS915RxBeaconSetup( RxBeaconSetup_t* rxBeaconSetup, uint8_t* outDr );
/*! \} defgroup REGIONUS915 */
+#ifdef __cplusplus
+}
+#endif
+
#endif // __REGION_US915_H__
diff --git a/lib/lora/mac/secure-element.h b/lib/lora/mac/secure-element.h
new file mode 100644
index 0000000000..9321340820
--- /dev/null
+++ b/lib/lora/mac/secure-element.h
@@ -0,0 +1,216 @@
+/*!
+ * \file secure-element.h
+ *
+ * \brief Secure Element driver API
+ *
+ * \copyright Revised BSD License, see section \ref LICENSE.
+ *
+ * \code
+ * ______ _
+ * / _____) _ | |
+ * ( (____ _____ ____ _| |_ _____ ____| |__
+ * \____ \| ___ | (_ _) ___ |/ ___) _ \
+ * _____) ) ____| | | || |_| ____( (___| | | |
+ * (______/|_____)_|_|_| \__)_____)\____)_| |_|
+ * (C)2013 Semtech
+ *
+ * ___ _____ _ ___ _ _____ ___ ___ ___ ___
+ * / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
+ * \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
+ * |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
+ * embedded.connectivity.solutions===============
+ *
+ * \endcode
+ *
+ * \author Miguel Luis ( Semtech )
+ *
+ * \author Gregory Cristian ( Semtech )
+ *
+ * \author Daniel Jaeckle ( STACKFORCE )
+ *
+ * \author Johannes Bruder ( STACKFORCE )
+ *
+ * \defgroup SECUREELEMENT Secure Element API Definition
+ *
+ * \{
+ *
+ */
+#ifndef __SECURE_ELEMENT_H__
+#define __SECURE_ELEMENT_H__
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include
+#include "LoRaMacCrypto.h"
+
+#define SE_EUI_SIZE 16
+
+/*!
+ * Return values.
+ */
+typedef enum eSecureElementStatus
+{
+ /*!
+ * No error occurred
+ */
+ SECURE_ELEMENT_SUCCESS = 0,
+ /*!
+ * CMAC does not match
+ */
+ SECURE_ELEMENT_FAIL_CMAC,
+ /*!
+ * Null pointer exception
+ */
+ SECURE_ELEMENT_ERROR_NPE,
+ /*!
+ * Invalid key identifier exception
+ */
+ SECURE_ELEMENT_ERROR_INVALID_KEY_ID,
+ /*!
+ * Invalid LoRaWAN specification version
+ */
+ SECURE_ELEMENT_ERROR_INVALID_LORAWAM_SPEC_VERSION,
+ /*!
+ * Incompatible buffer size
+ */
+ SECURE_ELEMENT_ERROR_BUF_SIZE,
+ /*!
+ * Undefined Error occurred
+ */
+ SECURE_ELEMENT_ERROR,
+}SecureElementStatus_t;
+
+/*!
+ * Signature of callback function to be called by the Secure Element driver when the
+ * non volatile context have to be stored.
+ *
+ */
+typedef void ( *SecureElementNvmEvent )( void );
+
+/*!
+ * Initialization of Secure Element driver
+ *
+ * \param[IN] seNvmCtxChanged - Callback function which will be called when the
+ * non-volatile context have to be stored.
+ * \retval - Status of the operation
+ */
+SecureElementStatus_t SecureElementInit( SecureElementNvmEvent seNvmCtxChanged );
+
+/*!
+ * Restores the internal nvm context from passed pointer.
+ *
+ * \param[IN] seNvmCtx - Pointer to non-volatile module context to be restored.
+ * \retval - Status of the operation
+ */
+SecureElementStatus_t SecureElementRestoreNvmCtx( void* seNvmCtx );
+
+/*!
+ * Returns a pointer to the internal non-volatile context.
+ *
+ * \param[IN] seNvmCtxSize - Size of the module non volatile context
+ * \retval - Points to a structure where the module store its non volatile context
+ */
+void* SecureElementGetNvmCtx( size_t* seNvmCtxSize );
+
+/*!
+ * Sets a key
+ *
+ * \param[IN] keyID - Key identifier
+ * \param[IN] key - Key value
+ * \retval - Status of the operation
+ */
+SecureElementStatus_t SecureElementSetKey( KeyIdentifier_t keyID, uint8_t* key );
+
+/*!
+ * Computes a CMAC of a message using provided initial Bx block
+ *
+ * \param[IN] micBxBuffer - Buffer containing the initial Bx block
+ * \param[IN] buffer - Data buffer
+ * \param[IN] size - Data buffer size
+ * \param[IN] keyID - Key identifier to determine the AES key to be used
+ * \param[OUT] cmac - Computed cmac
+ * \retval - Status of the operation
+ */
+SecureElementStatus_t SecureElementComputeAesCmac( uint8_t* micBxBuffer, uint8_t* buffer, uint16_t size, KeyIdentifier_t keyID, uint32_t* cmac );
+
+/*!
+ * Verifies a CMAC (computes and compare with expected cmac)
+ *
+ * \param[IN] buffer - Data buffer
+ * \param[IN] size - Data buffer size
+ * \param[in] expectedCmac - Expected cmac
+ * \param[IN] keyID - Key identifier to determine the AES key to be used
+ * \retval - Status of the operation
+ */
+SecureElementStatus_t SecureElementVerifyAesCmac( uint8_t* buffer, uint16_t size, uint32_t expectedCmac, KeyIdentifier_t keyID );
+
+/*!
+ * Encrypt a buffer
+ *
+ * \param[IN] buffer - Data buffer
+ * \param[IN] size - Data buffer size
+ * \param[IN] keyID - Key identifier to determine the AES key to be used
+ * \param[OUT] encBuffer - Encrypted buffer
+ * \retval - Status of the operation
+ */
+SecureElementStatus_t SecureElementAesEncrypt( uint8_t* buffer, uint16_t size, KeyIdentifier_t keyID, uint8_t* encBuffer );
+
+/*!
+ * Derives and store a key
+ *
+ * \param[IN] version - LoRaWAN specification version currently in use.
+ * \param[IN] input - Input data from which the key is derived ( 16 byte )
+ * \param[IN] rootKeyID - Key identifier of the root key to use to perform the derivation
+ * \param[IN] targetKeyID - Key identifier of the key which will be derived
+ * \retval - Status of the operation
+ */
+SecureElementStatus_t SecureElementDeriveAndStoreKey( Version_t version, uint8_t* input, KeyIdentifier_t rootKeyID, KeyIdentifier_t targetKeyID );
+
+/*!
+ * Generates a random number
+ *
+ * \param[OUT] randomNum - 32 bit random number
+ * \retval - Status of the operation
+ */
+SecureElementStatus_t SecureElementRandomNumber( uint32_t* randomNum );
+
+/*!
+ * Sets the DevEUI
+ *
+ * \param[IN] devEui - Pointer to the 16-byte devEUI
+ * \retval - Status of the operation
+ */
+SecureElementStatus_t SecureElementSetDevEui( uint8_t* devEui );
+
+/*!
+ * Gets the DevEUI
+ *
+ * \retval - Pointer to the 16-byte devEUI
+ */
+uint8_t* SecureElementGetDevEui( void );
+
+/*!
+ * Sets the JoinEUI
+ *
+ * \param[IN] joinEui - Pointer to the 16-byte joinEui
+ * \retval - Status of the operation
+ */
+SecureElementStatus_t SecureElementSetJoinEui( uint8_t* joinEui );
+
+/*!
+ * Gets the DevEUI
+ *
+ * \retval - Pointer to the 16-byte joinEui
+ */
+uint8_t* SecureElementGetJoinEui( void );
+
+/*! \} defgroup SECUREELEMENT */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // __SECURE_ELEMENT_H__
diff --git a/lib/lora/mac/soft-se.c b/lib/lora/mac/soft-se.c
new file mode 100644
index 0000000000..04c082874a
--- /dev/null
+++ b/lib/lora/mac/soft-se.c
@@ -0,0 +1,417 @@
+/*
+ / _____) _ | |
+( (____ _____ ____ _| |_ _____ ____| |__
+ \____ \| ___ | (_ _) ___ |/ ___) _ \
+ _____) ) ____| | | || |_| ____( (___| | | |
+(______/|_____)_|_|_| \__)_____)\____)_| |_|
+ (C)2013 Semtech
+ ___ _____ _ ___ _ _____ ___ ___ ___ ___
+/ __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
+\__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
+|___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
+embedded.connectivity.solutions===============
+
+Description: Secure Element software implementation
+
+License: Revised BSD License, see LICENSE.TXT file include in the project
+
+Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ),
+ Daniel Jaeckle ( STACKFORCE ), Johannes Bruder ( STACKFORCE )
+*/
+#include "lora/mac/secure-element.h"
+
+#include
+#include
+
+#include "lora/mac/LoRaMacCrypto.h"
+#include "utilities.h"
+#include "lora/system/crypto/aes.h"
+#include "lora/system/crypto/cmac.h"
+#include "radio.h"
+
+#define NUM_OF_KEYS 24
+#define KEY_SIZE 16
+
+/*!
+ * Identifier value pair type for Keys
+ */
+typedef struct sKey
+{
+ /*
+ * Key identifier
+ */
+ KeyIdentifier_t KeyID;
+ /*
+ * Key value
+ */
+ uint8_t KeyValue[KEY_SIZE];
+} Key_t;
+
+/*
+ * Secure Element Non Volatile Context structure
+ */
+typedef struct sSecureElementNvCtx
+{
+ /*
+ * DevEUI storage
+ */
+ uint8_t DevEui[SE_EUI_SIZE];
+ /*
+ * Join EUI storage
+ */
+ uint8_t JoinEui[SE_EUI_SIZE];
+ /*
+ * AES computation context variable
+ */
+ aes_context AesContext;
+ /*
+ * CMAC computation context variable
+ */
+ AES_CMAC_CTX AesCmacCtx[1];
+ /*
+ * Key List
+ */
+ Key_t KeyList[NUM_OF_KEYS];
+}SecureElementNvCtx_t;
+
+/*
+ * Module context
+ */
+static SecureElementNvCtx_t SeNvmCtx;
+
+static SecureElementNvmEvent SeNvmCtxChanged;
+
+/*
+ * Local functions
+ */
+
+/*
+ * Gets key item from key list.
+ *
+ * cmac = aes128_cmac(keyID, B0 | msg)
+ *
+ * \param[IN] keyID - Key identifier
+ * \param[OUT] keyItem - Key item reference
+ * \retval - Status of the operation
+ */
+SecureElementStatus_t GetKeyByID( KeyIdentifier_t keyID, Key_t** keyItem )
+{
+ for( uint8_t i = 0; i < NUM_OF_KEYS; i++ )
+ {
+ if( SeNvmCtx.KeyList[i].KeyID == keyID )
+ {
+ *keyItem = &( SeNvmCtx.KeyList[i] );
+ return SECURE_ELEMENT_SUCCESS;
+ }
+ }
+ return SECURE_ELEMENT_ERROR_INVALID_KEY_ID;
+}
+
+/*
+ * Dummy callback in case if the user provides NULL function pointer
+ */
+static void DummyCB( void )
+{
+ return;
+}
+
+/*
+ * Computes a CMAC of a message using provided initial Bx block
+ *
+ * cmac = aes128_cmac(keyID, blocks[i].Buffer)
+ *
+ * \param[IN] micBxBuffer - Buffer containing the initial Bx block
+ * \param[IN] buffer - Data buffer
+ * \param[IN] size - Data buffer size
+ * \param[IN] keyID - Key identifier to determine the AES key to be used
+ * \param[OUT] cmac - Computed cmac
+ * \retval - Status of the operation
+ */
+static SecureElementStatus_t ComputeCmac( uint8_t *micBxBuffer, uint8_t *buffer, uint16_t size, KeyIdentifier_t keyID, uint32_t* cmac )
+{
+ if( ( buffer == NULL ) || ( cmac == NULL ) )
+ {
+ return SECURE_ELEMENT_ERROR_NPE;
+ }
+
+ uint8_t Cmac[16];
+
+ AES_CMAC_Init( SeNvmCtx.AesCmacCtx );
+
+ Key_t* keyItem;
+ SecureElementStatus_t retval = GetKeyByID( keyID, &keyItem );
+
+ if( retval == SECURE_ELEMENT_SUCCESS )
+ {
+ AES_CMAC_SetKey( SeNvmCtx.AesCmacCtx, keyItem->KeyValue );
+
+ if( micBxBuffer != NULL )
+ {
+ AES_CMAC_Update( SeNvmCtx.AesCmacCtx, micBxBuffer, 16 );
+ }
+
+ AES_CMAC_Update( SeNvmCtx.AesCmacCtx, buffer, size );
+
+ AES_CMAC_Final( Cmac, SeNvmCtx.AesCmacCtx );
+
+ // Bring into the required format
+ *cmac = ( uint32_t )( ( uint32_t ) Cmac[3] << 24 | ( uint32_t ) Cmac[2] << 16 | ( uint32_t ) Cmac[1] << 8 | ( uint32_t ) Cmac[0] );
+ }
+
+ return retval;
+}
+
+/*
+ * API functions
+ */
+
+SecureElementStatus_t SecureElementInit( SecureElementNvmEvent seNvmCtxChanged )
+{
+ uint8_t itr = 0;
+ uint8_t zeroKey[16] = { 0 };
+
+ // Initialize with defaults
+ SeNvmCtx.KeyList[itr++].KeyID = APP_KEY;
+ SeNvmCtx.KeyList[itr++].KeyID = GEN_APP_KEY;
+ SeNvmCtx.KeyList[itr++].KeyID = NWK_KEY;
+ SeNvmCtx.KeyList[itr++].KeyID = J_S_INT_KEY;
+ SeNvmCtx.KeyList[itr++].KeyID = J_S_ENC_KEY;
+ SeNvmCtx.KeyList[itr++].KeyID = F_NWK_S_INT_KEY;
+ SeNvmCtx.KeyList[itr++].KeyID = S_NWK_S_INT_KEY;
+ SeNvmCtx.KeyList[itr++].KeyID = NWK_S_ENC_KEY;
+ SeNvmCtx.KeyList[itr++].KeyID = APP_S_KEY;
+ SeNvmCtx.KeyList[itr++].KeyID = MC_ROOT_KEY;
+ SeNvmCtx.KeyList[itr++].KeyID = MC_KE_KEY;
+ SeNvmCtx.KeyList[itr++].KeyID = MC_KEY_0;
+ SeNvmCtx.KeyList[itr++].KeyID = MC_APP_S_KEY_0;
+ SeNvmCtx.KeyList[itr++].KeyID = MC_NWK_S_KEY_0;
+ SeNvmCtx.KeyList[itr++].KeyID = MC_KEY_1;
+ SeNvmCtx.KeyList[itr++].KeyID = MC_APP_S_KEY_1;
+ SeNvmCtx.KeyList[itr++].KeyID = MC_NWK_S_KEY_1;
+ SeNvmCtx.KeyList[itr++].KeyID = MC_KEY_2;
+ SeNvmCtx.KeyList[itr++].KeyID = MC_APP_S_KEY_2;
+ SeNvmCtx.KeyList[itr++].KeyID = MC_NWK_S_KEY_2;
+ SeNvmCtx.KeyList[itr++].KeyID = MC_KEY_3;
+ SeNvmCtx.KeyList[itr++].KeyID = MC_APP_S_KEY_3;
+ SeNvmCtx.KeyList[itr++].KeyID = MC_NWK_S_KEY_3;
+ SeNvmCtx.KeyList[itr].KeyID = SLOT_RAND_ZERO_KEY;
+
+ // Set standard keys
+ memcpy1( SeNvmCtx.KeyList[itr].KeyValue, zeroKey, KEY_SIZE );
+
+ memset1( SeNvmCtx.DevEui, 0, SE_EUI_SIZE );
+ memset1( SeNvmCtx.JoinEui, 0, SE_EUI_SIZE );
+
+ // Assign callback
+ if( seNvmCtxChanged != 0 )
+ {
+ SeNvmCtxChanged = seNvmCtxChanged;
+ }
+ else
+ {
+ SeNvmCtxChanged = DummyCB;
+ }
+
+ return SECURE_ELEMENT_SUCCESS;
+}
+
+SecureElementStatus_t SecureElementRestoreNvmCtx( void* seNvmCtx )
+{
+ // Restore nvm context
+ if( seNvmCtx != 0 )
+ {
+ memcpy1( ( uint8_t* ) &SeNvmCtx, ( uint8_t* ) seNvmCtx, sizeof( SeNvmCtx ) );
+ return SECURE_ELEMENT_SUCCESS;
+ }
+ else
+ {
+ return SECURE_ELEMENT_ERROR_NPE;
+ }
+}
+
+void* SecureElementGetNvmCtx( size_t* seNvmCtxSize )
+{
+ *seNvmCtxSize = sizeof( SeNvmCtx );
+ return &SeNvmCtx;
+}
+
+SecureElementStatus_t SecureElementSetKey( KeyIdentifier_t keyID, uint8_t* key )
+{
+ if( key == NULL )
+ {
+ return SECURE_ELEMENT_ERROR_NPE;
+ }
+
+ for( uint8_t i = 0; i < NUM_OF_KEYS; i++ )
+ {
+ if( SeNvmCtx.KeyList[i].KeyID == keyID )
+ {
+ if( ( keyID == MC_KEY_0 ) || ( keyID == MC_KEY_1 ) || ( keyID == MC_KEY_2 ) || ( keyID == MC_KEY_3 ) )
+ { // Decrypt the key if its a Mckey
+ SecureElementStatus_t retval = SECURE_ELEMENT_ERROR;
+ uint8_t decryptedKey[16] = { 0 };
+
+ retval = SecureElementAesEncrypt( key, 16, MC_KE_KEY, decryptedKey );
+
+ memcpy1( SeNvmCtx.KeyList[i].KeyValue, decryptedKey, KEY_SIZE );
+ SeNvmCtxChanged( );
+
+ return retval;
+ }
+ else
+ {
+ memcpy1( SeNvmCtx.KeyList[i].KeyValue, key, KEY_SIZE );
+ SeNvmCtxChanged( );
+ return SECURE_ELEMENT_SUCCESS;
+ }
+ }
+ }
+
+ return SECURE_ELEMENT_ERROR_INVALID_KEY_ID;
+}
+
+SecureElementStatus_t SecureElementComputeAesCmac( uint8_t *micBxBuffer, uint8_t *buffer, uint16_t size, KeyIdentifier_t keyID, uint32_t* cmac )
+{
+ if( keyID >= LORAMAC_CRYPTO_MULTICAST_KEYS )
+ {
+ //Never accept multicast key identifier for cmac computation
+ return SECURE_ELEMENT_ERROR_INVALID_KEY_ID;
+ }
+
+ return ComputeCmac( micBxBuffer, buffer, size, keyID, cmac );
+}
+
+SecureElementStatus_t SecureElementVerifyAesCmac( uint8_t* buffer, uint16_t size, uint32_t expectedCmac, KeyIdentifier_t keyID )
+{
+ if( buffer == NULL )
+ {
+ return SECURE_ELEMENT_ERROR_NPE;
+ }
+
+ SecureElementStatus_t retval = SECURE_ELEMENT_ERROR;
+ uint32_t compCmac = 0;
+ retval = ComputeCmac( NULL, buffer, size, keyID, &compCmac );
+ if( retval != SECURE_ELEMENT_SUCCESS )
+ {
+ return retval;
+ }
+
+ if( expectedCmac != compCmac )
+ {
+ retval = SECURE_ELEMENT_FAIL_CMAC;
+ }
+
+ return retval;
+}
+
+SecureElementStatus_t SecureElementAesEncrypt( uint8_t* buffer, uint16_t size, KeyIdentifier_t keyID, uint8_t* encBuffer )
+{
+ if( buffer == NULL || encBuffer == NULL )
+ {
+ return SECURE_ELEMENT_ERROR_NPE;
+ }
+
+ // Check if the size is divisible by 16,
+ if( ( size % 16 ) != 0 )
+ {
+ return SECURE_ELEMENT_ERROR_BUF_SIZE;
+ }
+
+ memset1( SeNvmCtx.AesContext.ksch, '\0', 240 );
+
+ Key_t* pItem;
+ SecureElementStatus_t retval = GetKeyByID( keyID, &pItem );
+
+ if( retval == SECURE_ELEMENT_SUCCESS )
+ {
+ aes_set_key_lora( pItem->KeyValue, 16, &SeNvmCtx.AesContext );
+
+ uint8_t block = 0;
+
+ while( size != 0 )
+ {
+ aes_encrypt_lora( &buffer[block], &encBuffer[block], &SeNvmCtx.AesContext );
+ block = block + 16;
+ size = size - 16;
+ }
+ }
+ return retval;
+}
+
+SecureElementStatus_t SecureElementDeriveAndStoreKey( Version_t version, uint8_t* input, KeyIdentifier_t rootKeyID, KeyIdentifier_t targetKeyID )
+{
+ if( input == NULL )
+ {
+ return SECURE_ELEMENT_ERROR_NPE;
+ }
+
+ SecureElementStatus_t retval = SECURE_ELEMENT_ERROR;
+ uint8_t key[16] = { 0 };
+
+ // In case of MC_KE_KEY, prevent other keys than NwkKey or AppKey for LoRaWAN 1.1 or later
+ if( targetKeyID == MC_KE_KEY )
+ {
+ if( ( ( rootKeyID == APP_KEY ) && ( version.Fields.Minor == 0 ) ) || ( rootKeyID == NWK_KEY ) )
+ {
+ return SECURE_ELEMENT_ERROR_INVALID_KEY_ID;
+ }
+ }
+
+ // Derive key
+ retval = SecureElementAesEncrypt( input, 16, rootKeyID, key );
+ if( retval != SECURE_ELEMENT_SUCCESS )
+ {
+ return retval;
+ }
+
+ // Store key
+ retval = SecureElementSetKey( targetKeyID, key );
+ if( retval != SECURE_ELEMENT_SUCCESS )
+ {
+ return retval;
+ }
+
+ return SECURE_ELEMENT_SUCCESS;
+}
+
+SecureElementStatus_t SecureElementRandomNumber( uint32_t* randomNum )
+{
+ if( randomNum == NULL )
+ {
+ return SECURE_ELEMENT_ERROR_NPE;
+ }
+ *randomNum = Radio.Random( );
+ return SECURE_ELEMENT_SUCCESS;
+}
+
+SecureElementStatus_t SecureElementSetDevEui( uint8_t* devEui )
+{
+ if( devEui == NULL )
+ {
+ return SECURE_ELEMENT_ERROR_NPE;
+ }
+ memcpy1( SeNvmCtx.DevEui, devEui, SE_EUI_SIZE );
+ SeNvmCtxChanged( );
+ return SECURE_ELEMENT_SUCCESS;
+}
+
+uint8_t* SecureElementGetDevEui( void )
+{
+ return SeNvmCtx.DevEui;
+}
+
+SecureElementStatus_t SecureElementSetJoinEui( uint8_t* joinEui )
+{
+ if( joinEui == NULL )
+ {
+ return SECURE_ELEMENT_ERROR_NPE;
+ }
+ memcpy1( SeNvmCtx.JoinEui, joinEui, SE_EUI_SIZE );
+ SeNvmCtxChanged( );
+ return SECURE_ELEMENT_SUCCESS;
+}
+
+uint8_t* SecureElementGetJoinEui( void )
+{
+ return SeNvmCtx.JoinEui;
+}
diff --git a/lib/lora/system/gpio.h b/lib/lora/system/gpio.h
index 95b13593c3..09b30b6034 100644
--- a/lib/lora/system/gpio.h
+++ b/lib/lora/system/gpio.h
@@ -93,7 +93,9 @@ typedef enum
NO_IRQ = 0xFF,
IRQ_RISING_EDGE = GPIO_INTR_POSEDGE,
IRQ_FALLING_EDGE = GPIO_INTR_NEGEDGE,
- IRQ_RISING_FALLING_EDGE = GPIO_INTR_ANYEDGE
+ IRQ_RISING_FALLING_EDGE = GPIO_INTR_ANYEDGE,
+ IRQ_LOW_LEVEL = GPIO_INTR_LOW_LEVEL,
+ IRQ_HIGH_LEVEL = GPIO_INTR_HIGH_LEVEL
}IrqModes;
/*!
@@ -119,7 +121,7 @@ typedef struct
/*!
* GPIO IRQ handler function prototype
*/
-typedef void( GpioIrqHandler )( void );
+typedef void( GpioIrqHandler )( void *);
/*!
* \brief Initializes the given GPIO object
diff --git a/lib/lora/system/spi.h b/lib/lora/system/spi.h
index 62e570c307..25db45fa2e 100644
--- a/lib/lora/system/spi.h
+++ b/lib/lora/system/spi.h
@@ -74,6 +74,10 @@ void SpiFrequency( Spi_t *obj, uint32_t hz );
*/
#if defined(LOPY) || defined (LOPY4) || defined(FIPY)
uint16_t SpiInOut( Spi_t *obj, uint16_t outData );
+void SpiIn0Out16(Spi_t *obj, uint16_t outData);
+uint8_t SpiIn8Out16(Spi_t *obj, uint16_t outData);
+void SpiOutBuf(Spi_t *obj, uint8_t* pData, uint8_t len);
+void SpiInBuf(Spi_t *obj, uint8_t* pData, uint8_t len);
#elif defined(SIPY)
uint8_t SpiInOut(uint32_t spiNum, uint32_t outData);
/*!
diff --git a/lib/lora/system/systime.c b/lib/lora/system/systime.c
new file mode 100644
index 0000000000..7072d52925
--- /dev/null
+++ b/lib/lora/system/systime.c
@@ -0,0 +1,351 @@
+/*!
+ * \file systime.c
+ *
+ * \brief System time functions implementation.
+ *
+ * \copyright Revised BSD License, see section \ref LICENSE.
+ *
+ * \code
+ * ______ _
+ * / _____) _ | |
+ * ( (____ _____ ____ _| |_ _____ ____| |__
+ * \____ \| ___ | (_ _) ___ |/ ___) _ \
+ * _____) ) ____| | | || |_| ____( (___| | | |
+ * (______/|_____)_|_|_| \__)_____)\____)_| |_|
+ * (C)2013-2018 Semtech - STMicroelectronics
+ *
+ * \endcode
+ *
+ * \author Miguel Luis ( Semtech )
+ *
+ * \author Gregory Cristian ( Semtech )
+ *
+ * \author MCD Application Team ( STMicroelectronics International )
+ */
+#include
+#include "rtc-board.h"
+#include "systime.h"
+
+#define END_OF_FEBRUARY_LEAP 60 //31+29
+#define END_OF_JULY_LEAP 213 //31+29+...
+
+#define END_OF_FEBRUARY_NORM 59 //31+28
+#define END_OF_JULY_NORM 212 //31+28+...
+
+#define UNIX_YEAR 68 //1968 is leap year
+
+//UNIX time 0 = start at 01:00:00, 01/01/1970
+#define UNIX_HOUR_OFFSET ( ( TM_DAYS_IN_LEAP_YEAR + TM_DAYS_IN_YEAR ) * TM_SECONDS_IN_1DAY )
+
+/*!
+ * \brief Correction factors
+ */
+#define DAYS_IN_MONTH_CORRECTION_NORM ( (uint32_t )0x99AAA0 )
+#define DAYS_IN_MONTH_CORRECTION_LEAP ( (uint32_t )0x445550 )
+
+
+/* 365.25 = (366 + 365 + 365 + 365)/4 */
+#define DIV_365_25( X ) ( ( ( X ) * 91867 + 22750 ) >> 25 )
+
+#define DIV_APPROX_86400( X ) ( ( ( X ) >> 18 ) + ( ( X ) >> 17 ) )
+
+#define DIV_APPROX_1000( X ) ( ( ( X ) >> 10 ) +( ( X ) >> 16 ) + ( ( X ) >> 17 ) )
+
+#define DIV_APPROX_60( X ) ( ( ( X ) * 17476 ) >> 20 )
+
+#define DIV_APPROX_61( X ) ( ( ( X ) * 68759 ) >> 22 )
+
+#define MODULO_7( X ) ( ( X ) -( ( ( ( ( X ) + 1 ) * 299593 ) >> 21 ) * 7 ) )
+
+/*!
+ * \brief Calculates ceiling( X / N )
+ */
+#define DIVC( X, N ) ( ( ( X ) + ( N ) -1 ) / ( N ) )
+
+#define DIVC_BY_4( X ) ( ( ( X ) + 3 ) >>2 )
+
+#define DIVC_BY_2( X ) ( ( ( X ) + 1 ) >> 1 )
+
+static uint32_t CalendarGetMonth( uint32_t days, uint32_t year );
+static void CalendarDiv86400( uint32_t in, uint32_t* out, uint32_t* remainder );
+static uint32_t CalendarDiv61( uint32_t in );
+static void CalendarDiv60( uint32_t in, uint32_t* out, uint32_t* remainder );
+
+const char *WeekDayString[]={ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
+
+SysTime_t SysTimeAdd( SysTime_t a, SysTime_t b )
+{
+ SysTime_t c = { .Seconds = 0, .SubSeconds = 0 };
+
+ c.Seconds = a.Seconds + b.Seconds;
+ c.SubSeconds = a.SubSeconds + b.SubSeconds;
+ if( c.SubSeconds >= 1000 )
+ {
+ c.Seconds++;
+ c.SubSeconds -= 1000;
+ }
+ return c;
+}
+
+SysTime_t SysTimeSub( SysTime_t a, SysTime_t b )
+{
+ SysTime_t c = { .Seconds = 0, .SubSeconds = 0 };
+
+ c.Seconds = a.Seconds - b.Seconds;
+ c.SubSeconds = a.SubSeconds - b.SubSeconds;
+ if( c.SubSeconds < 0 )
+ {
+ c.Seconds--;
+ c.SubSeconds += 1000;
+ }
+ return c;
+}
+
+void SysTimeSet( SysTime_t sysTime )
+{
+ SysTime_t deltaTime;
+
+ SysTime_t calendarTime = { .Seconds = 0, .SubSeconds = 0 };
+
+ calendarTime.Seconds = RtcGetCalendarTime( ( uint16_t* )&calendarTime.SubSeconds );
+
+ // sysTime is epoch
+ deltaTime = SysTimeSub( sysTime, calendarTime );
+
+ RtcBkupWrite( deltaTime.Seconds, ( uint32_t )deltaTime.SubSeconds );
+}
+
+SysTime_t SysTimeGet( void )
+{
+ SysTime_t calendarTime = { .Seconds = 0, .SubSeconds = 0 };
+ SysTime_t sysTime = { .Seconds = 0, .SubSeconds = 0 };
+ SysTime_t deltaTime;
+
+ calendarTime.Seconds = RtcGetCalendarTime( ( uint16_t* )&calendarTime.SubSeconds );
+
+ RtcBkupRead( &deltaTime.Seconds, ( uint32_t* )&deltaTime.SubSeconds );
+
+ sysTime = SysTimeAdd( deltaTime, calendarTime );
+
+ return sysTime;
+}
+
+SysTime_t SysTimeGetMcuTime( void )
+{
+ SysTime_t calendarTime = { .Seconds = 0, .SubSeconds = 0 };
+
+ calendarTime.Seconds = RtcGetCalendarTime( ( uint16_t* )&calendarTime.SubSeconds );
+
+ return calendarTime;
+}
+
+uint32_t SysTimeToMs( SysTime_t sysTime )
+{
+ SysTime_t deltaTime;
+ RtcBkupRead( &deltaTime.Seconds, ( uint32_t* )&deltaTime.SubSeconds );
+ SysTime_t calendarTime = SysTimeSub( sysTime, deltaTime );
+ return calendarTime.Seconds * 1000 + calendarTime.SubSeconds;
+}
+
+SysTime_t SysTimeFromMs( uint32_t timeMs )
+{
+ uint32_t seconds = timeMs / 1000;
+ SysTime_t sysTime = { .Seconds = seconds, .SubSeconds = timeMs - seconds * 1000 };
+ SysTime_t deltaTime = { 0 };
+ RtcBkupRead( &deltaTime.Seconds, ( uint32_t* )&deltaTime.SubSeconds );
+
+ return SysTimeAdd( sysTime, deltaTime );
+}
+
+uint32_t SysTimeMkTime( const struct tm* localtime )
+{
+ uint32_t nbdays;
+ uint32_t nbsecs;
+ uint32_t year = localtime->tm_year - UNIX_YEAR;
+ uint32_t correctionMonth[4] =
+ {
+ DAYS_IN_MONTH_CORRECTION_LEAP,
+ DAYS_IN_MONTH_CORRECTION_NORM,
+ DAYS_IN_MONTH_CORRECTION_NORM,
+ DAYS_IN_MONTH_CORRECTION_NORM
+ };
+
+ nbdays = DIVC( ( TM_DAYS_IN_YEAR * 3 + TM_DAYS_IN_LEAP_YEAR ) * year, 4 );
+
+ nbdays += ( DIVC_BY_2( ( localtime->tm_mon ) * ( 30 + 31 ) ) -
+ ( ( ( correctionMonth[year % 4] >> ( ( localtime->tm_mon ) * 2 ) ) & 0x03 ) ) );
+
+ nbdays += ( localtime->tm_mday - 1 );
+
+ // Convert from days to seconds
+ nbsecs = nbdays * TM_SECONDS_IN_1DAY;
+
+ nbsecs += ( ( uint32_t )localtime->tm_sec +
+ ( ( uint32_t )localtime->tm_min * TM_SECONDS_IN_1MINUTE ) +
+ ( ( uint32_t )localtime->tm_hour * TM_SECONDS_IN_1HOUR ) );
+ return nbsecs - UNIX_HOUR_OFFSET;
+}
+
+
+
+void SysTimeLocalTime( const uint32_t timestamp, struct tm *localtime )
+{
+ uint32_t correctionMonth[4] =
+ {
+ DAYS_IN_MONTH_CORRECTION_LEAP,
+ DAYS_IN_MONTH_CORRECTION_NORM,
+ DAYS_IN_MONTH_CORRECTION_NORM,
+ DAYS_IN_MONTH_CORRECTION_NORM
+ };
+ uint32_t weekDays = 1; // Monday 1st January 1968
+ uint32_t seconds;
+ uint32_t minutes;
+ uint32_t days;
+ uint32_t divOut;
+ uint32_t divReminder;
+
+ CalendarDiv86400( timestamp + UNIX_HOUR_OFFSET, &days, &seconds );
+
+ // Calculates seconds
+ CalendarDiv60( seconds, &minutes, &divReminder );
+ localtime->tm_sec = ( uint8_t )divReminder;
+
+ // Calculates minutes and hours
+ CalendarDiv60( minutes, &divOut, &divReminder);
+ localtime->tm_min = ( uint8_t )divReminder;
+ localtime->tm_hour = ( uint8_t )divOut;
+
+ // Calculates year
+ localtime->tm_year = DIV_365_25( days );
+ days-= DIVC_BY_4( ( TM_DAYS_IN_YEAR * 3 + TM_DAYS_IN_LEAP_YEAR ) * localtime->tm_year );
+
+ localtime->tm_yday = days;
+
+ // Calculates month
+ localtime->tm_mon = CalendarGetMonth( days, localtime->tm_year );
+
+ // calculates weekdays
+ weekDays += DIVC_BY_4( ( localtime->tm_year * 5 ) );
+ weekDays += days;
+ localtime->tm_wday = MODULO_7( weekDays );
+
+ days -= ( DIVC_BY_2( ( localtime->tm_mon ) * ( 30 + 31 ) ) -
+ ( ( ( correctionMonth[localtime->tm_year % 4] >> ( ( localtime->tm_mon ) * 2 ) ) & 0x03 ) ) );
+
+ // Convert 0 to 1 indexed.
+ localtime->tm_mday = days + 1;
+
+ localtime->tm_year += UNIX_YEAR;
+
+ localtime->tm_isdst = -1;
+}
+
+static uint32_t CalendarGetMonth( uint32_t days, uint32_t year )
+{
+ uint32_t month;
+ if( ( year % 4 ) == 0 )
+ { /*leap year*/
+ if( days < END_OF_FEBRUARY_LEAP )
+ { // January or February
+ // month = days * 2 / ( 30 + 31 );
+ month = CalendarDiv61( days * 2 );
+ }
+ else if( days < END_OF_JULY_LEAP )
+ {
+ month = CalendarDiv61( ( days - END_OF_FEBRUARY_LEAP ) * 2 ) + 2;
+ }
+ else
+ {
+ month = CalendarDiv61( ( days - END_OF_JULY_LEAP ) * 2 ) + 7;
+ }
+ }
+ else
+ {
+ if( days < END_OF_FEBRUARY_NORM )
+ { // January or February
+ month = CalendarDiv61( days * 2 );
+ }
+ else if( days < END_OF_JULY_NORM )
+ {
+ month = CalendarDiv61( ( days - END_OF_FEBRUARY_NORM ) * 2 ) + 2;
+ }
+ else
+ {
+ month = CalendarDiv61( ( days - END_OF_JULY_NORM ) * 2 ) + 7;
+ }
+ }
+ return month;
+}
+
+static void CalendarDiv86400( uint32_t in, uint32_t* out, uint32_t* remainder )
+{
+#if 0
+ *remainder = in % SECONDS_IN_1DAY;
+ *out = in / SECONDS_IN_1DAY;
+#else
+ uint32_t outTemp = 0;
+ uint32_t divResult = DIV_APPROX_86400( in );
+
+ while( divResult >=1 )
+ {
+ outTemp += divResult;
+ in -= divResult * 86400;
+ divResult= DIV_APPROX_86400( in );
+ }
+ if( in >= 86400 )
+ {
+ outTemp += 1;
+ in -= 86400;
+ }
+
+ *remainder = in;
+ *out = outTemp;
+#endif
+}
+
+static uint32_t CalendarDiv61( uint32_t in )
+{
+#if 0
+ return( in / 61 );
+#else
+ uint32_t outTemp = 0;
+ uint32_t divResult = DIV_APPROX_61( in );
+ while( divResult >=1 )
+ {
+ outTemp += divResult;
+ in -= divResult * 61;
+ divResult = DIV_APPROX_61( in );
+ }
+ if( in >= 61 )
+ {
+ outTemp += 1;
+ in -= 61;
+ }
+ return outTemp;
+#endif
+}
+
+static void CalendarDiv60( uint32_t in, uint32_t* out, uint32_t* remainder )
+{
+#if 0
+ *remainder = in % 60;
+ *out = in / 60;
+#else
+ uint32_t outTemp = 0;
+ uint32_t divResult = DIV_APPROX_60( in );
+
+ while( divResult >=1 )
+ {
+ outTemp += divResult;
+ in -= divResult * 60;
+ divResult = DIV_APPROX_60( in );
+ }
+ if( in >= 60 )
+ {
+ outTemp += 1;
+ in -= 60;
+ }
+ *remainder = in;
+ *out = outTemp;
+#endif
+}
diff --git a/lib/lora/system/systime.h b/lib/lora/system/systime.h
new file mode 100644
index 0000000000..2cb028fffa
--- /dev/null
+++ b/lib/lora/system/systime.h
@@ -0,0 +1,169 @@
+/*!
+ * \file systime.h
+ *
+ * \brief System time functions implementation.
+ *
+ * \copyright Revised BSD License, see section \ref LICENSE.
+ *
+ * \code
+ * ______ _
+ * / _____) _ | |
+ * ( (____ _____ ____ _| |_ _____ ____| |__
+ * \____ \| ___ | (_ _) ___ |/ ___) _ \
+ * _____) ) ____| | | || |_| ____( (___| | | |
+ * (______/|_____)_|_|_| \__)_____)\____)_| |_|
+ * (C)2013-2018 Semtech - STMicroelectronics
+ *
+ * \endcode
+ *
+ * \author Miguel Luis ( Semtech )
+ *
+ * \author Gregory Cristian ( Semtech )
+ *
+ * \author MCD Application Team ( STMicroelectronics International )
+ */
+#ifndef __SYS_TIME_H__
+#define __SYS_TIME_H__
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include
+#include "time.h"
+
+/*!
+ * \brief Days, Hours, Minutes and seconds of systime.h
+ */
+#define TM_DAYS_IN_LEAP_YEAR ( ( uint32_t ) 366U )
+#define TM_DAYS_IN_YEAR ( ( uint32_t ) 365U )
+#define TM_SECONDS_IN_1DAY ( ( uint32_t )86400U )
+#define TM_SECONDS_IN_1HOUR ( ( uint32_t ) 3600U )
+#define TM_SECONDS_IN_1MINUTE ( ( uint32_t ) 60U )
+#define TM_MINUTES_IN_1HOUR ( ( uint32_t ) 60U )
+#define TM_HOURS_IN_1DAY ( ( uint32_t ) 24U )
+
+
+/*!
+ * \brief Months of systime.h
+ */
+#define TM_MONTH_JANUARY ( ( uint8_t ) 0U )
+#define TM_MONTH_FEBRUARY ( ( uint8_t ) 1U )
+#define TM_MONTH_MARCH ( ( uint8_t ) 2U )
+#define TM_MONTH_APRIL ( ( uint8_t ) 3U )
+#define TM_MONTH_MAY ( ( uint8_t ) 4U )
+#define TM_MONTH_JUNE ( ( uint8_t ) 5U )
+#define TM_MONTH_JULY ( ( uint8_t ) 6U )
+#define TM_MONTH_AUGUST ( ( uint8_t ) 7U )
+#define TM_MONTH_SEPTEMBER ( ( uint8_t ) 8U )
+#define TM_MONTH_OCTOBER ( ( uint8_t ) 9U )
+#define TM_MONTH_NOVEMBER ( ( uint8_t )10U )
+#define TM_MONTH_DECEMBER ( ( uint8_t )11U )
+
+/*!
+ * \brief Week days of systime.h
+ */
+#define TM_WEEKDAY_SUNDAY ( ( uint8_t )0U )
+#define TM_WEEKDAY_MONDAY ( ( uint8_t )1U )
+#define TM_WEEKDAY_TUESDAY ( ( uint8_t )2U )
+#define TM_WEEKDAY_WEDNESDAY ( ( uint8_t )3U )
+#define TM_WEEKDAY_THURSDAY ( ( uint8_t )4U )
+#define TM_WEEKDAY_FRIDAY ( ( uint8_t )5U )
+#define TM_WEEKDAY_SATURDAY ( ( uint8_t )6U )
+
+/*!
+ * \brief Number of seconds elapsed between Unix and GPS epoch
+ */
+#define UNIX_GPS_EPOCH_OFFSET 315964800
+
+/*!
+ * \brief Structure holding the system time in seconds and milliseconds.
+ */
+typedef struct SysTime_s
+{
+ uint32_t Seconds;
+ int16_t SubSeconds;
+}SysTime_t;
+
+/*!
+ * \brief Adds 2 SysTime_t values
+ *
+ * \param a Value
+ * \param b Value to added
+ *
+ * \retval result Addition result (SysTime_t value)
+ */
+SysTime_t SysTimeAdd( SysTime_t a, SysTime_t b );
+
+/*!
+ * \brief Subtracts 2 SysTime_t values
+ *
+ * \param a Value
+ * \param b Value to be subtracted
+ *
+ * \retval result Subtraction result (SysTime_t value)
+ */
+SysTime_t SysTimeSub( SysTime_t a, SysTime_t b );
+
+/*!
+ * \brief Sets new system time
+ *
+ * \param sysTime New seconds/sub-seconds since UNIX epoch origin
+ */
+void SysTimeSet( SysTime_t sysTime );
+
+/*!
+ * \brief Gets current system time
+ *
+ * \retval sysTime Current seconds/sub-seconds since UNIX epoch origin
+ */
+SysTime_t SysTimeGet( void );
+
+/*!
+ * \brief Gets current MCU system time
+ *
+ * \retval sysTime Current seconds/sub-seconds since Mcu started
+ */
+SysTime_t SysTimeGetMcuTime( void );
+
+/*!
+ * Converts the given SysTime to the equivalent RTC value in milliseconds
+ *
+ * \param [IN] sysTime System time to be converted
+ *
+ * \retval timeMs The RTC converted time value in ms
+ */
+uint32_t SysTimeToMs( SysTime_t sysTime );
+
+/*!
+ * Converts the given RTC value in milliseconds to the equivalent SysTime
+ *
+ * \param [IN] timeMs The RTC time value in ms to be converted
+ *
+ * \retval sysTime Converted system time
+ */
+SysTime_t SysTimeFromMs( uint32_t timeMs );
+
+/*!
+ * \brief Convert a calendar time into time since UNIX epoch as a uint32_t.
+ *
+ * \param [IN] localtime Pointer to the object containing the calendar time
+ * \retval timestamp The calendar time as seconds since UNIX epoch.
+ */
+uint32_t SysTimeMkTime( const struct tm* localtime );
+
+/*!
+ * \brief Converts a given time in seconds since UNIX epoch into calendar time.
+ *
+ * \param [IN] timestamp The time since UNIX epoch to convert into calendar time.
+ * \param [OUT] localtime Pointer to the calendar time object which will contain
+ the result of the conversion.
+ */
+void SysTimeLocalTime( const uint32_t timestamp, struct tm *localtime );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // __SYS_TIME_H__
diff --git a/lib/lora/system/timer.c b/lib/lora/system/timer.c
index 26e6b358de..a55c010be5 100644
--- a/lib/lora/system/timer.c
+++ b/lib/lora/system/timer.c
@@ -1,19 +1,30 @@
-/*
- / _____) _ | |
-( (____ _____ ____ _| |_ _____ ____| |__
- \____ \| ___ | (_ _) ___ |/ ___) _ \
- _____) ) ____| | | || |_| ____( (___| | | |
-(______/|_____)_|_|_| \__)_____)\____)_| |_|
- (C)2013 Semtech
-
-Description: Timer objects and scheduling management
-
-License: Revised BSD License, see LICENSE.TXT file include in the project
-
-Maintainer: Miguel Luis and Gregory Cristian
-*/
+/*!
+ * \file timer.c
+ *
+ * \brief Timer objects and scheduling management implementation
+ *
+ * \copyright Revised BSD License, see section \ref LICENSE.
+ *
+ * \code
+ * ______ _
+ * / _____) _ | |
+ * ( (____ _____ ____ _| |_ _____ ____| |__
+ * \____ \| ___ | (_ _) ___ |/ ___) _ \
+ * _____) ) ____| | | || |_| ____( (___| | | |
+ * (______/|_____)_|_|_| \__)_____)\____)_| |_|
+ * (C)2013-2017 Semtech
+ *
+ * \endcode
+ *
+ * \author Miguel Luis ( Semtech )
+ *
+ * \author Gregory Cristian ( Semtech )
+ */
+#include "utilities.h"
#include "board.h"
-#include "timer-board.h"
+#include "rtc-board.h"
+#include "timer.h"
+
#include "modlora.h"
/*!
@@ -21,6 +32,23 @@ Maintainer: Miguel Luis and Gregory Cristian
*/
volatile uint8_t HasLoopedThroughMain = 0;
+/*!
+ * Safely execute call back
+ */
+#define ExecuteCallBack( _callback_, context ) \
+ do \
+ { \
+ if( _callback_ == NULL ) \
+ { \
+ while( 1 ); \
+ } \
+ else \
+ { \
+ /*_callback_( context );*/ \
+ modlora_set_timer_callback(_callback_, context);\
+ } \
+ }while( 0 );
+
/*!
* Timers list head pointer
*/
@@ -35,7 +63,7 @@ static TimerEvent_t *TimerListHead = NULL;
* \param [IN] obj Timer object to be become the new head
* \param [IN] remainingTime Remaining time of the previous head to be replaced
*/
-static void TimerInsertNewHeadTimer( TimerEvent_t *obj, uint32_t remainingTime );
+static void TimerInsertNewHeadTimer( TimerEvent_t *obj );
/*!
* \brief Adds a timer to the list.
@@ -46,7 +74,7 @@ static void TimerInsertNewHeadTimer( TimerEvent_t *obj, uint32_t remainingTime )
* \param [IN] obj Timer object to be added to the list
* \param [IN] remainingTime Remaining time of the running head after which the object may be added
*/
-static void TimerInsertTimer( TimerEvent_t *obj, uint32_t remainingTime );
+static void TimerInsertTimer( TimerEvent_t *obj );
/*!
* \brief Sets a timeout with the duration "timestamp"
@@ -63,226 +91,185 @@ static void TimerSetTimeout( TimerEvent_t *obj );
*/
static bool TimerExists( TimerEvent_t *obj );
-/*!
- * \brief Read the timer value of the currently running timer
- *
- * \retval value current timer value
- */
-TimerTime_t TimerGetValue( void );
-
-
-void TimerInit( TimerEvent_t *obj, void ( *callback )( void ) )
+void TimerInit( TimerEvent_t *obj, void ( *callback )( void *context ) )
{
obj->Timestamp = 0;
obj->ReloadValue = 0;
- obj->IsRunning = false;
+ obj->IsStarted = false;
+ obj->IsNext2Expire = false;
obj->Callback = callback;
+ obj->Context = NULL;
obj->Next = NULL;
}
+void TimerSetContext( TimerEvent_t *obj, void* context )
+{
+ obj->Context = context;
+}
+
IRAM_ATTR void TimerStart( TimerEvent_t *obj )
{
uint32_t elapsedTime = 0;
- uint32_t remainingTime = 0;
- uint32_t ilevel = MICROPY_BEGIN_ATOMIC_SECTION();
+ CRITICAL_SECTION_BEGIN( );
if( ( obj == NULL ) || ( TimerExists( obj ) == true ) )
{
- MICROPY_END_ATOMIC_SECTION(ilevel);
+ CRITICAL_SECTION_END( );
return;
}
obj->Timestamp = obj->ReloadValue;
- obj->IsRunning = false;
+ obj->IsStarted = true;
+ obj->IsNext2Expire = false;
if( TimerListHead == NULL )
{
- TimerInsertNewHeadTimer( obj, obj->Timestamp );
+ RtcSetTimerContext( );
+ // Inserts a timer at time now + obj->Timestamp
+ TimerInsertNewHeadTimer( obj );
}
else
{
- if( TimerListHead->IsRunning == true )
- {
- elapsedTime = TimerGetValue( );
- if( elapsedTime > TimerListHead->Timestamp )
- {
- elapsedTime = TimerListHead->Timestamp; // security but should never occur
- }
- remainingTime = TimerListHead->Timestamp - elapsedTime;
- }
- else
- {
- remainingTime = TimerListHead->Timestamp;
- }
+ elapsedTime = RtcGetTimerElapsedTime( );
+ obj->Timestamp += elapsedTime;
- if( obj->Timestamp < remainingTime )
+ if( obj->Timestamp < TimerListHead->Timestamp )
{
- TimerInsertNewHeadTimer( obj, remainingTime );
+ TimerInsertNewHeadTimer( obj );
}
else
{
- TimerInsertTimer( obj, remainingTime );
+ TimerInsertTimer( obj );
}
}
- MICROPY_END_ATOMIC_SECTION(ilevel);
+ CRITICAL_SECTION_END( );
}
-static IRAM_ATTR void TimerInsertTimer( TimerEvent_t *obj, uint32_t remainingTime )
+static IRAM_ATTR void TimerInsertTimer( TimerEvent_t *obj )
{
- uint32_t aggregatedTimestamp = 0; // hold the sum of timestamps
- uint32_t aggregatedTimestampNext = 0; // hold the sum of timestamps up to the next event
-
- TimerEvent_t* prev = TimerListHead;
- TimerEvent_t* cur = TimerListHead->Next;
+ TimerEvent_t* cur = TimerListHead;
+ TimerEvent_t* next = TimerListHead->Next;
- if( cur == NULL )
- { // obj comes just after the head
- obj->Timestamp -= remainingTime;
- prev->Next = obj;
- obj->Next = NULL;
- }
- else
+ while( cur->Next != NULL )
{
- aggregatedTimestamp = remainingTime;
- aggregatedTimestampNext = remainingTime + cur->Timestamp;
-
- while( prev != NULL )
+ if( obj->Timestamp > next->Timestamp )
{
- if( aggregatedTimestampNext > obj->Timestamp )
- {
- obj->Timestamp -= aggregatedTimestamp;
- if( cur != NULL )
- {
- cur->Timestamp -= obj->Timestamp;
- }
- prev->Next = obj;
- obj->Next = cur;
- break;
- }
- else
- {
- prev = cur;
- cur = cur->Next;
- if( cur == NULL )
- { // obj comes at the end of the list
- aggregatedTimestamp = aggregatedTimestampNext;
- obj->Timestamp -= aggregatedTimestamp;
- prev->Next = obj;
- obj->Next = NULL;
- break;
- }
- else
- {
- aggregatedTimestamp = aggregatedTimestampNext;
- aggregatedTimestampNext = aggregatedTimestampNext + cur->Timestamp;
- }
- }
+ cur = next;
+ next = next->Next;
+ }
+ else
+ {
+ cur->Next = obj;
+ obj->Next = next;
+ return;
}
}
+ cur->Next = obj;
+ obj->Next = NULL;
}
-static IRAM_ATTR void TimerInsertNewHeadTimer( TimerEvent_t *obj, uint32_t remainingTime )
+static IRAM_ATTR void TimerInsertNewHeadTimer( TimerEvent_t *obj )
{
TimerEvent_t* cur = TimerListHead;
if( cur != NULL )
{
- cur->Timestamp = remainingTime - obj->Timestamp;
- cur->IsRunning = false;
+ cur->IsNext2Expire = false;
}
obj->Next = cur;
- obj->IsRunning = true;
TimerListHead = obj;
TimerSetTimeout( TimerListHead );
}
-IRAM_ATTR void TimerIrqHandler( void )
+bool TimerIsStarted( TimerEvent_t *obj )
{
- uint32_t elapsedTime = 0;
+ return obj->IsStarted;
+}
- // when all timers are stopped or expired, TimerListHead is NULL
- if( TimerListHead == NULL )
- {
- return;
- }
+IRAM_ATTR void TimerIrqHandler( void )
+{
+ TimerEvent_t* cur;
+ TimerEvent_t* next;
- elapsedTime = TimerGetValue( );
+ uint32_t old = RtcGetTimerContext( );
+ uint32_t now = RtcSetTimerContext( );
+ uint32_t deltaContext = now - old; // intentional wrap around
- if( elapsedTime >= TimerListHead->Timestamp )
+ // Update timeStamp based upon new Time Reference
+ // because delta context should never exceed 2^32
+ if( TimerListHead != NULL )
{
- TimerListHead->Timestamp = 0;
+ for( cur = TimerListHead; cur->Next != NULL; cur = cur->Next )
+ {
+ next = cur->Next;
+
+ if( next->Timestamp > deltaContext )
+ {
+ next->Timestamp -= deltaContext;
+ }
+ else
+ {
+ next->Timestamp = 0;
+ }
+ }
}
- else
+
+ // Execute immediately the alarm callback
+ if ( TimerListHead != NULL )
{
- TimerListHead->Timestamp -= elapsedTime;
+ cur = TimerListHead;
+ TimerListHead = TimerListHead->Next;
+ cur->IsStarted = false;
+ ExecuteCallBack( cur->Callback, cur->Context );
}
- TimerListHead->IsRunning = false;
-
- while( ( TimerListHead != NULL ) && ( TimerListHead->Timestamp == 0 ) )
+ // Remove all the expired object from the list
+ while( ( TimerListHead != NULL ) && ( TimerListHead->Timestamp < RtcGetTimerElapsedTime( ) ) )
{
- TimerEvent_t* elapsedTimer = TimerListHead;
+ cur = TimerListHead;
TimerListHead = TimerListHead->Next;
-
- if( elapsedTimer->Callback != NULL )
- {
- // Callback will be processed out of the Interrupt context in a Thread
- modlora_set_timer_callback(elapsedTimer->Callback);
- }
+ cur->IsStarted = false;
+ ExecuteCallBack( cur->Callback, cur->Context );
}
- // start the next TimerListHead if it exists
- if( TimerListHead != NULL )
+ // Start the next TimerListHead if it exists AND NOT running
+ if( ( TimerListHead != NULL ) && ( TimerListHead->IsNext2Expire == false ) )
{
- if( TimerListHead->IsRunning != true )
- {
- TimerListHead->IsRunning = true;
- TimerSetTimeout( TimerListHead );
- }
+ TimerSetTimeout( TimerListHead );
}
}
IRAM_ATTR void TimerStop( TimerEvent_t *obj )
{
- uint32_t ilevel = MICROPY_BEGIN_ATOMIC_SECTION();
-
- uint32_t elapsedTime = 0;
- uint32_t remainingTime = 0;
+ CRITICAL_SECTION_BEGIN( );
TimerEvent_t* prev = TimerListHead;
TimerEvent_t* cur = TimerListHead;
- // List is empty or the Obj to stop does not exist
+ // List is empty or the obj to stop does not exist
if( ( TimerListHead == NULL ) || ( obj == NULL ) )
{
- MICROPY_END_ATOMIC_SECTION(ilevel);
+ CRITICAL_SECTION_END( );
return;
}
+ obj->IsStarted = false;
+
if( TimerListHead == obj ) // Stop the Head
{
- if( TimerListHead->IsRunning == true ) // The head is already running
+ if( TimerListHead->IsNext2Expire == true ) // The head is already running
{
- elapsedTime = TimerGetValue( );
- if( elapsedTime > obj->Timestamp )
- {
- elapsedTime = obj->Timestamp;
- }
-
- remainingTime = obj->Timestamp - elapsedTime;
-
+ TimerListHead->IsNext2Expire = false;
if( TimerListHead->Next != NULL )
{
- TimerListHead->IsRunning = false;
TimerListHead = TimerListHead->Next;
- TimerListHead->Timestamp += remainingTime;
- TimerListHead->IsRunning = true;
TimerSetTimeout( TimerListHead );
}
else
{
+ RtcStopAlarm( );
TimerListHead = NULL;
}
}
@@ -290,9 +277,7 @@ IRAM_ATTR void TimerStop( TimerEvent_t *obj )
{
if( TimerListHead->Next != NULL )
{
- remainingTime = obj->Timestamp;
TimerListHead = TimerListHead->Next;
- TimerListHead->Timestamp += remainingTime;
}
else
{
@@ -302,8 +287,6 @@ IRAM_ATTR void TimerStop( TimerEvent_t *obj )
}
else // Stop an object within the list
{
- remainingTime = obj->Timestamp;
-
while( cur != NULL )
{
if( cur == obj )
@@ -312,7 +295,6 @@ IRAM_ATTR void TimerStop( TimerEvent_t *obj )
{
cur = cur->Next;
prev->Next = cur;
- cur->Timestamp += remainingTime;
}
else
{
@@ -328,7 +310,7 @@ IRAM_ATTR void TimerStop( TimerEvent_t *obj )
}
}
}
- MICROPY_END_ATOMIC_SECTION(ilevel);
+ CRITICAL_SECTION_END( );
}
static IRAM_ATTR bool TimerExists( TimerEvent_t *obj )
@@ -354,35 +336,67 @@ void TimerReset( TimerEvent_t *obj )
void IRAM_ATTR TimerSetValue( TimerEvent_t *obj, uint32_t value )
{
+ uint32_t minValue = 0;
+ uint32_t ticks = RtcMs2Tick( value );
+
TimerStop( obj );
- obj->Timestamp = value;
- obj->ReloadValue = value;
+
+ minValue = RtcGetMinimumTimeout( );
+
+ if( ticks < minValue )
+ {
+ ticks = minValue;
+ }
+
+ obj->Timestamp = ticks;
+ obj->ReloadValue = ticks;
}
-IRAM_ATTR TimerTime_t TimerGetValue( void )
+TimerTime_t TimerGetCurrentTime( void )
{
- return TimerHwGetElapsedTime( );
+ uint32_t now = RtcGetTimerValue( );
+ return RtcTick2Ms( now );
}
-IRAM_ATTR TimerTime_t TimerGetCurrentTime( void )
+TimerTime_t TimerGetElapsedTime( TimerTime_t past )
{
- return TimerHwGetTime( );
+ if ( past == 0 )
+ {
+ return 0;
+ }
+ uint32_t nowInTicks = RtcGetTimerValue( );
+ uint32_t pastInTicks = RtcMs2Tick( past );
+
+ // Intentional wrap around. Works Ok if tick duration below 1ms
+ return RtcTick2Ms( nowInTicks - pastInTicks );
}
static IRAM_ATTR void TimerSetTimeout( TimerEvent_t *obj )
{
- HasLoopedThroughMain = 0;
- TimerHwStart( obj->Timestamp );
+ int32_t minTicks= RtcGetMinimumTimeout( );
+ obj->IsNext2Expire = true;
+
+ // In case deadline too soon
+ if( obj->Timestamp < ( RtcGetTimerElapsedTime( ) + minTicks ) )
+ {
+ obj->Timestamp = RtcGetTimerElapsedTime( ) + minTicks;
+ }
+ RtcSetAlarm( obj->Timestamp );
+}
+
+TimerTime_t TimerTempCompensation( TimerTime_t period, float temperature )
+{
+ return RtcTempCompensation( period, temperature );
}
-IRAM_ATTR TimerTime_t TimerGetElapsedTime( TimerTime_t savedTime )
+void TimerProcess( void )
{
- return TimerHwComputeTimeDifference( savedTime );
+ RtcProcess( );
}
void TimerLowPowerHandler( void )
{
- if( ( TimerListHead != NULL ) && ( TimerListHead->IsRunning == true ) )
+ if( ( TimerListHead != NULL ) && ( TimerListHead->IsStarted == true ) )
{
if( HasLoopedThroughMain < 5 )
{
diff --git a/lib/lora/system/timer.h b/lib/lora/system/timer.h
index c478c4a7ae..96b25e37a4 100644
--- a/lib/lora/system/timer.h
+++ b/lib/lora/system/timer.h
@@ -1,30 +1,49 @@
-/*
- / _____) _ | |
-( (____ _____ ____ _| |_ _____ ____| |__
- \____ \| ___ | (_ _) ___ |/ ___) _ \
- _____) ) ____| | | || |_| ____( (___| | | |
-(______/|_____)_|_|_| \__)_____)\____)_| |_|
- (C)2013 Semtech
-
-Description: Timer objects and scheduling management
-
-License: Revised BSD License, see LICENSE.TXT file include in the project
-
-Maintainer: Miguel Luis and Gregory Cristian
-*/
+/*!
+ * \file timer.h
+ *
+ * \brief Timer objects and scheduling management implementation
+ *
+ * \copyright Revised BSD License, see section \ref LICENSE.
+ *
+ * \code
+ * ______ _
+ * / _____) _ | |
+ * ( (____ _____ ____ _| |_ _____ ____| |__
+ * \____ \| ___ | (_ _) ___ |/ ___) _ \
+ * _____) ) ____| | | || |_| ____( (___| | | |
+ * (______/|_____)_|_|_| \__)_____)\____)_| |_|
+ * (C)2013-2017 Semtech
+ *
+ * \endcode
+ *
+ * \author Miguel Luis ( Semtech )
+ *
+ * \author Gregory Cristian ( Semtech )
+ */
#ifndef __TIMER_H__
#define __TIMER_H__
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include
+#include
+#include
+
/*!
* \brief Timer object description
*/
typedef struct TimerEvent_s
{
- uint32_t Timestamp; //! Current timer value
- uint32_t ReloadValue; //! Timer delay value
- bool IsRunning; //! Is the timer currently running
- void ( *Callback )( void ); //! Timer IRQ callback function
- struct TimerEvent_s *Next; //! Pointer to the next Timer object.
+ uint32_t Timestamp; //! Current timer value
+ uint32_t ReloadValue; //! Timer delay value
+ bool IsStarted; //! Is the timer currently running
+ bool IsNext2Expire; //! Is the next timer to expire
+ void ( *Callback )( void* context ); //! Timer IRQ callback function
+ void *Context; //! User defined data object pointer to pass back
+ struct TimerEvent_s *Next; //! Pointer to the next Timer object.
}TimerEvent_t;
/*!
@@ -32,6 +51,7 @@ typedef struct TimerEvent_s
*/
#ifndef TimerTime_t
typedef uint32_t TimerTime_t;
+#define TIMERTIME_T_MAX ( ( uint32_t )~0 )
#endif
/*!
@@ -43,7 +63,15 @@ typedef uint32_t TimerTime_t;
* \param [IN] obj Structure containing the timer object parameters
* \param [IN] callback Function callback called at the end of the timeout
*/
-void TimerInit( TimerEvent_t *obj, void ( *callback )( void ) );
+void TimerInit( TimerEvent_t *obj, void ( *callback )( void *context ) );
+
+/*!
+ * \brief Sets a user defined object pointer
+ *
+ * \param [IN] context User defined data object pointer to pass back
+ * on IRQ handler callback
+ */
+void TimerSetContext( TimerEvent_t *obj, void* context );
/*!
* Timer IRQ event handler
@@ -57,6 +85,16 @@ void TimerIrqHandler( void );
*/
void TimerStart( TimerEvent_t *obj );
+/*!
+ * \brief Checks if the provided timer is running
+ *
+ * \param [IN] obj Structure containing the timer object parameters
+ *
+ * \retval status returns the timer activity status [true: Started,
+ * false: Stopped]
+ */
+bool TimerIsStarted( TimerEvent_t *obj );
+
/*!
* \brief Stops and removes the timer object from the list of timer events
*
@@ -89,14 +127,36 @@ TimerTime_t TimerGetCurrentTime( void );
/*!
* \brief Return the Time elapsed since a fix moment in Time
*
- * \param [IN] savedTime fix moment in Time
+ * \remark TimerGetElapsedTime will return 0 for argument 0.
+ *
+ * \param [IN] past fix moment in Time
* \retval time returns elapsed time
*/
-TimerTime_t TimerGetElapsedTime( TimerTime_t savedTime );
+TimerTime_t TimerGetElapsedTime( TimerTime_t past );
+
+/*!
+ * \brief Computes the temperature compensation for a period of time on a
+ * specific temperature.
+ *
+ * \param [IN] period Time period to compensate
+ * \param [IN] temperature Current temperature
+ *
+ * \retval Compensated time period
+ */
+TimerTime_t TimerTempCompensation( TimerTime_t period, float temperature );
+
+/*!
+ * \brief Processes pending timer events
+ */
+void TimerProcess( void );
/*!
* \brief Manages the entry into ARM cortex deep-sleep mode
*/
void TimerLowPowerHandler( void );
-#endif // __TIMER_H__
+#ifdef __cplusplus
+}
+#endif
+
+#endif // __TIMER_H__
diff --git a/lib/lwip b/lib/lwip
index 92f23d6ca0..159e31b689 160000
--- a/lib/lwip
+++ b/lib/lwip
@@ -1 +1 @@
-Subproject commit 92f23d6ca0971a32f2085b9480e738d34174417b
+Subproject commit 159e31b689577dbf69cf0683bbaffbd71fa5ee10
diff --git a/lib/mbedtls b/lib/mbedtls
new file mode 160000
index 0000000000..3f8d78411a
--- /dev/null
+++ b/lib/mbedtls
@@ -0,0 +1 @@
+Subproject commit 3f8d78411a26e833db18d9fbde0e2f0baeda87f0
diff --git a/lib/mbedtls_errors/README.md b/lib/mbedtls_errors/README.md
new file mode 100644
index 0000000000..0e13021eb1
--- /dev/null
+++ b/lib/mbedtls_errors/README.md
@@ -0,0 +1,42 @@
+MBEDTLS Error Strings for MicroPython
+=====================================
+
+This directory contains source code and tools to rework the Mbedtls error strings for
+micropython to use less space. In short, instead of storing and printing something like
+"SSL - Our own certificate(s) is/are too large to send in an SSL message" it prints
+the name of the error #define, which would be "MBEDTLS_ERR_SSL_CERTIFICATE_TOO_LARGE" in
+this case, and only stores `SSL_CERTIFICATE_TOO_LARGE` in flash. The exact Mbedtls error
+defines are used because they're easy to search for to find more detailed information.
+
+Mbedtls defines a specific format for error value #defines and
+includes a Perl script to gather all `MBEDTLS_ERR` defines from includes files together with
+english error text. From that the Perl script generates `mbedtls_strerror()`. The files in this
+directory modify this process to produce a more space efficient error lookup table with
+shorter error strings.
+
+The files are as follows:
+- `generate_errors.diff` - diff for original mbedtls perl script
+- `error.fmt` - modified code template for MicroPython
+- `mp_mbedtls_errors.c` - source file with `mbedtls_strerror` this is built using the include
+ files in `../mbedtls`
+- `do-mp.sh` - shell script to produce `mp_mbedtls_errors.c`
+- `tester.c` - simple C main to test `mp_mbedtls_errors.c` locally on a dev box
+- `do-test.sh` - shell script to produce `mp_mbedtls_errors.c` and compile the `tester` app
+- `do-esp32.sh` - shell script to produce `esp32_mbedtls_errors.c` -- see below
+
+In order not to store multiple copies of `mbedtls_errors.c`
+([https://github.com/micropython/micropython/pull/5819#discussion_r445528006](see))
+it is assumed that all ports use the same version of mbedtls with the same error #defines.
+This is true as of MP v1.13, and ESP-IDF versions 3.3.2 and 4.0.1. If anything changes in the
+future the `do-esp32.sh` script can be used to generate an esp32-specific version.
+
+### How-to
+
+- To build MicroPython all that is needed is to include the `mp_mbedtls_errors.c` into the build
+ (the Makefiles do this automatically). Note that Perl is not needed for routine MicroPython
+ builds.
+- When a new version of Mbedtls is pulled-in the `do-mp.sh` script should be run to
+ re-generate `mp_mbedtls_errors.c`.
+- The `tester` app should be run if changes to the string handling in `error.fmt` are made:
+ it tests that there is not an off-by-one error in the string copying/appending, etc.
+- To include `mbedtls_strerror` error strings define `MBEDTLS_ERROR_C` in the build.
diff --git a/lib/mbedtls_errors/do-esp32.sh b/lib/mbedtls_errors/do-esp32.sh
new file mode 100755
index 0000000000..6fd4682415
--- /dev/null
+++ b/lib/mbedtls_errors/do-esp32.sh
@@ -0,0 +1,7 @@
+#! /bin/bash -e
+# Generate esp32_mbedtls_errors.c for use in the Esp32 port, with the ESP-IDF version of mbedtls
+# The IDF_PATH env var must be set to the top-level dir of ESPIDF
+echo "IDF_PATH=$IDF_PATH"
+MBEDTLS=$IDF_PATH/components/mbedtls/mbedtls
+patch -o esp32_generate_errors.pl $MBEDTLS/scripts/generate_errors.pl
+#endif
+
+#if defined(MBEDTLS_PLATFORM_C)
+#include "mbedtls/platform.h"
+#else
+#define mbedtls_snprintf snprintf
+#define mbedtls_time_t time_t
+#endif
+
+#if defined(MBEDTLS_ERROR_C)
+
+#include
+
+HEADER_INCLUDED
+
+// Error code table type
+struct ssl_errs {
+ int16_t errnum;
+ const char *errstr;
+};
+
+// Table of high level error codes
+static const struct ssl_errs mbedtls_high_level_error_tab[] = {
+// BEGIN generated code
+HIGH_LEVEL_CODE_CHECKS
+// END generated code
+};
+
+static const struct ssl_errs mbedtls_low_level_error_tab[] = {
+// Low level error codes
+//
+// BEGIN generated code
+LOW_LEVEL_CODE_CHECKS
+// END generated code
+};
+
+static const char *mbedtls_err_prefix = "MBEDTLS_ERR_";
+#define MBEDTLS_ERR_PREFIX_LEN ( sizeof("MBEDTLS_ERR_")-1 )
+
+// copy error text into buffer, ensure null termination, return strlen of result
+static size_t mbedtls_err_to_str(int err, const struct ssl_errs tab[], int tab_len, char *buf, size_t buflen) {
+ if (buflen == 0) return 0;
+
+ // prefix for all error names
+ strncpy(buf, mbedtls_err_prefix, buflen);
+ if (buflen <= MBEDTLS_ERR_PREFIX_LEN+1) {
+ buf[buflen-1] = 0;
+ return buflen-1;
+ }
+
+ // append error name from table
+ for (int i = 0; i < tab_len; i++) {
+ if (tab[i].errnum == err) {
+ strncpy(buf+MBEDTLS_ERR_PREFIX_LEN, tab[i].errstr, buflen-MBEDTLS_ERR_PREFIX_LEN);
+ buf[buflen-1] = 0;
+ return strlen(buf);
+ }
+ }
+
+ mbedtls_snprintf(buf+MBEDTLS_ERR_PREFIX_LEN, buflen-MBEDTLS_ERR_PREFIX_LEN, "UNKNOWN (0x%04X)",
+ err);
+ return strlen(buf);
+}
+
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
+
+void mbedtls_strerror(int ret, char *buf, size_t buflen) {
+ int use_ret;
+
+ if (buflen == 0) return;
+
+ buf[buflen-1] = 0;
+
+ if (ret < 0) ret = -ret;
+
+ //
+ // High-level error codes
+ //
+ uint8_t got_hl = (ret & 0xFF80) != 0;
+ if (got_hl) {
+ use_ret = ret & 0xFF80;
+
+ // special case
+#if defined(MBEDTLS_SSL_TLS_C)
+ if (use_ret == -(MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE)) {
+ strncpy(buf, "MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE", buflen);
+ buf[buflen-1] = 0;
+ return;
+ }
+#endif
+
+ size_t len = mbedtls_err_to_str(use_ret, mbedtls_high_level_error_tab,
+ ARRAY_SIZE(mbedtls_high_level_error_tab), buf, buflen);
+
+ buf += len;
+ buflen -= len;
+ if (buflen == 0) return;
+ }
+
+ //
+ // Low-level error codes
+ //
+ use_ret = ret & ~0xFF80;
+
+ if (use_ret == 0) return;
+
+ // If high level code is present, make a concatenation between both error strings.
+ if (got_hl) {
+ if (buflen < 2) return;
+ *buf++ = '+';
+ buflen--;
+ }
+
+ mbedtls_err_to_str(use_ret, mbedtls_low_level_error_tab,
+ ARRAY_SIZE(mbedtls_low_level_error_tab), buf, buflen);
+}
+
+#else /* MBEDTLS_ERROR_C */
+
+#if defined(MBEDTLS_ERROR_STRERROR_DUMMY)
+
+/*
+ * Provide an non-function in case MBEDTLS_ERROR_C is not defined
+ */
+void mbedtls_strerror( int ret, char *buf, size_t buflen )
+{
+ ((void) ret);
+
+ if( buflen > 0 )
+ buf[0] = '\0';
+}
+
+#endif /* MBEDTLS_ERROR_STRERROR_DUMMY */
+
+#endif /* MBEDTLS_ERROR_C */
diff --git a/lib/mbedtls_errors/generate_errors.diff b/lib/mbedtls_errors/generate_errors.diff
new file mode 100644
index 0000000000..ad24c372fa
--- /dev/null
+++ b/lib/mbedtls_errors/generate_errors.diff
@@ -0,0 +1,22 @@
+--- generate_errors_orig.pl 2020-06-20 08:40:38.819060379 -0700
++++ generate_errors.pl 2020-06-20 08:47:26.511163591 -0700
+@@ -162,16 +162,12 @@
+
+ if ($error_name eq "MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE")
+ {
+- ${$code_check} .= "${white_space}if( use_ret == -($error_name) )\n".
+- "${white_space}\{\n".
+- "${white_space} mbedtls_snprintf( buf, buflen, \"$module_name - $description\" );\n".
+- "${white_space} return;\n".
+- "${white_space}}\n"
++ # no-op, this case is hard-coded in error.fmt
+ }
+ else
+ {
+- ${$code_check} .= "${white_space}if( use_ret == -($error_name) )\n".
+- "${white_space} mbedtls_snprintf( buf, buflen, \"$module_name - $description\" );\n"
++ my $error_text = $error_name =~ s/^MBEDTLS_ERR_//r;
++ ${$code_check} .= "${white_space}{ -($error_name), \"$error_text\" },\n"
+ }
+ };
+
diff --git a/lib/mbedtls_errors/mp_mbedtls_errors.c b/lib/mbedtls_errors/mp_mbedtls_errors.c
new file mode 100644
index 0000000000..03a91f0dc9
--- /dev/null
+++ b/lib/mbedtls_errors/mp_mbedtls_errors.c
@@ -0,0 +1,705 @@
+/*
+ * Error message information
+ *
+ * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of mbed TLS (https://tls.mbed.org)
+ */
+
+#if !defined(MBEDTLS_CONFIG_FILE)
+#include "mbedtls/config.h"
+#else
+#include MBEDTLS_CONFIG_FILE
+#endif
+
+#if defined(MBEDTLS_ERROR_C) || defined(MBEDTLS_ERROR_STRERROR_DUMMY)
+#include "mbedtls/error.h"
+#include
+#endif
+
+#if defined(MBEDTLS_PLATFORM_C)
+#include "mbedtls/platform.h"
+#else
+#define mbedtls_snprintf snprintf
+#define mbedtls_time_t time_t
+#endif
+
+#if defined(MBEDTLS_ERROR_C)
+
+#include
+
+#if defined(MBEDTLS_AES_C)
+#include "mbedtls/aes.h"
+#endif
+
+#if defined(MBEDTLS_ARC4_C)
+#include "mbedtls/arc4.h"
+#endif
+
+#if defined(MBEDTLS_ARIA_C)
+#include "mbedtls/aria.h"
+#endif
+
+#if defined(MBEDTLS_BASE64_C)
+#include "mbedtls/base64.h"
+#endif
+
+#if defined(MBEDTLS_BIGNUM_C)
+#include "mbedtls/bignum.h"
+#endif
+
+#if defined(MBEDTLS_BLOWFISH_C)
+#include "mbedtls/blowfish.h"
+#endif
+
+#if defined(MBEDTLS_CAMELLIA_C)
+#include "mbedtls/camellia.h"
+#endif
+
+#if defined(MBEDTLS_CCM_C)
+#include "mbedtls/ccm.h"
+#endif
+
+#if defined(MBEDTLS_CHACHA20_C)
+#include "mbedtls/chacha20.h"
+#endif
+
+#if defined(MBEDTLS_CHACHAPOLY_C)
+#include "mbedtls/chachapoly.h"
+#endif
+
+#if defined(MBEDTLS_CIPHER_C)
+#include "mbedtls/cipher.h"
+#endif
+
+#if defined(MBEDTLS_CMAC_C)
+#include "mbedtls/cmac.h"
+#endif
+
+#if defined(MBEDTLS_CTR_DRBG_C)
+#include "mbedtls/ctr_drbg.h"
+#endif
+
+#if defined(MBEDTLS_DES_C)
+#include "mbedtls/des.h"
+#endif
+
+#if defined(MBEDTLS_DHM_C)
+#include "mbedtls/dhm.h"
+#endif
+
+#if defined(MBEDTLS_ECP_C)
+#include "mbedtls/ecp.h"
+#endif
+
+#if defined(MBEDTLS_ENTROPY_C)
+#include "mbedtls/entropy.h"
+#endif
+
+#if defined(MBEDTLS_GCM_C)
+#include "mbedtls/gcm.h"
+#endif
+
+#if defined(MBEDTLS_HKDF_C)
+#include "mbedtls/hkdf.h"
+#endif
+
+#if defined(MBEDTLS_HMAC_DRBG_C)
+#include "mbedtls/hmac_drbg.h"
+#endif
+
+#if defined(MBEDTLS_MD_C)
+#include "mbedtls/md.h"
+#endif
+
+#if defined(MBEDTLS_MD2_C)
+#include "mbedtls/md2.h"
+#endif
+
+#if defined(MBEDTLS_MD4_C)
+#include "mbedtls/md4.h"
+#endif
+
+#if defined(MBEDTLS_MD5_C)
+#include "mbedtls/md5.h"
+#endif
+
+#if defined(MBEDTLS_NET_C)
+#include "mbedtls/net_sockets.h"
+#endif
+
+#if defined(MBEDTLS_OID_C)
+#include "mbedtls/oid.h"
+#endif
+
+#if defined(MBEDTLS_PADLOCK_C)
+#include "mbedtls/padlock.h"
+#endif
+
+#if defined(MBEDTLS_PEM_PARSE_C) || defined(MBEDTLS_PEM_WRITE_C)
+#include "mbedtls/pem.h"
+#endif
+
+#if defined(MBEDTLS_PK_C)
+#include "mbedtls/pk.h"
+#endif
+
+#if defined(MBEDTLS_PKCS12_C)
+#include "mbedtls/pkcs12.h"
+#endif
+
+#if defined(MBEDTLS_PKCS5_C)
+#include "mbedtls/pkcs5.h"
+#endif
+
+#if defined(MBEDTLS_PLATFORM_C)
+#include "mbedtls/platform.h"
+#endif
+
+#if defined(MBEDTLS_POLY1305_C)
+#include "mbedtls/poly1305.h"
+#endif
+
+#if defined(MBEDTLS_RIPEMD160_C)
+#include "mbedtls/ripemd160.h"
+#endif
+
+#if defined(MBEDTLS_RSA_C)
+#include "mbedtls/rsa.h"
+#endif
+
+#if defined(MBEDTLS_SHA1_C)
+#include "mbedtls/sha1.h"
+#endif
+
+#if defined(MBEDTLS_SHA256_C)
+#include "mbedtls/sha256.h"
+#endif
+
+#if defined(MBEDTLS_SHA512_C)
+#include "mbedtls/sha512.h"
+#endif
+
+#if defined(MBEDTLS_SSL_TLS_C)
+#include "mbedtls/ssl.h"
+#endif
+
+#if defined(MBEDTLS_THREADING_C)
+#include "mbedtls/threading.h"
+#endif
+
+#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C)
+#include "mbedtls/x509.h"
+#endif
+
+#if defined(MBEDTLS_XTEA_C)
+#include "mbedtls/xtea.h"
+#endif
+
+
+// Error code table type
+struct ssl_errs {
+ int16_t errnum;
+ const char *errstr;
+};
+
+// Table of high level error codes
+static const struct ssl_errs mbedtls_high_level_error_tab[] = {
+// BEGIN generated code
+#if defined(MBEDTLS_CIPHER_C)
+ { -(MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE), "CIPHER_FEATURE_UNAVAILABLE" },
+ { -(MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA), "CIPHER_BAD_INPUT_DATA" },
+ { -(MBEDTLS_ERR_CIPHER_ALLOC_FAILED), "CIPHER_ALLOC_FAILED" },
+ { -(MBEDTLS_ERR_CIPHER_INVALID_PADDING), "CIPHER_INVALID_PADDING" },
+ { -(MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED), "CIPHER_FULL_BLOCK_EXPECTED" },
+ { -(MBEDTLS_ERR_CIPHER_AUTH_FAILED), "CIPHER_AUTH_FAILED" },
+ { -(MBEDTLS_ERR_CIPHER_INVALID_CONTEXT), "CIPHER_INVALID_CONTEXT" },
+ { -(MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED), "CIPHER_HW_ACCEL_FAILED" },
+#endif /* MBEDTLS_CIPHER_C */
+
+#if defined(MBEDTLS_DHM_C)
+ { -(MBEDTLS_ERR_DHM_BAD_INPUT_DATA), "DHM_BAD_INPUT_DATA" },
+ { -(MBEDTLS_ERR_DHM_READ_PARAMS_FAILED), "DHM_READ_PARAMS_FAILED" },
+ { -(MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED), "DHM_MAKE_PARAMS_FAILED" },
+ { -(MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED), "DHM_READ_PUBLIC_FAILED" },
+ { -(MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED), "DHM_MAKE_PUBLIC_FAILED" },
+ { -(MBEDTLS_ERR_DHM_CALC_SECRET_FAILED), "DHM_CALC_SECRET_FAILED" },
+ { -(MBEDTLS_ERR_DHM_INVALID_FORMAT), "DHM_INVALID_FORMAT" },
+ { -(MBEDTLS_ERR_DHM_ALLOC_FAILED), "DHM_ALLOC_FAILED" },
+ { -(MBEDTLS_ERR_DHM_FILE_IO_ERROR), "DHM_FILE_IO_ERROR" },
+ { -(MBEDTLS_ERR_DHM_HW_ACCEL_FAILED), "DHM_HW_ACCEL_FAILED" },
+ { -(MBEDTLS_ERR_DHM_SET_GROUP_FAILED), "DHM_SET_GROUP_FAILED" },
+#endif /* MBEDTLS_DHM_C */
+
+#if defined(MBEDTLS_ECP_C)
+ { -(MBEDTLS_ERR_ECP_BAD_INPUT_DATA), "ECP_BAD_INPUT_DATA" },
+ { -(MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL), "ECP_BUFFER_TOO_SMALL" },
+ { -(MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE), "ECP_FEATURE_UNAVAILABLE" },
+ { -(MBEDTLS_ERR_ECP_VERIFY_FAILED), "ECP_VERIFY_FAILED" },
+ { -(MBEDTLS_ERR_ECP_ALLOC_FAILED), "ECP_ALLOC_FAILED" },
+ { -(MBEDTLS_ERR_ECP_RANDOM_FAILED), "ECP_RANDOM_FAILED" },
+ { -(MBEDTLS_ERR_ECP_INVALID_KEY), "ECP_INVALID_KEY" },
+ { -(MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH), "ECP_SIG_LEN_MISMATCH" },
+ { -(MBEDTLS_ERR_ECP_HW_ACCEL_FAILED), "ECP_HW_ACCEL_FAILED" },
+ { -(MBEDTLS_ERR_ECP_IN_PROGRESS), "ECP_IN_PROGRESS" },
+#endif /* MBEDTLS_ECP_C */
+
+#if defined(MBEDTLS_MD_C)
+ { -(MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE), "MD_FEATURE_UNAVAILABLE" },
+ { -(MBEDTLS_ERR_MD_BAD_INPUT_DATA), "MD_BAD_INPUT_DATA" },
+ { -(MBEDTLS_ERR_MD_ALLOC_FAILED), "MD_ALLOC_FAILED" },
+ { -(MBEDTLS_ERR_MD_FILE_IO_ERROR), "MD_FILE_IO_ERROR" },
+ { -(MBEDTLS_ERR_MD_HW_ACCEL_FAILED), "MD_HW_ACCEL_FAILED" },
+#endif /* MBEDTLS_MD_C */
+
+#if defined(MBEDTLS_PEM_PARSE_C) || defined(MBEDTLS_PEM_WRITE_C)
+ { -(MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT), "PEM_NO_HEADER_FOOTER_PRESENT" },
+ { -(MBEDTLS_ERR_PEM_INVALID_DATA), "PEM_INVALID_DATA" },
+ { -(MBEDTLS_ERR_PEM_ALLOC_FAILED), "PEM_ALLOC_FAILED" },
+ { -(MBEDTLS_ERR_PEM_INVALID_ENC_IV), "PEM_INVALID_ENC_IV" },
+ { -(MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG), "PEM_UNKNOWN_ENC_ALG" },
+ { -(MBEDTLS_ERR_PEM_PASSWORD_REQUIRED), "PEM_PASSWORD_REQUIRED" },
+ { -(MBEDTLS_ERR_PEM_PASSWORD_MISMATCH), "PEM_PASSWORD_MISMATCH" },
+ { -(MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE), "PEM_FEATURE_UNAVAILABLE" },
+ { -(MBEDTLS_ERR_PEM_BAD_INPUT_DATA), "PEM_BAD_INPUT_DATA" },
+#endif /* MBEDTLS_PEM_PARSE_C || MBEDTLS_PEM_WRITE_C */
+
+#if defined(MBEDTLS_PK_C)
+ { -(MBEDTLS_ERR_PK_ALLOC_FAILED), "PK_ALLOC_FAILED" },
+ { -(MBEDTLS_ERR_PK_TYPE_MISMATCH), "PK_TYPE_MISMATCH" },
+ { -(MBEDTLS_ERR_PK_BAD_INPUT_DATA), "PK_BAD_INPUT_DATA" },
+ { -(MBEDTLS_ERR_PK_FILE_IO_ERROR), "PK_FILE_IO_ERROR" },
+ { -(MBEDTLS_ERR_PK_KEY_INVALID_VERSION), "PK_KEY_INVALID_VERSION" },
+ { -(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT), "PK_KEY_INVALID_FORMAT" },
+ { -(MBEDTLS_ERR_PK_UNKNOWN_PK_ALG), "PK_UNKNOWN_PK_ALG" },
+ { -(MBEDTLS_ERR_PK_PASSWORD_REQUIRED), "PK_PASSWORD_REQUIRED" },
+ { -(MBEDTLS_ERR_PK_PASSWORD_MISMATCH), "PK_PASSWORD_MISMATCH" },
+ { -(MBEDTLS_ERR_PK_INVALID_PUBKEY), "PK_INVALID_PUBKEY" },
+ { -(MBEDTLS_ERR_PK_INVALID_ALG), "PK_INVALID_ALG" },
+ { -(MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE), "PK_UNKNOWN_NAMED_CURVE" },
+ { -(MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE), "PK_FEATURE_UNAVAILABLE" },
+ { -(MBEDTLS_ERR_PK_SIG_LEN_MISMATCH), "PK_SIG_LEN_MISMATCH" },
+ { -(MBEDTLS_ERR_PK_HW_ACCEL_FAILED), "PK_HW_ACCEL_FAILED" },
+#endif /* MBEDTLS_PK_C */
+
+#if defined(MBEDTLS_PKCS12_C)
+ { -(MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA), "PKCS12_BAD_INPUT_DATA" },
+ { -(MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE), "PKCS12_FEATURE_UNAVAILABLE" },
+ { -(MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT), "PKCS12_PBE_INVALID_FORMAT" },
+ { -(MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH), "PKCS12_PASSWORD_MISMATCH" },
+#endif /* MBEDTLS_PKCS12_C */
+
+#if defined(MBEDTLS_PKCS5_C)
+ { -(MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA), "PKCS5_BAD_INPUT_DATA" },
+ { -(MBEDTLS_ERR_PKCS5_INVALID_FORMAT), "PKCS5_INVALID_FORMAT" },
+ { -(MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE), "PKCS5_FEATURE_UNAVAILABLE" },
+ { -(MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH), "PKCS5_PASSWORD_MISMATCH" },
+#endif /* MBEDTLS_PKCS5_C */
+
+#if defined(MBEDTLS_RSA_C)
+ { -(MBEDTLS_ERR_RSA_BAD_INPUT_DATA), "RSA_BAD_INPUT_DATA" },
+ { -(MBEDTLS_ERR_RSA_INVALID_PADDING), "RSA_INVALID_PADDING" },
+ { -(MBEDTLS_ERR_RSA_KEY_GEN_FAILED), "RSA_KEY_GEN_FAILED" },
+ { -(MBEDTLS_ERR_RSA_KEY_CHECK_FAILED), "RSA_KEY_CHECK_FAILED" },
+ { -(MBEDTLS_ERR_RSA_PUBLIC_FAILED), "RSA_PUBLIC_FAILED" },
+ { -(MBEDTLS_ERR_RSA_PRIVATE_FAILED), "RSA_PRIVATE_FAILED" },
+ { -(MBEDTLS_ERR_RSA_VERIFY_FAILED), "RSA_VERIFY_FAILED" },
+ { -(MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE), "RSA_OUTPUT_TOO_LARGE" },
+ { -(MBEDTLS_ERR_RSA_RNG_FAILED), "RSA_RNG_FAILED" },
+ { -(MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION), "RSA_UNSUPPORTED_OPERATION" },
+ { -(MBEDTLS_ERR_RSA_HW_ACCEL_FAILED), "RSA_HW_ACCEL_FAILED" },
+#endif /* MBEDTLS_RSA_C */
+
+#if defined(MBEDTLS_SSL_TLS_C)
+ { -(MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE), "SSL_FEATURE_UNAVAILABLE" },
+ { -(MBEDTLS_ERR_SSL_BAD_INPUT_DATA), "SSL_BAD_INPUT_DATA" },
+ { -(MBEDTLS_ERR_SSL_INVALID_MAC), "SSL_INVALID_MAC" },
+ { -(MBEDTLS_ERR_SSL_INVALID_RECORD), "SSL_INVALID_RECORD" },
+ { -(MBEDTLS_ERR_SSL_CONN_EOF), "SSL_CONN_EOF" },
+ { -(MBEDTLS_ERR_SSL_UNKNOWN_CIPHER), "SSL_UNKNOWN_CIPHER" },
+ { -(MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN), "SSL_NO_CIPHER_CHOSEN" },
+ { -(MBEDTLS_ERR_SSL_NO_RNG), "SSL_NO_RNG" },
+ { -(MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE), "SSL_NO_CLIENT_CERTIFICATE" },
+ { -(MBEDTLS_ERR_SSL_CERTIFICATE_TOO_LARGE), "SSL_CERTIFICATE_TOO_LARGE" },
+ { -(MBEDTLS_ERR_SSL_CERTIFICATE_REQUIRED), "SSL_CERTIFICATE_REQUIRED" },
+ { -(MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED), "SSL_PRIVATE_KEY_REQUIRED" },
+ { -(MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED), "SSL_CA_CHAIN_REQUIRED" },
+ { -(MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE), "SSL_UNEXPECTED_MESSAGE" },
+ { -(MBEDTLS_ERR_SSL_PEER_VERIFY_FAILED), "SSL_PEER_VERIFY_FAILED" },
+ { -(MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY), "SSL_PEER_CLOSE_NOTIFY" },
+ { -(MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO), "SSL_BAD_HS_CLIENT_HELLO" },
+ { -(MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO), "SSL_BAD_HS_SERVER_HELLO" },
+ { -(MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE), "SSL_BAD_HS_CERTIFICATE" },
+ { -(MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST), "SSL_BAD_HS_CERTIFICATE_REQUEST" },
+ { -(MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE), "SSL_BAD_HS_SERVER_KEY_EXCHANGE" },
+ { -(MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO_DONE), "SSL_BAD_HS_SERVER_HELLO_DONE" },
+ { -(MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE), "SSL_BAD_HS_CLIENT_KEY_EXCHANGE" },
+ { -(MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP), "SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP" },
+ { -(MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS), "SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS" },
+ { -(MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY), "SSL_BAD_HS_CERTIFICATE_VERIFY" },
+ { -(MBEDTLS_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC), "SSL_BAD_HS_CHANGE_CIPHER_SPEC" },
+ { -(MBEDTLS_ERR_SSL_BAD_HS_FINISHED), "SSL_BAD_HS_FINISHED" },
+ { -(MBEDTLS_ERR_SSL_ALLOC_FAILED), "SSL_ALLOC_FAILED" },
+ { -(MBEDTLS_ERR_SSL_HW_ACCEL_FAILED), "SSL_HW_ACCEL_FAILED" },
+ { -(MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH), "SSL_HW_ACCEL_FALLTHROUGH" },
+ { -(MBEDTLS_ERR_SSL_COMPRESSION_FAILED), "SSL_COMPRESSION_FAILED" },
+ { -(MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION), "SSL_BAD_HS_PROTOCOL_VERSION" },
+ { -(MBEDTLS_ERR_SSL_BAD_HS_NEW_SESSION_TICKET), "SSL_BAD_HS_NEW_SESSION_TICKET" },
+ { -(MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED), "SSL_SESSION_TICKET_EXPIRED" },
+ { -(MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH), "SSL_PK_TYPE_MISMATCH" },
+ { -(MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY), "SSL_UNKNOWN_IDENTITY" },
+ { -(MBEDTLS_ERR_SSL_INTERNAL_ERROR), "SSL_INTERNAL_ERROR" },
+ { -(MBEDTLS_ERR_SSL_COUNTER_WRAPPING), "SSL_COUNTER_WRAPPING" },
+ { -(MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO), "SSL_WAITING_SERVER_HELLO_RENEGO" },
+ { -(MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED), "SSL_HELLO_VERIFY_REQUIRED" },
+ { -(MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL), "SSL_BUFFER_TOO_SMALL" },
+ { -(MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE), "SSL_NO_USABLE_CIPHERSUITE" },
+ { -(MBEDTLS_ERR_SSL_WANT_READ), "SSL_WANT_READ" },
+ { -(MBEDTLS_ERR_SSL_WANT_WRITE), "SSL_WANT_WRITE" },
+ { -(MBEDTLS_ERR_SSL_TIMEOUT), "SSL_TIMEOUT" },
+ { -(MBEDTLS_ERR_SSL_CLIENT_RECONNECT), "SSL_CLIENT_RECONNECT" },
+ { -(MBEDTLS_ERR_SSL_UNEXPECTED_RECORD), "SSL_UNEXPECTED_RECORD" },
+ { -(MBEDTLS_ERR_SSL_NON_FATAL), "SSL_NON_FATAL" },
+ { -(MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH), "SSL_INVALID_VERIFY_HASH" },
+ { -(MBEDTLS_ERR_SSL_CONTINUE_PROCESSING), "SSL_CONTINUE_PROCESSING" },
+ { -(MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS), "SSL_ASYNC_IN_PROGRESS" },
+ { -(MBEDTLS_ERR_SSL_EARLY_MESSAGE), "SSL_EARLY_MESSAGE" },
+ { -(MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS), "SSL_CRYPTO_IN_PROGRESS" },
+#endif /* MBEDTLS_SSL_TLS_C */
+
+#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C)
+ { -(MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE), "X509_FEATURE_UNAVAILABLE" },
+ { -(MBEDTLS_ERR_X509_UNKNOWN_OID), "X509_UNKNOWN_OID" },
+ { -(MBEDTLS_ERR_X509_INVALID_FORMAT), "X509_INVALID_FORMAT" },
+ { -(MBEDTLS_ERR_X509_INVALID_VERSION), "X509_INVALID_VERSION" },
+ { -(MBEDTLS_ERR_X509_INVALID_SERIAL), "X509_INVALID_SERIAL" },
+ { -(MBEDTLS_ERR_X509_INVALID_ALG), "X509_INVALID_ALG" },
+ { -(MBEDTLS_ERR_X509_INVALID_NAME), "X509_INVALID_NAME" },
+ { -(MBEDTLS_ERR_X509_INVALID_DATE), "X509_INVALID_DATE" },
+ { -(MBEDTLS_ERR_X509_INVALID_SIGNATURE), "X509_INVALID_SIGNATURE" },
+ { -(MBEDTLS_ERR_X509_INVALID_EXTENSIONS), "X509_INVALID_EXTENSIONS" },
+ { -(MBEDTLS_ERR_X509_UNKNOWN_VERSION), "X509_UNKNOWN_VERSION" },
+ { -(MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG), "X509_UNKNOWN_SIG_ALG" },
+ { -(MBEDTLS_ERR_X509_SIG_MISMATCH), "X509_SIG_MISMATCH" },
+ { -(MBEDTLS_ERR_X509_CERT_VERIFY_FAILED), "X509_CERT_VERIFY_FAILED" },
+ { -(MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT), "X509_CERT_UNKNOWN_FORMAT" },
+ { -(MBEDTLS_ERR_X509_BAD_INPUT_DATA), "X509_BAD_INPUT_DATA" },
+ { -(MBEDTLS_ERR_X509_ALLOC_FAILED), "X509_ALLOC_FAILED" },
+ { -(MBEDTLS_ERR_X509_FILE_IO_ERROR), "X509_FILE_IO_ERROR" },
+ { -(MBEDTLS_ERR_X509_BUFFER_TOO_SMALL), "X509_BUFFER_TOO_SMALL" },
+ { -(MBEDTLS_ERR_X509_FATAL_ERROR), "X509_FATAL_ERROR" },
+#endif /* MBEDTLS_X509_USE_C || MBEDTLS_X509_CREATE_C */
+// END generated code
+};
+
+static const struct ssl_errs mbedtls_low_level_error_tab[] = {
+// Low level error codes
+//
+// BEGIN generated code
+#if defined(MBEDTLS_AES_C)
+ { -(MBEDTLS_ERR_AES_INVALID_KEY_LENGTH), "AES_INVALID_KEY_LENGTH" },
+ { -(MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH), "AES_INVALID_INPUT_LENGTH" },
+ { -(MBEDTLS_ERR_AES_BAD_INPUT_DATA), "AES_BAD_INPUT_DATA" },
+ { -(MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE), "AES_FEATURE_UNAVAILABLE" },
+ { -(MBEDTLS_ERR_AES_HW_ACCEL_FAILED), "AES_HW_ACCEL_FAILED" },
+#endif /* MBEDTLS_AES_C */
+
+#if defined(MBEDTLS_ARC4_C)
+ { -(MBEDTLS_ERR_ARC4_HW_ACCEL_FAILED), "ARC4_HW_ACCEL_FAILED" },
+#endif /* MBEDTLS_ARC4_C */
+
+#if defined(MBEDTLS_ARIA_C)
+ { -(MBEDTLS_ERR_ARIA_BAD_INPUT_DATA), "ARIA_BAD_INPUT_DATA" },
+ { -(MBEDTLS_ERR_ARIA_INVALID_INPUT_LENGTH), "ARIA_INVALID_INPUT_LENGTH" },
+ { -(MBEDTLS_ERR_ARIA_FEATURE_UNAVAILABLE), "ARIA_FEATURE_UNAVAILABLE" },
+ { -(MBEDTLS_ERR_ARIA_HW_ACCEL_FAILED), "ARIA_HW_ACCEL_FAILED" },
+#endif /* MBEDTLS_ARIA_C */
+
+#if defined(MBEDTLS_ASN1_PARSE_C)
+ { -(MBEDTLS_ERR_ASN1_OUT_OF_DATA), "ASN1_OUT_OF_DATA" },
+ { -(MBEDTLS_ERR_ASN1_UNEXPECTED_TAG), "ASN1_UNEXPECTED_TAG" },
+ { -(MBEDTLS_ERR_ASN1_INVALID_LENGTH), "ASN1_INVALID_LENGTH" },
+ { -(MBEDTLS_ERR_ASN1_LENGTH_MISMATCH), "ASN1_LENGTH_MISMATCH" },
+ { -(MBEDTLS_ERR_ASN1_INVALID_DATA), "ASN1_INVALID_DATA" },
+ { -(MBEDTLS_ERR_ASN1_ALLOC_FAILED), "ASN1_ALLOC_FAILED" },
+ { -(MBEDTLS_ERR_ASN1_BUF_TOO_SMALL), "ASN1_BUF_TOO_SMALL" },
+#endif /* MBEDTLS_ASN1_PARSE_C */
+
+#if defined(MBEDTLS_BASE64_C)
+ { -(MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL), "BASE64_BUFFER_TOO_SMALL" },
+ { -(MBEDTLS_ERR_BASE64_INVALID_CHARACTER), "BASE64_INVALID_CHARACTER" },
+#endif /* MBEDTLS_BASE64_C */
+
+#if defined(MBEDTLS_BIGNUM_C)
+ { -(MBEDTLS_ERR_MPI_FILE_IO_ERROR), "MPI_FILE_IO_ERROR" },
+ { -(MBEDTLS_ERR_MPI_BAD_INPUT_DATA), "MPI_BAD_INPUT_DATA" },
+ { -(MBEDTLS_ERR_MPI_INVALID_CHARACTER), "MPI_INVALID_CHARACTER" },
+ { -(MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL), "MPI_BUFFER_TOO_SMALL" },
+ { -(MBEDTLS_ERR_MPI_NEGATIVE_VALUE), "MPI_NEGATIVE_VALUE" },
+ { -(MBEDTLS_ERR_MPI_DIVISION_BY_ZERO), "MPI_DIVISION_BY_ZERO" },
+ { -(MBEDTLS_ERR_MPI_NOT_ACCEPTABLE), "MPI_NOT_ACCEPTABLE" },
+ { -(MBEDTLS_ERR_MPI_ALLOC_FAILED), "MPI_ALLOC_FAILED" },
+#endif /* MBEDTLS_BIGNUM_C */
+
+#if defined(MBEDTLS_BLOWFISH_C)
+ { -(MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA), "BLOWFISH_BAD_INPUT_DATA" },
+ { -(MBEDTLS_ERR_BLOWFISH_INVALID_INPUT_LENGTH), "BLOWFISH_INVALID_INPUT_LENGTH" },
+ { -(MBEDTLS_ERR_BLOWFISH_HW_ACCEL_FAILED), "BLOWFISH_HW_ACCEL_FAILED" },
+#endif /* MBEDTLS_BLOWFISH_C */
+
+#if defined(MBEDTLS_CAMELLIA_C)
+ { -(MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA), "CAMELLIA_BAD_INPUT_DATA" },
+ { -(MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH), "CAMELLIA_INVALID_INPUT_LENGTH" },
+ { -(MBEDTLS_ERR_CAMELLIA_HW_ACCEL_FAILED), "CAMELLIA_HW_ACCEL_FAILED" },
+#endif /* MBEDTLS_CAMELLIA_C */
+
+#if defined(MBEDTLS_CCM_C)
+ { -(MBEDTLS_ERR_CCM_BAD_INPUT), "CCM_BAD_INPUT" },
+ { -(MBEDTLS_ERR_CCM_AUTH_FAILED), "CCM_AUTH_FAILED" },
+ { -(MBEDTLS_ERR_CCM_HW_ACCEL_FAILED), "CCM_HW_ACCEL_FAILED" },
+#endif /* MBEDTLS_CCM_C */
+
+#if defined(MBEDTLS_CHACHA20_C)
+ { -(MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA), "CHACHA20_BAD_INPUT_DATA" },
+ { -(MBEDTLS_ERR_CHACHA20_FEATURE_UNAVAILABLE), "CHACHA20_FEATURE_UNAVAILABLE" },
+ { -(MBEDTLS_ERR_CHACHA20_HW_ACCEL_FAILED), "CHACHA20_HW_ACCEL_FAILED" },
+#endif /* MBEDTLS_CHACHA20_C */
+
+#if defined(MBEDTLS_CHACHAPOLY_C)
+ { -(MBEDTLS_ERR_CHACHAPOLY_BAD_STATE), "CHACHAPOLY_BAD_STATE" },
+ { -(MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED), "CHACHAPOLY_AUTH_FAILED" },
+#endif /* MBEDTLS_CHACHAPOLY_C */
+
+#if defined(MBEDTLS_CMAC_C)
+ { -(MBEDTLS_ERR_CMAC_HW_ACCEL_FAILED), "CMAC_HW_ACCEL_FAILED" },
+#endif /* MBEDTLS_CMAC_C */
+
+#if defined(MBEDTLS_CTR_DRBG_C)
+ { -(MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED), "CTR_DRBG_ENTROPY_SOURCE_FAILED" },
+ { -(MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG), "CTR_DRBG_REQUEST_TOO_BIG" },
+ { -(MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG), "CTR_DRBG_INPUT_TOO_BIG" },
+ { -(MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR), "CTR_DRBG_FILE_IO_ERROR" },
+#endif /* MBEDTLS_CTR_DRBG_C */
+
+#if defined(MBEDTLS_DES_C)
+ { -(MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH), "DES_INVALID_INPUT_LENGTH" },
+ { -(MBEDTLS_ERR_DES_HW_ACCEL_FAILED), "DES_HW_ACCEL_FAILED" },
+#endif /* MBEDTLS_DES_C */
+
+#if defined(MBEDTLS_ENTROPY_C)
+ { -(MBEDTLS_ERR_ENTROPY_SOURCE_FAILED), "ENTROPY_SOURCE_FAILED" },
+ { -(MBEDTLS_ERR_ENTROPY_MAX_SOURCES), "ENTROPY_MAX_SOURCES" },
+ { -(MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED), "ENTROPY_NO_SOURCES_DEFINED" },
+ { -(MBEDTLS_ERR_ENTROPY_NO_STRONG_SOURCE), "ENTROPY_NO_STRONG_SOURCE" },
+ { -(MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR), "ENTROPY_FILE_IO_ERROR" },
+#endif /* MBEDTLS_ENTROPY_C */
+
+#if defined(MBEDTLS_GCM_C)
+ { -(MBEDTLS_ERR_GCM_AUTH_FAILED), "GCM_AUTH_FAILED" },
+ { -(MBEDTLS_ERR_GCM_HW_ACCEL_FAILED), "GCM_HW_ACCEL_FAILED" },
+ { -(MBEDTLS_ERR_GCM_BAD_INPUT), "GCM_BAD_INPUT" },
+#endif /* MBEDTLS_GCM_C */
+
+#if defined(MBEDTLS_HKDF_C)
+ { -(MBEDTLS_ERR_HKDF_BAD_INPUT_DATA), "HKDF_BAD_INPUT_DATA" },
+#endif /* MBEDTLS_HKDF_C */
+
+#if defined(MBEDTLS_HMAC_DRBG_C)
+ { -(MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG), "HMAC_DRBG_REQUEST_TOO_BIG" },
+ { -(MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG), "HMAC_DRBG_INPUT_TOO_BIG" },
+ { -(MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR), "HMAC_DRBG_FILE_IO_ERROR" },
+ { -(MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED), "HMAC_DRBG_ENTROPY_SOURCE_FAILED" },
+#endif /* MBEDTLS_HMAC_DRBG_C */
+
+#if defined(MBEDTLS_MD2_C)
+ { -(MBEDTLS_ERR_MD2_HW_ACCEL_FAILED), "MD2_HW_ACCEL_FAILED" },
+#endif /* MBEDTLS_MD2_C */
+
+#if defined(MBEDTLS_MD4_C)
+ { -(MBEDTLS_ERR_MD4_HW_ACCEL_FAILED), "MD4_HW_ACCEL_FAILED" },
+#endif /* MBEDTLS_MD4_C */
+
+#if defined(MBEDTLS_MD5_C)
+ { -(MBEDTLS_ERR_MD5_HW_ACCEL_FAILED), "MD5_HW_ACCEL_FAILED" },
+#endif /* MBEDTLS_MD5_C */
+
+#if defined(MBEDTLS_NET_C)
+ { -(MBEDTLS_ERR_NET_SOCKET_FAILED), "NET_SOCKET_FAILED" },
+ { -(MBEDTLS_ERR_NET_CONNECT_FAILED), "NET_CONNECT_FAILED" },
+ { -(MBEDTLS_ERR_NET_BIND_FAILED), "NET_BIND_FAILED" },
+ { -(MBEDTLS_ERR_NET_LISTEN_FAILED), "NET_LISTEN_FAILED" },
+ { -(MBEDTLS_ERR_NET_ACCEPT_FAILED), "NET_ACCEPT_FAILED" },
+ { -(MBEDTLS_ERR_NET_RECV_FAILED), "NET_RECV_FAILED" },
+ { -(MBEDTLS_ERR_NET_SEND_FAILED), "NET_SEND_FAILED" },
+ { -(MBEDTLS_ERR_NET_CONN_RESET), "NET_CONN_RESET" },
+ { -(MBEDTLS_ERR_NET_UNKNOWN_HOST), "NET_UNKNOWN_HOST" },
+ { -(MBEDTLS_ERR_NET_BUFFER_TOO_SMALL), "NET_BUFFER_TOO_SMALL" },
+ { -(MBEDTLS_ERR_NET_INVALID_CONTEXT), "NET_INVALID_CONTEXT" },
+ { -(MBEDTLS_ERR_NET_POLL_FAILED), "NET_POLL_FAILED" },
+ { -(MBEDTLS_ERR_NET_BAD_INPUT_DATA), "NET_BAD_INPUT_DATA" },
+#endif /* MBEDTLS_NET_C */
+
+#if defined(MBEDTLS_OID_C)
+ { -(MBEDTLS_ERR_OID_NOT_FOUND), "OID_NOT_FOUND" },
+ { -(MBEDTLS_ERR_OID_BUF_TOO_SMALL), "OID_BUF_TOO_SMALL" },
+#endif /* MBEDTLS_OID_C */
+
+#if defined(MBEDTLS_PADLOCK_C)
+ { -(MBEDTLS_ERR_PADLOCK_DATA_MISALIGNED), "PADLOCK_DATA_MISALIGNED" },
+#endif /* MBEDTLS_PADLOCK_C */
+
+#if defined(MBEDTLS_PLATFORM_C)
+ { -(MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED), "PLATFORM_HW_ACCEL_FAILED" },
+ { -(MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED), "PLATFORM_FEATURE_UNSUPPORTED" },
+#endif /* MBEDTLS_PLATFORM_C */
+
+#if defined(MBEDTLS_POLY1305_C)
+ { -(MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA), "POLY1305_BAD_INPUT_DATA" },
+ { -(MBEDTLS_ERR_POLY1305_FEATURE_UNAVAILABLE), "POLY1305_FEATURE_UNAVAILABLE" },
+ { -(MBEDTLS_ERR_POLY1305_HW_ACCEL_FAILED), "POLY1305_HW_ACCEL_FAILED" },
+#endif /* MBEDTLS_POLY1305_C */
+
+#if defined(MBEDTLS_RIPEMD160_C)
+ { -(MBEDTLS_ERR_RIPEMD160_HW_ACCEL_FAILED), "RIPEMD160_HW_ACCEL_FAILED" },
+#endif /* MBEDTLS_RIPEMD160_C */
+
+#if defined(MBEDTLS_SHA1_C)
+ { -(MBEDTLS_ERR_SHA1_HW_ACCEL_FAILED), "SHA1_HW_ACCEL_FAILED" },
+ { -(MBEDTLS_ERR_SHA1_BAD_INPUT_DATA), "SHA1_BAD_INPUT_DATA" },
+#endif /* MBEDTLS_SHA1_C */
+
+#if defined(MBEDTLS_SHA256_C)
+ { -(MBEDTLS_ERR_SHA256_HW_ACCEL_FAILED), "SHA256_HW_ACCEL_FAILED" },
+ { -(MBEDTLS_ERR_SHA256_BAD_INPUT_DATA), "SHA256_BAD_INPUT_DATA" },
+#endif /* MBEDTLS_SHA256_C */
+
+#if defined(MBEDTLS_SHA512_C)
+ { -(MBEDTLS_ERR_SHA512_HW_ACCEL_FAILED), "SHA512_HW_ACCEL_FAILED" },
+ { -(MBEDTLS_ERR_SHA512_BAD_INPUT_DATA), "SHA512_BAD_INPUT_DATA" },
+#endif /* MBEDTLS_SHA512_C */
+
+#if defined(MBEDTLS_THREADING_C)
+ { -(MBEDTLS_ERR_THREADING_FEATURE_UNAVAILABLE), "THREADING_FEATURE_UNAVAILABLE" },
+ { -(MBEDTLS_ERR_THREADING_BAD_INPUT_DATA), "THREADING_BAD_INPUT_DATA" },
+ { -(MBEDTLS_ERR_THREADING_MUTEX_ERROR), "THREADING_MUTEX_ERROR" },
+#endif /* MBEDTLS_THREADING_C */
+
+#if defined(MBEDTLS_XTEA_C)
+ { -(MBEDTLS_ERR_XTEA_INVALID_INPUT_LENGTH), "XTEA_INVALID_INPUT_LENGTH" },
+ { -(MBEDTLS_ERR_XTEA_HW_ACCEL_FAILED), "XTEA_HW_ACCEL_FAILED" },
+#endif /* MBEDTLS_XTEA_C */
+// END generated code
+};
+
+static const char *mbedtls_err_prefix = "MBEDTLS_ERR_";
+#define MBEDTLS_ERR_PREFIX_LEN ( sizeof("MBEDTLS_ERR_")-1 )
+
+// copy error text into buffer, ensure null termination, return strlen of result
+static size_t mbedtls_err_to_str(int err, const struct ssl_errs tab[], int tab_len, char *buf, size_t buflen) {
+ if (buflen == 0) return 0;
+
+ // prefix for all error names
+ strncpy(buf, mbedtls_err_prefix, buflen);
+ if (buflen <= MBEDTLS_ERR_PREFIX_LEN+1) {
+ buf[buflen-1] = 0;
+ return buflen-1;
+ }
+
+ // append error name from table
+ for (int i = 0; i < tab_len; i++) {
+ if (tab[i].errnum == err) {
+ strncpy(buf+MBEDTLS_ERR_PREFIX_LEN, tab[i].errstr, buflen-MBEDTLS_ERR_PREFIX_LEN);
+ buf[buflen-1] = 0;
+ return strlen(buf);
+ }
+ }
+
+ mbedtls_snprintf(buf+MBEDTLS_ERR_PREFIX_LEN, buflen-MBEDTLS_ERR_PREFIX_LEN, "UNKNOWN (0x%04X)",
+ err);
+ return strlen(buf);
+}
+
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
+
+void mbedtls_strerror(int ret, char *buf, size_t buflen) {
+ int use_ret;
+
+ if (buflen == 0) return;
+
+ buf[buflen-1] = 0;
+
+ if (ret < 0) ret = -ret;
+
+ //
+ // High-level error codes
+ //
+ uint8_t got_hl = (ret & 0xFF80) != 0;
+ if (got_hl) {
+ use_ret = ret & 0xFF80;
+
+ // special case
+#if defined(MBEDTLS_SSL_TLS_C)
+ if (use_ret == -(MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE)) {
+ strncpy(buf, "MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE", buflen);
+ buf[buflen-1] = 0;
+ return;
+ }
+#endif
+
+ size_t len = mbedtls_err_to_str(use_ret, mbedtls_high_level_error_tab,
+ ARRAY_SIZE(mbedtls_high_level_error_tab), buf, buflen);
+
+ buf += len;
+ buflen -= len;
+ if (buflen == 0) return;
+ }
+
+ //
+ // Low-level error codes
+ //
+ use_ret = ret & ~0xFF80;
+
+ if (use_ret == 0) return;
+
+ // If high level code is present, make a concatenation between both error strings.
+ if (got_hl) {
+ if (buflen < 2) return;
+ *buf++ = '+';
+ buflen--;
+ }
+
+ mbedtls_err_to_str(use_ret, mbedtls_low_level_error_tab,
+ ARRAY_SIZE(mbedtls_low_level_error_tab), buf, buflen);
+}
+
+#else /* MBEDTLS_ERROR_C */
+
+#if defined(MBEDTLS_ERROR_STRERROR_DUMMY)
+
+/*
+ * Provide an non-function in case MBEDTLS_ERROR_C is not defined
+ */
+void mbedtls_strerror( int ret, char *buf, size_t buflen )
+{
+ ((void) ret);
+
+ if( buflen > 0 )
+ buf[0] = '\0';
+}
+
+#endif /* MBEDTLS_ERROR_STRERROR_DUMMY */
+
+#endif /* MBEDTLS_ERROR_C */
diff --git a/lib/mbedtls_errors/tester.c b/lib/mbedtls_errors/tester.c
new file mode 100644
index 0000000000..6f1c788f50
--- /dev/null
+++ b/lib/mbedtls_errors/tester.c
@@ -0,0 +1,58 @@
+#include "mbedtls/error.h"
+#include
+#include
+
+// test_code checks that the provided code results in the provided error string for any size
+// buffer. It calls mbedtls_strerror() to fill a buffer that is from 1 to 100 bytes in length
+// and then checks that the buffer contents is OK and that a few guard bytes before and after
+// the buffer were not overwritten.
+int test_code(int code, char *str) {
+ char buf[100];
+ int ok = 1;
+ int res;
+
+ // test zero-length buffer
+ memset(buf, -3, 100);
+ mbedtls_strerror(code, buf + 4, 0);
+ for (int i = 0; i < 10; i++) {
+ if (buf[i] != -3) {
+ printf("Error: guard overwritten buflen=0 i=%d buf[i]=%d\n", i, buf[i]);
+ ok = 0;
+ }
+ }
+
+ // test
+ for (size_t buflen = 1; buflen < 90; buflen++) {
+ memset(buf, -3, 100);
+ mbedtls_strerror(code, buf + 4, buflen);
+ for (int i = 0; i < 4; i++) {
+ if (buf[i] != -3) {
+ printf("Error: pre-guard overwritten buflen=%d i=%d buf[i]=%d\n", buflen, i, buf[i]);
+ ok = 0;
+ }
+ }
+ for (int i = 4 + buflen; i < 100; i++) {
+ if (buf[i] != -3) {
+ printf("Error: post-guard overwritten buflen=%d i=%d buf[i]=%d\n", buflen, i, buf[i]);
+ ok = 0;
+ }
+ }
+ char exp[100];
+ strncpy(exp, str, buflen);
+ exp[buflen - 1] = 0;
+ if (strcmp(buf + 4, exp) != 0) {
+ printf("Error: expected %s, got %s\n", exp, buf);
+ ok = 0;
+ }
+ }
+
+ printf("Test %x -> %s is %s\n", code, str, ok?"OK":"*** BAD ***");
+}
+
+int main() {
+ test_code(0x7200, "MBEDTLS_ERR_SSL_INVALID_RECORD");
+ test_code(0x7780, "MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE");
+ test_code(0x0074, "MBEDTLS_ERR_SHA256_BAD_INPUT_DATA");
+ test_code(0x6600 | 0x0074, "MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH+MBEDTLS_ERR_SHA256_BAD_INPUT_DATA");
+ test_code(103, "MBEDTLS_ERR_UNKNOWN (0x0067)");
+}
diff --git a/lib/mp-readline/readline.c b/lib/mp-readline/readline.c
index 9d254d8cfe..296c8aa4ab 100644
--- a/lib/mp-readline/readline.c
+++ b/lib/mp-readline/readline.c
@@ -74,6 +74,7 @@ STATIC void mp_hal_move_cursor_back(uint pos) {
// snprintf needs space for the terminating null character
int n = snprintf(&vt100_command[0], sizeof(vt100_command), "\x1b[%u", pos);
if (n > 0) {
+ assert((unsigned)n < sizeof(vt100_command));
vt100_command[n] = 'D'; // replace null char
mp_hal_stdout_tx_strn(vt100_command, n + 1);
}
@@ -98,6 +99,35 @@ typedef struct _readline_t {
STATIC readline_t rl;
+#if MICROPY_REPL_EMACS_WORDS_MOVE
+STATIC size_t cursor_count_word(int forward) {
+ const char *line_buf = vstr_str(rl.line);
+ size_t pos = rl.cursor_pos;
+ bool in_word = false;
+
+ for (;;) {
+ // if moving backwards and we've reached 0... break
+ if (!forward && pos == 0) {
+ break;
+ }
+ // or if moving forwards and we've reached to the end of line... break
+ else if (forward && pos == vstr_len(rl.line)) {
+ break;
+ }
+
+ if (unichar_isalnum(line_buf[pos + (forward - 1)])) {
+ in_word = true;
+ } else if (in_word) {
+ break;
+ }
+
+ pos += forward ? forward : -1;
+ }
+
+ return forward ? pos - rl.cursor_pos : rl.cursor_pos - pos;
+}
+#endif
+
int readline_process_char(int c) {
size_t last_line_len = rl.line->len;
int redraw_step_back = 0;
@@ -148,6 +178,10 @@ int readline_process_char(int c) {
redraw_step_back = rl.cursor_pos - rl.orig_line_len;
redraw_from_cursor = true;
#endif
+ #if MICROPY_REPL_EMACS_EXTRA_WORDS_MOVE
+ } else if (c == CHAR_CTRL_W) {
+ goto backward_kill_word;
+ #endif
} else if (c == '\r') {
// newline
mp_hal_stdout_tx_str("\r\n");
@@ -221,9 +255,40 @@ int readline_process_char(int c) {
case 'O':
rl.escape_seq = ESEQ_ESC_O;
break;
+ #if MICROPY_REPL_EMACS_WORDS_MOVE
+ case 'b':
+#if MICROPY_REPL_EMACS_EXTRA_WORDS_MOVE
+backward_word:
+#endif
+ redraw_step_back = cursor_count_word(0);
+ rl.escape_seq = ESEQ_NONE;
+ break;
+ case 'f':
+#if MICROPY_REPL_EMACS_EXTRA_WORDS_MOVE
+forward_word:
+#endif
+ redraw_step_forward = cursor_count_word(1);
+ rl.escape_seq = ESEQ_NONE;
+ break;
+ case 'd':
+ vstr_cut_out_bytes(rl.line, rl.cursor_pos, cursor_count_word(1));
+ redraw_from_cursor = true;
+ rl.escape_seq = ESEQ_NONE;
+ break;
+ case 127:
+#if MICROPY_REPL_EMACS_EXTRA_WORDS_MOVE
+backward_kill_word:
+#endif
+ redraw_step_back = cursor_count_word(0);
+ vstr_cut_out_bytes(rl.line, rl.cursor_pos - redraw_step_back, redraw_step_back);
+ redraw_from_cursor = true;
+ rl.escape_seq = ESEQ_NONE;
+ break;
+ #endif
default:
DEBUG_printf("(ESC %d)", c);
rl.escape_seq = ESEQ_NONE;
+ break;
}
} else if (rl.escape_seq == ESEQ_ESC_BRACKET) {
if ('0' <= c && c <= '9') {
@@ -311,6 +376,24 @@ int readline_process_char(int c) {
} else {
DEBUG_printf("(ESC [ %c %d)", rl.escape_seq_buf[0], c);
}
+ #if MICROPY_REPL_EMACS_EXTRA_WORDS_MOVE
+ } else if (c == ';' && rl.escape_seq_buf[0] == '1') {
+ // ';' is used to separate parameters. so first parameter was '1',
+ // that's used for sequences like ctrl+left, which we will try to parse.
+ // escape_seq state is reset back to ESEQ_ESC_BRACKET, as if we've just received
+ // the opening bracket, because more parameters are to come.
+ // we don't track the parameters themselves to keep low on logic and code size. that
+ // might be required in the future if more complex sequences are added.
+ rl.escape_seq = ESEQ_ESC_BRACKET;
+ // goto away from the state-machine, as rl.escape_seq will be overridden.
+ goto redraw;
+ } else if (rl.escape_seq_buf[0] == '5' && c == 'C') {
+ // ctrl+right
+ goto forward_word;
+ } else if (rl.escape_seq_buf[0] == '5' && c == 'D') {
+ // ctrl+left
+ goto backward_word;
+ #endif
} else {
DEBUG_printf("(ESC [ %c %d)", rl.escape_seq_buf[0], c);
}
@@ -329,6 +412,10 @@ int readline_process_char(int c) {
rl.escape_seq = ESEQ_NONE;
}
+#if MICROPY_REPL_EMACS_EXTRA_WORDS_MOVE
+redraw:
+#endif
+
// redraw command prompt, efficiently
if (redraw_step_back > 0) {
mp_hal_move_cursor_back(redraw_step_back);
diff --git a/lib/mp-readline/readline.h b/lib/mp-readline/readline.h
index 00aa9622a8..a19e1209ab 100644
--- a/lib/mp-readline/readline.h
+++ b/lib/mp-readline/readline.h
@@ -36,6 +36,7 @@
#define CHAR_CTRL_N (14)
#define CHAR_CTRL_P (16)
#define CHAR_CTRL_U (21)
+#define CHAR_CTRL_W (23)
void readline_init0(void);
int readline(vstr_t *line, const char *prompt);
diff --git a/lib/mynewt-nimble b/lib/mynewt-nimble
new file mode 160000
index 0000000000..97ce3eacaa
--- /dev/null
+++ b/lib/mynewt-nimble
@@ -0,0 +1 @@
+Subproject commit 97ce3eacaaa79e8ed6cf71717149ced4f5328ee7
diff --git a/lib/netutils/dhcpserver.c b/lib/netutils/dhcpserver.c
new file mode 100644
index 0000000000..7f97ee6e46
--- /dev/null
+++ b/lib/netutils/dhcpserver.c
@@ -0,0 +1,304 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018-2019 Damien P. George
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+// For DHCP specs see:
+// https://www.ietf.org/rfc/rfc2131.txt
+// https://tools.ietf.org/html/rfc2132 -- DHCP Options and BOOTP Vendor Extensions
+
+#include
+#include
+#include "py/mperrno.h"
+#include "py/mphal.h"
+
+#if MICROPY_PY_LWIP
+
+#include "lib/netutils/dhcpserver.h"
+#include "lwip/udp.h"
+
+#define DHCPDISCOVER (1)
+#define DHCPOFFER (2)
+#define DHCPREQUEST (3)
+#define DHCPDECLINE (4)
+#define DHCPACK (5)
+#define DHCPNACK (6)
+#define DHCPRELEASE (7)
+#define DHCPINFORM (8)
+
+#define DHCP_OPT_PAD (0)
+#define DHCP_OPT_SUBNET_MASK (1)
+#define DHCP_OPT_ROUTER (3)
+#define DHCP_OPT_DNS (6)
+#define DHCP_OPT_HOST_NAME (12)
+#define DHCP_OPT_REQUESTED_IP (50)
+#define DHCP_OPT_IP_LEASE_TIME (51)
+#define DHCP_OPT_MSG_TYPE (53)
+#define DHCP_OPT_SERVER_ID (54)
+#define DHCP_OPT_PARAM_REQUEST_LIST (55)
+#define DHCP_OPT_MAX_MSG_SIZE (57)
+#define DHCP_OPT_VENDOR_CLASS_ID (60)
+#define DHCP_OPT_CLIENT_ID (61)
+#define DHCP_OPT_END (255)
+
+#define PORT_DHCP_SERVER (67)
+#define PORT_DHCP_CLIENT (68)
+
+#define DEFAULT_DNS MAKE_IP4(8, 8, 8, 8)
+#define DEFAULT_LEASE_TIME_S (24 * 60 * 60) // in seconds
+
+#define MAC_LEN (6)
+#define MAKE_IP4(a, b, c, d) ((a) << 24 | (b) << 16 | (c) << 8 | (d))
+
+typedef struct {
+ uint8_t op; // message opcode
+ uint8_t htype; // hardware address type
+ uint8_t hlen; // hardware address length
+ uint8_t hops;
+ uint32_t xid; // transaction id, chosen by client
+ uint16_t secs; // client seconds elapsed
+ uint16_t flags;
+ uint8_t ciaddr[4]; // client IP address
+ uint8_t yiaddr[4]; // your IP address
+ uint8_t siaddr[4]; // next server IP address
+ uint8_t giaddr[4]; // relay agent IP address
+ uint8_t chaddr[16]; // client hardware address
+ uint8_t sname[64]; // server host name
+ uint8_t file[128]; // boot file name
+ uint8_t options[312]; // optional parameters, variable, starts with magic
+} dhcp_msg_t;
+
+static int dhcp_socket_new_dgram(struct udp_pcb **udp, void *cb_data, udp_recv_fn cb_udp_recv) {
+ // family is AF_INET
+ // type is SOCK_DGRAM
+
+ *udp = udp_new();
+ if (*udp == NULL) {
+ return -MP_ENOMEM;
+ }
+
+ // Register callback
+ udp_recv(*udp, cb_udp_recv, (void *)cb_data);
+
+ return 0; // success
+}
+
+static void dhcp_socket_free(struct udp_pcb **udp) {
+ if (*udp != NULL) {
+ udp_remove(*udp);
+ *udp = NULL;
+ }
+}
+
+static int dhcp_socket_bind(struct udp_pcb **udp, uint32_t ip, uint16_t port) {
+ ip_addr_t addr;
+ IP4_ADDR(&addr, ip >> 24 & 0xff, ip >> 16 & 0xff, ip >> 8 & 0xff, ip & 0xff);
+ // TODO convert lwIP errors to errno
+ return udp_bind(*udp, &addr, port);
+}
+
+static int dhcp_socket_sendto(struct udp_pcb **udp, const void *buf, size_t len, uint32_t ip, uint16_t port) {
+ if (len > 0xffff) {
+ len = 0xffff;
+ }
+
+ struct pbuf *p = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM);
+ if (p == NULL) {
+ return -MP_ENOMEM;
+ }
+
+ memcpy(p->payload, buf, len);
+
+ ip_addr_t dest;
+ IP4_ADDR(&dest, ip >> 24 & 0xff, ip >> 16 & 0xff, ip >> 8 & 0xff, ip & 0xff);
+ err_t err = udp_sendto(*udp, p, &dest, port);
+
+ pbuf_free(p);
+
+ if (err != ERR_OK) {
+ return err;
+ }
+
+ return len;
+}
+
+static uint8_t *opt_find(uint8_t *opt, uint8_t cmd) {
+ for (int i = 0; i < 308 && opt[i] != DHCP_OPT_END;) {
+ if (opt[i] == cmd) {
+ return &opt[i];
+ }
+ i += 2 + opt[i + 1];
+ }
+ return NULL;
+}
+
+static void opt_write_n(uint8_t **opt, uint8_t cmd, size_t n, void *data) {
+ uint8_t *o = *opt;
+ *o++ = cmd;
+ *o++ = n;
+ memcpy(o, data, n);
+ *opt = o + n;
+}
+
+static void opt_write_u8(uint8_t **opt, uint8_t cmd, uint8_t val) {
+ uint8_t *o = *opt;
+ *o++ = cmd;
+ *o++ = 1;
+ *o++ = val;
+ *opt = o;
+}
+
+static void opt_write_u32(uint8_t **opt, uint8_t cmd, uint32_t val) {
+ uint8_t *o = *opt;
+ *o++ = cmd;
+ *o++ = 4;
+ *o++ = val >> 24;
+ *o++ = val >> 16;
+ *o++ = val >> 8;
+ *o++ = val;
+ *opt = o;
+}
+
+static void dhcp_server_process(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *src_addr, u16_t src_port) {
+ dhcp_server_t *d = arg;
+ (void)upcb;
+ (void)src_addr;
+ (void)src_port;
+
+ // This is around 548 bytes
+ dhcp_msg_t dhcp_msg;
+
+ #define DHCP_MIN_SIZE (240 + 3)
+ if (p->tot_len < DHCP_MIN_SIZE) {
+ goto ignore_request;
+ }
+
+ size_t len = pbuf_copy_partial(p, &dhcp_msg, sizeof(dhcp_msg), 0);
+ if (len < DHCP_MIN_SIZE) {
+ goto ignore_request;
+ }
+
+ dhcp_msg.op = DHCPOFFER;
+ memcpy(&dhcp_msg.yiaddr, &d->ip.addr, 4);
+
+ uint8_t *opt = (uint8_t *)&dhcp_msg.options;
+ opt += 4; // assume magic cookie: 99, 130, 83, 99
+
+ switch (opt[2]) {
+ case DHCPDISCOVER: {
+ int yi = DHCPS_MAX_IP;
+ for (int i = 0; i < DHCPS_MAX_IP; ++i) {
+ if (memcmp(d->lease[i].mac, dhcp_msg.chaddr, MAC_LEN) == 0) {
+ // MAC match, use this IP address
+ yi = i;
+ break;
+ }
+ if (yi == DHCPS_MAX_IP) {
+ // Look for a free IP address
+ if (memcmp(d->lease[i].mac, "\x00\x00\x00\x00\x00\x00", MAC_LEN) == 0) {
+ // IP available
+ yi = i;
+ }
+ uint32_t expiry = d->lease[i].expiry << 16 | 0xffff;
+ if ((int32_t)(expiry - mp_hal_ticks_ms()) < 0) {
+ // IP expired, reuse it
+ memset(d->lease[i].mac, 0, MAC_LEN);
+ yi = i;
+ }
+ }
+ }
+ if (yi == DHCPS_MAX_IP) {
+ // No more IP addresses left
+ goto ignore_request;
+ }
+ dhcp_msg.yiaddr[3] = DHCPS_BASE_IP + yi;
+ opt_write_u8(&opt, DHCP_OPT_MSG_TYPE, DHCPOFFER);
+ break;
+ }
+
+ case DHCPREQUEST: {
+ uint8_t *o = opt_find(opt, DHCP_OPT_REQUESTED_IP);
+ if (o == NULL) {
+ // Should be NACK
+ goto ignore_request;
+ }
+ if (memcmp(o + 2, &d->ip.addr, 3) != 0) {
+ // Should be NACK
+ goto ignore_request;
+ }
+ uint8_t yi = o[5] - DHCPS_BASE_IP;
+ if (yi >= DHCPS_MAX_IP) {
+ // Should be NACK
+ goto ignore_request;
+ }
+ if (memcmp(d->lease[yi].mac, dhcp_msg.chaddr, MAC_LEN) == 0) {
+ // MAC match, ok to use this IP address
+ } else if (memcmp(d->lease[yi].mac, "\x00\x00\x00\x00\x00\x00", MAC_LEN) == 0) {
+ // IP unused, ok to use this IP address
+ memcpy(d->lease[yi].mac, dhcp_msg.chaddr, MAC_LEN);
+ } else {
+ // IP already in use
+ // Should be NACK
+ goto ignore_request;
+ }
+ d->lease[yi].expiry = (mp_hal_ticks_ms() + DEFAULT_LEASE_TIME_S * 1000) >> 16;
+ dhcp_msg.yiaddr[3] = DHCPS_BASE_IP + yi;
+ opt_write_u8(&opt, DHCP_OPT_MSG_TYPE, DHCPACK);
+ printf("DHCPS: client connected: MAC=%02x:%02x:%02x:%02x:%02x:%02x IP=%u.%u.%u.%u\n",
+ dhcp_msg.chaddr[0], dhcp_msg.chaddr[1], dhcp_msg.chaddr[2], dhcp_msg.chaddr[3], dhcp_msg.chaddr[4], dhcp_msg.chaddr[5],
+ dhcp_msg.yiaddr[0], dhcp_msg.yiaddr[1], dhcp_msg.yiaddr[2], dhcp_msg.yiaddr[3]);
+ break;
+ }
+
+ default:
+ goto ignore_request;
+ }
+
+ opt_write_n(&opt, DHCP_OPT_SERVER_ID, 4, &d->ip.addr);
+ opt_write_n(&opt, DHCP_OPT_SUBNET_MASK, 4, &d->nm.addr);
+ opt_write_n(&opt, DHCP_OPT_ROUTER, 4, &d->ip.addr); // aka gateway; can have mulitple addresses
+ opt_write_u32(&opt, DHCP_OPT_DNS, DEFAULT_DNS); // can have mulitple addresses
+ opt_write_u32(&opt, DHCP_OPT_IP_LEASE_TIME, DEFAULT_LEASE_TIME_S);
+ *opt++ = DHCP_OPT_END;
+ dhcp_socket_sendto(&d->udp, &dhcp_msg, opt - (uint8_t *)&dhcp_msg, 0xffffffff, PORT_DHCP_CLIENT);
+
+ignore_request:
+ pbuf_free(p);
+}
+
+void dhcp_server_init(dhcp_server_t *d, ip_addr_t *ip, ip_addr_t *nm) {
+ ip_addr_copy(d->ip, *ip);
+ ip_addr_copy(d->nm, *nm);
+ memset(d->lease, 0, sizeof(d->lease));
+ if (dhcp_socket_new_dgram(&d->udp, d, dhcp_server_process) != 0) {
+ return;
+ }
+ dhcp_socket_bind(&d->udp, 0, PORT_DHCP_SERVER);
+}
+
+void dhcp_server_deinit(dhcp_server_t *d) {
+ dhcp_socket_free(&d->udp);
+}
+
+#endif // MICROPY_PY_LWIP
diff --git a/lib/netutils/dhcpserver.h b/lib/netutils/dhcpserver.h
new file mode 100644
index 0000000000..2349d2ea42
--- /dev/null
+++ b/lib/netutils/dhcpserver.h
@@ -0,0 +1,49 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018-2019 Damien P. George
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#ifndef MICROPY_INCLUDED_LIB_NETUTILS_DHCPSERVER_H
+#define MICROPY_INCLUDED_LIB_NETUTILS_DHCPSERVER_H
+
+#include "lwip/ip_addr.h"
+
+#define DHCPS_BASE_IP (16)
+#define DHCPS_MAX_IP (8)
+
+typedef struct _dhcp_server_lease_t {
+ uint8_t mac[6];
+ uint16_t expiry;
+} dhcp_server_lease_t;
+
+typedef struct _dhcp_server_t {
+ ip_addr_t ip;
+ ip_addr_t nm;
+ dhcp_server_lease_t lease[DHCPS_MAX_IP];
+ struct udp_pcb *udp;
+} dhcp_server_t;
+
+void dhcp_server_init(dhcp_server_t *d, ip_addr_t *ip, ip_addr_t *nm);
+void dhcp_server_deinit(dhcp_server_t *d);
+
+#endif // MICROPY_INCLUDED_LIB_NETUTILS_DHCPSERVER_H
diff --git a/lib/netutils/netutils.c b/lib/netutils/netutils.c
index 073f46b199..40fbd5bca3 100644
--- a/lib/netutils/netutils.c
+++ b/lib/netutils/netutils.c
@@ -64,7 +64,7 @@ void netutils_parse_ipv4_addr(mp_obj_t addr_in, uint8_t *out_ip, netutils_endian
}
const char *s = addr_str;
const char *s_top = addr_str + addr_len;
- for (mp_uint_t i = 3 ; ; i--) {
+ for (mp_uint_t i = 3; ; i--) {
mp_uint_t val = 0;
for (; s < s_top && *s != '.'; s++) {
val = val * 10 + *s - '0';
@@ -79,7 +79,7 @@ void netutils_parse_ipv4_addr(mp_obj_t addr_in, uint8_t *out_ip, netutils_endian
} else if (i > 0 && s < s_top && *s == '.') {
s++;
} else {
- mp_raise_ValueError("invalid arguments");
+ mp_raise_ValueError(MP_ERROR_TEXT("invalid arguments"));
}
}
}
diff --git a/lib/netutils/trace.c b/lib/netutils/trace.c
index 7c79713b32..1610966c2d 100644
--- a/lib/netutils/trace.c
+++ b/lib/netutils/trace.c
@@ -44,10 +44,14 @@ static void dump_hex_bytes(const mp_print_t *print, size_t len, const uint8_t *b
static const char *ethertype_str(uint16_t type) {
// A value between 0x0000 - 0x05dc (inclusive) indicates a length, not type
switch (type) {
- case 0x0800: return "IPv4";
- case 0x0806: return "ARP";
- case 0x86dd: return "IPv6";
- default: return NULL;
+ case 0x0800:
+ return "IPv4";
+ case 0x0806:
+ return "ARP";
+ case 0x86dd:
+ return "IPv6";
+ default:
+ return NULL;
}
}
@@ -113,14 +117,30 @@ void netutils_ethernet_trace(const mp_print_t *print, size_t len, const uint8_t
buf += n;
mp_printf(print, " opts:");
switch (buf[6]) {
- case 1: mp_printf(print, " DISCOVER"); break;
- case 2: mp_printf(print, " OFFER"); break;
- case 3: mp_printf(print, " REQUEST"); break;
- case 4: mp_printf(print, " DECLINE"); break;
- case 5: mp_printf(print, " ACK"); break;
- case 6: mp_printf(print, " NACK"); break;
- case 7: mp_printf(print, " RELEASE"); break;
- case 8: mp_printf(print, " INFORM"); break;
+ case 1:
+ mp_printf(print, " DISCOVER");
+ break;
+ case 2:
+ mp_printf(print, " OFFER");
+ break;
+ case 3:
+ mp_printf(print, " REQUEST");
+ break;
+ case 4:
+ mp_printf(print, " DECLINE");
+ break;
+ case 5:
+ mp_printf(print, " ACK");
+ break;
+ case 6:
+ mp_printf(print, " NACK");
+ break;
+ case 7:
+ mp_printf(print, " RELEASE");
+ break;
+ case 8:
+ mp_printf(print, " INFORM");
+ break;
}
}
} else {
diff --git a/lib/nrfx b/lib/nrfx
new file mode 160000
index 0000000000..7a4c9d946c
--- /dev/null
+++ b/lib/nrfx
@@ -0,0 +1 @@
+Subproject commit 7a4c9d946cf1801771fc180acdbf7b878f270093
diff --git a/lib/nrfx/.gitignore b/lib/nrfx/.gitignore
deleted file mode 100644
index 16e737e81b..0000000000
--- a/lib/nrfx/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-doc/html/*
-doc/warnings_nrfx.txt
diff --git a/lib/nrfx/CHANGELOG.md b/lib/nrfx/CHANGELOG.md
deleted file mode 100644
index e17a19da64..0000000000
--- a/lib/nrfx/CHANGELOG.md
+++ /dev/null
@@ -1,197 +0,0 @@
-# Changelog
-All notable changes to this project are documented in this file.
-
-## [1.7.1] - 2019-04-08
-### Added
-- Added functions in the NVMC driver for getting the flash page size, the count of pages and the total flash size.
-
-### Fixed
-- Fixed handling of short unaligned write requests (1 or 2 bytes in length) in the nrfx_nvmc_bytes_write() function.
-
-## [1.7.0] - 2019-03-29
-### Added
-- Added drivers for NVMC and TEMP.
-- Added HALs: AAR and FICR.
-- Added support for the custom instruction long frame mode in the QSPI driver.
-
-### Changed
-- Reworked HAL for NVMC. Now it can be used for all SoCs supported by nrfx.
-- Reworked HAL for TEMP.
-- Improved documentation. Now it is more precise and can be generated without warnings with newer versions of doxygen.
-- Improved the UARTE driver to consume less current after the TX operation. Now at the end of the transmission the transmitter is turned off by the STOPTX task.
-- Improved C++ support in drivers. Now fields in structures are filled up in the correct order.
-- Changed to size_t the type used for holding the amount of data in the TWIS driver.
-
-### Fixed
-- Fixed a race condition in the USBD driver. It could occur when an IN transfer was interrupted by an OUT transaction, which in turn was interrupted by a process with a higher priority.
-
-## [1.6.2] - 2019-02-12
-### Added
-- Added the possibility to use the macro NRFX_COREDEP_DELAY_US_LOOP_CYCLES to specify the number of cycles consumed by one iteration of the internal loop in the function nrfx_coredep_delay_us().
-
-### Changed
-- Updated MDK to version 8.24.1.
-
-## [1.6.1] - 2019-01-29
-### Fixed
-- Fixed an issue in the NFCT driver that caused a performance loss on nRF52832. The interrupt configuration is now properly restored after the NRFX_NFCT_EVT_FIELD_LOST event.
-
-## [1.6.0] - 2019-01-18
-### Added
-- Added support for nRF52811.
-- Added support for the legacy peripherals SPI, TWI, and UART in nRF52810.
-- Added support for SAMPLERATE in nrf_saadc.h.
-- Added clearing of the STOPPED event in the nrfx_saadc_init() function to prevent driver deadlock in some cases.
-- Added HALs: BPROT, MPU, MWU.
-- Added function for reading the pin input buffer configuration in the GPIO HAL.
-- Implemented workaround for nRF9160 anomaly 1 in the I2S driver.
-
-### Changed
-- Improved handling of hardware anomalies in the USBD driver.
-- Updated MDK to version 8.23.1.
-
-### Fixed
-- Fixed the condition in NRFX_WAIT_FOR in the nrfx_saadc_abort() function. The macro now correctly waits for a stop of the driver.
-- Fixed the pending interrupt clearing in NVIC in the nrfx_usbd_stop() function. The driver now correctly handles power management.
-- Fixed the case when nrfx_uarte_tx_in_progress() function would return an incorrect value. The driver now correctly updates the tx_buffer_length variable internally.
-
-## [1.5.0] - 2018-12-12
-### Added
-- Added support for nRF9160.
-- Added allocator for DPPI.
-- Added HALs: DPPI, KMU, REGULATORS, SPU, VMC.
-- Added support for DPPI subscription and publishing in HALs related to nRF9160.
-- Added support for instances 2 and 3 in SPIS, TWIM, TWIS, and UARTE drivers.
-
-### Changed
-- Updated MDK to version 8.21.1.
-
-### Fixed
-- Corrected NRFX_I2S_CONFIG_RATIO value in nrfx_config.h. It now correctly uses supported value.
-
-## [1.4.0] - 2018-11-30
-### Added
-- Added the nrfx_is_word_aligned() function for checking whether an address is word-aligned.
-- Added HAL for ACL.
-- Added functions for disabling and re-enabling interrupts in the SWI driver.
-- Added possibility to completely remove interrupt handling from the WDT driver.
-
-### Changed
-- Updated the documentation for the nrfx_uarte_rx() function. It now correctly reflects the actual behavior of the function.
-
-### Fixed
-- Corrected the type of the nrfx_uarte_xfer_evt_t structure field that holds the amount of transferred bytes.
-- Corrected the way of disabling interrupts in the NFCT driver when moving the peripheral to the disabled state.
-- Fixed a typo in the name of the bmRequest field in the nrfx_usbd_setup_t structure. The new correct name is bRequest.
-- Fixed the nrfx_ppi_channel_fork_assign() function. It now accepts also pre-programmed channels.
-- Fixed handling of long custom instruction responses in the QSPI driver.
-- Fixed a bug affecting the conversion of time to ticks in the TIMER HAL.
-
-## [1.3.1] - 2018-09-28
-### Fixed
-- Corrected the type of nrfx_usbd_ep_status_get() return value.
-- Corrected calls to undefined macros in NFCT and USBD drivers.
-
-## [1.3.0] - 2018-09-21
-### Added
-- Added HAL and driver for NFCT.
-- Added driver for USBD.
-- Added function for setting the burst mode in the SAADC HAL.
-- Added the NRFX_ARRAY_SIZE macro.
-
-### Changed
-- Moved the implementation of nrfx_power_clock_irq_handler() to nrfx_power.c, removed nrfx_power_clock.c.
-
-### Fixed
-- Replaced ARRAY_SIZE macro calls with NRFX_ARRAY_SIZE ones.
-
-## [1.2.0] - 2018-09-06
-### Added
-- Added function for checking if a specific channel is enabled in the GPIOTE HAL.
-- Added support for using the QDEC driver without LED.
-- Added functions for modifying only the event endpoint or only the task endpoint in the PPI HAL.
-- Added function for reading the pin pull configuration in the GPIO HAL.
-
-### Changed
-- Corrected ISOSPLIT enumerator names in the USBD HAL.
-
-### Fixed
-- Fixed a double buffering bug that occurred in the UARTE driver after the RX abort.
-- Fixed the TXRX transfers in the TWIM driver. They can now be started after transfers that are not ended with the stop condition.
-
-## [1.1.0] - 2018-06-15
-### Added
-- Implemented workaround for nRF52832 and nRF52840 anomaly 194 in the I2S driver.
-- Implemented workaround for nRF52840 anomaly 195 in the SPIM driver.
-- Added HALs for CCM, ECB, and RADIO.
-- Extended HALs for GPIO, PPI, SAADC, and USBD.
-- Added support for external LFCLK sources.
-
-### Changed
-- Corrected handling of transfer lengths in the TWI driver.
-- Updated MDK to version 8.17.0.
-
-### Fixed
-- Fixed logging in the PPI driver.
-- Fixed SPIM interrupt definition for nRF52810.
-- Fixed Slave Select configuration in the SPIM driver.
-- Corrected default settings for NRF_SPIM3.
-- Fixed a typo in the UARTE TXDRDY event definition.
-- Corrected the TIMEOUT event clearing in the WDT interrupt handler.
-
-## [1.0.0] - 2018-03-21
-### Added
-- Added the NRFX_WAIT_FOR macro to improve the time-out functionality in QSPI and SAADC drivers.
-- Added glue layer macros for checking and modifying the pending status of interrupts.
-- Added new enumeration values for interrupts and events in the UARTE HAL.
-- Implemented workarounds for nRF52 anomalies 192 and 201 in the CLOCK driver.
-- Implemented workaround for nRF52840 anomaly 122 in the QSPI driver.
-- Implemented workaround for nRF52840 anomaly 198 in the SPIM driver.
-
-### Changed
-- Updated MDK to 8.16.0.
-- Extended input pin configuration in the GPIOTE driver.
-- Unified the way of checking if a required event handler was provided. Now, all drivers do it with assertions.
-- Changed the RNG bias correction configuration option to be enabled by default.
-- Refactored the ADC driver and HAL.
-- Corrected assertions in the TIMER driver to make it usable in debug version with PPI.
-- Improved buffer handling in the I2S driver. The API of the driver has been slightly modified.
-- Enhanced SPIS driver API: added the "p_context" parameter, allowed NULL pointers for zero-length buffers.
-
-### Fixed
-- Fixed result value casting in the TEMP HAL.
-- Fixed types of conversion result and buffer size in the ADC HAL and driver.
-- Fixed time-out in the SAADC driver in abort function.
-
-## [0.8.0] - 2017-12-20
-### Added
-- Added XIP support in the QSPI driver.
-- Implemented Errata 132 in the CLOCK driver.
-- Added function for checking if a TIMER instance is enabled.
-- Added extended SPIM support.
-
-### Changed
-- Updated MDK to 8.15.0. Introduced Segger Embedded Studio startup files.
-- Updated drivers: COMP, PWM, QDEC, SAADC, SPIS, TIMER, TWI, TWIS.
-- Changed the type used for transfer lengths to 'size_t' in drivers: SPI, SPIM, SPIS, TWI, TWIM, TWIS, UART, UARTE. Introduced checking of EasyDMA transfers limits.
-- Updated HALs: COMP, NVMC, UART, UARTE, USBD.
-- Updated template files and documentation of configuration options.
-
-### Fixed
-- Fixed TWI and TWIM drivers so that they now support GPIOs from all ports.
-- Fixed definitions related to compare channels in the TIMER HAL.
-
-### Removed
-- Removed the possibility of passing NULL instead of configuration to get default settings during drivers initialization.
-- Removed support for UART1 and PRS box #5.
-
-## [0.7.0] - 2017-10-20
-### Added
-- This CHANGELOG.md file.
-- README.md file with simple description and explanations.
-- HAL for: ADC, CLOCK, COMP, ECB, EGU, GPIO, GPIOTE, I2S, LPCOMP, NVMC, PDM, POWER, PPI, PWM, QDEC, QSPI, RNG, RTC, SAADC, SPI, SPIM, SPIS, ARM(R) SysTick, TEMP, TIMER, TWI, TWIM, TWIS, UART, UARTE, USBD, WDT.
-- Drivers for: ADC, CLOCK, COMP, GPIOTE, I2S, LPCOMP, PDM, POWER, PWM, QDEC, QSPI, RNG, RTC, SAADC, SPI, SPIM, SPIS, ARM(R) SysTick, TIMER, TWI, TWIM, TWIS, UART, UARTE, WDT.
-- Allocators for: PPI, SWI/EGU.
-- MDK in version 8.14.0.
-- Offline documentation for every added driver and simple integration description.
-- Template integration files.
diff --git a/lib/nrfx/LICENSE b/lib/nrfx/LICENSE
deleted file mode 100644
index ed92c3b4f1..0000000000
--- a/lib/nrfx/LICENSE
+++ /dev/null
@@ -1,29 +0,0 @@
-Copyright (c) 2017 - 2019, Nordic Semiconductor ASA
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-1. Redistributions of source code must retain the above copyright notice, this
- list of conditions and the following disclaimer.
-
-2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
-3. Neither the name of the copyright holder nor the names of its
- contributors may be used to endorse or promote products derived from this
- software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-
diff --git a/lib/nrfx/README.md b/lib/nrfx/README.md
deleted file mode 100644
index ab233c0eed..0000000000
--- a/lib/nrfx/README.md
+++ /dev/null
@@ -1,42 +0,0 @@
-# nrfx
-
-## Overview
-
-nrfx is a standalone set of drivers for peripherals present in Nordic
-Semiconductor's SoCs. It originated as an extract from the nRF5 SDK.
-The intention was to provide drivers that can be used in various environments
-without the necessity to integrate other parts of the SDK into them.
-For the user's convenience, the drivers come with the MDK package. This package
-contains definitions of register structures and bitfields for all supported
-SoCs, as well as startup and initialization files for them.
-
-## Supported SoCs
-
-* nRF51 Series
-* nRF52810
-* nRF52811
-* nRF52832
-* nRF52840
-* nRF9160
-
-## Directories
-
-```
- .
- ├── doc # Project documentation files
- ├── drivers # nrfx drivers files
- │ └── include # nrfx drivers headers
- │ └── src # nrfx drivers sources
- ├── hal # Hardware Access Layer files
- ├── mdk # Nordic MDK files
- ├── soc # Nordic SoC related files
- └── templates # Templates of nrfx integration files
-```
-
-## Generating documentation
-
-nrfx documentation is available in the `doc\html` folder of the release package.
-
-You can also generate documentation yourself from the source code. To do it, install doxygen
-and run one of the scripts: `generate_html_doc.bat` or `generate_html_doc.sh`. Generated
-documentation will be stored in the `doc\html` directory. Use `index.html` to open it.
diff --git a/lib/nrfx/doc/buildfiles/extra_stylesheet.css b/lib/nrfx/doc/buildfiles/extra_stylesheet.css
deleted file mode 100644
index 3b53f268df..0000000000
--- a/lib/nrfx/doc/buildfiles/extra_stylesheet.css
+++ /dev/null
@@ -1,506 +0,0 @@
-.appliesto {background-color:#3D578C;color:#fff}
-
-div.header
-{
- background-image:none;
- background-color: #FFF;
- border-bottom: 0px;
-}
-
-body, table, div, p, dl {
- font-size: 16px;
- font-family: Open Sans, Calibri, Arial, Sans-Serif;
- color: #474747;
- line-height: 20px;
-
-}
-
-a.code {
- color: #1c99c7;
-}
-
-a.el {
- font-weight: normal;
-}
-
-.contents a:visited, a:visited.code {
- color: #16779a;
-}
-
-.title {
- font-size: 1.34em
-}
-
-h1 {
- font-size: 1.25em
-}
-
-h2 {
- font-size: 1.15em
-}
-
-h3 {
- font-size: 1.05em
-}
-
-h4 {
- font-size: 1em
-}
-
-table.memberdecls, table.directory, table.memname {
- margin:0px;
- border:0px;
- -moz-box-shadow: 0 0px 0px #d1d1d1;
- -webkit-box-shadow: 0 0px 0px #d1d1d1;
- box-shadow: 0 0px 0px #d1d1d1;
-}
-
-table.memberdecls tr {
- padding-left:0px;
-}
-
-table.memberdecls tr:hover td, table.memname tr:hover td {
- background: inherit;
-}
-
-table.directory tr.even, table.directory tr.odd {
- background: inherit;
-}
-
-table.memberdecls td, table.directory td, table.directory td.desc {
- border:0px;
- padding: 2px 0px 0px;
-}
-
-table.memberdecls td.memSeparator {
- background-color:#inherit;
- padding:2px;
- border-bottom: 1px dotted #DEE4F0;
-}
-
-.mdescLeft, .mdescRight,
-.memItemLeft, .memItemRight,
-.memTemplItemLeft, .memTemplItemRight, .memTemplParams {
- background-color: inherit;
-}
-
-div.levels {
- display:none;
-}
-
-table.retval {
-border:#ccc 1px solid;
-}
-
-
-table.memname td, table.params td, table.retval td {
-padding:5px;
-border:0px;
-}
-
-div.fragment div.line {
-font-size: 14px;
-line-height:18px;
-}
-
-table.fieldtable, table.params, table.retval {
- -moz-box-shadow: none;
- -webkit-box-shadow: none;
- box-shadow: none;
-}
-
-table.fieldtable th {
- border:none;
- border-bottom:1px solid #A8B8D9;
-}
-
-table.blank, table.blank tr th, table.blank tr td {
- border:none;
- -moz-box-shadow: none;
- -webkit-box-shadow: none;
- box-shadow: none;
-}
-
-table.blank tr:hover td {
- background: #ffffff;
-}
-
-
-#projectlogo
-{
- text-align: left;
- vertical-align: middle;
- border-collapse: separate;
-}
-
-#projectname
-{
- font-size: 40px;
- font-family: Open Sans, Calibri, Arial, Sans-Serif;
- margin: 0px;
- padding: 2px 0px;
-}
-
-#projectbrief
-{
- font-size: 30px;
- margin: 0px;
- padding: 0px;
-}
-
-#titlearea
-{
- border-bottom: 1px solid #e0e0e0;
-}
-
-.label a, .item a
-{
- border-bottom: none;
-
-}
-
-#nav-tree {
- background-image: none;
- background-color: #FAFAFA;
-}
-
-div.contents {
- margin-left: 30px;
- margin-right: 30px;
-
-}
-
-div.header {
- margin-left: 20px;
-}
-
-table td.doclinks a {
- font-size: 12px;
- font-style: italic;
- color: #e97c25;
- border: 1px solid #e97c25;
- padding: 2px 5px;
- text-decoration: none;
-}
-
-table td.docselected a {
- background: #e97c25;
- color: #fff;
-}
-
-table td.doclinkintro {
- font-size: 12px;
- font-style: italic;
-}
-
-
-/* nordic.css */
-.p {
- margin-top: .3em;
-}
-
-/* fix for table spacing */
-td p.p {
- margin: 0em;
- padding: 0px;
-}
-dt.line_sep {
- border-top: solid #c9c9c9 1px;
- padding-top: 5px;
-
-}
-
-a
-{
- color: #1c99c7;
- text-decoration: none;
- border-bottom: 1px #e5e5e5 solid;
-
-}
-
-a:visited
-{
- color: #16779a;
-}
-a:hover
-{
- color: #none;
- text-decoration: underline;
- border: none;
-}
-
-a:active
-{
-
-}
-
-ul.ul {
- margin-top: 4px;
- margin-bottom: 10px;
-}
-
-
-a[href*='.pdf'] {
-background:transparent url(./pdf.png) center left no-repeat;
-padding-left:22px;
-line-height:18px;
-}
-
-
-a[href*='.zip'] {
-background:transparent url(./zip_s.png) center left no-repeat;
-padding-left:22px;
-line-height:18px;
-}
-
-a[href*='.exe'] {
-background:transparent url(./execute_s.png) center left no-repeat;
-padding-left:22px;
-line-height:18px;
-}
-
-a[href*='.msi'] {
-background:transparent url(./msi_s.png) center left no-repeat;
-padding-left:22px;
-line-height:18px;
-}
-
-table a:link {
- color: #1c99c7;
- text-decoration: none;
- border-bottom: 1px #e5e5e5 solid;
-}
-table a:visited {
- color: #16779a;
-}
-table a:active,
-table a:hover {
- color: #none;
- text-decoration: underline;
- border: none;
-}
-table {
- font-family:Calibri, Arial, Sans-Serif;
- color:#474747;
- font-size:16px;
- margin-left: auto;
- margin-right: auto;
- border:#ccc 1px solid;
-
-
- -moz-box-shadow: 0 1px 2px #d1d1d1;
- -webkit-box-shadow: 0 1px 2px #d1d1d1;
- box-shadow: 0 1px 2px #d1d1d1;
-}
-table th {
- color: #000;
- font-size: 18px;
- font-weight: bold;
- text-align: left;
- padding:10px 15px 10px 10px;
- border-top:1px solid #7eceed;
- border-bottom:1px solid #7eceed;
- border-right:1px solid #7eceed;
- border-left:1px solid #7eceed;
-
- background: #7eceed;
- background: -webkit-gradient(linear, left top, left bottom, from(#7eceed), to(#7eceed));
- background: -moz-linear-gradient(top, #7eceed, #7eceed);
-}
-
-table th.center {
- text-align: center;
-}
-table tr {
- text-align: left;
-
-}
-table td {
- padding:5px 5px 5px 10px;
- border-top: 1px solid #ffffff;
- border-bottom:1px solid #e0e0e0;
- border-left: 1px solid #e0e0e0;
- border-right: 1px solid #e0e0e0;
-
-}
-table tr:hover td {
- background: #ebebeb;
- background: -webkit-gradient(linear, left top, left bottom, from(#f2f2f2), to(#f0f0f0));
- background: -moz-linear-gradient(top, #f2f2f2, #f0f0f0);
-}
-
-
-
-
-img {
- border: 0;
- margin-left: auto;
- margin-right: auto;
- max-width:100%;
-}
-
-
-/* make svg files scale in IE. compatible with Dita OT v2.0
-img:not(.png) {
- width: 100%;
- margin-left: auto;
- margin-right: auto;
-}
-*/
-
-
-/* make svg files scale in IE */
-embed.image:not(.png):not(.gif):not(.jpg) {
- width: 100%;
- margin-left: auto;
- margin-right: auto;
- margin-bottom: 15px;
-}
-
-svg {
- position: absolute;
- top: 0;
- left: 0;
-
-}
-
-caption {
- caption-side: bottom;
- text-align: center;
- font-size: 100%;
- font-weight: bold;
- margin-top: 15px;
- margin-bottom: 35px;
-
- }
-
-figdesc {
- caption-side: bottom;
- text-align: center;
- font-size: 100%;
- font-weight: bold;
- margin-top: 15px;
- margin-bottom: 20px;
-
- }
-
-/* to get figure captions to appear below the image and center */
-
-div.fig {
- display: table;
- width: 100%;
- margin-top: 10px;
- margin-bottom: 55px;
-}
-
-div.fig span.figcap {
- display:table-footer-group;
- text-align:center;
- font-size: 100%;
- font-weight: bold;
- margin-top: 10px;
- margin-bottom: 20px;
- font-style: normal;
-}
-div.fig div.imagecenter {
- display:table-row-group;
-}
-
-
-/* fix to hide borders in image maps (Chrome only) */
-img.map, map area{
- outline: none;
-}
-
-
-/* fix placement of ® */
-sup {
- line-height: 1em;
-}
-
-.sdkversion span {
- font-size: 12px;
- font-style: italic;
- color: #e97c25;
- border: 1px solid #e97c25;
- padding: 2px 5px;
-}
-
-.sdkversion {
- text-align: right;
-}
-
-.whichSDs span,.whichnRF span {
- font-size: 12px;
- font-style: italic;
- color: #e97c25;
- border: 1px solid #e97c25;
- padding: 2px 5px;
- }
-
-.whichSDs.nRF52 span,.whichnRF.nRF52 span {
- color: #e97c25;
- border-color: #e97c25;
-}
-
-.whichSDs.nRF52840 span,.whichnRF.nRF52840 span {
- color: #0081B7;
- border-color: #0081B7;
-}
-
-.whichSDs.nRF51 span,.whichnRF.nRF51 span {
- color: #7f7f7f;
- border-color: #7f7f7f;
-}
-
-div.whichnRF {
- padding-bottom: 5px;
-}
-
-span.whichnRF{
- font-size: 12px;
- font-style: italic;
- color: #e97c25;
- border: 1px solid #e97c25;
- padding: 2px 5px;
-}
-
-span.whichnRF.nRF52 {
- color: #e97c25;
- border-color: #e97c25;
-}
-
-span.whichnRF.nRF52840 {
- color: #0081B7;
- border-color: #0081B7;
-}
-
-span.whichnRF.nRF51 {
- color: #7f7f7f;
- border-color: #7f7f7f;
-}
-
-.orange {
- color: #e97c25;
-}
-
-hr {
- margin-top:20px;
- border-top:1px solid #8EA7B0;
-}
-
-
-.directory td.entry {
- white-space: normal;
- width:50%;
-}
-
-/* overrides */
-.topicfooter {
- text-align: right;
-// margin-top: 1px;
- padding-right: 10px;
- box-shadow: inset 0px 1px 0px 0px #e0e0e0;
- font-size: 13px;
-}
-
diff --git a/lib/nrfx/doc/buildfiles/favicon.ico b/lib/nrfx/doc/buildfiles/favicon.ico
deleted file mode 100644
index 0bd6cc0845..0000000000
Binary files a/lib/nrfx/doc/buildfiles/favicon.ico and /dev/null differ
diff --git a/lib/nrfx/doc/buildfiles/footer.html b/lib/nrfx/doc/buildfiles/footer.html
deleted file mode 100644
index 974fce90cf..0000000000
--- a/lib/nrfx/doc/buildfiles/footer.html
+++ /dev/null
@@ -1,10 +0,0 @@
-
-