diff --git a/docs/zephyr/quickref.rst b/docs/zephyr/quickref.rst
index 783621316c70..329a9c41c0cc 100644
--- a/docs/zephyr/quickref.rst
+++ b/docs/zephyr/quickref.rst
@@ -151,7 +151,7 @@ Use the :ref:`zsensor.Sensor ` class to access sensor data::
accel.measure() # obtain a measurement reading from the accelerometer
# each of these prints the value taken by measure()
- accel.float(zsensor.ACCEL_X) # print measurement value for accelerometer X-axis sensor channel as float
- accel.millis(zsensor.ACCEL_Y) # print measurement value for accelerometer Y-axis sensor channel in millionths
- accel.micro(zsensor.ACCEL_Z) # print measurement value for accelerometer Z-axis sensor channel in thousandths
- accel.int(zsensor.ACCEL_X) # print measurement integer value only for accelerometer X-axis sensor channel
+ accel.get_float(zsensor.ACCEL_X) # print measurement value for accelerometer X-axis sensor channel as float
+ accel.get_millis(zsensor.ACCEL_Y) # print measurement value for accelerometer Y-axis sensor channel in millionths
+ accel.get_micro(zsensor.ACCEL_Z) # print measurement value for accelerometer Z-axis sensor channel in thousandths
+ accel.get_int(zsensor.ACCEL_X) # print measurement integer value only for accelerometer X-axis sensor channel
diff --git a/docs/zephyr/tutorial/repl.rst b/docs/zephyr/tutorial/repl.rst
index 6e11c04cb3a0..8cd57c9435bf 100644
--- a/docs/zephyr/tutorial/repl.rst
+++ b/docs/zephyr/tutorial/repl.rst
@@ -31,8 +31,8 @@ With your serial program open (PuTTY, screen, picocom, etc) you may see a
blank screen with a flashing cursor. Press Enter (or reset the board) and
you should be presented with the following text::
- *** Booting Zephyr OS build zephyr-v3.0.0 ***
- MicroPython v1.18-169-g665f0e2a6-dirty on 2022-03-02; zephyr-frdm_k64f with mk64f12
+ *** Booting Zephyr OS build zephyr-v3.1.0 ***
+ MicroPython v1.19.1-9-g4fd54a475 on 2022-06-17; zephyr-frdm_k64f with mk64f12
Type "help()" for more information.
>>>
diff --git a/drivers/README.md b/drivers/README.md
index 854acc50b62c..e4fac9fe8d43 100644
--- a/drivers/README.md
+++ b/drivers/README.md
@@ -1,2 +1,2 @@
-This directory contains drivers for specific hardware. The drivers are
+This directory contains C drivers for specific hardware. The drivers are
intended to work across multiple ports.
diff --git a/drivers/bus/qspi.h b/drivers/bus/qspi.h
index 7dfaaf3d40c6..009f55b159d4 100644
--- a/drivers/bus/qspi.h
+++ b/drivers/bus/qspi.h
@@ -41,10 +41,10 @@ enum {
typedef struct _mp_qspi_proto_t {
int (*ioctl)(void *self, uint32_t cmd);
- void (*write_cmd_data)(void *self, uint8_t cmd, size_t len, uint32_t data);
- void (*write_cmd_addr_data)(void *self, uint8_t cmd, uint32_t addr, size_t len, const uint8_t *src);
- uint32_t (*read_cmd)(void *self, uint8_t cmd, size_t len);
- void (*read_cmd_qaddr_qdata)(void *self, uint8_t cmd, uint32_t addr, size_t len, uint8_t *dest);
+ int (*write_cmd_data)(void *self, uint8_t cmd, size_t len, uint32_t data);
+ int (*write_cmd_addr_data)(void *self, uint8_t cmd, uint32_t addr, size_t len, const uint8_t *src);
+ int (*read_cmd)(void *self, uint8_t cmd, size_t len, uint32_t *dest);
+ int (*read_cmd_qaddr_qdata)(void *self, uint8_t cmd, uint32_t addr, size_t len, uint8_t *dest);
} mp_qspi_proto_t;
typedef struct _mp_soft_qspi_obj_t {
diff --git a/drivers/bus/softqspi.c b/drivers/bus/softqspi.c
index 71ab559768b1..dc205da3a7c4 100644
--- a/drivers/bus/softqspi.c
+++ b/drivers/bus/softqspi.c
@@ -158,15 +158,16 @@ STATIC void mp_soft_qspi_qwrite(mp_soft_qspi_obj_t *self, size_t len, const uint
//mp_hal_pin_input(self->io1);
}
-STATIC void mp_soft_qspi_write_cmd_data(void *self_in, uint8_t cmd, size_t len, uint32_t data) {
+STATIC int mp_soft_qspi_write_cmd_data(void *self_in, uint8_t cmd, size_t len, uint32_t data) {
mp_soft_qspi_obj_t *self = (mp_soft_qspi_obj_t*)self_in;
uint32_t cmd_buf = cmd | data << 8;
CS_LOW(self);
mp_soft_qspi_transfer(self, 1 + len, (uint8_t*)&cmd_buf, NULL);
CS_HIGH(self);
+ return 0;
}
-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) {
+STATIC int 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[5] = {cmd};
uint8_t addr_len = mp_spi_set_addr_buff(&cmd_buf[1], addr);
@@ -174,18 +175,20 @@ STATIC void mp_soft_qspi_write_cmd_addr_data(void *self_in, uint8_t cmd, uint32_
mp_soft_qspi_transfer(self, addr_len + 1, cmd_buf, NULL);
mp_soft_qspi_transfer(self, len, src, NULL);
CS_HIGH(self);
+ return 0;
}
-STATIC uint32_t mp_soft_qspi_read_cmd(void *self_in, uint8_t cmd, size_t len) {
+STATIC int mp_soft_qspi_read_cmd(void *self_in, uint8_t cmd, size_t len, uint32_t *dest) {
mp_soft_qspi_obj_t *self = (mp_soft_qspi_obj_t*)self_in;
uint32_t cmd_buf = cmd;
CS_LOW(self);
mp_soft_qspi_transfer(self, 1 + len, (uint8_t*)&cmd_buf, (uint8_t*)&cmd_buf);
CS_HIGH(self);
- return cmd_buf >> 8;
+ *dest = cmd_buf >> 8;
+ return 0;
}
-STATIC void mp_soft_qspi_read_cmd_qaddr_qdata(void *self_in, uint8_t cmd, uint32_t addr, size_t len, uint8_t *dest) {
+STATIC int 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};
uint8_t addr_len = mp_spi_set_addr_buff(&cmd_buf[1], addr);
@@ -194,6 +197,7 @@ STATIC void mp_soft_qspi_read_cmd_qaddr_qdata(void *self_in, uint8_t cmd, uint32
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);
+ return 0;
}
const mp_qspi_proto_t mp_soft_qspi_proto = {
diff --git a/drivers/cc3000/inc/cc3000_common.h b/drivers/cc3000/inc/cc3000_common.h
deleted file mode 100644
index d0c4b1d4b92e..000000000000
--- a/drivers/cc3000/inc/cc3000_common.h
+++ /dev/null
@@ -1,365 +0,0 @@
-/*****************************************************************************
-*
-* cc3000_common.h - CC3000 Host Driver Implementation.
-* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
-*
-* 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 Texas Instruments Incorporated 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
-* OWNER 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.
-*
-*****************************************************************************/
-#ifndef __CC3000_COMMON_H__
-#define __CC3000_COMMON_H__
-
-#include "data_types.h"
-
-//******************************************************************************
-// Include files
-//******************************************************************************
-#include
-#include
-
-//*****************************************************************************
-// Prefix exported names to avoid name clash
-//*****************************************************************************
-#define CC3000_EXPORT(name) cc3000_ ## name
-
-//*****************************************************************************
-//
-// If building with a C++ compiler, make all of the definitions in this header
-// have a C binding.
-//
-//*****************************************************************************
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-extern int CC3000_EXPORT(errno);
-
-//*****************************************************************************
-// ERROR CODES
-//*****************************************************************************
-#define ESUCCESS 0
-#define EFAIL -1
-#define EERROR EFAIL
-
-//*****************************************************************************
-// COMMON DEFINES
-//*****************************************************************************
-#define ERROR_SOCKET_INACTIVE -57
-
-#define WLAN_ENABLE (1)
-#define WLAN_DISABLE (0)
-
-#define MAC_ADDR_LEN (6)
-
-#define SP_PORTION_SIZE (32)
-
-/*Defines for minimal and maximal RX buffer size. This size includes the spi
- header and hci header.
- The maximal buffer size derives from:
- MTU + HCI header + SPI header + sendto() agrs size
- The minimum buffer size derives from:
- HCI header + SPI header + max args size
-
- This buffer is used for receiving events and data.
- The packet can not be longer than MTU size and CC3000 does not support
- fragmentation. Note that the same buffer is used for reception of the data
- and events from CC3000. That is why the minimum is defined.
- The calculation for the actual size of buffer for reception is:
- Given the maximal data size MAX_DATA that is expected to be received by
- application, the required buffer is:
- Using recv() or recvfrom():
-
- max(CC3000_MINIMAL_RX_SIZE, MAX_DATA + HEADERS_SIZE_DATA + fromlen
- + ucArgsize + 1)
-
- Using gethostbyname() with minimal buffer size will limit the host name
- returned to 99 bytes only.
- The 1 is used for the overrun detection
-
- Buffer size increased to 130 following the add_profile() with WEP security
- which requires TX buffer size of 130 bytes:
- HEADERS_SIZE_EVNT + WLAN_ADD_PROFILE_WEP_PARAM_LEN + MAX SSID LEN + 4 * MAX KEY LEN = 130
- MAX SSID LEN = 32
- MAX SSID LEN = 13 (with add_profile only ascii key setting is supported,
- therfore maximum key size is 13)
-*/
-
-#define CC3000_MINIMAL_RX_SIZE (130 + 1)
-#define CC3000_MAXIMAL_RX_SIZE (1519 + 1)
-
-/*Defines for minimal and maximal TX buffer size.
- This buffer is used for sending events and data.
- The packet can not be longer than MTU size and CC3000 does not support
- fragmentation. Note that the same buffer is used for transmission of the data
- and commands. That is why the minimum is defined.
- The calculation for the actual size of buffer for transmission is:
- Given the maximal data size MAX_DATA, the required buffer is:
- Using Sendto():
-
- max(CC3000_MINIMAL_TX_SIZE, MAX_DATA + SPI_HEADER_SIZE
- + SOCKET_SENDTO_PARAMS_LEN + SIMPLE_LINK_HCI_DATA_HEADER_SIZE + 1)
-
- Using Send():
-
- max(CC3000_MINIMAL_TX_SIZE, MAX_DATA + SPI_HEADER_SIZE
- + HCI_CMND_SEND_ARG_LENGTH + SIMPLE_LINK_HCI_DATA_HEADER_SIZE + 1)
-
- The 1 is used for the overrun detection */
-
-#define CC3000_MINIMAL_TX_SIZE (130 + 1)
-#define CC3000_MAXIMAL_TX_SIZE (1519 + 1)
-
-//TX and RX buffer sizes, allow to receive and transmit maximum data at length 8.
-#ifdef CC3000_TINY_DRIVER
-#define TINY_CC3000_MAXIMAL_RX_SIZE 44
-#define TINY_CC3000_MAXIMAL_TX_SIZE 59
-#endif
-
-/*In order to determine your preferred buffer size,
- change CC3000_MAXIMAL_RX_SIZE and CC3000_MAXIMAL_TX_SIZE to a value between
- the minimal and maximal specified above.
- Note that the buffers are allocated by SPI.
- In case you change the size of those buffers, you might need also to change
- the linker file, since for example on MSP430 FRAM devices the buffers are
- allocated in the FRAM section that is allocated manually and not by IDE.
-*/
-
-#ifndef CC3000_TINY_DRIVER
-
- #define CC3000_RX_BUFFER_SIZE (CC3000_MAXIMAL_RX_SIZE)
- #define CC3000_TX_BUFFER_SIZE (CC3000_MAXIMAL_TX_SIZE)
-
-//if defined TINY DRIVER we use smaller RX and TX buffer in order to minimize RAM consumption
-#else
- #define CC3000_RX_BUFFER_SIZE (TINY_CC3000_MAXIMAL_RX_SIZE)
- #define CC3000_TX_BUFFER_SIZE (TINY_CC3000_MAXIMAL_TX_SIZE)
-
-#endif
-
-//*****************************************************************************
-// Compound Types
-//*****************************************************************************
-typedef INT32 cc3000_time_t;
-typedef UINT32 clock_t;
-typedef INT32 suseconds_t;
-
-typedef struct cc3000_timeval cc3000_timeval;
-
-struct cc3000_timeval
-{
- cc3000_time_t tv_sec; /* seconds */
- suseconds_t tv_usec; /* microseconds */
-};
-
-typedef CHAR *(*tFWPatches)(UINT32 *usLength);
-
-typedef CHAR *(*tDriverPatches)(UINT32 *usLength);
-
-typedef CHAR *(*tBootLoaderPatches)(UINT32 *usLength);
-
-typedef void (*tWlanCB)(INT32 event_type, CHAR * data, UINT8 length );
-
-typedef INT32 (*tWlanReadInteruptPin)(void);
-
-typedef void (*tWlanInterruptEnable)(void);
-
-typedef void (*tWlanInterruptDisable)(void);
-
-typedef void (*tWriteWlanPin)(UINT8 val);
-
-typedef struct
-{
- UINT16 usRxEventOpcode;
- UINT16 usEventOrDataReceived;
- UINT8 *pucReceivedData;
- UINT8 *pucTxCommandBuffer;
-
- tFWPatches sFWPatches;
- tDriverPatches sDriverPatches;
- tBootLoaderPatches sBootLoaderPatches;
- tWlanCB sWlanCB;
- tWlanReadInteruptPin ReadWlanInterruptPin;
- tWlanInterruptEnable WlanInterruptEnable;
- tWlanInterruptDisable WlanInterruptDisable;
- tWriteWlanPin WriteWlanPin;
-
- INT32 slTransmitDataError;
- UINT16 usNumberOfFreeBuffers;
- UINT16 usSlBufferLength;
- UINT16 usBufferSize;
- UINT16 usRxDataPending;
-
- UINT32 NumberOfSentPackets;
- UINT32 NumberOfReleasedPackets;
-
- UINT8 InformHostOnTxComplete;
-}sSimplLinkInformation;
-
-extern volatile sSimplLinkInformation tSLInformation;
-
-
-//*****************************************************************************
-// Prototypes for the APIs.
-//*****************************************************************************
-
-
-
-//*****************************************************************************
-//
-//! SimpleLinkWaitEvent
-//!
-//! @param usOpcode command operation code
-//! @param pRetParams command return parameters
-//!
-//! @return none
-//!
-//! @brief Wait for event, pass it to the hci_event_handler and
-//! update the event opcode in a global variable.
-//
-//*****************************************************************************
-
-extern void SimpleLinkWaitEvent(UINT16 usOpcode, void *pRetParams);
-
-//*****************************************************************************
-//
-//! SimpleLinkWaitData
-//!
-//! @param pBuf data buffer
-//! @param from from information
-//! @param fromlen from information length
-//!
-//! @return none
-//!
-//! @brief Wait for data, pass it to the hci_event_handler
-//! and update in a global variable that there is
-//! data to read.
-//
-//*****************************************************************************
-
-extern void SimpleLinkWaitData(UINT8 *pBuf, UINT8 *from, UINT8 *fromlen);
-
-//*****************************************************************************
-//
-//! UINT32_TO_STREAM_f
-//!
-//! \param p pointer to the new stream
-//! \param u32 pointer to the 32 bit
-//!
-//! \return pointer to the new stream
-//!
-//! \brief This function is used for copying 32 bit to stream
-//! while converting to little endian format.
-//
-//*****************************************************************************
-
-extern UINT8* UINT32_TO_STREAM_f (UINT8 *p, UINT32 u32);
-
-//*****************************************************************************
-//
-//! UINT16_TO_STREAM_f
-//!
-//! \param p pointer to the new stream
-//! \param u32 pointer to the 16 bit
-//!
-//! \return pointer to the new stream
-//!
-//! \brief This function is used for copying 16 bit to stream
-//! while converting to little endian format.
-//
-//*****************************************************************************
-
-extern UINT8* UINT16_TO_STREAM_f (UINT8 *p, UINT16 u16);
-
-//*****************************************************************************
-//
-//! STREAM_TO_UINT16_f
-//!
-//! \param p pointer to the stream
-//! \param offset offset in the stream
-//!
-//! \return pointer to the new 16 bit
-//!
-//! \brief This function is used for copying received stream to
-//! 16 bit in little endian format.
-//
-//*****************************************************************************
-
-extern UINT16 STREAM_TO_UINT16_f(CHAR* p, UINT16 offset);
-
-//*****************************************************************************
-//
-//! STREAM_TO_UINT32_f
-//!
-//! \param p pointer to the stream
-//! \param offset offset in the stream
-//!
-//! \return pointer to the new 32 bit
-//!
-//! \brief This function is used for copying received stream to
-//! 32 bit in little endian format.
-//
-//*****************************************************************************
-
-extern UINT32 STREAM_TO_UINT32_f(CHAR* p, UINT16 offset);
-
-
-//*****************************************************************************
-// COMMON MACROs
-//*****************************************************************************
-
-
-//This macro is used for copying 8 bit to stream while converting to little endian format.
-#define UINT8_TO_STREAM(_p, _val) {*(_p)++ = (_val);}
-//This macro is used for copying 16 bit to stream while converting to little endian format.
-#define UINT16_TO_STREAM(_p, _u16) (UINT16_TO_STREAM_f(_p, _u16))
-//This macro is used for copying 32 bit to stream while converting to little endian format.
-#define UINT32_TO_STREAM(_p, _u32) (UINT32_TO_STREAM_f(_p, _u32))
-//This macro is used for copying a specified value length bits (l) to stream while converting to little endian format.
-#define ARRAY_TO_STREAM(p, a, l) {register INT16 _i; for (_i = 0; _i < l; _i++) *(p)++ = ((UINT8 *) a)[_i];}
-//This macro is used for copying received stream to 8 bit in little endian format.
-#define STREAM_TO_UINT8(_p, _offset, _u8) {_u8 = (UINT8)(*(_p + _offset));}
-//This macro is used for copying received stream to 16 bit in little endian format.
-#define STREAM_TO_UINT16(_p, _offset, _u16) {_u16 = STREAM_TO_UINT16_f(_p, _offset);}
-//This macro is used for copying received stream to 32 bit in little endian format.
-#define STREAM_TO_UINT32(_p, _offset, _u32) {_u32 = STREAM_TO_UINT32_f(_p, _offset);}
-#define STREAM_TO_STREAM(p, a, l) {register INT16 _i; for (_i = 0; _i < l; _i++) *(a)++= ((UINT8 *) p)[_i];}
-
-
-
-
-//*****************************************************************************
-//
-// Mark the end of the C bindings section for C++ compilers.
-//
-//*****************************************************************************
-#ifdef __cplusplus
-}
-#endif // __cplusplus
-
-#endif // __CC3000_COMMON_H__
diff --git a/drivers/cc3000/inc/ccspi.h b/drivers/cc3000/inc/ccspi.h
deleted file mode 100644
index 8fa3ecd10c2f..000000000000
--- a/drivers/cc3000/inc/ccspi.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/*****************************************************************************
-*
-* spi.h - CC3000 Host Driver Implementation.
-* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
-*
-* 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 Texas Instruments Incorporated 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
-* OWNER 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.
-*
-*****************************************************************************/
-
-
-#ifndef __CC3000_SPI_H__
-#define __CC3000_SPI_H__
-
-//*****************************************************************************
-//
-// If building with a C++ compiler, make all of the definitions in this header
-// have a C binding.
-//
-//*****************************************************************************
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef void (*gcSpiHandleRx)(void *p);
-typedef void (*gcSpiHandleTx)(void);
-extern unsigned char wlan_tx_buffer[];
-
-//*****************************************************************************
-//
-// Prototypes for the APIs.
-//
-//*****************************************************************************
-
-// the arguments must be of type pin_obj_t* and SPI_HandleTypeDef*
-extern void SpiInit(void *spi, const void *pin_cs, const void *pin_en, const void *pin_irq);
-
-extern void SpiOpen(gcSpiHandleRx pfRxHandler);
-extern void SpiClose(void);
-extern void SpiPauseSpi(void);
-extern void SpiResumeSpi(void);
-extern long SpiWrite(unsigned char *pUserBuffer, unsigned short usLength);
-extern void SpiConfigureHwMapping(void);
-extern void SpiCleanGPIOISR(void);
-extern void SSIConfigure(unsigned long ulSSIFreq, unsigned long bForceGpioConfiguration, unsigned long uiReconfigureSysClock);
-extern int init_spi(void);
-extern long ReadWlanInterruptPin(void);
-extern void WriteWlanPin(unsigned char val);
-//*****************************************************************************
-//
-// Mark the end of the C bindings section for C++ compilers.
-//
-//*****************************************************************************
-#ifdef __cplusplus
-}
-#endif // __cplusplus
-
-#endif
-
diff --git a/drivers/cc3000/inc/data_types.h b/drivers/cc3000/inc/data_types.h
deleted file mode 100644
index 0520a9202fb8..000000000000
--- a/drivers/cc3000/inc/data_types.h
+++ /dev/null
@@ -1,107 +0,0 @@
-/*****************************************************************************
-*
-* data_types.h - CC3000 Host Driver Implementation.
-* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
-*
-* 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 Texas Instruments Incorporated 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
-* OWNER 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.
-*
-*****************************************************************************/
-#ifndef __CC3000_DATA_TYPES__
-#define __CC3000_DATA_TYPES__
-
-//*****************************************************************************
-//
-// If building with a C++ compiler, make all of the definitions in this header
-// have a C binding.
-//
-//*****************************************************************************
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-#ifndef NULL
-#define NULL (0)
-#endif
-
-#ifndef FALSE
-#define FALSE (0)
-#endif
-
-#ifndef TRUE
-#define TRUE (!FALSE)
-#endif
-
-#ifndef OK
-#define OK (0)
-#endif
-
-#ifndef _INT8
-#define _INT8
-typedef signed char INT8;
-#endif
-
-#ifndef _UINT8
-#define _UINT8
-typedef unsigned char UINT8;
-#endif
-
-#ifndef _INT16
-#define _INT16
-typedef signed short INT16;
-#endif
-
-#ifndef _UINT16
-#define _UINT16
-typedef unsigned short UINT16;
-#endif
-
-#ifndef _BOOLEAN
-#define _BOOLEAN
-typedef unsigned char BOOLEAN;
-#endif
-
-#ifndef _INT32
-#define _INT32
-typedef signed long INT32;
-#endif
-
-#ifndef _UINT32
-#define _UINT32
-typedef unsigned long UINT32;
-#endif
-
-typedef int INT;
-typedef char CHAR;
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif /* __CC3000_DATA_TYPES__ */
diff --git a/drivers/cc3000/inc/evnt_handler.h b/drivers/cc3000/inc/evnt_handler.h
deleted file mode 100644
index d05a442f05fb..000000000000
--- a/drivers/cc3000/inc/evnt_handler.h
+++ /dev/null
@@ -1,166 +0,0 @@
-/*****************************************************************************
-*
-* evnt_handler.h - CC3000 Host Driver Implementation.
-* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
-*
-* 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 Texas Instruments Incorporated 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
-* OWNER 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.
-*
-*****************************************************************************/
-#ifndef __CC3000_EVENT_HANDLER_H__
-#define __CC3000_EVENT_HANDLER_H__
-#include "hci.h"
-#include "socket.h"
-
-//*****************************************************************************
-//
-// If building with a C++ compiler, make all of the definitions in this header
-// have a C binding.
-//
-//*****************************************************************************
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-//*****************************************************************************
-//
-// Prototypes for the APIs.
-//
-//*****************************************************************************
-
-//*****************************************************************************
-//
-//! hci_event_handler
-//!
-//! @param pRetParams incoming data buffer
-//! @param from from information (in case of data received)
-//! @param fromlen from information length (in case of data received)
-//!
-//! @return none
-//!
-//! @brief Parse the incoming events packets and issues corresponding
-//! event handler from global array of handlers pointers
-//
-//*****************************************************************************
-extern UINT8 *hci_event_handler(void *pRetParams, UINT8 *from, UINT8 *fromlen);
-
-//*****************************************************************************
-//
-//! hci_unsol_event_handler
-//!
-//! @param event_hdr event header
-//!
-//! @return 1 if event supported and handled
-//! 0 if event is not supported
-//!
-//! @brief Handle unsolicited events
-//
-//*****************************************************************************
-extern INT32 hci_unsol_event_handler(CHAR *event_hdr);
-
-//*****************************************************************************
-//
-//! hci_unsolicited_event_handler
-//!
-//! @param None
-//!
-//! @return ESUCCESS if successful, EFAIL if an error occurred
-//!
-//! @brief Parse the incoming unsolicited event packets and issues
-//! corresponding event handler.
-//
-//*****************************************************************************
-extern INT32 hci_unsolicited_event_handler(void);
-
-#define M_BSD_RESP_PARAMS_OFFSET(hci_event_hdr)((CHAR *)(hci_event_hdr) + HCI_EVENT_HEADER_SIZE)
-
-#define SOCKET_STATUS_ACTIVE 0
-#define SOCKET_STATUS_INACTIVE 1
-/* Init socket_active_status = 'all ones': init all sockets with SOCKET_STATUS_INACTIVE.
- Will be changed by 'set_socket_active_status' upon 'connect' and 'accept' calls */
-#define SOCKET_STATUS_INIT_VAL 0xFFFF
-#define M_IS_VALID_SD(sd) ((0 <= (sd)) && ((sd) <= 7))
-#define M_IS_VALID_STATUS(status) (((status) == SOCKET_STATUS_ACTIVE)||((status) == SOCKET_STATUS_INACTIVE))
-
-extern UINT32 socket_active_status;
-
-extern void set_socket_active_status(INT32 Sd, INT32 Status);
-extern INT32 get_socket_active_status(INT32 Sd);
-
-typedef struct _bsd_accept_return_t
-{
- INT32 iSocketDescriptor;
- INT32 iStatus;
- sockaddr tSocketAddress;
-
-} tBsdReturnParams;
-
-
-typedef struct _bsd_read_return_t
-{
- INT32 iSocketDescriptor;
- INT32 iNumberOfBytes;
- UINT32 uiFlags;
-} tBsdReadReturnParams;
-
-#define BSD_RECV_FROM_FROMLEN_OFFSET (4)
-#define BSD_RECV_FROM_FROM_OFFSET (16)
-
-
-typedef struct _bsd_select_return_t
-{
- INT32 iStatus;
- UINT32 uiRdfd;
- UINT32 uiWrfd;
- UINT32 uiExfd;
-} tBsdSelectRecvParams;
-
-
-typedef struct _bsd_getsockopt_return_t
-{
- UINT8 ucOptValue[4];
- CHAR iStatus;
-} tBsdGetSockOptReturnParams;
-
-typedef struct _bsd_gethostbyname_return_t
-{
- INT32 retVal;
- INT32 outputAddress;
-} tBsdGethostbynameParams;
-
-//*****************************************************************************
-//
-// Mark the end of the C bindings section for C++ compilers.
-//
-//*****************************************************************************
-#ifdef __cplusplus
-}
-#endif // __cplusplus
-
-#endif // __CC3000_EVENT_HANDLER_H__
-
diff --git a/drivers/cc3000/inc/hci.h b/drivers/cc3000/inc/hci.h
deleted file mode 100644
index f12b00e918e1..000000000000
--- a/drivers/cc3000/inc/hci.h
+++ /dev/null
@@ -1,330 +0,0 @@
-/*****************************************************************************
-*
-* hci.h - CC3000 Host Driver Implementation.
-* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
-*
-* 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 Texas Instruments Incorporated 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
-* OWNER 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.
-*
-*****************************************************************************/
-#ifndef __CC3000_HCI_H__
-#define __CC3000_HCI_H__
-
-#include "cc3000_common.h"
-
-//*****************************************************************************
-//
-// If building with a C++ compiler, make all of the definitions in this header
-// have a C binding.
-//
-//*****************************************************************************
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-#define SPI_HEADER_SIZE (5)
-#define SIMPLE_LINK_HCI_CMND_HEADER_SIZE (4)
-#define HEADERS_SIZE_CMD (SPI_HEADER_SIZE + SIMPLE_LINK_HCI_CMND_HEADER_SIZE)
-#define SIMPLE_LINK_HCI_DATA_CMND_HEADER_SIZE (5)
-#define SIMPLE_LINK_HCI_DATA_HEADER_SIZE (5)
-#define SIMPLE_LINK_HCI_PATCH_HEADER_SIZE (2)
-
-
-//*****************************************************************************
-//
-// Values that can be used as HCI Commands and HCI Packet header defines
-//
-//*****************************************************************************
-#define HCI_TYPE_CMND 0x1
-#define HCI_TYPE_DATA 0x2
-#define HCI_TYPE_PATCH 0x3
-#define HCI_TYPE_EVNT 0x4
-
-
-#define HCI_EVENT_PATCHES_DRV_REQ (1)
-#define HCI_EVENT_PATCHES_FW_REQ (2)
-#define HCI_EVENT_PATCHES_BOOTLOAD_REQ (3)
-
-
-#define HCI_CMND_WLAN_BASE (0x0000)
-#define HCI_CMND_WLAN_CONNECT 0x0001
-#define HCI_CMND_WLAN_DISCONNECT 0x0002
-#define HCI_CMND_WLAN_IOCTL_SET_SCANPARAM 0x0003
-#define HCI_CMND_WLAN_IOCTL_SET_CONNECTION_POLICY 0x0004
-#define HCI_CMND_WLAN_IOCTL_ADD_PROFILE 0x0005
-#define HCI_CMND_WLAN_IOCTL_DEL_PROFILE 0x0006
-#define HCI_CMND_WLAN_IOCTL_GET_SCAN_RESULTS 0x0007
-#define HCI_CMND_EVENT_MASK 0x0008
-#define HCI_CMND_WLAN_IOCTL_STATUSGET 0x0009
-#define HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_START 0x000A
-#define HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_STOP 0x000B
-#define HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_SET_PREFIX 0x000C
-#define HCI_CMND_WLAN_CONFIGURE_PATCH 0x000D
-
-
-#define HCI_CMND_SOCKET_BASE 0x1000
-#define HCI_CMND_SOCKET 0x1001
-#define HCI_CMND_BIND 0x1002
-#define HCI_CMND_RECV 0x1004
-#define HCI_CMND_ACCEPT 0x1005
-#define HCI_CMND_LISTEN 0x1006
-#define HCI_CMND_CONNECT 0x1007
-#define HCI_CMND_BSD_SELECT 0x1008
-#define HCI_CMND_SETSOCKOPT 0x1009
-#define HCI_CMND_GETSOCKOPT 0x100A
-#define HCI_CMND_CLOSE_SOCKET 0x100B
-#define HCI_CMND_RECVFROM 0x100D
-#define HCI_CMND_GETHOSTNAME 0x1010
-#define HCI_CMND_MDNS_ADVERTISE 0x1011
-#define HCI_CMND_GETMSSVALUE 0x1012
-
-
-#define HCI_DATA_BASE 0x80
-
-#define HCI_CMND_SEND (0x01 + HCI_DATA_BASE)
-#define HCI_CMND_SENDTO (0x03 + HCI_DATA_BASE)
-#define HCI_DATA_BSD_RECVFROM (0x04 + HCI_DATA_BASE)
-#define HCI_DATA_BSD_RECV (0x05 + HCI_DATA_BASE)
-
-
-#define HCI_CMND_NVMEM_CBASE (0x0200)
-
-
-#define HCI_CMND_NVMEM_CREATE_ENTRY (0x0203)
-#define HCI_CMND_NVMEM_SWAP_ENTRY (0x0205)
-#define HCI_CMND_NVMEM_READ (0x0201)
-#define HCI_CMND_NVMEM_WRITE (0x0090)
-#define HCI_CMND_NVMEM_WRITE_PATCH (0x0204)
-#define HCI_CMND_READ_SP_VERSION (0x0207)
-
-#define HCI_CMND_READ_BUFFER_SIZE 0x400B
-#define HCI_CMND_SIMPLE_LINK_START 0x4000
-
-#define HCI_CMND_NETAPP_BASE 0x2000
-
-#define HCI_NETAPP_DHCP (0x0001 + HCI_CMND_NETAPP_BASE)
-#define HCI_NETAPP_PING_SEND (0x0002 + HCI_CMND_NETAPP_BASE)
-#define HCI_NETAPP_PING_REPORT (0x0003 + HCI_CMND_NETAPP_BASE)
-#define HCI_NETAPP_PING_STOP (0x0004 + HCI_CMND_NETAPP_BASE)
-#define HCI_NETAPP_IPCONFIG (0x0005 + HCI_CMND_NETAPP_BASE)
-#define HCI_NETAPP_ARP_FLUSH (0x0006 + HCI_CMND_NETAPP_BASE)
-#define HCI_NETAPP_SET_DEBUG_LEVEL (0x0008 + HCI_CMND_NETAPP_BASE)
-#define HCI_NETAPP_SET_TIMERS (0x0009 + HCI_CMND_NETAPP_BASE)
-
-
-
-
-
-
-//*****************************************************************************
-//
-// Values that can be used as HCI Events defines
-//
-//*****************************************************************************
-#define HCI_EVNT_WLAN_BASE 0x0000
-#define HCI_EVNT_WLAN_CONNECT 0x0001
-#define HCI_EVNT_WLAN_DISCONNECT \
- 0x0002
-#define HCI_EVNT_WLAN_IOCTL_ADD_PROFILE \
- 0x0005
-
-
-#define HCI_EVNT_SOCKET HCI_CMND_SOCKET
-#define HCI_EVNT_BIND HCI_CMND_BIND
-#define HCI_EVNT_RECV HCI_CMND_RECV
-#define HCI_EVNT_ACCEPT HCI_CMND_ACCEPT
-#define HCI_EVNT_LISTEN HCI_CMND_LISTEN
-#define HCI_EVNT_CONNECT HCI_CMND_CONNECT
-#define HCI_EVNT_SELECT HCI_CMND_BSD_SELECT
-#define HCI_EVNT_CLOSE_SOCKET HCI_CMND_CLOSE_SOCKET
-#define HCI_EVNT_RECVFROM HCI_CMND_RECVFROM
-#define HCI_EVNT_SETSOCKOPT HCI_CMND_SETSOCKOPT
-#define HCI_EVNT_GETSOCKOPT HCI_CMND_GETSOCKOPT
-#define HCI_EVNT_BSD_GETHOSTBYNAME HCI_CMND_GETHOSTNAME
-#define HCI_EVNT_MDNS_ADVERTISE HCI_CMND_MDNS_ADVERTISE
-#define HCI_EVNT_GETMSSVALUE HCI_CMND_GETMSSVALUE
-
-#define HCI_EVNT_SEND 0x1003
-#define HCI_EVNT_WRITE 0x100E
-#define HCI_EVNT_SENDTO 0x100F
-
-#define HCI_EVNT_PATCHES_REQ 0x1000
-
-#define HCI_EVNT_UNSOL_BASE 0x4000
-
-#define HCI_EVNT_WLAN_UNSOL_BASE (0x8000)
-
-#define HCI_EVNT_WLAN_UNSOL_CONNECT (0x0001 + HCI_EVNT_WLAN_UNSOL_BASE)
-#define HCI_EVNT_WLAN_UNSOL_DISCONNECT (0x0002 + HCI_EVNT_WLAN_UNSOL_BASE)
-#define HCI_EVNT_WLAN_UNSOL_INIT (0x0004 + HCI_EVNT_WLAN_UNSOL_BASE)
-#define HCI_EVNT_WLAN_TX_COMPLETE (0x0008 + HCI_EVNT_WLAN_UNSOL_BASE)
-#define HCI_EVNT_WLAN_UNSOL_DHCP (0x0010 + HCI_EVNT_WLAN_UNSOL_BASE)
-#define HCI_EVNT_WLAN_ASYNC_PING_REPORT (0x0040 + HCI_EVNT_WLAN_UNSOL_BASE)
-#define HCI_EVNT_WLAN_ASYNC_SIMPLE_CONFIG_DONE (0x0080 + HCI_EVNT_WLAN_UNSOL_BASE)
-#define HCI_EVNT_WLAN_KEEPALIVE (0x0200 + HCI_EVNT_WLAN_UNSOL_BASE)
-#define HCI_EVNT_BSD_TCP_CLOSE_WAIT (0x0800 + HCI_EVNT_WLAN_UNSOL_BASE)
-
-#define HCI_EVNT_DATA_UNSOL_FREE_BUFF \
- 0x4100
-
-#define HCI_EVNT_NVMEM_CREATE_ENTRY \
- HCI_CMND_NVMEM_CREATE_ENTRY
-#define HCI_EVNT_NVMEM_SWAP_ENTRY HCI_CMND_NVMEM_SWAP_ENTRY
-
-#define HCI_EVNT_NVMEM_READ HCI_CMND_NVMEM_READ
-#define HCI_EVNT_NVMEM_WRITE (0x0202)
-
-#define HCI_EVNT_READ_SP_VERSION \
- HCI_CMND_READ_SP_VERSION
-
-#define HCI_EVNT_INPROGRESS 0xFFFF
-
-
-#define HCI_DATA_RECVFROM 0x84
-#define HCI_DATA_RECV 0x85
-#define HCI_DATA_NVMEM 0x91
-
-#define HCI_EVENT_CC3000_CAN_SHUT_DOWN 0x99
-
-//*****************************************************************************
-//
-// Prototypes for the structures for APIs.
-//
-//*****************************************************************************
-
-#define HCI_DATA_HEADER_SIZE (5)
-#define HCI_EVENT_HEADER_SIZE (5)
-#define HCI_DATA_CMD_HEADER_SIZE (5)
-#define HCI_PATCH_HEADER_SIZE (6)
-
-#define HCI_PACKET_TYPE_OFFSET (0)
-#define HCI_PACKET_ARGSIZE_OFFSET (2)
-#define HCI_PACKET_LENGTH_OFFSET (3)
-
-
-#define HCI_EVENT_OPCODE_OFFSET (1)
-#define HCI_EVENT_LENGTH_OFFSET (3)
-#define HCI_EVENT_STATUS_OFFSET (4)
-#define HCI_DATA_LENGTH_OFFSET (3)
-
-
-
-
-//*****************************************************************************
-//
-// Prototypes for the APIs.
-//
-//*****************************************************************************
-
-//*****************************************************************************
-//
-//! hci_command_send
-//!
-//! @param usOpcode command operation code
-//! @param pucBuff pointer to the command's arguments buffer
-//! @param ucArgsLength length of the arguments
-//!
-//! @return none
-//!
-//! @brief Initiate an HCI command.
-//
-//*****************************************************************************
-extern UINT16 hci_command_send(UINT16 usOpcode,
- UINT8 *ucArgs,
- UINT8 ucArgsLength);
-
-
-//*****************************************************************************
-//
-//! hci_data_send
-//!
-//! @param usOpcode command operation code
-//! @param ucArgs pointer to the command's arguments buffer
-//! @param usArgsLength length of the arguments
-//! @param ucTail pointer to the data buffer
-//! @param usTailLength buffer length
-//!
-//! @return none
-//!
-//! @brief Initiate an HCI data write operation
-//
-//*****************************************************************************
-extern INT32 hci_data_send(UINT8 ucOpcode,
- UINT8 *ucArgs,
- UINT16 usArgsLength,
- UINT16 usDataLength,
- const UINT8 *ucTail,
- UINT16 usTailLength);
-
-
-//*****************************************************************************
-//
-//! hci_data_command_send
-//!
-//! @param usOpcode command operation code
-//! @param pucBuff pointer to the data buffer
-//! @param ucArgsLength arguments length
-//! @param ucDataLength data length
-//!
-//! @return none
-//!
-//! @brief Prepare HCI header and initiate an HCI data write operation
-//
-//*****************************************************************************
-extern void hci_data_command_send(UINT16 usOpcode, UINT8 *pucBuff,
- UINT8 ucArgsLength, UINT16 ucDataLength);
-
-//*****************************************************************************
-//
-//! hci_patch_send
-//!
-//! @param usOpcode command operation code
-//! @param pucBuff pointer to the command's arguments buffer
-//! @param patch pointer to patch content buffer
-//! @param usDataLength data length
-//!
-//! @return none
-//!
-//! @brief Prepare HCI header and initiate an HCI patch write operation
-//
-//*****************************************************************************
-extern void hci_patch_send(UINT8 ucOpcode, UINT8 *pucBuff, CHAR *patch, UINT16 usDataLength);
-
-
-
-//*****************************************************************************
-//
-// Mark the end of the C bindings section for C++ compilers.
-//
-//*****************************************************************************
-#ifdef __cplusplus
-}
-#endif // __cplusplus
-
-#endif // __CC3000_HCI_H__
diff --git a/drivers/cc3000/inc/host_driver_version.h b/drivers/cc3000/inc/host_driver_version.h
deleted file mode 100644
index a28d21f1beac..000000000000
--- a/drivers/cc3000/inc/host_driver_version.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*****************************************************************************
-*
-* host_driver_version.h - CC3000 Host Driver Implementation.
-* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
-*
-* 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 Texas Instruments Incorporated 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
-* OWNER 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.
-*
-*****************************************************************************/
-#ifndef __CC3000_HOST_DRIVER_VERSION_H__
-#define __CC3000_HOST_DRIVER_VERSION_H__
-
-#define DRIVER_VERSION_NUMBER 15
-
-#endif // __CC3000_HOST_DRIVER_VERSION_H__
diff --git a/drivers/cc3000/inc/inet_ntop.h b/drivers/cc3000/inc/inet_ntop.h
deleted file mode 100644
index fa70806206ac..000000000000
--- a/drivers/cc3000/inc/inet_ntop.h
+++ /dev/null
@@ -1,4 +0,0 @@
-#ifndef __INET_NTOP_H
-#define __INET_NTOP_H
-char *inet_ntop(int af, const void *addr, char *buf, size_t size);
-#endif /* __INET_NTOP_H */
diff --git a/drivers/cc3000/inc/inet_pton.h b/drivers/cc3000/inc/inet_pton.h
deleted file mode 100644
index 0896d5d29fd7..000000000000
--- a/drivers/cc3000/inc/inet_pton.h
+++ /dev/null
@@ -1,4 +0,0 @@
-#ifndef __INET_PTON_H
-#define __INET_PTON_H
-int inet_pton(int, const char *, void *);
-#endif /* __INET_PTON_H */
diff --git a/drivers/cc3000/inc/netapp.h b/drivers/cc3000/inc/netapp.h
deleted file mode 100644
index 1e4f26589656..000000000000
--- a/drivers/cc3000/inc/netapp.h
+++ /dev/null
@@ -1,343 +0,0 @@
-/*****************************************************************************
-*
-* netapp.h - CC3000 Host Driver Implementation.
-* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
-*
-* 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 Texas Instruments Incorporated 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
-* OWNER 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.
-*
-*****************************************************************************/
-#ifndef __CC3000_NETAPP_H__
-#define __CC3000_NETAPP_H__
-
-#include "data_types.h"
-
-//*****************************************************************************
-//
-// If building with a C++ compiler, make all of the definitions in this header
-// have a C binding.
-//
-//*****************************************************************************
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-//*****************************************************************************
-//
-//! \addtogroup netapp_api
-//! @{
-//
-//*****************************************************************************
-
-typedef struct _netapp_dhcp_ret_args_t
-{
- UINT8 aucIP[4];
- UINT8 aucSubnetMask[4];
- UINT8 aucDefaultGateway[4];
- UINT8 aucDHCPServer[4];
- UINT8 aucDNSServer[4];
-}tNetappDhcpParams;
-
-typedef struct _netapp_ipconfig_ret_args_t
-{
- UINT8 aucIP[4];
- UINT8 aucSubnetMask[4];
- UINT8 aucDefaultGateway[4];
- UINT8 aucDHCPServer[4];
- UINT8 aucDNSServer[4];
- UINT8 uaMacAddr[6];
- UINT8 uaSSID[32];
-}tNetappIpconfigRetArgs;
-
-
-/*Ping send report parameters*/
-typedef struct _netapp_pingreport_args
-{
- UINT32 packets_sent;
- UINT32 packets_received;
- UINT32 min_round_time;
- UINT32 max_round_time;
- UINT32 avg_round_time;
-} netapp_pingreport_args_t;
-
-
-//*****************************************************************************
-//
-//! netapp_config_mac_adrress
-//!
-//! @param mac device mac address, 6 bytes. Saved: yes
-//!
-//! @return return on success 0, otherwise error.
-//!
-//! @brief Configure device MAC address and store it in NVMEM.
-//! The value of the MAC address configured through the API will
-//! be stored in CC3000 non volatile memory, thus preserved
-//! over resets.
-//
-//*****************************************************************************
-extern INT32 netapp_config_mac_adrress( UINT8 *mac );
-
-//*****************************************************************************
-//
-//! netapp_dhcp
-//!
-//! @param aucIP device mac address, 6 bytes. Saved: yes
-//! @param aucSubnetMask device mac address, 6 bytes. Saved: yes
-//! @param aucDefaultGateway device mac address, 6 bytes. Saved: yes
-//! @param aucDNSServer device mac address, 6 bytes. Saved: yes
-//!
-//! @return return on success 0, otherwise error.
-//!
-//! @brief netapp_dhcp is used to configure the network interface,
-//! static or dynamic (DHCP).\n In order to activate DHCP mode,
-//! aucIP, aucSubnetMask, aucDefaultGateway must be 0.
-//! The default mode of CC3000 is DHCP mode.
-//! Note that the configuration is saved in non volatile memory
-//! and thus preserved over resets.
-//!
-//! @note If the mode is altered a reset of CC3000 device is required
-//! in order to apply changes.\nAlso note that asynchronous event
-//! of DHCP_EVENT, which is generated when an IP address is
-//! allocated either by the DHCP server or due to static
-//! allocation is generated only upon a connection to the
-//! AP was established.
-//!
-//*****************************************************************************
-extern INT32 netapp_dhcp(UINT32 *aucIP, UINT32 *aucSubnetMask,UINT32 *aucDefaultGateway, UINT32 *aucDNSServer);
-
-
-
-//*****************************************************************************
-//
-//! netapp_timeout_values
-//!
-//! @param aucDHCP DHCP lease time request, also impact
-//! the DHCP renew timeout. Range: [0-0xffffffff] seconds,
-//! 0 or 0xffffffff == infinity lease timeout.
-//! Resolution:10 seconds. Influence: only after
-//! reconnecting to the AP.
-//! Minimal bound value: MIN_TIMER_VAL_SECONDS - 10 seconds.
-//! The parameter is saved into the CC3000 NVMEM.
-//! The default value on CC3000 is 14400 seconds.
-//!
-//! @param aucARP ARP refresh timeout, if ARP entry is not updated by
-//! incoming packet, the ARP entry will be deleted by
-//! the end of the timeout.
-//! Range: [0-0xffffffff] seconds, 0 == infinity ARP timeout
-//! Resolution: 10 seconds. Influence: on runtime.
-//! Minimal bound value: MIN_TIMER_VAL_SECONDS - 10 seconds
-//! The parameter is saved into the CC3000 NVMEM.
-//! The default value on CC3000 is 3600 seconds.
-//!
-//! @param aucKeepalive Keepalive event sent by the end of keepalive timeout
-//! Range: [0-0xffffffff] seconds, 0 == infinity timeout
-//! Resolution: 10 seconds.
-//! Influence: on runtime.
-//! Minimal bound value: MIN_TIMER_VAL_SECONDS - 10 sec
-//! The parameter is saved into the CC3000 NVMEM.
-//! The default value on CC3000 is 10 seconds.
-//!
-//! @param aucInactivity Socket inactivity timeout, socket timeout is
-//! refreshed by incoming or outgoing packet, by the
-//! end of the socket timeout the socket will be closed
-//! Range: [0-0xffffffff] sec, 0 == infinity timeout.
-//! Resolution: 10 seconds. Influence: on runtime.
-//! Minimal bound value: MIN_TIMER_VAL_SECONDS - 10 sec
-//! The parameter is saved into the CC3000 NVMEM.
-//! The default value on CC3000 is 60 seconds.
-//!
-//! @return return on success 0, otherwise error.
-//!
-//! @brief Set new timeout values. Function set new timeout values for:
-//! DHCP lease timeout, ARP refresh timeout, keepalive event
-//! timeout and socket inactivity timeout
-//!
-//! @note If a parameter set to non zero value which is less than 10s,
-//! it will be set automatically to 10s.
-//!
-//*****************************************************************************
-#ifndef CC3000_TINY_DRIVER
-extern INT32 netapp_timeout_values(UINT32 *aucDHCP, UINT32 *aucARP, UINT32 *aucKeepalive, UINT32 *aucInactivity);
-#endif
-
-//*****************************************************************************
-//
-//! netapp_ping_send
-//!
-//! @param ip destination IP address
-//! @param pingAttempts number of echo requests to send
-//! @param pingSize send buffer size which may be up to 1400 bytes
-//! @param pingTimeout Time to wait for a response,in milliseconds.
-//!
-//! @return return on success 0, otherwise error.
-//!
-//! @brief send ICMP ECHO_REQUEST to network hosts
-//!
-//! @note If an operation finished successfully asynchronous ping report
-//! event will be generated. The report structure is as defined
-//! by structure netapp_pingreport_args_t.
-//!
-//! @warning Calling this function while a previous Ping Requests are in
-//! progress will stop the previous ping request.
-//*****************************************************************************
-
- #ifndef CC3000_TINY_DRIVER
-extern INT32 netapp_ping_send(UINT32 *ip, UINT32 ulPingAttempts, UINT32 ulPingSize, UINT32 ulPingTimeout);
-#endif
-
-//*****************************************************************************
-//
-//! netapp_ping_stop
-//!
-//! @param none
-//!
-//! @return On success, zero is returned. On error, -1 is returned.
-//!
-//! @brief Stop any ping request.
-//!
-//!
-//*****************************************************************************
-
-#ifndef CC3000_TINY_DRIVER
-extern INT32 netapp_ping_stop();
-#endif
-//*****************************************************************************
-//
-//! netapp_ping_report
-//!
-//! @param none
-//!
-//! @return none
-//!
-//! @brief Request for ping status. This API triggers the CC3000 to send
-//! asynchronous events: HCI_EVNT_WLAN_ASYNC_PING_REPORT.
-//! This event will carry the report structure:
-//! netapp_pingreport_args_t. This structure is filled in with ping
-//! results up till point of triggering API.
-//! netapp_pingreport_args_t:\n packets_sent - echo sent,
-//! packets_received - echo reply, min_round_time - minimum
-//! round time, max_round_time - max round time,
-//! avg_round_time - average round time
-//!
-//! @note When a ping operation is not active, the returned structure
-//! fields are 0.
-//!
-//*****************************************************************************
-#ifndef CC3000_TINY_DRIVER
-extern void netapp_ping_report();
-#endif
-
-
-//*****************************************************************************
-//
-//! netapp_ipconfig
-//!
-//! @param[out] ipconfig This argument is a pointer to a
-//! tNetappIpconfigRetArgs structure. This structure is
-//! filled in with the network interface configuration.
-//! tNetappIpconfigRetArgs:\n aucIP - ip address,
-//! aucSubnetMask - mask, aucDefaultGateway - default
-//! gateway address, aucDHCPServer - dhcp server address
-//! aucDNSServer - dns server address, uaMacAddr - mac
-//! address, uaSSID - connected AP ssid
-//!
-//! @return none
-//!
-//! @brief Obtain the CC3000 Network interface information.
-//! Note that the information is available only after the WLAN
-//! connection was established. Calling this function before
-//! associated, will cause non-defined values to be returned.
-//!
-//! @note The function is useful for figuring out the IP Configuration of
-//! the device when DHCP is used and for figuring out the SSID of
-//! the Wireless network the device is associated with.
-//!
-//*****************************************************************************
-
-extern void netapp_ipconfig( tNetappIpconfigRetArgs * ipconfig );
-
-
-//*****************************************************************************
-//
-//! netapp_arp_flush
-//!
-//! @param none
-//!
-//! @return none
-//!
-//! @brief Flushes ARP table
-//!
-//*****************************************************************************
-
-#ifndef CC3000_TINY_DRIVER
-extern INT32 netapp_arp_flush();
-#endif
-
-
-//*****************************************************************************
-//
-//! netapp_set_debug_level
-//!
-//! @param[in] level debug level. Bitwise [0-8],
-//! 0(disable)or 1(enable).\n Bitwise map: 0 - Critical
-//! message, 1 information message, 2 - core messages, 3 -
-//! HCI messages, 4 - Network stack messages, 5 - wlan
-//! messages, 6 - wlan driver messages, 7 - epprom messages,
-//! 8 - general messages. Default: 0x13f. Saved: no
-//!
-//! @return On success, zero is returned. On error, -1 is returned
-//!
-//! @brief Debug messages sent via the UART debug channel, this function
-//! enable/disable the debug level
-//!
-//*****************************************************************************
-
-
-#ifndef CC3000_TINY_DRIVER
-INT32 netapp_set_debug_level(UINT32 ulLevel);
-#endif
-//*****************************************************************************
-//
-// Close the Doxygen group.
-//! @}
-//
-//*****************************************************************************
-
-
-
-//*****************************************************************************
-//
-// Mark the end of the C bindings section for C++ compilers.
-//
-//*****************************************************************************
-#ifdef __cplusplus
-}
-#endif // __cplusplus
-
-#endif // __CC3000_NETAPP_H__
-
diff --git a/drivers/cc3000/inc/nvmem.h b/drivers/cc3000/inc/nvmem.h
deleted file mode 100644
index b99a2e7b9ec5..000000000000
--- a/drivers/cc3000/inc/nvmem.h
+++ /dev/null
@@ -1,248 +0,0 @@
-/*****************************************************************************
-*
-* nvmem.h - CC3000 Host Driver Implementation.
-* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
-*
-* 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 Texas Instruments Incorporated 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
-* OWNER 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.
-*
-*****************************************************************************/
-#ifndef __CC3000_NVRAM_H__
-#define __CC3000_NVRAM_H__
-
-#include "cc3000_common.h"
-
-
-//*****************************************************************************
-//
-// If building with a C++ compiler, make all of the definitions in this header
-// have a C binding.
-//
-//*****************************************************************************
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-//*****************************************************************************
-//
-//! \addtogroup nvmem_api
-//! @{
-//
-//*****************************************************************************
-
-/****************************************************************************
-**
-** Definitions for File IDs
-**
-****************************************************************************/
-/* NVMEM file ID - system files*/
-#define NVMEM_NVS_FILEID (0)
-#define NVMEM_NVS_SHADOW_FILEID (1)
-#define NVMEM_WLAN_CONFIG_FILEID (2)
-#define NVMEM_WLAN_CONFIG_SHADOW_FILEID (3)
-#define NVMEM_WLAN_DRIVER_SP_FILEID (4)
-#define NVMEM_WLAN_FW_SP_FILEID (5)
-#define NVMEM_MAC_FILEID (6)
-#define NVMEM_FRONTEND_VARS_FILEID (7)
-#define NVMEM_IP_CONFIG_FILEID (8)
-#define NVMEM_IP_CONFIG_SHADOW_FILEID (9)
-#define NVMEM_BOOTLOADER_SP_FILEID (10)
-#define NVMEM_RM_FILEID (11)
-
-/* NVMEM file ID - user files*/
-#define NVMEM_AES128_KEY_FILEID (12)
-#define NVMEM_SHARED_MEM_FILEID (13)
-
-/* max entry in order to invalid nvmem */
-#define NVMEM_MAX_ENTRY (16)
-
-
-//*****************************************************************************
-//
-//! nvmem_read
-//!
-//! @param ulFileId nvmem file id:\n
-//! NVMEM_NVS_FILEID, NVMEM_NVS_SHADOW_FILEID,
-//! NVMEM_WLAN_CONFIG_FILEID, NVMEM_WLAN_CONFIG_SHADOW_FILEID,
-//! NVMEM_WLAN_DRIVER_SP_FILEID, NVMEM_WLAN_FW_SP_FILEID,
-//! NVMEM_MAC_FILEID, NVMEM_FRONTEND_VARS_FILEID,
-//! NVMEM_IP_CONFIG_FILEID, NVMEM_IP_CONFIG_SHADOW_FILEID,
-//! NVMEM_BOOTLOADER_SP_FILEID, NVMEM_RM_FILEID,
-//! and user files 12-15.
-//! @param ulLength number of bytes to read
-//! @param ulOffset ulOffset in file from where to read
-//! @param buff output buffer pointer
-//!
-//! @return on success 0, error otherwise.
-//!
-//! @brief Reads data from the file referred by the ulFileId parameter.
-//! Reads data from file ulOffset till length. Err if the file can't
-//! be used, is invalid, or if the read is out of bounds.
-//!
-//*****************************************************************************
-
-extern INT32 nvmem_read(UINT32 file_id, UINT32 length, UINT32 offset, UINT8 *buff);
-
-//*****************************************************************************
-//
-//! nvmem_write
-//!
-//! @param ulFileId nvmem file id:\n
-//! NVMEM_WLAN_DRIVER_SP_FILEID, NVMEM_WLAN_FW_SP_FILEID,
-//! NVMEM_MAC_FILEID, NVMEM_BOOTLOADER_SP_FILEID,
-//! and user files 12-15.
-//! @param ulLength number of bytes to write
-//! @param ulEntryOffset offset in file to start write operation from
-//! @param buff data to write
-//!
-//! @return on success 0, error otherwise.
-//!
-//! @brief Write data to nvmem.
-//! writes data to file referred by the ulFileId parameter.
-//! Writes data to file ulOffset till ulLength.The file id will be
-//! marked invalid till the write is done. The file entry doesn't
-//! need to be valid - only allocated.
-//!
-//*****************************************************************************
-
-extern INT32 nvmem_write(UINT32 ulFileId, UINT32 ulLength, UINT32 ulEntryOffset, UINT8 *buff);
-
-
-//*****************************************************************************
-//
-//! nvmem_set_mac_address
-//!
-//! @param mac mac address to be set
-//!
-//! @return on success 0, error otherwise.
-//!
-//! @brief Write MAC address to EEPROM.
-//! mac address as appears over the air (OUI first)
-//!
-//*****************************************************************************
-extern UINT8 nvmem_set_mac_address(UINT8 *mac);
-
-
-//*****************************************************************************
-//
-//! nvmem_get_mac_address
-//!
-//! @param[out] mac mac address
-//!
-//! @return on success 0, error otherwise.
-//!
-//! @brief Read MAC address from EEPROM.
-//! mac address as appears over the air (OUI first)
-//!
-//*****************************************************************************
-extern UINT8 nvmem_get_mac_address(UINT8 *mac);
-
-
-//*****************************************************************************
-//
-//! nvmem_write_patch
-//!
-//! @param ulFileId nvmem file id:\n
-//! NVMEM_WLAN_DRIVER_SP_FILEID, NVMEM_WLAN_FW_SP_FILEID,
-//! @param spLength number of bytes to write
-//! @param spData SP data to write
-//!
-//! @return on success 0, error otherwise.
-//!
-//! @brief program a patch to a specific file ID.
-//! The SP data is assumed to be organized in 2-dimensional.
-//! Each line is SP_PORTION_SIZE bytes long. Actual programming is
-//! applied in SP_PORTION_SIZE bytes portions.
-//!
-//*****************************************************************************
-extern UINT8 nvmem_write_patch(UINT32 ulFileId, UINT32 spLength, const UINT8 *spData);
-
-
-//*****************************************************************************
-//
-//! nvmem_read_sp_version
-//!
-//! @param[out] patchVer first number indicates package ID and the second
-//! number indicates package build number
-//!
-//! @return on success 0, error otherwise.
-//!
-//! @brief Read patch version. read package version (WiFi FW patch,
-//! driver-supplicant-NS patch, bootloader patch)
-//!
-//*****************************************************************************
-#ifndef CC3000_TINY_DRIVER
-extern UINT8 nvmem_read_sp_version(UINT8* patchVer);
-#endif
-
-//*****************************************************************************
-//
-//! nvmem_create_entry
-//!
-//! @param ulFileId nvmem file Id:\n
-//! * NVMEM_AES128_KEY_FILEID: 12
-//! * NVMEM_SHARED_MEM_FILEID: 13
-//! * and fileIDs 14 and 15
-//! @param ulNewLen entry ulLength
-//!
-//! @return on success 0, error otherwise.
-//!
-//! @brief Create new file entry and allocate space on the NVMEM.
-//! Applies only to user files.
-//! Modify the size of file.
-//! If the entry is unallocated - allocate it to size
-//! ulNewLen (marked invalid).
-//! If it is allocated then deallocate it first.
-//! To just mark the file as invalid without resizing -
-//! set ulNewLen=0.
-//!
-//*****************************************************************************
-extern INT32 nvmem_create_entry(UINT32 file_id, UINT32 newlen);
-
-
-//*****************************************************************************
-//
-// Mark the end of the C bindings section for C++ compilers.
-//
-//*****************************************************************************
-
-
-//*****************************************************************************
-//
-// Close the Doxygen group.
-//! @}
-//
-//*****************************************************************************
-
-
-#ifdef __cplusplus
-}
-#endif // __cplusplus
-
-#endif // __CC3000_NVRAM_H__
diff --git a/drivers/cc3000/inc/patch_prog.h b/drivers/cc3000/inc/patch_prog.h
deleted file mode 100644
index 0a141a0cb535..000000000000
--- a/drivers/cc3000/inc/patch_prog.h
+++ /dev/null
@@ -1,11 +0,0 @@
-#ifndef __CC3000_PATCH_PROG_H__
-#define __CC3000_PATCH_PROG_H__
-extern unsigned short fw_length;
-extern const unsigned char fw_patch[];
-
-extern unsigned short drv_length;
-extern const unsigned char wlan_drv_patch[];
-extern const unsigned char cRMdefaultParams[128];
-
-void patch_prog_start();
-#endif //__CC3000_PATCH_PROG_H__
diff --git a/drivers/cc3000/inc/security.h b/drivers/cc3000/inc/security.h
deleted file mode 100644
index cd1baf55416f..000000000000
--- a/drivers/cc3000/inc/security.h
+++ /dev/null
@@ -1,130 +0,0 @@
-/*****************************************************************************
-*
-* security.h - CC3000 Host Driver Implementation.
-* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
-*
-* 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 Texas Instruments Incorporated 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
-* OWNER 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.
-*
-*****************************************************************************/
-#ifndef __CC3000_SECURITY__
-#define __CC3000_SECURITY__
-
-#include "nvmem.h"
-
-//*****************************************************************************
-//
-// If building with a C++ compiler, make all of the definitions in this header
-// have a C binding.
-//
-//*****************************************************************************
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-#define AES128_KEY_SIZE 16
-
-#ifndef CC3000_UNENCRYPTED_SMART_CONFIG
-
-
-//*****************************************************************************
-//
-//! aes_encrypt
-//!
-//! @param[in] key AES128 key of size 16 bytes
-//! @param[in\out] state 16 bytes of plain text and cipher text
-//!
-//! @return none
-//!
-//! @brief AES128 encryption:
-//! Given AES128 key and 16 bytes plain text, cipher text of 16 bytes
-//! is computed. The AES implementation is in mode ECB (Electronic
-//! Code Book).
-//!
-//!
-//*****************************************************************************
-extern void aes_encrypt(UINT8 *state, UINT8 *key);
-
-//*****************************************************************************
-//
-//! aes_decrypt
-//!
-//! @param[in] key AES128 key of size 16 bytes
-//! @param[in\out] state 16 bytes of cipher text and plain text
-//!
-//! @return none
-//!
-//! @brief AES128 decryption:
-//! Given AES128 key and 16 bytes cipher text, plain text of 16 bytes
-//! is computed The AES implementation is in mode ECB
-//! (Electronic Code Book).
-//!
-//!
-//*****************************************************************************
-extern void aes_decrypt(UINT8 *state, UINT8 *key);
-
-
-//*****************************************************************************
-//
-//! aes_read_key
-//!
-//! @param[out] key AES128 key of size 16 bytes
-//!
-//! @return on success 0, error otherwise.
-//!
-//! @brief Reads AES128 key from EEPROM
-//! Reads the AES128 key from fileID #12 in EEPROM
-//! returns an error if the key does not exist.
-//!
-//!
-//*****************************************************************************
-extern INT32 aes_read_key(UINT8 *key);
-
-//*****************************************************************************
-//
-//! aes_write_key
-//!
-//! @param[out] key AES128 key of size 16 bytes
-//!
-//! @return on success 0, error otherwise.
-//!
-//! @brief writes AES128 key from EEPROM
-//! Writes the AES128 key to fileID #12 in EEPROM
-//!
-//!
-//*****************************************************************************
-extern INT32 aes_write_key(UINT8 *key);
-
-#endif //CC3000_UNENCRYPTED_SMART_CONFIG
-
-#ifdef __cplusplus
-}
-#endif // __cplusplus
-
-#endif
diff --git a/drivers/cc3000/inc/socket.h b/drivers/cc3000/inc/socket.h
deleted file mode 100644
index 96c814bf77a0..000000000000
--- a/drivers/cc3000/inc/socket.h
+++ /dev/null
@@ -1,676 +0,0 @@
-/*****************************************************************************
-*
-* socket.h - CC3000 Host Driver Implementation.
-* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
-*
-* 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 Texas Instruments Incorporated 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
-* OWNER 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.
-*
-*****************************************************************************/
-#ifndef __CC3000_SOCKET_H__
-#define __CC3000_SOCKET_H__
-
-#include "cc3000_common.h"
-
-//*****************************************************************************
-//
-//! \addtogroup socket_api
-//! @{
-//
-//*****************************************************************************
-
-
-//*****************************************************************************
-//
-// If building with a C++ compiler, make all of the definitions in this header
-// have a C binding.
-//
-//*****************************************************************************
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define HOSTNAME_MAX_LENGTH (230) // 230 bytes + header shouldn't exceed 8 bit value
-
-//--------- Address Families --------
-
-#define AF_INET 2
-#define AF_INET6 23
-
-//------------ Socket Types ------------
-
-#define SOCK_STREAM 1
-#define SOCK_DGRAM 2
-#define SOCK_RAW 3 // Raw sockets allow new IPv4 protocols to be implemented in user space. A raw socket receives or sends the raw datagram not including link level headers
-#define SOCK_RDM 4
-#define SOCK_SEQPACKET 5
-
-//----------- Socket Protocol ----------
-
-#define IPPROTO_IP 0 // dummy for IP
-#define IPPROTO_ICMP 1 // control message protocol
-#define IPPROTO_IPV4 IPPROTO_IP // IP inside IP
-#define IPPROTO_TCP 6 // tcp
-#define IPPROTO_UDP 17 // user datagram protocol
-#define IPPROTO_IPV6 41 // IPv6 in IPv6
-#define IPPROTO_NONE 59 // No next header
-#define IPPROTO_RAW 255 // raw IP packet
-#define IPPROTO_MAX 256
-
-//----------- Socket retunr codes -----------
-
-#define SOC_ERROR (-1) // error
-#define SOC_IN_PROGRESS (-2) // socket in progress
-
-//----------- Socket Options -----------
-#define SOL_SOCKET 0xffff // socket level
-#define SOCKOPT_RECV_NONBLOCK 0 // recv non block mode, set SOCK_ON or SOCK_OFF (default block mode)
-#define SOCKOPT_RECV_TIMEOUT 1 // optname to configure recv and recvfromtimeout
-#define SOCKOPT_ACCEPT_NONBLOCK 2 // accept non block mode, set SOCK_ON or SOCK_OFF (default block mode)
-#define SOCK_ON 0 // socket non-blocking mode is enabled
-#define SOCK_OFF 1 // socket blocking mode is enabled
-
-#define MAX_PACKET_SIZE 1500
-#define MAX_LISTEN_QUEUE 4
-
-#define IOCTL_SOCKET_EVENTMASK
-
-#define ENOBUFS 55 // No buffer space available
-
-#define __FD_SETSIZE 32
-
-#define ASIC_ADDR_LEN 8
-
-#define NO_QUERY_RECIVED -3
-
-
-typedef struct _in_addr_t
-{
- UINT32 s_addr; // load with inet_aton()
-} in_addr;
-
-typedef struct _sockaddr_t
-{
- UINT16 sa_family;
- UINT8 sa_data[14];
-} sockaddr;
-
-typedef struct _sockaddr_in_t
-{
- INT16 sin_family; // e.g. AF_INET
- UINT16 sin_port; // e.g. htons(3490)
- in_addr sin_addr; // see struct in_addr, below
- CHAR sin_zero[8]; // zero this if you want to
-} sockaddr_in;
-
-typedef UINT32 socklen_t;
-
-// The fd_set member is required to be an array of INT32s.
-typedef INT32 __fd_mask;
-
-// It's easier to assume 8-bit bytes than to get CHAR_BIT.
-#define __NFDBITS (8 * sizeof (__fd_mask))
-#define __FDELT(d) ((d) / __NFDBITS)
-#define __FDMASK(d) ((__fd_mask) 1 << ((d) % __NFDBITS))
-
-// fd_set for select and pselect.
-typedef struct
-{
- __fd_mask fds_bits[__FD_SETSIZE / __NFDBITS];
-#define __FDS_BITS(set) ((set)->fds_bits)
-} fd_set;
-
-// We don't use `memset' because this would require a prototype and
-// the array isn't too big.
-#define __FD_ZERO(set) \
- do { \
- UINT16 __i; \
- fd_set *__arr = (set); \
- for (__i = 0; __i < sizeof (fd_set) / sizeof (__fd_mask); ++__i) \
- __FDS_BITS (__arr)[__i] = 0; \
- } while (0)
-#define __FD_SET(d, set) (__FDS_BITS (set)[__FDELT (d)] |= __FDMASK (d))
-#define __FD_CLR(d, set) (__FDS_BITS (set)[__FDELT (d)] &= ~__FDMASK (d))
-#define __FD_ISSET(d, set) (__FDS_BITS (set)[__FDELT (d)] & __FDMASK (d))
-
-// Access macros for 'fd_set'.
-#define FD_SET(fd, fdsetp) __FD_SET (fd, fdsetp)
-#define FD_CLR(fd, fdsetp) __FD_CLR (fd, fdsetp)
-#define FD_ISSET(fd, fdsetp) __FD_ISSET (fd, fdsetp)
-#define FD_ZERO(fdsetp) __FD_ZERO (fdsetp)
-
-//Use in case of Big Endian only
-
-#define htonl(A) ((((UINT32)(A) & 0xff000000) >> 24) | \
- (((UINT32)(A) & 0x00ff0000) >> 8) | \
- (((UINT32)(A) & 0x0000ff00) << 8) | \
- (((UINT32)(A) & 0x000000ff) << 24))
-
-#define ntohl htonl
-
-//Use in case of Big Endian only
-#define htons(A) ((((UINT32)(A) & 0xff00) >> 8) | \
- (((UINT32)(A) & 0x00ff) << 8))
-
-
-#define ntohs htons
-
-// mDNS port - 5353 mDNS multicast address - 224.0.0.251
-#define SET_mDNS_ADD(sockaddr) sockaddr.sa_data[0] = 0x14; \
- sockaddr.sa_data[1] = 0xe9; \
- sockaddr.sa_data[2] = 0xe0; \
- sockaddr.sa_data[3] = 0x0; \
- sockaddr.sa_data[4] = 0x0; \
- sockaddr.sa_data[5] = 0xfb;
-
-
-//*****************************************************************************
-//
-// Prototypes for the APIs.
-//
-//*****************************************************************************
-
-//*****************************************************************************
-//
-//! socket
-//!
-//! @param domain selects the protocol family which will be used for
-//! communication. On this version only AF_INET is supported
-//! @param type specifies the communication semantics. On this version
-//! only SOCK_STREAM, SOCK_DGRAM, SOCK_RAW are supported
-//! @param protocol specifies a particular protocol to be used with the
-//! socket IPPROTO_TCP, IPPROTO_UDP or IPPROTO_RAW are
-//! supported.
-//!
-//! @return On success, socket handle that is used for consequent socket
-//! operations. On error, -1 is returned.
-//!
-//! @brief create an endpoint for communication
-//! The socket function creates a socket that is bound to a specific
-//! transport service provider. This function is called by the
-//! application layer to obtain a socket handle.
-//
-//*****************************************************************************
-extern INT16 CC3000_EXPORT(socket)(INT32 domain, INT32 type, INT32 protocol);
-
-//*****************************************************************************
-//
-//! closesocket
-//!
-//! @param sd socket handle.
-//!
-//! @return On success, zero is returned. On error, -1 is returned.
-//!
-//! @brief The socket function closes a created socket.
-//
-//*****************************************************************************
-extern INT32 CC3000_EXPORT(closesocket)(INT32 sd);
-
-//*****************************************************************************
-//
-//! accept
-//!
-//! @param[in] sd socket descriptor (handle)
-//! @param[out] addr the argument addr is a pointer to a sockaddr structure
-//! This structure is filled in with the address of the
-//! peer socket, as known to the communications layer.
-//! determined. The exact format of the address returned
-//! addr is by the socket's address sockaddr.
-//! On this version only AF_INET is supported.
-//! This argument returns in network order.
-//! @param[out] addrlen the addrlen argument is a value-result argument:
-//! it should initially contain the size of the structure
-//! pointed to by addr.
-//!
-//! @return For socket in blocking mode:
-//! On success, socket handle. on failure negative
-//! For socket in non-blocking mode:
-//! - On connection establishment, socket handle
-//! - On connection pending, SOC_IN_PROGRESS (-2)
-//! - On failure, SOC_ERROR (-1)
-//!
-//! @brief accept a connection on a socket:
-//! This function is used with connection-based socket types
-//! (SOCK_STREAM). It extracts the first connection request on the
-//! queue of pending connections, creates a new connected socket, and
-//! returns a new file descriptor referring to that socket.
-//! The newly created socket is not in the listening state.
-//! The original socket sd is unaffected by this call.
-//! The argument sd is a socket that has been created with socket(),
-//! bound to a local address with bind(), and is listening for
-//! connections after a listen(). The argument addr is a pointer
-//! to a sockaddr structure. This structure is filled in with the
-//! address of the peer socket, as known to the communications layer.
-//! The exact format of the address returned addr is determined by the
-//! socket's address family. The addrlen argument is a value-result
-//! argument: it should initially contain the size of the structure
-//! pointed to by addr, on return it will contain the actual
-//! length (in bytes) of the address returned.
-//!
-//! @sa socket ; bind ; listen
-//
-//*****************************************************************************
-extern INT32 CC3000_EXPORT(accept)(INT32 sd, sockaddr *addr, socklen_t *addrlen);
-
-//*****************************************************************************
-//
-//! bind
-//!
-//! @param[in] sd socket descriptor (handle)
-//! @param[out] addr specifies the destination address. On this version
-//! only AF_INET is supported.
-//! @param[out] addrlen contains the size of the structure pointed to by addr.
-//!
-//! @return On success, zero is returned. On error, -1 is returned.
-//!
-//! @brief assign a name to a socket
-//! This function gives the socket the local address addr.
-//! addr is addrlen bytes long. Traditionally, this is called when a
-//! socket is created with socket, it exists in a name space (address
-//! family) but has no name assigned.
-//! It is necessary to assign a local address before a SOCK_STREAM
-//! socket may receive connections.
-//!
-//! @sa socket ; accept ; listen
-//
-//*****************************************************************************
-extern INT32 CC3000_EXPORT(bind)(INT32 sd, const sockaddr *addr, INT32 addrlen);
-
-//*****************************************************************************
-//
-//! listen
-//!
-//! @param[in] sd socket descriptor (handle)
-//! @param[in] backlog specifies the listen queue depth. On this version
-//! backlog is not supported.
-//! @return On success, zero is returned. On error, -1 is returned.
-//!
-//! @brief listen for connections on a socket
-//! The willingness to accept incoming connections and a queue
-//! limit for incoming connections are specified with listen(),
-//! and then the connections are accepted with accept.
-//! The listen() call applies only to sockets of type SOCK_STREAM
-//! The backlog parameter defines the maximum length the queue of
-//! pending connections may grow to.
-//!
-//! @sa socket ; accept ; bind
-//!
-//! @note On this version, backlog is not supported
-//
-//*****************************************************************************
-extern INT32 CC3000_EXPORT(listen)(INT32 sd, INT32 backlog);
-
-//*****************************************************************************
-//
-//! gethostbyname
-//!
-//! @param[in] hostname host name
-//! @param[in] usNameLen name length
-//! @param[out] out_ip_addr This parameter is filled in with host IP address.
-//! In case that host name is not resolved,
-//! out_ip_addr is zero.
-//! @return On success, positive is returned. On error, negative is returned
-//!
-//! @brief Get host IP by name. Obtain the IP Address of machine on network,
-//! by its name.
-//!
-//! @note On this version, only blocking mode is supported. Also note that
-//! the function requires DNS server to be configured prior to its usage.
-//
-//*****************************************************************************
-#ifndef CC3000_TINY_DRIVER
-extern INT16 CC3000_EXPORT(gethostbyname)(CHAR * hostname, UINT16 usNameLen, UINT32* out_ip_addr);
-#endif
-
-
-//*****************************************************************************
-//
-//! connect
-//!
-//! @param[in] sd socket descriptor (handle)
-//! @param[in] addr specifies the destination addr. On this version
-//! only AF_INET is supported.
-//! @param[out] addrlen contains the size of the structure pointed to by addr
-//! @return On success, zero is returned. On error, -1 is returned
-//!
-//! @brief initiate a connection on a socket
-//! Function connects the socket referred to by the socket descriptor
-//! sd, to the address specified by addr. The addrlen argument
-//! specifies the size of addr. The format of the address in addr is
-//! determined by the address space of the socket. If it is of type
-//! SOCK_DGRAM, this call specifies the peer with which the socket is
-//! to be associated; this address is that to which datagrams are to be
-//! sent, and the only address from which datagrams are to be received.
-//! If the socket is of type SOCK_STREAM, this call attempts to make a
-//! connection to another socket. The other socket is specified by
-//! address, which is an address in the communications space of the
-//! socket. Note that the function implements only blocking behavior
-//! thus the caller will be waiting either for the connection
-//! establishment or for the connection establishment failure.
-//!
-//! @sa socket
-//
-//*****************************************************************************
-extern INT32 CC3000_EXPORT(connect)(INT32 sd, const sockaddr *addr, INT32 addrlen);
-
-//*****************************************************************************
-//
-//! select
-//!
-//! @param[in] nfds the highest-numbered file descriptor in any of the
-//! three sets, plus 1.
-//! @param[out] writesds socket descriptors list for write monitoring
-//! @param[out] readsds socket descriptors list for read monitoring
-//! @param[out] exceptsds socket descriptors list for exception monitoring
-//! @param[in] timeout is an upper bound on the amount of time elapsed
-//! before select() returns. Null means infinity
-//! timeout. The minimum timeout is 5 milliseconds,
-//! less than 5 milliseconds will be set
-//! automatically to 5 milliseconds.
-//! @return On success, select() returns the number of file descriptors
-//! contained in the three returned descriptor sets (that is, the
-//! total number of bits that are set in readfds, writefds,
-//! exceptfds) which may be zero if the timeout expires before
-//! anything interesting happens.
-//! On error, -1 is returned.
-//! *readsds - return the sockets on which Read request will
-//! return without delay with valid data.
-//! *writesds - return the sockets on which Write request
-//! will return without delay.
-//! *exceptsds - return the sockets which closed recently.
-//!
-//! @brief Monitor socket activity
-//! Select allow a program to monitor multiple file descriptors,
-//! waiting until one or more of the file descriptors become
-//! "ready" for some class of I/O operation
-//!
-//! @Note If the timeout value set to less than 5ms it will automatically set
-//! to 5ms to prevent overload of the system
-//!
-//! @sa socket
-//
-//*****************************************************************************
-extern INT16 CC3000_EXPORT(select)(INT32 nfds, fd_set *readsds, fd_set *writesds,
- fd_set *exceptsds, struct cc3000_timeval *timeout);
-
-//*****************************************************************************
-//
-//! setsockopt
-//!
-//! @param[in] sd socket handle
-//! @param[in] level defines the protocol level for this option
-//! @param[in] optname defines the option name to Interrogate
-//! @param[in] optval specifies a value for the option
-//! @param[in] optlen specifies the length of the option value
-//! @return On success, zero is returned. On error, -1 is returned
-//!
-//! @brief set socket options
-//! This function manipulate the options associated with a socket.
-//! Options may exist at multiple protocol levels; they are always
-//! present at the uppermost socket level.
-//! When manipulating socket options the level at which the option
-//! resides and the name of the option must be specified.
-//! To manipulate options at the socket level, level is specified as
-//! SOL_SOCKET. To manipulate options at any other level the protocol
-//! number of the appropriate protocol controlling the option is
-//! supplied. For example, to indicate that an option is to be
-//! interpreted by the TCP protocol, level should be set to the
-//! protocol number of TCP;
-//! The parameters optval and optlen are used to access optval -
-//! use for setsockopt(). For getsockopt() they identify a buffer
-//! in which the value for the requested option(s) are to
-//! be returned. For getsockopt(), optlen is a value-result
-//! parameter, initially containing the size of the buffer
-//! pointed to by option_value, and modified on return to
-//! indicate the actual size of the value returned. If no option
-//! value is to be supplied or returned, option_value may be NULL.
-//!
-//! @Note On this version the following two socket options are enabled:
-//! The only protocol level supported in this version
-//! is SOL_SOCKET (level).
-//! 1. SOCKOPT_RECV_TIMEOUT (optname)
-//! SOCKOPT_RECV_TIMEOUT configures recv and recvfrom timeout
-//! in milliseconds.
-//! In that case optval should be pointer to UINT32.
-//! 2. SOCKOPT_NONBLOCK (optname). sets the socket non-blocking mode on
-//! or off.
-//! In that case optval should be SOCK_ON or SOCK_OFF (optval).
-//!
-//! @sa getsockopt
-//
-//*****************************************************************************
-#ifndef CC3000_TINY_DRIVER
-extern INT16 CC3000_EXPORT(setsockopt)(INT32 sd, INT32 level, INT32 optname, const void *optval,
- socklen_t optlen);
-#endif
-//*****************************************************************************
-//
-//! getsockopt
-//!
-//! @param[in] sd socket handle
-//! @param[in] level defines the protocol level for this option
-//! @param[in] optname defines the option name to Interrogate
-//! @param[out] optval specifies a value for the option
-//! @param[out] optlen specifies the length of the option value
-//! @return On success, zero is returned. On error, -1 is returned
-//!
-//! @brief set socket options
-//! This function manipulate the options associated with a socket.
-//! Options may exist at multiple protocol levels; they are always
-//! present at the uppermost socket level.
-//! When manipulating socket options the level at which the option
-//! resides and the name of the option must be specified.
-//! To manipulate options at the socket level, level is specified as
-//! SOL_SOCKET. To manipulate options at any other level the protocol
-//! number of the appropriate protocol controlling the option is
-//! supplied. For example, to indicate that an option is to be
-//! interpreted by the TCP protocol, level should be set to the
-//! protocol number of TCP;
-//! The parameters optval and optlen are used to access optval -
-//! use for setsockopt(). For getsockopt() they identify a buffer
-//! in which the value for the requested option(s) are to
-//! be returned. For getsockopt(), optlen is a value-result
-//! parameter, initially containing the size of the buffer
-//! pointed to by option_value, and modified on return to
-//! indicate the actual size of the value returned. If no option
-//! value is to be supplied or returned, option_value may be NULL.
-//!
-//! @Note On this version the following two socket options are enabled:
-//! The only protocol level supported in this version
-//! is SOL_SOCKET (level).
-//! 1. SOCKOPT_RECV_TIMEOUT (optname)
-//! SOCKOPT_RECV_TIMEOUT configures recv and recvfrom timeout
-//! in milliseconds.
-//! In that case optval should be pointer to UINT32.
-//! 2. SOCKOPT_NONBLOCK (optname). sets the socket non-blocking mode on
-//! or off.
-//! In that case optval should be SOCK_ON or SOCK_OFF (optval).
-//!
-//! @sa setsockopt
-//
-//*****************************************************************************
-extern INT16 CC3000_EXPORT(getsockopt)(INT32 sd, INT32 level, INT32 optname, void *optval,
- socklen_t *optlen);
-
-//*****************************************************************************
-//
-//! recv
-//!
-//! @param[in] sd socket handle
-//! @param[out] buf Points to the buffer where the message should be stored
-//! @param[in] len Specifies the length in bytes of the buffer pointed to
-//! by the buffer argument.
-//! @param[in] flags Specifies the type of message reception.
-//! On this version, this parameter is not supported.
-//!
-//! @return Return the number of bytes received, or -1 if an error
-//! occurred
-//!
-//! @brief function receives a message from a connection-mode socket
-//!
-//! @sa recvfrom
-//!
-//! @Note On this version, only blocking mode is supported.
-//
-//*****************************************************************************
-extern INT16 CC3000_EXPORT(recv)(INT32 sd, void *buf, INT32 len, INT32 flags);
-
-//*****************************************************************************
-//
-//! recvfrom
-//!
-//! @param[in] sd socket handle
-//! @param[out] buf Points to the buffer where the message should be stored
-//! @param[in] len Specifies the length in bytes of the buffer pointed to
-//! by the buffer argument.
-//! @param[in] flags Specifies the type of message reception.
-//! On this version, this parameter is not supported.
-//! @param[in] from pointer to an address structure indicating the source
-//! address: sockaddr. On this version only AF_INET is
-//! supported.
-//! @param[in] fromlen source address structure size
-//!
-//! @return Return the number of bytes received, or -1 if an error
-//! occurred
-//!
-//! @brief read data from socket
-//! function receives a message from a connection-mode or
-//! connectionless-mode socket. Note that raw sockets are not
-//! supported.
-//!
-//! @sa recv
-//!
-//! @Note On this version, only blocking mode is supported.
-//
-//*****************************************************************************
-extern INT16 CC3000_EXPORT(recvfrom)(INT32 sd, void *buf, INT32 len, INT32 flags, sockaddr *from,
- socklen_t *fromlen);
-
-//*****************************************************************************
-//
-//! send
-//!
-//! @param sd socket handle
-//! @param buf Points to a buffer containing the message to be sent
-//! @param len message size in bytes
-//! @param flags On this version, this parameter is not supported
-//!
-//! @return Return the number of bytes transmitted, or -1 if an
-//! error occurred
-//!
-//! @brief Write data to TCP socket
-//! This function is used to transmit a message to another
-//! socket.
-//!
-//! @Note On this version, only blocking mode is supported.
-//!
-//! @sa sendto
-//
-//*****************************************************************************
-
-extern INT16 CC3000_EXPORT(send)(INT32 sd, const void *buf, INT32 len, INT32 flags);
-
-//*****************************************************************************
-//
-//! sendto
-//!
-//! @param sd socket handle
-//! @param buf Points to a buffer containing the message to be sent
-//! @param len message size in bytes
-//! @param flags On this version, this parameter is not supported
-//! @param to pointer to an address structure indicating the destination
-//! address: sockaddr. On this version only AF_INET is
-//! supported.
-//! @param tolen destination address structure size
-//!
-//! @return Return the number of bytes transmitted, or -1 if an
-//! error occurred
-//!
-//! @brief Write data to TCP socket
-//! This function is used to transmit a message to another
-//! socket.
-//!
-//! @Note On this version, only blocking mode is supported.
-//!
-//! @sa send
-//
-//*****************************************************************************
-
-extern INT16 CC3000_EXPORT(sendto)(INT32 sd, const void *buf, INT32 len, INT32 flags,
- const sockaddr *to, socklen_t tolen);
-
-//*****************************************************************************
-//
-//! mdnsAdvertiser
-//!
-//! @param[in] mdnsEnabled flag to enable/disable the mDNS feature
-//! @param[in] deviceServiceName Service name as part of the published
-//! canonical domain name
-//! @param[in] deviceServiceNameLength Length of the service name - up to 32 chars
-//!
-//!
-//! @return On success, zero is returned, return SOC_ERROR if socket was not
-//! opened successfully, or if an error occurred.
-//!
-//! @brief Set CC3000 in mDNS advertiser mode in order to advertise itself.
-//
-//*****************************************************************************
-extern INT16 CC3000_EXPORT(mdnsAdvertiser)(UINT16 mdnsEnabled, CHAR * deviceServiceName, UINT16 deviceServiceNameLength);
-
-
-//*****************************************************************************
-//
-//! getmssvalue
-//!
-//! @param[in] sd socket descriptor
-//!
-//! @return On success, returns the MSS value of a TCP connection
-//!
-//! @brief Returns the MSS value of a TCP connection according to the socket descriptor
-//
-//*****************************************************************************
-extern UINT16 CC3000_EXPORT(getmssvalue) (INT32 sd);
-
-//*****************************************************************************
-//
-// Close the Doxygen group.
-//! @}
-//
-//*****************************************************************************
-
-
-//*****************************************************************************
-//
-// Mark the end of the C bindings section for C++ compilers.
-//
-//*****************************************************************************
-#ifdef __cplusplus
-}
-#endif // __cplusplus
-
-#endif // __SOCKET_H__
diff --git a/drivers/cc3000/inc/wlan.h b/drivers/cc3000/inc/wlan.h
deleted file mode 100644
index 48d195b32ae8..000000000000
--- a/drivers/cc3000/inc/wlan.h
+++ /dev/null
@@ -1,518 +0,0 @@
-/*****************************************************************************
-*
-* wlan.h - CC3000 Host Driver Implementation.
-* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
-*
-* 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 Texas Instruments Incorporated 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
-* OWNER 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.
-*
-*****************************************************************************/
-#ifndef __CC3000_WLAN_H__
-#define __CC3000_WLAN_H__
-
-#include "cc3000_common.h"
-
-//*****************************************************************************
-//
-// If building with a C++ compiler, make all of the definitions in this header
-// have a C binding.
-//
-//*****************************************************************************
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define WLAN_SEC_UNSEC (0)
-#define WLAN_SEC_WEP (1)
-#define WLAN_SEC_WPA (2)
-#define WLAN_SEC_WPA2 (3)
-//*****************************************************************************
-//
-//! \addtogroup wlan_api
-//! @{
-//
-//*****************************************************************************
-
-
-//*****************************************************************************
-//
-//! wlan_init
-//!
-//! @param sWlanCB Asynchronous events callback.
-//! 0 no event call back.
-//! -call back parameters:
-//! 1) event_type: HCI_EVNT_WLAN_UNSOL_CONNECT connect event,
-//! HCI_EVNT_WLAN_UNSOL_DISCONNECT disconnect event,
-//! HCI_EVNT_WLAN_ASYNC_SIMPLE_CONFIG_DONE config done,
-//! HCI_EVNT_WLAN_UNSOL_DHCP dhcp report,
-//! HCI_EVNT_WLAN_ASYNC_PING_REPORT ping report OR
-//! HCI_EVNT_WLAN_KEEPALIVE keepalive.
-//! 2) data: pointer to extra data that received by the event
-//! (NULL no data).
-//! 3) length: data length.
-//! -Events with extra data:
-//! HCI_EVNT_WLAN_UNSOL_DHCP: 4 bytes IP, 4 bytes Mask,
-//! 4 bytes default gateway, 4 bytes DHCP server and 4 bytes
-//! for DNS server.
-//! HCI_EVNT_WLAN_ASYNC_PING_REPORT: 4 bytes Packets sent,
-//! 4 bytes Packets received, 4 bytes Min round time,
-//! 4 bytes Max round time and 4 bytes for Avg round time.
-//!
-//! @param sFWPatches 0 no patch or pointer to FW patches
-//! @param sDriverPatches 0 no patch or pointer to driver patches
-//! @param sBootLoaderPatches 0 no patch or pointer to bootloader patches
-//! @param sReadWlanInterruptPin init callback. the callback read wlan
-//! interrupt status.
-//! @param sWlanInterruptEnable init callback. the callback enable wlan
-//! interrupt.
-//! @param sWlanInterruptDisable init callback. the callback disable wlan
-//! interrupt.
-//! @param sWriteWlanPin init callback. the callback write value
-//! to device pin.
-//!
-//! @return none
-//!
-//! @sa wlan_set_event_mask , wlan_start , wlan_stop
-//!
-//! @brief Initialize wlan driver
-//!
-//! @warning This function must be called before ANY other wlan driver function
-//
-//*****************************************************************************
-extern void wlan_init( tWlanCB sWlanCB,
- tFWPatches sFWPatches,
- tDriverPatches sDriverPatches,
- tBootLoaderPatches sBootLoaderPatches,
- tWlanReadInteruptPin sReadWlanInterruptPin,
- tWlanInterruptEnable sWlanInterruptEnable,
- tWlanInterruptDisable sWlanInterruptDisable,
- tWriteWlanPin sWriteWlanPin);
-
-
-
-//*****************************************************************************
-//
-//! wlan_start
-//!
-//! @param usPatchesAvailableAtHost - flag to indicate if patches available
-//! from host or from EEPROM. Due to the
-//! fact the patches are burn to the EEPROM
-//! using the patch programmer utility, the
-//! patches will be available from the EEPROM
-//! and not from the host.
-//!
-//! @return none
-//!
-//! @brief Start WLAN device. This function asserts the enable pin of
-//! the device (WLAN_EN), starting the HW initialization process.
-//! The function blocked until device Initialization is completed.
-//! Function also configure patches (FW, driver or bootloader)
-//! and calls appropriate device callbacks.
-//!
-//! @Note Prior calling the function wlan_init shall be called.
-//! @Warning This function must be called after wlan_init and before any
-//! other wlan API
-//! @sa wlan_init , wlan_stop
-//!
-//
-//*****************************************************************************
-extern int wlan_start(UINT16 usPatchesAvailableAtHost);
-
-//*****************************************************************************
-//
-//! wlan_stop
-//!
-//! @param none
-//!
-//! @return none
-//!
-//! @brief Stop WLAN device by putting it into reset state.
-//!
-//! @sa wlan_start
-//
-//*****************************************************************************
-extern void wlan_stop(void);
-
-//*****************************************************************************
-//
-//! wlan_connect
-//!
-//! @param sec_type security options:
-//! WLAN_SEC_UNSEC,
-//! WLAN_SEC_WEP (ASCII support only),
-//! WLAN_SEC_WPA or WLAN_SEC_WPA2
-//! @param ssid up to 32 bytes and is ASCII SSID of the AP
-//! @param ssid_len length of the SSID
-//! @param bssid 6 bytes specified the AP bssid
-//! @param key up to 32 bytes specified the AP security key
-//! @param key_len key length
-//!
-//! @return On success, zero is returned. On error, negative is returned.
-//! Note that even though a zero is returned on success to trigger
-//! connection operation, it does not mean that CCC3000 is already
-//! connected. An asynchronous "Connected" event is generated when
-//! actual association process finishes and CC3000 is connected to
-//! the AP. If DHCP is set, An asynchronous "DHCP" event is
-//! generated when DHCP process is finish.
-//!
-//!
-//! @brief Connect to AP
-//! @warning Please Note that when connection to AP configured with security
-//! type WEP, please confirm that the key is set as ASCII and not
-//! as HEX.
-//! @sa wlan_disconnect
-//
-//*****************************************************************************
-#ifndef CC3000_TINY_DRIVER
-extern INT32 wlan_connect(UINT32 ulSecType, CHAR *ssid, INT32 ssid_len,
- UINT8 *bssid, UINT8 *key, INT32 key_len);
-#else
-extern INT32 wlan_connect(CHAR *ssid, INT32 ssid_len);
-
-#endif
-
-//*****************************************************************************
-//
-//! wlan_disconnect
-//!
-//! @return 0 disconnected done, other CC3000 already disconnected
-//!
-//! @brief Disconnect connection from AP.
-//!
-//! @sa wlan_connect
-//
-//*****************************************************************************
-
-extern INT32 wlan_disconnect(void);
-
-//*****************************************************************************
-//
-//! wlan_add_profile
-//!
-//! @param ulSecType WLAN_SEC_UNSEC,WLAN_SEC_WEP,WLAN_SEC_WPA,WLAN_SEC_WPA2
-//! @param ucSsid ssid SSID up to 32 bytes
-//! @param ulSsidLen ssid length
-//! @param ucBssid bssid 6 bytes
-//! @param ulPriority ulPriority profile priority. Lowest priority:0.
-//! @param ulPairwiseCipher_Or_TxKeyLen key length for WEP security
-//! @param ulGroupCipher_TxKeyIndex key index
-//! @param ulKeyMgmt KEY management
-//! @param ucPf_OrKey security key
-//! @param ulPassPhraseLen security key length for WPA\WPA2
-//!
-//! @return On success, index (1-7) of the stored profile is returned.
-//! On error, -1 is returned.
-//!
-//! @brief When auto start is enabled, the device connects to
-//! station from the profiles table. Up to 7 profiles are supported.
-//! If several profiles configured the device choose the highest
-//! priority profile, within each priority group, device will choose
-//! profile based on security policy, signal strength, etc
-//! parameters. All the profiles are stored in CC3000 NVMEM.
-//!
-//! @sa wlan_ioctl_del_profile
-//
-//*****************************************************************************
-
-extern INT32 wlan_add_profile(UINT32 ulSecType, UINT8* ucSsid,
- UINT32 ulSsidLen,
- UINT8 *ucBssid,
- UINT32 ulPriority,
- UINT32 ulPairwiseCipher_Or_Key,
- UINT32 ulGroupCipher_TxKeyLen,
- UINT32 ulKeyMgmt,
- UINT8* ucPf_OrKey,
- UINT32 ulPassPhraseLen);
-
-
-
-//*****************************************************************************
-//
-//! wlan_ioctl_del_profile
-//!
-//! @param index number of profile to delete
-//!
-//! @return On success, zero is returned. On error, -1 is returned
-//!
-//! @brief Delete WLAN profile
-//!
-//! @Note In order to delete all stored profile, set index to 255.
-//!
-//! @sa wlan_add_profile
-//
-//*****************************************************************************
-extern INT32 wlan_ioctl_del_profile(UINT32 ulIndex);
-
-//*****************************************************************************
-//
-//! wlan_set_event_mask
-//!
-//! @param mask mask option:
-//! HCI_EVNT_WLAN_UNSOL_CONNECT connect event
-//! HCI_EVNT_WLAN_UNSOL_DISCONNECT disconnect event
-//! HCI_EVNT_WLAN_ASYNC_SIMPLE_CONFIG_DONE smart config done
-//! HCI_EVNT_WLAN_UNSOL_INIT init done
-//! HCI_EVNT_WLAN_UNSOL_DHCP dhcp event report
-//! HCI_EVNT_WLAN_ASYNC_PING_REPORT ping report
-//! HCI_EVNT_WLAN_KEEPALIVE keepalive
-//! HCI_EVNT_WLAN_TX_COMPLETE - disable information on end of transmission
-//! Saved: no.
-//!
-//! @return On success, zero is returned. On error, -1 is returned
-//!
-//! @brief Mask event according to bit mask. In case that event is
-//! masked (1), the device will not send the masked event to host.
-//
-//*****************************************************************************
-extern INT32 wlan_set_event_mask(UINT32 ulMask);
-
-//*****************************************************************************
-//
-//! wlan_ioctl_statusget
-//!
-//! @param none
-//!
-//! @return WLAN_STATUS_DISCONNECTED, WLAN_STATUS_SCANING,
-//! STATUS_CONNECTING or WLAN_STATUS_CONNECTED
-//!
-//! @brief get wlan status: disconnected, scanning, connecting or connected
-//
-//*****************************************************************************
-extern INT32 wlan_ioctl_statusget(void);
-
-
-//*****************************************************************************
-//
-//! wlan_ioctl_set_connection_policy
-//!
-//! @param should_connect_to_open_ap enable(1), disable(0) connect to any
-//! available AP. This parameter corresponds to the configuration of
-//! item # 3 in the brief description.
-//! @param should_use_fast_connect enable(1), disable(0). if enabled, tries
-//! to connect to the last connected AP. This parameter corresponds
-//! to the configuration of item # 1 in the brief description.
-//! @param auto_start enable(1), disable(0) auto connect
-//! after reset and periodically reconnect if needed. This
-//! configuration configures option 2 in the above description.
-//!
-//! @return On success, zero is returned. On error, -1 is returned
-//!
-//! @brief When auto is enabled, the device tries to connect according
-//! the following policy:
-//! 1) If fast connect is enabled and last connection is valid,
-//! the device will try to connect to it without the scanning
-//! procedure (fast). The last connection will be marked as
-//! invalid, due to adding/removing profile.
-//! 2) If profile exists, the device will try to connect it
-//! (Up to seven profiles).
-//! 3) If fast and profiles are not found, and open mode is
-//! enabled, the device will try to connect to any AP.
-//! * Note that the policy settings are stored in the CC3000 NVMEM.
-//!
-//! @sa wlan_add_profile , wlan_ioctl_del_profile
-//
-//*****************************************************************************
-extern INT32 wlan_ioctl_set_connection_policy(
- UINT32 should_connect_to_open_ap,
- UINT32 should_use_fast_connect,
- UINT32 ulUseProfiles);
-
-//*****************************************************************************
-//
-//! wlan_ioctl_get_scan_results
-//!
-//! @param[in] scan_timeout parameter not supported
-//! @param[out] ucResults scan result (_wlan_full_scan_results_args_t)
-//!
-//! @return On success, zero is returned. On error, -1 is returned
-//!
-//! @brief Gets entry from scan result table.
-//! The scan results are returned one by one, and each entry
-//! represents a single AP found in the area. The following is a
-//! format of the scan result:
-//! - 4 Bytes: number of networks found
-//! - 4 Bytes: The status of the scan: 0 - aged results,
-//! 1 - results valid, 2 - no results
-//! - 42 bytes: Result entry, where the bytes are arranged as follows:
-//!
-//! - 1 bit isValid - is result valid or not
-//! - 7 bits rssi - RSSI value;
-//! - 2 bits: securityMode - security mode of the AP:
-//! 0 - Open, 1 - WEP, 2 WPA, 3 WPA2
-//! - 6 bits: SSID name length
-//! - 2 bytes: the time at which the entry has entered into
-//! scans result table
-//! - 32 bytes: SSID name
-//! - 6 bytes: BSSID
-//!
-//! @Note scan_timeout, is not supported on this version.
-//!
-//! @sa wlan_ioctl_set_scan_params
-//
-//*****************************************************************************
-
-
-extern INT32 wlan_ioctl_get_scan_results(UINT32 ulScanTimeout,
- UINT8 *ucResults);
-
-//*****************************************************************************
-//
-//! wlan_ioctl_set_scan_params
-//!
-//! @param uiEnable - start/stop application scan:
-//! 1 = start scan with default interval value of 10 min.
-//! in order to set a different scan interval value apply the value
-//! in milliseconds. minimum 1 second. 0=stop). Wlan reset
-//! (wlan_stop() wlan_start()) is needed when changing scan interval
-//! value. Saved: No
-//! @param uiMinDwellTime minimum dwell time value to be used for each
-//! channel, in milliseconds. Saved: yes
-//! Recommended Value: 100 (Default: 20)
-//! @param uiMaxDwellTime maximum dwell time value to be used for each
-//! channel, in milliseconds. Saved: yes
-//! Recommended Value: 100 (Default: 30)
-//! @param uiNumOfProbeRequests max probe request between dwell time.
-//! Saved: yes. Recommended Value: 5 (Default:2)
-//! @param uiChannelMask bitwise, up to 13 channels (0x1fff).
-//! Saved: yes. Default: 0x7ff
-//! @param uiRSSIThreshold RSSI threshold. Saved: yes (Default: -80)
-//! @param uiSNRThreshold NSR threshold. Saved: yes (Default: 0)
-//! @param uiDefaultTxPower probe Tx power. Saved: yes (Default: 205)
-//! @param aiIntervalList pointer to array with 16 entries (16 channels)
-//! each entry (UINT32) holds timeout between periodic scan
-//! (connection scan) - in milliseconds. Saved: yes. Default 2000ms.
-//!
-//! @return On success, zero is returned. On error, -1 is returned
-//!
-//! @brief start and stop scan procedure. Set scan parameters.
-//!
-//! @Note uiDefaultTxPower, is not supported on this version.
-//!
-//! @sa wlan_ioctl_get_scan_results
-//
-//*****************************************************************************
-extern INT32 wlan_ioctl_set_scan_params(UINT32 uiEnable, UINT32
- uiMinDwellTime,UINT32 uiMaxDwellTime,
- UINT32 uiNumOfProbeRequests,
- UINT32 uiChannelMask,
- INT32 iRSSIThreshold,UINT32 uiSNRThreshold,
- UINT32 uiDefaultTxPower,
- UINT32 *aiIntervalList);
-
-
-//*****************************************************************************
-//
-//! wlan_smart_config_start
-//!
-//! @param algoEncryptedFlag indicates whether the information is encrypted
-//!
-//! @return On success, zero is returned. On error, -1 is returned
-//!
-//! @brief Start to acquire device profile. The device acquire its own
-//! profile, if profile message is found. The acquired AP information
-//! is stored in CC3000 EEPROM only in case AES128 encryption is used.
-//! In case AES128 encryption is not used, a profile is created by
-//! CC3000 internally.
-//!
-//! @Note An asynchronous event - Smart Config Done will be generated as soon
-//! as the process finishes successfully.
-//!
-//! @sa wlan_smart_config_set_prefix , wlan_smart_config_stop
-//
-//*****************************************************************************
-extern INT32 wlan_smart_config_start(UINT32 algoEncryptedFlag);
-
-
-//*****************************************************************************
-//
-//! wlan_smart_config_stop
-//!
-//! @param algoEncryptedFlag indicates whether the information is encrypted
-//!
-//! @return On success, zero is returned. On error, -1 is returned
-//!
-//! @brief Stop the acquire profile procedure
-//!
-//! @sa wlan_smart_config_start , wlan_smart_config_set_prefix
-//
-//*****************************************************************************
-extern INT32 wlan_smart_config_stop(void);
-
-//*****************************************************************************
-//
-//! wlan_smart_config_set_prefix
-//!
-//! @param newPrefix 3 bytes identify the SSID prefix for the Smart Config.
-//!
-//! @return On success, zero is returned. On error, -1 is returned
-//!
-//! @brief Configure station ssid prefix. The prefix is used internally
-//! in CC3000. It should always be TTT.
-//!
-//! @Note The prefix is stored in CC3000 NVMEM
-//!
-//! @sa wlan_smart_config_start , wlan_smart_config_stop
-//
-//*****************************************************************************
-extern INT32 wlan_smart_config_set_prefix(CHAR* cNewPrefix);
-
-//*****************************************************************************
-//
-//! wlan_smart_config_process
-//!
-//! @param none
-//!
-//! @return On success, zero is returned. On error, -1 is returned
-//!
-//! @brief process the acquired data and store it as a profile. The acquired
-//! AP information is stored in CC3000 EEPROM encrypted.
-//! The encrypted data is decrypted and stored as a profile.
-//! behavior is as defined by connection policy.
-//
-//*****************************************************************************
-extern INT32 wlan_smart_config_process(void);
-
-//*****************************************************************************
-//
-// Close the Doxygen group.
-//! @}
-//
-//*****************************************************************************
-
-
-
-//*****************************************************************************
-//
-// Mark the end of the C bindings section for C++ compilers.
-//
-//*****************************************************************************
-#ifdef __cplusplus
-}
-#endif // __cplusplus
-
-#endif // __CC3000_WLAN_H__
diff --git a/drivers/cc3000/src/cc3000_common.c b/drivers/cc3000/src/cc3000_common.c
deleted file mode 100644
index b4c87848cf47..000000000000
--- a/drivers/cc3000/src/cc3000_common.c
+++ /dev/null
@@ -1,164 +0,0 @@
-/*****************************************************************************
-*
-* cc3000_common.c.c - CC3000 Host Driver Implementation.
-* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
-*
-* 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 Texas Instruments Incorporated 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
-* OWNER 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.
-*
-*****************************************************************************/
-//*****************************************************************************
-//
-//! \addtogroup common_api
-//! @{
-//
-//*****************************************************************************
-/******************************************************************************
-*
-* Include files
-*
-*****************************************************************************/
-
-#include "cc3000_common.h"
-#include "socket.h"
-#include "wlan.h"
-#include "evnt_handler.h"
-
-//*****************************************************************************
-//
-//! __error__
-//!
-//! @param pcFilename - file name, where error occurred
-//! @param ulLine - line number, where error occurred
-//!
-//! @return none
-//!
-//! @brief stub function for ASSERT macro
-//
-//*****************************************************************************
-void __error__(CHAR *pcFilename, UINT32 ulLine)
-{
- //TODO full up function
-}
-
-
-
-//*****************************************************************************
-//
-//! UINT32_TO_STREAM_f
-//!
-//! @param p pointer to the new stream
-//! @param u32 pointer to the 32 bit
-//!
-//! @return pointer to the new stream
-//!
-//! @brief This function is used for copying 32 bit to stream
-//! while converting to little endian format.
-//
-//*****************************************************************************
-
-UINT8* UINT32_TO_STREAM_f (UINT8 *p, UINT32 u32)
-{
- *(p)++ = (UINT8)(u32);
- *(p)++ = (UINT8)((u32) >> 8);
- *(p)++ = (UINT8)((u32) >> 16);
- *(p)++ = (UINT8)((u32) >> 24);
- return p;
-}
-
-//*****************************************************************************
-//
-//! UINT16_TO_STREAM_f
-//!
-//! @param p pointer to the new stream
-//! @param u32 pointer to the 16 bit
-//!
-//! @return pointer to the new stream
-//!
-//! @brief This function is used for copying 16 bit to stream
-//! while converting to little endian format.
-//
-//*****************************************************************************
-
-UINT8* UINT16_TO_STREAM_f (UINT8 *p, UINT16 u16)
-{
- *(p)++ = (UINT8)(u16);
- *(p)++ = (UINT8)((u16) >> 8);
- return p;
-}
-
-//*****************************************************************************
-//
-//! STREAM_TO_UINT16_f
-//!
-//! @param p pointer to the stream
-//! @param offset offset in the stream
-//!
-//! @return pointer to the new 16 bit
-//!
-//! @brief This function is used for copying received stream to
-//! 16 bit in little endian format.
-//
-//*****************************************************************************
-
-UINT16 STREAM_TO_UINT16_f(CHAR* p, UINT16 offset)
-{
- return (UINT16)((UINT16)((UINT16)
- (*(p + offset + 1)) << 8) + (UINT16)(*(p + offset)));
-}
-
-//*****************************************************************************
-//
-//! STREAM_TO_UINT32_f
-//!
-//! @param p pointer to the stream
-//! @param offset offset in the stream
-//!
-//! @return pointer to the new 32 bit
-//!
-//! @brief This function is used for copying received stream to
-//! 32 bit in little endian format.
-//
-//*****************************************************************************
-
-UINT32 STREAM_TO_UINT32_f(CHAR* p, UINT16 offset)
-{
- return (UINT32)((UINT32)((UINT32)
- (*(p + offset + 3)) << 24) + (UINT32)((UINT32)
- (*(p + offset + 2)) << 16) + (UINT32)((UINT32)
- (*(p + offset + 1)) << 8) + (UINT32)(*(p + offset)));
-}
-
-
-
-//*****************************************************************************
-//
-// Close the Doxygen group.
-//! @}
-//
-//*****************************************************************************
diff --git a/drivers/cc3000/src/ccspi.c b/drivers/cc3000/src/ccspi.c
deleted file mode 100644
index 1dcd61884086..000000000000
--- a/drivers/cc3000/src/ccspi.c
+++ /dev/null
@@ -1,455 +0,0 @@
-/*****************************************************************************
- *
- * spi.c - CC3000 Host Driver Implementation.
- * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
- *
- * 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 Texas Instruments Incorporated 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
- * OWNER 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.
- *
- *****************************************************************************/
-
-#include
-
-#include "py/runtime.h"
-#include "pin.h"
-#include "led.h"
-#include "extint.h"
-#include "spi.h"
-#include "ccspi.h"
-#include "evnt_handler.h"
-
-#if 0 // print debugging info
-#include
-#define DEBUG_printf(args...) printf(args)
-#else // don't print debugging info
-#define DEBUG_printf(args...) (void)0
-#endif
-
-// these need to be set to valid values before anything in this file will work
-STATIC const spi_t *SPI_HANDLE = NULL;
-STATIC const pin_obj_t *PIN_CS = NULL;
-STATIC const pin_obj_t *PIN_EN = NULL;
-STATIC const pin_obj_t *PIN_IRQ = NULL;
-
-#define CS_LOW() HAL_GPIO_WritePin(PIN_CS->gpio, PIN_CS->pin_mask, GPIO_PIN_RESET)
-#define CS_HIGH() HAL_GPIO_WritePin(PIN_CS->gpio, PIN_CS->pin_mask, GPIO_PIN_SET)
-
-#define READ 3
-#define WRITE 1
-
-#define HI(value) (((value) & 0xFF00) >> 8)
-#define LO(value) ((value) & 0x00FF)
-
-#define SPI_TIMEOUT (1000)
-#define HEADERS_SIZE_EVNT (SPI_HEADER_SIZE + 5)
-
-/* SPI bus states */
-#define eSPI_STATE_POWERUP (0)
-#define eSPI_STATE_INITIALIZED (1)
-#define eSPI_STATE_IDLE (2)
-#define eSPI_STATE_WRITE_IRQ (3)
-#define eSPI_STATE_WRITE_FIRST_PORTION (4)
-#define eSPI_STATE_WRITE_EOT (5)
-#define eSPI_STATE_READ_IRQ (6)
-#define eSPI_STATE_READ_FIRST_PORTION (7)
-#define eSPI_STATE_READ_EOT (8)
-
-// The magic number that resides at the end of the TX/RX buffer (1 byte after the allocated size)
-// for the purpose of detection of the overrun. The location of the memory where the magic number
-// resides shall never be written. In case it is written - the overrun occured and either recevie function
-// or send function will stuck forever.
-#define CC3000_BUFFER_MAGIC_NUMBER (0xDE)
-
-typedef struct {
- gcSpiHandleRx SPIRxHandler;
- unsigned short usTxPacketLength;
- unsigned short usRxPacketLength;
- unsigned long ulSpiState;
- unsigned char *pTxPacket;
- unsigned char *pRxPacket;
-} tSpiInformation;
-STATIC tSpiInformation sSpiInformation;
-
-STATIC char spi_buffer[CC3000_RX_BUFFER_SIZE];
-unsigned char wlan_tx_buffer[CC3000_TX_BUFFER_SIZE];
-
-STATIC const mp_obj_fun_builtin_fixed_t irq_callback_obj;
-
-// set the pins to use to communicate with the CC3000
-// the arguments must be of type pin_obj_t* and SPI_HandleTypeDef*
-void SpiInit(void *spi, const void *pin_cs, const void *pin_en, const void *pin_irq) {
- SPI_HANDLE = spi;
- PIN_CS = pin_cs;
- PIN_EN = pin_en;
- PIN_IRQ = pin_irq;
-}
-
-void SpiClose(void)
-{
- if (sSpiInformation.pRxPacket) {
- sSpiInformation.pRxPacket = 0;
- }
-
- tSLInformation.WlanInterruptDisable();
-
- //HAL_SPI_DeInit(SPI_HANDLE);
-}
-
-void SpiOpen(gcSpiHandleRx pfRxHandler)
-{
- DEBUG_printf("SpiOpen\n");
-
- /* initialize SPI state */
- sSpiInformation.ulSpiState = eSPI_STATE_POWERUP;
- sSpiInformation.SPIRxHandler = pfRxHandler;
- sSpiInformation.usTxPacketLength = 0;
- sSpiInformation.pTxPacket = NULL;
- sSpiInformation.pRxPacket = (unsigned char *)spi_buffer;
- sSpiInformation.usRxPacketLength = 0;
- spi_buffer[CC3000_RX_BUFFER_SIZE - 1] = CC3000_BUFFER_MAGIC_NUMBER;
- wlan_tx_buffer[CC3000_TX_BUFFER_SIZE - 1] = CC3000_BUFFER_MAGIC_NUMBER;
-
- /* SPI configuration */
- SPI_InitTypeDef *init = &SPI_HANDLE->spi->Init;
- init->Mode = SPI_MODE_MASTER;
- init->Direction = SPI_DIRECTION_2LINES;
- init->DataSize = SPI_DATASIZE_8BIT;
- init->CLKPolarity = SPI_POLARITY_LOW;
- init->CLKPhase = SPI_PHASE_2EDGE;
- init->NSS = SPI_NSS_SOFT;
- init->BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8;
- init->FirstBit = SPI_FIRSTBIT_MSB;
- init->TIMode = SPI_TIMODE_DISABLED;
- init->CRCCalculation = SPI_CRCCALCULATION_DISABLED;
- init->CRCPolynomial = 7;
- spi_init(SPI_HANDLE, false);
-
- // configure wlan CS and EN pins
- GPIO_InitTypeDef GPIO_InitStructure;
- GPIO_InitStructure.Speed = GPIO_SPEED_FAST;
- GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
- GPIO_InitStructure.Pull = GPIO_NOPULL;
- GPIO_InitStructure.Alternate = 0;
-
- GPIO_InitStructure.Pin = PIN_CS->pin_mask;
- HAL_GPIO_Init(PIN_CS->gpio, &GPIO_InitStructure);
-
- GPIO_InitStructure.Pin = PIN_EN->pin_mask;
- HAL_GPIO_Init(PIN_EN->gpio, &GPIO_InitStructure);
-
- HAL_GPIO_WritePin(PIN_CS->gpio, PIN_CS->pin_mask, GPIO_PIN_SET);
- HAL_GPIO_WritePin(PIN_EN->gpio, PIN_EN->pin_mask, GPIO_PIN_RESET);
-
- /* do a dummy read, this ensures SCLK is low before
- actual communications start, it might be required */
- CS_LOW();
- uint8_t buf[1];
- HAL_SPI_Receive(SPI_HANDLE->spi, buf, sizeof(buf), SPI_TIMEOUT);
- CS_HIGH();
-
- // register EXTI
- extint_register((mp_obj_t)PIN_IRQ, GPIO_MODE_IT_FALLING, GPIO_PULLUP, (mp_obj_t)&irq_callback_obj, true);
- extint_enable(PIN_IRQ->pin);
-
- DEBUG_printf("SpiOpen finished; IRQ.pin=%d IRQ_LINE=%d\n", PIN_IRQ->pin, PIN_IRQ->pin);
-}
-
-long ReadWlanInterruptPin(void)
-{
- return HAL_GPIO_ReadPin(PIN_IRQ->gpio, PIN_IRQ->pin_mask);
-}
-
-void WriteWlanPin(unsigned char val)
-{
- HAL_GPIO_WritePin(PIN_EN->gpio, PIN_EN->pin_mask,
- (WLAN_ENABLE)? GPIO_PIN_SET:GPIO_PIN_RESET);
-}
-
-STATIC void SpiWriteDataSynchronous(unsigned char *data, unsigned short size)
-{
- DEBUG_printf("SpiWriteDataSynchronous(data=%p [%x %x %x %x], size=%u)\n", data, data[0], data[1], data[2], data[3], size);
- __disable_irq();
- if (HAL_SPI_TransmitReceive(SPI_HANDLE->spi, data, data, size, SPI_TIMEOUT) != HAL_OK) {
- //BREAK();
- }
- __enable_irq();
- DEBUG_printf(" - rx data = [%x %x %x %x]\n", data[0], data[1], data[2], data[3]);
-}
-
-STATIC void SpiReadDataSynchronous(unsigned char *data, unsigned short size)
-{
- memset(data, READ, size);
- __disable_irq();
- if (HAL_SPI_TransmitReceive(SPI_HANDLE->spi, data, data, size, SPI_TIMEOUT) != HAL_OK) {
- //BREAK();
- }
- __enable_irq();
-}
-
-STATIC void __delay_cycles(volatile int x)
-{
- x *= 6; // for 168 MHz CPU
- while (x--);
-}
-
-STATIC long SpiFirstWrite(unsigned char *ucBuf, unsigned short usLength)
-{
- DEBUG_printf("SpiFirstWrite %lu\n", sSpiInformation.ulSpiState);
-
- CS_LOW();
-
- // Assuming we are running on 24 MHz ~50 micro delay is 1200 cycles;
- __delay_cycles(1200);
-
- // SPI writes first 4 bytes of data
- SpiWriteDataSynchronous(ucBuf, 4);
-
- __delay_cycles(1200);
-
- SpiWriteDataSynchronous(ucBuf + 4, usLength - 4);
-
- // From this point on - operate in a regular way
- sSpiInformation.ulSpiState = eSPI_STATE_IDLE;
-
- CS_HIGH();
-
- return(0);
-}
-
-long SpiWrite(unsigned char *pUserBuffer, unsigned short usLength)
-{
- DEBUG_printf("SpiWrite %lu\n", sSpiInformation.ulSpiState);
-
- unsigned char ucPad = 0;
-
- // Figure out the total length of the packet in order to figure out if there
- // is padding or not
- if(!(usLength & 0x0001)) {
- ucPad++;
- }
-
- pUserBuffer[0] = WRITE;
- pUserBuffer[1] = HI(usLength + ucPad);
- pUserBuffer[2] = LO(usLength + ucPad);
- pUserBuffer[3] = 0;
- pUserBuffer[4] = 0;
-
- usLength += (SPI_HEADER_SIZE + ucPad);
-
- // The magic number that resides at the end of the TX/RX buffer (1 byte after the allocated size)
- // for the purpose of detection of the overrun. If the magic number is overriten - buffer overrun
- // occurred - and we will stuck here forever!
- if (wlan_tx_buffer[CC3000_TX_BUFFER_SIZE - 1] != CC3000_BUFFER_MAGIC_NUMBER) {
- while (1);
- }
-
- if (sSpiInformation.ulSpiState == eSPI_STATE_POWERUP) {
- while (sSpiInformation.ulSpiState != eSPI_STATE_INITIALIZED);
- }
-
- if (sSpiInformation.ulSpiState == eSPI_STATE_INITIALIZED) {
- // This is time for first TX/RX transactions over SPI:
- // the IRQ is down - so need to send read buffer size command
- SpiFirstWrite(pUserBuffer, usLength);
- } else {
- //
- // We need to prevent here race that can occur in case 2 back to back packets are sent to the
- // device, so the state will move to IDLE and once again to not IDLE due to IRQ
- //
- tSLInformation.WlanInterruptDisable();
-
- while (sSpiInformation.ulSpiState != eSPI_STATE_IDLE);
-
- sSpiInformation.ulSpiState = eSPI_STATE_WRITE_IRQ;
- sSpiInformation.pTxPacket = pUserBuffer;
- sSpiInformation.usTxPacketLength = usLength;
-
- // Assert the CS line and wait till SSI IRQ line is active and then initialize write operation
- CS_LOW();
-
- // Re-enable IRQ - if it was not disabled - this is not a problem...
- tSLInformation.WlanInterruptEnable();
-
- // check for a missing interrupt between the CS assertion and enabling back the interrupts
- if (tSLInformation.ReadWlanInterruptPin() == 0) {
- SpiWriteDataSynchronous(sSpiInformation.pTxPacket, sSpiInformation.usTxPacketLength);
-
- sSpiInformation.ulSpiState = eSPI_STATE_IDLE;
-
- CS_HIGH();
- }
- }
-
- // Due to the fact that we are currently implementing a blocking situation
- // here we will wait till end of transaction
- while (eSPI_STATE_IDLE != sSpiInformation.ulSpiState);
-
- return(0);
-}
-
-#if 0
-unused
-STATIC void SpiReadPacket(void)
-{
- int length;
-
- /* read SPI header */
- SpiReadDataSynchronous(sSpiInformation.pRxPacket, SPI_HEADER_SIZE);
-
- /* parse data length */
- STREAM_TO_UINT8(sSpiInformation.pRxPacket, SPI_HEADER_SIZE-1, length);
-
- /* read the remainder of the packet */
- SpiReadDataSynchronous(sSpiInformation.pRxPacket + SPI_HEADER_SIZE, length);
-
- sSpiInformation.ulSpiState = eSPI_STATE_READ_EOT;
-}
-#endif
-
-STATIC void SpiReadHeader(void)
-{
- SpiReadDataSynchronous(sSpiInformation.pRxPacket, 10);
-}
-
-STATIC void SpiTriggerRxProcessing(void)
-{
- SpiPauseSpi();
- CS_HIGH();
-
- // The magic number that resides at the end of the TX/RX buffer (1 byte after the allocated size)
- // for the purpose of detection of the overrun. If the magic number is overriten - buffer overrun
- // occurred - and we will stuck here forever!
- if (sSpiInformation.pRxPacket[CC3000_RX_BUFFER_SIZE - 1] != CC3000_BUFFER_MAGIC_NUMBER) {
- while (1);
- }
-
- sSpiInformation.ulSpiState = eSPI_STATE_IDLE;
- sSpiInformation.SPIRxHandler(sSpiInformation.pRxPacket + SPI_HEADER_SIZE);
-}
-
-
-STATIC long SpiReadDataCont(void)
-{
- long data_to_recv=0;
- unsigned char *evnt_buff, type;
-
- //determine what type of packet we have
- evnt_buff = sSpiInformation.pRxPacket;
- STREAM_TO_UINT8((char *)(evnt_buff + SPI_HEADER_SIZE), HCI_PACKET_TYPE_OFFSET, type);
-
- switch (type) {
- case HCI_TYPE_DATA:{
- // We need to read the rest of data..
- STREAM_TO_UINT16((char *)(evnt_buff + SPI_HEADER_SIZE),
- HCI_DATA_LENGTH_OFFSET, data_to_recv);
- if (!((HEADERS_SIZE_EVNT + data_to_recv) & 1)) {
- data_to_recv++;
- }
-
- if (data_to_recv) {
- SpiReadDataSynchronous(evnt_buff + 10, data_to_recv);
- }
- break;
- }
- case HCI_TYPE_EVNT: {
- // Calculate the rest length of the data
- STREAM_TO_UINT8((char *)(evnt_buff + SPI_HEADER_SIZE),
- HCI_EVENT_LENGTH_OFFSET, data_to_recv);
- data_to_recv -= 1;
-
- // Add padding byte if needed
- if ((HEADERS_SIZE_EVNT + data_to_recv) & 1) {
- data_to_recv++;
- }
-
- if (data_to_recv) {
- SpiReadDataSynchronous(evnt_buff + 10, data_to_recv);
- }
-
- sSpiInformation.ulSpiState = eSPI_STATE_READ_EOT;
- break;
- }
- }
-
- return 0;
-}
-
-STATIC void SSIContReadOperation(void)
-{
- // The header was read - continue with the payload read
- if (!SpiReadDataCont()) {
- /* All the data was read - finalize handling by switching
- to the task and calling from task Event Handler */
- SpiTriggerRxProcessing();
- }
-}
-
-STATIC mp_obj_t irq_callback(mp_obj_t line) {
- DEBUG_printf("<< IRQ; state=%lu >>\n", sSpiInformation.ulSpiState);
- switch (sSpiInformation.ulSpiState) {
- case eSPI_STATE_POWERUP:
- /* This means IRQ line was low call a callback of HCI Layer to inform on event */
- DEBUG_printf(" - POWERUP\n");
- sSpiInformation.ulSpiState = eSPI_STATE_INITIALIZED;
- break;
- case eSPI_STATE_IDLE:
- DEBUG_printf(" - IDLE\n");
- sSpiInformation.ulSpiState = eSPI_STATE_READ_IRQ;
-
- /* IRQ line goes down - we are start reception */
- CS_LOW();
-
- // Wait for TX/RX Compete which will come as DMA interrupt
- SpiReadHeader();
-
- sSpiInformation.ulSpiState = eSPI_STATE_READ_EOT;
-
- SSIContReadOperation();
- break;
- case eSPI_STATE_WRITE_IRQ:
- DEBUG_printf(" - WRITE IRQ\n");
- SpiWriteDataSynchronous(sSpiInformation.pTxPacket, sSpiInformation.usTxPacketLength);
-
- sSpiInformation.ulSpiState = eSPI_STATE_IDLE;
-
- CS_HIGH();
- break;
- }
- return mp_const_none;
-}
-
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(irq_callback_obj, irq_callback);
-
-void SpiPauseSpi(void) {
- DEBUG_printf("SpiPauseSpi\n");
- extint_disable(PIN_IRQ->pin);
-}
-
-void SpiResumeSpi(void) {
- DEBUG_printf("SpiResumeSpi\n");
- extint_enable(PIN_IRQ->pin);
-}
diff --git a/drivers/cc3000/src/evnt_handler.c b/drivers/cc3000/src/evnt_handler.c
deleted file mode 100644
index 80f34e469b24..000000000000
--- a/drivers/cc3000/src/evnt_handler.c
+++ /dev/null
@@ -1,849 +0,0 @@
-/*****************************************************************************
-*
-* evnt_handler.c - CC3000 Host Driver Implementation.
-* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
-*
-* 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 Texas Instruments Incorporated 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
-* OWNER 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.
-*
-*****************************************************************************/
-//*****************************************************************************
-//
-//! \addtogroup evnt_handler_api
-//! @{
-//
-//******************************************************************************
-
-//******************************************************************************
-// INCLUDE FILES
-//******************************************************************************
-
-#include "cc3000_common.h"
-#include "string.h"
-#include "hci.h"
-#include "evnt_handler.h"
-#include "wlan.h"
-#include "socket.h"
-#include "netapp.h"
-#include "ccspi.h"
-
-
-
-//*****************************************************************************
-// COMMON DEFINES
-//*****************************************************************************
-
-#define FLOW_CONTROL_EVENT_HANDLE_OFFSET (0)
-#define FLOW_CONTROL_EVENT_BLOCK_MODE_OFFSET (1)
-#define FLOW_CONTROL_EVENT_FREE_BUFFS_OFFSET (2)
-#define FLOW_CONTROL_EVENT_SIZE (4)
-
-#define BSD_RSP_PARAMS_SOCKET_OFFSET (0)
-#define BSD_RSP_PARAMS_STATUS_OFFSET (4)
-
-#define GET_HOST_BY_NAME_RETVAL_OFFSET (0)
-#define GET_HOST_BY_NAME_ADDR_OFFSET (4)
-
-#define ACCEPT_SD_OFFSET (0)
-#define ACCEPT_RETURN_STATUS_OFFSET (4)
-#define ACCEPT_ADDRESS__OFFSET (8)
-
-#define SL_RECEIVE_SD_OFFSET (0)
-#define SL_RECEIVE_NUM_BYTES_OFFSET (4)
-#define SL_RECEIVE__FLAGS__OFFSET (8)
-
-
-#define SELECT_STATUS_OFFSET (0)
-#define SELECT_READFD_OFFSET (4)
-#define SELECT_WRITEFD_OFFSET (8)
-#define SELECT_EXFD_OFFSET (12)
-
-
-#define NETAPP_IPCONFIG_IP_OFFSET (0)
-#define NETAPP_IPCONFIG_SUBNET_OFFSET (4)
-#define NETAPP_IPCONFIG_GW_OFFSET (8)
-#define NETAPP_IPCONFIG_DHCP_OFFSET (12)
-#define NETAPP_IPCONFIG_DNS_OFFSET (16)
-#define NETAPP_IPCONFIG_MAC_OFFSET (20)
-#define NETAPP_IPCONFIG_SSID_OFFSET (26)
-
-#define NETAPP_IPCONFIG_IP_LENGTH (4)
-#define NETAPP_IPCONFIG_MAC_LENGTH (6)
-#define NETAPP_IPCONFIG_SSID_LENGTH (32)
-
-
-#define NETAPP_PING_PACKETS_SENT_OFFSET (0)
-#define NETAPP_PING_PACKETS_RCVD_OFFSET (4)
-#define NETAPP_PING_MIN_RTT_OFFSET (8)
-#define NETAPP_PING_MAX_RTT_OFFSET (12)
-#define NETAPP_PING_AVG_RTT_OFFSET (16)
-
-#define GET_SCAN_RESULTS_TABlE_COUNT_OFFSET (0)
-#define GET_SCAN_RESULTS_SCANRESULT_STATUS_OFFSET (4)
-#define GET_SCAN_RESULTS_ISVALID_TO_SSIDLEN_OFFSET (8)
-#define GET_SCAN_RESULTS_FRAME_TIME_OFFSET (10)
-#define GET_SCAN_RESULTS_SSID_MAC_LENGTH (38)
-
-#define GET_MSS_VAL_RETVAL_OFFSET (0)
-
-//*****************************************************************************
-// GLOBAL VARAIABLES
-//*****************************************************************************
-
-UINT32 socket_active_status = SOCKET_STATUS_INIT_VAL;
-
-
-//*****************************************************************************
-// Prototypes for the static functions
-//*****************************************************************************
-
-static INT32 hci_event_unsol_flowcontrol_handler(CHAR *pEvent);
-
-static void update_socket_active_status(CHAR *resp_params);
-
-
-//*****************************************************************************
-//
-//! hci_unsol_handle_patch_request
-//!
-//! @param event_hdr event header
-//!
-//! @return none
-//!
-//! @brief Handle unsolicited event from type patch request
-//
-//*****************************************************************************
-void hci_unsol_handle_patch_request(CHAR *event_hdr)
-{
- CHAR *params = (CHAR *)(event_hdr) + HCI_EVENT_HEADER_SIZE;
- UINT32 ucLength = 0;
- CHAR *patch;
-
- switch (*params)
- {
- case HCI_EVENT_PATCHES_DRV_REQ:
-
- if (tSLInformation.sDriverPatches)
- {
- patch = tSLInformation.sDriverPatches(&ucLength);
-
- if (patch)
- {
- hci_patch_send(HCI_EVENT_PATCHES_DRV_REQ,
- tSLInformation.pucTxCommandBuffer, patch, ucLength);
- return;
- }
- }
-
- // Send 0 length Patches response event
- hci_patch_send(HCI_EVENT_PATCHES_DRV_REQ,
- tSLInformation.pucTxCommandBuffer, 0, 0);
- break;
-
- case HCI_EVENT_PATCHES_FW_REQ:
-
- if (tSLInformation.sFWPatches)
- {
- patch = tSLInformation.sFWPatches(&ucLength);
-
- // Build and send a patch
- if (patch)
- {
- hci_patch_send(HCI_EVENT_PATCHES_FW_REQ,
- tSLInformation.pucTxCommandBuffer, patch, ucLength);
- return;
- }
- }
-
- // Send 0 length Patches response event
- hci_patch_send(HCI_EVENT_PATCHES_FW_REQ,
- tSLInformation.pucTxCommandBuffer, 0, 0);
- break;
-
- case HCI_EVENT_PATCHES_BOOTLOAD_REQ:
-
- if (tSLInformation.sBootLoaderPatches)
- {
- patch = tSLInformation.sBootLoaderPatches(&ucLength);
-
- if (patch)
- {
- hci_patch_send(HCI_EVENT_PATCHES_BOOTLOAD_REQ,
- tSLInformation.pucTxCommandBuffer, patch, ucLength);
- return;
- }
- }
-
- // Send 0 length Patches response event
- hci_patch_send(HCI_EVENT_PATCHES_BOOTLOAD_REQ,
- tSLInformation.pucTxCommandBuffer, 0, 0);
- break;
- }
-}
-
-
-
-//*****************************************************************************
-//
-//! hci_event_handler
-//!
-//! @param pRetParams incoming data buffer
-//! @param from from information (in case of data received)
-//! @param fromlen from information length (in case of data received)
-//!
-//! @return none
-//!
-//! @brief Parse the incoming events packets and issues corresponding
-//! event handler from global array of handlers pointers
-//
-//*****************************************************************************
-
-
-UINT8 * hci_event_handler(void *pRetParams, UINT8 *from, UINT8 *fromlen)
-{
- UINT8 *pucReceivedData, ucArgsize;
- UINT16 usLength;
- UINT8 *pucReceivedParams;
- UINT16 usReceivedEventOpcode = 0;
- UINT32 retValue32;
- UINT8 * RecvParams;
- UINT8 *RetParams;
-
-
- while (1)
- {
- if (tSLInformation.usEventOrDataReceived != 0)
- {
- pucReceivedData = (tSLInformation.pucReceivedData);
-
- if (*pucReceivedData == HCI_TYPE_EVNT)
- {
- // Event Received
- STREAM_TO_UINT16((CHAR *)pucReceivedData, HCI_EVENT_OPCODE_OFFSET,
- usReceivedEventOpcode);
- pucReceivedParams = pucReceivedData + HCI_EVENT_HEADER_SIZE;
- RecvParams = pucReceivedParams;
- RetParams = pRetParams;
-
- // In case unsolicited event received - here the handling finished
- if (hci_unsol_event_handler((CHAR *)pucReceivedData) == 0)
- {
- STREAM_TO_UINT8(pucReceivedData, HCI_DATA_LENGTH_OFFSET, usLength);
-
- switch(usReceivedEventOpcode)
- {
- case HCI_CMND_READ_BUFFER_SIZE:
- {
- STREAM_TO_UINT8((CHAR *)pucReceivedParams, 0,
- tSLInformation.usNumberOfFreeBuffers);
- STREAM_TO_UINT16((CHAR *)pucReceivedParams, 1,
- tSLInformation.usSlBufferLength);
- }
- break;
-
- case HCI_CMND_WLAN_CONFIGURE_PATCH:
- case HCI_NETAPP_DHCP:
- case HCI_NETAPP_PING_SEND:
- case HCI_NETAPP_PING_STOP:
- case HCI_NETAPP_ARP_FLUSH:
- case HCI_NETAPP_SET_DEBUG_LEVEL:
- case HCI_NETAPP_SET_TIMERS:
- case HCI_EVNT_NVMEM_READ:
- case HCI_EVNT_NVMEM_CREATE_ENTRY:
- case HCI_CMND_NVMEM_WRITE_PATCH:
- case HCI_NETAPP_PING_REPORT:
- case HCI_EVNT_MDNS_ADVERTISE:
-
- STREAM_TO_UINT8(pucReceivedData, HCI_EVENT_STATUS_OFFSET
- ,*(UINT8 *)pRetParams);
- break;
-
- case HCI_CMND_SETSOCKOPT:
- case HCI_CMND_WLAN_CONNECT:
- case HCI_CMND_WLAN_IOCTL_STATUSGET:
- case HCI_EVNT_WLAN_IOCTL_ADD_PROFILE:
- case HCI_CMND_WLAN_IOCTL_DEL_PROFILE:
- case HCI_CMND_WLAN_IOCTL_SET_CONNECTION_POLICY:
- case HCI_CMND_WLAN_IOCTL_SET_SCANPARAM:
- case HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_START:
- case HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_STOP:
- case HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_SET_PREFIX:
- case HCI_CMND_EVENT_MASK:
- case HCI_EVNT_WLAN_DISCONNECT:
- case HCI_EVNT_SOCKET:
- case HCI_EVNT_BIND:
- case HCI_CMND_LISTEN:
- case HCI_EVNT_CLOSE_SOCKET:
- case HCI_EVNT_CONNECT:
- case HCI_EVNT_NVMEM_WRITE:
-
- STREAM_TO_UINT32((CHAR *)pucReceivedParams,0
- ,*(UINT32 *)pRetParams);
- break;
-
- case HCI_EVNT_READ_SP_VERSION:
-
- STREAM_TO_UINT8(pucReceivedData, HCI_EVENT_STATUS_OFFSET
- ,*(UINT8 *)pRetParams);
- pRetParams = ((CHAR *)pRetParams) + 1;
- STREAM_TO_UINT32((CHAR *)pucReceivedParams, 0, retValue32);
- UINT32_TO_STREAM((UINT8 *)pRetParams, retValue32);
- break;
-
- case HCI_EVNT_BSD_GETHOSTBYNAME:
-
- STREAM_TO_UINT32((CHAR *)pucReceivedParams
- ,GET_HOST_BY_NAME_RETVAL_OFFSET,*(UINT32 *)pRetParams);
- pRetParams = ((CHAR *)pRetParams) + 4;
- STREAM_TO_UINT32((CHAR *)pucReceivedParams
- ,GET_HOST_BY_NAME_ADDR_OFFSET,*(UINT32 *)pRetParams);
- break;
-
- case HCI_EVNT_GETMSSVALUE:
-
- STREAM_TO_UINT16((CHAR *)pucReceivedParams
- ,GET_MSS_VAL_RETVAL_OFFSET,*(UINT16 *)pRetParams);
-
- break;
-
- case HCI_EVNT_ACCEPT:
- {
- STREAM_TO_UINT32((CHAR *)pucReceivedParams,ACCEPT_SD_OFFSET
- ,*(UINT32 *)pRetParams);
- pRetParams = ((CHAR *)pRetParams) + 4;
- STREAM_TO_UINT32((CHAR *)pucReceivedParams
- ,ACCEPT_RETURN_STATUS_OFFSET,*(UINT32 *)pRetParams);
- pRetParams = ((CHAR *)pRetParams) + 4;
-
- //This argument returns in network order
- memcpy((UINT8 *)pRetParams,
- pucReceivedParams + ACCEPT_ADDRESS__OFFSET, sizeof(sockaddr));
- break;
- }
-
- case HCI_EVNT_RECV:
- case HCI_EVNT_RECVFROM:
- {
- STREAM_TO_UINT32((CHAR *)pucReceivedParams,SL_RECEIVE_SD_OFFSET ,*(UINT32 *)pRetParams);
- pRetParams = ((CHAR *)pRetParams) + 4;
- STREAM_TO_UINT32((CHAR *)pucReceivedParams,SL_RECEIVE_NUM_BYTES_OFFSET,*(UINT32 *)pRetParams);
- pRetParams = ((CHAR *)pRetParams) + 4;
- STREAM_TO_UINT32((CHAR *)pucReceivedParams,SL_RECEIVE__FLAGS__OFFSET,*(UINT32 *)pRetParams);
-
- if(((tBsdReadReturnParams *)pRetParams)->iNumberOfBytes == ERROR_SOCKET_INACTIVE)
- {
- set_socket_active_status(((tBsdReadReturnParams *)pRetParams)->iSocketDescriptor,SOCKET_STATUS_INACTIVE);
- }
- break;
- }
-
- case HCI_EVNT_SEND:
- case HCI_EVNT_SENDTO:
- {
- STREAM_TO_UINT32((CHAR *)pucReceivedParams,SL_RECEIVE_SD_OFFSET ,*(UINT32 *)pRetParams);
- pRetParams = ((CHAR *)pRetParams) + 4;
- STREAM_TO_UINT32((CHAR *)pucReceivedParams,SL_RECEIVE_NUM_BYTES_OFFSET,*(UINT32 *)pRetParams);
- pRetParams = ((CHAR *)pRetParams) + 4;
-
- break;
- }
-
- case HCI_EVNT_SELECT:
- {
- STREAM_TO_UINT32((CHAR *)pucReceivedParams,SELECT_STATUS_OFFSET,*(UINT32 *)pRetParams);
- pRetParams = ((CHAR *)pRetParams) + 4;
- STREAM_TO_UINT32((CHAR *)pucReceivedParams,SELECT_READFD_OFFSET,*(UINT32 *)pRetParams);
- pRetParams = ((CHAR *)pRetParams) + 4;
- STREAM_TO_UINT32((CHAR *)pucReceivedParams,SELECT_WRITEFD_OFFSET,*(UINT32 *)pRetParams);
- pRetParams = ((CHAR *)pRetParams) + 4;
- STREAM_TO_UINT32((CHAR *)pucReceivedParams,SELECT_EXFD_OFFSET,*(UINT32 *)pRetParams);
- break;
- }
-
- case HCI_CMND_GETSOCKOPT:
-
- STREAM_TO_UINT8(pucReceivedData, HCI_EVENT_STATUS_OFFSET,((tBsdGetSockOptReturnParams *)pRetParams)->iStatus);
- //This argument returns in network order
- memcpy((UINT8 *)pRetParams, pucReceivedParams, 4);
- break;
-
- case HCI_CMND_WLAN_IOCTL_GET_SCAN_RESULTS:
-
- STREAM_TO_UINT32((CHAR *)pucReceivedParams,GET_SCAN_RESULTS_TABlE_COUNT_OFFSET,*(UINT32 *)pRetParams);
- pRetParams = ((CHAR *)pRetParams) + 4;
- STREAM_TO_UINT32((CHAR *)pucReceivedParams,GET_SCAN_RESULTS_SCANRESULT_STATUS_OFFSET,*(UINT32 *)pRetParams);
- pRetParams = ((CHAR *)pRetParams) + 4;
- STREAM_TO_UINT16((CHAR *)pucReceivedParams,GET_SCAN_RESULTS_ISVALID_TO_SSIDLEN_OFFSET,*(UINT32 *)pRetParams);
- pRetParams = ((CHAR *)pRetParams) + 2;
- STREAM_TO_UINT16((CHAR *)pucReceivedParams,GET_SCAN_RESULTS_FRAME_TIME_OFFSET,*(UINT32 *)pRetParams);
- pRetParams = ((CHAR *)pRetParams) + 2;
- memcpy((UINT8 *)pRetParams, (CHAR *)(pucReceivedParams + GET_SCAN_RESULTS_FRAME_TIME_OFFSET + 2), GET_SCAN_RESULTS_SSID_MAC_LENGTH);
- break;
-
- case HCI_CMND_SIMPLE_LINK_START:
- break;
-
- case HCI_NETAPP_IPCONFIG:
-
- //Read IP address
- STREAM_TO_STREAM(RecvParams,RetParams,NETAPP_IPCONFIG_IP_LENGTH);
- RecvParams += 4;
-
- //Read subnet
- STREAM_TO_STREAM(RecvParams,RetParams,NETAPP_IPCONFIG_IP_LENGTH);
- RecvParams += 4;
-
- //Read default GW
- STREAM_TO_STREAM(RecvParams,RetParams,NETAPP_IPCONFIG_IP_LENGTH);
- RecvParams += 4;
-
- //Read DHCP server
- STREAM_TO_STREAM(RecvParams,RetParams,NETAPP_IPCONFIG_IP_LENGTH);
- RecvParams += 4;
-
- //Read DNS server
- STREAM_TO_STREAM(RecvParams,RetParams,NETAPP_IPCONFIG_IP_LENGTH);
- RecvParams += 4;
-
- //Read Mac address
- STREAM_TO_STREAM(RecvParams,RetParams,NETAPP_IPCONFIG_MAC_LENGTH);
- RecvParams += 6;
-
- //Read SSID
- STREAM_TO_STREAM(RecvParams,RetParams,NETAPP_IPCONFIG_SSID_LENGTH);
-
- }
- }
-
- if (usReceivedEventOpcode == tSLInformation.usRxEventOpcode)
- {
- tSLInformation.usRxEventOpcode = 0;
- }
- }
- else
- {
- pucReceivedParams = pucReceivedData;
- STREAM_TO_UINT8((CHAR *)pucReceivedData, HCI_PACKET_ARGSIZE_OFFSET, ucArgsize);
-
- STREAM_TO_UINT16((CHAR *)pucReceivedData, HCI_PACKET_LENGTH_OFFSET, usLength);
-
- // Data received: note that the only case where from and from length
- // are not null is in recv from, so fill the args accordingly
- if (from)
- {
- STREAM_TO_UINT32((CHAR *)(pucReceivedData + HCI_DATA_HEADER_SIZE), BSD_RECV_FROM_FROMLEN_OFFSET, *(UINT32 *)fromlen);
- memcpy(from, (pucReceivedData + HCI_DATA_HEADER_SIZE + BSD_RECV_FROM_FROM_OFFSET) ,*fromlen);
- }
-
- memcpy(pRetParams, pucReceivedParams + HCI_DATA_HEADER_SIZE + ucArgsize,
- usLength - ucArgsize);
-
- tSLInformation.usRxDataPending = 0;
- }
-
- tSLInformation.usEventOrDataReceived = 0;
-
- SpiResumeSpi();
-
- // Since we are going to TX - we need to handle this event after the
- // ResumeSPi since we need interrupts
- if ((*pucReceivedData == HCI_TYPE_EVNT) &&
- (usReceivedEventOpcode == HCI_EVNT_PATCHES_REQ))
- {
- hci_unsol_handle_patch_request((CHAR *)pucReceivedData);
- }
-
- if ((tSLInformation.usRxEventOpcode == 0) && (tSLInformation.usRxDataPending == 0))
- {
- return NULL;
- }
- }
- }
-
-}
-
-//*****************************************************************************
-//
-//! hci_unsol_event_handler
-//!
-//! @param event_hdr event header
-//!
-//! @return 1 if event supported and handled
-//! 0 if event is not supported
-//!
-//! @brief Handle unsolicited events
-//
-//*****************************************************************************
-INT32 hci_unsol_event_handler(CHAR *event_hdr)
-{
- CHAR * data = NULL;
- INT32 event_type;
- UINT32 NumberOfReleasedPackets;
- UINT32 NumberOfSentPackets;
-
- STREAM_TO_UINT16(event_hdr, HCI_EVENT_OPCODE_OFFSET,event_type);
-
- if (event_type & HCI_EVNT_UNSOL_BASE)
- {
- switch(event_type)
- {
-
- case HCI_EVNT_DATA_UNSOL_FREE_BUFF:
- {
- hci_event_unsol_flowcontrol_handler(event_hdr);
-
- NumberOfReleasedPackets = tSLInformation.NumberOfReleasedPackets;
- NumberOfSentPackets = tSLInformation.NumberOfSentPackets;
-
- if (NumberOfReleasedPackets == NumberOfSentPackets)
- {
- if (tSLInformation.InformHostOnTxComplete)
- {
- tSLInformation.sWlanCB(HCI_EVENT_CC3000_CAN_SHUT_DOWN, NULL, 0);
- }
- }
- return 1;
-
- }
- }
- }
-
- if(event_type & HCI_EVNT_WLAN_UNSOL_BASE)
- {
- switch(event_type)
- {
- case HCI_EVNT_WLAN_KEEPALIVE:
- case HCI_EVNT_WLAN_UNSOL_CONNECT:
- case HCI_EVNT_WLAN_UNSOL_DISCONNECT:
- case HCI_EVNT_WLAN_UNSOL_INIT:
- case HCI_EVNT_WLAN_ASYNC_SIMPLE_CONFIG_DONE:
-
- if( tSLInformation.sWlanCB )
- {
- tSLInformation.sWlanCB(event_type, 0, 0);
- }
- break;
-
- case HCI_EVNT_WLAN_UNSOL_DHCP:
- {
- UINT8 params[NETAPP_IPCONFIG_MAC_OFFSET + 1]; // extra byte is for the status
- UINT8 *recParams = params;
-
- data = (CHAR*)(event_hdr) + HCI_EVENT_HEADER_SIZE;
-
- //Read IP address
- STREAM_TO_STREAM(data,recParams,NETAPP_IPCONFIG_IP_LENGTH);
- data += 4;
- //Read subnet
- STREAM_TO_STREAM(data,recParams,NETAPP_IPCONFIG_IP_LENGTH);
- data += 4;
- //Read default GW
- STREAM_TO_STREAM(data,recParams,NETAPP_IPCONFIG_IP_LENGTH);
- data += 4;
- //Read DHCP server
- STREAM_TO_STREAM(data,recParams,NETAPP_IPCONFIG_IP_LENGTH);
- data += 4;
- //Read DNS server
- STREAM_TO_STREAM(data,recParams,NETAPP_IPCONFIG_IP_LENGTH);
- // read the status
- STREAM_TO_UINT8(event_hdr, HCI_EVENT_STATUS_OFFSET, *recParams);
-
-
- if( tSLInformation.sWlanCB )
- {
- tSLInformation.sWlanCB(event_type, (CHAR *)params, sizeof(params));
- }
- }
- break;
-
- case HCI_EVNT_WLAN_ASYNC_PING_REPORT:
- {
- netapp_pingreport_args_t params;
- data = (CHAR*)(event_hdr) + HCI_EVENT_HEADER_SIZE;
- STREAM_TO_UINT32(data, NETAPP_PING_PACKETS_SENT_OFFSET, params.packets_sent);
- STREAM_TO_UINT32(data, NETAPP_PING_PACKETS_RCVD_OFFSET, params.packets_received);
- STREAM_TO_UINT32(data, NETAPP_PING_MIN_RTT_OFFSET, params.min_round_time);
- STREAM_TO_UINT32(data, NETAPP_PING_MAX_RTT_OFFSET, params.max_round_time);
- STREAM_TO_UINT32(data, NETAPP_PING_AVG_RTT_OFFSET, params.avg_round_time);
-
- if( tSLInformation.sWlanCB )
- {
- tSLInformation.sWlanCB(event_type, (CHAR *)¶ms, sizeof(params));
- }
- }
- break;
- case HCI_EVNT_BSD_TCP_CLOSE_WAIT:
- {
- data = (CHAR *)(event_hdr) + HCI_EVENT_HEADER_SIZE;
- if( tSLInformation.sWlanCB )
- {
- //data[0] represents the socket id, for which FIN was received by remote.
- //Upon receiving this event, the user can close the socket, or else the
- //socket will be closded after inacvitity timeout (by default 60 seconds)
- tSLInformation.sWlanCB(event_type, data, 1);
- }
- }
- break;
-
- //'default' case which means "event not supported"
- default:
- return (0);
- }
- return(1);
- }
-
- if ((event_type == HCI_EVNT_SEND) || (event_type == HCI_EVNT_SENDTO)
- || (event_type == HCI_EVNT_WRITE))
- {
- CHAR *pArg;
- INT32 status;
-
- pArg = M_BSD_RESP_PARAMS_OFFSET(event_hdr);
- STREAM_TO_UINT32(pArg, BSD_RSP_PARAMS_STATUS_OFFSET,status);
-
- if (ERROR_SOCKET_INACTIVE == status)
- {
- // The only synchronous event that can come from SL device in form of
- // command complete is "Command Complete" on data sent, in case SL device
- // was unable to transmit
- STREAM_TO_UINT8(event_hdr, HCI_EVENT_STATUS_OFFSET, tSLInformation.slTransmitDataError);
- update_socket_active_status(M_BSD_RESP_PARAMS_OFFSET(event_hdr));
-
- return (1);
- }
- else
- return (0);
- }
-
- //handle a case where unsolicited event arrived, but was not handled by any of the cases above
- if ((event_type != tSLInformation.usRxEventOpcode) && (event_type != HCI_EVNT_PATCHES_REQ))
- {
- return(1);
- }
-
- return(0);
-}
-
-//*****************************************************************************
-//
-//! hci_unsolicited_event_handler
-//!
-//! @param None
-//!
-//! @return ESUCCESS if successful, EFAIL if an error occurred
-//!
-//! @brief Parse the incoming unsolicited event packets and issues
-//! corresponding event handler.
-//
-//*****************************************************************************
-INT32 hci_unsolicited_event_handler(void)
-{
- UINT32 res = 0;
- UINT8 *pucReceivedData;
-
- if (tSLInformation.usEventOrDataReceived != 0)
- {
- pucReceivedData = (tSLInformation.pucReceivedData);
-
- if (*pucReceivedData == HCI_TYPE_EVNT)
- {
-
- // In case unsolicited event received - here the handling finished
- if (hci_unsol_event_handler((CHAR *)pucReceivedData) == 1)
- {
-
- // There was an unsolicited event received - we can release the buffer
- // and clean the event received
- tSLInformation.usEventOrDataReceived = 0;
-
- res = 1;
- SpiResumeSpi();
- }
- }
- }
-
- return res;
-}
-
-//*****************************************************************************
-//
-//! set_socket_active_status
-//!
-//! @param Sd
-//! @param Status
-//! @return none
-//!
-//! @brief Check if the socket ID and status are valid and set
-//! accordingly the global socket status
-//
-//*****************************************************************************
-void set_socket_active_status(INT32 Sd, INT32 Status)
-{
- if(M_IS_VALID_SD(Sd) && M_IS_VALID_STATUS(Status))
- {
- socket_active_status &= ~(1 << Sd); /* clean socket's mask */
- socket_active_status |= (Status << Sd); /* set new socket's mask */
- }
-}
-
-
-//*****************************************************************************
-//
-//! hci_event_unsol_flowcontrol_handler
-//!
-//! @param pEvent pointer to the string contains parameters for IPERF
-//! @return ESUCCESS if successful, EFAIL if an error occurred
-//!
-//! @brief Called in case unsolicited event from type
-//! HCI_EVNT_DATA_UNSOL_FREE_BUFF has received.
-//! Keep track on the number of packets transmitted and update the
-//! number of free buffer in the SL device.
-//
-//*****************************************************************************
-INT32 hci_event_unsol_flowcontrol_handler(CHAR *pEvent)
-{
-
- INT32 temp, value;
- UINT16 i;
- UINT16 pusNumberOfHandles=0;
- CHAR *pReadPayload;
-
- STREAM_TO_UINT16((CHAR *)pEvent,HCI_EVENT_HEADER_SIZE,pusNumberOfHandles);
- pReadPayload = ((CHAR *)pEvent +
- HCI_EVENT_HEADER_SIZE + sizeof(pusNumberOfHandles));
- temp = 0;
-
- for(i = 0; i < pusNumberOfHandles ; i++)
- {
- STREAM_TO_UINT16(pReadPayload, FLOW_CONTROL_EVENT_FREE_BUFFS_OFFSET, value);
- temp += value;
- pReadPayload += FLOW_CONTROL_EVENT_SIZE;
- }
-
- tSLInformation.usNumberOfFreeBuffers += temp;
- tSLInformation.NumberOfReleasedPackets += temp;
-
- return(ESUCCESS);
-}
-
-//*****************************************************************************
-//
-//! get_socket_active_status
-//!
-//! @param Sd Socket IS
-//! @return Current status of the socket.
-//!
-//! @brief Retrieve socket status
-//
-//*****************************************************************************
-
-INT32 get_socket_active_status(INT32 Sd)
-{
- if(M_IS_VALID_SD(Sd))
- {
- return (socket_active_status & (1 << Sd)) ? SOCKET_STATUS_INACTIVE : SOCKET_STATUS_ACTIVE;
- }
- return SOCKET_STATUS_INACTIVE;
-}
-
-//*****************************************************************************
-//
-//! update_socket_active_status
-//!
-//! @param resp_params Socket IS
-//! @return Current status of the socket.
-//!
-//! @brief Retrieve socket status
-//
-//*****************************************************************************
-void update_socket_active_status(CHAR *resp_params)
-{
- INT32 status, sd;
-
- STREAM_TO_UINT32(resp_params, BSD_RSP_PARAMS_SOCKET_OFFSET,sd);
- STREAM_TO_UINT32(resp_params, BSD_RSP_PARAMS_STATUS_OFFSET,status);
-
- if(ERROR_SOCKET_INACTIVE == status)
- {
- set_socket_active_status(sd, SOCKET_STATUS_INACTIVE);
- }
-}
-
-
-//*****************************************************************************
-//
-//! SimpleLinkWaitEvent
-//!
-//! @param usOpcode command operation code
-//! @param pRetParams command return parameters
-//!
-//! @return none
-//!
-//! @brief Wait for event, pass it to the hci_event_handler and
-//! update the event opcode in a global variable.
-//
-//*****************************************************************************
-
-void SimpleLinkWaitEvent(UINT16 usOpcode, void *pRetParams)
-{
- // In the blocking implementation the control to caller will be returned only
- // after the end of current transaction
- tSLInformation.usRxEventOpcode = usOpcode;
- hci_event_handler(pRetParams, 0, 0);
-}
-
-//*****************************************************************************
-//
-//! SimpleLinkWaitData
-//!
-//! @param pBuf data buffer
-//! @param from from information
-//! @param fromlen from information length
-//!
-//! @return none
-//!
-//! @brief Wait for data, pass it to the hci_event_handler
-//! and update in a global variable that there is
-//! data to read.
-//
-//*****************************************************************************
-
-void SimpleLinkWaitData(UINT8 *pBuf, UINT8 *from, UINT8 *fromlen)
-{
- // In the blocking implementation the control to caller will be returned only
- // after the end of current transaction, i.e. only after data will be received
- tSLInformation.usRxDataPending = 1;
- hci_event_handler(pBuf, from, fromlen);
-}
-
-//*****************************************************************************
-//
-// Close the Doxygen group.
-//! @}
-//
-//*****************************************************************************
diff --git a/drivers/cc3000/src/hci.c b/drivers/cc3000/src/hci.c
deleted file mode 100644
index 4391692b8bc2..000000000000
--- a/drivers/cc3000/src/hci.c
+++ /dev/null
@@ -1,225 +0,0 @@
-/*****************************************************************************
-*
-* hci.c - CC3000 Host Driver Implementation.
-* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
-*
-* 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 Texas Instruments Incorporated 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
-* OWNER 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.
-*
-*****************************************************************************/
-
-//*****************************************************************************
-//
-//! \addtogroup hci_app
-//! @{
-//
-//*****************************************************************************
-
-#include
-#include "cc3000_common.h"
-#include "hci.h"
-#include "ccspi.h"
-#include "evnt_handler.h"
-#include "wlan.h"
-
-#define SL_PATCH_PORTION_SIZE (1000)
-
-
-//*****************************************************************************
-//
-//! hci_command_send
-//!
-//! @param usOpcode command operation code
-//! @param pucBuff pointer to the command's arguments buffer
-//! @param ucArgsLength length of the arguments
-//!
-//! @return none
-//!
-//! @brief Initiate an HCI command.
-//
-//*****************************************************************************
-UINT16 hci_command_send(UINT16 usOpcode, UINT8 *pucBuff, UINT8 ucArgsLength)
-{
- UINT8 *stream;
-
- stream = (pucBuff + SPI_HEADER_SIZE);
-
- UINT8_TO_STREAM(stream, HCI_TYPE_CMND);
- stream = UINT16_TO_STREAM(stream, usOpcode);
- UINT8_TO_STREAM(stream, ucArgsLength);
-
- //Update the opcode of the event we will be waiting for
- SpiWrite(pucBuff, ucArgsLength + SIMPLE_LINK_HCI_CMND_HEADER_SIZE);
-
- return(0);
-}
-
-//*****************************************************************************
-//
-//! hci_data_send
-//!
-//! @param usOpcode command operation code
-//! @param ucArgs pointer to the command's arguments buffer
-//! @param usArgsLength length of the arguments
-//! @param ucTail pointer to the data buffer
-//! @param usTailLength buffer length
-//!
-//! @return none
-//!
-//! @brief Initiate an HCI data write operation
-//
-//*****************************************************************************
-INT32 hci_data_send(UINT8 ucOpcode,
- UINT8 *ucArgs,
- UINT16 usArgsLength,
- UINT16 usDataLength,
- const UINT8 *ucTail,
- UINT16 usTailLength)
-{
- UINT8 *stream;
-
- stream = ((ucArgs) + SPI_HEADER_SIZE);
-
- UINT8_TO_STREAM(stream, HCI_TYPE_DATA);
- UINT8_TO_STREAM(stream, ucOpcode);
- UINT8_TO_STREAM(stream, usArgsLength);
- stream = UINT16_TO_STREAM(stream, usArgsLength + usDataLength + usTailLength);
-
- // Send the packet over the SPI
- SpiWrite(ucArgs, SIMPLE_LINK_HCI_DATA_HEADER_SIZE + usArgsLength + usDataLength + usTailLength);
-
- return(ESUCCESS);
-}
-
-
-//*****************************************************************************
-//
-//! hci_data_command_send
-//!
-//! @param usOpcode command operation code
-//! @param pucBuff pointer to the data buffer
-//! @param ucArgsLength arguments length
-//! @param ucDataLength data length
-//!
-//! @return none
-//!
-//! @brief Prepeare HCI header and initiate an HCI data write operation
-//
-//*****************************************************************************
-void hci_data_command_send(UINT16 usOpcode, UINT8 *pucBuff, UINT8 ucArgsLength,UINT16 ucDataLength)
-{
- UINT8 *stream = (pucBuff + SPI_HEADER_SIZE);
-
- UINT8_TO_STREAM(stream, HCI_TYPE_DATA);
- UINT8_TO_STREAM(stream, usOpcode);
- UINT8_TO_STREAM(stream, ucArgsLength);
- stream = UINT16_TO_STREAM(stream, ucArgsLength + ucDataLength);
-
- // Send the command over SPI on data channel
- SpiWrite(pucBuff, ucArgsLength + ucDataLength + SIMPLE_LINK_HCI_DATA_CMND_HEADER_SIZE);
-
- return;
-}
-
-//*****************************************************************************
-//
-//! hci_patch_send
-//!
-//! @param usOpcode command operation code
-//! @param pucBuff pointer to the command's arguments buffer
-//! @param patch pointer to patch content buffer
-//! @param usDataLength data length
-//!
-//! @return none
-//!
-//! @brief Prepeare HCI header and initiate an HCI patch write operation
-//
-//*****************************************************************************
-void hci_patch_send(UINT8 ucOpcode, UINT8 *pucBuff, CHAR *patch, UINT16 usDataLength)
-{
- UINT8 *data_ptr = (pucBuff + SPI_HEADER_SIZE);
- UINT16 usTransLength;
- UINT8 *stream = (pucBuff + SPI_HEADER_SIZE);
-
- UINT8_TO_STREAM(stream, HCI_TYPE_PATCH);
- UINT8_TO_STREAM(stream, ucOpcode);
- stream = UINT16_TO_STREAM(stream, usDataLength + SIMPLE_LINK_HCI_PATCH_HEADER_SIZE);
-
- if (usDataLength <= SL_PATCH_PORTION_SIZE)
- {
- UINT16_TO_STREAM(stream, usDataLength);
- stream = UINT16_TO_STREAM(stream, usDataLength);
- memcpy((pucBuff + SPI_HEADER_SIZE) + HCI_PATCH_HEADER_SIZE, patch, usDataLength);
-
- // Update the opcode of the event we will be waiting for
- SpiWrite(pucBuff, usDataLength + HCI_PATCH_HEADER_SIZE);
- }
- else
- {
-
- usTransLength = (usDataLength/SL_PATCH_PORTION_SIZE);
- UINT16_TO_STREAM(stream, usDataLength + SIMPLE_LINK_HCI_PATCH_HEADER_SIZE + usTransLength*SIMPLE_LINK_HCI_PATCH_HEADER_SIZE);
- stream = UINT16_TO_STREAM(stream, SL_PATCH_PORTION_SIZE);
- memcpy(pucBuff + SPI_HEADER_SIZE + HCI_PATCH_HEADER_SIZE, patch, SL_PATCH_PORTION_SIZE);
- usDataLength -= SL_PATCH_PORTION_SIZE;
- patch += SL_PATCH_PORTION_SIZE;
-
- // Update the opcode of the event we will be waiting for
- SpiWrite(pucBuff, SL_PATCH_PORTION_SIZE + HCI_PATCH_HEADER_SIZE);
-
- while (usDataLength)
- {
- if (usDataLength <= SL_PATCH_PORTION_SIZE)
- {
- usTransLength = usDataLength;
- usDataLength = 0;
-
- }
- else
- {
- usTransLength = SL_PATCH_PORTION_SIZE;
- usDataLength -= usTransLength;
- }
-
- *(UINT16 *)data_ptr = usTransLength;
- memcpy(data_ptr + SIMPLE_LINK_HCI_PATCH_HEADER_SIZE, patch, usTransLength);
- patch += usTransLength;
-
- // Update the opcode of the event we will be waiting for
- SpiWrite((UINT8 *)data_ptr, usTransLength + sizeof(usTransLength));
- }
- }
-}
-
-//*****************************************************************************
-//
-// Close the Doxygen group.
-//! @}
-//
-//
-//*****************************************************************************
diff --git a/drivers/cc3000/src/inet_ntop.c b/drivers/cc3000/src/inet_ntop.c
deleted file mode 100644
index 83242efa00b0..000000000000
--- a/drivers/cc3000/src/inet_ntop.c
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- * Copyright (C) 1996-2001 Internet Software Consortium.
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
- * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
- * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
- * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
- * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
- * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
- * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include
-#include "cc3000_common.h"
-#include "socket.h"
-#include "inet_ntop.h"
-
-// We can't include stdio.h because it defines _types_fd_set, but we
-// need to use the CC3000 version of this type. So we must provide
-// our own declaration of snprintf. Grrr.
-int snprintf(char *str, size_t size, const char *fmt, ...);
-
-#define IN6ADDRSZ 16
-#define INADDRSZ 4
-#define INT16SZ 2
-
-#define ENOSPC (28)
-#define EAFNOSUPPORT (106)
-#define SET_ERRNO(err) (CC3000_EXPORT(errno)=-err)
-
-/*
- * Format an IPv4 address, more or less like inet_ntoa().
- *
- * Returns `dst' (as a const)
- * Note:
- * - uses no statics
- * - takes a unsigned char* not an in_addr as input
- */
-static char *inet_ntop4 (const unsigned char *src, char *dst, size_t size)
-{
- size_t len;
- char tmp[sizeof "255.255.255.255"];
-
- tmp[0] = '\0';
- (void)snprintf(tmp, sizeof(tmp), "%d.%d.%d.%d",
- ((int)((unsigned char)src[3])) & 0xff,
- ((int)((unsigned char)src[2])) & 0xff,
- ((int)((unsigned char)src[1])) & 0xff,
- ((int)((unsigned char)src[0])) & 0xff);
-
- len = strlen(tmp);
- if(len == 0 || len >= size)
- {
- SET_ERRNO(ENOSPC);
- return (NULL);
- }
- strcpy(dst, tmp);
- return dst;
-}
-
-#ifdef ENABLE_IPV6
-/*
- * Convert IPv6 binary address into presentation (printable) format.
- */
-static char *inet_ntop6 (const unsigned char *src, char *dst, size_t size)
-{
- /*
- * Note that int32_t and int16_t need only be "at least" large enough
- * to contain a value of the specified size. On some systems, like
- * Crays, there is no such thing as an integer variable with 16 bits.
- * Keep this in mind if you think this function should have been coded
- * to use pointer overlays. All the world's not a VAX.
- */
- char tmp[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
- char *tp;
- struct {
- long base;
- long len;
- } best, cur;
- unsigned long words[IN6ADDRSZ / INT16SZ];
- int i;
-
- /* Preprocess:
- * Copy the input (bytewise) array into a wordwise array.
- * Find the longest run of 0x00's in src[] for :: shorthanding.
- */
- memset(words, '\0', sizeof(words));
- for (i = 0; i < IN6ADDRSZ; i++)
- words[i/2] |= (src[i] << ((1 - (i % 2)) << 3));
-
- best.base = -1;
- cur.base = -1;
- best.len = 0;
- cur.len = 0;
-
- for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++)
- {
- if(words[i] == 0)
- {
- if(cur.base == -1)
- cur.base = i, cur.len = 1;
- else
- cur.len++;
- }
- else if(cur.base != -1)
- {
- if(best.base == -1 || cur.len > best.len)
- best = cur;
- cur.base = -1;
- }
- }
- if((cur.base != -1) && (best.base == -1 || cur.len > best.len))
- best = cur;
- if(best.base != -1 && best.len < 2)
- best.base = -1;
-
- /* Format the result.
- */
- tp = tmp;
- for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++)
- {
- /* Are we inside the best run of 0x00's?
- */
- if(best.base != -1 && i >= best.base && i < (best.base + best.len))
- {
- if(i == best.base)
- *tp++ = ':';
- continue;
- }
-
- /* Are we following an initial run of 0x00s or any real hex?
- */
- if(i != 0)
- *tp++ = ':';
-
- /* Is this address an encapsulated IPv4?
- */
- if(i == 6 && best.base == 0 &&
- (best.len == 6 || (best.len == 5 && words[5] == 0xffff)))
- {
- if(!inet_ntop4(src+12, tp, sizeof(tmp) - (tp - tmp)))
- {
- SET_ERRNO(ENOSPC);
- return (NULL);
- }
- tp += strlen(tp);
- break;
- }
- tp += snprintf(tp, 5, "%lx", words[i]);
- }
-
- /* Was it a trailing run of 0x00's?
- */
- if(best.base != -1 && (best.base + best.len) == (IN6ADDRSZ / INT16SZ))
- *tp++ = ':';
- *tp++ = '\0';
-
- /* Check for overflow, copy, and we're done.
- */
- if((size_t)(tp - tmp) > size)
- {
- SET_ERRNO(ENOSPC);
- return (NULL);
- }
- strcpy(dst, tmp);
- return dst;
-}
-#endif /* ENABLE_IPV6 */
-
-/*
- * Convert a network format address to presentation format.
- *
- * Returns pointer to presentation format address (`buf').
- * Returns NULL on error and errno set with the specific
- * error, EAFNOSUPPORT or ENOSPC.
- *
- * On Windows we store the error in the thread errno, not
- * in the winsock error code. This is to avoid loosing the
- * actual last winsock error. So use macro ERRNO to fetch the
- * errno this funtion sets when returning NULL, not SOCKERRNO.
- */
-char *inet_ntop(int af, const void *src, char *buf, size_t size)
-{
- switch (af) {
- case AF_INET:
- return inet_ntop4((const unsigned char*)src, buf, size);
-#ifdef ENABLE_IPV6
- case AF_INET6:
- return inet_ntop6((const unsigned char*)src, buf, size);
-#endif
- default:
- SET_ERRNO(EAFNOSUPPORT);
- return NULL;
- }
-}
diff --git a/drivers/cc3000/src/inet_pton.c b/drivers/cc3000/src/inet_pton.c
deleted file mode 100644
index 5f5ae5f9d7f1..000000000000
--- a/drivers/cc3000/src/inet_pton.c
+++ /dev/null
@@ -1,216 +0,0 @@
-/* This is from the BIND 4.9.4 release, modified to compile by itself */
-
-/* Copyright (c) 1996 by Internet Software Consortium.
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
- * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
- * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
- * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
- * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
- * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
- * SOFTWARE.
- */
-
-#include
-#include "cc3000_common.h"
-#include "socket.h"
-#include "inet_pton.h"
-
-#define IN6ADDRSZ 16
-#define INADDRSZ 4
-#define INT16SZ 2
-
-static int inet_pton4(const char *src, unsigned char *dst);
-#ifdef ENABLE_IPV6
-static int inet_pton6(const char *src, unsigned char *dst);
-#endif
-
-#define EAFNOSUPPORT (106)
-#define SET_ERRNO(err) (CC3000_EXPORT(errno)=-err)
-
-/* int
- * inet_pton(af, src, dst)
- * convert from presentation format (which usually means ASCII printable)
- * to network format (which is usually some kind of binary format).
- * return:
- * 1 if the address was valid for the specified address family
- * 0 if the address wasn't valid (`dst' is untouched in this case)
- * -1 if some other error occurred (`dst' is untouched in this case, too)
- * notice:
- * On Windows we store the error in the thread errno, not
- * in the winsock error code. This is to avoid loosing the
- * actual last winsock error. So use macro ERRNO to fetch the
- * errno this funtion sets when returning (-1), not SOCKERRNO.
- * author:
- * Paul Vixie, 1996.
- */
-int inet_pton(int af, const char *src, void *dst)
-{
- switch (af) {
- case AF_INET:
- return (inet_pton4(src, (unsigned char *)dst));
-#ifdef ENABLE_IPV6
- case AF_INET6:
- return (inet_pton6(src, (unsigned char *)dst));
-#endif
- default:
- SET_ERRNO(EAFNOSUPPORT);
- return (-1);
- }
- /* NOTREACHED */
-}
-
-/* int
- * inet_pton4(src, dst)
- * like inet_aton() but without all the hexadecimal and shorthand.
- * return:
- * 1 if `src' is a valid dotted quad, else 0.
- * notice:
- * does not touch `dst' unless it's returning 1.
- * author:
- * Paul Vixie, 1996.
- */
-static int inet_pton4(const char *src, unsigned char *dst)
-{
- static const char digits[] = "0123456789";
- int saw_digit, octets, ch;
- unsigned char tmp[INADDRSZ], *tp;
-
- saw_digit = 0;
- octets = 0;
- tp = tmp;
- *tp = 0;
- while((ch = *src++) != '\0') {
- const char *pch;
-
- if((pch = strchr(digits, ch)) != NULL) {
- unsigned int val = *tp * 10 + (unsigned int)(pch - digits);
-
- if(saw_digit && *tp == 0)
- return (0);
- if(val > 255)
- return (0);
- *tp = (unsigned char)val;
- if(! saw_digit) {
- if(++octets > 4)
- return (0);
- saw_digit = 1;
- }
- }
- else if(ch == '.' && saw_digit) {
- if(octets == 4)
- return (0);
- *++tp = 0;
- saw_digit = 0;
- }
- else
- return (0);
- }
- if(octets < 4)
- return (0);
- memcpy(dst, tmp, INADDRSZ);
- return (1);
-}
-
-#ifdef ENABLE_IPV6
-/* int
- * inet_pton6(src, dst)
- * convert presentation level address to network order binary form.
- * return:
- * 1 if `src' is a valid [RFC1884 2.2] address, else 0.
- * notice:
- * (1) does not touch `dst' unless it's returning 1.
- * (2) :: in a full address is silently ignored.
- * credit:
- * inspired by Mark Andrews.
- * author:
- * Paul Vixie, 1996.
- */
-static int inet_pton6(const char *src, unsigned char *dst)
-{
- static const char xdigits_l[] = "0123456789abcdef",
- xdigits_u[] = "0123456789ABCDEF";
- unsigned char tmp[IN6ADDRSZ], *tp, *endp, *colonp;
- const char *xdigits, *curtok;
- int ch, saw_xdigit;
- unsigned int val;
-
- memset((tp = tmp), 0, IN6ADDRSZ);
- endp = tp + IN6ADDRSZ;
- colonp = NULL;
- /* Leading :: requires some special handling. */
- if(*src == ':')
- if(*++src != ':')
- return (0);
- curtok = src;
- saw_xdigit = 0;
- val = 0;
- while((ch = *src++) != '\0') {
- const char *pch;
-
- if((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
- pch = strchr((xdigits = xdigits_u), ch);
- if(pch != NULL) {
- val <<= 4;
- val |= (pch - xdigits);
- if(++saw_xdigit > 4)
- return (0);
- continue;
- }
- if(ch == ':') {
- curtok = src;
- if(!saw_xdigit) {
- if(colonp)
- return (0);
- colonp = tp;
- continue;
- }
- if(tp + INT16SZ > endp)
- return (0);
- *tp++ = (unsigned char) (val >> 8) & 0xff;
- *tp++ = (unsigned char) val & 0xff;
- saw_xdigit = 0;
- val = 0;
- continue;
- }
- if(ch == '.' && ((tp + INADDRSZ) <= endp) &&
- inet_pton4(curtok, tp) > 0) {
- tp += INADDRSZ;
- saw_xdigit = 0;
- break; /* '\0' was seen by inet_pton4(). */
- }
- return (0);
- }
- if(saw_xdigit) {
- if(tp + INT16SZ > endp)
- return (0);
- *tp++ = (unsigned char) (val >> 8) & 0xff;
- *tp++ = (unsigned char) val & 0xff;
- }
- if(colonp != NULL) {
- /*
- * Since some memmove()'s erroneously fail to handle
- * overlapping regions, we'll do the shift by hand.
- */
- const long n = tp - colonp;
- long i;
-
- if(tp == endp)
- return (0);
- for (i = 1; i <= n; i++) {
- endp[- i] = colonp[n - i];
- colonp[n - i] = 0;
- }
- tp = endp;
- }
- if(tp != endp)
- return (0);
- memcpy(dst, tmp, IN6ADDRSZ);
- return (1);
-}
-#endif /* ENABLE_IPV6 */
diff --git a/drivers/cc3000/src/netapp.c b/drivers/cc3000/src/netapp.c
deleted file mode 100644
index a6f60feda0d4..000000000000
--- a/drivers/cc3000/src/netapp.c
+++ /dev/null
@@ -1,459 +0,0 @@
-/*****************************************************************************
-*
-* netapp.c - CC3000 Host Driver Implementation.
-* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
-*
-* 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 Texas Instruments Incorporated 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
-* OWNER 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.
-*
-*****************************************************************************/
-
-#include
-#include "netapp.h"
-#include "hci.h"
-#include "socket.h"
-#include "evnt_handler.h"
-#include "nvmem.h"
-
-#define MIN_TIMER_VAL_SECONDS 10
-#define MIN_TIMER_SET(t) if ((0 != t) && (t < MIN_TIMER_VAL_SECONDS)) \
- { \
- t = MIN_TIMER_VAL_SECONDS; \
- }
-
-
-#define NETAPP_DHCP_PARAMS_LEN (20)
-#define NETAPP_SET_TIMER_PARAMS_LEN (20)
-#define NETAPP_SET_DEBUG_LEVEL_PARAMS_LEN (4)
-#define NETAPP_PING_SEND_PARAMS_LEN (16)
-
-
-//*****************************************************************************
-//
-//! netapp_config_mac_adrress
-//!
-//! @param mac device mac address, 6 bytes. Saved: yes
-//!
-//! @return return on success 0, otherwise error.
-//!
-//! @brief Configure device MAC address and store it in NVMEM.
-//! The value of the MAC address configured through the API will
-//! be stored in CC3000 non volatile memory, thus preserved
-//! over resets.
-//
-//*****************************************************************************
-INT32 netapp_config_mac_adrress(UINT8 * mac)
-{
- return nvmem_set_mac_address(mac);
-}
-
-//*****************************************************************************
-//
-//! netapp_dhcp
-//!
-//! @param aucIP device mac address, 6 bytes. Saved: yes
-//! @param aucSubnetMask device mac address, 6 bytes. Saved: yes
-//! @param aucDefaultGateway device mac address, 6 bytes. Saved: yes
-//! @param aucDNSServer device mac address, 6 bytes. Saved: yes
-//!
-//! @return return on success 0, otherwise error.
-//!
-//! @brief netapp_dhcp is used to configure the network interface,
-//! static or dynamic (DHCP).\n In order to activate DHCP mode,
-//! aucIP, aucSubnetMask, aucDefaultGateway must be 0.
-//! The default mode of CC3000 is DHCP mode.
-//! Note that the configuration is saved in non volatile memory
-//! and thus preserved over resets.
-//!
-//! @note If the mode is altered a reset of CC3000 device is required
-//! in order to apply changes.\nAlso note that asynchronous event
-//! of DHCP_EVENT, which is generated when an IP address is
-//! allocated either by the DHCP server or due to static
-//! allocation is generated only upon a connection to the
-//! AP was established.
-//!
-//*****************************************************************************
-INT32 netapp_dhcp(UINT32 *aucIP, UINT32 *aucSubnetMask,UINT32 *aucDefaultGateway, UINT32 *aucDNSServer)
-{
- INT8 scRet;
- UINT8 *ptr;
- UINT8 *args;
-
- scRet = EFAIL;
- ptr = tSLInformation.pucTxCommandBuffer;
- args = (ptr + HEADERS_SIZE_CMD);
-
- // Fill in temporary command buffer
- ARRAY_TO_STREAM(args,aucIP,4);
- ARRAY_TO_STREAM(args,aucSubnetMask,4);
- ARRAY_TO_STREAM(args,aucDefaultGateway,4);
- args = UINT32_TO_STREAM(args, 0);
- ARRAY_TO_STREAM(args,aucDNSServer,4);
-
- // Initiate a HCI command
- hci_command_send(HCI_NETAPP_DHCP, ptr, NETAPP_DHCP_PARAMS_LEN);
-
- // Wait for command complete event
- SimpleLinkWaitEvent(HCI_NETAPP_DHCP, &scRet);
-
- return(scRet);
-}
-
-
-//*****************************************************************************
-//
-//! netapp_timeout_values
-//!
-//! @param aucDHCP DHCP lease time request, also impact
-//! the DHCP renew timeout. Range: [0-0xffffffff] seconds,
-//! 0 or 0xffffffff == infinity lease timeout.
-//! Resolution:10 seconds. Influence: only after
-//! reconnecting to the AP.
-//! Minimal bound value: MIN_TIMER_VAL_SECONDS - 10 seconds.
-//! The parameter is saved into the CC3000 NVMEM.
-//! The default value on CC3000 is 14400 seconds.
-//!
-//! @param aucARP ARP refresh timeout, if ARP entry is not updated by
-//! incoming packet, the ARP entry will be deleted by
-//! the end of the timeout.
-//! Range: [0-0xffffffff] seconds, 0 == infinity ARP timeout
-//! Resolution: 10 seconds. Influence: on runtime.
-//! Minimal bound value: MIN_TIMER_VAL_SECONDS - 10 seconds
-//! The parameter is saved into the CC3000 NVMEM.
-//! The default value on CC3000 is 3600 seconds.
-//!
-//! @param aucKeepalive Keepalive event sent by the end of keepalive timeout
-//! Range: [0-0xffffffff] seconds, 0 == infinity timeout
-//! Resolution: 10 seconds.
-//! Influence: on runtime.
-//! Minimal bound value: MIN_TIMER_VAL_SECONDS - 10 sec
-//! The parameter is saved into the CC3000 NVMEM.
-//! The default value on CC3000 is 10 seconds.
-//!
-//! @param aucInactivity Socket inactivity timeout, socket timeout is
-//! refreshed by incoming or outgoing packet, by the
-//! end of the socket timeout the socket will be closed
-//! Range: [0-0xffffffff] sec, 0 == infinity timeout.
-//! Resolution: 10 seconds. Influence: on runtime.
-//! Minimal bound value: MIN_TIMER_VAL_SECONDS - 10 sec
-//! The parameter is saved into the CC3000 NVMEM.
-//! The default value on CC3000 is 60 seconds.
-//!
-//! @return return on success 0, otherwise error.
-//!
-//! @brief Set new timeout values. Function set new timeout values for:
-//! DHCP lease timeout, ARP refresh timeout, keepalive event
-//! timeout and socket inactivity timeout
-//!
-//! @note If a parameter set to non zero value which is less than 10s,
-//! it will be set automatically to 10s.
-//!
-//*****************************************************************************
-
-#ifndef CC3000_TINY_DRIVER
-INT32 netapp_timeout_values(UINT32 *aucDHCP, UINT32 *aucARP,UINT32 *aucKeepalive, UINT32 *aucInactivity)
-{
- INT8 scRet;
- UINT8 *ptr;
- UINT8 *args;
-
- scRet = EFAIL;
- ptr = tSLInformation.pucTxCommandBuffer;
- args = (ptr + HEADERS_SIZE_CMD);
-
- // Set minimal values of timers
- MIN_TIMER_SET(*aucDHCP)
- MIN_TIMER_SET(*aucARP)
- MIN_TIMER_SET(*aucKeepalive)
- MIN_TIMER_SET(*aucInactivity)
-
- // Fill in temporary command buffer
- args = UINT32_TO_STREAM(args, *aucDHCP);
- args = UINT32_TO_STREAM(args, *aucARP);
- args = UINT32_TO_STREAM(args, *aucKeepalive);
- args = UINT32_TO_STREAM(args, *aucInactivity);
-
- // Initiate a HCI command
- hci_command_send(HCI_NETAPP_SET_TIMERS, ptr, NETAPP_SET_TIMER_PARAMS_LEN);
-
- // Wait for command complete event
- SimpleLinkWaitEvent(HCI_NETAPP_SET_TIMERS, &scRet);
-
- return(scRet);
-}
-#endif
-
-
-//*****************************************************************************
-//
-//! netapp_ping_send
-//!
-//! @param ip destination IP address
-//! @param pingAttempts number of echo requests to send
-//! @param pingSize send buffer size which may be up to 1400 bytes
-//! @param pingTimeout Time to wait for a response,in milliseconds.
-//!
-//! @return return on success 0, otherwise error.
-//!
-//! @brief send ICMP ECHO_REQUEST to network hosts
-//!
-//! @note If an operation finished successfully asynchronous ping report
-//! event will be generated. The report structure is as defined
-//! by structure netapp_pingreport_args_t.
-//!
-//! @warning Calling this function while a previous Ping Requests are in
-//! progress will stop the previous ping request.
-//*****************************************************************************
-
-#ifndef CC3000_TINY_DRIVER
-INT32
- netapp_ping_send(UINT32 *ip, UINT32 ulPingAttempts, UINT32 ulPingSize, UINT32 ulPingTimeout)
-{
- INT8 scRet;
- UINT8 *ptr, *args;
-
- scRet = EFAIL;
- ptr = tSLInformation.pucTxCommandBuffer;
- args = (ptr + HEADERS_SIZE_CMD);
-
- // Fill in temporary command buffer
- args = UINT32_TO_STREAM(args, *ip);
- args = UINT32_TO_STREAM(args, ulPingAttempts);
- args = UINT32_TO_STREAM(args, ulPingSize);
- args = UINT32_TO_STREAM(args, ulPingTimeout);
-
- // Initiate a HCI command
- hci_command_send(HCI_NETAPP_PING_SEND, ptr, NETAPP_PING_SEND_PARAMS_LEN);
-
- // Wait for command complete event
- SimpleLinkWaitEvent(HCI_NETAPP_PING_SEND, &scRet);
-
- return(scRet);
-}
-#endif
-
-//*****************************************************************************
-//
-//! netapp_ping_report
-//!
-//! @param none
-//!
-//! @return none
-//!
-//! @brief Request for ping status. This API triggers the CC3000 to send
-//! asynchronous events: HCI_EVNT_WLAN_ASYNC_PING_REPORT.
-//! This event will carry the report structure:
-//! netapp_pingreport_args_t. This structure is filled in with ping
-//! results up till point of triggering API.
-//! netapp_pingreport_args_t:\n packets_sent - echo sent,
-//! packets_received - echo reply, min_round_time - minimum
-//! round time, max_round_time - max round time,
-//! avg_round_time - average round time
-//!
-//! @note When a ping operation is not active, the returned structure
-//! fields are 0.
-//!
-//*****************************************************************************
-
-
-#ifndef CC3000_TINY_DRIVER
-void netapp_ping_report()
-{
- UINT8 *ptr;
- ptr = tSLInformation.pucTxCommandBuffer;
- INT8 scRet;
-
- scRet = EFAIL;
-
- // Initiate a HCI command
- hci_command_send(HCI_NETAPP_PING_REPORT, ptr, 0);
-
- // Wait for command complete event
- SimpleLinkWaitEvent(HCI_NETAPP_PING_REPORT, &scRet);
-}
-#endif
-
-//*****************************************************************************
-//
-//! netapp_ping_stop
-//!
-//! @param none
-//!
-//! @return On success, zero is returned. On error, -1 is returned.
-//!
-//! @brief Stop any ping request.
-//!
-//!
-//*****************************************************************************
-
-#ifndef CC3000_TINY_DRIVER
-INT32 netapp_ping_stop()
-{
- INT8 scRet;
- UINT8 *ptr;
-
- scRet = EFAIL;
- ptr = tSLInformation.pucTxCommandBuffer;
-
- // Initiate a HCI command
- hci_command_send(HCI_NETAPP_PING_STOP, ptr, 0);
-
- // Wait for command complete event
- SimpleLinkWaitEvent(HCI_NETAPP_PING_STOP, &scRet);
-
- return(scRet);
-}
-#endif
-
-//*****************************************************************************
-//
-//! netapp_ipconfig
-//!
-//! @param[out] ipconfig This argument is a pointer to a
-//! tNetappIpconfigRetArgs structure. This structure is
-//! filled in with the network interface configuration.
-//! tNetappIpconfigRetArgs:\n aucIP - ip address,
-//! aucSubnetMask - mask, aucDefaultGateway - default
-//! gateway address, aucDHCPServer - dhcp server address
-//! aucDNSServer - dns server address, uaMacAddr - mac
-//! address, uaSSID - connected AP ssid
-//!
-//! @return none
-//!
-//! @brief Obtain the CC3000 Network interface information.
-//! Note that the information is available only after the WLAN
-//! connection was established. Calling this function before
-//! associated, will cause non-defined values to be returned.
-//!
-//! @note The function is useful for figuring out the IP Configuration of
-//! the device when DHCP is used and for figuring out the SSID of
-//! the Wireless network the device is associated with.
-//!
-//*****************************************************************************
-
-#ifndef CC3000_TINY_DRIVER
-void netapp_ipconfig( tNetappIpconfigRetArgs * ipconfig )
-{
- UINT8 *ptr;
-
- ptr = tSLInformation.pucTxCommandBuffer;
-
- // Initiate a HCI command
- hci_command_send(HCI_NETAPP_IPCONFIG, ptr, 0);
-
- // Wait for command complete event
- SimpleLinkWaitEvent(HCI_NETAPP_IPCONFIG, ipconfig );
-
-}
-#else
-void netapp_ipconfig( tNetappIpconfigRetArgs * ipconfig )
-{
-
-}
-#endif
-
-//*****************************************************************************
-//
-//! netapp_arp_flush
-//!
-//! @param none
-//!
-//! @return none
-//!
-//! @brief Flushes ARP table
-//!
-//*****************************************************************************
-
-#ifndef CC3000_TINY_DRIVER
-INT32 netapp_arp_flush(void)
-{
- INT8 scRet;
- UINT8 *ptr;
-
- scRet = EFAIL;
- ptr = tSLInformation.pucTxCommandBuffer;
-
- // Initiate a HCI command
- hci_command_send(HCI_NETAPP_ARP_FLUSH, ptr, 0);
-
- // Wait for command complete event
- SimpleLinkWaitEvent(HCI_NETAPP_ARP_FLUSH, &scRet);
-
- return(scRet);
-}
-#endif
-
-//*****************************************************************************
-//
-//! netapp_set_debug_level
-//!
-//! @param[in] level debug level. Bitwise [0-8],
-//! 0(disable)or 1(enable).\n Bitwise map: 0 - Critical
-//! message, 1 information message, 2 - core messages, 3 -
-//! HCI messages, 4 - Network stack messages, 5 - wlan
-//! messages, 6 - wlan driver messages, 7 - epprom messages,
-//! 8 - general messages. Default: 0x13f. Saved: no
-//!
-//! @return On success, zero is returned. On error, -1 is returned
-//!
-//! @brief Debug messages sent via the UART debug channel, this function
-//! enable/disable the debug level
-//!
-//*****************************************************************************
-
-
-#ifndef CC3000_TINY_DRIVER
-INT32 netapp_set_debug_level(UINT32 ulLevel)
-{
- INT8 scRet;
- UINT8 *ptr, *args;
-
- scRet = EFAIL;
- ptr = tSLInformation.pucTxCommandBuffer;
- args = (ptr + HEADERS_SIZE_CMD);
-
- //
- // Fill in temporary command buffer
- //
- args = UINT32_TO_STREAM(args, ulLevel);
-
-
- //
- // Initiate a HCI command
- //
- hci_command_send(HCI_NETAPP_SET_DEBUG_LEVEL, ptr, NETAPP_SET_DEBUG_LEVEL_PARAMS_LEN);
-
- //
- // Wait for command complete event
- //
- SimpleLinkWaitEvent(HCI_NETAPP_SET_DEBUG_LEVEL, &scRet);
-
- return(scRet);
-
-}
-#endif
diff --git a/drivers/cc3000/src/nvmem.c b/drivers/cc3000/src/nvmem.c
deleted file mode 100644
index c6e170a74650..000000000000
--- a/drivers/cc3000/src/nvmem.c
+++ /dev/null
@@ -1,334 +0,0 @@
-/*****************************************************************************
-*
-* nvmem.c - CC3000 Host Driver Implementation.
-* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
-*
-* 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 Texas Instruments Incorporated 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
-* OWNER 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.
-*
-*****************************************************************************/
-
-//*****************************************************************************
-//
-//! \addtogroup nvmem_api
-//! @{
-//
-//*****************************************************************************
-
-#include
-#include "nvmem.h"
-#include "hci.h"
-#include "socket.h"
-#include "evnt_handler.h"
-
-//*****************************************************************************
-//
-// Prototypes for the structures for APIs.
-//
-//*****************************************************************************
-
-#define NVMEM_READ_PARAMS_LEN (12)
-#define NVMEM_CREATE_PARAMS_LEN (8)
-#define NVMEM_WRITE_PARAMS_LEN (16)
-
-//*****************************************************************************
-//
-//! nvmem_read
-//!
-//! @param ulFileId nvmem file id:\n
-//! NVMEM_NVS_FILEID, NVMEM_NVS_SHADOW_FILEID,
-//! NVMEM_WLAN_CONFIG_FILEID, NVMEM_WLAN_CONFIG_SHADOW_FILEID,
-//! NVMEM_WLAN_DRIVER_SP_FILEID, NVMEM_WLAN_FW_SP_FILEID,
-//! NVMEM_MAC_FILEID, NVMEM_FRONTEND_VARS_FILEID,
-//! NVMEM_IP_CONFIG_FILEID, NVMEM_IP_CONFIG_SHADOW_FILEID,
-//! NVMEM_BOOTLOADER_SP_FILEID, NVMEM_RM_FILEID,
-//! and user files 12-15.
-//! @param ulLength number of bytes to read
-//! @param ulOffset ulOffset in file from where to read
-//! @param buff output buffer pointer
-//!
-//! @return on success 0, error otherwise.
-//!
-//! @brief Reads data from the file referred by the ulFileId parameter.
-//! Reads data from file ulOffset till length. Err if the file can't
-//! be used, is invalid, or if the read is out of bounds.
-//!
-//*****************************************************************************
-
-INT32 nvmem_read(UINT32 ulFileId, UINT32 ulLength, UINT32 ulOffset, UINT8 *buff)
-{
- UINT8 ucStatus = 0xFF;
- UINT8 *ptr;
- UINT8 *args;
-
- ptr = tSLInformation.pucTxCommandBuffer;
- args = (ptr + HEADERS_SIZE_CMD);
-
- // Fill in HCI packet structure
- args = UINT32_TO_STREAM(args, ulFileId);
- args = UINT32_TO_STREAM(args, ulLength);
- args = UINT32_TO_STREAM(args, ulOffset);
-
- // Initiate a HCI command
- hci_command_send(HCI_CMND_NVMEM_READ, ptr, NVMEM_READ_PARAMS_LEN);
- SimpleLinkWaitEvent(HCI_CMND_NVMEM_READ, &ucStatus);
-
- // In case there is data - read it - even if an error code is returned
- // Note: It is the user responsibility to ignore the data in case of an error code
-
- // Wait for the data in a synchronous way. Here we assume that the buffer is
- // big enough to store also parameters of nvmem
-
- SimpleLinkWaitData(buff, 0, 0);
-
- return(ucStatus);
-}
-
-//*****************************************************************************
-//
-//! nvmem_write
-//!
-//! @param ulFileId nvmem file id:\n
-//! NVMEM_WLAN_DRIVER_SP_FILEID, NVMEM_WLAN_FW_SP_FILEID,
-//! NVMEM_MAC_FILEID, NVMEM_BOOTLOADER_SP_FILEID,
-//! and user files 12-15.
-//! @param ulLength number of bytes to write
-//! @param ulEntryOffset offset in file to start write operation from
-//! @param buff data to write
-//!
-//! @return on success 0, error otherwise.
-//!
-//! @brief Write data to nvmem.
-//! writes data to file referred by the ulFileId parameter.
-//! Writes data to file ulOffset till ulLength.The file id will be
-//! marked invalid till the write is done. The file entry doesn't
-//! need to be valid - only allocated.
-//!
-//*****************************************************************************
-
-INT32 nvmem_write(UINT32 ulFileId, UINT32 ulLength, UINT32 ulEntryOffset, UINT8 *buff)
-{
- INT32 iRes;
- UINT8 *ptr;
- UINT8 *args;
-
- iRes = EFAIL;
-
- ptr = tSLInformation.pucTxCommandBuffer;
- args = (ptr + SPI_HEADER_SIZE + HCI_DATA_CMD_HEADER_SIZE);
-
- // Fill in HCI packet structure
- args = UINT32_TO_STREAM(args, ulFileId);
- args = UINT32_TO_STREAM(args, 12);
- args = UINT32_TO_STREAM(args, ulLength);
- args = UINT32_TO_STREAM(args, ulEntryOffset);
-
- memcpy((ptr + SPI_HEADER_SIZE + HCI_DATA_CMD_HEADER_SIZE +
- NVMEM_WRITE_PARAMS_LEN),buff,ulLength);
-
- // Initiate a HCI command but it will come on data channel
- hci_data_command_send(HCI_CMND_NVMEM_WRITE, ptr, NVMEM_WRITE_PARAMS_LEN,
- ulLength);
-
- SimpleLinkWaitEvent(HCI_EVNT_NVMEM_WRITE, &iRes);
-
- return(iRes);
-}
-
-
-//*****************************************************************************
-//
-//! nvmem_set_mac_address
-//!
-//! @param mac mac address to be set
-//!
-//! @return on success 0, error otherwise.
-//!
-//! @brief Write MAC address to EEPROM.
-//! mac address as appears over the air (OUI first)
-//!
-//*****************************************************************************
-
-UINT8 nvmem_set_mac_address(UINT8 *mac)
-{
- return nvmem_write(NVMEM_MAC_FILEID, MAC_ADDR_LEN, 0, mac);
-}
-
-//*****************************************************************************
-//
-//! nvmem_get_mac_address
-//!
-//! @param[out] mac mac address
-//!
-//! @return on success 0, error otherwise.
-//!
-//! @brief Read MAC address from EEPROM.
-//! mac address as appears over the air (OUI first)
-//!
-//*****************************************************************************
-
-UINT8 nvmem_get_mac_address(UINT8 *mac)
-{
- return nvmem_read(NVMEM_MAC_FILEID, MAC_ADDR_LEN, 0, mac);
-}
-
-//*****************************************************************************
-//
-//! nvmem_write_patch
-//!
-//! @param ulFileId nvmem file id:\n
-//! NVMEM_WLAN_DRIVER_SP_FILEID, NVMEM_WLAN_FW_SP_FILEID,
-//! @param spLength number of bytes to write
-//! @param spData SP data to write
-//!
-//! @return on success 0, error otherwise.
-//!
-//! @brief program a patch to a specific file ID.
-//! The SP data is assumed to be organized in 2-dimensional.
-//! Each line is SP_PORTION_SIZE bytes long. Actual programming is
-//! applied in SP_PORTION_SIZE bytes portions.
-//!
-//*****************************************************************************
-
-UINT8 nvmem_write_patch(UINT32 ulFileId, UINT32 spLength, const UINT8 *spData)
-{
- UINT8 status = 0;
- UINT16 offset = 0;
- UINT8* spDataPtr = (UINT8*)spData;
-
- while ((status == 0) && (spLength >= SP_PORTION_SIZE))
- {
- status = nvmem_write(ulFileId, SP_PORTION_SIZE, offset, spDataPtr);
- offset += SP_PORTION_SIZE;
- spLength -= SP_PORTION_SIZE;
- spDataPtr += SP_PORTION_SIZE;
- }
-
- if (status !=0)
- {
- // NVMEM error occurred
- return status;
- }
-
- if (spLength != 0)
- {
- // if reached here, a reminder is left
- status = nvmem_write(ulFileId, spLength, offset, spDataPtr);
- }
-
- return status;
-}
-
-//*****************************************************************************
-//
-//! nvmem_read_sp_version
-//!
-//! @param[out] patchVer first number indicates package ID and the second
-//! number indicates package build number
-//!
-//! @return on success 0, error otherwise.
-//!
-//! @brief Read patch version. read package version (WiFi FW patch,
-//! driver-supplicant-NS patch, bootloader patch)
-//!
-//*****************************************************************************
-
-#ifndef CC3000_TINY_DRIVER
-UINT8 nvmem_read_sp_version(UINT8* patchVer)
-{
- UINT8 *ptr;
- // 1st byte is the status and the rest is the SP version
- UINT8 retBuf[5];
-
- ptr = tSLInformation.pucTxCommandBuffer;
-
- // Initiate a HCI command, no args are required
- hci_command_send(HCI_CMND_READ_SP_VERSION, ptr, 0);
- SimpleLinkWaitEvent(HCI_CMND_READ_SP_VERSION, retBuf);
-
- // package ID
- *patchVer = retBuf[3];
- // package build number
- *(patchVer+1) = retBuf[4];
-
- return(retBuf[0]);
-}
-#endif
-
-//*****************************************************************************
-//
-//! nvmem_create_entry
-//!
-//! @param ulFileId nvmem file Id:\n
-//! * NVMEM_AES128_KEY_FILEID: 12
-//! * NVMEM_SHARED_MEM_FILEID: 13
-//! * and fileIDs 14 and 15
-//! @param ulNewLen entry ulLength
-//!
-//! @return on success 0, error otherwise.
-//!
-//! @brief Create new file entry and allocate space on the NVMEM.
-//! Applies only to user files.
-//! Modify the size of file.
-//! If the entry is unallocated - allocate it to size
-//! ulNewLen (marked invalid).
-//! If it is allocated then deallocate it first.
-//! To just mark the file as invalid without resizing -
-//! set ulNewLen=0.
-//!
-//*****************************************************************************
-
-INT32 nvmem_create_entry(UINT32 ulFileId, UINT32 ulNewLen)
-{
- UINT8 *ptr;
- UINT8 *args;
- UINT8 retval;
-
- ptr = tSLInformation.pucTxCommandBuffer;
- args = (ptr + HEADERS_SIZE_CMD);
-
- // Fill in HCI packet structure
- args = UINT32_TO_STREAM(args, ulFileId);
- args = UINT32_TO_STREAM(args, ulNewLen);
-
- // Initiate a HCI command
- hci_command_send(HCI_CMND_NVMEM_CREATE_ENTRY,ptr, NVMEM_CREATE_PARAMS_LEN);
-
- SimpleLinkWaitEvent(HCI_CMND_NVMEM_CREATE_ENTRY, &retval);
-
- return(retval);
-}
-
-
-
-//*****************************************************************************
-//
-// Close the Doxygen group.
-//! @}
-//
-//*****************************************************************************
diff --git a/drivers/cc3000/src/patch.c b/drivers/cc3000/src/patch.c
deleted file mode 100644
index 227be3c9f2a3..000000000000
--- a/drivers/cc3000/src/patch.c
+++ /dev/null
@@ -1,117 +0,0 @@
-/*****************************************************************************
- *
- * {PatchProgrammer_DR_Patch.c}
- *
- * Burn Patches to EEPROM
- *
- * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
- * ALL RIGHTS RESERVED
- *
- *****************************************************************************/
-//
-// Service Pack version P1.13.7.15.28 - Driver patches
-// This file contains the CC3K driver and firmware patches
-// From CC3000-FRAM-PATCH V:1.13.7 15-MAY-2014
-
-unsigned short fw_length = 5700;
-unsigned short drv_length = 8024;
-
-const unsigned char wlan_drv_patch[8024] = { 0x00, 0x01, 0x00, 0x00, 0x50, 0x1F, 0x00, 0x00, 0xF0, 0x03, 0x18, 0x00, 0xE4, 0x62, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x7A, 0x63, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x10, 0x64, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x20, 0x0C, 0x49, 0x08, 0x60, 0x0C, 0x48, 0x19, 0x30, 0xF7, 0x46, 0x30, 0xB5, 0x05, 0x1C, 0xAC, 0x69, 0x68, 0x68, 0x5F, 0x30, 0x09, 0xD1, 0x60, 0x6B, 0x0C, 0x38, 0x01, 0x21, 0x8E, 0x46, 0x06, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x00, 0x20, 0x60, 0x63, 0xAC, 0x69, 0x6C, 0x60, 0x04, 0x48, 0x5B, 0x30, 0x30, 0xBD, 0x40, 0x3B, 0x08, 0x00, 0x49, 0xD0, 0x01, 0x00, 0x09, 0xEA, 0x02, 0x00, 0x91, 0xE1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xA6, 0x64, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3C, 0x65, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xB5, 0x85, 0xB0, 0x05, 0x1C, 0xA8, 0x88, 0x00, 0x90, 0x28, 0x89, 0x01, 0x90, 0xE9, 0x68, 0x02, 0x91, 0x28, 0x7C, 0x03, 0x90, 0x2A, 0x6A, 0x00, 0x20, 0x17, 0x56, 0x68, 0x60, 0x00, 0x29, 0x4C, 0xD0, 0x00, 0x2F, 0x4A, 0xDC ,
-0xCA, 0x49, 0x0C, 0x1C, 0x08, 0x26, 0x04, 0x90, 0x21, 0x88, 0x00, 0x98, 0x81, 0x42, 0x0C, 0xD1, 0x62, 0x88, 0x01, 0x98, 0x82, 0x42, 0x08, 0xD1, 0x46, 0x20, 0x02, 0x5D, 0x03, 0x98, 0x82, 0x42, 0x03, 0xD1, 0x0E, 0x20, 0x00, 0x57, 0xB8, 0x42, 0x0A, 0xD0, 0x46, 0x20, 0x00, 0x5D, 0x11, 0x28, 0x22, 0xD1, 0x00, 0x98, 0x81, 0x42, 0x1F, 0xD1, 0x0E, 0x20, 0x00, 0x57, 0xFF, 0xFF, 0xD2, 0x65, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0xB8, 0x42, 0x1B, 0xD1, 0x04, 0x20, 0x02, 0x1C, 0x02, 0x98, 0xB9, 0x49, 0x01, 0x23, 0x9E, 0x46, 0xEC, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x00, 0x28, 0x17, 0xD0, 0x20, 0x1D, 0x02, 0x99, 0x04, 0x22, 0x01, 0x23, 0x9E, 0x46, 0xE7, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x00, 0x28, 0x0D, 0xD0, 0x46, 0x20, 0x00, 0x5D, 0x11, 0x28, 0x09, 0xD0, 0xA0, 0x6D, 0x00, 0x28, 0x06, 0xD0, 0xAC, 0x34, 0x04, 0x98, 0x01, 0x30, 0x04, 0x90, 0x01, 0x3E, 0xC1, 0xD1, 0x07, 0xE0, 0x04, 0x98, 0x00, 0x06, 0x00, 0x0E ,
-0xAC, 0x21, 0x41, 0x43, 0xA6, 0x48, 0x40, 0x18, 0x68, 0x60, 0xA6, 0x48, 0xAD, 0x30, 0x05, 0xB0, 0xF0, 0xBD, 0x00, 0xB5, 0xC2, 0x68, 0x90, 0x69, 0x02, 0x21, 0x01, 0x23, 0x9E, 0x46, 0xA2, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0xA2, 0x48, 0x61, 0x30, 0x00, 0xBD, 0x01, 0x79, 0x0B, 0x29, 0x03, 0xD0, 0x89, 0x00, 0x9F, 0x4A, 0x51, 0x5A, 0x01, 0xE0, 0x01, 0x21, 0x49, 0x02, 0x41, 0x60, 0x9D, 0x48, 0x0D, 0x30, 0xF7, 0x46, 0x01, 0x1C, 0xFF, 0xFF, 0x68, 0x66, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x9C, 0x48, 0x02, 0x68, 0x9C, 0x48, 0x01, 0x2A, 0x01, 0xD1, 0x25, 0x30, 0xF7, 0x46, 0x9B, 0x4A, 0x12, 0x68, 0x4A, 0x60, 0x19, 0x30, 0xF7, 0x46, 0x00, 0x21, 0x41, 0x60, 0x99, 0x48, 0x98, 0x49, 0x08, 0x18, 0xF7, 0x46, 0x00, 0x21, 0x41, 0x60, 0x97, 0x48, 0xE7, 0x49, 0x08, 0x18, 0xF7, 0x46, 0xFF, 0xB5, 0x46, 0x69, 0x40, 0x68, 0x01, 0x90, 0x94, 0x49, 0x0A, 0x7C, 0x9A, 0x4F, 0x01, 0x2A, 0x63, 0xD0, 0x09, 0x7C, 0x03, 0x29 ,
-0x60, 0xD0, 0x91, 0x4A, 0x92, 0x4B, 0x00, 0x21, 0x02, 0x91, 0x59, 0x56, 0x24, 0x23, 0x59, 0x43, 0x53, 0x18, 0x03, 0x93, 0x01, 0x28, 0x17, 0xD1, 0x8A, 0x18, 0x04, 0x23, 0x6C, 0x46, 0x8C, 0x49, 0x15, 0x79, 0x08, 0x78, 0xC0, 0x43, 0x28, 0x43, 0x20, 0x70, 0x01, 0x32, 0x01, 0x31, 0x01, 0x34, 0x01, 0x3B, 0xF5, 0xD1, 0x31, 0x1D, 0x68, 0x46, 0x04, 0x22, 0x01, 0x23, 0x9E, 0x46, 0xA9, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x00, 0x28, 0x40, 0xD0, 0x35, 0x1D, 0x82, 0x48, 0x00, 0x78, 0xFF, 0x28, 0xFF, 0xFF, 0xFE, 0x66, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x11, 0xD0, 0x00, 0x28, 0x0F, 0xD0, 0x03, 0x98, 0x01, 0x1D, 0x28, 0x1C, 0x01, 0x24, 0xA6, 0x46, 0x7E, 0x4A, 0xFE, 0x44, 0x10, 0x47, 0x00, 0x28, 0x05, 0xD1, 0x7A, 0x48, 0xA6, 0x46, 0x7B, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x05, 0xE0, 0x28, 0x1C, 0x01, 0x21, 0x8E, 0x46, 0x78, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x01, 0x99, 0x01, 0x29, 0x01, 0xD1, 0x00, 0x28, 0x1E, 0xD1 ,
-0x01, 0x99, 0x5F, 0x31, 0x01, 0xD0, 0x00, 0x28, 0x0F, 0xD1, 0xA8, 0x20, 0x81, 0x5D, 0x00, 0x29, 0x08, 0xD0, 0x49, 0x1E, 0x81, 0x55, 0x80, 0x5D, 0x00, 0x28, 0x09, 0xD1, 0x38, 0x1C, 0xFF, 0x30, 0x08, 0x30, 0x11, 0xE0, 0x03, 0x21, 0x02, 0x91, 0x00, 0xE0, 0xA8, 0x20, 0x02, 0x99, 0x81, 0x55, 0x38, 0x1C, 0xFF, 0x30, 0x16, 0x30, 0x07, 0xE0, 0x01, 0x98, 0x01, 0x28, 0x02, 0xD1, 0x38, 0x1C, 0xA3, 0x30, 0x01, 0xE0, 0x38, 0x1C, 0x9F, 0x30, 0x00, 0x90, 0xFF, 0xBD, 0x00, 0xB5, 0x02, 0x1C, 0x10, 0x6A, 0xD1, 0x69, 0x52, 0x69, 0xC3, 0x69, 0x5A, 0x60, 0xFF, 0xFF, 0x94, 0x67, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x01, 0x22, 0x96, 0x46, 0x5E, 0x4A, 0xFE, 0x44, 0x10, 0x47, 0x5E, 0x48, 0xFF, 0x30, 0x6E, 0x30, 0x00, 0xBD, 0x10, 0xB5, 0x0A, 0x1C, 0x41, 0x69, 0x00, 0x6A, 0x93, 0x69, 0xDB, 0x69, 0x58, 0x60, 0x90, 0x69, 0x01, 0x24, 0xA6, 0x46, 0x56, 0x4A, 0xFE, 0x44, 0x10, 0x47, 0xA6, 0x46, 0x56, 0x48, 0xFE, 0x44 ,
-0x00, 0x47, 0x55, 0x48, 0xFF, 0x30, 0xB6, 0x30, 0x10, 0xBD, 0x70, 0xB5, 0x05, 0x1C, 0x6E, 0x69, 0x53, 0x48, 0x02, 0x68, 0x5C, 0x21, 0x88, 0x5D, 0x04, 0x28, 0x15, 0xD1, 0x07, 0x20, 0x88, 0x55, 0x10, 0x0B, 0x11, 0xD2, 0x01, 0x24, 0xA6, 0x46, 0x4E, 0x48, 0xFE, 0x44, 0x00, 0x47, 0x00, 0x28, 0x0A, 0xD0, 0x47, 0x21, 0x89, 0x57, 0xC1, 0x60, 0x11, 0x21, 0xC9, 0x02, 0x00, 0x22, 0x04, 0x23, 0xA6, 0x46, 0xE8, 0x4C, 0xFE, 0x44, 0x20, 0x47, 0x01, 0x20, 0x68, 0x60, 0x43, 0x48, 0xED, 0x49, 0x08, 0x18, 0x70, 0xBD, 0x70, 0xB5, 0x05, 0x1C, 0xAE, 0x69, 0x9C, 0x20, 0x80, 0x19, 0x4B, 0x21, 0x89, 0x00, 0x01, 0x24, 0xFF, 0xFF, 0x2A, 0x68, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0xA6, 0x46, 0xE8, 0x4A, 0xFE, 0x44, 0x10, 0x47, 0x5C, 0x21, 0x88, 0x5D, 0x07, 0x28, 0x01, 0xD1, 0x09, 0x20, 0x00, 0xE0, 0x05, 0x20, 0xAA, 0x69, 0x88, 0x54, 0x30, 0x1C, 0xA6, 0x46, 0xE9, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x68, 0x60, 0xE8, 0x48 ,
-0x4D, 0x30, 0x70, 0xBD, 0xF0, 0xB5, 0x41, 0x68, 0x82, 0x68, 0x88, 0x23, 0x5E, 0x18, 0x37, 0x88, 0x0B, 0x6F, 0x00, 0x2B, 0x01, 0xD1, 0x00, 0x2F, 0x10, 0xD1, 0x06, 0x2F, 0x02, 0xDD, 0x00, 0x21, 0xC9, 0x43, 0x07, 0xE0, 0x33, 0x88, 0x9B, 0x00, 0xC9, 0x18, 0x0A, 0x67, 0x31, 0x88, 0x01, 0x31, 0x31, 0x80, 0x01, 0x21, 0x81, 0x60, 0xE1, 0x48, 0x1D, 0x30, 0xF0, 0xBD, 0x0B, 0x1C, 0x01, 0x24, 0x5D, 0x6F, 0x1D, 0x67, 0x04, 0x33, 0x01, 0x34, 0x06, 0x2C, 0xE1, 0xDA, 0xF8, 0xE7, 0x00, 0xB5, 0x00, 0x21, 0xC1, 0x60, 0xE9, 0x48, 0x01, 0x68, 0x10, 0x31, 0xE6, 0x48, 0x20, 0x22, 0x01, 0x23, 0x9E, 0x46, 0xE7, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0xE5, 0x48, 0xFB, 0x30, 0x00, 0xBD, 0xFF, 0xFF, 0xC0, 0x68, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x14, 0x0D, 0x1B, 0x00, 0x54, 0x19, 0x1B, 0x00, 0x91, 0x1A, 0x01, 0x00, 0x4B, 0xAD, 0x03, 0x00, 0x61, 0x4E, 0x01, 0x00, 0x06, 0x32, 0x08, 0x00, 0x1F, 0x0B, 0x02, 0x00, 0x54, 0x3F ,
-0x08, 0x00, 0x45, 0xC1, 0x00, 0x00, 0x84, 0x3C, 0x08, 0x00, 0x1B, 0x02, 0x00, 0x00, 0xED, 0x17, 0x00, 0x00, 0xF3, 0xC1, 0x01, 0x00, 0x34, 0x19, 0x1B, 0x00, 0x08, 0x19, 0x1B, 0x00, 0xA6, 0x44, 0x08, 0x00, 0x1C, 0x17, 0x1B, 0x00, 0x18, 0x17, 0x1B, 0x00, 0xCB, 0x67, 0x03, 0x00, 0x0D, 0x47, 0x02, 0x00, 0x39, 0x42, 0x03, 0x00, 0xBD, 0xE7, 0x02, 0x00, 0xB1, 0x40, 0x03, 0x00, 0xB9, 0xEA, 0x01, 0x00, 0x45, 0xDA, 0x00, 0x00, 0x24, 0x41, 0x08, 0x00, 0x71, 0xC0, 0x02, 0x00, 0xF0, 0xB5, 0x88, 0xB0, 0x06, 0x91, 0x07, 0x90, 0x86, 0x69, 0xF0, 0x1C, 0xD9, 0xA1, 0x04, 0x22, 0x01, 0x24, 0xA6, 0x46, 0x14, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x00, 0x28, 0x32, 0xD1, 0xF2, 0x79, 0xD7, 0x48, 0x02, 0x70, 0x35, 0x7A, 0x77, 0x7A, 0x78, 0x1B, 0xFF, 0xFF, 0x56, 0x69, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x43, 0x1C, 0x93, 0x42, 0x1D, 0xD0, 0x16, 0x2A, 0x0C, 0xDB, 0x00, 0x2D, 0x0A, 0xD1, 0xD6, 0x48, 0x04, 0x70, 0x0A, 0x20 ,
-0x81, 0x19, 0xD0, 0x48, 0x1A, 0x1C, 0xA6, 0x46, 0xB8, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x74, 0xE0, 0xD2, 0x48, 0x04, 0x70, 0xCC, 0x48, 0x40, 0x19, 0x0A, 0x21, 0x89, 0x19, 0x7A, 0x1B, 0x52, 0x1C, 0xA6, 0x46, 0xB1, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x67, 0xE0, 0x8F, 0xC6, 0x03, 0x00, 0xC9, 0x48, 0x04, 0x70, 0xC9, 0x48, 0x04, 0x70, 0x0A, 0x20, 0x81, 0x19, 0xC2, 0x48, 0xA6, 0x46, 0xAA, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x59, 0xE0, 0xF0, 0x1C, 0x03, 0x21, 0x0A, 0x1C, 0xBC, 0xA1, 0xA6, 0x46, 0xC6, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x00, 0x28, 0x4F, 0xD1, 0xF1, 0x79, 0xBB, 0x48, 0x01, 0x70, 0xBB, 0x4D, 0xB2, 0x79, 0x2A, 0x70, 0x03, 0x20, 0x17, 0x49, 0xF4, 0x31, 0xA6, 0x46, 0xB8, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x28, 0x78, 0x00, 0x28, 0x0B, 0xD1, 0xFF, 0xE7, 0xB8, 0x49, 0x0C, 0x70, 0xB8, 0x49, 0xFF, 0xFF, 0xEC, 0x69, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x0C, 0x70, 0x03, 0x20, 0x0F, 0x49, 0xF5, 0x31, 0xA6, 0x46 ,
-0xB6, 0x4A, 0xFE, 0x44, 0x10, 0x47, 0x20, 0x1C, 0xF2, 0x79, 0x35, 0x7A, 0x77, 0x7A, 0x79, 0x1B, 0x4B, 0x1C, 0x93, 0x42, 0x20, 0xD0, 0xA9, 0x49, 0x09, 0x78, 0x16, 0x29, 0x0F, 0xDB, 0x00, 0x2D, 0x0D, 0xD1, 0xAB, 0x49, 0x08, 0x70, 0x0A, 0x20, 0x81, 0x19, 0xE9, 0x48, 0x1A, 0x1C, 0xA6, 0x46, 0x8B, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x1A, 0xE0, 0xC0, 0x46, 0xC7, 0x04, 0x00, 0x00, 0xA5, 0x49, 0x08, 0x70, 0xE3, 0x48, 0x40, 0x19, 0x0A, 0x21, 0x89, 0x19, 0x7A, 0x1B, 0x52, 0x1C, 0xA6, 0x46, 0x83, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x0A, 0xE0, 0x9E, 0x49, 0x08, 0x70, 0x9E, 0x49, 0x08, 0x70, 0x0A, 0x20, 0x81, 0x19, 0xDB, 0x48, 0xA6, 0x46, 0x7D, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x96, 0x48, 0x00, 0x78, 0x00, 0x28, 0x0A, 0xD0, 0x95, 0x48, 0x00, 0x78, 0x00, 0x28, 0x06, 0xD0, 0x94, 0x48, 0x00, 0x78, 0x00, 0x28, 0x02, 0xD0, 0x93, 0x48, 0x00, 0x78, 0x00, 0x28, 0xFF, 0xFF, 0x82, 0x6A, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00 ,
-0x00, 0xD1, 0x8C, 0xE0, 0x03, 0x20, 0x17, 0x21, 0x89, 0x01, 0xA6, 0x46, 0x90, 0x4A, 0xFE, 0x44, 0x10, 0x47, 0x87, 0x48, 0x01, 0x78, 0x87, 0x48, 0x07, 0x78, 0x84, 0x4E, 0x83, 0x4D, 0xE0, 0x48, 0x00, 0x68, 0x00, 0x28, 0x2E, 0xD1, 0x07, 0x98, 0x41, 0x61, 0x06, 0x62, 0xC6, 0x48, 0x06, 0x9A, 0x10, 0x64, 0x02, 0x2F, 0x01, 0xD0, 0x03, 0x2F, 0x01, 0xD1, 0x03, 0x22, 0x00, 0xE0, 0x3A, 0x1C, 0x06, 0x9B, 0xDA, 0x63, 0x2A, 0x78, 0x9A, 0x63, 0x01, 0x2F, 0x03, 0xD1, 0x05, 0x29, 0x04, 0xD0, 0x0D, 0x29, 0x02, 0xD0, 0xEC, 0x48, 0xDB, 0x30, 0x64, 0xE0, 0x00, 0x25, 0x00, 0x95, 0x01, 0x91, 0x02, 0x96, 0x03, 0x95, 0x04, 0x90, 0x2B, 0x1C, 0x20, 0x1C, 0x01, 0x1C, 0x8E, 0x46, 0xE6, 0x4E, 0xFE, 0x44, 0x30, 0x47, 0xE6, 0x48, 0x04, 0x60, 0x28, 0x1C, 0xA6, 0x46, 0xE5, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x4C, 0xE0, 0x0D, 0x27, 0x00, 0x20, 0x39, 0x1C, 0x05, 0xAA, 0xA6, 0x46, 0xE3, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x68, 0x46 ,
-0xFF, 0xFF, 0x18, 0x6B, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x80, 0x8A, 0x40, 0x08, 0x05, 0xD2, 0x38, 0x1C, 0x50, 0x21, 0xA6, 0x46, 0xDC, 0x4A, 0xFE, 0x44, 0x10, 0x47, 0x38, 0x1C, 0x21, 0x1C, 0x0B, 0x1C, 0x29, 0x1C, 0x00, 0x22, 0xA6, 0x46, 0xD9, 0x4F, 0xFE, 0x44, 0x38, 0x47, 0x2B, 0x78, 0x0D, 0x20, 0x31, 0x1C, 0x22, 0x1C, 0xA6, 0x46, 0xD5, 0x4E, 0xFE, 0x44, 0x30, 0x47, 0x28, 0x78, 0x01, 0x30, 0x02, 0x1C, 0x0D, 0x20, 0x57, 0x49, 0x23, 0x1C, 0xA6, 0x46, 0xD0, 0x4E, 0xFE, 0x44, 0x30, 0x47, 0x55, 0x4E, 0x28, 0x78, 0x02, 0x30, 0x02, 0x1C, 0x0D, 0x20, 0x31, 0x1C, 0x23, 0x1C, 0xA6, 0x46, 0xCA, 0x4F, 0xFE, 0x44, 0x38, 0x47, 0x30, 0x78, 0x00, 0x28, 0x0A, 0xD0, 0x28, 0x78, 0x03, 0x30, 0x02, 0x1C, 0x4C, 0x48, 0x03, 0x78, 0x0D, 0x20, 0x8F, 0x49, 0xA6, 0x46, 0xC3, 0x4D, 0xFE, 0x44, 0x28, 0x47, 0xBF, 0x48, 0x04, 0x60, 0x00, 0x20, 0xA6, 0x46, 0xBE, 0x49, 0xFE, 0x44, 0x08, 0x47, 0xB9, 0x48, 0xEC, 0x49 ,
-0x08, 0x18, 0x08, 0xB0, 0xF0, 0xBD, 0xC0, 0x46, 0x7B, 0xC0, 0xFF, 0xFF, 0xAE, 0x6B, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x1C, 0xE9, 0x48, 0x02, 0x68, 0xE9, 0x48, 0x00, 0x2A, 0x04, 0xD0, 0x00, 0x22, 0x0A, 0x62, 0x8A, 0x61, 0x1D, 0x30, 0xF7, 0x46, 0xD7, 0x30, 0xF7, 0x46, 0xC0, 0x46, 0x9F, 0x03, 0x00, 0x00, 0x7D, 0xB8, 0x03, 0x00, 0x01, 0x1C, 0xE2, 0x48, 0x02, 0x68, 0xE2, 0x48, 0x00, 0x2A, 0x02, 0xD0, 0xFF, 0x30, 0xB4, 0x30, 0xF7, 0x46, 0x00, 0x22, 0xCA, 0x61, 0x8A, 0x61, 0x4F, 0x30, 0xF7, 0x46, 0xC9, 0x21, 0x01, 0x00, 0x91, 0xE1, 0x00, 0x00, 0xDB, 0x48, 0x01, 0x68, 0x8A, 0x69, 0x01, 0x20, 0xC0, 0x03, 0x10, 0x43, 0x88, 0x61, 0x00, 0x20, 0x08, 0x61, 0xD8, 0x48, 0x23, 0x30, 0xF7, 0x46, 0x89, 0x17, 0x02, 0x00, 0x70, 0xB5, 0x05, 0x1C, 0xD5, 0x4E, 0x29, 0x6A, 0xEA, 0x69, 0x30, 0x1C, 0x01, 0x24, 0xA6, 0x46, 0x0B, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x68, 0x69, 0xA6, 0x46, 0xD1, 0x49 ,
-0xFE, 0x44, 0x08, 0x47, 0xA8, 0x69, 0x06, 0x30, 0xA8, 0x60, 0xCF, 0x48, 0x00, 0x68, 0x68, 0x60, 0xEE, 0x60, 0xCE, 0x48, 0xFF, 0xFF, 0x44, 0x6C, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x6D, 0x30, 0x70, 0xBD, 0x46, 0x17, 0x1B, 0x00, 0x30, 0x3F, 0x08, 0x00, 0x41, 0xEB, 0x00, 0x00, 0x09, 0xB4, 0x03, 0x00, 0x30, 0xB5, 0xEE, 0x48, 0x01, 0x6D, 0x80, 0x6C, 0x08, 0x43, 0x18, 0xD0, 0xEC, 0x49, 0x08, 0x1C, 0x07, 0x22, 0xFF, 0x23, 0x09, 0x33, 0x1B, 0x58, 0x00, 0x2B, 0x04, 0xD0, 0xFF, 0x30, 0x1D, 0x30, 0x01, 0x3A, 0xF6, 0xD1, 0x0B, 0xE0, 0x02, 0x20, 0xF0, 0x4A, 0xF1, 0x4B, 0x01, 0x24, 0xA6, 0x46, 0xF0, 0x4D, 0xFE, 0x44, 0x28, 0x47, 0xA6, 0x46, 0xEF, 0x48, 0xFE, 0x44, 0x00, 0x47, 0xEF, 0x48, 0xFF, 0x30, 0x5C, 0x30, 0x30, 0xBD, 0xC0, 0x46, 0x53, 0x53, 0x49, 0x44, 0x00, 0xC0, 0x46, 0xC0, 0x4B, 0x45, 0x59, 0x00, 0xEE, 0x62, 0x08, 0x00, 0xF0, 0x62, 0x08, 0x00, 0xEC, 0x62, 0x08, 0x00, 0xED, 0x62, 0x08, 0x00 ,
-0xE7, 0x7E, 0x03, 0x00, 0xE8, 0x62, 0x08, 0x00, 0xE9, 0x62, 0x08, 0x00, 0xEA, 0x62, 0x08, 0x00, 0xEB, 0x62, 0x08, 0x00, 0xDD, 0x7E, 0x03, 0x00, 0x8F, 0xC6, 0x03, 0x00, 0xF0, 0xB5, 0xFF, 0xFF, 0xDA, 0x6C, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x87, 0xB0, 0x00, 0x91, 0x01, 0x90, 0x6B, 0x48, 0x01, 0x68, 0xCC, 0x4A, 0x14, 0x1C, 0x02, 0x94, 0x07, 0x26, 0x00, 0x25, 0x03, 0x95, 0x04, 0x94, 0x05, 0x95, 0xDF, 0x48, 0x00, 0x68, 0x08, 0x43, 0x27, 0xD0, 0xE0, 0x68, 0x03, 0x99, 0x88, 0x42, 0x0A, 0xDD, 0x03, 0x90, 0x40, 0x1C, 0x00, 0x99, 0x88, 0x60, 0xC2, 0x49, 0xFF, 0x20, 0x1D, 0x30, 0x68, 0x43, 0x0C, 0x18, 0xE0, 0x68, 0x04, 0x91, 0x02, 0x99, 0xC9, 0x68, 0x88, 0x42, 0x10, 0xDB, 0x88, 0x42, 0x10, 0xD1, 0x02, 0x98, 0x01, 0x27, 0xBE, 0x46, 0xCE, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x06, 0x90, 0x20, 0x1C, 0xBE, 0x46, 0xCB, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x06, 0x99, 0x88, 0x42, 0x01, 0xDA, 0x05, 0x95, 0x02, 0x94 ,
-0x51, 0x48, 0x01, 0x68, 0xFF, 0x27, 0x09, 0x37, 0x38, 0x59, 0x00, 0x28, 0x06, 0xD0, 0xC7, 0x48, 0x00, 0x68, 0x07, 0x2E, 0x00, 0xD1, 0x2E, 0x1C, 0x08, 0x43, 0x04, 0xD0, 0xFF, 0x34, 0x1D, 0x34, 0x01, 0x35, 0x07, 0x2D, 0xC2, 0xDB, 0x07, 0x2E, 0xFF, 0xFF, 0x70, 0x6D, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x0A, 0xD1, 0xC0, 0x48, 0x00, 0x68, 0x08, 0x43, 0x06, 0xD0, 0x05, 0x9E, 0x30, 0x1C, 0x01, 0x21, 0x8E, 0x46, 0xBA, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x01, 0x98, 0x47, 0x61, 0x00, 0x21, 0x81, 0x61, 0xFF, 0x22, 0x1D, 0x32, 0x72, 0x43, 0x04, 0x99, 0x89, 0x18, 0xC1, 0x61, 0x06, 0x62, 0xB4, 0x48, 0x39, 0x30, 0x07, 0xB0, 0xF0, 0xBD, 0x10, 0xB5, 0x04, 0x1C, 0x00, 0x20, 0x01, 0x21, 0x8E, 0x46, 0xB1, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x40, 0x1E, 0x00, 0xD5, 0x00, 0x20, 0x60, 0x60, 0xE0, 0x61, 0xAE, 0x48, 0x21, 0x30, 0x10, 0xBD, 0xC0, 0x46, 0x10, 0x63, 0x08, 0x00, 0x70, 0xB5, 0x04, 0x1C, 0xE5, 0x69, 0x66, 0x69 ,
-0x00, 0x20, 0x01, 0x21, 0x8E, 0x46, 0xA7, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x60, 0x60, 0xAB, 0x19, 0xA6, 0x4A, 0xA5, 0x49, 0x93, 0x42, 0x02, 0xD3, 0x9A, 0x1A, 0x82, 0x42, 0x02, 0xD9, 0x08, 0x1C, 0x99, 0x30, 0x70, 0xBD, 0x08, 0x1C, 0xAB, 0x30, 0x70, 0xBD, 0x08, 0x6B, 0x41, 0x7D, 0x02, 0x88, 0x92, 0x00, 0xFF, 0xFF, 0x06, 0x6E, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x51, 0x1A, 0x3C, 0x39, 0xFF, 0x22, 0x5F, 0x32, 0x91, 0x42, 0x03, 0xD9, 0x65, 0x21, 0x01, 0x80, 0x02, 0x21, 0x81, 0x73, 0x9B, 0x48, 0x99, 0x49, 0x08, 0x18, 0xF7, 0x46, 0xC0, 0x46, 0x30, 0x63, 0x08, 0x00, 0xF8, 0xB5, 0x40, 0x68, 0x24, 0x21, 0x41, 0x43, 0x97, 0x48, 0x45, 0x18, 0x28, 0x1D, 0x0C, 0x21, 0x49, 0x19, 0x04, 0x22, 0x01, 0x23, 0x9E, 0x46, 0x94, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x91, 0x4C, 0x00, 0x28, 0x1B, 0xD0, 0x2B, 0x1C, 0x04, 0x22, 0x6E, 0x46, 0x91, 0x49, 0x1F, 0x7B, 0x08, 0x78, 0xC0, 0x43, 0x38, 0x43, 0x30, 0x70, 0x01, 0x33 ,
-0x01, 0x31, 0x01, 0x36, 0x01, 0x3A, 0xF5, 0xD1, 0x0C, 0x20, 0x41, 0x19, 0x68, 0x46, 0x04, 0x22, 0x01, 0x23, 0x9E, 0x46, 0x87, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x00, 0x28, 0x02, 0xD0, 0x20, 0x1C, 0x4A, 0x30, 0xF8, 0xBD, 0x20, 0x1C, 0xF8, 0xBD, 0xB1, 0xBD, 0x00, 0x00, 0x15, 0x95, 0x00, 0x00, 0x58, 0x3F, 0x08, 0x00, 0xF3, 0xF8, 0x00, 0x00, 0xE9, 0x09, 0x02, 0x00, 0xFF, 0xFF, 0x9C, 0x6E, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x2B, 0x09, 0x02, 0x00, 0xDD, 0x0A, 0x02, 0x00, 0xF8, 0xB5, 0x05, 0x1C, 0xAA, 0x69, 0x7D, 0x49, 0x00, 0x20, 0x08, 0x56, 0x24, 0x21, 0x41, 0x43, 0x76, 0x48, 0x43, 0x18, 0x04, 0x24, 0x6E, 0x46, 0x76, 0x49, 0x1F, 0x79, 0x08, 0x78, 0xC0, 0x43, 0x38, 0x43, 0x30, 0x70, 0x01, 0x33, 0x01, 0x31, 0x01, 0x36, 0x01, 0x3C, 0xF5, 0xD1, 0x11, 0x1D, 0x68, 0x46, 0x04, 0x22, 0x01, 0x24, 0xA6, 0x46, 0x6D, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x01, 0x1C, 0x6D, 0x48, 0x04, 0xD0, 0x6E, 0x49, 0x09, 0x78 ,
-0x69, 0x60, 0x45, 0x30, 0xF8, 0xBD, 0xEC, 0x61, 0xAF, 0x30, 0xF8, 0xBD, 0x70, 0xB5, 0xC5, 0x68, 0x81, 0x68, 0x0A, 0x89, 0x6D, 0x4E, 0x00, 0x2A, 0x22, 0xD0, 0x01, 0x24, 0xC2, 0x6D, 0xA2, 0x18, 0xC2, 0x65, 0x08, 0x89, 0x0D, 0x28, 0x1B, 0xD1, 0x68, 0x6B, 0x21, 0x1C, 0xA6, 0x46, 0x63, 0x4A, 0xFE, 0x44, 0x10, 0x47, 0x22, 0x1C, 0x28, 0x1C, 0x00, 0x21, 0xA6, 0x46, 0x60, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x2C, 0x60, 0xE9, 0x6B, 0xFF, 0xFF, 0x32, 0x6F, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x28, 0x1C, 0xA6, 0x46, 0x5E, 0x4A, 0xFE, 0x44, 0x10, 0x47, 0x28, 0x1C, 0xA6, 0x46, 0x5C, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x30, 0x1C, 0x3D, 0x30, 0x70, 0xBD, 0x30, 0x1C, 0x23, 0x30, 0x70, 0xBD, 0xC0, 0x46, 0xB1, 0x02, 0x00, 0x00, 0x74, 0x3F, 0x08, 0x00, 0x19, 0xC6, 0x00, 0x00, 0x5C, 0x3F, 0x08, 0x00, 0x1D, 0xC2, 0x00, 0x00, 0x68, 0x44, 0x08, 0x00, 0x43, 0x12, 0x03, 0x00, 0x34, 0x63, 0x08, 0x00, 0x2F, 0x7A, 0x02, 0x00 ,
-0xB4, 0x36, 0x08, 0x00, 0x8F, 0xF4, 0x01, 0x00, 0xF0, 0xB5, 0x05, 0x1C, 0xAB, 0x69, 0xEC, 0x69, 0x60, 0x68, 0x00, 0x68, 0x2A, 0x30, 0x01, 0x78, 0x0A, 0x06, 0x41, 0x78, 0x09, 0x04, 0x8A, 0x18, 0x81, 0x78, 0x09, 0x02, 0x8A, 0x18, 0xC1, 0x78, 0x8A, 0x18, 0x8E, 0x26, 0xF1, 0x5A, 0x09, 0x0A, 0x01, 0x70, 0xF0, 0x5C, 0x61, 0x68, 0x09, 0x68, 0x2B, 0x26, 0x70, 0x54, 0x8C, 0x20, 0xC0, 0x18, 0x61, 0x68, 0x0E, 0x68, 0x01, 0x88, 0x09, 0x0A, 0x2C, 0x27, 0xB9, 0x55, 0x61, 0x68, 0x09, 0x68, 0xFF, 0xFF, 0xC8, 0x6F, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x2D, 0x26, 0x00, 0x78, 0x70, 0x54, 0x60, 0x68, 0x01, 0x68, 0x32, 0x31, 0x08, 0x78, 0x00, 0x02, 0x49, 0x78, 0x08, 0x18, 0x00, 0x04, 0x00, 0x0C, 0x8C, 0x21, 0xCB, 0x58, 0x35, 0x49, 0x41, 0x40, 0x08, 0x04, 0x00, 0x0C, 0xC0, 0x18, 0x80, 0x1A, 0x01, 0x21, 0x8E, 0x46, 0x32, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x61, 0x68, 0x0A, 0x68, 0x32, 0x23, 0x01, 0x0A, 0x99, 0x54 ,
-0x61, 0x68, 0x09, 0x68, 0x33, 0x22, 0x50, 0x54, 0x60, 0x68, 0x68, 0x60, 0x2C, 0x48, 0xF0, 0xBD, 0x00, 0x00, 0x1B, 0x00, 0x34, 0x04, 0x1B, 0x00, 0x02, 0x6A, 0x8B, 0x69, 0xDB, 0x69, 0x1B, 0x68, 0x83, 0x60, 0x88, 0x69, 0xC0, 0x69, 0x41, 0x68, 0x8A, 0x42, 0x00, 0xDA, 0x42, 0x60, 0x25, 0x48, 0x79, 0x30, 0xF7, 0x46, 0x24, 0x48, 0x57, 0x30, 0xF7, 0x46, 0x24, 0x48, 0x91, 0x30, 0xF7, 0x46, 0x32, 0x04, 0x00, 0x00, 0xC4, 0x07, 0x00, 0x00, 0x15, 0x09, 0x02, 0x00, 0xC5, 0x93, 0x00, 0x00, 0x0D, 0x91, 0x00, 0x00, 0x40, 0x1E, 0x80, 0x00, 0x1E, 0x4B, 0xFF, 0xFF, 0x5E, 0x70, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x19, 0x50, 0x1C, 0x49, 0x0A, 0x50, 0xF7, 0x46, 0xC0, 0x46, 0xBD, 0xB5, 0x00, 0x00, 0x95, 0x92, 0x00, 0x00, 0xFD, 0x93, 0x00, 0x00, 0x54, 0x3F, 0x08, 0x00, 0x29, 0x4F, 0x03, 0x00, 0xDF, 0xE8, 0x02, 0x00, 0x36, 0x89, 0x41, 0x00, 0x81, 0x06, 0x00, 0x00, 0xB1, 0x78, 0x00, 0x00, 0x94, 0xEC, 0x01, 0x00 ,
-0x08, 0x19, 0x1B, 0x00, 0x8F, 0xC6, 0x03, 0x00, 0x1C, 0x17, 0x1B, 0x00, 0x67, 0x66, 0x03, 0x00, 0xA6, 0x44, 0x08, 0x00, 0x18, 0x17, 0x1B, 0x00, 0xA7, 0x2F, 0x02, 0x00, 0x91, 0x44, 0x03, 0x00, 0x91, 0x63, 0x03, 0x00, 0x5B, 0x44, 0x03, 0x00, 0xE7, 0x44, 0x03, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x61, 0xA2, 0x03, 0x00, 0x6A, 0x1E, 0x01, 0x00, 0x45, 0xDA, 0x00, 0x00, 0xD7, 0xE8, 0x01, 0x00, 0xE9, 0x78, 0x02, 0x00, 0x04, 0xF3, 0x1A, 0x00, 0x80, 0x7B, 0x08, 0x00, 0xFC, 0xB5, 0x04, 0x1C, 0xA5, 0x69, 0x60, 0x6A, 0x01, 0x90, 0x20, 0x69, 0x00, 0x28, 0x35, 0xD4, 0x08, 0x28, 0x33, 0xDA, 0xE1, 0x69, 0x09, 0x68, 0xFF, 0xFF, 0xF4, 0x70, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x10, 0x29, 0x2F, 0xD1, 0xAC, 0x21, 0x41, 0x43, 0x9E, 0x4A, 0x51, 0x5C, 0x49, 0x08, 0x27, 0xD3, 0x00, 0x06, 0x00, 0x16, 0xA2, 0x68, 0x69, 0x46, 0x01, 0x23, 0x9E, 0x46, 0x9A, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x06, 0x1C, 0x39, 0x30, 0x1F, 0xD0 ,
-0x00, 0x2E, 0x1D, 0xD0, 0x00, 0x98, 0x07, 0x68, 0x00, 0x99, 0x0C, 0x39, 0x01, 0x98, 0x01, 0x60, 0x28, 0x1D, 0x10, 0x21, 0x79, 0x1A, 0x04, 0x22, 0x01, 0x23, 0x9E, 0x46, 0x91, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x02, 0x22, 0x2A, 0x80, 0xA8, 0x1C, 0x08, 0x21, 0x79, 0x1A, 0x01, 0x23, 0x9E, 0x46, 0x8C, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x03, 0xE0, 0x38, 0x20, 0x00, 0xE0, 0x00, 0x20, 0xC6, 0x43, 0x26, 0x60, 0x89, 0x48, 0x7C, 0x30, 0x20, 0x62, 0xFC, 0xBD, 0x30, 0xB5, 0x05, 0x1C, 0x28, 0x69, 0xA9, 0x69, 0x90, 0x29, 0x1D, 0xD1, 0x69, 0x69, 0x09, 0x78, 0x04, 0x29, 0x19, 0xD0, 0x05, 0x29, 0x17, 0xD0, 0x0A, 0x29, 0x15, 0xD0, 0x06, 0x29, 0x13, 0xD0, 0x0C, 0x29, 0x01, 0xDB, 0xFF, 0xFF, 0x8A, 0x71, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x10, 0x29, 0x0F, 0xD1, 0x01, 0x24, 0xA6, 0x46, 0x7D, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x7C, 0x48, 0x7D, 0x49, 0x00, 0x22, 0xA6, 0x46, 0x7C, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x7C, 0x48 ,
-0xFF, 0x30, 0x5F, 0x30, 0x28, 0x62, 0x30, 0xBD, 0xF0, 0xB5, 0x89, 0xB0, 0x05, 0x90, 0x41, 0x69, 0x02, 0x69, 0x75, 0x48, 0x79, 0x4E, 0x82, 0x42, 0x3A, 0xD0, 0x04, 0x30, 0x82, 0x42, 0x25, 0xD0, 0x74, 0x4D, 0xAA, 0x42, 0x00, 0xD0, 0xCC, 0xE0, 0x08, 0x68, 0x06, 0x1C, 0x0C, 0x22, 0x8F, 0x1A, 0x4A, 0x68, 0x89, 0x18, 0x09, 0x1D, 0x10, 0x22, 0x01, 0x24, 0xA6, 0x46, 0x6E, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x01, 0x1C, 0x09, 0xD1, 0xAC, 0x22, 0x72, 0x43, 0xCB, 0x48, 0x80, 0x18, 0x46, 0x22, 0x12, 0x5C, 0x11, 0x2A, 0x01, 0xD1, 0x44, 0x22, 0x14, 0x54, 0x28, 0x1C, 0x3A, 0x1C, 0xA6, 0x46, 0x62, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x69, 0x48, 0xEC, 0x30, 0xAB, 0xE0, 0x08, 0x68, 0xC0, 0x00, 0x30, 0x18, 0x8A, 0x68, 0x02, 0x2A, 0x02, 0xD0, 0xFF, 0xFF, 0x20, 0x72, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0xE7, 0x20, 0x80, 0x00, 0xA2, 0xE0, 0xCA, 0x68, 0x89, 0x18, 0x09, 0x7B, 0x41, 0x60, 0x80, 0x21, 0x01, 0x60, 0x3B, 0x20 ,
-0x00, 0x01, 0x99, 0xE0, 0x08, 0x68, 0x06, 0x90, 0xC0, 0x00, 0x34, 0x58, 0x10, 0x20, 0x04, 0x90, 0x01, 0x25, 0xAE, 0x46, 0x57, 0x48, 0xFE, 0x44, 0x00, 0x47, 0x07, 0x90, 0x00, 0x28, 0x00, 0xD1, 0x89, 0xE0, 0x0C, 0x21, 0x07, 0x98, 0x0F, 0x18, 0xB0, 0x49, 0xAC, 0x20, 0x06, 0x9A, 0x50, 0x43, 0x08, 0x18, 0x48, 0x22, 0x13, 0x5C, 0x5B, 0x06, 0x5B, 0x0E, 0x13, 0x54, 0x06, 0x9A, 0xD2, 0x00, 0xB6, 0x18, 0x71, 0x68, 0x00, 0x29, 0x47, 0xD1, 0x00, 0x2C, 0x01, 0xDD, 0x08, 0x2C, 0x21, 0xDB, 0x00, 0x22, 0x69, 0x46, 0x0A, 0x70, 0x01, 0x92, 0x0A, 0x81, 0x8A, 0x72, 0xCD, 0x72, 0x0D, 0x73, 0x4D, 0x73, 0x01, 0x88, 0x44, 0x48, 0x06, 0x23, 0xAE, 0x46, 0x44, 0x4C, 0xFE, 0x44, 0x20, 0x47, 0x04, 0x1C, 0x02, 0xDC, 0x00, 0x20, 0xC0, 0x43, 0x36, 0xE0, 0x34, 0x60, 0xAC, 0x20, 0x60, 0x43, 0x9A, 0x49, 0xFF, 0xFF, 0xB6, 0x72, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x09, 0x18, 0x5C, 0x22, 0x28, 0x1C, 0x50, 0x54, 0x48, 0x20 ,
-0x42, 0x5C, 0x52, 0x06, 0x52, 0x0E, 0x42, 0x54, 0xAC, 0x20, 0x60, 0x43, 0x94, 0x49, 0x08, 0x18, 0x5C, 0x21, 0x09, 0x5C, 0x49, 0x1E, 0x02, 0x29, 0x16, 0xD9, 0x03, 0x39, 0x08, 0xD0, 0x00, 0x20, 0x30, 0x56, 0xAE, 0x46, 0xEA, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x80, 0x20, 0x30, 0x60, 0xDB, 0xE7, 0x08, 0x94, 0x80, 0x21, 0x31, 0x60, 0x48, 0x22, 0x13, 0x5C, 0x19, 0x43, 0x11, 0x54, 0xAE, 0x46, 0xE4, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x0A, 0xE0, 0x01, 0x20, 0xCE, 0xE7, 0x06, 0x98, 0x39, 0x1C, 0x04, 0xAA, 0xAE, 0x46, 0xE0, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x04, 0x1C, 0x08, 0x90, 0x06, 0x98, 0x38, 0x60, 0x08, 0x98, 0x78, 0x60, 0x00, 0x28, 0x15, 0xD0, 0xAC, 0x20, 0x60, 0x43, 0x7C, 0x49, 0x09, 0x18, 0x48, 0x88, 0x02, 0x04, 0x02, 0x20, 0x10, 0x43, 0xB8, 0x60, 0x48, 0x68, 0x02, 0x0E, 0x01, 0x02, 0x09, 0x0E, 0x09, 0x02, 0x11, 0x43, 0x02, 0x04, 0x12, 0x0E, 0xFF, 0xFF, 0x4C, 0x73, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00 ,
-0x12, 0x04, 0x0A, 0x43, 0x00, 0x06, 0x10, 0x43, 0xF8, 0x60, 0x07, 0x98, 0x0D, 0x49, 0x00, 0x22, 0x10, 0x23, 0xAE, 0x46, 0xCE, 0x4C, 0xFE, 0x44, 0x20, 0x47, 0x13, 0x48, 0x00, 0xE0, 0x16, 0x20, 0xCC, 0x49, 0x09, 0x18, 0x05, 0x98, 0x01, 0x62, 0x09, 0xB0, 0xF0, 0xBD, 0x5D, 0x0D, 0x1B, 0x00, 0x81, 0xE7, 0x02, 0x00, 0x09, 0xB4, 0x03, 0x00, 0x27, 0x1A, 0x02, 0x00, 0x2F, 0x7A, 0x02, 0x00, 0x02, 0x02, 0x00, 0x00, 0x05, 0x10, 0x00, 0x00, 0xCF, 0xF6, 0x00, 0x00, 0xD5, 0xF4, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x91, 0x19, 0x02, 0x00, 0x50, 0x65, 0x08, 0x00, 0x71, 0xC0, 0x02, 0x00, 0x50, 0x19, 0x1B, 0x00, 0x29, 0x16, 0x01, 0x00, 0x2A, 0x03, 0x00, 0x00, 0xF0, 0xB5, 0x8B, 0xB0, 0x07, 0x90, 0x05, 0x69, 0x47, 0x69, 0x0C, 0x20, 0x38, 0x1A, 0x08, 0x90, 0xB6, 0x49, 0x8D, 0x42, 0x16, 0xD1, 0x78, 0x68, 0x0F, 0x30, 0x00, 0x11, 0x00, 0x01, 0x78, 0x60, 0x38, 0x68, 0x0B, 0x28, 0x0E, 0xD8, 0x00, 0x23, 0x68, 0x46 ,
-0xFF, 0xFF, 0xE2, 0x73, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x03, 0x70, 0x08, 0x98, 0x05, 0x22, 0x01, 0x24, 0xA6, 0x46, 0xAE, 0x4C, 0xFE, 0x44, 0x20, 0x47, 0xAE, 0x48, 0xFF, 0x30, 0x95, 0x30, 0x07, 0x99, 0x08, 0x62, 0xAC, 0x48, 0x85, 0x42, 0x23, 0xD1, 0xAC, 0x48, 0x02, 0x78, 0x6C, 0x46, 0x22, 0x72, 0x43, 0x78, 0x63, 0x72, 0x81, 0x78, 0xA1, 0x72, 0xC0, 0x78, 0xE0, 0x72, 0x00, 0x91, 0x01, 0x90, 0x03, 0x20, 0xA6, 0x49, 0x01, 0x39, 0x01, 0x26, 0xB6, 0x46, 0xF3, 0x4E, 0xFE, 0x44, 0x30, 0x47, 0x04, 0x20, 0x20, 0x70, 0x08, 0x98, 0x9F, 0x49, 0x00, 0x22, 0x02, 0xAB, 0x01, 0x24, 0xA6, 0x46, 0x9B, 0x4C, 0xFE, 0x44, 0x20, 0x47, 0x9A, 0x48, 0xFF, 0x30, 0x95, 0x30, 0x07, 0x99, 0x08, 0x62, 0xEB, 0x49, 0x8D, 0x42, 0x14, 0xD1, 0x02, 0x22, 0x68, 0x46, 0x02, 0x70, 0x3A, 0x68, 0xAC, 0x20, 0x42, 0x43, 0x30, 0x48, 0x68, 0x30, 0x83, 0x18, 0x08, 0x98, 0x00, 0x22, 0x01, 0x24, 0xA6, 0x46, 0x8F, 0x4C, 0xFE, 0x44 ,
-0x20, 0x47, 0x8E, 0x48, 0xFF, 0x30, 0x95, 0x30, 0x07, 0x99, 0xFF, 0xFF, 0x78, 0x74, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x08, 0x62, 0xEF, 0x48, 0x85, 0x42, 0x00, 0xD0, 0x04, 0xE1, 0x03, 0x20, 0x8C, 0x49, 0x01, 0x22, 0x96, 0x46, 0xEC, 0x4A, 0xFE, 0x44, 0x10, 0x47, 0x86, 0x48, 0xFF, 0x30, 0x95, 0x30, 0x09, 0x90, 0x38, 0x68, 0xEA, 0x4D, 0x00, 0x28, 0x00, 0xD1, 0xE2, 0xE0, 0x01, 0x24, 0xA6, 0x46, 0xE6, 0x48, 0xFE, 0x44, 0x00, 0x47, 0x00, 0x28, 0x00, 0xD1, 0xD6, 0xE0, 0xE4, 0x48, 0x02, 0x68, 0x03, 0x20, 0x7F, 0x49, 0x01, 0x31, 0xA6, 0x46, 0xE2, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0xDF, 0x48, 0x00, 0x68, 0x00, 0x28, 0x5A, 0xD1, 0xDF, 0x4D, 0x2E, 0x20, 0x41, 0x19, 0xB8, 0x68, 0x03, 0x30, 0x08, 0x70, 0x38, 0x7A, 0x48, 0x70, 0x2E, 0x1C, 0x30, 0x36, 0xB8, 0x68, 0x28, 0x18, 0x30, 0x30, 0xDA, 0x49, 0x0A, 0x68, 0x30, 0x3A, 0x31, 0x1C, 0xA6, 0x46, 0xD8, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x78, 0x68, 0x38, 0x18 ,
-0x01, 0x1D, 0xBA, 0x68, 0x30, 0x1C, 0xA6, 0x46, 0xD9, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0xB8, 0x68, 0x41, 0x19, 0x97, 0x22, 0xFF, 0xFF, 0x0E, 0x75, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x09, 0x30, 0x50, 0x54, 0xB8, 0x68, 0x46, 0x19, 0x9E, 0x36, 0x30, 0x70, 0x01, 0x36, 0xB8, 0x68, 0x01, 0xE0, 0x14, 0x0D, 0x1B, 0x00, 0x30, 0x18, 0xCA, 0x49, 0x0A, 0x68, 0x9E, 0x3A, 0x31, 0x1C, 0xA6, 0x46, 0xC8, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x78, 0x68, 0x38, 0x18, 0x01, 0x1D, 0xBA, 0x68, 0x30, 0x1C, 0xA6, 0x46, 0xC9, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0xB8, 0x68, 0x40, 0x00, 0xC0, 0x49, 0x09, 0x68, 0x08, 0x18, 0x28, 0x18, 0xC0, 0x49, 0x0A, 0x79, 0x02, 0x70, 0x4A, 0x79, 0x42, 0x70, 0x8A, 0x79, 0x82, 0x70, 0xC9, 0x79, 0xC1, 0x70, 0x04, 0x30, 0x0F, 0x21, 0x41, 0x1A, 0x0A, 0x78, 0xBB, 0x68, 0x9A, 0x18, 0x0A, 0x70, 0x40, 0x1B, 0x00, 0x04, 0x00, 0x0C, 0xB5, 0x49, 0x08, 0x60, 0xB1, 0x48, 0x04, 0x60, 0x02, 0x20, 0x01, 0x1C ,
-0x11, 0x22, 0xA6, 0x46, 0xB4, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x06, 0x1C, 0x63, 0xD4, 0x03, 0x20, 0xA6, 0x46, 0xB1, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x0A, 0x90, 0x00, 0x25, 0x01, 0x1C, 0xFF, 0xFF, 0xA4, 0x75, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x8D, 0x42, 0x50, 0xD0, 0x29, 0x1C, 0x2B, 0x22, 0xA6, 0x46, 0xAD, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x0C, 0x20, 0x0A, 0x99, 0x40, 0x18, 0xAC, 0x22, 0x72, 0x43, 0xAB, 0x49, 0x8F, 0x18, 0x78, 0x63, 0x29, 0x1C, 0x18, 0x22, 0xA6, 0x46, 0xA6, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x9F, 0x48, 0x02, 0x68, 0x79, 0x6B, 0x4A, 0x60, 0x0A, 0x98, 0xAC, 0x30, 0x08, 0x60, 0x08, 0x68, 0x9A, 0x49, 0xA6, 0x46, 0xA0, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x29, 0x1C, 0x03, 0xA8, 0x10, 0x22, 0xA6, 0x46, 0x9C, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0xE0, 0x21, 0x68, 0x46, 0x01, 0x74, 0x45, 0x74, 0x85, 0x74, 0xFB, 0x21, 0xC1, 0x74, 0xEE, 0x49, 0xC1, 0x81, 0x02, 0x21, 0x81, 0x81, 0x79, 0x6B, 0xCA, 0x68 ,
-0x01, 0x20, 0xC0, 0x03, 0x10, 0x43, 0xC8, 0x60, 0x48, 0x68, 0x00, 0x90, 0x2A, 0x1C, 0x30, 0x1C, 0x0A, 0x9D, 0x29, 0x1C, 0x03, 0xAB, 0xA6, 0x46, 0xE6, 0x4F, 0xFE, 0x44, 0x38, 0x47, 0x07, 0x1C, 0x30, 0x06, 0x00, 0x16, 0xA6, 0x46, 0xEF, 0x49, 0xFF, 0xFF, 0x3A, 0x76, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0xFE, 0x44, 0x08, 0x47, 0x28, 0x1C, 0xA6, 0x46, 0xEE, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x11, 0xE0, 0x30, 0x06, 0x00, 0x16, 0xA6, 0x46, 0xE9, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x01, 0x20, 0xC7, 0x43, 0x08, 0xE0, 0x07, 0x1C, 0x06, 0xE0, 0x00, 0x20, 0x00, 0x21, 0xCF, 0x43, 0x01, 0xE0, 0x00, 0x20, 0x07, 0x1C, 0x28, 0x60, 0x00, 0x23, 0x68, 0x46, 0x03, 0x70, 0x3A, 0x06, 0x12, 0x0E, 0x08, 0x98, 0x6F, 0x49, 0x01, 0x24, 0xA6, 0x46, 0x09, 0x4C, 0xFE, 0x44, 0x20, 0x47, 0x07, 0x98, 0x09, 0x99, 0x01, 0x62, 0x0B, 0xB0, 0xF0, 0xBD, 0xC1, 0x18, 0x01, 0x00, 0xF1, 0x1B, 0x01, 0x00, 0xF3, 0x1C, 0x02, 0x00, 0x7B, 0xC0 ,
-0x02, 0x00, 0x91, 0xF0, 0x00, 0x00, 0x03, 0x02, 0x00, 0x00, 0xA3, 0xC0, 0x02, 0x00, 0xA9, 0xE9, 0x00, 0x00, 0x07, 0x02, 0x00, 0x00, 0xE4, 0x62, 0x08, 0x00, 0xAC, 0x05, 0x00, 0x00, 0xFE, 0xB5, 0x07, 0x1C, 0x7D, 0x69, 0xBE, 0x69, 0x0C, 0x20, 0x30, 0x1A, 0x01, 0x90, 0xDF, 0x4C, 0x0A, 0x2D, 0x13, 0xD1, 0xFF, 0xFF, 0xD0, 0x76, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x30, 0x68, 0xDB, 0x49, 0x08, 0x60, 0x01, 0x20, 0x86, 0x46, 0xDA, 0x48, 0xFE, 0x44, 0x00, 0x47, 0x0A, 0x20, 0x00, 0x21, 0x01, 0x9A, 0x01, 0x23, 0x9E, 0x46, 0xE6, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0xF5, 0x20, 0x80, 0x00, 0x00, 0x19, 0x38, 0x62, 0x03, 0x2D, 0x79, 0xD1, 0xF5, 0x20, 0x80, 0x00, 0x00, 0x19, 0x02, 0x90, 0x70, 0x68, 0x00, 0x28, 0x0C, 0xD1, 0x00, 0x21, 0xCF, 0x48, 0x01, 0x60, 0xCF, 0x48, 0x00, 0x68, 0x00, 0x28, 0x61, 0xD0, 0x01, 0x21, 0x8E, 0x46, 0xCD, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x5B, 0xE0, 0xCC, 0x48, 0xB1, 0x68, 0x01, 0x60 ,
-0xF1, 0x68, 0x41, 0x60, 0x31, 0x69, 0x81, 0x60, 0x71, 0x69, 0xC1, 0x60, 0xB1, 0x69, 0xC1, 0x63, 0xF1, 0x69, 0x01, 0x64, 0x31, 0x6A, 0xC1, 0x64, 0x01, 0x24, 0xA6, 0x46, 0xC5, 0x48, 0xFE, 0x44, 0x00, 0x47, 0xA6, 0x46, 0xC4, 0x48, 0xFE, 0x44, 0x00, 0x47, 0x70, 0x68, 0x7D, 0x25, 0xED, 0x00, 0xA8, 0x42, 0x21, 0xD8, 0x01, 0x28, 0x18, 0xD0, 0x02, 0x28, 0x05, 0xD0, 0xFF, 0xFF, 0x66, 0x77, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x28, 0x1C, 0xA6, 0x46, 0xBE, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x1C, 0xE0, 0xB9, 0x48, 0x00, 0x23, 0x19, 0x1C, 0x59, 0x43, 0x3E, 0x22, 0x4A, 0x43, 0x82, 0x83, 0x02, 0x30, 0x01, 0x33, 0x10, 0x2B, 0xF6, 0xDB, 0xA6, 0x46, 0xB4, 0x48, 0xFE, 0x44, 0x00, 0x47, 0xB5, 0x48, 0x0D, 0xE0, 0xB5, 0x4D, 0x28, 0x1C, 0xA6, 0x46, 0xB2, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x04, 0xE0, 0xA6, 0x46, 0xAF, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x75, 0x68, 0xAE, 0x48, 0x05, 0x60, 0x05, 0x1C, 0xA7, 0x4E, 0x30, 0x68 ,
-0x00, 0x28, 0x06, 0xD1, 0xAD, 0x48, 0x00, 0x68, 0xA6, 0x46, 0xAC, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x30, 0x60, 0x00, 0x94, 0x2B, 0x68, 0xAA, 0x49, 0xAB, 0x4A, 0xA6, 0x46, 0xAB, 0x4D, 0xFE, 0x44, 0x28, 0x47, 0x9C, 0x48, 0x04, 0x60, 0x03, 0x20, 0x00, 0x21, 0x01, 0x9A, 0x01, 0x23, 0x9E, 0x46, 0xA7, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x02, 0x98, 0x38, 0x62, 0xFE, 0xBD, 0xC0, 0x46, 0x13, 0x7F, 0x03, 0x00, 0x12, 0x10, 0x00, 0x00, 0xFF, 0xFF, 0xFC, 0x77, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x30, 0xB5, 0x05, 0x1C, 0x00, 0x20, 0x01, 0x24, 0xA6, 0x46, 0xA0, 0x49, 0xFE, 0x44, 0x08, 0x47, 0xA6, 0x46, 0x9F, 0x49, 0xFE, 0x44, 0x08, 0x47, 0xA6, 0x46, 0x9E, 0x48, 0xFE, 0x44, 0x00, 0x47, 0x7D, 0x21, 0xC9, 0x00, 0xA6, 0x46, 0x9E, 0x4A, 0xFE, 0x44, 0x10, 0x47, 0x9B, 0x49, 0x08, 0x18, 0x99, 0x49, 0x08, 0x80, 0x9B, 0x48, 0x0A, 0x30, 0x28, 0x62, 0x30, 0xBD, 0x11, 0x10, 0x00, 0x00, 0xDD, 0x7E, 0x03, 0x00, 0xB9, 0x90 ,
-0x00, 0x00, 0x6C, 0x64, 0x08, 0x00, 0xE7, 0x7E, 0x03, 0x00, 0x74, 0x64, 0x08, 0x00, 0x70, 0x64, 0x08, 0x00, 0x6D, 0xC6, 0x03, 0x00, 0x08, 0x19, 0x1B, 0x00, 0x11, 0x18, 0x02, 0x00, 0xD1, 0x78, 0x02, 0x00, 0xC9, 0xBA, 0x03, 0x00, 0x09, 0xB4, 0x03, 0x00, 0x14, 0x0D, 0x1B, 0x00, 0xFE, 0xB5, 0x02, 0x90, 0x45, 0x69, 0x68, 0x46, 0x01, 0x21, 0x8E, 0x46, 0x89, 0x49, 0xFE, 0x44, 0x08, 0x47, 0x89, 0x48, 0x04, 0x1C, 0x68, 0x68, 0x01, 0x69, 0x4A, 0x78, 0x00, 0x27, 0x3E, 0x1C, 0x20, 0x88, 0xFF, 0xFF, 0x92, 0x78, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x40, 0x08, 0x22, 0xD3, 0x20, 0x1D, 0x89, 0x1C, 0x01, 0x23, 0x9E, 0x46, 0x83, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x00, 0x28, 0x07, 0xD1, 0x68, 0x68, 0x00, 0x69, 0x40, 0x78, 0x21, 0x88, 0x09, 0x04, 0x89, 0x16, 0x81, 0x42, 0x3D, 0xD0, 0x02, 0x20, 0x00, 0x5F, 0x00, 0x99, 0x08, 0x1A, 0x00, 0x04, 0x00, 0x14, 0x3C, 0x28, 0x03, 0xDD, 0x20, 0x88, 0x40, 0x10, 0x40, 0x00 ,
-0x20, 0x80, 0x78, 0x1C, 0x07, 0x06, 0x3F, 0x0E, 0x68, 0x68, 0x01, 0x69, 0x4A, 0x78, 0x2A, 0x34, 0x01, 0x36, 0x14, 0x2E, 0xD5, 0xDB, 0x00, 0x2A, 0x02, 0xD1, 0xAB, 0x20, 0x40, 0x00, 0x50, 0xE0, 0x00, 0x9B, 0x6D, 0x48, 0x14, 0x21, 0x00, 0x22, 0x04, 0x88, 0x64, 0x08, 0x03, 0xD3, 0x2A, 0x30, 0x01, 0x32, 0x01, 0x39, 0xF8, 0xD1, 0x12, 0x06, 0x12, 0x0E, 0x14, 0x2F, 0x16, 0xD1, 0x66, 0x48, 0x00, 0x88, 0x00, 0x06, 0x44, 0x16, 0x64, 0x49, 0x00, 0x22, 0x01, 0x20, 0x4E, 0x8D, 0x36, 0x06, 0x76, 0x16, 0xA6, 0x42, 0x02, 0xDD, 0x34, 0x1C, 0x02, 0x06, 0xFF, 0xFF, 0x28, 0x79, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0x12, 0x0E, 0x2A, 0x31, 0x01, 0x30, 0x14, 0x28, 0xF3, 0xDB, 0x02, 0xE0, 0x32, 0x06, 0x12, 0x0E, 0x00, 0x9B, 0x2A, 0x20, 0x42, 0x43, 0x5A, 0x48, 0x11, 0x18, 0x0C, 0x88, 0x01, 0x20, 0x20, 0x43, 0x00, 0x04, 0x00, 0x0C, 0x08, 0x80, 0xFE, 0x24, 0xA0, 0x43, 0x14, 0x24, 0x64, 0x57, 0x64, 0x06, 0x24, 0x0E ,
-0x04, 0x43, 0x52, 0x48, 0x14, 0x52, 0x14, 0x18, 0x63, 0x80, 0x08, 0x88, 0x80, 0x05, 0x82, 0x0D, 0x68, 0x68, 0x00, 0x69, 0x40, 0x78, 0x80, 0x02, 0x10, 0x43, 0x08, 0x80, 0x68, 0x68, 0x02, 0x69, 0x20, 0x1D, 0x91, 0x1C, 0x52, 0x78, 0x01, 0x23, 0x9E, 0x46, 0x4B, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x02, 0x98, 0x04, 0x61, 0xFE, 0x20, 0x47, 0x49, 0x09, 0x18, 0x02, 0x98, 0x01, 0x62, 0xFE, 0xBD, 0x82, 0x69, 0x41, 0x69, 0x03, 0x69, 0x02, 0x2B, 0x0A, 0xD1, 0x01, 0x2A, 0x01, 0xD1, 0x00, 0x29, 0x05, 0xD0, 0x02, 0x2A, 0x04, 0xD1, 0x00, 0x29, 0x02, 0xD1, 0x11, 0x21, 0x00, 0xE0, 0x06, 0x21, 0x41, 0x61, 0xF7, 0x46, 0xFF, 0xFF, 0xBE, 0x79, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0xC0, 0x46, 0x14, 0xE9, 0x00, 0x00, 0xC9, 0x18, 0x02, 0x00, 0x30, 0xB5, 0x05, 0x1C, 0x3A, 0x48, 0x00, 0x78, 0x00, 0x28, 0x04, 0xD0, 0x01, 0x20, 0x86, 0x46, 0x38, 0x48, 0xFE, 0x44, 0x00, 0x47, 0x01, 0x24, 0xA6, 0x46, 0x37, 0x48, 0xFE, 0x44 ,
-0x00, 0x47, 0xA6, 0x46, 0x36, 0x48, 0xFE, 0x44, 0x00, 0x47, 0x35, 0x48, 0x0E, 0x30, 0x28, 0x62, 0x30, 0xBD, 0x49, 0x19, 0x01, 0x00, 0x2F, 0x7A, 0x02, 0x00, 0x18, 0xB5, 0x43, 0x69, 0x81, 0x69, 0x31, 0x48, 0x81, 0x29, 0x00, 0xD1, 0x0B, 0x38, 0x00, 0x21, 0x00, 0x91, 0x1A, 0x68, 0x9B, 0x68, 0x01, 0x24, 0xA6, 0x46, 0x2D, 0x4C, 0xFE, 0x44, 0x20, 0x47, 0x18, 0xBD, 0x18, 0xB5, 0x40, 0x69, 0x00, 0x21, 0x00, 0x91, 0x02, 0x68, 0x83, 0x68, 0x27, 0x48, 0x01, 0x30, 0x01, 0x24, 0xA6, 0x46, 0x26, 0x4C, 0xFE, 0x44, 0x20, 0x47, 0x18, 0xBD, 0xC0, 0x46, 0x30, 0x63, 0x08, 0x00, 0x19, 0x9E, 0x00, 0x00, 0xB9, 0xEC, 0x00, 0x00, 0x74, 0x3F, 0x08, 0x00, 0x80, 0x3F, 0x08, 0x00, 0xFF, 0xFF, 0x54, 0x7A, 0x08, 0x00, 0x96, 0x00, 0x00, 0x00, 0xB7, 0x5D, 0x03, 0x00, 0x00, 0x00, 0x1B, 0x00, 0xD3, 0x8E, 0x00, 0x00, 0xF7, 0xC6, 0x00, 0x00, 0xE5, 0x90, 0x00, 0x00, 0x68, 0x64, 0x08, 0x00, 0xC0, 0x27, 0x09, 0x00, 0xA0, 0x3B ,
-0x08, 0x00, 0x3D, 0x5D, 0x03, 0x00, 0x19, 0xC6, 0x00, 0x00, 0xE8, 0x3A, 0x08, 0x00, 0x81, 0x5D, 0x03, 0x00, 0xCF, 0xF6, 0x00, 0x00, 0x4B, 0x4F, 0x03, 0x00, 0x6B, 0xC0, 0x03, 0x00, 0x95, 0x1E, 0x01, 0x00, 0xDA, 0x40, 0x08, 0x00, 0xDC, 0x05, 0x00, 0x00, 0x55, 0xAA, 0x03, 0x00, 0x0D, 0x91, 0x00, 0x00, 0xD7, 0x56, 0x03, 0x00, 0x08, 0x51, 0x08, 0x00, 0x8F, 0xC6, 0x03, 0x00, 0x65, 0xB8, 0x00, 0x00, 0x09, 0xB4, 0x03, 0x00, 0x84, 0x17, 0x1B, 0x00, 0xB5, 0x86, 0x01, 0x00, 0x3D, 0x47, 0x02, 0x00, 0x73, 0x49, 0x02, 0x00, 0x5F, 0x90, 0x00, 0x00, 0x0E, 0x10, 0x00, 0x00, 0xF7, 0xF6, 0x00, 0x00, 0xFF, 0xB5, 0x68, 0x46, 0xFF, 0xF7, 0x76, 0xFF, 0xFF, 0xBD, 0xFF, 0xB5, 0x68, 0x46, 0xFF, 0xF7, 0x5A, 0xFF, 0xFF, 0xBD, 0xFF, 0xB5, 0xFF, 0xFF, 0xEA, 0x7A, 0x08, 0x00, 0x58, 0x00, 0x00, 0x00, 0x68, 0x46, 0xFF, 0xF7, 0x99, 0xFF, 0xFF, 0xBD, 0xFF, 0xB5, 0x68, 0x46, 0xFF, 0xF7, 0x83, 0xFF, 0xFF, 0xBD, 0xFF, 0xB5 ,
-0x68, 0x46, 0xFF, 0xF7, 0xB6, 0xFE, 0xFF, 0xBD, 0xFF, 0xB5, 0x68, 0x46, 0xFF, 0xF7, 0x55, 0xFC, 0xFF, 0xBD, 0xFF, 0xB5, 0x68, 0x46, 0xFF, 0xF7, 0x27, 0xFB, 0xFF, 0xBD, 0xFF, 0xB5, 0x68, 0x46, 0xFF, 0xF7, 0xDD, 0xFA, 0xFF, 0xBD, 0xFF, 0xB5, 0x68, 0x46, 0xFF, 0xF7, 0x68, 0xFE, 0xFF, 0xBD, 0xFF, 0xB5, 0x68, 0x46, 0xFF, 0xF7, 0x3D, 0xFB, 0xFF, 0xBD, 0xFF, 0xB5, 0x68, 0x46, 0xFF, 0xF7, 0xBE, 0xFD, 0xFF, 0xBD, 0x78, 0x7B, 0x08, 0x00, 0x88, 0x00, 0x00, 0x00, 0x00, 0xB5, 0xF8, 0xF0, 0x43, 0xFA, 0x00, 0xBD, 0x35, 0x66, 0x08, 0x00, 0x67, 0x66, 0x08, 0x00, 0x71, 0x65, 0x08, 0x00, 0x4D, 0x66, 0x08, 0x00, 0x25, 0x64, 0x08, 0x00, 0x81, 0x66, 0x08, 0x00, 0x8D, 0x66, 0x08, 0x00, 0x99, 0x66, 0x08, 0x00, 0x87, 0x67, 0x08, 0x00, 0xA7, 0x67, 0x08, 0x00, 0xD1, 0x67, 0x08, 0x00, 0x1B, 0x68, 0x08, 0x00, 0x57, 0x68, 0x08, 0x00, 0x2D, 0x69, 0x08, 0x00, 0xB1, 0x6B, 0x08, 0x00, 0xD5, 0x6B, 0x08, 0x00, 0xF9, 0x6B ,
-0x08, 0x00, 0x15, 0x6C, 0x08, 0x00, 0xA1, 0x68, 0x08, 0x00, 0x59, 0x6C, 0x08, 0x00, 0xA7, 0x6D, 0x08, 0x00, 0xFF, 0x6D, 0x08, 0x00, 0x29, 0x6E, 0x08, 0x00, 0xF9, 0x6E, 0x08, 0x00, 0xD9, 0x6C, 0x08, 0x00, 0xA5, 0x6E, 0x08, 0x00, 0xCD, 0x6D, 0x08, 0x00, 0x81, 0x6F, 0x08, 0x00, 0x1D, 0x70, 0x08, 0x00, 0x31, 0x64, 0x08, 0x00, 0x39, 0x70, 0x08, 0x00, 0x3F, 0x70, 0x08, 0x00, 0x04, 0xF3, 0x1A, 0x00, 0x80, 0x00, 0x00, 0x00, 0xB2, 0x4E, 0x01, 0x00, 0x5A, 0xC1, 0x00, 0x00, 0x96, 0x1A, 0x01, 0x00, 0x22, 0x0B, 0x02, 0x00, 0x60, 0xD0, 0x01, 0x00, 0x06, 0x1A, 0x00, 0x00, 0xB8, 0xC6, 0x01, 0x00, 0xD8, 0x42, 0x03, 0x00, 0x16, 0x42, 0x03, 0x00, 0xEE, 0xDB, 0x00, 0x00, 0x62, 0xDC, 0x00, 0x00, 0xC8, 0xE1, 0x00, 0x00, 0x8A, 0x17, 0x02, 0x00, 0x38, 0xBE, 0x00, 0x00, 0x26, 0xC6, 0x00, 0x00, 0x56, 0xC2, 0x00, 0x00, 0x62, 0x12, 0x03, 0x00, 0xE4, 0xF4, 0x01, 0x00, 0x3A, 0xEC, 0x00, 0x00, 0x5E, 0x92, 0x00, 0x00 ,
-0xFE, 0xE8, 0x02, 0x00, 0x18, 0x7F, 0x00, 0x00, 0x64, 0xEC, 0x01, 0x00, 0xFE, 0x44, 0x03, 0x00, 0x1C, 0x94, 0x00, 0x00, 0xA8, 0x66, 0x03, 0x00, 0x74, 0xE9, 0x02, 0x00, 0x68, 0x1E, 0x01, 0x00, 0xBC, 0xDA, 0x00, 0x00, 0xEA, 0xE1, 0x00, 0x00, 0x24, 0xE9, 0x01, 0x00, 0x70, 0x79, 0x02, 0x00, 0x00, 0x00, 0x18, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x06, 0x01, 0x1C, 0xF0, 0xB5, 0x88, 0xB0, 0xCA, 0x4C, 0x03, 0x20, 0x22, 0x78, 0x63, 0x78, 0xCA, 0x4E, 0x31, 0x1C, 0x01, 0x39, 0x01, 0x25, 0xAE, 0x46, 0xC7, 0x4F, 0xFE, 0x44, 0x38, 0x47, 0xA2, 0x78, 0xE3, 0x78, 0x03, 0x20, 0x31, 0x1C, 0xAE, 0x46, 0xC3, 0x4F, 0xFE, 0x44, 0x38, 0x47, 0x03, 0x20, 0x31, 0x1C, 0x01, 0x31, 0xAE, 0x46, 0xC1, 0x4A, 0xFE, 0x44, 0x10, 0x47, 0xC1, 0x48, 0x21, 0x78, 0x01, 0x70, 0x61, 0x78, 0x41, 0x70, 0xE1, 0x78, 0xC1, 0x70, 0xA1, 0x78, 0x81, 0x70, 0xBF, 0x48, 0x04, 0x1C, 0x33, 0x3C, 0x20, 0x1C, 0x00, 0x21, 0xDC, 0x22, 0xAE, 0x46 ,
-0xBA, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x84, 0x20, 0xA0, 0x70, 0x05, 0x27, 0xE7, 0x71, 0x0C, 0x26, 0x26, 0x73, 0x0D, 0x20, 0x00, 0x19, 0x98, 0xA1, 0x32, 0x1C, 0xAE, 0x46, 0xB4, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x04, 0x20, 0x60, 0x76, 0x1A, 0x20, 0x00, 0x19, 0x97, 0xA1, 0x06, 0x91, 0x04, 0x22, 0xAE, 0x46, 0xAE, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0xFF, 0xFF, 0x96, 0x00, 0x18, 0x00, 0x96, 0x00, 0x00, 0x00, 0xA7, 0x77, 0x1F, 0x34, 0x95, 0xA1, 0x07, 0x91, 0x20, 0x1C, 0x3A, 0x1C, 0xAE, 0x46, 0xA9, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0xE6, 0x71, 0x28, 0x1C, 0x60, 0x72, 0x11, 0x20, 0x20, 0x73, 0x94, 0x20, 0x60, 0x73, 0xC0, 0x25, 0x65, 0x74, 0xA6, 0x74, 0x09, 0x22, 0xE2, 0x74, 0xA3, 0x4C, 0x20, 0x1C, 0x8C, 0xA1, 0x01, 0x23, 0x9E, 0x46, 0x9F, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x07, 0x22, 0x62, 0x72, 0x9E, 0x4C, 0x0A, 0x34, 0x20, 0x1C, 0x89, 0xA1, 0x01, 0x23, 0x9E, 0x46, 0x9A, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x04, 0x20 ,
-0xE0, 0x71, 0x98, 0x4C, 0x12, 0x34, 0x20, 0x1C, 0x06, 0x99, 0x04, 0x22, 0x01, 0x23, 0x9E, 0x46, 0x94, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x27, 0x71, 0x93, 0x4C, 0x17, 0x34, 0x20, 0x1C, 0x07, 0x99, 0x3A, 0x1C, 0x01, 0x23, 0x9E, 0x46, 0x8E, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0xE6, 0x71, 0x01, 0x20, 0x60, 0x72, 0x11, 0x20, 0x20, 0x73, 0x94, 0x20, 0x60, 0x73, 0x02, 0x20, 0xE0, 0x73, 0x25, 0x74, 0x66, 0x74, 0xFF, 0xFF, 0x2C, 0x01, 0x18, 0x00, 0x96, 0x00, 0x00, 0x00, 0xA5, 0x74, 0x2F, 0x27, 0xE7, 0x74, 0x10, 0x20, 0x60, 0x75, 0x80, 0x26, 0xA6, 0x75, 0x01, 0x20, 0xE0, 0x75, 0x11, 0x20, 0xA0, 0x76, 0x94, 0x20, 0xE0, 0x76, 0x24, 0x20, 0x60, 0x77, 0x0A, 0x22, 0xA2, 0x77, 0x80, 0x4C, 0x36, 0x34, 0x20, 0x1C, 0x6D, 0xA1, 0x01, 0x23, 0x9E, 0x46, 0x7C, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x18, 0x22, 0xA2, 0x72, 0x7A, 0x4C, 0x41, 0x34, 0x20, 0x1C, 0x6B, 0xA1, 0x01, 0x23, 0x9E, 0x46, 0x76, 0x4B, 0xFE, 0x44, 0x18, 0x47 ,
-0x25, 0x76, 0x67, 0x76, 0x21, 0x20, 0xE0, 0x76, 0x26, 0x77, 0x01, 0x20, 0x60, 0x77, 0x72, 0x48, 0x61, 0x30, 0x11, 0x21, 0x01, 0x70, 0x94, 0x21, 0x41, 0x70, 0x04, 0x21, 0x01, 0x72, 0xD2, 0x21, 0x41, 0x72, 0xC5, 0x72, 0x1E, 0x21, 0x01, 0x73, 0x45, 0x73, 0x9E, 0x21, 0x81, 0x73, 0x01, 0x21, 0x01, 0x74, 0x46, 0x74, 0x81, 0x74, 0x11, 0x21, 0x41, 0x75, 0x94, 0x21, 0x81, 0x75, 0x04, 0x21, 0x01, 0x76, 0xAD, 0x20, 0x66, 0x49, 0x08, 0x60, 0x00, 0x24, 0x0F, 0x25, 0xFF, 0xFF, 0xC2, 0x01, 0x18, 0x00, 0x96, 0x00, 0x00, 0x00, 0x29, 0x06, 0x09, 0x0E, 0x00, 0x20, 0x6A, 0x46, 0x01, 0x23, 0x9E, 0x46, 0x62, 0x4B, 0xFE, 0x44, 0x18, 0x47, 0x6B, 0x46, 0x18, 0x88, 0x40, 0x08, 0x0E, 0xD3, 0xA0, 0x00, 0x0F, 0x21, 0xCA, 0x43, 0x69, 0x46, 0x0E, 0x88, 0x16, 0x40, 0x01, 0xAF, 0x3E, 0x52, 0x49, 0x88, 0x11, 0x40, 0x68, 0x44, 0xC1, 0x80, 0x60, 0x1C, 0x04, 0x04, 0x24, 0x0C, 0x01, 0x3D, 0x0B, 0x2D, 0xE0, 0xDA, 0x60, 0x1E ,
-0x00, 0x04, 0x00, 0x0C, 0x1D, 0xD0, 0x86, 0x46, 0x01, 0x1C, 0x01, 0xAD, 0x01, 0x22, 0xAE, 0x88, 0x90, 0x00, 0xC7, 0x5A, 0xB7, 0x42, 0x0A, 0xDA, 0xBC, 0x46, 0x07, 0x1C, 0x6F, 0x44, 0x7F, 0x88, 0x68, 0x44, 0x06, 0x80, 0xEE, 0x88, 0x46, 0x80, 0x60, 0x46, 0xA8, 0x80, 0xEF, 0x80, 0x04, 0x35, 0x50, 0x1C, 0x02, 0x04, 0x12, 0x0C, 0x01, 0x39, 0xE9, 0xD1, 0x70, 0x46, 0x01, 0x38, 0x86, 0x46, 0xE2, 0xD1, 0x99, 0x88, 0x68, 0x46, 0xC0, 0x88, 0x40, 0x18, 0x00, 0x04, 0x00, 0x0C, 0x42, 0x4B, 0x18, 0x80, 0x42, 0x49, 0x08, 0x1A, 0xFF, 0xFF, 0x58, 0x02, 0x18, 0x00, 0x96, 0x00, 0x00, 0x00, 0x58, 0x80, 0x02, 0x2C, 0x1E, 0xDB, 0x65, 0x1E, 0x01, 0xAA, 0x01, 0x20, 0x01, 0x1C, 0x8C, 0x00, 0x6B, 0x46, 0xE6, 0x5A, 0x93, 0x88, 0xD4, 0x88, 0xE7, 0x18, 0xB7, 0x42, 0x0C, 0xDA, 0x06, 0x24, 0x44, 0x43, 0x38, 0x4B, 0x1B, 0x19, 0x1F, 0x80, 0x1C, 0x88, 0x34, 0x1B, 0x5C, 0x80, 0x01, 0x24, 0x1C, 0x71, 0x40, 0x1C, 0x00, 0x04 ,
-0x00, 0x0C, 0x04, 0x32, 0x49, 0x1C, 0x09, 0x06, 0x09, 0x0E, 0x01, 0x3D, 0xE4, 0xD1, 0x00, 0x24, 0x31, 0x48, 0x04, 0x70, 0x31, 0x48, 0x04, 0x70, 0x31, 0x48, 0x04, 0x70, 0x31, 0x48, 0x04, 0x70, 0x01, 0x20, 0x86, 0x46, 0x30, 0x48, 0xFE, 0x44, 0x00, 0x47, 0x2F, 0x49, 0x22, 0x1C, 0x08, 0x68, 0x00, 0x28, 0x02, 0xD0, 0x01, 0x20, 0x90, 0x40, 0x04, 0x43, 0x04, 0x31, 0x01, 0x32, 0x20, 0x2A, 0xF5, 0xD3, 0x2A, 0x48, 0x04, 0x60, 0x08, 0xB0, 0xF0, 0xBD, 0x5F, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x2D, 0x69, 0x6E, 0x66, 0x6F, 0x00, 0xC0, 0x46, 0xC0, 0x5F, 0x75, 0x64, 0x70, 0x00, 0xC0, 0xFF, 0xFF, 0xEE, 0x02, 0x18, 0x00, 0x96, 0x00, 0x00, 0x00, 0x46, 0xC0, 0x6C, 0x6F, 0x63, 0x61, 0x6C, 0x00, 0xC0, 0x46, 0x5F, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x00, 0xC0, 0x46, 0x5F, 0x64, 0x6E, 0x73, 0x2D, 0x73, 0x64, 0x00, 0x64, 0x65, 0x76, 0x3D, 0x43, 0x43, 0x33, 0x30, 0x30, 0x30, 0x00, 0xC0, 0x76, 0x65 ,
-0x6E, 0x64, 0x6F, 0x72, 0x3D, 0x54, 0x65, 0x78, 0x61, 0x73, 0x2D, 0x49, 0x6E, 0x73, 0x74, 0x72, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x73, 0x00, 0xC0, 0x46, 0xC0, 0x00, 0x00, 0x18, 0x00, 0xF3, 0x7E, 0x03, 0x00, 0xC6, 0x05, 0x00, 0x00, 0xDD, 0x7E, 0x03, 0x00, 0xE4, 0x62, 0x08, 0x00, 0xC9, 0xBA, 0x03, 0x00, 0x09, 0xB4, 0x03, 0x00, 0xA7, 0x64, 0x08, 0x00, 0x70, 0x64, 0x08, 0x00, 0xDD, 0x0A, 0x02, 0x00, 0x48, 0x32, 0x08, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0xE8, 0x62, 0x08, 0x00, 0xE9, 0x62, 0x08, 0x00, 0xEA, 0x62, 0x08, 0x00, 0xEB, 0x62, 0x08, 0x00, 0x81, 0x03, 0x18, 0x00, 0x80, 0x7B, 0x08, 0x00, 0x84, 0xF3, 0x1A, 0x00, 0x0D, 0x49, 0x0E, 0x48, 0xFF, 0xFF, 0x84, 0x03, 0x18, 0x00, 0x6C, 0x00, 0x00, 0x00, 0x88, 0x67, 0x0E, 0x48, 0x88, 0x64, 0x0E, 0x48, 0x48, 0x64, 0x0E, 0x48, 0xC8, 0x64, 0x0E, 0x48, 0x08, 0x65, 0x11, 0x48, 0x02, 0x1C, 0x04, 0x32, 0x0C, 0x4B, 0x13, 0x60, 0x0C, 0x4B, 0x93, 0x62, 0x0C, 0x4A ,
-0x8A, 0x66, 0x0D, 0x49, 0x01, 0x60, 0x0D, 0x48, 0x0E, 0x49, 0x01, 0x60, 0x0E, 0x49, 0x41, 0x60, 0xF7, 0x46, 0x1C, 0x21, 0x08, 0x00, 0x1B, 0x7B, 0x08, 0x00, 0x11, 0x7B, 0x08, 0x00, 0x07, 0x7B, 0x08, 0x00, 0x39, 0x7B, 0x08, 0x00, 0x2F, 0x7B, 0x08, 0x00, 0x25, 0x7B, 0x08, 0x00, 0xFD, 0x7A, 0x08, 0x00, 0xDF, 0x7A, 0x08, 0x00, 0x50, 0x23, 0x08, 0x00, 0xD5, 0x7A, 0x08, 0x00, 0x58, 0x26, 0x08, 0x00, 0xF3, 0x7A, 0x08, 0x00, 0xE9, 0x7A, 0x08, 0x00 };
-
-
-const unsigned char cRMdefaultParams[128] = { 0x03, 0x00, 0x01, 0x01, 0x14, 0x14, 0x00, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x23, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x23, 0x23, 0x23, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x01, 0x77, 0x80, 0x1D, 0x1F, 0x22, 0x26, 0x28, 0x29, 0x1A, 0x1F, 0x22, 0x24, 0x26, 0x28, 0x16, 0x1D, 0x1E, 0x20, 0x24, 0x25, 0x1E, 0x2D, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x15, 0x15, 0x15, 0x11, 0x15, 0x15, 0x0E, 0x00};
-
-//
-//Service Pack version P1.13.7.15.15 - FW patches
-//
-const unsigned char fw_patch[5700] = { 0x00, 0x01, 0x00, 0x00, 0x3C, 0x16, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x14, 0x03, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x68, 0x46, 0x25, 0xF0, 0x95, 0xFB, 0xE0, 0x6B, 0xD0, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x25, 0xF0, 0x38, 0xFB, 0x2C, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x25, 0xF0, 0x0A, 0xFB, 0x04, 0x15, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xB8, 0xF1, 0x90, 0x0F, 0xA4, 0x16, 0x00, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x66, 0xE0, 0x04, 0xA8, 0x35, 0x1D, 0x21, 0xF0, 0x99, 0xFC, 0x68, 0x46, 0x23, 0xF0, 0x28, 0xFB, 0x9A, 0xF8, 0x00, 0x00, 0x01, 0x28, 0x07, 0xD1, 0x28, 0x46, 0x05, 0xF0, 0xC3, 0xFE, 0x01, 0x46, 0x01, 0xAA, 0x00, 0x20, 0x21, 0xF0, 0x50, 0xF9, 0x28, 0x46, 0x05, 0xF0, 0xBB, 0xFE, 0x01, 0xA9, 0x21, 0xF0, 0x2A, 0xFA, 0xE9, 0x79, 0x4F, 0xEA, 0xE0, 0x00, 0x40, 0xB2, 0x11, 0xB1, 0x00, 0xF1, 0x06, 0x00, 0x40, 0xB2, 0xA8, 0x71, 0x1F, 0x38, 0x40, 0x00, 0xE8, 0x71, 0x30, 0x46 ,
-0x01, 0xF0, 0x0D, 0xFF, 0x10, 0xF1, 0x00, 0x09, 0x4F, 0xF0, 0x00, 0x01, 0x09, 0xD0, 0x28, 0x68, 0x40, 0x0C, 0x09, 0xD3, 0xE8, 0x68, 0xC0, 0x0B, 0x03, 0xD2, 0x48, 0x46, 0xFF, 0xF7, 0xDD, 0xFE, 0x01, 0x21, 0x28, 0x68, 0x40, 0x0C, 0x0A, 0xD2, 0x38, 0x68, 0x40, 0x1C, 0x38, 0x60, 0x20, 0x68, 0x6F, 0xF3, 0x0F, 0x00, 0x20, 0x60, 0x22, 0x68, 0x38, 0x68, 0x10, 0x43, 0x20, 0x60, 0xE8, 0x68, 0xC0, 0x0B, 0x0F, 0xD3, 0xD8, 0xF8, 0x00, 0x00, 0x00, 0xF1, 0x01, 0x00, 0xC8, 0xF8, 0x00, 0x00, 0x20, 0x68, 0x6F, 0xF3, 0x1F, 0x40, 0x20, 0x60, 0xD8, 0xF8, 0x00, 0x20, 0x20, 0x68, 0x40, 0xEA, 0x02, 0x40, 0x20, 0x60, 0x49, 0xB9, 0xB9, 0xF1, 0x00, 0x0F, 0x03, 0xD1, 0x30, 0x46, 0x07, 0xF0, 0xBE, 0xF9, 0x02, 0xE0, 0x48, 0x46, 0x07, 0xF0, 0x06, 0xFA, 0x6C, 0x17, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x68, 0x46, 0x0E, 0xF0, 0x85, 0xFB, 0x00, 0x9E, 0x00, 0x2E, 0x96, 0xD1, 0x05, 0xB0, 0xBD, 0xE8, 0xF0, 0x87, 0xC0, 0x46 ,
-0x9C, 0x20, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x23, 0xF0, 0x2A, 0xFE, 0x74, 0x47, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0B, 0x21, 0x21, 0xF0, 0x41, 0xFA, 0x20, 0x68, 0x18, 0x4B, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x21, 0xF0, 0x1C, 0xF9, 0x0A, 0xE0, 0x20, 0x68, 0x00, 0x68, 0x0C, 0x21, 0x40, 0xF0, 0x20, 0x00, 0x21, 0xF0, 0x14, 0xF9, 0x10, 0x57, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0xA8, 0x20, 0xF0, 0x97, 0xF9, 0x01, 0x98, 0x5C, 0x57, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0xA8, 0x20, 0xF0, 0x71, 0xF9, 0x03, 0x98, 0x00, 0x58, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0xF0, 0x20, 0xF9, 0x1C, 0x58, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0xF0, 0x12, 0xF9, 0x54, 0x58, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0xA8, 0x20, 0xF0, 0xF5, 0xF8, 0x04, 0xAB, 0x04, 0x62, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x20, 0x79, 0x1F, 0xF0, 0x1B, 0xFD, 0x69, 0xE0, 0x60, 0x93, 0x00, 0x00, 0x40, 0x00 ,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0xA6, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x78, 0x1B, 0xF0, 0x39, 0xFB, 0x28, 0x46, 0x90, 0xA8, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x78, 0x1B, 0xF0, 0x69, 0xF9, 0x1E, 0x48, 0x34, 0xAD, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x09, 0x68, 0xFF, 0x29, 0x98, 0xAD, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x10, 0xD4, 0x21, 0xD4, 0xB2, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0xD0, 0x1A, 0xF0, 0x47, 0xFC, 0x20, 0x98, 0xAC, 0xC5, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x78, 0x19, 0xF0 ,
-0xDB, 0xFA, 0x09, 0x49, 0x28, 0xC6, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x19, 0xF0, 0x9E, 0xFA, 0xDC, 0xD3, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0xB5, 0x18, 0xF0, 0xAB, 0xFC, 0x00, 0xF0, 0x03, 0xF8, 0x00, 0xBD, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xDF, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x17, 0xF0, 0xA8, 0xFD, 0xCC, 0xEB, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x38, 0x78, 0x17, 0xF0, 0x77, 0xF8, 0x38, 0x78, 0x16, 0xF0, 0xF0, 0xFF, 0xA8, 0xF7, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0E, 0x49, 0x09, 0x68, 0x23, 0x22, 0x41, 0x61, 0xC8, 0xF7, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x31, 0x2E, 0x31, 0x39, 0x2E, 0x33, 0x31, 0x34, 0x5F, 0x4E, 0x65, 0x77, 0x5F, 0x43, 0x43, 0x41, 0x5F, 0x61, 0x6C, 0x67, 0x6F, 0x72, 0x69, 0x74, 0x68, 0x6D, 0x00, 0xC0, 0x74, 0x56, 0x30, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4C, 0xF9, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0xA8, 0x16, 0xF0, 0x79, 0xF8 ,
-0x12, 0xE0, 0x38, 0xFA, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0xA8, 0x16, 0xF0, 0x03, 0xF8, 0x32, 0x20, 0x94, 0xFB, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x0C, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, 0x05, 0xA8, 0x14, 0xF0, 0x05, 0xFF, 0x01, 0xF0, 0x10, 0x1B, 0x01, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x1E, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x13, 0xF0, 0x46, 0xBF, 0x18, 0x30, 0x01, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x30, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x12, 0xF0, 0xD8, 0xFC, 0x9C, 0x31, 0x01, 0x00, 0x08, 0x00 ,
-0x00, 0x00, 0x68, 0x46, 0x12, 0xF0, 0x51, 0xFC, 0xFE, 0xF7, 0xF0, 0x35, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, 0x68, 0x46, 0x12, 0xF0, 0x27, 0xFA, 0xFE, 0xF7, 0xF0, 0x3D, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, 0x05, 0xA9, 0x11, 0xF0, 0x27, 0xFE, 0x20, 0x6F, 0xD0, 0x62, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0F, 0xF0, 0xB8, 0xFB, 0x80, 0x7E, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0xDF, 0xF8, 0x58, 0x82, 0xE0, 0x7E, 0x01, 0x00, 0x18, 0x00, 0x00, 0x00, 0x0D, 0xF0, 0x6A, 0xFE, 0x0B, 0xF0, 0x9A, 0xF9, 0x03, 0x20, 0xA8, 0xF5, 0x88, 0x71, 0x08, 0x60, 0xF2, 0xF7, 0x16, 0xF9, 0x7A, 0x48, 0x6B, 0x49, 0x9C, 0x7F, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x70, 0x51, 0x4D, 0xC4, 0x7F, 0x01, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x40, 0x49, 0x00, 0xF1, 0x52, 0x00, 0x3A, 0x4A, 0xA8, 0x81, 0x28, 0x83, 0xE8, 0x83, 0xE8, 0x84, 0xA8, 0x85, 0x2A, 0x60, 0x39, 0x48, 0x41, 0xF2, 0x11, 0x12, 0x2A, 0x85, 0x18, 0x90, 0x19, 0x91 ,
-0x39, 0x49, 0x1A, 0x91, 0x39, 0x49, 0x1B, 0x91, 0x39, 0x49, 0x20, 0x46, 0xDF, 0xF8, 0xC4, 0x90, 0x1C, 0x91, 0x38, 0x49, 0xDF, 0xF8, 0xC0, 0xB0, 0x31, 0x4E, 0x1D, 0x91, 0x48, 0x80, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0D, 0xF0, 0x7C, 0xFA, 0xB4, 0x80, 0x01, 0x00, 0x34, 0x00, 0x00, 0x00, 0x34, 0x12, 0x66, 0x09, 0x84, 0x6B, 0x00, 0x20, 0x94, 0x70, 0x00, 0x20, 0xB4, 0x70, 0x00, 0x20, 0xC4, 0x78, 0x00, 0x20, 0x50, 0x7A, 0x00, 0x20, 0xFE, 0xFF, 0x03, 0x00, 0xA4, 0x70, 0x00, 0x20, 0xB0, 0x70, 0x00, 0x20, 0xB8, 0x70, 0x00, 0x20, 0x60, 0x55, 0x30, 0x80, 0x3C, 0x5C, 0x00, 0x20, 0x04, 0x74, 0x00, 0x20, 0xB8, 0xE4, 0x01, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x20, 0x78, 0x07, 0xF0, 0x01, 0xFC, 0x20, 0x78, 0x07, 0xF0, 0x7A, 0xFB, 0x04, 0x4D, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0xAD, 0xF1, 0x8C, 0x0D, 0x04, 0x68, 0x0F, 0x30, 0x03, 0x94, 0xFE, 0xF7, 0xDB, 0xFA, 0x04, 0xF1, 0x14, 0x00 ,
-0x04, 0x90, 0x21, 0x7D, 0x00, 0x20, 0x21, 0xF0, 0x73, 0x01, 0x88, 0x29, 0x08, 0xBF, 0x01, 0x20, 0x05, 0x90, 0x03, 0x98, 0x00, 0x1D, 0x06, 0x90, 0x5D, 0x48, 0x00, 0x68, 0x01, 0x28, 0x40, 0xF0, 0xFA, 0x83, 0x5B, 0x4D, 0x5C, 0x48, 0xDF, 0xF8, 0x70, 0x91, 0x29, 0x68, 0xDF, 0xF8, 0x70, 0x81, 0xDF, 0xF8, 0x74, 0xA1, 0x88, 0x42, 0x21, 0xD1, 0x10, 0x22, 0x00, 0x21, 0x48, 0x46, 0x4F, 0x46, 0xFB, 0xF7, 0xB7, 0xFE, 0x10, 0x22, 0x00, 0x21, 0x40, 0x46, 0xFB, 0xF7, 0xB2, 0xFE, 0x54, 0x49, 0x08, 0x68, 0x40, 0xF4, 0x80, 0x10, 0x08, 0x60, 0x01, 0x20, 0x51, 0x46, 0x08, 0x60, 0x00, 0x21, 0x29, 0x60, 0x39, 0x78, 0x46, 0x46, 0x00, 0x91, 0x31, 0x78, 0x41, 0xF2, 0x11, 0x13, 0x04, 0x22, 0x01, 0x91, 0x07, 0x21, 0x02, 0x90, 0x03, 0x20, 0xF3, 0xF7, 0x41, 0xFC, 0x51, 0x46, 0x07, 0x91, 0x08, 0x68, 0x56, 0x49, 0xDF, 0xF8, 0x5C, 0xB1, 0x01, 0x28, 0x08, 0x91, 0x56, 0x49, 0xDF, 0xF8, 0x48, 0xA1, 0x09, 0x91, 0x55, 0x49 ,
-0x0A, 0x91, 0x44, 0x49, 0x0B, 0x91, 0x44, 0x49, 0x0C, 0x91, 0x44, 0x49, 0x0D, 0x91, 0x44, 0x49, 0x0E, 0x91, 0x44, 0x49, 0x0F, 0x91, 0x44, 0x49, 0x10, 0x91, 0x44, 0x49, 0xCC, 0x4D, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x11, 0x91, 0x44, 0x49, 0x12, 0x91, 0x44, 0x49, 0x13, 0x91, 0x44, 0x49, 0x14, 0x91, 0x44, 0x49, 0x15, 0x91, 0x44, 0x49, 0x16, 0x91, 0x9F, 0x49, 0x17, 0x91, 0x9F, 0x49, 0x18, 0x91, 0x9F, 0x49, 0x19, 0x91, 0x9F, 0x49, 0x1A, 0x91, 0x9F, 0x49, 0x1B, 0x91, 0x9F, 0x49, 0x1C, 0x91, 0x9F, 0x49, 0x1D, 0x91, 0x9F, 0x49, 0x1E, 0x91, 0x9F, 0x49, 0x1F, 0x91, 0x40, 0xF0, 0x00, 0x81, 0x04, 0x98, 0x40, 0x78, 0x00, 0xF0, 0x03, 0x01, 0x01, 0x29, 0x40, 0xF0, 0xF9, 0x80, 0x04, 0x99, 0x09, 0x78, 0x01, 0xF0, 0x0C, 0x01, 0x08, 0x29, 0x40, 0xF0, 0xF2, 0x80, 0x06, 0x99, 0x09, 0x88, 0xA1, 0xF1, 0x3C, 0x01, 0x0E, 0xB2, 0x05, 0x99, 0x11, 0xB1, 0xA6, 0xF1, 0x02, 0x06, 0x36, 0xB2, 0xC0, 0x09, 0x4F, 0xF0 ,
-0x00, 0x07, 0x15, 0xD3, 0x08, 0x3E, 0x36, 0xB2, 0x03, 0x2E, 0x10, 0xD0, 0x17, 0x2E, 0x0E, 0xD0, 0x08, 0x3E, 0x36, 0xB2, 0x03, 0x2E, 0x08, 0xD0, 0x17, 0x2E, 0x06, 0xD0, 0x36, 0x1F, 0x36, 0xB2, 0x03, 0x2E, 0x14, 0xBF, 0x17, 0x2E, 0x02, 0x27, 0x02, 0xE0, 0x03, 0x27, 0x00, 0xE0, 0x01, 0x27, 0x03, 0x2E, 0x18, 0xBF, 0x17, 0x2E, 0x04, 0x9A, 0x40, 0xF0, 0xC8, 0x80, 0x0A, 0x32, 0x12, 0xF8, 0x01, 0x1B, 0x05, 0x24, 0x12, 0xF8, 0x01, 0x3B, 0x4B, 0x40, 0x64, 0x1E, 0xD9, 0xB2, 0xF9, 0xD1, 0x81, 0xEA, 0x21, 0x11, 0x03, 0x2E, 0x94, 0x4E, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x01, 0xF0, 0x0F, 0x01, 0x48, 0x46, 0x35, 0xD0, 0x43, 0x46, 0xCA, 0x5C, 0x52, 0x1C, 0xCA, 0x54, 0x0C, 0x18, 0x33, 0xE0, 0x50, 0x57, 0x02, 0x00, 0x04, 0x74, 0x00, 0x20, 0x34, 0x12, 0x66, 0x09, 0x60, 0x57, 0x02, 0x00, 0x70, 0x57, 0x02, 0x00, 0xC8, 0x48, 0x30, 0x80, 0x4C, 0x57, 0x02, 0x00, 0x88, 0x57, 0x02, 0x00, 0x80, 0x57, 0x02, 0x00 ,
-0x18, 0x58, 0x02, 0x00, 0x20, 0x58, 0x02, 0x00, 0x28, 0x58, 0x02, 0x00, 0x30, 0x58, 0x02, 0x00, 0x38, 0x58, 0x02, 0x00, 0x40, 0x58, 0x02, 0x00, 0xE4, 0x58, 0x02, 0x00, 0xE2, 0x58, 0x02, 0x00, 0x14, 0x58, 0x02, 0x00, 0xEF, 0x58, 0x02, 0x00, 0xE0, 0x58, 0x02, 0x00, 0xEE, 0x58, 0x02, 0x00, 0x5C, 0x57, 0x02, 0x00, 0xE6, 0x58, 0x02, 0x00, 0xE8, 0x58, 0x02, 0x00, 0x0C, 0x18, 0x20, 0x78, 0x40, 0x1C, 0x20, 0x70, 0x20, 0x78, 0x43, 0x46, 0x03, 0xEB, 0x01, 0x08, 0x0A, 0x28, 0x76, 0xDB, 0x98, 0xF8, 0x00, 0x00, 0x0A, 0x28, 0x72, 0xDB, 0x94, 0x48, 0x00, 0x25, 0x01, 0x60, 0x04, 0x98, 0x00, 0xF1, 0x0A, 0x09, 0x40, 0x78, 0x41, 0x08, 0x24, 0xBF, 0x04, 0x99, 0x09, 0x1D, 0x04, 0xD2, 0x80, 0x08, 0x2E, 0xBF, 0x49, 0x46, 0x04, 0x99, 0x10, 0x31, 0x0B, 0x98, 0x06, 0x22, 0xFA, 0xF7, 0xB9, 0xFC, 0x0C, 0x98, 0x06, 0x22, 0x49, 0x46, 0xFA, 0xF7, 0xB4, 0xFC, 0x9B, 0x48, 0x9A, 0x49, 0x5C, 0x4F, 0x02, 0x00, 0xC8, 0x00 ,
-0x00, 0x00, 0x00, 0x78, 0x08, 0x22, 0x08, 0x60, 0x58, 0x46, 0x07, 0x60, 0x0D, 0x98, 0x29, 0x46, 0xFB, 0xF7, 0xAF, 0xFD, 0x08, 0x22, 0x0E, 0x98, 0x29, 0x46, 0xFB, 0xF7, 0xAA, 0xFD, 0x08, 0x22, 0x0F, 0x98, 0x29, 0x46, 0xFB, 0xF7, 0xA5, 0xFD, 0x08, 0x22, 0x10, 0x98, 0x29, 0x46, 0xFB, 0xF7, 0xA0, 0xFD, 0x08, 0x22, 0x11, 0x98, 0x29, 0x46, 0xFB, 0xF7, 0x9B, 0xFD, 0x08, 0x22, 0x12, 0x98, 0x29, 0x46, 0xFB, 0xF7, 0x96, 0xFD, 0x07, 0x99, 0x02, 0x20, 0x08, 0x60, 0x13, 0x99, 0x28, 0x46, 0x08, 0x80, 0x08, 0x99, 0x08, 0x70, 0x14, 0x99, 0x08, 0x70, 0x15, 0x99, 0x08, 0x60, 0x16, 0x99, 0x08, 0x70, 0x17, 0x99, 0x08, 0x60, 0x18, 0x99, 0x08, 0x60, 0x19, 0x99, 0x08, 0x60, 0x09, 0x99, 0x08, 0x80, 0x0A, 0x99, 0x08, 0x80, 0x1A, 0x99, 0x08, 0x80, 0x7D, 0x49, 0x0D, 0x60, 0x1B, 0x99, 0x08, 0x70, 0x1C, 0x99, 0x08, 0x70, 0x1D, 0x99, 0x08, 0x70, 0x1E, 0x99, 0x08, 0x80, 0x1F, 0x99, 0x08, 0x80, 0x51, 0x46, 0x08, 0x80 ,
-0x20, 0x78, 0x00, 0x96, 0x04, 0x22, 0x01, 0x90, 0x98, 0xF8, 0x00, 0x00, 0x41, 0xF2, 0x14, 0x13, 0x07, 0x21, 0x02, 0x90, 0x03, 0x20, 0xF3, 0xF7, 0x07, 0xFB, 0x07, 0x98, 0xA2, 0x49, 0x00, 0x68, 0x20, 0x91, 0xA2, 0x49, 0x05, 0x28, 0x21, 0x91, 0x9E, 0x49, 0x22, 0x91, 0x40, 0xF0, 0x37, 0x82, 0x04, 0x98, 0x40, 0x78, 0x24, 0x50, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x41, 0x08, 0x24, 0xBF, 0x04, 0x99, 0x09, 0x1D, 0x05, 0xD2, 0x80, 0x08, 0x27, 0xBF, 0x04, 0x99, 0x0A, 0x31, 0x04, 0x99, 0x10, 0x31, 0x0B, 0x98, 0xF8, 0xF7, 0x2D, 0xFC, 0x01, 0x28, 0x04, 0x98, 0x40, 0xF0, 0x23, 0x82, 0x40, 0x78, 0x00, 0xF0, 0x03, 0x00, 0x03, 0x28, 0x18, 0xD0, 0x02, 0x28, 0x07, 0xBF, 0x04, 0x99, 0x10, 0x31, 0x04, 0x99, 0x0A, 0x31, 0x13, 0xE0, 0x48, 0x58, 0x02, 0x00, 0x4C, 0x58, 0x02, 0x00, 0x50, 0x58, 0x02, 0x00, 0xF0, 0x58, 0x02, 0x00, 0xF2, 0x58, 0x02, 0x00, 0xF3, 0x58, 0x02, 0x00, 0xF4, 0x58, 0x02, 0x00, 0xEA, 0x58 ,
-0x02, 0x00, 0xEC, 0x58, 0x02, 0x00, 0x04, 0x99, 0x18, 0x31, 0x0C, 0x98, 0xF8, 0xF7, 0x06, 0xFC, 0x04, 0x99, 0x01, 0x28, 0x40, 0xF0, 0xFC, 0x81, 0x49, 0x78, 0x01, 0xF0, 0x03, 0x01, 0x01, 0x29, 0x40, 0xF0, 0xF6, 0x81, 0x59, 0x46, 0x09, 0x68, 0x04, 0x9A, 0x8E, 0x46, 0x51, 0x46, 0xD2, 0x8A, 0x0B, 0x88, 0x12, 0x11, 0x93, 0x42, 0x00, 0xF0, 0x37, 0x82, 0x0A, 0x80, 0x06, 0x99, 0x09, 0x88, 0x3C, 0x39, 0x0B, 0xB2, 0x71, 0x46, 0x49, 0x1E, 0x09, 0xD0, 0x49, 0x1E, 0x04, 0xD0, 0x49, 0x1E, 0x08, 0xD1, 0xA3, 0xF1, 0x10, 0x03, 0x04, 0xE0, 0xA3, 0xF1, 0x14, 0x03, 0x01, 0xE0, 0xA3, 0xF1, 0x08, 0x03, 0x1B, 0xB2, 0x05, 0x98, 0x10, 0xB1, 0xA3, 0xF1, 0x02, 0x03, 0x1B, 0xB2, 0xEC, 0x50, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x00, 0x2B, 0x00, 0xF1, 0xCE, 0x81, 0x16, 0x98, 0x40, 0xF2, 0x77, 0x51, 0x99, 0x42, 0x0B, 0x90, 0x14, 0x98, 0x05, 0x90, 0x00, 0xF0, 0xA3, 0x81, 0x08, 0x46, 0x00, 0xF1, 0x3C, 0x00, 0x98, 0x42 ,
-0x05, 0x9A, 0x00, 0xF0, 0x9A, 0x81, 0xDF, 0xF8, 0x48, 0x82, 0x14, 0x78, 0x0B, 0x9A, 0xBB, 0x2C, 0x12, 0x78, 0x0C, 0x92, 0x63, 0xD1, 0xDD, 0xF8, 0x68, 0xC0, 0xBC, 0xF9, 0x00, 0x20, 0x91, 0x42, 0x18, 0xBF, 0x90, 0x42, 0x5B, 0xD1, 0x1C, 0x2B, 0x4F, 0xF0, 0x00, 0x00, 0xC0, 0xF2, 0x82, 0x81, 0x3D, 0x2B, 0x13, 0x9D, 0x80, 0xF2, 0x7E, 0x81, 0xA3, 0xF1, 0x1C, 0x01, 0x09, 0xB2, 0x29, 0x80, 0x1E, 0x9A, 0xDD, 0xF8, 0x30, 0x90, 0xB2, 0xF9, 0x00, 0x60, 0xB9, 0xF1, 0x01, 0x0F, 0x15, 0xD1, 0xDD, 0xF8, 0x24, 0x90, 0x03, 0x2E, 0x0D, 0xDA, 0xB9, 0xF9, 0x00, 0x70, 0xB9, 0x42, 0x07, 0xD0, 0x01, 0x26, 0x16, 0x80, 0x4A, 0x46, 0x0E, 0x46, 0x03, 0xE0, 0xC0, 0x46, 0x90, 0x57, 0x02, 0x00, 0x76, 0x1C, 0x16, 0x80, 0x1B, 0x9A, 0x16, 0x78, 0x1D, 0x9A, 0x16, 0x70, 0x0C, 0x9A, 0x1F, 0x9E, 0x02, 0x2A, 0x28, 0xD1, 0xB6, 0xF9, 0x00, 0x20, 0xBE, 0xF1, 0x00, 0x0F, 0x1A, 0xD0, 0x03, 0x2A, 0x35, 0x46, 0x0B, 0xDA, 0x0A, 0x9E ,
-0xB6, 0xF9, 0x00, 0x70, 0xB9, 0x42, 0x04, 0xD0, 0x01, 0x22, 0x2A, 0x80, 0x0A, 0x46, 0x35, 0x46, 0x00, 0xE0, 0xB4, 0x51, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x52, 0x1C, 0x2A, 0x80, 0x1C, 0x99, 0x0A, 0x78, 0x1D, 0x99, 0x0A, 0x70, 0x0F, 0xE0, 0xC0, 0x46, 0x58, 0x57, 0x02, 0x00, 0xA6, 0x64, 0x00, 0x20, 0x54, 0x57, 0x02, 0x00, 0x28, 0x80, 0x05, 0x99, 0x08, 0x70, 0x08, 0x9A, 0x11, 0x78, 0x41, 0xF0, 0x04, 0x01, 0x11, 0x70, 0x04, 0x46, 0x45, 0x46, 0xAC, 0xF8, 0x00, 0x00, 0x28, 0x70, 0xCC, 0x2C, 0x09, 0x9A, 0x40, 0xF0, 0x00, 0x81, 0xDD, 0xF8, 0x7C, 0xC0, 0x0A, 0x99, 0x1E, 0x9F, 0x45, 0x46, 0xB1, 0xF9, 0x00, 0x60, 0xB2, 0xF9, 0x00, 0x90, 0x28, 0x78, 0xCD, 0xF8, 0x50, 0xC0, 0x16, 0x91, 0x0A, 0x97, 0x13, 0x92, 0x09, 0x95, 0x0C, 0x99, 0x01, 0x29, 0x05, 0xD1, 0x05, 0x9A, 0xB0, 0xEB, 0x49, 0x0F, 0x01, 0xD1, 0x00, 0x21, 0x11, 0x70, 0x0C, 0x99, 0x02, 0x29, 0x05, 0xD1, 0x05, 0x9A, 0xB0, 0xEB, 0x46, 0x0F ,
-0x01, 0xD1, 0x00, 0x21, 0x11, 0x70, 0xB3, 0xF5, 0x14, 0x7F, 0x40, 0xF3, 0xBA, 0x80, 0x40, 0xF2, 0x51, 0x31, 0x99, 0x42, 0x08, 0x99, 0x40, 0xF3, 0xB4, 0x80, 0x09, 0x78, 0x06, 0x29, 0x00, 0xF0, 0xB0, 0x80, 0xA3, 0xF2, 0x51, 0x21, 0x0B, 0xB2, 0x4F, 0xEA, 0xE3, 0x01, 0x03, 0xEB, 0x11, 0x71, 0x4F, 0xEA, 0x21, 0x11, 0xCA, 0xB2, 0x4F, 0xEA, 0xE3, 0x01, 0x03, 0xEB, 0x11, 0x71, 0x15, 0x9D, 0x21, 0xF0, 0x0F, 0x01, 0xA3, 0xEB, 0x01, 0x03, 0x1D, 0x99, 0x2E, 0x68, 0x7C, 0x52, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x91, 0xF8, 0x00, 0xE0, 0x5F, 0xFA, 0x83, 0xF8, 0x60, 0xB1, 0x31, 0x18, 0x11, 0xF8, 0x01, 0x1C, 0x51, 0x40, 0xCB, 0xB2, 0x07, 0xE0, 0xC0, 0x46, 0x58, 0x58, 0x02, 0x00, 0x54, 0x58, 0x02, 0x00, 0xDC, 0x58, 0x02, 0x00, 0x13, 0x46, 0x19, 0x99, 0xDD, 0xF8, 0x6C, 0xA0, 0xDD, 0xF8, 0x70, 0xB0, 0xD1, 0xF8, 0x00, 0xC0, 0x00, 0xF0, 0x0F, 0x01, 0x99, 0x42, 0x22, 0xD0, 0x0A, 0x9B, 0x86, 0x45, 0x9A, 0xF8 ,
-0x00, 0x10, 0xB3, 0xF9, 0x00, 0x30, 0x9B, 0xF8, 0x00, 0x50, 0x15, 0xDD, 0x37, 0x5C, 0x44, 0x1C, 0x82, 0xEA, 0x07, 0x0C, 0x04, 0xF0, 0x0F, 0x07, 0x67, 0x45, 0x0B, 0xD0, 0xA6, 0x45, 0x06, 0x44, 0x0A, 0xDD, 0x76, 0x78, 0x72, 0x40, 0x86, 0x1C, 0x06, 0xF0, 0x0F, 0x06, 0x96, 0x42, 0x03, 0xD1, 0xC0, 0x1C, 0x4D, 0xE0, 0x80, 0x1C, 0x4B, 0xE0, 0x05, 0x9E, 0x00, 0x22, 0x32, 0x70, 0x4A, 0xE0, 0x00, 0xF0, 0x1F, 0x01, 0x01, 0x22, 0x8A, 0x40, 0x17, 0x99, 0xC4, 0x10, 0x0B, 0x68, 0x24, 0xF0, 0x03, 0x01, 0x5C, 0xF8, 0x01, 0x70, 0x3A, 0x42, 0x32, 0xD1, 0x5F, 0x58, 0x3A, 0x42, 0x06, 0x44, 0x1F, 0xD0, 0x18, 0x9B, 0x37, 0x78, 0x1B, 0x68, 0xB8, 0x45, 0x04, 0xD1, 0x58, 0x58, 0x02, 0x42, 0x19, 0xD0, 0x63, 0x46, 0x15, 0xE0, 0xA1, 0x10, 0x8C, 0x00, 0x19, 0x59, 0x91, 0x43, 0x19, 0x51, 0x00, 0x90, 0x30, 0x78, 0x01, 0x90, 0x44, 0x53, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x03, 0x20, 0x06, 0x21, 0x02, 0x46, 0x4D, 0xF6 ,
-0x80, 0x53, 0xF3, 0xF7, 0x63, 0xF9, 0x09, 0x99, 0x28, 0x68, 0x0E, 0x78, 0x36, 0x18, 0x06, 0xE0, 0xE3, 0x58, 0x02, 0x00, 0xA0, 0x10, 0x81, 0x00, 0x58, 0x58, 0x02, 0x43, 0x5A, 0x50, 0x86, 0xF8, 0x00, 0x80, 0x0B, 0x98, 0x00, 0x78, 0x0C, 0x90, 0x13, 0x98, 0xB0, 0xF9, 0x00, 0x90, 0x09, 0x98, 0x00, 0x78, 0x0A, 0x9A, 0x40, 0x1C, 0x9B, 0xF8, 0x00, 0x50, 0x9A, 0xF8, 0x00, 0x10, 0xB2, 0xF9, 0x00, 0x30, 0x09, 0x9A, 0xC0, 0xB2, 0x10, 0x70, 0x0C, 0x9A, 0x01, 0x2A, 0x03, 0xD1, 0x88, 0x42, 0xC8, 0xBF, 0x8A, 0xF8, 0x00, 0x00, 0x0C, 0x99, 0x02, 0x29, 0x07, 0xD1, 0xA8, 0x42, 0xC8, 0xBF, 0x8B, 0xF8, 0x00, 0x00, 0x02, 0xE0, 0x0A, 0x98, 0xB0, 0xF9, 0x00, 0x30, 0xB9, 0xF1, 0x00, 0x0F, 0x06, 0xDD, 0x03, 0x2B, 0x04, 0xD1, 0x11, 0x98, 0x01, 0x22, 0x49, 0x46, 0x00, 0xF0, 0x72, 0xFB, 0x16, 0x98, 0xB0, 0xF9, 0x00, 0x10, 0x14, 0x98, 0x00, 0x29, 0xB0, 0xF9, 0x00, 0x00, 0x05, 0xDD, 0x03, 0x28, 0x03, 0xD1, 0x12, 0x98 ,
-0x02, 0x22, 0x00, 0xF0, 0x64, 0xFB, 0x05, 0x98, 0x04, 0x78, 0x0B, 0x98, 0x00, 0x78, 0x0C, 0x90, 0x08, 0x98, 0xBB, 0x2C, 0x01, 0x78, 0x02, 0xD0, 0xAA, 0x2C, 0x2F, 0xD0, 0x31, 0xE0, 0x0C, 0x98, 0x01, 0x28, 0x0B, 0xD1, 0x0D, 0x98, 0x17, 0x9A, 0x10, 0x60, 0x0C, 0x54, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x0F, 0x98, 0x18, 0x9A, 0x10, 0x60, 0x19, 0x9A, 0x11, 0x98, 0x10, 0x60, 0x47, 0x4A, 0x15, 0x98, 0x02, 0x60, 0x0C, 0x98, 0x02, 0x28, 0x0B, 0xD1, 0x0E, 0x98, 0x17, 0x9A, 0x10, 0x60, 0x10, 0x98, 0x18, 0x9A, 0x10, 0x60, 0x19, 0x9A, 0x12, 0x98, 0x10, 0x60, 0x41, 0x4A, 0x15, 0x98, 0x02, 0x60, 0xCC, 0x20, 0x0F, 0xE0, 0x08, 0x99, 0x09, 0x78, 0x0C, 0xE0, 0x02, 0x20, 0x00, 0xE0, 0x01, 0x20, 0x0B, 0x99, 0x08, 0x70, 0x1A, 0x99, 0x0B, 0x80, 0x13, 0x99, 0x00, 0x20, 0x08, 0x80, 0x08, 0x98, 0x01, 0x78, 0xBB, 0x20, 0x05, 0x9A, 0x10, 0x70, 0x06, 0x29, 0x07, 0x99, 0x11, 0xD1, 0x06, 0x20, 0x08, 0x60, 0x20, 0x98 ,
-0x00, 0x25, 0x05, 0x70, 0x21, 0x98, 0x29, 0x46, 0x04, 0x22, 0xFB, 0xF7, 0x27, 0xFB, 0x01, 0x20, 0x00, 0xF0, 0x3A, 0xFA, 0x02, 0x20, 0x00, 0xF0, 0x37, 0xFA, 0x22, 0x98, 0x05, 0x60, 0x07, 0x98, 0x04, 0x99, 0x00, 0x68, 0x07, 0x28, 0x44, 0xD1, 0x09, 0x78, 0x03, 0x9C, 0x80, 0x29, 0x40, 0xD1, 0x38, 0x34, 0x21, 0x78, 0x64, 0x1C, 0x22, 0x46, 0x00, 0x29, 0x3A, 0xD1, 0x20, 0x98, 0x90, 0xF8, 0x00, 0xA0, 0x22, 0x98, 0x05, 0x90, 0xD0, 0xF8, 0x00, 0x90, 0x51, 0x46, 0x48, 0x46, 0xFD, 0xF7, 0x79, 0xF9, 0x5F, 0xFA, 0x80, 0xF8, 0x21, 0x9F, 0x15, 0x78, 0x51, 0x46, 0x48, 0x46, 0x17, 0xF8, 0x08, 0x30, 0xFD, 0xF7, 0xD4, 0x54, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x6F, 0xF9, 0x1E, 0x46, 0x1B, 0x1D, 0xC0, 0xB2, 0x38, 0x5C, 0x00, 0x1D, 0xA8, 0x42, 0x28, 0x46, 0x07, 0xDD, 0x80, 0x18, 0x82, 0x1C, 0x10, 0x78, 0x2D, 0x18, 0xAD, 0x1C, 0xAD, 0xB2, 0xAB, 0x42, 0xF7, 0xDC, 0x04, 0xF8, 0x01, 0x6B, 0x11, 0x49, 0x32, 0x46 ,
-0x20, 0x46, 0x01, 0xEB, 0x48, 0x11, 0xFA, 0xF7, 0xDC, 0xF9, 0xAD, 0x1B, 0xFF, 0x20, 0x34, 0x19, 0xAD, 0x1E, 0x04, 0xF8, 0x01, 0x0B, 0x25, 0x70, 0x05, 0x98, 0x01, 0x68, 0x49, 0x1C, 0x01, 0x60, 0x07, 0x98, 0x00, 0x68, 0x07, 0x28, 0x04, 0xD0, 0x06, 0x99, 0x08, 0x68, 0x20, 0xF4, 0x80, 0x30, 0x08, 0x60, 0x23, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0xC0, 0x46, 0x94, 0x57, 0x02, 0x00, 0xD4, 0x57, 0x02, 0x00, 0x5C, 0x58, 0x02, 0x00, 0x6E, 0x48, 0x2D, 0xE9, 0xF0, 0x47, 0x6E, 0x4D, 0x82, 0x89, 0x4A, 0xF6, 0x55, 0x21, 0xAD, 0xF5, 0xFE, 0x7D, 0x91, 0x42, 0x4F, 0xF0, 0x00, 0x01, 0xAD, 0xF1, 0x38, 0x0D, 0x12, 0xD1, 0x29, 0x60, 0x68, 0x4A, 0x11, 0x70, 0x41, 0xF2, 0x10, 0x41, 0x81, 0x81, 0x4F, 0xF6, 0xFF, 0x70, 0x66, 0x49, 0x08, 0x60, 0x28, 0x68, 0x00, 0x90, 0x02, 0x22, 0x05, 0x21, 0x03, 0x20, 0x41, 0xF2, 0x34, 0x23, 0xF3, 0xF7, 0x48, 0xF8, 0x29, 0x68, 0x61, 0x4C, 0x01, 0x29, 0x20, 0x68, 0x40, 0xF0, 0xAF, 0x80 ,
-0x5F, 0x4D, 0x02, 0x28, 0x29, 0x68, 0x23, 0xD1, 0x9C, 0x55, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x5E, 0x48, 0x00, 0x68, 0x5F, 0x4A, 0x12, 0x5C, 0x00, 0x92, 0x01, 0x91, 0x5E, 0x49, 0x09, 0x68, 0x02, 0x91, 0x5B, 0x49, 0x0B, 0x5C, 0x03, 0x20, 0x07, 0x21, 0x04, 0x22, 0xF3, 0xF7, 0x2E, 0xF8, 0x5B, 0x49, 0x4A, 0x79, 0x59, 0x48, 0x00, 0x92, 0x02, 0x79, 0x01, 0x92, 0x40, 0x79, 0x04, 0x22, 0x02, 0x90, 0x03, 0x20, 0x0B, 0x79, 0x07, 0x21, 0xF3, 0xF7, 0x20, 0xF8, 0x03, 0x20, 0x20, 0x60, 0xEC, 0xF7, 0x1A, 0xFF, 0x20, 0x68, 0x29, 0x68, 0x04, 0x28, 0x15, 0xD1, 0x0D, 0x20, 0x8D, 0xF8, 0x10, 0x00, 0x00, 0x25, 0x8D, 0xF8, 0x14, 0x50, 0x8D, 0xF8, 0x15, 0x10, 0x28, 0x46, 0x63, 0x21, 0x00, 0xF0, 0xAA, 0xFB, 0x63, 0x21, 0x28, 0x46, 0x00, 0xF0, 0xFA, 0xFA, 0x03, 0xA9, 0x04, 0xA8, 0xE0, 0xF7, 0xCA, 0xFC, 0x05, 0x20, 0x20, 0x60, 0x46, 0x4D, 0x05, 0x28, 0x29, 0x68, 0x01, 0xF1, 0x01, 0x01, 0x29, 0x60, 0x1D, 0xD1 ,
-0x44, 0x4A, 0x8A, 0x42, 0x1A, 0xD1, 0x43, 0x48, 0x01, 0x68, 0x00, 0x91, 0x40, 0x68, 0x01, 0x90, 0x03, 0x20, 0x02, 0x46, 0x06, 0x21, 0x41, 0x4E, 0x33, 0x46, 0x22, 0x3B, 0xF2, 0xF7, 0xEB, 0xFF, 0x3E, 0x48, 0x01, 0x68, 0x00, 0x91, 0x40, 0x68, 0x33, 0x46, 0x06, 0x21, 0x01, 0x90, 0x03, 0x20, 0x02, 0x46, 0xF2, 0xF7, 0xE0, 0xFF, 0x00, 0x20, 0x28, 0x60, 0x20, 0x68, 0x06, 0x28, 0x47, 0xD1, 0x4F, 0xF0, 0x64, 0x56, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x07, 0x0A, 0xC4, 0xF8, 0x00, 0xA0, 0x03, 0x20, 0x48, 0xF2, 0x70, 0x53, 0x01, 0x22, 0x04, 0x21, 0xF2, 0xF7, 0xD0, 0xFF, 0xDF, 0xF8, 0xCC, 0x80, 0x31, 0x4F, 0x48, 0xF2, 0x70, 0x59, 0x01, 0x25, 0x49, 0xEA, 0x05, 0x03, 0x01, 0x22, 0x04, 0x21, 0x03, 0x20, 0xF2, 0xF7, 0xC3, 0xFF, 0x00, 0x24, 0x17, 0xF8, 0x02, 0x0F, 0x20, 0xE0, 0x69, 0x01, 0x04, 0xEB, 0x08, 0x02, 0x88, 0x18, 0xC6, 0x1C, 0x43, 0x78, 0x00, 0x93, 0x80, 0x78, 0x01, 0x90, 0x30, 0x78, 0x02, 0x90 ,
-0x53, 0x5C, 0x51, 0x46, 0x04, 0x22, 0x03, 0x20, 0xF2, 0xF7, 0xAE, 0xFF, 0x38, 0x78, 0x01, 0x1B, 0xB1, 0xF1, 0xFF, 0x3F, 0x08, 0xD1, 0xF0, 0x78, 0x00, 0x90, 0xB3, 0x78, 0x03, 0x20, 0x02, 0x22, 0x05, 0x21, 0xF2, 0xF7, 0xA1, 0xFF, 0x38, 0x78, 0x24, 0x1D, 0xE4, 0xB2, 0xA0, 0x42, 0xDC, 0xDC, 0xAD, 0x1C, 0xED, 0xB2, 0x04, 0x2D, 0xCD, 0xDB, 0x63, 0x21, 0x4F, 0xF4, 0x05, 0x70, 0xF1, 0xF7, 0xA3, 0xFC, 0xE1, 0xF7, 0x85, 0xFD, 0x7F, 0xB0, 0x0E, 0xB0, 0xBD, 0xE8, 0xF0, 0x87, 0xC0, 0x46, 0x04, 0x74, 0x00, 0x20, 0x50, 0x57, 0x02, 0x00, 0x6C, 0x5D, 0x02, 0x00, 0x40, 0x00, 0x3D, 0x80, 0x4C, 0x57, 0x02, 0x00, 0x58, 0x57, 0x02, 0x00, 0x90, 0x57, 0x02, 0x00, 0x60, 0x57, 0x02, 0x00, 0x70, 0x57, 0x02, 0x00, 0x5C, 0x57, 0x02, 0x00, 0x80, 0x57, 0x02, 0x00, 0x2C, 0x57, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x88, 0x57, 0x02, 0x00, 0x54, 0x57, 0x02, 0x00, 0xFF, 0xFF, 0x03, 0x00, 0x38, 0x58, 0x02, 0x00, 0x40, 0x58 ,
-0x02, 0x00, 0x66, 0x55, 0xDD, 0xEE, 0xDB, 0x58, 0x02, 0x00, 0x5C, 0x58, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF4, 0x57, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBC, 0x58, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2D, 0xE9, 0xFE, 0x4F, 0x4A, 0x4A, 0x49, 0x4D, 0x00, 0x90, 0xB2, 0xF9, 0x00, 0x20, 0x43, 0xA3, 0x29, 0x78, 0x01, 0x93, 0x43, 0xA3, 0x01, 0x28, 0x02, 0x93, 0x47, 0x4E, 0xDF, 0xF8, 0x1C, 0x81, 0xDF, 0xF8, 0x1C, 0x91, 0x1E, 0xD0, 0x43, 0x48, 0x04, 0x78, 0x48, 0x01, 0x87, 0x19, 0x30, 0x18, 0x01, 0x99, 0x06, 0x22, 0xF9, 0xF7, 0xC8, 0xFF, 0x40, 0x46, 0x01, 0x78, 0x00, 0x68, 0x07, 0xF1, 0x06, 0x07, 0x07, 0xF8, 0x01, 0x1B, 0x07, 0xF8, 0x01, 0x4B, 0x4F, 0xF0, 0x00, 0x01, 0x07, 0xF8, 0x01, 0x1B, 0x20, 0xB9, 0x39, 0x70, 0x28, 0x78, 0x4E, 0x46, 0x0A, 0x21, 0x58, 0xE0, 0xDF, 0xF8, 0xE4, 0xB0, 0x0F, 0xE0, 0xD4, 0xB2, 0x48, 0x01, 0x87, 0x19, 0x30, 0x18, 0x02, 0x99, 0x07, 0x22, 0xF9, 0xF7, 0xAA, 0xFF, 0xFF, 0x1D, 0x00, 0x20, 0xDF, 0xF8, 0xCC, 0xB0, 0x07, 0xF8, 0x01, 0x4B, 0x07, 0xF8, 0x01, 0x0B, 0x16, 0x2C, 0xB2, 0x46, 0xAE, 0xBF, 0x14, 0x20, 0x84, 0x59 ,
-0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x60, 0x1E, 0xC0, 0xB2, 0x38, 0x70, 0x4E, 0x46, 0x7F, 0x1C, 0x40, 0x1C, 0xC2, 0xB2, 0x28, 0x78, 0x5B, 0x46, 0x00, 0x21, 0x32, 0x54, 0x38, 0x46, 0x00, 0xF0, 0xBC, 0xF9, 0x28, 0x78, 0x16, 0x2C, 0x31, 0x5C, 0x01, 0xF1, 0x0A, 0x01, 0x31, 0x54, 0x00, 0xF1, 0x01, 0x00, 0xC0, 0xB2, 0x28, 0x70, 0x2B, 0xDB, 0x00, 0x99, 0x0A, 0xEB, 0x40, 0x10, 0x07, 0x46, 0x01, 0x29, 0xA4, 0xF1, 0x01, 0x09, 0x09, 0xD0, 0x01, 0x99, 0x06, 0x22, 0xF9, 0xF7, 0x79, 0xFF, 0x40, 0x46, 0x00, 0x78, 0xBF, 0x1D, 0x07, 0xF8, 0x01, 0x0B, 0x04, 0xE0, 0x02, 0x99, 0x07, 0x22, 0xF9, 0xF7, 0x6F, 0xFF, 0xFF, 0x1D, 0x07, 0xF8, 0x01, 0x4B, 0x15, 0x3C, 0x15, 0x21, 0x28, 0x78, 0xE2, 0xB2, 0x5B, 0x46, 0x07, 0xF8, 0x01, 0x1B, 0x32, 0x54, 0x07, 0xF8, 0x01, 0x9B, 0x38, 0x46, 0x00, 0xF0, 0x8B, 0xF9, 0x28, 0x78, 0x31, 0x5C, 0x0A, 0x31, 0x31, 0x54, 0x40, 0x1C, 0x28, 0x70, 0xBD, 0xE8, 0xFE, 0x8F, 0xC0, 0x46 ,
-0x54, 0x54, 0x54, 0x4B, 0x45, 0x59, 0x00, 0xC0, 0x54, 0x54, 0x54, 0x53, 0x53, 0x49, 0x44, 0x00, 0x54, 0x58, 0x02, 0x00, 0xE6, 0x58, 0x02, 0x00, 0xE8, 0x58, 0x02, 0x00, 0x5C, 0x58, 0x02, 0x00, 0x5C, 0x57, 0x02, 0x00, 0xDC, 0x58, 0x02, 0x00, 0xD4, 0x57, 0x02, 0x00, 0x94, 0x57, 0x02, 0x00, 0xFF, 0xB5, 0x0C, 0x46, 0x06, 0x46, 0xF7, 0xF7, 0x4C, 0x5A, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0xE3, 0xFE, 0x15, 0x49, 0x15, 0x4A, 0x0D, 0x68, 0x01, 0xA9, 0x92, 0xE8, 0x8C, 0x00, 0x81, 0xE8, 0x8C, 0x00, 0xF7, 0xF7, 0xFD, 0xFE, 0x01, 0x98, 0x11, 0x49, 0x28, 0x1A, 0x03, 0x9D, 0x25, 0x60, 0x02, 0x9A, 0x80, 0x18, 0x82, 0x42, 0x30, 0x60, 0x0E, 0xD8, 0x08, 0x46, 0x00, 0x68, 0x22, 0x68, 0x82, 0x42, 0x0E, 0xD2, 0x68, 0x46, 0xE8, 0xF7, 0xB9, 0xFF, 0x9D, 0xF8, 0x00, 0x00, 0x05, 0xF1, 0x01, 0x05, 0x30, 0xB9, 0x03, 0x95, 0x03, 0xE0, 0x25, 0x68, 0x6D, 0x1C, 0x25, 0x60, 0x0C, 0x46, 0x25, 0x60, 0x00, 0x20, 0x00, 0x90 ,
-0xFF, 0xBD, 0x60, 0x55, 0x30, 0x80, 0x24, 0x5D, 0x00, 0x20, 0x6C, 0x5D, 0x02, 0x00, 0x70, 0xB5, 0x4D, 0x00, 0x20, 0x2D, 0x4F, 0xF0, 0x00, 0x01, 0x0C, 0x46, 0x4F, 0xEA, 0x55, 0x13, 0x09, 0xD3, 0x50, 0xF8, 0x21, 0x60, 0xB6, 0xF1, 0xFF, 0x3F, 0x04, 0xD1, 0x49, 0x1C, 0xC9, 0xB2, 0x20, 0x3D, 0x5B, 0x1E, 0xF5, 0xD1, 0x4D, 0xB1, 0x20, 0x2D, 0x09, 0xD2, 0x01, 0x23, 0xAB, 0x40, 0x5B, 0x1E, 0x50, 0xF8, 0x21, 0x00, 0x18, 0x40, 0x83, 0x42, 0x01, 0xD1, 0x4F, 0xF0, 0x01, 0x04, 0x07, 0x48, 0x03, 0x78, 0x2C, 0xB9, 0x01, 0x21, 0x91, 0x40, 0xC9, 0x43, 0xC9, 0xB2, 0x0B, 0x40, 0x03, 0xE0, 0x01, 0x21, 0x91, 0x40, 0xC9, 0xB2, 0x0B, 0x43, 0x03, 0x70, 0x70, 0xBD, 0xC0, 0x46, 0xEE, 0x58, 0x02, 0x00, 0x14, 0x5B, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x7E, 0xB5, 0x05, 0x46, 0x95, 0xF8, 0x36, 0x20, 0x0E, 0x46, 0x0F, 0x49, 0x07, 0x2A, 0x12, 0xBF, 0x08, 0x68, 0x01, 0x20, 0x08, 0x60, 0x0D, 0x4C, 0x00, 0x92, 0x21, 0x68 ,
-0x41, 0xF2, 0x12, 0x13, 0x04, 0x22, 0x01, 0x91, 0x07, 0x21, 0x02, 0x90, 0x03, 0x20, 0xF2, 0xF7, 0x6B, 0xFD, 0x31, 0x46, 0x28, 0x46, 0xE7, 0xF7, 0x21, 0xFC, 0x21, 0x68, 0x00, 0x22, 0x05, 0x29, 0x02, 0xD1, 0x04, 0x49, 0x08, 0x31, 0x0A, 0x60, 0x7E, 0xBD, 0xC0, 0x46, 0x50, 0x57, 0x02, 0x00, 0x4C, 0x57, 0x02, 0x00, 0x00, 0x7C, 0x00, 0x20, 0x0E, 0x49, 0x09, 0x68, 0x49, 0x08, 0x15, 0xD2, 0x0D, 0x49, 0x09, 0x78, 0x91, 0xB1, 0x44, 0xF2, 0xE9, 0x21, 0x68, 0xB9, 0x0B, 0x48, 0x01, 0x78, 0x07, 0x48, 0x01, 0x29, 0x03, 0xD1, 0x0A, 0x49, 0x09, 0x78, 0x0E, 0x29, 0x02, 0xD0, 0x44, 0xF2, 0xDE, 0x21, 0x41, 0x60, 0x01, 0x21, 0x00, 0xE0, 0x06, 0x48, 0x01, 0x60, 0x70, 0x47, 0xC0, 0x46, 0x00, 0x97, 0x3C, 0x80, 0x10, 0x0C, 0x30, 0x80, 0xDD, 0x6A, 0x00, 0x20, 0xE0, 0x7C, 0x00, 0x20, 0xA6, 0x64, 0x00, 0x20, 0x04, 0x97, 0x3C, 0x80, 0x00, 0xB5, 0xAD, 0xF1, 0x18, 0x0D, 0x4F, 0xF0, 0x09, 0x00, 0x00, 0x90, 0x4F, 0xF4 ,
-0x0C, 0x60, 0x03, 0x90, 0x4F, 0xF0, 0x00, 0x00, 0x01, 0x90, 0x02, 0x90, 0x08, 0x48, 0x08, 0x49, 0x05, 0x90, 0x08, 0x68, 0x20, 0xB9, 0xDC, 0x5B, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x68, 0x46, 0x03, 0x22, 0xED, 0xF7, 0x3A, 0xFA, 0x03, 0xE0, 0x68, 0x46, 0x03, 0x22, 0xED, 0xF7, 0xC1, 0xFC, 0x06, 0xB0, 0x00, 0xBD, 0xC0, 0x46, 0x81, 0x5C, 0x02, 0x00, 0xDC, 0x7C, 0x00, 0x20, 0x1C, 0xB5, 0x0F, 0x4C, 0x22, 0x68, 0x01, 0x2A, 0x15, 0xD1, 0x0C, 0x48, 0x00, 0x68, 0x07, 0x28, 0x14, 0xBF, 0x40, 0x20, 0x4F, 0xF4, 0x05, 0x70, 0x63, 0x21, 0xF1, 0xF7, 0x0F, 0xFA, 0x20, 0x68, 0x00, 0x90, 0x43, 0xF2, 0x33, 0x33, 0x06, 0x21, 0x40, 0x20, 0x01, 0x90, 0x03, 0x20, 0x02, 0x46, 0xF2, 0xF7, 0xF4, 0xFC, 0x1C, 0xBD, 0xF1, 0xF7, 0x01, 0xFA, 0x1C, 0xBD, 0x4C, 0x57, 0x02, 0x00, 0x50, 0x57, 0x02, 0x00, 0x1E, 0xB5, 0x04, 0x46, 0x0A, 0x49, 0x00, 0x20, 0x0A, 0x4A, 0x08, 0x60, 0x0A, 0x49, 0x00, 0x90, 0x01, 0x90, 0x11, 0x60 ,
-0x09, 0x4A, 0x45, 0xF2, 0x55, 0x53, 0x02, 0x91, 0x10, 0x60, 0x07, 0x21, 0x04, 0x22, 0x03, 0x20, 0xF2, 0xF7, 0xD8, 0xFC, 0x20, 0x46, 0xE7, 0xF7, 0x59, 0xFD, 0x1E, 0xBD, 0x50, 0x57, 0x02, 0x00, 0x04, 0x74, 0x00, 0x20, 0x34, 0x12, 0x66, 0x09, 0x4C, 0x57, 0x02, 0x00, 0x00, 0xB5, 0x0B, 0x49, 0x00, 0x20, 0x08, 0x60, 0xE0, 0x20, 0xF7, 0xF7, 0xAA, 0xFD, 0x09, 0x49, 0x09, 0x78, 0x49, 0xB1, 0x08, 0x49, 0x0A, 0x78, 0x08, 0x49, 0x00, 0x2A, 0x06, 0xBF, 0x01, 0x22, 0x09, 0x1F, 0x44, 0xF2, 0xA4, 0x5C, 0x02, 0x00, 0xC8, 0x00, 0x00, 0x00, 0xE9, 0x22, 0x0A, 0x60, 0xF7, 0xF7, 0xA1, 0xFD, 0x00, 0xBD, 0xC0, 0x46, 0xDC, 0x7C, 0x00, 0x20, 0xDD, 0x6A, 0x00, 0x20, 0xA7, 0x64, 0x00, 0x20, 0x04, 0x97, 0x3C, 0x80, 0x50, 0xB9, 0x09, 0x48, 0x00, 0x78, 0x01, 0x28, 0x06, 0xD1, 0x08, 0x48, 0x00, 0x78, 0x0E, 0x28, 0x08, 0xBF, 0x44, 0xF2, 0xCB, 0x20, 0x01, 0xD0, 0x44, 0xF2, 0xDE, 0x20, 0x04, 0x49, 0x08, 0x60, 0x01, 0x20 ,
-0x41, 0xF8, 0x04, 0x0C, 0x70, 0x47, 0xE0, 0x7C, 0x00, 0x20, 0xA6, 0x64, 0x00, 0x20, 0x04, 0x97, 0x3C, 0x80, 0x30, 0xB5, 0x0D, 0x46, 0x84, 0x69, 0xDC, 0xF7, 0x97, 0xFB, 0x24, 0x1D, 0x01, 0x28, 0x04, 0xEB, 0x45, 0x01, 0x06, 0xD1, 0x89, 0x8E, 0x04, 0xEB, 0x85, 0x04, 0x11, 0xB9, 0x21, 0x69, 0x01, 0xB9, 0x00, 0x20, 0x30, 0xBD, 0x30, 0xB5, 0x05, 0x46, 0x5A, 0xB1, 0x03, 0xEB, 0x41, 0x03, 0x1C, 0x78, 0x59, 0x78, 0x41, 0xEA, 0x04, 0x11, 0x52, 0x1E, 0x03, 0xF1, 0x02, 0x03, 0x05, 0xF8, 0x01, 0x1B, 0xF5, 0xD1, 0x30, 0xBD, 0x00, 0xB5, 0x00, 0x20, 0xE7, 0xF7, 0xD6, 0xFE, 0x03, 0x48, 0x01, 0x68, 0x03, 0x29, 0x04, 0xBF, 0x04, 0x21, 0x01, 0x60, 0x00, 0xBD, 0xC0, 0x46, 0x4C, 0x57, 0x02, 0x00, 0x03, 0x4A, 0x12, 0x68, 0x01, 0x2A, 0x04, 0xBF, 0x02, 0x48, 0x63, 0x21, 0xF1, 0xF7, 0x76, 0xB9, 0x50, 0x57, 0x02, 0x00, 0x02, 0x20, 0x01, 0x00, 0x6C, 0x5D, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
diff --git a/drivers/cc3000/src/patch_prog.c b/drivers/cc3000/src/patch_prog.c
deleted file mode 100644
index fd128928fbaf..000000000000
--- a/drivers/cc3000/src/patch_prog.c
+++ /dev/null
@@ -1,414 +0,0 @@
-#include
-#include
-#include "cc3000_common.h"
-#include "nvmem.h"
-#include "ccspi.h"
-#include "hci.h"
-#include "wlan.h"
-#include "patch_prog.h"
-#define BIT0 0x1
-#define BIT1 0x2
-#define BIT2 0x4
-#define BIT3 0x8
-#define BIT4 0x10
-#define BIT5 0x20
-#define BIT6 0x40
-#define BIT7 0x80
-
-static unsigned char ucStatus_Dr;
-static unsigned char ucStatus_FW;
-static unsigned char return_status = 0xFF;
-
-static signed char mac_status = -1;
-static unsigned char counter = 0;
-
-// Array to store RM parameters from EEPROM.
-static unsigned char cRMParamsFromEeprom[128];
-// Array to store MAC address from EEPROM.
-static unsigned char cMacFromEeprom[MAC_ADDR_LEN];
-// Smart Config Prefix
-static const char aucCC3000_prefix[] = {'T', 'T', 'T'};
-
-static void systick_sleep(unsigned long ms) {
- extern void HAL_Delay(volatile uint32_t Delay);
- HAL_Delay(ms);
-}
-
-// 2 dim array to store address and length of new FAT
-static const unsigned short aFATEntries[2][NVMEM_RM_FILEID + 1] =
-/* address */ {{0x50, 0x1f0, 0x390, 0x1390, 0x2390, 0x4390, 0x6390, 0x63a0, 0x63b0, 0x63f0, 0x6430, 0x6830},
-/* length */ {0x1a0, 0x1a0, 0x1000, 0x1000, 0x2000, 0x2000, 0x10, 0x10, 0x40, 0x40, 0x400, 0x200}};
-/* 0. NVS */
-/* 1. NVS Shadow */
-/* 2. Wireless Conf */
-/* 3. Wireless Conf Shadow */
-/* 4. BT (WLAN driver) Patches */
-/* 5. WiLink (Firmware) Patches */
-/* 6. MAC addr */
-/* 7. Frontend Vars */
-/* 8. IP config */
-/* 9. IP config Shadow */
-/* 10. Bootloader Patches */
-/* 11. Radio Module params */
-/* 12. AES128 for smart config */
-/* 13. user file */
-/* 14. user file */
-/* 15. user file */
-
-//*****************************************************************************
-//
-//! sendDriverPatch
-//!
-//! \param pointer to the length
-//!
-//! \return none
-//!
-//! \brief The function returns a pointer to the driver patch:
-//! since there is no patch yet - it returns 0
-//
-//*****************************************************************************
-
-static char *sendDriverPatch(unsigned long *Length)
-{
- *Length = 0;
- return NULL;
-}
-
-
-//*****************************************************************************
-//
-//! sendBootLoaderPatch
-//!
-//! \param pointer to the length
-//!
-//! \return none
-//!
-//! \brief The function returns a pointer to the boot loader patch:
-//! since there is no patch yet - it returns 0
-//
-//*****************************************************************************
-
-static char *sendBootLoaderPatch(unsigned long *Length)
-{
- *Length = 0;
- return NULL;
-}
-
-//*****************************************************************************
-//
-//! sendWLFWPatch
-//!
-//! \param pointer to the length
-//!
-//! \return none
-//!
-//! \brief The function returns a pointer to the FW patch:
-//! since there is no patch yet - it returns 0
-//
-//*****************************************************************************
-
-static char *sendWLFWPatch(unsigned long *Length)
-{
- *Length = 0;
- return NULL;
-}
-
-//*****************************************************************************
-//
-//! CC3000_UsynchCallback
-//!
-//! \param Event type
-//!
-//! \return none
-//!
-//! \brief The function handles asynchronous events that come from CC3000
-//! device and operates a LED4 to have an on-board indication
-//
-//*****************************************************************************
-
-static void CC3000_UsynchCallback(long lEventType, char * data, unsigned char length)
-{
-
-}
-
-//*****************************************************************************
-//
-//! initDriver
-//!
-//! \param[in] cRequestPatch 0 to load with EEPROM patches
-//! and 1 to load with no patches
-//!
-//! \return none
-//!
-//! \brief The function initializes a CC3000 device
-//! and triggers it to start operation
-//
-//*****************************************************************************
-static int initDriver(unsigned short cRequestPatch)
-{
- // WLAN On API Implementation
- wlan_init(CC3000_UsynchCallback, sendWLFWPatch, sendDriverPatch, sendBootLoaderPatch,
- ReadWlanInterruptPin, SpiResumeSpi, SpiPauseSpi, WriteWlanPin);
-
- // Trigger a WLAN device
- wlan_start(cRequestPatch);
- wlan_smart_config_set_prefix((char*)aucCC3000_prefix);
- wlan_ioctl_set_connection_policy(0, 0, 0);
- wlan_ioctl_del_profile(255);
-
- // Mask out all non-required events from CC3000
- wlan_set_event_mask(HCI_EVNT_WLAN_KEEPALIVE|
- HCI_EVNT_WLAN_UNSOL_INIT|
- HCI_EVNT_WLAN_ASYNC_PING_REPORT);
-
- //unsolicicted_events_timer_init();
- systick_sleep(100);
- return(0);
-}
-
-
-//*****************************************************************************
-//
-//! fat_read_content
-//!
-//! \param[out] is_allocated array of is_allocated in FAT table:\n
-//! an allocated entry implies the address and length of the
-//! file are valid.
-//! 0: not allocated; 1: allocated.
-//! \param[out] is_valid array of is_valid in FAT table:\n
-//! a valid entry implies the content of the file is relevant.
-//! 0: not valid; 1: valid.
-//! \param[out] write_protected array of write_protected in FAT table:\n
-//! a write protected entry implies it is not possible to write
-//! into this entry.
-//! 0: not protected; 1: protected.
-//! \param[out] file_address array of file address in FAT table:\n
-//! this is the absolute address of the file in the EEPROM.
-//! \param[out] file_length array of file length in FAT table:\n
-//! this is the upper limit of the file size in the EEPROM.
-//!
-//! \return on succes 0, error otherwise
-//!
-//! \brief parse the FAT table from eeprom
-//
-//*****************************************************************************
-static unsigned char __attribute__ ((unused))
-fat_read_content(unsigned char *is_allocated, unsigned char *is_valid,
- unsigned char *write_protected, unsigned short *file_address, unsigned short *file_length)
-{
- unsigned short index;
- unsigned char ucStatus;
- unsigned char fatTable[48];
- unsigned char* fatTablePtr = fatTable;
-
- //
- // Read in 6 parts to work with tiny driver
- //
- for (index = 0; index < 6; index++)
- {
- ucStatus = nvmem_read(16, 8, 4 + 8*index, fatTablePtr);
- fatTablePtr += 8;
- }
-
- fatTablePtr = fatTable;
-
- for (index = 0; index <= NVMEM_RM_FILEID; index++)
- {
- *is_allocated++ = (*fatTablePtr) & BIT0;
- *is_valid++ = ((*fatTablePtr) & BIT1) >> 1;
- *write_protected++ = ((*fatTablePtr) & BIT2) >> 2;
- *file_address++ = ((*(fatTablePtr+1)<<8) | (*fatTablePtr)) & (BIT4|BIT5|BIT6|BIT7);
- *file_length++ = ((*(fatTablePtr+3)<<8) | (*(fatTablePtr+2))) & (BIT4|BIT5|BIT6|BIT7);
-
- //
- // Move to next file ID
- //
- fatTablePtr += 4;
- }
-
- return ucStatus;
-}
-
-//*****************************************************************************
-//
-//! fat_write_content
-//!
-//! \param[in] file_address array of file address in FAT table:\n
-//! this is the absolute address of the file in the EEPROM.
-//! \param[in] file_length array of file length in FAT table:\n
-//! this is the upper limit of the file size in the EEPROM.
-//!
-//! \return on succes 0, error otherwise
-//!
-//! \brief parse the FAT table from eeprom
-//
-//*****************************************************************************
-static unsigned char fat_write_content(unsigned short const *file_address,
- unsigned short const *file_length)
-{
- unsigned short index = 0;
- unsigned char ucStatus;
- unsigned char fatTable[48];
- unsigned char* fatTablePtr = fatTable;
-
- //
- // First, write the magic number.
- //
- ucStatus = nvmem_write(16, 2, 0, (unsigned char*)"LS");
-
- for (; index <= NVMEM_RM_FILEID; index++)
- {
- //
- // Write address low char and mark as allocated.
- //
- *fatTablePtr++ = (unsigned char)(file_address[index] & 0xff) | BIT0;
-
- //
- // Write address high char.
- //
- *fatTablePtr++ = (unsigned char)((file_address[index]>>8) & 0xff);
-
- //
- // Write length low char.
- //
- *fatTablePtr++ = (unsigned char)(file_length[index] & 0xff);
-
- //
- // Write length high char.
- //
- *fatTablePtr++ = (unsigned char)((file_length[index]>>8) & 0xff);
- }
-
- //
- // Second, write the FAT.
- // Write in two parts to work with tiny driver.
- //
- ucStatus = nvmem_write(16, 24, 4, fatTable);
- ucStatus = nvmem_write(16, 24, 24+4, &fatTable[24]);
-
- //
- // Third, we want to erase any user files.
- //
- memset(fatTable, 0, sizeof(fatTable));
- ucStatus = nvmem_write(16, 16, 52, fatTable);
-
- return ucStatus;
-}
-
-void patch_prog_start()
-{
- unsigned short index;
- unsigned char *pRMParams;
-
- printf("Initializing module...\n");
-
- // Init module and request to load with no patches.
- // This is in order to overwrite restrictions to
- // write to specific places in EEPROM.
- initDriver(1);
-
- // Read MAC address.
- mac_status = nvmem_get_mac_address(cMacFromEeprom);
-
- return_status = 1;
-
- printf("Reading RM parameters...\n");
- while ((return_status) && (counter < 3)) {
- // Read RM parameters.
- // Read in 16 parts to work with tiny driver.
- return_status = 0;
- pRMParams = cRMParamsFromEeprom;
- for (index = 0; index < 16; index++) {
- return_status |= nvmem_read(NVMEM_RM_FILEID, 8, 8*index, pRMParams);
- pRMParams += 8;
- }
- counter++;
- }
-
- // If RM file is not valid, load the default one.
- if (counter == 3) {
- printf("RM is not valid, loading default one...\n");
- pRMParams = (unsigned char *)cRMdefaultParams;
- } else {
- printf("RM is valid.\n");
- pRMParams = cRMParamsFromEeprom;
- }
-
- return_status = 1;
-
- printf("Writing new FAT\n");
- while (return_status) {
- // Write new FAT.
- return_status = fat_write_content(aFATEntries[0], aFATEntries[1]);
- }
-
- return_status = 1;
-
- printf("Writing RM parameters...\n");
- while (return_status) {
- // Write RM parameters.
- // Write in 4 parts to work with tiny driver.
- return_status = 0;
-
- for (index = 0; index < 4; index++) {
- return_status |= nvmem_write(NVMEM_RM_FILEID,
- 32,
- 32*index,
- (pRMParams + 32*index));
- }
- }
-
- return_status = 1;
-
- // Write back the MAC address, only if exists.
- if (mac_status == 0) {
- // Zero out MCAST bit if set.
- cMacFromEeprom[0] &= 0xfe;
- printf("Writing back MAC address..\n");
- while (return_status) {
- return_status = nvmem_set_mac_address(cMacFromEeprom);
- }
- }
-
- // Update driver
- ucStatus_Dr = 1;
- printf("Updating driver patch...\n");
- while (ucStatus_Dr) {
- // Writing driver patch to EEPRROM - PROTABLE CODE
- // Note that the array itself is changing between the
- // different Service Packs.
- ucStatus_Dr = nvmem_write_patch(NVMEM_WLAN_DRIVER_SP_FILEID,
- drv_length,
- wlan_drv_patch);
- }
-
- // Update firmware
- ucStatus_FW = 1;
- printf("Updating firmware patch...\n");
- while (ucStatus_FW) {
- // Writing FW patch to EEPRROM - PROTABLE CODE
- // Note that the array itself is changing between the
- // different Service Packs.
- ucStatus_FW = nvmem_write_patch(NVMEM_WLAN_FW_SP_FILEID,
- fw_length,
- fw_patch);
- }
-
- printf("Update complete, resetting module\n"\
- "If this doesn't work, reset manually...\n");
-
- wlan_stop();
- systick_sleep(500);
-
- // Re-Init module and request to load with patches.
- initDriver(0);
-
- // If MAC does not exist, it is recommended
- // that the user will write a valid mac address.
- if (mac_status != 0) {
- printf("MAC address is not valid, please write a new one\n");
- }
-
- // Patch update done
- printf("All done, call wlan.patch_version()\n");
-}
diff --git a/drivers/cc3000/src/security.c b/drivers/cc3000/src/security.c
deleted file mode 100644
index 62b4f881343a..000000000000
--- a/drivers/cc3000/src/security.c
+++ /dev/null
@@ -1,530 +0,0 @@
-/*****************************************************************************
-*
-* security.c - CC3000 Host Driver Implementation.
-* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
-*
-* 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 Texas Instruments Incorporated 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
-* OWNER 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.
-*
-*****************************************************************************/
-
-//*****************************************************************************
-//
-//! \addtogroup security_api
-//! @{
-//
-//*****************************************************************************
-
-#include "security.h"
-
-#ifndef CC3000_UNENCRYPTED_SMART_CONFIG
-// foreward sbox
-const UINT8 sbox[256] = {
-//0 1 2 3 4 5 6 7 8 9 A B C D E F
-0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, //0
-0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, //1
-0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, //2
-0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, //3
-0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, //4
-0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, //5
-0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, //6
-0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, //7
-0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, //8
-0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, //9
-0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, //A
-0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, //B
-0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, //C
-0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, //D
-0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, //E
-0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 }; //F
-// inverse sbox
-const UINT8 rsbox[256] =
-{ 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb
-, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb
-, 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e
-, 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25
-, 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92
-, 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84
-, 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06
-, 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b
-, 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73
-, 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e
-, 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b
-, 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4
-, 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f
-, 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef
-, 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61
-, 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d };
-// round constant
-const UINT8 Rcon[11] = {
- 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36};
-
-
-UINT8 expandedKey[176];
-
-//*****************************************************************************
-//
-//! expandKey
-//!
-//! @param key AES128 key - 16 bytes
-//! @param expandedKey expanded AES128 key
-//!
-//! @return none
-//!
-//! @brief expend a 16 bytes key for AES128 implementation
-//!
-//*****************************************************************************
-
-void expandKey(UINT8 *expandedKey, UINT8 *key)
-{
- UINT16 ii, buf1;
- for (ii=0;ii<16;ii++)
- expandedKey[ii] = key[ii];
- for (ii=1;ii<11;ii++){
- buf1 = expandedKey[ii*16 - 4];
- expandedKey[ii*16 + 0] = sbox[expandedKey[ii*16 - 3]]^expandedKey[(ii-1)*16 + 0]^Rcon[ii];
- expandedKey[ii*16 + 1] = sbox[expandedKey[ii*16 - 2]]^expandedKey[(ii-1)*16 + 1];
- expandedKey[ii*16 + 2] = sbox[expandedKey[ii*16 - 1]]^expandedKey[(ii-1)*16 + 2];
- expandedKey[ii*16 + 3] = sbox[buf1 ]^expandedKey[(ii-1)*16 + 3];
- expandedKey[ii*16 + 4] = expandedKey[(ii-1)*16 + 4]^expandedKey[ii*16 + 0];
- expandedKey[ii*16 + 5] = expandedKey[(ii-1)*16 + 5]^expandedKey[ii*16 + 1];
- expandedKey[ii*16 + 6] = expandedKey[(ii-1)*16 + 6]^expandedKey[ii*16 + 2];
- expandedKey[ii*16 + 7] = expandedKey[(ii-1)*16 + 7]^expandedKey[ii*16 + 3];
- expandedKey[ii*16 + 8] = expandedKey[(ii-1)*16 + 8]^expandedKey[ii*16 + 4];
- expandedKey[ii*16 + 9] = expandedKey[(ii-1)*16 + 9]^expandedKey[ii*16 + 5];
- expandedKey[ii*16 +10] = expandedKey[(ii-1)*16 +10]^expandedKey[ii*16 + 6];
- expandedKey[ii*16 +11] = expandedKey[(ii-1)*16 +11]^expandedKey[ii*16 + 7];
- expandedKey[ii*16 +12] = expandedKey[(ii-1)*16 +12]^expandedKey[ii*16 + 8];
- expandedKey[ii*16 +13] = expandedKey[(ii-1)*16 +13]^expandedKey[ii*16 + 9];
- expandedKey[ii*16 +14] = expandedKey[(ii-1)*16 +14]^expandedKey[ii*16 +10];
- expandedKey[ii*16 +15] = expandedKey[(ii-1)*16 +15]^expandedKey[ii*16 +11];
- }
-
-}
-
-//*****************************************************************************
-//
-//! galois_mul2
-//!
-//! @param value argument to multiply
-//!
-//! @return multiplied argument
-//!
-//! @brief multiply by 2 in the galois field
-//!
-//*****************************************************************************
-
-UINT8 galois_mul2(UINT8 value)
-{
- if (value>>7)
- {
- value = value << 1;
- return (value^0x1b);
- } else
- return value<<1;
-}
-
-//*****************************************************************************
-//
-//! aes_encr
-//!
-//! @param[in] expandedKey expanded AES128 key
-//! @param[in/out] state 16 bytes of plain text and cipher text
-//!
-//! @return none
-//!
-//! @brief internal implementation of AES128 encryption.
-//! straight forward aes encryption implementation
-//! first the group of operations
-//! - addRoundKey
-//! - subbytes
-//! - shiftrows
-//! - mixcolums
-//! is executed 9 times, after this addroundkey to finish the 9th
-//! round, after that the 10th round without mixcolums
-//! no further subfunctions to save cycles for function calls
-//! no structuring with "for (....)" to save cycles.
-//!
-//!
-//*****************************************************************************
-
-void aes_encr(UINT8 *state, UINT8 *expandedKey)
-{
- UINT8 buf1, buf2, buf3, round;
-
- for (round = 0; round < 9; round ++){
- // addroundkey, sbox and shiftrows
- // row 0
- state[ 0] = sbox[(state[ 0] ^ expandedKey[(round*16) ])];
- state[ 4] = sbox[(state[ 4] ^ expandedKey[(round*16) + 4])];
- state[ 8] = sbox[(state[ 8] ^ expandedKey[(round*16) + 8])];
- state[12] = sbox[(state[12] ^ expandedKey[(round*16) + 12])];
- // row 1
- buf1 = state[1] ^ expandedKey[(round*16) + 1];
- state[ 1] = sbox[(state[ 5] ^ expandedKey[(round*16) + 5])];
- state[ 5] = sbox[(state[ 9] ^ expandedKey[(round*16) + 9])];
- state[ 9] = sbox[(state[13] ^ expandedKey[(round*16) + 13])];
- state[13] = sbox[buf1];
- // row 2
- buf1 = state[2] ^ expandedKey[(round*16) + 2];
- buf2 = state[6] ^ expandedKey[(round*16) + 6];
- state[ 2] = sbox[(state[10] ^ expandedKey[(round*16) + 10])];
- state[ 6] = sbox[(state[14] ^ expandedKey[(round*16) + 14])];
- state[10] = sbox[buf1];
- state[14] = sbox[buf2];
- // row 3
- buf1 = state[15] ^ expandedKey[(round*16) + 15];
- state[15] = sbox[(state[11] ^ expandedKey[(round*16) + 11])];
- state[11] = sbox[(state[ 7] ^ expandedKey[(round*16) + 7])];
- state[ 7] = sbox[(state[ 3] ^ expandedKey[(round*16) + 3])];
- state[ 3] = sbox[buf1];
-
- // mixcolums //////////
- // col1
- buf1 = state[0] ^ state[1] ^ state[2] ^ state[3];
- buf2 = state[0];
- buf3 = state[0]^state[1]; buf3=galois_mul2(buf3); state[0] = state[0] ^ buf3 ^ buf1;
- buf3 = state[1]^state[2]; buf3=galois_mul2(buf3); state[1] = state[1] ^ buf3 ^ buf1;
- buf3 = state[2]^state[3]; buf3=galois_mul2(buf3); state[2] = state[2] ^ buf3 ^ buf1;
- buf3 = state[3]^buf2; buf3=galois_mul2(buf3); state[3] = state[3] ^ buf3 ^ buf1;
- // col2
- buf1 = state[4] ^ state[5] ^ state[6] ^ state[7];
- buf2 = state[4];
- buf3 = state[4]^state[5]; buf3=galois_mul2(buf3); state[4] = state[4] ^ buf3 ^ buf1;
- buf3 = state[5]^state[6]; buf3=galois_mul2(buf3); state[5] = state[5] ^ buf3 ^ buf1;
- buf3 = state[6]^state[7]; buf3=galois_mul2(buf3); state[6] = state[6] ^ buf3 ^ buf1;
- buf3 = state[7]^buf2; buf3=galois_mul2(buf3); state[7] = state[7] ^ buf3 ^ buf1;
- // col3
- buf1 = state[8] ^ state[9] ^ state[10] ^ state[11];
- buf2 = state[8];
- buf3 = state[8]^state[9]; buf3=galois_mul2(buf3); state[8] = state[8] ^ buf3 ^ buf1;
- buf3 = state[9]^state[10]; buf3=galois_mul2(buf3); state[9] = state[9] ^ buf3 ^ buf1;
- buf3 = state[10]^state[11]; buf3=galois_mul2(buf3); state[10] = state[10] ^ buf3 ^ buf1;
- buf3 = state[11]^buf2; buf3=galois_mul2(buf3); state[11] = state[11] ^ buf3 ^ buf1;
- // col4
- buf1 = state[12] ^ state[13] ^ state[14] ^ state[15];
- buf2 = state[12];
- buf3 = state[12]^state[13]; buf3=galois_mul2(buf3); state[12] = state[12] ^ buf3 ^ buf1;
- buf3 = state[13]^state[14]; buf3=galois_mul2(buf3); state[13] = state[13] ^ buf3 ^ buf1;
- buf3 = state[14]^state[15]; buf3=galois_mul2(buf3); state[14] = state[14] ^ buf3 ^ buf1;
- buf3 = state[15]^buf2; buf3=galois_mul2(buf3); state[15] = state[15] ^ buf3 ^ buf1;
-
- }
- // 10th round without mixcols
- state[ 0] = sbox[(state[ 0] ^ expandedKey[(round*16) ])];
- state[ 4] = sbox[(state[ 4] ^ expandedKey[(round*16) + 4])];
- state[ 8] = sbox[(state[ 8] ^ expandedKey[(round*16) + 8])];
- state[12] = sbox[(state[12] ^ expandedKey[(round*16) + 12])];
- // row 1
- buf1 = state[1] ^ expandedKey[(round*16) + 1];
- state[ 1] = sbox[(state[ 5] ^ expandedKey[(round*16) + 5])];
- state[ 5] = sbox[(state[ 9] ^ expandedKey[(round*16) + 9])];
- state[ 9] = sbox[(state[13] ^ expandedKey[(round*16) + 13])];
- state[13] = sbox[buf1];
- // row 2
- buf1 = state[2] ^ expandedKey[(round*16) + 2];
- buf2 = state[6] ^ expandedKey[(round*16) + 6];
- state[ 2] = sbox[(state[10] ^ expandedKey[(round*16) + 10])];
- state[ 6] = sbox[(state[14] ^ expandedKey[(round*16) + 14])];
- state[10] = sbox[buf1];
- state[14] = sbox[buf2];
- // row 3
- buf1 = state[15] ^ expandedKey[(round*16) + 15];
- state[15] = sbox[(state[11] ^ expandedKey[(round*16) + 11])];
- state[11] = sbox[(state[ 7] ^ expandedKey[(round*16) + 7])];
- state[ 7] = sbox[(state[ 3] ^ expandedKey[(round*16) + 3])];
- state[ 3] = sbox[buf1];
- // last addroundkey
- state[ 0]^=expandedKey[160];
- state[ 1]^=expandedKey[161];
- state[ 2]^=expandedKey[162];
- state[ 3]^=expandedKey[163];
- state[ 4]^=expandedKey[164];
- state[ 5]^=expandedKey[165];
- state[ 6]^=expandedKey[166];
- state[ 7]^=expandedKey[167];
- state[ 8]^=expandedKey[168];
- state[ 9]^=expandedKey[169];
- state[10]^=expandedKey[170];
- state[11]^=expandedKey[171];
- state[12]^=expandedKey[172];
- state[13]^=expandedKey[173];
- state[14]^=expandedKey[174];
- state[15]^=expandedKey[175];
-}
-
-//*****************************************************************************
-//
-//! aes_decr
-//!
-//! @param[in] expandedKey expanded AES128 key
-//! @param[in\out] state 16 bytes of cipher text and plain text
-//!
-//! @return none
-//!
-//! @brief internal implementation of AES128 decryption.
-//! straight forward aes decryption implementation
-//! the order of substeps is the exact reverse of decryption
-//! inverse functions:
-//! - addRoundKey is its own inverse
-//! - rsbox is inverse of sbox
-//! - rightshift instead of leftshift
-//! - invMixColumns = barreto + mixColumns
-//! no further subfunctions to save cycles for function calls
-//! no structuring with "for (....)" to save cycles
-//!
-//*****************************************************************************
-
-void aes_decr(UINT8 *state, UINT8 *expandedKey)
-{
- UINT8 buf1, buf2, buf3;
- INT8 round;
- round = 9;
-
- // initial addroundkey
- state[ 0]^=expandedKey[160];
- state[ 1]^=expandedKey[161];
- state[ 2]^=expandedKey[162];
- state[ 3]^=expandedKey[163];
- state[ 4]^=expandedKey[164];
- state[ 5]^=expandedKey[165];
- state[ 6]^=expandedKey[166];
- state[ 7]^=expandedKey[167];
- state[ 8]^=expandedKey[168];
- state[ 9]^=expandedKey[169];
- state[10]^=expandedKey[170];
- state[11]^=expandedKey[171];
- state[12]^=expandedKey[172];
- state[13]^=expandedKey[173];
- state[14]^=expandedKey[174];
- state[15]^=expandedKey[175];
-
- // 10th round without mixcols
- state[ 0] = rsbox[state[ 0]] ^ expandedKey[(round*16) ];
- state[ 4] = rsbox[state[ 4]] ^ expandedKey[(round*16) + 4];
- state[ 8] = rsbox[state[ 8]] ^ expandedKey[(round*16) + 8];
- state[12] = rsbox[state[12]] ^ expandedKey[(round*16) + 12];
- // row 1
- buf1 = rsbox[state[13]] ^ expandedKey[(round*16) + 1];
- state[13] = rsbox[state[ 9]] ^ expandedKey[(round*16) + 13];
- state[ 9] = rsbox[state[ 5]] ^ expandedKey[(round*16) + 9];
- state[ 5] = rsbox[state[ 1]] ^ expandedKey[(round*16) + 5];
- state[ 1] = buf1;
- // row 2
- buf1 = rsbox[state[ 2]] ^ expandedKey[(round*16) + 10];
- buf2 = rsbox[state[ 6]] ^ expandedKey[(round*16) + 14];
- state[ 2] = rsbox[state[10]] ^ expandedKey[(round*16) + 2];
- state[ 6] = rsbox[state[14]] ^ expandedKey[(round*16) + 6];
- state[10] = buf1;
- state[14] = buf2;
- // row 3
- buf1 = rsbox[state[ 3]] ^ expandedKey[(round*16) + 15];
- state[ 3] = rsbox[state[ 7]] ^ expandedKey[(round*16) + 3];
- state[ 7] = rsbox[state[11]] ^ expandedKey[(round*16) + 7];
- state[11] = rsbox[state[15]] ^ expandedKey[(round*16) + 11];
- state[15] = buf1;
-
- for (round = 8; round >= 0; round--){
- // barreto
- //col1
- buf1 = galois_mul2(galois_mul2(state[0]^state[2]));
- buf2 = galois_mul2(galois_mul2(state[1]^state[3]));
- state[0] ^= buf1; state[1] ^= buf2; state[2] ^= buf1; state[3] ^= buf2;
- //col2
- buf1 = galois_mul2(galois_mul2(state[4]^state[6]));
- buf2 = galois_mul2(galois_mul2(state[5]^state[7]));
- state[4] ^= buf1; state[5] ^= buf2; state[6] ^= buf1; state[7] ^= buf2;
- //col3
- buf1 = galois_mul2(galois_mul2(state[8]^state[10]));
- buf2 = galois_mul2(galois_mul2(state[9]^state[11]));
- state[8] ^= buf1; state[9] ^= buf2; state[10] ^= buf1; state[11] ^= buf2;
- //col4
- buf1 = galois_mul2(galois_mul2(state[12]^state[14]));
- buf2 = galois_mul2(galois_mul2(state[13]^state[15]));
- state[12] ^= buf1; state[13] ^= buf2; state[14] ^= buf1; state[15] ^= buf2;
- // mixcolums //////////
- // col1
- buf1 = state[0] ^ state[1] ^ state[2] ^ state[3];
- buf2 = state[0];
- buf3 = state[0]^state[1]; buf3=galois_mul2(buf3); state[0] = state[0] ^ buf3 ^ buf1;
- buf3 = state[1]^state[2]; buf3=galois_mul2(buf3); state[1] = state[1] ^ buf3 ^ buf1;
- buf3 = state[2]^state[3]; buf3=galois_mul2(buf3); state[2] = state[2] ^ buf3 ^ buf1;
- buf3 = state[3]^buf2; buf3=galois_mul2(buf3); state[3] = state[3] ^ buf3 ^ buf1;
- // col2
- buf1 = state[4] ^ state[5] ^ state[6] ^ state[7];
- buf2 = state[4];
- buf3 = state[4]^state[5]; buf3=galois_mul2(buf3); state[4] = state[4] ^ buf3 ^ buf1;
- buf3 = state[5]^state[6]; buf3=galois_mul2(buf3); state[5] = state[5] ^ buf3 ^ buf1;
- buf3 = state[6]^state[7]; buf3=galois_mul2(buf3); state[6] = state[6] ^ buf3 ^ buf1;
- buf3 = state[7]^buf2; buf3=galois_mul2(buf3); state[7] = state[7] ^ buf3 ^ buf1;
- // col3
- buf1 = state[8] ^ state[9] ^ state[10] ^ state[11];
- buf2 = state[8];
- buf3 = state[8]^state[9]; buf3=galois_mul2(buf3); state[8] = state[8] ^ buf3 ^ buf1;
- buf3 = state[9]^state[10]; buf3=galois_mul2(buf3); state[9] = state[9] ^ buf3 ^ buf1;
- buf3 = state[10]^state[11]; buf3=galois_mul2(buf3); state[10] = state[10] ^ buf3 ^ buf1;
- buf3 = state[11]^buf2; buf3=galois_mul2(buf3); state[11] = state[11] ^ buf3 ^ buf1;
- // col4
- buf1 = state[12] ^ state[13] ^ state[14] ^ state[15];
- buf2 = state[12];
- buf3 = state[12]^state[13]; buf3=galois_mul2(buf3); state[12] = state[12] ^ buf3 ^ buf1;
- buf3 = state[13]^state[14]; buf3=galois_mul2(buf3); state[13] = state[13] ^ buf3 ^ buf1;
- buf3 = state[14]^state[15]; buf3=galois_mul2(buf3); state[14] = state[14] ^ buf3 ^ buf1;
- buf3 = state[15]^buf2; buf3=galois_mul2(buf3); state[15] = state[15] ^ buf3 ^ buf1;
-
- // addroundkey, rsbox and shiftrows
- // row 0
- state[ 0] = rsbox[state[ 0]] ^ expandedKey[(round*16) ];
- state[ 4] = rsbox[state[ 4]] ^ expandedKey[(round*16) + 4];
- state[ 8] = rsbox[state[ 8]] ^ expandedKey[(round*16) + 8];
- state[12] = rsbox[state[12]] ^ expandedKey[(round*16) + 12];
- // row 1
- buf1 = rsbox[state[13]] ^ expandedKey[(round*16) + 1];
- state[13] = rsbox[state[ 9]] ^ expandedKey[(round*16) + 13];
- state[ 9] = rsbox[state[ 5]] ^ expandedKey[(round*16) + 9];
- state[ 5] = rsbox[state[ 1]] ^ expandedKey[(round*16) + 5];
- state[ 1] = buf1;
- // row 2
- buf1 = rsbox[state[ 2]] ^ expandedKey[(round*16) + 10];
- buf2 = rsbox[state[ 6]] ^ expandedKey[(round*16) + 14];
- state[ 2] = rsbox[state[10]] ^ expandedKey[(round*16) + 2];
- state[ 6] = rsbox[state[14]] ^ expandedKey[(round*16) + 6];
- state[10] = buf1;
- state[14] = buf2;
- // row 3
- buf1 = rsbox[state[ 3]] ^ expandedKey[(round*16) + 15];
- state[ 3] = rsbox[state[ 7]] ^ expandedKey[(round*16) + 3];
- state[ 7] = rsbox[state[11]] ^ expandedKey[(round*16) + 7];
- state[11] = rsbox[state[15]] ^ expandedKey[(round*16) + 11];
- state[15] = buf1;
- }
-
-}
-
-//*****************************************************************************
-//
-//! aes_encrypt
-//!
-//! @param[in] key AES128 key of size 16 bytes
-//! @param[in\out] state 16 bytes of plain text and cipher text
-//!
-//! @return none
-//!
-//! @brief AES128 encryption:
-//! Given AES128 key and 16 bytes plain text, cipher text of 16 bytes
-//! is computed. The AES implementation is in mode ECB (Electronic
-//! Code Book).
-//!
-//!
-//*****************************************************************************
-
-void aes_encrypt(UINT8 *state, UINT8 *key)
-{
- // expand the key into 176 bytes
- expandKey(expandedKey, key);
- aes_encr(state, expandedKey);
-}
-
-//*****************************************************************************
-//
-//! aes_decrypt
-//!
-//! @param[in] key AES128 key of size 16 bytes
-//! @param[in\out] state 16 bytes of cipher text and plain text
-//!
-//! @return none
-//!
-//! @brief AES128 decryption:
-//! Given AES128 key and 16 bytes cipher text, plain text of 16 bytes
-//! is computed The AES implementation is in mode ECB
-//! (Electronic Code Book).
-//!
-//!
-//*****************************************************************************
-
-void aes_decrypt(UINT8 *state, UINT8 *key)
-{
- expandKey(expandedKey, key); // expand the key into 176 bytes
- aes_decr(state, expandedKey);
-}
-
-//*****************************************************************************
-//
-//! aes_read_key
-//!
-//! @param[out] key AES128 key of size 16 bytes
-//!
-//! @return on success 0, error otherwise.
-//!
-//! @brief Reads AES128 key from EEPROM
-//! Reads the AES128 key from fileID #12 in EEPROM
-//! returns an error if the key does not exist.
-//!
-//!
-//*****************************************************************************
-
-INT32 aes_read_key(UINT8 *key)
-{
- INT32 returnValue;
-
- returnValue = nvmem_read(NVMEM_AES128_KEY_FILEID, AES128_KEY_SIZE, 0, key);
-
- return returnValue;
-}
-
-//*****************************************************************************
-//
-//! aes_write_key
-//!
-//! @param[out] key AES128 key of size 16 bytes
-//!
-//! @return on success 0, error otherwise.
-//!
-//! @brief writes AES128 key from EEPROM
-//! Writes the AES128 key to fileID #12 in EEPROM
-//!
-//!
-//*****************************************************************************
-
-INT32 aes_write_key(UINT8 *key)
-{
- INT32 returnValue;
-
- returnValue = nvmem_write(NVMEM_AES128_KEY_FILEID, AES128_KEY_SIZE, 0, key);
-
- return returnValue;
-}
-
-#endif //CC3000_UNENCRYPTED_SMART_CONFIG
-
-//*****************************************************************************
-//
-// Close the Doxygen group.
-//! @}
-//
-//*****************************************************************************
diff --git a/drivers/cc3000/src/socket.c b/drivers/cc3000/src/socket.c
deleted file mode 100644
index ddd7e56e8075..000000000000
--- a/drivers/cc3000/src/socket.c
+++ /dev/null
@@ -1,1182 +0,0 @@
-/*****************************************************************************
-*
-* socket.c - CC3000 Host Driver Implementation.
-* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
-*
-* 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 Texas Instruments Incorporated 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
-* OWNER 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.
-*
-*****************************************************************************/
-
-//*****************************************************************************
-//
-//! \addtogroup socket_api
-//! @{
-//
-//*****************************************************************************
-
-#include
-#include
-#include "hci.h"
-#include "socket.h"
-#include "evnt_handler.h"
-#include "netapp.h"
-
-
-
-//Enable this flag if and only if you must comply with BSD socket
-//close() function
-#ifdef _API_USE_BSD_CLOSE
-#define close(sd) closesocket(sd)
-#endif
-
-//Enable this flag if and only if you must comply with BSD socket read() and
-//write() functions
-#ifdef _API_USE_BSD_READ_WRITE
-#define read(sd, buf, len, flags) recv(sd, buf, len, flags)
-#define write(sd, buf, len, flags) send(sd, buf, len, flags)
-#endif
-
-#define SOCKET_OPEN_PARAMS_LEN (12)
-#define SOCKET_CLOSE_PARAMS_LEN (4)
-#define SOCKET_ACCEPT_PARAMS_LEN (4)
-#define SOCKET_BIND_PARAMS_LEN (20)
-#define SOCKET_LISTEN_PARAMS_LEN (8)
-#define SOCKET_GET_HOST_BY_NAME_PARAMS_LEN (9)
-#define SOCKET_CONNECT_PARAMS_LEN (20)
-#define SOCKET_SELECT_PARAMS_LEN (44)
-#define SOCKET_SET_SOCK_OPT_PARAMS_LEN (20)
-#define SOCKET_GET_SOCK_OPT_PARAMS_LEN (12)
-#define SOCKET_RECV_FROM_PARAMS_LEN (12)
-#define SOCKET_SENDTO_PARAMS_LEN (24)
-#define SOCKET_MDNS_ADVERTISE_PARAMS_LEN (12)
-#define SOCKET_GET_MSS_VALUE_PARAMS_LEN (4)
-
-// The legnth of arguments for the SEND command: sd + buff_offset + len + flags,
-// while size of each parameter is 32 bit - so the total length is 16 bytes;
-
-#define HCI_CMND_SEND_ARG_LENGTH (16)
-
-
-#define SELECT_TIMEOUT_MIN_MICRO_SECONDS 5000
-
-#define HEADERS_SIZE_DATA (SPI_HEADER_SIZE + 5)
-
-#define SIMPLE_LINK_HCI_CMND_TRANSPORT_HEADER_SIZE (SPI_HEADER_SIZE + SIMPLE_LINK_HCI_CMND_HEADER_SIZE)
-
-#define MDNS_DEVICE_SERVICE_MAX_LENGTH (32)
-
-
-//*****************************************************************************
-//
-//! HostFlowControlConsumeBuff
-//!
-//! @param sd socket descriptor
-//!
-//! @return 0 in case there are buffers available,
-//! -1 in case of bad socket
-//! -2 if there are no free buffers present (only when
-//! SEND_NON_BLOCKING is enabled)
-//!
-//! @brief if SEND_NON_BLOCKING not define - block until have free buffer
-//! becomes available, else return immediately with correct status
-//! regarding the buffers available.
-//
-//*****************************************************************************
-static INT16 HostFlowControlConsumeBuff(INT16 sd)
-{
-#ifndef SEND_NON_BLOCKING
- /* wait in busy loop */
- do
- {
- // In case last transmission failed then we will return the last failure
- // reason here.
- // Note that the buffer will not be allocated in this case
- if (tSLInformation.slTransmitDataError != 0)
- {
- CC3000_EXPORT(errno) = tSLInformation.slTransmitDataError;
- tSLInformation.slTransmitDataError = 0;
- return CC3000_EXPORT(errno);
- }
-
- if(SOCKET_STATUS_ACTIVE != get_socket_active_status(sd))
- return -1;
- } while(0 == tSLInformation.usNumberOfFreeBuffers);
-
- tSLInformation.usNumberOfFreeBuffers--;
-
- return 0;
-#else
-
- // In case last transmission failed then we will return the last failure
- // reason here.
- // Note that the buffer will not be allocated in this case
- if (tSLInformation.slTransmitDataError != 0)
- {
- CC3000_EXPORT(errno) = tSLInformation.slTransmitDataError;
- tSLInformation.slTransmitDataError = 0;
- return CC3000_EXPORT(errno);
- }
- if(SOCKET_STATUS_ACTIVE != get_socket_active_status(sd))
- return -1;
-
- //If there are no available buffers, return -2. It is recommended to use
- // select or receive to see if there is any buffer occupied with received data
- // If so, call receive() to release the buffer.
- if(0 == tSLInformation.usNumberOfFreeBuffers)
- {
- return -2;
- }
- else
- {
- tSLInformation.usNumberOfFreeBuffers--;
- return 0;
- }
-#endif
-}
-
-//*****************************************************************************
-//
-//! socket
-//!
-//! @param domain selects the protocol family which will be used for
-//! communication. On this version only AF_INET is supported
-//! @param type specifies the communication semantics. On this version
-//! only SOCK_STREAM, SOCK_DGRAM, SOCK_RAW are supported
-//! @param protocol specifies a particular protocol to be used with the
-//! socket IPPROTO_TCP, IPPROTO_UDP or IPPROTO_RAW are
-//! supported.
-//!
-//! @return On success, socket handle that is used for consequent socket
-//! operations. On error, -1 is returned.
-//!
-//! @brief create an endpoint for communication
-//! The socket function creates a socket that is bound to a specific
-//! transport service provider. This function is called by the
-//! application layer to obtain a socket handle.
-//
-//*****************************************************************************
-
-INT16 CC3000_EXPORT(socket)(INT32 domain, INT32 type, INT32 protocol)
-{
- INT32 ret;
- UINT8 *ptr, *args;
-
- ret = EFAIL;
- ptr = tSLInformation.pucTxCommandBuffer;
- args = (ptr + HEADERS_SIZE_CMD);
-
- // Fill in HCI packet structure
- args = UINT32_TO_STREAM(args, domain);
- args = UINT32_TO_STREAM(args, type);
- args = UINT32_TO_STREAM(args, protocol);
-
- // Initiate a HCI command
- hci_command_send(HCI_CMND_SOCKET, ptr, SOCKET_OPEN_PARAMS_LEN);
-
- // Since we are in blocking state - wait for event complete
- SimpleLinkWaitEvent(HCI_CMND_SOCKET, &ret);
-
- // Process the event
- CC3000_EXPORT(errno) = ret;
-
- set_socket_active_status(ret, SOCKET_STATUS_ACTIVE);
-
- return(ret);
-}
-
-//*****************************************************************************
-//
-//! closesocket
-//!
-//! @param sd socket handle.
-//!
-//! @return On success, zero is returned. On error, -1 is returned.
-//!
-//! @brief The socket function closes a created socket.
-//
-//*****************************************************************************
-
-INT32 CC3000_EXPORT(closesocket)(INT32 sd)
-{
- INT32 ret;
- UINT8 *ptr, *args;
-
- ret = EFAIL;
- ptr = tSLInformation.pucTxCommandBuffer;
- args = (ptr + HEADERS_SIZE_CMD);
-
- // Fill in HCI packet structure
- args = UINT32_TO_STREAM(args, sd);
-
- // Initiate a HCI command
- hci_command_send(HCI_CMND_CLOSE_SOCKET,
- ptr, SOCKET_CLOSE_PARAMS_LEN);
-
- // Since we are in blocking state - wait for event complete
- SimpleLinkWaitEvent(HCI_CMND_CLOSE_SOCKET, &ret);
- CC3000_EXPORT(errno) = ret;
-
- // since 'close' call may result in either OK (and then it closed) or error
- // mark this socket as invalid
- set_socket_active_status(sd, SOCKET_STATUS_INACTIVE);
-
- return(ret);
-}
-
-//*****************************************************************************
-//
-//! accept
-//!
-//! @param[in] sd socket descriptor (handle)
-//! @param[out] addr the argument addr is a pointer to a sockaddr structure
-//! This structure is filled in with the address of the
-//! peer socket, as known to the communications layer.
-//! determined. The exact format of the address returned
-//! addr is by the socket's address sockaddr.
-//! On this version only AF_INET is supported.
-//! This argument returns in network order.
-//! @param[out] addrlen the addrlen argument is a value-result argument:
-//! it should initially contain the size of the structure
-//! pointed to by addr.
-//!
-//! @return For socket in blocking mode:
-//! On success, socket handle. on failure negative
-//! For socket in non-blocking mode:
-//! - On connection establishment, socket handle
-//! - On connection pending, SOC_IN_PROGRESS (-2)
-//! - On failure, SOC_ERROR (-1)
-//!
-//! @brief accept a connection on a socket:
-//! This function is used with connection-based socket types
-//! (SOCK_STREAM). It extracts the first connection request on the
-//! queue of pending connections, creates a new connected socket, and
-//! returns a new file descriptor referring to that socket.
-//! The newly created socket is not in the listening state.
-//! The original socket sd is unaffected by this call.
-//! The argument sd is a socket that has been created with socket(),
-//! bound to a local address with bind(), and is listening for
-//! connections after a listen(). The argument addr is a pointer
-//! to a sockaddr structure. This structure is filled in with the
-//! address of the peer socket, as known to the communications layer.
-//! The exact format of the address returned addr is determined by the
-//! socket's address family. The addrlen argument is a value-result
-//! argument: it should initially contain the size of the structure
-//! pointed to by addr, on return it will contain the actual
-//! length (in bytes) of the address returned.
-//!
-//! @sa socket ; bind ; listen
-//
-//*****************************************************************************
-
-INT32 CC3000_EXPORT(accept)(INT32 sd, sockaddr *addr, socklen_t *addrlen)
-{
- INT32 ret;
- UINT8 *ptr, *args;
- tBsdReturnParams tAcceptReturnArguments;
-
- ret = EFAIL;
- ptr = tSLInformation.pucTxCommandBuffer;
- args = (ptr + HEADERS_SIZE_CMD);
-
- // Fill in temporary command buffer
- args = UINT32_TO_STREAM(args, sd);
-
- // Initiate a HCI command
- hci_command_send(HCI_CMND_ACCEPT,
- ptr, SOCKET_ACCEPT_PARAMS_LEN);
-
- // Since we are in blocking state - wait for event complete
- SimpleLinkWaitEvent(HCI_CMND_ACCEPT, &tAcceptReturnArguments);
-
-
- // need specify return parameters!!!
- memcpy(addr, &tAcceptReturnArguments.tSocketAddress, ASIC_ADDR_LEN);
- *addrlen = ASIC_ADDR_LEN;
- CC3000_EXPORT(errno) = tAcceptReturnArguments.iStatus;
- ret = CC3000_EXPORT(errno);
-
- // if succeeded, iStatus = new socket descriptor. otherwise - error number
- if(M_IS_VALID_SD(ret))
- {
- set_socket_active_status(ret, SOCKET_STATUS_ACTIVE);
- }
- else
- {
- set_socket_active_status(sd, SOCKET_STATUS_INACTIVE);
- }
-
- return(ret);
-}
-
-//*****************************************************************************
-//
-//! bind
-//!
-//! @param[in] sd socket descriptor (handle)
-//! @param[out] addr specifies the destination address. On this version
-//! only AF_INET is supported.
-//! @param[out] addrlen contains the size of the structure pointed to by addr.
-//!
-//! @return On success, zero is returned. On error, -1 is returned.
-//!
-//! @brief assign a name to a socket
-//! This function gives the socket the local address addr.
-//! addr is addrlen bytes long. Traditionally, this is called when a
-//! socket is created with socket, it exists in a name space (address
-//! family) but has no name assigned.
-//! It is necessary to assign a local address before a SOCK_STREAM
-//! socket may receive connections.
-//!
-//! @sa socket ; accept ; listen
-//
-//*****************************************************************************
-
-INT32 CC3000_EXPORT(bind)(INT32 sd, const sockaddr *addr, INT32 addrlen)
-{
- INT32 ret;
- UINT8 *ptr, *args;
-
- ret = EFAIL;
- ptr = tSLInformation.pucTxCommandBuffer;
- args = (ptr + HEADERS_SIZE_CMD);
-
- addrlen = ASIC_ADDR_LEN;
-
- // Fill in temporary command buffer
- args = UINT32_TO_STREAM(args, sd);
- args = UINT32_TO_STREAM(args, 0x00000008);
- args = UINT32_TO_STREAM(args, addrlen);
- ARRAY_TO_STREAM(args, ((UINT8 *)addr), addrlen);
-
- // Initiate a HCI command
- hci_command_send(HCI_CMND_BIND,
- ptr, SOCKET_BIND_PARAMS_LEN);
-
- // Since we are in blocking state - wait for event complete
- SimpleLinkWaitEvent(HCI_CMND_BIND, &ret);
-
- CC3000_EXPORT(errno) = ret;
-
- return(ret);
-}
-
-//*****************************************************************************
-//
-//! listen
-//!
-//! @param[in] sd socket descriptor (handle)
-//! @param[in] backlog specifies the listen queue depth. On this version
-//! backlog is not supported.
-//! @return On success, zero is returned. On error, -1 is returned.
-//!
-//! @brief listen for connections on a socket
-//! The willingness to accept incoming connections and a queue
-//! limit for incoming connections are specified with listen(),
-//! and then the connections are accepted with accept.
-//! The listen() call applies only to sockets of type SOCK_STREAM
-//! The backlog parameter defines the maximum length the queue of
-//! pending connections may grow to.
-//!
-//! @sa socket ; accept ; bind
-//!
-//! @note On this version, backlog is not supported
-//
-//*****************************************************************************
-
-INT32 CC3000_EXPORT(listen)(INT32 sd, INT32 backlog)
-{
- INT32 ret;
- UINT8 *ptr, *args;
-
- ret = EFAIL;
- ptr = tSLInformation.pucTxCommandBuffer;
- args = (ptr + HEADERS_SIZE_CMD);
-
- // Fill in temporary command buffer
- args = UINT32_TO_STREAM(args, sd);
- args = UINT32_TO_STREAM(args, backlog);
-
- // Initiate a HCI command
- hci_command_send(HCI_CMND_LISTEN,
- ptr, SOCKET_LISTEN_PARAMS_LEN);
-
- // Since we are in blocking state - wait for event complete
- SimpleLinkWaitEvent(HCI_CMND_LISTEN, &ret);
- CC3000_EXPORT(errno) = ret;
-
- return(ret);
-}
-
-//*****************************************************************************
-//
-//! gethostbyname
-//!
-//! @param[in] hostname host name
-//! @param[in] usNameLen name length
-//! @param[out] out_ip_addr This parameter is filled in with host IP address.
-//! In case that host name is not resolved,
-//! out_ip_addr is zero.
-//! @return On success, positive is returned. On error, negative is returned
-//!
-//! @brief Get host IP by name. Obtain the IP Address of machine on network,
-//! by its name.
-//!
-//! @note On this version, only blocking mode is supported. Also note that
-//! the function requires DNS server to be configured prior to its usage.
-//
-//*****************************************************************************
-
-#ifndef CC3000_TINY_DRIVER
-INT16 CC3000_EXPORT(gethostbyname)(CHAR * hostname, UINT16 usNameLen,
- UINT32* out_ip_addr)
-{
- tBsdGethostbynameParams ret;
- UINT8 *ptr, *args;
-
- CC3000_EXPORT(errno) = EFAIL;
-
- if (usNameLen > HOSTNAME_MAX_LENGTH)
- {
- return CC3000_EXPORT(errno);
- }
-
- ptr = tSLInformation.pucTxCommandBuffer;
- args = (ptr + SIMPLE_LINK_HCI_CMND_TRANSPORT_HEADER_SIZE);
-
- // Fill in HCI packet structure
- args = UINT32_TO_STREAM(args, 8);
- args = UINT32_TO_STREAM(args, usNameLen);
- ARRAY_TO_STREAM(args, hostname, usNameLen);
-
- // Initiate a HCI command
- hci_command_send(HCI_CMND_GETHOSTNAME, ptr, SOCKET_GET_HOST_BY_NAME_PARAMS_LEN
- + usNameLen - 1);
-
- // Since we are in blocking state - wait for event complete
- SimpleLinkWaitEvent(HCI_EVNT_BSD_GETHOSTBYNAME, &ret);
-
- CC3000_EXPORT(errno) = ret.retVal;
-
- (*((INT32*)out_ip_addr)) = ret.outputAddress;
-
- return CC3000_EXPORT(errno);
-
-}
-#endif
-
-//*****************************************************************************
-//
-//! connect
-//!
-//! @param[in] sd socket descriptor (handle)
-//! @param[in] addr specifies the destination addr. On this version
-//! only AF_INET is supported.
-//! @param[out] addrlen contains the size of the structure pointed to by addr
-//! @return On success, zero is returned. On error, -1 is returned
-//!
-//! @brief initiate a connection on a socket
-//! Function connects the socket referred to by the socket descriptor
-//! sd, to the address specified by addr. The addrlen argument
-//! specifies the size of addr. The format of the address in addr is
-//! determined by the address space of the socket. If it is of type
-//! SOCK_DGRAM, this call specifies the peer with which the socket is
-//! to be associated; this address is that to which datagrams are to be
-//! sent, and the only address from which datagrams are to be received.
-//! If the socket is of type SOCK_STREAM, this call attempts to make a
-//! connection to another socket. The other socket is specified by
-//! address, which is an address in the communications space of the
-//! socket. Note that the function implements only blocking behavior
-//! thus the caller will be waiting either for the connection
-//! establishment or for the connection establishment failure.
-//!
-//! @sa socket
-//
-//*****************************************************************************
-
-INT32 CC3000_EXPORT(connect)(INT32 sd, const sockaddr *addr, INT32 addrlen)
-{
- INT32 ret;
- UINT8 *ptr, *args;
-
- ret = EFAIL;
- ptr = tSLInformation.pucTxCommandBuffer;
- args = (ptr + SIMPLE_LINK_HCI_CMND_TRANSPORT_HEADER_SIZE);
- addrlen = 8;
-
- // Fill in temporary command buffer
- args = UINT32_TO_STREAM(args, sd);
- args = UINT32_TO_STREAM(args, 0x00000008);
- args = UINT32_TO_STREAM(args, addrlen);
- ARRAY_TO_STREAM(args, ((UINT8 *)addr), addrlen);
-
- // Initiate a HCI command
- hci_command_send(HCI_CMND_CONNECT,
- ptr, SOCKET_CONNECT_PARAMS_LEN);
-
- // Since we are in blocking state - wait for event complete
- SimpleLinkWaitEvent(HCI_CMND_CONNECT, &ret);
-
- CC3000_EXPORT(errno) = ret;
-
- return((INT32)ret);
-}
-
-
-//*****************************************************************************
-//
-//! select
-//!
-//! @param[in] nfds the highest-numbered file descriptor in any of the
-//! three sets, plus 1.
-//! @param[out] writesds socket descriptors list for write monitoring
-//! @param[out] readsds socket descriptors list for read monitoring
-//! @param[out] exceptsds socket descriptors list for exception monitoring
-//! @param[in] timeout is an upper bound on the amount of time elapsed
-//! before select() returns. Null means infinity
-//! timeout. The minimum timeout is 5 milliseconds,
-//! less than 5 milliseconds will be set
-//! automatically to 5 milliseconds.
-//! @return On success, select() returns the number of file descriptors
-//! contained in the three returned descriptor sets (that is, the
-//! total number of bits that are set in readfds, writefds,
-//! exceptfds) which may be zero if the timeout expires before
-//! anything interesting happens.
-//! On error, -1 is returned.
-//! *readsds - return the sockets on which Read request will
-//! return without delay with valid data.
-//! *writesds - return the sockets on which Write request
-//! will return without delay.
-//! *exceptsds - return the sockets which closed recently.
-//!
-//! @brief Monitor socket activity
-//! Select allow a program to monitor multiple file descriptors,
-//! waiting until one or more of the file descriptors become
-//! "ready" for some class of I/O operation
-//!
-//! @Note If the timeout value set to less than 5ms it will automatically set
-//! to 5ms to prevent overload of the system
-//!
-//! @sa socket
-//
-//*****************************************************************************
-
-INT16 CC3000_EXPORT(select)(INT32 nfds, fd_set *readsds, fd_set *writesds, fd_set *exceptsds,
-struct cc3000_timeval *timeout)
-{
- UINT8 *ptr, *args;
- tBsdSelectRecvParams tParams;
- UINT32 is_blocking;
-
- if( timeout == NULL)
- {
- is_blocking = 1; /* blocking , infinity timeout */
- }
- else
- {
- is_blocking = 0; /* no blocking, timeout */
- }
-
- // Fill in HCI packet structure
- ptr = tSLInformation.pucTxCommandBuffer;
- args = (ptr + HEADERS_SIZE_CMD);
-
- // Fill in temporary command buffer
- args = UINT32_TO_STREAM(args, nfds);
- args = UINT32_TO_STREAM(args, 0x00000014);
- args = UINT32_TO_STREAM(args, 0x00000014);
- args = UINT32_TO_STREAM(args, 0x00000014);
- args = UINT32_TO_STREAM(args, 0x00000014);
- args = UINT32_TO_STREAM(args, is_blocking);
- args = UINT32_TO_STREAM(args, ((readsds) ? *(UINT32*)readsds : 0));
- args = UINT32_TO_STREAM(args, ((writesds) ? *(UINT32*)writesds : 0));
- args = UINT32_TO_STREAM(args, ((exceptsds) ? *(UINT32*)exceptsds : 0));
-
- if (timeout)
- {
- if ( 0 == timeout->tv_sec && timeout->tv_usec <
- SELECT_TIMEOUT_MIN_MICRO_SECONDS)
- {
- timeout->tv_usec = SELECT_TIMEOUT_MIN_MICRO_SECONDS;
- }
- args = UINT32_TO_STREAM(args, timeout->tv_sec);
- args = UINT32_TO_STREAM(args, timeout->tv_usec);
- }
-
- // Initiate a HCI command
- hci_command_send(HCI_CMND_BSD_SELECT, ptr, SOCKET_SELECT_PARAMS_LEN);
-
- // Since we are in blocking state - wait for event complete
- SimpleLinkWaitEvent(HCI_EVNT_SELECT, &tParams);
-
- // Update actually read FD
- if (tParams.iStatus >= 0)
- {
- if (readsds)
- {
- memcpy(readsds, &tParams.uiRdfd, sizeof(tParams.uiRdfd));
- }
-
- if (writesds)
- {
- memcpy(writesds, &tParams.uiWrfd, sizeof(tParams.uiWrfd));
- }
-
- if (exceptsds)
- {
- memcpy(exceptsds, &tParams.uiExfd, sizeof(tParams.uiExfd));
- }
-
- return(tParams.iStatus);
-
- }
- else
- {
- CC3000_EXPORT(errno) = tParams.iStatus;
- return(-1);
- }
-}
-
-//*****************************************************************************
-//
-//! setsockopt
-//!
-//! @param[in] sd socket handle
-//! @param[in] level defines the protocol level for this option
-//! @param[in] optname defines the option name to Interrogate
-//! @param[in] optval specifies a value for the option
-//! @param[in] optlen specifies the length of the option value
-//! @return On success, zero is returned. On error, -1 is returned
-//!
-//! @brief set socket options
-//! This function manipulate the options associated with a socket.
-//! Options may exist at multiple protocol levels; they are always
-//! present at the uppermost socket level.
-//! When manipulating socket options the level at which the option
-//! resides and the name of the option must be specified.
-//! To manipulate options at the socket level, level is specified as
-//! SOL_SOCKET. To manipulate options at any other level the protocol
-//! number of the appropriate protocol controlling the option is
-//! supplied. For example, to indicate that an option is to be
-//! interpreted by the TCP protocol, level should be set to the
-//! protocol number of TCP;
-//! The parameters optval and optlen are used to access optval -
-//! use for setsockopt(). For getsockopt() they identify a buffer
-//! in which the value for the requested option(s) are to
-//! be returned. For getsockopt(), optlen is a value-result
-//! parameter, initially containing the size of the buffer
-//! pointed to by option_value, and modified on return to
-//! indicate the actual size of the value returned. If no option
-//! value is to be supplied or returned, option_value may be NULL.
-//!
-//! @Note On this version the following two socket options are enabled:
-//! The only protocol level supported in this version
-//! is SOL_SOCKET (level).
-//! 1. SOCKOPT_RECV_TIMEOUT (optname)
-//! SOCKOPT_RECV_TIMEOUT configures recv and recvfrom timeout
-//! in milliseconds.
-//! In that case optval should be pointer to UINT32.
-//! 2. SOCKOPT_NONBLOCK (optname). sets the socket non-blocking mode on
-//! or off.
-//! In that case optval should be SOCK_ON or SOCK_OFF (optval).
-//!
-//! @sa getsockopt
-//
-//*****************************************************************************
-
-#ifndef CC3000_TINY_DRIVER
-INT16 CC3000_EXPORT(setsockopt)(INT32 sd, INT32 level, INT32 optname, const void *optval,
- socklen_t optlen)
-{
- INT32 ret;
- UINT8 *ptr, *args;
-
- ptr = tSLInformation.pucTxCommandBuffer;
- args = (ptr + HEADERS_SIZE_CMD);
-
- // Fill in temporary command buffer
- args = UINT32_TO_STREAM(args, sd);
- args = UINT32_TO_STREAM(args, level);
- args = UINT32_TO_STREAM(args, optname);
- args = UINT32_TO_STREAM(args, 0x00000008);
- args = UINT32_TO_STREAM(args, optlen);
- ARRAY_TO_STREAM(args, ((UINT8 *)optval), optlen);
-
- // Initiate a HCI command
- hci_command_send(HCI_CMND_SETSOCKOPT,
- ptr, SOCKET_SET_SOCK_OPT_PARAMS_LEN + optlen);
-
- // Since we are in blocking state - wait for event complete
- SimpleLinkWaitEvent(HCI_CMND_SETSOCKOPT, &ret);
-
- if (ret >= 0)
- {
- return (0);
- }
- else
- {
- CC3000_EXPORT(errno) = ret;
- return ret;
- }
-}
-#endif
-
-//*****************************************************************************
-//
-//! getsockopt
-//!
-//! @param[in] sd socket handle
-//! @param[in] level defines the protocol level for this option
-//! @param[in] optname defines the option name to Interrogate
-//! @param[out] optval specifies a value for the option
-//! @param[out] optlen specifies the length of the option value
-//! @return On success, zero is returned. On error, -1 is returned
-//!
-//! @brief set socket options
-//! This function manipulate the options associated with a socket.
-//! Options may exist at multiple protocol levels; they are always
-//! present at the uppermost socket level.
-//! When manipulating socket options the level at which the option
-//! resides and the name of the option must be specified.
-//! To manipulate options at the socket level, level is specified as
-//! SOL_SOCKET. To manipulate options at any other level the protocol
-//! number of the appropriate protocol controlling the option is
-//! supplied. For example, to indicate that an option is to be
-//! interpreted by the TCP protocol, level should be set to the
-//! protocol number of TCP;
-//! The parameters optval and optlen are used to access optval -
-//! use for setsockopt(). For getsockopt() they identify a buffer
-//! in which the value for the requested option(s) are to
-//! be returned. For getsockopt(), optlen is a value-result
-//! parameter, initially containing the size of the buffer
-//! pointed to by option_value, and modified on return to
-//! indicate the actual size of the value returned. If no option
-//! value is to be supplied or returned, option_value may be NULL.
-//!
-//! @Note On this version the following two socket options are enabled:
-//! The only protocol level supported in this version
-//! is SOL_SOCKET (level).
-//! 1. SOCKOPT_RECV_TIMEOUT (optname)
-//! SOCKOPT_RECV_TIMEOUT configures recv and recvfrom timeout
-//! in milliseconds.
-//! In that case optval should be pointer to UINT32.
-//! 2. SOCKOPT_NONBLOCK (optname). sets the socket non-blocking mode on
-//! or off.
-//! In that case optval should be SOCK_ON or SOCK_OFF (optval).
-//!
-//! @sa setsockopt
-//
-//*****************************************************************************
-
-INT16 CC3000_EXPORT(getsockopt) (INT32 sd, INT32 level, INT32 optname, void *optval, socklen_t *optlen)
-{
- UINT8 *ptr, *args;
- tBsdGetSockOptReturnParams tRetParams;
-
- ptr = tSLInformation.pucTxCommandBuffer;
- args = (ptr + HEADERS_SIZE_CMD);
-
- // Fill in temporary command buffer
- args = UINT32_TO_STREAM(args, sd);
- args = UINT32_TO_STREAM(args, level);
- args = UINT32_TO_STREAM(args, optname);
-
- // Initiate a HCI command
- hci_command_send(HCI_CMND_GETSOCKOPT,
- ptr, SOCKET_GET_SOCK_OPT_PARAMS_LEN);
-
- // Since we are in blocking state - wait for event complete
- SimpleLinkWaitEvent(HCI_CMND_GETSOCKOPT, &tRetParams);
-
- if (((INT8)tRetParams.iStatus) >= 0)
- {
- *optlen = 4;
- memcpy(optval, tRetParams.ucOptValue, 4);
- return (0);
- }
- else
- {
- CC3000_EXPORT(errno) = tRetParams.iStatus;
- return CC3000_EXPORT(errno);
- }
-}
-
-//*****************************************************************************
-//
-//! simple_link_recv
-//!
-//! @param sd socket handle
-//! @param buf read buffer
-//! @param len buffer length
-//! @param flags indicates blocking or non-blocking operation
-//! @param from pointer to an address structure indicating source address
-//! @param fromlen source address structure size
-//!
-//! @return Return the number of bytes received, or -1 if an error
-//! occurred
-//!
-//! @brief Read data from socket
-//! Return the length of the message on successful completion.
-//! If a message is too long to fit in the supplied buffer,
-//! excess bytes may be discarded depending on the type of
-//! socket the message is received from
-//
-//*****************************************************************************
-static INT16 simple_link_recv(INT32 sd, void *buf, INT32 len, INT32 flags, sockaddr *from,
- socklen_t *fromlen, INT32 opcode)
-{
- UINT8 *ptr, *args;
- tBsdReadReturnParams tSocketReadEvent;
-
- ptr = tSLInformation.pucTxCommandBuffer;
- args = (ptr + HEADERS_SIZE_CMD);
-
- // Fill in HCI packet structure
- args = UINT32_TO_STREAM(args, sd);
- args = UINT32_TO_STREAM(args, len);
- args = UINT32_TO_STREAM(args, flags);
-
- // Generate the read command, and wait for the
- hci_command_send(opcode, ptr, SOCKET_RECV_FROM_PARAMS_LEN);
-
- // Since we are in blocking state - wait for event complete
- SimpleLinkWaitEvent(opcode, &tSocketReadEvent);
-
- // In case the number of bytes is more then zero - read data
- if (tSocketReadEvent.iNumberOfBytes > 0)
- {
- // Wait for the data in a synchronous way. Here we assume that the bug is
- // big enough to store also parameters of receive from too....
- SimpleLinkWaitData(buf, (UINT8 *)from, (UINT8 *)fromlen);
- }
-
- CC3000_EXPORT(errno) = tSocketReadEvent.iNumberOfBytes;
-
- return(tSocketReadEvent.iNumberOfBytes);
-}
-
-//*****************************************************************************
-//
-//! recv
-//!
-//! @param[in] sd socket handle
-//! @param[out] buf Points to the buffer where the message should be stored
-//! @param[in] len Specifies the length in bytes of the buffer pointed to
-//! by the buffer argument.
-//! @param[in] flags Specifies the type of message reception.
-//! On this version, this parameter is not supported.
-//!
-//! @return Return the number of bytes received, or -1 if an error
-//! occurred
-//!
-//! @brief function receives a message from a connection-mode socket
-//!
-//! @sa recvfrom
-//!
-//! @Note On this version, only blocking mode is supported.
-//
-//*****************************************************************************
-
-INT16 CC3000_EXPORT(recv)(INT32 sd, void *buf, INT32 len, INT32 flags)
-{
- return(simple_link_recv(sd, buf, len, flags, NULL, NULL, HCI_CMND_RECV));
-}
-
-//*****************************************************************************
-//
-//! recvfrom
-//!
-//! @param[in] sd socket handle
-//! @param[out] buf Points to the buffer where the message should be stored
-//! @param[in] len Specifies the length in bytes of the buffer pointed to
-//! by the buffer argument.
-//! @param[in] flags Specifies the type of message reception.
-//! On this version, this parameter is not supported.
-//! @param[in] from pointer to an address structure indicating the source
-//! address: sockaddr. On this version only AF_INET is
-//! supported.
-//! @param[in] fromlen source address tructure size
-//!
-//! @return Return the number of bytes received, or -1 if an error
-//! occurred
-//!
-//! @brief read data from socket
-//! function receives a message from a connection-mode or
-//! connectionless-mode socket. Note that raw sockets are not
-//! supported.
-//!
-//! @sa recv
-//!
-//! @Note On this version, only blocking mode is supported.
-//
-//*****************************************************************************
-INT16 CC3000_EXPORT(recvfrom)(INT32 sd, void *buf, INT32 len, INT32 flags, sockaddr *from,
- socklen_t *fromlen)
-{
- return(simple_link_recv(sd, buf, len, flags, from, fromlen,
- HCI_CMND_RECVFROM));
-}
-
-//*****************************************************************************
-//
-//! simple_link_send
-//!
-//! @param sd socket handle
-//! @param buf write buffer
-//! @param len buffer length
-//! @param flags On this version, this parameter is not supported
-//! @param to pointer to an address structure indicating destination
-//! address
-//! @param tolen destination address structure size
-//!
-//! @return Return the number of bytes transmitted, or -1 if an error
-//! occurred, or -2 in case there are no free buffers available
-//! (only when SEND_NON_BLOCKING is enabled)
-//!
-//! @brief This function is used to transmit a message to another
-//! socket
-//
-//*****************************************************************************
-static INT16 simple_link_send(INT32 sd, const void *buf, INT32 len, INT32 flags,
- const sockaddr *to, INT32 tolen, INT32 opcode)
-{
- UINT8 uArgSize=0, addrlen;
- UINT8 *ptr, *pDataPtr=0, *args;
- UINT32 addr_offset=0;
- INT16 res;
- tBsdReadReturnParams tSocketSendEvent;
-
- // Check the bsd_arguments
- if (0 != (res = HostFlowControlConsumeBuff(sd)))
- {
- return res;
- }
-
- //Update the number of sent packets
- tSLInformation.NumberOfSentPackets++;
-
- // Allocate a buffer and construct a packet and send it over spi
- ptr = tSLInformation.pucTxCommandBuffer;
- args = (ptr + HEADERS_SIZE_DATA);
-
- // Update the offset of data and parameters according to the command
- switch(opcode)
- {
- case HCI_CMND_SENDTO:
- {
- addr_offset = len + sizeof(len) + sizeof(len);
- addrlen = 8;
- uArgSize = SOCKET_SENDTO_PARAMS_LEN;
- pDataPtr = ptr + HEADERS_SIZE_DATA + SOCKET_SENDTO_PARAMS_LEN;
- break;
- }
-
- case HCI_CMND_SEND:
- {
- tolen = 0;
- to = NULL;
- uArgSize = HCI_CMND_SEND_ARG_LENGTH;
- pDataPtr = ptr + HEADERS_SIZE_DATA + HCI_CMND_SEND_ARG_LENGTH;
- break;
- }
-
- default:
- {
- break;
- }
- }
-
- // Fill in temporary command buffer
- args = UINT32_TO_STREAM(args, sd);
- args = UINT32_TO_STREAM(args, uArgSize - sizeof(sd));
- args = UINT32_TO_STREAM(args, len);
- args = UINT32_TO_STREAM(args, flags);
-
- if (opcode == HCI_CMND_SENDTO)
- {
- args = UINT32_TO_STREAM(args, addr_offset);
- args = UINT32_TO_STREAM(args, addrlen);
- }
-
- // Copy the data received from user into the TX Buffer
- ARRAY_TO_STREAM(pDataPtr, ((UINT8 *)buf), len);
-
- // In case we are using SendTo, copy the to parameters
- if (opcode == HCI_CMND_SENDTO)
- {
- ARRAY_TO_STREAM(pDataPtr, ((UINT8 *)to), tolen);
- }
-
- // Initiate a HCI command
- hci_data_send(opcode, ptr, uArgSize, len,(UINT8*)to, tolen);
-
- if (opcode == HCI_CMND_SENDTO)
- SimpleLinkWaitEvent(HCI_EVNT_SENDTO, &tSocketSendEvent);
- else
- SimpleLinkWaitEvent(HCI_EVNT_SEND, &tSocketSendEvent);
-
- return (len);
-}
-
-
-//*****************************************************************************
-//
-//! send
-//!
-//! @param sd socket handle
-//! @param buf Points to a buffer containing the message to be sent
-//! @param len message size in bytes
-//! @param flags On this version, this parameter is not supported
-//!
-//! @return Return the number of bytes transmitted, or -1 if an
-//! error occurred
-//!
-//! @brief Write data to TCP socket
-//! This function is used to transmit a message to another
-//! socket.
-//!
-//! @Note On this version, only blocking mode is supported.
-//!
-//! @sa sendto
-//
-//*****************************************************************************
-
-INT16 CC3000_EXPORT(send)(INT32 sd, const void *buf, INT32 len, INT32 flags)
-{
- return(simple_link_send(sd, buf, len, flags, NULL, 0, HCI_CMND_SEND));
-}
-
-//*****************************************************************************
-//
-//! sendto
-//!
-//! @param sd socket handle
-//! @param buf Points to a buffer containing the message to be sent
-//! @param len message size in bytes
-//! @param flags On this version, this parameter is not supported
-//! @param to pointer to an address structure indicating the destination
-//! address: sockaddr. On this version only AF_INET is
-//! supported.
-//! @param tolen destination address structure size
-//!
-//! @return Return the number of bytes transmitted, or -1 if an
-//! error occurred
-//!
-//! @brief Write data to TCP socket
-//! This function is used to transmit a message to another
-//! socket.
-//!
-//! @Note On this version, only blocking mode is supported.
-//!
-//! @sa send
-//
-//*****************************************************************************
-
-INT16 CC3000_EXPORT(sendto)(INT32 sd, const void *buf, INT32 len, INT32 flags, const sockaddr *to,
- socklen_t tolen)
-{
- return(simple_link_send(sd, buf, len, flags, to, tolen, HCI_CMND_SENDTO));
-}
-
-//*****************************************************************************
-//
-//! mdnsAdvertiser
-//!
-//! @param[in] mdnsEnabled flag to enable/disable the mDNS feature
-//! @param[in] deviceServiceName Service name as part of the published
-//! canonical domain name
-//! @param[in] deviceServiceNameLength Length of the service name - up to 32 chars
-//!
-//!
-//! @return On success, zero is returned, return SOC_ERROR if socket was not
-//! opened successfully, or if an error occurred.
-//!
-//! @brief Set CC3000 in mDNS advertiser mode in order to advertise itself.
-//
-//*****************************************************************************
-
-INT16 CC3000_EXPORT(mdnsAdvertiser)(UINT16 mdnsEnabled, CHAR * deviceServiceName, UINT16 deviceServiceNameLength)
-{
- INT8 ret;
- UINT8 *pTxBuffer, *pArgs;
-
- if (deviceServiceNameLength > MDNS_DEVICE_SERVICE_MAX_LENGTH)
- {
- return EFAIL;
- }
-
- pTxBuffer = tSLInformation.pucTxCommandBuffer;
- pArgs = (pTxBuffer + SIMPLE_LINK_HCI_CMND_TRANSPORT_HEADER_SIZE);
-
- // Fill in HCI packet structure
- pArgs = UINT32_TO_STREAM(pArgs, mdnsEnabled);
- pArgs = UINT32_TO_STREAM(pArgs, 8);
- pArgs = UINT32_TO_STREAM(pArgs, deviceServiceNameLength);
- ARRAY_TO_STREAM(pArgs, deviceServiceName, deviceServiceNameLength);
-
- // Initiate a HCI command
- hci_command_send(HCI_CMND_MDNS_ADVERTISE, pTxBuffer, SOCKET_MDNS_ADVERTISE_PARAMS_LEN + deviceServiceNameLength);
-
- // Since we are in blocking state - wait for event complete
- SimpleLinkWaitEvent(HCI_EVNT_MDNS_ADVERTISE, &ret);
-
- return ret;
-
-}
-
-
-//*****************************************************************************
-//
-//! getmssvalue
-//!
-//! @param[in] sd socket descriptor
-//!
-//! @return On success, returns the MSS value of a TCP connection
-//!
-//! @brief Returns the MSS value of a TCP connection according to the socket descriptor
-//
-//*****************************************************************************
-UINT16 CC3000_EXPORT(getmssvalue) (INT32 sd)
-{
- UINT8 *ptr, *args;
- UINT16 ret;
-
- ptr = tSLInformation.pucTxCommandBuffer;
- args = (ptr + HEADERS_SIZE_CMD);
-
- // Fill in temporary command buffer
- args = UINT32_TO_STREAM(args, sd);
-
- // Initiate a HCI command
- hci_command_send(HCI_CMND_GETMSSVALUE, ptr, SOCKET_GET_MSS_VALUE_PARAMS_LEN);
-
- // Since we are in blocking state - wait for event complete
- SimpleLinkWaitEvent(HCI_EVNT_GETMSSVALUE, &ret);
-
- return ret;
-}
diff --git a/drivers/cc3000/src/wlan.c b/drivers/cc3000/src/wlan.c
deleted file mode 100644
index 6385937778cc..000000000000
--- a/drivers/cc3000/src/wlan.c
+++ /dev/null
@@ -1,1252 +0,0 @@
-/*****************************************************************************
-*
-* wlan.c - CC3000 Host Driver Implementation.
-* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
-*
-* 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 Texas Instruments Incorporated 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
-* OWNER 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.
-*
-*****************************************************************************/
-
-//*****************************************************************************
-//
-//! \addtogroup wlan_api
-//! @{
-//
-//*****************************************************************************
-
-#include
-#include "wlan.h"
-#include "hci.h"
-#include "ccspi.h"
-#include "socket.h"
-#include "nvmem.h"
-#include "security.h"
-#include "evnt_handler.h"
-
-
-volatile sSimplLinkInformation tSLInformation;
-
-#define SMART_CONFIG_PROFILE_SIZE 67 // 67 = 32 (max ssid) + 32 (max key) + 1 (SSID length) + 1 (security type) + 1 (key length)
-
-#ifndef CC3000_UNENCRYPTED_SMART_CONFIG
-UINT8 key[AES128_KEY_SIZE];
-UINT8 profileArray[SMART_CONFIG_PROFILE_SIZE];
-#endif //CC3000_UNENCRYPTED_SMART_CONFIG
-
-/* patches type */
-#define PATCHES_HOST_TYPE_WLAN_DRIVER 0x01
-#define PATCHES_HOST_TYPE_WLAN_FW 0x02
-#define PATCHES_HOST_TYPE_BOOTLOADER 0x03
-
-#define SL_SET_SCAN_PARAMS_INTERVAL_LIST_SIZE (16)
-#define SL_SIMPLE_CONFIG_PREFIX_LENGTH (3)
-#define ETH_ALEN (6)
-#define MAXIMAL_SSID_LENGTH (32)
-
-#define SL_PATCHES_REQUEST_DEFAULT (0)
-#define SL_PATCHES_REQUEST_FORCE_HOST (1)
-#define SL_PATCHES_REQUEST_FORCE_NONE (2)
-
-
-#define WLAN_SEC_UNSEC (0)
-#define WLAN_SEC_WEP (1)
-#define WLAN_SEC_WPA (2)
-#define WLAN_SEC_WPA2 (3)
-
-
-#define WLAN_SL_INIT_START_PARAMS_LEN (1)
-#define WLAN_PATCH_PARAMS_LENGTH (8)
-#define WLAN_SET_CONNECTION_POLICY_PARAMS_LEN (12)
-#define WLAN_DEL_PROFILE_PARAMS_LEN (4)
-#define WLAN_SET_MASK_PARAMS_LEN (4)
-#define WLAN_SET_SCAN_PARAMS_LEN (100)
-#define WLAN_GET_SCAN_RESULTS_PARAMS_LEN (4)
-#define WLAN_ADD_PROFILE_NOSEC_PARAM_LEN (24)
-#define WLAN_ADD_PROFILE_WEP_PARAM_LEN (36)
-#define WLAN_ADD_PROFILE_WPA_PARAM_LEN (44)
-#define WLAN_CONNECT_PARAM_LEN (29)
-#define WLAN_SMART_CONFIG_START_PARAMS_LEN (4)
-
-
-
-
-//*****************************************************************************
-//
-//! SimpleLink_Init_Start
-//!
-//! @param usPatchesAvailableAtHost flag to indicate if patches available
-//! from host or from EEPROM. Due to the
-//! fact the patches are burn to the EEPROM
-//! using the patch programmer utility, the
-//! patches will be available from the EEPROM
-//! and not from the host.
-//!
-//! @return none
-//!
-//! @brief Send HCI_CMND_SIMPLE_LINK_START to CC3000
-//
-//*****************************************************************************
-static void SimpleLink_Init_Start(UINT16 usPatchesAvailableAtHost)
-{
- UINT8 *ptr;
- UINT8 *args;
-
- ptr = tSLInformation.pucTxCommandBuffer;
- args = (UINT8 *)(ptr + HEADERS_SIZE_CMD);
-
- UINT8_TO_STREAM(args, ((usPatchesAvailableAtHost) ? SL_PATCHES_REQUEST_FORCE_NONE : SL_PATCHES_REQUEST_DEFAULT));
-
- // IRQ Line asserted - send HCI_CMND_SIMPLE_LINK_START to CC3000
- hci_command_send(HCI_CMND_SIMPLE_LINK_START, ptr, WLAN_SL_INIT_START_PARAMS_LEN);
-
- SimpleLinkWaitEvent(HCI_CMND_SIMPLE_LINK_START, 0);
-}
-
-
-
-//*****************************************************************************
-//
-//! wlan_init
-//!
-//! @param sWlanCB Asynchronous events callback.
-//! 0 no event call back.
-//! -call back parameters:
-//! 1) event_type: HCI_EVNT_WLAN_UNSOL_CONNECT connect event,
-//! HCI_EVNT_WLAN_UNSOL_DISCONNECT disconnect event,
-//! HCI_EVNT_WLAN_ASYNC_SIMPLE_CONFIG_DONE config done,
-//! HCI_EVNT_WLAN_UNSOL_DHCP dhcp report,
-//! HCI_EVNT_WLAN_ASYNC_PING_REPORT ping report OR
-//! HCI_EVNT_WLAN_KEEPALIVE keepalive.
-//! 2) data: pointer to extra data that received by the event
-//! (NULL no data).
-//! 3) length: data length.
-//! -Events with extra data:
-//! HCI_EVNT_WLAN_UNSOL_DHCP: 4 bytes IP, 4 bytes Mask,
-//! 4 bytes default gateway, 4 bytes DHCP server and 4 bytes
-//! for DNS server.
-//! HCI_EVNT_WLAN_ASYNC_PING_REPORT: 4 bytes Packets sent,
-//! 4 bytes Packets received, 4 bytes Min round time,
-//! 4 bytes Max round time and 4 bytes for Avg round time.
-//!
-//! @param sFWPatches 0 no patch or pointer to FW patches
-//! @param sDriverPatches 0 no patch or pointer to driver patches
-//! @param sBootLoaderPatches 0 no patch or pointer to bootloader patches
-//! @param sReadWlanInterruptPin init callback. the callback read wlan
-//! interrupt status.
-//! @param sWlanInterruptEnable init callback. the callback enable wlan
-//! interrupt.
-//! @param sWlanInterruptDisable init callback. the callback disable wlan
-//! interrupt.
-//! @param sWriteWlanPin init callback. the callback write value
-//! to device pin.
-//!
-//! @return none
-//!
-//! @sa wlan_set_event_mask , wlan_start , wlan_stop
-//!
-//! @brief Initialize wlan driver
-//!
-//! @warning This function must be called before ANY other wlan driver function
-//
-//*****************************************************************************
-
-void wlan_init( tWlanCB sWlanCB,
- tFWPatches sFWPatches,
- tDriverPatches sDriverPatches,
- tBootLoaderPatches sBootLoaderPatches,
- tWlanReadInteruptPin sReadWlanInterruptPin,
- tWlanInterruptEnable sWlanInterruptEnable,
- tWlanInterruptDisable sWlanInterruptDisable,
- tWriteWlanPin sWriteWlanPin)
-{
-
- tSLInformation.sFWPatches = sFWPatches;
- tSLInformation.sDriverPatches = sDriverPatches;
- tSLInformation.sBootLoaderPatches = sBootLoaderPatches;
-
- // init io callback
- tSLInformation.ReadWlanInterruptPin = sReadWlanInterruptPin;
- tSLInformation.WlanInterruptEnable = sWlanInterruptEnable;
- tSLInformation.WlanInterruptDisable = sWlanInterruptDisable;
- tSLInformation.WriteWlanPin = sWriteWlanPin;
-
- //init asynchronous events callback
- tSLInformation.sWlanCB= sWlanCB;
-
- // By default TX Complete events are routed to host too
- tSLInformation.InformHostOnTxComplete = 1;
-}
-
-//*****************************************************************************
-//
-//! SpiReceiveHandler
-//!
-//! @param pvBuffer - pointer to the received data buffer
-//! The function triggers Received event/data processing
-//!
-//! @param Pointer to the received data
-//! @return none
-//!
-//! @brief The function triggers Received event/data processing. It is
-//! called from the SPI library to receive the data
-//
-//*****************************************************************************
-void SpiReceiveHandler(void *pvBuffer)
-{
- tSLInformation.usEventOrDataReceived = 1;
- tSLInformation.pucReceivedData = (UINT8 *)pvBuffer;
-
- hci_unsolicited_event_handler();
-}
-
-
-//*****************************************************************************
-//
-//! wlan_start
-//!
-//! @param usPatchesAvailableAtHost - flag to indicate if patches available
-//! from host or from EEPROM. Due to the
-//! fact the patches are burn to the EEPROM
-//! using the patch programmer utility, the
-//! patches will be available from the EEPROM
-//! and not from the host.
-//!
-//! @return none
-//!
-//! @brief Start WLAN device. This function asserts the enable pin of
-//! the device (WLAN_EN), starting the HW initialization process.
-//! The function blocked until device Initialization is completed.
-//! Function also configure patches (FW, driver or bootloader)
-//! and calls appropriate device callbacks.
-//!
-//! @Note Prior calling the function wlan_init shall be called.
-//! @Warning This function must be called after wlan_init and before any
-//! other wlan API
-//! @sa wlan_init , wlan_stop
-//!
-//
-//*****************************************************************************
-#define TIMEOUT (500000)
-
-int wlan_start(UINT16 usPatchesAvailableAtHost)
-{
-
- UINT32 ulSpiIRQState;
- UINT32 wlan_timeout;
-
- tSLInformation.NumberOfSentPackets = 0;
- tSLInformation.NumberOfReleasedPackets = 0;
- tSLInformation.usRxEventOpcode = 0;
- tSLInformation.usNumberOfFreeBuffers = 0;
- tSLInformation.usSlBufferLength = 0;
- tSLInformation.usBufferSize = 0;
- tSLInformation.usRxDataPending = 0;
- tSLInformation.slTransmitDataError = 0;
- tSLInformation.usEventOrDataReceived = 0;
- tSLInformation.pucReceivedData = 0;
-
- // Allocate the memory for the RX/TX data transactions
- tSLInformation.pucTxCommandBuffer = (UINT8 *)wlan_tx_buffer;
-
- // init spi
- SpiOpen(SpiReceiveHandler);
-
- // Check the IRQ line
- ulSpiIRQState = tSLInformation.ReadWlanInterruptPin();
-
- // Chip enable: toggle WLAN EN line
- tSLInformation.WriteWlanPin( WLAN_ENABLE );
-
- wlan_timeout = TIMEOUT;
- if (ulSpiIRQState) {
- // wait till the IRQ line goes low
- while(tSLInformation.ReadWlanInterruptPin() != 0 && --wlan_timeout)
- {
- }
- }
- else
- {
- // wait till the IRQ line goes high and than low
- while(tSLInformation.ReadWlanInterruptPin() == 0 && --wlan_timeout)
- {
- }
-
- if (wlan_timeout == 0) {
- return -1;
- }
-
- wlan_timeout = TIMEOUT;
- while(tSLInformation.ReadWlanInterruptPin() != 0 && --wlan_timeout)
- {
- }
- }
-
- if (wlan_timeout ==0) {
- return -1;
- }
-
- SimpleLink_Init_Start(usPatchesAvailableAtHost);
-
- // Read Buffer's size and finish
- hci_command_send(HCI_CMND_READ_BUFFER_SIZE, tSLInformation.pucTxCommandBuffer, 0);
- SimpleLinkWaitEvent(HCI_CMND_READ_BUFFER_SIZE, 0);
-
- return 0;
-}
-
-
-//*****************************************************************************
-//
-//! wlan_stop
-//!
-//! @param none
-//!
-//! @return none
-//!
-//! @brief Stop WLAN device by putting it into reset state.
-//!
-//! @sa wlan_start
-//
-//*****************************************************************************
-
-void wlan_stop(void)
-{
- // Chip disable
- tSLInformation.WriteWlanPin( WLAN_DISABLE );
-
- // Wait till IRQ line goes high...
- while(tSLInformation.ReadWlanInterruptPin() == 0)
- {
- }
-
- // Free the used by WLAN Driver memory
- if (tSLInformation.pucTxCommandBuffer)
- {
- tSLInformation.pucTxCommandBuffer = 0;
- }
-
- SpiClose();
-}
-
-
-//*****************************************************************************
-//
-//! wlan_connect
-//!
-//! @param sec_type security options:
-//! WLAN_SEC_UNSEC,
-//! WLAN_SEC_WEP (ASCII support only),
-//! WLAN_SEC_WPA or WLAN_SEC_WPA2
-//! @param ssid up to 32 bytes and is ASCII SSID of the AP
-//! @param ssid_len length of the SSID
-//! @param bssid 6 bytes specified the AP bssid
-//! @param key up to 32 bytes specified the AP security key
-//! @param key_len key length
-//!
-//! @return On success, zero is returned. On error, negative is returned.
-//! Note that even though a zero is returned on success to trigger
-//! connection operation, it does not mean that CCC3000 is already
-//! connected. An asynchronous "Connected" event is generated when
-//! actual association process finishes and CC3000 is connected to
-//! the AP. If DHCP is set, An asynchronous "DHCP" event is
-//! generated when DHCP process is finish.
-//!
-//!
-//! @brief Connect to AP
-//! @warning Please Note that when connection to AP configured with security
-//! type WEP, please confirm that the key is set as ASCII and not
-//! as HEX.
-//! @sa wlan_disconnect
-//
-//*****************************************************************************
-
-#ifndef CC3000_TINY_DRIVER
-INT32 wlan_connect(UINT32 ulSecType, CHAR *ssid, INT32 ssid_len,
- UINT8 *bssid, UINT8 *key, INT32 key_len)
-{
- INT32 ret;
- UINT8 *ptr;
- UINT8 *args;
- UINT8 bssid_zero[] = {0, 0, 0, 0, 0, 0};
-
- ret = EFAIL;
- ptr = tSLInformation.pucTxCommandBuffer;
- args = (ptr + HEADERS_SIZE_CMD);
-
- // Fill in command buffer
- args = UINT32_TO_STREAM(args, 0x0000001c);
- args = UINT32_TO_STREAM(args, ssid_len);
- args = UINT32_TO_STREAM(args, ulSecType);
- args = UINT32_TO_STREAM(args, 0x00000010 + ssid_len);
- args = UINT32_TO_STREAM(args, key_len);
- args = UINT16_TO_STREAM(args, 0);
-
- // padding shall be zeroed
- if(bssid)
- {
- ARRAY_TO_STREAM(args, bssid, ETH_ALEN);
- }
- else
- {
- ARRAY_TO_STREAM(args, bssid_zero, ETH_ALEN);
- }
-
- ARRAY_TO_STREAM(args, ssid, ssid_len);
-
- if(key_len && key)
- {
- ARRAY_TO_STREAM(args, key, key_len);
- }
-
- // Initiate a HCI command
- hci_command_send(HCI_CMND_WLAN_CONNECT, ptr, WLAN_CONNECT_PARAM_LEN +
- ssid_len + key_len - 1);
-
- // Wait for command complete event
- SimpleLinkWaitEvent(HCI_CMND_WLAN_CONNECT, &ret);
- CC3000_EXPORT(errno) = ret;
-
- return(ret);
-}
-#else
-INT32 wlan_connect(CHAR *ssid, INT32 ssid_len)
-{
- INT32 ret;
- UINT8 *ptr;
- UINT8 *args;
- UINT8 bssid_zero[] = {0, 0, 0, 0, 0, 0};
-
- ret = EFAIL;
- ptr = tSLInformation.pucTxCommandBuffer;
- args = (ptr + HEADERS_SIZE_CMD);
-
- // Fill in command buffer
- args = UINT32_TO_STREAM(args, 0x0000001c);
- args = UINT32_TO_STREAM(args, ssid_len);
- args = UINT32_TO_STREAM(args, 0);
- args = UINT32_TO_STREAM(args, 0x00000010 + ssid_len);
- args = UINT32_TO_STREAM(args, 0);
- args = UINT16_TO_STREAM(args, 0);
-
- // padding shall be zeroed
- ARRAY_TO_STREAM(args, bssid_zero, ETH_ALEN);
- ARRAY_TO_STREAM(args, ssid, ssid_len);
-
- // Initiate a HCI command
- hci_command_send(HCI_CMND_WLAN_CONNECT, ptr, WLAN_CONNECT_PARAM_LEN +
- ssid_len - 1);
-
- // Wait for command complete event
- SimpleLinkWaitEvent(HCI_CMND_WLAN_CONNECT, &ret);
- CC3000_EXPORT(errno) = ret;
-
- return(ret);
-}
-#endif
-
-//*****************************************************************************
-//
-//! wlan_disconnect
-//!
-//! @return 0 disconnected done, other CC3000 already disconnected
-//!
-//! @brief Disconnect connection from AP.
-//!
-//! @sa wlan_connect
-//
-//*****************************************************************************
-
-INT32 wlan_disconnect()
-{
- INT32 ret;
- UINT8 *ptr;
-
- ret = EFAIL;
- ptr = tSLInformation.pucTxCommandBuffer;
-
- hci_command_send(HCI_CMND_WLAN_DISCONNECT, ptr, 0);
-
- // Wait for command complete event
- SimpleLinkWaitEvent(HCI_CMND_WLAN_DISCONNECT, &ret);
- CC3000_EXPORT(errno) = ret;
-
- return(ret);
-}
-
-//*****************************************************************************
-//
-//! wlan_ioctl_set_connection_policy
-//!
-//! @param should_connect_to_open_ap enable(1), disable(0) connect to any
-//! available AP. This parameter corresponds to the configuration of
-//! item # 3 in the brief description.
-//! @param should_use_fast_connect enable(1), disable(0). if enabled, tries
-//! to connect to the last connected AP. This parameter corresponds
-//! to the configuration of item # 1 in the brief description.
-//! @param auto_start enable(1), disable(0) auto connect
-//! after reset and periodically reconnect if needed. This
-//! configuration configures option 2 in the above description.
-//!
-//! @return On success, zero is returned. On error, -1 is returned
-//!
-//! @brief When auto is enabled, the device tries to connect according
-//! the following policy:
-//! 1) If fast connect is enabled and last connection is valid,
-//! the device will try to connect to it without the scanning
-//! procedure (fast). The last connection will be marked as
-//! invalid, due to adding/removing profile.
-//! 2) If profile exists, the device will try to connect it
-//! (Up to seven profiles).
-//! 3) If fast and profiles are not found, and open mode is
-//! enabled, the device will try to connect to any AP.
-//! * Note that the policy settings are stored in the CC3000 NVMEM.
-//!
-//! @sa wlan_add_profile , wlan_ioctl_del_profile
-//
-//*****************************************************************************
-
-INT32 wlan_ioctl_set_connection_policy(UINT32 should_connect_to_open_ap,
- UINT32 ulShouldUseFastConnect,
- UINT32 ulUseProfiles)
-{
- INT32 ret;
- UINT8 *ptr;
- UINT8 *args;
-
- ret = EFAIL;
- ptr = tSLInformation.pucTxCommandBuffer;
- args = (UINT8 *)(ptr + HEADERS_SIZE_CMD);
-
- // Fill in HCI packet structure
- args = UINT32_TO_STREAM(args, should_connect_to_open_ap);
- args = UINT32_TO_STREAM(args, ulShouldUseFastConnect);
- args = UINT32_TO_STREAM(args, ulUseProfiles);
-
- // Initiate a HCI command
- hci_command_send(HCI_CMND_WLAN_IOCTL_SET_CONNECTION_POLICY,
- ptr, WLAN_SET_CONNECTION_POLICY_PARAMS_LEN);
-
- // Wait for command complete event
- SimpleLinkWaitEvent(HCI_CMND_WLAN_IOCTL_SET_CONNECTION_POLICY, &ret);
-
- return(ret);
-}
-
-//*****************************************************************************
-//
-//! wlan_add_profile
-//!
-//! @param ulSecType WLAN_SEC_UNSEC,WLAN_SEC_WEP,WLAN_SEC_WPA,WLAN_SEC_WPA2
-//! @param ucSsid ssid SSID up to 32 bytes
-//! @param ulSsidLen ssid length
-//! @param ucBssid bssid 6 bytes
-//! @param ulPriority ulPriority profile priority. Lowest priority:0.
-//! Important Note: Smartconfig process (in unencrypted mode)
-//! stores the profile internally with priority 1, so changing
-//! priorities when adding new profiles should be done with extra care
-//! @param ulPairwiseCipher_Or_TxKeyLen key length for WEP security
-//! @param ulGroupCipher_TxKeyIndex key index
-//! @param ulKeyMgmt KEY management
-//! @param ucPf_OrKey security key
-//! @param ulPassPhraseLen security key length for WPA\WPA2
-//!
-//! @return On success, index (1-7) of the stored profile is returned.
-//! On error, -1 is returned.
-//!
-//! @brief When auto start is enabled, the device connects to
-//! station from the profiles table. Up to 7 profiles are supported.
-//! If several profiles configured the device choose the highest
-//! priority profile, within each priority group, device will choose
-//! profile based on security policy, signal strength, etc
-//! parameters. All the profiles are stored in CC3000 NVMEM.
-//!
-//! @sa wlan_ioctl_del_profile
-//
-//*****************************************************************************
-
-#ifndef CC3000_TINY_DRIVER
-INT32 wlan_add_profile(UINT32 ulSecType,
- UINT8* ucSsid,
- UINT32 ulSsidLen,
- UINT8 *ucBssid,
- UINT32 ulPriority,
- UINT32 ulPairwiseCipher_Or_TxKeyLen,
- UINT32 ulGroupCipher_TxKeyIndex,
- UINT32 ulKeyMgmt,
- UINT8* ucPf_OrKey,
- UINT32 ulPassPhraseLen)
-{
- UINT16 arg_len=0;
- INT32 ret;
- UINT8 *ptr;
- INT32 i = 0;
- UINT8 *args;
- UINT8 bssid_zero[] = {0, 0, 0, 0, 0, 0};
-
- ptr = tSLInformation.pucTxCommandBuffer;
- args = (ptr + HEADERS_SIZE_CMD);
-
- args = UINT32_TO_STREAM(args, ulSecType);
-
- // Setup arguments in accordance with the security type
- switch (ulSecType)
- {
- //OPEN
- case WLAN_SEC_UNSEC:
- {
- args = UINT32_TO_STREAM(args, 0x00000014);
- args = UINT32_TO_STREAM(args, ulSsidLen);
- args = UINT16_TO_STREAM(args, 0);
- if(ucBssid)
- {
- ARRAY_TO_STREAM(args, ucBssid, ETH_ALEN);
- }
- else
- {
- ARRAY_TO_STREAM(args, bssid_zero, ETH_ALEN);
- }
- args = UINT32_TO_STREAM(args, ulPriority);
- ARRAY_TO_STREAM(args, ucSsid, ulSsidLen);
-
- arg_len = WLAN_ADD_PROFILE_NOSEC_PARAM_LEN + ulSsidLen;
- }
- break;
-
- //WEP
- case WLAN_SEC_WEP:
- {
- args = UINT32_TO_STREAM(args, 0x00000020);
- args = UINT32_TO_STREAM(args, ulSsidLen);
- args = UINT16_TO_STREAM(args, 0);
- if(ucBssid)
- {
- ARRAY_TO_STREAM(args, ucBssid, ETH_ALEN);
- }
- else
- {
- ARRAY_TO_STREAM(args, bssid_zero, ETH_ALEN);
- }
- args = UINT32_TO_STREAM(args, ulPriority);
- args = UINT32_TO_STREAM(args, 0x0000000C + ulSsidLen);
- args = UINT32_TO_STREAM(args, ulPairwiseCipher_Or_TxKeyLen);
- args = UINT32_TO_STREAM(args, ulGroupCipher_TxKeyIndex);
- ARRAY_TO_STREAM(args, ucSsid, ulSsidLen);
-
- for(i = 0; i < 4; i++)
- {
- UINT8 *p = &ucPf_OrKey[i * ulPairwiseCipher_Or_TxKeyLen];
-
- ARRAY_TO_STREAM(args, p, ulPairwiseCipher_Or_TxKeyLen);
- }
-
- arg_len = WLAN_ADD_PROFILE_WEP_PARAM_LEN + ulSsidLen +
- ulPairwiseCipher_Or_TxKeyLen * 4;
-
- }
- break;
-
- //WPA
- //WPA2
- case WLAN_SEC_WPA:
- case WLAN_SEC_WPA2:
- {
- args = UINT32_TO_STREAM(args, 0x00000028);
- args = UINT32_TO_STREAM(args, ulSsidLen);
- args = UINT16_TO_STREAM(args, 0);
- if(ucBssid)
- {
- ARRAY_TO_STREAM(args, ucBssid, ETH_ALEN);
- }
- else
- {
- ARRAY_TO_STREAM(args, bssid_zero, ETH_ALEN);
- }
- args = UINT32_TO_STREAM(args, ulPriority);
- args = UINT32_TO_STREAM(args, ulPairwiseCipher_Or_TxKeyLen);
- args = UINT32_TO_STREAM(args, ulGroupCipher_TxKeyIndex);
- args = UINT32_TO_STREAM(args, ulKeyMgmt);
- args = UINT32_TO_STREAM(args, 0x00000008 + ulSsidLen);
- args = UINT32_TO_STREAM(args, ulPassPhraseLen);
- ARRAY_TO_STREAM(args, ucSsid, ulSsidLen);
- ARRAY_TO_STREAM(args, ucPf_OrKey, ulPassPhraseLen);
-
- arg_len = WLAN_ADD_PROFILE_WPA_PARAM_LEN + ulSsidLen + ulPassPhraseLen;
- }
-
- break;
- }
-
- // Initiate a HCI command
- hci_command_send(HCI_CMND_WLAN_IOCTL_ADD_PROFILE,
- ptr, arg_len);
-
- // Wait for command complete event
- SimpleLinkWaitEvent(HCI_CMND_WLAN_IOCTL_ADD_PROFILE, &ret);
-
- return(ret);
-}
-#else
-INT32 wlan_add_profile(UINT32 ulSecType,
- UINT8* ucSsid,
- UINT32 ulSsidLen,
- UINT8 *ucBssid,
- UINT32 ulPriority,
- UINT32 ulPairwiseCipher_Or_TxKeyLen,
- UINT32 ulGroupCipher_TxKeyIndex,
- UINT32 ulKeyMgmt,
- UINT8* ucPf_OrKey,
- UINT32 ulPassPhraseLen)
-{
- return -1;
-}
-#endif
-
-//*****************************************************************************
-//
-//! wlan_ioctl_del_profile
-//!
-//! @param index number of profile to delete
-//!
-//! @return On success, zero is returned. On error, -1 is returned
-//!
-//! @brief Delete WLAN profile
-//!
-//! @Note In order to delete all stored profile, set index to 255.
-//!
-//! @sa wlan_add_profile
-//
-//*****************************************************************************
-
-INT32 wlan_ioctl_del_profile(UINT32 ulIndex)
-{
- INT32 ret;
- UINT8 *ptr;
- UINT8 *args;
-
- ptr = tSLInformation.pucTxCommandBuffer;
- args = (UINT8 *)(ptr + HEADERS_SIZE_CMD);
-
- // Fill in HCI packet structure
- args = UINT32_TO_STREAM(args, ulIndex);
- ret = EFAIL;
-
- // Initiate a HCI command
- hci_command_send(HCI_CMND_WLAN_IOCTL_DEL_PROFILE,
- ptr, WLAN_DEL_PROFILE_PARAMS_LEN);
-
- // Wait for command complete event
- SimpleLinkWaitEvent(HCI_CMND_WLAN_IOCTL_DEL_PROFILE, &ret);
-
- return(ret);
-}
-
-//*****************************************************************************
-//
-//! wlan_ioctl_get_scan_results
-//!
-//! @param[in] scan_timeout parameter not supported
-//! @param[out] ucResults scan results (_wlan_full_scan_results_args_t)
-//!
-//! @return On success, zero is returned. On error, -1 is returned
-//!
-//! @brief Gets entry from scan result table.
-//! The scan results are returned one by one, and each entry
-//! represents a single AP found in the area. The following is a
-//! format of the scan result:
-//! - 4 Bytes: number of networks found
-//! - 4 Bytes: The status of the scan: 0 - aged results,
-//! 1 - results valid, 2 - no results
-//! - 42 bytes: Result entry, where the bytes are arranged as follows:
-//!
-//! - 1 bit isValid - is result valid or not
-//! - 7 bits rssi - RSSI value;
-//! - 2 bits: securityMode - security mode of the AP:
-//! 0 - Open, 1 - WEP, 2 WPA, 3 WPA2
-//! - 6 bits: SSID name length
-//! - 2 bytes: the time at which the entry has entered into
-//! scans result table
-//! - 32 bytes: SSID name
-//! - 6 bytes: BSSID
-//!
-//! @Note scan_timeout, is not supported on this version.
-//!
-//! @sa wlan_ioctl_set_scan_params
-//
-//*****************************************************************************
-
-#ifndef CC3000_TINY_DRIVER
-INT32 wlan_ioctl_get_scan_results(UINT32 ulScanTimeout,
- UINT8 *ucResults)
-{
- UINT8 *ptr;
- UINT8 *args;
-
- ptr = tSLInformation.pucTxCommandBuffer;
- args = (ptr + HEADERS_SIZE_CMD);
-
- // Fill in temporary command buffer
- args = UINT32_TO_STREAM(args, ulScanTimeout);
-
- // Initiate a HCI command
- hci_command_send(HCI_CMND_WLAN_IOCTL_GET_SCAN_RESULTS,
- ptr, WLAN_GET_SCAN_RESULTS_PARAMS_LEN);
-
- // Wait for command complete event
- SimpleLinkWaitEvent(HCI_CMND_WLAN_IOCTL_GET_SCAN_RESULTS, ucResults);
-
- return(0);
-}
-#endif
-
-//*****************************************************************************
-//
-//! wlan_ioctl_set_scan_params
-//!
-//! @param uiEnable - start/stop application scan:
-//! 1 = start scan with default interval value of 10 min.
-//! in order to set a different scan interval value apply the value
-//! in milliseconds. minimum 1 second. 0=stop). Wlan reset
-//! (wlan_stop() wlan_start()) is needed when changing scan interval
-//! value. Saved: No
-//! @param uiMinDwellTime minimum dwell time value to be used for each
-//! channel, in milliseconds. Saved: yes
-//! Recommended Value: 100 (Default: 20)
-//! @param uiMaxDwellTime maximum dwell time value to be used for each
-//! channel, in milliseconds. Saved: yes
-//! Recommended Value: 100 (Default: 30)
-//! @param uiNumOfProbeRequests max probe request between dwell time.
-//! Saved: yes. Recommended Value: 5 (Default:2)
-//! @param uiChannelMask bitwise, up to 13 channels (0x1fff).
-//! Saved: yes. Default: 0x7ff
-//! @param uiRSSIThreshold RSSI threshold. Saved: yes (Default: -80)
-//! @param uiSNRThreshold NSR threshold. Saved: yes (Default: 0)
-//! @param uiDefaultTxPower probe Tx power. Saved: yes (Default: 205)
-//! @param aiIntervalList pointer to array with 16 entries (16 channels)
-//! each entry (UINT32) holds timeout between periodic scan
-//! (connection scan) - in millisecond. Saved: yes. Default 2000ms.
-//!
-//! @return On success, zero is returned. On error, -1 is returned
-//!
-//! @brief start and stop scan procedure. Set scan parameters.
-//!
-//! @Note uiDefaultTxPower, is not supported on this version.
-//!
-//! @sa wlan_ioctl_get_scan_results
-//
-//*****************************************************************************
-
-#ifndef CC3000_TINY_DRIVER
-INT32 wlan_ioctl_set_scan_params(UINT32 uiEnable, UINT32 uiMinDwellTime,
- UINT32 uiMaxDwellTime,
- UINT32 uiNumOfProbeRequests,
- UINT32 uiChannelMask,INT32 iRSSIThreshold,
- UINT32 uiSNRThreshold,
- UINT32 uiDefaultTxPower,
- UINT32 *aiIntervalList)
-{
- UINT32 uiRes;
- UINT8 *ptr;
- UINT8 *args;
-
- ptr = tSLInformation.pucTxCommandBuffer;
- args = (ptr + HEADERS_SIZE_CMD);
-
- // Fill in temporary command buffer
- args = UINT32_TO_STREAM(args, 36);
- args = UINT32_TO_STREAM(args, uiEnable);
- args = UINT32_TO_STREAM(args, uiMinDwellTime);
- args = UINT32_TO_STREAM(args, uiMaxDwellTime);
- args = UINT32_TO_STREAM(args, uiNumOfProbeRequests);
- args = UINT32_TO_STREAM(args, uiChannelMask);
- args = UINT32_TO_STREAM(args, iRSSIThreshold);
- args = UINT32_TO_STREAM(args, uiSNRThreshold);
- args = UINT32_TO_STREAM(args, uiDefaultTxPower);
- ARRAY_TO_STREAM(args, aiIntervalList, sizeof(UINT32) *
- SL_SET_SCAN_PARAMS_INTERVAL_LIST_SIZE);
-
- // Initiate a HCI command
- hci_command_send(HCI_CMND_WLAN_IOCTL_SET_SCANPARAM,
- ptr, WLAN_SET_SCAN_PARAMS_LEN);
-
- // Wait for command complete event
- SimpleLinkWaitEvent(HCI_CMND_WLAN_IOCTL_SET_SCANPARAM, &uiRes);
-
- return(uiRes);
-}
-#endif
-
-//*****************************************************************************
-//
-//! wlan_set_event_mask
-//!
-//! @param mask mask option:
-//! HCI_EVNT_WLAN_UNSOL_CONNECT connect event
-//! HCI_EVNT_WLAN_UNSOL_DISCONNECT disconnect event
-//! HCI_EVNT_WLAN_ASYNC_SIMPLE_CONFIG_DONE smart config done
-//! HCI_EVNT_WLAN_UNSOL_INIT init done
-//! HCI_EVNT_WLAN_UNSOL_DHCP dhcp event report
-//! HCI_EVNT_WLAN_ASYNC_PING_REPORT ping report
-//! HCI_EVNT_WLAN_KEEPALIVE keepalive
-//! HCI_EVNT_WLAN_TX_COMPLETE - disable information on end of transmission
-//! Saved: no.
-//!
-//! @return On success, zero is returned. On error, -1 is returned
-//!
-//! @brief Mask event according to bit mask. In case that event is
-//! masked (1), the device will not send the masked event to host.
-//
-//*****************************************************************************
-
-INT32 wlan_set_event_mask(UINT32 ulMask)
-{
- INT32 ret;
- UINT8 *ptr;
- UINT8 *args;
-
-
- if ((ulMask & HCI_EVNT_WLAN_TX_COMPLETE) == HCI_EVNT_WLAN_TX_COMPLETE)
- {
- tSLInformation.InformHostOnTxComplete = 0;
-
- // Since an event is a virtual event - i.e. it is not coming from CC3000
- // there is no need to send anything to the device if it was an only event
- if (ulMask == HCI_EVNT_WLAN_TX_COMPLETE)
- {
- return 0;
- }
-
- ulMask &= ~HCI_EVNT_WLAN_TX_COMPLETE;
- ulMask |= HCI_EVNT_WLAN_UNSOL_BASE;
- }
- else
- {
- tSLInformation.InformHostOnTxComplete = 1;
- }
-
- ret = EFAIL;
- ptr = tSLInformation.pucTxCommandBuffer;
- args = (UINT8 *)(ptr + HEADERS_SIZE_CMD);
-
- // Fill in HCI packet structure
- args = UINT32_TO_STREAM(args, ulMask);
-
- // Initiate a HCI command
- hci_command_send(HCI_CMND_EVENT_MASK,
- ptr, WLAN_SET_MASK_PARAMS_LEN);
-
- // Wait for command complete event
- SimpleLinkWaitEvent(HCI_CMND_EVENT_MASK, &ret);
-
- return(ret);
-}
-
-//*****************************************************************************
-//
-//! wlan_ioctl_statusget
-//!
-//! @param none
-//!
-//! @return WLAN_STATUS_DISCONNECTED, WLAN_STATUS_SCANING,
-//! STATUS_CONNECTING or WLAN_STATUS_CONNECTED
-//!
-//! @brief get wlan status: disconnected, scanning, connecting or connected
-//
-//*****************************************************************************
-
-#ifndef CC3000_TINY_DRIVER
-INT32 wlan_ioctl_statusget(void)
-{
- INT32 ret;
- UINT8 *ptr;
-
- ret = EFAIL;
- ptr = tSLInformation.pucTxCommandBuffer;
-
- hci_command_send(HCI_CMND_WLAN_IOCTL_STATUSGET,
- ptr, 0);
-
- // Wait for command complete event
- SimpleLinkWaitEvent(HCI_CMND_WLAN_IOCTL_STATUSGET, &ret);
-
- return(ret);
-}
-#endif
-
-//*****************************************************************************
-//
-//! wlan_smart_config_start
-//!
-//! @param algoEncryptedFlag indicates whether the information is encrypted
-//!
-//! @return On success, zero is returned. On error, -1 is returned
-//!
-//! @brief Start to acquire device profile. The device acquire its own
-//! profile, if profile message is found. The acquired AP information
-//! is stored in CC3000 EEPROM only in case AES128 encryption is used.
-//! In case AES128 encryption is not used, a profile is created by
-//! CC3000 internally.
-//!
-//! @Note An asynchronous event - Smart Config Done will be generated as soon
-//! as the process finishes successfully.
-//!
-//! @sa wlan_smart_config_set_prefix , wlan_smart_config_stop
-//
-//*****************************************************************************
-
-INT32 wlan_smart_config_start(UINT32 algoEncryptedFlag)
-{
- INT32 ret;
- UINT8 *ptr;
- UINT8 *args;
-
- ret = EFAIL;
- ptr = tSLInformation.pucTxCommandBuffer;
- args = (UINT8 *)(ptr + HEADERS_SIZE_CMD);
-
- // Fill in HCI packet structure
- args = UINT32_TO_STREAM(args, algoEncryptedFlag);
- ret = EFAIL;
-
- hci_command_send(HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_START, ptr,
- WLAN_SMART_CONFIG_START_PARAMS_LEN);
-
- // Wait for command complete event
- SimpleLinkWaitEvent(HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_START, &ret);
-
- return(ret);
-}
-
-//*****************************************************************************
-//
-//! wlan_smart_config_stop
-//!
-//! @param algoEncryptedFlag indicates whether the information is encrypted
-//!
-//! @return On success, zero is returned. On error, -1 is returned
-//!
-//! @brief Stop the acquire profile procedure
-//!
-//! @sa wlan_smart_config_start , wlan_smart_config_set_prefix
-//
-//*****************************************************************************
-
-INT32 wlan_smart_config_stop(void)
-{
- INT32 ret;
- UINT8 *ptr;
-
- ret = EFAIL;
- ptr = tSLInformation.pucTxCommandBuffer;
-
- hci_command_send(HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_STOP, ptr, 0);
-
- // Wait for command complete event
- SimpleLinkWaitEvent(HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_STOP, &ret);
-
- return(ret);
-}
-
-//*****************************************************************************
-//
-//! wlan_smart_config_set_prefix
-//!
-//! @param newPrefix 3 bytes identify the SSID prefix for the Smart Config.
-//!
-//! @return On success, zero is returned. On error, -1 is returned
-//!
-//! @brief Configure station ssid prefix. The prefix is used internally
-//! in CC3000. It should always be TTT.
-//!
-//! @Note The prefix is stored in CC3000 NVMEM
-//!
-//! @sa wlan_smart_config_start , wlan_smart_config_stop
-//
-//*****************************************************************************
-
-INT32 wlan_smart_config_set_prefix(CHAR* cNewPrefix)
-{
- INT32 ret;
- UINT8 *ptr;
- UINT8 *args;
-
- ret = EFAIL;
- ptr = tSLInformation.pucTxCommandBuffer;
- args = (ptr + HEADERS_SIZE_CMD);
-
- if (cNewPrefix == NULL)
- return ret;
- else // with the new Smart Config, prefix must be TTT
- {
- *cNewPrefix = 'T';
- *(cNewPrefix + 1) = 'T';
- *(cNewPrefix + 2) = 'T';
- }
-
- ARRAY_TO_STREAM(args, cNewPrefix, SL_SIMPLE_CONFIG_PREFIX_LENGTH);
-
- hci_command_send(HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_SET_PREFIX, ptr,
- SL_SIMPLE_CONFIG_PREFIX_LENGTH);
-
- // Wait for command complete event
- SimpleLinkWaitEvent(HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_SET_PREFIX, &ret);
-
- return(ret);
-}
-
-//*****************************************************************************
-//
-//! wlan_smart_config_process
-//!
-//! @param none
-//!
-//! @return On success, zero is returned. On error, -1 is returned
-//!
-//! @brief process the acquired data and store it as a profile. The acquired
-//! AP information is stored in CC3000 EEPROM encrypted.
-//! The encrypted data is decrypted and stored as a profile.
-//! behavior is as defined by connection policy.
-//
-//*****************************************************************************
-
-
-#ifndef CC3000_UNENCRYPTED_SMART_CONFIG
-INT32 wlan_smart_config_process()
-{
- INT32 returnValue;
- UINT32 ssidLen, keyLen;
- UINT8 *decKeyPtr;
- UINT8 *ssidPtr;
-
- // read the key from EEPROM - fileID 12
- returnValue = aes_read_key(key);
-
- if (returnValue != 0)
- return returnValue;
-
- // read the received data from fileID #13 and parse it according to the followings:
- // 1) SSID LEN - not encrypted
- // 2) SSID - not encrypted
- // 3) KEY LEN - not encrypted. always 32 bytes long
- // 4) Security type - not encrypted
- // 5) KEY - encrypted together with true key length as the first byte in KEY
- // to elaborate, there are two corner cases:
- // 1) the KEY is 32 bytes long. In this case, the first byte does not represent KEY length
- // 2) the KEY is 31 bytes long. In this case, the first byte represent KEY length and equals 31
- returnValue = nvmem_read(NVMEM_SHARED_MEM_FILEID, SMART_CONFIG_PROFILE_SIZE, 0, profileArray);
-
- if (returnValue != 0)
- return returnValue;
-
- ssidPtr = &profileArray[1];
-
- ssidLen = profileArray[0];
-
- decKeyPtr = &profileArray[profileArray[0] + 3];
-
- aes_decrypt(decKeyPtr, key);
- if (profileArray[profileArray[0] + 1] > 16)
- aes_decrypt((UINT8 *)(decKeyPtr + 16), key);
-
- if (*(UINT8 *)(decKeyPtr +31) != 0)
- {
- if (*decKeyPtr == 31)
- {
- keyLen = 31;
- decKeyPtr++;
- }
- else
- {
- keyLen = 32;
- }
- }
- else
- {
- keyLen = *decKeyPtr;
- decKeyPtr++;
- }
-
- // add a profile
- switch (profileArray[profileArray[0] + 2])
- {
- case WLAN_SEC_UNSEC://None
- {
- returnValue = wlan_add_profile(profileArray[profileArray[0] + 2], // security type
- ssidPtr, // SSID
- ssidLen, // SSID length
- NULL, // BSSID
- 1, // Priority
- 0, 0, 0, 0, 0);
-
- break;
- }
-
- case WLAN_SEC_WEP://WEP
- {
- returnValue = wlan_add_profile(profileArray[profileArray[0] + 2], // security type
- ssidPtr, // SSID
- ssidLen, // SSID length
- NULL, // BSSID
- 1, // Priority
- keyLen, // KEY length
- 0, // KEY index
- 0,
- decKeyPtr, // KEY
- 0);
-
- break;
- }
-
- case WLAN_SEC_WPA://WPA
- case WLAN_SEC_WPA2://WPA2
- {
- returnValue = wlan_add_profile(WLAN_SEC_WPA2, // security type
- ssidPtr,
- ssidLen,
- NULL, // BSSID
- 1, // Priority
- 0x18, // PairwiseCipher
- 0x1e, // GroupCipher
- 2, // KEY management
- decKeyPtr, // KEY
- keyLen); // KEY length
-
- break;
- }
- }
-
- return returnValue;
-}
-#endif //CC3000_UNENCRYPTED_SMART_CONFIG
-
-//*****************************************************************************
-//
-// Close the Doxygen group.
-//! @}
-//
-//*****************************************************************************
diff --git a/drivers/cc3100/src/wlan.c b/drivers/cc3100/src/wlan.c
index 59adf02f0228..22be4d7ddf55 100644
--- a/drivers/cc3100/src/wlan.c
+++ b/drivers/cc3100/src/wlan.c
@@ -536,10 +536,7 @@ _i16 sl_WlanProfileGet(const _i16 Index,_i8* pName, _i16 *pNameLen, _u8 *pMacAd
*pNameLen = Msg.Rsp.Args.Common.SsidLen;
*pPriority = Msg.Rsp.Args.Common.Priority;
- if (NULL != Msg.Rsp.Args.Common.Bssid)
- {
- sl_Memcpy(pMacAddr, Msg.Rsp.Args.Common.Bssid, sizeof(Msg.Rsp.Args.Common.Bssid));
- }
+ sl_Memcpy(pMacAddr, Msg.Rsp.Args.Common.Bssid, sizeof(Msg.Rsp.Args.Common.Bssid));
sl_Memcpy(pName, EAP_PROFILE_SSID_STRING(&Msg), *pNameLen);
diff --git a/drivers/codec/wm8960.py b/drivers/codec/wm8960.py
deleted file mode 100644
index ad1cb1cbf872..000000000000
--- a/drivers/codec/wm8960.py
+++ /dev/null
@@ -1,753 +0,0 @@
-#
-# Driver class for the WM8960 Codec to be used e.g. with MIMXRT_1xxx Boards.
-# Derived from the NXP SDK drivers.
-#
-# Copyright (c) 2015, Freescale Semiconductor, Inc., (C-Code)
-# Copyright 2016-2021 NXP, (C-Code)
-# All rights reserved.
-#
-# Translated to MicroPython by Robert Hammelrath, 2022
-#
-# SPDX-License-Identifier: BSD-3-Clause
-#
-
-import array
-from micropython import const
-
-# Define the register addresses of WM8960.
-_LINVOL = const(0x0)
-_RINVOL = const(0x1)
-_LOUT1 = const(0x2)
-_ROUT1 = const(0x3)
-_CLOCK1 = const(0x4)
-_DACCTL1 = const(0x5)
-_DACCTL2 = const(0x6)
-_IFACE1 = const(0x7)
-_CLOCK2 = const(0x8)
-_IFACE2 = const(0x9)
-_LDAC = const(0xA)
-_RDAC = const(0xB)
-_RESET = const(0xF)
-_3D = const(0x10)
-_ALC1 = const(0x11)
-_ALC2 = const(0x12)
-_ALC3 = const(0x13)
-_NOISEG = const(0x14)
-_LADC = const(0x15)
-_RADC = const(0x16)
-_ADDCTL1 = const(0x17)
-# Register _ADDCTL2 = const(0x18)
-_POWER1 = const(0x19)
-_POWER2 = const(0x1A)
-_ADDCTL3 = const(0x1B)
-# Register _APOP1 = const(0x1C)
-# Register _APOP2 = const(0x1D)
-_LINPATH = const(0x20)
-_RINPATH = const(0x21)
-_LOUTMIX = const(0x22)
-_ROUTMIX = const(0x25)
-_MONOMIX1 = const(0x26)
-_MONOMIX2 = const(0x27)
-_LOUT2 = const(0x28)
-_ROUT2 = const(0x29)
-_MONO = const(0x2A)
-_INBMIX1 = const(0x2B)
-_INBMIX2 = const(0x2C)
-_BYPASS1 = const(0x2D)
-_BYPASS2 = const(0x2E)
-_POWER3 = const(0x2F)
-_ADDCTL4 = const(0x30)
-_CLASSD1 = const(0x31)
-# Register _CLASSD3 = const(0x33)
-_PLL1 = const(0x34)
-_PLL2 = const(0x35)
-_PLL3 = const(0x36)
-_PLL4 = const(0x37)
-
-# WM8960 PLLN range */
-_PLL_N_MIN_VALUE = const(6)
-_PLL_N_MAX_VALUE = const(12)
-
-# WM8960 CLOCK2 bits
-_CLOCK2_BCLK_DIV_MASK = const(0x0F)
-_CLOCK2_DCLK_DIV_MASK = const(0x1C0)
-_CLOCK2_DCLK_DIV_SHIFT = const(0x06)
-
-# Register _IFACE1
-_IFACE1_FORMAT_MASK = const(0x03)
-_IFACE1_WL_MASK = const(0x0C)
-_IFACE1_WL_SHIFT = const(0x02)
-_IFACE1_LRP_MASK = const(0x10)
-_IFACE1_MS_MASK = const(0x40)
-_IFACE1_DLRSWAP_MASK = const(0x20)
-_IFACE1_ALRSWAP_MASK = const(0x100)
-
-# Register _POWER1
-_POWER1_VREF_MASK = const(0x40)
-_POWER1_VREF_SHIFT = const(0x06)
-_POWER1_AINL_MASK = const(0x20)
-_POWER1_AINR_MASK = const(0x10)
-_POWER1_ADCL_MASK = const(0x08)
-_POWER1_ADCR_MASK = const(0x0)
-_POWER1_MICB_MASK = const(0x02)
-_POWER1_MICB_SHIFT = const(0x01)
-
-# Register _POWER2
-_POWER2_DACL_MASK = const(0x100)
-_POWER2_DACR_MASK = const(0x80)
-_POWER2_LOUT1_MASK = const(0x40)
-_POWER2_ROUT1_MASK = const(0x20)
-_POWER2_SPKL_MASK = const(0x10)
-_POWER2_SPKR_MASK = const(0x08)
-_POWER3_LMIC_MASK = const(0x20)
-_POWER3_RMIC_MASK = const(0x10)
-_POWER3_LOMIX_MASK = const(0x08)
-_POWER3_ROMIX_MASK = const(0x04)
-
-# Register _DACCTL1 .. 3
-_DACCTL1_MONOMIX_MASK = const(0x10)
-_DACCTL1_MONOMIX_SHIFT = const(0x4)
-_DACCTL1_DACMU_MASK = const(0x08)
-_DACCTL1_DEEM_MASK = const(0x06)
-_DACCTL1_DEEM_SHIFT = const(0x01)
-_DACCTL2_DACSMM_MASK = const(0x08)
-_DACCTL2_DACMR_MASK = const(0x04)
-_DACCTL3_ALCSR_MASK = const(0x07)
-
-# _WM8060_ALC1 .. 3
-_ALC_CHANNEL_MASK = const(0x180)
-_ALC_CHANNEL_SHIFT = const(0x7)
-_ALC_MODE_MASK = const(0x100)
-_ALC_MODE_SHIFT = const(0x8)
-_ALC_GAIN_MASK = const(0x70)
-_ALC_GAIN_SHIFT = const(0x4)
-_ALC_TARGET_MASK = const(0x0F)
-_ALC_ATTACK_MASK = const(0x0F)
-_ALC_DECAY_MASK = const(0xF0)
-_ALC_DECAY_SHIFT = const(4)
-_ALC_HOLD_MASK = const(0xF)
-
-# Register _NOISEG
-_NOISEG_LEVEL_SHIFT = const(3)
-
-_I2C_ADDR = const(0x1A)
-
-# WM8960 maximum volume values
-_MAX_VOLUME_ADC = const(0xFF)
-_MAX_VOLUME_DAC = const(0xFF)
-_MAX_VOLUME_HEADPHONE = const(0x7F)
-_MAX_VOLUME_LINEIN = const(0x3F)
-_MAX_VOLUME_SPEAKER = const(0x7F)
-
-# Config symbol names
-# Modules
-MODULE_ADC = const(0) # ADC module in WM8960
-MODULE_DAC = const(1) # DAC module in WM8960
-MODULE_VREF = const(2) # VREF module
-MODULE_HEADPHONE = const(3) # Headphone
-MODULE_MIC_BIAS = const(4) # Mic bias
-MODULE_MIC = const(5) # Input Mic
-MODULE_LINE_IN = const(6) # Analog in PGA
-MODULE_LINE_OUT = const(7) # Line out module
-MODULE_SPEAKER = const(8) # Speaker module
-MODULE_OMIX = const(9) # Output mixer
-MODULE_MONO_OUT = const(10) # Mono mix
-
-# Route
-ROUTE_BYPASS = const(0) # LINEIN->Headphone.
-ROUTE_PLAYBACK = const(1) # I2SIN->DAC->Headphone.
-ROUTE_PLAYBACK_RECORD = const(2) # I2SIN->DAC->Headphone, LINEIN->ADC->I2SOUT.
-ROUTE_RECORD = const(5) # LINEIN->ADC->I2SOUT.
-
-# Input
-INPUT_CLOSED = const(0) # Input device is closed
-INPUT_MIC1 = const(1) # Input as single ended mic, only use L/RINPUT1
-INPUT_MIC2 = const(2) # Input as diff. mic, use L/RINPUT1 and L/RINPUT2
-INPUT_MIC3 = const(3) # Input as diff. mic, use L/RINPUT1 and L/RINPUT3
-INPUT_LINE2 = const(4) # Input as line input, only use L/RINPUT2
-INPUT_LINE3 = const(5) # Input as line input, only use L/RINPUT3
-
-# ADC sync input
-SYNC_ADC = const(0) # Use ADCLRC pin for ADC sync
-SYNC_DAC = const(1) # used DACLRC pin for ADC sync
-
-# Protocol type
-BUS_I2S = const(2) # I2S type
-BUS_LEFT_JUSTIFIED = const(1) # Left justified mode
-BUS_RIGHT_JUSTIFIED = const(0) # Right justified mode
-BUS_PCMA = const(3) # PCM A mode
-BUS_PCMB = const(3 | (1 << 4)) # PCM B mode
-
-# Channel swap
-SWAP_NONE = const(0)
-SWAP_INPUT = const(1)
-SWAP_OUTPUT = const(2)
-
-# Mute settings
-MUTE_FAST = const(0)
-MUTE_SLOW = const(1)
-
-# ALC settings
-ALC_OFF = const(0)
-ALC_RIGHT = const(1)
-ALC_LEFT = const(2)
-ALC_STEREO = const(3)
-ALC_MODE = const(0) # ALC mode
-ALC_LIMITER = const(1) # Limiter mode
-
-# Clock Source
-SYSCLK_MCLK = const(0) # sysclk source from external MCLK
-SYSCLK_PLL = const(1) # sysclk source from internal PLL
-
-
-class Regs:
- # register cache of 56 register. Since registers cannot be read back, they are
- # kept in the table for modification
- # fmt: off
- cache = array.array("H", (
- 0x0097, 0x0097, 0x0000, 0x0000, 0x0000, 0x0008, 0x0000,
- 0x000a, 0x01c0, 0x0000, 0x00ff, 0x00ff, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x007b, 0x0100, 0x0032, 0x0000,
- 0x00c3, 0x00c3, 0x01c0, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0100, 0x0100, 0x0050,
- 0x0050, 0x0050, 0x0050, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0040, 0x0000, 0x0000, 0x0050, 0x0050, 0x0000, 0x0002,
- 0x0037, 0x004d, 0x0080, 0x0008, 0x0031, 0x0026, 0x00e9
- ))
- # fmt: on
-
- def __init__(self, i2c, i2c_address=_I2C_ADDR):
- self.value_buffer = bytearray(2)
- self.i2c = i2c
- self.i2c_address = i2c_address
-
- def __getitem__(self, reg):
- return self.cache[reg]
-
- def __setitem__(self, reg, value):
- if type(reg) is tuple:
- if type(value) is tuple:
- self[reg[0]] = value[0]
- self[reg[1]] = value[1]
- else:
- self[reg[0]] = value
- self[reg[1]] = value
- else:
- if type(value) is tuple:
- val = (self.cache[reg] & (~value[0] & 0xFFFF)) | value[1]
- else:
- val = value
- self.cache[reg] = val
- self.value_buffer[0] = (reg << 1) | ((val >> 8) & 0x01)
- self.value_buffer[1] = val & 0xFF
- self.i2c.writeto(self.i2c_address, self.value_buffer)
-
-
-class WM8960:
-
- _bit_clock_divider_table = {
- 2: 0,
- 3: 1,
- 4: 2,
- 6: 3,
- 8: 4,
- 11: 5,
- 12: 6,
- 16: 7,
- 22: 8,
- 24: 9,
- 32: 10,
- 44: 11,
- 48: 12,
- }
-
- _dac_divider_table = {
- 1.0 * 256: 0b000,
- 1.5 * 256: 0b001,
- 2 * 256: 0b010,
- 3 * 256: 0b011,
- 4 * 256: 0b100,
- 5.5 * 256: 0b101,
- 6 * 256: 0b110,
- }
-
- _audio_word_length_table = {
- 16: 0b00,
- 20: 0b01,
- 24: 0b10,
- 32: 0b11,
- }
-
- _alc_sample_rate_table = {
- 48000: 0,
- 44100: 0,
- 32000: 1,
- 24000: 2,
- 22050: 2,
- 16000: 3,
- 12000: 4,
- 11025: 4,
- 8000: 5,
- }
-
- _volume_config_table = {
- MODULE_ADC: (_MAX_VOLUME_ADC, _LADC, 0x100),
- MODULE_DAC: (_MAX_VOLUME_DAC, _LDAC, 0x100),
- MODULE_HEADPHONE: (_MAX_VOLUME_HEADPHONE, _LOUT1, 0x180),
- MODULE_LINE_IN: (_MAX_VOLUME_LINEIN, _LINVOL, 0x140),
- MODULE_SPEAKER: (_MAX_VOLUME_SPEAKER, _LOUT2, 0x180),
- }
-
- _input_config_table = {
- INPUT_CLOSED: None,
- INPUT_MIC1: (0x138, 0x117),
- INPUT_MIC2: (0x178, 0x117),
- INPUT_MIC3: (0x1B8, 0x117),
- INPUT_LINE2: (0, 0xE),
- INPUT_LINE3: (0, 0x70),
- }
-
- def __init__(
- self,
- i2c,
- sample_rate=16000,
- bits=16,
- swap=SWAP_NONE,
- route=ROUTE_PLAYBACK_RECORD,
- left_input=INPUT_MIC3,
- right_input=INPUT_MIC2,
- sysclk_source=SYSCLK_MCLK,
- mclk_freq=None,
- primary=False,
- adc_sync=SYNC_DAC,
- protocol=BUS_I2S,
- i2c_address=_I2C_ADDR,
- ):
- self.regs = regs = Regs(i2c, i2c_address)
- self.sample_rate = sample_rate
-
- # check parameter consistency and set the sysclk value
- if sysclk_source == SYSCLK_PLL:
- if sample_rate in (11025, 22050, 44100):
- sysclk = 11289600
- else:
- sysclk = 12288000
- if sysclk < sample_rate * 256:
- sysclk = sample_rate * 256
- if mclk_freq is None:
- mclk_freq = sysclk
- else: # sysclk_source == SYSCLK_MCLK
- if mclk_freq is None:
- mclk_freq = sample_rate * 256
- sysclk = mclk_freq
-
- regs[_RESET] = 0x00
- # VMID=50K, Enable VREF, AINL, AINR, ADCL and ADCR
- # I2S_IN (bit 0), I2S_OUT (bit 1), DAP (bit 4), DAC (bit 5), ADC (bit 6) are powered on
- regs[_POWER1] = 0xFE
- # Enable DACL, DACR, LOUT1, ROUT1, PLL down, SPKL, SPKR
- regs[_POWER2] = 0x1F8
- # Enable left and right channel input PGA, left and right output mixer
- regs[_POWER3] = 0x3C
-
- if adc_sync == SYNC_ADC:
- # ADC and DAC use different Frame Clock Pins
- regs[_IFACE2] = 0x00 # ADCLRC 0x00:Input 0x40:output.
- else:
- # ADC and DAC use the same Frame Clock Pin
- regs[_IFACE2] = 0x40 # ADCLRC 0x00:Input 0x40:output.
- self.set_data_route(route)
- self.set_protocol(protocol)
-
- if sysclk_source == SYSCLK_PLL:
- self.set_internal_pll_config(mclk_freq, sysclk)
- if primary:
- self.set_master_clock(sysclk, sample_rate, bits)
- # set master bit.
- self.regs[_IFACE1] = (0, _IFACE1_MS_MASK)
-
- self.set_speaker_clock(sysclk)
-
- # swap channels
- if swap & SWAP_INPUT:
- regs[_IFACE1] = (0, _IFACE1_ALRSWAP_MASK)
- if swap & SWAP_OUTPUT:
- regs[_IFACE1] = (0, _IFACE1_DLRSWAP_MASK)
-
- self.set_left_input(left_input)
- self.set_right_input(right_input)
-
- regs[_ADDCTL1] = 0x0C0
- regs[_ADDCTL4] = 0x60 # Set GPIO1 to 0.
-
- regs[_BYPASS1] = regs[_BYPASS2] = 0x0
- # ADC volume, 0dB
- regs[_LADC, _RADC] = 0x1C3
- # Digital DAC volume, 0dB
- regs[_LDAC, _RDAC] = 0x1FF
- # Headphone volume, LOUT1 and ROUT1, 0dB
- regs[_LOUT1, _ROUT1] = 0x16F
- # speaker volume 6dB
- regs[_LOUT2, _ROUT2] = 0x1FF
- # enable class D output
- regs[_CLASSD1] = 0xF7
- # Unmute DAC.
- regs[_DACCTL1] = 0x0000
- # Input PGA volume 0 dB
- regs[_LINVOL, _RINVOL] = 0x117
-
- self.config_data_format(sysclk, sample_rate, bits)
-
- def deinit(self):
-
- self.set_module(MODULE_ADC, False)
- self.set_module(MODULE_DAC, False)
- self.set_module(MODULE_VREF, False)
- self.set_module(MODULE_LINE_IN, False)
- self.set_module(MODULE_LINE_OUT, False)
- self.set_module(MODULE_SPEAKER, False)
-
- def set_internal_pll_config(self, input_mclk, output_clk):
- regs = self.regs
- pllF2 = output_clk * 4
- pll_prescale = 0
- sysclk_div = 1
- frac_mode = 0
-
- # disable PLL power
- regs[_POWER2] = (1, 0)
- regs[_CLOCK1] = (7, 0)
-
- pllN = pllF2 // input_mclk
- if pllN < _PLL_N_MIN_VALUE:
- input_mclk //= 2
- pll_prescale = 1
- pllN = pllF2 // input_mclk
- if pllN < _PLL_N_MIN_VALUE:
- sysclk_div = 2
- pllF2 *= 2
- pllN = pllF2 // input_mclk
-
- if (pllN < _PLL_N_MIN_VALUE) or (pllN > _PLL_N_MAX_VALUE):
- raise ValueError("Invalid MCLK vs. sysclk ratio")
-
- pllK = ((pllF2 % input_mclk) * (1 << 24)) // input_mclk
- if pllK != 0:
- frac_mode = 1
-
- regs[_PLL1] = (frac_mode << 5) | (pll_prescale << 4) | (pllN & 0x0F)
- regs[_PLL2] = (pllK >> 16) & 0xFF
- regs[_PLL3] = (pllK >> 8) & 0xFF
- regs[_PLL4] = pllK & 0xFF
- # enable PLL power
- regs[_POWER2] = (1, 1)
- regs[_CLOCK1] = (7, ((0 if sysclk_div == 1 else sysclk_div) << 1) | 1)
-
- def set_master_clock(self, sysclk, sample_rate, bit_width):
- bit_clock_divider = (sysclk * 2) // (sample_rate * bit_width * 2)
- try:
- reg_divider = self._bit_clock_divider_table[bit_clock_divider]
- except:
- raise ValueError("Invalid ratio of sysclk sample rate and bits")
- # configure the master bit clock divider
- self.regs[_CLOCK2] = (_CLOCK2_BCLK_DIV_MASK, reg_divider)
-
- def set_speaker_clock(self, sysclk):
- speaker_divider_table = (1.5, 2, 3, 4, 6, 8, 12, 16)
- for val in range(8):
- divider = speaker_divider_table[val]
- f = sysclk / divider
- if 500_000 < f < 1_000_000:
- break
- else:
- val = 7
- self.regs[_CLOCK2] = (
- _CLOCK2_DCLK_DIV_MASK,
- val << _CLOCK2_DCLK_DIV_SHIFT,
- )
-
- def set_module(self, module, is_enabled):
-
- is_enabled = 1 if is_enabled else 0
- regs = self.regs
-
- if module == MODULE_ADC:
-
- regs[_POWER1] = (
- _POWER1_ADCL_MASK | _POWER1_ADCR_MASK,
- (_POWER1_ADCL_MASK | _POWER1_ADCR_MASK) * is_enabled,
- )
-
- elif module == MODULE_DAC:
-
- regs[_POWER2] = (
- _POWER2_DACL_MASK | _POWER2_DACR_MASK,
- (_POWER2_DACL_MASK | _POWER2_DACR_MASK) * is_enabled,
- )
-
- elif module == MODULE_VREF:
-
- regs[_POWER1] = (
- _POWER1_VREF_MASK,
- (is_enabled << _POWER1_VREF_SHIFT),
- )
-
- elif module == MODULE_LINE_IN:
-
- regs[_POWER1] = (
- _POWER1_AINL_MASK | _POWER1_AINR_MASK,
- (_POWER1_AINL_MASK | _POWER1_AINR_MASK) * is_enabled,
- )
- regs[_POWER3] = (
- _POWER3_LMIC_MASK | _POWER3_RMIC_MASK,
- (_POWER3_LMIC_MASK | _POWER3_RMIC_MASK) * is_enabled,
- )
-
- elif module == MODULE_LINE_OUT:
-
- regs[_POWER2] = (
- _POWER2_LOUT1_MASK | _POWER2_ROUT1_MASK,
- (_POWER2_LOUT1_MASK | _POWER2_ROUT1_MASK) * is_enabled,
- )
-
- elif module == MODULE_MIC_BIAS:
-
- regs[_POWER1] = (
- _POWER1_MICB_MASK,
- (is_enabled << _POWER1_MICB_SHIFT),
- )
-
- elif module == MODULE_SPEAKER:
-
- regs[_POWER2] = (
- _POWER2_SPKL_MASK | _POWER2_SPKR_MASK,
- (_POWER2_SPKL_MASK | _POWER2_SPKR_MASK) * is_enabled,
- )
- regs[_CLASSD1] = 0xF7
-
- elif module == MODULE_OMIX:
-
- regs[_POWER3] = (
- _POWER3_LOMIX_MASK | _POWER3_ROMIX_MASK,
- (_POWER3_LOMIX_MASK | _POWER3_ROMIX_MASK) * is_enabled,
- )
-
- elif module == MODULE_MONO_OUT:
-
- regs[_MONOMIX1] = regs[_MONOMIX2] = is_enabled << 7
- regs[_MONO] = is_enabled << 6
-
- else:
- raise ValueError("Invalid module")
-
- def enable_module(self, module):
- self.set_module(module, True)
-
- def disable_module(self, module):
- self.set_module(module, False)
-
- def set_data_route(self, route):
- regs = self.regs
- if route == ROUTE_BYPASS:
- # Bypass means from line-in to HP
- # Left LINPUT3 to left output mixer, LINPUT3 left output mixer volume = 0dB
- # Right RINPUT3 to right output mixer, RINPUT3 right output mixer volume = 0dB
- regs[_LOUTMIX, _ROUTMIX] = 0x80
-
- elif route == ROUTE_PLAYBACK:
- # Data route I2S_IN-> DAC-> HP
- #
- # Left DAC to left output mixer, LINPUT3 left output mixer volume = 0dB
- # Right DAC to right output mixer, RINPUT3 right output mixer volume = 0dB
- regs[_LOUTMIX, _ROUTMIX] = 0x100
- regs[_POWER3] = 0x0C
- # Set power for DAC
- self.set_module(MODULE_DAC, True)
- self.set_module(MODULE_OMIX, True)
- self.set_module(MODULE_LINE_OUT, True)
-
- elif route == ROUTE_PLAYBACK_RECORD:
- #
- # Left DAC to left output mixer, LINPUT3 left output mixer volume = 0dB
- # Right DAC to right output mixer, RINPUT3 right output mixer volume = 0dB
- regs[_LOUTMIX, _ROUTMIX] = 0x100
- regs[_POWER3] = 0x3C
- self.set_module(MODULE_DAC, True)
- self.set_module(MODULE_ADC, True)
- self.set_module(MODULE_LINE_IN, True)
- self.set_module(MODULE_OMIX, True)
- self.set_module(MODULE_LINE_OUT, True)
-
- elif route == ROUTE_RECORD:
- # LINE_IN->ADC->I2S_OUT
- # Left and right input boost, LIN3BOOST and RIN3BOOST = 0dB
- regs[_POWER3] = 0x30
- # Power up ADC and AIN
- self.set_module(MODULE_LINE_IN, True)
- self.set_module(MODULE_ADC, True)
-
- else:
- raise ValueError("Invalid route")
-
- def set_left_input(self, input):
- if not input in self._input_config_table.keys():
- raise ValueError("Invalid input")
-
- input = self._input_config_table[input]
-
- regs = self.regs
- if input is None:
- regs[_POWER1] = (_POWER1_AINL_MASK | _POWER1_ADCL_MASK, 0)
- elif input[0] == 0:
- regs[_POWER1] = (0, _POWER1_AINL_MASK | _POWER1_ADCL_MASK)
- regs[_INBMIX1] = input
- else:
- regs[_POWER1] = (0, _POWER1_AINL_MASK | _POWER1_ADCL_MASK | _POWER1_MICB_MASK)
- regs[_LINPATH] = input[0]
- regs[_LINVOL] = input[1]
-
- def set_right_input(self, input):
- if not input in self._input_config_table.keys():
- raise ValueError("Invalid input name")
-
- input = self._input_config_table[input]
-
- regs = self.regs
- if input is None:
- regs[_POWER1] = (_POWER1_AINR_MASK | _POWER1_ADCR_MASK, 0)
- elif input[0] == 0:
- regs[_POWER1] = (0, _POWER1_AINL_MASK | _POWER1_ADCR_MASK)
- regs[_INBMIX2] = input
- else:
- regs[_POWER1] = (0, _POWER1_AINR_MASK | _POWER1_ADCR_MASK | _POWER1_MICB_MASK)
- regs[_RINPATH] = input[0]
- regs[_RINVOL] = input[1]
-
- def set_protocol(self, protocol):
- self.regs[_IFACE1] = (
- _IFACE1_FORMAT_MASK | _IFACE1_LRP_MASK,
- protocol,
- )
-
- def config_data_format(self, sysclk, sample_rate, bits):
- # Compute sample rate divider, dac and adc are the same sample rate
- try:
- divider = self._dac_divider_table[sysclk // sample_rate]
- wl = self._audio_word_length_table[bits]
- except:
- raise ValueError("Invalid ratio sysclk/sample_rate or invalid bit length")
-
- self.regs[_CLOCK1] = (0x1F8, divider << 6 | divider << 3)
- self.regs[_IFACE1] = (_IFACE1_WL_MASK, wl << _IFACE1_WL_SHIFT)
-
- def volume(self, module, volume_l=None, volume_r=None):
- if not module in self._volume_config_table.keys():
- raise ValueError("Invalid module")
-
- if volume_l is None: # get volume
- vol_max, regnum, _ = self._volume_config_table[module]
- return (
- int((self.regs[regnum] & vol_max) * 100 / vol_max + 0.5),
- int((self.regs[regnum + 1] & vol_max) * 100 / vol_max + 0.5),
- )
- else: # set volume
- if volume_r is None:
- volume_r = volume_l
-
- if not ((0 <= volume_l <= 100) and (0 <= volume_r <= 100)):
- raise ValueError("Invalid value for volume")
- elif not module in self._volume_config_table.keys():
- raise ValueError("Invalid module")
-
- vol_max, regnum, flags = self._volume_config_table[module]
- self.regs[regnum] = int(volume_l * vol_max / 100 + 0.5) | flags
- self.regs[regnum + 1] = int(volume_r * vol_max / 100 + 0.5) | flags
-
- def mute(self, enable, soft=True, ramp=MUTE_FAST):
- enable = _DACCTL1_DACMU_MASK if enable else 0
- soft = _DACCTL2_DACSMM_MASK if soft else 0
- ramp = _DACCTL2_DACMR_MASK if ramp == MUTE_SLOW else 0
- self.regs[_DACCTL1] = (_DACCTL1_DACMU_MASK, enable)
- self.regs[_DACCTL2] = (
- _DACCTL2_DACSMM_MASK | _DACCTL2_DACMR_MASK,
- soft | ramp,
- )
-
- def expand_3d(self, depth=0):
- depth &= 0x0F
- cutoff = 0 if self.sample_rate >= 32000 else 0b1100000
- self.regs[_3D] = cutoff | depth << 1 | (1 if depth > 0 else 0)
-
- def mono(self, enable):
- enable = 1 if enable else 0
- self.regs[_DACCTL1] = (
- _DACCTL1_MONOMIX_MASK,
- enable << _DACCTL1_MONOMIX_SHIFT,
- )
-
- def alc_mode(self, channel, mode=ALC_MODE):
- if mode != ALC_MODE:
- mode = ALC_LIMITER
- channel &= 3
- self.regs[_ALC1] = (
- _ALC_CHANNEL_MASK,
- channel << _ALC_CHANNEL_SHIFT,
- )
- self.regs[_ALC3] = (_ALC_MODE_MASK, mode << _ALC_MODE_SHIFT)
- try:
- rate = _alc_sample_rate_table[self.sample_rate]
- except:
- rate = 0
- self.regs[_ADDCTL3] = (_DACCTL3_ALCSR_MASK, rate)
-
- def alc_gain(self, target=-12, max_gain=30, min_gain=-17.25, noise_gate=-78):
- def limit(value, minval, maxval):
- value = int(value)
- if value < minval:
- value = minval
- if value > maxval:
- value = maxval
- return value
-
- target = limit((16 + (target * 2) // 3), 0, 15)
- max_gain = limit((max_gain + 12) // 6, 0, 7)
- min_gain = limit((min_gain * 4 + 69) // 24, 0, 7)
- noise_gate = limit((noise_gate * 2 + 153) // 3, -1, 31)
- self.regs[_ALC1] = (
- _ALC_GAIN_MASK | _ALC_TARGET_MASK,
- (max_gain << _ALC_GAIN_SHIFT) | target,
- )
- self.regs[_ALC2] = (_ALC_GAIN_MASK, (min_gain << _ALC_GAIN_SHIFT))
- if noise_gate >= 0:
- self.regs[_NOISEG] = noise_gate << _NOISEG_LEVEL_SHIFT | 1
- else:
- self.regs[_NOISEG] = 0
-
- def alc_time(self, attack=24, decay=192, hold=0):
- def logb(value, limit):
- value = int(value)
- lb = 0
- while value > 1:
- value >>= 1
- lb += 1
- if lb > limit:
- lb = limit
- return lb
-
- attack = logb(attack / 6, 7)
- decay = logb(decay / 24, 7)
- hold = logb((hold * 3) / 8, 15)
- self.regs[_ALC2] = (_ALC_HOLD_MASK, hold)
- self.regs[_ALC3] = (
- _ALC_DECAY_MASK | _ALC_ATTACK_MASK,
- (decay << _ALC_DECAY_SHIFT) | attack,
- )
-
- def deemphasis(self, enable):
- deem_table = (32000, 44100, 48000)
- enable = not not enable
- if enable and self.sample_rate in deem_table:
- val = deem_table.index(self.sample_rate) + 1
- else:
- val = 0
- self.regs[_DACCTL1] = (_DACCTL1_DEEM_MASK, val << _DACCTL1_DEEM_SHIFT)
diff --git a/drivers/cyw43/cyw43.h b/drivers/cyw43/cyw43.h
deleted file mode 100644
index 7d3e30f5d4ed..000000000000
--- a/drivers/cyw43/cyw43.h
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * 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 "shared/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
deleted file mode 100644
index 203bc812ac13..000000000000
--- a/drivers/cyw43/cyw43_ctrl.c
+++ /dev/null
@@ -1,593 +0,0 @@
-/*
- * 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/mperrno.h"
-#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)
-
-#define CYW43_STA_IS_ACTIVE(self) (((self)->itf_state >> CYW43_ITF_STA) & 1)
-#define CYW43_AP_IS_ACTIVE(self) (((self)->itf_state >> CYW43_ITF_AP) & 1)
-
-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) {
- if (cyw43_poll == NULL) {
- return;
- }
-
- CYW_ENTER
-
- // Stop the TCP/IP network interfaces.
- cyw43_tcpip_deinit(self, 0);
- cyw43_tcpip_deinit(self, 1);
-
- // Turn off the SDIO bus.
- #if USE_SDIOIT
- sdio_enable_irq(false);
- #endif
- sdio_deinit();
-
- // Power off the WLAN chip and make sure all state is reset.
- cyw43_init(self);
-
- 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
- sdio_enable_irq(true);
- #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
- sdio_enable_irq(true);
- #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
- sdio_reenable();
- #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 -MP_EPERM;
- }
-
- 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) {
- if (!CYW43_STA_IS_ACTIVE(self)) {
- return -MP_EPERM;
- }
-
- 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
deleted file mode 100644
index 879367a2edd9..000000000000
--- a/drivers/cyw43/cyw43_ll.h
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * 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
deleted file mode 100644
index 16ae6023755a..000000000000
--- a/drivers/cyw43/cyw43_lwip.c
+++ /dev/null
@@ -1,198 +0,0 @@
-/*
- * 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 "shared/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
index 64aeb871c38b..33e749bbf9f4 100644
--- a/drivers/cyw43/cywbt.c
+++ b/drivers/cyw43/cywbt.c
@@ -35,8 +35,8 @@
#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)
+#include "lib/cyw43-driver/src/cyw43_config.h"
+#include "lib/cyw43-driver/firmware/cyw43_btfw_4343A1.h"
// Provided by the port.
extern pyb_uart_obj_t mp_bluetooth_hci_uart_obj;
@@ -159,8 +159,8 @@ STATIC int cywbt_download_firmware(const uint8_t *firmware) {
#endif
mp_bluetooth_hci_uart_set_baudrate(115200);
- cywbt_set_baudrate(3000000);
- mp_bluetooth_hci_uart_set_baudrate(3000000);
+ cywbt_set_baudrate(MICROPY_HW_BLE_UART_BAUDRATE_SECONDARY);
+ mp_bluetooth_hci_uart_set_baudrate(MICROPY_HW_BLE_UART_BAUDRATE_SECONDARY);
return 0;
}
@@ -191,11 +191,13 @@ int mp_bluetooth_hci_controller_init(void) {
// Reset
cywbt_hci_cmd(0x03, 0x0003, 0, NULL);
+ #ifdef MICROPY_HW_BLE_UART_BAUDRATE_DOWNLOAD_FIRMWARE
// Change baudrate
- cywbt_set_baudrate(3000000);
- mp_bluetooth_hci_uart_set_baudrate(3000000);
+ cywbt_set_baudrate(MICROPY_HW_BLE_UART_BAUDRATE_DOWNLOAD_FIRMWARE);
+ mp_bluetooth_hci_uart_set_baudrate(MICROPY_HW_BLE_UART_BAUDRATE_DOWNLOAD_FIRMWARE);
+ #endif
- cywbt_download_firmware((const uint8_t*)CYWBT_FW_ADDR);
+ cywbt_download_firmware((const uint8_t*)&cyw43_btfw_4343A1[0]);
// Reset
cywbt_hci_cmd(0x03, 0x0003, 0, NULL);
diff --git a/drivers/cyw43/libcyw43.a b/drivers/cyw43/libcyw43.a
deleted file mode 100644
index 7d0ff93dcbe6..000000000000
Binary files a/drivers/cyw43/libcyw43.a and /dev/null differ
diff --git a/drivers/dht/dht.py b/drivers/dht/dht.py
deleted file mode 100644
index 411e9a8d28a6..000000000000
--- a/drivers/dht/dht.py
+++ /dev/null
@@ -1,46 +0,0 @@
-# DHT11/DHT22 driver for MicroPython on ESP8266
-# MIT license; Copyright (c) 2016 Damien P. George
-
-import sys
-
-if sys.platform.startswith("esp"):
- from esp import dht_readinto
-elif sys.platform == "mimxrt":
- from mimxrt import dht_readinto
-elif sys.platform == "rp2":
- from rp2 import dht_readinto
-elif sys.platform == "pyboard":
- from pyb import dht_readinto
-else:
- from machine import dht_readinto
-
-
-class DHTBase:
- def __init__(self, pin):
- self.pin = pin
- self.buf = bytearray(5)
-
- def measure(self):
- buf = self.buf
- dht_readinto(self.pin, buf)
- 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]
-
- 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
- if self.buf[2] & 0x80:
- t = -t
- return t
diff --git a/drivers/display/lcd160cr.py b/drivers/display/lcd160cr.py
deleted file mode 100644
index f792418aa2b5..000000000000
--- a/drivers/display/lcd160cr.py
+++ /dev/null
@@ -1,482 +0,0 @@
-# Driver for official MicroPython LCD160CR display
-# MIT license; Copyright (c) 2017 Damien P. George
-
-from micropython import const
-from utime import sleep_ms
-from ustruct import calcsize, pack_into
-import uerrno, machine
-
-# for set_orient
-PORTRAIT = const(0)
-LANDSCAPE = const(1)
-PORTRAIT_UPSIDEDOWN = const(2)
-LANDSCAPE_UPSIDEDOWN = const(3)
-
-# for set_startup_deco; can be or'd
-STARTUP_DECO_NONE = const(0)
-STARTUP_DECO_MLOGO = const(1)
-STARTUP_DECO_INFO = const(2)
-
-_uart_baud_table = {
- 2400: 0,
- 4800: 1,
- 9600: 2,
- 19200: 3,
- 38400: 4,
- 57600: 5,
- 115200: 6,
- 230400: 7,
- 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"):
- i = connect[-1]
- j = connect[0]
- y = j + "4"
- elif connect == "C":
- i = 2
- j = 2
- 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"')
-
- if pwr is None:
- pwr = machine.Pin(y, machine.Pin.OUT)
- if i2c is None:
- i2c = machine.I2C(i, freq=1000000)
- if spi is None:
- spi = machine.SPI(j, baudrate=13500000, polarity=0, phase=0)
-
- if not pwr.value():
- pwr(1)
- sleep_ms(10)
- # else:
- # alread have power
- # lets be optimistic...
-
- # set connections
- self.pwr = pwr
- self.i2c = i2c
- self.spi = spi
- self.i2c_addr = i2c_addr
-
- # create temp buffers and memoryviews
- self.buf16 = bytearray(16)
- self.buf19 = bytearray(19)
- self.buf = [None] * 10
- for i in range(1, 10):
- self.buf[i] = memoryview(self.buf16)[0:i]
- self.buf1 = self.buf[1]
- self.array4 = [0, 0, 0, 0]
-
- # set default orientation and window
- self.set_orient(PORTRAIT)
- self._fcmd2b("= n:
- self.i2c.readfrom_into(self.i2c_addr, buf)
- return
- t -= 1
- sleep_ms(1)
- raise OSError(uerrno.ETIMEDOUT)
-
- def oflush(self, n=255):
- t = 5000
- while t:
- self.i2c.readfrom_into(self.i2c_addr + 1, self.buf1)
- r = self.buf1[0]
- if r >= n:
- return
- t -= 1
- machine.idle()
- raise OSError(uerrno.ETIMEDOUT)
-
- def iflush(self):
- t = 5000
- while t:
- self.i2c.readfrom_into(self.i2c_addr, self.buf16)
- if self.buf16[0] == 0:
- return
- t -= 1
- sleep_ms(1)
- raise OSError(uerrno.ETIMEDOUT)
-
- #### MISC METHODS ####
-
- @staticmethod
- def rgb(r, g, b):
- return ((b & 0xF8) << 8) | ((g & 0xFC) << 3) | (r >> 3)
-
- @staticmethod
- def clip_line(c, w, h):
- while True:
- ca = ce = 0
- if c[1] < 0:
- ca |= 8
- elif c[1] > h:
- ca |= 4
- if c[0] < 0:
- ca |= 1
- elif c[0] > w:
- ca |= 2
- if c[3] < 0:
- ce |= 8
- elif c[3] > h:
- ce |= 4
- if c[2] < 0:
- ce |= 1
- elif c[2] > w:
- ce |= 2
- if ca & ce:
- return False
- elif ca | ce:
- ca |= ce
- if ca & 1:
- if c[2] < c[0]:
- c[0], c[2] = c[2], c[0]
- c[1], c[3] = c[3], c[1]
- c[1] += ((-c[0]) * (c[3] - c[1])) // (c[2] - c[0])
- c[0] = 0
- elif ca & 2:
- if c[2] < c[0]:
- c[0], c[2] = c[2], c[0]
- c[1], c[3] = c[3], c[1]
- c[3] += ((w - 1 - c[2]) * (c[3] - c[1])) // (c[2] - c[0])
- c[2] = w - 1
- elif ca & 4:
- if c[0] == c[2]:
- if c[1] >= h:
- c[1] = h - 1
- if c[3] >= h:
- c[3] = h - 1
- else:
- if c[3] < c[1]:
- c[0], c[2] = c[2], c[0]
- c[1], c[3] = c[3], c[1]
- c[2] += ((h - 1 - c[3]) * (c[2] - c[0])) // (c[3] - c[1])
- c[3] = h - 1
- else:
- if c[0] == c[2]:
- if c[1] < 0:
- c[1] = 0
- if c[3] < 0:
- c[3] = 0
- else:
- if c[3] < c[1]:
- c[0], c[2] = c[2], c[0]
- c[1], c[3] = c[3], c[1]
- c[0] += ((-c[1]) * (c[2] - c[0])) // (c[3] - c[1])
- c[1] = 0
- else:
- return True
-
- #### SETUP COMMANDS ####
-
- def set_power(self, on):
- self.pwr(on)
- sleep_ms(15)
-
- def set_orient(self, orient):
- self._fcmd2("= 2:
- self.i2c.readfrom_into(self.i2c_addr, self.buf[3])
- return self.buf[3][1] | self.buf[3][2] << 8
- t -= 1
- sleep_ms(1)
- raise OSError(uerrno.ETIMEDOUT)
-
- def get_line(self, x, y, buf):
- l = len(buf) // 2
- self._fcmd2b("= l:
- self.i2c.readfrom_into(self.i2c_addr, buf)
- return
- t -= 1
- sleep_ms(1)
- raise OSError(uerrno.ETIMEDOUT)
-
- def screen_dump(self, buf, x=0, y=0, w=None, h=None):
- if w is None:
- w = self.w - x
- if h is None:
- h = self.h - y
- if w <= 127:
- line = bytearray(2 * w + 1)
- line2 = None
- else:
- # split line if more than 254 bytes needed
- buflen = (w + 1) // 2
- line = bytearray(2 * buflen + 1)
- line2 = memoryview(line)[: 2 * (w - buflen) + 1]
- for i in range(min(len(buf) // (2 * w), h)):
- ix = i * w * 2
- self.get_line(x, y + i, line)
- buf[ix : ix + len(line) - 1] = memoryview(line)[1:]
- ix += len(line) - 1
- if line2:
- self.get_line(x + buflen, y + i, line2)
- buf[ix : ix + len(line2) - 1] = memoryview(line2)[1:]
- ix += len(line2) - 1
-
- def screen_load(self, buf):
- l = self.w * self.h * 2 + 2
- self._fcmd2b("= 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")
- n += 1
-
- #### TEXT COMMANDS ####
-
- def set_pos(self, x, y):
- self._fcmd2("= self.w or y >= self.h:
- return
- elif x < 0 or y < 0:
- left = top = True
- if x < 0:
- left = False
- w += x
- x = 0
- if y < 0:
- top = False
- h += y
- 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
- b = self.buf[4]
- self._waitfor(3, b)
- return b[1] >> 7, b[2], b[3]
-
- #### 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")
- self.oflush()
- self._fcmd2(" 0:
- s = "%6.3fV" % data[i]
- else:
- 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.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)
- rtc = pyb.RTC()
- except:
- adc = None
- rtc = None
-
- # set orientation and clear screen
- lcd = get_lcd(lcd)
- lcd.set_orient(orient)
- lcd.set_pen(0, 0)
- lcd.erase()
-
- # 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.vline(4, 4, 12, 0)
- mlogo.vline(8, 1, 12, 0)
- mlogo.vline(12, 4, 12, 0)
- mlogo.vline(14, 13, 2, 0)
-
- # create inline framebuf
- offx = 14
- offy = 19
- w = 100
- h = 75
- fbuf = framebuf.FrameBuffer(bytearray(w * h * 2), w, h, framebuf.RGB565)
- lcd.set_spi_win(offx, offy, w, h)
-
- # initialise loop parameters
- tx = ty = 0
- t0 = time.ticks_us()
-
- for i in range(300):
- # update position of cross-hair
- t, tx2, ty2 = lcd.get_touch()
- if t:
- tx2 -= offx
- ty2 -= offy
- 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
-
- # 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,
- w // 2 + int(40 * math.cos(0.2 * i)),
- h // 2 + int(40 * math.sin(0.2 * i)),
- 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))
- for phase in (-0.2, 0, 0.2):
- x = w // 2 - 8 + int(50 * math.cos(0.05 * i + phase))
- 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),
- )
- lcd.show_framebuf(fbuf)
-
- # show results from the ADC
- if adc:
- show_adc(lcd, adc)
-
- # show the time
- if rtc:
- 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)
- )
-
- # compute the frame rate
- t1 = time.ticks_us()
- dt = time.ticks_diff(t1, t0)
- t0 = t1
-
- # show the frame rate
- lcd.set_pos(2, 9)
- 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.erase()
-
- # function to compute Mandelbrot pixels
- def in_set(c):
- z = 0
- for i in range(32):
- z = z * z + c
- if abs(z) > 100:
- return i
- return 0
-
- # cache width and height of LCD
- w = lcd.w
- h = lcd.h
-
- # create the buffer for each line and set SPI parameters
- line = bytearray(w * 2)
- lcd.set_spi_win(0, 0, w, h)
- spi = lcd.fast_spi()
-
- # draw the Mandelbrot set line-by-line
- 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
- 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(' argument should be a connection, eg "X", or an LCD160CR object')
diff --git a/drivers/display/ssd1306.py b/drivers/display/ssd1306.py
deleted file mode 100644
index a504cdadcc94..000000000000
--- a/drivers/display/ssd1306.py
+++ /dev/null
@@ -1,163 +0,0 @@
-# MicroPython SSD1306 OLED driver, I2C and SPI interfaces
-
-from micropython import const
-import framebuf
-
-
-# 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_DISP_START_LINE = const(0x40)
-SET_SEG_REMAP = const(0xA0)
-SET_MUX_RATIO = const(0xA8)
-SET_IREF_SELECT = const(0xAD)
-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
-class SSD1306(framebuf.FrameBuffer):
- def __init__(self, width, height, external_vcc):
- self.width = width
- self.height = height
- self.external_vcc = external_vcc
- self.pages = self.height // 8
- self.buffer = bytearray(self.pages * self.width)
- super().__init__(self.buffer, self.width, self.height, framebuf.MONO_VLSB)
- self.init_display()
-
- def init_display(self):
- for cmd in (
- SET_DISP, # display off
- # address setting
- SET_MEM_ADDR,
- 0x00, # horizontal
- # resolution and layout
- SET_DISP_START_LINE, # start at line 0
- 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
- # display
- SET_CONTRAST,
- 0xFF, # maximum
- SET_ENTIRE_ON, # output follows RAM contents
- SET_NORM_INV, # not inverted
- SET_IREF_SELECT,
- 0x30, # enable internal IREF during display on
- # charge pump
- SET_CHARGE_PUMP,
- 0x10 if self.external_vcc else 0x14,
- SET_DISP | 0x01, # display on
- ): # on
- self.write_cmd(cmd)
- self.fill(0)
- self.show()
-
- def poweroff(self):
- self.write_cmd(SET_DISP)
-
- def poweron(self):
- self.write_cmd(SET_DISP | 0x01)
-
- def contrast(self, contrast):
- self.write_cmd(SET_CONTRAST)
- self.write_cmd(contrast)
-
- def invert(self, invert):
- self.write_cmd(SET_NORM_INV | (invert & 1))
-
- def rotate(self, rotate):
- self.write_cmd(SET_COM_OUT_DIR | ((rotate & 1) << 3))
- self.write_cmd(SET_SEG_REMAP | (rotate & 1))
-
- def show(self):
- x0 = 0
- x1 = self.width - 1
- if self.width != 128:
- # narrow displays use centred columns
- col_offset = (128 - self.width) // 2
- x0 += col_offset
- x1 += col_offset
- self.write_cmd(SET_COL_ADDR)
- self.write_cmd(x0)
- self.write_cmd(x1)
- self.write_cmd(SET_PAGE_ADDR)
- self.write_cmd(0)
- self.write_cmd(self.pages - 1)
- self.write_data(self.buffer)
-
-
-class SSD1306_I2C(SSD1306):
- 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[1] = cmd
- self.i2c.writeto(self.addr, self.temp)
-
- def write_data(self, buf):
- self.write_list[1] = buf
- self.i2c.writevto(self.addr, self.write_list)
-
-
-class SSD1306_SPI(SSD1306):
- def __init__(self, width, height, spi, dc, res, cs, external_vcc=False):
- self.rate = 10 * 1024 * 1024
- dc.init(dc.OUT, value=0)
- res.init(res.OUT, value=0)
- cs.init(cs.OUT, value=1)
- self.spi = spi
- self.dc = dc
- self.res = res
- self.cs = cs
- import time
-
- self.res(1)
- time.sleep_ms(1)
- self.res(0)
- time.sleep_ms(10)
- self.res(1)
- super().__init__(width, height, external_vcc)
-
- def write_cmd(self, cmd):
- self.spi.init(baudrate=self.rate, polarity=0, phase=0)
- self.cs(1)
- self.dc(0)
- self.cs(0)
- self.spi.write(bytearray([cmd]))
- self.cs(1)
-
- def write_data(self, buf):
- self.spi.init(baudrate=self.rate, polarity=0, phase=0)
- self.cs(1)
- self.dc(1)
- self.cs(0)
- self.spi.write(buf)
- self.cs(1)
diff --git a/drivers/lsm6dsox/lsm6dsox.py b/drivers/lsm6dsox/lsm6dsox.py
deleted file mode 100644
index 98e19fa4ca7b..000000000000
--- a/drivers/lsm6dsox/lsm6dsox.py
+++ /dev/null
@@ -1,271 +0,0 @@
-"""
-LSM6DSOX STMicro driver for MicroPython based on LSM9DS1:
-Source repo: https://github.com/hoihu/projects/tree/master/raspi-hat
-
-The MIT License (MIT)
-
-Copyright (c) 2021 Damien P. George
-Copyright (c) 2021-2022 Ibrahim Abdelkader
-
-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.
-
-Basic example usage:
-
-import time
-from lsm6dsox import LSM6DSOX
-
-from machine import Pin, SPI, I2C
-# Init in I2C mode.
-lsm = LSM6DSOX(I2C(0, scl=Pin(13), sda=Pin(12)))
-
-# Or init in SPI mode.
-#lsm = LSM6DSOX(SPI(5), cs_pin=Pin(10))
-
-while (True):
- print('Accelerometer: x:{:>8.3f} y:{:>8.3f} z:{:>8.3f}'.format(*lsm.read_accel()))
- print('Gyroscope: x:{:>8.3f} y:{:>8.3f} z:{:>8.3f}'.format(*lsm.read_gyro()))
- print("")
- time.sleep_ms(100)
-"""
-
-import array
-from micropython import const
-
-
-class LSM6DSOX:
- _CTRL3_C = const(0x12)
- _CTRL1_XL = const(0x10)
- _CTRL8_XL = const(0x17)
- _CTRL9_XL = const(0x18)
-
- _CTRL2_G = const(0x11)
- _CTRL7_G = const(0x16)
-
- _OUTX_L_G = const(0x22)
- _OUTX_L_XL = const(0x28)
- _MLC_STATUS = const(0x38)
-
- _DEFAULT_ADDR = const(0x6A)
- _WHO_AM_I_REG = const(0x0F)
-
- _FUNC_CFG_ACCESS = const(0x01)
- _FUNC_CFG_BANK_USER = const(0)
- _FUNC_CFG_BANK_HUB = const(1)
- _FUNC_CFG_BANK_EMBED = const(2)
-
- _MLC0_SRC = const(0x70)
- _MLC_INT1 = const(0x0D)
- _TAP_CFG0 = const(0x56)
-
- _EMB_FUNC_EN_A = const(0x04)
- _EMB_FUNC_EN_B = const(0x05)
-
- def __init__(
- self,
- bus,
- cs_pin=None,
- address=_DEFAULT_ADDR,
- gyro_odr=104,
- accel_odr=104,
- gyro_scale=2000,
- accel_scale=4,
- ucf=None,
- ):
- """Initalizes Gyro and Accelerator.
- accel_odr: (0, 1.6Hz, 3.33Hz, 6.66Hz, 12.5Hz, 26Hz, 52Hz, 104Hz, 208Hz, 416Hz, 888Hz)
- gyro_odr: (0, 1.6Hz, 3.33Hz, 6.66Hz, 12.5Hz, 26Hz, 52Hz, 104Hz, 208Hz, 416Hz, 888Hz)
- gyro_scale: (245dps, 500dps, 1000dps, 2000dps)
- accel_scale: (+/-2g, +/-4g, +/-8g, +-16g)
- ucf: MLC program to load.
- """
- self.bus = bus
- self.cs_pin = cs_pin
- self.address = address
- self._use_i2c = hasattr(self.bus, "readfrom_mem")
-
- if not self._use_i2c and cs_pin is None:
- raise ValueError("A CS pin must be provided in SPI mode")
-
- # check the id of the Accelerometer/Gyro
- if self.__read_reg(_WHO_AM_I_REG) != 108:
- raise OSError("No LSM6DS device was found at address 0x%x" % (self.address))
-
- # allocate scratch buffer for efficient conversions and memread op's
- self.scratch_int = array.array("h", [0, 0, 0])
-
- SCALE_GYRO = {250: 0, 500: 1, 1000: 2, 2000: 3}
- SCALE_ACCEL = {2: 0, 4: 2, 8: 3, 16: 1}
- # XL_HM_MODE = 0 by default. G_HM_MODE = 0 by default.
- ODR = {
- 0: 0x00,
- 1.6: 0x08,
- 3.33: 0x09,
- 6.66: 0x0A,
- 12.5: 0x01,
- 26: 0x02,
- 52: 0x03,
- 104: 0x04,
- 208: 0x05,
- 416: 0x06,
- 888: 0x07,
- }
-
- gyro_odr = round(gyro_odr, 2)
- accel_odr = round(accel_odr, 2)
-
- # Sanity checks
- if not gyro_odr in ODR:
- raise ValueError("Invalid sampling rate: %d" % accel_odr)
- if not gyro_scale in SCALE_GYRO:
- raise ValueError("invalid gyro scaling: %d" % gyro_scale)
- if not accel_odr in ODR:
- raise ValueError("Invalid sampling rate: %d" % accel_odr)
- if not accel_scale in SCALE_ACCEL:
- raise ValueError("invalid accelerometer scaling: %d" % accel_scale)
-
- # Soft-reset the device.
- self.reset()
-
- # Load and configure MLC if UCF file is provided
- if ucf != None:
- self.load_mlc(ucf)
-
- # Set Gyroscope datarate and scale.
- # Note output from LPF2 second filtering stage is selected. See Figure 18.
- self.__write_reg(_CTRL1_XL, (ODR[accel_odr] << 4) | (SCALE_ACCEL[accel_scale] << 2) | 2)
-
- # Enable LPF2 and HPF fast-settling mode, ODR/4
- self.__write_reg(_CTRL8_XL, 0x09)
-
- # Set Gyroscope datarate and scale.
- self.__write_reg(_CTRL2_G, (ODR[gyro_odr] << 4) | (SCALE_GYRO[gyro_scale] << 2) | 0)
-
- self.gyro_scale = 32768 / gyro_scale
- self.accel_scale = 32768 / accel_scale
-
- def __read_reg(self, reg, size=1):
- if self._use_i2c:
- buf = self.bus.readfrom_mem(self.address, reg, size)
- else:
- try:
- self.cs_pin(0)
- self.bus.write(bytes([reg | 0x80]))
- buf = self.bus.read(size)
- finally:
- self.cs_pin(1)
- if size == 1:
- return int(buf[0])
- return [int(x) for x in buf]
-
- def __write_reg(self, reg, val):
- if self._use_i2c:
- self.bus.writeto_mem(self.address, reg, bytes([val]))
- else:
- try:
- self.cs_pin(0)
- self.bus.write(bytes([reg, val]))
- finally:
- self.cs_pin(1)
-
- def __read_reg_into(self, reg, buf):
- if self._use_i2c:
- self.bus.readfrom_mem_into(self.address, reg, buf)
- else:
- try:
- self.cs_pin(0)
- self.bus.write(bytes([reg | 0x80]))
- self.bus.readinto(buf)
- finally:
- self.cs_pin(1)
-
- def reset(self):
- self.__write_reg(_CTRL3_C, self.__read_reg(_CTRL3_C) | 0x1)
- for i in range(0, 10):
- if (self.__read_reg(_CTRL3_C) & 0x01) == 0:
- return
- time.sleep_ms(10)
- raise OSError("Failed to reset LSM6DS device.")
-
- def set_mem_bank(self, bank):
- cfg = self.__read_reg(_FUNC_CFG_ACCESS) & 0x3F
- self.__write_reg(_FUNC_CFG_ACCESS, cfg | (bank << 6))
-
- def set_embedded_functions(self, enable, emb_ab=None):
- self.set_mem_bank(_FUNC_CFG_BANK_EMBED)
- if enable:
- self.__write_reg(_EMB_FUNC_EN_A, emb_ab[0])
- self.__write_reg(_EMB_FUNC_EN_B, emb_ab[1])
- else:
- emb_a = self.__read_reg(_EMB_FUNC_EN_A)
- emb_b = self.__read_reg(_EMB_FUNC_EN_B)
- self.__write_reg(_EMB_FUNC_EN_A, (emb_a & 0xC7))
- self.__write_reg(_EMB_FUNC_EN_B, (emb_b & 0xE6))
- emb_ab = (emb_a, emb_b)
-
- self.set_mem_bank(_FUNC_CFG_BANK_USER)
- return emb_ab
-
- def load_mlc(self, ucf):
- # Load MLC config from file
- with open(ucf, "r") as ucf_file:
- for l in ucf_file:
- if l.startswith("Ac"):
- v = [int(v, 16) for v in l.strip().split(" ")[1:3]]
- self.__write_reg(v[0], v[1])
-
- emb_ab = self.set_embedded_functions(False)
-
- # Disable I3C interface
- self.__write_reg(_CTRL9_XL, self.__read_reg(_CTRL9_XL) | 0x01)
-
- # Enable Block Data Update
- self.__write_reg(_CTRL3_C, self.__read_reg(_CTRL3_C) | 0x40)
-
- # Route signals on interrupt pin 1
- self.set_mem_bank(_FUNC_CFG_BANK_EMBED)
- self.__write_reg(_MLC_INT1, self.__read_reg(_MLC_INT1) & 0x01)
- self.set_mem_bank(_FUNC_CFG_BANK_USER)
-
- # Configure interrupt pin mode
- self.__write_reg(_TAP_CFG0, self.__read_reg(_TAP_CFG0) | 0x41)
-
- self.set_embedded_functions(True, emb_ab)
-
- def read_mlc_output(self):
- buf = None
- if self.__read_reg(_MLC_STATUS) & 0x1:
- self.__read_reg(0x1A, size=12)
- self.set_mem_bank(_FUNC_CFG_BANK_EMBED)
- buf = self.__read_reg(_MLC0_SRC, 8)
- self.set_mem_bank(_FUNC_CFG_BANK_USER)
- return buf
-
- def read_gyro(self):
- """Returns gyroscope vector in degrees/sec."""
- mv = memoryview(self.scratch_int)
- f = self.gyro_scale
- self.__read_reg_into(_OUTX_L_G, mv)
- return (mv[0] / f, mv[1] / f, mv[2] / f)
-
- def read_accel(self):
- """Returns acceleration vector in gravity units (9.81m/s^2)."""
- mv = memoryview(self.scratch_int)
- f = self.accel_scale
- self.__read_reg_into(_OUTX_L_XL, mv)
- return (mv[0] / f, mv[1] / f, mv[2] / f)
diff --git a/drivers/lsm6dsox/lsm6dsox_basic.py b/drivers/lsm6dsox/lsm6dsox_basic.py
deleted file mode 100644
index 0ffe9e92b768..000000000000
--- a/drivers/lsm6dsox/lsm6dsox_basic.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# LSM6DSOX Basic Example.
-import time
-from lsm6dsox import LSM6DSOX
-
-from machine import Pin, I2C
-
-lsm = LSM6DSOX(I2C(0, scl=Pin(13), sda=Pin(12)))
-# Or init in SPI mode.
-# lsm = LSM6DSOX(SPI(5), cs_pin=Pin(10))
-
-while True:
- print("Accelerometer: x:{:>8.3f} y:{:>8.3f} z:{:>8.3f}".format(*lsm.read_accel()))
- print("Gyroscope: x:{:>8.3f} y:{:>8.3f} z:{:>8.3f}".format(*lsm.read_gyro()))
- print("")
- time.sleep_ms(100)
diff --git a/drivers/lsm6dsox/lsm6dsox_mlc.py b/drivers/lsm6dsox/lsm6dsox_mlc.py
deleted file mode 100644
index 866498d0ce13..000000000000
--- a/drivers/lsm6dsox/lsm6dsox_mlc.py
+++ /dev/null
@@ -1,48 +0,0 @@
-# LSM6DSOX IMU MLC (Machine Learning Core) Example.
-# Download the raw UCF file, copy to storage and reset.
-
-# NOTE: The pre-trained models (UCF files) for the examples can be found here:
-# https://github.com/STMicroelectronics/STMems_Machine_Learning_Core/tree/master/application_examples/lsm6dsox
-
-import time
-from lsm6dsox import LSM6DSOX
-from machine import Pin, I2C
-
-INT_MODE = True # Run in interrupt mode.
-INT_FLAG = False # Set True on interrupt.
-
-
-def imu_int_handler(pin):
- global INT_FLAG
- INT_FLAG = True
-
-
-if INT_MODE == True:
- int_pin = Pin(24)
- int_pin.irq(handler=imu_int_handler, trigger=Pin.IRQ_RISING)
-
-i2c = I2C(0, scl=Pin(13), sda=Pin(12))
-
-# Vibration detection example
-UCF_FILE = "lsm6dsox_vibration_monitoring.ucf"
-UCF_LABELS = {0: "no vibration", 1: "low vibration", 2: "high vibration"}
-# NOTE: Selected data rate and scale must match the MLC data rate and scale.
-lsm = LSM6DSOX(i2c, gyro_odr=26, accel_odr=26, gyro_scale=2000, accel_scale=4, ucf=UCF_FILE)
-
-# Head gestures example
-# UCF_FILE = "lsm6dsox_head_gestures.ucf"
-# UCF_LABELS = {0:"Nod", 1:"Shake", 2:"Stationary", 3:"Swing", 4:"Walk"}
-# NOTE: Selected data rate and scale must match the MLC data rate and scale.
-# lsm = LSM6DSOX(i2c, gyro_odr=26, accel_odr=26, gyro_scale=250, accel_scale=2, ucf=UCF_FILE)
-
-print("MLC configured...")
-
-while True:
- if INT_MODE:
- if INT_FLAG:
- INT_FLAG = False
- print(UCF_LABELS[lsm.read_mlc_output()[0]])
- else:
- buf = lsm.read_mlc_output()
- if buf != None:
- print(UCF_LABELS[buf[0]])
diff --git a/drivers/memory/spiflash.c b/drivers/memory/spiflash.c
index 9f8dc29a734d..52739b1d8bdf 100644
--- a/drivers/memory/spiflash.c
+++ b/drivers/memory/spiflash.c
@@ -70,7 +70,8 @@ STATIC void mp_spiflash_release_bus(mp_spiflash_t *self) {
}
}
-STATIC void mp_spiflash_write_cmd_data(mp_spiflash_t *self, uint8_t cmd, size_t len, uint32_t data) {
+STATIC int mp_spiflash_write_cmd_data(mp_spiflash_t *self, uint8_t cmd, size_t len, uint32_t data) {
+ int ret = 0;
const mp_spiflash_config_t *c = self->config;
if (c->bus_kind == MP_SPIFLASH_BUS_SPI) {
// Note: len/data are unused for standard SPI
@@ -78,11 +79,13 @@ STATIC void mp_spiflash_write_cmd_data(mp_spiflash_t *self, uint8_t cmd, size_t
c->bus.u_spi.proto->transfer(c->bus.u_spi.data, 1, &cmd, NULL);
mp_hal_pin_write(c->bus.u_spi.cs, 1);
} else {
- c->bus.u_qspi.proto->write_cmd_data(c->bus.u_qspi.data, cmd, len, data);
+ ret = c->bus.u_qspi.proto->write_cmd_data(c->bus.u_qspi.data, cmd, len, data);
}
+ return ret;
}
-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) {
+STATIC int 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) {
+ int ret = 0;
const mp_spiflash_config_t *c = self->config;
if (c->bus_kind == MP_SPIFLASH_BUS_SPI) {
uint8_t buf[5] = {cmd, 0};
@@ -98,28 +101,28 @@ STATIC void mp_spiflash_transfer_cmd_addr_data(mp_spiflash_t *self, uint8_t cmd,
mp_hal_pin_write(c->bus.u_spi.cs, 1);
} else {
if (dest != NULL) {
- c->bus.u_qspi.proto->read_cmd_qaddr_qdata(c->bus.u_qspi.data, cmd, addr, len, dest);
+ ret = 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);
+ ret = c->bus.u_qspi.proto->write_cmd_addr_data(c->bus.u_qspi.data, cmd, addr, len, src);
}
}
+ return ret;
}
-STATIC uint32_t mp_spiflash_read_cmd(mp_spiflash_t *self, uint8_t cmd, size_t len) {
+STATIC int mp_spiflash_read_cmd(mp_spiflash_t *self, uint8_t cmd, size_t len, uint32_t *dest) {
const mp_spiflash_config_t *c = self->config;
if (c->bus_kind == MP_SPIFLASH_BUS_SPI) {
- uint32_t buf;
mp_hal_pin_write(c->bus.u_spi.cs, 0);
c->bus.u_spi.proto->transfer(c->bus.u_spi.data, 1, &cmd, NULL);
- c->bus.u_spi.proto->transfer(c->bus.u_spi.data, len, (void*)&buf, (void*)&buf);
+ c->bus.u_spi.proto->transfer(c->bus.u_spi.data, len, (void*)dest, (void*)dest);
mp_hal_pin_write(c->bus.u_spi.cs, 1);
- return buf;
+ return 0;
} else {
- return c->bus.u_qspi.proto->read_cmd(c->bus.u_qspi.data, cmd, len);
+ return c->bus.u_qspi.proto->read_cmd(c->bus.u_qspi.data, cmd, len, dest);
}
}
-STATIC void mp_spiflash_read_data(mp_spiflash_t *self, uint32_t addr, size_t len, uint8_t *dest) {
+STATIC int 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) {
@@ -127,17 +130,20 @@ STATIC void mp_spiflash_read_data(mp_spiflash_t *self, uint32_t addr, size_t len
} else {
cmd = MICROPY_HW_SPI_ADDR_IS_32BIT(addr) ? CMD_C4READ_32 : CMD_C4READ;
}
- mp_spiflash_transfer_cmd_addr_data(self, cmd, addr, len, NULL, dest);
+ return 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 int mp_spiflash_write_cmd(mp_spiflash_t *self, uint8_t cmd) {
+ return mp_spiflash_write_cmd_data(self, cmd, 0, 0);
}
STATIC int mp_spiflash_wait_sr(mp_spiflash_t *self, uint8_t mask, uint8_t val, uint32_t timeout) {
- uint8_t sr;
do {
- sr = mp_spiflash_read_cmd(self, CMD_RDSR, 1);
+ uint32_t sr;
+ int ret = mp_spiflash_read_cmd(self, CMD_RDSR, 1, &sr);
+ if (ret != 0) {
+ return ret;
+ }
if ((sr & mask) == val) {
return 0; // success
}
@@ -176,17 +182,23 @@ void mp_spiflash_init(mp_spiflash_t *self) {
#if defined(CHECK_DEVID)
// Validate device id
- uint32_t devid = mp_spiflash_read_cmd(self, CMD_RD_DEVID, 3);
- if (devid != CHECK_DEVID) {
- return 0;
+ uint32_t devid;
+ int ret = mp_spiflash_read_cmd(self, CMD_RD_DEVID, 3, &devid);
+ if (ret != 0 || devid != CHECK_DEVID) {
+ mp_spiflash_release_bus(self);
+ return;
}
#endif
if (self->config->bus_kind == MP_SPIFLASH_BUS_QSPI) {
// Set QE bit
- uint32_t data = (mp_spiflash_read_cmd(self, CMD_RDSR, 1) & 0xff)
- | (mp_spiflash_read_cmd(self, CMD_RDCR, 1) & 0xff) << 8;
- if (!(data & (QSPI_QE_MASK << 8))) {
+ uint32_t sr = 0, cr = 0;
+ int ret = mp_spiflash_read_cmd(self, CMD_RDSR, 1, &sr);
+ if (ret == 0) {
+ ret = mp_spiflash_read_cmd(self, CMD_RDCR, 1, &cr);
+ }
+ uint32_t data = (sr & 0xff) | (cr & 0xff) << 8;
+ if (ret == 0 && !(data & (QSPI_QE_MASK << 8))) {
data |= QSPI_QE_MASK << 8;
mp_spiflash_write_cmd(self, CMD_WREN);
mp_spiflash_write_cmd_data(self, CMD_WRSR, 2, data);
@@ -208,36 +220,50 @@ void mp_spiflash_deepsleep(mp_spiflash_t *self, int value) {
}
STATIC int mp_spiflash_erase_block_internal(mp_spiflash_t *self, uint32_t addr) {
+ int ret = 0;
// enable writes
- mp_spiflash_write_cmd(self, CMD_WREN);
+ ret = mp_spiflash_write_cmd(self, CMD_WREN);
+ if (ret != 0) {
+ return ret;
+ }
// wait WEL=1
- int ret = mp_spiflash_wait_wel1(self);
+ ret = mp_spiflash_wait_wel1(self);
if (ret != 0) {
return ret;
}
// erase the sector
uint8_t cmd = MICROPY_HW_SPI_ADDR_IS_32BIT(addr) ? CMD_SEC_ERASE_32 : CMD_SEC_ERASE;
- mp_spiflash_transfer_cmd_addr_data(self, cmd, addr, 0, NULL, NULL);
+ ret = mp_spiflash_transfer_cmd_addr_data(self, cmd, addr, 0, NULL, NULL);
+ if (ret != 0) {
+ return ret;
+ }
// wait WIP=0
return mp_spiflash_wait_wip0(self);
}
STATIC int mp_spiflash_write_page(mp_spiflash_t *self, uint32_t addr, size_t len, const uint8_t *src) {
+ int ret = 0;
// enable writes
- mp_spiflash_write_cmd(self, CMD_WREN);
+ ret = mp_spiflash_write_cmd(self, CMD_WREN);
+ if (ret != 0) {
+ return ret;
+ }
// wait WEL=1
- int ret = mp_spiflash_wait_wel1(self);
+ ret = mp_spiflash_wait_wel1(self);
if (ret != 0) {
return ret;
}
// write the page
uint8_t cmd = MICROPY_HW_SPI_ADDR_IS_32BIT(addr) ? CMD_WRITE_32 : CMD_WRITE;
- mp_spiflash_transfer_cmd_addr_data(self, cmd, addr, len, src, NULL);
+ ret = mp_spiflash_transfer_cmd_addr_data(self, cmd, addr, len, src, NULL);
+ if (ret != 0) {
+ return ret;
+ }
// wait WIP=0
return mp_spiflash_wait_wip0(self);
@@ -253,13 +279,14 @@ int mp_spiflash_erase_block(mp_spiflash_t *self, uint32_t addr) {
return ret;
}
-void mp_spiflash_read(mp_spiflash_t *self, uint32_t addr, size_t len, uint8_t *dest) {
+int mp_spiflash_read(mp_spiflash_t *self, uint32_t addr, size_t len, uint8_t *dest) {
if (len == 0) {
- return;
+ return 0;
}
mp_spiflash_acquire_bus(self);
- mp_spiflash_read_data(self, addr, len, dest);
+ int ret = mp_spiflash_read_data(self, addr, len, dest);
mp_spiflash_release_bus(self);
+ return ret;
}
int mp_spiflash_write(mp_spiflash_t *self, uint32_t addr, size_t len, const uint8_t *src) {
@@ -289,9 +316,9 @@ int mp_spiflash_write(mp_spiflash_t *self, uint32_t addr, size_t len, const uint
#if MICROPY_HW_SPIFLASH_ENABLE_CACHE
-void mp_spiflash_cached_read(mp_spiflash_t *self, uint32_t addr, size_t len, uint8_t *dest) {
+int mp_spiflash_cached_read(mp_spiflash_t *self, uint32_t addr, size_t len, uint8_t *dest) {
if (len == 0) {
- return;
+ return 0;
}
mp_spiflash_acquire_bus(self);
mp_spiflash_cache_t *cache = self->config->cache;
@@ -304,7 +331,11 @@ void mp_spiflash_cached_read(mp_spiflash_t *self, uint32_t addr, size_t len, uin
if (bis < cache->block) {
// Read direct from flash for first part
rest = cache->block * SECTOR_SIZE - addr;
- mp_spiflash_read_data(self, addr, rest, dest);
+ int ret = mp_spiflash_read_data(self, addr, rest, dest);
+ if (ret != 0) {
+ mp_spiflash_release_bus(self);
+ return ret;
+ }
len -= rest;
dest += rest;
addr += rest;
@@ -318,21 +349,22 @@ void mp_spiflash_cached_read(mp_spiflash_t *self, uint32_t addr, size_t len, uin
len -= rest;
if (len == 0) {
mp_spiflash_release_bus(self);
- return;
+ return 0;
}
dest += rest;
addr += rest;
}
}
// Read rest direct from flash
- mp_spiflash_read_data(self, addr, len, dest);
+ int ret = mp_spiflash_read_data(self, addr, len, dest);
mp_spiflash_release_bus(self);
+ return ret;
}
-STATIC void mp_spiflash_cache_flush_internal(mp_spiflash_t *self) {
+STATIC int mp_spiflash_cache_flush_internal(mp_spiflash_t *self) {
#if USE_WR_DELAY
if (!(self->flags & 1)) {
- return;
+ return 0;
}
self->flags &= ~1;
@@ -342,7 +374,7 @@ STATIC void mp_spiflash_cache_flush_internal(mp_spiflash_t *self) {
// Erase sector
int ret = mp_spiflash_erase_block_internal(self, cache->block * SECTOR_SIZE);
if (ret != 0) {
- return;
+ return ret;
}
// Write
@@ -350,16 +382,18 @@ STATIC void mp_spiflash_cache_flush_internal(mp_spiflash_t *self) {
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;
+ return ret;
}
}
#endif
+ return 0;
}
-void mp_spiflash_cache_flush(mp_spiflash_t *self) {
+int mp_spiflash_cache_flush(mp_spiflash_t *self) {
mp_spiflash_acquire_bus(self);
- mp_spiflash_cache_flush_internal(self);
+ int ret = mp_spiflash_cache_flush_internal(self);
mp_spiflash_release_bus(self);
+ return ret;
}
STATIC int mp_spiflash_cached_write_part(mp_spiflash_t *self, uint32_t addr, size_t len, const uint8_t *src) {
@@ -389,10 +423,16 @@ STATIC int mp_spiflash_cached_write_part(mp_spiflash_t *self, uint32_t addr, siz
// Read sector
#if USE_WR_DELAY
if (cache->block != 0xffffffff) {
- mp_spiflash_cache_flush_internal(self);
+ int ret = mp_spiflash_cache_flush_internal(self);
+ if (ret != 0) {
+ return ret;
+ }
}
#endif
- mp_spiflash_read_data(self, addr, SECTOR_SIZE, cache->buf);
+ int ret = mp_spiflash_read_data(self, addr, SECTOR_SIZE, cache->buf);
+ if (ret != 0) {
+ return ret;
+ }
}
#if USE_WR_DELAY
diff --git a/drivers/memory/spiflash.h b/drivers/memory/spiflash.h
index c4162ff21cdc..5ccf7d44c97d 100644
--- a/drivers/memory/spiflash.h
+++ b/drivers/memory/spiflash.h
@@ -76,13 +76,13 @@ 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_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);
#if MICROPY_HW_SPIFLASH_ENABLE_CACHE
// 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_cache_flush(mp_spiflash_t *self);
+int 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
diff --git a/drivers/neopixel/manifest.py b/drivers/neopixel/manifest.py
deleted file mode 100644
index 27f610adc0ad..000000000000
--- a/drivers/neopixel/manifest.py
+++ /dev/null
@@ -1,5 +0,0 @@
-freeze(
- ".",
- "neopixel.py",
- opt=3,
-)
diff --git a/drivers/neopixel/neopixel.py b/drivers/neopixel/neopixel.py
deleted file mode 100644
index caa12dc84536..000000000000
--- a/drivers/neopixel/neopixel.py
+++ /dev/null
@@ -1,50 +0,0 @@
-# NeoPixel driver for MicroPython
-# MIT license; Copyright (c) 2016 Damien P. George, 2021 Jim Mussared
-
-from machine import bitstream
-
-
-class NeoPixel:
- # G R B W
- ORDER = (1, 0, 2, 3)
-
- def __init__(self, pin, n, bpp=3, timing=1):
- self.pin = pin
- self.n = n
- self.bpp = bpp
- self.buf = bytearray(n * bpp)
- self.pin.init(pin.OUT)
- # Timing arg can either be 1 for 800kHz or 0 for 400kHz,
- # or a user-specified timing ns tuple (high_0, low_0, high_1, low_1).
- self.timing = (
- ((400, 850, 800, 450) if timing else (800, 1700, 1600, 900))
- if isinstance(timing, int)
- else timing
- )
-
- def __len__(self):
- return self.n
-
- def __setitem__(self, i, v):
- offset = i * self.bpp
- for i in range(self.bpp):
- self.buf[offset + self.ORDER[i]] = v[i]
-
- def __getitem__(self, i):
- offset = i * self.bpp
- return tuple(self.buf[offset + self.ORDER[i]] for i in range(self.bpp))
-
- def fill(self, v):
- b = self.buf
- l = len(self.buf)
- bpp = self.bpp
- for i in range(bpp):
- c = v[i]
- j = self.ORDER[i]
- while j < l:
- b[j] = c
- j += bpp
-
- def write(self):
- # BITSTREAM_TYPE_HIGH_LOW = 0
- bitstream(self.pin, 0, self.timing, self.buf)
diff --git a/drivers/ninaw10/machine_pin_nina.c b/drivers/ninaw10/machine_pin_nina.c
new file mode 100644
index 000000000000..025ecb66af0d
--- /dev/null
+++ b/drivers/ninaw10/machine_pin_nina.c
@@ -0,0 +1,101 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2022 Ibrahim Abdelkader
+ *
+ * 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"
+
+#if defined(MICROPY_PY_NETWORK_NINAW10) && defined(MICROPY_HW_PIN_EXT_COUNT)
+
+#include "modmachine.h"
+#include "machine_pin.h"
+#include "nina_wifi_drv.h"
+
+#define NINA_GPIO_INPUT (0x00)
+#define NINA_GPIO_OUTPUT (0x01)
+#define NINA_GPIO_INPUT_PULLUP (0x02)
+
+#define NINA_GPIO_MODE (0x50)
+#define NINA_GPIO_READ (0x53)
+#define NINA_GPIO_WRITE (0x51)
+#define NINA_GPIO_IS_INPUT_ONLY(p) ((p >= 34 && p <= 36) || (p == 39))
+
+static uint8_t pin_map[MICROPY_HW_PIN_EXT_COUNT] = {
+ 27, // LEDR
+ 25, // LEDG
+ 26, // LEDB
+ 34, // A4
+ 39, // A5
+ 36, // A6
+ 35, // A7
+};
+
+void machine_pin_ext_init(void) {
+ nina_init();
+}
+
+void machine_pin_ext_set(machine_pin_obj_t *self, bool value) {
+ if (self->id >= 0 && self->id < MICROPY_HW_PIN_EXT_COUNT) {
+ uint8_t buf[] = {pin_map[self->id], value};
+ nina_ioctl(NINA_GPIO_WRITE, sizeof(buf), buf, 0);
+ }
+}
+
+bool machine_pin_ext_get(machine_pin_obj_t *self) {
+ bool value = false;
+ if (self->id >= 0 && self->id < MICROPY_HW_PIN_EXT_COUNT) {
+ uint8_t buf[] = {pin_map[self->id]};
+ nina_ioctl(NINA_GPIO_READ, sizeof(buf), buf, 0);
+ value = buf[0];
+ }
+ return value;
+}
+
+void machine_pin_ext_config(machine_pin_obj_t *self, int mode, int value) {
+ if (mode == MACHINE_PIN_MODE_IN) {
+ mode = NINA_GPIO_INPUT;
+ self->is_output = false;
+ } else if (mode == MACHINE_PIN_MODE_OUT) {
+ mode = NINA_GPIO_OUTPUT;
+ self->is_output = true;
+ } else {
+ mp_raise_ValueError("only Pin.OUT and Pin.IN are supported for this pin");
+ }
+ if (self->id >= 0 && self->id < MICROPY_HW_PIN_EXT_COUNT) {
+ uint8_t buf[] = {pin_map[self->id], mode};
+ if (mode == NINA_GPIO_OUTPUT) {
+ if (NINA_GPIO_IS_INPUT_ONLY(buf[0])) {
+ mp_raise_ValueError("only Pin.IN is supported for this pin");
+ }
+ machine_pin_ext_set(self, value);
+ }
+ nina_ioctl(NINA_GPIO_MODE, sizeof(buf), buf, 0);
+ }
+}
+
+#endif // defined(MICROPY_PY_NETWORK_NINAW10) && defined(MICROPY_HW_PIN_EXT_COUNT)
diff --git a/drivers/ninaw10/nina_wifi_bsp.c b/drivers/ninaw10/nina_wifi_bsp.c
index a65ef7fd8644..c65fb111fb10 100644
--- a/drivers/ninaw10/nina_wifi_bsp.c
+++ b/drivers/ninaw10/nina_wifi_bsp.c
@@ -73,7 +73,7 @@ int nina_bsp_init(void) {
MP_OBJ_NEW_SMALL_INT(MICROPY_HW_WIFI_SPI_BAUDRATE),
};
- MP_STATE_PORT(mp_wifi_spi) = machine_spi_type.make_new((mp_obj_t)&machine_spi_type, 2, 0, args);
+ MP_STATE_PORT(mp_wifi_spi) = MP_OBJ_TYPE_GET_SLOT(&machine_spi_type, make_new)((mp_obj_t)&machine_spi_type, 2, 0, args);
return 0;
}
@@ -137,7 +137,7 @@ int nina_bsp_spi_slave_deselect(void) {
int nina_bsp_spi_transfer(const uint8_t *tx_buf, uint8_t *rx_buf, uint32_t size) {
mp_obj_t mp_wifi_spi = MP_STATE_PORT(mp_wifi_spi);
- ((mp_machine_spi_p_t *)machine_spi_type.protocol)->transfer(mp_wifi_spi, size, tx_buf, rx_buf);
+ ((mp_machine_spi_p_t *)MP_OBJ_TYPE_GET_SLOT(&machine_spi_type, protocol))->transfer(mp_wifi_spi, size, tx_buf, rx_buf);
#if NINA_DEBUG
for (int i = 0; i < size; i++) {
if (tx_buf) {
diff --git a/drivers/ninaw10/nina_wifi_drv.c b/drivers/ninaw10/nina_wifi_drv.c
index 7a1167b2c94c..22ad0aae70ea 100644
--- a/drivers/ninaw10/nina_wifi_drv.c
+++ b/drivers/ninaw10/nina_wifi_drv.c
@@ -108,6 +108,7 @@ typedef enum {
// Disonnect/status commands.
NINA_CMD_DISCONNECT = 0x30,
NINA_CMD_CONN_STATUS = 0x20,
+ NINA_CMD_CONN_REASON = 0x1F,
// Interface config commands.
NINA_CMD_SET_IF_CONFIG = 0x14,
@@ -173,19 +174,6 @@ typedef enum {
NINA_CMD_CMD_DOWNLOAD_OTA = 0x67,
} nina_cmd_t;
-typedef enum {
- NINA_STATUS_IDLE = 0,
- NINA_STATUS_NO_SSID_AVAIL,
- NINA_STATUS_SCAN_COMPLETED,
- NINA_STATUS_CONNECTED,
- NINA_STATUS_CONNECT_FAILED,
- NINA_STATUS_CONNECTION_LOST,
- NINA_STATUS_DISCONNECTED,
- NINA_STATUS_AP_LISTENING,
- NINA_STATUS_AP_CONNECTED,
- NINA_STATUS_AP_FAILED
-} nina_status_t;
-
typedef enum {
SOCKET_STATE_CLOSED = 0,
SOCKET_STATE_LISTEN,
@@ -364,13 +352,15 @@ int nina_deinit(void) {
return nina_bsp_deinit();
}
-static int nina_connection_status() {
+int nina_connection_status(void) {
return nina_send_command_read_ack(NINA_CMD_CONN_STATUS, 0, ARG_8BITS, NULL);
}
-int nina_connect(const char *ssid, uint8_t security, const char *key, uint16_t channel) {
- uint8_t status = NINA_STATUS_CONNECT_FAILED;
+int nina_connection_reason(void) {
+ return nina_send_command_read_ack(NINA_CMD_CONN_REASON, 0, ARG_8BITS, NULL);
+}
+int nina_connect(const char *ssid, uint8_t security, const char *key, uint16_t channel) {
if (key == NULL && security != NINA_SEC_OPEN) {
return -1;
}
@@ -398,18 +388,7 @@ int nina_connect(const char *ssid, uint8_t security, const char *key, uint16_t c
return -1;
}
- for (mp_uint_t start = mp_hal_ticks_ms(); ; mp_hal_delay_ms(10)) {
- status = nina_connection_status();
- if ((status != NINA_STATUS_IDLE) && (status != NINA_STATUS_NO_SSID_AVAIL) && (status != NINA_STATUS_SCAN_COMPLETED)) {
- break;
- }
-
- if ((mp_hal_ticks_ms() - start) >= NINA_CONNECT_TIMEOUT) {
- break;
- }
- }
-
- return (status == NINA_STATUS_CONNECTED) ? 0 : -1;
+ return 0;
}
int nina_start_ap(const char *ssid, uint8_t security, const char *key, uint16_t channel) {
@@ -439,7 +418,7 @@ int nina_start_ap(const char *ssid, uint8_t security, const char *key, uint16_t
for (mp_uint_t start = mp_hal_ticks_ms(); ; mp_hal_delay_ms(10)) {
status = nina_connection_status();
- if ((status != NINA_STATUS_IDLE) && (status != NINA_STATUS_NO_SSID_AVAIL) && (status != NINA_STATUS_SCAN_COMPLETED)) {
+ if ((status != NINA_STATUS_IDLE) && (status != NINA_STATUS_NO_SSID_AVAIL)) {
break;
}
diff --git a/drivers/ninaw10/nina_wifi_drv.h b/drivers/ninaw10/nina_wifi_drv.h
index 22163c7286e9..4b09ac8bd24a 100644
--- a/drivers/ninaw10/nina_wifi_drv.h
+++ b/drivers/ninaw10/nina_wifi_drv.h
@@ -46,6 +46,17 @@
#define NINA_FW_VER_MINOR_OFFS (2)
#define NINA_FW_VER_PATCH_OFFS (4)
+#define NINA_ESP_REASON_AUTH_EXPIRE (2)
+#define NINA_ESP_REASON_ASSOC_EXPIRE (4)
+#define NINA_ESP_REASON_NOT_AUTHED (6)
+#define NINA_ESP_REASON_4WAY_HANDSHAKE_TIMEOUT (15)
+#define NINA_ESP_REASON_BEACON_TIMEOUT (200)
+#define NINA_ESP_REASON_NO_AP_FOUND (201)
+#define NINA_ESP_REASON_AUTH_FAIL (202)
+#define NINA_ESP_REASON_ASSOC_FAIL (203)
+#define NINA_ESP_REASON_HANDSHAKE_TIMEOUT (204)
+#define NINA_ESP_REASON_CONNECTION_FAIL (205)
+
typedef enum {
NINA_SEC_INVALID = 0,
NINA_SEC_OPEN,
@@ -59,6 +70,19 @@ typedef enum {
NINA_SOCKET_TYPE_RAW = 3,
} nina_socket_type_t;
+typedef enum {
+ NINA_STATUS_IDLE = 0,
+ NINA_STATUS_NO_SSID_AVAIL = 1,
+ NINA_STATUS_SCAN_COMPLETED = 2,
+ NINA_STATUS_CONNECTED = 3,
+ NINA_STATUS_CONNECT_FAILED = 4,
+ NINA_STATUS_CONNECTION_LOST = 5,
+ NINA_STATUS_DISCONNECTED = 6,
+ NINA_STATUS_AP_LISTENING = 7,
+ NINA_STATUS_AP_CONNECTED = 8,
+ NINA_STATUS_AP_FAILED = 9
+} nina_status_t;
+
typedef struct {
uint8_t ip_addr[NINA_IPV4_ADDR_LEN];
uint8_t subnet_addr[NINA_IPV4_ADDR_LEN];
@@ -85,6 +109,8 @@ typedef int (*nina_scan_callback_t)(nina_scan_result_t *, void *);
int nina_init(void);
int nina_deinit(void);
+int nina_connection_status(void);
+int nina_connection_reason(void);
int nina_connect(const char *ssid, uint8_t security, const char *key, uint16_t channel);
int nina_start_ap(const char *ssid, uint8_t security, const char *key, uint16_t channel);
int nina_disconnect(void);
diff --git a/drivers/nrf24l01/nrf24l01.py b/drivers/nrf24l01/nrf24l01.py
deleted file mode 100644
index 76d55312f856..000000000000
--- a/drivers/nrf24l01/nrf24l01.py
+++ /dev/null
@@ -1,252 +0,0 @@
-"""NRF24L01 driver for MicroPython
-"""
-
-from micropython import const
-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)
-FIFO_STATUS = const(0x17)
-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
-
-# 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)
-
-# 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
-
-# FIFO_STATUS register
-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
-
-
-class NRF24L01:
- def __init__(self, spi, cs, ce, channel=46, payload_size=16):
- assert payload_size <= 32
-
- self.buf = bytearray(1)
-
- # store the pins
- self.spi = spi
- self.cs = cs
- self.ce = ce
-
- # init the SPI bus and pins
- self.init_spi(4000000)
-
- # reset everything
- ce.init(ce.OUT, value=0)
- cs.init(cs.OUT, value=1)
-
- self.payload_size = payload_size
- self.pipe0_read_addr = None
- utime.sleep_ms(5)
-
- # set address width to 5 bytes and check for device present
- self.reg_write(SETUP_AW, 0b11)
- if self.reg_read(SETUP_AW) != 0b11:
- raise OSError("nRF24L01+ Hardware not responding")
-
- # disable dynamic payloads
- self.reg_write(DYNPD, 0)
-
- # auto retransmit delay: 1750us
- # auto retransmit count: 8
- 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
-
- # init CRC
- self.set_crc(2)
-
- # clear status flags
- self.reg_write(STATUS, RX_DR | TX_DS | MAX_RT)
-
- # set channel
- self.set_channel(channel)
-
- # flush buffers
- self.flush_rx()
- self.flush_tx()
-
- def init_spi(self, baudrate):
- try:
- master = self.spi.MASTER
- except AttributeError:
- self.spi.init(baudrate=baudrate, polarity=0, phase=0)
- else:
- self.spi.init(master, baudrate=baudrate, polarity=0, phase=0)
-
- def reg_read(self, reg):
- self.cs(0)
- self.spi.readinto(self.buf, reg)
- self.spi.readinto(self.buf)
- self.cs(1)
- return self.buf[0]
-
- def reg_write_bytes(self, reg, buf):
- self.cs(0)
- self.spi.readinto(self.buf, 0x20 | reg)
- self.spi.write(buf)
- self.cs(1)
- return self.buf[0]
-
- def reg_write(self, reg, value):
- self.cs(0)
- self.spi.readinto(self.buf, 0x20 | reg)
- ret = self.buf[0]
- self.spi.readinto(self.buf, value)
- self.cs(1)
- return ret
-
- def flush_rx(self):
- self.cs(0)
- self.spi.readinto(self.buf, FLUSH_RX)
- self.cs(1)
-
- def flush_tx(self):
- self.cs(0)
- self.spi.readinto(self.buf, FLUSH_TX)
- self.cs(1)
-
- # power is one of POWER_x defines; speed is one of SPEED_x defines
- def set_power_speed(self, power, speed):
- setup = self.reg_read(RF_SETUP) & 0b11010001
- self.reg_write(RF_SETUP, setup | power | speed)
-
- # length in bytes: 0, 1 or 2
- def set_crc(self, length):
- config = self.reg_read(CONFIG) & ~(CRCO | EN_CRC)
- if length == 0:
- pass
- elif length == 1:
- config |= EN_CRC
- else:
- config |= EN_CRC | CRCO
- self.reg_write(CONFIG, config)
-
- def set_channel(self, channel):
- self.reg_write(RF_CH, min(channel, 125))
-
- # address should be a bytes object 5 bytes long
- def open_tx_pipe(self, address):
- assert len(address) == 5
- self.reg_write_bytes(RX_ADDR_P0, address)
- self.reg_write_bytes(TX_ADDR, address)
- self.reg_write(RX_PW_P0, self.payload_size)
-
- # address should be a bytes object 5 bytes long
- # pipe 0 and 1 have 5 byte address
- # pipes 2-5 use same 4 most-significant bytes as pipe 1, plus 1 extra byte
- def open_rx_pipe(self, pipe_id, address):
- assert len(address) == 5
- assert 0 <= pipe_id <= 5
- if pipe_id == 0:
- self.pipe0_read_addr = address
- if pipe_id < 2:
- self.reg_write_bytes(RX_ADDR_P0 + pipe_id, address)
- else:
- self.reg_write(RX_ADDR_P0 + pipe_id, address[0])
- self.reg_write(RX_PW_P0 + pipe_id, self.payload_size)
- self.reg_write(EN_RXADDR, self.reg_read(EN_RXADDR) | (1 << pipe_id))
-
- def start_listening(self):
- self.reg_write(CONFIG, self.reg_read(CONFIG) | PWR_UP | PRIM_RX)
- self.reg_write(STATUS, RX_DR | TX_DS | MAX_RT)
-
- if self.pipe0_read_addr is not None:
- self.reg_write_bytes(RX_ADDR_P0, self.pipe0_read_addr)
-
- self.flush_rx()
- self.flush_tx()
- self.ce(1)
- utime.sleep_us(130)
-
- def stop_listening(self):
- self.ce(0)
- self.flush_tx()
- self.flush_rx()
-
- # returns True if any data available to recv
- def any(self):
- return not bool(self.reg_read(FIFO_STATUS) & RX_EMPTY)
-
- def recv(self):
- # get the data
- self.cs(0)
- self.spi.readinto(self.buf, R_RX_PAYLOAD)
- buf = self.spi.read(self.payload_size)
- self.cs(1)
- # clear RX ready flag
- self.reg_write(STATUS, RX_DR)
-
- return buf
-
- # blocking wait for tx complete
- def send(self, buf, timeout=500):
- self.send_start(buf)
- 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
- if result == 2:
- raise OSError("send failed")
-
- # non-blocking tx
- def send_start(self, buf):
- # power up
- self.reg_write(CONFIG, (self.reg_read(CONFIG) | PWR_UP) & ~PRIM_RX)
- utime.sleep_us(150)
- # send the data
- self.cs(0)
- 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.cs(1)
-
- # enable the chip so it can send the data
- self.ce(1)
- 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
-
- # either finished or failed: get and clear status flags, power down
- status = self.reg_write(STATUS, RX_DR | TX_DS | MAX_RT)
- self.reg_write(CONFIG, self.reg_read(CONFIG) & ~PWR_UP)
- return 1 if status & TX_DS else 2
diff --git a/drivers/nrf24l01/nrf24l01test.py b/drivers/nrf24l01/nrf24l01test.py
deleted file mode 100644
index 56bdb6e26eb9..000000000000
--- a/drivers/nrf24l01/nrf24l01test.py
+++ /dev/null
@@ -1,150 +0,0 @@
-"""Test for nrf24l01 module. Portable between MicroPython targets."""
-
-import usys
-import ustruct as struct
-import utime
-from machine import Pin, SPI
-from nrf24l01 import NRF24L01
-from micropython import const
-
-# Slave pause between receiving data and checking for further packets.
-_RX_POLL_DELAY = const(15)
-# Slave pauses an additional _SLAVE_SEND_DELAY ms after receiving data and before
-# transmitting to allow the (remote) master time to get into receive mode. The
-# master may be a slow device. Value tested with Pyboard, ESP32 and ESP8266.
-_SLAVE_SEND_DELAY = const(10)
-
-if usys.platform == "pyboard":
- cfg = {"spi": 2, "miso": "Y7", "mosi": "Y8", "sck": "Y6", "csn": "Y5", "ce": "Y4"}
-elif usys.platform == "esp8266": # Hardware SPI
- cfg = {"spi": 1, "miso": 12, "mosi": 13, "sck": 14, "csn": 4, "ce": 5}
-elif usys.platform == "esp32": # Software SPI
- cfg = {"spi": -1, "miso": 32, "mosi": 33, "sck": 25, "csn": 26, "ce": 27}
-else:
- raise ValueError("Unsupported platform {}".format(usys.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")
-
-
-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"]))
- nrf = NRF24L01(spi, csn, ce, payload_size=8)
- else:
- nrf = NRF24L01(SPI(cfg["spi"]), csn, ce, payload_size=8)
-
- nrf.open_tx_pipe(pipes[0])
- nrf.open_rx_pipe(1, pipes[1])
- nrf.start_listening()
-
- num_needed = 16
- num_successes = 0
- num_failures = 0
- led_state = 0
-
- 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)
- try:
- nrf.send(struct.pack("ii", millis, led_state))
- except OSError:
- pass
-
- # start listening again
- nrf.start_listening()
-
- # wait for response, with 250ms timeout
- start_time = utime.ticks_ms()
- timeout = False
- while not nrf.any() and not timeout:
- if utime.ticks_diff(utime.ticks_ms(), start_time) > 250:
- timeout = True
-
- if timeout:
- print("failed, response timed out")
- num_failures += 1
-
- else:
- # recv packet
- (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)",
- )
- num_successes += 1
-
- # delay then loop
- utime.sleep_ms(250)
-
- 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"]))
- nrf = NRF24L01(spi, csn, ce, payload_size=8)
- else:
- 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)")
-
- while True:
- if nrf.any():
- while nrf.any():
- buf = nrf.recv()
- millis, led_state = struct.unpack("ii", buf)
- print("received:", millis, led_state)
- for led in leds:
- if led_state & 1:
- led.on()
- else:
- led.off()
- led_state >>= 1
- utime.sleep_ms(_RX_POLL_DELAY)
-
- # Give master time to get into receive mode.
- utime.sleep_ms(_SLAVE_SEND_DELAY)
- nrf.stop_listening()
- try:
- nrf.send(struct.pack("i", millis))
- except OSError:
- pass
- 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")
diff --git a/drivers/onewire/ds18x20.py b/drivers/onewire/ds18x20.py
deleted file mode 100644
index ad2d9f52cdd0..000000000000
--- a/drivers/onewire/ds18x20.py
+++ /dev/null
@@ -1,52 +0,0 @@
-# DS18x20 temperature sensor driver for MicroPython.
-# MIT license; Copyright (c) 2016 Damien P. George
-
-from micropython import const
-
-_CONVERT = const(0x44)
-_RD_SCRATCH = const(0xBE)
-_WR_SCRATCH = const(0x4E)
-
-
-class DS18X20:
- def __init__(self, onewire):
- self.ow = onewire
- self.buf = bytearray(9)
-
- def scan(self):
- return [rom for rom in self.ow.scan() if rom[0] in (0x10, 0x22, 0x28)]
-
- def convert_temp(self):
- self.ow.reset(True)
- self.ow.writebyte(self.ow.SKIP_ROM)
- self.ow.writebyte(_CONVERT)
-
- def read_scratch(self, rom):
- self.ow.reset(True)
- self.ow.select_rom(rom)
- self.ow.writebyte(_RD_SCRATCH)
- self.ow.readinto(self.buf)
- if self.ow.crc8(self.buf):
- raise Exception("CRC error")
- return self.buf
-
- def write_scratch(self, rom, buf):
- self.ow.reset(True)
- self.ow.select_rom(rom)
- self.ow.writebyte(_WR_SCRATCH)
- self.ow.write(buf)
-
- def read_temp(self, rom):
- buf = self.read_scratch(rom)
- if rom[0] == 0x10:
- if buf[1]:
- t = buf[0] >> 1 | 0x80
- 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)
- return t / 16
diff --git a/drivers/onewire/onewire.py b/drivers/onewire/onewire.py
deleted file mode 100644
index 4c6da741c74c..000000000000
--- a/drivers/onewire/onewire.py
+++ /dev/null
@@ -1,92 +0,0 @@
-# 1-Wire driver for MicroPython
-# MIT license; Copyright (c) 2016 Damien P. George
-
-import _onewire as _ow
-
-
-class OneWireError(Exception):
- pass
-
-
-class OneWire:
- SEARCH_ROM = 0xF0
- MATCH_ROM = 0x55
- SKIP_ROM = 0xCC
-
- def __init__(self, pin):
- self.pin = pin
- self.pin.init(pin.OPEN_DRAIN, pin.PULL_UP)
-
- def reset(self, required=False):
- reset = _ow.reset(self.pin)
- if required and not reset:
- raise OneWireError
- return reset
-
- def readbit(self):
- return _ow.readbit(self.pin)
-
- def readbyte(self):
- return _ow.readbyte(self.pin)
-
- def readinto(self, buf):
- for i in range(len(buf)):
- buf[i] = _ow.readbyte(self.pin)
-
- def writebit(self, value):
- return _ow.writebit(self.pin, value)
-
- def writebyte(self, value):
- return _ow.writebyte(self.pin, value)
-
- def write(self, buf):
- for b in buf:
- _ow.writebyte(self.pin, b)
-
- def select_rom(self, rom):
- self.reset()
- self.writebyte(self.MATCH_ROM)
- self.write(rom)
-
- def scan(self):
- devices = []
- diff = 65
- rom = False
- for i in range(0xFF):
- rom, diff = self._search_rom(rom, diff)
- if rom:
- devices += [rom]
- if diff == 0:
- break
- return devices
-
- def _search_rom(self, l_rom, diff):
- if not self.reset():
- return None, 0
- self.writebyte(self.SEARCH_ROM)
- if not l_rom:
- l_rom = bytearray(8)
- rom = bytearray(8)
- next_diff = 0
- i = 64
- for byte in range(8):
- r_b = 0
- 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
- return None, 0
- else:
- 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
- self.writebit(b)
- if b:
- r_b |= 1 << bit
- i -= 1
- rom[byte] = r_b
- return rom, next_diff
-
- def crc8(self, data):
- return _ow.crc8(data)
diff --git a/drivers/sdcard/sdcard.py b/drivers/sdcard/sdcard.py
deleted file mode 100644
index f4520acbb537..000000000000
--- a/drivers/sdcard/sdcard.py
+++ /dev/null
@@ -1,298 +0,0 @@
-"""
-MicroPython driver for SD cards using SPI bus.
-
-Requires an SPI bus and a CS pin. Provides readblocks and writeblocks
-methods so the device can be mounted as a filesystem.
-
-Example usage on pyboard:
-
- import pyb, sdcard, os
- sd = sdcard.SDCard(pyb.SPI(1), pyb.Pin.board.X5)
- pyb.mount(sd, '/sd2')
- os.listdir('/')
-
-Example usage on ESP8266:
-
- import machine, sdcard, os
- sd = sdcard.SDCard(machine.SPI(1), machine.Pin(15))
- os.mount(sd, '/sd')
- os.listdir('/')
-
-"""
-
-from micropython import const
-import time
-
-
-_CMD_TIMEOUT = const(100)
-
-_R1_IDLE_STATE = const(1 << 0)
-# R1_ERASE_RESET = const(1 << 1)
-_R1_ILLEGAL_COMMAND = const(1 << 2)
-# R1_COM_CRC_ERROR = const(1 << 3)
-# R1_ERASE_SEQUENCE_ERROR = const(1 << 4)
-# R1_ADDRESS_ERROR = const(1 << 5)
-# R1_PARAMETER_ERROR = const(1 << 6)
-_TOKEN_CMD25 = const(0xFC)
-_TOKEN_STOP_TRAN = const(0xFD)
-_TOKEN_DATA = const(0xFE)
-
-
-class SDCard:
- def __init__(self, spi, cs, baudrate=1320000):
- self.spi = spi
- self.cs = cs
-
- self.cmdbuf = bytearray(6)
- self.dummybuf = bytearray(512)
- self.tokenbuf = bytearray(1)
- for i in range(512):
- self.dummybuf[i] = 0xFF
- self.dummybuf_memoryview = memoryview(self.dummybuf)
-
- # initialise the card
- self.init_card(baudrate)
-
- def init_spi(self, baudrate):
- try:
- master = self.spi.MASTER
- except AttributeError:
- # on ESP8266
- self.spi.init(baudrate=baudrate, phase=0, polarity=0)
- else:
- # on pyboard
- self.spi.init(master, baudrate=baudrate, phase=0, polarity=0)
-
- def init_card(self, baudrate):
-
- # init CS pin
- self.cs.init(self.cs.OUT, value=1)
-
- # init SPI bus; use low data rate for initialisation
- self.init_spi(100000)
-
- # clock card at least 100 cycles with cs high
- for i in range(16):
- self.spi.write(b"\xff")
-
- # CMD0: init card; should return _R1_IDLE_STATE (allow 5 attempts)
- for _ in range(5):
- if self.cmd(0, 0, 0x95) == _R1_IDLE_STATE:
- break
- else:
- raise OSError("no SD card")
-
- # CMD8: determine card version
- r = self.cmd(8, 0x01AA, 0x87, 4)
- if r == _R1_IDLE_STATE:
- self.init_card_v2()
- elif r == (_R1_IDLE_STATE | _R1_ILLEGAL_COMMAND):
- self.init_card_v1()
- else:
- raise OSError("couldn't determine SD card version")
-
- # get the number of sectors
- # CMD9: response R2 (R1 byte + 16-byte block read)
- if self.cmd(9, 0, 0, 0, False) != 0:
- raise OSError("no response from SD card")
- csd = bytearray(16)
- self.readinto(csd)
- if csd[0] & 0xC0 == 0x40: # 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) << 10 | csd[7] << 2 | csd[8] >> 6
- c_size_mult = (csd[9] & 0b11) << 1 | csd[10] >> 7
- read_bl_len = csd[5] & 0b1111
- capacity = (c_size + 1) * (2 ** (c_size_mult + 2)) * (2**read_bl_len)
- self.sectors = capacity // 512
- else:
- raise OSError("SD card CSD format not supported")
- # print('sectors', self.sectors)
-
- # CMD16: set block length to 512 bytes
- if self.cmd(16, 512, 0) != 0:
- raise OSError("can't set 512 block size")
-
- # set to high data rate now that it's initialised
- self.init_spi(baudrate)
-
- def init_card_v1(self):
- for i in range(_CMD_TIMEOUT):
- self.cmd(55, 0, 0)
- if self.cmd(41, 0, 0) == 0:
- # SDSC card, uses byte addressing in read/write/erase commands
- self.cdv = 512
- # print("[SDCard] v1 card")
- return
- raise OSError("timeout waiting for v1 card")
-
- def init_card_v2(self):
- for i in range(_CMD_TIMEOUT):
- time.sleep_ms(50)
- self.cmd(58, 0, 0, 4)
- self.cmd(55, 0, 0)
- if self.cmd(41, 0x40000000, 0) == 0:
- self.cmd(58, 0, 0, -4) # 4-byte response, negative means keep the first byte
- ocr = self.tokenbuf[0] # get first byte of response, which is OCR
- if not ocr & 0x40:
- # SDSC card, uses byte addressing in read/write/erase commands
- self.cdv = 512
- else:
- # SDHC/SDXC card, uses block addressing in read/write/erase commands
- self.cdv = 1
- # print("[SDCard] v2 card")
- return
- raise OSError("timeout waiting for v2 card")
-
- def cmd(self, cmd, arg, crc, final=0, release=True, skip1=False):
- self.cs(0)
-
- # create and send the command
- buf = self.cmdbuf
- buf[0] = 0x40 | cmd
- buf[1] = arg >> 24
- buf[2] = arg >> 16
- buf[3] = arg >> 8
- buf[4] = arg
- buf[5] = crc
- self.spi.write(buf)
-
- if skip1:
- 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)
- response = self.tokenbuf[0]
- if not (response & 0x80):
- # this could be a big-endian integer that we are getting here
- # if final<0 then store the first byte to tokenbuf and discard the rest
- if final < 0:
- self.spi.readinto(self.tokenbuf, 0xFF)
- final = -1 - final
- for j in range(final):
- self.spi.write(b"\xff")
- if release:
- self.cs(1)
- self.spi.write(b"\xff")
- return response
-
- # timeout
- self.cs(1)
- self.spi.write(b"\xff")
- return -1
-
- def readinto(self, buf):
- self.cs(0)
-
- # read until start byte (0xff)
- for i in range(_CMD_TIMEOUT):
- self.spi.readinto(self.tokenbuf, 0xFF)
- if self.tokenbuf[0] == _TOKEN_DATA:
- break
- time.sleep_ms(1)
- 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)]
- self.spi.write_readinto(mv, buf)
-
- # read checksum
- self.spi.write(b"\xff")
- self.spi.write(b"\xff")
-
- self.cs(1)
- self.spi.write(b"\xff")
-
- def write(self, token, buf):
- self.cs(0)
-
- # send: start of block, data, checksum
- self.spi.read(1, token)
- self.spi.write(buf)
- self.spi.write(b"\xff")
- self.spi.write(b"\xff")
-
- # check the response
- if (self.spi.read(1, 0xFF)[0] & 0x1F) != 0x05:
- self.cs(1)
- self.spi.write(b"\xff")
- return
-
- # wait for write to finish
- while self.spi.read(1, 0xFF)[0] == 0:
- pass
-
- self.cs(1)
- self.spi.write(b"\xff")
-
- def write_token(self, token):
- self.cs(0)
- self.spi.read(1, token)
- self.spi.write(b"\xff")
- # wait for write to finish
- while self.spi.read(1, 0xFF)[0] == 0x00:
- pass
-
- self.cs(1)
- 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"
- if nblocks == 1:
- # CMD17: set read address for single block
- 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, 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
-
- def writeblocks(self, block_num, buf):
- nblocks, err = divmod(len(buf), 512)
- assert nblocks and not err, "Buffer length is invalid"
- if nblocks == 1:
- # CMD24: set write address for single block
- if self.cmd(24, block_num * self.cdv, 0) != 0:
- 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
- # send the data
- offset = 0
- mv = memoryview(buf)
- while nblocks:
- self.write(_TOKEN_CMD25, mv[offset : offset + 512])
- offset += 512
- nblocks -= 1
- self.write_token(_TOKEN_STOP_TRAN)
-
- def ioctl(self, op, arg):
- if op == 4: # get number of blocks
- return self.sectors
- if op == 5: # get block size in bytes
- return 512
diff --git a/drivers/sdcard/sdtest.py b/drivers/sdcard/sdtest.py
deleted file mode 100644
index 018ef7c64aa1..000000000000
--- a/drivers/sdcard/sdtest.py
+++ /dev/null
@@ -1,61 +0,0 @@
-# Test for sdcard block protocol
-# Peter hinch 30th Jan 2016
-import os, sdcard, machine
-
-
-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:
- n = f.write(lines)
- print(n, "bytes written")
- n = f.write(short)
- print(n, "bytes written")
- n = f.write(lines)
- print(n, "bytes written")
-
- with open(fn, "r") as f:
- result1 = f.read()
- print(len(result1), "bytes read")
-
- 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")
-
- with open(fn, "r") as f:
- result2 = f.read()
- print(len(result2), "bytes read")
-
- os.umount("/fc")
-
- print()
- print("Verifying data read back")
- success = True
- if result1 == "".join((lines, short, lines)):
- print("Large file Pass")
- else:
- print("Large file Fail")
- success = False
- if result2 == short:
- print("Small file Pass")
- else:
- print("Small file Fail")
- success = False
- print()
- print("Tests", "passed" if success else "failed")
diff --git a/drivers/wiznet5k/README.md b/drivers/wiznet5k/README.md
deleted file mode 100644
index 88f25a2b8dbc..000000000000
--- a/drivers/wiznet5k/README.md
+++ /dev/null
@@ -1,6 +0,0 @@
-This is the driver for the WIZnet5x00 series of Ethernet controllers.
-
-Adapted for MicroPython.
-
-Original source: https://github.com/Wiznet/W5500_EVB/tree/master/ioLibrary
-Taken on: 30 August 2014
diff --git a/drivers/wiznet5k/ethernet/socket.c b/drivers/wiznet5k/ethernet/socket.c
deleted file mode 100644
index 3ffda3a722df..000000000000
--- a/drivers/wiznet5k/ethernet/socket.c
+++ /dev/null
@@ -1,725 +0,0 @@
-//*****************************************************************************
-//
-//! \file socket.c
-//! \brief SOCKET APIs Implements file.
-//! \details SOCKET APIs like as Berkeley Socket APIs.
-//! \version 1.0.3
-//! \date 2013/10/21
-//! \par Revision history
-//! <2014/05/01> V1.0.3. Refer to M20140501
-//! 1. Implicit type casting -> Explicit type casting.
-//! 2. replace 0x01 with PACK_REMAINED in recvfrom()
-//! 3. Validation a destination ip in connect() & sendto():
-//! It occurs a fatal error on converting unint32 address if uint8* addr parameter is not aligned by 4byte address.
-//! Copy 4 byte addr value into temporary uint32 variable and then compares it.
-//! <2013/12/20> V1.0.2 Refer to M20131220
-//! Remove Warning.
-//! <2013/11/04> V1.0.1 2nd Release. Refer to "20131104".
-//! In sendto(), Add to clear timeout interrupt status (Sn_IR_TIMEOUT)
-//! <2013/10/21> 1st Release
-//! \author MidnightCow
-//! \copyright
-//!
-//! Copyright (c) 2013, WIZnet Co., LTD.
-//! 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 the 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 OWNER 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.
-//
-//*****************************************************************************
-
-#include
-
-#include "py/mpthread.h"
-#include "socket.h"
-
-#define SOCK_ANY_PORT_NUM 0xC000;
-
-static uint16_t sock_any_port = SOCK_ANY_PORT_NUM;
-static uint16_t sock_io_mode = 0;
-static uint16_t sock_is_sending = 0;
-static uint16_t sock_remained_size[_WIZCHIP_SOCK_NUM_] = {0,0,};
-static uint8_t sock_pack_info[_WIZCHIP_SOCK_NUM_] = {0,};
-
-#if _WIZCHIP_ == 5200
- static uint16_t sock_next_rd[_WIZCHIP_SOCK_NUM_] ={0,};
-#endif
-
-#define CHECK_SOCKNUM() \
- do{ \
- if(sn > _WIZCHIP_SOCK_NUM_) return SOCKERR_SOCKNUM; \
- }while(0); \
-
-#define CHECK_SOCKMODE(mode) \
- do{ \
- if((getSn_MR(sn) & 0x0F) != mode) return SOCKERR_SOCKMODE; \
- }while(0); \
-
-#define CHECK_SOCKINIT() \
- do{ \
- if((getSn_SR(sn) != SOCK_INIT)) return SOCKERR_SOCKINIT; \
- }while(0); \
-
-#define CHECK_SOCKDATA() \
- do{ \
- if(len == 0) return SOCKERR_DATALEN; \
- }while(0); \
-
-void WIZCHIP_EXPORT(socket_reset)(void) {
- sock_any_port = SOCK_ANY_PORT_NUM;
- sock_io_mode = 0;
- sock_is_sending = 0;
- /*
- memset(sock_remained_size, 0, _WIZCHIP_SOCK_NUM_ * sizeof(uint16_t));
- memset(sock_pack_info, 0, _WIZCHIP_SOCK_NUM_ * sizeof(uint8_t));
- */
-
-#if _WIZCHIP_ == 5200
- memset(sock_next_rd, 0, _WIZCHIP_SOCK_NUM_ * sizeof(uint16_t));
-#endif
-}
-
-int8_t WIZCHIP_EXPORT(socket)(uint8_t sn, uint8_t protocol, uint16_t port, uint8_t flag)
-{
- CHECK_SOCKNUM();
- switch(protocol)
- {
- case Sn_MR_TCP :
- case Sn_MR_UDP :
- case Sn_MR_MACRAW :
- break;
- #if ( _WIZCHIP_ < 5200 )
- case Sn_MR_IPRAW :
- case Sn_MR_PPPoE :
- break;
- #endif
- default :
- return SOCKERR_SOCKMODE;
- }
- if((flag & 0x06) != 0) return SOCKERR_SOCKFLAG;
-#if _WIZCHIP_ == 5200
- if(flag & 0x10) return SOCKERR_SOCKFLAG;
-#endif
-
- if(flag != 0)
- {
- switch(protocol)
- {
- case Sn_MR_TCP:
- if((flag & (SF_TCP_NODELAY|SF_IO_NONBLOCK))==0) return SOCKERR_SOCKFLAG;
- break;
- case Sn_MR_UDP:
- if(flag & SF_IGMP_VER2)
- {
- if((flag & SF_MULTI_ENABLE)==0) return SOCKERR_SOCKFLAG;
- }
- #if _WIZCHIP_ == 5500
- if(flag & SF_UNI_BLOCK)
- {
- if((flag & SF_MULTI_ENABLE) == 0) return SOCKERR_SOCKFLAG;
- }
- #endif
- break;
- default:
- break;
- }
- }
- WIZCHIP_EXPORT(close)(sn);
- setSn_MR(sn, (protocol | (flag & 0xF0)));
- if(!port)
- {
- port = sock_any_port++;
- if(sock_any_port == 0xFFF0) sock_any_port = SOCK_ANY_PORT_NUM;
- }
- setSn_PORT(sn,port);
- setSn_CR(sn,Sn_CR_OPEN);
- while(getSn_CR(sn));
- sock_io_mode |= ((flag & SF_IO_NONBLOCK) << sn);
- sock_is_sending &= ~(1< freesize) len = freesize; // check size not to exceed MAX size.
- while(1)
- {
- freesize = getSn_TX_FSR(sn);
- tmp = getSn_SR(sn);
- if ((tmp != SOCK_ESTABLISHED) && (tmp != SOCK_CLOSE_WAIT))
- {
- WIZCHIP_EXPORT(close)(sn);
- return SOCKERR_SOCKSTATUS;
- }
- if( (sock_io_mode & (1< freesize) ) return SOCK_BUSY;
- if(len <= freesize) break;
- MICROPY_THREAD_YIELD();
- }
- wiz_send_data(sn, buf, len);
- #if _WIZCHIP_ == 5200
- sock_next_rd[sn] = getSn_TX_RD(sn) + len;
- #endif
- setSn_CR(sn,Sn_CR_SEND);
- /* wait to process the command... */
- while(getSn_CR(sn));
- sock_is_sending |= (1 << sn);
- return len;
-}
-
-
-int32_t WIZCHIP_EXPORT(recv)(uint8_t sn, uint8_t * buf, uint16_t len)
-{
- uint8_t tmp = 0;
- uint16_t recvsize = 0;
- CHECK_SOCKNUM();
- CHECK_SOCKMODE(Sn_MR_TCP);
- CHECK_SOCKDATA();
-
- recvsize = getSn_RxMAX(sn);
- if(recvsize < len) len = recvsize;
- while(1)
- {
- recvsize = getSn_RX_RSR(sn);
- tmp = getSn_SR(sn);
- if (tmp != SOCK_ESTABLISHED)
- {
- if(tmp == SOCK_CLOSE_WAIT)
- {
- if(recvsize != 0) break;
- else if(getSn_TX_FSR(sn) == getSn_TxMAX(sn))
- {
- // dpgeorge: Getting here seems to be an orderly shutdown of the
- // socket, and trying to get POSIX behaviour we return 0 because:
- // "If no messages are available to be received and the peer has per‐
- // formed an orderly shutdown, recv() shall return 0".
- // TODO this return value clashes with SOCK_BUSY in non-blocking mode.
- WIZCHIP_EXPORT(close)(sn);
- return 0;
- }
- }
- else
- {
- WIZCHIP_EXPORT(close)(sn);
- return SOCKERR_SOCKSTATUS;
- }
- }
- if((sock_io_mode & (1< freesize) len = freesize; // check size not to exceed MAX size.
- while(1)
- {
- freesize = getSn_TX_FSR(sn);
- if(getSn_SR(sn) == SOCK_CLOSED) return SOCKERR_SOCKCLOSED;
- if( (sock_io_mode & (1< freesize) ) return SOCK_BUSY;
- if(len <= freesize) break;
- MICROPY_THREAD_YIELD();
- };
- wiz_send_data(sn, buf, len);
-
- #if _WIZCHIP_ == 5200 // for W5200 ARP errata
- setSUBR(wizchip_getsubn());
- #endif
-
- setSn_CR(sn,Sn_CR_SEND);
- /* wait to process the command... */
- while(getSn_CR(sn));
- while(1)
- {
- tmp = getSn_IR(sn);
- if(tmp & Sn_IR_SENDOK)
- {
- setSn_IR(sn, Sn_IR_SENDOK);
- break;
- }
- //M:20131104
- //else if(tmp & Sn_IR_TIMEOUT) return SOCKERR_TIMEOUT;
- else if(tmp & Sn_IR_TIMEOUT)
- {
- setSn_IR(sn, Sn_IR_TIMEOUT);
- #if _WIZCHIP_ == 5200 // for W5200 ARP errata
- setSUBR((uint8_t*)"\x00\x00\x00\x00");
- #endif
- return SOCKERR_TIMEOUT;
- }
- ////////////
- MICROPY_THREAD_YIELD();
- }
- #if _WIZCHIP_ == 5200 // for W5200 ARP errata
- setSUBR((uint8_t*)"\x00\x00\x00\x00");
- #endif
- return len;
-}
-
-
-
-int32_t WIZCHIP_EXPORT(recvfrom)(uint8_t sn, uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t *port)
-{
- uint8_t mr;
- uint8_t head[8];
- uint16_t pack_len=0;
-
- CHECK_SOCKNUM();
- //CHECK_SOCKMODE(Sn_MR_UDP);
- switch((mr=getSn_MR(sn)) & 0x0F)
- {
- case Sn_MR_UDP:
- case Sn_MR_MACRAW:
- break;
- #if ( _WIZCHIP_ < 5200 )
- case Sn_MR_IPRAW:
- case Sn_MR_PPPoE:
- break;
- #endif
- default:
- return SOCKERR_SOCKMODE;
- }
- CHECK_SOCKDATA();
- if(sock_remained_size[sn] == 0)
- {
- while(1)
- {
- pack_len = getSn_RX_RSR(sn);
- if(getSn_SR(sn) == SOCK_CLOSED) return SOCKERR_SOCKCLOSED;
- if( (sock_io_mode & (1< 1514)
- {
- WIZCHIP_EXPORT(close)(sn);
- return SOCKFATAL_PACKLEN;
- }
- sock_pack_info[sn] = PACK_FIRST;
- }
- if(len < sock_remained_size[sn]) pack_len = len;
- else pack_len = sock_remained_size[sn];
- wiz_recv_data(sn,buf,pack_len);
- break;
- #if ( _WIZCHIP_ < 5200 )
- case Sn_MR_IPRAW:
- if(sock_remained_size[sn] == 0)
- {
- wiz_recv_data(sn, head, 6);
- setSn_CR(sn,Sn_CR_RECV);
- while(getSn_CR(sn));
- addr[0] = head[0];
- addr[1] = head[1];
- addr[2] = head[2];
- addr[3] = head[3];
- sock_remained_size[sn] = head[4];
- sock_remaiend_size[sn] = (sock_remained_size[sn] << 8) + head[5];
- sock_pack_info[sn] = PACK_FIRST;
- }
- //
- // Need to packet length check
- //
- if(len < sock_remained_size[sn]) pack_len = len;
- else pack_len = sock_remained_size[sn];
- wiz_recv_data(sn, buf, pack_len); // data copy.
- break;
- #endif
- default:
- wiz_recv_ignore(sn, pack_len); // data copy.
- sock_remained_size[sn] = pack_len;
- break;
- }
- setSn_CR(sn,Sn_CR_RECV);
- /* wait to process the command... */
- while(getSn_CR(sn)) ;
- sock_remained_size[sn] -= pack_len;
- //M20140501 : replace 0x01 with PACK_REMAINED
- //if(sock_remained_size[sn] != 0) sock_pack_info[sn] |= 0x01;
- if(sock_remained_size[sn] != 0) sock_pack_info[sn] |= PACK_REMAINED;
- //
- return pack_len;
-}
-
-
-int8_t WIZCHIP_EXPORT(ctlsocket)(uint8_t sn, ctlsock_type cstype, void* arg)
-{
- uint8_t tmp = 0;
- CHECK_SOCKNUM();
- switch(cstype)
- {
- case CS_SET_IOMODE:
- tmp = *((uint8_t*)arg);
- if(tmp == SOCK_IO_NONBLOCK) sock_io_mode |= (1< explict type casting
- //*((uint8_t*)arg) = (sock_io_mode >> sn) & 0x0001;
- *((uint8_t*)arg) = (uint8_t)((sock_io_mode >> sn) & 0x0001);
- //
- break;
- case CS_GET_MAXTXBUF:
- *((uint16_t*)arg) = getSn_TxMAX(sn);
- break;
- case CS_GET_MAXRXBUF:
- *((uint16_t*)arg) = getSn_RxMAX(sn);
- break;
- case CS_CLR_INTERRUPT:
- if( (*(uint8_t*)arg) > SIK_ALL) return SOCKERR_ARG;
- setSn_IR(sn,*(uint8_t*)arg);
- break;
- case CS_GET_INTERRUPT:
- *((uint8_t*)arg) = getSn_IR(sn);
- break;
- case CS_SET_INTMASK:
- if( (*(uint8_t*)arg) > SIK_ALL) return SOCKERR_ARG;
- setSn_IMR(sn,*(uint8_t*)arg);
- break;
- case CS_GET_INTMASK:
- *((uint8_t*)arg) = getSn_IMR(sn);
- default:
- return SOCKERR_ARG;
- }
- return SOCK_OK;
-}
-
-int8_t WIZCHIP_EXPORT(setsockopt)(uint8_t sn, sockopt_type sotype, void* arg)
-{
- // M20131220 : Remove warning
- //uint8_t tmp;
- CHECK_SOCKNUM();
- switch(sotype)
- {
- case SO_TTL:
- setSn_TTL(sn,*(uint8_t*)arg);
- break;
- case SO_TOS:
- setSn_TOS(sn,*(uint8_t*)arg);
- break;
- case SO_MSS:
- setSn_MSSR(sn,*(uint16_t*)arg);
- break;
- case SO_DESTIP:
- setSn_DIPR(sn, (uint8_t*)arg);
- break;
- case SO_DESTPORT:
- setSn_DPORT(sn, *(uint16_t*)arg);
- break;
-#if _WIZCHIP_ != 5100
- case SO_KEEPALIVESEND:
- CHECK_SOCKMODE(Sn_MR_TCP);
- #if _WIZCHIP_ > 5200
- if(getSn_KPALVTR(sn) != 0) return SOCKERR_SOCKOPT;
- #endif
- setSn_CR(sn,Sn_CR_SEND_KEEP);
- while(getSn_CR(sn) != 0)
- {
- // M20131220
- //if ((tmp = getSn_IR(sn)) & Sn_IR_TIMEOUT)
- if (getSn_IR(sn) & Sn_IR_TIMEOUT)
- {
- setSn_IR(sn, Sn_IR_TIMEOUT);
- return SOCKERR_TIMEOUT;
- }
- }
- break;
- #if _WIZCHIP_ > 5200
- case SO_KEEPALIVEAUTO:
- CHECK_SOCKMODE(Sn_MR_TCP);
- setSn_KPALVTR(sn,*(uint8_t*)arg);
- break;
- #endif
-#endif
- default:
- return SOCKERR_ARG;
- }
- return SOCK_OK;
-}
-
-int8_t WIZCHIP_EXPORT(getsockopt)(uint8_t sn, sockopt_type sotype, void* arg)
-{
- CHECK_SOCKNUM();
- switch(sotype)
- {
- case SO_FLAG:
- *(uint8_t*)arg = getSn_MR(sn) & 0xF0;
- break;
- case SO_TTL:
- *(uint8_t*) arg = getSn_TTL(sn);
- break;
- case SO_TOS:
- *(uint8_t*) arg = getSn_TOS(sn);
- break;
- case SO_MSS:
- *(uint8_t*) arg = getSn_MSSR(sn);
- case SO_DESTIP:
- getSn_DIPR(sn, (uint8_t*)arg);
- break;
- case SO_DESTPORT:
- *(uint16_t*) arg = getSn_DPORT(sn);
- break;
- #if _WIZCHIP_ > 5200
- case SO_KEEPALIVEAUTO:
- CHECK_SOCKMODE(Sn_MR_TCP);
- *(uint16_t*) arg = getSn_KPALVTR(sn);
- break;
- #endif
- case SO_SENDBUF:
- *(uint16_t*) arg = getSn_TX_FSR(sn);
- case SO_RECVBUF:
- *(uint16_t*) arg = getSn_RX_RSR(sn);
- case SO_STATUS:
- *(uint8_t*) arg = getSn_SR(sn);
- break;
- case SO_REMAINSIZE:
- if(getSn_MR(sn) == Sn_MR_TCP)
- *(uint16_t*)arg = getSn_RX_RSR(sn);
- else
- *(uint16_t*)arg = sock_remained_size[sn];
- break;
- case SO_PACKINFO:
- CHECK_SOCKMODE(Sn_MR_TCP);
- *(uint8_t*)arg = sock_pack_info[sn];
- break;
- default:
- return SOCKERR_SOCKOPT;
- }
- return SOCK_OK;
-}
diff --git a/drivers/wiznet5k/ethernet/socket.h b/drivers/wiznet5k/ethernet/socket.h
deleted file mode 100644
index 2f03a34eba01..000000000000
--- a/drivers/wiznet5k/ethernet/socket.h
+++ /dev/null
@@ -1,472 +0,0 @@
-//*****************************************************************************
-//
-//! \file socket.h
-//! \brief SOCKET APIs Header file.
-//! \details SOCKET APIs like as berkeley socket api.
-//! \version 1.0.2
-//! \date 2013/10/21
-//! \par Revision history
-//! <2014/05/01> V1.0.2. Refer to M20140501
-//! 1. Modify the comment : SO_REMAINED -> PACK_REMAINED
-//! 2. Add the comment as zero byte udp data reception in getsockopt().
-//! <2013/10/21> 1st Release
-//! \author MidnightCow
-//! \copyright
-//!
-//! Copyright (c) 2013, WIZnet Co., LTD.
-//! 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 the 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 OWNER 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.
-//
-//*****************************************************************************
-/**
- * @defgroup WIZnet_socket_APIs 1. WIZnet socket APIs
- * @brief WIZnet socket APIs are based on Berkeley socket APIs, thus it has much similar name and interface.
- * But there is a little bit of difference.
- * @details
- * Comparison between WIZnet and Berkeley SOCKET APIs
- *
- *
API
WIZnet
Berkeley
- *
socket()
O
O
- *
bind()
X
O
- *
listen()
O
O
- *
connect()
O
O
- *
accept()
X
O
- *
recv()
O
O
- *
send()
O
O
- *
recvfrom()
O
O
- *
sendto()
O
O
- *
closesocket()
O close() & disconnect()
O
- *
- * There are @b bind() and @b accept() functions in @b Berkeley SOCKET API but,
- * not in @b WIZnet SOCKET API. Because socket() of WIZnet is not only creating a SOCKET but also binding a local port number,
- * and listen() of WIZnet is not only listening to connection request from client but also accepting the connection request. \n
- * When you program "TCP SERVER" with Berkeley SOCKET API, you can use only one listen port.
- * When the listen SOCKET accepts a connection request from a client, it keeps listening.
- * After accepting the connection request, a new SOCKET is created and the new SOCKET is used in communication with the client. \n
- * Following figure shows network flow diagram by Berkeley SOCKET API.
- * @image html Berkeley_SOCKET.jpg ""
- * But, When you program "TCP SERVER" with WIZnet SOCKET API, you can use as many as 8 listen SOCKET with same port number. \n
- * Because there's no accept() in WIZnet SOCKET APIs, when the listen SOCKET accepts a connection request from a client,
- * it is changed in order to communicate with the client.
- * And the changed SOCKET is not listening any more and is dedicated for communicating with the client. \n
- * If there're many listen SOCKET with same listen port number and a client requests a connection,
- * the SOCKET which has the smallest SOCKET number accepts the request and is changed as communication SOCKET. \n
- * Following figure shows network flow diagram by WIZnet SOCKET API.
- * @image html WIZnet_SOCKET.jpg ""
- */
-#ifndef _WIZCHIP_SOCKET_H_
-#define _WIZCHIP_SOCKET_H_
-
-// use this macro for exported names to avoid name clashes
-#define WIZCHIP_EXPORT(name) wizchip_ ## name
-
-#include "wizchip_conf.h"
-
-#define SOCKET uint8_t ///< SOCKET type define for legacy driver
-
-#define SOCK_OK 1 ///< Result is OK about socket process.
-#define SOCK_BUSY 0 ///< Socket is busy on processing the operation. Valid only Non-block IO Mode.
-#define SOCK_FATAL -1000 ///< Result is fatal error about socket process.
-
-#define SOCK_ERROR 0
-#define SOCKERR_SOCKNUM (SOCK_ERROR - 1) ///< Invalid socket number
-#define SOCKERR_SOCKOPT (SOCK_ERROR - 2) ///< Invalid socket option
-#define SOCKERR_SOCKINIT (SOCK_ERROR - 3) ///< Socket is not initialized
-#define SOCKERR_SOCKCLOSED (SOCK_ERROR - 4) ///< Socket unexpectedly closed.
-#define SOCKERR_SOCKMODE (SOCK_ERROR - 5) ///< Invalid socket mode for socket operation.
-#define SOCKERR_SOCKFLAG (SOCK_ERROR - 6) ///< Invalid socket flag
-#define SOCKERR_SOCKSTATUS (SOCK_ERROR - 7) ///< Invalid socket status for socket operation.
-#define SOCKERR_ARG (SOCK_ERROR - 10) ///< Invalid argument.
-#define SOCKERR_PORTZERO (SOCK_ERROR - 11) ///< Port number is zero
-#define SOCKERR_IPINVALID (SOCK_ERROR - 12) ///< Invalid IP address
-#define SOCKERR_TIMEOUT (SOCK_ERROR - 13) ///< Timeout occurred
-#define SOCKERR_DATALEN (SOCK_ERROR - 14) ///< Data length is zero or greater than buffer max size.
-#define SOCKERR_BUFFER (SOCK_ERROR - 15) ///< Socket buffer is not enough for data communication.
-
-#define SOCKFATAL_PACKLEN (SOCK_FATAL - 1) ///< Invalid packet length. Fatal Error.
-
-/*
- * SOCKET FLAG
- */
-#define SF_ETHER_OWN (Sn_MR_MFEN) ///< In \ref Sn_MR_MACRAW, Receive only the packet as broadcast, multicast and own packet
-#define SF_IGMP_VER2 (Sn_MR_MC) ///< In \ref Sn_MR_UDP with \ref SF_MULTI_ENABLE, Select IGMP version 2.
-#define SF_TCP_NODELAY (Sn_MR_ND) ///< In \ref Sn_MR_TCP, Use to nodelayed ack.
-#define SF_MULTI_ENABLE (Sn_MR_MULTI) ///< In \ref Sn_MR_UDP, Enable multicast mode.
-
-#if _WIZCHIP_ == 5500
- #define SF_BROAD_BLOCK (Sn_MR_BCASTB) ///< In \ref Sn_MR_UDP or \ref Sn_MR_MACRAW, Block broadcast packet. Valid only in W5500
- #define SF_MULTI_BLOCK (Sn_MR_MMB) ///< In \ref Sn_MR_MACRAW, Block multicast packet. Valid only in W5500
- #define SF_IPv6_BLOCK (Sn_MR_MIP6B) ///< In \ref Sn_MR_MACRAW, Block IPv6 packet. Valid only in W5500
- #define SF_UNI_BLOCK (Sn_MR_UCASTB) ///< In \ref Sn_MR_UDP with \ref SF_MULTI_ENABLE. Valid only in W5500
-#endif
-
-#define SF_IO_NONBLOCK 0x01 ///< Socket nonblock io mode. It used parameter in \ref socket().
-
-/*
- * UDP & MACRAW Packet Infomation
- */
-#define PACK_FIRST 0x80 ///< In Non-TCP packet, It indicates to start receiving a packet.
-#define PACK_REMAINED 0x01 ///< In Non-TCP packet, It indicates to remain a packet to be received.
-#define PACK_COMPLETED 0x00 ///< In Non-TCP packet, It indicates to complete to receive a packet.
-
-// resets all global state associated with the socket interface
-void WIZCHIP_EXPORT(socket_reset)(void);
-
-/**
- * @ingroup WIZnet_socket_APIs
- * @brief Open a socket.
- * @details Initializes the socket with 'sn' passed as parameter and open.
- *
- * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_.
- * @param protocol Protocol type to operate such as TCP, UDP and MACRAW.
- * @param port Port number to be bined.
- * @param flag Socket flags as \ref SF_ETHER_OWN, \ref SF_IGMP_VER2, \ref SF_TCP_NODELAY, \ref SF_MULTI_ENABLE, \ref SF_IO_NONBLOCK and so on.\n
- * Valid flags only in W5500 : @ref SF_BROAD_BLOCK, @ref SF_MULTI_BLOCK, @ref SF_IPv6_BLOCK, and @ref SF_UNI_BLOCK.
- * @sa Sn_MR
- *
- * @return @b Success : The socket number @b 'sn' passed as parameter\n
- * @b Fail :\n @ref SOCKERR_SOCKNUM - Invalid socket number\n
- * @ref SOCKERR_SOCKMODE - Not support socket mode as TCP, UDP, and so on. \n
- * @ref SOCKERR_SOCKFLAG - Invaild socket flag.
- */
-int8_t WIZCHIP_EXPORT(socket)(uint8_t sn, uint8_t protocol, uint16_t port, uint8_t flag);
-
-/**
- * @ingroup WIZnet_socket_APIs
- * @brief Close a socket.
- * @details It closes the socket with @b'sn' passed as parameter.
- *
- * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_.
- *
- * @return @b Success : @ref SOCK_OK \n
- * @b Fail : @ref SOCKERR_SOCKNUM - Invalid socket number
- */
-int8_t WIZCHIP_EXPORT(close)(uint8_t sn);
-
-/**
- * @ingroup WIZnet_socket_APIs
- * @brief Listen to a connection request from a client.
- * @details It is listening to a connection request from a client.
- * If connection request is accepted successfully, the connection is established. Socket sn is used in passive(server) mode.
- *
- * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_.
- * @return @b Success : @ref SOCK_OK \n
- * @b Fail :\n @ref SOCKERR_SOCKINIT - Socket is not initialized \n
- * @ref SOCKERR_SOCKCLOSED - Socket closed unexpectedly.
- */
-int8_t WIZCHIP_EXPORT(listen)(uint8_t sn);
-
-/**
- * @ingroup WIZnet_socket_APIs
- * @brief Try to connect a server.
- * @details It requests connection to the server with destination IP address and port number passed as parameter.\n
- * @note It is valid only in TCP client mode.
- * In block io mode, it does not return until connection is completed.
- * In Non-block io mode, it return @ref SOCK_BUSY immediately.
- *
- * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_.
- * @param addr Pointer variable of destination IP address. It should be allocated 4 bytes.
- * @param port Destination port number.
- *
- * @return @b Success : @ref SOCK_OK \n
- * @b Fail :\n @ref SOCKERR_SOCKNUM - Invalid socket number\n
- * @ref SOCKERR_SOCKMODE - Invalid socket mode\n
- * @ref SOCKERR_SOCKINIT - Socket is not initialized\n
- * @ref SOCKERR_IPINVALID - Wrong server IP address\n
- * @ref SOCKERR_PORTZERO - Server port zero\n
- * @ref SOCKERR_TIMEOUT - Timeout occurred during request connection\n
- * @ref SOCK_BUSY - In non-block io mode, it returned immediately\n
- */
-int8_t WIZCHIP_EXPORT(connect)(uint8_t sn, uint8_t * addr, uint16_t port);
-
-/**
- * @ingroup WIZnet_socket_APIs
- * @brief Try to disconnect a connection socket.
- * @details It sends request message to disconnect the TCP socket 'sn' passed as parameter to the server or client.
- * @note It is valid only in TCP server or client mode. \n
- * In block io mode, it does not return until disconnection is completed. \n
- * In Non-block io mode, it return @ref SOCK_BUSY immediately. \n
-
- * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_.
- * @return @b Success : @ref SOCK_OK \n
- * @b Fail :\n @ref SOCKERR_SOCKNUM - Invalid socket number \n
- * @ref SOCKERR_SOCKMODE - Invalid operation in the socket \n
- * @ref SOCKERR_TIMEOUT - Timeout occurred \n
- * @ref SOCK_BUSY - Socket is busy.
- */
-int8_t WIZCHIP_EXPORT(disconnect)(uint8_t sn);
-
-/**
- * @ingroup WIZnet_socket_APIs
- * @brief Send data to the connected peer in TCP socket.
- * @details It is used to send outgoing data to the connected socket.
- * @note It is valid only in TCP server or client mode. It can't send data greater than socket buffer size. \n
- * In block io mode, It doesn't return until data send is completed - socket buffer size is greater than data. \n
- * In non-block io mode, It return @ref SOCK_BUSY immediately when socket buffer is not enough. \n
- * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_.
- * @param buf Pointer buffer containing data to be sent.
- * @param len The byte length of data in buf.
- * @return @b Success : The sent data size \n
- * @b Fail : \n @ref SOCKERR_SOCKSTATUS - Invalid socket status for socket operation \n
- * @ref SOCKERR_TIMEOUT - Timeout occurred \n
- * @ref SOCKERR_SOCKMODE - Invalid operation in the socket \n
- * @ref SOCKERR_SOCKNUM - Invalid socket number \n
- * @ref SOCKERR_DATALEN - zero data length \n
- * @ref SOCK_BUSY - Socket is busy.
- */
-int32_t WIZCHIP_EXPORT(send)(uint8_t sn, uint8_t * buf, uint16_t len);
-
-/**
- * @ingroup WIZnet_socket_APIs
- * @brief Receive data from the connected peer.
- * @details It is used to read incoming data from the connected socket.\n
- * It waits for data as much as the application wants to receive.
- * @note It is valid only in TCP server or client mode. It can't receive data greater than socket buffer size. \n
- * In block io mode, it doesn't return until data reception is completed - data is filled as len in socket buffer. \n
- * In non-block io mode, it return @ref SOCK_BUSY immediately when len is greater than data size in socket buffer. \n
- *
- * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_.
- * @param buf Pointer buffer to read incoming data.
- * @param len The max data length of data in buf.
- * @return @b Success : The real received data size \n
- * @b Fail :\n
- * @ref SOCKERR_SOCKSTATUS - Invalid socket status for socket operation \n
- * @ref SOCKERR_SOCKMODE - Invalid operation in the socket \n
- * @ref SOCKERR_SOCKNUM - Invalid socket number \n
- * @ref SOCKERR_DATALEN - zero data length \n
- * @ref SOCK_BUSY - Socket is busy.
- */
-int32_t WIZCHIP_EXPORT(recv)(uint8_t sn, uint8_t * buf, uint16_t len);
-
-/**
- * @ingroup WIZnet_socket_APIs
- * @brief Sends datagram to the peer with destination IP address and port number passed as parameter.
- * @details It sends datagram of UDP or MACRAW to the peer with destination IP address and port number passed as parameter.\n
- * Even if the connectionless socket has been previously connected to a specific address,
- * the address and port number parameters override the destination address for that particular datagram only.
- * @note In block io mode, It doesn't return until data send is completed - socket buffer size is greater than len.
- * In non-block io mode, It return @ref SOCK_BUSY immediately when socket buffer is not enough.
- *
- * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_.
- * @param buf Pointer buffer to send outgoing data.
- * @param len The byte length of data in buf.
- * @param addr Pointer variable of destination IP address. It should be allocated 4 bytes.
- * @param port Destination port number.
- *
- * @return @b Success : The sent data size \n
- * @b Fail :\n @ref SOCKERR_SOCKNUM - Invalid socket number \n
- * @ref SOCKERR_SOCKMODE - Invalid operation in the socket \n
- * @ref SOCKERR_SOCKSTATUS - Invalid socket status for socket operation \n
- * @ref SOCKERR_DATALEN - zero data length \n
- * @ref SOCKERR_IPINVALID - Wrong server IP address\n
- * @ref SOCKERR_PORTZERO - Server port zero\n
- * @ref SOCKERR_SOCKCLOSED - Socket unexpectedly closed \n
- * @ref SOCKERR_TIMEOUT - Timeout occurred \n
- * @ref SOCK_BUSY - Socket is busy.
- */
-int32_t WIZCHIP_EXPORT(sendto)(uint8_t sn, uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t port);
-
-/**
- * @ingroup WIZnet_socket_APIs
- * @brief Receive datagram of UDP or MACRAW
- * @details This function is an application I/F function which is used to receive the data in other then TCP mode. \n
- * This function is used to receive UDP and MAC_RAW mode, and handle the header as well.
- * This function can divide to received the packet data.
- * On the MACRAW SOCKET, the addr and port parameters are ignored.
- * @note In block io mode, it doesn't return until data reception is completed - data is filled as len in socket buffer
- * In non-block io mode, it return @ref SOCK_BUSY immediately when len is greater than data size in socket buffer.
- *
- * @param sn Socket number. It should be 0 ~ @ref \_WIZCHIP_SOCK_NUM_.
- * @param buf Pointer buffer to read incoming data.
- * @param len The max data length of data in buf.
- * When the received packet size <= len, receives data as packet sized.
- * When others, receives data as len.
- * @param addr Pointer variable of destination IP address. It should be allocated 4 bytes.
- * It is valid only when the first call recvfrom for receiving the packet.
- * When it is valid, @ref packinfo[7] should be set as '1' after call @ref getsockopt(sn, SO_PACKINFO, &packinfo).
- * @param port Pointer variable of destination port number.
- * It is valid only when the first call recvform for receiving the packet.
-* When it is valid, @ref packinfo[7] should be set as '1' after call @ref getsockopt(sn, SO_PACKINFO, &packinfo).
- *
- * @return @b Success : This function return real received data size for success.\n
- * @b Fail : @ref SOCKERR_DATALEN - zero data length \n
- * @ref SOCKERR_SOCKMODE - Invalid operation in the socket \n
- * @ref SOCKERR_SOCKNUM - Invalid socket number \n
- * @ref SOCKBUSY - Socket is busy.
- */
-int32_t WIZCHIP_EXPORT(recvfrom)(uint8_t sn, uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t *port);
-
-
-/////////////////////////////
-// SOCKET CONTROL & OPTION //
-/////////////////////////////
-#define SOCK_IO_BLOCK 0 ///< Socket Block IO Mode in @ref setsockopt().
-#define SOCK_IO_NONBLOCK 1 ///< Socket Non-block IO Mode in @ref setsockopt().
-
-/**
- * @defgroup DATA_TYPE DATA TYPE
- */
-
-/**
- * @ingroup DATA_TYPE
- * @brief The kind of Socket Interrupt.
- * @sa Sn_IR, Sn_IMR, setSn_IR(), getSn_IR(), setSn_IMR(), getSn_IMR()
- */
-typedef enum
-{
- SIK_CONNECTED = (1 << 0), ///< connected
- SIK_DISCONNECTED = (1 << 1), ///< disconnected
- SIK_RECEIVED = (1 << 2), ///< data received
- SIK_TIMEOUT = (1 << 3), ///< timeout occurred
- SIK_SENT = (1 << 4), ///< send ok
- SIK_ALL = 0x1F, ///< all interrupt
-}sockint_kind;
-
-/**
- * @ingroup DATA_TYPE
- * @brief The type of @ref ctlsocket().
- */
-typedef enum
-{
- CS_SET_IOMODE, ///< set socket IO mode with @ref SOCK_IO_BLOCK or @ref SOCK_IO_NONBLOCK
- CS_GET_IOMODE, ///< get socket IO mode
- CS_GET_MAXTXBUF, ///< get the size of socket buffer allocated in TX memory
- CS_GET_MAXRXBUF, ///< get the size of socket buffer allocated in RX memory
- CS_CLR_INTERRUPT, ///< clear the interrupt of socket with @ref sockint_kind
- CS_GET_INTERRUPT, ///< get the socket interrupt. refer to @ref sockint_kind
- CS_SET_INTMASK, ///< set the interrupt mask of socket with @ref sockint_kind
- CS_GET_INTMASK ///< get the masked interrupt of socket. refer to @ref sockint_kind
-}ctlsock_type;
-
-
-/**
- * @ingroup DATA_TYPE
- * @brief The type of socket option in @ref setsockopt() or @ref getsockopt()
- */
-typedef enum
-{
- SO_FLAG, ///< Valid only in getsockopt(), For set flag of socket refer to flag in @ref socket().
- SO_TTL, ///< Set/Get TTL. @ref Sn_TTL ( @ref setSn_TTL(), @ref getSn_TTL() )
- SO_TOS, ///< Set/Get TOS. @ref Sn_TOS ( @ref setSn_TOS(), @ref getSn_TOS() )
- SO_MSS, ///< Set/Get MSS. @ref Sn_MSSR ( @ref setSn_MSSR(), @ref getSn_MSSR() )
- SO_DESTIP, ///< Set/Get the destination IP address. @ref Sn_DIPR ( @ref setSn_DIPR(), @ref getSn_DIPR() )
- SO_DESTPORT, ///< Set/Get the destination Port number. @ref Sn_DPORT ( @ref setSn_DPORT(), @ref getSn_DPORT() )
-#if _WIZCHIP_ != 5100
- SO_KEEPALIVESEND, ///< Valid only in setsockopt. Manually send keep-alive packet in TCP mode
- #if _WIZCHIP_ > 5200
- SO_KEEPALIVEAUTO, ///< Set/Get keep-alive auto transmission timer in TCP mode
- #endif
-#endif
- SO_SENDBUF, ///< Valid only in getsockopt. Get the free data size of Socekt TX buffer. @ref Sn_TX_FSR, @ref getSn_TX_FSR()
- SO_RECVBUF, ///< Valid only in getsockopt. Get the received data size in socket RX buffer. @ref Sn_RX_RSR, @ref getSn_RX_RSR()
- SO_STATUS, ///< Valid only in getsockopt. Get the socket status. @ref Sn_SR, @ref getSn_SR()
- SO_REMAINSIZE, ///< Valid only in getsockopt. Get the remained packet size in other then TCP mode.
- SO_PACKINFO ///< Valid only in getsockopt. Get the packet information as @ref PACK_FIRST, @ref PACK_REMAINED, and @ref PACK_COMPLETED in other then TCP mode.
-}sockopt_type;
-
-/**
- * @ingroup WIZnet_socket_APIs
- * @brief Control socket.
- * @details Control IO mode, Interrupt & Mask of socket and get the socket buffer information.
- * Refer to @ref ctlsock_type.
- * @param sn socket number
- * @param cstype type of control socket. refer to @ref ctlsock_type.
- * @param arg Data type and value is determined according to @ref ctlsock_type. \n
- *
- * @return @b Success @ref SOCK_OK \n
- * @b fail @ref SOCKERR_ARG - Invalid argument\n
- */
-int8_t WIZCHIP_EXPORT(ctlsocket)(uint8_t sn, ctlsock_type cstype, void* arg);
-
-/**
- * @ingroup WIZnet_socket_APIs
- * @brief set socket options
- * @details Set socket option like as TTL, MSS, TOS, and so on. Refer to @ref sockopt_type.
- *
- * @param sn socket number
- * @param sotype socket option type. refer to @ref sockopt_type
- * @param arg Data type and value is determined according to sotype. \n
- *
- *
@b sotype
@b data type
@b value
- *
@ref SO_TTL
uint8_t
0 ~ 255
- *
@ref SO_TOS
uint8_t
0 ~ 255
- *
@ref SO_MSS
uint16_t
0 ~ 65535
- *
@ref SO_DESTIP
uint8_t[4]
- *
@ref SO_DESTPORT
uint16_t
0 ~ 65535
- *
@ref SO_KEEPALIVESEND
null
null
- *
@ref SO_KEEPALIVEAUTO
uint8_t
0 ~ 255
- *
- * @return
- * - @b Success : @ref SOCK_OK \n
- * - @b Fail
- * - @ref SOCKERR_SOCKNUM - Invalid Socket number \n
- * - @ref SOCKERR_SOCKMODE - Invalid socket mode \n
- * - @ref SOCKERR_SOCKOPT - Invalid socket option or its value \n
- * - @ref SOCKERR_TIMEOUT - Timeout occurred when sending keep-alive packet \n
- */
-int8_t WIZCHIP_EXPORT(setsockopt)(uint8_t sn, sockopt_type sotype, void* arg);
-
-/**
- * @ingroup WIZnet_socket_APIs
- * @brief get socket options
- * @details Get socket option like as FLAG, TTL, MSS, and so on. Refer to @ref sockopt_type
- * @param sn socket number
- * @param sotype socket option type. refer to @ref sockopt_type
- * @param arg Data type and value is determined according to sotype. \n
- *
- *
@b sotype
@b data type
@b value
- *
@ref SO_FLAG
uint8_t
@ref SF_ETHER_OWN, etc...
- *
@ref SO_TOS
uint8_t
0 ~ 255
- *
@ref SO_MSS
uint16_t
0 ~ 65535
- *
@ref SO_DESTIP
uint8_t[4]
- *
@ref SO_DESTPORT
uint16_t
- *
@ref SO_KEEPALIVEAUTO
uint8_t
0 ~ 255
- *
@ref SO_SENDBUF
uint16_t
0 ~ 65535
- *
@ref SO_RECVBUF
uint16_t
0 ~ 65535
- *
@ref SO_STATUS
uint8_t
@ref SOCK_ESTABLISHED, etc..
- *
@ref SO_REMAINSIZE
uint16_t
0~ 65535
- *
@ref SO_PACKINFO
uint8_t
@ref PACK_FIRST, etc...
- *
- * @return
- * - @b Success : @ref SOCK_OK \n
- * - @b Fail
- * - @ref SOCKERR_SOCKNUM - Invalid Socket number \n
- * - @ref SOCKERR_SOCKOPT - Invalid socket option or its value \n
- * - @ref SOCKERR_SOCKMODE - Invalid socket mode \n
- * @note
- * The option as PACK_REMAINED and SO_PACKINFO is valid only in NON-TCP mode and after call @ref recvfrom(). \n
- * When SO_PACKINFO value is PACK_FIRST and the return value of recvfrom() is zero,
- * This means the zero byte UDP data(UDP Header only) received.
- */
-int8_t WIZCHIP_EXPORT(getsockopt)(uint8_t sn, sockopt_type sotype, void* arg);
-
-#endif // _WIZCHIP_SOCKET_H_
diff --git a/drivers/wiznet5k/ethernet/w5200/w5200.c b/drivers/wiznet5k/ethernet/w5200/w5200.c
deleted file mode 100644
index a84d3c9fa7bc..000000000000
--- a/drivers/wiznet5k/ethernet/w5200/w5200.c
+++ /dev/null
@@ -1,215 +0,0 @@
-// dpgeorge: this file taken from w5500/w5500.c and adapted to W5200
-
-//*****************************************************************************
-//
-//! \file w5500.c
-//! \brief W5500 HAL Interface.
-//! \version 1.0.1
-//! \date 2013/10/21
-//! \par Revision history
-//! <2014/05/01> V1.0.2
-//! 1. Implicit type casting -> Explicit type casting. Refer to M20140501
-//! Fixed the problem on porting into under 32bit MCU
-//! Issued by Mathias ClauBen, wizwiki forum ID Think01 and bobh
-//! Thank for your interesting and serious advices.
-//! <2013/10/21> 1st Release
-//! <2013/12/20> V1.0.1
-//! 1. Remove warning
-//! 2. WIZCHIP_READ_BUF WIZCHIP_WRITE_BUF in case _WIZCHIP_IO_MODE_SPI_FDM_
-//! for loop optimized(removed). refer to M20131220
-//! \author MidnightCow
-//! \copyright
-//!
-//! Copyright (c) 2013, WIZnet Co., LTD.
-//! 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 the 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 OWNER 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.
-//
-//*****************************************************************************
-
-#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)
-#define SBASE(sn) (TXBUF_BASE + SSIZE * (sn)) /* tx buffer base for socket sn */
-#define RBASE(sn) (RXBUF_BASE + RSIZE * (sn)) /* rx buffer base for socket sn */
-
-uint8_t WIZCHIP_READ(uint32_t AddrSel) {
- WIZCHIP_CRITICAL_ENTER();
- WIZCHIP.CS._select();
-
- uint8_t spi_data[4] = {
- AddrSel >> 8,
- AddrSel,
- 0x00,
- 0x01,
- };
- WIZCHIP.IF.SPI._write_bytes(spi_data, 4);
- uint8_t ret;
- WIZCHIP.IF.SPI._read_bytes(&ret, 1);
-
- WIZCHIP.CS._deselect();
- WIZCHIP_CRITICAL_EXIT();
-
- return ret;
-}
-
-void WIZCHIP_WRITE(uint32_t AddrSel, uint8_t wb) {
- WIZCHIP_CRITICAL_ENTER();
- WIZCHIP.CS._select();
-
- uint8_t spi_data[5] = {
- AddrSel >> 8,
- AddrSel,
- 0x80,
- 0x01,
- wb,
- };
- WIZCHIP.IF.SPI._write_bytes(spi_data, 5);
-
- WIZCHIP.CS._deselect();
- WIZCHIP_CRITICAL_EXIT();
-}
-
-void WIZCHIP_READ_BUF(uint32_t AddrSel, uint8_t* pBuf, uint16_t len) {
- WIZCHIP_CRITICAL_ENTER();
- WIZCHIP.CS._select();
-
- uint8_t spi_data[4] = {
- AddrSel >> 8,
- AddrSel,
- 0x00 | ((len >> 8) & 0x7f),
- len & 0xff,
- };
- WIZCHIP.IF.SPI._write_bytes(spi_data, 4);
- WIZCHIP.IF.SPI._read_bytes(pBuf, len);
-
- WIZCHIP.CS._deselect();
- WIZCHIP_CRITICAL_EXIT();
-}
-
-void WIZCHIP_WRITE_BUF(uint32_t AddrSel, uint8_t* pBuf, uint16_t len) {
- WIZCHIP_CRITICAL_ENTER();
- WIZCHIP.CS._select();
-
- uint8_t spi_data[4] = {
- AddrSel >> 8,
- AddrSel,
- 0x80 | ((len >> 8) & 0x7f),
- len & 0xff,
- };
- WIZCHIP.IF.SPI._write_bytes(spi_data, 4);
- WIZCHIP.IF.SPI._write_bytes(pBuf, len);
-
- WIZCHIP.CS._deselect();
- WIZCHIP_CRITICAL_EXIT();
-}
-
-uint16_t getSn_TX_FSR(uint8_t sn) {
- uint16_t val = 0, val1 = 0;
- do {
- val1 = (WIZCHIP_READ(Sn_TX_FSR(sn)) << 8) | WIZCHIP_READ(Sn_TX_FSR(sn) + 1);
- if (val1 != 0) {
- val = (WIZCHIP_READ(Sn_TX_FSR(sn)) << 8) | WIZCHIP_READ(Sn_TX_FSR(sn) + 1);
- }
- } while (val != val1);
- return val;
-}
-
-uint16_t getSn_RX_RSR(uint8_t sn) {
- uint16_t val = 0, val1 = 0;
- do {
- val1 = (WIZCHIP_READ(Sn_RX_RSR(sn)) << 8) | WIZCHIP_READ(Sn_RX_RSR(sn) + 1);
- if (val1 != 0) {
- val = (WIZCHIP_READ(Sn_RX_RSR(sn)) << 8) | WIZCHIP_READ(Sn_RX_RSR(sn) + 1);
- }
- } while (val != val1);
- return val;
-}
-
-void wiz_send_data(uint8_t sn, uint8_t *wizdata, uint16_t len) {
- if (len == 0) {
- return;
- }
-
- uint16_t ptr = getSn_TX_WR(sn);
- uint16_t offset = ptr & SMASK;
- uint32_t addr = offset + SBASE(sn);
-
- if (offset + len > SSIZE) {
- // implement wrap-around circular buffer
- uint16_t size = SSIZE - offset;
- WIZCHIP_WRITE_BUF(addr, wizdata, size);
- WIZCHIP_WRITE_BUF(SBASE(sn), wizdata + size, len - size);
- } else {
- WIZCHIP_WRITE_BUF(addr, wizdata, len);
- }
-
- ptr += len;
- setSn_TX_WR(sn, ptr);
-}
-
-void wiz_recv_data(uint8_t sn, uint8_t *wizdata, uint16_t len) {
- if (len == 0) {
- return;
- }
-
- uint16_t ptr = getSn_RX_RD(sn);
- uint16_t offset = ptr & RMASK;
- uint16_t addr = RBASE(sn) + offset;
-
- if (offset + len > RSIZE) {
- // implement wrap-around circular buffer
- uint16_t size = RSIZE - offset;
- WIZCHIP_READ_BUF(addr, wizdata, size);
- WIZCHIP_READ_BUF(RBASE(sn), wizdata + size, len - size);
- } else {
- WIZCHIP_READ_BUF(addr, wizdata, len);
- }
-
- ptr += len;
- setSn_RX_RD(sn, ptr);
-}
-
-void wiz_recv_ignore(uint8_t sn, uint16_t len) {
- uint16_t ptr = getSn_RX_RD(sn);
- ptr += len;
- setSn_RX_RD(sn, ptr);
-}
diff --git a/drivers/wiznet5k/ethernet/w5200/w5200.h b/drivers/wiznet5k/ethernet/w5200/w5200.h
deleted file mode 100644
index 63561940f8b5..000000000000
--- a/drivers/wiznet5k/ethernet/w5200/w5200.h
+++ /dev/null
@@ -1,2092 +0,0 @@
-// dpgeorge: this file taken from w5500/w5500.h and adapted to W5200
-
-//*****************************************************************************
-//
-//! \file w5500.h
-//! \brief W5500 HAL Header File.
-//! \version 1.0.0
-//! \date 2013/10/21
-//! \par Revision history
-//! <2013/10/21> 1st Release
-//! \author MidnightCow
-//! \copyright
-//!
-//! Copyright (c) 2013, WIZnet Co., LTD.
-//! 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 the 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 OWNER 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.
-//
-//*****************************************************************************
-
-#ifndef _W5200_H_
-#define _W5200_H_
-
-#include
-#include "../wizchip_conf.h"
-//#include "board.h"
-
-#define _W5200_IO_BASE_ 0x00000000
-
-#define WIZCHIP_CREG_ADDR(addr) (_W5200_IO_BASE_ + (addr))
-
-#define WIZCHIP_CH_BASE (0x4000)
-#define WIZCHIP_CH_SIZE (0x100)
-#define WIZCHIP_SREG_ADDR(sn, addr) (_W5200_IO_BASE_ + WIZCHIP_CH_BASE + (sn) * WIZCHIP_CH_SIZE + (addr))
-
-//////////////////////////////
-//-------------------------- defgroup ---------------------------------
-/**
- * @defgroup W5500 W5500
- *
- * @brief WHIZCHIP register defines and I/O functions of @b W5500.
- *
- * - @ref WIZCHIP_register : @ref Common_register_group and @ref Socket_register_group
- * - @ref WIZCHIP_IO_Functions : @ref Basic_IO_function, @ref Common_register_access_function and @ref Socket_register_access_function
- */
-
-
-/**
- * @defgroup WIZCHIP_register WIZCHIP register
- * @ingroup W5500
- *
- * @brief WHIZCHIP register defines register group of @b W5500.
- *
- * - @ref Common_register_group : Common register group
- * - @ref Socket_register_group : \c SOCKET n register group
- */
-
-
-/**
- * @defgroup WIZCHIP_IO_Functions WIZCHIP I/O functions
- * @ingroup W5500
- *
- * @brief This supports the basic I/O functions for @ref WIZCHIP_register.
- *
- * - Basic I/O function \n
- * WIZCHIP_READ(), WIZCHIP_WRITE(), WIZCHIP_READ_BUF(), WIZCHIP_WRITE_BUF() \n\n
- *
- * - @ref Common_register_group access functions \n
- * -# @b Mode \n
- * getMR(), setMR()
- * -# @b Interrupt \n
- * getIR(), setIR(), getIMR(), setIMR(), getSIR(), setSIR(), getSIMR(), setSIMR(), getINTLEVEL(), setINTLEVEL()
- * -# Network Information \n
- * getSHAR(), setSHAR(), getGAR(), setGAR(), getSUBR(), setSUBR(), getSIPR(), setSIPR()
- * -# @b Retransmission \n
- * getRCR(), setRCR(), getRTR(), setRTR()
- * -# @b PPPoE \n
- * getPTIMER(), setPTIMER(), getPMAGIC(), getPMAGIC(), getPSID(), setPSID(), getPHAR(), setPHAR(), getPMRU(), setPMRU()
- * -# ICMP packet \n
- * getUIPR(), getUPORTR()
- * -# @b etc. \n
- * getPHYCFGR(), setPHYCFGR(), getVERSIONR() \n\n
- *
- * - \ref Socket_register_group access functions \n
- * -# SOCKET control \n
- * getSn_MR(), setSn_MR(), getSn_CR(), setSn_CR(), getSn_IMR(), setSn_IMR(), getSn_IR(), setSn_IR()
- * -# SOCKET information \n
- * getSn_SR(), getSn_DHAR(), setSn_DHAR(), getSn_PORT(), setSn_PORT(), getSn_DIPR(), setSn_DIPR(), getSn_DPORT(), setSn_DPORT()
- * getSn_MSSR(), setSn_MSSR()
- * -# SOCKET communication \n
- * getSn_RXBUF_SIZE(), setSn_RXBUF_SIZE(), getSn_TXBUF_SIZE(), setSn_TXBUF_SIZE() \n
- * getSn_TX_RD(), getSn_TX_WR(), setSn_TX_WR() \n
- * getSn_RX_RD(), setSn_RX_RD(), getSn_RX_WR() \n
- * getSn_TX_FSR(), getSn_RX_RSR(), getSn_KPALVTR(), setSn_KPALVTR()
- * -# IP header field \n
- * getSn_FRAG(), setSn_FRAG(), getSn_TOS(), setSn_TOS() \n
- * getSn_TTL(), setSn_TTL()
- */
-
-
-
-/**
- * @defgroup Common_register_group Common register
- * @ingroup WIZCHIP_register
- *
- * @brief Common register group\n
- * It set the basic for the networking\n
- * It set the configuration such as interrupt, network information, ICMP, etc.
- * @details
- * @sa MR : Mode register.
- * @sa GAR, SUBR, SHAR, SIPR
- * @sa INTLEVEL, IR, IMR, SIR, SIMR : Interrupt.
- * @sa RTR, RCR : Data retransmission.
- * @sa PTIMER, PMAGIC, PHAR, PSID, PMRU : PPPoE.
- * @sa UIPR, UPORTR : ICMP message.
- * @sa PHYCFGR, VERSIONR : etc.
- */
-
-
-
-/**
- * @defgroup Socket_register_group Socket register
- * @ingroup WIZCHIP_register
- *
- * @brief Socket register group.\n
- * Socket register configures and control SOCKETn which is necessary to data communication.
- * @details
- * @sa Sn_MR, Sn_CR, Sn_IR, Sn_IMR : SOCKETn Control
- * @sa Sn_SR, Sn_PORT, Sn_DHAR, Sn_DIPR, Sn_DPORT : SOCKETn Information
- * @sa Sn_MSSR, Sn_TOS, Sn_TTL, Sn_KPALVTR, Sn_FRAG : Internet protocol.
- * @sa Sn_RXBUF_SIZE, Sn_TXBUF_SIZE, Sn_TX_FSR, Sn_TX_RD, Sn_TX_WR, Sn_RX_RSR, Sn_RX_RD, Sn_RX_WR : Data communication
- */
-
-
-
- /**
- * @defgroup Basic_IO_function Basic I/O function
- * @ingroup WIZCHIP_IO_Functions
- * @brief These are basic input/output functions to read values from register or write values to register.
- */
-
-/**
- * @defgroup Common_register_access_function Common register access functions
- * @ingroup WIZCHIP_IO_Functions
- * @brief These are functions to access common registers.
- */
-
-/**
- * @defgroup Socket_register_access_function Socket register access functions
- * @ingroup WIZCHIP_IO_Functions
- * @brief These are functions to access socket registers.
- */
-
-//------------------------------- defgroup end --------------------------------------------
-//----------------------------- W5500 Common Registers IOMAP -----------------------------
-/**
- * @ingroup Common_register_group
- * @brief Mode Register address(R/W)\n
- * @ref MR is used for S/W reset, ping block mode, PPPoE mode and etc.
- * @details Each bit of @ref MR defined as follows.
- *
- *
7
6
5
4
3
2
1
0
- *
RST
Reserved
WOL
PB
PPPoE
Reserved
FARP
Reserved
- *
- * - \ref MR_RST : Reset
- * - \ref MR_WOL : Wake on LAN
- * - \ref MR_PB : Ping block
- * - \ref MR_PPPOE : PPPoE mode
- * - \ref MR_FARP : Force ARP mode
- */
-#define MR WIZCHIP_CREG_ADDR(0x0000)
-
-/**
- * @ingroup Common_register_group
- * @brief Gateway IP Register address(R/W)
- * @details @ref GAR configures the default gateway address.
- */
-#define GAR WIZCHIP_CREG_ADDR(0x0001)
-
-/**
- * @ingroup Common_register_group
- * @brief Subnet mask Register address(R/W)
- * @details @ref SUBR configures the subnet mask address.
- */
-#define SUBR WIZCHIP_CREG_ADDR(0x0005)
-
-/**
- * @ingroup Common_register_group
- * @brief Source MAC Register address(R/W)
- * @details @ref SHAR configures the source hardware address.
- */
-#define SHAR WIZCHIP_CREG_ADDR(0x0009)
-
-/**
- * @ingroup Common_register_group
- * @brief Source IP Register address(R/W)
- * @details @ref SIPR configures the source IP address.
- */
-#define SIPR WIZCHIP_CREG_ADDR(0x000f)
-
-/**
- * @ingroup Common_register_group
- * @brief Set Interrupt low level timer register address(R/W)
- * @details @ref INTLEVEL configures the Interrupt Assert Time.
- */
-//#define INTLEVEL (_W5500_IO_BASE_ + (0x0013 << 8) + (WIZCHIP_CREG_BLOCK << 3))
-
-/**
- * @ingroup Common_register_group
- * @brief Interrupt Register(R/W)
- * @details @ref IR indicates the interrupt status. Each bit of @ref IR will be still until the bit will be written to by the host.
- * If @ref IR is not equal to x00 INTn PIN is asserted to low until it is x00\n\n
- * Each bit of @ref IR defined as follows.
- *
- *
7
6
5
4
3
2
1
0
- *
CONFLICT
UNREACH
PPPoE
MP
Reserved
Reserved
Reserved
Reserved
- *
- * - \ref IR_CONFLICT : IP conflict
- * - \ref IR_UNREACH : Destination unreachable
- * - \ref IR_PPPoE : PPPoE connection close
- * - \ref IR_MP : Magic packet
- */
-#define IR WIZCHIP_CREG_ADDR(0x0015)
-
-/**
- * @ingroup Common_register_group
- * @brief Interrupt mask register(R/W)
- * @details @ref IMR is used to mask interrupts. Each bit of @ref IMR corresponds to each bit of @ref IR.
- * When a bit of @ref IMR is and the corresponding bit of @ref IR is an interrupt will be issued. In other words,
- * if a bit of @ref IMR is an interrupt will not be issued even if the corresponding bit of @ref IR is \n\n
- * Each bit of @ref IMR defined as the following.
- *
- *
7
6
5
4
3
2
1
0
- *
IM_IR7
IM_IR6
IM_IR5
IM_IR4
Reserved
Reserved
Reserved
Reserved
- *
- * - \ref IM_IR7 : IP Conflict Interrupt Mask
- * - \ref IM_IR6 : Destination unreachable Interrupt Mask
- * - \ref IM_IR5 : PPPoE Close Interrupt Mask
- * - \ref IM_IR4 : Magic Packet Interrupt Mask
- */
-#define IMR WIZCHIP_CREG_ADDR(0x0016)
-
-/**
- * @ingroup Common_register_group
- * @brief Socket Interrupt Register(R/W)
- * @details @ref SIR indicates the interrupt status of Socket.\n
- * Each bit of @ref SIR be still until @ref Sn_IR is cleared by the host.\n
- * If @ref Sn_IR is not equal to x00 the n-th bit of @ref SIR is and INTn PIN is asserted until @ref SIR is x00 */
-//#define SIR (_W5500_IO_BASE_ + (0x0017 << 8) + (WIZCHIP_CREG_BLOCK << 3))
-
-/**
- * @ingroup Common_register_group
- * @brief Socket Interrupt Mask Register(R/W)
- * @details Each bit of @ref SIMR corresponds to each bit of @ref SIR.
- * When a bit of @ref SIMR is and the corresponding bit of @ref SIR is Interrupt will be issued.
- * In other words, if a bit of @ref SIMR is an interrupt will be not issued even if the corresponding bit of @ref SIR is
- */
-//#define SIMR (_W5500_IO_BASE_ + (0x0018 << 8) + (WIZCHIP_CREG_BLOCK << 3))
-
-/**
- * @ingroup Common_register_group
- * @brief Timeout register address( 1 is 100us )(R/W)
- * @details @ref RTR configures the retransmission timeout period. The unit of timeout period is 100us and the default of @ref RTR is x07D0or 000
- * And so the default timeout period is 200ms(100us X 2000). During the time configured by @ref RTR, W5500 waits for the peer response
- * to the packet that is transmitted by \ref Sn_CR (CONNECT, DISCON, CLOSE, SEND, SEND_MAC, SEND_KEEP command).
- * If the peer does not respond within the @ref RTR time, W5500 retransmits the packet or issues timeout.
- */
-#define RTR WIZCHIP_CREG_ADDR(0x0017)
-
-/**
- * @ingroup Common_register_group
- * @brief Retry count register(R/W)
- * @details @ref RCR configures the number of time of retransmission.
- * When retransmission occurs as many as ref RCR+1 Timeout interrupt is issued (@ref Sn_IR[TIMEOUT] = .
- */
-#define RCR WIZCHIP_CREG_ADDR(0x0019)
-
-/**
- * @ingroup Common_register_group
- * @brief PPP LCP Request Timer register in PPPoE mode(R/W)
- * @details @ref PTIMER configures the time for sending LCP echo request. The unit of time is 25ms.
- */
-#define PTIMER WIZCHIP_CREG_ADDR(0x0028)
-
-/**
- * @ingroup Common_register_group
- * @brief PPP LCP Magic number register in PPPoE mode(R/W)
- * @details @ref PMAGIC configures the 4bytes magic number to be used in LCP negotiation.
- */
-#define PMAGIC WIZCHIP_CREG_ADDR(0x0029)
-
-/**
- * @ingroup Common_register_group
- * @brief PPP Destination MAC Register address(R/W)
- * @details @ref PHAR configures the PPPoE server hardware address that is acquired during PPPoE connection process.
- */
-//#define PHAR (_W5500_IO_BASE_ + (0x001E << 8) + (WIZCHIP_CREG_BLOCK << 3))
-
-/**
- * @ingroup Common_register_group
- * @brief PPP Session Identification Register(R/W)
- * @details @ref PSID configures the PPPoE sever session ID acquired during PPPoE connection process.
- */
-//#define PSID (_W5500_IO_BASE_ + (0x0024 << 8) + (WIZCHIP_CREG_BLOCK << 3))
-
-/**
- * @ingroup Common_register_group
- * @brief PPP Maximum Segment Size(MSS) register(R/W)
- * @details @ref PMRU configures the maximum receive unit of PPPoE.
- */
-//#define PMRU (_W5500_IO_BASE_ + (0x0026 << 8) + (WIZCHIP_CREG_BLOCK << 3))
-
-/**
- * @ingroup Common_register_group
- * @brief Unreachable IP register address in UDP mode(R)
- * @details W5500 receives an ICMP packet(Destination port unreachable) when data is sent to a port number
- * which socket is not open and @ref UNREACH bit of @ref IR becomes and @ref UIPR & @ref UPORTR indicates
- * the destination IP address & port number respectively.
- */
-//#define UIPR (_W5500_IO_BASE_ + (0x002a << 8) + (WIZCHIP_CREG_BLOCK << 3))
-
-/**
- * @ingroup Common_register_group
- * @brief Unreachable Port register address in UDP mode(R)
- * @details W5500 receives an ICMP packet(Destination port unreachable) when data is sent to a port number
- * which socket is not open and @ref UNREACH bit of @ref IR becomes and @ref UIPR & @ref UPORTR
- * indicates the destination IP address & port number respectively.
- */
-//#define UPORTR (_W5500_IO_BASE_ + (0x002e << 8) + (WIZCHIP_CREG_BLOCK << 3))
-
-/**
- * @ingroup Common_register_group
- * @brief PHY Status Register(R/W)
- * @details @ref PHYCFGR configures PHY operation mode and resets PHY. In addition, @ref PHYCFGR indicates the status of PHY such as duplex, Speed, Link.
- */
-//#define PHYCFGR (_W5500_IO_BASE_ + (0x002E << 8) + (WIZCHIP_CREG_BLOCK << 3))
-#define PHYSTATUS WIZCHIP_CREG_ADDR(0x0035)
-
-// Reserved (_W5500_IO_BASE_ + (0x002F << 8) + (WIZCHIP_CREG_BLOCK << 3))
-// Reserved (_W5500_IO_BASE_ + (0x0030 << 8) + (WIZCHIP_CREG_BLOCK << 3))
-// Reserved (_W5500_IO_BASE_ + (0x0031 << 8) + (WIZCHIP_CREG_BLOCK << 3))
-// Reserved (_W5500_IO_BASE_ + (0x0032 << 8) + (WIZCHIP_CREG_BLOCK << 3))
-// Reserved (_W5500_IO_BASE_ + (0x0033 << 8) + (WIZCHIP_CREG_BLOCK << 3))
-// Reserved (_W5500_IO_BASE_ + (0x0034 << 8) + (WIZCHIP_CREG_BLOCK << 3))
-// Reserved (_W5500_IO_BASE_ + (0x0035 << 8) + (WIZCHIP_CREG_BLOCK << 3))
-// Reserved (_W5500_IO_BASE_ + (0x0036 << 8) + (WIZCHIP_CREG_BLOCK << 3))
-// Reserved (_W5500_IO_BASE_ + (0x0037 << 8) + (WIZCHIP_CREG_BLOCK << 3))
-// Reserved (_W5500_IO_BASE_ + (0x0038 << 8) + (WIZCHIP_CREG_BLOCK << 3))
-
-/**
- * @ingroup Common_register_group
- * @brief chip version register address(R)
- * @details @ref VERSIONR always indicates the W5500 version as @b 0x04.
- */
-//#define VERSIONR (_W5200_IO_BASE_ + (0x0039 << 8) + (WIZCHIP_CREG_BLOCK << 3))
-
-
-//----------------------------- W5500 Socket Registers IOMAP -----------------------------
-/**
- * @ingroup Socket_register_group
- * @brief socket Mode register(R/W)
- * @details @ref Sn_MR configures the option or protocol type of Socket n.\n\n
- * Each bit of @ref Sn_MR defined as the following.
- *
- *
7
6
5
4
3
2
1
0
- *
MULTI/MFEN
BCASTB
ND/MC/MMB
UCASTB/MIP6B
Protocol[3]
Protocol[2]
Protocol[1]
Protocol[0]
- *
- * - @ref Sn_MR_MULTI : Support UDP Multicasting
- * - @ref Sn_MR_BCASTB : Broadcast block in UDP Multicasting
- * - @ref Sn_MR_ND : No Delayed Ack(TCP) flag
- * - @ref Sn_MR_MC : IGMP version used in UDP mulitcasting
- * - @ref Sn_MR_MMB : Multicast Blocking in @ref Sn_MR_MACRAW mode
- * - @ref Sn_MR_UCASTB : Unicast Block in UDP Multicating
- * - @ref Sn_MR_MIP6B : IPv6 packet Blocking in @ref Sn_MR_MACRAW mode
- * - Protocol
- *
- *
Protocol[3]
Protocol[2]
Protocol[1]
Protocol[0]
@b Meaning
- *
0
0
0
0
Closed
- *
0
0
0
1
TCP
- *
0
0
1
0
UDP
- *
0
1
0
0
MACRAW
- *
- * - @ref Sn_MR_MACRAW : MAC LAYER RAW SOCK \n
- * - @ref Sn_MR_UDP : UDP
- * - @ref Sn_MR_TCP : TCP
- * - @ref Sn_MR_CLOSE : Unused socket
- * @note MACRAW mode should be only used in Socket 0.
- */
-#define Sn_MR(N) WIZCHIP_SREG_ADDR(N, 0x0000)
-
-/**
- * @ingroup Socket_register_group
- * @brief Socket command register(R/W)
- * @details This is used to set the command for Socket n such as OPEN, CLOSE, CONNECT, LISTEN, SEND, and RECEIVE.\n
- * After W5500 accepts the command, the @ref Sn_CR register is automatically cleared to 0x00.
- * Even though @ref Sn_CR is cleared to 0x00, the command is still being processed.\n
- * To check whether the command is completed or not, please check the @ref Sn_IR or @ref Sn_SR.
- * - @ref Sn_CR_OPEN : Initialize or open socket.
- * - @ref Sn_CR_LISTEN : Wait connection request in TCP mode(Server mode)
- * - @ref Sn_CR_CONNECT : Send connection request in TCP mode(Client mode)
- * - @ref Sn_CR_DISCON : Send closing request in TCP mode.
- * - @ref Sn_CR_CLOSE : Close socket.
- * - @ref Sn_CR_SEND : Update TX buffer pointer and send data.
- * - @ref Sn_CR_SEND_MAC : Send data with MAC address, so without ARP process.
- * - @ref Sn_CR_SEND_KEEP : Send keep alive message.
- * - @ref Sn_CR_RECV : Update RX buffer pointer and receive data.
- */
-#define Sn_CR(N) WIZCHIP_SREG_ADDR(N, 0x0001)
-
-/**
- * @ingroup Socket_register_group
- * @brief Socket interrupt register(R)
- * @details @ref Sn_IR indicates the status of Socket Interrupt such as establishment, termination, receiving data, timeout).\n
- * When an interrupt occurs and the corresponding bit of @ref Sn_IMR is the corresponding bit of @ref Sn_IR becomes \n
- * In order to clear the @ref Sn_IR bit, the host should write the bit to \n
- *
- *
7
6
5
4
3
2
1
0
- *
Reserved
Reserved
Reserved
SEND_OK
TIMEOUT
RECV
DISCON
CON
- *
- * - \ref Sn_IR_SENDOK : SEND_OK Interrupt
- * - \ref Sn_IR_TIMEOUT : TIMEOUT Interrupt
- * - \ref Sn_IR_RECV : RECV Interrupt
- * - \ref Sn_IR_DISCON : DISCON Interrupt
- * - \ref Sn_IR_CON : CON Interrupt
- */
-#define Sn_IR(N) WIZCHIP_SREG_ADDR(N, 0x0002)
-
-/**
- * @ingroup Socket_register_group
- * @brief Socket status register(R)
- * @details @ref Sn_SR indicates the status of Socket n.\n
- * The status of Socket n is changed by @ref Sn_CR or some special control packet as SYN, FIN packet in TCP.
- * @par Normal status
- * - @ref SOCK_CLOSED : Closed
- * - @ref SOCK_INIT : Initiate state
- * - @ref SOCK_LISTEN : Listen state
- * - @ref SOCK_ESTABLISHED : Success to connect
- * - @ref SOCK_CLOSE_WAIT : Closing state
- * - @ref SOCK_UDP : UDP socket
- * - @ref SOCK_MACRAW : MAC raw mode socket
- *@par Temporary status during changing the status of Socket n.
- * - @ref SOCK_SYNSENT : This indicates Socket n sent the connect-request packet (SYN packet) to a peer.
- * - @ref SOCK_SYNRECV : It indicates Socket n successfully received the connect-request packet (SYN packet) from a peer.
- * - @ref SOCK_FIN_WAIT : Connection state
- * - @ref SOCK_CLOSING : Closing state
- * - @ref SOCK_TIME_WAIT : Closing state
- * - @ref SOCK_LAST_ACK : Closing state
- */
-#define Sn_SR(N) WIZCHIP_SREG_ADDR(N, 0x0003)
-
-/**
- * @ingroup Socket_register_group
- * @brief source port register(R/W)
- * @details @ref Sn_PORT configures the source port number of Socket n.
- * It is valid when Socket n is used in TCP/UPD mode. It should be set before OPEN command is ordered.
- */
-#define Sn_PORT(N) WIZCHIP_SREG_ADDR(N, 0x0004)
-
-/**
- * @ingroup Socket_register_group
- * @brief Peer MAC register address(R/W)
- * @details @ref Sn_DHAR configures the destination hardware address of Socket n when using SEND_MAC command in UDP mode or
- * it indicates that it is acquired in ARP-process by CONNECT/SEND command.
- */
-#define Sn_DHAR(N) WIZCHIP_SREG_ADDR(N, 0x0006)
-
-/**
- * @ingroup Socket_register_group
- * @brief Peer IP register address(R/W)
- * @details @ref Sn_DIPR configures or indicates the destination IP address of Socket n. It is valid when Socket n is used in TCP/UDP mode.
- * In TCP client mode, it configures an IP address of �TCP serverbefore CONNECT command.
- * In TCP server mode, it indicates an IP address of �TCP clientafter successfully establishing connection.
- * In UDP mode, it configures an IP address of peer to be received the UDP packet by SEND or SEND_MAC command.
- */
-#define Sn_DIPR(N) WIZCHIP_SREG_ADDR(N, 0x000c)
-
-/**
- * @ingroup Socket_register_group
- * @brief Peer port register address(R/W)
- * @details @ref Sn_DPORT configures or indicates the destination port number of Socket n. It is valid when Socket n is used in TCP/UDP mode.
- * In �TCP clientmode, it configures the listen port number of �TCP serverbefore CONNECT command.
- * In �TCP Servermode, it indicates the port number of TCP client after successfully establishing connection.
- * In UDP mode, it configures the port number of peer to be transmitted the UDP packet by SEND/SEND_MAC command.
- */
-#define Sn_DPORT(N) WIZCHIP_SREG_ADDR(N, 0x0010)
-
-/**
- * @ingroup Socket_register_group
- * @brief Maximum Segment Size(Sn_MSSR0) register address(R/W)
- * @details @ref Sn_MSSR configures or indicates the MTU(Maximum Transfer Unit) of Socket n.
- */
-#define Sn_MSSR(N) WIZCHIP_SREG_ADDR(N, 0x0012)
-
-// Reserved (_W5500_IO_BASE_ + (0x0014 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
-
-/**
- * @ingroup Socket_register_group
- * @brief IP Type of Service(TOS) Register(R/W)
- * @details @ref Sn_TOS configures the TOS(Type Of Service field in IP Header) of Socket n.
- * It is set before OPEN command.
- */
-#define Sn_TOS(N) WIZCHIP_SREG_ADDR(N, 0x0015)
-/**
- * @ingroup Socket_register_group
- * @brief IP Time to live(TTL) Register(R/W)
- * @details @ref Sn_TTL configures the TTL(Time To Live field in IP header) of Socket n.
- * It is set before OPEN command.
- */
-#define Sn_TTL(N) WIZCHIP_SREG_ADDR(N, 0x0016)
-// Reserved (_W5500_IO_BASE_ + (0x0017 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
-// Reserved (_W5500_IO_BASE_ + (0x0018 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
-// Reserved (_W5500_IO_BASE_ + (0x0019 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
-// Reserved (_W5500_IO_BASE_ + (0x001A << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
-// Reserved (_W5500_IO_BASE_ + (0x001B << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
-// Reserved (_W5500_IO_BASE_ + (0x001C << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
-// Reserved (_W5500_IO_BASE_ + (0x001D << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
-
-/**
- * @ingroup Socket_register_group
- * @brief Receive memory size register(R/W)
- * @details @ref Sn_RXBUF_SIZE configures the RX buffer block size of Socket n.
- * Socket n RX Buffer Block size can be configured with 1,2,4,8, and 16 Kbytes.
- * If a different size is configured, the data cannot be normally received from a peer.
- * Although Socket n RX Buffer Block size is initially configured to 2Kbytes,
- * user can re-configure its size using @ref Sn_RXBUF_SIZE. The total sum of @ref Sn_RXBUF_SIZE can not be exceed 16Kbytes.
- * When exceeded, the data reception error is occurred.
- */
-#define Sn_RXBUF_SIZE(N) WIZCHIP_SREG_ADDR(N, 0x001e)
-
-/**
- * @ingroup Socket_register_group
- * @brief Transmit memory size register(R/W)
- * @details @ref Sn_TXBUF_SIZE configures the TX buffer block size of Socket n. Socket n TX Buffer Block size can be configured with 1,2,4,8, and 16 Kbytes.
- * If a different size is configured, the data can�t be normally transmitted to a peer.
- * Although Socket n TX Buffer Block size is initially configured to 2Kbytes,
- * user can be re-configure its size using @ref Sn_TXBUF_SIZE. The total sum of @ref Sn_TXBUF_SIZE can not be exceed 16Kbytes.
- * When exceeded, the data transmission error is occurred.
- */
-#define Sn_TXBUF_SIZE(N) WIZCHIP_SREG_ADDR(N, 0x001f)
-
-/**
- * @ingroup Socket_register_group
- * @brief Transmit free memory size register(R)
- * @details @ref Sn_TX_FSR indicates the free size of Socket n TX Buffer Block. It is initialized to the configured size by @ref Sn_TXBUF_SIZE.
- * Data bigger than @ref Sn_TX_FSR should not be saved in the Socket n TX Buffer because the bigger data overwrites the previous saved data not yet sent.
- * Therefore, check before saving the data to the Socket n TX Buffer, and if data is equal or smaller than its checked size,
- * transmit the data with SEND/SEND_MAC command after saving the data in Socket n TX buffer. But, if data is bigger than its checked size,
- * transmit the data after dividing into the checked size and saving in the Socket n TX buffer.
- */
-#define Sn_TX_FSR(N) WIZCHIP_SREG_ADDR(N, 0x0020)
-
-/**
- * @ingroup Socket_register_group
- * @brief Transmit memory read pointer register address(R)
- * @details @ref Sn_TX_RD is initialized by OPEN command. However, if Sn_MR(P[3:0]) is TCP mode(001, it is re-initialized while connecting with TCP.
- * After its initialization, it is auto-increased by SEND command.
- * SEND command transmits the saved data from the current @ref Sn_TX_RD to the @ref Sn_TX_WR in the Socket n TX Buffer.
- * After transmitting the saved data, the SEND command increases the @ref Sn_TX_RD as same as the @ref Sn_TX_WR.
- * If its increment value exceeds the maximum value 0xFFFF, (greater than 0x10000 and the carry bit occurs),
- * then the carry bit is ignored and will automatically update with the lower 16bits value.
- */
-#define Sn_TX_RD(N) WIZCHIP_SREG_ADDR(N, 0x0022)
-
-/**
- * @ingroup Socket_register_group
- * @brief Transmit memory write pointer register address(R/W)
- * @details @ref Sn_TX_WR is initialized by OPEN command. However, if Sn_MR(P[3:0]) is TCP mode(001, it is re-initialized while connecting with TCP.\n
- * It should be read or be updated like as follows.\n
- * 1. Read the starting address for saving the transmitting data.\n
- * 2. Save the transmitting data from the starting address of Socket n TX buffer.\n
- * 3. After saving the transmitting data, update @ref Sn_TX_WR to the increased value as many as transmitting data size.
- * If the increment value exceeds the maximum value 0xFFFF(greater than 0x10000 and the carry bit occurs),
- * then the carry bit is ignored and will automatically update with the lower 16bits value.\n
- * 4. Transmit the saved data in Socket n TX Buffer by using SEND/SEND command
- */
-#define Sn_TX_WR(N) WIZCHIP_SREG_ADDR(N, 0x0024)
-
-/**
- * @ingroup Socket_register_group
- * @brief Received data size register(R)
- * @details @ref Sn_RX_RSR indicates the data size received and saved in Socket n RX Buffer.
- * @ref Sn_RX_RSR does not exceed the @ref Sn_RXBUF_SIZE and is calculated as the difference between
- * �Socket n RX Write Pointer (@ref Sn_RX_WR)and �Socket n RX Read Pointer (@ref Sn_RX_RD)
- */
-#define Sn_RX_RSR(N) WIZCHIP_SREG_ADDR(N, 0x0026)
-
-/**
- * @ingroup Socket_register_group
- * @brief Read point of Receive memory(R/W)
- * @details @ref Sn_RX_RD is initialized by OPEN command. Make sure to be read or updated as follows.\n
- * 1. Read the starting save address of the received data.\n
- * 2. Read data from the starting address of Socket n RX Buffer.\n
- * 3. After reading the received data, Update @ref Sn_RX_RD to the increased value as many as the reading size.
- * If the increment value exceeds the maximum value 0xFFFF, that is, is greater than 0x10000 and the carry bit occurs,
- * update with the lower 16bits value ignored the carry bit.\n
- * 4. Order RECV command is for notifying the updated @ref Sn_RX_RD to W5500.
- */
-#define Sn_RX_RD(N) WIZCHIP_SREG_ADDR(N, 0x0028)
-
-/**
- * @ingroup Socket_register_group
- * @brief Write point of Receive memory(R)
- * @details @ref Sn_RX_WR is initialized by OPEN command and it is auto-increased by the data reception.
- * If the increased value exceeds the maximum value 0xFFFF, (greater than 0x10000 and the carry bit occurs),
- * then the carry bit is ignored and will automatically update with the lower 16bits value.
- */
-#define Sn_RX_WR(N) WIZCHIP_SREG_ADDR(N, 0x002a)
-
-/**
- * @ingroup Socket_register_group
- * @brief socket interrupt mask register(R)
- * @details @ref Sn_IMR masks the interrupt of Socket n.
- * Each bit corresponds to each bit of @ref Sn_IR. When a Socket n Interrupt is occurred and the corresponding bit of @ref Sn_IMR is
- * the corresponding bit of @ref Sn_IR becomes When both the corresponding bit of @ref Sn_IMR and @ref Sn_IR are and the n-th bit of @ref IR is
- * Host is interrupted by asserted INTn PIN to low.
- */
-//#define Sn_IMR(N) (_W5500_IO_BASE_ + (0x002C << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
-
-/**
- * @ingroup Socket_register_group
- * @brief Fragment field value in IP header register(R/W)
- * @details @ref Sn_FRAG configures the FRAG(Fragment field in IP header).
- */
-//#define Sn_FRAG(N) (_W5500_IO_BASE_ + (0x002D << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
-
-/**
- * @ingroup Socket_register_group
- * @brief Keep Alive Timer register(R/W)
- * @details @ref Sn_KPALVTR configures the transmitting timer of �KEEP ALIVE(KA)packet of SOCKETn. It is valid only in TCP mode,
- * and ignored in other modes. The time unit is 5s.
- * KA packet is transmittable after @ref Sn_SR is changed to SOCK_ESTABLISHED and after the data is transmitted or received to/from a peer at least once.
- * In case of '@ref Sn_KPALVTR > 0', W5500 automatically transmits KA packet after time-period for checking the TCP connection (Auto-keepalive-process).
- * In case of '@ref Sn_KPALVTR = 0', Auto-keep-alive-process will not operate,
- * and KA packet can be transmitted by SEND_KEEP command by the host (Manual-keep-alive-process).
- * Manual-keep-alive-process is ignored in case of '@ref Sn_KPALVTR > 0'.
- */
-//#define Sn_KPALVTR(N) (_W5500_IO_BASE_ + (0x002F << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
-
-//#define Sn_TSR(N) (_W5500_IO_BASE_ + (0x0030 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
-
-
-//----------------------------- W5500 Register values -----------------------------
-
-/* MODE register values */
-/**
- * @brief Reset
- * @details If this bit is All internal registers will be initialized. It will be automatically cleared as after S/W reset.
- */
-#define MR_RST 0x80
-
-/**
- * @brief Wake on LAN
- * @details 0 : Disable WOL mode\n
- * 1 : Enable WOL mode\n
- * If WOL mode is enabled and the received magic packet over UDP has been normally processed, the Interrupt PIN (INTn) asserts to low.
- * When using WOL mode, the UDP Socket should be opened with any source port number. (Refer to Socket n Mode Register (@ref Sn_MR) for opening Socket.)
- * @note The magic packet over UDP supported by W5500 consists of 6 bytes synchronization stream (xFFFFFFFFFFFF and
- * 16 times Target MAC address stream in UDP payload. The options such like password are ignored. You can use any UDP source port number for WOL mode.
- */
-#define MR_WOL 0x20
-
-/**
- * @brief Ping block
- * @details 0 : Disable Ping block\n
- * 1 : Enable Ping block\n
- * If the bit is it blocks the response to a ping request.
- */
-#define MR_PB 0x10
-
-/**
- * @brief Enable PPPoE
- * @details 0 : DisablePPPoE mode\n
- * 1 : EnablePPPoE mode\n
- * If you use ADSL, this bit should be
- */
-#define MR_PPPOE 0x08
-
-/**
- * @brief Enable UDP_FORCE_ARP CHECHK
- * @details 0 : Disable Force ARP mode\n
- * 1 : Enable Force ARP mode\n
- * In Force ARP mode, It forces on sending ARP Request whenever data is sent.
- */
-#define MR_FARP 0x02
-
-/* IR register values */
-/**
- * @brief Check IP conflict.
- * @details Bit is set as when own source IP address is same with the sender IP address in the received ARP request.
- */
-#define IR_CONFLICT 0x80
-
-/**
- * @brief Get the destination unreachable message in UDP sending.
- * @details When receiving the ICMP (Destination port unreachable) packet, this bit is set as
- * When this bit is Destination Information such as IP address and Port number may be checked with the corresponding @ref UIPR & @ref UPORTR.
- */
-#define IR_UNREACH 0x40
-
-/**
- * @brief Get the PPPoE close message.
- * @details When PPPoE is disconnected during PPPoE mode, this bit is set.
- */
-#define IR_PPPoE 0x20
-
-/**
- * @brief Get the magic packet interrupt.
- * @details When WOL mode is enabled and receives the magic packet over UDP, this bit is set.
- */
-#define IR_MP 0x10
-
-
-/* PHYCFGR register value */
-#define PHYCFGR_RST ~(1<<7) //< For PHY reset, must operate AND mask.
-#define PHYCFGR_OPMD (1<<6) // Configre PHY with OPMDC value
-#define PHYCFGR_OPMDC_ALLA (7<<3)
-#define PHYCFGR_OPMDC_PDOWN (6<<3)
-#define PHYCFGR_OPMDC_NA (5<<3)
-#define PHYCFGR_OPMDC_100FA (4<<3)
-#define PHYCFGR_OPMDC_100F (3<<3)
-#define PHYCFGR_OPMDC_100H (2<<3)
-#define PHYCFGR_OPMDC_10F (1<<3)
-#define PHYCFGR_OPMDC_10H (0<<3)
-#define PHYCFGR_DPX_FULL (1<<2)
-#define PHYCFGR_DPX_HALF (0<<2)
-#define PHYCFGR_SPD_100 (1<<1)
-#define PHYCFGR_SPD_10 (0<<1)
-#define PHYCFGR_LNK_ON (1<<0)
-#define PHYCFGR_LNK_OFF (0<<0)
-
-// PHYSTATUS register
-#define PHYSTATUS_POWERDOWN (0x08)
-#define PHYSTATUS_LINK (0x20)
-
-/* IMR register values */
-/**
- * @brief IP Conflict Interrupt Mask.
- * @details 0: Disable IP Conflict Interrupt\n
- * 1: Enable IP Conflict Interrupt
- */
-#define IM_IR7 0x80
-
-/**
- * @brief Destination unreachable Interrupt Mask.
- * @details 0: Disable Destination unreachable Interrupt\n
- * 1: Enable Destination unreachable Interrupt
- */
-#define IM_IR6 0x40
-
-/**
- * @brief PPPoE Close Interrupt Mask.
- * @details 0: Disable PPPoE Close Interrupt\n
- * 1: Enable PPPoE Close Interrupt
- */
-#define IM_IR5 0x20
-
-/**
- * @brief Magic Packet Interrupt Mask.
- * @details 0: Disable Magic Packet Interrupt\n
- * 1: Enable Magic Packet Interrupt
- */
-#define IM_IR4 0x10
-
-/* Sn_MR Default values */
-/**
- * @brief Support UDP Multicasting
- * @details 0 : disable Multicasting\n
- * 1 : enable Multicasting\n
- * This bit is applied only during UDP mode(P[3:0] = 010.\n
- * To use multicasting, @ref Sn_DIPR & @ref Sn_DPORT should be respectively configured with the multicast group IP address & port number
- * before Socket n is opened by OPEN command of @ref Sn_CR.
- */
-#define Sn_MR_MULTI 0x80
-
-/**
- * @brief Broadcast block in UDP Multicasting.
- * @details 0 : disable Broadcast Blocking\n
- * 1 : enable Broadcast Blocking\n
- * This bit blocks to receive broadcasting packet during UDP mode(P[3:0] = 010.\m
- * In addition, This bit does when MACRAW mode(P[3:0] = 100
- */
-//#define Sn_MR_BCASTB 0x40
-
-/**
- * @brief No Delayed Ack(TCP), Multicast flag
- * @details 0 : Disable No Delayed ACK option\n
- * 1 : Enable No Delayed ACK option\n
- * This bit is applied only during TCP mode (P[3:0] = 001.\n
- * When this bit is It sends the ACK packet without delay as soon as a Data packet is received from a peer.\n
- * When this bit is It sends the ACK packet after waiting for the timeout time configured by @ref RTR.
- */
-#define Sn_MR_ND 0x20
-
-/**
- * @brief Unicast Block in UDP Multicasting
- * @details 0 : disable Unicast Blocking\n
- * 1 : enable Unicast Blocking\n
- * This bit blocks receiving the unicast packet during UDP mode(P[3:0] = 010 and MULTI =
- */
-//#define Sn_MR_UCASTB 0x10
-
-/**
- * @brief MAC LAYER RAW SOCK
- * @details This configures the protocol mode of Socket n.
- * @note MACRAW mode should be only used in Socket 0.
- */
-#define Sn_MR_MACRAW 0x04
-
-#define Sn_MR_IPRAW 0x03 /**< IP LAYER RAW SOCK */
-
-/**
- * @brief UDP
- * @details This configures the protocol mode of Socket n.
- */
-#define Sn_MR_UDP 0x02
-
-/**
- * @brief TCP
- * @details This configures the protocol mode of Socket n.
- */
-#define Sn_MR_TCP 0x01
-
-/**
- * @brief Unused socket
- * @details This configures the protocol mode of Socket n.
- */
-#define Sn_MR_CLOSE 0x00
-
-/* Sn_MR values used with Sn_MR_MACRAW */
-/**
- * @brief MAC filter enable in @ref Sn_MR_MACRAW mode
- * @details 0 : disable MAC Filtering\n
- * 1 : enable MAC Filtering\n
- * This bit is applied only during MACRAW mode(P[3:0] = 100.\n
- * When set as W5500 can only receive broadcasting packet or packet sent to itself.
- * When this bit is W5500 can receive all packets on Ethernet.
- * If user wants to implement Hybrid TCP/IP stack,
- * it is recommended that this bit is set as for reducing host overhead to process the all received packets.
- */
-#define Sn_MR_MFEN Sn_MR_MULTI
-
-/**
- * @brief Multicast Blocking in @ref Sn_MR_MACRAW mode
- * @details 0 : using IGMP version 2\n
- * 1 : using IGMP version 1\n
- * This bit is applied only during UDP mode(P[3:0] = 010 and MULTI =
- * It configures the version for IGMP messages (Join/Leave/Report).
- */
-#define Sn_MR_MMB Sn_MR_ND
-
-/**
- * @brief IPv6 packet Blocking in @ref Sn_MR_MACRAW mode
- * @details 0 : disable IPv6 Blocking\n
- * 1 : enable IPv6 Blocking\n
- * This bit is applied only during MACRAW mode (P[3:0] = 100. It blocks to receiving the IPv6 packet.
- */
-#define Sn_MR_MIP6B Sn_MR_UCASTB
-
-/* Sn_MR value used with Sn_MR_UDP & Sn_MR_MULTI */
-/**
- * @brief IGMP version used in UDP mulitcasting
- * @details 0 : disable Multicast Blocking\n
- * 1 : enable Multicast Blocking\n
- * This bit is applied only when MACRAW mode(P[3:0] = 100. It blocks to receive the packet with multicast MAC address.
- */
-#define Sn_MR_MC Sn_MR_ND
-
-/* Sn_MR alternate values */
-/**
- * @brief For Berkeley Socket API
- */
-#define SOCK_STREAM Sn_MR_TCP
-
-/**
- * @brief For Berkeley Socket API
- */
-#define SOCK_DGRAM Sn_MR_UDP
-
-
-/* Sn_CR values */
-/**
- * @brief Initialize or open socket
- * @details Socket n is initialized and opened according to the protocol selected in Sn_MR(P3:P0).
- * The table below shows the value of @ref Sn_SR corresponding to @ref Sn_MR.\n
- *
- *
\b Sn_MR (P[3:0])
\b Sn_SR
- *
Sn_MR_CLOSE (000
- *
Sn_MR_TCP (001
SOCK_INIT (0x13)
- *
Sn_MR_UDP (010
SOCK_UDP (0x22)
- *
S0_MR_MACRAW (100
SOCK_MACRAW (0x02)
- *
- */
-#define Sn_CR_OPEN 0x01
-
-/**
- * @brief Wait connection request in TCP mode(Server mode)
- * @details This is valid only in TCP mode (Sn_MR(P3:P0) = Sn_MR_TCP).
- * In this mode, Socket n operates as a �TCP serverand waits for connection-request (SYN packet) from any �TCP client
- * The @ref Sn_SR changes the state from SOCK_INIT to SOCKET_LISTEN.
- * When a �TCP clientconnection request is successfully established,
- * the @ref Sn_SR changes from SOCK_LISTEN to SOCK_ESTABLISHED and the Sn_IR(0) becomes
- * But when a �TCP clientconnection request is failed, Sn_IR(3) becomes and the status of @ref Sn_SR changes to SOCK_CLOSED.
- */
-#define Sn_CR_LISTEN 0x02
-
-/**
- * @brief Send connection request in TCP mode(Client mode)
- * @details To connect, a connect-request (SYN packet) is sent to b>TCP serverconfigured by @ref Sn_DIPR & Sn_DPORT(destination address & port).
- * If the connect-request is successful, the @ref Sn_SR is changed to @ref SOCK_ESTABLISHED and the Sn_IR(0) becomes \n\n
- * The connect-request fails in the following three cases.\n
- * 1. When a @b ARPTO occurs (@ref Sn_IR[3] = ) because destination hardware address is not acquired through the ARP-process.\n
- * 2. When a @b SYN/ACK packet is not received and @b TCPTO (Sn_IR(3) = )\n
- * 3. When a @b RST packet is received instead of a @b SYN/ACK packet. In these cases, @ref Sn_SR is changed to @ref SOCK_CLOSED.
- * @note This is valid only in TCP mode and operates when Socket n acts as b>TCP client
- */
-#define Sn_CR_CONNECT 0x04
-
-/**
- * @brief Send closing request in TCP mode
- * @details Regardless of b>TCP serveror b>TCP client the DISCON command processes the disconnect-process (b>Active closeor b>Passive close.\n
- * @par Active close
- * it transmits disconnect-request(FIN packet) to the connected peer\n
- * @par Passive close
- * When FIN packet is received from peer, a FIN packet is replied back to the peer.\n
- * @details When the disconnect-process is successful (that is, FIN/ACK packet is received successfully), @ref Sn_SR is changed to @ref SOCK_CLOSED.\n
- * Otherwise, TCPTO occurs (Sn_IR(3)=)= and then @ref Sn_SR is changed to @ref SOCK_CLOSED.
- * @note Valid only in TCP mode.
- */
-#define Sn_CR_DISCON 0x08
-
-/**
- * @brief Close socket
- * @details Sn_SR is changed to @ref SOCK_CLOSED.
- */
-#define Sn_CR_CLOSE 0x10
-
-/**
- * @brief Update TX buffer pointer and send data
- * @details SEND transmits all the data in the Socket n TX buffer.\n
- * For more details, please refer to Socket n TX Free Size Register (@ref Sn_TX_FSR), Socket n,
- * TX Write Pointer Register(@ref Sn_TX_WR), and Socket n TX Read Pointer Register(@ref Sn_TX_RD).
- */
-#define Sn_CR_SEND 0x20
-
-/**
- * @brief Send data with MAC address, so without ARP process
- * @details The basic operation is same as SEND.\n
- * Normally SEND transmits data after destination hardware address is acquired by the automatic ARP-process(Address Resolution Protocol).\n
- * But SEND_MAC transmits data without the automatic ARP-process.\n
- * In this case, the destination hardware address is acquired from @ref Sn_DHAR configured by host, instead of APR-process.
- * @note Valid only in UDP mode.
- */
-#define Sn_CR_SEND_MAC 0x21
-
-/**
- * @brief Send keep alive message
- * @details It checks the connection status by sending 1byte keep-alive packet.\n
- * If the peer can not respond to the keep-alive packet during timeout time, the connection is terminated and the timeout interrupt will occur.
- * @note Valid only in TCP mode.
- */
-#define Sn_CR_SEND_KEEP 0x22
-
-/**
- * @brief Update RX buffer pointer and receive data
- * @details RECV completes the processing of the received data in Socket n RX Buffer by using a RX read pointer register (@ref Sn_RX_RD).\n
- * For more details, refer to Socket n RX Received Size Register (@ref Sn_RX_RSR), Socket n RX Write Pointer Register (@ref Sn_RX_WR),
- * and Socket n RX Read Pointer Register (@ref Sn_RX_RD).
- */
-#define Sn_CR_RECV 0x40
-
-/* Sn_IR values */
-/**
- * @brief SEND_OK Interrupt
- * @details This is issued when SEND command is completed.
- */
-#define Sn_IR_SENDOK 0x10
-
-/**
- * @brief TIMEOUT Interrupt
- * @details This is issued when ARPTO or TCPTO occurs.
- */
-#define Sn_IR_TIMEOUT 0x08
-
-/**
- * @brief RECV Interrupt
- * @details This is issued whenever data is received from a peer.
- */
-#define Sn_IR_RECV 0x04
-
-/**
- * @brief DISCON Interrupt
- * @details This is issued when FIN or FIN/ACK packet is received from a peer.
- */
-#define Sn_IR_DISCON 0x02
-
-/**
- * @brief CON Interrupt
- * @details This is issued one time when the connection with peer is successful and then @ref Sn_SR is changed to @ref SOCK_ESTABLISHED.
- */
-#define Sn_IR_CON 0x01
-
-/* Sn_SR values */
-/**
- * @brief Closed
- * @details This indicates that Socket n is released.\N
- * When DICON, CLOSE command is ordered, or when a timeout occurs, it is changed to @ref SOCK_CLOSED regardless of previous status.
- */
-#define SOCK_CLOSED 0x00
-
-/**
- * @brief Initiate state
- * @details This indicates Socket n is opened with TCP mode.\N
- * It is changed to @ref SOCK_INIT when Sn_MR(P[3:0]) = 001and OPEN command is ordered.\N
- * After @ref SOCK_INIT, user can use LISTEN /CONNECT command.
- */
-#define SOCK_INIT 0x13
-
-/**
- * @brief Listen state
- * @details This indicates Socket n is operating as b>TCP servermode and waiting for connection-request (SYN packet) from a peer (b>TCP client.\n
- * It will change to @ref SOCK_ESTALBLISHED when the connection-request is successfully accepted.\n
- * Otherwise it will change to @ref SOCK_CLOSED after TCPTO occurred (Sn_IR(TIMEOUT) = .
- */
-#define SOCK_LISTEN 0x14
-
-/**
- * @brief Connection state
- * @details This indicates Socket n sent the connect-request packet (SYN packet) to a peer.\n
- * It is temporarily shown when @ref Sn_SR is changed from @ref SOCK_INIT to @ref SOCK_ESTABLISHED by CONNECT command.\n
- * If connect-accept(SYN/ACK packet) is received from the peer at SOCK_SYNSENT, it changes to @ref SOCK_ESTABLISHED.\n
- * Otherwise, it changes to @ref SOCK_CLOSED after TCPTO (@ref Sn_IR[TIMEOUT] = is occurred.
- */
-#define SOCK_SYNSENT 0x15
-
-/**
- * @brief Connection state
- * @details It indicates Socket n successfully received the connect-request packet (SYN packet) from a peer.\n
- * If socket n sends the response (SYN/ACK packet) to the peer successfully, it changes to @ref SOCK_ESTABLISHED. \n
- * If not, it changes to @ref SOCK_CLOSED after timeout occurs (@ref Sn_IR[TIMEOUT] = .
- */
-#define SOCK_SYNRECV 0x16
-
-/**
- * @brief Success to connect
- * @details This indicates the status of the connection of Socket n.\n
- * It changes to @ref SOCK_ESTABLISHED when the b>TCP SERVERprocessed the SYN packet from the b>TCP CLIENTduring @ref SOCK_LISTEN, or
- * when the CONNECT command is successful.\n
- * During @ref SOCK_ESTABLISHED, DATA packet can be transferred using SEND or RECV command.
- */
-#define SOCK_ESTABLISHED 0x17
-
-/**
- * @brief Closing state
- * @details These indicate Socket n is closing.\n
- * These are shown in disconnect-process such as active-close and passive-close.\n
- * When Disconnect-process is successfully completed, or when timeout occurs, these change to @ref SOCK_CLOSED.
- */
-#define SOCK_FIN_WAIT 0x18
-
-/**
- * @brief Closing state
- * @details These indicate Socket n is closing.\n
- * These are shown in disconnect-process such as active-close and passive-close.\n
- * When Disconnect-process is successfully completed, or when timeout occurs, these change to @ref SOCK_CLOSED.
- */
-#define SOCK_CLOSING 0x1A
-
-/**
- * @brief Closing state
- * @details These indicate Socket n is closing.\n
- * These are shown in disconnect-process such as active-close and passive-close.\n
- * When Disconnect-process is successfully completed, or when timeout occurs, these change to @ref SOCK_CLOSED.
- */
-#define SOCK_TIME_WAIT 0x1B
-
-/**
- * @brief Closing state
- * @details This indicates Socket n received the disconnect-request (FIN packet) from the connected peer.\n
- * This is half-closing status, and data can be transferred.\n
- * For full-closing, DISCON command is used. But For just-closing, CLOSE command is used.
- */
-#define SOCK_CLOSE_WAIT 0x1C
-
-/**
- * @brief Closing state
- * @details This indicates Socket n is waiting for the response (FIN/ACK packet) to the disconnect-request (FIN packet) by passive-close.\n
- * It changes to @ref SOCK_CLOSED when Socket n received the response successfully, or when timeout occurs (@ref Sn_IR[TIMEOUT] = .
- */
-#define SOCK_LAST_ACK 0x1D
-
-/**
- * @brief UDP socket
- * @details This indicates Socket n is opened in UDP mode(Sn_MR(P[3:0]) = 010.\n
- * It changes to SOCK_UPD when Sn_MR(P[3:0]) = 010 and OPEN command is ordered.\n
- * Unlike TCP mode, data can be transfered without the connection-process.
- */
-#define SOCK_UDP 0x22
-
-//#define SOCK_IPRAW 0x32 /**< IP raw mode socket */
-
-/**
- * @brief MAC raw mode socket
- * @details This indicates Socket 0 is opened in MACRAW mode (S0_MR(P[3:0]) = 100and is valid only in Socket 0.\n
- * It changes to SOCK_MACRAW when S0_MR(P[3:0] = 100and OPEN command is ordered.\n
- * Like UDP mode socket, MACRAW mode Socket 0 can transfer a MAC packet (Ethernet frame) without the connection-process.
- */
-#define SOCK_MACRAW 0x42
-
-//#define SOCK_PPPOE 0x5F
-
-/* IP PROTOCOL */
-#define IPPROTO_IP 0 //< Dummy for IP
-#define IPPROTO_ICMP 1 //< Control message protocol
-#define IPPROTO_IGMP 2 //< Internet group management protocol
-#define IPPROTO_GGP 3 //< Gateway^2 (deprecated)
-#define IPPROTO_TCP 6 //< TCP
-#define IPPROTO_PUP 12 //< PUP
-#define IPPROTO_UDP 17 //< UDP
-#define IPPROTO_IDP 22 //< XNS idp
-#define IPPROTO_ND 77 //< UNOFFICIAL net disk protocol
-#define IPPROTO_RAW 255 //< Raw IP packet
-
-
-/**
- * @brief Enter a critical section
- *
- * @details It is provided to protect your shared code which are executed without distribution. \n \n
- *
- * In non-OS environment, It can be just implemented by disabling whole interrupt.\n
- * In OS environment, You can replace it to critical section api supported by OS.
- *
- * \sa WIZCHIP_READ(), WIZCHIP_WRITE(), WIZCHIP_READ_BUF(), WIZCHIP_WRITE_BUF()
- * \sa WIZCHIP_CRITICAL_EXIT()
- */
-#define WIZCHIP_CRITICAL_ENTER() WIZCHIP.CRIS._enter()
-
-/**
- * @brief Exit a critical section
- *
- * @details It is provided to protect your shared code which are executed without distribution. \n\n
- *
- * In non-OS environment, It can be just implemented by disabling whole interrupt. \n
- * In OS environment, You can replace it to critical section api supported by OS.
- *
- * @sa WIZCHIP_READ(), WIZCHIP_WRITE(), WIZCHIP_READ_BUF(), WIZCHIP_WRITE_BUF()
- * @sa WIZCHIP_CRITICAL_ENTER()
- */
-#ifdef _exit
-#undef _exit
-#endif
-#define WIZCHIP_CRITICAL_EXIT() WIZCHIP.CRIS._exit()
-
-
-
-////////////////////////
-// Basic I/O Function //
-////////////////////////
-
-/**
- * @ingroup Basic_IO_function
- * @brief It reads 1 byte value from a register.
- * @param AddrSel Register address
- * @return The value of register
- */
-uint8_t WIZCHIP_READ (uint32_t AddrSel);
-
-/**
- * @ingroup Basic_IO_function
- * @brief It writes 1 byte value to a register.
- * @param AddrSel Register address
- * @param wb Write data
- * @return void
- */
-void WIZCHIP_WRITE(uint32_t AddrSel, uint8_t wb );
-
-/**
- * @ingroup Basic_IO_function
- * @brief It reads sequence data from registers.
- * @param AddrSel Register address
- * @param pBuf Pointer buffer to read data
- * @param len Data length
- */
-void WIZCHIP_READ_BUF (uint32_t AddrSel, uint8_t* pBuf, uint16_t len);
-
-/**
- * @ingroup Basic_IO_function
- * @brief It writes sequence data to registers.
- * @param AddrSel Register address
- * @param pBuf Pointer buffer to write data
- * @param len Data length
- */
-void WIZCHIP_WRITE_BUF(uint32_t AddrSel, uint8_t* pBuf, uint16_t len);
-
-/////////////////////////////////
-// Common Register I/O function //
-/////////////////////////////////
-/**
- * @ingroup Common_register_access_function
- * @brief Set Mode Register
- * @param (uint8_t)mr The value to be set.
- * @sa getMR()
- */
-#define setMR(mr) \
- WIZCHIP_WRITE(MR,mr)
-
-
-/**
- * @ingroup Common_register_access_function
- * @brief Get Mode Register
- * @return uint8_t. The value of Mode register.
- * @sa setMR()
- */
-#define getMR() \
- WIZCHIP_READ(MR)
-
-/**
- * @ingroup Common_register_access_function
- * @brief Set gateway IP address
- * @param (uint8_t*)gar Pointer variable to set gateway IP address. It should be allocated 4 bytes.
- * @sa getGAR()
- */
-#define setGAR(gar) \
- WIZCHIP_WRITE_BUF(GAR,gar,4)
-
-/**
- * @ingroup Common_register_access_function
- * @brief Get gateway IP address
- * @param (uint8_t*)gar Pointer variable to get gateway IP address. It should be allocated 4 bytes.
- * @sa setGAR()
- */
-#define getGAR(gar) \
- WIZCHIP_READ_BUF(GAR,gar,4)
-
-/**
- * @ingroup Common_register_access_function
- * @brief Set subnet mask address
- * @param (uint8_t*)subr Pointer variable to set subnet mask address. It should be allocated 4 bytes.
- * @sa getSUBR()
- */
-#define setSUBR(subr) \
- WIZCHIP_WRITE_BUF(SUBR, subr,4)
-
-
-/**
- * @ingroup Common_register_access_function
- * @brief Get subnet mask address
- * @param (uint8_t*)subr Pointer variable to get subnet mask address. It should be allocated 4 bytes.
- * @sa setSUBR()
- */
-#define getSUBR(subr) \
- WIZCHIP_READ_BUF(SUBR, subr, 4)
-
-/**
- * @ingroup Common_register_access_function
- * @brief Set local MAC address
- * @param (uint8_t*)shar Pointer variable to set local MAC address. It should be allocated 6 bytes.
- * @sa getSHAR()
- */
-#define setSHAR(shar) \
- WIZCHIP_WRITE_BUF(SHAR, shar, 6)
-
-/**
- * @ingroup Common_register_access_function
- * @brief Get local MAC address
- * @param (uint8_t*)shar Pointer variable to get local MAC address. It should be allocated 6 bytes.
- * @sa setSHAR()
- */
-#define getSHAR(shar) \
- WIZCHIP_READ_BUF(SHAR, shar, 6)
-
-/**
- * @ingroup Common_register_access_function
- * @brief Set local IP address
- * @param (uint8_t*)sipr Pointer variable to set local IP address. It should be allocated 4 bytes.
- * @sa getSIPR()
- */
-#define setSIPR(sipr) \
- WIZCHIP_WRITE_BUF(SIPR, sipr, 4)
-
-/**
- * @ingroup Common_register_access_function
- * @brief Get local IP address
- * @param (uint8_t*)sipr Pointer variable to get local IP address. It should be allocated 4 bytes.
- * @sa setSIPR()
- */
-#define getSIPR(sipr) \
- WIZCHIP_READ_BUF(SIPR, sipr, 4)
-
-/**
- * @ingroup Common_register_access_function
- * @brief Set INTLEVEL register
- * @param (uint16_t)intlevel Value to set @ref INTLEVEL register.
- * @sa getINTLEVEL()
- */
-// dpgeorge: not yet implemented
-#define setINTLEVEL(intlevel) (void)intlevel
-#if 0
-#define setINTLEVEL(intlevel) {\
- WIZCHIP_WRITE(INTLEVEL, (uint8_t)(intlevel >> 8)); \
- WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(INTLEVEL,1), (uint8_t) intlevel); \
- }
-#endif
-
-
-/**
- * @ingroup Common_register_access_function
- * @brief Get INTLEVEL register
- * @return uint16_t. Value of @ref INTLEVEL register.
- * @sa setINTLEVEL()
- */
-// dpgeorge: not yet implemented
-#define getINTLEVEL() (0)
-#if 0
-#define getINTLEVEL() \
- ((WIZCHIP_READ(INTLEVEL) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(INTLEVEL,1)))
-#endif
-
-/**
- * @ingroup Common_register_access_function
- * @brief Set @ref IR register
- * @param (uint8_t)ir Value to set @ref IR register.
- * @sa getIR()
- */
-#define setIR(ir) \
- WIZCHIP_WRITE(IR, (ir & 0xF0))
-
-/**
- * @ingroup Common_register_access_function
- * @brief Get @ref IR register
- * @return uint8_t. Value of @ref IR register.
- * @sa setIR()
- */
-#define getIR() \
- (WIZCHIP_READ(IR) & 0xF0)
-/**
- * @ingroup Common_register_access_function
- * @brief Set @ref IMR register
- * @param (uint8_t)imr Value to set @ref IMR register.
- * @sa getIMR()
- */
-#define setIMR(imr) \
- WIZCHIP_WRITE(IMR, imr)
-
-/**
- * @ingroup Common_register_access_function
- * @brief Get @ref IMR register
- * @return uint8_t. Value of @ref IMR register.
- * @sa setIMR()
- */
-#define getIMR() \
- WIZCHIP_READ(IMR)
-
-
-/**
- * @ingroup Common_register_access_function
- * @brief Set @ref SIR register
- * @param (uint8_t)sir Value to set @ref SIR register.
- * @sa getSIR()
- */
-// dpgeorge: not yet implemented
-#define setSIR(sir) ((void)sir)
-#if 0
-#define setSIR(sir) \
- WIZCHIP_WRITE(SIR, sir)
-#endif
-
-/**
- * @ingroup Common_register_access_function
- * @brief Get @ref SIR register
- * @return uint8_t. Value of @ref SIR register.
- * @sa setSIR()
- */
-// dpgeorge: not yet implemented
-#define getSIR() (0)
-#if 0
-#define getSIR() \
- WIZCHIP_READ(SIR)
-#endif
-
-/**
- * @ingroup Common_register_access_function
- * @brief Set @ref SIMR register
- * @param (uint8_t)simr Value to set @ref SIMR register.
- * @sa getSIMR()
- */
-// dpgeorge: not yet implemented
-#define setSIMR(simr) ((void)simr)
-#if 0
-#define setSIMR(simr) \
- WIZCHIP_WRITE(SIMR, simr)
-#endif
-
-/**
- * @ingroup Common_register_access_function
- * @brief Get @ref SIMR register
- * @return uint8_t. Value of @ref SIMR register.
- * @sa setSIMR()
- */
-// dpgeorge: not yet implemented
-#define getSIMR() (0)
-#if 0
-#define getSIMR() \
- WIZCHIP_READ(SIMR)
-#endif
-
-/**
- * @ingroup Common_register_access_function
- * @brief Set @ref RTR register
- * @param (uint16_t)rtr Value to set @ref RTR register.
- * @sa getRTR()
- */
-#define setRTR(rtr) {\
- WIZCHIP_WRITE(RTR, (uint8_t)(rtr >> 8)); \
- WIZCHIP_WRITE(RTR + 1, (uint8_t) rtr); \
- }
-
-/**
- * @ingroup Common_register_access_function
- * @brief Get @ref RTR register
- * @return uint16_t. Value of @ref RTR register.
- * @sa setRTR()
- */
-#define getRTR() \
- ((WIZCHIP_READ(RTR) << 8) + WIZCHIP_READ(RTR + 1))
-
-/**
- * @ingroup Common_register_access_function
- * @brief Set @ref RCR register
- * @param (uint8_t)rcr Value to set @ref RCR register.
- * @sa getRCR()
- */
-#define setRCR(rcr) \
- WIZCHIP_WRITE(RCR, rcr)
-
-/**
- * @ingroup Common_register_access_function
- * @brief Get @ref RCR register
- * @return uint8_t. Value of @ref RCR register.
- * @sa setRCR()
- */
-#define getRCR() \
- WIZCHIP_READ(RCR)
-
-//================================================== test done ===========================================================
-
-/**
- * @ingroup Common_register_access_function
- * @brief Set @ref PTIMER register
- * @param (uint8_t)ptimer Value to set @ref PTIMER register.
- * @sa getPTIMER()
- */
-#define setPTIMER(ptimer) \
- WIZCHIP_WRITE(PTIMER, ptimer)
-
-/**
- * @ingroup Common_register_access_function
- * @brief Get @ref PTIMER register
- * @return uint8_t. Value of @ref PTIMER register.
- * @sa setPTIMER()
- */
-#define getPTIMER() \
- WIZCHIP_READ(PTIMER)
-
-/**
- * @ingroup Common_register_access_function
- * @brief Set @ref PMAGIC register
- * @param (uint8_t)pmagic Value to set @ref PMAGIC register.
- * @sa getPMAGIC()
- */
-#define setPMAGIC(pmagic) \
- WIZCHIP_WRITE(PMAGIC, pmagic)
-
-/**
- * @ingroup Common_register_access_function
- * @brief Get @ref PMAGIC register
- * @return uint8_t. Value of @ref PMAGIC register.
- * @sa setPMAGIC()
- */
-#define getPMAGIC() \
- WIZCHIP_READ(PMAGIC)
-
-/**
- * @ingroup Common_register_access_function
- * @brief Set PHAR address
- * @param (uint8_t*)phar Pointer variable to set PPP destination MAC register address. It should be allocated 6 bytes.
- * @sa getPHAR()
- */
-#if 0
-#define setPHAR(phar) \
- WIZCHIP_WRITE_BUF(PHAR, phar, 6)
-
-/**
- * @ingroup Common_register_access_function
- * @brief Get local IP address
- * @param (uint8_t*)phar Pointer variable to PPP destination MAC register address. It should be allocated 6 bytes.
- * @sa setPHAR()
- */
-#define getPHAR(phar) \
- WIZCHIP_READ_BUF(PHAR, phar, 6)
-
-/**
- * @ingroup Common_register_access_function
- * @brief Set @ref PSID register
- * @param (uint16_t)psid Value to set @ref PSID register.
- * @sa getPSID()
- */
-#define setPSID(psid) {\
- WIZCHIP_WRITE(PSID, (uint8_t)(psid >> 8)); \
- WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(PSID,1), (uint8_t) psid); \
- }
-
-/**
- * @ingroup Common_register_access_function
- * @brief Get @ref PSID register
- * @return uint16_t. Value of @ref PSID register.
- * @sa setPSID()
- */
-//uint16_t getPSID(void);
-#define getPSID() \
- ((WIZCHIP_READ(PSID) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(PSID,1)))
-
-/**
- * @ingroup Common_register_access_function
- * @brief Set @ref PMRU register
- * @param (uint16_t)pmru Value to set @ref PMRU register.
- * @sa getPMRU()
- */
-#define setPMRU(pmru) { \
- WIZCHIP_WRITE(PMRU, (uint8_t)(pmru>>8)); \
- WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(PMRU,1), (uint8_t) pmru); \
- }
-
-/**
- * @ingroup Common_register_access_function
- * @brief Get @ref PMRU register
- * @return uint16_t. Value of @ref PMRU register.
- * @sa setPMRU()
- */
-#define getPMRU() \
- ((WIZCHIP_READ(PMRU) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(PMRU,1)))
-
-/**
- * @ingroup Common_register_access_function
- * @brief Get unreachable IP address
- * @param (uint8_t*)uipr Pointer variable to get unreachable IP address. It should be allocated 4 bytes.
- */
-#define getUIPR(uipr) \
- WIZCHIP_READ_BUF(UIPR,uipr,6)
-
-/**
- * @ingroup Common_register_access_function
- * @brief Get @ref UPORTR register
- * @return uint16_t. Value of @ref UPORTR register.
- */
-#define getUPORTR() \
- ((WIZCHIP_READ(UPORTR) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(UPORTR,1)))
-
-/**
- * @ingroup Common_register_access_function
- * @brief Set @ref PHYCFGR register
- * @param (uint8_t)phycfgr Value to set @ref PHYCFGR register.
- * @sa getPHYCFGR()
- */
-#define setPHYCFGR(phycfgr) \
- WIZCHIP_WRITE(PHYCFGR, phycfgr)
-#endif
-
-/**
- * @ingroup Common_register_access_function
- * @brief Get @ref PHYCFGR register
- * @return uint8_t. Value of @ref PHYCFGR register.
- * @sa setPHYCFGR()
- */
-#define getPHYSTATUS() \
- WIZCHIP_READ(PHYSTATUS)
-
-/**
- * @ingroup Common_register_access_function
- * @brief Get @ref VERSIONR register
- * @return uint8_t. Value of @ref VERSIONR register.
- */
-/*
-#define getVERSIONR() \
- WIZCHIP_READ(VERSIONR)
- */
-/////////////////////////////////////
-
-///////////////////////////////////
-// Socket N register I/O function //
-///////////////////////////////////
-/**
- * @ingroup Socket_register_access_function
- * @brief Set @ref Sn_MR register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @param (uint8_t)mr Value to set @ref Sn_MR
- * @sa getSn_MR()
- */
-#define setSn_MR(sn, mr) \
- WIZCHIP_WRITE(Sn_MR(sn),mr)
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Get @ref Sn_MR register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @return uint8_t. Value of @ref Sn_MR.
- * @sa setSn_MR()
- */
-#define getSn_MR(sn) \
- WIZCHIP_READ(Sn_MR(sn))
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Set @ref Sn_CR register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @param (uint8_t)cr Value to set @ref Sn_CR
- * @sa getSn_CR()
- */
-#define setSn_CR(sn, cr) \
- WIZCHIP_WRITE(Sn_CR(sn), cr)
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Get @ref Sn_CR register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @return uint8_t. Value of @ref Sn_CR.
- * @sa setSn_CR()
- */
-#define getSn_CR(sn) \
- WIZCHIP_READ(Sn_CR(sn))
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Set @ref Sn_IR register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @param (uint8_t)ir Value to set @ref Sn_IR
- * @sa getSn_IR()
- */
-#define setSn_IR(sn, ir) \
- WIZCHIP_WRITE(Sn_IR(sn), (ir & 0x1F))
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Get @ref Sn_IR register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @return uint8_t. Value of @ref Sn_IR.
- * @sa setSn_IR()
- */
-#define getSn_IR(sn) \
- (WIZCHIP_READ(Sn_IR(sn)) & 0x1F)
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Set @ref Sn_IMR register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @param (uint8_t)imr Value to set @ref Sn_IMR
- * @sa getSn_IMR()
- */
-// dpgeorge: not yet implemented
-#define setSn_IMR(sn, imr) (void)sn; (void)imr
-#if 0
-#define setSn_IMR(sn, imr) \
- WIZCHIP_WRITE(Sn_IMR(sn), (imr & 0x1F))
-#endif
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Get @ref Sn_IMR register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @return uint8_t. Value of @ref Sn_IMR.
- * @sa setSn_IMR()
- */
-// dpgeorge: not yet implemented
-#define getSn_IMR(sn) (0)
-#if 0
-#define getSn_IMR(sn) \
- (WIZCHIP_READ(Sn_IMR(sn)) & 0x1F)
-#endif
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Get @ref Sn_SR register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @return uint8_t. Value of @ref Sn_SR.
- */
-#define getSn_SR(sn) \
- WIZCHIP_READ(Sn_SR(sn))
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Set @ref Sn_PORT register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @param (uint16_t)port Value to set @ref Sn_PORT.
- * @sa getSn_PORT()
- */
-#define setSn_PORT(sn, port) { \
- WIZCHIP_WRITE(Sn_PORT(sn), (uint8_t)(port >> 8)); \
- WIZCHIP_WRITE(Sn_PORT(sn) + 1, (uint8_t) port); \
- }
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Get @ref Sn_PORT register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @return uint16_t. Value of @ref Sn_PORT.
- * @sa setSn_PORT()
- */
-#define getSn_PORT(sn) \
- ((WIZCHIP_READ(Sn_PORT(sn)) << 8) | WIZCHIP_READ(Sn_PORT(sn) + 1))
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Set @ref Sn_DHAR register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @param (uint8_t*)dhar Pointer variable to set socket n destination hardware address. It should be allocated 6 bytes.
- * @sa getSn_DHAR()
- */
-#define setSn_DHAR(sn, dhar) \
- WIZCHIP_WRITE_BUF(Sn_DHAR(sn), dhar, 6)
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Get @ref Sn_MR register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @param (uint8_t*)dhar Pointer variable to get socket n destination hardware address. It should be allocated 6 bytes.
- * @sa setSn_DHAR()
- */
-#define getSn_DHAR(sn, dhar) \
- WIZCHIP_READ_BUF(Sn_DHAR(sn), dhar, 6)
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Set @ref Sn_DIPR register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @param (uint8_t*)dipr Pointer variable to set socket n destination IP address. It should be allocated 4 bytes.
- * @sa getSn_DIPR()
- */
-#define setSn_DIPR(sn, dipr) \
- WIZCHIP_WRITE_BUF(Sn_DIPR(sn), dipr, 4)
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Get @ref Sn_DIPR register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @param (uint8_t*)dipr Pointer variable to get socket n destination IP address. It should be allocated 4 bytes.
- * @sa SetSn_DIPR()
- */
-#define getSn_DIPR(sn, dipr) \
- WIZCHIP_READ_BUF(Sn_DIPR(sn), dipr, 4)
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Set @ref Sn_DPORT register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @param (uint16_t)dport Value to set @ref Sn_DPORT
- * @sa getSn_DPORT()
- */
-#define setSn_DPORT(sn, dport) { \
- WIZCHIP_WRITE(Sn_DPORT(sn), (uint8_t) (dport>>8)); \
- WIZCHIP_WRITE(Sn_DPORT(sn) + 1, (uint8_t) dport); \
- }
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Get @ref Sn_DPORT register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @return uint16_t. Value of @ref Sn_DPORT.
- * @sa setSn_DPORT()
- */
-#define getSn_DPORT(sn) \
- ((WIZCHIP_READ(Sn_DPORT(sn)) << 8) + WIZCHIP_READ((Sn_DPORT(sn)+1)))
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Set @ref Sn_MSSR register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @param (uint16_t)mss Value to set @ref Sn_MSSR
- * @sa setSn_MSSR()
- */
-#define setSn_MSSR(sn, mss) { \
- WIZCHIP_WRITE(Sn_MSSR(sn), (uint8_t)(mss>>8)); \
- WIZCHIP_WRITE((Sn_MSSR(sn)+1), (uint8_t) mss); \
- }
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Get @ref Sn_MSSR register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @return uint16_t. Value of @ref Sn_MSSR.
- * @sa setSn_MSSR()
- */
-#define getSn_MSSR(sn) \
- ((WIZCHIP_READ(Sn_MSSR(sn)) << 8) + WIZCHIP_READ((Sn_MSSR(sn)+1)))
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Set @ref Sn_TOS register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @param (uint8_t)tos Value to set @ref Sn_TOS
- * @sa getSn_TOS()
- */
-#define setSn_TOS(sn, tos) \
- WIZCHIP_WRITE(Sn_TOS(sn), tos)
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Get @ref Sn_TOS register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @return uint8_t. Value of Sn_TOS.
- * @sa setSn_TOS()
- */
-#define getSn_TOS(sn) \
- WIZCHIP_READ(Sn_TOS(sn))
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Set @ref Sn_TTL register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @param (uint8_t)ttl Value to set @ref Sn_TTL
- * @sa getSn_TTL()
- */
-#define setSn_TTL(sn, ttl) \
- WIZCHIP_WRITE(Sn_TTL(sn), ttl)
-
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Get @ref Sn_TTL register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @return uint8_t. Value of @ref Sn_TTL.
- * @sa setSn_TTL()
- */
-#define getSn_TTL(sn) \
- WIZCHIP_READ(Sn_TTL(sn))
-
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Set @ref Sn_RXBUF_SIZE register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @param (uint8_t)rxbufsize Value to set @ref Sn_RXBUF_SIZE
- * @sa getSn_RXBUF_SIZE()
- */
-#define setSn_RXBUF_SIZE(sn, rxbufsize) \
- WIZCHIP_WRITE(Sn_RXBUF_SIZE(sn),rxbufsize)
-
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Get @ref Sn_RXBUF_SIZE register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @return uint8_t. Value of @ref Sn_RXBUF_SIZE.
- * @sa setSn_RXBUF_SIZE()
- */
-#define getSn_RXBUF_SIZE(sn) \
- WIZCHIP_READ(Sn_RXBUF_SIZE(sn))
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Set @ref Sn_TXBUF_SIZE register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @param (uint8_t)txbufsize Value to set @ref Sn_TXBUF_SIZE
- * @sa getSn_TXBUF_SIZE()
- */
-#define setSn_TXBUF_SIZE(sn, txbufsize) \
- WIZCHIP_WRITE(Sn_TXBUF_SIZE(sn), txbufsize)
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Get @ref Sn_TXBUF_SIZE register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @return uint8_t. Value of @ref Sn_TXBUF_SIZE.
- * @sa setSn_TXBUF_SIZE()
- */
-#define getSn_TXBUF_SIZE(sn) \
- WIZCHIP_READ(Sn_TXBUF_SIZE(sn))
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Get @ref Sn_TX_FSR register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @return uint16_t. Value of @ref Sn_TX_FSR.
- */
-uint16_t getSn_TX_FSR(uint8_t sn);
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Get @ref Sn_TX_RD register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @return uint16_t. Value of @ref Sn_TX_RD.
- */
-#define getSn_TX_RD(sn) \
- ((WIZCHIP_READ(Sn_TX_RD(sn)) << 8) + WIZCHIP_READ((Sn_TX_RD(sn)+1)))
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Set @ref Sn_TX_WR register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @param (uint16_t)txwr Value to set @ref Sn_TX_WR
- * @sa GetSn_TX_WR()
- */
-#define setSn_TX_WR(sn, txwr) { \
- WIZCHIP_WRITE(Sn_TX_WR(sn), (uint8_t)(txwr>>8)); \
- WIZCHIP_WRITE((Sn_TX_WR(sn)+1), (uint8_t) txwr); \
- }
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Get @ref Sn_TX_WR register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @return uint16_t. Value of @ref Sn_TX_WR.
- * @sa setSn_TX_WR()
- */
-#define getSn_TX_WR(sn) \
- ((WIZCHIP_READ(Sn_TX_WR(sn)) << 8) + WIZCHIP_READ((Sn_TX_WR(sn)+1)))
-
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Get @ref Sn_RX_RSR register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @return uint16_t. Value of @ref Sn_RX_RSR.
- */
-uint16_t getSn_RX_RSR(uint8_t sn);
-
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Set @ref Sn_RX_RD register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @param (uint16_t)rxrd Value to set @ref Sn_RX_RD
- * @sa getSn_RX_RD()
- */
-#define setSn_RX_RD(sn, rxrd) { \
- WIZCHIP_WRITE(Sn_RX_RD(sn), (uint8_t)(rxrd>>8)); \
- WIZCHIP_WRITE((Sn_RX_RD(sn)+1), (uint8_t) rxrd); \
- }
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Get @ref Sn_RX_RD register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @regurn uint16_t. Value of @ref Sn_RX_RD.
- * @sa setSn_RX_RD()
- */
-#define getSn_RX_RD(sn) \
- ((WIZCHIP_READ(Sn_RX_RD(sn)) << 8) + WIZCHIP_READ((Sn_RX_RD(sn)+1)))
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Get @ref Sn_RX_WR register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @return uint16_t. Value of @ref Sn_RX_WR.
- */
-#define getSn_RX_WR(sn) \
- ((WIZCHIP_READ(Sn_RX_WR(sn)) << 8) + WIZCHIP_READ((Sn_RX_WR(sn)+1)))
-
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Set @ref Sn_FRAG register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @param (uint16_t)frag Value to set @ref Sn_FRAG
- * @sa getSn_FRAD()
- */
-#if 0 // dpgeorge
-#define setSn_FRAG(sn, frag) { \
- WIZCHIP_WRITE(Sn_FRAG(sn), (uint8_t)(frag >>8)); \
- WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_FRAG(sn),1), (uint8_t) frag); \
- }
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Get @ref Sn_FRAG register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @return uint16_t. Value of @ref Sn_FRAG.
- * @sa setSn_FRAG()
- */
-#define getSn_FRAG(sn) \
- ((WIZCHIP_READ(Sn_FRAG(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_FRAG(sn),1)))
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Set @ref Sn_KPALVTR register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @param (uint8_t)kpalvt Value to set @ref Sn_KPALVTR
- * @sa getSn_KPALVTR()
- */
-#define setSn_KPALVTR(sn, kpalvt) \
- WIZCHIP_WRITE(Sn_KPALVTR(sn), kpalvt)
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Get @ref Sn_KPALVTR register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @return uint8_t. Value of @ref Sn_KPALVTR.
- * @sa setSn_KPALVTR()
- */
-#define getSn_KPALVTR(sn) \
- WIZCHIP_READ(Sn_KPALVTR(sn))
-
-//////////////////////////////////////
-#endif
-
-/////////////////////////////////////
-// Sn_TXBUF & Sn_RXBUF IO function //
-/////////////////////////////////////
-/**
- * @brief Gets the max buffer size of socket sn passed as parameter.
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @return uint16_t. Value of Socket n RX max buffer size.
- */
-#define getSn_RxMAX(sn) \
- (getSn_RXBUF_SIZE(sn) << 10)
-
-/**
- * @brief Gets the max buffer size of socket sn passed as parameters.
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @return uint16_t. Value of Socket n TX max buffer size.
- */
-//uint16_t getSn_TxMAX(uint8_t sn);
-#define getSn_TxMAX(sn) \
- (getSn_TXBUF_SIZE(sn) << 10)
-
-void wiz_init(void);
-
-/**
- * @ingroup Basic_IO_function
- * @brief It copies data to internal TX memory
- *
- * @details This function reads the Tx write pointer register and after that,
- * it copies the wizdata(pointer buffer) of the length of len(variable) bytes to internal TX memory
- * and updates the Tx write pointer register.
- * This function is being called by send() and sendto() function also.
- *
- * @note User should read upper byte first and lower byte later to get proper value.
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @param wizdata Pointer buffer to write data
- * @param len Data length
- * @sa wiz_recv_data()
- */
-void wiz_send_data(uint8_t sn, uint8_t *wizdata, uint16_t len);
-
-/**
- * @ingroup Basic_IO_function
- * @brief It copies data to your buffer from internal RX memory
- *
- * @details This function read the Rx read pointer register and after that,
- * it copies the received data from internal RX memory
- * to wizdata(pointer variable) of the length of len(variable) bytes.
- * This function is being called by recv() also.
- *
- * @note User should read upper byte first and lower byte later to get proper value.
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @param wizdata Pointer buffer to read data
- * @param len Data length
- * @sa wiz_send_data()
- */
-void wiz_recv_data(uint8_t sn, uint8_t *wizdata, uint16_t len);
-
-/**
- * @ingroup Basic_IO_function
- * @brief It discard the received data in RX memory.
- * @details It discards the data of the length of len(variable) bytes in internal RX memory.
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @param len Data length
- */
-void wiz_recv_ignore(uint8_t sn, uint16_t len);
-
-#endif // _W5500_H_
diff --git a/drivers/wiznet5k/ethernet/w5500/w5500.c b/drivers/wiznet5k/ethernet/w5500/w5500.c
deleted file mode 100644
index 3107b1b71aa3..000000000000
--- a/drivers/wiznet5k/ethernet/w5500/w5500.c
+++ /dev/null
@@ -1,247 +0,0 @@
-//*****************************************************************************
-//
-//! \file w5500.c
-//! \brief W5500 HAL Interface.
-//! \version 1.0.1
-//! \date 2013/10/21
-//! \par Revision history
-//! <2014/05/01> V1.0.2
-//! 1. Implicit type casting -> Explicit type casting. Refer to M20140501
-//! Fixed the problem on porting into under 32bit MCU
-//! Issued by Mathias ClauBen, wizwiki forum ID Think01 and bobh
-//! Thank for your interesting and serious advices.
-//! <2013/10/21> 1st Release
-//! <2013/12/20> V1.0.1
-//! 1. Remove warning
-//! 2. WIZCHIP_READ_BUF WIZCHIP_WRITE_BUF in case _WIZCHIP_IO_MODE_SPI_FDM_
-//! for loop optimized(removed). refer to M20131220
-//! \author MidnightCow
-//! \copyright
-//!
-//! Copyright (c) 2013, WIZnet Co., LTD.
-//! 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 the 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 OWNER 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.
-//
-//*****************************************************************************
-//#include
-#include "w5500.h"
-
-#define _W5500_SPI_VDM_OP_ 0x00
-#define _W5500_SPI_FDM_OP_LEN1_ 0x01
-#define _W5500_SPI_FDM_OP_LEN2_ 0x02
-#define _W5500_SPI_FDM_OP_LEN4_ 0x03
-
-////////////////////////////////////////////////////
-
-#define LPC_SSP0 (0)
-
-static void Chip_SSP_ReadFrames_Blocking(int dummy, uint8_t *buf, uint32_t len) {
- WIZCHIP.IF.SPI._read_bytes(buf, len);
-}
-
-static void Chip_SSP_WriteFrames_Blocking(int dummy, const uint8_t *buf, uint32_t len) {
- WIZCHIP.IF.SPI._write_bytes(buf, len);
-}
-
-uint8_t WIZCHIP_READ(uint32_t AddrSel)
-{
- uint8_t ret;
- uint8_t spi_data[3];
-
- WIZCHIP_CRITICAL_ENTER();
- WIZCHIP.CS._select();
-
- AddrSel |= (_W5500_SPI_READ_ | _W5500_SPI_VDM_OP_);
-
- //WIZCHIP.IF.SPI._write_byte((AddrSel & 0x00FF0000) >> 16);
- //WIZCHIP.IF.SPI._write_byte((AddrSel & 0x0000FF00) >> 8);
- //WIZCHIP.IF.SPI._write_byte((AddrSel & 0x000000FF) >> 0);
- //ret = WIZCHIP.IF.SPI._read_byte();
- spi_data[0] = (AddrSel & 0x00FF0000) >> 16;
- spi_data[1] = (AddrSel & 0x0000FF00) >> 8;
- spi_data[2] = (AddrSel & 0x000000FF) >> 0;
- Chip_SSP_WriteFrames_Blocking(LPC_SSP0, spi_data, 3);
- Chip_SSP_ReadFrames_Blocking(LPC_SSP0, &ret, 1);
-
- WIZCHIP.CS._deselect();
- WIZCHIP_CRITICAL_EXIT();
- return ret;
-}
-
-void WIZCHIP_WRITE(uint32_t AddrSel, uint8_t wb )
-{
- uint8_t spi_data[4];
-
- WIZCHIP_CRITICAL_ENTER();
- WIZCHIP.CS._select();
-
- AddrSel |= (_W5500_SPI_WRITE_ | _W5500_SPI_VDM_OP_);
-
- //WIZCHIP.IF.SPI._write_byte((AddrSel & 0x00FF0000) >> 16);
- //WIZCHIP.IF.SPI._write_byte((AddrSel & 0x0000FF00) >> 8);
- //WIZCHIP.IF.SPI._write_byte((AddrSel & 0x000000FF) >> 0);
- //WIZCHIP.IF.SPI._write_byte(wb);
- spi_data[0] = (AddrSel & 0x00FF0000) >> 16;
- spi_data[1] = (AddrSel & 0x0000FF00) >> 8;
- spi_data[2] = (AddrSel & 0x000000FF) >> 0;
- spi_data[3] = wb;
- Chip_SSP_WriteFrames_Blocking(LPC_SSP0, spi_data, 4);
-
- WIZCHIP.CS._deselect();
- WIZCHIP_CRITICAL_EXIT();
-}
-
-void WIZCHIP_READ_BUF (uint32_t AddrSel, uint8_t* pBuf, uint16_t len)
-{
- uint8_t spi_data[3];
- //uint16_t i;
-
- WIZCHIP_CRITICAL_ENTER();
- WIZCHIP.CS._select();
-
- AddrSel |= (_W5500_SPI_READ_ | _W5500_SPI_VDM_OP_);
-
- //WIZCHIP.IF.SPI._write_byte((AddrSel & 0x00FF0000) >> 16);
- //WIZCHIP.IF.SPI._write_byte((AddrSel & 0x0000FF00) >> 8);
- //WIZCHIP.IF.SPI._write_byte((AddrSel & 0x000000FF) >> 0);
- //for(i = 0; i < len; i++)
- // pBuf[i] = WIZCHIP.IF.SPI._read_byte();
- spi_data[0] = (AddrSel & 0x00FF0000) >> 16;
- spi_data[1] = (AddrSel & 0x0000FF00) >> 8;
- spi_data[2] = (AddrSel & 0x000000FF) >> 0;
- Chip_SSP_WriteFrames_Blocking(LPC_SSP0, spi_data, 3);
- Chip_SSP_ReadFrames_Blocking(LPC_SSP0, pBuf, len);
-
- WIZCHIP.CS._deselect();
- WIZCHIP_CRITICAL_EXIT();
-}
-
-void WIZCHIP_WRITE_BUF(uint32_t AddrSel, uint8_t* pBuf, uint16_t len)
-{
- uint8_t spi_data[3];
- //uint16_t i;
-
- WIZCHIP_CRITICAL_ENTER();
- WIZCHIP.CS._select();
-
- AddrSel |= (_W5500_SPI_WRITE_ | _W5500_SPI_VDM_OP_);
-
- //WIZCHIP.IF.SPI._write_byte((AddrSel & 0x00FF0000) >> 16);
- //WIZCHIP.IF.SPI._write_byte((AddrSel & 0x0000FF00) >> 8);
- //WIZCHIP.IF.SPI._write_byte((AddrSel & 0x000000FF) >> 0);
- //for(i = 0; i < len; i++)
- // WIZCHIP.IF.SPI._write_byte(pBuf[i]);
- spi_data[0] = (AddrSel & 0x00FF0000) >> 16;
- spi_data[1] = (AddrSel & 0x0000FF00) >> 8;
- spi_data[2] = (AddrSel & 0x000000FF) >> 0;
- Chip_SSP_WriteFrames_Blocking(LPC_SSP0, spi_data, 3);
- Chip_SSP_WriteFrames_Blocking(LPC_SSP0, pBuf, len);
-
- WIZCHIP.CS._deselect();
- WIZCHIP_CRITICAL_EXIT();
-}
-
-
-uint16_t getSn_TX_FSR(uint8_t sn)
-{
- uint16_t val=0,val1=0;
-
- do
- {
- val1 = WIZCHIP_READ(Sn_TX_FSR(sn));
- val1 = (val1 << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_TX_FSR(sn),1));
- if (val1 != 0)
- {
- val = WIZCHIP_READ(Sn_TX_FSR(sn));
- val = (val << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_TX_FSR(sn),1));
- }
- }while (val != val1);
- return val;
-}
-
-
-uint16_t getSn_RX_RSR(uint8_t sn)
-{
- uint16_t val=0,val1=0;
-
- do
- {
- val1 = WIZCHIP_READ(Sn_RX_RSR(sn));
- val1 = (val1 << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_RX_RSR(sn),1));
- if (val1 != 0)
- {
- val = WIZCHIP_READ(Sn_RX_RSR(sn));
- val = (val << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_RX_RSR(sn),1));
- }
- }while (val != val1);
- return val;
-}
-
-void wiz_send_data(uint8_t sn, uint8_t *wizdata, uint16_t len)
-{
- uint16_t ptr = 0;
- uint32_t addrsel = 0;
-
- if(len == 0) return;
- ptr = getSn_TX_WR(sn);
- //M20140501 : implict type casting -> explict type casting
- //addrsel = (ptr << 8) + (WIZCHIP_TXBUF_BLOCK(sn) << 3);
- addrsel = ((uint32_t)ptr << 8) + (WIZCHIP_TXBUF_BLOCK(sn) << 3);
- //
- WIZCHIP_WRITE_BUF(addrsel,wizdata, len);
-
- ptr += len;
- setSn_TX_WR(sn,ptr);
-}
-
-void wiz_recv_data(uint8_t sn, uint8_t *wizdata, uint16_t len)
-{
- uint16_t ptr = 0;
- uint32_t addrsel = 0;
-
- if(len == 0) return;
- ptr = getSn_RX_RD(sn);
- //M20140501 : implict type casting -> explict type casting
- //addrsel = ((ptr << 8) + (WIZCHIP_RXBUF_BLOCK(sn) << 3);
- addrsel = ((uint32_t)ptr << 8) + (WIZCHIP_RXBUF_BLOCK(sn) << 3);
- //
- WIZCHIP_READ_BUF(addrsel, wizdata, len);
- ptr += len;
-
- setSn_RX_RD(sn,ptr);
-}
-
-
-void wiz_recv_ignore(uint8_t sn, uint16_t len)
-{
- uint16_t ptr = 0;
-
- ptr = getSn_RX_RD(sn);
- ptr += len;
- setSn_RX_RD(sn,ptr);
-}
-
diff --git a/drivers/wiznet5k/ethernet/w5500/w5500.h b/drivers/wiznet5k/ethernet/w5500/w5500.h
deleted file mode 100644
index c2afb180ebba..000000000000
--- a/drivers/wiznet5k/ethernet/w5500/w5500.h
+++ /dev/null
@@ -1,2057 +0,0 @@
-//*****************************************************************************
-//
-//! \file w5500.h
-//! \brief W5500 HAL Header File.
-//! \version 1.0.0
-//! \date 2013/10/21
-//! \par Revision history
-//! <2013/10/21> 1st Release
-//! \author MidnightCow
-//! \copyright
-//!
-//! Copyright (c) 2013, WIZnet Co., LTD.
-//! 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 the 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 OWNER 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.
-//
-//*****************************************************************************
-
-#ifndef _W5500_H_
-#define _W5500_H_
-
-#include
-#include "../wizchip_conf.h"
-
-#define _W5500_IO_BASE_ 0x00000000
-
-#define _W5500_SPI_READ_ (0x00 << 2) //< SPI interface Read operation in Control Phase
-#define _W5500_SPI_WRITE_ (0x01 << 2) //< SPI interface Write operation in Control Phase
-
-#define WIZCHIP_CREG_BLOCK 0x00 //< Common register block
-#define WIZCHIP_SREG_BLOCK(N) (1+4*N) //< Socket N register block
-#define WIZCHIP_TXBUF_BLOCK(N) (2+4*N) //< Socket N Tx buffer address block
-#define WIZCHIP_RXBUF_BLOCK(N) (3+4*N) //< Socket N Rx buffer address block
-
-#define WIZCHIP_OFFSET_INC(ADDR, N) (ADDR + (N<<8)) //< Increase offset address
-
-
-///////////////////////////////////////
-// Definition For Legacy Chip Driver //
-///////////////////////////////////////
-#define IINCHIP_READ(ADDR) WIZCHIP_READ(ADDR) ///< The defined for legacy chip driver
-#define IINCHIP_WRITE(ADDR,VAL) WIZCHIP_WRITE(ADDR,VAL) ///< The defined for legacy chip driver
-#define IINCHIP_READ_BUF(ADDR,BUF,LEN) WIZCHIP_READ_BUF(ADDR,BUF,LEN) ///< The defined for legacy chip driver
-#define IINCHIP_WRITE_BUF(ADDR,BUF,LEN) WIZCHIP_WRITE(ADDR,BUF,LEN) ///< The defined for legacy chip driver
-
-//////////////////////////////
-//-------------------------- defgroup ---------------------------------
-/**
- * @defgroup W5500 W5500
- *
- * @brief WHIZCHIP register defines and I/O functions of @b W5500.
- *
- * - @ref WIZCHIP_register : @ref Common_register_group and @ref Socket_register_group
- * - @ref WIZCHIP_IO_Functions : @ref Basic_IO_function, @ref Common_register_access_function and @ref Socket_register_access_function
- */
-
-
-/**
- * @defgroup WIZCHIP_register WIZCHIP register
- * @ingroup W5500
- *
- * @brief WHIZCHIP register defines register group of @b W5500.
- *
- * - @ref Common_register_group : Common register group
- * - @ref Socket_register_group : \c SOCKET n register group
- */
-
-
-/**
- * @defgroup WIZCHIP_IO_Functions WIZCHIP I/O functions
- * @ingroup W5500
- *
- * @brief This supports the basic I/O functions for @ref WIZCHIP_register.
- *
- * - Basic I/O function \n
- * WIZCHIP_READ(), WIZCHIP_WRITE(), WIZCHIP_READ_BUF(), WIZCHIP_WRITE_BUF() \n\n
- *
- * - @ref Common_register_group access functions \n
- * -# @b Mode \n
- * getMR(), setMR()
- * -# @b Interrupt \n
- * getIR(), setIR(), getIMR(), setIMR(), getSIR(), setSIR(), getSIMR(), setSIMR(), getINTLEVEL(), setINTLEVEL()
- * -# Network Information \n
- * getSHAR(), setSHAR(), getGAR(), setGAR(), getSUBR(), setSUBR(), getSIPR(), setSIPR()
- * -# @b Retransmission \n
- * getRCR(), setRCR(), getRTR(), setRTR()
- * -# @b PPPoE \n
- * getPTIMER(), setPTIMER(), getPMAGIC(), getPMAGIC(), getPSID(), setPSID(), getPHAR(), setPHAR(), getPMRU(), setPMRU()
- * -# ICMP packet \n
- * getUIPR(), getUPORTR()
- * -# @b etc. \n
- * getPHYCFGR(), setPHYCFGR(), getVERSIONR() \n\n
- *
- * - \ref Socket_register_group access functions \n
- * -# SOCKET control \n
- * getSn_MR(), setSn_MR(), getSn_CR(), setSn_CR(), getSn_IMR(), setSn_IMR(), getSn_IR(), setSn_IR()
- * -# SOCKET information \n
- * getSn_SR(), getSn_DHAR(), setSn_DHAR(), getSn_PORT(), setSn_PORT(), getSn_DIPR(), setSn_DIPR(), getSn_DPORT(), setSn_DPORT()
- * getSn_MSSR(), setSn_MSSR()
- * -# SOCKET communication \n
- * getSn_RXBUF_SIZE(), setSn_RXBUF_SIZE(), getSn_TXBUF_SIZE(), setSn_TXBUF_SIZE() \n
- * getSn_TX_RD(), getSn_TX_WR(), setSn_TX_WR() \n
- * getSn_RX_RD(), setSn_RX_RD(), getSn_RX_WR() \n
- * getSn_TX_FSR(), getSn_RX_RSR(), getSn_KPALVTR(), setSn_KPALVTR()
- * -# IP header field \n
- * getSn_FRAG(), setSn_FRAG(), getSn_TOS(), setSn_TOS() \n
- * getSn_TTL(), setSn_TTL()
- */
-
-
-
-/**
- * @defgroup Common_register_group Common register
- * @ingroup WIZCHIP_register
- *
- * @brief Common register group\n
- * It set the basic for the networking\n
- * It set the configuration such as interrupt, network information, ICMP, etc.
- * @details
- * @sa MR : Mode register.
- * @sa GAR, SUBR, SHAR, SIPR
- * @sa INTLEVEL, IR, IMR, SIR, SIMR : Interrupt.
- * @sa RTR, RCR : Data retransmission.
- * @sa PTIMER, PMAGIC, PHAR, PSID, PMRU : PPPoE.
- * @sa UIPR, UPORTR : ICMP message.
- * @sa PHYCFGR, VERSIONR : etc.
- */
-
-
-
-/**
- * @defgroup Socket_register_group Socket register
- * @ingroup WIZCHIP_register
- *
- * @brief Socket register group.\n
- * Socket register configures and control SOCKETn which is necessary to data communication.
- * @details
- * @sa Sn_MR, Sn_CR, Sn_IR, Sn_IMR : SOCKETn Control
- * @sa Sn_SR, Sn_PORT, Sn_DHAR, Sn_DIPR, Sn_DPORT : SOCKETn Information
- * @sa Sn_MSSR, Sn_TOS, Sn_TTL, Sn_KPALVTR, Sn_FRAG : Internet protocol.
- * @sa Sn_RXBUF_SIZE, Sn_TXBUF_SIZE, Sn_TX_FSR, Sn_TX_RD, Sn_TX_WR, Sn_RX_RSR, Sn_RX_RD, Sn_RX_WR : Data communication
- */
-
-
-
- /**
- * @defgroup Basic_IO_function Basic I/O function
- * @ingroup WIZCHIP_IO_Functions
- * @brief These are basic input/output functions to read values from register or write values to register.
- */
-
-/**
- * @defgroup Common_register_access_function Common register access functions
- * @ingroup WIZCHIP_IO_Functions
- * @brief These are functions to access common registers.
- */
-
-/**
- * @defgroup Socket_register_access_function Socket register access functions
- * @ingroup WIZCHIP_IO_Functions
- * @brief These are functions to access socket registers.
- */
-
-//------------------------------- defgroup end --------------------------------------------
-//----------------------------- W5500 Common Registers IOMAP -----------------------------
-/**
- * @ingroup Common_register_group
- * @brief Mode Register address(R/W)\n
- * @ref MR is used for S/W reset, ping block mode, PPPoE mode and etc.
- * @details Each bit of @ref MR defined as follows.
- *
- *
7
6
5
4
3
2
1
0
- *
RST
Reserved
WOL
PB
PPPoE
Reserved
FARP
Reserved
- *
- * - \ref MR_RST : Reset
- * - \ref MR_WOL : Wake on LAN
- * - \ref MR_PB : Ping block
- * - \ref MR_PPPOE : PPPoE mode
- * - \ref MR_FARP : Force ARP mode
- */
-#define MR (_W5500_IO_BASE_ + (0x0000 << 8) + (WIZCHIP_CREG_BLOCK << 3))
-
-/**
- * @ingroup Common_register_group
- * @brief Gateway IP Register address(R/W)
- * @details @ref GAR configures the default gateway address.
- */
-#define GAR (_W5500_IO_BASE_ + (0x0001 << 8) + (WIZCHIP_CREG_BLOCK << 3))
-
-/**
- * @ingroup Common_register_group
- * @brief Subnet mask Register address(R/W)
- * @details @ref SUBR configures the subnet mask address.
- */
-#define SUBR (_W5500_IO_BASE_ + (0x0005 << 8) + (WIZCHIP_CREG_BLOCK << 3))
-
-/**
- * @ingroup Common_register_group
- * @brief Source MAC Register address(R/W)
- * @details @ref SHAR configures the source hardware address.
- */
-#define SHAR (_W5500_IO_BASE_ + (0x0009 << 8) + (WIZCHIP_CREG_BLOCK << 3))
-
-/**
- * @ingroup Common_register_group
- * @brief Source IP Register address(R/W)
- * @details @ref SIPR configures the source IP address.
- */
-#define SIPR (_W5500_IO_BASE_ + (0x000F << 8) + (WIZCHIP_CREG_BLOCK << 3))
-
-/**
- * @ingroup Common_register_group
- * @brief Set Interrupt low level timer register address(R/W)
- * @details @ref INTLEVEL configures the Interrupt Assert Time.
- */
-#define INTLEVEL (_W5500_IO_BASE_ + (0x0013 << 8) + (WIZCHIP_CREG_BLOCK << 3))
-
-/**
- * @ingroup Common_register_group
- * @brief Interrupt Register(R/W)
- * @details @ref IR indicates the interrupt status. Each bit of @ref IR will be still until the bit will be written to by the host.
- * If @ref IR is not equal to x00 INTn PIN is asserted to low until it is x00\n\n
- * Each bit of @ref IR defined as follows.
- *
- *
7
6
5
4
3
2
1
0
- *
CONFLICT
UNREACH
PPPoE
MP
Reserved
Reserved
Reserved
Reserved
- *
- * - \ref IR_CONFLICT : IP conflict
- * - \ref IR_UNREACH : Destination unreachable
- * - \ref IR_PPPoE : PPPoE connection close
- * - \ref IR_MP : Magic packet
- */
-#define IR (_W5500_IO_BASE_ + (0x0015 << 8) + (WIZCHIP_CREG_BLOCK << 3))
-
-/**
- * @ingroup Common_register_group
- * @brief Interrupt mask register(R/W)
- * @details @ref IMR is used to mask interrupts. Each bit of @ref IMR corresponds to each bit of @ref IR.
- * When a bit of @ref IMR is and the corresponding bit of @ref IR is an interrupt will be issued. In other words,
- * if a bit of @ref IMR is an interrupt will not be issued even if the corresponding bit of @ref IR is \n\n
- * Each bit of @ref IMR defined as the following.
- *
- *
7
6
5
4
3
2
1
0
- *
IM_IR7
IM_IR6
IM_IR5
IM_IR4
Reserved
Reserved
Reserved
Reserved
- *
- * - \ref IM_IR7 : IP Conflict Interrupt Mask
- * - \ref IM_IR6 : Destination unreachable Interrupt Mask
- * - \ref IM_IR5 : PPPoE Close Interrupt Mask
- * - \ref IM_IR4 : Magic Packet Interrupt Mask
- */
-#define IMR (_W5500_IO_BASE_ + (0x0016 << 8) + (WIZCHIP_CREG_BLOCK << 3))
-
-/**
- * @ingroup Common_register_group
- * @brief Socket Interrupt Register(R/W)
- * @details @ref SIR indicates the interrupt status of Socket.\n
- * Each bit of @ref SIR be still until @ref Sn_IR is cleared by the host.\n
- * If @ref Sn_IR is not equal to x00 the n-th bit of @ref SIR is and INTn PIN is asserted until @ref SIR is x00 */
-#define SIR (_W5500_IO_BASE_ + (0x0017 << 8) + (WIZCHIP_CREG_BLOCK << 3))
-
-/**
- * @ingroup Common_register_group
- * @brief Socket Interrupt Mask Register(R/W)
- * @details Each bit of @ref SIMR corresponds to each bit of @ref SIR.
- * When a bit of @ref SIMR is and the corresponding bit of @ref SIR is Interrupt will be issued.
- * In other words, if a bit of @ref SIMR is an interrupt will be not issued even if the corresponding bit of @ref SIR is
- */
-#define SIMR (_W5500_IO_BASE_ + (0x0018 << 8) + (WIZCHIP_CREG_BLOCK << 3))
-
-/**
- * @ingroup Common_register_group
- * @brief Timeout register address( 1 is 100us )(R/W)
- * @details @ref RTR configures the retransmission timeout period. The unit of timeout period is 100us and the default of @ref RTR is x07D0or 000
- * And so the default timeout period is 200ms(100us X 2000). During the time configured by @ref RTR, W5500 waits for the peer response
- * to the packet that is transmitted by \ref Sn_CR (CONNECT, DISCON, CLOSE, SEND, SEND_MAC, SEND_KEEP command).
- * If the peer does not respond within the @ref RTR time, W5500 retransmits the packet or issues timeout.
- */
-#define RTR (_W5500_IO_BASE_ + (0x0019 << 8) + (WIZCHIP_CREG_BLOCK << 3))
-
-/**
- * @ingroup Common_register_group
- * @brief Retry count register(R/W)
- * @details @ref RCR configures the number of time of retransmission.
- * When retransmission occurs as many as ref RCR+1 Timeout interrupt is issued (@ref Sn_IR[TIMEOUT] = .
- */
-#define RCR (_W5500_IO_BASE_ + (0x001B << 8) + (WIZCHIP_CREG_BLOCK << 3))
-
-/**
- * @ingroup Common_register_group
- * @brief PPP LCP Request Timer register in PPPoE mode(R/W)
- * @details @ref PTIMER configures the time for sending LCP echo request. The unit of time is 25ms.
- */
-#define PTIMER (_W5500_IO_BASE_ + (0x001C << 8) + (WIZCHIP_CREG_BLOCK << 3))
-
-/**
- * @ingroup Common_register_group
- * @brief PPP LCP Magic number register in PPPoE mode(R/W)
- * @details @ref PMAGIC configures the 4bytes magic number to be used in LCP negotiation.
- */
-#define PMAGIC (_W5500_IO_BASE_ + (0x001D << 8) + (WIZCHIP_CREG_BLOCK << 3))
-
-/**
- * @ingroup Common_register_group
- * @brief PPP Destination MAC Register address(R/W)
- * @details @ref PHAR configures the PPPoE server hardware address that is acquired during PPPoE connection process.
- */
-#define PHAR (_W5500_IO_BASE_ + (0x001E << 8) + (WIZCHIP_CREG_BLOCK << 3))
-
-/**
- * @ingroup Common_register_group
- * @brief PPP Session Identification Register(R/W)
- * @details @ref PSID configures the PPPoE sever session ID acquired during PPPoE connection process.
- */
-#define PSID (_W5500_IO_BASE_ + (0x0024 << 8) + (WIZCHIP_CREG_BLOCK << 3))
-
-/**
- * @ingroup Common_register_group
- * @brief PPP Maximum Segment Size(MSS) register(R/W)
- * @details @ref PMRU configures the maximum receive unit of PPPoE.
- */
-#define PMRU (_W5500_IO_BASE_ + (0x0026 << 8) + (WIZCHIP_CREG_BLOCK << 3))
-
-/**
- * @ingroup Common_register_group
- * @brief Unreachable IP register address in UDP mode(R)
- * @details W5500 receives an ICMP packet(Destination port unreachable) when data is sent to a port number
- * which socket is not open and @ref UNREACH bit of @ref IR becomes and @ref UIPR & @ref UPORTR indicates
- * the destination IP address & port number respectively.
- */
-#define UIPR (_W5500_IO_BASE_ + (0x0028 << 8) + (WIZCHIP_CREG_BLOCK << 3))
-
-/**
- * @ingroup Common_register_group
- * @brief Unreachable Port register address in UDP mode(R)
- * @details W5500 receives an ICMP packet(Destination port unreachable) when data is sent to a port number
- * which socket is not open and @ref UNREACH bit of @ref IR becomes and @ref UIPR & @ref UPORTR
- * indicates the destination IP address & port number respectively.
- */
-#define UPORTR (_W5500_IO_BASE_ + (0x002C << 8) + (WIZCHIP_CREG_BLOCK << 3))
-
-/**
- * @ingroup Common_register_group
- * @brief PHY Status Register(R/W)
- * @details @ref PHYCFGR configures PHY operation mode and resets PHY. In addition, @ref PHYCFGR indicates the status of PHY such as duplex, Speed, Link.
- */
-#define PHYCFGR (_W5500_IO_BASE_ + (0x002E << 8) + (WIZCHIP_CREG_BLOCK << 3))
-
-// Reserved (_W5500_IO_BASE_ + (0x002F << 8) + (WIZCHIP_CREG_BLOCK << 3))
-// Reserved (_W5500_IO_BASE_ + (0x0030 << 8) + (WIZCHIP_CREG_BLOCK << 3))
-// Reserved (_W5500_IO_BASE_ + (0x0031 << 8) + (WIZCHIP_CREG_BLOCK << 3))
-// Reserved (_W5500_IO_BASE_ + (0x0032 << 8) + (WIZCHIP_CREG_BLOCK << 3))
-// Reserved (_W5500_IO_BASE_ + (0x0033 << 8) + (WIZCHIP_CREG_BLOCK << 3))
-// Reserved (_W5500_IO_BASE_ + (0x0034 << 8) + (WIZCHIP_CREG_BLOCK << 3))
-// Reserved (_W5500_IO_BASE_ + (0x0035 << 8) + (WIZCHIP_CREG_BLOCK << 3))
-// Reserved (_W5500_IO_BASE_ + (0x0036 << 8) + (WIZCHIP_CREG_BLOCK << 3))
-// Reserved (_W5500_IO_BASE_ + (0x0037 << 8) + (WIZCHIP_CREG_BLOCK << 3))
-// Reserved (_W5500_IO_BASE_ + (0x0038 << 8) + (WIZCHIP_CREG_BLOCK << 3))
-
-/**
- * @ingroup Common_register_group
- * @brief chip version register address(R)
- * @details @ref VERSIONR always indicates the W5500 version as @b 0x04.
- */
-#define VERSIONR (_W5500_IO_BASE_ + (0x0039 << 8) + (WIZCHIP_CREG_BLOCK << 3))
-
-
-//----------------------------- W5500 Socket Registers IOMAP -----------------------------
-/**
- * @ingroup Socket_register_group
- * @brief socket Mode register(R/W)
- * @details @ref Sn_MR configures the option or protocol type of Socket n.\n\n
- * Each bit of @ref Sn_MR defined as the following.
- *
- *
7
6
5
4
3
2
1
0
- *
MULTI/MFEN
BCASTB
ND/MC/MMB
UCASTB/MIP6B
Protocol[3]
Protocol[2]
Protocol[1]
Protocol[0]
- *
- * - @ref Sn_MR_MULTI : Support UDP Multicasting
- * - @ref Sn_MR_BCASTB : Broadcast block in UDP Multicasting
- * - @ref Sn_MR_ND : No Delayed Ack(TCP) flag
- * - @ref Sn_MR_MC : IGMP version used in UDP mulitcasting
- * - @ref Sn_MR_MMB : Multicast Blocking in @ref Sn_MR_MACRAW mode
- * - @ref Sn_MR_UCASTB : Unicast Block in UDP Multicating
- * - @ref Sn_MR_MIP6B : IPv6 packet Blocking in @ref Sn_MR_MACRAW mode
- * - Protocol
- *
- *
Protocol[3]
Protocol[2]
Protocol[1]
Protocol[0]
@b Meaning
- *
0
0
0
0
Closed
- *
0
0
0
1
TCP
- *
0
0
1
0
UDP
- *
0
1
0
0
MACRAW
- *
- * - @ref Sn_MR_MACRAW : MAC LAYER RAW SOCK \n
- * - @ref Sn_MR_UDP : UDP
- * - @ref Sn_MR_TCP : TCP
- * - @ref Sn_MR_CLOSE : Unused socket
- * @note MACRAW mode should be only used in Socket 0.
- */
-#define Sn_MR(N) (_W5500_IO_BASE_ + (0x0000 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
-
-/**
- * @ingroup Socket_register_group
- * @brief Socket command register(R/W)
- * @details This is used to set the command for Socket n such as OPEN, CLOSE, CONNECT, LISTEN, SEND, and RECEIVE.\n
- * After W5500 accepts the command, the @ref Sn_CR register is automatically cleared to 0x00.
- * Even though @ref Sn_CR is cleared to 0x00, the command is still being processed.\n
- * To check whether the command is completed or not, please check the @ref Sn_IR or @ref Sn_SR.
- * - @ref Sn_CR_OPEN : Initialize or open socket.
- * - @ref Sn_CR_LISTEN : Wait connection request in TCP mode(Server mode)
- * - @ref Sn_CR_CONNECT : Send connection request in TCP mode(Client mode)
- * - @ref Sn_CR_DISCON : Send closing request in TCP mode.
- * - @ref Sn_CR_CLOSE : Close socket.
- * - @ref Sn_CR_SEND : Update TX buffer pointer and send data.
- * - @ref Sn_CR_SEND_MAC : Send data with MAC address, so without ARP process.
- * - @ref Sn_CR_SEND_KEEP : Send keep alive message.
- * - @ref Sn_CR_RECV : Update RX buffer pointer and receive data.
- */
-#define Sn_CR(N) (_W5500_IO_BASE_ + (0x0001 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
-
-/**
- * @ingroup Socket_register_group
- * @brief Socket interrupt register(R)
- * @details @ref Sn_IR indicates the status of Socket Interrupt such as establishment, termination, receiving data, timeout).\n
- * When an interrupt occurs and the corresponding bit of @ref Sn_IMR is the corresponding bit of @ref Sn_IR becomes \n
- * In order to clear the @ref Sn_IR bit, the host should write the bit to \n
- *
- *
7
6
5
4
3
2
1
0
- *
Reserved
Reserved
Reserved
SEND_OK
TIMEOUT
RECV
DISCON
CON
- *
- * - \ref Sn_IR_SENDOK : SEND_OK Interrupt
- * - \ref Sn_IR_TIMEOUT : TIMEOUT Interrupt
- * - \ref Sn_IR_RECV : RECV Interrupt
- * - \ref Sn_IR_DISCON : DISCON Interrupt
- * - \ref Sn_IR_CON : CON Interrupt
- */
-#define Sn_IR(N) (_W5500_IO_BASE_ + (0x0002 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
-
-/**
- * @ingroup Socket_register_group
- * @brief Socket status register(R)
- * @details @ref Sn_SR indicates the status of Socket n.\n
- * The status of Socket n is changed by @ref Sn_CR or some special control packet as SYN, FIN packet in TCP.
- * @par Normal status
- * - @ref SOCK_CLOSED : Closed
- * - @ref SOCK_INIT : Initiate state
- * - @ref SOCK_LISTEN : Listen state
- * - @ref SOCK_ESTABLISHED : Success to connect
- * - @ref SOCK_CLOSE_WAIT : Closing state
- * - @ref SOCK_UDP : UDP socket
- * - @ref SOCK_MACRAW : MAC raw mode socket
- *@par Temporary status during changing the status of Socket n.
- * - @ref SOCK_SYNSENT : This indicates Socket n sent the connect-request packet (SYN packet) to a peer.
- * - @ref SOCK_SYNRECV : It indicates Socket n successfully received the connect-request packet (SYN packet) from a peer.
- * - @ref SOCK_FIN_WAIT : Connection state
- * - @ref SOCK_CLOSING : Closing state
- * - @ref SOCK_TIME_WAIT : Closing state
- * - @ref SOCK_LAST_ACK : Closing state
- */
-#define Sn_SR(N) (_W5500_IO_BASE_ + (0x0003 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
-
-/**
- * @ingroup Socket_register_group
- * @brief source port register(R/W)
- * @details @ref Sn_PORT configures the source port number of Socket n.
- * It is valid when Socket n is used in TCP/UPD mode. It should be set before OPEN command is ordered.
- */
-#define Sn_PORT(N) (_W5500_IO_BASE_ + (0x0004 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
-
-/**
- * @ingroup Socket_register_group
- * @brief Peer MAC register address(R/W)
- * @details @ref Sn_DHAR configures the destination hardware address of Socket n when using SEND_MAC command in UDP mode or
- * it indicates that it is acquired in ARP-process by CONNECT/SEND command.
- */
-#define Sn_DHAR(N) (_W5500_IO_BASE_ + (0x0006 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
-
-/**
- * @ingroup Socket_register_group
- * @brief Peer IP register address(R/W)
- * @details @ref Sn_DIPR configures or indicates the destination IP address of Socket n. It is valid when Socket n is used in TCP/UDP mode.
- * In TCP client mode, it configures an IP address of �TCP serverbefore CONNECT command.
- * In TCP server mode, it indicates an IP address of �TCP clientafter successfully establishing connection.
- * In UDP mode, it configures an IP address of peer to be received the UDP packet by SEND or SEND_MAC command.
- */
-#define Sn_DIPR(N) (_W5500_IO_BASE_ + (0x000C << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
-
-/**
- * @ingroup Socket_register_group
- * @brief Peer port register address(R/W)
- * @details @ref Sn_DPORT configures or indicates the destination port number of Socket n. It is valid when Socket n is used in TCP/UDP mode.
- * In �TCP clientmode, it configures the listen port number of �TCP serverbefore CONNECT command.
- * In �TCP Servermode, it indicates the port number of TCP client after successfully establishing connection.
- * In UDP mode, it configures the port number of peer to be transmitted the UDP packet by SEND/SEND_MAC command.
- */
-#define Sn_DPORT(N) (_W5500_IO_BASE_ + (0x0010 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
-
-/**
- * @ingroup Socket_register_group
- * @brief Maximum Segment Size(Sn_MSSR0) register address(R/W)
- * @details @ref Sn_MSSR configures or indicates the MTU(Maximum Transfer Unit) of Socket n.
- */
-#define Sn_MSSR(N) (_W5500_IO_BASE_ + (0x0012 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
-
-// Reserved (_W5500_IO_BASE_ + (0x0014 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
-
-/**
- * @ingroup Socket_register_group
- * @brief IP Type of Service(TOS) Register(R/W)
- * @details @ref Sn_TOS configures the TOS(Type Of Service field in IP Header) of Socket n.
- * It is set before OPEN command.
- */
-#define Sn_TOS(N) (_W5500_IO_BASE_ + (0x0015 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
-/**
- * @ingroup Socket_register_group
- * @brief IP Time to live(TTL) Register(R/W)
- * @details @ref Sn_TTL configures the TTL(Time To Live field in IP header) of Socket n.
- * It is set before OPEN command.
- */
-#define Sn_TTL(N) (_W5500_IO_BASE_ + (0x0016 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
-// Reserved (_W5500_IO_BASE_ + (0x0017 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
-// Reserved (_W5500_IO_BASE_ + (0x0018 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
-// Reserved (_W5500_IO_BASE_ + (0x0019 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
-// Reserved (_W5500_IO_BASE_ + (0x001A << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
-// Reserved (_W5500_IO_BASE_ + (0x001B << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
-// Reserved (_W5500_IO_BASE_ + (0x001C << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
-// Reserved (_W5500_IO_BASE_ + (0x001D << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
-
-/**
- * @ingroup Socket_register_group
- * @brief Receive memory size register(R/W)
- * @details @ref Sn_RXBUF_SIZE configures the RX buffer block size of Socket n.
- * Socket n RX Buffer Block size can be configured with 1,2,4,8, and 16 Kbytes.
- * If a different size is configured, the data cannot be normally received from a peer.
- * Although Socket n RX Buffer Block size is initially configured to 2Kbytes,
- * user can re-configure its size using @ref Sn_RXBUF_SIZE. The total sum of @ref Sn_RXBUF_SIZE can not be exceed 16Kbytes.
- * When exceeded, the data reception error is occurred.
- */
-#define Sn_RXBUF_SIZE(N) (_W5500_IO_BASE_ + (0x001E << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
-
-/**
- * @ingroup Socket_register_group
- * @brief Transmit memory size register(R/W)
- * @details @ref Sn_TXBUF_SIZE configures the TX buffer block size of Socket n. Socket n TX Buffer Block size can be configured with 1,2,4,8, and 16 Kbytes.
- * If a different size is configured, the data can�t be normally transmitted to a peer.
- * Although Socket n TX Buffer Block size is initially configured to 2Kbytes,
- * user can be re-configure its size using @ref Sn_TXBUF_SIZE. The total sum of @ref Sn_TXBUF_SIZE can not be exceed 16Kbytes.
- * When exceeded, the data transmission error is occurred.
- */
-#define Sn_TXBUF_SIZE(N) (_W5500_IO_BASE_ + (0x001F << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
-
-/**
- * @ingroup Socket_register_group
- * @brief Transmit free memory size register(R)
- * @details @ref Sn_TX_FSR indicates the free size of Socket n TX Buffer Block. It is initialized to the configured size by @ref Sn_TXBUF_SIZE.
- * Data bigger than @ref Sn_TX_FSR should not be saved in the Socket n TX Buffer because the bigger data overwrites the previous saved data not yet sent.
- * Therefore, check before saving the data to the Socket n TX Buffer, and if data is equal or smaller than its checked size,
- * transmit the data with SEND/SEND_MAC command after saving the data in Socket n TX buffer. But, if data is bigger than its checked size,
- * transmit the data after dividing into the checked size and saving in the Socket n TX buffer.
- */
-#define Sn_TX_FSR(N) (_W5500_IO_BASE_ + (0x0020 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
-
-/**
- * @ingroup Socket_register_group
- * @brief Transmit memory read pointer register address(R)
- * @details @ref Sn_TX_RD is initialized by OPEN command. However, if Sn_MR(P[3:0]) is TCP mode(001, it is re-initialized while connecting with TCP.
- * After its initialization, it is auto-increased by SEND command.
- * SEND command transmits the saved data from the current @ref Sn_TX_RD to the @ref Sn_TX_WR in the Socket n TX Buffer.
- * After transmitting the saved data, the SEND command increases the @ref Sn_TX_RD as same as the @ref Sn_TX_WR.
- * If its increment value exceeds the maximum value 0xFFFF, (greater than 0x10000 and the carry bit occurs),
- * then the carry bit is ignored and will automatically update with the lower 16bits value.
- */
-#define Sn_TX_RD(N) (_W5500_IO_BASE_ + (0x0022 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
-
-/**
- * @ingroup Socket_register_group
- * @brief Transmit memory write pointer register address(R/W)
- * @details @ref Sn_TX_WR is initialized by OPEN command. However, if Sn_MR(P[3:0]) is TCP mode(001, it is re-initialized while connecting with TCP.\n
- * It should be read or be updated like as follows.\n
- * 1. Read the starting address for saving the transmitting data.\n
- * 2. Save the transmitting data from the starting address of Socket n TX buffer.\n
- * 3. After saving the transmitting data, update @ref Sn_TX_WR to the increased value as many as transmitting data size.
- * If the increment value exceeds the maximum value 0xFFFF(greater than 0x10000 and the carry bit occurs),
- * then the carry bit is ignored and will automatically update with the lower 16bits value.\n
- * 4. Transmit the saved data in Socket n TX Buffer by using SEND/SEND command
- */
-#define Sn_TX_WR(N) (_W5500_IO_BASE_ + (0x0024 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
-
-/**
- * @ingroup Socket_register_group
- * @brief Received data size register(R)
- * @details @ref Sn_RX_RSR indicates the data size received and saved in Socket n RX Buffer.
- * @ref Sn_RX_RSR does not exceed the @ref Sn_RXBUF_SIZE and is calculated as the difference between
- * �Socket n RX Write Pointer (@ref Sn_RX_WR)and �Socket n RX Read Pointer (@ref Sn_RX_RD)
- */
-#define Sn_RX_RSR(N) (_W5500_IO_BASE_ + (0x0026 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
-
-/**
- * @ingroup Socket_register_group
- * @brief Read point of Receive memory(R/W)
- * @details @ref Sn_RX_RD is initialized by OPEN command. Make sure to be read or updated as follows.\n
- * 1. Read the starting save address of the received data.\n
- * 2. Read data from the starting address of Socket n RX Buffer.\n
- * 3. After reading the received data, Update @ref Sn_RX_RD to the increased value as many as the reading size.
- * If the increment value exceeds the maximum value 0xFFFF, that is, is greater than 0x10000 and the carry bit occurs,
- * update with the lower 16bits value ignored the carry bit.\n
- * 4. Order RECV command is for notifying the updated @ref Sn_RX_RD to W5500.
- */
-#define Sn_RX_RD(N) (_W5500_IO_BASE_ + (0x0028 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
-
-/**
- * @ingroup Socket_register_group
- * @brief Write point of Receive memory(R)
- * @details @ref Sn_RX_WR is initialized by OPEN command and it is auto-increased by the data reception.
- * If the increased value exceeds the maximum value 0xFFFF, (greater than 0x10000 and the carry bit occurs),
- * then the carry bit is ignored and will automatically update with the lower 16bits value.
- */
-#define Sn_RX_WR(N) (_W5500_IO_BASE_ + (0x002A << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
-
-/**
- * @ingroup Socket_register_group
- * @brief socket interrupt mask register(R)
- * @details @ref Sn_IMR masks the interrupt of Socket n.
- * Each bit corresponds to each bit of @ref Sn_IR. When a Socket n Interrupt is occurred and the corresponding bit of @ref Sn_IMR is
- * the corresponding bit of @ref Sn_IR becomes When both the corresponding bit of @ref Sn_IMR and @ref Sn_IR are and the n-th bit of @ref IR is
- * Host is interrupted by asserted INTn PIN to low.
- */
-#define Sn_IMR(N) (_W5500_IO_BASE_ + (0x002C << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
-
-/**
- * @ingroup Socket_register_group
- * @brief Fragment field value in IP header register(R/W)
- * @details @ref Sn_FRAG configures the FRAG(Fragment field in IP header).
- */
-#define Sn_FRAG(N) (_W5500_IO_BASE_ + (0x002D << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
-
-/**
- * @ingroup Socket_register_group
- * @brief Keep Alive Timer register(R/W)
- * @details @ref Sn_KPALVTR configures the transmitting timer of �KEEP ALIVE(KA)packet of SOCKETn. It is valid only in TCP mode,
- * and ignored in other modes. The time unit is 5s.
- * KA packet is transmittable after @ref Sn_SR is changed to SOCK_ESTABLISHED and after the data is transmitted or received to/from a peer at least once.
- * In case of '@ref Sn_KPALVTR > 0', W5500 automatically transmits KA packet after time-period for checking the TCP connection (Auto-keepalive-process).
- * In case of '@ref Sn_KPALVTR = 0', Auto-keep-alive-process will not operate,
- * and KA packet can be transmitted by SEND_KEEP command by the host (Manual-keep-alive-process).
- * Manual-keep-alive-process is ignored in case of '@ref Sn_KPALVTR > 0'.
- */
-#define Sn_KPALVTR(N) (_W5500_IO_BASE_ + (0x002F << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
-
-//#define Sn_TSR(N) (_W5500_IO_BASE_ + (0x0030 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3))
-
-
-//----------------------------- W5500 Register values -----------------------------
-
-/* MODE register values */
-/**
- * @brief Reset
- * @details If this bit is All internal registers will be initialized. It will be automatically cleared as after S/W reset.
- */
-#define MR_RST 0x80
-
-/**
- * @brief Wake on LAN
- * @details 0 : Disable WOL mode\n
- * 1 : Enable WOL mode\n
- * If WOL mode is enabled and the received magic packet over UDP has been normally processed, the Interrupt PIN (INTn) asserts to low.
- * When using WOL mode, the UDP Socket should be opened with any source port number. (Refer to Socket n Mode Register (@ref Sn_MR) for opening Socket.)
- * @note The magic packet over UDP supported by W5500 consists of 6 bytes synchronization stream (xFFFFFFFFFFFF and
- * 16 times Target MAC address stream in UDP payload. The options such like password are ignored. You can use any UDP source port number for WOL mode.
- */
-#define MR_WOL 0x20
-
-/**
- * @brief Ping block
- * @details 0 : Disable Ping block\n
- * 1 : Enable Ping block\n
- * If the bit is it blocks the response to a ping request.
- */
-#define MR_PB 0x10
-
-/**
- * @brief Enable PPPoE
- * @details 0 : DisablePPPoE mode\n
- * 1 : EnablePPPoE mode\n
- * If you use ADSL, this bit should be
- */
-#define MR_PPPOE 0x08
-
-/**
- * @brief Enable UDP_FORCE_ARP CHECHK
- * @details 0 : Disable Force ARP mode\n
- * 1 : Enable Force ARP mode\n
- * In Force ARP mode, It forces on sending ARP Request whenever data is sent.
- */
-#define MR_FARP 0x02
-
-/* IR register values */
-/**
- * @brief Check IP conflict.
- * @details Bit is set as when own source IP address is same with the sender IP address in the received ARP request.
- */
-#define IR_CONFLICT 0x80
-
-/**
- * @brief Get the destination unreachable message in UDP sending.
- * @details When receiving the ICMP (Destination port unreachable) packet, this bit is set as
- * When this bit is Destination Information such as IP address and Port number may be checked with the corresponding @ref UIPR & @ref UPORTR.
- */
-#define IR_UNREACH 0x40
-
-/**
- * @brief Get the PPPoE close message.
- * @details When PPPoE is disconnected during PPPoE mode, this bit is set.
- */
-#define IR_PPPoE 0x20
-
-/**
- * @brief Get the magic packet interrupt.
- * @details When WOL mode is enabled and receives the magic packet over UDP, this bit is set.
- */
-#define IR_MP 0x10
-
-
-/* PHYCFGR register value */
-#define PHYCFGR_RST ~(1<<7) //< For PHY reset, must operate AND mask.
-#define PHYCFGR_OPMD (1<<6) // Configre PHY with OPMDC value
-#define PHYCFGR_OPMDC_ALLA (7<<3)
-#define PHYCFGR_OPMDC_PDOWN (6<<3)
-#define PHYCFGR_OPMDC_NA (5<<3)
-#define PHYCFGR_OPMDC_100FA (4<<3)
-#define PHYCFGR_OPMDC_100F (3<<3)
-#define PHYCFGR_OPMDC_100H (2<<3)
-#define PHYCFGR_OPMDC_10F (1<<3)
-#define PHYCFGR_OPMDC_10H (0<<3)
-#define PHYCFGR_DPX_FULL (1<<2)
-#define PHYCFGR_DPX_HALF (0<<2)
-#define PHYCFGR_SPD_100 (1<<1)
-#define PHYCFGR_SPD_10 (0<<1)
-#define PHYCFGR_LNK_ON (1<<0)
-#define PHYCFGR_LNK_OFF (0<<0)
-
-/* IMR register values */
-/**
- * @brief IP Conflict Interrupt Mask.
- * @details 0: Disable IP Conflict Interrupt\n
- * 1: Enable IP Conflict Interrupt
- */
-#define IM_IR7 0x80
-
-/**
- * @brief Destination unreachable Interrupt Mask.
- * @details 0: Disable Destination unreachable Interrupt\n
- * 1: Enable Destination unreachable Interrupt
- */
-#define IM_IR6 0x40
-
-/**
- * @brief PPPoE Close Interrupt Mask.
- * @details 0: Disable PPPoE Close Interrupt\n
- * 1: Enable PPPoE Close Interrupt
- */
-#define IM_IR5 0x20
-
-/**
- * @brief Magic Packet Interrupt Mask.
- * @details 0: Disable Magic Packet Interrupt\n
- * 1: Enable Magic Packet Interrupt
- */
-#define IM_IR4 0x10
-
-/* Sn_MR Default values */
-/**
- * @brief Support UDP Multicasting
- * @details 0 : disable Multicasting\n
- * 1 : enable Multicasting\n
- * This bit is applied only during UDP mode(P[3:0] = 010.\n
- * To use multicasting, @ref Sn_DIPR & @ref Sn_DPORT should be respectively configured with the multicast group IP address & port number
- * before Socket n is opened by OPEN command of @ref Sn_CR.
- */
-#define Sn_MR_MULTI 0x80
-
-/**
- * @brief Broadcast block in UDP Multicasting.
- * @details 0 : disable Broadcast Blocking\n
- * 1 : enable Broadcast Blocking\n
- * This bit blocks to receive broadcasting packet during UDP mode(P[3:0] = 010.\m
- * In addition, This bit does when MACRAW mode(P[3:0] = 100
- */
-#define Sn_MR_BCASTB 0x40
-
-/**
- * @brief No Delayed Ack(TCP), Multicast flag
- * @details 0 : Disable No Delayed ACK option\n
- * 1 : Enable No Delayed ACK option\n
- * This bit is applied only during TCP mode (P[3:0] = 001.\n
- * When this bit is It sends the ACK packet without delay as soon as a Data packet is received from a peer.\n
- * When this bit is It sends the ACK packet after waiting for the timeout time configured by @ref RTR.
- */
-#define Sn_MR_ND 0x20
-
-/**
- * @brief Unicast Block in UDP Multicasting
- * @details 0 : disable Unicast Blocking\n
- * 1 : enable Unicast Blocking\n
- * This bit blocks receiving the unicast packet during UDP mode(P[3:0] = 010 and MULTI =
- */
-#define Sn_MR_UCASTB 0x10
-
-/**
- * @brief MAC LAYER RAW SOCK
- * @details This configures the protocol mode of Socket n.
- * @note MACRAW mode should be only used in Socket 0.
- */
-#define Sn_MR_MACRAW 0x04
-
-//#define Sn_MR_IPRAW 0x03 /**< IP LAYER RAW SOCK */
-
-/**
- * @brief UDP
- * @details This configures the protocol mode of Socket n.
- */
-#define Sn_MR_UDP 0x02
-
-/**
- * @brief TCP
- * @details This configures the protocol mode of Socket n.
- */
-#define Sn_MR_TCP 0x01
-
-/**
- * @brief Unused socket
- * @details This configures the protocol mode of Socket n.
- */
-#define Sn_MR_CLOSE 0x00
-
-/* Sn_MR values used with Sn_MR_MACRAW */
-/**
- * @brief MAC filter enable in @ref Sn_MR_MACRAW mode
- * @details 0 : disable MAC Filtering\n
- * 1 : enable MAC Filtering\n
- * This bit is applied only during MACRAW mode(P[3:0] = 100.\n
- * When set as W5500 can only receive broadcasting packet or packet sent to itself.
- * When this bit is W5500 can receive all packets on Ethernet.
- * If user wants to implement Hybrid TCP/IP stack,
- * it is recommended that this bit is set as for reducing host overhead to process the all received packets.
- */
-#define Sn_MR_MFEN Sn_MR_MULTI
-
-/**
- * @brief Multicast Blocking in @ref Sn_MR_MACRAW mode
- * @details 0 : using IGMP version 2\n
- * 1 : using IGMP version 1\n
- * This bit is applied only during UDP mode(P[3:0] = 010 and MULTI =
- * It configures the version for IGMP messages (Join/Leave/Report).
- */
-#define Sn_MR_MMB Sn_MR_ND
-
-/**
- * @brief IPv6 packet Blocking in @ref Sn_MR_MACRAW mode
- * @details 0 : disable IPv6 Blocking\n
- * 1 : enable IPv6 Blocking\n
- * This bit is applied only during MACRAW mode (P[3:0] = 100. It blocks to receiving the IPv6 packet.
- */
-#define Sn_MR_MIP6B Sn_MR_UCASTB
-
-/* Sn_MR value used with Sn_MR_UDP & Sn_MR_MULTI */
-/**
- * @brief IGMP version used in UDP mulitcasting
- * @details 0 : disable Multicast Blocking\n
- * 1 : enable Multicast Blocking\n
- * This bit is applied only when MACRAW mode(P[3:0] = 100. It blocks to receive the packet with multicast MAC address.
- */
-#define Sn_MR_MC Sn_MR_ND
-
-/* Sn_MR alternate values */
-/**
- * @brief For Berkeley Socket API
- */
-#define SOCK_STREAM Sn_MR_TCP
-
-/**
- * @brief For Berkeley Socket API
- */
-#define SOCK_DGRAM Sn_MR_UDP
-
-
-/* Sn_CR values */
-/**
- * @brief Initialize or open socket
- * @details Socket n is initialized and opened according to the protocol selected in Sn_MR(P3:P0).
- * The table below shows the value of @ref Sn_SR corresponding to @ref Sn_MR.\n
- *
- *
\b Sn_MR (P[3:0])
\b Sn_SR
- *
Sn_MR_CLOSE (000
- *
Sn_MR_TCP (001
SOCK_INIT (0x13)
- *
Sn_MR_UDP (010
SOCK_UDP (0x22)
- *
S0_MR_MACRAW (100
SOCK_MACRAW (0x02)
- *
- */
-#define Sn_CR_OPEN 0x01
-
-/**
- * @brief Wait connection request in TCP mode(Server mode)
- * @details This is valid only in TCP mode (Sn_MR(P3:P0) = Sn_MR_TCP).
- * In this mode, Socket n operates as a �TCP serverand waits for connection-request (SYN packet) from any �TCP client
- * The @ref Sn_SR changes the state from SOCK_INIT to SOCKET_LISTEN.
- * When a �TCP clientconnection request is successfully established,
- * the @ref Sn_SR changes from SOCK_LISTEN to SOCK_ESTABLISHED and the Sn_IR(0) becomes
- * But when a �TCP clientconnection request is failed, Sn_IR(3) becomes and the status of @ref Sn_SR changes to SOCK_CLOSED.
- */
-#define Sn_CR_LISTEN 0x02
-
-/**
- * @brief Send connection request in TCP mode(Client mode)
- * @details To connect, a connect-request (SYN packet) is sent to b>TCP serverconfigured by @ref Sn_DIPR & Sn_DPORT(destination address & port).
- * If the connect-request is successful, the @ref Sn_SR is changed to @ref SOCK_ESTABLISHED and the Sn_IR(0) becomes \n\n
- * The connect-request fails in the following three cases.\n
- * 1. When a @b ARPTO occurs (@ref Sn_IR[3] = ) because destination hardware address is not acquired through the ARP-process.\n
- * 2. When a @b SYN/ACK packet is not received and @b TCPTO (Sn_IR(3) = )\n
- * 3. When a @b RST packet is received instead of a @b SYN/ACK packet. In these cases, @ref Sn_SR is changed to @ref SOCK_CLOSED.
- * @note This is valid only in TCP mode and operates when Socket n acts as b>TCP client
- */
-#define Sn_CR_CONNECT 0x04
-
-/**
- * @brief Send closing request in TCP mode
- * @details Regardless of b>TCP serveror b>TCP client the DISCON command processes the disconnect-process (b>Active closeor b>Passive close.\n
- * @par Active close
- * it transmits disconnect-request(FIN packet) to the connected peer\n
- * @par Passive close
- * When FIN packet is received from peer, a FIN packet is replied back to the peer.\n
- * @details When the disconnect-process is successful (that is, FIN/ACK packet is received successfully), @ref Sn_SR is changed to @ref SOCK_CLOSED.\n
- * Otherwise, TCPTO occurs (Sn_IR(3)=)= and then @ref Sn_SR is changed to @ref SOCK_CLOSED.
- * @note Valid only in TCP mode.
- */
-#define Sn_CR_DISCON 0x08
-
-/**
- * @brief Close socket
- * @details Sn_SR is changed to @ref SOCK_CLOSED.
- */
-#define Sn_CR_CLOSE 0x10
-
-/**
- * @brief Update TX buffer pointer and send data
- * @details SEND transmits all the data in the Socket n TX buffer.\n
- * For more details, please refer to Socket n TX Free Size Register (@ref Sn_TX_FSR), Socket n,
- * TX Write Pointer Register(@ref Sn_TX_WR), and Socket n TX Read Pointer Register(@ref Sn_TX_RD).
- */
-#define Sn_CR_SEND 0x20
-
-/**
- * @brief Send data with MAC address, so without ARP process
- * @details The basic operation is same as SEND.\n
- * Normally SEND transmits data after destination hardware address is acquired by the automatic ARP-process(Address Resolution Protocol).\n
- * But SEND_MAC transmits data without the automatic ARP-process.\n
- * In this case, the destination hardware address is acquired from @ref Sn_DHAR configured by host, instead of APR-process.
- * @note Valid only in UDP mode.
- */
-#define Sn_CR_SEND_MAC 0x21
-
-/**
- * @brief Send keep alive message
- * @details It checks the connection status by sending 1byte keep-alive packet.\n
- * If the peer can not respond to the keep-alive packet during timeout time, the connection is terminated and the timeout interrupt will occur.
- * @note Valid only in TCP mode.
- */
-#define Sn_CR_SEND_KEEP 0x22
-
-/**
- * @brief Update RX buffer pointer and receive data
- * @details RECV completes the processing of the received data in Socket n RX Buffer by using a RX read pointer register (@ref Sn_RX_RD).\n
- * For more details, refer to Socket n RX Received Size Register (@ref Sn_RX_RSR), Socket n RX Write Pointer Register (@ref Sn_RX_WR),
- * and Socket n RX Read Pointer Register (@ref Sn_RX_RD).
- */
-#define Sn_CR_RECV 0x40
-
-/* Sn_IR values */
-/**
- * @brief SEND_OK Interrupt
- * @details This is issued when SEND command is completed.
- */
-#define Sn_IR_SENDOK 0x10
-
-/**
- * @brief TIMEOUT Interrupt
- * @details This is issued when ARPTO or TCPTO occurs.
- */
-#define Sn_IR_TIMEOUT 0x08
-
-/**
- * @brief RECV Interrupt
- * @details This is issued whenever data is received from a peer.
- */
-#define Sn_IR_RECV 0x04
-
-/**
- * @brief DISCON Interrupt
- * @details This is issued when FIN or FIN/ACK packet is received from a peer.
- */
-#define Sn_IR_DISCON 0x02
-
-/**
- * @brief CON Interrupt
- * @details This is issued one time when the connection with peer is successful and then @ref Sn_SR is changed to @ref SOCK_ESTABLISHED.
- */
-#define Sn_IR_CON 0x01
-
-/* Sn_SR values */
-/**
- * @brief Closed
- * @details This indicates that Socket n is released.\N
- * When DICON, CLOSE command is ordered, or when a timeout occurs, it is changed to @ref SOCK_CLOSED regardless of previous status.
- */
-#define SOCK_CLOSED 0x00
-
-/**
- * @brief Initiate state
- * @details This indicates Socket n is opened with TCP mode.\N
- * It is changed to @ref SOCK_INIT when Sn_MR(P[3:0]) = 001and OPEN command is ordered.\N
- * After @ref SOCK_INIT, user can use LISTEN /CONNECT command.
- */
-#define SOCK_INIT 0x13
-
-/**
- * @brief Listen state
- * @details This indicates Socket n is operating as b>TCP servermode and waiting for connection-request (SYN packet) from a peer (b>TCP client.\n
- * It will change to @ref SOCK_ESTALBLISHED when the connection-request is successfully accepted.\n
- * Otherwise it will change to @ref SOCK_CLOSED after TCPTO occurred (Sn_IR(TIMEOUT) = .
- */
-#define SOCK_LISTEN 0x14
-
-/**
- * @brief Connection state
- * @details This indicates Socket n sent the connect-request packet (SYN packet) to a peer.\n
- * It is temporarily shown when @ref Sn_SR is changed from @ref SOCK_INIT to @ref SOCK_ESTABLISHED by CONNECT command.\n
- * If connect-accept(SYN/ACK packet) is received from the peer at SOCK_SYNSENT, it changes to @ref SOCK_ESTABLISHED.\n
- * Otherwise, it changes to @ref SOCK_CLOSED after TCPTO (@ref Sn_IR[TIMEOUT] = is occurred.
- */
-#define SOCK_SYNSENT 0x15
-
-/**
- * @brief Connection state
- * @details It indicates Socket n successfully received the connect-request packet (SYN packet) from a peer.\n
- * If socket n sends the response (SYN/ACK packet) to the peer successfully, it changes to @ref SOCK_ESTABLISHED. \n
- * If not, it changes to @ref SOCK_CLOSED after timeout occurs (@ref Sn_IR[TIMEOUT] = .
- */
-#define SOCK_SYNRECV 0x16
-
-/**
- * @brief Success to connect
- * @details This indicates the status of the connection of Socket n.\n
- * It changes to @ref SOCK_ESTABLISHED when the b>TCP SERVERprocessed the SYN packet from the b>TCP CLIENTduring @ref SOCK_LISTEN, or
- * when the CONNECT command is successful.\n
- * During @ref SOCK_ESTABLISHED, DATA packet can be transferred using SEND or RECV command.
- */
-#define SOCK_ESTABLISHED 0x17
-
-/**
- * @brief Closing state
- * @details These indicate Socket n is closing.\n
- * These are shown in disconnect-process such as active-close and passive-close.\n
- * When Disconnect-process is successfully completed, or when timeout occurs, these change to @ref SOCK_CLOSED.
- */
-#define SOCK_FIN_WAIT 0x18
-
-/**
- * @brief Closing state
- * @details These indicate Socket n is closing.\n
- * These are shown in disconnect-process such as active-close and passive-close.\n
- * When Disconnect-process is successfully completed, or when timeout occurs, these change to @ref SOCK_CLOSED.
- */
-#define SOCK_CLOSING 0x1A
-
-/**
- * @brief Closing state
- * @details These indicate Socket n is closing.\n
- * These are shown in disconnect-process such as active-close and passive-close.\n
- * When Disconnect-process is successfully completed, or when timeout occurs, these change to @ref SOCK_CLOSED.
- */
-#define SOCK_TIME_WAIT 0x1B
-
-/**
- * @brief Closing state
- * @details This indicates Socket n received the disconnect-request (FIN packet) from the connected peer.\n
- * This is half-closing status, and data can be transferred.\n
- * For full-closing, DISCON command is used. But For just-closing, CLOSE command is used.
- */
-#define SOCK_CLOSE_WAIT 0x1C
-
-/**
- * @brief Closing state
- * @details This indicates Socket n is waiting for the response (FIN/ACK packet) to the disconnect-request (FIN packet) by passive-close.\n
- * It changes to @ref SOCK_CLOSED when Socket n received the response successfully, or when timeout occurs (@ref Sn_IR[TIMEOUT] = .
- */
-#define SOCK_LAST_ACK 0x1D
-
-/**
- * @brief UDP socket
- * @details This indicates Socket n is opened in UDP mode(Sn_MR(P[3:0]) = 010.\n
- * It changes to SOCK_UPD when Sn_MR(P[3:0]) = 010 and OPEN command is ordered.\n
- * Unlike TCP mode, data can be transfered without the connection-process.
- */
-#define SOCK_UDP 0x22
-
-//#define SOCK_IPRAW 0x32 /**< IP raw mode socket */
-
-/**
- * @brief MAC raw mode socket
- * @details This indicates Socket 0 is opened in MACRAW mode (S0_MR(P[3:0]) = 100and is valid only in Socket 0.\n
- * It changes to SOCK_MACRAW when S0_MR(P[3:0] = 100and OPEN command is ordered.\n
- * Like UDP mode socket, MACRAW mode Socket 0 can transfer a MAC packet (Ethernet frame) without the connection-process.
- */
-#define SOCK_MACRAW 0x42
-
-//#define SOCK_PPPOE 0x5F
-
-/* IP PROTOCOL */
-#define IPPROTO_IP 0 //< Dummy for IP
-#define IPPROTO_ICMP 1 //< Control message protocol
-#define IPPROTO_IGMP 2 //< Internet group management protocol
-#define IPPROTO_GGP 3 //< Gateway^2 (deprecated)
-#define IPPROTO_TCP 6 //< TCP
-#define IPPROTO_PUP 12 //< PUP
-#define IPPROTO_UDP 17 //< UDP
-#define IPPROTO_IDP 22 //< XNS idp
-#define IPPROTO_ND 77 //< UNOFFICIAL net disk protocol
-#define IPPROTO_RAW 255 //< Raw IP packet
-
-
-/**
- * @brief Enter a critical section
- *
- * @details It is provided to protect your shared code which are executed without distribution. \n \n
- *
- * In non-OS environment, It can be just implemented by disabling whole interrupt.\n
- * In OS environment, You can replace it to critical section api supported by OS.
- *
- * \sa WIZCHIP_READ(), WIZCHIP_WRITE(), WIZCHIP_READ_BUF(), WIZCHIP_WRITE_BUF()
- * \sa WIZCHIP_CRITICAL_EXIT()
- */
-#define WIZCHIP_CRITICAL_ENTER() WIZCHIP.CRIS._enter()
-
-/**
- * @brief Exit a critical section
- *
- * @details It is provided to protect your shared code which are executed without distribution. \n\n
- *
- * In non-OS environment, It can be just implemented by disabling whole interrupt. \n
- * In OS environment, You can replace it to critical section api supported by OS.
- *
- * @sa WIZCHIP_READ(), WIZCHIP_WRITE(), WIZCHIP_READ_BUF(), WIZCHIP_WRITE_BUF()
- * @sa WIZCHIP_CRITICAL_ENTER()
- */
-#ifdef _exit
-#undef _exit
-#endif
-#define WIZCHIP_CRITICAL_EXIT() WIZCHIP.CRIS._exit()
-
-
-
-////////////////////////
-// Basic I/O Function //
-////////////////////////
-
-/**
- * @ingroup Basic_IO_function
- * @brief It reads 1 byte value from a register.
- * @param AddrSel Register address
- * @return The value of register
- */
-uint8_t WIZCHIP_READ (uint32_t AddrSel);
-
-/**
- * @ingroup Basic_IO_function
- * @brief It writes 1 byte value to a register.
- * @param AddrSel Register address
- * @param wb Write data
- * @return void
- */
-void WIZCHIP_WRITE(uint32_t AddrSel, uint8_t wb );
-
-/**
- * @ingroup Basic_IO_function
- * @brief It reads sequence data from registers.
- * @param AddrSel Register address
- * @param pBuf Pointer buffer to read data
- * @param len Data length
- */
-void WIZCHIP_READ_BUF (uint32_t AddrSel, uint8_t* pBuf, uint16_t len);
-
-/**
- * @ingroup Basic_IO_function
- * @brief It writes sequence data to registers.
- * @param AddrSel Register address
- * @param pBuf Pointer buffer to write data
- * @param len Data length
- */
-void WIZCHIP_WRITE_BUF(uint32_t AddrSel, uint8_t* pBuf, uint16_t len);
-
-/////////////////////////////////
-// Common Register I/O function //
-/////////////////////////////////
-/**
- * @ingroup Common_register_access_function
- * @brief Set Mode Register
- * @param (uint8_t)mr The value to be set.
- * @sa getMR()
- */
-#define setMR(mr) \
- WIZCHIP_WRITE(MR,mr)
-
-
-/**
- * @ingroup Common_register_access_function
- * @brief Get Mode Register
- * @return uint8_t. The value of Mode register.
- * @sa setMR()
- */
-#define getMR() \
- WIZCHIP_READ(MR)
-
-/**
- * @ingroup Common_register_access_function
- * @brief Set gateway IP address
- * @param (uint8_t*)gar Pointer variable to set gateway IP address. It should be allocated 4 bytes.
- * @sa getGAR()
- */
-#define setGAR(gar) \
- WIZCHIP_WRITE_BUF(GAR,gar,4)
-
-/**
- * @ingroup Common_register_access_function
- * @brief Get gateway IP address
- * @param (uint8_t*)gar Pointer variable to get gateway IP address. It should be allocated 4 bytes.
- * @sa setGAR()
- */
-#define getGAR(gar) \
- WIZCHIP_READ_BUF(GAR,gar,4)
-
-/**
- * @ingroup Common_register_access_function
- * @brief Set subnet mask address
- * @param (uint8_t*)subr Pointer variable to set subnet mask address. It should be allocated 4 bytes.
- * @sa getSUBR()
- */
-#define setSUBR(subr) \
- WIZCHIP_WRITE_BUF(SUBR, subr,4)
-
-
-/**
- * @ingroup Common_register_access_function
- * @brief Get subnet mask address
- * @param (uint8_t*)subr Pointer variable to get subnet mask address. It should be allocated 4 bytes.
- * @sa setSUBR()
- */
-#define getSUBR(subr) \
- WIZCHIP_READ_BUF(SUBR, subr, 4)
-
-/**
- * @ingroup Common_register_access_function
- * @brief Set local MAC address
- * @param (uint8_t*)shar Pointer variable to set local MAC address. It should be allocated 6 bytes.
- * @sa getSHAR()
- */
-#define setSHAR(shar) \
- WIZCHIP_WRITE_BUF(SHAR, shar, 6)
-
-/**
- * @ingroup Common_register_access_function
- * @brief Get local MAC address
- * @param (uint8_t*)shar Pointer variable to get local MAC address. It should be allocated 6 bytes.
- * @sa setSHAR()
- */
-#define getSHAR(shar) \
- WIZCHIP_READ_BUF(SHAR, shar, 6)
-
-/**
- * @ingroup Common_register_access_function
- * @brief Set local IP address
- * @param (uint8_t*)sipr Pointer variable to set local IP address. It should be allocated 4 bytes.
- * @sa getSIPR()
- */
-#define setSIPR(sipr) \
- WIZCHIP_WRITE_BUF(SIPR, sipr, 4)
-
-/**
- * @ingroup Common_register_access_function
- * @brief Get local IP address
- * @param (uint8_t*)sipr Pointer variable to get local IP address. It should be allocated 4 bytes.
- * @sa setSIPR()
- */
-#define getSIPR(sipr) \
- WIZCHIP_READ_BUF(SIPR, sipr, 4)
-
-/**
- * @ingroup Common_register_access_function
- * @brief Set INTLEVEL register
- * @param (uint16_t)intlevel Value to set @ref INTLEVEL register.
- * @sa getINTLEVEL()
- */
-#define setINTLEVEL(intlevel) {\
- WIZCHIP_WRITE(INTLEVEL, (uint8_t)(intlevel >> 8)); \
- WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(INTLEVEL,1), (uint8_t) intlevel); \
- }
-
-
-/**
- * @ingroup Common_register_access_function
- * @brief Get INTLEVEL register
- * @return uint16_t. Value of @ref INTLEVEL register.
- * @sa setINTLEVEL()
- */
-#define getINTLEVEL() \
- ((WIZCHIP_READ(INTLEVEL) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(INTLEVEL,1)))
-
-/**
- * @ingroup Common_register_access_function
- * @brief Set @ref IR register
- * @param (uint8_t)ir Value to set @ref IR register.
- * @sa getIR()
- */
-#define setIR(ir) \
- WIZCHIP_WRITE(IR, (ir & 0xF0))
-
-/**
- * @ingroup Common_register_access_function
- * @brief Get @ref IR register
- * @return uint8_t. Value of @ref IR register.
- * @sa setIR()
- */
-#define getIR() \
- (WIZCHIP_READ(IR) & 0xF0)
-/**
- * @ingroup Common_register_access_function
- * @brief Set @ref IMR register
- * @param (uint8_t)imr Value to set @ref IMR register.
- * @sa getIMR()
- */
-#define setIMR(imr) \
- WIZCHIP_WRITE(IMR, imr)
-
-/**
- * @ingroup Common_register_access_function
- * @brief Get @ref IMR register
- * @return uint8_t. Value of @ref IMR register.
- * @sa setIMR()
- */
-#define getIMR() \
- WIZCHIP_READ(IMR)
-
-
-/**
- * @ingroup Common_register_access_function
- * @brief Set @ref SIR register
- * @param (uint8_t)sir Value to set @ref SIR register.
- * @sa getSIR()
- */
-#define setSIR(sir) \
- WIZCHIP_WRITE(SIR, sir)
-
-/**
- * @ingroup Common_register_access_function
- * @brief Get @ref SIR register
- * @return uint8_t. Value of @ref SIR register.
- * @sa setSIR()
- */
-#define getSIR() \
- WIZCHIP_READ(SIR)
-/**
- * @ingroup Common_register_access_function
- * @brief Set @ref SIMR register
- * @param (uint8_t)simr Value to set @ref SIMR register.
- * @sa getSIMR()
- */
-#define setSIMR(simr) \
- WIZCHIP_WRITE(SIMR, simr)
-
-/**
- * @ingroup Common_register_access_function
- * @brief Get @ref SIMR register
- * @return uint8_t. Value of @ref SIMR register.
- * @sa setSIMR()
- */
-#define getSIMR() \
- WIZCHIP_READ(SIMR)
-
-/**
- * @ingroup Common_register_access_function
- * @brief Set @ref RTR register
- * @param (uint16_t)rtr Value to set @ref RTR register.
- * @sa getRTR()
- */
-#define setRTR(rtr) {\
- WIZCHIP_WRITE(RTR, (uint8_t)(rtr >> 8)); \
- WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(RTR,1), (uint8_t) rtr); \
- }
-
-/**
- * @ingroup Common_register_access_function
- * @brief Get @ref RTR register
- * @return uint16_t. Value of @ref RTR register.
- * @sa setRTR()
- */
-#define getRTR() \
- ((WIZCHIP_READ(RTR) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(RTR,1)))
-
-/**
- * @ingroup Common_register_access_function
- * @brief Set @ref RCR register
- * @param (uint8_t)rcr Value to set @ref RCR register.
- * @sa getRCR()
- */
-#define setRCR(rcr) \
- WIZCHIP_WRITE(RCR, rcr)
-
-/**
- * @ingroup Common_register_access_function
- * @brief Get @ref RCR register
- * @return uint8_t. Value of @ref RCR register.
- * @sa setRCR()
- */
-#define getRCR() \
- WIZCHIP_READ(RCR)
-
-//================================================== test done ===========================================================
-
-/**
- * @ingroup Common_register_access_function
- * @brief Set @ref PTIMER register
- * @param (uint8_t)ptimer Value to set @ref PTIMER register.
- * @sa getPTIMER()
- */
-#define setPTIMER(ptimer) \
- WIZCHIP_WRITE(PTIMER, ptimer)
-
-/**
- * @ingroup Common_register_access_function
- * @brief Get @ref PTIMER register
- * @return uint8_t. Value of @ref PTIMER register.
- * @sa setPTIMER()
- */
-#define getPTIMER() \
- WIZCHIP_READ(PTIMER)
-
-/**
- * @ingroup Common_register_access_function
- * @brief Set @ref PMAGIC register
- * @param (uint8_t)pmagic Value to set @ref PMAGIC register.
- * @sa getPMAGIC()
- */
-#define setPMAGIC(pmagic) \
- WIZCHIP_WRITE(PMAGIC, pmagic)
-
-/**
- * @ingroup Common_register_access_function
- * @brief Get @ref PMAGIC register
- * @return uint8_t. Value of @ref PMAGIC register.
- * @sa setPMAGIC()
- */
-#define getPMAGIC() \
- WIZCHIP_READ(PMAGIC)
-
-/**
- * @ingroup Common_register_access_function
- * @brief Set PHAR address
- * @param (uint8_t*)phar Pointer variable to set PPP destination MAC register address. It should be allocated 6 bytes.
- * @sa getPHAR()
- */
-#define setPHAR(phar) \
- WIZCHIP_WRITE_BUF(PHAR, phar, 6)
-
-/**
- * @ingroup Common_register_access_function
- * @brief Get local IP address
- * @param (uint8_t*)phar Pointer variable to PPP destination MAC register address. It should be allocated 6 bytes.
- * @sa setPHAR()
- */
-#define getPHAR(phar) \
- WIZCHIP_READ_BUF(PHAR, phar, 6)
-
-/**
- * @ingroup Common_register_access_function
- * @brief Set @ref PSID register
- * @param (uint16_t)psid Value to set @ref PSID register.
- * @sa getPSID()
- */
-#define setPSID(psid) {\
- WIZCHIP_WRITE(PSID, (uint8_t)(psid >> 8)); \
- WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(PSID,1), (uint8_t) psid); \
- }
-
-/**
- * @ingroup Common_register_access_function
- * @brief Get @ref PSID register
- * @return uint16_t. Value of @ref PSID register.
- * @sa setPSID()
- */
-//uint16_t getPSID(void);
-#define getPSID() \
- ((WIZCHIP_READ(PSID) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(PSID,1)))
-
-/**
- * @ingroup Common_register_access_function
- * @brief Set @ref PMRU register
- * @param (uint16_t)pmru Value to set @ref PMRU register.
- * @sa getPMRU()
- */
-#define setPMRU(pmru) { \
- WIZCHIP_WRITE(PMRU, (uint8_t)(pmru>>8)); \
- WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(PMRU,1), (uint8_t) pmru); \
- }
-
-/**
- * @ingroup Common_register_access_function
- * @brief Get @ref PMRU register
- * @return uint16_t. Value of @ref PMRU register.
- * @sa setPMRU()
- */
-#define getPMRU() \
- ((WIZCHIP_READ(PMRU) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(PMRU,1)))
-
-/**
- * @ingroup Common_register_access_function
- * @brief Get unreachable IP address
- * @param (uint8_t*)uipr Pointer variable to get unreachable IP address. It should be allocated 4 bytes.
- */
-#define getUIPR(uipr) \
- WIZCHIP_READ_BUF(UIPR,uipr,6)
-
-/**
- * @ingroup Common_register_access_function
- * @brief Get @ref UPORTR register
- * @return uint16_t. Value of @ref UPORTR register.
- */
-#define getUPORTR() \
- ((WIZCHIP_READ(UPORTR) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(UPORTR,1)))
-
-/**
- * @ingroup Common_register_access_function
- * @brief Set @ref PHYCFGR register
- * @param (uint8_t)phycfgr Value to set @ref PHYCFGR register.
- * @sa getPHYCFGR()
- */
-#define setPHYCFGR(phycfgr) \
- WIZCHIP_WRITE(PHYCFGR, phycfgr)
-
-/**
- * @ingroup Common_register_access_function
- * @brief Get @ref PHYCFGR register
- * @return uint8_t. Value of @ref PHYCFGR register.
- * @sa setPHYCFGR()
- */
-#define getPHYCFGR() \
- WIZCHIP_READ(PHYCFGR)
-
-/**
- * @ingroup Common_register_access_function
- * @brief Get @ref VERSIONR register
- * @return uint8_t. Value of @ref VERSIONR register.
- */
-#define getVERSIONR() \
- WIZCHIP_READ(VERSIONR)
-
-/////////////////////////////////////
-
-///////////////////////////////////
-// Socket N register I/O function //
-///////////////////////////////////
-/**
- * @ingroup Socket_register_access_function
- * @brief Set @ref Sn_MR register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @param (uint8_t)mr Value to set @ref Sn_MR
- * @sa getSn_MR()
- */
-#define setSn_MR(sn, mr) \
- WIZCHIP_WRITE(Sn_MR(sn),mr)
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Get @ref Sn_MR register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @return uint8_t. Value of @ref Sn_MR.
- * @sa setSn_MR()
- */
-#define getSn_MR(sn) \
- WIZCHIP_READ(Sn_MR(sn))
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Set @ref Sn_CR register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @param (uint8_t)cr Value to set @ref Sn_CR
- * @sa getSn_CR()
- */
-#define setSn_CR(sn, cr) \
- WIZCHIP_WRITE(Sn_CR(sn), cr)
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Get @ref Sn_CR register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @return uint8_t. Value of @ref Sn_CR.
- * @sa setSn_CR()
- */
-#define getSn_CR(sn) \
- WIZCHIP_READ(Sn_CR(sn))
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Set @ref Sn_IR register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @param (uint8_t)ir Value to set @ref Sn_IR
- * @sa getSn_IR()
- */
-#define setSn_IR(sn, ir) \
- WIZCHIP_WRITE(Sn_IR(sn), (ir & 0x1F))
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Get @ref Sn_IR register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @return uint8_t. Value of @ref Sn_IR.
- * @sa setSn_IR()
- */
-#define getSn_IR(sn) \
- (WIZCHIP_READ(Sn_IR(sn)) & 0x1F)
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Set @ref Sn_IMR register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @param (uint8_t)imr Value to set @ref Sn_IMR
- * @sa getSn_IMR()
- */
-#define setSn_IMR(sn, imr) \
- WIZCHIP_WRITE(Sn_IMR(sn), (imr & 0x1F))
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Get @ref Sn_IMR register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @return uint8_t. Value of @ref Sn_IMR.
- * @sa setSn_IMR()
- */
-#define getSn_IMR(sn) \
- (WIZCHIP_READ(Sn_IMR(sn)) & 0x1F)
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Get @ref Sn_SR register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @return uint8_t. Value of @ref Sn_SR.
- */
-#define getSn_SR(sn) \
- WIZCHIP_READ(Sn_SR(sn))
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Set @ref Sn_PORT register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @param (uint16_t)port Value to set @ref Sn_PORT.
- * @sa getSn_PORT()
- */
-#define setSn_PORT(sn, port) { \
- WIZCHIP_WRITE(Sn_PORT(sn), (uint8_t)(port >> 8)); \
- WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_PORT(sn),1), (uint8_t) port); \
- }
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Get @ref Sn_PORT register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @return uint16_t. Value of @ref Sn_PORT.
- * @sa setSn_PORT()
- */
-#define getSn_PORT(sn) \
- ((WIZCHIP_READ(Sn_PORT(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_PORT(sn),1)))
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Set @ref Sn_DHAR register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @param (uint8_t*)dhar Pointer variable to set socket n destination hardware address. It should be allocated 6 bytes.
- * @sa getSn_DHAR()
- */
-#define setSn_DHAR(sn, dhar) \
- WIZCHIP_WRITE_BUF(Sn_DHAR(sn), dhar, 6)
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Get @ref Sn_MR register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @param (uint8_t*)dhar Pointer variable to get socket n destination hardware address. It should be allocated 6 bytes.
- * @sa setSn_DHAR()
- */
-#define getSn_DHAR(sn, dhar) \
- WIZCHIP_READ_BUF(Sn_DHAR(sn), dhar, 6)
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Set @ref Sn_DIPR register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @param (uint8_t*)dipr Pointer variable to set socket n destination IP address. It should be allocated 4 bytes.
- * @sa getSn_DIPR()
- */
-#define setSn_DIPR(sn, dipr) \
- WIZCHIP_WRITE_BUF(Sn_DIPR(sn), dipr, 4)
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Get @ref Sn_DIPR register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @param (uint8_t*)dipr Pointer variable to get socket n destination IP address. It should be allocated 4 bytes.
- * @sa SetSn_DIPR()
- */
-#define getSn_DIPR(sn, dipr) \
- WIZCHIP_READ_BUF(Sn_DIPR(sn), dipr, 4)
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Set @ref Sn_DPORT register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @param (uint16_t)dport Value to set @ref Sn_DPORT
- * @sa getSn_DPORT()
- */
-#define setSn_DPORT(sn, dport) { \
- WIZCHIP_WRITE(Sn_DPORT(sn), (uint8_t) (dport>>8)); \
- WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_DPORT(sn),1), (uint8_t) dport); \
- }
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Get @ref Sn_DPORT register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @return uint16_t. Value of @ref Sn_DPORT.
- * @sa setSn_DPORT()
- */
-#define getSn_DPORT(sn) \
- ((WIZCHIP_READ(Sn_DPORT(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_DPORT(sn),1)))
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Set @ref Sn_MSSR register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @param (uint16_t)mss Value to set @ref Sn_MSSR
- * @sa setSn_MSSR()
- */
-#define setSn_MSSR(sn, mss) { \
- WIZCHIP_WRITE(Sn_MSSR(sn), (uint8_t)(mss>>8)); \
- WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_MSSR(sn),1), (uint8_t) mss); \
- }
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Get @ref Sn_MSSR register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @return uint16_t. Value of @ref Sn_MSSR.
- * @sa setSn_MSSR()
- */
-#define getSn_MSSR(sn) \
- ((WIZCHIP_READ(Sn_MSSR(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_MSSR(sn),1)))
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Set @ref Sn_TOS register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @param (uint8_t)tos Value to set @ref Sn_TOS
- * @sa getSn_TOS()
- */
-#define setSn_TOS(sn, tos) \
- WIZCHIP_WRITE(Sn_TOS(sn), tos)
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Get @ref Sn_TOS register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @return uint8_t. Value of Sn_TOS.
- * @sa setSn_TOS()
- */
-#define getSn_TOS(sn) \
- WIZCHIP_READ(Sn_TOS(sn))
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Set @ref Sn_TTL register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @param (uint8_t)ttl Value to set @ref Sn_TTL
- * @sa getSn_TTL()
- */
-#define setSn_TTL(sn, ttl) \
- WIZCHIP_WRITE(Sn_TTL(sn), ttl)
-
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Get @ref Sn_TTL register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @return uint8_t. Value of @ref Sn_TTL.
- * @sa setSn_TTL()
- */
-#define getSn_TTL(sn) \
- WIZCHIP_READ(Sn_TTL(sn))
-
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Set @ref Sn_RXBUF_SIZE register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @param (uint8_t)rxbufsize Value to set @ref Sn_RXBUF_SIZE
- * @sa getSn_RXBUF_SIZE()
- */
-#define setSn_RXBUF_SIZE(sn, rxbufsize) \
- WIZCHIP_WRITE(Sn_RXBUF_SIZE(sn),rxbufsize)
-
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Get @ref Sn_RXBUF_SIZE register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @return uint8_t. Value of @ref Sn_RXBUF_SIZE.
- * @sa setSn_RXBUF_SIZE()
- */
-#define getSn_RXBUF_SIZE(sn) \
- WIZCHIP_READ(Sn_RXBUF_SIZE(sn))
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Set @ref Sn_TXBUF_SIZE register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @param (uint8_t)txbufsize Value to set @ref Sn_TXBUF_SIZE
- * @sa getSn_TXBUF_SIZE()
- */
-#define setSn_TXBUF_SIZE(sn, txbufsize) \
- WIZCHIP_WRITE(Sn_TXBUF_SIZE(sn), txbufsize)
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Get @ref Sn_TXBUF_SIZE register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @return uint8_t. Value of @ref Sn_TXBUF_SIZE.
- * @sa setSn_TXBUF_SIZE()
- */
-#define getSn_TXBUF_SIZE(sn) \
- WIZCHIP_READ(Sn_TXBUF_SIZE(sn))
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Get @ref Sn_TX_FSR register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @return uint16_t. Value of @ref Sn_TX_FSR.
- */
-uint16_t getSn_TX_FSR(uint8_t sn);
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Get @ref Sn_TX_RD register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @return uint16_t. Value of @ref Sn_TX_RD.
- */
-#define getSn_TX_RD(sn) \
- ((WIZCHIP_READ(Sn_TX_RD(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_TX_RD(sn),1)))
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Set @ref Sn_TX_WR register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @param (uint16_t)txwr Value to set @ref Sn_TX_WR
- * @sa GetSn_TX_WR()
- */
-#define setSn_TX_WR(sn, txwr) { \
- WIZCHIP_WRITE(Sn_TX_WR(sn), (uint8_t)(txwr>>8)); \
- WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_TX_WR(sn),1), (uint8_t) txwr); \
- }
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Get @ref Sn_TX_WR register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @return uint16_t. Value of @ref Sn_TX_WR.
- * @sa setSn_TX_WR()
- */
-#define getSn_TX_WR(sn) \
- ((WIZCHIP_READ(Sn_TX_WR(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_TX_WR(sn),1)))
-
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Get @ref Sn_RX_RSR register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @return uint16_t. Value of @ref Sn_RX_RSR.
- */
-uint16_t getSn_RX_RSR(uint8_t sn);
-
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Set @ref Sn_RX_RD register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @param (uint16_t)rxrd Value to set @ref Sn_RX_RD
- * @sa getSn_RX_RD()
- */
-#define setSn_RX_RD(sn, rxrd) { \
- WIZCHIP_WRITE(Sn_RX_RD(sn), (uint8_t)(rxrd>>8)); \
- WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_RX_RD(sn),1), (uint8_t) rxrd); \
- }
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Get @ref Sn_RX_RD register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @regurn uint16_t. Value of @ref Sn_RX_RD.
- * @sa setSn_RX_RD()
- */
-#define getSn_RX_RD(sn) \
- ((WIZCHIP_READ(Sn_RX_RD(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_RX_RD(sn),1)))
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Get @ref Sn_RX_WR register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @return uint16_t. Value of @ref Sn_RX_WR.
- */
-#define getSn_RX_WR(sn) \
- ((WIZCHIP_READ(Sn_RX_WR(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_RX_WR(sn),1)))
-
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Set @ref Sn_FRAG register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @param (uint16_t)frag Value to set @ref Sn_FRAG
- * @sa getSn_FRAD()
- */
-#define setSn_FRAG(sn, frag) { \
- WIZCHIP_WRITE(Sn_FRAG(sn), (uint8_t)(frag >>8)); \
- WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_FRAG(sn),1), (uint8_t) frag); \
- }
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Get @ref Sn_FRAG register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @return uint16_t. Value of @ref Sn_FRAG.
- * @sa setSn_FRAG()
- */
-#define getSn_FRAG(sn) \
- ((WIZCHIP_READ(Sn_FRAG(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_FRAG(sn),1)))
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Set @ref Sn_KPALVTR register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @param (uint8_t)kpalvt Value to set @ref Sn_KPALVTR
- * @sa getSn_KPALVTR()
- */
-#define setSn_KPALVTR(sn, kpalvt) \
- WIZCHIP_WRITE(Sn_KPALVTR(sn), kpalvt)
-
-/**
- * @ingroup Socket_register_access_function
- * @brief Get @ref Sn_KPALVTR register
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @return uint8_t. Value of @ref Sn_KPALVTR.
- * @sa setSn_KPALVTR()
- */
-#define getSn_KPALVTR(sn) \
- WIZCHIP_READ(Sn_KPALVTR(sn))
-
-//////////////////////////////////////
-
-/////////////////////////////////////
-// Sn_TXBUF & Sn_RXBUF IO function //
-/////////////////////////////////////
-/**
- * @brief Gets the max buffer size of socket sn passed as parameter.
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @return uint16_t. Value of Socket n RX max buffer size.
- */
-#define getSn_RxMAX(sn) \
- (getSn_RXBUF_SIZE(sn) << 10)
-
-/**
- * @brief Gets the max buffer size of socket sn passed as parameters.
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @return uint16_t. Value of Socket n TX max buffer size.
- */
-//uint16_t getSn_TxMAX(uint8_t sn);
-#define getSn_TxMAX(sn) \
- (getSn_TXBUF_SIZE(sn) << 10)
-
-/**
- * @ingroup Basic_IO_function
- * @brief It copies data to internal TX memory
- *
- * @details This function reads the Tx write pointer register and after that,
- * it copies the wizdata(pointer buffer) of the length of len(variable) bytes to internal TX memory
- * and updates the Tx write pointer register.
- * This function is being called by send() and sendto() function also.
- *
- * @note User should read upper byte first and lower byte later to get proper value.
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @param wizdata Pointer buffer to write data
- * @param len Data length
- * @sa wiz_recv_data()
- */
-void wiz_send_data(uint8_t sn, uint8_t *wizdata, uint16_t len);
-
-/**
- * @ingroup Basic_IO_function
- * @brief It copies data to your buffer from internal RX memory
- *
- * @details This function read the Rx read pointer register and after that,
- * it copies the received data from internal RX memory
- * to wizdata(pointer variable) of the length of len(variable) bytes.
- * This function is being called by recv() also.
- *
- * @note User should read upper byte first and lower byte later to get proper value.
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @param wizdata Pointer buffer to read data
- * @param len Data length
- * @sa wiz_send_data()
- */
-void wiz_recv_data(uint8_t sn, uint8_t *wizdata, uint16_t len);
-
-/**
- * @ingroup Basic_IO_function
- * @brief It discard the received data in RX memory.
- * @details It discards the data of the length of len(variable) bytes in internal RX memory.
- * @param (uint8_t)sn Socket number. It should be 0 ~ 7.
- * @param len Data length
- */
-void wiz_recv_ignore(uint8_t sn, uint16_t len);
-
-#endif // _W5500_H_
diff --git a/drivers/wiznet5k/ethernet/wizchip_conf.c b/drivers/wiznet5k/ethernet/wizchip_conf.c
deleted file mode 100644
index 3e54d2c90bcd..000000000000
--- a/drivers/wiznet5k/ethernet/wizchip_conf.c
+++ /dev/null
@@ -1,662 +0,0 @@
-//****************************************************************************/
-//!
-//! \file wizchip_conf.c
-//! \brief WIZCHIP Config Header File.
-//! \version 1.0.1
-//! \date 2013/10/21
-//! \par Revision history
-//! <2014/05/01> V1.0.1 Refer to M20140501
-//! 1. Explicit type casting in wizchip_bus_readbyte() & wizchip_bus_writebyte()
-// Issued by Mathias ClauBen.
-//! uint32_t type converts into ptrdiff_t first. And then recoverting it into uint8_t*
-//! For remove the warning when pointer type size is not 32bit.
-//! If ptrdiff_t doesn't support in your complier, You should must replace ptrdiff_t into your suitable pointer type.
-//! <2013/10/21> 1st Release
-//! \author MidnightCow
-//! \copyright
-//!
-//! Copyright (c) 2013, WIZnet Co., LTD.
-//! 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 the 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 OWNER 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.
-//
-//*****************************************************************************/
-//A20140501 : for use the type - ptrdiff_t
-#include
-//
-
-#include "wizchip_conf.h"
-#include "socket.h"
-
-/**
- * @brief Default function to enable interrupt.
- * @note This function help not to access wrong address. If you do not describe this function or register any functions,
- * null function is called.
- */
-void wizchip_cris_enter(void) {};
-/**
- * @brief Default function to disable interrupt.
- * @note This function help not to access wrong address. If you do not describe this function or register any functions,
- * null function is called.
- */
-void wizchip_cris_exit(void) {};
-/**
- * @brief Default function to select chip.
- * @note This function help not to access wrong address. If you do not describe this function or register any functions,
- * null function is called.
- */
-void wizchip_cs_select(void) {};
-/**
- * @brief Default function to deselect chip.
- * @note This function help not to access wrong address. If you do not describe this function or register any functions,
- * null function is called.
- */
-void wizchip_cs_deselect(void) {};
-/**
- * @brief Default function to read in direct or indirect interface.
- * @note This function help not to access wrong address. If you do not describe this function or register any functions,
- * null function is called.
- */
- //M20140501 : Explict pointer type casting
-//uint8_t wizchip_bus_readbyte(uint32_t AddrSel) { return * ((volatile uint8_t *) AddrSel); };
-uint8_t wizchip_bus_readbyte(uint32_t AddrSel) { return * ((volatile uint8_t *)((ptrdiff_t) AddrSel)); };
-/**
- * @brief Default function to write in direct or indirect interface.
- * @note This function help not to access wrong address. If you do not describe this function or register any functions,
- * null function is called.
- */
-
-//M20140501 : Explict pointer type casting
-//void wizchip_bus_writebyte(uint32_t AddrSel, uint8_t wb) { *((volatile uint8_t*) AddrSel) = wb; };
-void wizchip_bus_writebyte(uint32_t AddrSel, uint8_t wb) { *((volatile uint8_t*)((ptrdiff_t)AddrSel)) = wb; };
-
-/**
- * @brief Default function to read in SPI interface.
- * @note This function help not to access wrong address. If you do not describe this function or register any functions,
- * null function is called.
- */
-void wizchip_spi_readbytes(uint8_t *buf, uint32_t len) {}
-/**
- * @brief Default function to write in SPI interface.
- * @note This function help not to access wrong address. If you do not describe this function or register any functions,
- * null function is called.
- */
-void wizchip_spi_writebytes(const uint8_t *buf, uint32_t len) {}
-
-/**
- * @\ref _WIZCHIP instance
- */
-_WIZCHIP WIZCHIP =
- {
- .id = _WIZCHIP_ID_,
- .if_mode = _WIZCHIP_IO_MODE_,
- .CRIS._enter = wizchip_cris_enter,
- .CRIS._exit = wizchip_cris_exit,
- .CS._select = wizchip_cs_select,
- .CS._deselect = wizchip_cs_deselect,
- .IF.BUS._read_byte = wizchip_bus_readbyte,
- .IF.BUS._write_byte = wizchip_bus_writebyte
-// .IF.SPI._read_byte = wizchip_spi_readbyte,
-// .IF.SPI._write_byte = wizchip_spi_writebyte
- };
-
-#if _WIZCHIP_ == 5200 // for W5200 ARP errata
-static uint8_t _SUBN_[4]; // subnet
-#endif
-static uint8_t _DNS_[4]; // DNS server ip address
-static dhcp_mode _DHCP_; // DHCP mode
-
-void reg_wizchip_cris_cbfunc(void(*cris_en)(void), void(*cris_ex)(void))
-{
- if(!cris_en || !cris_ex)
- {
- WIZCHIP.CRIS._enter = wizchip_cris_enter;
- WIZCHIP.CRIS._exit = wizchip_cris_exit;
- }
- else
- {
- WIZCHIP.CRIS._enter = cris_en;
- WIZCHIP.CRIS._exit = cris_ex;
- }
-}
-
-void reg_wizchip_cs_cbfunc(void(*cs_sel)(void), void(*cs_desel)(void))
-{
- if(!cs_sel || !cs_desel)
- {
- WIZCHIP.CS._select = wizchip_cs_select;
- WIZCHIP.CS._deselect = wizchip_cs_deselect;
- }
- else
- {
- WIZCHIP.CS._select = cs_sel;
- WIZCHIP.CS._deselect = cs_desel;
- }
-}
-
-void reg_wizchip_bus_cbfunc(uint8_t(*bus_rb)(uint32_t addr), void (*bus_wb)(uint32_t addr, uint8_t wb))
-{
- while(!(WIZCHIP.if_mode & _WIZCHIP_IO_MODE_BUS_));
-
- if(!bus_rb || !bus_wb)
- {
- WIZCHIP.IF.BUS._read_byte = wizchip_bus_readbyte;
- WIZCHIP.IF.BUS._write_byte = wizchip_bus_writebyte;
- }
- else
- {
- WIZCHIP.IF.BUS._read_byte = bus_rb;
- WIZCHIP.IF.BUS._write_byte = bus_wb;
- }
-}
-
-void reg_wizchip_spi_cbfunc(void (*spi_rb)(uint8_t *, uint32_t), void (*spi_wb)(const uint8_t *, uint32_t))
-{
- while(!(WIZCHIP.if_mode & _WIZCHIP_IO_MODE_SPI_));
-
- if(!spi_rb || !spi_wb)
- {
- WIZCHIP.IF.SPI._read_bytes = wizchip_spi_readbytes;
- WIZCHIP.IF.SPI._write_bytes = wizchip_spi_writebytes;
- }
- else
- {
- WIZCHIP.IF.SPI._read_bytes = spi_rb;
- WIZCHIP.IF.SPI._write_bytes = spi_wb;
- }
-}
-
-int8_t ctlwizchip(ctlwizchip_type cwtype, void* arg)
-{
- uint8_t tmp = 0;
- uint8_t* ptmp[2] = {0,0};
- switch(cwtype)
- {
- case CW_RESET_WIZCHIP:
- wizchip_sw_reset();
- break;
- case CW_INIT_WIZCHIP:
- if(arg != 0)
- {
- ptmp[0] = (uint8_t*)arg;
- ptmp[1] = ptmp[0] + _WIZCHIP_SOCK_NUM_;
- }
- return wizchip_init(ptmp[0], ptmp[1]);
- case CW_CLR_INTERRUPT:
- wizchip_clrinterrupt(*((intr_kind*)arg));
- break;
- case CW_GET_INTERRUPT:
- *((intr_kind*)arg) = wizchip_getinterrupt();
- break;
- case CW_SET_INTRMASK:
- wizchip_setinterruptmask(*((intr_kind*)arg));
- break;
- case CW_GET_INTRMASK:
- *((intr_kind*)arg) = wizchip_getinterruptmask();
- break;
- #if _WIZCHIP_ > 5100
- case CW_SET_INTRTIME:
- setINTLEVEL(*(uint16_t*)arg);
- break;
- case CW_GET_INTRTIME:
- *(uint16_t*)arg = getINTLEVEL();
- break;
- #endif
- case CW_GET_ID:
- ((uint8_t*)arg)[0] = WIZCHIP.id[0];
- ((uint8_t*)arg)[1] = WIZCHIP.id[1];
- ((uint8_t*)arg)[2] = WIZCHIP.id[2];
- ((uint8_t*)arg)[3] = WIZCHIP.id[3];
- ((uint8_t*)arg)[4] = WIZCHIP.id[4];
- ((uint8_t*)arg)[5] = 0;
- break;
- #if _WIZCHIP_ == 5500
- case CW_RESET_PHY:
- wizphy_reset();
- break;
- case CW_SET_PHYCONF:
- wizphy_setphyconf((wiz_PhyConf*)arg);
- break;
- case CW_GET_PHYCONF:
- wizphy_getphyconf((wiz_PhyConf*)arg);
- break;
- case CW_GET_PHYSTATUS:
- break;
- case CW_SET_PHYPOWMODE:
- return wizphy_setphypmode(*(uint8_t*)arg);
- #endif
- case CW_GET_PHYPOWMODE:
- tmp = wizphy_getphypmode();
- if((int8_t)tmp == -1) return -1;
- *(uint8_t*)arg = tmp;
- break;
- case CW_GET_PHYLINK:
- tmp = wizphy_getphylink();
- if((int8_t)tmp == -1) return -1;
- *(uint8_t*)arg = tmp;
- break;
- default:
- return -1;
- }
- return 0;
-}
-
-
-int8_t ctlnetwork(ctlnetwork_type cntype, void* arg)
-{
-
- switch(cntype)
- {
- case CN_SET_NETINFO:
- wizchip_setnetinfo((wiz_NetInfo*)arg);
- break;
- case CN_GET_NETINFO:
- wizchip_getnetinfo((wiz_NetInfo*)arg);
- break;
- case CN_SET_NETMODE:
- return wizchip_setnetmode(*(netmode_type*)arg);
- case CN_GET_NETMODE:
- *(netmode_type*)arg = wizchip_getnetmode();
- break;
- case CN_SET_TIMEOUT:
- wizchip_settimeout((wiz_NetTimeout*)arg);
- break;
- case CN_GET_TIMEOUT:
- wizchip_gettimeout((wiz_NetTimeout*)arg);
- break;
- default:
- return -1;
- }
- return 0;
-}
-
-void wizchip_sw_reset(void)
-{
- uint8_t gw[4], sn[4], sip[4];
- uint8_t mac[6];
- getSHAR(mac);
- getGAR(gw); getSUBR(sn); getSIPR(sip);
- setMR(MR_RST);
- getMR(); // for delay
- setSHAR(mac);
- setGAR(gw);
- setSUBR(sn);
- setSIPR(sip);
-}
-
-int8_t wizchip_init(uint8_t* txsize, uint8_t* rxsize)
-{
- int8_t i;
- int8_t tmp = 0;
- wizchip_sw_reset();
- if(txsize)
- {
- tmp = 0;
- for(i = 0 ; i < _WIZCHIP_SOCK_NUM_; i++)
- tmp += txsize[i];
- if(tmp > 16) return -1;
- for(i = 0 ; i < _WIZCHIP_SOCK_NUM_; i++)
- setSn_TXBUF_SIZE(i, txsize[i]);
- }
- if(rxsize)
- {
- tmp = 0;
- for(i = 0 ; i < _WIZCHIP_SOCK_NUM_; i++)
- tmp += rxsize[i];
- if(tmp > 16) return -1;
- for(i = 0 ; i < _WIZCHIP_SOCK_NUM_; i++)
- setSn_RXBUF_SIZE(i, rxsize[i]);
- }
-
- WIZCHIP_EXPORT(socket_reset)();
-
- return 0;
-}
-
-void wizchip_clrinterrupt(intr_kind intr)
-{
- uint8_t ir = (uint8_t)intr;
- uint8_t sir = (uint8_t)((uint16_t)intr >> 8);
-#if _WIZCHIP_ < 5500
- ir |= (1<<4); // IK_WOL
-#endif
-#if _WIZCHIP_ == 5200
- ir |= (1 << 6);
-#endif
-
-#if _WIZCHIP_ < 5200
- sir &= 0x0F;
-#endif
-
-#if _WIZCHIP_ == 5100
- ir |= sir;
- setIR(ir);
-#else
- setIR(ir);
- setSIR(sir);
-#endif
-}
-
-intr_kind wizchip_getinterrupt(void)
-{
- uint8_t ir = 0;
- uint8_t sir = 0;
- uint16_t ret = 0;
-#if _WIZCHIP_ == 5100
- ir = getIR();
- sir = ir 0x0F;
-#else
- ir = getIR();
- sir = getSIR();
-#endif
-
-#if _WIZCHIP_ < 5500
- ir &= ~(1<<4); // IK_WOL
-#endif
-#if _WIZCHIP_ == 5200
- ir &= ~(1 << 6);
-#endif
- ret = sir;
- ret = (ret << 8) + ir;
- return (intr_kind)ret;
-}
-
-void wizchip_setinterruptmask(intr_kind intr)
-{
- uint8_t imr = (uint8_t)intr;
- uint8_t simr = (uint8_t)((uint16_t)intr >> 8);
-#if _WIZCHIP_ < 5500
- imr &= ~(1<<4); // IK_WOL
-#endif
-#if _WIZCHIP_ == 5200
- imr &= ~(1 << 6);
-#endif
-
-#if _WIZCHIP_ < 5200
- simr &= 0x0F;
-#endif
-
-#if _WIZCHIP_ == 5100
- imr |= simr;
- setIMR(imr);
-#else
- setIMR(imr);
- setSIMR(simr);
-#endif
-}
-
-intr_kind wizchip_getinterruptmask(void)
-{
- uint8_t imr = 0;
- uint8_t simr = 0;
- uint16_t ret = 0;
-#if _WIZCHIP_ == 5100
- imr = getIMR();
- simr = imr 0x0F;
-#else
- imr = getIMR();
- simr = getSIMR();
-#endif
-
-#if _WIZCHIP_ < 5500
- imr &= ~(1<<4); // IK_WOL
-#endif
-#if _WIZCHIP_ == 5200
- imr &= ~(1 << 6); // IK_DEST_UNREACH
-#endif
- ret = simr;
- ret = (ret << 8) + imr;
- return (intr_kind)ret;
-}
-
-int8_t wizphy_getphylink(void)
-{
- int8_t tmp;
-#if _WIZCHIP_ == 5200
- if(getPHYSTATUS() & PHYSTATUS_LINK)
- tmp = PHY_LINK_ON;
- else
- tmp = PHY_LINK_OFF;
-#elif _WIZCHIP_ == 5500
- if(getPHYCFGR() & PHYCFGR_LNK_ON)
- tmp = PHY_LINK_ON;
- else
- tmp = PHY_LINK_OFF;
-#else
- tmp = -1;
-#endif
- return tmp;
-}
-
-#if _WIZCHIP_ > 5100
-
-int8_t wizphy_getphypmode(void)
-{
- int8_t tmp = 0;
- #if _WIZCHIP_ == 5200
- if(getPHYSTATUS() & PHYSTATUS_POWERDOWN)
- tmp = PHY_POWER_DOWN;
- else
- tmp = PHY_POWER_NORM;
- #elif _WIZCHIP_ == 5500
- if(getPHYCFGR() & PHYCFGR_OPMDC_PDOWN)
- tmp = PHY_POWER_DOWN;
- else
- tmp = PHY_POWER_NORM;
- #else
- tmp = -1;
- #endif
- return tmp;
-}
-#endif
-
-#if _WIZCHIP_ == 5500
-void wizphy_reset(void)
-{
- uint8_t tmp = getPHYCFGR();
- tmp &= PHYCFGR_RST;
- setPHYCFGR(tmp);
- tmp = getPHYCFGR();
- tmp |= ~PHYCFGR_RST;
- setPHYCFGR(tmp);
-}
-
-void wizphy_setphyconf(wiz_PhyConf* phyconf)
-{
- uint8_t tmp = 0;
- if(phyconf->by == PHY_CONFBY_SW)
- tmp |= PHYCFGR_OPMD;
- else
- tmp &= ~PHYCFGR_OPMD;
- if(phyconf->mode == PHY_MODE_AUTONEGO)
- tmp |= PHYCFGR_OPMDC_ALLA;
- else
- {
- if(phyconf->duplex == PHY_DUPLEX_FULL)
- {
- if(phyconf->speed == PHY_SPEED_100)
- tmp |= PHYCFGR_OPMDC_100F;
- else
- tmp |= PHYCFGR_OPMDC_10F;
- }
- else
- {
- if(phyconf->speed == PHY_SPEED_100)
- tmp |= PHYCFGR_OPMDC_100H;
- else
- tmp |= PHYCFGR_OPMDC_10H;
- }
- }
- setPHYCFGR(tmp);
- wizphy_reset();
-}
-
-void wizphy_getphyconf(wiz_PhyConf* phyconf)
-{
- uint8_t tmp = 0;
- tmp = getPHYCFGR();
- phyconf->by = (tmp & PHYCFGR_OPMD) ? PHY_CONFBY_SW : PHY_CONFBY_HW;
- switch(tmp & PHYCFGR_OPMDC_ALLA)
- {
- case PHYCFGR_OPMDC_ALLA:
- case PHYCFGR_OPMDC_100FA:
- phyconf->mode = PHY_MODE_AUTONEGO;
- break;
- default:
- phyconf->mode = PHY_MODE_MANUAL;
- break;
- }
- switch(tmp & PHYCFGR_OPMDC_ALLA)
- {
- case PHYCFGR_OPMDC_100FA:
- case PHYCFGR_OPMDC_100F:
- case PHYCFGR_OPMDC_100H:
- phyconf->speed = PHY_SPEED_100;
- break;
- default:
- phyconf->speed = PHY_SPEED_10;
- break;
- }
- switch(tmp & PHYCFGR_OPMDC_ALLA)
- {
- case PHYCFGR_OPMDC_100FA:
- case PHYCFGR_OPMDC_100F:
- case PHYCFGR_OPMDC_10F:
- phyconf->duplex = PHY_DUPLEX_FULL;
- break;
- default:
- phyconf->duplex = PHY_DUPLEX_HALF;
- break;
- }
-}
-
-void wizphy_getphystat(wiz_PhyConf* phyconf)
-{
- uint8_t tmp = getPHYCFGR();
- phyconf->duplex = (tmp & PHYCFGR_DPX_FULL) ? PHY_DUPLEX_FULL : PHY_DUPLEX_HALF;
- phyconf->speed = (tmp & PHYCFGR_SPD_100) ? PHY_SPEED_100 : PHY_SPEED_10;
-}
-
-int8_t wizphy_setphypmode(uint8_t pmode)
-{
- uint8_t tmp = 0;
- tmp = getPHYCFGR();
- if((tmp & PHYCFGR_OPMD)== 0) return -1;
- tmp &= ~PHYCFGR_OPMDC_ALLA;
- if( pmode == PHY_POWER_DOWN)
- tmp |= PHYCFGR_OPMDC_PDOWN;
- else
- tmp |= PHYCFGR_OPMDC_ALLA;
- setPHYCFGR(tmp);
- wizphy_reset();
- tmp = getPHYCFGR();
- if( pmode == PHY_POWER_DOWN)
- {
- if(tmp & PHYCFGR_OPMDC_PDOWN) return 0;
- }
- else
- {
- if(tmp & PHYCFGR_OPMDC_ALLA) return 0;
- }
- return -1;
-}
-#endif
-
-
-void wizchip_setnetinfo(wiz_NetInfo* pnetinfo)
-{
- setSHAR(pnetinfo->mac);
- setGAR(pnetinfo->gw);
- setSUBR(pnetinfo->sn);
- setSIPR(pnetinfo->ip);
-#if _WIZCHIP_ == 5200 // for W5200 ARP errata
- _SUBN_[0] = pnetinfo->sn[0];
- _SUBN_[1] = pnetinfo->sn[1];
- _SUBN_[2] = pnetinfo->sn[2];
- _SUBN_[3] = pnetinfo->sn[3];
-#endif
- _DNS_[0] = pnetinfo->dns[0];
- _DNS_[1] = pnetinfo->dns[1];
- _DNS_[2] = pnetinfo->dns[2];
- _DNS_[3] = pnetinfo->dns[3];
- _DHCP_ = pnetinfo->dhcp;
-}
-
-void wizchip_getnetinfo(wiz_NetInfo* pnetinfo)
-{
- getSHAR(pnetinfo->mac);
- getGAR(pnetinfo->gw);
- getSUBR(pnetinfo->sn);
- getSIPR(pnetinfo->ip);
-#if _WIZCHIP_ == 5200 // for W5200 ARP errata
- pnetinfo->sn[0] = _SUBN_[0];
- pnetinfo->sn[1] = _SUBN_[1];
- pnetinfo->sn[2] = _SUBN_[2];
- pnetinfo->sn[3] = _SUBN_[3];
-#endif
- pnetinfo->dns[0]= _DNS_[0];
- pnetinfo->dns[1]= _DNS_[1];
- pnetinfo->dns[2]= _DNS_[2];
- pnetinfo->dns[3]= _DNS_[3];
- pnetinfo->dhcp = _DHCP_;
-}
-
-#if _WIZCHIP_ == 5200 // for W5200 ARP errata
-uint8_t *wizchip_getsubn(void) {
- return _SUBN_;
-}
-#endif
-
-int8_t wizchip_setnetmode(netmode_type netmode)
-{
- uint8_t tmp = 0;
-#if _WIZCHIP_ != 5500
- if(netmode & ~(NM_WAKEONLAN | NM_PPPOE | NM_PINGBLOCK)) return -1;
-#else
- if(netmode & ~(NM_WAKEONLAN | NM_PPPOE | NM_PINGBLOCK | NM_FORCEARP)) return -1;
-#endif
- tmp = getMR();
- tmp |= (uint8_t)netmode;
- setMR(tmp);
- return 0;
-}
-
-netmode_type wizchip_getnetmode(void)
-{
- return (netmode_type) getMR();
-}
-
-void wizchip_settimeout(wiz_NetTimeout* nettime)
-{
- setRCR(nettime->retry_cnt);
- setRTR(nettime->time_100us);
-}
-
-void wizchip_gettimeout(wiz_NetTimeout* nettime)
-{
- nettime->retry_cnt = getRCR();
- nettime->time_100us = getRTR();
-}
diff --git a/drivers/wiznet5k/ethernet/wizchip_conf.h b/drivers/wiznet5k/ethernet/wizchip_conf.h
deleted file mode 100644
index 4a7a7bd69140..000000000000
--- a/drivers/wiznet5k/ethernet/wizchip_conf.h
+++ /dev/null
@@ -1,554 +0,0 @@
-//*****************************************************************************
-//
-//! \file wizchip_conf.h
-//! \brief WIZCHIP Config Header File.
-//! \version 1.0.0
-//! \date 2013/10/21
-//! \par Revision history
-//! <2013/10/21> 1st Release
-//! \author MidnightCow
-//! \copyright
-//!
-//! Copyright (c) 2013, WIZnet Co., LTD.
-//! 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 the 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 OWNER 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.
-//
-//*****************************************************************************
-
-/**
- * @defgroup extra_functions 2. WIZnet Extra Functions
- *
- * @brief These functions is optional function. It could be replaced at WIZCHIP I/O function because they were made by WIZCHIP I/O functions.
- * @details There are functions of configuring WIZCHIP, network, interrupt, phy, network information and timer. \n
- *
- */
-
-#ifndef _WIZCHIP_CONF_H_
-#define _WIZCHIP_CONF_H_
-
-#include
-/**
- * @brief Select WIZCHIP.
- * @todo You should select one, \b 5100, \b 5200 ,\b 5500 or etc. \n\n
- * ex> #define \_WIZCHIP_ 5500
- */
-#ifndef _WIZCHIP_
-#define _WIZCHIP_ 5200 // 5100, 5200, 5500
-#endif
-
-#define _WIZCHIP_IO_MODE_NONE_ 0x0000
-#define _WIZCHIP_IO_MODE_BUS_ 0x0100 /**< Bus interface mode */
-#define _WIZCHIP_IO_MODE_SPI_ 0x0200 /**< SPI interface mode */
-//#define _WIZCHIP_IO_MODE_IIC_ 0x0400
-//#define _WIZCHIP_IO_MODE_SDIO_ 0x0800
-// Add to
-//
-
-#define _WIZCHIP_IO_MODE_BUS_DIR_ (_WIZCHIP_IO_MODE_BUS_ + 1) /**< BUS interface mode for direct */
-#define _WIZCHIP_IO_MODE_BUS_INDIR_ (_WIZCHIP_IO_MODE_BUS_ + 2) /**< BUS interface mode for indirect */
-
-#define _WIZCHIP_IO_MODE_SPI_VDM_ (_WIZCHIP_IO_MODE_SPI_ + 1) /**< SPI interface mode for variable length data*/
-#define _WIZCHIP_IO_MODE_SPI_FDM_ (_WIZCHIP_IO_MODE_SPI_ + 2) /**< SPI interface mode for fixed length data mode*/
-
-
-#if (_WIZCHIP_ == 5100)
- #define _WIZCHIP_ID_ "W5100\0"
-/**
- * @brief Define interface mode.
- * @todo you should select interface mode as chip. Select one of @ref \_WIZCHIP_IO_MODE_SPI_ , @ref \_WIZCHIP_IO_MODE_BUS_DIR_ or @ref \_WIZCHIP_IO_MODE_BUS_INDIR_
- */
-
-// #define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_BUS_DIR_
-// #define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_BUS_INDIR_
- #define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_SPI_
-
-#elif (_WIZCHIP_ == 5200)
- #define _WIZCHIP_ID_ "W5200\0"
-/**
- * @brief Define interface mode.
- * @todo you should select interface mode as chip. Select one of @ref \_WIZCHIP_IO_MODE_SPI_ or @ref \_WIZCHIP_IO_MODE_BUS_INDIR_
- */
-// #define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_BUS_INDIR_
- #define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_SPI_
- #include "w5200/w5200.h"
-#elif (_WIZCHIP_ == 5500)
- #define _WIZCHIP_ID_ "W5500\0"
-
-/**
- * @brief Define interface mode. \n
- * @todo Should select interface mode as chip.
- * - @ref \_WIZCHIP_IO_MODE_SPI_ \n
- * -@ref \_WIZCHIP_IO_MODE_SPI_VDM_ : Valid only in @ref \_WIZCHIP_ == 5500 \n
- * -@ref \_WIZCHIP_IO_MODE_SPI_FDM_ : Valid only in @ref \_WIZCHIP_ == 5500 \n
- * - @ref \_WIZCHIP_IO_MODE_BUS_ \n
- * - @ref \_WIZCHIP_IO_MODE_BUS_DIR_ \n
- * - @ref \_WIZCHIP_IO_MODE_BUS_INDIR_ \n
- * - Others will be defined in future. \n\n
- * ex> #define \_WIZCHIP_IO_MODE_ \_WIZCHIP_IO_MODE_SPI_VDM_
- *
- */
- //#define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_SPI_FDM_
- #define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_SPI_VDM_
- #include "w5500/w5500.h"
-#else
- #error "Unknown defined _WIZCHIP_. You should define one of 5100, 5200, and 5500 !!!"
-#endif
-
-#ifndef _WIZCHIP_IO_MODE_
- #error "Undefined _WIZCHIP_IO_MODE_. You should define it !!!"
-#endif
-
-/**
- * @brief Define I/O base address when BUS IF mode.
- * @todo Should re-define it to fit your system when BUS IF Mode (@ref \_WIZCHIP_IO_MODE_BUS_,
- * @ref \_WIZCHIP_IO_MODE_BUS_DIR_, @ref \_WIZCHIP_IO_MODE_BUS_INDIR_). \n\n
- * ex> #define \_WIZCHIP_IO_BASE_ 0x00008000
- */
-#define _WIZCHIP_IO_BASE_ 0x00000000 //
-
-#if _WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_BUS
- #ifndef _WIZCHIP_IO_BASE_
- #error "You should be define _WIZCHIP_IO_BASE to fit your system memory map."
- #endif
-#endif
-
-#if _WIZCHIP_ > 5100
- #define _WIZCHIP_SOCK_NUM_ 8 ///< The count of independant socket of @b WIZCHIP
-#else
- #define _WIZCHIP_SOCK_NUM_ 4 ///< The count of independant socket of @b WIZCHIP
-#endif
-
-
-/********************************************************
-* WIZCHIP BASIC IF functions for SPI, SDIO, I2C , ETC.
-*********************************************************/
-/**
- * @ingroup DATA_TYPE
- * @brief The set of callback functions for W5500:@ref WIZCHIP_IO_Functions W5200:@ref WIZCHIP_IO_Functions_W5200
- */
-typedef struct __WIZCHIP
-{
- uint16_t if_mode; ///< host interface mode
- uint8_t id[6]; ///< @b WIZCHIP ID such as @b 5100, @b 5200, @b 5500, and so on.
- /**
- * The set of critical section callback func.
- */
- struct _CRIS
- {
- void (*_enter) (void); ///< crtical section enter
- void (*_exit) (void); ///< critial section exit
- }CRIS;
- /**
- * The set of @ref\_WIZCHIP_ select control callback func.
- */
- struct _CS
- {
- void (*_select) (void); ///< @ref \_WIZCHIP_ selected
- void (*_deselect)(void); ///< @ref \_WIZCHIP_ deselected
- }CS;
- /**
- * The set of interface IO callback func.
- */
- union _IF
- {
- /**
- * For BUS interface IO
- */
- struct
- {
- uint8_t (*_read_byte) (uint32_t AddrSel);
- void (*_write_byte) (uint32_t AddrSel, uint8_t wb);
- }BUS;
- /**
- * For SPI interface IO
- */
- struct
- {
- void (*_read_bytes) (uint8_t *buf, uint32_t len);
- void (*_write_bytes) (const uint8_t *buf, uint32_t len);
- }SPI;
- // To be added
- //
- }IF;
-}_WIZCHIP;
-
-extern _WIZCHIP WIZCHIP;
-
-/**
- * @ingroup DATA_TYPE
- * WIZCHIP control type enumration used in @ref ctlwizchip().
- */
-typedef enum
-{
- CW_RESET_WIZCHIP, ///< Resets WIZCHIP by softly
- CW_INIT_WIZCHIP, ///< Inializes to WIZCHIP with SOCKET buffer size 2 or 1 dimension array typed uint8_t.
- CW_GET_INTERRUPT, ///< Get Interrupt status of WIZCHIP
- CW_CLR_INTERRUPT, ///< Clears interrupt
- CW_SET_INTRMASK, ///< Masks interrupt
- CW_GET_INTRMASK, ///< Get interrupt mask
- CW_SET_INTRTIME, ///< Set interval time between the current and next interrupt.
- CW_GET_INTRTIME, ///< Set interval time between the current and next interrupt.
- CW_GET_ID, ///< Gets WIZCHIP name.
-
-#if _WIZCHIP_ == 5500
- CW_RESET_PHY, ///< Resets internal PHY. Valid Only W5000
- CW_SET_PHYCONF, ///< When PHY configured by interal register, PHY operation mode (Manual/Auto, 10/100, Half/Full). Valid Only W5000
- CW_GET_PHYCONF, ///< Get PHY operation mode in interal register. Valid Only W5000
- CW_GET_PHYSTATUS, ///< Get real PHY status on operating. Valid Only W5000
- CW_SET_PHYPOWMODE, ///< Set PHY power mode as noraml and down when PHYSTATUS.OPMD == 1. Valid Only W5000
-#endif
- CW_GET_PHYPOWMODE, ///< Get PHY Power mode as down or normal
- CW_GET_PHYLINK ///< Get PHY Link status
-}ctlwizchip_type;
-
-/**
- * @ingroup DATA_TYPE
- * Network control type enumration used in @ref ctlnetwork().
- */
-typedef enum
-{
- CN_SET_NETINFO, ///< Set Network with @ref wiz_NetInfo
- CN_GET_NETINFO, ///< Get Network with @ref wiz_NetInfo
- CN_SET_NETMODE, ///< Set network mode as WOL, PPPoE, Ping Block, and Force ARP mode
- CN_GET_NETMODE, ///< Get network mode as WOL, PPPoE, Ping Block, and Force ARP mode
- CN_SET_TIMEOUT, ///< Set network timeout as retry count and time.
- CN_GET_TIMEOUT, ///< Get network timeout as retry count and time.
-}ctlnetwork_type;
-
-/**
- * @ingroup DATA_TYPE
- * Interrupt kind when CW_SET_INTRRUPT, CW_GET_INTERRUPT, CW_SET_INTRMASK
- * and CW_GET_INTRMASK is used in @ref ctlnetwork().
- * It can be used with OR operation.
- */
-typedef enum
-{
-#if _WIZCHIP_ > 5200
- IK_WOL = (1 << 4), ///< Wake On Lan by receiving the magic packet. Valid in W500.
-#endif
-
- IK_PPPOE_TERMINATED = (1 << 5), ///< PPPoE Disconnected
-
-#if _WIZCHIP_ != 5200
- IK_DEST_UNREACH = (1 << 6), ///< Destination IP & Port Unreable, No use in W5200
-#endif
-
- IK_IP_CONFLICT = (1 << 7), ///< IP conflict occurred
-
- IK_SOCK_0 = (1 << 8), ///< Socket 0 interrupt
- IK_SOCK_1 = (1 << 9), ///< Socket 1 interrupt
- IK_SOCK_2 = (1 << 10), ///< Socket 2 interrupt
- IK_SOCK_3 = (1 << 11), ///< Socket 3 interrupt
-#if _WIZCHIP_ > 5100
- IK_SOCK_4 = (1 << 12), ///< Socket 4 interrupt, No use in 5100
- IK_SOCK_5 = (1 << 13), ///< Socket 5 interrupt, No use in 5100
- IK_SOCK_6 = (1 << 14), ///< Socket 6 interrupt, No use in 5100
- IK_SOCK_7 = (1 << 15), ///< Socket 7 interrupt, No use in 5100
-#endif
-
-#if _WIZCHIP_ > 5100
- IK_SOCK_ALL = (0xFF << 8) ///< All Socket interrpt
-#else
- IK_SOCK_ALL = (0x0F << 8) ///< All Socket interrpt
-#endif
-}intr_kind;
-
-#define PHY_CONFBY_HW 0 ///< Configured PHY operation mode by HW pin
-#define PHY_CONFBY_SW 1 ///< Configured PHY operation mode by SW register
-#define PHY_MODE_MANUAL 0 ///< Configured PHY operation mode with user setting.
-#define PHY_MODE_AUTONEGO 1 ///< Configured PHY operation mode with auto-negotiation
-#define PHY_SPEED_10 0 ///< Link Speed 10
-#define PHY_SPEED_100 1 ///< Link Speed 100
-#define PHY_DUPLEX_HALF 0 ///< Link Half-Duplex
-#define PHY_DUPLEX_FULL 1 ///< Link Full-Duplex
-#define PHY_LINK_OFF 0 ///< Link Off
-#define PHY_LINK_ON 1 ///< Link On
-#define PHY_POWER_NORM 0 ///< PHY power normal mode
-#define PHY_POWER_DOWN 1 ///< PHY power down mode
-
-
-#if _WIZCHIP_ == 5500
-/**
- * @ingroup DATA_TYPE
- * It configures PHY configuration when CW_SET PHYCONF or CW_GET_PHYCONF in W5500,
- * and it indicates the real PHY status configured by HW or SW in all WIZCHIP. \n
- * Valid only in W5500.
- */
-typedef struct wiz_PhyConf_t
-{
- uint8_t by; ///< set by @ref PHY_CONFBY_HW or @ref PHY_CONFBY_SW
- uint8_t mode; ///< set by @ref PHY_MODE_MANUAL or @ref PHY_MODE_AUTONEGO
- uint8_t speed; ///< set by @ref PHY_SPEED_10 or @ref PHY_SPEED_100
- uint8_t duplex; ///< set by @ref PHY_DUPLEX_HALF @ref PHY_DUPLEX_FULL
- //uint8_t power; ///< set by @ref PHY_POWER_NORM or @ref PHY_POWER_DOWN
- //uint8_t link; ///< Valid only in CW_GET_PHYSTATUS. set by @ref PHY_LINK_ON or PHY_DUPLEX_OFF
- }wiz_PhyConf;
-#endif
-
-/**
- * @ingroup DATA_TYPE
- * It used in setting dhcp_mode of @ref wiz_NetInfo.
- */
-typedef enum
-{
- NETINFO_STATIC = 1, ///< Static IP configuration by manually.
- NETINFO_DHCP ///< Dynamic IP configruation from a DHCP sever
-}dhcp_mode;
-
-/**
- * @ingroup DATA_TYPE
- * Network Information for WIZCHIP
- */
-typedef struct wiz_NetInfo_t
-{
- uint8_t mac[6]; ///< Source Mac Address
- uint8_t ip[4]; ///< Source IP Address
- uint8_t sn[4]; ///< Subnet Mask
- uint8_t gw[4]; ///< Gateway IP Address
- uint8_t dns[4]; ///< DNS server IP Address
- dhcp_mode dhcp; ///< 1 - Static, 2 - DHCP
-}wiz_NetInfo;
-
-/**
- * @ingroup DATA_TYPE
- * Network mode
- */
-typedef enum
-{
-#if _WIZCHIP_ == 5500
- NM_FORCEARP = (1<<1), ///< Force to APP send whenever udp data is sent. Valid only in W5500
-#endif
- NM_WAKEONLAN = (1<<5), ///< Wake On Lan
- NM_PINGBLOCK = (1<<4), ///< Block ping-request
- NM_PPPOE = (1<<3), ///< PPPoE mode
-}netmode_type;
-
-/**
- * @ingroup DATA_TYPE
- * Used in CN_SET_TIMEOUT or CN_GET_TIMEOUT of @ref ctlwizchip() for timeout configruation.
- */
-typedef struct wiz_NetTimeout_t
-{
- uint8_t retry_cnt; ///< retry count
- uint16_t time_100us; ///< time unit 100us
-}wiz_NetTimeout;
-
-/**
- *@brief Registers call back function for critical section of I/O functions such as
- *\ref WIZCHIP_READ, @ref WIZCHIP_WRITE, @ref WIZCHIP_READ_BUF and @ref WIZCHIP_WRITE_BUF.
- *@param cris_en : callback function for critical section enter.
- *@param cris_ex : callback function for critical section exit.
- *@todo Describe @ref WIZCHIP_CRITICAL_ENTER and @ref WIZCHIP_CRITICAL_EXIT marco or register your functions.
- *@note If you do not describe or register, default functions(@ref wizchip_cris_enter & @ref wizchip_cris_exit) is called.
- */
-void reg_wizchip_cris_cbfunc(void(*cris_en)(void), void(*cris_ex)(void));
-
-
-/**
- *@brief Registers call back function for WIZCHIP select & deselect.
- *@param cs_sel : callback function for WIZCHIP select
- *@param cs_desel : callback fucntion for WIZCHIP deselect
- *@todo Describe @ref wizchip_cs_select and @ref wizchip_cs_deselect function or register your functions.
- *@note If you do not describe or register, null function is called.
- */
-void reg_wizchip_cs_cbfunc(void(*cs_sel)(void), void(*cs_desel)(void));
-
-/**
- *@brief Registers call back function for bus interface.
- *@param bus_rb : callback function to read byte data using system bus
- *@param bus_wb : callback function to write byte data using system bus
- *@todo Describe @ref wizchip_bus_readbyte and @ref wizchip_bus_writebyte function
- *or register your functions.
- *@note If you do not describe or register, null function is called.
- */
-void reg_wizchip_bus_cbfunc(uint8_t (*bus_rb)(uint32_t addr), void (*bus_wb)(uint32_t addr, uint8_t wb));
-
-/**
- *@brief Registers call back function for SPI interface.
- *@param spi_rb : callback function to read byte usig SPI
- *@param spi_wb : callback function to write byte usig SPI
- *@todo Describe \ref wizchip_spi_readbyte and \ref wizchip_spi_writebyte function
- *or register your functions.
- *@note If you do not describe or register, null function is called.
- */
-void reg_wizchip_spi_cbfunc(void (*spi_rb)(uint8_t *, uint32_t), void (*spi_wb)(const uint8_t *, uint32_t));
-
-/**
- * @ingroup extra_functions
- * @brief Controls to the WIZCHIP.
- * @details Resets WIZCHIP & internal PHY, Configures PHY mode, Monitor PHY(Link,Speed,Half/Full/Auto),
- * controls interrupt & mask and so on.
- * @param cwtype : Decides to the control type
- * @param arg : arg type is dependent on cwtype.
- * @return 0 : Success \n
- * -1 : Fail because of invalid \ref ctlwizchip_type or unsupported \ref ctlwizchip_type in WIZCHIP
- */
-int8_t ctlwizchip(ctlwizchip_type cwtype, void* arg);
-
-/**
- * @ingroup extra_functions
- * @brief Controls to network.
- * @details Controls to network environment, mode, timeout and so on.
- * @param cntype : Input. Decides to the control type
- * @param arg : Inout. arg type is dependent on cntype.
- * @return -1 : Fail because of invalid \ref ctlnetwork_type or unsupported \ref ctlnetwork_type in WIZCHIP \n
- * 0 : Success
- */
-int8_t ctlnetwork(ctlnetwork_type cntype, void* arg);
-
-
-/*
- * The following functions are implemented for internal use.
- * but You can call these functions for code size reduction instead of ctlwizchip() and ctlnetwork().
- */
-
-/**
- * @ingroup extra_functions
- * @brief Reset WIZCHIP by softly.
- */
-void wizchip_sw_reset(void);
-
-/**
- * @ingroup extra_functions
- * @brief Initializes WIZCHIP with socket buffer size
- * @param txsize Socket tx buffer sizes. If null, initialized the default size 2KB.
- * @param rxsize Socket rx buffer sizes. If null, initialized the default size 2KB.
- * @return 0 : succcess \n
- * -1 : fail. Invalid buffer size
- */
-int8_t wizchip_init(uint8_t* txsize, uint8_t* rxsize);
-
-/**
- * @ingroup extra_functions
- * @brief Clear Interrupt of WIZCHIP.
- * @param intr : @ref intr_kind value operated OR. It can type-cast to uint16_t.
- */
-void wizchip_clrinterrupt(intr_kind intr);
-
-/**
- * @ingroup extra_functions
- * @brief Get Interrupt of WIZCHIP.
- * @return @ref intr_kind value operated OR. It can type-cast to uint16_t.
- */
-intr_kind wizchip_getinterrupt(void);
-
-/**
- * @ingroup extra_functions
- * @brief Mask or Unmask Interrupt of WIZCHIP.
- * @param intr : @ref intr_kind value operated OR. It can type-cast to uint16_t.
- */
-void wizchip_setinterruptmask(intr_kind intr);
-
-/**
- * @ingroup extra_functions
- * @brief Get Interrupt mask of WIZCHIP.
- * @return : The operated OR vaule of @ref intr_kind. It can type-cast to uint16_t.
- */
-intr_kind wizchip_getinterruptmask(void);
-
-#if _WIZCHIP_ > 5100
- int8_t wizphy_getphylink(void); ///< get the link status of phy in WIZCHIP. No use in W5100
- int8_t wizphy_getphypmode(void); ///< get the power mode of PHY in WIZCHIP. No use in W5100
-#endif
-
-#if _WIZCHIP_ == 5500
- void wizphy_reset(void); ///< Reset phy. Vailid only in W5500
-/**
- * @ingroup extra_functions
- * @brief Set the phy information for WIZCHIP without power mode
- * @param phyconf : @ref wiz_PhyConf
- */
- void wizphy_setphyconf(wiz_PhyConf* phyconf);
- /**
- * @ingroup extra_functions
- * @brief Get phy configuration information.
- * @param phyconf : @ref wiz_PhyConf
- */
- void wizphy_getphyconf(wiz_PhyConf* phyconf);
- /**
- * @ingroup extra_functions
- * @brief Get phy status.
- * @param phyconf : @ref wiz_PhyConf
- */
- void wizphy_getphystat(wiz_PhyConf* phyconf);
- /**
- * @ingroup extra_functions
- * @brief set the power mode of phy inside WIZCHIP. Refer to @ref PHYCFGR in W5500, @ref PHYSTATUS in W5200
- * @param pmode Settig value of power down mode.
- */
- int8_t wizphy_setphypmode(uint8_t pmode);
-#endif
-
-/**
-* @ingroup extra_functions
- * @brief Set the network information for WIZCHIP
- * @param pnetinfo : @ref wizNetInfo
- */
-void wizchip_setnetinfo(wiz_NetInfo* pnetinfo);
-
-/**
- * @ingroup extra_functions
- * @brief Get the network information for WIZCHIP
- * @param pnetinfo : @ref wizNetInfo
- */
-void wizchip_getnetinfo(wiz_NetInfo* pnetinfo);
-
-#if _WIZCHIP_ == 5200 // for W5200 ARP errata
-uint8_t *wizchip_getsubn(void);
-#endif
-
-/**
- * @ingroup extra_functions
- * @brief Set the network mode such WOL, PPPoE, Ping Block, and etc.
- * @param pnetinfo Value of network mode. Refer to @ref netmode_type.
- */
-int8_t wizchip_setnetmode(netmode_type netmode);
-
-/**
- * @ingroup extra_functions
- * @brief Get the network mode such WOL, PPPoE, Ping Block, and etc.
- * @return Value of network mode. Refer to @ref netmode_type.
- */
-netmode_type wizchip_getnetmode(void);
-
-/**
- * @ingroup extra_functions
- * @brief Set retry time value(@ref RTR) and retry count(@ref RCR).
- * @details @ref RTR configures the retransmission timeout period and @ref RCR configures the number of time of retransmission.
- * @param nettime @ref RTR value and @ref RCR value. Refer to @ref wiz_NetTimeout.
- */
-void wizchip_settimeout(wiz_NetTimeout* nettime);
-
-/**
- * @ingroup extra_functions
- * @brief Get retry time value(@ref RTR) and retry count(@ref RCR).
- * @details @ref RTR configures the retransmission timeout period and @ref RCR configures the number of time of retransmission.
- * @param nettime @ref RTR value and @ref RCR value. Refer to @ref wiz_NetTimeout.
- */
-void wizchip_gettimeout(wiz_NetTimeout* nettime);
-
-#endif // _WIZCHIP_CONF_H_
diff --git a/drivers/wiznet5k/internet/dhcp/dhcp.c b/drivers/wiznet5k/internet/dhcp/dhcp.c
deleted file mode 100644
index 5747582599db..000000000000
--- a/drivers/wiznet5k/internet/dhcp/dhcp.c
+++ /dev/null
@@ -1,978 +0,0 @@
-//*****************************************************************************
-//
-//! \file dhcp.c
-//! \brief DHCP APIs implement file.
-//! \details Processig DHCP protocol as DISCOVER, OFFER, REQUEST, ACK, NACK and DECLINE.
-//! \version 1.1.0
-//! \date 2013/11/18
-//! \par Revision history
-//! <2013/11/18> 1st Release
-//! <2012/12/20> V1.1.0
-//! 1. Optimize code
-//! 2. Add reg_dhcp_cbfunc()
-//! 3. Add DHCP_stop()
-//! 4. Integrate check_DHCP_state() & DHCP_run() to DHCP_run()
-//! 5. Don't care system endian
-//! 6. Add comments
-//! <2012/12/26> V1.1.1
-//! 1. Modify variable declaration: dhcp_tick_1s is declared volatile for code optimization
-//! \author Eric Jung & MidnightCow
-//! \copyright
-//!
-//! Copyright (c) 2013, WIZnet Co., LTD.
-//! 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 the 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 OWNER 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.
-//
-//*****************************************************************************
-
-//#include "Ethernet/socket.h"
-//#include "Internet/DHCP/dhcp.h"
-#include "../../Ethernet/socket.h"
-#include "dhcp.h"
-
-/* If you want to display debug & processing message, Define _DHCP_DEBUG_ in dhcp.h */
-
-#ifdef _DHCP_DEBUG_
- #include
-#endif
-
-/* DHCP state machine. */
-#define STATE_DHCP_INIT 0 ///< Initialize
-#define STATE_DHCP_DISCOVER 1 ///< send DISCOVER and wait OFFER
-#define STATE_DHCP_REQUEST 2 ///< send REQEUST and wait ACK or NACK
-#define STATE_DHCP_LEASED 3 ///< ReceiveD ACK and IP leased
-#define STATE_DHCP_REREQUEST 4 ///< send REQUEST for maintaining leased IP
-#define STATE_DHCP_RELEASE 5 ///< No use
-#define STATE_DHCP_STOP 6 ///< Stop processing DHCP
-
-#define DHCP_FLAGSBROADCAST 0x8000 ///< The broadcast value of flags in @ref RIP_MSG
-#define DHCP_FLAGSUNICAST 0x0000 ///< The unicast value of flags in @ref RIP_MSG
-
-/* DHCP message OP code */
-#define DHCP_BOOTREQUEST 1 ///< Request Message used in op of @ref RIP_MSG
-#define DHCP_BOOTREPLY 2 ///< Reply Message used i op of @ref RIP_MSG
-
-/* DHCP message type */
-#define DHCP_DISCOVER 1 ///< DISCOVER message in OPT of @ref RIP_MSG
-#define DHCP_OFFER 2 ///< OFFER message in OPT of @ref RIP_MSG
-#define DHCP_REQUEST 3 ///< REQUEST message in OPT of @ref RIP_MSG
-#define DHCP_DECLINE 4 ///< DECLINE message in OPT of @ref RIP_MSG
-#define DHCP_ACK 5 ///< ACK message in OPT of @ref RIP_MSG
-#define DHCP_NAK 6 ///< NACK message in OPT of @ref RIP_MSG
-#define DHCP_RELEASE 7 ///< RELEASE message in OPT of @ref RIP_MSG. No use
-#define DHCP_INFORM 8 ///< INFORM message in OPT of @ref RIP_MSG. No use
-
-#define DHCP_HTYPE10MB 1 ///< Used in type of @ref RIP_MSG
-#define DHCP_HTYPE100MB 2 ///< Used in type of @ref RIP_MSG
-
-#define DHCP_HLENETHERNET 6 ///< Used in hlen of @ref RIP_MSG
-#define DHCP_HOPS 0 ///< Used in hops of @ref RIP_MSG
-#define DHCP_SECS 0 ///< Used in secs of @ref RIP_MSG
-
-#define INFINITE_LEASETIME 0xffffffff ///< Infinite lease time
-
-#define OPT_SIZE 312 /// Max OPT size of @ref RIP_MSG
-#define RIP_MSG_SIZE (236+OPT_SIZE) /// Max size of @ref RIP_MSG
-
-/*
- * @brief DHCP option and value (cf. RFC1533)
- */
-enum
-{
- padOption = 0,
- subnetMask = 1,
- timerOffset = 2,
- routersOnSubnet = 3,
- timeServer = 4,
- nameServer = 5,
- dns = 6,
- logServer = 7,
- cookieServer = 8,
- lprServer = 9,
- impressServer = 10,
- resourceLocationServer = 11,
- hostName = 12,
- bootFileSize = 13,
- meritDumpFile = 14,
- domainName = 15,
- swapServer = 16,
- rootPath = 17,
- extentionsPath = 18,
- IPforwarding = 19,
- nonLocalSourceRouting = 20,
- policyFilter = 21,
- maxDgramReasmSize = 22,
- defaultIPTTL = 23,
- pathMTUagingTimeout = 24,
- pathMTUplateauTable = 25,
- ifMTU = 26,
- allSubnetsLocal = 27,
- broadcastAddr = 28,
- performMaskDiscovery = 29,
- maskSupplier = 30,
- performRouterDiscovery = 31,
- routerSolicitationAddr = 32,
- staticRoute = 33,
- trailerEncapsulation = 34,
- arpCacheTimeout = 35,
- ethernetEncapsulation = 36,
- tcpDefaultTTL = 37,
- tcpKeepaliveInterval = 38,
- tcpKeepaliveGarbage = 39,
- nisDomainName = 40,
- nisServers = 41,
- ntpServers = 42,
- vendorSpecificInfo = 43,
- netBIOSnameServer = 44,
- netBIOSdgramDistServer = 45,
- netBIOSnodeType = 46,
- netBIOSscope = 47,
- xFontServer = 48,
- xDisplayManager = 49,
- dhcpRequestedIPaddr = 50,
- dhcpIPaddrLeaseTime = 51,
- dhcpOptionOverload = 52,
- dhcpMessageType = 53,
- dhcpServerIdentifier = 54,
- dhcpParamRequest = 55,
- dhcpMsg = 56,
- dhcpMaxMsgSize = 57,
- dhcpT1value = 58,
- dhcpT2value = 59,
- dhcpClassIdentifier = 60,
- dhcpClientIdentifier = 61,
- endOption = 255
-};
-
-/*
- * @brief DHCP message format
- */
-typedef struct {
- uint8_t op; ///< @ref DHCP_BOOTREQUEST or @ref DHCP_BOOTREPLY
- uint8_t htype; ///< @ref DHCP_HTYPE10MB or @ref DHCP_HTYPE100MB
- uint8_t hlen; ///< @ref DHCP_HLENETHERNET
- uint8_t hops; ///< @ref DHCP_HOPS
- uint32_t xid; ///< @ref DHCP_XID This increase one every DHCP transaction.
- uint16_t secs; ///< @ref DHCP_SECS
- uint16_t flags; ///< @ref DHCP_FLAGSBROADCAST or @ref DHCP_FLAGSUNICAST
- uint8_t ciaddr[4]; ///< @ref Request IP to DHCP sever
- uint8_t yiaddr[4]; ///< @ref Offered IP from DHCP server
- uint8_t siaddr[4]; ///< No use
- uint8_t giaddr[4]; ///< No use
- uint8_t chaddr[16]; ///< DHCP client 6bytes MAC address. Others is filled to zero
- uint8_t sname[64]; ///< No use
- uint8_t file[128]; ///< No use
- uint8_t OPT[OPT_SIZE]; ///< Option
-} RIP_MSG;
-
-
-
-uint8_t DHCP_SOCKET; // Socket number for DHCP
-
-uint8_t DHCP_SIP[4]; // DHCP Server IP address
-
-// Network information from DHCP Server
-uint8_t OLD_allocated_ip[4] = {0, }; // Previous IP address
-uint8_t DHCP_allocated_ip[4] = {0, }; // IP address from DHCP
-uint8_t DHCP_allocated_gw[4] = {0, }; // Gateway address from DHCP
-uint8_t DHCP_allocated_sn[4] = {0, }; // Subnet mask from DHCP
-uint8_t DHCP_allocated_dns[4] = {0, }; // DNS address from DHCP
-
-
-int8_t dhcp_state = STATE_DHCP_INIT; // DHCP state
-int8_t dhcp_retry_count = 0;
-
-uint32_t dhcp_lease_time = INFINITE_LEASETIME;
-volatile uint32_t dhcp_tick_1s = 0; // unit 1 second
-uint32_t dhcp_tick_next = DHCP_WAIT_TIME ;
-
-uint32_t DHCP_XID; // Any number
-
-RIP_MSG* pDHCPMSG; // Buffer pointer for DHCP processing
-
-uint8_t HOST_NAME[] = DCHP_HOST_NAME;
-
-uint8_t DHCP_CHADDR[6]; // DHCP Client MAC address.
-
-/* The default callback function */
-void default_ip_assign(void);
-void default_ip_update(void);
-void default_ip_conflict(void);
-
-/* Callback handler */
-void (*dhcp_ip_assign)(void) = default_ip_assign; /* handler to be called when the IP address from DHCP server is first assigned */
-void (*dhcp_ip_update)(void) = default_ip_update; /* handler to be called when the IP address from DHCP server is updated */
-void (*dhcp_ip_conflict)(void) = default_ip_conflict; /* handler to be called when the IP address from DHCP server is conflict */
-
-void reg_dhcp_cbfunc(void(*ip_assign)(void), void(*ip_update)(void), void(*ip_conflict)(void));
-
-
-/* send DISCOVER message to DHCP server */
-void send_DHCP_DISCOVER(void);
-
-/* send REQEUST message to DHCP server */
-void send_DHCP_REQUEST(void);
-
-/* send DECLINE message to DHCP server */
-void send_DHCP_DECLINE(void);
-
-/* IP conflict check by sending ARP-request to leased IP and wait ARP-response. */
-int8_t check_DHCP_leasedIP(void);
-
-/* check the timeout in DHCP process */
-uint8_t check_DHCP_timeout(void);
-
-/* Intialize to timeout process. */
-void reset_DHCP_timeout(void);
-
-/* Parse message as OFFER and ACK and NACK from DHCP server.*/
-int8_t parseDHCPCMSG(void);
-
-/* The default handler of ip assign first */
-void default_ip_assign(void)
-{
- setSIPR(DHCP_allocated_ip);
- setSUBR(DHCP_allocated_sn);
- setGAR (DHCP_allocated_gw);
-}
-
-/* The default handler of ip changed */
-void default_ip_update(void)
-{
- /* WIZchip Software Reset */
- setMR(MR_RST);
- getMR(); // for delay
- default_ip_assign();
- setSHAR(DHCP_CHADDR);
-}
-
-/* The default handler of ip changed */
-void default_ip_conflict(void)
-{
- // WIZchip Software Reset
- setMR(MR_RST);
- getMR(); // for delay
- setSHAR(DHCP_CHADDR);
-}
-
-/* register the call back func. */
-void reg_dhcp_cbfunc(void(*ip_assign)(void), void(*ip_update)(void), void(*ip_conflict)(void))
-{
- dhcp_ip_assign = default_ip_assign;
- dhcp_ip_update = default_ip_update;
- dhcp_ip_conflict = default_ip_conflict;
- if(ip_assign) dhcp_ip_assign = ip_assign;
- if(ip_update) dhcp_ip_update = ip_update;
- if(ip_conflict) dhcp_ip_conflict = ip_conflict;
-}
-
-/* make the common DHCP message */
-void makeDHCPMSG(void)
-{
- uint8_t bk_mac[6];
- uint8_t* ptmp;
- uint8_t i;
- getSHAR(bk_mac);
- pDHCPMSG->op = DHCP_BOOTREQUEST;
- pDHCPMSG->htype = DHCP_HTYPE10MB;
- pDHCPMSG->hlen = DHCP_HLENETHERNET;
- pDHCPMSG->hops = DHCP_HOPS;
- ptmp = (uint8_t*)(&pDHCPMSG->xid);
- *(ptmp+0) = (uint8_t)((DHCP_XID & 0xFF000000) >> 24);
- *(ptmp+1) = (uint8_t)((DHCP_XID & 0x00FF0000) >> 16);
- *(ptmp+2) = (uint8_t)((DHCP_XID & 0x0000FF00) >> 8);
- *(ptmp+3) = (uint8_t)((DHCP_XID & 0x000000FF) >> 0);
- pDHCPMSG->secs = DHCP_SECS;
- ptmp = (uint8_t*)(&pDHCPMSG->flags);
- *(ptmp+0) = (uint8_t)((DHCP_FLAGSBROADCAST & 0xFF00) >> 8);
- *(ptmp+1) = (uint8_t)((DHCP_FLAGSBROADCAST & 0x00FF) >> 0);
-
- pDHCPMSG->ciaddr[0] = 0;
- pDHCPMSG->ciaddr[1] = 0;
- pDHCPMSG->ciaddr[2] = 0;
- pDHCPMSG->ciaddr[3] = 0;
-
- pDHCPMSG->yiaddr[0] = 0;
- pDHCPMSG->yiaddr[1] = 0;
- pDHCPMSG->yiaddr[2] = 0;
- pDHCPMSG->yiaddr[3] = 0;
-
- pDHCPMSG->siaddr[0] = 0;
- pDHCPMSG->siaddr[1] = 0;
- pDHCPMSG->siaddr[2] = 0;
- pDHCPMSG->siaddr[3] = 0;
-
- pDHCPMSG->giaddr[0] = 0;
- pDHCPMSG->giaddr[1] = 0;
- pDHCPMSG->giaddr[2] = 0;
- pDHCPMSG->giaddr[3] = 0;
-
- pDHCPMSG->chaddr[0] = DHCP_CHADDR[0];
- pDHCPMSG->chaddr[1] = DHCP_CHADDR[1];
- pDHCPMSG->chaddr[2] = DHCP_CHADDR[2];
- pDHCPMSG->chaddr[3] = DHCP_CHADDR[3];
- pDHCPMSG->chaddr[4] = DHCP_CHADDR[4];
- pDHCPMSG->chaddr[5] = DHCP_CHADDR[5];
-
- for (i = 6; i < 16; i++) pDHCPMSG->chaddr[i] = 0;
- for (i = 0; i < 64; i++) pDHCPMSG->sname[i] = 0;
- for (i = 0; i < 128; i++) pDHCPMSG->file[i] = 0;
-
- // MAGIC_COOKIE
- pDHCPMSG->OPT[0] = (uint8_t)((MAGIC_COOKIE & 0xFF000000) >> 24);
- pDHCPMSG->OPT[1] = (uint8_t)((MAGIC_COOKIE & 0x00FF0000) >> 16);
- pDHCPMSG->OPT[2] = (uint8_t)((MAGIC_COOKIE & 0x0000FF00) >> 8);
- pDHCPMSG->OPT[3] = (uint8_t) (MAGIC_COOKIE & 0x000000FF) >> 0;
-}
-
-/* SEND DHCP DISCOVER */
-void send_DHCP_DISCOVER(void)
-{
- uint16_t i;
- uint8_t ip[4];
- uint16_t k = 0;
-
- makeDHCPMSG();
-
- k = 4; // because MAGIC_COOKIE already made by makeDHCPMSG()
-
- // Option Request Param
- pDHCPMSG->OPT[k++] = dhcpMessageType;
- pDHCPMSG->OPT[k++] = 0x01;
- pDHCPMSG->OPT[k++] = DHCP_DISCOVER;
-
- // Client identifier
- pDHCPMSG->OPT[k++] = dhcpClientIdentifier;
- pDHCPMSG->OPT[k++] = 0x07;
- pDHCPMSG->OPT[k++] = 0x01;
- pDHCPMSG->OPT[k++] = DHCP_CHADDR[0];
- pDHCPMSG->OPT[k++] = DHCP_CHADDR[1];
- pDHCPMSG->OPT[k++] = DHCP_CHADDR[2];
- pDHCPMSG->OPT[k++] = DHCP_CHADDR[3];
- pDHCPMSG->OPT[k++] = DHCP_CHADDR[4];
- pDHCPMSG->OPT[k++] = DHCP_CHADDR[5];
-
- // host name
- pDHCPMSG->OPT[k++] = hostName;
- pDHCPMSG->OPT[k++] = 0; // fill zero length of hostname
- for(i = 0 ; HOST_NAME[i] != 0; i++)
- pDHCPMSG->OPT[k++] = HOST_NAME[i];
- pDHCPMSG->OPT[k++] = DHCP_CHADDR[3];
- pDHCPMSG->OPT[k++] = DHCP_CHADDR[4];
- pDHCPMSG->OPT[k++] = DHCP_CHADDR[5];
- pDHCPMSG->OPT[k - (i+3+1)] = i+3; // length of hostname
-
- pDHCPMSG->OPT[k++] = dhcpParamRequest;
- pDHCPMSG->OPT[k++] = 0x06; // length of request
- pDHCPMSG->OPT[k++] = subnetMask;
- pDHCPMSG->OPT[k++] = routersOnSubnet;
- pDHCPMSG->OPT[k++] = dns;
- pDHCPMSG->OPT[k++] = domainName;
- pDHCPMSG->OPT[k++] = dhcpT1value;
- pDHCPMSG->OPT[k++] = dhcpT2value;
- pDHCPMSG->OPT[k++] = endOption;
-
- for (i = k; i < OPT_SIZE; i++) pDHCPMSG->OPT[i] = 0;
-
- // send broadcasting packet
- ip[0] = 255;
- ip[1] = 255;
- ip[2] = 255;
- ip[3] = 255;
-
-#ifdef _DHCP_DEBUG_
- printf("> Send DHCP_DISCOVER\r\n");
-#endif
-
- sendto(DHCP_SOCKET, (uint8_t *)pDHCPMSG, RIP_MSG_SIZE, ip, DHCP_SERVER_PORT);
-}
-
-/* SEND DHCP REQUEST */
-void send_DHCP_REQUEST(void)
-{
- int i;
- uint8_t ip[4];
- uint16_t k = 0;
-
- makeDHCPMSG();
-
- if(dhcp_state == STATE_DHCP_LEASED || dhcp_state == STATE_DHCP_REREQUEST)
- {
- *((uint8_t*)(&pDHCPMSG->flags)) = ((DHCP_FLAGSUNICAST & 0xFF00)>> 8);
- *((uint8_t*)(&pDHCPMSG->flags)+1) = (DHCP_FLAGSUNICAST & 0x00FF);
- pDHCPMSG->ciaddr[0] = DHCP_allocated_ip[0];
- pDHCPMSG->ciaddr[1] = DHCP_allocated_ip[1];
- pDHCPMSG->ciaddr[2] = DHCP_allocated_ip[2];
- pDHCPMSG->ciaddr[3] = DHCP_allocated_ip[3];
- ip[0] = DHCP_SIP[0];
- ip[1] = DHCP_SIP[1];
- ip[2] = DHCP_SIP[2];
- ip[3] = DHCP_SIP[3];
- }
- else
- {
- ip[0] = 255;
- ip[1] = 255;
- ip[2] = 255;
- ip[3] = 255;
- }
-
- k = 4; // because MAGIC_COOKIE already made by makeDHCPMSG()
-
- // Option Request Param.
- pDHCPMSG->OPT[k++] = dhcpMessageType;
- pDHCPMSG->OPT[k++] = 0x01;
- pDHCPMSG->OPT[k++] = DHCP_REQUEST;
-
- pDHCPMSG->OPT[k++] = dhcpClientIdentifier;
- pDHCPMSG->OPT[k++] = 0x07;
- pDHCPMSG->OPT[k++] = 0x01;
- pDHCPMSG->OPT[k++] = DHCP_CHADDR[0];
- pDHCPMSG->OPT[k++] = DHCP_CHADDR[1];
- pDHCPMSG->OPT[k++] = DHCP_CHADDR[2];
- pDHCPMSG->OPT[k++] = DHCP_CHADDR[3];
- pDHCPMSG->OPT[k++] = DHCP_CHADDR[4];
- pDHCPMSG->OPT[k++] = DHCP_CHADDR[5];
-
- if(ip[3] == 255) // if(dchp_state == STATE_DHCP_LEASED || dchp_state == DHCP_REREQUEST_STATE)
- {
- pDHCPMSG->OPT[k++] = dhcpRequestedIPaddr;
- pDHCPMSG->OPT[k++] = 0x04;
- pDHCPMSG->OPT[k++] = DHCP_allocated_ip[0];
- pDHCPMSG->OPT[k++] = DHCP_allocated_ip[1];
- pDHCPMSG->OPT[k++] = DHCP_allocated_ip[2];
- pDHCPMSG->OPT[k++] = DHCP_allocated_ip[3];
-
- pDHCPMSG->OPT[k++] = dhcpServerIdentifier;
- pDHCPMSG->OPT[k++] = 0x04;
- pDHCPMSG->OPT[k++] = DHCP_SIP[0];
- pDHCPMSG->OPT[k++] = DHCP_SIP[1];
- pDHCPMSG->OPT[k++] = DHCP_SIP[2];
- pDHCPMSG->OPT[k++] = DHCP_SIP[3];
- }
-
- // host name
- pDHCPMSG->OPT[k++] = hostName;
- pDHCPMSG->OPT[k++] = 0; // length of hostname
- for(i = 0 ; HOST_NAME[i] != 0; i++)
- pDHCPMSG->OPT[k++] = HOST_NAME[i];
- pDHCPMSG->OPT[k++] = DHCP_CHADDR[3];
- pDHCPMSG->OPT[k++] = DHCP_CHADDR[4];
- pDHCPMSG->OPT[k++] = DHCP_CHADDR[5];
- pDHCPMSG->OPT[k - (i+3+1)] = i+3; // length of hostname
-
- pDHCPMSG->OPT[k++] = dhcpParamRequest;
- pDHCPMSG->OPT[k++] = 0x08;
- pDHCPMSG->OPT[k++] = subnetMask;
- pDHCPMSG->OPT[k++] = routersOnSubnet;
- pDHCPMSG->OPT[k++] = dns;
- pDHCPMSG->OPT[k++] = domainName;
- pDHCPMSG->OPT[k++] = dhcpT1value;
- pDHCPMSG->OPT[k++] = dhcpT2value;
- pDHCPMSG->OPT[k++] = performRouterDiscovery;
- pDHCPMSG->OPT[k++] = staticRoute;
- pDHCPMSG->OPT[k++] = endOption;
-
- for (i = k; i < OPT_SIZE; i++) pDHCPMSG->OPT[i] = 0;
-
-#ifdef _DHCP_DEBUG_
- printf("> Send DHCP_REQUEST\r\n");
-#endif
-
- sendto(DHCP_SOCKET, (uint8_t *)pDHCPMSG, RIP_MSG_SIZE, ip, DHCP_SERVER_PORT);
-
-}
-
-/* SEND DHCP DHCPDECLINE */
-void send_DHCP_DECLINE(void)
-{
- int i;
- uint8_t ip[4];
- uint16_t k = 0;
-
- makeDHCPMSG();
-
- k = 4; // because MAGIC_COOKIE already made by makeDHCPMSG()
-
- *((uint8_t*)(&pDHCPMSG->flags)) = ((DHCP_FLAGSUNICAST & 0xFF00)>> 8);
- *((uint8_t*)(&pDHCPMSG->flags)+1) = (DHCP_FLAGSUNICAST & 0x00FF);
-
- // Option Request Param.
- pDHCPMSG->OPT[k++] = dhcpMessageType;
- pDHCPMSG->OPT[k++] = 0x01;
- pDHCPMSG->OPT[k++] = DHCP_DECLINE;
-
- pDHCPMSG->OPT[k++] = dhcpClientIdentifier;
- pDHCPMSG->OPT[k++] = 0x07;
- pDHCPMSG->OPT[k++] = 0x01;
- pDHCPMSG->OPT[k++] = DHCP_CHADDR[0];
- pDHCPMSG->OPT[k++] = DHCP_CHADDR[1];
- pDHCPMSG->OPT[k++] = DHCP_CHADDR[2];
- pDHCPMSG->OPT[k++] = DHCP_CHADDR[3];
- pDHCPMSG->OPT[k++] = DHCP_CHADDR[4];
- pDHCPMSG->OPT[k++] = DHCP_CHADDR[5];
-
- pDHCPMSG->OPT[k++] = dhcpRequestedIPaddr;
- pDHCPMSG->OPT[k++] = 0x04;
- pDHCPMSG->OPT[k++] = DHCP_allocated_ip[0];
- pDHCPMSG->OPT[k++] = DHCP_allocated_ip[1];
- pDHCPMSG->OPT[k++] = DHCP_allocated_ip[2];
- pDHCPMSG->OPT[k++] = DHCP_allocated_ip[3];
-
- pDHCPMSG->OPT[k++] = dhcpServerIdentifier;
- pDHCPMSG->OPT[k++] = 0x04;
- pDHCPMSG->OPT[k++] = DHCP_SIP[0];
- pDHCPMSG->OPT[k++] = DHCP_SIP[1];
- pDHCPMSG->OPT[k++] = DHCP_SIP[2];
- pDHCPMSG->OPT[k++] = DHCP_SIP[3];
-
- pDHCPMSG->OPT[k++] = endOption;
-
- for (i = k; i < OPT_SIZE; i++) pDHCPMSG->OPT[i] = 0;
-
- //send broadcasting packet
- ip[0] = 0xFF;
- ip[1] = 0xFF;
- ip[2] = 0xFF;
- ip[3] = 0xFF;
-
-#ifdef _DHCP_DEBUG_
- printf("\r\n> Send DHCP_DECLINE\r\n");
-#endif
-
- sendto(DHCP_SOCKET, (uint8_t *)pDHCPMSG, RIP_MSG_SIZE, ip, DHCP_SERVER_PORT);
-}
-
-/* PARSE REPLY pDHCPMSG */
-int8_t parseDHCPMSG(void)
-{
- uint8_t svr_addr[6];
- uint16_t svr_port;
- uint16_t len;
-
- uint8_t * p;
- uint8_t * e;
- uint8_t type;
- uint8_t opt_len;
-
- if((len = getSn_RX_RSR(DHCP_SOCKET)) > 0)
- {
- len = recvfrom(DHCP_SOCKET, (uint8_t *)pDHCPMSG, len, svr_addr, &svr_port);
- #ifdef _DHCP_DEBUG_
- printf("DHCP message : %d.%d.%d.%d(%d) %d received. \r\n",svr_addr[0],svr_addr[1],svr_addr[2], svr_addr[3],svr_port, len);
- #endif
- }
- else return 0;
- if (svr_port == DHCP_SERVER_PORT) {
- // compare mac address
- if ( (pDHCPMSG->chaddr[0] != DHCP_CHADDR[0]) || (pDHCPMSG->chaddr[1] != DHCP_CHADDR[1]) ||
- (pDHCPMSG->chaddr[2] != DHCP_CHADDR[2]) || (pDHCPMSG->chaddr[3] != DHCP_CHADDR[3]) ||
- (pDHCPMSG->chaddr[4] != DHCP_CHADDR[4]) || (pDHCPMSG->chaddr[5] != DHCP_CHADDR[5]) )
- return 0;
- type = 0;
- p = (uint8_t *)(&pDHCPMSG->op);
- p = p + 240; // 240 = sizeof(RIP_MSG) + MAGIC_COOKIE size in RIP_MSG.opt - sizeof(RIP_MSG.opt)
- e = p + (len - 240);
-
- while ( p < e ) {
-
- switch ( *p ) {
-
- case endOption :
- p = e; // for break while(p < e)
- break;
- case padOption :
- p++;
- break;
- case dhcpMessageType :
- p++;
- p++;
- type = *p++;
- break;
- case subnetMask :
- p++;
- p++;
- DHCP_allocated_sn[0] = *p++;
- DHCP_allocated_sn[1] = *p++;
- DHCP_allocated_sn[2] = *p++;
- DHCP_allocated_sn[3] = *p++;
- break;
- case routersOnSubnet :
- p++;
- opt_len = *p++;
- DHCP_allocated_gw[0] = *p++;
- DHCP_allocated_gw[1] = *p++;
- DHCP_allocated_gw[2] = *p++;
- DHCP_allocated_gw[3] = *p++;
- p = p + (opt_len - 4);
- break;
- case dns :
- p++;
- opt_len = *p++;
- DHCP_allocated_dns[0] = *p++;
- DHCP_allocated_dns[1] = *p++;
- DHCP_allocated_dns[2] = *p++;
- DHCP_allocated_dns[3] = *p++;
- p = p + (opt_len - 4);
- break;
- case dhcpIPaddrLeaseTime :
- p++;
- opt_len = *p++;
- dhcp_lease_time = *p++;
- dhcp_lease_time = (dhcp_lease_time << 8) + *p++;
- dhcp_lease_time = (dhcp_lease_time << 8) + *p++;
- dhcp_lease_time = (dhcp_lease_time << 8) + *p++;
- #ifdef _DHCP_DEBUG_
- dhcp_lease_time = 10;
- #endif
- break;
- case dhcpServerIdentifier :
- p++;
- opt_len = *p++;
- DHCP_SIP[0] = *p++;
- DHCP_SIP[1] = *p++;
- DHCP_SIP[2] = *p++;
- DHCP_SIP[3] = *p++;
- break;
- default :
- p++;
- opt_len = *p++;
- p += opt_len;
- break;
- } // switch
- } // while
- } // if
- return type;
-}
-
-uint8_t DHCP_run(void)
-{
- uint8_t type;
- uint8_t ret;
-
- if(dhcp_state == STATE_DHCP_STOP) return DHCP_STOPPED;
-
- if(getSn_SR(DHCP_SOCKET) != SOCK_UDP)
- socket(DHCP_SOCKET, Sn_MR_UDP, DHCP_CLIENT_PORT, 0x00);
-
- ret = DHCP_RUNNING;
- type = parseDHCPMSG();
-
- switch ( dhcp_state ) {
- case STATE_DHCP_INIT :
- DHCP_allocated_ip[0] = 0;
- DHCP_allocated_ip[1] = 0;
- DHCP_allocated_ip[2] = 0;
- DHCP_allocated_ip[3] = 0;
- send_DHCP_DISCOVER();
- dhcp_state = STATE_DHCP_DISCOVER;
- break;
- case STATE_DHCP_DISCOVER :
- if (type == DHCP_OFFER){
-#ifdef _DHCP_DEBUG_
- printf("> Receive DHCP_OFFER\r\n");
-#endif
- DHCP_allocated_ip[0] = pDHCPMSG->yiaddr[0];
- DHCP_allocated_ip[1] = pDHCPMSG->yiaddr[1];
- DHCP_allocated_ip[2] = pDHCPMSG->yiaddr[2];
- DHCP_allocated_ip[3] = pDHCPMSG->yiaddr[3];
-
- send_DHCP_REQUEST();
- dhcp_state = STATE_DHCP_REQUEST;
- } else ret = check_DHCP_timeout();
- break;
-
- case STATE_DHCP_REQUEST :
- if (type == DHCP_ACK) {
-
-#ifdef _DHCP_DEBUG_
- printf("> Receive DHCP_ACK\r\n");
-#endif
- if (check_DHCP_leasedIP()) {
- // Network info assignment from DHCP
- dhcp_ip_assign();
- reset_DHCP_timeout();
-
- dhcp_state = STATE_DHCP_LEASED;
- } else {
- // IP address conflict occurred
- reset_DHCP_timeout();
- dhcp_ip_conflict();
- dhcp_state = STATE_DHCP_INIT;
- }
- } else if (type == DHCP_NAK) {
-
-#ifdef _DHCP_DEBUG_
- printf("> Receive DHCP_NACK\r\n");
-#endif
-
- reset_DHCP_timeout();
-
- dhcp_state = STATE_DHCP_DISCOVER;
- } else ret = check_DHCP_timeout();
- break;
-
- case STATE_DHCP_LEASED :
- ret = DHCP_IP_LEASED;
- if ((dhcp_lease_time != INFINITE_LEASETIME) && ((dhcp_lease_time/2) < dhcp_tick_1s)) {
-
-#ifdef _DHCP_DEBUG_
- printf("> Maintains the IP address \r\n");
-#endif
-
- type = 0;
- OLD_allocated_ip[0] = DHCP_allocated_ip[0];
- OLD_allocated_ip[1] = DHCP_allocated_ip[1];
- OLD_allocated_ip[2] = DHCP_allocated_ip[2];
- OLD_allocated_ip[3] = DHCP_allocated_ip[3];
-
- DHCP_XID++;
-
- send_DHCP_REQUEST();
-
- reset_DHCP_timeout();
-
- dhcp_state = STATE_DHCP_REREQUEST;
- }
- break;
-
- case STATE_DHCP_REREQUEST :
- ret = DHCP_IP_LEASED;
- if (type == DHCP_ACK) {
- dhcp_retry_count = 0;
- if (OLD_allocated_ip[0] != DHCP_allocated_ip[0] ||
- OLD_allocated_ip[1] != DHCP_allocated_ip[1] ||
- OLD_allocated_ip[2] != DHCP_allocated_ip[2] ||
- OLD_allocated_ip[3] != DHCP_allocated_ip[3])
- {
- ret = DHCP_IP_CHANGED;
- dhcp_ip_update();
- #ifdef _DHCP_DEBUG_
- printf(">IP changed.\r\n");
- #endif
-
- }
- #ifdef _DHCP_DEBUG_
- else printf(">IP is continued.\r\n");
- #endif
- reset_DHCP_timeout();
- dhcp_state = STATE_DHCP_LEASED;
- } else if (type == DHCP_NAK) {
-
-#ifdef _DHCP_DEBUG_
- printf("> Receive DHCP_NACK, Failed to maintain ip\r\n");
-#endif
-
- reset_DHCP_timeout();
-
- dhcp_state = STATE_DHCP_DISCOVER;
- } else ret = check_DHCP_timeout();
- break;
- default :
- break;
- }
-
- return ret;
-}
-
-void DHCP_stop(void)
-{
- close(DHCP_SOCKET);
- dhcp_state = STATE_DHCP_STOP;
-}
-
-uint8_t check_DHCP_timeout(void)
-{
- uint8_t ret = DHCP_RUNNING;
-
- if (dhcp_retry_count < MAX_DHCP_RETRY) {
- if (dhcp_tick_next < dhcp_tick_1s) {
-
- switch ( dhcp_state ) {
- case STATE_DHCP_DISCOVER :
-// printf("<> state : STATE_DHCP_DISCOVER\r\n");
- send_DHCP_DISCOVER();
- break;
-
- case STATE_DHCP_REQUEST :
-// printf("<> state : STATE_DHCP_REQUEST\r\n");
-
- send_DHCP_REQUEST();
- break;
-
- case STATE_DHCP_REREQUEST :
-// printf("<> state : STATE_DHCP_REREQUEST\r\n");
-
- send_DHCP_REQUEST();
- break;
-
- default :
- break;
- }
-
- dhcp_tick_1s = 0;
- dhcp_tick_next = dhcp_tick_1s + DHCP_WAIT_TIME;
- dhcp_retry_count++;
- }
- } else { // timeout occurred
-
- switch(dhcp_state) {
- case STATE_DHCP_DISCOVER:
- dhcp_state = STATE_DHCP_INIT;
- ret = DHCP_FAILED;
- break;
- case STATE_DHCP_REQUEST:
- case STATE_DHCP_REREQUEST:
- send_DHCP_DISCOVER();
- dhcp_state = STATE_DHCP_DISCOVER;
- break;
- default :
- break;
- }
- reset_DHCP_timeout();
- }
- return ret;
-}
-
-int8_t check_DHCP_leasedIP(void)
-{
- uint8_t tmp;
- int32_t ret;
-
- //WIZchip RCR value changed for ARP Timeout count control
- tmp = getRCR();
- setRCR(0x03);
-
- // IP conflict detection : ARP request - ARP reply
- // Broadcasting ARP Request for check the IP conflict using UDP sendto() function
- ret = sendto(DHCP_SOCKET, (uint8_t *)"CHECK_IP_CONFLICT", 17, DHCP_allocated_ip, 5000);
-
- // RCR value restore
- setRCR(tmp);
-
- if(ret == SOCKERR_TIMEOUT) {
- // UDP send Timeout occurred : allocated IP address is unique, DHCP Success
-
-#ifdef _DHCP_DEBUG_
- printf("\r\n> Check leased IP - OK\r\n");
-#endif
-
- return 1;
- } else {
- // Received ARP reply or etc : IP address conflict occur, DHCP Failed
- send_DHCP_DECLINE();
-
- ret = dhcp_tick_1s;
- while((dhcp_tick_1s - ret) < 2) ; // wait for 1s over; wait to complete to send DECLINE message;
-
- return 0;
- }
-}
-
-void DHCP_init(uint8_t s, uint8_t * buf)
-{
- uint8_t zeroip[4] = {0,0,0,0};
- getSHAR(DHCP_CHADDR);
- if((DHCP_CHADDR[0] | DHCP_CHADDR[1] | DHCP_CHADDR[2] | DHCP_CHADDR[3] | DHCP_CHADDR[4] | DHCP_CHADDR[5]) == 0x00)
- {
- // assign temporary mac address, you should be set SHAR before call this function.
- DHCP_CHADDR[0] = 0x00;
- DHCP_CHADDR[1] = 0x08;
- DHCP_CHADDR[2] = 0xdc;
- DHCP_CHADDR[3] = 0x00;
- DHCP_CHADDR[4] = 0x00;
- DHCP_CHADDR[5] = 0x00;
- setSHAR(DHCP_CHADDR);
- }
-
- DHCP_SOCKET = s; // SOCK_DHCP
- pDHCPMSG = (RIP_MSG*)buf;
- DHCP_XID = 0x12345678;
-
- // WIZchip Netinfo Clear
- setSIPR(zeroip);
- setSIPR(zeroip);
- setGAR(zeroip);
-
- reset_DHCP_timeout();
- dhcp_state = STATE_DHCP_INIT;
-}
-
-
-/* Rset the DHCP timeout count and retry count. */
-void reset_DHCP_timeout(void)
-{
- dhcp_tick_1s = 0;
- dhcp_tick_next = DHCP_WAIT_TIME;
- dhcp_retry_count = 0;
-}
-
-void DHCP_time_handler(void)
-{
- dhcp_tick_1s++;
-}
-
-void getIPfromDHCP(uint8_t* ip)
-{
- ip[0] = DHCP_allocated_ip[0];
- ip[1] = DHCP_allocated_ip[1];
- ip[2] = DHCP_allocated_ip[2];
- ip[3] = DHCP_allocated_ip[3];
-}
-
-void getGWfromDHCP(uint8_t* ip)
-{
- ip[0] =DHCP_allocated_gw[0];
- ip[1] =DHCP_allocated_gw[1];
- ip[2] =DHCP_allocated_gw[2];
- ip[3] =DHCP_allocated_gw[3];
-}
-
-void getSNfromDHCP(uint8_t* ip)
-{
- ip[0] = DHCP_allocated_sn[0];
- ip[1] = DHCP_allocated_sn[1];
- ip[2] = DHCP_allocated_sn[2];
- ip[3] = DHCP_allocated_sn[3];
-}
-
-void getDNSfromDHCP(uint8_t* ip)
-{
- ip[0] = DHCP_allocated_dns[0];
- ip[1] = DHCP_allocated_dns[1];
- ip[2] = DHCP_allocated_dns[2];
- ip[3] = DHCP_allocated_dns[3];
-}
-
-uint32_t getDHCPLeasetime(void)
-{
- return dhcp_lease_time;
-}
-
-
-
-
diff --git a/drivers/wiznet5k/internet/dhcp/dhcp.h b/drivers/wiznet5k/internet/dhcp/dhcp.h
deleted file mode 100644
index ee154d506ac3..000000000000
--- a/drivers/wiznet5k/internet/dhcp/dhcp.h
+++ /dev/null
@@ -1,150 +0,0 @@
-//*****************************************************************************
-//
-//! \file dhcp.h
-//! \brief DHCP APIs Header file.
-//! \details Processig DHCP protocol as DISCOVER, OFFER, REQUEST, ACK, NACK and DECLINE.
-//! \version 1.1.0
-//! \date 2013/11/18
-//! \par Revision history
-//! <2013/11/18> 1st Release
-//! <2012/12/20> V1.1.0
-//! 1. Move unreferenced DEFINE to dhcp.c
-//! <2012/12/26> V1.1.1
-//! \author Eric Jung & MidnightCow
-//! \copyright
-//!
-//! Copyright (c) 2013, WIZnet Co., LTD.
-//! 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 the 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 OWNER 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.
-//
-//*****************************************************************************
-#ifndef _DHCP_H_
-#define _DHCP_H_
-
-/*
- * @brief
- * @details If you want to display debug & processing message, Define _DHCP_DEBUG_
- * @note If defined, it depends on
- */
-
-//#define _DHCP_DEBUG_
-
-/* Retry to processing DHCP */
-#define MAX_DHCP_RETRY 2 ///< Maximum retry count
-#define DHCP_WAIT_TIME 10 ///< Wait Time 10s
-
-/* UDP port numbers for DHCP */
-#define DHCP_SERVER_PORT 67 ///< DHCP server port number
-#define DHCP_CLIENT_PORT 68 ///< DHCP client port number
-
-#define MAGIC_COOKIE 0x63825363 ///< Any number. You can be modified it any number
-
-#define DCHP_HOST_NAME "WIZnet\0"
-
-/*
- * @brief return value of @ref DHCP_run()
- */
-enum
-{
- DHCP_FAILED = 0, ///< Processing Fail
- DHCP_RUNNING, ///< Processing DHCP protocol
- DHCP_IP_ASSIGN, ///< First Occupy IP from DHPC server (if cbfunc == null, act as default default_ip_assign)
- DHCP_IP_CHANGED, ///< Change IP address by new IP address from DHCP (if cbfunc == null, act as default default_ip_update)
- DHCP_IP_LEASED, ///< Stand by
- DHCP_STOPPED ///< Stop processing DHCP protocol
-};
-
-/*
- * @brief DHCP client initialization (outside of the main loop)
- * @param s - socket number
- * @param buf - buffer for processing DHCP message
- */
-void DHCP_init(uint8_t s, uint8_t * buf);
-
-/*
- * @brief DHCP 1s Tick Timer handler
- * @note SHOULD BE register to your system 1s Tick timer handler
- */
-void DHCP_time_handler(void);
-
-/*
- * @brief Register call back function
- * @param ip_assign - callback func when IP is assigned from DHCP server first
- * @param ip_update - callback func when IP is changed
- * @prarm ip_conflict - callback func when the assigned IP is conflict with others.
- */
-void reg_dhcp_cbfunc(void(*ip_assign)(void), void(*ip_update)(void), void(*ip_conflict)(void));
-
-/*
- * @brief DHCP client in the main loop
- * @return The value is as the follow \n
- * @ref DHCP_FAILED \n
- * @ref DHCP_RUNNING \n
- * @ref DHCP_IP_ASSIGN \n
- * @ref DHCP_IP_CHANGED \n
- * @ref DHCP_IP_LEASED \n
- * @ref DHCP_STOPPED \n
- *
- * @note This function is always called by you main task.
- */
-uint8_t DHCP_run(void);
-
-/*
- * @brief Stop DHCP processing
- * @note If you want to restart. call DHCP_init() and DHCP_run()
- */
-void DHCP_stop(void);
-
-/* Get Network information assigned from DHCP server */
-/*
- * @brief Get IP address
- * @param ip - IP address to be returned
- */
-void getIPfromDHCP(uint8_t* ip);
-/*
- * @brief Get Gateway address
- * @param ip - Gateway address to be returned
- */
-void getGWfromDHCP(uint8_t* ip);
-/*
- * @brief Get Subnet mask value
- * @param ip - Subnet mask to be returned
- */
-void getSNfromDHCP(uint8_t* ip);
-/*
- * @brief Get DNS address
- * @param ip - DNS address to be returned
- */
-void getDNSfromDHCP(uint8_t* ip);
-
-/*
- * @brief Get the leased time by DHCP sever
- * @return unit 1s
- */
-uint32_t getDHCPLeasetime(void);
-
-#endif /* _DHCP_H_ */
diff --git a/drivers/wiznet5k/internet/dns/dns.c b/drivers/wiznet5k/internet/dns/dns.c
deleted file mode 100644
index c0ad570c0097..000000000000
--- a/drivers/wiznet5k/internet/dns/dns.c
+++ /dev/null
@@ -1,566 +0,0 @@
-//*****************************************************************************
-//
-//! \file dns.c
-//! \brief DNS APIs Implement file.
-//! \details Send DNS query & Receive DNS reponse. \n
-//! It depends on stdlib.h & string.h in ansi-c library
-//! \version 1.1.0
-//! \date 2013/11/18
-//! \par Revision history
-//! <2013/10/21> 1st Release
-//! <2013/12/20> V1.1.0
-//! 1. Remove secondary DNS server in DNS_run
-//! If 1st DNS_run failed, call DNS_run with 2nd DNS again
-//! 2. DNS_timerHandler -> DNS_time_handler
-//! 3. Remove the unused define
-//! 4. Integrated dns.h dns.c & dns_parse.h dns_parse.c into dns.h & dns.c
-//! <2013/12/20> V1.1.0
-//!
-//! \author Eric Jung & MidnightCow
-//! \copyright
-//!
-//! Copyright (c) 2013, WIZnet Co., LTD.
-//! 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 the 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 OWNER 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.
-//
-//*****************************************************************************
-
-#include
-#include
-
-//#include "Ethernet/socket.h"
-//#include "Internet/DNS/dns.h"
-#include "../../ethernet/socket.h"
-#include "dns.h"
-
-#ifdef _DNS_DEBUG_
- #include
-#endif
-
-#define INITRTT 2000L /* Initial smoothed response time */
-#define MAXCNAME (MAX_DOMAIN_NAME + (MAX_DOMAIN_NAME>>1)) /* Maximum amount of cname recursion */
-
-#define TYPE_A 1 /* Host address */
-#define TYPE_NS 2 /* Name server */
-#define TYPE_MD 3 /* Mail destination (obsolete) */
-#define TYPE_MF 4 /* Mail forwarder (obsolete) */
-#define TYPE_CNAME 5 /* Canonical name */
-#define TYPE_SOA 6 /* Start of Authority */
-#define TYPE_MB 7 /* Mailbox name (experimental) */
-#define TYPE_MG 8 /* Mail group member (experimental) */
-#define TYPE_MR 9 /* Mail rename name (experimental) */
-#define TYPE_NULL 10 /* Null (experimental) */
-#define TYPE_WKS 11 /* Well-known sockets */
-#define TYPE_PTR 12 /* Pointer record */
-#define TYPE_HINFO 13 /* Host information */
-#define TYPE_MINFO 14 /* Mailbox information (experimental)*/
-#define TYPE_MX 15 /* Mail exchanger */
-#define TYPE_TXT 16 /* Text strings */
-#define TYPE_ANY 255 /* Matches any type */
-
-#define CLASS_IN 1 /* The ARPA Internet */
-
-/* Round trip timing parameters */
-#define AGAIN 8 /* Average RTT gain = 1/8 */
-#define LAGAIN 3 /* Log2(AGAIN) */
-#define DGAIN 4 /* Mean deviation gain = 1/4 */
-#define LDGAIN 2 /* log2(DGAIN) */
-
-/* Header for all domain messages */
-struct dhdr
-{
- uint16_t id; /* Identification */
- uint8_t qr; /* Query/Response */
-#define QUERY 0
-#define RESPONSE 1
- uint8_t opcode;
-#define IQUERY 1
- uint8_t aa; /* Authoratative answer */
- uint8_t tc; /* Truncation */
- uint8_t rd; /* Recursion desired */
- uint8_t ra; /* Recursion available */
- uint8_t rcode; /* Response code */
-#define NO_ERROR 0
-#define FORMAT_ERROR 1
-#define SERVER_FAIL 2
-#define NAME_ERROR 3
-#define NOT_IMPL 4
-#define REFUSED 5
- uint16_t qdcount; /* Question count */
- uint16_t ancount; /* Answer count */
- uint16_t nscount; /* Authority (name server) count */
- uint16_t arcount; /* Additional record count */
-};
-
-
-uint8_t* pDNSMSG; // DNS message buffer
-uint8_t DNS_SOCKET; // SOCKET number for DNS
-uint16_t DNS_MSGID; // DNS message ID
-
-extern uint32_t HAL_GetTick(void);
-uint32_t hal_sys_tick;
-
-/* converts uint16_t from network buffer to a host byte order integer. */
-uint16_t get16(uint8_t * s)
-{
- uint16_t i;
- i = *s++ << 8;
- i = i + *s;
- return i;
-}
-
-/* copies uint16_t to the network buffer with network byte order. */
-uint8_t * put16(uint8_t * s, uint16_t i)
-{
- *s++ = i >> 8;
- *s++ = i;
- return s;
-}
-
-
-/*
- * CONVERT A DOMAIN NAME TO THE HUMAN-READABLE FORM
- *
- * Description : This function converts a compressed domain name to the human-readable form
- * Arguments : msg - is a pointer to the reply message
- * compressed - is a pointer to the domain name in reply message.
- * buf - is a pointer to the buffer for the human-readable form name.
- * len - is the MAX. size of buffer.
- * Returns : the length of compressed message
- */
-int parse_name(uint8_t * msg, uint8_t * compressed, char * buf, int16_t len)
-{
- uint16_t slen; /* Length of current segment */
- uint8_t * cp;
- int clen = 0; /* Total length of compressed name */
- int indirect = 0; /* Set if indirection encountered */
- int nseg = 0; /* Total number of segments in name */
-
- cp = compressed;
-
- for (;;)
- {
- slen = *cp++; /* Length of this segment */
-
- if (!indirect) clen++;
-
- if ((slen & 0xc0) == 0xc0)
- {
- if (!indirect)
- clen++;
- indirect = 1;
- /* Follow indirection */
- cp = &msg[((slen & 0x3f)<<8) + *cp];
- slen = *cp++;
- }
-
- if (slen == 0) /* zero length == all done */
- break;
-
- len -= slen + 1;
-
- if (len < 0) return -1;
-
- if (!indirect) clen += slen;
-
- while (slen-- != 0) *buf++ = (char)*cp++;
- *buf++ = '.';
- nseg++;
- }
-
- if (nseg == 0)
- {
- /* Root name; represent as single dot */
- *buf++ = '.';
- len--;
- }
-
- *buf++ = '\0';
- len--;
-
- return clen; /* Length of compressed message */
-}
-
-/*
- * PARSE QUESTION SECTION
- *
- * Description : This function parses the question record of the reply message.
- * Arguments : msg - is a pointer to the reply message
- * cp - is a pointer to the question record.
- * Returns : a pointer the to next record.
- */
-uint8_t * dns_question(uint8_t * msg, uint8_t * cp)
-{
- int len;
- char name[MAXCNAME];
-
- len = parse_name(msg, cp, name, MAXCNAME);
-
-
- if (len == -1) return 0;
-
- cp += len;
- cp += 2; /* type */
- cp += 2; /* class */
-
- return cp;
-}
-
-
-/*
- * PARSE ANSER SECTION
- *
- * Description : This function parses the answer record of the reply message.
- * Arguments : msg - is a pointer to the reply message
- * cp - is a pointer to the answer record.
- * Returns : a pointer the to next record.
- */
-uint8_t * dns_answer(uint8_t * msg, uint8_t * cp, uint8_t * ip_from_dns)
-{
- int len, type;
- char name[MAXCNAME];
-
- len = parse_name(msg, cp, name, MAXCNAME);
-
- if (len == -1) return 0;
-
- cp += len;
- type = get16(cp);
- cp += 2; /* type */
- cp += 2; /* class */
- cp += 4; /* ttl */
- cp += 2; /* len */
-
-
- switch (type)
- {
- case TYPE_A:
- /* Just read the address directly into the structure */
- ip_from_dns[0] = *cp++;
- ip_from_dns[1] = *cp++;
- ip_from_dns[2] = *cp++;
- ip_from_dns[3] = *cp++;
- break;
- case TYPE_CNAME:
- case TYPE_MB:
- case TYPE_MG:
- case TYPE_MR:
- case TYPE_NS:
- case TYPE_PTR:
- /* These types all consist of a single domain name */
- /* convert it to ASCII format */
- len = parse_name(msg, cp, name, MAXCNAME);
- if (len == -1) return 0;
-
- cp += len;
- break;
- case TYPE_HINFO:
- len = *cp++;
- cp += len;
-
- len = *cp++;
- cp += len;
- break;
- case TYPE_MX:
- cp += 2;
- /* Get domain name of exchanger */
- len = parse_name(msg, cp, name, MAXCNAME);
- if (len == -1) return 0;
-
- cp += len;
- break;
- case TYPE_SOA:
- /* Get domain name of name server */
- len = parse_name(msg, cp, name, MAXCNAME);
- if (len == -1) return 0;
-
- cp += len;
-
- /* Get domain name of responsible person */
- len = parse_name(msg, cp, name, MAXCNAME);
- if (len == -1) return 0;
-
- cp += len;
-
- cp += 4;
- cp += 4;
- cp += 4;
- cp += 4;
- cp += 4;
- break;
- case TYPE_TXT:
- /* Just stash */
- break;
- default:
- /* Ignore */
- break;
- }
-
- return cp;
-}
-
-/*
- * PARSE THE DNS REPLY
- *
- * Description : This function parses the reply message from DNS server.
- * Arguments : dhdr - is a pointer to the header for DNS message
- * buf - is a pointer to the reply message.
- * len - is the size of reply message.
- * Returns : -1 - Domain name length is too big
- * 0 - Fail (Timeout or parse error)
- * 1 - Success,
- */
-int8_t parseDNSMSG(struct dhdr * pdhdr, uint8_t * pbuf, uint8_t * ip_from_dns)
-{
- uint16_t tmp;
- uint16_t i;
- uint8_t * msg;
- uint8_t * cp;
-
- msg = pbuf;
- memset(pdhdr, 0, sizeof(*pdhdr));
-
- pdhdr->id = get16(&msg[0]);
- tmp = get16(&msg[2]);
- if (tmp & 0x8000) pdhdr->qr = 1;
-
- pdhdr->opcode = (tmp >> 11) & 0xf;
-
- if (tmp & 0x0400) pdhdr->aa = 1;
- if (tmp & 0x0200) pdhdr->tc = 1;
- if (tmp & 0x0100) pdhdr->rd = 1;
- if (tmp & 0x0080) pdhdr->ra = 1;
-
- pdhdr->rcode = tmp & 0xf;
- pdhdr->qdcount = get16(&msg[4]);
- pdhdr->ancount = get16(&msg[6]);
- pdhdr->nscount = get16(&msg[8]);
- pdhdr->arcount = get16(&msg[10]);
-
-
- /* Now parse the variable length sections */
- cp = &msg[12];
-
- /* Question section */
- for (i = 0; i < pdhdr->qdcount; i++)
- {
- cp = dns_question(msg, cp);
- if(!cp)
- {
-#ifdef _DNS_DEBUG_
- printf("MAX_DOMAIN_NAME is too small, it should be redefined in dns.h\r\n");
-#endif
- return -1;
- }
- }
-
- /* Answer section */
- for (i = 0; i < pdhdr->ancount; i++)
- {
- cp = dns_answer(msg, cp, ip_from_dns);
- if(!cp)
- {
-#ifdef _DNS_DEBUG_
- printf("MAX_DOMAIN_NAME is too small, it should be redefined in dns.h\r\n");
-#endif
- return -1;
- }
-
- }
-
- /* Name server (authority) section */
- for (i = 0; i < pdhdr->nscount; i++)
- {
- ;
- }
-
- /* Additional section */
- for (i = 0; i < pdhdr->arcount; i++)
- {
- ;
- }
-
- if(pdhdr->rcode == 0) return 1; // No error
- else return 0;
-}
-
-
-/*
- * MAKE DNS QUERY MESSAGE
- *
- * Description : This function makes DNS query message.
- * Arguments : op - Recursion desired
- * name - is a pointer to the domain name.
- * buf - is a pointer to the buffer for DNS message.
- * len - is the MAX. size of buffer.
- * Returns : the pointer to the DNS message.
- */
-int16_t dns_makequery(uint16_t op, char * name, uint8_t * buf, uint16_t len)
-{
- uint8_t *cp;
- char *cp1;
- char sname[MAXCNAME];
- char *dname;
- uint16_t p;
- uint16_t dlen;
-
- cp = buf;
-
- DNS_MSGID++;
- cp = put16(cp, DNS_MSGID);
- p = (op << 11) | 0x0100; /* Recursion desired */
- cp = put16(cp, p);
- cp = put16(cp, 1);
- cp = put16(cp, 0);
- cp = put16(cp, 0);
- cp = put16(cp, 0);
-
- strcpy(sname, name);
- dname = sname;
- dlen = strlen(dname);
- for (;;)
- {
- /* Look for next dot */
- cp1 = strchr(dname, '.');
-
- if (cp1 != NULL) len = cp1 - dname; /* More to come */
- else len = dlen; /* Last component */
-
- *cp++ = len; /* Write length of component */
- if (len == 0) break;
-
- /* Copy component up to (but not including) dot */
- memcpy(cp, dname, len);
- cp += len;
- if (cp1 == NULL)
- {
- *cp++ = 0; /* Last one; write null and finish */
- break;
- }
- dname += len+1;
- dlen -= len+1;
- }
-
- cp = put16(cp, 0x0001); /* type */
- cp = put16(cp, 0x0001); /* class */
-
- return ((int16_t)((uint32_t)(cp) - (uint32_t)(buf)));
-}
-
-/*
- * CHECK DNS TIMEOUT
- *
- * Description : This function check the DNS timeout
- * Arguments : None.
- * Returns : -1 - timeout occurred, 0 - timer over, but no timeout, 1 - no timer over, no timeout occur
- * Note : timeout : retry count and timer both over.
- */
-
-int8_t check_DNS_timeout(void)
-{
- static uint8_t retry_count;
-
- uint32_t tick = HAL_GetTick();
- if(tick - hal_sys_tick >= DNS_WAIT_TIME * 1000)
- {
- hal_sys_tick = tick;
- if(retry_count >= MAX_DNS_RETRY) {
- retry_count = 0;
- return -1; // timeout occurred
- }
- retry_count++;
- return 0; // timer over, but no timeout
- }
-
- return 1; // no timer over, no timeout occur
-}
-
-
-
-/* DNS CLIENT INIT */
-void DNS_init(uint8_t s, uint8_t * buf)
-{
- DNS_SOCKET = s; // SOCK_DNS
- pDNSMSG = buf; // User's shared buffer
- DNS_MSGID = DNS_MSG_ID;
-}
-
-/* DNS CLIENT RUN */
-int8_t DNS_run(uint8_t * dns_ip, uint8_t * name, uint8_t * ip_from_dns)
-{
- int8_t ret;
- struct dhdr dhp;
- uint8_t ip[4];
- uint16_t len, port;
- int8_t ret_check_timeout;
-
- hal_sys_tick = HAL_GetTick();
-
- // Socket open
- WIZCHIP_EXPORT(socket)(DNS_SOCKET, Sn_MR_UDP, 0, 0);
-
-#ifdef _DNS_DEBUG_
- printf("> DNS Query to DNS Server : %d.%d.%d.%d\r\n", dns_ip[0], dns_ip[1], dns_ip[2], dns_ip[3]);
-#endif
-
- len = dns_makequery(0, (char *)name, pDNSMSG, MAX_DNS_BUF_SIZE);
- WIZCHIP_EXPORT(sendto)(DNS_SOCKET, pDNSMSG, len, dns_ip, IPPORT_DOMAIN);
-
- while (1)
- {
- if ((len = getSn_RX_RSR(DNS_SOCKET)) > 0)
- {
- if (len > MAX_DNS_BUF_SIZE) len = MAX_DNS_BUF_SIZE;
- len = WIZCHIP_EXPORT(recvfrom)(DNS_SOCKET, pDNSMSG, len, ip, &port);
- #ifdef _DNS_DEBUG_
- printf("> Receive DNS message from %d.%d.%d.%d(%d). len = %d\r\n", ip[0], ip[1], ip[2], ip[3],port,len);
- #endif
- ret = parseDNSMSG(&dhp, pDNSMSG, ip_from_dns);
- break;
- }
- // Check Timeout
- ret_check_timeout = check_DNS_timeout();
- if (ret_check_timeout < 0) {
-
-#ifdef _DNS_DEBUG_
- printf("> DNS Server is not responding : %d.%d.%d.%d\r\n", dns_ip[0], dns_ip[1], dns_ip[2], dns_ip[3]);
-#endif
- return 0; // timeout occurred
- }
- else if (ret_check_timeout == 0) {
-
-#ifdef _DNS_DEBUG_
- printf("> DNS Timeout\r\n");
-#endif
- WIZCHIP_EXPORT(sendto)(DNS_SOCKET, pDNSMSG, len, dns_ip, IPPORT_DOMAIN);
- }
- }
- WIZCHIP_EXPORT(close)(DNS_SOCKET);
- // Return value
- // 0 > : failed / 1 - success
- return ret;
-}
diff --git a/drivers/wiznet5k/internet/dns/dns.h b/drivers/wiznet5k/internet/dns/dns.h
deleted file mode 100644
index de0039515e28..000000000000
--- a/drivers/wiznet5k/internet/dns/dns.h
+++ /dev/null
@@ -1,96 +0,0 @@
-//*****************************************************************************
-//
-//! \file dns.h
-//! \brief DNS APIs Header file.
-//! \details Send DNS query & Receive DNS reponse.
-//! \version 1.1.0
-//! \date 2013/11/18
-//! \par Revision history
-//! <2013/10/21> 1st Release
-//! <2013/12/20> V1.1.0
-//! 1. Remove secondary DNS server in DNS_run
-//! If 1st DNS_run failed, call DNS_run with 2nd DNS again
-//! 2. DNS_timerHandler -> DNS_time_handler
-//! 3. Move the no reference define to dns.c
-//! 4. Integrated dns.h dns.c & dns_parse.h dns_parse.c into dns.h & dns.c
-//! <2013/12/20> V1.1.0
-//!
-//! \author Eric Jung & MidnightCow
-//! \copyright
-//!
-//! Copyright (c) 2013, WIZnet Co., LTD.
-//! 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 the 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 OWNER 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.
-//
-//*****************************************************************************
-
-#ifndef _DNS_H_
-#define _DNS_H_
-
-#include
-/*
- * @brief Define it for Debug & Monitor DNS processing.
- * @note If defined, it depends on
- */
-
-//#define _DNS_DEBUG_
-
-#define MAX_DNS_BUF_SIZE 256 ///< maximum size of DNS buffer. */
-/*
- * @brief Maximum length of your queried Domain name
- * @todo SHOULD BE defined it equal as or greater than your Domain name length + null character(1)
- * @note SHOULD BE careful to stack overflow because it is allocated 1.5 times as MAX_DOMAIN_NAME in stack.
- */
-#define MAX_DOMAIN_NAME 32 // for example "www.google.com"
-
-#define MAX_DNS_RETRY 2 ///< Requery Count
-#define DNS_WAIT_TIME 4 ///< Wait response time. unit 1s.
-
-#define IPPORT_DOMAIN 53 ///< DNS server port number
-
-#define DNS_MSG_ID 0x1122 ///< ID for DNS message. You can be modified it any number
-/*
- * @brief DNS process initialize
- * @param s : Socket number for DNS
- * @param buf : Buffer for DNS message
- */
-void DNS_init(uint8_t s, uint8_t * buf);
-
-/*
- * @brief DNS process
- * @details Send DNS query and receive DNS response
- * @param dns_ip : DNS server ip address
- * @param name : Domain name to be queried
- * @param ip_from_dns : IP address from DNS server
- * @return -1 : failed. @ref MAX_DOMIN_NAME is too small \n
- * 0 : failed (Timeout or Parse error)\n
- * 1 : success
- * @note This function blocks until success or fail. max time = @ref MAX_DNS_RETRY * @ref DNS_WAIT_TIME
- */
-int8_t DNS_run(uint8_t * dns_ip, uint8_t * name, uint8_t * ip_from_dns);
-
-#endif /* _DNS_H_ */
diff --git a/examples/SDdatalogger/datalogger.py b/examples/SDdatalogger/datalogger.py
index 3d6f98b38927..1d1195700cbb 100644
--- a/examples/SDdatalogger/datalogger.py
+++ b/examples/SDdatalogger/datalogger.py
@@ -10,7 +10,6 @@
# loop
while True:
-
# wait for interrupt
# this reduces power consumption while waiting for switch press
pyb.wfi()
diff --git a/examples/asmsum.py b/examples/asmsum.py
index f465b25afda7..f2c7f285badc 100644
--- a/examples/asmsum.py
+++ b/examples/asmsum.py
@@ -1,6 +1,5 @@
@micropython.asm_thumb
def asm_sum_words(r0, r1):
-
# r0 = len
# r1 = ptr
# r2 = sum
@@ -25,7 +24,6 @@ def asm_sum_words(r0, r1):
@micropython.asm_thumb
def asm_sum_bytes(r0, r1):
-
# r0 = len
# r1 = ptr
# r2 = sum
diff --git a/examples/bluetooth/ble_simple_central.py b/examples/bluetooth/ble_simple_central.py
index a6bbdc6ee079..3c0cf2a0d49e 100644
--- a/examples/bluetooth/ble_simple_central.py
+++ b/examples/bluetooth/ble_simple_central.py
@@ -179,7 +179,7 @@ def connect(self, addr_type=None, addr=None, callback=None):
# Disconnect from current device.
def disconnect(self):
- if not self._conn_handle:
+ if self._conn_handle is None:
return
self._ble.gap_disconnect(self._conn_handle)
self._reset()
diff --git a/examples/bluetooth/ble_temperature_central.py b/examples/bluetooth/ble_temperature_central.py
index 96c4aad1445a..afa914672ce4 100644
--- a/examples/bluetooth/ble_temperature_central.py
+++ b/examples/bluetooth/ble_temperature_central.py
@@ -39,14 +39,7 @@
_ENV_SENSE_UUID = bluetooth.UUID(0x181A)
# org.bluetooth.characteristic.temperature
_TEMP_UUID = bluetooth.UUID(0x2A6E)
-_TEMP_CHAR = (
- _TEMP_UUID,
- bluetooth.FLAG_READ | bluetooth.FLAG_NOTIFY,
-)
-_ENV_SENSE_SERVICE = (
- _ENV_SENSE_UUID,
- (_TEMP_CHAR,),
-)
+
# org.bluetooth.characteristic.gap.appearance.xml
_ADV_APPEARANCE_GENERIC_THERMOMETER = const(768)
@@ -196,7 +189,7 @@ def connect(self, addr_type=None, addr=None, callback=None):
# Disconnect from current device.
def disconnect(self):
- if not self._conn_handle:
+ if self._conn_handle is None:
return
self._ble.gap_disconnect(self._conn_handle)
self._reset()
diff --git a/examples/bluetooth/ble_uart_repl.py b/examples/bluetooth/ble_uart_repl.py
index 9e8a38ff4b5e..7d92c1f31829 100644
--- a/examples/bluetooth/ble_uart_repl.py
+++ b/examples/bluetooth/ble_uart_repl.py
@@ -20,6 +20,7 @@
else:
_timer = None
+
# Batch writes into 50ms intervals.
def schedule_in(handler, delay_ms):
def _wrap(_arg):
diff --git a/examples/conwaylife.py b/examples/conwaylife.py
index 44c1a507be8a..00cbd9cfccaa 100644
--- a/examples/conwaylife.py
+++ b/examples/conwaylife.py
@@ -4,6 +4,7 @@
lcd = pyb.LCD("x")
lcd.light(1)
+
# do 1 iteration of Conway's Game of Life
def conway_step():
for x in range(128): # loop over x coordinates
diff --git a/examples/embedding/Makefile b/examples/embedding/Makefile
index 99f239a7c5af..13bfdf12395d 100644
--- a/examples/embedding/Makefile
+++ b/examples/embedding/Makefile
@@ -1,8 +1,25 @@
-MPTOP = ../..
-CFLAGS = -std=c99 -I. -I$(MPTOP) -DNO_QSTR
-LDFLAGS = -L.
+# This file is part of the MicroPython project, http://micropython.org/
+# The MIT License (MIT)
+# Copyright (c) 2022-2023 Damien P. George
+#
+# This is a very simple makefile that demonstrates how to build the embed port.
+# All it needs to do is build all *.c files in the micropython_embed directory.
+# This makefile would be replaced with your custom build system.
-hello-embed: hello-embed.o -lmicropython
+EMBED_DIR = micropython_embed
+PROG = embed
--lmicropython:
- $(MAKE) -f $(MPTOP)/examples/embedding/Makefile.upylib MPTOP=$(MPTOP)
+CFLAGS += -I.
+CFLAGS += -I$(EMBED_DIR)
+CFLAGS += -I$(EMBED_DIR)/port
+CFLAGS += -Wall -Og
+
+SRC += main.c
+SRC += $(wildcard $(EMBED_DIR)/*/*.c) $(wildcard $(EMBED_DIR)/*/*/*.c)
+OBJ += $(SRC:.c=.o)
+
+$(PROG): $(OBJ)
+ $(CC) -o $@ $^
+
+clean:
+ /bin/rm -f $(OBJ) $(PROG)
diff --git a/examples/embedding/Makefile.upylib b/examples/embedding/Makefile.upylib
deleted file mode 100644
index 80f7eed159bc..000000000000
--- a/examples/embedding/Makefile.upylib
+++ /dev/null
@@ -1,193 +0,0 @@
-MPTOP = ../..
--include mpconfigport.mk
-include $(MPTOP)/py/mkenv.mk
-
-all: lib
-
-# OS name, for simple autoconfig
-UNAME_S := $(shell uname -s)
-
-# include py core make definitions
-include $(MPTOP)/py/py.mk
-
-INC += -I.
-INC += -I..
-INC += -I$(MPTOP)
-INC += -I$(MPTOP)/ports/unix
-INC += -I$(BUILD)
-
-# compiler settings
-CWARN = -Wall -Werror
-CWARN += -Wpointer-arith -Wuninitialized
-CFLAGS = $(INC) $(CWARN) -std=gnu99 -DUNIX $(CFLAGS_MOD) $(COPT) $(CFLAGS_EXTRA)
-
-# Some systems (eg MacOS) need -fno-common so that mp_state_ctx is placed in the BSS.
-CFLAGS += -fno-common
-
-# Debugging/Optimization
-ifdef DEBUG
-CFLAGS += -g
-COPT = -O0
-else
-COPT = -Os #-DNDEBUG
-# _FORTIFY_SOURCE is a feature in gcc/glibc which is intended to provide extra
-# security for detecting buffer overflows. Some distros (Ubuntu at the very least)
-# have it enabled by default.
-#
-# gcc already optimizes some printf calls to call puts and/or putchar. When
-# _FORTIFY_SOURCE is enabled and compiling with -O1 or greater, then some
-# printf calls will also be optimized to call __printf_chk (in glibc). Any
-# printfs which get redirected to __printf_chk are then no longer synchronized
-# with printfs that go through mp_printf.
-#
-# In MicroPython, we don't want to use the runtime library's printf but rather
-# go through mp_printf, so that stdout is properly tied into streams, etc.
-# This means that we either need to turn off _FORTIFY_SOURCE or provide our
-# own implementation of __printf_chk. We've chosen to turn off _FORTIFY_SOURCE.
-# It should also be noted that the use of printf in MicroPython is typically
-# quite limited anyways (primarily for debug and some error reporting, etc
-# in the unix version).
-#
-# Information about _FORTIFY_SOURCE seems to be rather scarce. The best I could
-# find was this: https://securityblog.redhat.com/2014/03/26/fortify-and-you/
-# Original patchset was introduced by
-# https://gcc.gnu.org/ml/gcc-patches/2004-09/msg02055.html .
-#
-# Turning off _FORTIFY_SOURCE is only required when compiling with -O1 or greater
-CFLAGS += -U _FORTIFY_SOURCE
-endif
-
-# On OSX, 'gcc' is a symlink to clang unless a real gcc is installed.
-# The unix port of MicroPython on OSX must be compiled with clang,
-# while cross-compile ports require gcc, so we test here for OSX and
-# if necessary override the value of 'CC' set in py/mkenv.mk
-ifeq ($(UNAME_S),Darwin)
-CC = clang
-# Use clang syntax for map file
-LDFLAGS_ARCH = -Wl,-map,$@.map
-else
-# Use gcc syntax for map file
-LDFLAGS_ARCH = -Wl,-Map=$@.map,--cref
-endif
-LDFLAGS = $(LDFLAGS_MOD) $(LDFLAGS_ARCH) -lm $(LDFLAGS_EXTRA)
-
-ifeq ($(MICROPY_FORCE_32BIT),1)
-# Note: you may need to install i386 versions of dependency packages,
-# starting with linux-libc-dev:i386
-ifeq ($(MICROPY_PY_FFI),1)
-ifeq ($(UNAME_S),Linux)
-CFLAGS_MOD += -I/usr/include/i686-linux-gnu
-endif
-endif
-endif
-
-ifeq ($(MICROPY_USE_READLINE),1)
-INC += -I$(MPTOP)/shared/readline
-CFLAGS_MOD += -DMICROPY_USE_READLINE=1
-SHARED_SRC_C_EXTRA += readline/readline.c
-endif
-ifeq ($(MICROPY_USE_READLINE),2)
-CFLAGS_MOD += -DMICROPY_USE_READLINE=2
-LDFLAGS_MOD += -lreadline
-# the following is needed for BSD
-#LDFLAGS_MOD += -ltermcap
-endif
-ifeq ($(MICROPY_PY_TIME),1)
-CFLAGS_MOD += -DMICROPY_PY_TIME=1
-SRC_MOD += modtime.c
-endif
-ifeq ($(MICROPY_PY_TERMIOS),1)
-CFLAGS_MOD += -DMICROPY_PY_TERMIOS=1
-SRC_MOD += modtermios.c
-endif
-ifeq ($(MICROPY_PY_SOCKET),1)
-CFLAGS_MOD += -DMICROPY_PY_SOCKET=1
-SRC_MOD += modsocket.c
-endif
-
-ifeq ($(MICROPY_PY_FFI),1)
-
-ifeq ($(MICROPY_STANDALONE),1)
-LIBFFI_CFLAGS_MOD := -I$(shell ls -1d $(MPTOP)/lib/libffi/build_dir/out/lib/libffi-*/include)
- ifeq ($(MICROPY_FORCE_32BIT),1)
- LIBFFI_LDFLAGS_MOD = $(MPTOP)/lib/libffi/build_dir/out/lib32/libffi.a
- else
- LIBFFI_LDFLAGS_MOD = $(MPTOP)/lib/libffi/build_dir/out/lib/libffi.a
- endif
-else
-LIBFFI_CFLAGS_MOD := $(shell pkg-config --cflags libffi)
-LIBFFI_LDFLAGS_MOD := $(shell pkg-config --libs libffi)
-endif
-
-ifeq ($(UNAME_S),Linux)
-LIBFFI_LDFLAGS_MOD += -ldl
-endif
-
-CFLAGS_MOD += $(LIBFFI_CFLAGS_MOD) -DMICROPY_PY_FFI=1
-LDFLAGS_MOD += $(LIBFFI_LDFLAGS_MOD)
-SRC_MOD += modffi.c
-endif
-
-MAIN_C = main.c
-
-# source files
-SRC_C = $(addprefix ports/unix/,\
- $(MAIN_C) \
- gccollect.c \
- unix_mphal.c \
- input.c \
- modmachine.c \
- moduselect.c \
- alloc.c \
- coverage.c \
- fatfs_port.c \
- $(SRC_MOD) \
- )
-
-SHARED_SRC_C = $(addprefix shared/,\
- libc/printf.c \
- runtime/gchelper_generic.c \
- timeutils/timeutils.c \
- $(SHARED_SRC_C_EXTRA) \
- )
-
-OBJ = $(PY_O)
-OBJ += $(addprefix $(BUILD)/, $(SRC_C:.c=.o))
-OBJ += $(addprefix $(BUILD)/, $(SHARED_SRC_C:.c=.o))
-
-# List of sources for qstr extraction
-SRC_QSTR += $(SRC_C) $(SHARED_SRC_C)
-# Append any auto-generated sources that are needed by sources listed in
-# SRC_QSTR
-SRC_QSTR_AUTO_DEPS +=
-
-include $(MPTOP)/py/mkrules.mk
-
-# Value of configure's --host= option (required for cross-compilation).
-# Deduce it from CROSS_COMPILE by default, but can be overridden.
-ifneq ($(CROSS_COMPILE),)
-CROSS_COMPILE_HOST = --host=$(patsubst %-,%,$(CROSS_COMPILE))
-else
-CROSS_COMPILE_HOST =
-endif
-
-deplibs: libffi axtls
-
-# install-exec-recursive & install-data-am targets are used to avoid building
-# docs and depending on makeinfo
-libffi:
- cd $(MPTOP)/lib/libffi; git clean -d -x -f
- cd $(MPTOP)/lib/libffi; ./autogen.sh
- mkdir -p $(MPTOP)/lib/libffi/build_dir; cd $(MPTOP)/lib/libffi/build_dir; \
- ../configure $(CROSS_COMPILE_HOST) --prefix=$$PWD/out CC="$(CC)" CXX="$(CXX)" LD="$(LD)"; \
- make install-exec-recursive; make -C include install-data-am
-
-axtls: $(MPTOP)/lib/axtls/README
- cd $(MPTOP)/lib/axtls; cp config/upyconfig config/.config
- cd $(MPTOP)/lib/axtls; make oldconfig -B
- cd $(MPTOP)/lib/axtls; make clean
- cd $(MPTOP)/lib/axtls; make all CC="$(CC)" LD="$(LD)"
-
-$(MPTOP)/lib/axtls/README:
- @echo "You cloned without --recursive, fetching submodules for you."
- (cd $(MPTOP); git submodule update --init --recursive)
diff --git a/examples/embedding/README.md b/examples/embedding/README.md
index 0dfc52e1dcad..e3683acdc22a 100644
--- a/examples/embedding/README.md
+++ b/examples/embedding/README.md
@@ -1,67 +1,37 @@
Example of embedding MicroPython in a standalone C application
==============================================================
-This directory contains a (very simple!) example of how to embed a MicroPython
-in an existing C application.
-
-A C application is represented by the file `hello-embed.c`. It executes a simple
-Python statement which prints to the standard output.
+This directory contains a simple example of how to embed MicroPython in an
+existing C application.
+A C application is represented here by the file `main.c`. It executes two
+simple Python scripts which print things to the standard output.
Building the example
--------------------
-Building the example is as simple as running:
-
- make
-
-It's worth to trace what's happening behind the scenes though:
-
-1. As a first step, a MicroPython library is built. This is handled by a
-separate makefile, `Makefile.upylib`. It is more or less complex, but the
-good news is that you won't need to change anything in it, just use it
-as is, the main `Makefile` shows how. What may require editing though is
-a MicroPython configuration file. MicroPython is highly configurable, so
-you would need to build a library suiting your application well, while
-not bloating its size. Check the options in the file `mpconfigport.h`.
-Included is a copy of the "minimal" Unix port, which should be a good start
-for minimal embedding. For the list of all available options, see
-`py/mpconfig.h`.
+First build the embed port using:
-2. Once the MicroPython library is built, your application is compiled
-and linked it. The main Makefile is very simple and shows that the changes
-you would need to do to your application's `Makefile` (or other build
-configuration) are also simple:
+ $ make -f micropython_embed.mk
-a) You would need to use C99 standard (you're using this 15+ years old
-standard already, not a 25+ years old one, right?).
+This will generate the `micropython_embed` directory which is a self-contained
+copy of MicroPython suitable for embedding. The .c files in this directory need
+to be compiled into your project, in whatever way your project can do that. The
+example here uses make and a provided `Makefile`.
-b) You need to provide a path to MicroPython's top-level dir, for includes.
+To build the example project, based on `main.c`, use:
-c) You need to include `-DNO_QSTR` compile-time flag.
+ $ make
-d) Otherwise, just link with the MicroPython library produced in step 1.
+That will create an exacutable called `embed` which you can run:
+ $ ./embed
Out of tree build
-----------------
This example is set up to work out of the box, being part of the MicroPython
-tree. Your application of course will be outside of its tree, but the
-only thing you need to do is to pass `MPTOP` variable pointing to
-MicroPython directory to both Makefiles (in this example, the main Makefile
-automatically passes it to `Makefile.upylib`; in your own Makefile, don't forget
-to use a suitable value).
-
-A practical way to embed MicroPython in your application is to include it
-as a git submodule. Suppose you included it as `libs/micropython`. Then in
-your main Makefile you would have something like:
-
-~~~
-MPTOP = libs/micropython
-
-my_app: $(MY_OBJS) -lmicropython
-
--lmicropython:
- $(MAKE) -f $(MPTOP)/examples/embedding/Makefile.upylib MPTOP=$(MPTOP)
-~~~
+tree. Your application will be outside of this tree, but the only thing you
+need to do for that is to change `MICROPYTHON_TOP` (found in `micropython_embed.mk`)
+to point to the location of the MicroPython repository. The MicroPython
+repository may, for example, be a git submodule in your project.
diff --git a/examples/embedding/main.c b/examples/embedding/main.c
new file mode 100644
index 000000000000..ee673fc93a68
--- /dev/null
+++ b/examples/embedding/main.c
@@ -0,0 +1,44 @@
+/* This file is part of the MicroPython project, http://micropython.org/
+ * The MIT License (MIT)
+ * Copyright (c) 2022-2023 Damien P. George
+ */
+
+#include "port/micropython_embed.h"
+
+// This is example 1 script, which will be compiled and executed.
+static const char *example_1 =
+ "print('hello world!', list(x + 1 for x in range(10)), end='eol\\n')";
+
+// This is example 2 script, which will be compiled and executed.
+static const char *example_2 =
+ "for i in range(10):\n"
+ " print('iter {:08}'.format(i))\n"
+ "\n"
+ "try:\n"
+ " 1//0\n"
+ "except Exception as er:\n"
+ " print('caught exception', repr(er))\n"
+ "\n"
+ "import gc\n"
+ "print('run GC collect')\n"
+ "gc.collect()\n"
+ "\n"
+ "print('finish')\n"
+ ;
+
+// This array is the MicroPython GC heap.
+static char heap[8 * 1024];
+
+int main() {
+ // Initialise MicroPython.
+ mp_embed_init(&heap[0], sizeof(heap));
+
+ // Run the example scripts (they will be compiled first).
+ mp_embed_exec_str(example_1);
+ mp_embed_exec_str(example_2);
+
+ // Deinitialise MicroPython.
+ mp_embed_deinit();
+
+ return 0;
+}
diff --git a/examples/embedding/micropython_embed.mk b/examples/embedding/micropython_embed.mk
new file mode 100644
index 000000000000..5db541592750
--- /dev/null
+++ b/examples/embedding/micropython_embed.mk
@@ -0,0 +1,9 @@
+# This file is part of the MicroPython project, http://micropython.org/
+# The MIT License (MIT)
+# Copyright (c) 2022-2023 Damien P. George
+
+# Set the location of the top of the MicroPython repository.
+MICROPYTHON_TOP = ../..
+
+# Include the main makefile fragment to build the MicroPython component.
+include $(MICROPYTHON_TOP)/ports/embed/embed.mk
diff --git a/examples/embedding/mpconfigport.h b/examples/embedding/mpconfigport.h
index 89c180b2a815..ed34a5d766ae 100644
--- a/examples/embedding/mpconfigport.h
+++ b/examples/embedding/mpconfigport.h
@@ -1 +1,15 @@
-#include "mpconfigport_minimal.h"
+/* This file is part of the MicroPython project, http://micropython.org/
+ * The MIT License (MIT)
+ * Copyright (c) 2022-2023 Damien P. George
+ */
+
+// Include common MicroPython embed configuration.
+#include
+
+// Use the minimal starting configuration (disables all optional features).
+#define MICROPY_CONFIG_ROM_LEVEL (MICROPY_CONFIG_ROM_LEVEL_MINIMUM)
+
+// MicroPython configuration.
+#define MICROPY_ENABLE_COMPILER (1)
+#define MICROPY_ENABLE_GC (1)
+#define MICROPY_PY_GC (1)
diff --git a/examples/embedding/mpconfigport_minimal.h b/examples/embedding/mpconfigport_minimal.h
deleted file mode 100644
index 6cc84dcbc1e4..000000000000
--- a/examples/embedding/mpconfigport_minimal.h
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * This file is part of the MicroPython project, http://micropython.org/
- *
- * The MIT License (MIT)
- *
- * Copyright (c) 2015 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.
- */
-
-// options to control how MicroPython is built
-
-#define MICROPY_ALLOC_PATH_MAX (PATH_MAX)
-#define MICROPY_ENABLE_GC (1)
-#define MICROPY_ENABLE_FINALISER (0)
-#define MICROPY_STACK_CHECK (0)
-#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)
-#define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_TERSE)
-#define MICROPY_WARNINGS (0)
-#define MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF (0)
-#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_NONE)
-#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_NONE)
-#define MICROPY_STREAMS_NON_BLOCK (0)
-#define MICROPY_OPT_COMPUTED_GOTO (0)
-#define MICROPY_CAN_OVERRIDE_BUILTINS (0)
-#define MICROPY_BUILTIN_METHOD_CHECK_SELF_ARG (0)
-#define MICROPY_CPYTHON_COMPAT (0)
-#define MICROPY_PY_BUILTINS_BYTEARRAY (0)
-#define MICROPY_PY_BUILTINS_MEMORYVIEW (0)
-#define MICROPY_PY_BUILTINS_COMPILE (0)
-#define MICROPY_PY_BUILTINS_ENUMERATE (0)
-#define MICROPY_PY_BUILTINS_FILTER (0)
-#define MICROPY_PY_BUILTINS_FROZENSET (0)
-#define MICROPY_PY_BUILTINS_REVERSED (0)
-#define MICROPY_PY_BUILTINS_SET (0)
-#define MICROPY_PY_BUILTINS_SLICE (0)
-#define MICROPY_PY_BUILTINS_STR_UNICODE (0)
-#define MICROPY_PY_BUILTINS_PROPERTY (0)
-#define MICROPY_PY_BUILTINS_MIN_MAX (0)
-#define MICROPY_PY___FILE__ (0)
-#define MICROPY_PY_MICROPYTHON_MEM_INFO (0)
-#define MICROPY_PY_GC (0)
-#define MICROPY_PY_GC_COLLECT_RETVAL (0)
-#define MICROPY_PY_ARRAY (0)
-#define MICROPY_PY_COLLECTIONS (0)
-#define MICROPY_PY_MATH (0)
-#define MICROPY_PY_CMATH (0)
-#define MICROPY_PY_IO (0)
-#define MICROPY_PY_IO_FILEIO (0)
-#define MICROPY_PY_STRUCT (0)
-#define MICROPY_PY_SYS (1)
-#define MICROPY_PY_SYS_EXIT (0)
-#define MICROPY_PY_SYS_PLATFORM "linux"
-#define MICROPY_PY_SYS_MAXSIZE (0)
-#define MICROPY_PY_SYS_PATH_DEFAULT ".frozen"
-#define MICROPY_PY_SYS_STDFILES (0)
-#define MICROPY_PY_CMATH (0)
-#define MICROPY_PY_UCTYPES (0)
-#define MICROPY_PY_UZLIB (0)
-#define MICROPY_PY_UJSON (0)
-#define MICROPY_PY_UOS (1)
-#define MICROPY_PY_URE (0)
-#define MICROPY_PY_UHEAPQ (0)
-#define MICROPY_PY_UHASHLIB (0)
-#define MICROPY_PY_UBINASCII (0)
-
-#define MICROPY_PORT_ROOT_POINTERS \
-
-//////////////////////////////////////////
-// Do not change anything beyond this line
-//////////////////////////////////////////
-
-#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
-
-#ifdef __LP64__
-typedef long mp_int_t; // must be pointer size
-typedef unsigned long mp_uint_t; // must be pointer size
-#else
-// These are definitions for machines where sizeof(int) == sizeof(void*),
-// regardless for actual size.
-typedef int mp_int_t; // must be pointer size
-typedef unsigned int mp_uint_t; // must be pointer size
-#endif
-
-// Cannot include , as it may lead to symbol name clashes
-#if _FILE_OFFSET_BITS == 64 && !defined(__LP64__)
-typedef long long mp_off_t;
-#else
-typedef long mp_off_t;
-#endif
-
-// We need to provide a declaration/definition of alloca()
-#ifdef __FreeBSD__
-#include
-#else
-#include
-#endif
diff --git a/examples/hwapi/README.md b/examples/hwapi/README.md
index 1992eb66094e..df16b4c86be5 100644
--- a/examples/hwapi/README.md
+++ b/examples/hwapi/README.md
@@ -116,7 +116,7 @@ For example, one may invent a "configuration manager" helper module which will
try to detect current board (among well-known ones), and load appropriate
`hwconfig_*.py` - this assumes that a user would lazily deploy them all
(or that application will be automatically installed, e.g. using MicroPython's
-`upip` package manager). The key point in this case remains the same as
+`mip` package manager). The key point in this case remains the same as
elaborated above - always assume there can, and will be a custom configuration,
and it should be well supported. So, any automatic detection should be
overridable by a user, and instructions how to do so are among the most
diff --git a/examples/natmod/btree/btree_c.c b/examples/natmod/btree/btree_c.c
index 5e8a34ac4009..c897f2e9a385 100644
--- a/examples/natmod/btree/btree_c.c
+++ b/examples/natmod/btree/btree_c.c
@@ -51,7 +51,7 @@ int *__errno (void)
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;
+ const mp_stream_p_t *stream_p = MP_OBJ_TYPE_GET_SLOT(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;
@@ -62,7 +62,7 @@ ssize_t mp_stream_posix_write(void *stream, const void *buf, size_t len) {
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;
+ const mp_stream_p_t *stream_p = MP_OBJ_TYPE_GET_SLOT(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;
@@ -73,7 +73,7 @@ ssize_t mp_stream_posix_read(void *stream, void *buf, size_t len) {
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;
+ const mp_stream_p_t *stream_p = MP_OBJ_TYPE_GET_SLOT(o->type, protocol);
struct mp_stream_seek_t seek_s;
seek_s.offset = offset;
seek_s.whence = whence;
@@ -86,7 +86,7 @@ off_t mp_stream_posix_lseek(void *stream, off_t offset, int whence) {
int mp_stream_posix_fsync(void *stream) {
mp_obj_base_t* o = stream;
- const mp_stream_p_t *stream_p = o->type->protocol;
+ const mp_stream_p_t *stream_p = MP_OBJ_TYPE_GET_SLOT(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;
@@ -94,7 +94,8 @@ int mp_stream_posix_fsync(void *stream) {
return res;
}
-mp_obj_type_t btree_type;
+mp_obj_full_type_t btree_type;
+mp_getiter_iternext_custom_t btree_getiter_iternext;
#include "extmod/modbtree.c"
@@ -122,13 +123,16 @@ 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_getiter_iternext.getiter = btree_getiter;
+ btree_getiter_iternext.iternext = btree_iternext;
+
btree_type.base.type = (void*)&mp_fun_table.type_type;
+ btree_type.flags = MP_TYPE_FLAG_ITER_IS_CUSTOM;
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;
+ MP_OBJ_TYPE_SET_SLOT(&btree_type, print, btree_print, 0);
+ MP_OBJ_TYPE_SET_SLOT(&btree_type, iter, &btree_getiter_iternext, 1);
+ MP_OBJ_TYPE_SET_SLOT(&btree_type, binary_op, btree_binary_op, 2);
+ MP_OBJ_TYPE_SET_SLOT(&btree_type, subscr, btree_subscr, 3);
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) };
@@ -137,7 +141,7 @@ mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *a
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_OBJ_TYPE_SET_SLOT(&btree_type, locals_dict, (void*)&btree_locals_dict, 4);
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));
diff --git a/examples/natmod/framebuf/framebuf.c b/examples/natmod/framebuf/framebuf.c
index 8d488cffd685..32b67eabcf84 100644
--- a/examples/natmod/framebuf/framebuf.c
+++ b/examples/natmod/framebuf/framebuf.c
@@ -8,11 +8,11 @@ void *memset(void *s, int c, size_t n) {
}
#endif
-mp_obj_type_t mp_type_framebuf;
+mp_obj_full_type_t mp_type_framebuf;
#include "extmod/modframebuf.c"
-mp_map_elem_t framebuf_locals_dict_table[10];
+mp_map_elem_t framebuf_locals_dict_table[11];
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) {
@@ -20,8 +20,8 @@ mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *a
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;
+ MP_OBJ_TYPE_SET_SLOT(&mp_type_framebuf, make_new, framebuf_make_new, 0);
+ MP_OBJ_TYPE_SET_SLOT(&mp_type_framebuf, buffer, framebuf_get_buffer, 1);
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) };
@@ -29,10 +29,11 @@ mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *a
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;
+ framebuf_locals_dict_table[7] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_ellipse), MP_OBJ_FROM_PTR(&framebuf_ellipse_obj) };
+ framebuf_locals_dict_table[8] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_blit), MP_OBJ_FROM_PTR(&framebuf_blit_obj) };
+ framebuf_locals_dict_table[9] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_scroll), MP_OBJ_FROM_PTR(&framebuf_scroll_obj) };
+ framebuf_locals_dict_table[10] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_text), MP_OBJ_FROM_PTR(&framebuf_text_obj) };
+ MP_OBJ_TYPE_SET_SLOT(&mp_type_framebuf, locals_dict, (void*)&framebuf_locals_dict, 2);
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));
diff --git a/examples/natmod/ure/ure.c b/examples/natmod/ure/ure.c
index 175b93e395ef..d4bd680abd42 100644
--- a/examples/natmod/ure/ure.c
+++ b/examples/natmod/ure/ure.c
@@ -32,8 +32,8 @@ 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;
+mp_obj_full_type_t match_type;
+mp_obj_full_type_t re_type;
#include "extmod/modure.c"
@@ -54,21 +54,21 @@ mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *a
match_type.base.type = (void*)&mp_fun_table.type_type;
match_type.name = MP_QSTR_match;
- match_type.print = match_print;
+ MP_OBJ_TYPE_SET_SLOT(&match_type, print, match_print, 0);
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;
+ MP_OBJ_TYPE_SET_SLOT(&match_type, locals_dict, (void*)&match_locals_dict, 1);
re_type.base.type = (void*)&mp_fun_table.type_type;
re_type.name = MP_QSTR_ure;
- re_type.print = re_print;
+ MP_OBJ_TYPE_SET_SLOT(&re_type, print, re_print, 0);
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_OBJ_TYPE_SET_SLOT(&re_type, locals_dict, (void*)&re_locals_dict, 1);
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));
diff --git a/examples/natmod/uzlib/uzlib.c b/examples/natmod/uzlib/uzlib.c
index 99b3691761ea..9cf58b10e78e 100644
--- a/examples/natmod/uzlib/uzlib.c
+++ b/examples/natmod/uzlib/uzlib.c
@@ -8,7 +8,7 @@ void *memset(void *s, int c, size_t n) {
}
#endif
-mp_obj_type_t decompio_type;
+mp_obj_full_type_t decompio_type;
#include "extmod/moduzlib.c"
@@ -20,12 +20,12 @@ mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *a
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;
+ MP_OBJ_TYPE_SET_SLOT(&decompio_type, make_new, &decompio_make_new, 0);
+ MP_OBJ_TYPE_SET_SLOT(&decompio_type, protocol, &decompio_stream_p, 1);
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_OBJ_TYPE_SET_SLOT(&decompio_type, locals_dict, (void*)&decompio_locals_dict, 2);
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));
diff --git a/examples/rp2/pio_1hz.py b/examples/rp2/pio_1hz.py
index c18aa22fc0ec..84d761fa1434 100644
--- a/examples/rp2/pio_1hz.py
+++ b/examples/rp2/pio_1hz.py
@@ -1,4 +1,5 @@
# Example using PIO to blink an LED and raise an IRQ at 1Hz.
+# Note: this does not work on Pico W because it uses Pin(25) for LED output.
import time
from machine import Pin
@@ -16,9 +17,10 @@ def blink_1hz():
nop() [29]
jmp(x_dec, "delay_high")
- # Cycles: 1 + 7 + 32 * (30 + 1) = 1000
+ # Cycles: 1 + 1 + 6 + 32 * (30 + 1) = 1000
+ nop()
set(pins, 0)
- set(x, 31) [6]
+ set(x, 31) [5]
label("delay_low")
nop() [29]
jmp(x_dec, "delay_low")
diff --git a/examples/rp2/pio_exec.py b/examples/rp2/pio_exec.py
index d8cbc33ef015..ce39f2df8430 100644
--- a/examples/rp2/pio_exec.py
+++ b/examples/rp2/pio_exec.py
@@ -1,4 +1,5 @@
# Example using PIO to turn on an LED via an explicit exec.
+# Note: this does not work on Pico W because it uses Pin(25) for LED output.
#
# Demonstrates:
# - using set_init and set_base
@@ -8,6 +9,7 @@
from machine import Pin
import rp2
+
# Define an empty program that uses a single set pin.
@rp2.asm_pio(set_init=rp2.PIO.OUT_LOW)
def prog():
diff --git a/examples/rp2/pio_uart_tx.py b/examples/rp2/pio_uart_tx.py
index 0f8c1260bd7d..5e4af8f6ccfd 100644
--- a/examples/rp2/pio_uart_tx.py
+++ b/examples/rp2/pio_uart_tx.py
@@ -33,6 +33,7 @@ def uart_tx():
sm.active(1)
uarts.append(sm)
+
# We can print characters from each UART by pushing them to the TX FIFO
def pio_uart_print(sm, s):
for c in s:
diff --git a/examples/rp2/pwm_fade.py b/examples/rp2/pwm_fade.py
index 7264edaa293a..5b7089c6b1ad 100644
--- a/examples/rp2/pwm_fade.py
+++ b/examples/rp2/pwm_fade.py
@@ -1,4 +1,5 @@
# Example using PWM to fade an LED.
+# Note: this does not work on Pico W because it uses Pin(25) for LED output.
import time
from machine import Pin, PWM
diff --git a/examples/usercmodule/cexample/examplemodule.c b/examples/usercmodule/cexample/examplemodule.c
index 93a58be2ed28..ccce03bcbdcf 100644
--- a/examples/usercmodule/cexample/examplemodule.c
+++ b/examples/usercmodule/cexample/examplemodule.c
@@ -1,6 +1,9 @@
// Include MicroPython API.
#include "py/runtime.h"
+// Used to get the time in the Timer class example.
+#include "py/mphal.h"
+
// This is the function which will be called from Python as cexample.add_ints(a, b).
STATIC mp_obj_t example_add_ints(mp_obj_t a_obj, mp_obj_t b_obj) {
// Extract the ints from the micropython input objects.
@@ -13,6 +16,58 @@ STATIC mp_obj_t example_add_ints(mp_obj_t a_obj, mp_obj_t b_obj) {
// Define a Python reference to the function above.
STATIC MP_DEFINE_CONST_FUN_OBJ_2(example_add_ints_obj, example_add_ints);
+// This structure represents Timer instance objects.
+typedef struct _example_Timer_obj_t {
+ // All objects start with the base.
+ mp_obj_base_t base;
+ // Everything below can be thought of as instance attributes, but they
+ // cannot be accessed by MicroPython code directly. In this example we
+ // store the time at which the object was created.
+ mp_uint_t start_time;
+} example_Timer_obj_t;
+
+// This is the Timer.time() method. After creating a Timer object, this
+// can be called to get the time elapsed since creating the Timer.
+STATIC mp_obj_t example_Timer_time(mp_obj_t self_in) {
+ // The first argument is self. It is cast to the *example_Timer_obj_t
+ // type so we can read its attributes.
+ example_Timer_obj_t *self = MP_OBJ_TO_PTR(self_in);
+
+ // Get the elapsed time and return it as a MicroPython integer.
+ mp_uint_t elapsed = mp_hal_ticks_ms() - self->start_time;
+ return mp_obj_new_int_from_uint(elapsed);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(example_Timer_time_obj, example_Timer_time);
+
+// This represents Timer.__new__ and Timer.__init__, which is called when
+// the user instantiates a Timer object.
+STATIC mp_obj_t example_Timer_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
+ // Allocates the new object and sets the type.
+ example_Timer_obj_t *self = mp_obj_malloc(example_Timer_obj_t, type);
+
+ // Initializes the time for this Timer instance.
+ self->start_time = mp_hal_ticks_ms();
+
+ // The make_new function always returns self.
+ return MP_OBJ_FROM_PTR(self);
+}
+
+// This collects all methods and other static class attributes of the Timer.
+// The table structure is similar to the module table, as detailed below.
+STATIC const mp_rom_map_elem_t example_Timer_locals_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_time), MP_ROM_PTR(&example_Timer_time_obj) },
+};
+STATIC MP_DEFINE_CONST_DICT(example_Timer_locals_dict, example_Timer_locals_dict_table);
+
+// This defines the type(Timer) object.
+MP_DEFINE_CONST_OBJ_TYPE(
+ example_type_Timer,
+ MP_QSTR_Timer,
+ MP_TYPE_FLAG_NONE,
+ make_new, example_Timer_make_new,
+ locals_dict, &example_Timer_locals_dict
+ );
+
// Define all properties of the module.
// Table entries are key/value pairs of the attribute name (a string)
// and the MicroPython object reference.
@@ -21,6 +76,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(example_add_ints_obj, example_add_ints);
STATIC const mp_rom_map_elem_t example_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_cexample) },
{ MP_ROM_QSTR(MP_QSTR_add_ints), MP_ROM_PTR(&example_add_ints_obj) },
+ { MP_ROM_QSTR(MP_QSTR_Timer), MP_ROM_PTR(&example_type_Timer) },
};
STATIC MP_DEFINE_CONST_DICT(example_module_globals, example_module_globals_table);
diff --git a/extmod/axtls-include/axtls_os_port.h b/extmod/axtls-include/axtls_os_port.h
index ef2683acfc70..057642f9741b 100644
--- a/extmod/axtls-include/axtls_os_port.h
+++ b/extmod/axtls-include/axtls_os_port.h
@@ -26,7 +26,11 @@
#ifndef AXTLS_OS_PORT_H
#define AXTLS_OS_PORT_H
+#ifndef __ets__
+#include
+#endif
#include
+#include
#include "py/stream.h"
#include "lib/crypto-algorithms/sha256.h"
diff --git a/extmod/btstack/btstack.mk b/extmod/btstack/btstack.mk
index 7ecc23000317..281d032ae110 100644
--- a/extmod/btstack/btstack.mk
+++ b/extmod/btstack/btstack.mk
@@ -2,17 +2,22 @@
ifeq ($(MICROPY_BLUETOOTH_BTSTACK),1)
+GIT_SUBMODULES += lib/btstack
+
MICROPY_BLUETOOTH_BTSTACK_USB ?= 0
+MICROPY_BLUETOOTH_BTSTACK_H4 ?= 1
+MICROPY_BLUETOOTH_BTSTACK_CONFIG_FILE ?= '"extmod/btstack/btstack_config_common.h"'
BTSTACK_EXTMOD_DIR = extmod/btstack
-EXTMOD_SRC_C += extmod/btstack/modbluetooth_btstack.c
+SRC_EXTMOD_C += $(BTSTACK_EXTMOD_DIR)/modbluetooth_btstack.c
INC += -I$(TOP)/$(BTSTACK_EXTMOD_DIR)
-CFLAGS_MOD += -DMICROPY_BLUETOOTH_BTSTACK=1
-CFLAGS_MOD += -DMICROPY_PY_BLUETOOTH_USE_SYNC_EVENTS=1
-CFLAGS_MOD += -DMICROPY_PY_BLUETOOTH_ENABLE_PAIRING_BONDING=1
+CFLAGS_EXTMOD += -DMICROPY_BLUETOOTH_BTSTACK=1
+CFLAGS_EXTMOD += -DMICROPY_BLUETOOTH_BTSTACK_CONFIG_FILE=$(MICROPY_BLUETOOTH_BTSTACK_CONFIG_FILE)
+CFLAGS_EXTMOD += -DMICROPY_PY_BLUETOOTH_USE_SYNC_EVENTS=1
+CFLAGS_EXTMOD += -DMICROPY_PY_BLUETOOTH_ENABLE_PAIRING_BONDING=1
BTSTACK_DIR = $(TOP)/lib/btstack
@@ -27,44 +32,51 @@ 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 = \
+SRC_BTSTACK_C = \
$(addprefix lib/btstack/src/, $(SRC_FILES)) \
$(addprefix lib/btstack/src/ble/, $(filter-out %_tlv.c, $(SRC_BLE_FILES))) \
+ lib/btstack/platform/embedded/hci_dump_embedded_stdout.c \
ifeq ($(MICROPY_BLUETOOTH_BTSTACK_USB),1)
ifeq ($(MICROPY_BLUETOOTH_BTSTACK_H4),1)
- $(error Cannot specifiy both MICROPY_BLUETOOTH_BTSTACK_USB and MICROPY_BLUETOOTH_BTSTACK_H4)
+ $(error Cannot enable both MICROPY_BLUETOOTH_BTSTACK_USB and MICROPY_BLUETOOTH_BTSTACK_H4)
+endif
+endif
+
+ifneq ($(MICROPY_BLUETOOTH_BTSTACK_USB),1)
+ifneq ($(MICROPY_BLUETOOTH_BTSTACK_H4),1)
+ $(error Must enable one of MICROPY_BLUETOOTH_BTSTACK_USB or MICROPY_BLUETOOTH_BTSTACK_H4)
endif
endif
ifeq ($(MICROPY_BLUETOOTH_BTSTACK_USB),1)
-SRC_BTSTACK += \
+SRC_BTSTACK_C += \
lib/btstack/platform/libusb/hci_transport_h2_libusb.c
-CFLAGS_MOD += -DMICROPY_BLUETOOTH_BTSTACK_USB=1
+CFLAGS_EXTMOD += -DMICROPY_BLUETOOTH_BTSTACK_USB=1
-CFLAGS += $(shell pkg-config libusb-1.0 --cflags)
-LDFLAGS += $(shell pkg-config libusb-1.0 --libs)
+CFLAGS_THIRDPARTY += $(shell pkg-config libusb-1.0 --cflags)
+LDFLAGS_THIRDPARTY += $(shell pkg-config libusb-1.0 --libs)
endif
ifeq ($(MICROPY_BLUETOOTH_BTSTACK_H4),1)
-SRC_BTSTACK += \
+SRC_BTSTACK_C += \
lib/btstack/src/hci_transport_h4.c \
lib/btstack/chipset/zephyr/btstack_chipset_zephyr.c
-EXTMOD_SRC_C += \
+SRC_BTSTACK_C += \
extmod/btstack/btstack_hci_uart.c \
-CFLAGS_MOD += -DMICROPY_BLUETOOTH_BTSTACK_H4=1
+CFLAGS_EXTMOD += -DMICROPY_BLUETOOTH_BTSTACK_H4=1
endif
ifeq ($(MICROPY_BLUETOOTH_BTSTACK_ENABLE_CLASSIC),1)
include $(BTSTACK_DIR)/src/classic/Makefile.inc
-SRC_BTSTACK += \
+SRC_BTSTACK_C += \
$(addprefix lib/btstack/src/classic/, $(SRC_CLASSIC_FILES))
endif
-LIB_SRC_C += $(SRC_BTSTACK)
+SRC_THIRDPARTY_C += $(SRC_BTSTACK_C)
# Suppress some warnings.
BTSTACK_WARNING_CFLAGS = -Wno-old-style-definition -Wno-unused-variable -Wno-unused-parameter -Wno-implicit-fallthrough
diff --git a/extmod/btstack/btstack_config.h b/extmod/btstack/btstack_config.h
index e56a84f94a16..84f0dab2bdb4 100644
--- a/extmod/btstack/btstack_config.h
+++ b/extmod/btstack/btstack_config.h
@@ -1,48 +1,6 @@
#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_DEBUG
-#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
+#include MICROPY_BLUETOOTH_BTSTACK_CONFIG_FILE
#endif // MICROPY_INCLUDED_EXTMOD_BTSTACK_BTSTACK_CONFIG_H
diff --git a/extmod/btstack/btstack_config_common.h b/extmod/btstack/btstack_config_common.h
new file mode 100644
index 000000000000..0f616f7505e6
--- /dev/null
+++ b/extmod/btstack/btstack_config_common.h
@@ -0,0 +1,49 @@
+#ifndef MICROPY_INCLUDED_EXTMOD_BTSTACK_BTSTACK_CONFIG_COMMON_H
+#define MICROPY_INCLUDED_EXTMOD_BTSTACK_BTSTACK_CONFIG_COMMON_H
+
+// BTstack features that can be enabled
+#define ENABLE_BLE
+#define ENABLE_LE_PERIPHERAL
+#define ENABLE_LE_CENTRAL
+// #define ENABLE_CLASSIC
+#define ENABLE_L2CAP_LE_CREDIT_BASED_FLOW_CONTROL_MODE
+#define ENABLE_PRINTF_HEXDUMP
+// #define ENABLE_LOG_INFO
+// #define ENABLE_LOG_DEBUG
+#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_COMMON_H
diff --git a/extmod/btstack/btstack_hci_uart.c b/extmod/btstack/btstack_hci_uart.c
index 83e865b71d2d..f945efc762cb 100644
--- a/extmod/btstack/btstack_hci_uart.c
+++ b/extmod/btstack/btstack_hci_uart.c
@@ -159,6 +159,12 @@ const btstack_uart_block_t mp_bluetooth_btstack_hci_uart_block = {
&btstack_uart_get_supported_sleep_modes,
&btstack_uart_set_sleep,
&btstack_uart_set_wakeup_handler,
+
+ // The following are needed for H5 mode only.
+ NULL, // set_frame_received
+ NULL, // set_frame_sent,
+ NULL, // receive_frame,
+ NULL, // send_frame,
};
void mp_bluetooth_btstack_hci_uart_process(void) {
diff --git a/extmod/btstack/btstack_hci_uart.h b/extmod/btstack/btstack_hci_uart.h
index 8011e587dee3..74983808ec28 100644
--- a/extmod/btstack/btstack_hci_uart.h
+++ b/extmod/btstack/btstack_hci_uart.h
@@ -28,7 +28,7 @@
#ifndef MICROPY_INCLUDED_EXTMOD_BTSTACK_HCI_UART_H
#define MICROPY_INCLUDED_EXTMOD_BTSTACK_HCI_UART_H
-#include "lib/btstack/src/btstack.h"
+#include "lib/btstack/src/btstack_uart_block.h"
// --- Used by the port to create the HCI transport ---------------------------
extern const btstack_uart_block_t mp_bluetooth_btstack_hci_uart_block;
diff --git a/extmod/btstack/modbluetooth_btstack.c b/extmod/btstack/modbluetooth_btstack.c
index e56e488b1c28..0e29c38efde4 100644
--- a/extmod/btstack/modbluetooth_btstack.c
+++ b/extmod/btstack/modbluetooth_btstack.c
@@ -93,156 +93,57 @@ STATIC mp_obj_bluetooth_uuid_t create_mp_uuid(uint16_t uuid16, const uint8_t *uu
}
#endif // MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE
-// 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 {
+#if MICROPY_PY_BLUETOOTH_ENABLE_GATT_CLIENT
+typedef struct _mp_btstack_active_connection_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_printf("btstack_notify_indicate_ready_handler op_type=%d conn_handle=%d value_handle=%d len=%zu\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_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_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_printf("btstack_enqueue_pending_operation op_type=%d conn_handle=%d value_handle=%d len=%zu\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);
+ // Read/write.
+ uint16_t pending_value_handle;
+
+ // Write only. Buffer must be retained until the operation completes.
+ uint8_t *pending_write_value;
+ size_t pending_write_value_len;
+} mp_btstack_active_connection_t;
+
+STATIC mp_btstack_active_connection_t *create_active_connection(uint16_t conn_handle) {
+ DEBUG_printf("create_active_connection: conn_handle=%d\n", conn_handle);
+ mp_btstack_active_connection_t *conn = m_new(mp_btstack_active_connection_t, 1);
+ conn->conn_handle = conn_handle;
+ conn->pending_value_handle = 0xffff;
+ conn->pending_write_value = NULL;
+ conn->pending_write_value_len = 0;
+ bool added = btstack_linked_list_add(&MP_STATE_PORT(bluetooth_btstack_root_pointers)->active_connections, (btstack_linked_item_t *)conn);
(void)added;
- MICROPY_PY_BLUETOOTH_EXIT
-
- return pending_op;
+ assert(added);
+ return conn;
}
-#if MICROPY_PY_BLUETOOTH_ENABLE_GATT_CLIENT
-
-// 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_printf("btstack_finish_pending_operation op_type=%d conn_handle=%d value_handle=%d\n", op_type, conn_handle, value_handle);
+STATIC mp_btstack_active_connection_t *find_active_connection(uint16_t conn_handle) {
+ DEBUG_printf("find_active_connection: conn_handle=%d\n", conn_handle);
btstack_linked_list_iterator_t it;
- btstack_linked_list_iterator_init(&it, &MP_STATE_PORT(bluetooth_btstack_root_pointers)->pending_ops);
+ btstack_linked_list_iterator_init(&it, &MP_STATE_PORT(bluetooth_btstack_root_pointers)->active_connections);
+ mp_btstack_active_connection_t *conn = NULL;
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_printf("btstack_finish_pending_operation: found value_handle=%d len=%zu\n", pending_op->value_handle, pending_op->len);
- btstack_remove_pending_operation(pending_op, del);
- MICROPY_PY_BLUETOOTH_EXIT
- return del ? NULL : pending_op;
+ conn = (mp_btstack_active_connection_t *)btstack_linked_list_iterator_next(&it);
+ DEBUG_printf(" --> iter conn %d\n", conn->conn_handle);
+ if (conn->conn_handle == conn_handle) {
+ break;
}
}
- DEBUG_printf("btstack_finish_pending_operation: not found\n");
- MICROPY_PY_BLUETOOTH_EXIT
- return NULL;
+ return conn;
+}
+
+STATIC void remove_active_connection(uint16_t conn_handle) {
+ DEBUG_printf("remove_active_connection: conn_handle=%d\n", conn_handle);
+ mp_btstack_active_connection_t *conn = find_active_connection(conn_handle);
+ if (conn) {
+ bool removed = btstack_linked_list_remove(&MP_STATE_PORT(bluetooth_btstack_root_pointers)->active_connections, (btstack_linked_item_t *)conn);
+ (void)removed;
+ assert(removed);
+ m_del(mp_btstack_active_connection_t, conn, 1);
+ }
}
#endif
@@ -271,12 +172,14 @@ STATIC void btstack_packet_handler_att_server(uint8_t packet_type, uint16_t chan
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 == ATT_EVENT_MTU_EXCHANGE_COMPLETE) {
+ DEBUG_printf(" --> att mtu exchange complete\n");
// This is triggered in peripheral mode, when exchange initiated by us or remote.
uint16_t conn_handle = att_event_mtu_exchange_complete_get_handle(packet);
uint16_t mtu = att_event_mtu_exchange_complete_get_MTU(packet);
mp_bluetooth_gatts_on_mtu_exchanged(conn_handle, mtu);
} else if (event_type == HCI_EVENT_LE_META || event_type == HCI_EVENT_DISCONNECTION_COMPLETE) {
// Ignore, duplicated by att_server.c.
+ DEBUG_printf(" --> hci att server event type: le_meta/disconnection (0x%02x)\n", event_type);
} else {
DEBUG_printf(" --> hci att server event type: unknown (0x%02x)\n", event_type);
}
@@ -290,8 +193,10 @@ STATIC bool controller_static_addr_available = false;
STATIC const uint8_t read_static_address_command_complete_prefix[] = { 0x0e, 0x1b, 0x01, 0x09, 0xfc };
#endif
-STATIC void btstack_packet_handler(uint8_t packet_type, uint8_t *packet, uint8_t irq) {
- DEBUG_printf("btstack_packet_handler(packet_type=%u, packet=%p)\n", packet_type, packet);
+STATIC void btstack_packet_handler_generic(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size) {
+ (void)channel;
+ (void)size;
+ DEBUG_printf("btstack_packet_handler_generic(packet_type=%u, packet=%p)\n", packet_type, packet);
if (packet_type != HCI_EVENT_PACKET) {
return;
}
@@ -314,6 +219,9 @@ STATIC void btstack_packet_handler(uint8_t packet_type, uint8_t *packet, uint8_t
// Slave role.
irq_event = MP_BLUETOOTH_IRQ_CENTRAL_CONNECT;
}
+ #if MICROPY_PY_BLUETOOTH_ENABLE_GATT_CLIENT
+ create_active_connection(conn_handle);
+ #endif
mp_bluetooth_gap_on_connected_disconnected(irq_event, conn_handle, addr_type, addr);
break;
}
@@ -368,7 +276,7 @@ STATIC void btstack_packet_handler(uint8_t packet_type, uint8_t *packet, uint8_t
event_type == SM_EVENT_PAIRING_COMPLETE ||
// event_type == GAP_EVENT_DEDICATED_BONDING_COMPLETED || // No conn_handle
event_type == HCI_EVENT_ENCRYPTION_CHANGE) {
- DEBUG_printf(" --> enc/auth/pair/bond change\n", );
+ DEBUG_printf(" --> enc/auth/pair/bond change\n");
#if MICROPY_PY_BLUETOOTH_ENABLE_PAIRING_BONDING
uint16_t conn_handle;
switch (event_type) {
@@ -407,6 +315,9 @@ STATIC void btstack_packet_handler(uint8_t packet_type, uint8_t *packet, uint8_t
}
uint8_t addr[6] = {0};
mp_bluetooth_gap_on_connected_disconnected(irq_event, conn_handle, 0xff, addr);
+ #if MICROPY_PY_BLUETOOTH_ENABLE_GATT_CLIENT
+ remove_active_connection(conn_handle);
+ #endif
#if MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE
} else if (event_type == GAP_EVENT_ADVERTISING_REPORT) {
DEBUG_printf(" --> gap advertising report\n");
@@ -420,51 +331,12 @@ STATIC void btstack_packet_handler(uint8_t packet_type, uint8_t *packet, uint8_t
mp_bluetooth_gap_on_scan_result(address_type, address, adv_event_type, rssi, data, length);
#endif // MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE
#if MICROPY_PY_BLUETOOTH_ENABLE_GATT_CLIENT
- } 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_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_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_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_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_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_bluetooth_gattc_on_data_available(MP_BLUETOOTH_IRQ_GATTC_READ_RESULT, conn_handle, value_handle, &data, &len, 1);
+ } else if (event_type == GATT_EVENT_MTU) {
+ // This is triggered in central mode.
+ DEBUG_printf(" --> gatt event mtu\n");
+ uint16_t conn_handle = gatt_event_mtu_get_handle(packet);
+ uint16_t mtu = gatt_event_mtu_get_MTU(packet);
+ mp_bluetooth_gatts_on_mtu_exchanged(conn_handle, mtu);
} else if (event_type == GATT_EVENT_NOTIFICATION) {
DEBUG_printf(" --> gatt notification\n");
uint16_t conn_handle = gatt_event_notification_get_handle(packet);
@@ -482,28 +354,24 @@ STATIC void btstack_packet_handler(uint8_t packet_type, uint8_t *packet, uint8_t
} else if (event_type == GATT_EVENT_CAN_WRITE_WITHOUT_RESPONSE) {
uint16_t conn_handle = gatt_event_can_write_without_response_get_handle(packet);
DEBUG_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_printf(" --> ready for value_handle=%d len=%zu\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.
+ mp_btstack_active_connection_t *conn = find_active_connection(conn_handle);
+ if (!conn || conn->pending_value_handle == 0xffff || !conn->pending_write_value) {
+ return;
}
-
+ DEBUG_printf(" --> ready for value_handle=%d len=%lu\n", conn->pending_value_handle, conn->pending_write_value_len);
+ int err = gatt_client_write_value_of_characteristic_without_response(conn_handle, conn->pending_value_handle, conn->pending_write_value_len, conn->pending_write_value);
+ (void)err;
+ assert(err == ERROR_CODE_SUCCESS);
+ conn->pending_value_handle = 0xffff;
+ m_del(uint8_t, conn->pending_write_value, conn->pending_write_value_len);
+ conn->pending_write_value = NULL;
+ conn->pending_write_value_len = 0;
#endif // MICROPY_PY_BLUETOOTH_ENABLE_GATT_CLIENT
} else {
DEBUG_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
};
@@ -513,35 +381,121 @@ STATIC btstack_packet_callback_registration_t hci_event_callback_registration =
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);
+ if (packet_type != HCI_EVENT_PACKET) {
+ return;
+ }
+ uint8_t event_type = hci_event_packet_get_type(packet);
+ if (event_type == GATT_EVENT_SERVICE_QUERY_RESULT) {
+ DEBUG_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_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_printf(" --> gatt query services complete conn_handle=%d status=%d\n", conn_handle, status);
+ mp_bluetooth_gattc_on_discover_complete(MP_BLUETOOTH_IRQ_GATTC_SERVICE_DONE, conn_handle, status);
+ }
}
// 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);
+ if (packet_type != HCI_EVENT_PACKET) {
+ return;
+ }
+ uint8_t event_type = hci_event_packet_get_type(packet);
+ if (event_type == GATT_EVENT_CHARACTERISTIC_QUERY_RESULT) {
+ DEBUG_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.value_handle, characteristic.end_handle, characteristic.properties, &characteristic_uuid);
+ } 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_printf(" --> gatt query characteristics complete conn_handle=%d status=%d\n", conn_handle, status);
+ mp_bluetooth_gattc_on_discover_complete(MP_BLUETOOTH_IRQ_GATTC_CHARACTERISTIC_DONE, conn_handle, status);
+ }
}
// 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);
+ if (packet_type != HCI_EVENT_PACKET) {
+ return;
+ }
+ uint8_t event_type = hci_event_packet_get_type(packet);
+ if (event_type == GATT_EVENT_ALL_CHARACTERISTIC_DESCRIPTORS_QUERY_RESULT) {
+ DEBUG_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_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_printf(" --> gatt query descriptors complete conn_handle=%d status=%d\n", conn_handle, status);
+ mp_bluetooth_gattc_on_discover_complete(MP_BLUETOOTH_IRQ_GATTC_DESCRIPTOR_DONE, conn_handle, status);
+ }
}
// 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);
+ if (packet_type != HCI_EVENT_PACKET) {
+ return;
+ }
+ uint8_t event_type = hci_event_packet_get_type(packet);
+ 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_printf(" --> gatt query read complete conn_handle=%d status=%d\n", conn_handle, status);
+ mp_btstack_active_connection_t *conn = find_active_connection(conn_handle);
+ if (!conn) {
+ return;
+ }
+ mp_bluetooth_gattc_on_read_write_status(MP_BLUETOOTH_IRQ_GATTC_READ_DONE, conn_handle, conn->pending_value_handle, status);
+ conn->pending_value_handle = 0xffff;
+ } else if (event_type == GATT_EVENT_CHARACTERISTIC_VALUE_QUERY_RESULT) {
+ DEBUG_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_bluetooth_gattc_on_data_available(MP_BLUETOOTH_IRQ_GATTC_READ_RESULT, conn_handle, value_handle, &data, &len, 1);
+ }
}
// 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);
+ if (packet_type != HCI_EVENT_PACKET) {
+ return;
+ }
+ uint8_t event_type = hci_event_packet_get_type(packet);
+ 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_printf(" --> gatt query write complete conn_handle=%d status=%d\n", conn_handle, status);
+ mp_btstack_active_connection_t *conn = find_active_connection(conn_handle);
+ if (!conn) {
+ return;
+ }
+ mp_bluetooth_gattc_on_read_write_status(MP_BLUETOOTH_IRQ_GATTC_WRITE_DONE, conn_handle, conn->pending_value_handle, status);
+ conn->pending_value_handle = 0xffff;
+ m_del(uint8_t, conn->pending_write_value, conn->pending_write_value_len);
+ conn->pending_write_value = NULL;
+ conn->pending_write_value_len = 0;
+ }
}
#endif // MICROPY_PY_BLUETOOTH_ENABLE_GATT_CLIENT
@@ -625,6 +579,19 @@ STATIC void set_random_address(void) {
DEBUG_printf("set_random_address: Address loaded by controller\n");
}
+STATIC void deinit_stack(void) {
+ mp_bluetooth_btstack_state = MP_BLUETOOTH_BTSTACK_STATE_OFF;
+
+ // Deinitialise BTstack components.
+ sm_deinit();
+ l2cap_deinit();
+ hci_deinit();
+ btstack_memory_deinit();
+ btstack_run_loop_deinit();
+
+ MP_STATE_PORT(bluetooth_btstack_root_pointers) = NULL;
+}
+
int mp_bluetooth_init(void) {
DEBUG_printf("mp_bluetooth_init\n");
@@ -702,8 +669,8 @@ int mp_bluetooth_init(void) {
// Attempt a shutdown (may not do anything).
mp_bluetooth_btstack_port_deinit();
- // Clean up.
- MP_STATE_PORT(bluetooth_btstack_root_pointers) = NULL;
+ // Clean up BTstack.
+ deinit_stack();
return timeout ? MP_ETIMEDOUT : MP_EINVAL;
}
@@ -726,6 +693,13 @@ int mp_bluetooth_init(void) {
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 // MICROPY_PY_BLUETOOTH_ENABLE_GATT_CLIENT
+ // Always include at least the standard GAP and GATT default services. A
+ // peripheral (likely a server) will almost always override this with its
+ // own services, but a central should get the default services, e.g. so
+ // the remote end can find out its GAP name.
+ mp_bluetooth_gatts_register_service_begin(false);
+ mp_bluetooth_gatts_register_service_end();
+
return 0;
}
@@ -757,8 +731,8 @@ void mp_bluetooth_deinit(void) {
}
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;
+ // Clean up BTstack.
+ deinit_stack();
DEBUG_printf("mp_bluetooth_deinit: complete\n");
}
@@ -836,7 +810,7 @@ void mp_bluetooth_set_io_capability(uint8_t capability) {
#endif // MICROPY_PY_BLUETOOTH_ENABLE_PAIRING_BONDING
size_t mp_bluetooth_gap_get_device_name(const uint8_t **buf) {
- uint8_t *value = NULL;
+ const 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;
@@ -915,8 +889,8 @@ int mp_bluetooth_gatts_register_service_begin(bool append) {
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;
+ assert(handle == BTSTACK_GAP_DEVICE_NAME_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);
@@ -968,7 +942,11 @@ STATIC int att_write_callback(hci_con_handle_t connection_handle, uint16_t att_h
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);
+ uint16_t handle_uuid = att_uuid_for_handle(att_handle);
+ if (handle_uuid != GATT_CLIENT_CHARACTERISTICS_CONFIGURATION) {
+ // Suppress the Python callback for writes to the CCCD.
+ mp_bluetooth_gatts_on_write(connection_handle, att_handle);
+ }
return 0;
}
@@ -1020,7 +998,7 @@ int mp_bluetooth_gatts_register_service(mp_obj_bluetooth_uuid_t *service_uuid, m
size_t handle_index = 0;
size_t descriptor_index = 0;
- static uint8_t cccb_buf[2] = {0};
+ static uint8_t cccd_buf[2] = {0};
for (size_t i = 0; i < num_characteristics; ++i) {
uint16_t props = (characteristic_flags[i] & 0x7f) | ATT_PROPERTY_DYNAMIC;
@@ -1036,11 +1014,11 @@ int mp_bluetooth_gatts_register_service(mp_obj_bluetooth_uuid_t *service_uuid, m
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 a NOTIFY or INDICATE characteristic is added, then we need to manage a value for the CCCD.
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));
+ // btstack automatically creates the CCCD as the next handle if the notify or indicate properties are set.
+ mp_bluetooth_gatts_db_create_entry(MP_STATE_PORT(bluetooth_btstack_root_pointers)->gatts_db, handles[handle_index] + 1, MP_BLUETOOTH_CCCD_LEN);
+ int ret = mp_bluetooth_gatts_db_write(MP_STATE_PORT(bluetooth_btstack_root_pointers)->gatts_db, handles[handle_index] + 1, cccd_buf, sizeof(cccd_buf));
if (ret) {
return ret;
}
@@ -1077,7 +1055,7 @@ int mp_bluetooth_gatts_register_service_end(void) {
return 0;
}
-int mp_bluetooth_gatts_read(uint16_t value_handle, uint8_t **value, size_t *value_len) {
+int mp_bluetooth_gatts_read(uint16_t value_handle, const uint8_t **value, size_t *value_len) {
DEBUG_printf("mp_bluetooth_gatts_read\n");
if (!mp_bluetooth_is_active()) {
return ERRNO_BLUETOOTH_NOT_ACTIVE;
@@ -1091,90 +1069,152 @@ int mp_bluetooth_gatts_write(uint16_t value_handle, const uint8_t *value, size_t
return ERRNO_BLUETOOTH_NOT_ACTIVE;
}
if (send_update) {
- return MP_EOPNOTSUPP;
+ DEBUG_printf(" --> send_update\n");
+ // If a characteristic has notify or indicate set, then btstack automatically creates the CCCD as the next handle.
+ // So if the next handle is a CCCD, then this characteristic must have had notify/indicate set.
+ uint16_t next_handle_uuid = att_uuid_for_handle(value_handle + 1);
+ if (next_handle_uuid != GATT_CLIENT_CHARACTERISTICS_CONFIGURATION) {
+ return MP_EINVAL;
+ }
+ DEBUG_printf(" --> got handle for cccd: %d\n", value_handle + 1);
+ }
+ int err = mp_bluetooth_gatts_db_write(MP_STATE_PORT(bluetooth_btstack_root_pointers)->gatts_db, value_handle, value, value_len);
+ if (!send_update || err) {
+ return err;
}
- 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_printf("mp_bluetooth_gatts_notify\n");
+ // Read the CCCD value. TODO: These should be per-connection.
+ const uint8_t *cccd;
+ size_t cccd_len;
+ err = mp_bluetooth_gatts_db_read(MP_STATE_PORT(bluetooth_btstack_root_pointers)->gatts_db, value_handle + 1, &cccd, &cccd_len);
+ if (cccd_len != 2 || err) {
+ return err;
+ }
- if (!mp_bluetooth_is_active()) {
- return ERRNO_BLUETOOTH_NOT_ACTIVE;
+ // Notify/indicate all active connections.
+ btstack_linked_list_iterator_t it;
+ hci_connections_get_iterator(&it);
+ while (btstack_linked_list_iterator_has_next(&it)) {
+ hci_connection_t *connection = (hci_connection_t *)btstack_linked_list_iterator_next(&it);
+ if (cccd[0] & 1) {
+ err = mp_bluetooth_gatts_notify_indicate(connection->con_handle, value_handle, MP_BLUETOOTH_GATTS_OP_NOTIFY, value, value_len);
+ if (err) {
+ return err;
+ }
+ }
+ if (cccd[0] & 2) {
+ err = mp_bluetooth_gatts_notify_indicate(connection->con_handle, value_handle, MP_BLUETOOTH_GATTS_OP_INDICATE, value, value_len);
+ if (err) {
+ return err;
+ }
+ }
}
- // 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);
+ return 0;
}
-int mp_bluetooth_gatts_notify_send(uint16_t conn_handle, uint16_t value_handle, const uint8_t *value, size_t value_len) {
- DEBUG_printf("mp_bluetooth_gatts_notify_send\n");
+#if !MICROPY_TRACKED_ALLOC
+#error "btstack requires MICROPY_TRACKED_ALLOC"
+#endif
- if (!mp_bluetooth_is_active()) {
- return ERRNO_BLUETOOTH_NOT_ACTIVE;
- }
+typedef struct {
+ btstack_context_callback_registration_t btstack_registration;
+ int gatts_op;
+ uint16_t conn_handle;
+ uint16_t value_handle;
+ size_t value_len;
+ uint8_t value[];
+} notify_indicate_pending_op_t;
- // Attempt to send immediately. If it succeeds, btstack will copy the buffer.
+// Called in response to a gatts_notify/indicate being unable to complete, which then calls
+// att_server_request_to_send_notification.
+STATIC void btstack_notify_indicate_ready_handler(void *context) {
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_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);
+ notify_indicate_pending_op_t *pending_op = (notify_indicate_pending_op_t *)context;
+ DEBUG_printf("btstack_notify_indicate_ready_handler gatts_op=%d conn_handle=%d value_handle=%d len=%lu\n", pending_op->gatts_op, pending_op->conn_handle, pending_op->value_handle, pending_op->value_len);
+ int err = ERROR_CODE_SUCCESS;
+ switch (pending_op->gatts_op) {
+ case MP_BLUETOOTH_GATTS_OP_NOTIFY:
+ err = att_server_notify(pending_op->conn_handle, pending_op->value_handle, pending_op->value, pending_op->value_len);
+ DEBUG_printf("btstack_notify_indicate_ready_handler: sending notification err=%d\n", err);
+ break;
+ case MP_BLUETOOTH_GATTS_OP_INDICATE:
+ err = att_server_indicate(pending_op->conn_handle, pending_op->value_handle, pending_op->value, pending_op->value_len);
+ DEBUG_printf("btstack_notify_indicate_ready_handler: sending indication err=%d\n", err);
+ break;
}
+ assert(err == ERROR_CODE_SUCCESS);
+ (void)err;
+ MICROPY_PY_BLUETOOTH_EXIT
+ m_tracked_free(pending_op);
}
-int mp_bluetooth_gatts_indicate(uint16_t conn_handle, uint16_t value_handle) {
- DEBUG_printf("mp_bluetooth_gatts_indicate\n");
+int mp_bluetooth_gatts_notify_indicate(uint16_t conn_handle, uint16_t value_handle, int gatts_op, const uint8_t *value, size_t value_len) {
+ DEBUG_printf("mp_bluetooth_gatts_notify_indicate: gatts_op=%d\n", gatts_op);
if (!mp_bluetooth_is_active()) {
return ERRNO_BLUETOOTH_NOT_ACTIVE;
}
- 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);
+ if (!value) {
+ // NULL value means "use DB value".
+ mp_bluetooth_gatts_db_read(MP_STATE_PORT(bluetooth_btstack_root_pointers)->gatts_db, value_handle, &value, &value_len);
+ }
- // Indicate will raise ATT_EVENT_HANDLE_VALUE_INDICATION_COMPLETE when
- // acknowledged (or timeout/error).
+ // Even if a lower MTU is negotiated, btstack allows sending a larger
+ // notification/indication. Truncate at the MTU-3 (to match NimBLE).
+ uint16_t current_mtu = att_server_get_mtu(conn_handle);
+ if (current_mtu) {
+ current_mtu -= 3;
+ value_len = MIN(value_len, current_mtu);
+ }
- // Attempt to send immediately, will copy buffer.
+ int err = ERROR_CODE_UNKNOWN_HCI_COMMAND;
+
+ // Attempt to send immediately. If it succeeds, btstack will copy the buffer.
MICROPY_PY_BLUETOOTH_ENTER
- int err = att_server_indicate(conn_handle, value_handle, data, len);
+ switch (gatts_op) {
+ case MP_BLUETOOTH_GATTS_OP_NOTIFY:
+ err = att_server_notify(conn_handle, value_handle, value, value_len);
+ break;
+ case MP_BLUETOOTH_GATTS_OP_INDICATE:
+ // Indicate will raise ATT_EVENT_HANDLE_VALUE_INDICATION_COMPLETE when
+ // acknowledged (or timeout/error).
+ err = att_server_indicate(conn_handle, value_handle, value, value_len);
+ break;
+ }
MICROPY_PY_BLUETOOTH_EXIT
- if (err == BTSTACK_ACL_BUFFERS_FULL) {
- DEBUG_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 == BTSTACK_ACL_BUFFERS_FULL || err == ATT_HANDLE_VALUE_INDICATION_IN_PROGRESS) {
+ DEBUG_printf("mp_bluetooth_gatts_notify_indicate: ACL buffer full / indication in progress, scheduling callback\n");
+
+ // Copy the value and ask btstack to let us know when it can be sent.
+ notify_indicate_pending_op_t *pending_op = m_tracked_calloc(1, sizeof(notify_indicate_pending_op_t) + value_len);
+ pending_op->btstack_registration.context = pending_op;
+ pending_op->btstack_registration.callback = &btstack_notify_indicate_ready_handler;
+ pending_op->gatts_op = gatts_op;
+ pending_op->conn_handle = conn_handle;
+ pending_op->value_handle = value_handle;
+ pending_op->value_len = value_len;
+ memcpy(pending_op->value, value, value_len);
+
+ MICROPY_PY_BLUETOOTH_ENTER
+ switch (gatts_op) {
+ case MP_BLUETOOTH_GATTS_OP_NOTIFY:
+ err = att_server_request_to_send_notification(&pending_op->btstack_registration, conn_handle);
+ break;
+ case MP_BLUETOOTH_GATTS_OP_INDICATE:
+ err = att_server_request_to_send_indication(&pending_op->btstack_registration, conn_handle);
+ break;
+ }
+ MICROPY_PY_BLUETOOTH_EXIT
if (err != ERROR_CODE_SUCCESS) {
- // Failure. Unref and free the pending operation.
- btstack_remove_pending_operation(pending_op, true /* del */);
+ m_tracked_free(pending_op);
}
-
- return 0;
- } else {
- return btstack_error_to_errno(err);
}
+
+ return btstack_error_to_errno(err);
}
int mp_bluetooth_gatts_set_buffer(uint16_t value_handle, size_t len, bool append) {
@@ -1358,9 +1398,9 @@ int mp_bluetooth_gattc_discover_descriptors(uint16_t conn_handle, uint16_t start
}
gatt_client_characteristic_t characteristic = {
- // Only start/end handles needed for gatt_client_discover_characteristic_descriptors.
- .start_handle = start_handle,
- .value_handle = 0,
+ // Only value/end handles needed for gatt_client_discover_characteristic_descriptors.
+ .start_handle = 0,
+ .value_handle = start_handle,
.end_handle = end_handle,
.properties = 0,
.uuid16 = 0,
@@ -1374,58 +1414,99 @@ int mp_bluetooth_gattc_read(uint16_t conn_handle, uint16_t value_handle) {
if (!mp_bluetooth_is_active()) {
return ERRNO_BLUETOOTH_NOT_ACTIVE;
}
- return btstack_error_to_errno(gatt_client_read_value_of_characteristic_using_value_handle(&btstack_packet_handler_read, conn_handle, value_handle));
+
+ // There can only be a single pending GATT client operation per connection.
+ mp_btstack_active_connection_t *conn = find_active_connection(conn_handle);
+ if (!conn) {
+ DEBUG_printf(" --> no active connection %d\n", conn_handle);
+ return MP_ENOTCONN;
+ }
+ if (conn->pending_value_handle != 0xffff) {
+ // There's either a read in progress, a write-with-response in progress, or a pending can-write-without-response request outstanding.
+ DEBUG_printf("--> busy\n");
+ return MP_EALREADY;
+ }
+ conn->pending_value_handle = value_handle;
+ int err = gatt_client_read_value_of_characteristic_using_value_handle(&btstack_packet_handler_read, conn_handle, value_handle);
+ if (err != ERROR_CODE_SUCCESS) {
+ DEBUG_printf("--> can't send read %d\n", err);
+ conn->pending_value_handle = 0xffff;
+ }
+ return btstack_error_to_errno(err);
}
-int mp_bluetooth_gattc_write(uint16_t conn_handle, uint16_t value_handle, const uint8_t *value, size_t *value_len, unsigned int mode) {
+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_printf("mp_bluetooth_gattc_write\n");
if (!mp_bluetooth_is_active()) {
return ERRNO_BLUETOOTH_NOT_ACTIVE;
}
- // We should be distinguishing between gatt_client_write_value_of_characteristic vs
+ // Note: 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_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_printf("mp_bluetooth_gattc_write: other failure: %d\n", err);
+ // Simplest case -- if the write can be dispatched directly, then the buffer is copied 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_printf("--> can't send write-without-response %d\n", err);
+ return btstack_error_to_errno(err);
}
+ }
+
+ // There can only be a single pending read/write request per connection.
+ mp_btstack_active_connection_t *conn = find_active_connection(conn_handle);
+ if (!conn) {
+ DEBUG_printf(" --> no active connection %d\n", conn_handle);
+ return MP_ENOTCONN;
+ }
+ if (conn->pending_value_handle != 0xffff) {
+ // There's either a read in progress, a write-with-response in progress, or a pending can-write-without-response request outstanding.
+ DEBUG_printf(" --> busy\n");
+ return MP_EALREADY;
+ }
+ conn->pending_value_handle = value_handle;
+ conn->pending_write_value_len = value_len;
+ conn->pending_write_value = m_new(uint8_t, value_len);
+ memcpy(conn->pending_write_value, value, value_len);
+
+ if (mode == MP_BLUETOOTH_WRITE_MODE_NO_RESPONSE) {
+ DEBUG_printf(" --> client busy\n");
+ // Raise the GATT_EVENT_CAN_WRITE_WITHOUT_RESPONSE event when
+ // write-without-response will succeed. The only way this fails is if
+ // there's an outstanding request (unlike for the server-equivalent,
+ // att_server_request_to_send_notification, which has a queue) but
+ // we've already checked that there isn't one.
+ err = gatt_client_request_can_write_without_response_event(&btstack_packet_handler_generic, conn_handle);
} 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);
+ // Attempt to write immediately. This can fail if there's another
+ // client operation in progress (e.g. discover).
+ err = gatt_client_write_value_of_characteristic(&btstack_packet_handler_write_with_response, conn_handle, value_handle, value_len, conn->pending_write_value);
} 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 */);
+ if (err != ERROR_CODE_SUCCESS) {
+ DEBUG_printf("--> write failed %d\n", err);
+ // We knew that there was no read/write in progress, but some other
+ // client operation is in progress, so release the pending state.
+ m_del(uint8_t, conn->pending_write_value, value_len);
+ conn->pending_write_value_len = 0;
+ conn->pending_value_handle = 0xffff;
}
return btstack_error_to_errno(err);
}
int mp_bluetooth_gattc_exchange_mtu(uint16_t conn_handle) {
- DEBUG_printf("mp_bluetooth_exchange_mtu: conn_handle=%d mtu=%d\n", conn_handle, l2cap_max_le_mtu());
+ DEBUG_printf("mp_bluetooth_gattc_exchange_mtu: conn_handle=%d mtu=%d\n", conn_handle, l2cap_max_le_mtu());
- gatt_client_send_mtu_negotiation(&btstack_packet_handler_att_server, conn_handle);
+ gatt_client_send_mtu_negotiation(&btstack_packet_handler_generic, conn_handle);
return 0;
}
@@ -1460,4 +1541,6 @@ int mp_bluetooth_l2cap_recvinto(uint16_t conn_handle, uint16_t cid, uint8_t *buf
#endif // MICROPY_PY_BLUETOOTH_ENABLE_L2CAP_CHANNELS
+MP_REGISTER_ROOT_POINTER(struct _mp_bluetooth_btstack_root_pointers_t *bluetooth_btstack_root_pointers);
+
#endif // MICROPY_PY_BLUETOOTH && MICROPY_BLUETOOTH_BTSTACK
diff --git a/extmod/btstack/modbluetooth_btstack.h b/extmod/btstack/modbluetooth_btstack.h
index 7890bbfae2c4..7f4a1820737a 100644
--- a/extmod/btstack/modbluetooth_btstack.h
+++ b/extmod/btstack/modbluetooth_btstack.h
@@ -33,8 +33,6 @@
#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;
@@ -44,11 +42,12 @@ typedef struct _mp_bluetooth_btstack_root_pointers_t {
// Characteristic (and descriptor) value storage.
mp_gatts_db_t gatts_db;
- btstack_linked_list_t pending_ops;
-
- #if MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE
+ #if MICROPY_PY_BLUETOOTH_ENABLE_GATT_CLIENT
// Registration for notify/indicate events.
gatt_client_notification_t notification;
+
+ // Active connections (only used for GATT clients).
+ btstack_linked_list_t active_connections;
#endif
} mp_bluetooth_btstack_root_pointers_t;
diff --git a/extmod/extmod.cmake b/extmod/extmod.cmake
index 551dec714c6e..0e5ed942260f 100644
--- a/extmod/extmod.cmake
+++ b/extmod/extmod.cmake
@@ -14,8 +14,8 @@ set(MICROPY_SOURCE_EXTMOD
${MICROPY_EXTMOD_DIR}/machine_signal.c
${MICROPY_EXTMOD_DIR}/machine_spi.c
${MICROPY_EXTMOD_DIR}/modbluetooth.c
- ${MICROPY_EXTMOD_DIR}/modbtree.c
${MICROPY_EXTMOD_DIR}/modframebuf.c
+ ${MICROPY_EXTMOD_DIR}/modlwip.c
${MICROPY_EXTMOD_DIR}/modnetwork.c
${MICROPY_EXTMOD_DIR}/modonewire.c
${MICROPY_EXTMOD_DIR}/moduasyncio.c
@@ -37,6 +37,10 @@ set(MICROPY_SOURCE_EXTMOD
${MICROPY_EXTMOD_DIR}/moduwebsocket.c
${MICROPY_EXTMOD_DIR}/moduzlib.c
${MICROPY_EXTMOD_DIR}/modwebrepl.c
+ ${MICROPY_EXTMOD_DIR}/network_cyw43.c
+ ${MICROPY_EXTMOD_DIR}/network_lwip.c
+ ${MICROPY_EXTMOD_DIR}/network_ninaw10.c
+ ${MICROPY_EXTMOD_DIR}/network_wiznet5k.c
${MICROPY_EXTMOD_DIR}/uos_dupterm.c
${MICROPY_EXTMOD_DIR}/utime_mphal.c
${MICROPY_EXTMOD_DIR}/vfs.c
@@ -93,9 +97,14 @@ if(MICROPY_PY_BTREE)
)
list(APPEND MICROPY_DEF_CORE
+ MICROPY_PY_BTREE=1
__DBINTERFACE_PRIVATE=1
"virt_fd_t=void*"
)
+
+ list(APPEND MICROPY_SOURCE_EXTMOD
+ ${MICROPY_EXTMOD_DIR}/modbtree.c
+ )
endif()
# Library for mbedtls
@@ -110,6 +119,7 @@ if(MICROPY_SSL_MBEDTLS)
)
target_sources(micropy_lib_mbedtls INTERFACE
+ ${MICROPY_DIR}/lib/mbedtls_errors/mp_mbedtls_errors.c
${MICROPY_LIB_MBEDTLS_DIR}/library/aes.c
${MICROPY_LIB_MBEDTLS_DIR}/library/aesni.c
${MICROPY_LIB_MBEDTLS_DIR}/library/arc4.c
@@ -137,7 +147,6 @@ if(MICROPY_SSL_MBEDTLS)
${MICROPY_LIB_MBEDTLS_DIR}/library/ecp_curves.c
${MICROPY_LIB_MBEDTLS_DIR}/library/entropy.c
${MICROPY_LIB_MBEDTLS_DIR}/library/entropy_poll.c
- ${MICROPY_LIB_MBEDTLS_DIR}/library/error.c
${MICROPY_LIB_MBEDTLS_DIR}/library/gcm.c
${MICROPY_LIB_MBEDTLS_DIR}/library/havege.c
${MICROPY_LIB_MBEDTLS_DIR}/library/hmac_drbg.c
@@ -183,8 +192,12 @@ if(MICROPY_SSL_MBEDTLS)
${MICROPY_LIB_MBEDTLS_DIR}/library/xtea.c
)
+ if(NOT MBEDTLS_CONFIG_FILE)
+ set(MBEDTLS_CONFIG_FILE "${MICROPY_PORT_DIR}/mbedtls/mbedtls_config.h")
+ endif()
+
target_compile_definitions(micropy_lib_mbedtls INTERFACE
- MBEDTLS_CONFIG_FILE="${MICROPY_PORT_DIR}/mbedtls/mbedtls_config.h"
+ MBEDTLS_CONFIG_FILE="${MBEDTLS_CONFIG_FILE}"
)
list(APPEND MICROPY_INC_CORE
@@ -246,4 +259,6 @@ if(MICROPY_PY_LWIP)
list(APPEND MICROPY_INC_CORE
${MICROPY_LIB_LWIP_DIR}/include
)
+
+ string(CONCAT GIT_SUBMODULES "${GIT_SUBMODULES} " lib/lwip)
endif()
diff --git a/extmod/extmod.mk b/extmod/extmod.mk
index ff24a549a9a0..5aecedc2281b 100644
--- a/extmod/extmod.mk
+++ b/extmod/extmod.mk
@@ -1,4 +1,68 @@
-# This makefile fragment provides rules to build 3rd-party components for extmod modules
+# This makefile fragment adds the source code files for the core extmod modules
+# and provides rules to build 3rd-party components for extmod modules.
+
+SRC_EXTMOD_C += \
+ extmod/machine_bitstream.c \
+ extmod/machine_i2c.c \
+ extmod/machine_mem.c \
+ extmod/machine_pinbase.c \
+ extmod/machine_pulse.c \
+ extmod/machine_pwm.c \
+ extmod/machine_signal.c \
+ extmod/machine_spi.c \
+ extmod/machine_timer.c \
+ extmod/modbluetooth.c \
+ extmod/modbtree.c \
+ extmod/modframebuf.c \
+ extmod/modlwip.c \
+ extmod/modnetwork.c \
+ extmod/modonewire.c \
+ extmod/moduasyncio.c \
+ extmod/modubinascii.c \
+ extmod/moducryptolib.c \
+ extmod/moductypes.c \
+ extmod/moduhashlib.c \
+ extmod/moduheapq.c \
+ extmod/modujson.c \
+ extmod/moduos.c \
+ extmod/moduplatform.c\
+ extmod/modurandom.c \
+ extmod/modure.c \
+ extmod/moduselect.c \
+ extmod/modusocket.c \
+ extmod/modussl_axtls.c \
+ extmod/modussl_mbedtls.c \
+ extmod/modutimeq.c \
+ extmod/moduwebsocket.c \
+ extmod/moduzlib.c \
+ extmod/modwebrepl.c \
+ extmod/network_cyw43.c \
+ extmod/network_lwip.c \
+ extmod/network_ninaw10.c \
+ extmod/network_wiznet5k.c \
+ extmod/uos_dupterm.c \
+ extmod/utime_mphal.c \
+ extmod/vfs.c \
+ extmod/vfs_blockdev.c \
+ extmod/vfs_fat.c \
+ extmod/vfs_fat_diskio.c \
+ extmod/vfs_fat_file.c \
+ extmod/vfs_lfs.c \
+ extmod/vfs_posix.c \
+ extmod/vfs_posix_file.c \
+ extmod/vfs_reader.c \
+ extmod/virtpin.c \
+ shared/libc/abort_.c \
+ shared/libc/printf.c \
+
+SRC_THIRDPARTY_C += \
+
+PY_O += $(addprefix $(BUILD)/, $(SRC_EXTMOD_C:.c=.o))
+PY_O += $(addprefix $(BUILD)/, $(SRC_THIRDPARTY_C:.c=.o))
+SRC_QSTR += $(SRC_EXTMOD_C)
+
+CFLAGS += $(CFLAGS_EXTMOD) $(CFLAGS_THIRDPARTY)
+LDFLAGS += $(LDFLAGS_EXTMOD) $(LDFLAGS_THIRDPARTY)
################################################################################
# VFS FAT FS
@@ -6,11 +70,11 @@
OOFATFS_DIR = lib/oofatfs
# this sets the config file for FatFs
-CFLAGS_MOD += -DFFCONF_H=\"$(OOFATFS_DIR)/ffconf.h\"
+CFLAGS_THIRDPARTY += -DFFCONF_H=\"$(OOFATFS_DIR)/ffconf.h\"
ifeq ($(MICROPY_VFS_FAT),1)
-CFLAGS_MOD += -DMICROPY_VFS_FAT=1
-SRC_MOD += $(addprefix $(OOFATFS_DIR)/,\
+CFLAGS_EXTMOD += -DMICROPY_VFS_FAT=1
+SRC_THIRDPARTY_C += $(addprefix $(OOFATFS_DIR)/,\
ff.c \
ffunicode.c \
)
@@ -22,18 +86,18 @@ endif
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)/,\
+CFLAGS_EXTMOD += -DMICROPY_VFS_LFS1=1
+CFLAGS_THIRDPARTY += -DLFS1_NO_MALLOC -DLFS1_NO_DEBUG -DLFS1_NO_WARN -DLFS1_NO_ERROR -DLFS1_NO_ASSERT
+SRC_THIRDPARTY_C += $(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)/,\
+CFLAGS_EXTMOD += -DMICROPY_VFS_LFS2=1
+CFLAGS_THIRDPARTY += -DLFS2_NO_MALLOC -DLFS2_NO_DEBUG -DLFS2_NO_WARN -DLFS2_NO_ERROR -DLFS2_NO_ASSERT
+SRC_THIRDPARTY_C += $(addprefix $(LITTLEFS_DIR)/,\
lfs2.c \
lfs2_util.c \
)
@@ -45,12 +109,13 @@ endif
# ussl
ifeq ($(MICROPY_PY_USSL),1)
-CFLAGS_MOD += -DMICROPY_PY_USSL=1
+CFLAGS_EXTMOD += -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
+GIT_SUBMODULES += $(AXTLS_DIR)
+CFLAGS_EXTMOD += -DMICROPY_SSL_AXTLS=1 -I$(TOP)/lib/axtls/ssl -I$(TOP)/lib/axtls/crypto -I$(TOP)/extmod/axtls-include
$(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)/,\
+SRC_THIRDPARTY_C += $(addprefix $(AXTLS_DIR)/,\
ssl/asn1.c \
ssl/loader.c \
ssl/tls1.c \
@@ -67,8 +132,12 @@ SRC_MOD += $(addprefix $(AXTLS_DIR)/,\
)
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/,\
+MBEDTLS_CONFIG_FILE ?= \"mbedtls/mbedtls_config.h\"
+GIT_SUBMODULES += $(MBEDTLS_DIR)
+CFLAGS_EXTMOD += -DMBEDTLS_CONFIG_FILE=$(MBEDTLS_CONFIG_FILE)
+CFLAGS_EXTMOD += -DMICROPY_SSL_MBEDTLS=1 -I$(TOP)/$(MBEDTLS_DIR)/include
+SRC_THIRDPARTY_C += lib/mbedtls_errors/mp_mbedtls_errors.c
+SRC_THIRDPARTY_C += $(addprefix $(MBEDTLS_DIR)/library/,\
aes.c \
aesni.c \
arc4.c \
@@ -96,7 +165,6 @@ SRC_MOD += $(addprefix $(MBEDTLS_DIR)/library/,\
ecp_curves.c \
entropy.c \
entropy_poll.c \
- error.c \
gcm.c \
havege.c \
hmac_drbg.c \
@@ -148,13 +216,14 @@ endif
# lwip
ifeq ($(MICROPY_PY_LWIP),1)
+GIT_SUBMODULES += lib/lwip
# 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 shared/netutils/netutils.c
-SRC_MOD += $(addprefix $(LWIP_DIR)/,\
+CFLAGS_EXTMOD += -DMICROPY_PY_LWIP=1
+$(BUILD)/$(LWIP_DIR)/core/ipv4/dhcp.o: CFLAGS += -Wno-address
+SRC_THIRDPARTY_C += shared/netutils/netutils.c
+SRC_THIRDPARTY_C += $(addprefix $(LWIP_DIR)/,\
apps/mdns/mdns.c \
core/def.c \
core/dns.c \
@@ -193,8 +262,8 @@ SRC_MOD += $(addprefix $(LWIP_DIR)/,\
netif/ethernet.c \
)
ifeq ($(MICROPY_PY_LWIP_SLIP),1)
-CFLAGS_MOD += -DMICROPY_PY_LWIP_SLIP=1
-SRC_MOD += $(LWIP_DIR)/netif/slipif.c
+CFLAGS_EXTMOD += -DMICROPY_PY_LWIP_SLIP=1
+SRC_THIRDPARTY_C += $(LWIP_DIR)/netif/slipif.c
endif
endif
@@ -205,8 +274,7 @@ 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)/,\
+SRC_THIRDPARTY_C += $(addprefix $(BTREE_DIR)/,\
btree/bt_close.c \
btree/bt_conv.c \
btree/bt_debug.c \
@@ -222,10 +290,79 @@ SRC_MOD += $(addprefix $(BTREE_DIR)/,\
btree/bt_utils.c \
mpool/mpool.c \
)
-CFLAGS_MOD += -DMICROPY_PY_BTREE=1
+CFLAGS_EXTMOD += -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
+################################################################################
+# networking
+
+ifeq ($(MICROPY_PY_NETWORK_CYW43),1)
+CYW43_DIR = lib/cyw43-driver
+GIT_SUBMODULES += $(CYW43_DIR)
+CFLAGS_EXTMOD += -DMICROPY_PY_NETWORK_CYW43=1
+SRC_THIRDPARTY_C += $(addprefix $(CYW43_DIR)/src/,\
+ cyw43_ctrl.c \
+ cyw43_lwip.c \
+ cyw43_ll.c \
+ cyw43_sdio.c \
+ cyw43_stats.c \
+ )
+ifeq ($(MICROPY_PY_BLUETOOTH),1)
+DRIVERS_SRC_C += drivers/cyw43/cywbt.c
+endif
+
+$(BUILD)/$(CYW43_DIR)/src/cyw43_%.o: CFLAGS += -std=c11
+endif # MICROPY_PY_NETWORK_CYW43
+
+ifneq ($(MICROPY_PY_NETWORK_WIZNET5K),)
+ifneq ($(MICROPY_PY_NETWORK_WIZNET5K),0)
+WIZNET5K_DIR=lib/wiznet5k
+GIT_SUBMODULES += lib/wiznet5k
+INC += -I$(TOP)/$(WIZNET5K_DIR) -I$(TOP)/$(WIZNET5K_DIR)/Ethernet
+CFLAGS += -DMICROPY_PY_NETWORK_WIZNET5K=$(MICROPY_PY_NETWORK_WIZNET5K) -D_WIZCHIP_=$(MICROPY_PY_NETWORK_WIZNET5K)
+CFLAGS_THIRDPARTY += -DWIZCHIP_PREFIXED_EXPORTS=1
+ifeq ($(MICROPY_PY_LWIP),1)
+# When using MACRAW mode (with lwIP), maximum buffer space must be used for the raw socket
+CFLAGS_THIRDPARTY += -DWIZCHIP_USE_MAX_BUFFER
+endif
+SRC_THIRDPARTY_C += $(addprefix $(WIZNET5K_DIR)/,\
+ Ethernet/W$(MICROPY_PY_NETWORK_WIZNET5K)/w$(MICROPY_PY_NETWORK_WIZNET5K).c \
+ Ethernet/wizchip_conf.c \
+ Ethernet/socket.c \
+ Internet/DNS/dns.c \
+ Internet/DHCP/dhcp.c \
+ )
+endif
+endif
+
+################################################################################
+# bluetooth
+
+ifeq ($(MICROPY_PY_BLUETOOTH),1)
+CFLAGS_EXTMOD += -DMICROPY_PY_BLUETOOTH=1
+
+ifeq ($(MICROPY_BLUETOOTH_NIMBLE),1)
+ifeq ($(MICROPY_BLUETOOTH_BTSTACK),1)
+$(error Cannot enable both NimBLE and BTstack at the same time)
+endif
+endif
+
+ifneq ($(MICROPY_BLUETOOTH_NIMBLE),1)
+ifneq ($(MICROPY_BLUETOOTH_BTSTACK),1)
+$(error Must enable one of MICROPY_BLUETOOTH_NIMBLE or MICROPY_BLUETOOTH_BTSTACK)
+endif
+endif
+
+ifeq ($(MICROPY_BLUETOOTH_NIMBLE),1)
+include $(TOP)/extmod/nimble/nimble.mk
+endif
+
+ifeq ($(MICROPY_BLUETOOTH_BTSTACK),1)
+include $(TOP)/extmod/btstack/btstack.mk
+endif
+
+endif
diff --git a/extmod/machine_i2c.c b/extmod/machine_i2c.c
index 452f07a2ebdb..3563b3243c36 100644
--- a/extmod/machine_i2c.c
+++ b/extmod/machine_i2c.c
@@ -273,7 +273,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 *)MP_OBJ_TYPE_GET_SLOT(self->type, protocol);
int ret = i2c_p->transfer_single(self, addr, len, buf, flags);
if (n > 1) {
@@ -292,14 +292,14 @@ 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 *)MP_OBJ_TYPE_GET_SLOT(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_p_t *i2c_p = (mp_machine_i2c_p_t *)MP_OBJ_TYPE_GET_SLOT(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);
@@ -310,7 +310,7 @@ STATIC int mp_machine_i2c_writeto(mp_obj_base_t *self, uint16_t addr, const uint
STATIC mp_obj_t machine_i2c_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_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_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t *)MP_OBJ_TYPE_GET_SLOT(self->type, protocol);
if (i2c_p->init == NULL) {
mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("I2C operation not supported"));
}
@@ -328,6 +328,9 @@ STATIC mp_obj_t machine_i2c_scan(mp_obj_t self_in) {
if (ret == 0) {
mp_obj_list_append(list, MP_OBJ_NEW_SMALL_INT(addr));
}
+ #ifdef MICROPY_EVENT_POLL_HOOK
+ MICROPY_EVENT_POLL_HOOK
+ #endif
}
return list;
}
@@ -335,7 +338,7 @@ 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_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t *)MP_OBJ_TYPE_GET_SLOT(self->type, protocol);
if (i2c_p->start == NULL) {
mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("I2C operation not supported"));
}
@@ -349,7 +352,7 @@ 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_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t *)MP_OBJ_TYPE_GET_SLOT(self->type, protocol);
if (i2c_p->stop == NULL) {
mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("I2C operation not supported"));
}
@@ -363,7 +366,7 @@ 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_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t *)MP_OBJ_TYPE_GET_SLOT(self->type, protocol);
if (i2c_p->read == NULL) {
mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("I2C operation not supported"));
}
@@ -387,7 +390,7 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_i2c_readinto_obj, 2, 3, machine_i2c_
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_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t *)MP_OBJ_TYPE_GET_SLOT(self->type, protocol);
if (i2c_p->write == NULL) {
mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("I2C operation not supported"));
}
@@ -417,7 +420,7 @@ STATIC mp_obj_t machine_i2c_readfrom(size_t n_args, const mp_obj_t *args) {
if (ret < 0) {
mp_raise_OSError(-ret);
}
- return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
+ return mp_obj_new_bytes_from_vstr(&vstr);
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_i2c_readfrom_obj, 3, 4, machine_i2c_readfrom);
@@ -483,7 +486,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 *)MP_OBJ_TYPE_GET_SLOT(self->type, protocol);
int ret = i2c_p->transfer(self, addr, nbufs, bufs, stop ? MP_MACHINE_I2C_FLAG_STOP : 0);
mp_local_free(bufs);
@@ -516,7 +519,7 @@ STATIC int read_mem(mp_obj_t self_in, uint16_t addr, uint32_t memaddr, uint8_t a
#if MICROPY_PY_MACHINE_I2C_TRANSFER_WRITE1
// The I2C transfer function may support the MP_MACHINE_I2C_FLAG_WRITE1 option
- 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 *)MP_OBJ_TYPE_GET_SLOT(self->type, protocol);
if (i2c_p->transfer_supports_write1) {
// Create partial write and read buffers
mp_machine_i2c_buf_t bufs[2] = {
@@ -553,7 +556,7 @@ STATIC int write_mem(mp_obj_t self_in, uint16_t addr, uint32_t memaddr, uint8_t
};
// 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 *)MP_OBJ_TYPE_GET_SLOT(self->type, protocol);
return i2c_p->transfer(self, addr, 2, bufs, MP_MACHINE_I2C_FLAG_STOP);
}
@@ -581,7 +584,7 @@ STATIC mp_obj_t machine_i2c_readfrom_mem(size_t n_args, const mp_obj_t *pos_args
mp_raise_OSError(-ret);
}
- return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
+ return mp_obj_new_bytes_from_vstr(&vstr);
}
MP_DEFINE_CONST_FUN_OBJ_KW(machine_i2c_readfrom_mem_obj, 1, machine_i2c_readfrom_mem);
@@ -727,13 +730,14 @@ STATIC const mp_machine_i2c_p_t mp_machine_soft_i2c_p = {
.transfer = mp_machine_soft_i2c_transfer,
};
-const mp_obj_type_t mp_machine_soft_i2c_type = {
- { &mp_type_type },
- .name = MP_QSTR_SoftI2C,
- .print = mp_machine_soft_i2c_print,
- .make_new = mp_machine_soft_i2c_make_new,
- .protocol = &mp_machine_soft_i2c_p,
- .locals_dict = (mp_obj_dict_t *)&mp_machine_i2c_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ mp_machine_soft_i2c_type,
+ MP_QSTR_SoftI2C,
+ MP_TYPE_FLAG_NONE,
+ make_new, mp_machine_soft_i2c_make_new,
+ print, mp_machine_soft_i2c_print,
+ protocol, &mp_machine_soft_i2c_p,
+ locals_dict, &mp_machine_i2c_locals_dict
+ );
#endif // MICROPY_PY_MACHINE_SOFTI2C
diff --git a/extmod/machine_i2c.h b/extmod/machine_i2c.h
index a3363d4c341c..600145bfedf4 100644
--- a/extmod/machine_i2c.h
+++ b/extmod/machine_i2c.h
@@ -38,7 +38,7 @@
--n_args; \
++all_args; \
} \
- return mp_machine_soft_i2c_type.make_new(&mp_machine_soft_i2c_type, n_args, n_kw, all_args); \
+ return MP_OBJ_TYPE_GET_SLOT(&mp_machine_soft_i2c_type, make_new)(&mp_machine_soft_i2c_type, n_args, n_kw, all_args); \
} \
} while (0)
diff --git a/extmod/machine_mem.c b/extmod/machine_mem.c
index 73e2f7fd1fcb..f27356e02836 100644
--- a/extmod/machine_mem.c
+++ b/extmod/machine_mem.c
@@ -101,12 +101,13 @@ STATIC mp_obj_t machine_mem_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t va
}
}
-const mp_obj_type_t machine_mem_type = {
- { &mp_type_type },
- .name = MP_QSTR_mem,
- .print = machine_mem_print,
- .subscr = machine_mem_subscr,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ machine_mem_type,
+ MP_QSTR_mem,
+ MP_TYPE_FLAG_NONE,
+ print, machine_mem_print,
+ subscr, machine_mem_subscr
+ );
const machine_mem_obj_t machine_mem8_obj = {{&machine_mem_type}, 1};
const machine_mem_obj_t machine_mem16_obj = {{&machine_mem_type}, 2};
diff --git a/extmod/machine_pinbase.c b/extmod/machine_pinbase.c
index 070c5cde9d3a..8607e6ed3de9 100644
--- a/extmod/machine_pinbase.c
+++ b/extmod/machine_pinbase.c
@@ -77,11 +77,12 @@ STATIC const mp_pin_p_t pinbase_pin_p = {
.ioctl = pinbase_ioctl,
};
-const mp_obj_type_t machine_pinbase_type = {
- { &mp_type_type },
- .name = MP_QSTR_PinBase,
- .make_new = pinbase_make_new,
- .protocol = &pinbase_pin_p,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ machine_pinbase_type,
+ MP_QSTR_PinBase,
+ MP_TYPE_FLAG_NONE,
+ make_new, pinbase_make_new,
+ protocol, &pinbase_pin_p
+ );
#endif // MICROPY_PY_MACHINE
diff --git a/extmod/machine_pwm.c b/extmod/machine_pwm.c
index ddf49c1358a5..220d34d7da58 100644
--- a/extmod/machine_pwm.c
+++ b/extmod/machine_pwm.c
@@ -132,12 +132,13 @@ STATIC const mp_rom_map_elem_t machine_pwm_locals_dict_table[] = {
};
STATIC MP_DEFINE_CONST_DICT(machine_pwm_locals_dict, machine_pwm_locals_dict_table);
-const mp_obj_type_t machine_pwm_type = {
- { &mp_type_type },
- .name = MP_QSTR_PWM,
- .print = mp_machine_pwm_print,
- .make_new = mp_machine_pwm_make_new,
- .locals_dict = (mp_obj_dict_t *)&machine_pwm_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ machine_pwm_type,
+ MP_QSTR_PWM,
+ MP_TYPE_FLAG_NONE,
+ make_new, mp_machine_pwm_make_new,
+ print, mp_machine_pwm_print,
+ locals_dict, &machine_pwm_locals_dict
+ );
#endif // MICROPY_PY_MACHINE_PWM
diff --git a/extmod/machine_signal.c b/extmod/machine_signal.c
index cf7550a2e084..7922ed70771e 100644
--- a/extmod/machine_signal.c
+++ b/extmod/machine_signal.c
@@ -51,7 +51,7 @@ STATIC mp_obj_t signal_make_new(const mp_obj_type_t *type, size_t n_args, size_t
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;
+ pin_p = (mp_pin_p_t *)MP_OBJ_TYPE_GET_SLOT_OR_NULL(pin_base->type, protocol);
}
if (pin_p == NULL) {
@@ -172,13 +172,14 @@ STATIC const mp_pin_p_t signal_pin_p = {
.ioctl = signal_ioctl,
};
-const mp_obj_type_t machine_signal_type = {
- { &mp_type_type },
- .name = MP_QSTR_Signal,
- .make_new = signal_make_new,
- .call = signal_call,
- .protocol = &signal_pin_p,
- .locals_dict = (void *)&signal_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ machine_signal_type,
+ MP_QSTR_Signal,
+ MP_TYPE_FLAG_NONE,
+ make_new, signal_make_new,
+ call, signal_call,
+ protocol, &signal_pin_p,
+ locals_dict, &signal_locals_dict
+ );
#endif // MICROPY_PY_MACHINE
diff --git a/extmod/machine_spi.c b/extmod/machine_spi.c
index f160f97d04b4..8c4d91a3cf63 100644
--- a/extmod/machine_spi.c
+++ b/extmod/machine_spi.c
@@ -28,6 +28,9 @@
#include
#include "py/runtime.h"
+
+#if MICROPY_PY_MACHINE_SPI || MICROPY_PY_MACHINE_SOFTSPI
+
#include "extmod/machine_spi.h"
// if a port didn't define MSB/LSB constants then provide them
@@ -39,11 +42,9 @@
/******************************************************************************/
// MicroPython bindings for generic machine.SPI
-#if MICROPY_PY_MACHINE_SPI || MICROPY_PY_MACHINE_SOFTSPI
-
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_machine_spi_p_t *spi_p = (mp_machine_spi_p_t *)MP_OBJ_TYPE_GET_SLOT(s->type, protocol);
spi_p->init(s, n_args - 1, args + 1, kw_args);
return mp_const_none;
}
@@ -51,7 +52,7 @@ 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_machine_spi_p_t *spi_p = (mp_machine_spi_p_t *)MP_OBJ_TYPE_GET_SLOT(s->type, protocol);
if (spi_p->deinit != NULL) {
spi_p->deinit(s);
}
@@ -61,7 +62,7 @@ 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_machine_spi_p_t *spi_p = (mp_machine_spi_p_t *)MP_OBJ_TYPE_GET_SLOT(s->type, protocol);
spi_p->transfer(s, len, src, dest);
}
@@ -70,7 +71,7 @@ STATIC mp_obj_t mp_machine_spi_read(size_t n_args, const mp_obj_t *args) {
vstr_init_len(&vstr, mp_obj_get_int(args[1]));
memset(vstr.buf, n_args == 3 ? mp_obj_get_int(args[2]) : 0, vstr.len);
mp_machine_spi_transfer(args[0], vstr.len, vstr.buf, vstr.buf);
- return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
+ return mp_obj_new_bytes_from_vstr(&vstr);
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_machine_spi_read_obj, 2, 3, mp_machine_spi_read);
@@ -251,13 +252,14 @@ const mp_machine_spi_p_t mp_machine_soft_spi_p = {
.transfer = mp_machine_soft_spi_transfer,
};
-const mp_obj_type_t mp_machine_soft_spi_type = {
- { &mp_type_type },
- .name = MP_QSTR_SoftSPI,
- .print = mp_machine_soft_spi_print,
- .make_new = mp_machine_soft_spi_make_new,
- .protocol = &mp_machine_soft_spi_p,
- .locals_dict = (mp_obj_dict_t *)&mp_machine_spi_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ mp_machine_soft_spi_type,
+ MP_QSTR_SoftSPI,
+ MP_TYPE_FLAG_NONE,
+ make_new, mp_machine_soft_spi_make_new,
+ print, mp_machine_soft_spi_print,
+ protocol, &mp_machine_soft_spi_p,
+ locals_dict, &mp_machine_spi_locals_dict
+ );
#endif // MICROPY_PY_MACHINE_SOFTSPI
diff --git a/extmod/machine_spi.h b/extmod/machine_spi.h
index ca92c719a8b5..93ee8d00ca32 100644
--- a/extmod/machine_spi.h
+++ b/extmod/machine_spi.h
@@ -39,7 +39,7 @@
--n_args; \
++all_args; \
} \
- return mp_machine_soft_spi_type.make_new(&mp_machine_soft_spi_type, n_args, n_kw, all_args); \
+ return MP_OBJ_TYPE_GET_SLOT(&mp_machine_soft_spi_type, make_new)(&mp_machine_soft_spi_type, n_args, n_kw, all_args); \
} \
} while (0)
diff --git a/ports/stm32/machine_timer.c b/extmod/machine_timer.c
similarity index 94%
rename from ports/stm32/machine_timer.c
rename to extmod/machine_timer.c
index c94532218773..68702cb74f60 100644
--- a/ports/stm32/machine_timer.c
+++ b/extmod/machine_timer.c
@@ -26,7 +26,10 @@
#include "py/runtime.h"
#include "py/mphal.h"
-#include "softtimer.h"
+
+#if MICROPY_PY_MACHINE_TIMER
+
+#include "shared/runtime/softtimer.h"
typedef soft_timer_entry_t machine_timer_obj_t;
@@ -136,10 +139,13 @@ STATIC const mp_rom_map_elem_t machine_timer_locals_dict_table[] = {
};
STATIC MP_DEFINE_CONST_DICT(machine_timer_locals_dict, machine_timer_locals_dict_table);
-const mp_obj_type_t machine_timer_type = {
- { &mp_type_type },
- .name = MP_QSTR_Timer,
- .print = machine_timer_print,
- .make_new = machine_timer_make_new,
- .locals_dict = (mp_obj_dict_t *)&machine_timer_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ machine_timer_type,
+ MP_QSTR_Timer,
+ MP_TYPE_FLAG_NONE,
+ make_new, machine_timer_make_new,
+ print, machine_timer_print,
+ locals_dict, &machine_timer_locals_dict
+ );
+
+#endif // MICROPY_PY_MACHINE_TIMER
diff --git a/extmod/mbedtls/mbedtls_config_common.h b/extmod/mbedtls/mbedtls_config_common.h
new file mode 100644
index 000000000000..bfbc6f7ba298
--- /dev/null
+++ b/extmod/mbedtls/mbedtls_config_common.h
@@ -0,0 +1,113 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018-2022 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_MBEDTLS_CONFIG_COMMON_H
+#define MICROPY_INCLUDED_MBEDTLS_CONFIG_COMMON_H
+
+// If you want to debug MBEDTLS uncomment the following and
+// pass "3" to mbedtls_debug_set_threshold in socket_new.
+// #define MBEDTLS_DEBUG_C
+
+// Set mbedtls configuration.
+#define MBEDTLS_DEPRECATED_REMOVED
+#define MBEDTLS_AES_ROM_TABLES
+#define MBEDTLS_CIPHER_MODE_CBC
+#define MBEDTLS_ECP_DP_SECP192R1_ENABLED
+#define MBEDTLS_ECP_DP_SECP224R1_ENABLED
+#define MBEDTLS_ECP_DP_SECP256R1_ENABLED
+#define MBEDTLS_ECP_DP_SECP384R1_ENABLED
+#define MBEDTLS_ECP_DP_SECP521R1_ENABLED
+#define MBEDTLS_ECP_DP_SECP192K1_ENABLED
+#define MBEDTLS_ECP_DP_SECP224K1_ENABLED
+#define MBEDTLS_ECP_DP_SECP256K1_ENABLED
+#define MBEDTLS_KEY_EXCHANGE_RSA_ENABLED
+// #define MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED // enabling this currently breaks ssl_data.py test
+#define MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
+#define MBEDTLS_NO_PLATFORM_ENTROPY
+#define MBEDTLS_PKCS1_V15
+#define MBEDTLS_SHA256_SMALLER
+#define MBEDTLS_SSL_PROTO_TLS1
+#define MBEDTLS_SSL_PROTO_TLS1_1
+#define MBEDTLS_SSL_PROTO_TLS1_2
+#define MBEDTLS_SSL_SERVER_NAME_INDICATION
+
+// Use a smaller output buffer to reduce size of SSL context.
+#define MBEDTLS_SSL_MAX_CONTENT_LEN (16384)
+#define MBEDTLS_SSL_IN_CONTENT_LEN (MBEDTLS_SSL_MAX_CONTENT_LEN)
+#define MBEDTLS_SSL_OUT_CONTENT_LEN (4096)
+
+// Enable mbedtls modules.
+#define MBEDTLS_AES_C
+#define MBEDTLS_ASN1_PARSE_C
+#define MBEDTLS_ASN1_WRITE_C
+#define MBEDTLS_BIGNUM_C
+#define MBEDTLS_CIPHER_C
+#define MBEDTLS_CTR_DRBG_C
+#define MBEDTLS_ECDH_C
+#define MBEDTLS_ECDSA_C
+#define MBEDTLS_ECP_C
+#define MBEDTLS_ENTROPY_C
+#define MBEDTLS_ERROR_C
+#define MBEDTLS_MD_C
+#define MBEDTLS_MD5_C
+#define MBEDTLS_OID_C
+#define MBEDTLS_PKCS5_C
+#define MBEDTLS_PK_C
+#define MBEDTLS_PK_PARSE_C
+#define MBEDTLS_PLATFORM_C
+#define MBEDTLS_RSA_C
+#define MBEDTLS_SHA1_C
+#define MBEDTLS_SHA256_C
+#define MBEDTLS_SHA512_C
+#define MBEDTLS_SSL_CLI_C
+#define MBEDTLS_SSL_SRV_C
+#define MBEDTLS_SSL_TLS_C
+#define MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_KEY_EXCHANGE
+#define MBEDTLS_X509_CRT_PARSE_C
+#define MBEDTLS_X509_USE_C
+
+// A port may enable this option to select additional bare-metal configuration.
+#if MICROPY_MBEDTLS_CONFIG_BARE_METAL
+
+// Bare-metal mbedtls configuration.
+#define MBEDTLS_PLATFORM_MEMORY
+#define MBEDTLS_PLATFORM_NO_STD_FUNCTIONS
+#define MBEDTLS_ENTROPY_HARDWARE_ALT
+
+// Bare-metal memory allocation hooks.
+#include
+#include
+void *m_tracked_calloc(size_t nmemb, size_t size);
+void m_tracked_free(void *ptr);
+#define MBEDTLS_PLATFORM_STD_CALLOC m_tracked_calloc
+#define MBEDTLS_PLATFORM_STD_FREE m_tracked_free
+#define MBEDTLS_PLATFORM_SNPRINTF_MACRO snprintf
+
+#endif
+
+// Include mbedtls configuration checker.
+#include "mbedtls/check_config.h"
+
+#endif // MICROPY_INCLUDED_MBEDTLS_CONFIG_COMMON_H
diff --git a/extmod/modbluetooth.c b/extmod/modbluetooth.c
index 6bdea1616f05..e65851d6b4bb 100644
--- a/extmod/modbluetooth.c
+++ b/extmod/modbluetooth.c
@@ -34,6 +34,7 @@
#include "py/objarray.h"
#include "py/qstr.h"
#include "py/runtime.h"
+#include "py/stackctrl.h"
#include "extmod/modbluetooth.h"
#include
@@ -51,6 +52,9 @@
#error pairing and bonding require synchronous modbluetooth events
#endif
+// NimBLE can have fragmented data for GATTC events, so requires reassembly.
+#define MICROPY_PY_BLUETOOTH_USE_GATTC_EVENT_DATA_REASSEMBLY MICROPY_BLUETOOTH_NIMBLE
+
#define MP_BLUETOOTH_CONNECT_DEFAULT_SCAN_DURATION_MS 2000
#define MICROPY_PY_BLUETOOTH_MAX_EVENT_DATA_TUPLE_LEN 5
@@ -239,16 +243,16 @@ STATIC void ringbuf_get_uuid(ringbuf_t *ringbuf, mp_obj_bluetooth_uuid_t *uuid)
#endif // !MICROPY_PY_BLUETOOTH_USE_SYNC_EVENTS
-const mp_obj_type_t mp_type_bluetooth_uuid = {
- { &mp_type_type },
- .name = MP_QSTR_UUID,
- .make_new = bluetooth_uuid_make_new,
- .unary_op = bluetooth_uuid_unary_op,
- .binary_op = bluetooth_uuid_binary_op,
- .locals_dict = NULL,
- .print = bluetooth_uuid_print,
- .buffer_p = { .get_buffer = bluetooth_uuid_get_buffer },
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ mp_type_bluetooth_uuid,
+ MP_QSTR_UUID,
+ MP_TYPE_FLAG_NONE,
+ make_new, bluetooth_uuid_make_new,
+ unary_op, bluetooth_uuid_unary_op,
+ binary_op, bluetooth_uuid_binary_op,
+ print, bluetooth_uuid_print,
+ buffer, bluetooth_uuid_get_buffer
+ );
// ----------------------------------------------------------------------------
// Bluetooth object: General
@@ -528,43 +532,41 @@ STATIC int bluetooth_gatts_register_service(mp_obj_t uuid_in, mp_obj_t character
// Optional third element, iterable of descriptors.
if (characteristic_len >= 3) {
- mp_obj_t descriptors_len_in = mp_obj_len(characteristic_items[2]);
- num_descriptors[characteristic_index] = mp_obj_get_int(descriptors_len_in);
+ mp_int_t n = mp_obj_get_int(mp_obj_len(characteristic_items[2]));
+ if (n) {
+ num_descriptors[characteristic_index] = n;
+
+ // Grow the flattened uuids and flags arrays with this many more descriptors.
+ descriptor_uuids = m_renew(mp_obj_bluetooth_uuid_t *, descriptor_uuids, descriptor_index, descriptor_index + num_descriptors[characteristic_index]);
+ descriptor_flags = m_renew(uint16_t, descriptor_flags, descriptor_index, descriptor_index + num_descriptors[characteristic_index]);
+
+ // Also grow the handles array.
+ *handles = m_renew(uint16_t, *handles, *num_handles, *num_handles + num_descriptors[characteristic_index]);
+
+ mp_obj_iter_buf_t iter_buf_desc;
+ mp_obj_t iterable_desc = mp_getiter(characteristic_items[2], &iter_buf_desc);
+ mp_obj_t descriptor_obj;
+
+ // Extract out descriptors for this characteristic.
+ while ((descriptor_obj = mp_iternext(iterable_desc)) != MP_OBJ_STOP_ITERATION) {
+ // (uuid, flags,)
+ mp_obj_t *descriptor_items;
+ mp_obj_get_array_fixed_n(descriptor_obj, 2, &descriptor_items);
+ mp_obj_t desc_uuid_obj = descriptor_items[0];
+ if (!mp_obj_is_type(desc_uuid_obj, &mp_type_bluetooth_uuid)) {
+ mp_raise_ValueError(MP_ERROR_TEXT("invalid descriptor UUID"));
+ }
- if (num_descriptors[characteristic_index] == 0) {
- continue;
- }
+ descriptor_uuids[descriptor_index] = MP_OBJ_TO_PTR(desc_uuid_obj);
+ descriptor_flags[descriptor_index] = mp_obj_get_int(descriptor_items[1]);
+ ++descriptor_index;
- // Grow the flattened uuids and flags arrays with this many more descriptors.
- descriptor_uuids = m_renew(mp_obj_bluetooth_uuid_t *, descriptor_uuids, descriptor_index, descriptor_index + num_descriptors[characteristic_index]);
- descriptor_flags = m_renew(uint16_t, descriptor_flags, descriptor_index, descriptor_index + num_descriptors[characteristic_index]);
-
- // Also grow the handles array.
- *handles = m_renew(uint16_t, *handles, *num_handles, *num_handles + num_descriptors[characteristic_index]);
-
- mp_obj_iter_buf_t iter_buf_desc;
- mp_obj_t iterable_desc = mp_getiter(characteristic_items[2], &iter_buf_desc);
- mp_obj_t descriptor_obj;
-
- // Extract out descriptors for this characteristic.
- while ((descriptor_obj = mp_iternext(iterable_desc)) != MP_OBJ_STOP_ITERATION) {
- // (uuid, flags,)
- mp_obj_t *descriptor_items;
- mp_obj_get_array_fixed_n(descriptor_obj, 2, &descriptor_items);
- mp_obj_t desc_uuid_obj = descriptor_items[0];
- if (!mp_obj_is_type(desc_uuid_obj, &mp_type_bluetooth_uuid)) {
- mp_raise_ValueError(MP_ERROR_TEXT("invalid descriptor UUID"));
+ (*handles)[handle_index++] = 0xffff;
}
- descriptor_uuids[descriptor_index] = MP_OBJ_TO_PTR(desc_uuid_obj);
- descriptor_flags[descriptor_index] = mp_obj_get_int(descriptor_items[1]);
- ++descriptor_index;
-
- (*handles)[handle_index++] = 0xffff;
+ // Reflect that we've grown the handles array.
+ *num_handles += num_descriptors[characteristic_index];
}
-
- // Reflect that we've grown the handles array.
- *num_handles += num_descriptors[characteristic_index];
}
characteristic_uuids[characteristic_index] = MP_OBJ_TO_PTR(uuid_obj);
@@ -731,7 +733,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bluetooth_ble_gap_passkey_obj, 4, 4,
STATIC mp_obj_t bluetooth_ble_gatts_read(mp_obj_t self_in, mp_obj_t value_handle_in) {
(void)self_in;
size_t len = 0;
- uint8_t *buf;
+ const uint8_t *buf;
mp_bluetooth_gatts_read(mp_obj_get_int(value_handle_in), &buf, &len);
return mp_obj_new_bytes(buf, len);
}
@@ -749,32 +751,30 @@ STATIC mp_obj_t bluetooth_ble_gatts_write(size_t n_args, const mp_obj_t *args) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bluetooth_ble_gatts_write_obj, 3, 4, bluetooth_ble_gatts_write);
-STATIC mp_obj_t bluetooth_ble_gatts_notify(size_t n_args, const mp_obj_t *args) {
+STATIC mp_obj_t bluetooth_ble_gatts_notify_indicate(size_t n_args, const mp_obj_t *args, int gatts_op) {
mp_int_t conn_handle = mp_obj_get_int(args[1]);
mp_int_t value_handle = mp_obj_get_int(args[2]);
+ const uint8_t *value = NULL;
+ size_t value_len = 0;
if (n_args == 4 && args[3] != mp_const_none) {
mp_buffer_info_t bufinfo = {0};
mp_get_buffer_raise(args[3], &bufinfo, MP_BUFFER_READ);
- int err = mp_bluetooth_gatts_notify_send(conn_handle, value_handle, bufinfo.buf, bufinfo.len);
- bluetooth_handle_errno(err);
- return mp_const_none;
- } else {
- int err = mp_bluetooth_gatts_notify(conn_handle, value_handle);
- return bluetooth_handle_errno(err);
+ value = bufinfo.buf;
+ value_len = bufinfo.len;
}
+ return bluetooth_handle_errno(mp_bluetooth_gatts_notify_indicate(conn_handle, value_handle, gatts_op, value, value_len));
}
-STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bluetooth_ble_gatts_notify_obj, 3, 4, bluetooth_ble_gatts_notify);
-STATIC mp_obj_t bluetooth_ble_gatts_indicate(mp_obj_t self_in, mp_obj_t conn_handle_in, mp_obj_t value_handle_in) {
- (void)self_in;
- mp_int_t conn_handle = mp_obj_get_int(conn_handle_in);
- mp_int_t value_handle = mp_obj_get_int(value_handle_in);
+STATIC mp_obj_t bluetooth_ble_gatts_notify(size_t n_args, const mp_obj_t *args) {
+ return bluetooth_ble_gatts_notify_indicate(n_args, args, MP_BLUETOOTH_GATTS_OP_NOTIFY);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bluetooth_ble_gatts_notify_obj, 3, 4, bluetooth_ble_gatts_notify);
- int err = mp_bluetooth_gatts_indicate(conn_handle, value_handle);
- return bluetooth_handle_errno(err);
+STATIC mp_obj_t bluetooth_ble_gatts_indicate(size_t n_args, const mp_obj_t *args) {
+ return bluetooth_ble_gatts_notify_indicate(n_args, args, MP_BLUETOOTH_GATTS_OP_INDICATE);
}
-STATIC MP_DEFINE_CONST_FUN_OBJ_3(bluetooth_ble_gatts_indicate_obj, bluetooth_ble_gatts_indicate);
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bluetooth_ble_gatts_indicate_obj, 3, 4, bluetooth_ble_gatts_indicate);
STATIC mp_obj_t bluetooth_ble_gatts_set_buffer(size_t n_args, const mp_obj_t *args) {
mp_int_t value_handle = mp_obj_get_int(args[1]);
@@ -841,12 +841,11 @@ STATIC mp_obj_t bluetooth_ble_gattc_write(size_t n_args, const mp_obj_t *args) {
mp_obj_t data = args[3];
mp_buffer_info_t bufinfo = {0};
mp_get_buffer_raise(data, &bufinfo, MP_BUFFER_READ);
- size_t len = bufinfo.len;
unsigned int mode = MP_BLUETOOTH_WRITE_MODE_NO_RESPONSE;
if (n_args == 5) {
mode = mp_obj_get_int(args[4]);
}
- return bluetooth_handle_errno(mp_bluetooth_gattc_write(conn_handle, value_handle, bufinfo.buf, &len, mode));
+ return bluetooth_handle_errno(mp_bluetooth_gattc_write(conn_handle, value_handle, bufinfo.buf, bufinfo.len, mode));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bluetooth_ble_gattc_write_obj, 4, 5, bluetooth_ble_gattc_write);
@@ -977,12 +976,13 @@ STATIC const mp_rom_map_elem_t bluetooth_ble_locals_dict_table[] = {
};
STATIC MP_DEFINE_CONST_DICT(bluetooth_ble_locals_dict, bluetooth_ble_locals_dict_table);
-STATIC const mp_obj_type_t mp_type_bluetooth_ble = {
- { &mp_type_type },
- .name = MP_QSTR_BLE,
- .make_new = bluetooth_ble_make_new,
- .locals_dict = (void *)&bluetooth_ble_locals_dict,
-};
+STATIC MP_DEFINE_CONST_OBJ_TYPE(
+ mp_type_bluetooth_ble,
+ MP_QSTR_BLE,
+ MP_TYPE_FLAG_NONE,
+ make_new, bluetooth_ble_make_new,
+ locals_dict, &bluetooth_ble_locals_dict
+ );
STATIC const mp_rom_map_elem_t mp_module_bluetooth_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_ubluetooth) },
@@ -1102,7 +1102,7 @@ STATIC mp_obj_t bluetooth_ble_invoke_irq(mp_obj_t none_in) {
// conn_handle, start_handle, end_handle, uuid
ringbuf_extract(&o->ringbuf, data_tuple, 3, 0, NULL, 0, &o->irq_data_uuid, NULL);
} else if (event == MP_BLUETOOTH_IRQ_GATTC_CHARACTERISTIC_RESULT) {
- // conn_handle, def_handle, value_handle, properties, uuid
+ // conn_handle, end_handle, value_handle, properties, uuid
ringbuf_extract(&o->ringbuf, data_tuple, 3, 1, NULL, 0, &o->irq_data_uuid, NULL);
} else if (event == MP_BLUETOOTH_IRQ_GATTC_DESCRIPTOR_RESULT) {
// conn_handle, handle, uuid
@@ -1135,15 +1135,11 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(bluetooth_ble_invoke_irq_obj, bluetooth_ble_inv
#if MICROPY_PY_BLUETOOTH_USE_SYNC_EVENTS
-STATIC mp_obj_t invoke_irq_handler(uint16_t event,
+STATIC mp_obj_t invoke_irq_handler_run(uint16_t event,
const mp_int_t *numeric, size_t n_unsigned, size_t n_signed,
const uint8_t *addr,
const mp_obj_bluetooth_uuid_t *uuid,
- const uint8_t **data, size_t *data_len, size_t n_data) {
- mp_obj_bluetooth_ble_t *o = MP_OBJ_TO_PTR(MP_STATE_VM(bluetooth));
- if (o->irq_handler == mp_const_none) {
- return mp_const_none;
- }
+ const uint8_t **data, uint16_t *data_len, size_t n_data) {
mp_obj_array_t mv_addr;
mp_obj_array_t mv_data[2];
@@ -1168,6 +1164,34 @@ STATIC mp_obj_t invoke_irq_handler(uint16_t event,
data_tuple->items[data_tuple->len++] = MP_OBJ_FROM_PTR(uuid);
}
#endif
+
+ #if MICROPY_PY_BLUETOOTH_USE_GATTC_EVENT_DATA_REASSEMBLY
+ void *buf_to_free = NULL;
+ uint16_t buf_to_free_len = 0;
+ if (event == MP_BLUETOOTH_IRQ_GATTC_NOTIFY || event == MP_BLUETOOTH_IRQ_GATTC_INDICATE || event == MP_BLUETOOTH_IRQ_GATTC_READ_RESULT) {
+ if (n_data > 1) {
+ // Fragmented buffer, need to combine into a new heap-allocated buffer
+ // in order to pass to Python.
+ // Only gattc_on_data_available calls this code, so data and data_len are writable.
+ uint16_t total_len = 0;
+ for (size_t i = 0; i < n_data; ++i) {
+ total_len += data_len[i];
+ }
+ uint8_t *buf = m_new(uint8_t, total_len);
+ uint8_t *p = buf;
+ for (size_t i = 0; i < n_data; ++i) {
+ memcpy(p, data[i], data_len[i]);
+ p += data_len[i];
+ }
+ data[0] = buf;
+ data_len[0] = total_len;
+ n_data = 1;
+ buf_to_free = buf;
+ buf_to_free_len = total_len;
+ }
+ }
+ #endif
+
for (size_t i = 0; i < n_data; ++i) {
if (data[i]) {
mp_obj_memoryview_init(&mv_data[i], 'B', 0, data_len[i], (void *)data[i]);
@@ -1176,15 +1200,111 @@ STATIC mp_obj_t invoke_irq_handler(uint16_t event,
data_tuple->items[data_tuple->len++] = mp_const_none;
}
}
+
assert(data_tuple->len <= MICROPY_PY_BLUETOOTH_MAX_EVENT_DATA_TUPLE_LEN);
+ mp_obj_bluetooth_ble_t *o = MP_OBJ_TO_PTR(MP_STATE_VM(bluetooth));
mp_obj_t result = mp_call_function_2(o->irq_handler, MP_OBJ_NEW_SMALL_INT(event), MP_OBJ_FROM_PTR(data_tuple));
+ #if MICROPY_PY_BLUETOOTH_USE_GATTC_EVENT_DATA_REASSEMBLY
+ if (buf_to_free != NULL) {
+ m_del(uint8_t, (uint8_t *)buf_to_free, buf_to_free_len);
+ }
+ #endif
+
mp_local_free(data_tuple);
return result;
}
+STATIC mp_obj_t invoke_irq_handler_run_protected(uint16_t event,
+ const mp_int_t *numeric, size_t n_unsigned, size_t n_signed,
+ const uint8_t *addr,
+ const mp_obj_bluetooth_uuid_t *uuid,
+ const uint8_t **data, uint16_t *data_len, size_t n_data) {
+
+ mp_obj_bluetooth_ble_t *o = MP_OBJ_TO_PTR(MP_STATE_VM(bluetooth));
+ if (o->irq_handler == mp_const_none) {
+ return mp_const_none;
+ }
+
+ mp_obj_t result = mp_const_none;
+ nlr_buf_t nlr;
+ if (nlr_push(&nlr) == 0) {
+ result = invoke_irq_handler_run(event, numeric, n_unsigned, n_signed, addr, uuid, data, data_len, n_data);
+ nlr_pop();
+ } else {
+ // Uncaught exception, print it out.
+ mp_printf(MICROPY_ERROR_PRINTER, "Unhandled exception in IRQ callback handler\n");
+ mp_obj_print_exception(MICROPY_ERROR_PRINTER, MP_OBJ_FROM_PTR(nlr.ret_val));
+
+ // Disable the BLE IRQ handler.
+ o->irq_handler = mp_const_none;
+ }
+
+ return result;
+}
+
+#if MICROPY_PY_BLUETOOTH_USE_SYNC_EVENTS_WITH_INTERLOCK
+
+// On some systems the BLE event callbacks may occur on a system thread which is not
+// a MicroPython thread. In such cases the callback must set up relevant MicroPython
+// state and obtain the GIL, to synchronised with the rest of the runtime.
+
+#if MICROPY_ENABLE_PYSTACK
+#error not supported
+#endif
+
+STATIC mp_obj_t invoke_irq_handler(uint16_t event,
+ const mp_int_t *numeric, size_t n_unsigned, size_t n_signed,
+ const uint8_t *addr,
+ const mp_obj_bluetooth_uuid_t *uuid,
+ const uint8_t **data, uint16_t *data_len, size_t n_data) {
+
+ // This code may run on an existing MicroPython thread, or a non-MicroPython thread
+ // that's not using the mp_thread_get_state() value. In the former case the state
+ // must be restored once this callback finishes.
+ mp_state_thread_t *ts_orig = mp_thread_get_state();
+
+ mp_state_thread_t ts;
+ if (ts_orig == NULL) {
+ mp_thread_set_state(&ts);
+ mp_stack_set_top(&ts + 1); // need to include ts in root-pointer scan
+ mp_stack_set_limit(MICROPY_PY_BLUETOOTH_SYNC_EVENT_STACK_SIZE - 1024);
+ ts.gc_lock_depth = 0;
+ ts.mp_pending_exception = MP_OBJ_NULL;
+ mp_locals_set(mp_state_ctx.thread.dict_locals); // set from the outer context
+ mp_globals_set(mp_state_ctx.thread.dict_globals); // set from the outer context
+ MP_THREAD_GIL_ENTER();
+ }
+
+ mp_sched_lock();
+ mp_obj_t result = invoke_irq_handler_run_protected(event, numeric, n_unsigned, n_signed, addr, uuid, data, data_len, n_data);
+ mp_sched_unlock();
+
+ if (ts_orig == NULL) {
+ MP_THREAD_GIL_EXIT();
+ mp_thread_set_state(ts_orig);
+ }
+
+ return result;
+}
+
+#else
+
+// BLE event callbacks are called directly from the MicroPython runtime, so additional
+// synchronisation is not needed, and BLE event handlers can be called directly.
+
+STATIC mp_obj_t invoke_irq_handler(uint16_t event,
+ const mp_int_t *numeric, size_t n_unsigned, size_t n_signed,
+ const uint8_t *addr,
+ const mp_obj_bluetooth_uuid_t *uuid,
+ const uint8_t **data, uint16_t *data_len, size_t n_data) {
+ return invoke_irq_handler_run_protected(event, numeric, n_unsigned, n_signed, addr, uuid, data, data_len, n_data);
+}
+
+#endif
+
#define NULL_NUMERIC NULL
#define NULL_ADDR NULL
#define NULL_UUID NULL
@@ -1207,7 +1327,7 @@ void mp_bluetooth_gatts_on_encryption_update(uint16_t conn_handle, bool encrypte
invoke_irq_handler(MP_BLUETOOTH_IRQ_ENCRYPTION_UPDATE, args, 5, 0, NULL_ADDR, NULL_UUID, NULL_DATA, NULL_DATA_LEN, 0);
}
-bool mp_bluetooth_gap_on_get_secret(uint8_t type, uint8_t index, const uint8_t *key, size_t key_len, const uint8_t **value, size_t *value_len) {
+bool mp_bluetooth_gap_on_get_secret(uint8_t type, uint8_t index, const uint8_t *key, uint16_t key_len, const uint8_t **value, size_t *value_len) {
mp_int_t args[] = {type, index};
mp_obj_t result = invoke_irq_handler(MP_BLUETOOTH_IRQ_GET_SECRET, args, 2, 0, NULL_ADDR, NULL_UUID, &key, &key_len, 1);
if (result == mp_const_none) {
@@ -1223,7 +1343,7 @@ bool mp_bluetooth_gap_on_get_secret(uint8_t type, uint8_t index, const uint8_t *
bool mp_bluetooth_gap_on_set_secret(uint8_t type, const uint8_t *key, size_t key_len, const uint8_t *value, size_t value_len) {
mp_int_t args[] = { type };
const uint8_t *data[] = {key, value};
- size_t data_len[] = {key_len, value_len};
+ uint16_t data_len[] = {key_len, value_len};
mp_obj_t result = invoke_irq_handler(MP_BLUETOOTH_IRQ_SET_SECRET, args, 1, 0, NULL_ADDR, NULL_UUID, data, data_len, 2);
return mp_obj_is_true(result);
}
@@ -1294,7 +1414,7 @@ void mp_bluetooth_gap_on_scan_complete(void) {
invoke_irq_handler(MP_BLUETOOTH_IRQ_SCAN_DONE, NULL_NUMERIC, 0, 0, NULL_ADDR, NULL_UUID, NULL_DATA, NULL_DATA_LEN, 0);
}
-void mp_bluetooth_gap_on_scan_result(uint8_t addr_type, const uint8_t *addr, uint8_t adv_type, const int8_t rssi, const uint8_t *data, size_t data_len) {
+void mp_bluetooth_gap_on_scan_result(uint8_t addr_type, const uint8_t *addr, uint8_t adv_type, const int8_t rssi, const uint8_t *data, uint16_t data_len) {
mp_int_t args[] = {addr_type, adv_type, rssi};
invoke_irq_handler(MP_BLUETOOTH_IRQ_SCAN_RESULT, args, 1, 2, addr, NULL_UUID, &data, &data_len, 1);
}
@@ -1306,8 +1426,9 @@ void mp_bluetooth_gattc_on_primary_service_result(uint16_t conn_handle, uint16_t
invoke_irq_handler(MP_BLUETOOTH_IRQ_GATTC_SERVICE_RESULT, args, 3, 0, NULL_ADDR, service_uuid, NULL_DATA, NULL_DATA_LEN, 0);
}
-void mp_bluetooth_gattc_on_characteristic_result(uint16_t conn_handle, uint16_t def_handle, uint16_t value_handle, uint8_t properties, mp_obj_bluetooth_uuid_t *characteristic_uuid) {
- mp_int_t args[] = {conn_handle, def_handle, value_handle, properties};
+void mp_bluetooth_gattc_on_characteristic_result(uint16_t conn_handle, uint16_t value_handle, uint16_t end_handle, uint8_t properties, mp_obj_bluetooth_uuid_t *characteristic_uuid) {
+ // Note: "end_handle" replaces "def_handle" from the original version of this event.
+ mp_int_t args[] = {conn_handle, end_handle, value_handle, properties};
invoke_irq_handler(MP_BLUETOOTH_IRQ_GATTC_CHARACTERISTIC_RESULT, args, 4, 0, NULL_ADDR, characteristic_uuid, NULL_DATA, NULL_DATA_LEN, 0);
}
@@ -1322,35 +1443,8 @@ void mp_bluetooth_gattc_on_discover_complete(uint8_t event, uint16_t conn_handle
}
void mp_bluetooth_gattc_on_data_available(uint8_t event, uint16_t conn_handle, uint16_t value_handle, const uint8_t **data, uint16_t *data_len, size_t num) {
- const uint8_t *combined_data;
- size_t total_len;
-
- if (num > 1) {
- // Fragmented buffer, need to combine into a new heap-allocated buffer
- // in order to pass to Python.
- total_len = 0;
- for (size_t i = 0; i < num; ++i) {
- total_len += data_len[i];
- }
- uint8_t *buf = m_new(uint8_t, total_len);
- uint8_t *p = buf;
- for (size_t i = 0; i < num; ++i) {
- memcpy(p, data[i], data_len[i]);
- p += data_len[i];
- }
- combined_data = buf;
- } else {
- // Single buffer, use directly.
- combined_data = *data;
- total_len = *data_len;
- }
-
mp_int_t args[] = {conn_handle, value_handle};
- invoke_irq_handler(event, args, 2, 0, NULL_ADDR, NULL_UUID, &combined_data, &total_len, 1);
-
- if (num > 1) {
- m_del(uint8_t, (uint8_t *)combined_data, total_len);
- }
+ invoke_irq_handler(event, args, 2, 0, NULL_ADDR, NULL_UUID, data, data_len, num);
}
void mp_bluetooth_gattc_on_read_write_status(uint8_t event, uint16_t conn_handle, uint16_t value_handle, uint16_t status) {
@@ -1482,7 +1576,7 @@ void mp_bluetooth_gap_on_scan_complete(void) {
schedule_ringbuf(atomic_state);
}
-void mp_bluetooth_gap_on_scan_result(uint8_t addr_type, const uint8_t *addr, uint8_t adv_type, const int8_t rssi, const uint8_t *data, size_t data_len) {
+void mp_bluetooth_gap_on_scan_result(uint8_t addr_type, const uint8_t *addr, uint8_t adv_type, const int8_t rssi, const uint8_t *data, uint16_t data_len) {
MICROPY_PY_BLUETOOTH_ENTER
mp_obj_bluetooth_ble_t *o = MP_OBJ_TO_PTR(MP_STATE_VM(bluetooth));
data_len = MIN(o->irq_data_data_alloc, data_len);
@@ -1519,12 +1613,13 @@ void mp_bluetooth_gattc_on_primary_service_result(uint16_t conn_handle, uint16_t
schedule_ringbuf(atomic_state);
}
-void mp_bluetooth_gattc_on_characteristic_result(uint16_t conn_handle, uint16_t def_handle, uint16_t value_handle, uint8_t properties, mp_obj_bluetooth_uuid_t *characteristic_uuid) {
+void mp_bluetooth_gattc_on_characteristic_result(uint16_t conn_handle, uint16_t value_handle, uint16_t end_handle, uint8_t properties, mp_obj_bluetooth_uuid_t *characteristic_uuid) {
MICROPY_PY_BLUETOOTH_ENTER
mp_obj_bluetooth_ble_t *o = MP_OBJ_TO_PTR(MP_STATE_VM(bluetooth));
if (enqueue_irq(o, 2 + 2 + 2 + 1 + characteristic_uuid->type, MP_BLUETOOTH_IRQ_GATTC_CHARACTERISTIC_RESULT)) {
ringbuf_put16(&o->ringbuf, conn_handle);
- ringbuf_put16(&o->ringbuf, def_handle);
+ // Note: "end_handle" replaces "def_handle" from the original version of this event.
+ ringbuf_put16(&o->ringbuf, end_handle);
ringbuf_put16(&o->ringbuf, value_handle);
ringbuf_put(&o->ringbuf, properties);
ringbuf_put_uuid(&o->ringbuf, characteristic_uuid);
@@ -1620,7 +1715,7 @@ mp_bluetooth_gatts_db_entry_t *mp_bluetooth_gatts_db_lookup(mp_gatts_db_t db, ui
return MP_OBJ_TO_PTR(elem->value);
}
-int mp_bluetooth_gatts_db_read(mp_gatts_db_t db, uint16_t handle, uint8_t **value, size_t *value_len) {
+int mp_bluetooth_gatts_db_read(mp_gatts_db_t db, uint16_t handle, const uint8_t **value, size_t *value_len) {
MICROPY_PY_BLUETOOTH_ENTER
mp_bluetooth_gatts_db_entry_t *entry = mp_bluetooth_gatts_db_lookup(db, handle);
if (entry) {
@@ -1675,4 +1770,6 @@ int mp_bluetooth_gatts_db_resize(mp_gatts_db_t db, uint16_t handle, size_t len,
return entry ? 0 : MP_EINVAL;
}
+MP_REGISTER_ROOT_POINTER(mp_obj_t bluetooth);
+
#endif // MICROPY_PY_BLUETOOTH
diff --git a/extmod/modbluetooth.h b/extmod/modbluetooth.h
index 52053045f852..630a2705231e 100644
--- a/extmod/modbluetooth.h
+++ b/extmod/modbluetooth.h
@@ -84,7 +84,7 @@
#define MP_BLUETOOTH_DEFAULT_ATTR_LEN (20)
#endif
-#define MP_BLUETOOTH_CCCB_LEN (2)
+#define MP_BLUETOOTH_CCCD_LEN (2)
// Advertisement packet lengths
#define MP_BLUETOOTH_GAP_ADV_MAX_LEN (32)
@@ -186,6 +186,10 @@
#define MP_BLUETOOTH_PASSKEY_ACTION_DISPLAY (3)
#define MP_BLUETOOTH_PASSKEY_ACTION_NUMERIC_COMPARISON (4)
+// These are the ops for mp_bluetooth_gatts_notify_indicate.
+#define MP_BLUETOOTH_GATTS_OP_NOTIFY (1)
+#define MP_BLUETOOTH_GATTS_OP_INDICATE (2)
+
/*
These aren't included in the module for space reasons, but can be used
in your Python code if necessary.
@@ -333,15 +337,11 @@ int mp_bluetooth_gatts_register_service(mp_obj_bluetooth_uuid_t *service_uuid, m
int mp_bluetooth_gatts_register_service_end(void);
// Read the value from the local gatts db (likely this has been written by a central).
-int mp_bluetooth_gatts_read(uint16_t value_handle, uint8_t **value, size_t *value_len);
+int mp_bluetooth_gatts_read(uint16_t value_handle, const uint8_t **value, size_t *value_len);
// Write a value to the local gatts db (ready to be queried by a central). Optionally send notifications/indications.
int mp_bluetooth_gatts_write(uint16_t value_handle, const uint8_t *value, size_t value_len, bool send_update);
-// Notify the central that it should do a read.
-int mp_bluetooth_gatts_notify(uint16_t conn_handle, uint16_t value_handle);
-// Notify the central, including a data payload. (Note: does not set the gatts db value).
-int mp_bluetooth_gatts_notify_send(uint16_t conn_handle, uint16_t value_handle, const uint8_t *value, size_t value_len);
-// Indicate the central.
-int mp_bluetooth_gatts_indicate(uint16_t conn_handle, uint16_t value_handle);
+// Send a notification/indication to the central, optionally with custom payload (otherwise the DB value is used).
+int mp_bluetooth_gatts_notify_indicate(uint16_t conn_handle, uint16_t value_handle, int gatts_op, const uint8_t *value, size_t value_len);
// Resize and enable/disable append-mode on a value.
// Append-mode means that remote writes will append and local reads will clear after reading.
@@ -391,7 +391,7 @@ int mp_bluetooth_gattc_discover_descriptors(uint16_t conn_handle, uint16_t start
int mp_bluetooth_gattc_read(uint16_t conn_handle, uint16_t value_handle);
// 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);
+int mp_bluetooth_gattc_write(uint16_t conn_handle, uint16_t value_handle, const uint8_t *value, size_t value_len, unsigned int mode);
// Initiate MTU exchange for a specific connection using the preferred MTU.
int mp_bluetooth_gattc_exchange_mtu(uint16_t conn_handle);
@@ -426,7 +426,7 @@ void mp_bluetooth_gatts_on_encryption_update(uint16_t conn_handle, bool encrypte
// For get, if key is NULL, then the implementation must return the index'th matching key. Otherwise it should return a specific key.
// For set, if value is NULL, then delete.
// The "type" is stack-specific, but could also be used to implement versioning.
-bool mp_bluetooth_gap_on_get_secret(uint8_t type, uint8_t index, const uint8_t *key, size_t key_len, const uint8_t **value, size_t *value_len);
+bool mp_bluetooth_gap_on_get_secret(uint8_t type, uint8_t index, const uint8_t *key, uint16_t key_len, const uint8_t **value, size_t *value_len);
bool mp_bluetooth_gap_on_set_secret(uint8_t type, const uint8_t *key, size_t key_len, const uint8_t *value, size_t value_len);
// Call this when a passkey verification needs to be processed.
@@ -451,7 +451,7 @@ void mp_bluetooth_gatts_on_mtu_exchanged(uint16_t conn_handle, uint16_t value);
void mp_bluetooth_gap_on_scan_complete(void);
// Notify modbluetooth of a scan result.
-void mp_bluetooth_gap_on_scan_result(uint8_t addr_type, const uint8_t *addr, uint8_t adv_type, const int8_t rssi, const uint8_t *data, size_t data_len);
+void mp_bluetooth_gap_on_scan_result(uint8_t addr_type, const uint8_t *addr, uint8_t adv_type, const int8_t rssi, const uint8_t *data, uint16_t data_len);
#endif // MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE
#if MICROPY_PY_BLUETOOTH_ENABLE_GATT_CLIENT
@@ -459,7 +459,7 @@ void mp_bluetooth_gap_on_scan_result(uint8_t addr_type, const uint8_t *addr, uin
void mp_bluetooth_gattc_on_primary_service_result(uint16_t conn_handle, uint16_t start_handle, uint16_t end_handle, mp_obj_bluetooth_uuid_t *service_uuid);
// Notify modbluetooth that a characteristic was found (either by discover-all-on-service, or discover-by-uuid-on-service).
-void mp_bluetooth_gattc_on_characteristic_result(uint16_t conn_handle, uint16_t def_handle, uint16_t value_handle, uint8_t properties, mp_obj_bluetooth_uuid_t *characteristic_uuid);
+void mp_bluetooth_gattc_on_characteristic_result(uint16_t conn_handle, uint16_t value_handle, uint16_t end_handle, uint8_t properties, mp_obj_bluetooth_uuid_t *characteristic_uuid);
// Notify modbluetooth that a descriptor was found.
void mp_bluetooth_gattc_on_descriptor_result(uint16_t conn_handle, uint16_t handle, mp_obj_bluetooth_uuid_t *descriptor_uuid);
@@ -508,7 +508,7 @@ STATIC inline void mp_bluetooth_gatts_db_reset(mp_gatts_db_t db) {
void mp_bluetooth_gatts_db_create_entry(mp_gatts_db_t db, uint16_t handle, size_t len);
mp_bluetooth_gatts_db_entry_t *mp_bluetooth_gatts_db_lookup(mp_gatts_db_t db, uint16_t handle);
-int mp_bluetooth_gatts_db_read(mp_gatts_db_t db, uint16_t handle, uint8_t **value, size_t *value_len);
+int mp_bluetooth_gatts_db_read(mp_gatts_db_t db, uint16_t handle, const uint8_t **value, size_t *value_len);
int mp_bluetooth_gatts_db_write(mp_gatts_db_t db, uint16_t handle, const uint8_t *value, size_t value_len);
int mp_bluetooth_gatts_db_resize(mp_gatts_db_t db, uint16_t handle, size_t len, bool append);
diff --git a/extmod/modbtree.c b/extmod/modbtree.c
index 60a5beec6814..e9c760a38971 100644
--- a/extmod/modbtree.c
+++ b/extmod/modbtree.c
@@ -24,16 +24,14 @@
* THE SOFTWARE.
*/
-#include
-#include
-#include // for declaration of global errno variable
-#include
-
#include "py/runtime.h"
#include "py/stream.h"
#if MICROPY_PY_BTREE
+#include
+#include // for declaration of global errno variable
+#include
#include
#include <../../btree/btree.h>
@@ -67,7 +65,7 @@ void __dbpanic(DB *db) {
}
STATIC mp_obj_btree_t *btree_new(DB *db, mp_obj_t stream) {
- mp_obj_btree_t *o = mp_obj_malloc(mp_obj_btree_t, &btree_type);
+ mp_obj_btree_t *o = mp_obj_malloc(mp_obj_btree_t, (mp_obj_type_t *)&btree_type);
o->stream = stream;
o->db = db;
o->start_key = mp_const_none;
@@ -76,6 +74,13 @@ STATIC mp_obj_btree_t *btree_new(DB *db, mp_obj_t stream) {
return o;
}
+STATIC void buf_to_dbt(mp_obj_t obj, DBT *dbt) {
+ mp_buffer_info_t bufinfo;
+ mp_get_buffer_raise(obj, &bufinfo, MP_BUFFER_READ);
+ dbt->data = bufinfo.buf;
+ dbt->size = bufinfo.len;
+}
+
STATIC void btree_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
(void)kind;
mp_obj_btree_t *self = MP_OBJ_TO_PTR(self_in);
@@ -98,8 +103,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);
+ buf_to_dbt(args[1], &key);
+ buf_to_dbt(args[2], &val);
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);
@@ -107,7 +112,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);
+ buf_to_dbt(args[1], &key);
int res = __bt_get(self->db, &key, &val, 0);
if (res == RET_SPECIAL) {
if (n_args > 2) {
@@ -126,7 +131,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);
+ buf_to_dbt(args[2], &key);
}
int res = __bt_seq(self->db, &key, &val, flags);
@@ -201,7 +206,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);
+ buf_to_dbt(self->start_key, &key);
flags = R_CURSOR;
} else if (desc) {
flags = R_LAST;
@@ -219,7 +224,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);
+ buf_to_dbt(self->end_key, &end_key);
BTREE *t = self->db->internal;
int cmp = t->bt_cmp(&key, &end_key);
if (desc) {
@@ -254,7 +259,7 @@ 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);
+ buf_to_dbt(index, &key);
int res = __bt_delete(self->db, &key, 0);
if (res == RET_SPECIAL) {
mp_raise_type(&mp_type_KeyError);
@@ -264,7 +269,7 @@ STATIC mp_obj_t btree_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
} else if (value == MP_OBJ_SENTINEL) {
// load
DBT key, val;
- key.data = (void *)mp_obj_str_get_data(index, &key.size);
+ buf_to_dbt(index, &key);
int res = __bt_get(self->db, &key, &val, 0);
if (res == RET_SPECIAL) {
mp_raise_type(&mp_type_KeyError);
@@ -274,8 +279,8 @@ STATIC mp_obj_t btree_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
} 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);
+ buf_to_dbt(index, &key);
+ buf_to_dbt(value, &val);
int res = __bt_put(self->db, &key, &val, 0);
CHECK_ERROR(res);
return mp_const_none;
@@ -287,7 +292,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);
+ buf_to_dbt(rhs_in, &key);
int res = __bt_get(self->db, &key, &val, 0);
CHECK_ERROR(res);
return mp_obj_new_bool(res != RET_SPECIAL);
@@ -312,17 +317,22 @@ STATIC const mp_rom_map_elem_t btree_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(btree_locals_dict, btree_locals_dict_table);
-STATIC const mp_obj_type_t btree_type = {
- { &mp_type_type },
- // Save on qstr's, reuse same as for module
- .name = MP_QSTR_btree,
- .print = btree_print,
+STATIC const mp_getiter_iternext_custom_t btree_getiter_iternext = {
.getiter = btree_getiter,
.iternext = btree_iternext,
- .binary_op = btree_binary_op,
- .subscr = btree_subscr,
- .locals_dict = (void *)&btree_locals_dict,
};
+
+STATIC MP_DEFINE_CONST_OBJ_TYPE(
+ btree_type,
+ MP_QSTR_btree,
+ MP_TYPE_FLAG_ITER_IS_CUSTOM,
+ // Save on qstr's, reuse same as for module
+ print, btree_print,
+ iter, &btree_getiter_iternext,
+ binary_op, btree_binary_op,
+ subscr, btree_subscr,
+ locals_dict, &btree_locals_dict
+ );
#endif
STATIC const FILEVTABLE btree_stream_fvtable = {
diff --git a/extmod/modframebuf.c b/extmod/modframebuf.c
index 5b6575d5a650..87f7609dd8a8 100644
--- a/extmod/modframebuf.c
+++ b/extmod/modframebuf.c
@@ -28,6 +28,7 @@
#include
#include "py/runtime.h"
+#include "py/binary.h"
#if MICROPY_PY_FRAMEBUF
@@ -240,11 +241,17 @@ STATIC mp_framebuf_p_t formats[] = {
[FRAMEBUF_MHMSB] = {mono_horiz_setpixel, mono_horiz_getpixel, mono_horiz_fill_rect},
};
-static inline void setpixel(const mp_obj_framebuf_t *fb, unsigned int x, unsigned int y, uint32_t col) {
+STATIC inline void setpixel(const mp_obj_framebuf_t *fb, unsigned int x, unsigned int y, uint32_t col) {
formats[fb->format].setpixel(fb, x, y, col);
}
-static inline uint32_t getpixel(const mp_obj_framebuf_t *fb, unsigned int x, unsigned int y) {
+STATIC void setpixel_checked(const mp_obj_framebuf_t *fb, mp_int_t x, mp_int_t y, mp_int_t col, mp_int_t mask) {
+ if (mask && 0 <= x && x < fb->width && 0 <= y && y < fb->height) {
+ setpixel(fb, x, y, col);
+ }
+}
+
+STATIC inline uint32_t getpixel(const mp_obj_framebuf_t *fb, unsigned int x, unsigned int y) {
return formats[fb->format].getpixel(fb, x, y);
}
@@ -263,21 +270,21 @@ STATIC void fill_rect(const mp_obj_framebuf_t *fb, int x, int y, int w, int h, u
formats[fb->format].fill_rect(fb, x, y, xend - x, yend - y, col);
}
-STATIC mp_obj_t framebuf_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
+STATIC mp_obj_t framebuf_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args_in) {
mp_arg_check_num(n_args, n_kw, 4, 5, false);
mp_obj_framebuf_t *o = mp_obj_malloc(mp_obj_framebuf_t, type);
- o->buf_obj = args[0];
+ o->buf_obj = args_in[0];
mp_buffer_info_t bufinfo;
- mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_WRITE);
+ mp_get_buffer_raise(args_in[0], &bufinfo, MP_BUFFER_WRITE);
o->buf = bufinfo.buf;
- o->width = mp_obj_get_int(args[1]);
- o->height = mp_obj_get_int(args[2]);
- o->format = mp_obj_get_int(args[3]);
+ o->width = mp_obj_get_int(args_in[1]);
+ o->height = mp_obj_get_int(args_in[2]);
+ o->format = mp_obj_get_int(args_in[3]);
if (n_args >= 5) {
- o->stride = mp_obj_get_int(args[4]);
+ o->stride = mp_obj_get_int(args_in[4]);
} else {
o->stride = o->width;
}
@@ -305,6 +312,12 @@ STATIC mp_obj_t framebuf_make_new(const mp_obj_type_t *type, size_t n_args, size
return MP_OBJ_FROM_PTR(o);
}
+STATIC void framebuf_args(const mp_obj_t *args_in, mp_int_t *args_out, int n) {
+ for (int i = 0; i < n; ++i) {
+ args_out[i] = mp_obj_get_int(args_in[i + 1]);
+ }
+}
+
STATIC mp_int_t framebuf_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, mp_uint_t flags) {
(void)flags;
mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(self_in);
@@ -322,98 +335,75 @@ STATIC mp_obj_t framebuf_fill(mp_obj_t self_in, mp_obj_t col_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(framebuf_fill_obj, framebuf_fill);
-STATIC mp_obj_t framebuf_fill_rect(size_t n_args, const mp_obj_t *args) {
- (void)n_args;
-
- mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args[0]);
- mp_int_t x = mp_obj_get_int(args[1]);
- mp_int_t y = mp_obj_get_int(args[2]);
- mp_int_t width = mp_obj_get_int(args[3]);
- mp_int_t height = mp_obj_get_int(args[4]);
- mp_int_t col = mp_obj_get_int(args[5]);
-
- fill_rect(self, x, y, width, height, col);
-
+STATIC mp_obj_t framebuf_fill_rect(size_t n_args, const mp_obj_t *args_in) {
+ mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args_in[0]);
+ mp_int_t args[5]; // x, y, w, h, col
+ framebuf_args(args_in, args, 5);
+ fill_rect(self, args[0], args[1], args[2], args[3], args[4]);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_fill_rect_obj, 6, 6, framebuf_fill_rect);
-STATIC mp_obj_t framebuf_pixel(size_t n_args, const mp_obj_t *args) {
- mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args[0]);
- mp_int_t x = mp_obj_get_int(args[1]);
- mp_int_t y = mp_obj_get_int(args[2]);
+STATIC mp_obj_t framebuf_pixel(size_t n_args, const mp_obj_t *args_in) {
+ mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args_in[0]);
+ mp_int_t x = mp_obj_get_int(args_in[1]);
+ mp_int_t y = mp_obj_get_int(args_in[2]);
if (0 <= x && x < self->width && 0 <= y && y < self->height) {
if (n_args == 3) {
// get
return MP_OBJ_NEW_SMALL_INT(getpixel(self, x, y));
} else {
// set
- setpixel(self, x, y, mp_obj_get_int(args[3]));
+ setpixel(self, x, y, mp_obj_get_int(args_in[3]));
}
}
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_pixel_obj, 3, 4, framebuf_pixel);
-STATIC mp_obj_t framebuf_hline(size_t n_args, const mp_obj_t *args) {
+STATIC mp_obj_t framebuf_hline(size_t n_args, const mp_obj_t *args_in) {
(void)n_args;
- mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args[0]);
- mp_int_t x = mp_obj_get_int(args[1]);
- mp_int_t y = mp_obj_get_int(args[2]);
- mp_int_t w = mp_obj_get_int(args[3]);
- mp_int_t col = mp_obj_get_int(args[4]);
+ mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args_in[0]);
+ mp_int_t args[4]; // x, y, w, col
+ framebuf_args(args_in, args, 4);
- fill_rect(self, x, y, w, 1, col);
+ fill_rect(self, args[0], args[1], args[2], 1, args[3]);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_hline_obj, 5, 5, framebuf_hline);
-STATIC mp_obj_t framebuf_vline(size_t n_args, const mp_obj_t *args) {
+STATIC mp_obj_t framebuf_vline(size_t n_args, const mp_obj_t *args_in) {
(void)n_args;
- mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args[0]);
- mp_int_t x = mp_obj_get_int(args[1]);
- mp_int_t y = mp_obj_get_int(args[2]);
- mp_int_t h = mp_obj_get_int(args[3]);
- mp_int_t col = mp_obj_get_int(args[4]);
+ mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args_in[0]);
+ mp_int_t args[4]; // x, y, h, col
+ framebuf_args(args_in, args, 4);
- fill_rect(self, x, y, 1, h, col);
+ fill_rect(self, args[0], args[1], 1, args[2], args[3]);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_vline_obj, 5, 5, framebuf_vline);
-STATIC mp_obj_t framebuf_rect(size_t n_args, const mp_obj_t *args) {
- (void)n_args;
-
- mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args[0]);
- mp_int_t x = mp_obj_get_int(args[1]);
- mp_int_t y = mp_obj_get_int(args[2]);
- mp_int_t w = mp_obj_get_int(args[3]);
- mp_int_t h = mp_obj_get_int(args[4]);
- 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, 1, h, col);
- fill_rect(self, x + w - 1, y, 1, h, col);
-
+STATIC mp_obj_t framebuf_rect(size_t n_args, const mp_obj_t *args_in) {
+ mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args_in[0]);
+ mp_int_t args[5]; // x, y, w, h, col
+ framebuf_args(args_in, args, 5);
+ if (n_args > 6 && mp_obj_is_true(args_in[6])) {
+ fill_rect(self, args[0], args[1], args[2], args[3], args[4]);
+ } else {
+ fill_rect(self, args[0], args[1], args[2], 1, args[4]);
+ fill_rect(self, args[0], args[1] + args[3] - 1, args[2], 1, args[4]);
+ fill_rect(self, args[0], args[1], 1, args[3], args[4]);
+ fill_rect(self, args[0] + args[2] - 1, args[1], 1, args[3], args[4]);
+ }
return mp_const_none;
}
-STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_rect_obj, 6, 6, framebuf_rect);
-
-STATIC mp_obj_t framebuf_line(size_t n_args, const mp_obj_t *args) {
- (void)n_args;
-
- mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args[0]);
- mp_int_t x1 = mp_obj_get_int(args[1]);
- mp_int_t y1 = mp_obj_get_int(args[2]);
- mp_int_t x2 = mp_obj_get_int(args[3]);
- mp_int_t y2 = mp_obj_get_int(args[4]);
- mp_int_t col = mp_obj_get_int(args[5]);
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_rect_obj, 6, 7, framebuf_rect);
+STATIC void line(const mp_obj_framebuf_t *fb, mp_int_t x1, mp_int_t y1, mp_int_t x2, mp_int_t y2, mp_int_t col) {
mp_int_t dx = x2 - x1;
mp_int_t sx;
if (dx > 0) {
@@ -452,12 +442,12 @@ STATIC mp_obj_t framebuf_line(size_t n_args, const mp_obj_t *args) {
mp_int_t e = 2 * dy - dx;
for (mp_int_t i = 0; i < dx; ++i) {
if (steep) {
- if (0 <= y1 && y1 < self->width && 0 <= x1 && x1 < self->height) {
- setpixel(self, y1, x1, col);
+ if (0 <= y1 && y1 < fb->width && 0 <= x1 && x1 < fb->height) {
+ setpixel(fb, y1, x1, col);
}
} else {
- if (0 <= x1 && x1 < self->width && 0 <= y1 && y1 < self->height) {
- setpixel(self, x1, y1, col);
+ if (0 <= x1 && x1 < fb->width && 0 <= y1 && y1 < fb->height) {
+ setpixel(fb, x1, y1, col);
}
}
while (e >= 0) {
@@ -468,31 +458,250 @@ STATIC mp_obj_t framebuf_line(size_t n_args, const mp_obj_t *args) {
e += 2 * dy;
}
- if (0 <= x2 && x2 < self->width && 0 <= y2 && y2 < self->height) {
- setpixel(self, x2, y2, col);
+ if (0 <= x2 && x2 < fb->width && 0 <= y2 && y2 < fb->height) {
+ setpixel(fb, x2, y2, col);
}
+}
+
+STATIC mp_obj_t framebuf_line(size_t n_args, const mp_obj_t *args_in) {
+ (void)n_args;
+
+ mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args_in[0]);
+ mp_int_t args[5]; // x1, y1, x2, y2, col
+ framebuf_args(args_in, args, 5);
+
+ line(self, args[0], args[1], args[2], args[3], args[4]);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_line_obj, 6, 6, framebuf_line);
-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_t source_in = mp_obj_cast_to_native_base(args[1], MP_OBJ_FROM_PTR(&mp_type_framebuf));
+// Q2 Q1
+// Q3 Q4
+#define ELLIPSE_MASK_FILL (0x10)
+#define ELLIPSE_MASK_ALL (0x0f)
+#define ELLIPSE_MASK_Q1 (0x01)
+#define ELLIPSE_MASK_Q2 (0x02)
+#define ELLIPSE_MASK_Q3 (0x04)
+#define ELLIPSE_MASK_Q4 (0x08)
+
+STATIC void draw_ellipse_points(const mp_obj_framebuf_t *fb, mp_int_t cx, mp_int_t cy, mp_int_t x, mp_int_t y, mp_int_t col, mp_int_t mask) {
+ if (mask & ELLIPSE_MASK_FILL) {
+ if (mask & ELLIPSE_MASK_Q1) {
+ fill_rect(fb, cx, cy - y, x + 1, 1, col);
+ }
+ if (mask & ELLIPSE_MASK_Q2) {
+ fill_rect(fb, cx - x, cy - y, x + 1, 1, col);
+ }
+ if (mask & ELLIPSE_MASK_Q3) {
+ fill_rect(fb, cx - x, cy + y, x + 1, 1, col);
+ }
+ if (mask & ELLIPSE_MASK_Q4) {
+ fill_rect(fb, cx, cy + y, x + 1, 1, col);
+ }
+ } else {
+ setpixel_checked(fb, cx + x, cy - y, col, mask & ELLIPSE_MASK_Q1);
+ setpixel_checked(fb, cx - x, cy - y, col, mask & ELLIPSE_MASK_Q2);
+ setpixel_checked(fb, cx - x, cy + y, col, mask & ELLIPSE_MASK_Q3);
+ setpixel_checked(fb, cx + x, cy + y, col, mask & ELLIPSE_MASK_Q4);
+ }
+}
+
+STATIC mp_obj_t framebuf_ellipse(size_t n_args, const mp_obj_t *args_in) {
+ mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args_in[0]);
+ mp_int_t args[5];
+ framebuf_args(args_in, args, 5); // cx, cy, xradius, yradius, col
+ mp_int_t mask = (n_args > 6 && mp_obj_is_true(args_in[6])) ? ELLIPSE_MASK_FILL : 0;
+ if (n_args > 7) {
+ mask |= mp_obj_get_int(args_in[7]) & ELLIPSE_MASK_ALL;
+ } else {
+ mask |= ELLIPSE_MASK_ALL;
+ }
+ mp_int_t two_asquare = 2 * args[2] * args[2];
+ mp_int_t two_bsquare = 2 * args[3] * args[3];
+ mp_int_t x = args[2];
+ mp_int_t y = 0;
+ mp_int_t xchange = args[3] * args[3] * (1 - 2 * args[2]);
+ mp_int_t ychange = args[2] * args[2];
+ mp_int_t ellipse_error = 0;
+ mp_int_t stoppingx = two_bsquare * args[2];
+ mp_int_t stoppingy = 0;
+ while (stoppingx >= stoppingy) { // 1st set of points, y' > -1
+ draw_ellipse_points(self, args[0], args[1], x, y, args[4], mask);
+ y += 1;
+ stoppingy += two_asquare;
+ ellipse_error += ychange;
+ ychange += two_asquare;
+ if ((2 * ellipse_error + xchange) > 0) {
+ x -= 1;
+ stoppingx -= two_bsquare;
+ ellipse_error += xchange;
+ xchange += two_bsquare;
+ }
+ }
+ // 1st point set is done start the 2nd set of points
+ x = 0;
+ y = args[3];
+ xchange = args[3] * args[3];
+ ychange = args[2] * args[2] * (1 - 2 * args[3]);
+ ellipse_error = 0;
+ stoppingx = 0;
+ stoppingy = two_asquare * args[3];
+ while (stoppingx <= stoppingy) { // 2nd set of points, y' < -1
+ draw_ellipse_points(self, args[0], args[1], x, y, args[4], mask);
+ x += 1;
+ stoppingx += two_bsquare;
+ ellipse_error += xchange;
+ xchange += two_bsquare;
+ if ((2 * ellipse_error + ychange) > 0) {
+ y -= 1;
+ stoppingy -= two_asquare;
+ ellipse_error += ychange;
+ ychange += two_asquare;
+ }
+ }
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_ellipse_obj, 6, 8, framebuf_ellipse);
+
+#if MICROPY_PY_ARRAY && !MICROPY_ENABLE_DYNRUNTIME
+// TODO: poly needs mp_binary_get_size & mp_binary_get_val_array which aren't
+// available in dynruntime.h yet.
+
+STATIC mp_int_t poly_int(mp_buffer_info_t *bufinfo, size_t index) {
+ return mp_obj_get_int(mp_binary_get_val_array(bufinfo->typecode, bufinfo->buf, index));
+}
+
+STATIC mp_obj_t framebuf_poly(size_t n_args, const mp_obj_t *args_in) {
+ mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args_in[0]);
+
+ mp_int_t x = mp_obj_get_int(args_in[1]);
+ mp_int_t y = mp_obj_get_int(args_in[2]);
+
+ mp_buffer_info_t bufinfo;
+ mp_get_buffer_raise(args_in[3], &bufinfo, MP_BUFFER_READ);
+ // If an odd number of values was given, this rounds down to multiple of two.
+ int n_poly = bufinfo.len / (mp_binary_get_size('@', bufinfo.typecode, NULL) * 2);
+
+ if (n_poly == 0) {
+ return mp_const_none;
+ }
+
+ mp_int_t col = mp_obj_get_int(args_in[4]);
+ bool fill = n_args > 5 && mp_obj_is_true(args_in[5]);
+
+ if (fill) {
+ // This implements an integer version of http://alienryderflex.com/polygon_fill/
+
+ // The idea is for each scan line, compute the sorted list of x
+ // coordinates where the scan line intersects the polygon edges,
+ // then fill between each resulting pair.
+
+ // Restrict just to the scan lines that include the vertical extent of
+ // this polygon.
+ mp_int_t y_min = INT_MAX, y_max = INT_MIN;
+ for (int i = 0; i < n_poly; i++) {
+ mp_int_t py = poly_int(&bufinfo, i * 2 + 1);
+ y_min = MIN(y_min, py);
+ y_max = MAX(y_max, py);
+ }
+
+ for (mp_int_t row = y_min; row <= y_max; row++) {
+ // Each node is the x coordinate where an edge crosses this scan line.
+ mp_int_t nodes[n_poly];
+ int n_nodes = 0;
+ mp_int_t px1 = poly_int(&bufinfo, 0);
+ mp_int_t py1 = poly_int(&bufinfo, 1);
+ int i = n_poly * 2 - 1;
+ do {
+ mp_int_t py2 = poly_int(&bufinfo, i--);
+ mp_int_t px2 = poly_int(&bufinfo, i--);
+
+ // Don't include the bottom pixel of a given edge to avoid
+ // duplicating the node with the start of the next edge. This
+ // will miss some pixels on the boundary, and in particular
+ // at a local minima or inflection point.
+ if (py1 != py2 && ((py1 > row && py2 <= row) || (py1 <= row && py2 > row))) {
+ mp_int_t node = (32 * px1 + 32 * (px2 - px1) * (row - py1) / (py2 - py1) + 16) / 32;
+ nodes[n_nodes++] = node;
+ } else if (row == MAX(py1, py2)) {
+ // At local-minima, try and manually fill in the pixels that get missed above.
+ if (py1 < py2) {
+ setpixel_checked(self, x + px2, y + py2, col, 1);
+ } else if (py2 < py1) {
+ setpixel_checked(self, x + px1, y + py1, col, 1);
+ } else {
+ // Even though this is a hline and would be faster to
+ // use fill_rect, use line() because it handles x2 <
+ // x1.
+ line(self, x + px1, y + py1, x + px2, y + py2, col);
+ }
+ }
+
+ px1 = px2;
+ py1 = py2;
+ } while (i >= 0);
+
+ if (!n_nodes) {
+ continue;
+ }
+
+ // Sort the nodes left-to-right (bubble-sort for code size).
+ i = 0;
+ while (i < n_nodes - 1) {
+ if (nodes[i] > nodes[i + 1]) {
+ mp_int_t swap = nodes[i];
+ nodes[i] = nodes[i + 1];
+ nodes[i + 1] = swap;
+ if (i) {
+ i--;
+ }
+ } else {
+ i++;
+ }
+ }
+
+ // Fill between each pair of nodes.
+ for (i = 0; i < n_nodes; i += 2) {
+ fill_rect(self, x + nodes[i], y + row, (nodes[i + 1] - nodes[i]) + 1, 1, col);
+ }
+ }
+ } else {
+ // Outline only.
+ mp_int_t px1 = poly_int(&bufinfo, 0);
+ mp_int_t py1 = poly_int(&bufinfo, 1);
+ int i = n_poly * 2 - 1;
+ do {
+ mp_int_t py2 = poly_int(&bufinfo, i--);
+ mp_int_t px2 = poly_int(&bufinfo, i--);
+ line(self, x + px1, y + py1, x + px2, y + py2, col);
+ px1 = px2;
+ py1 = py2;
+ } while (i >= 0);
+ }
+
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_poly_obj, 5, 6, framebuf_poly);
+#endif // MICROPY_PY_ARRAY && !MICROPY_ENABLE_DYNRUNTIME
+
+STATIC mp_obj_t framebuf_blit(size_t n_args, const mp_obj_t *args_in) {
+ mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args_in[0]);
+ mp_obj_t source_in = mp_obj_cast_to_native_base(args_in[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 x = mp_obj_get_int(args_in[2]);
+ mp_int_t y = mp_obj_get_int(args_in[3]);
mp_int_t key = -1;
if (n_args > 4) {
- key = mp_obj_get_int(args[4]);
+ key = mp_obj_get_int(args_in[4]);
}
mp_obj_framebuf_t *palette = NULL;
- if (n_args > 5 && args[5] != mp_const_none) {
- palette = MP_OBJ_TO_PTR(mp_obj_cast_to_native_base(args[5], MP_OBJ_FROM_PTR(&mp_type_framebuf)));
+ if (n_args > 5 && args_in[5] != mp_const_none) {
+ palette = MP_OBJ_TO_PTR(mp_obj_cast_to_native_base(args_in[5], MP_OBJ_FROM_PTR(&mp_type_framebuf)));
}
if (
@@ -539,19 +748,31 @@ STATIC mp_obj_t framebuf_scroll(mp_obj_t self_in, mp_obj_t xstep_in, mp_obj_t ys
if (xstep < 0) {
sx = 0;
xend = self->width + xstep;
+ if (xend <= 0) {
+ return mp_const_none;
+ }
dx = 1;
} else {
sx = self->width - 1;
xend = xstep - 1;
+ if (xend >= sx) {
+ return mp_const_none;
+ }
dx = -1;
}
if (ystep < 0) {
y = 0;
yend = self->height + ystep;
+ if (yend <= 0) {
+ return mp_const_none;
+ }
dy = 1;
} else {
y = self->height - 1;
yend = ystep - 1;
+ if (yend >= y) {
+ return mp_const_none;
+ }
dy = -1;
}
for (; y != yend; y += dy) {
@@ -563,15 +784,15 @@ STATIC mp_obj_t framebuf_scroll(mp_obj_t self_in, mp_obj_t xstep_in, mp_obj_t ys
}
STATIC MP_DEFINE_CONST_FUN_OBJ_3(framebuf_scroll_obj, framebuf_scroll);
-STATIC mp_obj_t framebuf_text(size_t n_args, const mp_obj_t *args) {
+STATIC mp_obj_t framebuf_text(size_t n_args, const mp_obj_t *args_in) {
// extract arguments
- mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args[0]);
- const char *str = mp_obj_str_get_str(args[1]);
- mp_int_t x0 = mp_obj_get_int(args[2]);
- mp_int_t y0 = mp_obj_get_int(args[3]);
+ mp_obj_framebuf_t *self = MP_OBJ_TO_PTR(args_in[0]);
+ const char *str = mp_obj_str_get_str(args_in[1]);
+ mp_int_t x0 = mp_obj_get_int(args_in[2]);
+ mp_int_t y0 = mp_obj_get_int(args_in[3]);
mp_int_t col = 1;
if (n_args >= 5) {
- col = mp_obj_get_int(args[4]);
+ col = mp_obj_get_int(args_in[4]);
}
// loop over chars
@@ -610,34 +831,39 @@ STATIC const mp_rom_map_elem_t framebuf_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_vline), MP_ROM_PTR(&framebuf_vline_obj) },
{ MP_ROM_QSTR(MP_QSTR_rect), MP_ROM_PTR(&framebuf_rect_obj) },
{ MP_ROM_QSTR(MP_QSTR_line), MP_ROM_PTR(&framebuf_line_obj) },
+ { MP_ROM_QSTR(MP_QSTR_ellipse), MP_ROM_PTR(&framebuf_ellipse_obj) },
+ #if MICROPY_PY_ARRAY
+ { MP_ROM_QSTR(MP_QSTR_poly), MP_ROM_PTR(&framebuf_poly_obj) },
+ #endif
{ MP_ROM_QSTR(MP_QSTR_blit), MP_ROM_PTR(&framebuf_blit_obj) },
{ MP_ROM_QSTR(MP_QSTR_scroll), MP_ROM_PTR(&framebuf_scroll_obj) },
{ MP_ROM_QSTR(MP_QSTR_text), MP_ROM_PTR(&framebuf_text_obj) },
};
STATIC MP_DEFINE_CONST_DICT(framebuf_locals_dict, framebuf_locals_dict_table);
-STATIC const mp_obj_type_t mp_type_framebuf = {
- { &mp_type_type },
- .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,
-};
+STATIC MP_DEFINE_CONST_OBJ_TYPE(
+ mp_type_framebuf,
+ MP_QSTR_FrameBuffer,
+ MP_TYPE_FLAG_NONE,
+ make_new, framebuf_make_new,
+ buffer, framebuf_get_buffer,
+ locals_dict, &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) {
- mp_obj_framebuf_t *o = mp_obj_malloc(mp_obj_framebuf_t, &mp_type_framebuf);
+STATIC mp_obj_t legacy_framebuffer1(size_t n_args, const mp_obj_t *args_in) {
+ mp_obj_framebuf_t *o = mp_obj_malloc(mp_obj_framebuf_t, (mp_obj_type_t *)&mp_type_framebuf);
mp_buffer_info_t bufinfo;
- mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_WRITE);
+ mp_get_buffer_raise(args_in[0], &bufinfo, MP_BUFFER_WRITE);
o->buf = bufinfo.buf;
- o->width = mp_obj_get_int(args[1]);
- o->height = mp_obj_get_int(args[2]);
+ o->width = mp_obj_get_int(args_in[1]);
+ o->height = mp_obj_get_int(args_in[2]);
o->format = FRAMEBUF_MVLSB;
if (n_args >= 4) {
- o->stride = mp_obj_get_int(args[3]);
+ o->stride = mp_obj_get_int(args_in[3]);
} else {
o->stride = o->width;
}
diff --git a/extmod/modlwip.c b/extmod/modlwip.c
index ec5f3bfd6394..734722f83a12 100644
--- a/extmod/modlwip.c
+++ b/extmod/modlwip.c
@@ -35,6 +35,8 @@
#include "py/mperrno.h"
#include "py/mphal.h"
+#if MICROPY_PY_LWIP
+
#include "shared/netutils/netutils.h"
#include "lwip/init.h"
@@ -64,6 +66,7 @@
// All socket options should be globally distinct,
// because we ignore option levels for efficiency.
#define IP_ADD_MEMBERSHIP 0x400
+#define IP_DROP_MEMBERSHIP 0x401
// For compatibilily with older lwIP versions.
#ifndef ip_set_option
@@ -174,12 +177,13 @@ STATIC const mp_rom_map_elem_t lwip_slip_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(lwip_slip_locals_dict, lwip_slip_locals_dict_table);
-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,
-};
+STATIC MP_DEFINE_CONST_OBJ_TYPE(
+ lwip_slip_type,
+ MP_QSTR_slip,
+ MP_TYPE_FLAG_NONE,
+ make_new, lwip_slip_make_new,
+ locals_dict, &lwip_slip_locals_dict
+ );
#endif // MICROPY_PY_LWIP_SLIP
@@ -927,9 +931,20 @@ STATIC mp_obj_t lwip_socket_listen(size_t n_args, const mp_obj_t *args) {
mp_raise_OSError(MP_EOPNOTSUPP);
}
- struct tcp_pcb *new_pcb = tcp_listen_with_backlog(socket->pcb.tcp, (u8_t)backlog);
+ struct tcp_pcb *new_pcb;
+ #if LWIP_VERSION_MACRO < 0x02000100
+ new_pcb = tcp_listen_with_backlog(socket->pcb.tcp, (u8_t)backlog);
+ #else
+ err_t error;
+ new_pcb = tcp_listen_with_backlog_and_err(socket->pcb.tcp, (u8_t)backlog, &error);
+ #endif
+
if (new_pcb == NULL) {
+ #if LWIP_VERSION_MACRO < 0x02000100
mp_raise_OSError(MP_ENOMEM);
+ #else
+ mp_raise_OSError(error_lookup_table[-error]);
+ #endif
}
socket->pcb.tcp = new_pcb;
@@ -1195,7 +1210,7 @@ STATIC mp_obj_t lwip_socket_recv(mp_obj_t self_in, mp_obj_t len_in) {
return mp_const_empty_bytes;
}
vstr.len = ret;
- return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
+ return mp_obj_new_bytes_from_vstr(&vstr);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(lwip_socket_recv_obj, lwip_socket_recv);
@@ -1268,7 +1283,7 @@ STATIC mp_obj_t lwip_socket_recvfrom(mp_obj_t self_in, mp_obj_t len_in) {
tuple[0] = mp_const_empty_bytes;
} else {
vstr.len = ret;
- tuple[0] = mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
+ tuple[0] = mp_obj_new_bytes_from_vstr(&vstr);
}
tuple[1] = netutils_format_inet_addr(ip, port, NETUTILS_BIG);
return mp_obj_new_tuple(2, tuple);
@@ -1374,7 +1389,8 @@ STATIC mp_obj_t lwip_socket_setsockopt(size_t n_args, const mp_obj_t *args) {
}
// level: IPPROTO_IP
- case IP_ADD_MEMBERSHIP: {
+ case IP_ADD_MEMBERSHIP:
+ case IP_DROP_MEMBERSHIP: {
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(args[3], &bufinfo, MP_BUFFER_READ);
if (bufinfo.len != sizeof(ip_addr_t) * 2) {
@@ -1382,7 +1398,12 @@ 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;
+ if (opt == IP_ADD_MEMBERSHIP) {
+ err = igmp_joingroup((ip_addr_t *)bufinfo.buf + 1, bufinfo.buf);
+ } else {
+ err = igmp_leavegroup((ip_addr_t *)bufinfo.buf + 1, bufinfo.buf);
+ }
if (err != ERR_OK) {
mp_raise_OSError(error_lookup_table[-err]);
}
@@ -1585,14 +1606,15 @@ STATIC const mp_stream_p_t lwip_socket_stream_p = {
.ioctl = lwip_socket_ioctl,
};
-STATIC const mp_obj_type_t lwip_socket_type = {
- { &mp_type_type },
- .name = MP_QSTR_socket,
- .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,
-};
+STATIC MP_DEFINE_CONST_OBJ_TYPE(
+ lwip_socket_type,
+ MP_QSTR_socket,
+ MP_TYPE_FLAG_NONE,
+ make_new, lwip_socket_make_new,
+ print, lwip_socket_print,
+ protocol, &lwip_socket_stream_p,
+ locals_dict, &lwip_socket_locals_dict
+ );
/******************************************************************************/
// Support functions for memory protection. lwIP has its own memory management
@@ -1741,8 +1763,6 @@ STATIC mp_obj_t lwip_print_pcbs() {
}
MP_DEFINE_CONST_FUN_OBJ_0(lwip_print_pcbs_obj, lwip_print_pcbs);
-#if MICROPY_PY_LWIP
-
STATIC const mp_rom_map_elem_t mp_module_lwip_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_lwip) },
{ MP_ROM_QSTR(MP_QSTR_reset), MP_ROM_PTR(&mod_lwip_reset_obj) },
@@ -1769,6 +1789,7 @@ STATIC const mp_rom_map_elem_t mp_module_lwip_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_IPPROTO_IP), MP_ROM_INT(0) },
{ MP_ROM_QSTR(MP_QSTR_IP_ADD_MEMBERSHIP), MP_ROM_INT(IP_ADD_MEMBERSHIP) },
+ { MP_ROM_QSTR(MP_QSTR_IP_DROP_MEMBERSHIP), MP_ROM_INT(IP_DROP_MEMBERSHIP) },
};
STATIC MP_DEFINE_CONST_DICT(mp_module_lwip_globals, mp_module_lwip_globals_table);
@@ -1783,4 +1804,6 @@ MP_REGISTER_MODULE(MP_QSTR_lwip, mp_module_lwip);
// On LWIP-ports, this is the usocket module (replaces extmod/modusocket.c).
MP_REGISTER_MODULE(MP_QSTR_usocket, mp_module_lwip);
+MP_REGISTER_ROOT_POINTER(mp_obj_t lwip_slip_stream);
+
#endif // MICROPY_PY_LWIP
diff --git a/extmod/modnetwork.c b/extmod/modnetwork.c
index 87e155e09154..7c1b91de45d0 100644
--- a/extmod/modnetwork.c
+++ b/extmod/modnetwork.c
@@ -31,23 +31,35 @@
#include "py/objlist.h"
#include "py/runtime.h"
#include "py/mphal.h"
+
+#if MICROPY_PY_NETWORK
+
#include "shared/netutils/netutils.h"
#include "modnetwork.h"
-#if MICROPY_PY_NETWORK
+#if MICROPY_PY_NETWORK_CYW43
+// So that CYW43_LINK_xxx constants are available to MICROPY_PORT_NETWORK_INTERFACES.
+#include "lib/cyw43-driver/src/cyw43.h"
+#endif
-#if MICROPY_PY_LWIP
-#include "lwip/netif.h"
-#include "lwip/timeouts.h"
-#include "lwip/dns.h"
-#include "lwip/dhcp.h"
-#include "lwip/apps/mdns.h"
+#ifdef MICROPY_PY_NETWORK_INCLUDEFILE
+#include MICROPY_PY_NETWORK_INCLUDEFILE
#endif
/// \module network - network configuration
///
/// This module provides network drivers and routing configuration.
+char mod_network_country_code[2] = "XX";
+
+#ifndef MICROPY_PY_NETWORK_HOSTNAME_DEFAULT
+#error "MICROPY_PY_NETWORK_HOSTNAME_DEFAULT must be set in mpconfigport.h or mpconfigboard.h"
+#endif
+
+char mod_network_hostname[MICROPY_PY_NETWORK_HOSTNAME_MAX_LEN] = MICROPY_PY_NETWORK_HOSTNAME_DEFAULT;
+
+#ifdef MICROPY_PORT_NETWORK_INTERFACES
+
void mod_network_init(void) {
mp_obj_list_init(&MP_STATE_PORT(mod_network_nic_list), 0);
}
@@ -71,7 +83,7 @@ mp_obj_t mod_network_find_nic(const uint8_t *ip) {
for (mp_uint_t i = 0; i < MP_STATE_PORT(mod_network_nic_list).len; i++) {
mp_obj_t nic = MP_STATE_PORT(mod_network_nic_list).items[i];
// TODO check IP suitability here
- // mod_network_nic_type_t *nic_type = (mod_network_nic_type_t*)mp_obj_get_type(nic);
+ // mod_network_nic_protocol_t *nic_protocol = (mod_network_nic_protocol_t *)MP_OBJ_TYPE_GET_SLOT(mp_obj_get_type(nic), protocol);
return nic;
}
@@ -83,16 +95,61 @@ STATIC mp_obj_t network_route(void) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(network_route_obj, network_route);
+MP_REGISTER_ROOT_POINTER(mp_obj_list_t mod_network_nic_list);
+
+#endif // MICROPY_PORT_NETWORK_INTERFACES
+
+STATIC mp_obj_t network_country(size_t n_args, const mp_obj_t *args) {
+ if (n_args == 0) {
+ return mp_obj_new_str(mod_network_country_code, 2);
+ } else {
+ size_t len;
+ const char *str = mp_obj_str_get_data(args[0], &len);
+ if (len != 2) {
+ mp_raise_ValueError(NULL);
+ }
+ mod_network_country_code[0] = str[0];
+ mod_network_country_code[1] = str[1];
+ return mp_const_none;
+ }
+}
+// TODO: Non-static to allow backwards-compatible pyb.country.
+MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_network_country_obj, 0, 1, network_country);
+
+STATIC mp_obj_t network_hostname(size_t n_args, const mp_obj_t *args) {
+ if (n_args == 0) {
+ return mp_obj_new_str(mod_network_hostname, strlen(mod_network_hostname));
+ } else {
+ size_t len;
+ const char *str = mp_obj_str_get_data(args[0], &len);
+ if (len >= MICROPY_PY_NETWORK_HOSTNAME_MAX_LEN) {
+ mp_raise_ValueError(NULL);
+ }
+ strcpy(mod_network_hostname, str);
+ return mp_const_none;
+ }
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_network_hostname_obj, 0, 1, network_hostname);
+
STATIC const mp_rom_map_elem_t mp_module_network_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_network) },
- { MP_ROM_QSTR(MP_QSTR_route), MP_ROM_PTR(&network_route_obj) },
+ { MP_ROM_QSTR(MP_QSTR_country), MP_ROM_PTR(&mod_network_country_obj) },
+ { MP_ROM_QSTR(MP_QSTR_hostname), MP_ROM_PTR(&mod_network_hostname_obj) },
// Defined per port in mpconfigport.h
+ #ifdef MICROPY_PORT_NETWORK_INTERFACES
+ { MP_ROM_QSTR(MP_QSTR_route), MP_ROM_PTR(&network_route_obj) },
MICROPY_PORT_NETWORK_INTERFACES
+ #endif
+ // Allow a port to take mostly full control of the network module.
+ #ifdef MICROPY_PY_NETWORK_MODULE_GLOBALS_INCLUDEFILE
+ #include MICROPY_PY_NETWORK_MODULE_GLOBALS_INCLUDEFILE
+ #else
// Constants
{ MP_ROM_QSTR(MP_QSTR_STA_IF), MP_ROM_INT(MOD_NETWORK_STA_IF) },
{ MP_ROM_QSTR(MP_QSTR_AP_IF), MP_ROM_INT(MOD_NETWORK_AP_IF) },
+ #endif
};
STATIC MP_DEFINE_CONST_DICT(mp_module_network_globals, mp_module_network_globals_table);
@@ -104,58 +161,4 @@ const mp_obj_module_t mp_module_network = {
MP_REGISTER_MODULE(MP_QSTR_network, mp_module_network);
-/*******************************************************************************/
-// Implementations of network methods that can be used by any interface
-
-#if MICROPY_PY_LWIP
-
-mp_obj_t mod_network_nic_ifconfig(struct netif *netif, size_t n_args, const mp_obj_t *args) {
- if (n_args == 0) {
- // Get IP addresses
- const ip_addr_t *dns = dns_getserver(0);
- mp_obj_t tuple[4] = {
- netutils_format_ipv4_addr((uint8_t *)&netif->ip_addr, NETUTILS_BIG),
- netutils_format_ipv4_addr((uint8_t *)&netif->netmask, NETUTILS_BIG),
- netutils_format_ipv4_addr((uint8_t *)&netif->gw, NETUTILS_BIG),
- netutils_format_ipv4_addr((uint8_t *)dns, NETUTILS_BIG),
- };
- return mp_obj_new_tuple(4, tuple);
- } else if (args[0] == MP_OBJ_NEW_QSTR(MP_QSTR_dhcp)) {
- // Start the DHCP client
- if (dhcp_supplied_address(netif)) {
- dhcp_renew(netif);
- } else {
- dhcp_stop(netif);
- dhcp_start(netif);
- }
-
- // Wait for DHCP to get IP address
- uint32_t start = mp_hal_ticks_ms();
- while (!dhcp_supplied_address(netif)) {
- if (mp_hal_ticks_ms() - start > 10000) {
- mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("timeout waiting for DHCP to get IP address"));
- }
- mp_hal_delay_ms(100);
- }
-
- return mp_const_none;
- } else {
- // Release and stop any existing DHCP
- dhcp_release(netif);
- dhcp_stop(netif);
- // Set static IP addresses
- mp_obj_t *items;
- mp_obj_get_array_fixed_n(args[0], 4, &items);
- netutils_parse_ipv4_addr(items[0], (uint8_t *)&netif->ip_addr, NETUTILS_BIG);
- netutils_parse_ipv4_addr(items[1], (uint8_t *)&netif->netmask, NETUTILS_BIG);
- netutils_parse_ipv4_addr(items[2], (uint8_t *)&netif->gw, NETUTILS_BIG);
- ip_addr_t dns;
- netutils_parse_ipv4_addr(items[3], (uint8_t *)&dns, NETUTILS_BIG);
- dns_setserver(0, &dns);
- return mp_const_none;
- }
-}
-
-#endif
-
#endif // MICROPY_PY_NETWORK
diff --git a/extmod/modnetwork.h b/extmod/modnetwork.h
index 3481cc6dcc57..11691140fd6f 100644
--- a/extmod/modnetwork.h
+++ b/extmod/modnetwork.h
@@ -52,18 +52,24 @@
#define MOD_NETWORK_SS_CONNECTED (2)
#define MOD_NETWORK_SS_CLOSED (3)
+extern char mod_network_country_code[2];
+
+#ifndef MICROPY_PY_NETWORK_HOSTNAME_MAX_LEN
+#define MICROPY_PY_NETWORK_HOSTNAME_MAX_LEN (16)
+#endif
+
+extern char mod_network_hostname[MICROPY_PY_NETWORK_HOSTNAME_MAX_LEN];
+
#if MICROPY_PY_LWIP
struct netif;
void mod_network_lwip_init(void);
void mod_network_lwip_poll_wrapper(uint32_t ticks_ms);
mp_obj_t mod_network_nic_ifconfig(struct netif *netif, size_t n_args, const mp_obj_t *args);
-#else
+#elif defined(MICROPY_PORT_NETWORK_INTERFACES)
struct _mod_network_socket_obj_t;
-typedef struct _mod_network_nic_type_t {
- mp_obj_type_t base;
-
+typedef struct _mod_network_nic_protocol_t {
// API for non-socket operations
int (*gethostbyname)(mp_obj_t nic, const char *name, mp_uint_t len, uint8_t *ip_out);
@@ -81,12 +87,12 @@ typedef struct _mod_network_nic_type_t {
int (*setsockopt)(struct _mod_network_socket_obj_t *socket, mp_uint_t level, mp_uint_t opt, const void *optval, mp_uint_t optlen, int *_errno);
int (*settimeout)(struct _mod_network_socket_obj_t *socket, mp_uint_t timeout_ms, int *_errno);
int (*ioctl)(struct _mod_network_socket_obj_t *socket, mp_uint_t request, mp_uint_t arg, int *_errno);
-} mod_network_nic_type_t;
+} mod_network_nic_protocol_t;
typedef struct _mod_network_socket_obj_t {
mp_obj_base_t base;
mp_obj_t nic;
- mod_network_nic_type_t *nic_type;
+ mod_network_nic_protocol_t *nic_protocol;
uint32_t domain : 5;
uint32_t type : 5;
uint32_t proto : 5;
@@ -101,11 +107,13 @@ typedef struct _mod_network_socket_obj_t {
#endif
} mod_network_socket_obj_t;
-#endif // MICROPY_PY_LWIP
+#endif // MICROPY_PY_LWIP / MICROPY_PORT_NETWORK_INTERFACES
+#ifdef MICROPY_PORT_NETWORK_INTERFACES
void mod_network_init(void);
void mod_network_deinit(void);
void mod_network_register_nic(mp_obj_t nic);
mp_obj_t mod_network_find_nic(const uint8_t *ip);
+#endif
#endif // MICROPY_INCLUDED_MODNETWORK_H
diff --git a/extmod/moduasyncio.c b/extmod/moduasyncio.c
index 6e3603fa18a4..021e0da1be2c 100644
--- a/extmod/moduasyncio.c
+++ b/extmod/moduasyncio.c
@@ -144,12 +144,13 @@ STATIC const mp_rom_map_elem_t task_queue_locals_dict_table[] = {
};
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,
-};
+STATIC MP_DEFINE_CONST_OBJ_TYPE(
+ task_queue_type,
+ MP_QSTR_TaskQueue,
+ MP_TYPE_FLAG_NONE,
+ make_new, task_queue_make_new,
+ locals_dict, &task_queue_locals_dict
+ );
/******************************************************************************/
// Task class
@@ -286,15 +287,20 @@ STATIC mp_obj_t task_iternext(mp_obj_t 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,
+STATIC const mp_getiter_iternext_custom_t task_getiter_iternext = {
.getiter = task_getiter,
.iternext = task_iternext,
};
+STATIC MP_DEFINE_CONST_OBJ_TYPE(
+ task_type,
+ MP_QSTR_Task,
+ MP_TYPE_FLAG_ITER_IS_CUSTOM,
+ make_new, task_make_new,
+ attr, task_attr,
+ iter, &task_getiter_iternext
+ );
+
/******************************************************************************/
// C-level uasyncio module
diff --git a/extmod/modubinascii.c b/extmod/modubinascii.c
index c0e2c587fdd9..45a39c58d443 100644
--- a/extmod/modubinascii.c
+++ b/extmod/modubinascii.c
@@ -30,78 +30,21 @@
#include "py/runtime.h"
#include "py/binary.h"
+#include "py/objstr.h"
#if MICROPY_PY_UBINASCII
-STATIC mp_obj_t mod_binascii_hexlify(size_t n_args, const mp_obj_t *args) {
- // First argument is the data to convert.
- // Second argument is an optional separator to be used between values.
- const char *sep = NULL;
- mp_buffer_info_t bufinfo;
- mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_READ);
-
- // Code below assumes non-zero buffer length when computing size with
- // separator, so handle the zero-length case here.
- if (bufinfo.len == 0) {
- return mp_const_empty_bytes;
- }
-
- vstr_t vstr;
- size_t out_len = bufinfo.len * 2;
- if (n_args > 1) {
- // 1-char separator between hex numbers
- out_len += bufinfo.len - 1;
- sep = mp_obj_str_get_str(args[1]);
- }
- vstr_init_len(&vstr, out_len);
- byte *in = bufinfo.buf, *out = (byte *)vstr.buf;
- for (mp_uint_t i = bufinfo.len; i--;) {
- byte d = (*in >> 4);
- if (d > 9) {
- d += 'a' - '9' - 1;
- }
- *out++ = d + '0';
- d = (*in++ & 0xf);
- if (d > 9) {
- d += 'a' - '9' - 1;
- }
- *out++ = d + '0';
- if (sep != NULL && i != 0) {
- *out++ = *sep;
- }
- }
- return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
+#if MICROPY_PY_BUILTINS_BYTES_HEX
+STATIC mp_obj_t bytes_hex_as_bytes(size_t n_args, const mp_obj_t *args) {
+ return mp_obj_bytes_hex(n_args, args, &mp_type_bytes);
}
-STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_binascii_hexlify_obj, 1, 2, mod_binascii_hexlify);
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bytes_hex_as_bytes_obj, 1, 2, bytes_hex_as_bytes);
-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(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 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(MP_ERROR_TEXT("non-hex digit found"));
- }
- if (i & 1) {
- hex_byte <<= 4;
- } else {
- *out++ = hex_byte;
- hex_byte = 0;
- }
- }
- return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
+STATIC mp_obj_t bytes_fromhex_bytes(mp_obj_t data) {
+ return mp_obj_bytes_fromhex(MP_OBJ_FROM_PTR(&mp_type_bytes), data);
}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_binascii_unhexlify_obj, mod_binascii_unhexlify);
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(bytes_fromhex_obj, bytes_fromhex_bytes);
+#endif
// 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.
@@ -161,7 +104,7 @@ STATIC mp_obj_t mod_binascii_a2b_base64(mp_obj_t data) {
mp_raise_ValueError(MP_ERROR_TEXT("incorrect padding"));
}
- return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
+ return mp_obj_new_bytes_from_vstr(&vstr);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_binascii_a2b_base64_obj, mod_binascii_a2b_base64);
@@ -223,7 +166,7 @@ STATIC mp_obj_t mod_binascii_b2a_base64(size_t n_args, const mp_obj_t *pos_args,
if (newline) {
*out = '\n';
}
- return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
+ return mp_obj_new_bytes_from_vstr(&vstr);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mod_binascii_b2a_base64_obj, 1, mod_binascii_b2a_base64);
@@ -242,8 +185,10 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_binascii_crc32_obj, 1, 2, mod_bin
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) },
- { MP_ROM_QSTR(MP_QSTR_unhexlify), MP_ROM_PTR(&mod_binascii_unhexlify_obj) },
+ #if MICROPY_PY_BUILTINS_BYTES_HEX
+ { MP_ROM_QSTR(MP_QSTR_hexlify), MP_ROM_PTR(&bytes_hex_as_bytes_obj) },
+ { MP_ROM_QSTR(MP_QSTR_unhexlify), MP_ROM_PTR(&bytes_fromhex_obj) },
+ #endif
{ MP_ROM_QSTR(MP_QSTR_a2b_base64), MP_ROM_PTR(&mod_binascii_a2b_base64_obj) },
{ MP_ROM_QSTR(MP_QSTR_b2a_base64), MP_ROM_PTR(&mod_binascii_b2a_base64_obj) },
#if MICROPY_PY_UBINASCII_CRC32
diff --git a/extmod/moducryptolib.c b/extmod/moducryptolib.c
index c58abaada67e..fc3fcfd90d90 100644
--- a/extmod/moducryptolib.c
+++ b/extmod/moducryptolib.c
@@ -329,7 +329,7 @@ STATIC mp_obj_t aes_process(size_t n_args, const mp_obj_t *args, bool encrypt) {
if (out_buf != MP_OBJ_NULL) {
return out_buf;
}
- return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
+ return mp_obj_new_bytes_from_vstr(&vstr);
}
STATIC mp_obj_t ucryptolib_aes_encrypt(size_t n_args, const mp_obj_t *args) {
@@ -348,12 +348,13 @@ STATIC const mp_rom_map_elem_t ucryptolib_aes_locals_dict_table[] = {
};
STATIC MP_DEFINE_CONST_DICT(ucryptolib_aes_locals_dict, ucryptolib_aes_locals_dict_table);
-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,
-};
+STATIC MP_DEFINE_CONST_OBJ_TYPE(
+ ucryptolib_aes_type,
+ MP_QSTR_aes,
+ MP_TYPE_FLAG_NONE,
+ make_new, ucryptolib_aes_make_new,
+ locals_dict, &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) },
diff --git a/extmod/moductypes.c b/extmod/moductypes.c
index 547453c48e9f..15c36290a9f0 100644
--- a/extmod/moductypes.c
+++ b/extmod/moductypes.c
@@ -634,16 +634,17 @@ STATIC mp_obj_t uctypes_struct_bytes_at(mp_obj_t ptr, mp_obj_t size) {
}
MP_DEFINE_CONST_FUN_OBJ_2(uctypes_struct_bytes_at_obj, uctypes_struct_bytes_at);
-STATIC const mp_obj_type_t uctypes_struct_type = {
- { &mp_type_type },
- .name = MP_QSTR_struct,
- .print = uctypes_struct_print,
- .make_new = uctypes_struct_make_new,
- .attr = uctypes_struct_attr,
- .subscr = uctypes_struct_subscr,
- .unary_op = uctypes_struct_unary_op,
- .buffer_p = { .get_buffer = uctypes_get_buffer },
-};
+STATIC MP_DEFINE_CONST_OBJ_TYPE(
+ uctypes_struct_type,
+ MP_QSTR_struct,
+ MP_TYPE_FLAG_NONE,
+ make_new, uctypes_struct_make_new,
+ print, uctypes_struct_print,
+ attr, uctypes_struct_attr,
+ subscr, uctypes_struct_subscr,
+ unary_op, uctypes_struct_unary_op,
+ buffer, uctypes_get_buffer
+ );
STATIC const mp_rom_map_elem_t mp_module_uctypes_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uctypes) },
diff --git a/extmod/moduhashlib.c b/extmod/moduhashlib.c
index 39488788f271..64e15c444df8 100644
--- a/extmod/moduhashlib.c
+++ b/extmod/moduhashlib.c
@@ -109,7 +109,7 @@ STATIC mp_obj_t uhashlib_sha256_digest(mp_obj_t self_in) {
vstr_t vstr;
vstr_init_len(&vstr, 32);
mbedtls_sha256_finish_ret((mbedtls_sha256_context *)&self->state, (unsigned char *)vstr.buf);
- return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
+ return mp_obj_new_bytes_from_vstr(&vstr);
}
#else
@@ -143,7 +143,7 @@ STATIC mp_obj_t uhashlib_sha256_digest(mp_obj_t self_in) {
vstr_t vstr;
vstr_init_len(&vstr, SHA256_BLOCK_SIZE);
sha256_final((CRYAL_SHA256_CTX *)self->state, (byte *)vstr.buf);
- return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
+ return mp_obj_new_bytes_from_vstr(&vstr);
}
#endif
@@ -157,12 +157,13 @@ STATIC const mp_rom_map_elem_t uhashlib_sha256_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(uhashlib_sha256_locals_dict, uhashlib_sha256_locals_dict_table);
-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,
-};
+STATIC MP_DEFINE_CONST_OBJ_TYPE(
+ uhashlib_sha256_type,
+ MP_QSTR_sha256,
+ MP_TYPE_FLAG_NONE,
+ make_new, uhashlib_sha256_make_new,
+ locals_dict, &uhashlib_sha256_locals_dict
+ );
#endif
#if MICROPY_PY_UHASHLIB_SHA1
@@ -196,7 +197,7 @@ STATIC mp_obj_t uhashlib_sha1_digest(mp_obj_t self_in) {
vstr_t vstr;
vstr_init_len(&vstr, SHA1_SIZE);
SHA1_Final((byte *)vstr.buf, (SHA1_CTX *)self->state);
- return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
+ return mp_obj_new_bytes_from_vstr(&vstr);
}
#endif
@@ -237,7 +238,7 @@ STATIC mp_obj_t uhashlib_sha1_digest(mp_obj_t self_in) {
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);
- return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
+ return mp_obj_new_bytes_from_vstr(&vstr);
}
#endif
@@ -250,12 +251,13 @@ STATIC const mp_rom_map_elem_t uhashlib_sha1_locals_dict_table[] = {
};
STATIC MP_DEFINE_CONST_DICT(uhashlib_sha1_locals_dict, uhashlib_sha1_locals_dict_table);
-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,
-};
+STATIC MP_DEFINE_CONST_OBJ_TYPE(
+ uhashlib_sha1_type,
+ MP_QSTR_sha1,
+ MP_TYPE_FLAG_NONE,
+ make_new, uhashlib_sha1_make_new,
+ locals_dict, &uhashlib_sha1_locals_dict
+ );
#endif
#if MICROPY_PY_UHASHLIB_MD5
@@ -289,7 +291,7 @@ STATIC mp_obj_t uhashlib_md5_digest(mp_obj_t self_in) {
vstr_t vstr;
vstr_init_len(&vstr, MD5_SIZE);
MD5_Final((byte *)vstr.buf, (MD5_CTX *)self->state);
- return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
+ return mp_obj_new_bytes_from_vstr(&vstr);
}
#endif // MICROPY_SSL_AXTLS
@@ -330,7 +332,7 @@ STATIC mp_obj_t uhashlib_md5_digest(mp_obj_t self_in) {
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);
- return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
+ return mp_obj_new_bytes_from_vstr(&vstr);
}
#endif // MICROPY_SSL_MBEDTLS
@@ -343,12 +345,13 @@ STATIC const mp_rom_map_elem_t uhashlib_md5_locals_dict_table[] = {
};
STATIC MP_DEFINE_CONST_DICT(uhashlib_md5_locals_dict, uhashlib_md5_locals_dict_table);
-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,
-};
+STATIC MP_DEFINE_CONST_OBJ_TYPE(
+ uhashlib_md5_type,
+ MP_QSTR_md5,
+ MP_TYPE_FLAG_NONE,
+ make_new, uhashlib_md5_make_new,
+ locals_dict, &uhashlib_md5_locals_dict
+ );
#endif // MICROPY_PY_UHASHLIB_MD5
STATIC const mp_rom_map_elem_t mp_module_uhashlib_globals_table[] = {
diff --git a/extmod/modujson.c b/extmod/modujson.c
index bee432db255f..4e992e2245d1 100644
--- a/extmod/modujson.c
+++ b/extmod/modujson.c
@@ -67,7 +67,7 @@ STATIC mp_obj_t mod_ujson_dump_helper(size_t n_args, const mp_obj_t *pos_args, m
vstr_t vstr;
vstr_init_print(&vstr, 8, &print_ext.base);
mp_obj_print_helper(&print_ext.base, pos_args[0], PRINT_JSON);
- return mp_obj_new_str_from_vstr(&mp_type_str, &vstr);
+ return mp_obj_new_str_from_utf8_vstr(&vstr);
} else {
// dump(obj, stream)
print_ext.base.data = MP_OBJ_TO_PTR(pos_args[1]);
@@ -103,7 +103,7 @@ STATIC mp_obj_t mod_ujson_dumps(mp_obj_t obj) {
mp_print_t print;
vstr_init_print(&vstr, 8, &print);
mp_obj_print_helper(&print, obj, PRINT_JSON);
- return mp_obj_new_str_from_vstr(&mp_type_str, &vstr);
+ return mp_obj_new_str_from_utf8_vstr(&vstr);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_ujson_dumps_obj, mod_ujson_dumps);
@@ -270,7 +270,7 @@ STATIC mp_obj_t mod_ujson_load(mp_obj_t stream_obj) {
S_NEXT(s);
}
if (flt) {
- next = mp_parse_num_decimal(vstr.buf, vstr.len, false, false, NULL);
+ next = mp_parse_num_float(vstr.buf, vstr.len, false, NULL);
} else {
next = mp_parse_num_integer(vstr.buf, vstr.len, 10, NULL);
}
diff --git a/extmod/moduplatform.h b/extmod/moduplatform.h
index 2b9ad3ae49b7..42ed4de24871 100644
--- a/extmod/moduplatform.h
+++ b/extmod/moduplatform.h
@@ -37,11 +37,11 @@
#if defined(__ARM_ARCH)
#define MICROPY_PLATFORM_ARCH "arm"
-#elif defined(__x86_64__) || defined(_WIN64)
+#elif defined(__x86_64__) || defined(_M_X64)
#define MICROPY_PLATFORM_ARCH "x86_64"
#elif defined(__i386__) || defined(_M_IX86)
#define MICROPY_PLATFORM_ARCH "x86"
-#elif defined(__xtensa__) || defined(_M_IX86)
+#elif defined(__xtensa__)
#define MICROPY_PLATFORM_ARCH "xtensa"
#else
#define MICROPY_PLATFORM_ARCH ""
diff --git a/extmod/modure.c b/extmod/modure.c
index 6bd89898431f..801e5df89779 100644
--- a/extmod/modure.c
+++ b/extmod/modure.c
@@ -33,6 +33,10 @@
#include "py/objstr.h"
#include "py/stackctrl.h"
+#if MICROPY_PY_BUILTINS_STR_UNICODE
+#include "py/unicode.h"
+#endif
+
#if MICROPY_PY_URE
#define re1_5_stack_chk() MP_STACK_CHECK()
@@ -121,6 +125,18 @@ STATIC void match_span_helper(size_t n_args, const mp_obj_t *args, mp_obj_t span
e = self->caps[no * 2 + 1] - begin;
}
+ #if MICROPY_PY_BUILTINS_STR_UNICODE
+ if (mp_obj_get_type(self->str) == &mp_type_str) {
+ const byte *begin = (const byte *)mp_obj_str_get_str(self->str);
+ if (s != -1) {
+ s = utf8_ptr_to_index(begin, begin + s);
+ }
+ if (e != -1) {
+ e = utf8_ptr_to_index(begin, begin + e);
+ }
+ }
+ #endif
+
span[0] = mp_obj_new_int(s);
span[1] = mp_obj_new_int(e);
}
@@ -163,12 +179,13 @@ STATIC const mp_rom_map_elem_t match_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(match_locals_dict, match_locals_dict_table);
-STATIC const mp_obj_type_t match_type = {
- { &mp_type_type },
- .name = MP_QSTR_match,
- .print = match_print,
- .locals_dict = (void *)&match_locals_dict,
-};
+STATIC MP_DEFINE_CONST_OBJ_TYPE(
+ match_type,
+ MP_QSTR_match,
+ MP_TYPE_FLAG_NONE,
+ print, match_print,
+ locals_dict, &match_locals_dict
+ );
#endif
STATIC void re_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
@@ -180,7 +197,7 @@ 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;
- if (mp_obj_is_type(args[0], &re_type)) {
+ if (mp_obj_is_type(args[0], (mp_obj_type_t *)&re_type)) {
self = MP_OBJ_TO_PTR(args[0]);
} else {
self = MP_OBJ_TO_PTR(mod_re_compile(1, args));
@@ -199,7 +216,7 @@ STATIC mp_obj_t ure_exec(bool is_anchored, uint n_args, const mp_obj_t *args) {
return mp_const_none;
}
- match->base.type = &match_type;
+ match->base.type = (mp_obj_type_t *)&match_type;
match->num_matches = caps_num / 2; // caps_num counts start and end pointers
match->str = args[1];
return MP_OBJ_FROM_PTR(match);
@@ -264,7 +281,7 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(re_split_obj, 2, 3, re_split);
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)) {
+ if (mp_obj_is_type(args[0], (mp_obj_type_t *)&re_type)) {
self = MP_OBJ_TO_PTR(args[0]);
} else {
self = MP_OBJ_TO_PTR(mod_re_compile(1, args));
@@ -287,7 +304,7 @@ STATIC mp_obj_t re_sub_helper(size_t n_args, const mp_obj_t *args) {
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 *));
- match->base.type = &match_type;
+ match->base.type = (mp_obj_type_t *)&match_type;
match->num_matches = caps_num / 2; // caps_num counts start and end pointers
match->str = where;
@@ -372,7 +389,11 @@ STATIC mp_obj_t re_sub_helper(size_t n_args, const mp_obj_t *args) {
// Add post-match string
vstr_add_strn(&vstr_return, subj.begin, subj.end - subj.begin);
- return mp_obj_new_str_from_vstr(mp_obj_get_type(where), &vstr_return);
+ if (mp_obj_get_type(where) == &mp_type_str) {
+ return mp_obj_new_str_from_utf8_vstr(&vstr_return);
+ } else {
+ return mp_obj_new_bytes_from_vstr(&vstr_return);
+ }
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(re_sub_obj, 3, 5, re_sub_helper);
@@ -391,12 +412,13 @@ STATIC const mp_rom_map_elem_t re_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(re_locals_dict, re_locals_dict_table);
-STATIC const mp_obj_type_t re_type = {
- { &mp_type_type },
- .name = MP_QSTR_ure,
- .print = re_print,
- .locals_dict = (void *)&re_locals_dict,
-};
+STATIC MP_DEFINE_CONST_OBJ_TYPE(
+ re_type,
+ MP_QSTR_ure,
+ MP_TYPE_FLAG_NONE,
+ print, re_print,
+ locals_dict, &re_locals_dict
+ );
#endif
STATIC mp_obj_t mod_re_compile(size_t n_args, const mp_obj_t *args) {
@@ -406,7 +428,7 @@ STATIC mp_obj_t mod_re_compile(size_t n_args, const mp_obj_t *args) {
if (size == -1) {
goto error;
}
- mp_obj_re_t *o = mp_obj_malloc_var(mp_obj_re_t, char, size, &re_type);
+ mp_obj_re_t *o = mp_obj_malloc_var(mp_obj_re_t, char, size, (mp_obj_type_t *)&re_type);
#if MICROPY_PY_URE_DEBUG
int flags = 0;
if (n_args > 1) {
diff --git a/extmod/moduselect.c b/extmod/moduselect.c
index 70a1de2e4099..128154a4b6d9 100644
--- a/extmod/moduselect.c
+++ b/extmod/moduselect.c
@@ -336,13 +336,13 @@ STATIC const mp_rom_map_elem_t poll_locals_dict_table[] = {
};
STATIC MP_DEFINE_CONST_DICT(poll_locals_dict, poll_locals_dict_table);
-STATIC const mp_obj_type_t mp_type_poll = {
- { &mp_type_type },
- .name = MP_QSTR_poll,
- .getiter = mp_identity_getiter,
- .iternext = poll_iternext,
- .locals_dict = (void *)&poll_locals_dict,
-};
+STATIC MP_DEFINE_CONST_OBJ_TYPE(
+ mp_type_poll,
+ MP_QSTR_poll,
+ MP_TYPE_FLAG_ITER_IS_ITERNEXT,
+ iter, poll_iternext,
+ locals_dict, &poll_locals_dict
+ );
// poll()
STATIC mp_obj_t select_poll(void) {
diff --git a/extmod/modusocket.c b/extmod/modusocket.c
index 638ab0cf28c0..2aa6010884a0 100644
--- a/extmod/modusocket.c
+++ b/extmod/modusocket.c
@@ -32,11 +32,12 @@
#include "py/runtime.h"
#include "py/stream.h"
#include "py/mperrno.h"
-#include "shared/netutils/netutils.h"
-#include "modnetwork.h"
#if MICROPY_PY_NETWORK && MICROPY_PY_USOCKET && !MICROPY_PY_LWIP
+#include "shared/netutils/netutils.h"
+#include "modnetwork.h"
+
/******************************************************************************/
// socket class
@@ -56,7 +57,7 @@ STATIC mp_obj_t socket_make_new(const mp_obj_type_t *type, size_t n_args, size_t
mod_network_socket_obj_t *s = m_new_obj_with_finaliser(mod_network_socket_obj_t);
s->base.type = &socket_type;
s->nic = MP_OBJ_NULL;
- s->nic_type = NULL;
+ s->nic_protocol = NULL;
s->domain = MOD_NETWORK_AF_INET;
s->type = MOD_NETWORK_SOCK_STREAM;
s->proto = 0;
@@ -85,17 +86,17 @@ STATIC void socket_select_nic(mod_network_socket_obj_t *self, const byte *ip) {
if (self->nic == MP_OBJ_NULL) {
// select NIC based on IP
self->nic = mod_network_find_nic(ip);
- self->nic_type = (mod_network_nic_type_t *)mp_obj_get_type(self->nic);
+ self->nic_protocol = (mod_network_nic_protocol_t *)MP_OBJ_TYPE_GET_SLOT(mp_obj_get_type(self->nic), protocol);
// call the NIC to open the socket
int _errno;
- if (self->nic_type->socket(self, &_errno) != 0) {
+ if (self->nic_protocol->socket(self, &_errno) != 0) {
mp_raise_OSError(_errno);
}
#if MICROPY_PY_USOCKET_EXTENDED_STATE
// if a timeout was set before binding a NIC, call settimeout to reset it
- if (self->timeout != -1 && self->nic_type->settimeout(self, self->timeout, &_errno) != 0) {
+ if (self->timeout != -1 && self->nic_protocol->settimeout(self, self->timeout, &_errno) != 0) {
mp_raise_OSError(_errno);
}
#endif
@@ -115,7 +116,7 @@ STATIC mp_obj_t socket_bind(mp_obj_t self_in, mp_obj_t addr_in) {
// call the NIC to bind the socket
int _errno;
- if (self->nic_type->bind(self, ip, port, &_errno) != 0) {
+ if (self->nic_protocol->bind(self, ip, port, &_errno) != 0) {
mp_raise_OSError(_errno);
}
@@ -140,7 +141,7 @@ STATIC mp_obj_t socket_listen(size_t n_args, const mp_obj_t *args) {
}
int _errno;
- if (self->nic_type->listen(self, backlog, &_errno) != 0) {
+ if (self->nic_protocol->listen(self, backlog, &_errno) != 0) {
mp_raise_OSError(_errno);
}
@@ -165,7 +166,7 @@ STATIC mp_obj_t socket_accept(mp_obj_t self_in) {
mod_network_socket_obj_t *socket2 = m_new_obj_with_finaliser(mod_network_socket_obj_t);
socket2->base.type = &socket_type;
socket2->nic = MP_OBJ_NULL;
- socket2->nic_type = NULL;
+ socket2->nic_protocol = NULL;
// set the same address family, socket type and protocol as parent
socket2->domain = self->domain;
@@ -184,13 +185,13 @@ STATIC mp_obj_t socket_accept(mp_obj_t self_in) {
uint8_t ip[MOD_NETWORK_IPADDR_BUF_SIZE];
mp_uint_t port;
int _errno;
- if (self->nic_type->accept(self, socket2, ip, &port, &_errno) != 0) {
+ if (self->nic_protocol->accept(self, socket2, ip, &port, &_errno) != 0) {
mp_raise_OSError(_errno);
}
// new socket has valid state, so set the NIC to the same as parent
socket2->nic = self->nic;
- socket2->nic_type = self->nic_type;
+ socket2->nic_protocol = self->nic_protocol;
// make the return value
mp_obj_tuple_t *client = MP_OBJ_TO_PTR(mp_obj_new_tuple(2, NULL));
@@ -214,7 +215,7 @@ STATIC mp_obj_t socket_connect(mp_obj_t self_in, mp_obj_t addr_in) {
// call the NIC to connect the socket
int _errno;
- if (self->nic_type->connect(self, ip, port, &_errno) != 0) {
+ if (self->nic_protocol->connect(self, ip, port, &_errno) != 0) {
mp_raise_OSError(_errno);
}
@@ -235,7 +236,7 @@ STATIC mp_obj_t socket_send(mp_obj_t self_in, mp_obj_t buf_in) {
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ);
int _errno;
- mp_uint_t ret = self->nic_type->send(self, bufinfo.buf, bufinfo.len, &_errno);
+ mp_uint_t ret = self->nic_protocol->send(self, bufinfo.buf, bufinfo.len, &_errno);
if (ret == -1) {
mp_raise_OSError(_errno);
}
@@ -255,7 +256,7 @@ STATIC mp_obj_t socket_sendall(mp_obj_t self_in, mp_obj_t buf_in) {
int _errno;
mp_uint_t ret = 0;
if (self->timeout == 0) {
- ret = self->nic_type->send(self, bufinfo.buf, bufinfo.len, &_errno);
+ ret = self->nic_protocol->send(self, bufinfo.buf, bufinfo.len, &_errno);
if (ret == -1) {
mp_raise_OSError(_errno);
} else if (bufinfo.len > ret) {
@@ -265,7 +266,7 @@ STATIC mp_obj_t socket_sendall(mp_obj_t self_in, mp_obj_t buf_in) {
// TODO: In CPython3.5, socket timeout should apply to the
// entire sendall() operation, not to individual send() chunks.
while (bufinfo.len != 0) {
- ret = self->nic_type->send(self, bufinfo.buf, bufinfo.len, &_errno);
+ ret = self->nic_protocol->send(self, bufinfo.buf, bufinfo.len, &_errno);
if (ret == -1) {
mp_raise_OSError(_errno);
}
@@ -288,7 +289,7 @@ STATIC mp_obj_t socket_recv(mp_obj_t self_in, mp_obj_t len_in) {
vstr_t vstr;
vstr_init_len(&vstr, len);
int _errno;
- mp_uint_t ret = self->nic_type->recv(self, (byte *)vstr.buf, len, &_errno);
+ mp_uint_t ret = self->nic_protocol->recv(self, (byte *)vstr.buf, len, &_errno);
if (ret == -1) {
mp_raise_OSError(_errno);
}
@@ -296,7 +297,7 @@ STATIC mp_obj_t socket_recv(mp_obj_t self_in, mp_obj_t len_in) {
return mp_const_empty_bytes;
}
vstr.len = ret;
- return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
+ return mp_obj_new_bytes_from_vstr(&vstr);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_recv_obj, socket_recv);
@@ -317,7 +318,7 @@ STATIC mp_obj_t socket_sendto(mp_obj_t self_in, mp_obj_t data_in, mp_obj_t addr_
// call the NIC to sendto
int _errno;
- mp_int_t ret = self->nic_type->sendto(self, bufinfo.buf, bufinfo.len, ip, port, &_errno);
+ mp_int_t ret = self->nic_protocol->sendto(self, bufinfo.buf, bufinfo.len, ip, port, &_errno);
if (ret == -1) {
mp_raise_OSError(_errno);
}
@@ -338,7 +339,7 @@ STATIC mp_obj_t socket_recvfrom(mp_obj_t self_in, mp_obj_t len_in) {
byte ip[4];
mp_uint_t port;
int _errno;
- mp_int_t ret = self->nic_type->recvfrom(self, (byte *)vstr.buf, vstr.len, ip, &port, &_errno);
+ mp_int_t ret = self->nic_protocol->recvfrom(self, (byte *)vstr.buf, vstr.len, ip, &port, &_errno);
if (ret == -1) {
mp_raise_OSError(_errno);
}
@@ -347,7 +348,7 @@ STATIC mp_obj_t socket_recvfrom(mp_obj_t self_in, mp_obj_t len_in) {
tuple[0] = mp_const_empty_bytes;
} else {
vstr.len = ret;
- tuple[0] = mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
+ tuple[0] = mp_obj_new_bytes_from_vstr(&vstr);
}
tuple[1] = netutils_format_inet_addr(ip, port, NETUTILS_BIG);
return mp_obj_new_tuple(2, tuple);
@@ -388,7 +389,7 @@ STATIC mp_obj_t socket_setsockopt(size_t n_args, const mp_obj_t *args) {
}
int _errno;
- if (self->nic_type->setsockopt(self, level, opt, optval, optlen, &_errno) != 0) {
+ if (self->nic_protocol->setsockopt(self, level, opt, optval, optlen, &_errno) != 0) {
mp_raise_OSError(_errno);
}
@@ -428,7 +429,7 @@ STATIC mp_obj_t socket_settimeout(mp_obj_t self_in, mp_obj_t timeout_in) {
#endif
} else {
int _errno;
- if (self->nic_type->settimeout(self, timeout, &_errno) != 0) {
+ if (self->nic_protocol->settimeout(self, timeout, &_errno) != 0) {
mp_raise_OSError(_errno);
}
}
@@ -476,7 +477,7 @@ mp_uint_t socket_read(mp_obj_t self_in, void *buf, mp_uint_t size, int *errcode)
if (self->nic == MP_OBJ_NULL) {
return MP_STREAM_ERROR;
}
- mp_int_t ret = self->nic_type->recv(self, (byte *)buf, size, errcode);
+ mp_int_t ret = self->nic_protocol->recv(self, (byte *)buf, size, errcode);
if (ret < 0) {
ret = MP_STREAM_ERROR;
}
@@ -488,7 +489,7 @@ mp_uint_t socket_write(mp_obj_t self_in, const void *buf, mp_uint_t size, int *e
if (self->nic == MP_OBJ_NULL) {
return MP_STREAM_ERROR;
}
- mp_int_t ret = self->nic_type->send(self, buf, size, errcode);
+ mp_int_t ret = self->nic_protocol->send(self, buf, size, errcode);
if (ret < 0) {
ret = MP_STREAM_ERROR;
}
@@ -499,7 +500,7 @@ mp_uint_t socket_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *
mod_network_socket_obj_t *self = MP_OBJ_TO_PTR(self_in);
if (request == MP_STREAM_CLOSE) {
if (self->nic != MP_OBJ_NULL) {
- self->nic_type->close(self);
+ self->nic_protocol->close(self);
self->nic = MP_OBJ_NULL;
}
self->state = MOD_NETWORK_SS_CLOSED;
@@ -518,7 +519,7 @@ mp_uint_t socket_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *
*errcode = MP_EINVAL;
return MP_STREAM_ERROR;
}
- return self->nic_type->ioctl(self, request, arg, errcode);
+ return self->nic_protocol->ioctl(self, request, arg, errcode);
}
STATIC const mp_stream_p_t socket_stream_p = {
@@ -528,14 +529,15 @@ STATIC const mp_stream_p_t socket_stream_p = {
.is_text = false,
};
-STATIC const mp_obj_type_t socket_type = {
- { &mp_type_type },
- .name = MP_QSTR_socket,
- .print = socket_print,
- .make_new = socket_make_new,
- .protocol = &socket_stream_p,
- .locals_dict = (mp_obj_dict_t *)&socket_locals_dict,
-};
+STATIC MP_DEFINE_CONST_OBJ_TYPE(
+ socket_type,
+ MP_QSTR_socket,
+ MP_TYPE_FLAG_NONE,
+ make_new, socket_make_new,
+ protocol, &socket_stream_p,
+ locals_dict, &socket_locals_dict,
+ print, socket_print
+ );
/******************************************************************************/
// usocket module
@@ -587,9 +589,9 @@ STATIC mp_obj_t mod_usocket_getaddrinfo(size_t n_args, const mp_obj_t *args) {
// find a NIC that can do a name lookup
for (mp_uint_t i = 0; i < MP_STATE_PORT(mod_network_nic_list).len; i++) {
mp_obj_t nic = MP_STATE_PORT(mod_network_nic_list).items[i];
- mod_network_nic_type_t *nic_type = (mod_network_nic_type_t *)mp_obj_get_type(nic);
- if (nic_type->gethostbyname != NULL) {
- int ret = nic_type->gethostbyname(nic, host, hlen, out_ip);
+ mod_network_nic_protocol_t *nic_protocol = (mod_network_nic_protocol_t *)MP_OBJ_TYPE_GET_SLOT(mp_obj_get_type(nic), protocol);
+ if (nic_protocol->gethostbyname != NULL) {
+ int ret = nic_protocol->gethostbyname(nic, host, hlen, out_ip);
if (ret != 0) {
mp_raise_OSError(ret);
}
diff --git a/extmod/modussl_axtls.c b/extmod/modussl_axtls.c
index 9ba613a3e89e..2eae46504835 100644
--- a/extmod/modussl_axtls.c
+++ b/extmod/modussl_axtls.c
@@ -314,16 +314,15 @@ STATIC const mp_stream_p_t ussl_socket_stream_p = {
.ioctl = ussl_socket_ioctl,
};
-STATIC const mp_obj_type_t ussl_socket_type = {
- { &mp_type_type },
+STATIC MP_DEFINE_CONST_OBJ_TYPE(
+ ussl_socket_type,
+ MP_QSTR_ussl,
+ MP_TYPE_FLAG_NONE,
// Save on qstr's, reuse same as for module
- .name = MP_QSTR_ussl,
- .print = ussl_socket_print,
- .getiter = NULL,
- .iternext = NULL,
- .protocol = &ussl_socket_stream_p,
- .locals_dict = (void *)&ussl_socket_locals_dict,
-};
+ print, ussl_socket_print,
+ protocol, &ussl_socket_stream_p,
+ locals_dict, &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
diff --git a/extmod/modussl_mbedtls.c b/extmod/modussl_mbedtls.c
index 44668ae63bba..eea2d79532d8 100644
--- a/extmod/modussl_mbedtls.c
+++ b/extmod/modussl_mbedtls.c
@@ -46,6 +46,8 @@
#include "mbedtls/debug.h"
#include "mbedtls/error.h"
+#define MP_STREAM_POLL_RDWR (MP_STREAM_POLL_RD | MP_STREAM_POLL_WR)
+
typedef struct _mp_obj_ssl_socket_t {
mp_obj_base_t base;
mp_obj_t sock;
@@ -56,6 +58,9 @@ typedef struct _mp_obj_ssl_socket_t {
mbedtls_x509_crt cacert;
mbedtls_x509_crt cert;
mbedtls_pk_context pkey;
+
+ uintptr_t poll_mask; // Indicates which read or write operations the protocol needs next
+ int last_error; // The last error code, if any
} mp_obj_ssl_socket_t;
struct ssl_args {
@@ -63,6 +68,8 @@ struct ssl_args {
mp_arg_val_t cert;
mp_arg_val_t server_side;
mp_arg_val_t server_hostname;
+ mp_arg_val_t cert_reqs;
+ mp_arg_val_t cadata;
mp_arg_val_t do_handshake;
};
@@ -72,7 +79,7 @@ STATIC const mp_obj_type_t ussl_socket_type;
STATIC void mbedtls_debug(void *ctx, int level, const char *file, int line, const char *str) {
(void)ctx;
(void)level;
- printf("DBG:%s:%04d: %s\n", file, line, str);
+ mp_printf(&mp_plat_print, "DBG:%s:%04d: %s\n", file, line, str);
}
#endif
@@ -163,6 +170,8 @@ STATIC mp_obj_ssl_socket_t *socket_new(mp_obj_t sock, struct ssl_args *args) {
#endif
o->base.type = &ussl_socket_type;
o->sock = sock;
+ o->poll_mask = 0;
+ o->last_error = 0;
int ret;
mbedtls_ssl_init(&o->ssl);
@@ -173,7 +182,7 @@ STATIC mp_obj_ssl_socket_t *socket_new(mp_obj_t sock, struct ssl_args *args) {
mbedtls_ctr_drbg_init(&o->ctr_drbg);
#ifdef MBEDTLS_DEBUG_C
// Debug level (0-4) 1=warning, 2=info, 3=debug, 4=verbose
- mbedtls_debug_set_threshold(0);
+ mbedtls_debug_set_threshold(3);
#endif
mbedtls_entropy_init(&o->entropy);
@@ -191,7 +200,7 @@ STATIC mp_obj_ssl_socket_t *socket_new(mp_obj_t sock, struct ssl_args *args) {
goto cleanup;
}
- mbedtls_ssl_conf_authmode(&o->conf, MBEDTLS_SSL_VERIFY_NONE);
+ mbedtls_ssl_conf_authmode(&o->conf, args->cert_reqs.u_int);
mbedtls_ssl_conf_rng(&o->conf, mbedtls_ctr_drbg_random, &o->ctr_drbg);
#ifdef MBEDTLS_DEBUG_C
mbedtls_ssl_conf_dbg(&o->conf, mbedtls_debug, NULL);
@@ -237,6 +246,19 @@ STATIC mp_obj_ssl_socket_t *socket_new(mp_obj_t sock, struct ssl_args *args) {
}
}
+ if (args->cadata.u_obj != mp_const_none) {
+ size_t cacert_len;
+ const byte *cacert = (const byte *)mp_obj_str_get_data(args->cadata.u_obj, &cacert_len);
+ // len should include terminating null
+ ret = mbedtls_x509_crt_parse(&o->cacert, cacert, cacert_len + 1);
+ if (ret != 0) {
+ ret = MBEDTLS_ERR_X509_BAD_INPUT_DATA; // use general error for all cert errors
+ goto cleanup;
+ }
+
+ mbedtls_ssl_conf_ca_chain(&o->conf, &o->cacert, NULL);
+ }
+
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) {
@@ -291,6 +313,12 @@ STATIC void socket_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kin
STATIC mp_uint_t 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);
+ o->poll_mask = 0;
+
+ if (o->last_error) {
+ *errcode = o->last_error;
+ return MP_STREAM_ERROR;
+ }
int ret = mbedtls_ssl_read(&o->ssl, buf, size);
if (ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) {
@@ -307,6 +335,9 @@ STATIC mp_uint_t socket_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errc
// wanting to write next handshake message. The same may happen with
// renegotation.
ret = MP_EWOULDBLOCK;
+ o->poll_mask = MP_STREAM_POLL_WR;
+ } else {
+ o->last_error = ret;
}
*errcode = ret;
return MP_STREAM_ERROR;
@@ -314,6 +345,12 @@ STATIC mp_uint_t socket_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errc
STATIC mp_uint_t 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);
+ o->poll_mask = 0;
+
+ if (o->last_error) {
+ *errcode = o->last_error;
+ return MP_STREAM_ERROR;
+ }
int ret = mbedtls_ssl_write(&o->ssl, buf, size);
if (ret >= 0) {
@@ -326,6 +363,9 @@ STATIC mp_uint_t socket_write(mp_obj_t o_in, const void *buf, mp_uint_t size, in
// wanting to read next handshake message. The same may happen with
// renegotation.
ret = MP_EWOULDBLOCK;
+ o->poll_mask = MP_STREAM_POLL_RD;
+ } else {
+ o->last_error = ret;
}
*errcode = ret;
return MP_STREAM_ERROR;
@@ -343,7 +383,16 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_setblocking_obj, socket_setblocking);
STATIC mp_uint_t 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);
+ mp_uint_t ret = 0;
+ uintptr_t saved_arg = 0;
+ mp_obj_t sock = self->sock;
+ if (sock == MP_OBJ_NULL || (request != MP_STREAM_CLOSE && self->last_error != 0)) {
+ // Closed or error socket:
+ return MP_STREAM_POLL_NVAL;
+ }
+
if (request == MP_STREAM_CLOSE) {
+ self->sock = MP_OBJ_NULL;
mbedtls_pk_free(&self->pkey);
mbedtls_x509_crt_free(&self->cert);
mbedtls_x509_crt_free(&self->cacert);
@@ -351,9 +400,39 @@ STATIC mp_uint_t socket_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg, i
mbedtls_ssl_config_free(&self->conf);
mbedtls_ctr_drbg_free(&self->ctr_drbg);
mbedtls_entropy_free(&self->entropy);
+ } else if (request == MP_STREAM_POLL) {
+ // If the library signaled us that it needs reading or writing, only check that direction,
+ // but save what the caller asked because we need to restore it later
+ if (self->poll_mask && (arg & MP_STREAM_POLL_RDWR)) {
+ saved_arg = arg & MP_STREAM_POLL_RDWR;
+ arg = (arg & ~saved_arg) | self->poll_mask;
+ }
+
+ // Take into account that the library might have buffered data already
+ int has_pending = 0;
+ if (arg & MP_STREAM_POLL_RD) {
+ has_pending = mbedtls_ssl_check_pending(&self->ssl);
+ if (has_pending) {
+ ret |= MP_STREAM_POLL_RD;
+ if (arg == MP_STREAM_POLL_RD) {
+ // Shortcut if we only need to read and we have buffered data, no need to go to the underlying socket
+ return MP_STREAM_POLL_RD;
+ }
+ }
+ }
}
+
// Pass all requests down to the underlying socket
- return mp_get_stream(self->sock)->ioctl(self->sock, request, arg, errcode);
+ ret |= mp_get_stream(sock)->ioctl(sock, request, arg, errcode);
+
+ if (request == MP_STREAM_POLL) {
+ // The direction the library needed is available, return a fake result to the caller so that
+ // it reenters a read or a write to allow the handshake to progress
+ if (ret & self->poll_mask) {
+ ret |= saved_arg;
+ }
+ }
+ return ret;
}
STATIC const mp_rom_map_elem_t ussl_socket_locals_dict_table[] = {
@@ -366,6 +445,9 @@ STATIC const mp_rom_map_elem_t ussl_socket_locals_dict_table[] = {
#if MICROPY_PY_USSL_FINALISER
{ MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mp_stream_close_obj) },
#endif
+ #if MICROPY_UNIX_COVERAGE
+ { MP_ROM_QSTR(MP_QSTR_ioctl), MP_ROM_PTR(&mp_stream_ioctl_obj) },
+ #endif
{ MP_ROM_QSTR(MP_QSTR_getpeercert), MP_ROM_PTR(&mod_ssl_getpeercert_obj) },
};
@@ -377,16 +459,15 @@ STATIC const mp_stream_p_t ussl_socket_stream_p = {
.ioctl = socket_ioctl,
};
-STATIC const mp_obj_type_t ussl_socket_type = {
- { &mp_type_type },
+STATIC MP_DEFINE_CONST_OBJ_TYPE(
+ ussl_socket_type,
+ MP_QSTR_ussl,
+ MP_TYPE_FLAG_NONE,
// Save on qstr's, reuse same as for module
- .name = MP_QSTR_ussl,
- .print = socket_print,
- .getiter = NULL,
- .iternext = NULL,
- .protocol = &ussl_socket_stream_p,
- .locals_dict = (void *)&ussl_socket_locals_dict,
-};
+ print, socket_print,
+ protocol, &ussl_socket_stream_p,
+ locals_dict, &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
@@ -395,6 +476,8 @@ STATIC mp_obj_t mod_ssl_wrap_socket(size_t n_args, const mp_obj_t *pos_args, mp_
{ 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_NONE} },
+ { MP_QSTR_cert_reqs, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = MBEDTLS_SSL_VERIFY_NONE}},
+ { MP_QSTR_cadata, 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} },
};
@@ -412,6 +495,9 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mod_ssl_wrap_socket_obj, 1, mod_ssl_wrap_socke
STATIC const mp_rom_map_elem_t mp_module_ssl_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_ussl) },
{ MP_ROM_QSTR(MP_QSTR_wrap_socket), MP_ROM_PTR(&mod_ssl_wrap_socket_obj) },
+ { MP_ROM_QSTR(MP_QSTR_CERT_NONE), MP_ROM_INT(MBEDTLS_SSL_VERIFY_NONE) },
+ { MP_ROM_QSTR(MP_QSTR_CERT_OPTIONAL), MP_ROM_INT(MBEDTLS_SSL_VERIFY_OPTIONAL) },
+ { MP_ROM_QSTR(MP_QSTR_CERT_REQUIRED), MP_ROM_INT(MBEDTLS_SSL_VERIFY_REQUIRED) },
};
STATIC MP_DEFINE_CONST_DICT(mp_module_ssl_globals, mp_module_ssl_globals_table);
diff --git a/extmod/modutimeq.c b/extmod/modutimeq.c
index 1dde90bd1b02..1a38104eafcd 100644
--- a/extmod/modutimeq.c
+++ b/extmod/modutimeq.c
@@ -209,13 +209,14 @@ STATIC const mp_rom_map_elem_t utimeq_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(utimeq_locals_dict, utimeq_locals_dict_table);
-STATIC const mp_obj_type_t utimeq_type = {
- { &mp_type_type },
- .name = MP_QSTR_utimeq,
- .make_new = utimeq_make_new,
- .unary_op = utimeq_unary_op,
- .locals_dict = (void *)&utimeq_locals_dict,
-};
+STATIC MP_DEFINE_CONST_OBJ_TYPE(
+ utimeq_type,
+ MP_QSTR_utimeq,
+ MP_TYPE_FLAG_NONE,
+ make_new, utimeq_make_new,
+ unary_op, utimeq_unary_op,
+ locals_dict, &utimeq_locals_dict
+ );
STATIC const mp_rom_map_elem_t mp_module_utimeq_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_utimeq) },
diff --git a/extmod/moduwebsocket.c b/extmod/moduwebsocket.c
index a9ad0c22e3a5..9b12fc86358c 100644
--- a/extmod/moduwebsocket.c
+++ b/extmod/moduwebsocket.c
@@ -290,13 +290,14 @@ STATIC const mp_stream_p_t websocket_stream_p = {
.ioctl = websocket_ioctl,
};
-STATIC const mp_obj_type_t websocket_type = {
- { &mp_type_type },
- .name = MP_QSTR_websocket,
- .make_new = websocket_make_new,
- .protocol = &websocket_stream_p,
- .locals_dict = (void *)&websocket_locals_dict,
-};
+STATIC MP_DEFINE_CONST_OBJ_TYPE(
+ websocket_type,
+ MP_QSTR_websocket,
+ MP_TYPE_FLAG_NONE,
+ make_new, websocket_make_new,
+ protocol, &websocket_stream_p,
+ locals_dict, &websocket_locals_dict
+ );
STATIC const mp_rom_map_elem_t uwebsocket_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uwebsocket) },
diff --git a/extmod/moduzlib.c b/extmod/moduzlib.c
index 0161b9f49cdd..14d15321a3c1 100644
--- a/extmod/moduzlib.c
+++ b/extmod/moduzlib.c
@@ -140,13 +140,14 @@ STATIC const mp_stream_p_t decompio_stream_p = {
};
#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,
-};
+STATIC MP_DEFINE_CONST_OBJ_TYPE(
+ decompio_type,
+ MP_QSTR_DecompIO,
+ MP_TYPE_FLAG_NONE,
+ make_new, decompio_make_new,
+ protocol, &decompio_stream_p,
+ locals_dict, &decompio_locals_dict
+ );
#endif
STATIC mp_obj_t mod_uzlib_decompress(size_t n_args, const mp_obj_t *args) {
diff --git a/extmod/modwebrepl.c b/extmod/modwebrepl.c
index 1a2a718acfab..d86f35896234 100644
--- a/extmod/modwebrepl.c
+++ b/extmod/modwebrepl.c
@@ -342,13 +342,14 @@ STATIC const mp_stream_p_t webrepl_stream_p = {
.ioctl = webrepl_ioctl,
};
-STATIC const mp_obj_type_t webrepl_type = {
- { &mp_type_type },
- .name = MP_QSTR__webrepl,
- .make_new = webrepl_make_new,
- .protocol = &webrepl_stream_p,
- .locals_dict = (mp_obj_dict_t *)&webrepl_locals_dict,
-};
+STATIC MP_DEFINE_CONST_OBJ_TYPE(
+ webrepl_type,
+ MP_QSTR__webrepl,
+ MP_TYPE_FLAG_NONE,
+ make_new, webrepl_make_new,
+ protocol, &webrepl_stream_p,
+ locals_dict, &webrepl_locals_dict
+ );
STATIC const mp_rom_map_elem_t webrepl_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR__webrepl) },
diff --git a/extmod/network_cyw43.c b/extmod/network_cyw43.c
index d2383c718735..dc685031dc41 100644
--- a/extmod/network_cyw43.c
+++ b/extmod/network_cyw43.c
@@ -33,10 +33,12 @@
#if MICROPY_PY_NETWORK_CYW43
#include "lwip/netif.h"
-#include "drivers/cyw43/cyw43.h"
#include "extmod/network_cyw43.h"
#include "modnetwork.h"
+#include "lib/cyw43-driver/src/cyw43.h"
+#include "lib/cyw43-driver/src/cyw43_country.h"
+
typedef struct _network_cyw43_obj_t {
mp_obj_base_t base;
cyw43_t *cyw;
@@ -119,7 +121,8 @@ STATIC mp_obj_t network_cyw43_active(size_t n_args, const mp_obj_t *args) {
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]));
+ uint32_t country = CYW43_COUNTRY(mod_network_country_code[0], mod_network_country_code[1], 0);
+ cyw43_wifi_set_up(self->cyw, self->itf, mp_obj_is_true(args[1]), country);
return mp_const_none;
}
}
@@ -163,9 +166,10 @@ STATIC int network_cyw43_scan_cb(void *env, const cyw43_ev_scan_result_t *res) {
}
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 };
+ enum { ARG_passive, ARG_ssid, 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_ssid, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
{ 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} },
};
@@ -174,13 +178,18 @@ STATIC mp_obj_t network_cyw43_scan(size_t n_args, const mp_obj_t *pos_args, mp_m
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);
+ // Deprecated kwarg
+ if (args[ARG_essid].u_obj != mp_const_none) {
+ args[ARG_ssid].u_obj = args[ARG_essid].u_obj;
+ }
+
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) {
+ if (args[ARG_ssid].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);
+ mp_get_buffer_raise(args[ARG_ssid].u_obj, &ssid, MP_BUFFER_READ);
opts.ssid_len = MIN(ssid.len, sizeof(opts.ssid));
memcpy(opts.ssid, ssid.buf, opts.ssid_len);
}
@@ -210,26 +219,37 @@ STATIC mp_obj_t network_cyw43_scan(size_t n_args, const mp_obj_t *pos_args, mp_m
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 };
+ enum { ARG_ssid, ARG_key, ARG_auth, ARG_security, 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_ssid, 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_security, 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} },
+ { MP_QSTR_channel, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = CYW43_CHANNEL_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);
+ // Deprecated kwarg
+ if (args[ARG_auth].u_int != -1) {
+ args[ARG_security] = args[ARG_auth];
+ }
+
+ // Extract the SSID.
mp_buffer_info_t ssid;
- mp_get_buffer_raise(args[ARG_essid].u_obj, &ssid, MP_BUFFER_READ);
+ mp_get_buffer_raise(args[ARG_ssid].u_obj, &ssid, MP_BUFFER_READ);
+
+ // Extract the key, if given.
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);
}
+
+ // Extract the BSSID, if given.
mp_buffer_info_t bssid;
bssid.buf = NULL;
if (args[ARG_bssid].u_obj != mp_const_none) {
@@ -238,7 +258,25 @@ STATIC mp_obj_t network_cyw43_connect(size_t n_args, const mp_obj_t *pos_args, m
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);
+
+ // Extract the security type, if given.
+ uint32_t auth_type;
+ if (args[ARG_security].u_int == -1) {
+ if (key.buf == NULL || key.len == 0) {
+ // Default to open when no password set.
+ auth_type = CYW43_AUTH_OPEN;
+ } else {
+ // Default to WPA2 otherwise. All other modes require the security
+ // kwarg to be set explicitly.
+ auth_type = CYW43_AUTH_WPA2_MIXED_PSK;
+ }
+ } else {
+ auth_type = args[ARG_security].u_int;
+ }
+
+ // Start the WiFi join procedure. It will run in the background.
+ int ret = cyw43_wifi_join(self->cyw, ssid.len, ssid.buf, key.len, key.buf,
+ auth_type, bssid.buf, args[ARG_channel].u_int);
if (ret != 0) {
mp_raise_OSError(-ret);
}
@@ -276,6 +314,14 @@ STATIC mp_obj_t network_cyw43_status(size_t n_args, const mp_obj_t *args) {
// one argument: return status based on query parameter
switch (mp_obj_str_get_qstr(args[1])) {
+ case MP_QSTR_rssi: {
+ if (self->itf != CYW43_ITF_STA) {
+ mp_raise_ValueError(MP_ERROR_TEXT("STA required"));
+ }
+ int32_t rssi;
+ cyw43_wifi_get_rssi(self->cyw, &rssi);
+ return mp_obj_new_int(rssi);
+ }
case MP_QSTR_stations: {
// return list of connected stations
if (self->itf != CYW43_ITF_AP) {
@@ -330,6 +376,7 @@ STATIC mp_obj_t network_cyw43_config(size_t n_args, const mp_obj_t *args, mp_map
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_ssid:
case MP_QSTR_essid: {
if (self->itf == CYW43_ITF_STA) {
uint8_t buf[36];
@@ -342,6 +389,9 @@ STATIC mp_obj_t network_cyw43_config(size_t n_args, const mp_obj_t *args, mp_map
return mp_obj_new_str((const char *)buf, len);
}
}
+ case MP_QSTR_security: {
+ return MP_OBJ_NEW_SMALL_INT(cyw43_wifi_ap_get_auth(self->cyw));
+ }
case MP_QSTR_mac: {
uint8_t buf[6];
cyw43_wifi_get_mac(self->cyw, self->itf, buf);
@@ -353,6 +403,10 @@ STATIC mp_obj_t network_cyw43_config(size_t n_args, const mp_obj_t *args, mp_map
cyw43_ioctl(self->cyw, CYW43_IOCTL_GET_VAR, 13, buf, self->itf);
return MP_OBJ_NEW_SMALL_INT(nw_get_le32(buf) / 4);
}
+ case MP_QSTR_hostname: {
+ // TODO: Deprecated. Use network.hostname() instead.
+ return mp_obj_new_str(mod_network_hostname, strlen(mod_network_hostname));
+ }
default:
mp_raise_ValueError(MP_ERROR_TEXT("unknown config param"));
}
@@ -376,6 +430,7 @@ STATIC mp_obj_t network_cyw43_config(size_t n_args, const mp_obj_t *args, mp_map
cyw43_wifi_ap_set_channel(self->cyw, mp_obj_get_int(e->value));
break;
}
+ case MP_QSTR_ssid:
case MP_QSTR_essid: {
size_t len;
const char *str = mp_obj_str_get_data(e->value, &len);
@@ -397,6 +452,11 @@ STATIC mp_obj_t network_cyw43_config(size_t n_args, const mp_obj_t *args, mp_map
}
break;
}
+ case MP_QSTR_security: {
+ cyw43_wifi_ap_set_auth(self->cyw, mp_obj_get_int(e->value));
+ break;
+ }
+ case MP_QSTR_key:
case MP_QSTR_password: {
size_t len;
const char *str = mp_obj_str_get_data(e->value, &len);
@@ -419,6 +479,16 @@ STATIC mp_obj_t network_cyw43_config(size_t n_args, const mp_obj_t *args, mp_map
cyw43_ioctl(self->cyw, CYW43_IOCTL_SET_VAR, 9 + 4, buf, self->itf);
break;
}
+ case MP_QSTR_hostname: {
+ // TODO: Deprecated. Use network.hostname(name) instead.
+ size_t len;
+ const char *str = mp_obj_str_get_data(e->value, &len);
+ if (len >= MICROPY_PY_NETWORK_HOSTNAME_MAX_LEN) {
+ mp_raise_ValueError(NULL);
+ }
+ strcpy(mod_network_hostname, str);
+ break;
+ }
default:
mp_raise_ValueError(MP_ERROR_TEXT("unknown config param"));
}
@@ -449,12 +519,13 @@ STATIC const mp_rom_map_elem_t network_cyw43_locals_dict_table[] = {
};
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,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ mp_network_cyw43_type,
+ MP_QSTR_CYW43,
+ MP_TYPE_FLAG_NONE,
+ make_new, network_cyw43_make_new,
+ print, network_cyw43_print,
+ locals_dict, &network_cyw43_locals_dict
+ );
#endif // MICROPY_PY_NETWORK_CYW43
diff --git a/extmod/network_lwip.c b/extmod/network_lwip.c
new file mode 100644
index 000000000000..caa30f6fff4d
--- /dev/null
+++ b/extmod/network_lwip.c
@@ -0,0 +1,95 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2014 Damien P. George
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "py/runtime.h"
+#include "py/mphal.h"
+
+#if MICROPY_PY_NETWORK && MICROPY_PY_LWIP
+
+#include "shared/netutils/netutils.h"
+#include "extmod/modnetwork.h"
+
+#include "lwip/init.h"
+
+#if LWIP_VERSION_MAJOR >= 2
+
+#include "lwip/netif.h"
+#include "lwip/timeouts.h"
+#include "lwip/dns.h"
+#include "lwip/dhcp.h"
+
+// Implementations of network methods that can be used by any interface.
+
+mp_obj_t mod_network_nic_ifconfig(struct netif *netif, size_t n_args, const mp_obj_t *args) {
+ if (n_args == 0) {
+ // Get IP addresses
+ const ip_addr_t *dns = dns_getserver(0);
+ mp_obj_t tuple[4] = {
+ netutils_format_ipv4_addr((uint8_t *)&netif->ip_addr, NETUTILS_BIG),
+ netutils_format_ipv4_addr((uint8_t *)&netif->netmask, NETUTILS_BIG),
+ netutils_format_ipv4_addr((uint8_t *)&netif->gw, NETUTILS_BIG),
+ netutils_format_ipv4_addr((uint8_t *)dns, NETUTILS_BIG),
+ };
+ return mp_obj_new_tuple(4, tuple);
+ } else if (args[0] == MP_OBJ_NEW_QSTR(MP_QSTR_dhcp)) {
+ // Start the DHCP client
+ if (dhcp_supplied_address(netif)) {
+ dhcp_renew(netif);
+ } else {
+ dhcp_stop(netif);
+ dhcp_start(netif);
+ }
+
+ // Wait for DHCP to get IP address
+ uint32_t start = mp_hal_ticks_ms();
+ while (!dhcp_supplied_address(netif)) {
+ if (mp_hal_ticks_ms() - start > 10000) {
+ mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("timeout waiting for DHCP to get IP address"));
+ }
+ mp_hal_delay_ms(100);
+ }
+
+ return mp_const_none;
+ } else {
+ // Release and stop any existing DHCP
+ dhcp_release(netif);
+ dhcp_stop(netif);
+ // Set static IP addresses
+ mp_obj_t *items;
+ mp_obj_get_array_fixed_n(args[0], 4, &items);
+ netutils_parse_ipv4_addr(items[0], (uint8_t *)&netif->ip_addr, NETUTILS_BIG);
+ netutils_parse_ipv4_addr(items[1], (uint8_t *)&netif->netmask, NETUTILS_BIG);
+ netutils_parse_ipv4_addr(items[2], (uint8_t *)&netif->gw, NETUTILS_BIG);
+ ip_addr_t dns;
+ netutils_parse_ipv4_addr(items[3], (uint8_t *)&dns, NETUTILS_BIG);
+ dns_setserver(0, &dns);
+ return mp_const_none;
+ }
+}
+
+#endif // LWIP_VERSION_MAJOR >= 2
+
+#endif // MICROPY_PY_NETWORK && MICROPY_PY_LWIP
diff --git a/extmod/network_ninaw10.c b/extmod/network_ninaw10.c
index 6921ed3f2761..00f53eff137a 100644
--- a/extmod/network_ninaw10.c
+++ b/extmod/network_ninaw10.c
@@ -51,6 +51,9 @@ typedef struct _nina_obj_t {
mp_obj_base_t base;
bool active;
uint32_t itf;
+ mp_uint_t security;
+ char ssid[NINA_MAX_SSID_LEN + 1];
+ char key[NINA_MAX_WPA_LEN + 1];
} nina_obj_t;
// For auto-binding UDP sockets
@@ -74,10 +77,11 @@ typedef struct _nina_obj_t {
#define debug_printf(...) // mp_printf(&mp_plat_print, __VA_ARGS__)
static uint16_t bind_port = BIND_PORT_RANGE_MIN;
-const mod_network_nic_type_t mod_network_nic_type_nina;
+const mp_obj_type_t mod_network_nic_type_nina;
static nina_obj_t network_nina_wl_sta = {{(mp_obj_type_t *)&mod_network_nic_type_nina}, false, MOD_NETWORK_STA_IF};
static nina_obj_t network_nina_wl_ap = {{(mp_obj_type_t *)&mod_network_nic_type_nina}, false, MOD_NETWORK_AP_IF};
static mp_sched_node_t mp_wifi_sockpoll_node;
+static mp_sched_node_t mp_wifi_connpoll_node;
STATIC void network_ninaw10_poll_sockets(mp_sched_node_t *node) {
(void)node;
@@ -99,6 +103,40 @@ STATIC void network_ninaw10_poll_sockets(mp_sched_node_t *node) {
}
}
+STATIC void network_ninaw10_poll_connect(mp_sched_node_t *node) {
+ nina_obj_t *self = &network_nina_wl_sta;
+
+ int status = nina_connection_status();
+ if (status == NINA_STATUS_CONNECTED) {
+ // Connected to AP, nothing else to do.
+ return;
+ }
+
+ if (status != NINA_STATUS_NO_SSID_AVAIL) {
+ // If not connected, and no connection in progress, the connection attempt has failed.
+ // Read the ESP failure reason, reconnect and reschedule the connection polling code.
+ int reason = nina_connection_reason();
+ if (reason == NINA_ESP_REASON_AUTH_EXPIRE ||
+ reason == NINA_ESP_REASON_ASSOC_EXPIRE ||
+ reason == NINA_ESP_REASON_NOT_AUTHED ||
+ reason == NINA_ESP_REASON_4WAY_HANDSHAKE_TIMEOUT ||
+ reason >= NINA_ESP_REASON_BEACON_TIMEOUT) {
+ debug_printf(&mp_plat_print, "poll_connect() status: %d reason %d\n", status, reason);
+ if (nina_connect(self->ssid, self->security, self->key, 0) != 0) {
+ mp_raise_msg_varg(&mp_type_OSError,
+ MP_ERROR_TEXT("could not connect to ssid=%s, sec=%d, key=%s\n"),
+ self->ssid, self->security, self->key);
+ }
+ } else {
+ // Will not attempt to reconnect if there's another error code set.
+ return;
+ }
+ }
+
+ // Reschedule the connection polling code.
+ mp_sched_schedule_node(&mp_wifi_connpoll_node, network_ninaw10_poll_connect);
+}
+
STATIC mp_obj_t network_ninaw10_timer_callback(mp_obj_t none_in) {
if (MP_STATE_PORT(mp_wifi_sockpoll_list) != MP_OBJ_NULL && MP_STATE_PORT(mp_wifi_sockpoll_list)->len) {
mp_sched_schedule_node(&mp_wifi_sockpoll_node, network_ninaw10_poll_sockets);
@@ -159,7 +197,7 @@ STATIC mp_obj_t network_ninaw10_active(size_t n_args, const mp_obj_t *args) {
MP_OBJ_NEW_QSTR(MP_QSTR_freq), MP_OBJ_NEW_SMALL_INT(10),
MP_OBJ_NEW_QSTR(MP_QSTR_callback), MP_OBJ_FROM_PTR(&network_ninaw10_timer_callback_obj),
};
- MP_STATE_PORT(mp_wifi_timer) = machine_timer_type.make_new((mp_obj_t)&machine_timer_type, 0, 2, timer_args);
+ MP_STATE_PORT(mp_wifi_timer) = MP_OBJ_TYPE_GET_SLOT(&machine_timer_type, make_new)((mp_obj_t)&machine_timer_type, 0, 2, timer_args);
}
} else {
nina_deinit();
@@ -196,9 +234,9 @@ STATIC mp_obj_t network_ninaw10_scan(mp_obj_t self_in) {
STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_ninaw10_scan_obj, network_ninaw10_scan);
STATIC mp_obj_t network_ninaw10_connect(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
- enum { ARG_essid, ARG_key, ARG_security, ARG_channel };
+ enum { ARG_ssid, ARG_key, ARG_security, ARG_channel };
static const mp_arg_t allowed_args[] = {
- { MP_QSTR_essid, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
+ { MP_QSTR_ssid, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
{ MP_QSTR_key, MP_ARG_OBJ, {.u_obj = mp_const_none} },
{ MP_QSTR_security, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = NINA_SEC_WPA_PSK} },
{ MP_QSTR_channel, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1} },
@@ -210,7 +248,7 @@ STATIC mp_obj_t network_ninaw10_connect(mp_uint_t n_args, const mp_obj_t *pos_ar
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
// get ssid
- const char *ssid = mp_obj_str_get_str(args[ARG_essid].u_obj);
+ const char *ssid = mp_obj_str_get_str(args[ARG_ssid].u_obj);
if (strlen(ssid) == 0) {
mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("SSID can't be empty!"));
@@ -240,6 +278,12 @@ STATIC mp_obj_t network_ninaw10_connect(mp_uint_t n_args, const mp_obj_t *pos_ar
mp_raise_msg_varg(&mp_type_OSError,
MP_ERROR_TEXT("could not connect to ssid=%s, sec=%d, key=%s\n"), ssid, security, key);
}
+
+ // Save connection info to re-connect if needed.
+ self->security = security;
+ strncpy(self->key, key, NINA_MAX_WPA_LEN);
+ strncpy(self->ssid, ssid, NINA_MAX_SSID_LEN);
+ mp_sched_schedule_node(&mp_wifi_connpoll_node, network_ninaw10_poll_connect);
} else {
mp_uint_t channel = args[ARG_channel].u_int;
@@ -252,6 +296,7 @@ STATIC mp_obj_t network_ninaw10_connect(mp_uint_t n_args, const mp_obj_t *pos_ar
mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("failed to start in AP mode"));
}
}
+
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(network_ninaw10_connect_obj, 1, network_ninaw10_connect);
@@ -304,7 +349,7 @@ STATIC mp_obj_t network_ninaw10_config(size_t n_args, const mp_obj_t *args, mp_m
}
switch (mp_obj_str_get_qstr(args[1])) {
- case MP_QSTR_essid: {
+ case MP_QSTR_ssid: {
nina_netinfo_t netinfo;
nina_netinfo(&netinfo);
return mp_obj_new_str(netinfo.ssid, strlen(netinfo.ssid));
@@ -441,13 +486,33 @@ STATIC int network_ninaw10_socket_listening(mod_network_socket_obj_t *socket, in
STATIC int network_ninaw10_socket_socket(mod_network_socket_obj_t *socket, int *_errno) {
debug_printf("socket_socket(%d %d %d)\n", socket->domain, socket->type, socket->proto);
+ uint8_t socket_type;
+
+ switch (socket->type) {
+ case MOD_NETWORK_SOCK_STREAM:
+ socket_type = NINA_SOCKET_TYPE_TCP;
+ break;
+
+ case MOD_NETWORK_SOCK_DGRAM:
+ socket_type = NINA_SOCKET_TYPE_UDP;
+ break;
+
+ case MOD_NETWORK_SOCK_RAW:
+ socket_type = NINA_SOCKET_TYPE_RAW;
+ break;
+
+ default:
+ *_errno = MP_EINVAL;
+ return -1;
+ }
+
if (socket->domain != MOD_NETWORK_AF_INET) {
*_errno = MP_EAFNOSUPPORT;
return -1;
}
// open socket
- int fd = nina_socket_socket(socket->type, socket->proto);
+ int fd = nina_socket_socket(socket_type, socket->proto);
if (fd < 0) {
nina_socket_errno(_errno);
debug_printf("socket_socket() -> errno %d\n", *_errno);
@@ -477,20 +542,6 @@ STATIC void network_ninaw10_socket_close(mod_network_socket_obj_t *socket) {
STATIC int network_ninaw10_socket_bind(mod_network_socket_obj_t *socket, byte *ip, mp_uint_t port, int *_errno) {
debug_printf("socket_bind(%d, %d)\n", socket->fileno, port);
- uint8_t type;
- switch (socket->type) {
- case MOD_NETWORK_SOCK_STREAM:
- type = NINA_SOCKET_TYPE_TCP;
- break;
-
- case MOD_NETWORK_SOCK_DGRAM:
- type = NINA_SOCKET_TYPE_UDP;
- break;
-
- default:
- *_errno = MP_EINVAL;
- return -1;
- }
int ret = nina_socket_bind(socket->fileno, ip, port);
if (ret < 0) {
@@ -753,7 +804,7 @@ STATIC int network_ninaw10_socket_ioctl(mod_network_socket_obj_t *socket, mp_uin
return ret;
}
-static const mp_rom_map_elem_t nina_locals_dict_table[] = {
+STATIC const mp_rom_map_elem_t nina_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_active), MP_ROM_PTR(&network_ninaw10_active_obj) },
{ MP_ROM_QSTR(MP_QSTR_scan), MP_ROM_PTR(&network_ninaw10_scan_obj) },
{ MP_ROM_QSTR(MP_QSTR_connect), MP_ROM_PTR(&network_ninaw10_connect_obj) },
@@ -772,15 +823,9 @@ static const mp_rom_map_elem_t nina_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_WPA_PSK), MP_ROM_INT(NINA_SEC_WPA_PSK) },
};
-static MP_DEFINE_CONST_DICT(nina_locals_dict, nina_locals_dict_table);
+STATIC MP_DEFINE_CONST_DICT(nina_locals_dict, nina_locals_dict_table);
-const mod_network_nic_type_t mod_network_nic_type_nina = {
- .base = {
- { &mp_type_type },
- .name = MP_QSTR_nina,
- .make_new = network_ninaw10_make_new,
- .locals_dict = (mp_obj_t)&nina_locals_dict,
- },
+STATIC const mod_network_nic_protocol_t mod_network_nic_protocol_nina = {
.gethostbyname = network_ninaw10_gethostbyname,
.socket = network_ninaw10_socket_socket,
.close = network_ninaw10_socket_close,
@@ -797,4 +842,17 @@ const mod_network_nic_type_t mod_network_nic_type_nina = {
.ioctl = network_ninaw10_socket_ioctl,
};
+MP_DEFINE_CONST_OBJ_TYPE(
+ mod_network_nic_type_nina,
+ MP_QSTR_nina,
+ MP_TYPE_FLAG_NONE,
+ make_new, network_ninaw10_make_new,
+ locals_dict, &nina_locals_dict,
+ protocol, &mod_network_nic_protocol_nina
+ );
+
+MP_REGISTER_ROOT_POINTER(struct _machine_spi_obj_t *mp_wifi_spi);
+MP_REGISTER_ROOT_POINTER(struct _machine_timer_obj_t *mp_wifi_timer);
+MP_REGISTER_ROOT_POINTER(struct _mp_obj_list_t *mp_wifi_sockpoll_list);
+
#endif // #if MICROPY_PY_BLUETOOTH && MICROPY_PY_NETWORK_NINAW10
diff --git a/extmod/network_wiznet5k.c b/extmod/network_wiznet5k.c
index f328276a5b26..eed656ee2419 100644
--- a/extmod/network_wiznet5k.c
+++ b/extmod/network_wiznet5k.c
@@ -33,6 +33,9 @@
#include "py/stream.h"
#include "py/mperrno.h"
#include "py/mphal.h"
+
+#if MICROPY_PY_NETWORK_WIZNET5K
+
#include "shared/netutils/netutils.h"
#include "extmod/modnetwork.h"
#include "extmod/machine_spi.h"
@@ -40,8 +43,6 @@
#include "modmachine.h"
#include "drivers/bus/spi.h"
-#if MICROPY_PY_NETWORK_WIZNET5K
-
#include "lib/wiznet5k/Ethernet/wizchip_conf.h"
// The WIZNET5K module supports two usage modes:
@@ -91,12 +92,11 @@
#endif
#endif
-extern struct _machine_spi_obj_t *spi_from_mp_obj(mp_obj_t o);
-
typedef struct _wiznet5k_obj_t {
mp_obj_base_t base;
mp_uint_t cris_state;
- struct _machine_spi_obj_t *spi;
+ mp_obj_base_t *spi;
+ void (*spi_transfer)(mp_obj_base_t *obj, size_t len, const uint8_t *src, uint8_t *dest);
mp_hal_pin_obj_t cs;
mp_hal_pin_obj_t rst;
#if WIZNET5K_WITH_LWIP_STACK
@@ -148,21 +148,21 @@ void mpy_wiznet_yield(void) {
}
STATIC void wiz_spi_read(uint8_t *buf, uint16_t len) {
- ((mp_machine_spi_p_t *)machine_spi_type.protocol)->transfer((mp_obj_base_t *)wiznet5k_obj.spi, len, buf, buf);
+ wiznet5k_obj.spi_transfer(wiznet5k_obj.spi, len, buf, buf);
}
STATIC void wiz_spi_write(const uint8_t *buf, uint16_t len) {
- ((mp_machine_spi_p_t *)machine_spi_type.protocol)->transfer((mp_obj_base_t *)wiznet5k_obj.spi, len, buf, NULL);
+ wiznet5k_obj.spi_transfer(wiznet5k_obj.spi, len, buf, NULL);
}
STATIC uint8_t wiz_spi_readbyte() {
uint8_t buf = 0;
- ((mp_machine_spi_p_t *)machine_spi_type.protocol)->transfer((mp_obj_base_t *)wiznet5k_obj.spi, 1, &buf, &buf);
+ wiznet5k_obj.spi_transfer(wiznet5k_obj.spi, 1, &buf, &buf);
return buf;
}
STATIC void wiz_spi_writebyte(const uint8_t buf) {
- ((mp_machine_spi_p_t *)machine_spi_type.protocol)->transfer((mp_obj_base_t *)wiznet5k_obj.spi, 1, &buf, NULL);
+ wiznet5k_obj.spi_transfer(wiznet5k_obj.spi, 1, &buf, NULL);
}
STATIC void wiznet5k_get_mac_address(wiznet5k_obj_t *self, uint8_t mac[6]) {
@@ -177,11 +177,10 @@ STATIC void wiznet5k_lwip_init(wiznet5k_obj_t *self);
STATIC mp_obj_t mpy_wiznet_read_int(mp_obj_t none_in) {
(void)none_in;
- wizchip_clrinterrupt(IK_SOCK_0);
- setSn_IR(0, Sn_IR_RECV);
-
- // Handle incoming data
- wiznet5k_try_poll();
+ // Handle incoming data, unless the SPI bus is busy
+ if (mp_hal_pin_read(wiznet5k_obj.cs)) {
+ wiznet5k_try_poll();
+ }
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mpy_wiznet_read_int_obj, mpy_wiznet_read_int);
@@ -198,6 +197,16 @@ STATIC void wiznet5k_config_interrupt(bool enabled) {
);
}
+void wiznet5k_deinit(void) {
+ for (struct netif *netif = netif_list; netif != NULL; netif = netif->next) {
+ if (netif == &wiznet5k_obj.netif) {
+ netif_remove(netif);
+ netif->flags = 0;
+ break;
+ }
+ }
+}
+
STATIC void wiznet5k_init(void) {
// Configure wiznet for raw ethernet frame usage.
@@ -219,21 +228,17 @@ STATIC void wiznet5k_init(void) {
wiznet5k_config_interrupt(true);
}
+ // Deinit before a new init to clear the state from a previous activation
+ wiznet5k_deinit();
+
// Hook the Wiznet into lwIP
wiznet5k_lwip_init(&wiznet5k_obj);
netif_set_link_up(&wiznet5k_obj.netif);
netif_set_up(&wiznet5k_obj.netif);
-}
-void wiznet5k_deinit(void) {
- for (struct netif *netif = netif_list; netif != NULL; netif = netif->next) {
- if (netif == &wiznet5k_obj.netif) {
- netif_remove(netif);
- netif->flags = 0;
- break;
- }
- }
+ // register with network module
+ mod_network_register_nic(&wiznet5k_obj);
}
STATIC void wiznet5k_send_ethernet(wiznet5k_obj_t *self, size_t len, const uint8_t *buf) {
@@ -320,23 +325,25 @@ STATIC void wiznet5k_lwip_init(wiznet5k_obj_t *self) {
void wiznet5k_poll(void) {
wiznet5k_obj_t *self = &wiznet5k_obj;
- if (!(self->netif.flags & NETIF_FLAG_UP) ||
- !(self->netif.flags & NETIF_FLAG_LINK_UP)) {
- return;
- }
- uint16_t len;
- while ((len = wiznet5k_recv_ethernet(self)) > 0) {
- if (self->trace_flags & TRACE_ETH_RX) {
- netutils_ethernet_trace(MP_PYTHON_PRINTER, len, self->eth_frame, NETUTILS_TRACE_NEWLINE);
- }
- struct pbuf *p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
- if (p != NULL) {
- pbuf_take(p, self->eth_frame, len);
- if (self->netif.input(p, &self->netif) != ERR_OK) {
- pbuf_free(p);
+ if ((self->netif.flags & (NETIF_FLAG_UP | NETIF_FLAG_LINK_UP)) == (NETIF_FLAG_UP | NETIF_FLAG_LINK_UP)) {
+ uint16_t len;
+ while ((len = wiznet5k_recv_ethernet(self)) > 0) {
+ if (self->trace_flags & TRACE_ETH_RX) {
+ netutils_ethernet_trace(MP_PYTHON_PRINTER, len, self->eth_frame, NETUTILS_TRACE_NEWLINE);
+ }
+ struct pbuf *p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
+ if (p != NULL) {
+ pbuf_take(p, self->eth_frame, len);
+ if (self->netif.input(p, &self->netif) != ERR_OK) {
+ pbuf_free(p);
+ }
}
}
}
+ wizchip_clrinterrupt(IK_SOCK_0);
+ #if _WIZCHIP_ == W5100S
+ setSn_IR(0, Sn_IR_RECV); // W5100S driver bug: must write to the Sn_IR register to reset the IRQ signal
+ #endif
}
#endif // MICROPY_PY_LWIP
@@ -391,6 +398,9 @@ STATIC int wiznet5k_gethostbyname(mp_obj_t nic, const char *name, mp_uint_t len,
uint8_t dns_ip[MOD_NETWORK_IPADDR_BUF_SIZE] = {8, 8, 8, 8};
uint8_t *buf = m_new(uint8_t, MAX_DNS_BUF_SIZE);
DNS_init(2, buf);
+ if (wiznet5k_obj.netinfo.dns[0]) {
+ memcpy(dns_ip, wiznet5k_obj.netinfo.dns, MOD_NETWORK_IPADDR_BUF_SIZE);
+ }
mp_int_t ret = DNS_run(dns_ip, (uint8_t *)name, out_ip);
m_del(uint8_t, buf, MAX_DNS_BUF_SIZE);
if (ret == 1) {
@@ -673,7 +683,7 @@ STATIC void wiznet5k_dhcp_init(wiznet5k_obj_t *self) {
// WIZNET5K(spi, pin_cs, pin_rst[, pin_intn])
// Create and return a WIZNET5K object.
STATIC mp_obj_t wiznet5k_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
- struct _machine_spi_obj_t *spi;
+ mp_obj_base_t *spi;
mp_hal_pin_obj_t cs;
mp_hal_pin_obj_t rst;
@@ -686,10 +696,8 @@ STATIC mp_obj_t wiznet5k_make_new(const mp_obj_type_t *type, size_t n_args, size
#endif
#ifdef MICROPY_HW_WIZNET_SPI_ID
- // check arguments
- mp_arg_check_num(n_args, n_kw, 0, 3, false);
// Allow auto-configuration of SPI if defined for board and no args passed
- if (n_args == 0) {
+ if (n_args == 0 && n_kw == 0) {
// Initialize SPI.
mp_obj_t spi_obj = MP_OBJ_NEW_SMALL_INT(MICROPY_HW_WIZNET_SPI_SCK);
mp_obj_t miso_obj = MP_OBJ_NEW_SMALL_INT(MICROPY_HW_WIZNET_SPI_MISO);
@@ -701,7 +709,7 @@ STATIC mp_obj_t wiznet5k_make_new(const mp_obj_type_t *type, size_t n_args, size
MP_ROM_QSTR(MP_QSTR_miso), mp_pin_make_new(NULL, 1, 0, &miso_obj),
MP_ROM_QSTR(MP_QSTR_mosi), mp_pin_make_new(NULL, 1, 0, &mosi_obj),
};
- spi = machine_spi_type.make_new((mp_obj_t)&machine_spi_type, 2, 3, args);
+ spi = MP_OBJ_TO_PTR(MP_OBJ_TYPE_GET_SLOT(&machine_spi_type, make_new)((mp_obj_t)&machine_spi_type, 2, 3, args));
cs = mp_hal_get_pin_obj(mp_pin_make_new(NULL, 1, 0, (mp_obj_t[]) {MP_OBJ_NEW_SMALL_INT(MICROPY_HW_WIZNET_PIN_CS)}));
rst = mp_hal_get_pin_obj(mp_pin_make_new(NULL, 1, 0, (mp_obj_t[]) {MP_OBJ_NEW_SMALL_INT(MICROPY_HW_WIZNET_PIN_RST)}));
@@ -719,7 +727,7 @@ STATIC mp_obj_t wiznet5k_make_new(const mp_obj_type_t *type, size_t n_args, size
#else
mp_arg_check_num(n_args, n_kw, 3, 3, false);
#endif
- spi = spi_from_mp_obj(args[0]);
+ spi = mp_hal_get_spi_obj(args[0]);
cs = mp_hal_get_pin_obj(args[1]);
rst = mp_hal_get_pin_obj(args[2]);
#if WIZNET5K_WITH_LWIP_STACK
@@ -737,6 +745,7 @@ STATIC mp_obj_t wiznet5k_make_new(const mp_obj_type_t *type, size_t n_args, size
wiznet5k_obj.base.type = (mp_obj_type_t *)&mod_network_nic_type_wiznet5k;
wiznet5k_obj.cris_state = 0;
wiznet5k_obj.spi = spi;
+ wiznet5k_obj.spi_transfer = ((mp_machine_spi_p_t *)MP_OBJ_TYPE_GET_SLOT(spi->type, protocol))->transfer;
wiznet5k_obj.cs = cs;
wiznet5k_obj.rst = rst;
#if WIZNET5K_WITH_LWIP_STACK
@@ -1008,20 +1017,9 @@ STATIC const mp_rom_map_elem_t wiznet5k_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(wiznet5k_locals_dict, wiznet5k_locals_dict_table);
#if WIZNET5K_WITH_LWIP_STACK
-const mp_obj_type_t mod_network_nic_type_wiznet5k = {
- { &mp_type_type },
- .name = MP_QSTR_WIZNET5K,
- .make_new = wiznet5k_make_new,
- .locals_dict = (mp_obj_dict_t *)&wiznet5k_locals_dict,
-};
+#define NIC_TYPE_WIZNET_PROTOCOL
#else // WIZNET5K_PROVIDED_STACK
-const mod_network_nic_type_t mod_network_nic_type_wiznet5k = {
- .base = {
- { &mp_type_type },
- .name = MP_QSTR_WIZNET5K,
- .make_new = wiznet5k_make_new,
- .locals_dict = (mp_obj_dict_t *)&wiznet5k_locals_dict,
- },
+const mod_network_nic_protocol_t mod_network_nic_protocol_wiznet = {
.gethostbyname = wiznet5k_gethostbyname,
.socket = wiznet5k_socket_socket,
.close = wiznet5k_socket_close,
@@ -1037,6 +1035,16 @@ const mod_network_nic_type_t mod_network_nic_type_wiznet5k = {
.settimeout = wiznet5k_socket_settimeout,
.ioctl = wiznet5k_socket_ioctl,
};
+#define NIC_TYPE_WIZNET_PROTOCOL protocol, &mod_network_nic_protocol_wiznet,
#endif
+MP_DEFINE_CONST_OBJ_TYPE(
+ mod_network_nic_type_wiznet5k,
+ MP_QSTR_WIZNET5K,
+ MP_TYPE_FLAG_NONE,
+ make_new, wiznet5k_make_new,
+ NIC_TYPE_WIZNET_PROTOCOL
+ locals_dict, &wiznet5k_locals_dict
+ );
+
#endif // MICROPY_PY_NETWORK_WIZNET5K
diff --git a/extmod/nimble/hal/hal_uart.c b/extmod/nimble/hal/hal_uart.c
index 6c17da086071..7713f75d8d22 100644
--- a/extmod/nimble/hal/hal_uart.c
+++ b/extmod/nimble/hal/hal_uart.c
@@ -39,6 +39,9 @@
#endif
#define HCI_TRACE (0)
+#define COL_OFF "\033[0m"
+#define COL_GREEN "\033[0;32m"
+#define COL_BLUE "\033[0;34m"
static hal_uart_tx_cb_t hal_uart_tx_cb;
static void *hal_uart_tx_arg;
@@ -71,11 +74,11 @@ void hal_uart_start_tx(uint32_t port) {
}
#if HCI_TRACE
- printf("< [% 8d] %02x", (int)mp_hal_ticks_ms(), mp_bluetooth_hci_cmd_buf[0]);
+ printf(COL_GREEN "< [% 8d] %02x", (int)mp_hal_ticks_ms(), mp_bluetooth_hci_cmd_buf[0]);
for (size_t i = 1; i < len; ++i) {
printf(":%02x", mp_bluetooth_hci_cmd_buf[i]);
}
- printf("\n");
+ printf(COL_OFF "\n");
#endif
mp_bluetooth_hci_uart_write(mp_bluetooth_hci_cmd_buf, len);
@@ -92,7 +95,7 @@ int hal_uart_close(uint32_t port) {
STATIC void mp_bluetooth_hci_uart_char_cb(uint8_t chr) {
#if HCI_TRACE
- printf("> %02x\n", chr);
+ printf(COL_BLUE "> [% 8d] %02x" COL_OFF "\n", (int)mp_hal_ticks_ms(), chr);
#endif
hal_uart_rx_cb(hal_uart_rx_arg, chr);
}
diff --git a/extmod/nimble/modbluetooth_nimble.c b/extmod/nimble/modbluetooth_nimble.c
index fce99bcdf5bf..d9d4c132239f 100644
--- a/extmod/nimble/modbluetooth_nimble.c
+++ b/extmod/nimble/modbluetooth_nimble.c
@@ -851,6 +851,7 @@ static int characteristic_access_cb(uint16_t conn_handle, uint16_t value_handle,
switch (ctxt->op) {
case BLE_GATT_ACCESS_OP_READ_CHR:
case BLE_GATT_ACCESS_OP_READ_DSC: {
+ DEBUG_printf("write for %d %d (op=%d)\n", conn_handle, value_handle, ctxt->op);
// Allow Python code to override (by using gatts_write), or deny (by returning false) the read.
// Note this will be a no-op if the ringbuffer implementation is being used (i.e. the stack isn't
// run in the scheduler). The ringbuffer is not used on STM32 and Unix-H4 only.
@@ -872,6 +873,7 @@ static int characteristic_access_cb(uint16_t conn_handle, uint16_t value_handle,
}
case BLE_GATT_ACCESS_OP_WRITE_CHR:
case BLE_GATT_ACCESS_OP_WRITE_DSC:
+ DEBUG_printf("write for %d %d (op=%d)\n", conn_handle, value_handle, ctxt->op);
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;
@@ -963,7 +965,14 @@ int mp_bluetooth_gatts_register_service(mp_obj_bluetooth_uuid_t *service_uuid, m
descriptors[j].uuid = create_nimble_uuid(descriptor_uuids[descriptor_index], NULL);
descriptors[j].access_cb = characteristic_access_cb;
// NimBLE doesn't support security/privacy options on descriptors.
- descriptors[j].att_flags = (uint8_t)descriptor_flags[descriptor_index];
+ uint8_t desc_att_flags = 0;
+ if (descriptor_flags[descriptor_index] & MP_BLUETOOTH_CHARACTERISTIC_FLAG_READ) {
+ desc_att_flags |= BLE_ATT_F_READ;
+ }
+ if (descriptor_flags[descriptor_index] & (MP_BLUETOOTH_CHARACTERISTIC_FLAG_WRITE | MP_BLUETOOTH_CHARACTERISTIC_FLAG_WRITE_NO_RESPONSE)) {
+ desc_att_flags |= BLE_ATT_F_WRITE;
+ }
+ descriptors[j].att_flags = desc_att_flags;
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];
@@ -1008,7 +1017,7 @@ int mp_bluetooth_gap_disconnect(uint16_t conn_handle) {
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) {
+int mp_bluetooth_gatts_read(uint16_t value_handle, const uint8_t **value, size_t *value_len) {
if (!mp_bluetooth_is_active()) {
return ERRNO_BLUETOOTH_NOT_ACTIVE;
}
@@ -1026,35 +1035,40 @@ int mp_bluetooth_gatts_write(uint16_t value_handle, const uint8_t *value, size_t
return err;
}
-// 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) {
+int mp_bluetooth_gatts_notify_indicate(uint16_t conn_handle, uint16_t value_handle, int gatts_op, const uint8_t *value, size_t value_len) {
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;
+ int err = BLE_HS_EINVAL;
+
+ // NULL om in the _custom methods means "use DB value" (NimBLE will call
+ // back into mp_bluetooth_gatts_read for us).
+ struct os_mbuf *om = NULL;
+
+ if (value) {
+ om = ble_hs_mbuf_from_flat(value, value_len);
+ if (om == NULL) {
+ return MP_ENOMEM;
+ }
}
- 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;
+ // Note: Confusingly, Nimble's notify/notify_custom and indicate/indicate_custom
+ // are "gattc" functions (even though they're used by peripherals, i.e. gatt servers).
+ // See https://www.mail-archive.com/dev@mynewt.apache.org/msg01293.html
+
+ switch (gatts_op) {
+ case MP_BLUETOOTH_GATTS_OP_NOTIFY:
+ err = ble_gattc_notify_custom(conn_handle, value_handle, om);
+ break;
+ case MP_BLUETOOTH_GATTS_OP_INDICATE:
+ // This will raise BLE_GAP_EVENT_NOTIFY_TX with a status when it is
+ // acknowledged (or timeout/error).
+ err = ble_gattc_indicate_custom(conn_handle, value_handle, om);
+ break;
}
- // 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));
+
+ return ble_hs_err_to_errno(err);
}
int mp_bluetooth_gatts_set_buffer(uint16_t value_handle, size_t len, bool append) {
@@ -1310,15 +1324,51 @@ int mp_bluetooth_gattc_discover_primary_services(uint16_t conn_handle, const mp_
return ble_hs_err_to_errno(err);
}
+STATIC bool match_char_uuid(const mp_obj_bluetooth_uuid_t *filter_uuid, const ble_uuid_any_t *result_uuid) {
+ if (!filter_uuid) {
+ return true;
+ }
+ ble_uuid_any_t filter_uuid_nimble;
+ create_nimble_uuid(filter_uuid, &filter_uuid_nimble);
+ return ble_uuid_cmp(&result_uuid->u, &filter_uuid_nimble.u) == 0;
+}
+
STATIC int ble_gattc_characteristic_cb(uint16_t conn_handle, const struct ble_gatt_error *error, const struct ble_gatt_chr *characteristic, void *arg) {
DEBUG_printf("ble_gattc_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;
}
+
+ mp_bluetooth_nimble_pending_characteristic_t *pending = &MP_STATE_PORT(bluetooth_nimble_root_pointers)->pending_char_result;
+ if (pending->ready) {
+ // If there's a pending characteristic, we now know what it's end handle is, report it up to modbluetooth.
+ pending->ready = 0;
+
+ // The end handle will either be the end of the query range (there are
+ // no more results), or one before the current result's definition
+ // handle.
+ uint16_t end_handle = MP_STATE_PORT(bluetooth_nimble_root_pointers)->char_disc_end_handle;
+ if (error->status == 0) {
+ end_handle = characteristic->def_handle - 1;
+ }
+
+ // Assume same conn_handle because we're limiting to a single active discovery.
+ mp_bluetooth_gattc_on_characteristic_result(conn_handle, pending->value_handle, end_handle, pending->properties, &pending->uuid);
+ }
+
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);
+ // If there's no filter, or the filter matches, then save this result.
+ if (match_char_uuid(MP_STATE_PORT(bluetooth_nimble_root_pointers)->char_filter_uuid, &characteristic->uuid)) {
+ pending->value_handle = characteristic->val_handle;
+ pending->properties = characteristic->properties;
+ pending->uuid = create_mp_uuid(&characteristic->uuid);
+ pending->ready = 1;
+ }
} else {
+ // Finished (or failed). Allow another characteristic discovery to start.
+ MP_STATE_PORT(bluetooth_nimble_root_pointers)->char_disc_end_handle = 0;
+
+ // Report completion.
mp_bluetooth_gattc_on_discover_complete(MP_BLUETOOTH_IRQ_GATTC_CHARACTERISTIC_DONE, conn_handle, error->status == BLE_HS_EDONE ? 0 : error->status);
}
return 0;
@@ -1328,13 +1378,29 @@ int mp_bluetooth_gattc_discover_characteristics(uint16_t conn_handle, uint16_t s
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_gattc_characteristic_cb, NULL);
- } else {
- err = ble_gattc_disc_all_chrs(conn_handle, start_handle, end_handle, &ble_gattc_characteristic_cb, NULL);
+
+ // The implementation of characteristic discovery queries for all
+ // characteristics, and then UUID filtering is applied by NimBLE on each
+ // characteristic. Unfortunately, each characteristic result does not
+ // include its end handle, so you need to know the next characteristic
+ // before you can raise the previous one to modbluetooth. But if we let
+ // NimBLE do the filtering, then we don't necessarily see the next one.
+ // So we make NimBLE return all results and do the filtering here instead.
+
+ if (MP_STATE_PORT(bluetooth_nimble_root_pointers)->char_disc_end_handle) {
+ // Only allow a single discovery (otherwise we'd need to track a
+ // pending characteristic per conn handle).
+ return MP_EBUSY;
+ }
+
+ // Set the uuid filter (if any). This needs to be a root pointer,
+ // otherwise we'd use ble_gattc_disc_all_chrs's arg param.
+ MP_STATE_PORT(bluetooth_nimble_root_pointers)->char_filter_uuid = uuid;
+
+ int err = ble_gattc_disc_all_chrs(conn_handle, start_handle, end_handle, &ble_gattc_characteristic_cb, NULL);
+ if (!err) {
+ // Lock out concurrent characteristic discovery.
+ MP_STATE_PORT(bluetooth_nimble_root_pointers)->char_disc_end_handle = end_handle;
}
return ble_hs_err_to_errno(err);
}
@@ -1394,15 +1460,15 @@ STATIC int ble_gattc_attr_write_cb(uint16_t conn_handle, const struct ble_gatt_e
}
// 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) {
+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);
+ 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_gattc_attr_write_cb, NULL);
+ err = ble_gattc_write_flat(conn_handle, value_handle, value, value_len, &ble_gattc_attr_write_cb, NULL);
} else {
err = BLE_HS_EINVAL;
}
@@ -1966,4 +2032,9 @@ STATIC int ble_secret_store_delete(int obj_type, const union ble_store_key *key)
#endif // MICROPY_PY_BLUETOOTH_ENABLE_PAIRING_BONDING
+#if !MICROPY_BLUETOOTH_NIMBLE_BINDINGS_ONLY
+MP_REGISTER_ROOT_POINTER(struct _mp_bluetooth_nimble_malloc_t *bluetooth_nimble_memory);
+#endif
+MP_REGISTER_ROOT_POINTER(struct _mp_bluetooth_nimble_root_pointers_t *bluetooth_nimble_root_pointers);
+
#endif // MICROPY_PY_BLUETOOTH && MICROPY_BLUETOOTH_NIMBLE
diff --git a/extmod/nimble/modbluetooth_nimble.h b/extmod/nimble/modbluetooth_nimble.h
index 15648a9959a6..d9bef649201c 100644
--- a/extmod/nimble/modbluetooth_nimble.h
+++ b/extmod/nimble/modbluetooth_nimble.h
@@ -31,6 +31,13 @@
#define MP_BLUETOOTH_NIMBLE_MAX_SERVICES (8)
+typedef struct _mp_bluetooth_nimble_pending_characteristic_t {
+ uint16_t value_handle;
+ uint8_t properties;
+ mp_obj_bluetooth_uuid_t uuid;
+ uint8_t ready;
+} mp_bluetooth_nimble_pending_characteristic_t;
+
typedef struct _mp_bluetooth_nimble_root_pointers_t {
// Characteristic (and descriptor) value storage.
mp_gatts_db_t gatts_db;
@@ -44,6 +51,14 @@ typedef struct _mp_bluetooth_nimble_root_pointers_t {
struct _mp_bluetooth_nimble_l2cap_channel_t *l2cap_chan;
bool l2cap_listening;
#endif
+
+ #if MICROPY_PY_BLUETOOTH_ENABLE_GATT_CLIENT
+ // Workaround to allow us to get the end_handle of each characteristic
+ // during discovery. See mp_bluetooth_gattc_discover_characteristics().
+ uint16_t char_disc_end_handle;
+ const mp_obj_bluetooth_uuid_t *char_filter_uuid;
+ mp_bluetooth_nimble_pending_characteristic_t pending_char_result;
+ #endif
} mp_bluetooth_nimble_root_pointers_t;
enum {
diff --git a/extmod/nimble/nimble.mk b/extmod/nimble/nimble.mk
index 806630074eb8..fc1709f0e50a 100644
--- a/extmod/nimble/nimble.mk
+++ b/extmod/nimble/nimble.mk
@@ -5,33 +5,35 @@ ifeq ($(MICROPY_BLUETOOTH_NIMBLE),1)
EXTMOD_DIR = extmod
NIMBLE_EXTMOD_DIR = $(EXTMOD_DIR)/nimble
-EXTMOD_SRC_C += $(NIMBLE_EXTMOD_DIR)/modbluetooth_nimble.c
+SRC_EXTMOD_C += $(NIMBLE_EXTMOD_DIR)/modbluetooth_nimble.c
-CFLAGS_MOD += -DMICROPY_BLUETOOTH_NIMBLE=1
+CFLAGS_EXTMOD += -DMICROPY_BLUETOOTH_NIMBLE=1
# 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
-CFLAGS_MOD += -DMICROPY_BLUETOOTH_NIMBLE_BINDINGS_ONLY=$(MICROPY_BLUETOOTH_NIMBLE_BINDINGS_ONLY)
+CFLAGS_EXTMOD += -DMICROPY_BLUETOOTH_NIMBLE_BINDINGS_ONLY=$(MICROPY_BLUETOOTH_NIMBLE_BINDINGS_ONLY)
ifeq ($(MICROPY_BLUETOOTH_NIMBLE_BINDINGS_ONLY),0)
+GIT_SUBMODULES += lib/mynewt-nimble
+
# On all ports where we provide the full implementation (i.e. not just
# bindings like on ESP32), then we don't need to use the ringbuffer. In this
# case, all NimBLE events are run by the MicroPython scheduler. On Unix, the
# scheduler is also responsible for polling the UART, whereas on STM32 the
# UART is also polled by the RX IRQ.
-CFLAGS_MOD += -DMICROPY_PY_BLUETOOTH_USE_SYNC_EVENTS=1
+CFLAGS_EXTMOD += -DMICROPY_PY_BLUETOOTH_USE_SYNC_EVENTS=1
# Without the ringbuffer, and with the full implementation, we can also
# enable pairing and bonding. This requires both synchronous events and
# some customisation of the key store.
-CFLAGS_MOD += -DMICROPY_PY_BLUETOOTH_ENABLE_PAIRING_BONDING=1
+CFLAGS_EXTMOD += -DMICROPY_PY_BLUETOOTH_ENABLE_PAIRING_BONDING=1
NIMBLE_LIB_DIR = lib/mynewt-nimble
-LIB_SRC_C += $(addprefix $(NIMBLE_LIB_DIR)/, \
+SRC_THIRDPARTY_C += $(addprefix $(NIMBLE_LIB_DIR)/, \
$(addprefix ext/tinycrypt/src/, \
aes_encrypt.c \
cmac_mode.c \
@@ -96,7 +98,7 @@ LIB_SRC_C += $(addprefix $(NIMBLE_LIB_DIR)/, \
)
# nimble/host/store/ram/src/ble_store_ram.c \
-EXTMOD_SRC_C += $(addprefix $(NIMBLE_EXTMOD_DIR)/, \
+SRC_THIRDPARTY_C += $(addprefix $(NIMBLE_EXTMOD_DIR)/, \
nimble/nimble_npl_os.c \
hal/hal_uart.c \
)
diff --git a/extmod/uasyncio/__init__.py b/extmod/uasyncio/__init__.py
index fa64438f6b2a..373de52af464 100644
--- a/extmod/uasyncio/__init__.py
+++ b/extmod/uasyncio/__init__.py
@@ -18,6 +18,7 @@
"StreamWriter": "stream",
}
+
# Lazy loader, effectively does:
# global attr
# from .mod import attr
diff --git a/extmod/uasyncio/core.py b/extmod/uasyncio/core.py
index 10a310809c0e..f191d202e236 100644
--- a/extmod/uasyncio/core.py
+++ b/extmod/uasyncio/core.py
@@ -30,6 +30,7 @@ class TimeoutError(Exception):
################################################################################
# Sleep functions
+
# "Yield" once, then raise StopIteration
class SingletonGenerator:
def __init__(self):
@@ -132,6 +133,7 @@ def wait_io_event(self, dt):
################################################################################
# Main run loop
+
# Ensure the awaitable is a task
def _promote_to_task(aw):
return aw if isinstance(aw, Task) else create_task(aw)
diff --git a/extmod/uasyncio/event.py b/extmod/uasyncio/event.py
index c48904b9835c..43d47eb5f06f 100644
--- a/extmod/uasyncio/event.py
+++ b/extmod/uasyncio/event.py
@@ -3,6 +3,7 @@
from . import core
+
# Event class for primitive events that can be waited on, set, and cleared
class Event:
def __init__(self):
@@ -23,7 +24,8 @@ def set(self):
def clear(self):
self.state = False
- async def wait(self):
+ # async
+ def wait(self):
if not self.state:
# Event not set, put the calling task on the event's waiting queue
self.waiting.push(core.cur_task)
@@ -36,26 +38,29 @@ async def wait(self):
# MicroPython-extension: This can be set from outside the asyncio event loop,
# such as other threads, IRQs or scheduler context. Implementation is a stream
# that asyncio will poll until a flag is set.
-# Note: Unlike Event, this is self-clearing.
+# Note: Unlike Event, this is self-clearing after a wait().
try:
import uio
class ThreadSafeFlag(uio.IOBase):
def __init__(self):
- self._flag = 0
+ self.state = 0
def ioctl(self, req, flags):
if req == 3: # MP_STREAM_POLL
- return self._flag * flags
+ return self.state * flags
return None
def set(self):
- self._flag = 1
+ self.state = 1
+
+ def clear(self):
+ self.state = 0
async def wait(self):
- if not self._flag:
+ if not self.state:
yield core._io_queue.queue_read(self)
- self._flag = 0
+ self.state = 0
except ImportError:
pass
diff --git a/extmod/uasyncio/funcs.py b/extmod/uasyncio/funcs.py
index a1d38fbcbf97..23a585aa94d9 100644
--- a/extmod/uasyncio/funcs.py
+++ b/extmod/uasyncio/funcs.py
@@ -4,7 +4,7 @@
from . import core
-def _run(waiter, aw):
+async def _run(waiter, aw):
try:
result = await aw
status = True
@@ -61,7 +61,11 @@ def remove(t):
pass
-async def gather(*aws, return_exceptions=False):
+# async
+def gather(*aws, return_exceptions=False):
+ if not aws:
+ return []
+
def done(t, er):
# Sub-task "t" has finished, with exception "er".
nonlocal state
diff --git a/extmod/uasyncio/lock.py b/extmod/uasyncio/lock.py
index f50213d7c186..85a9437b4fe8 100644
--- a/extmod/uasyncio/lock.py
+++ b/extmod/uasyncio/lock.py
@@ -3,6 +3,7 @@
from . import core
+
# Lock class for primitive mutex capability
class Lock:
def __init__(self):
@@ -28,7 +29,8 @@ def release(self):
# No Task waiting so unlock
self.state = 0
- async def acquire(self):
+ # async
+ def acquire(self):
if self.state != 0:
# Lock unavailable, put the calling Task on the waiting queue
self.waiting.push(core.cur_task)
diff --git a/extmod/uasyncio/manifest.py b/extmod/uasyncio/manifest.py
index f5fa27bfcaa3..d425a467b3af 100644
--- a/extmod/uasyncio/manifest.py
+++ b/extmod/uasyncio/manifest.py
@@ -1,13 +1,15 @@
-# This list of frozen files doesn't include task.py because that's provided by the C module.
-freeze(
- "..",
+# This list of package files doesn't include task.py because that's provided
+# by the C module.
+package(
+ "uasyncio",
(
- "uasyncio/__init__.py",
- "uasyncio/core.py",
- "uasyncio/event.py",
- "uasyncio/funcs.py",
- "uasyncio/lock.py",
- "uasyncio/stream.py",
+ "__init__.py",
+ "core.py",
+ "event.py",
+ "funcs.py",
+ "lock.py",
+ "stream.py",
),
+ base_path="..",
opt=3,
)
diff --git a/extmod/uasyncio/stream.py b/extmod/uasyncio/stream.py
index af3b8feab358..875353c940f0 100644
--- a/extmod/uasyncio/stream.py
+++ b/extmod/uasyncio/stream.py
@@ -26,15 +26,26 @@ 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 read(self, n=-1):
+ r = b""
+ while True:
+ yield core._io_queue.queue_read(self.s)
+ r2 = self.s.read(n)
+ if r2 is not None:
+ if n >= 0:
+ return r2
+ if not len(r2):
+ return r
+ r += r2
- async def readinto(self, buf):
+ # async
+ def readinto(self, buf):
yield core._io_queue.queue_read(self.s)
return self.s.readinto(buf)
- async def readexactly(self, n):
+ # async
+ def readexactly(self, n):
r = b""
while n:
yield core._io_queue.queue_read(self.s)
@@ -46,7 +57,8 @@ async def readexactly(self, n):
n -= len(r2)
return r
- async def readline(self):
+ # async
+ def readline(self):
l = b""
while True:
yield core._io_queue.queue_read(self.s)
@@ -56,9 +68,20 @@ async def readline(self):
return l
def write(self, buf):
+ if not self.out_buf:
+ # Try to write immediately to the underlying stream.
+ ret = self.s.write(buf)
+ if ret == len(buf):
+ return
+ if ret is not None:
+ buf = buf[ret:]
self.out_buf += buf
- async def drain(self):
+ # async
+ def drain(self):
+ if not self.out_buf:
+ # Drain must always yield, so a tight loop of write+drain can't block the scheduler.
+ return (yield from core.sleep_ms(0))
mv = memoryview(self.out_buf)
off = 0
while off < len(mv):
@@ -75,7 +98,9 @@ async def drain(self):
# Create a TCP stream connection to a remote host
-async def open_connection(host, port):
+#
+# async
+def open_connection(host, port):
from uerrno import EINPROGRESS
import usocket as socket
diff --git a/extmod/uos_dupterm.c b/extmod/uos_dupterm.c
index e18d133b913a..981d05a63839 100644
--- a/extmod/uos_dupterm.c
+++ b/extmod/uos_dupterm.c
@@ -33,10 +33,11 @@
#include "py/objarray.h"
#include "py/stream.h"
#include "extmod/misc.h"
-#include "shared/runtime/interrupt_char.h"
#if MICROPY_PY_OS_DUPTERM
+#include "shared/runtime/interrupt_char.h"
+
void mp_uos_deactivate(size_t dupterm_idx, const char *msg, mp_obj_t exc) {
mp_obj_t term = MP_STATE_VM(dupterm_objs[dupterm_idx]);
MP_STATE_VM(dupterm_objs[dupterm_idx]) = MP_OBJ_NULL;
@@ -201,4 +202,6 @@ STATIC mp_obj_t mp_uos_dupterm(size_t n_args, const mp_obj_t *args) {
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_uos_dupterm_obj, 1, 2, mp_uos_dupterm);
-#endif
+MP_REGISTER_ROOT_POINTER(mp_obj_t dupterm_objs[MICROPY_PY_OS_DUPTERM]);
+
+#endif // MICROPY_PY_OS_DUPTERM
diff --git a/extmod/utime_mphal.c b/extmod/utime_mphal.c
index 3d1cdfd82062..9cd5d938d0f9 100644
--- a/extmod/utime_mphal.c
+++ b/extmod/utime_mphal.c
@@ -95,6 +95,19 @@ STATIC mp_obj_t time_ticks_add(mp_obj_t ticks_in, mp_obj_t delta_in) {
// we assume that first argument come from ticks_xx so is small int
mp_uint_t ticks = MP_OBJ_SMALL_INT_VALUE(ticks_in);
mp_uint_t delta = mp_obj_get_int(delta_in);
+
+ // Check that delta does not overflow the range that ticks_diff can handle.
+ // This ensures the following:
+ // - ticks_diff(ticks_add(T, delta), T) == delta
+ // - ticks_diff(T, ticks_add(T, delta)) == -delta
+ // The latter requires excluding delta=-TICKS_PERIOD/2.
+ //
+ // This unsigned comparison is equivalent to a signed comparison of:
+ // delta <= -TICKS_PERIOD/2 || delta >= TICKS_PERIOD/2
+ if (delta + MICROPY_PY_UTIME_TICKS_PERIOD / 2 - 1 >= MICROPY_PY_UTIME_TICKS_PERIOD - 1) {
+ mp_raise_msg(&mp_type_OverflowError, MP_ERROR_TEXT("ticks interval overflow"));
+ }
+
return MP_OBJ_NEW_SMALL_INT((ticks + delta) & (MICROPY_PY_UTIME_TICKS_PERIOD - 1));
}
MP_DEFINE_CONST_FUN_OBJ_2(mp_utime_ticks_add_obj, time_ticks_add);
diff --git a/extmod/vfs.c b/extmod/vfs.c
index 8e5e03632662..af63ceb37eb1 100644
--- a/extmod/vfs.c
+++ b/extmod/vfs.c
@@ -100,6 +100,8 @@ STATIC mp_vfs_mount_t *lookup_path(mp_obj_t path_in, mp_obj_t *path_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));
+ } else {
+ *path_out = MP_OBJ_NULL;
}
return vfs;
}
@@ -130,8 +132,9 @@ mp_import_stat_t mp_vfs_import_stat(const char *path) {
}
// If the mounted object has the VFS protocol, call its import_stat helper
- const mp_vfs_proto_t *proto = mp_obj_get_type(vfs->obj)->protocol;
- if (proto != NULL) {
+ const mp_obj_type_t *type = mp_obj_get_type(vfs->obj);
+ if (MP_OBJ_TYPE_HAS_SLOT(type, protocol)) {
+ const mp_vfs_proto_t *proto = MP_OBJ_TYPE_GET_SLOT(type, protocol);
return proto->import_stat(MP_OBJ_TO_PTR(vfs->obj), path_out);
}
@@ -170,7 +173,7 @@ STATIC mp_obj_t mp_vfs_autodetect(mp_obj_t bdev_obj) {
#if MICROPY_VFS_LFS1
if (memcmp(&buf[32], "littlefs", 8) == 0) {
// LFS1
- mp_obj_t vfs = mp_type_vfs_lfs1.make_new(&mp_type_vfs_lfs1, 1, 0, &bdev_obj);
+ mp_obj_t vfs = MP_OBJ_TYPE_GET_SLOT(&mp_type_vfs_lfs1, make_new)(&mp_type_vfs_lfs1, 1, 0, &bdev_obj);
nlr_pop();
return vfs;
}
@@ -178,7 +181,7 @@ STATIC mp_obj_t mp_vfs_autodetect(mp_obj_t bdev_obj) {
#if MICROPY_VFS_LFS2
if (memcmp(&buf[0], "littlefs", 8) == 0) {
// LFS2
- mp_obj_t vfs = mp_type_vfs_lfs2.make_new(&mp_type_vfs_lfs2, 1, 0, &bdev_obj);
+ mp_obj_t vfs = MP_OBJ_TYPE_GET_SLOT(&mp_type_vfs_lfs2, make_new)(&mp_type_vfs_lfs2, 1, 0, &bdev_obj);
nlr_pop();
return vfs;
}
@@ -191,7 +194,7 @@ STATIC mp_obj_t mp_vfs_autodetect(mp_obj_t bdev_obj) {
#endif
#if MICROPY_VFS_FAT
- return mp_fat_vfs_type.make_new(&mp_fat_vfs_type, 1, 0, &bdev_obj);
+ return MP_OBJ_TYPE_GET_SLOT(&mp_fat_vfs_type, make_new)(&mp_fat_vfs_type, 1, 0, &bdev_obj);
#endif
// no filesystem found
@@ -310,7 +313,7 @@ mp_obj_t mp_vfs_open(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args)
#if MICROPY_VFS_POSIX
// If the file is an integer then delegate straight to the POSIX handler
if (mp_obj_is_small_int(args[ARG_file].u_obj)) {
- return mp_vfs_posix_file_open(&mp_type_textio, args[ARG_file].u_obj, args[ARG_mode].u_obj);
+ return mp_vfs_posix_file_open(&mp_type_vfs_posix_textio, args[ARG_file].u_obj, args[ARG_mode].u_obj);
}
#endif
@@ -358,7 +361,7 @@ mp_obj_t mp_vfs_getcwd(void) {
if (!(cwd[0] == '/' && cwd[1] == 0)) {
vstr_add_str(&vstr, cwd);
}
- return mp_obj_new_str_from_vstr(&mp_type_str, &vstr);
+ return mp_obj_new_str_from_vstr(&vstr);
}
MP_DEFINE_CONST_FUN_OBJ_0(mp_vfs_getcwd_obj, mp_vfs_getcwd);
@@ -545,4 +548,7 @@ int mp_vfs_mount_and_chdir_protected(mp_obj_t bdev, mp_obj_t mount_point) {
return ret;
}
+MP_REGISTER_ROOT_POINTER(struct _mp_vfs_mount_t *vfs_cur);
+MP_REGISTER_ROOT_POINTER(struct _mp_vfs_mount_t *vfs_mount_table);
+
#endif // MICROPY_VFS
diff --git a/extmod/vfs_fat.c b/extmod/vfs_fat.c
index 27681ca77012..efb6bf7e9815 100644
--- a/extmod/vfs_fat.c
+++ b/extmod/vfs_fat.c
@@ -28,6 +28,10 @@
#include "py/mpconfig.h"
#if MICROPY_VFS_FAT
+#if !MICROPY_ENABLE_FINALISER
+#error "MICROPY_VFS_FAT requires MICROPY_ENABLE_FINALISER"
+#endif
+
#if !MICROPY_VFS
#error "with MICROPY_VFS_FAT enabled, must also enable MICROPY_VFS"
#endif
@@ -118,6 +122,7 @@ STATIC MP_DEFINE_CONST_STATICMETHOD_OBJ(fat_vfs_mkfs_obj, MP_ROM_PTR(&fat_vfs_mk
typedef struct _mp_vfs_fat_ilistdir_it_t {
mp_obj_base_t base;
mp_fun_1_t iternext;
+ mp_fun_1_t finaliser;
bool is_str;
FF_DIR dir;
} mp_vfs_fat_ilistdir_it_t;
@@ -162,6 +167,13 @@ STATIC mp_obj_t mp_vfs_fat_ilistdir_it_iternext(mp_obj_t self_in) {
return MP_OBJ_STOP_ITERATION;
}
+STATIC mp_obj_t mp_vfs_fat_ilistdir_it_del(mp_obj_t self_in) {
+ mp_vfs_fat_ilistdir_it_t *self = MP_OBJ_TO_PTR(self_in);
+ // ignore result / error because we may be closing a second time.
+ f_closedir(&self->dir);
+ return mp_const_none;
+}
+
STATIC mp_obj_t fat_vfs_ilistdir_func(size_t n_args, const mp_obj_t *args) {
mp_obj_fat_vfs_t *self = MP_OBJ_TO_PTR(args[0]);
bool is_str_type = true;
@@ -176,8 +188,10 @@ STATIC mp_obj_t fat_vfs_ilistdir_func(size_t n_args, const mp_obj_t *args) {
}
// Create a new iterator object to list the dir
- mp_vfs_fat_ilistdir_it_t *iter = mp_obj_malloc(mp_vfs_fat_ilistdir_it_t, &mp_type_polymorph_iter);
+ mp_vfs_fat_ilistdir_it_t *iter = m_new_obj_with_finaliser(mp_vfs_fat_ilistdir_it_t);
+ iter->base.type = &mp_type_polymorph_iter_with_finaliser;
iter->iternext = mp_vfs_fat_ilistdir_it_iternext;
+ iter->finaliser = mp_vfs_fat_ilistdir_it_del;
iter->is_str = is_str_type;
FRESULT res = f_opendir(&self->fatfs, &iter->dir, path);
if (res != FR_OK) {
@@ -417,13 +431,13 @@ STATIC const mp_vfs_proto_t fat_vfs_proto = {
.import_stat = fat_vfs_import_stat,
};
-const mp_obj_type_t mp_fat_vfs_type = {
- { &mp_type_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,
-
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ mp_fat_vfs_type,
+ MP_QSTR_VfsFat,
+ MP_TYPE_FLAG_NONE,
+ make_new, fat_vfs_make_new,
+ protocol, &fat_vfs_proto,
+ locals_dict, &fat_vfs_locals_dict
+ );
#endif // MICROPY_VFS_FAT
diff --git a/extmod/vfs_fat_file.c b/extmod/vfs_fat_file.c
index 537101d00f40..07e6df9bf959 100644
--- a/extmod/vfs_fat_file.c
+++ b/extmod/vfs_fat_file.c
@@ -151,18 +151,63 @@ 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_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_NONE} },
+// TODO gc hook to close the file if not already closed
+
+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) },
+ { MP_ROM_QSTR(MP_QSTR_readlines), MP_ROM_PTR(&mp_stream_unbuffered_readlines_obj) },
+ { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) },
+ { MP_ROM_QSTR(MP_QSTR_flush), MP_ROM_PTR(&mp_stream_flush_obj) },
+ { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&mp_stream_close_obj) },
+ { MP_ROM_QSTR(MP_QSTR_seek), MP_ROM_PTR(&mp_stream_seek_obj) },
+ { MP_ROM_QSTR(MP_QSTR_tell), MP_ROM_PTR(&mp_stream_tell_obj) },
+ { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mp_stream_close_obj) },
+ { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&mp_identity_obj) },
+ { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&file_obj___exit___obj) },
};
-#define FILE_OPEN_NUM_ARGS MP_ARRAY_SIZE(file_open_args)
-STATIC mp_obj_t file_open(fs_user_mount_t *vfs, const mp_obj_type_t *type, mp_arg_val_t *args) {
+STATIC MP_DEFINE_CONST_DICT(vfs_fat_rawfile_locals_dict, vfs_fat_rawfile_locals_dict_table);
+
+STATIC const mp_stream_p_t vfs_fat_fileio_stream_p = {
+ .read = file_obj_read,
+ .write = file_obj_write,
+ .ioctl = file_obj_ioctl,
+};
+
+MP_DEFINE_CONST_OBJ_TYPE(
+ mp_type_vfs_fat_fileio,
+ MP_QSTR_FileIO,
+ MP_TYPE_FLAG_ITER_IS_STREAM,
+ print, file_obj_print,
+ protocol, &vfs_fat_fileio_stream_p,
+ locals_dict, &vfs_fat_rawfile_locals_dict
+ );
+
+STATIC const mp_stream_p_t vfs_fat_textio_stream_p = {
+ .read = file_obj_read,
+ .write = file_obj_write,
+ .ioctl = file_obj_ioctl,
+ .is_text = true,
+};
+
+MP_DEFINE_CONST_OBJ_TYPE(
+ mp_type_vfs_fat_textio,
+ MP_QSTR_TextIOWrapper,
+ MP_TYPE_FLAG_ITER_IS_STREAM,
+ print, file_obj_print,
+ protocol, &vfs_fat_textio_stream_p,
+ locals_dict, &vfs_fat_rawfile_locals_dict
+ );
+
+// Factory function for I/O stream classes
+STATIC mp_obj_t fat_vfs_open(mp_obj_t self_in, mp_obj_t path_in, mp_obj_t mode_in) {
+ fs_user_mount_t *self = MP_OBJ_TO_PTR(self_in);
+
+ const mp_obj_type_t *type = &mp_type_vfs_fat_textio;
int mode = 0;
- const char *mode_s = mp_obj_str_get_str(args[1].u_obj);
+ const char *mode_s = mp_obj_str_get_str(mode_in);
// TODO make sure only one of r, w, x, a, and b, t are specified
while (*mode_s) {
switch (*mode_s++) {
@@ -181,11 +226,9 @@ STATIC mp_obj_t file_open(fs_user_mount_t *vfs, const mp_obj_type_t *type, mp_ar
case '+':
mode |= FA_READ | FA_WRITE;
break;
- #if MICROPY_PY_IO_FILEIO
case 'b':
type = &mp_type_vfs_fat_fileio;
break;
- #endif
case 't':
type = &mp_type_vfs_fat_textio;
break;
@@ -195,9 +238,8 @@ 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;
- const char *fname = mp_obj_str_get_str(args[0].u_obj);
- assert(vfs != NULL);
- FRESULT res = f_open(&vfs->fatfs, &o->fp, fname, mode);
+ const char *fname = mp_obj_str_get_str(path_in);
+ FRESULT res = f_open(&self->fatfs, &o->fp, fname, mode);
if (res != FR_OK) {
m_del_obj(pyb_file_obj_t, o);
mp_raise_OSError(fresult_to_errno_table[res]);
@@ -210,79 +252,6 @@ STATIC mp_obj_t file_open(fs_user_mount_t *vfs, const mp_obj_type_t *type, mp_ar
return MP_OBJ_FROM_PTR(o);
}
-
-STATIC mp_obj_t file_obj_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
- mp_arg_val_t arg_vals[FILE_OPEN_NUM_ARGS];
- mp_arg_parse_all_kw_array(n_args, n_kw, args, FILE_OPEN_NUM_ARGS, file_open_args, arg_vals);
- return file_open(NULL, type, arg_vals);
-}
-
-// TODO gc hook to close the file if not already closed
-
-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) },
- { MP_ROM_QSTR(MP_QSTR_readlines), MP_ROM_PTR(&mp_stream_unbuffered_readlines_obj) },
- { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) },
- { MP_ROM_QSTR(MP_QSTR_flush), MP_ROM_PTR(&mp_stream_flush_obj) },
- { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&mp_stream_close_obj) },
- { MP_ROM_QSTR(MP_QSTR_seek), MP_ROM_PTR(&mp_stream_seek_obj) },
- { MP_ROM_QSTR(MP_QSTR_tell), MP_ROM_PTR(&mp_stream_tell_obj) },
- { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mp_stream_close_obj) },
- { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&mp_identity_obj) },
- { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&file_obj___exit___obj) },
-};
-
-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 vfs_fat_fileio_stream_p = {
- .read = file_obj_read,
- .write = file_obj_write,
- .ioctl = file_obj_ioctl,
-};
-
-const mp_obj_type_t mp_type_vfs_fat_fileio = {
- { &mp_type_type },
- .name = MP_QSTR_FileIO,
- .print = file_obj_print,
- .make_new = file_obj_make_new,
- .getiter = mp_identity_getiter,
- .iternext = mp_stream_unbuffered_iter,
- .protocol = &vfs_fat_fileio_stream_p,
- .locals_dict = (mp_obj_dict_t *)&vfs_fat_rawfile_locals_dict,
-};
-#endif
-
-STATIC const mp_stream_p_t vfs_fat_textio_stream_p = {
- .read = file_obj_read,
- .write = file_obj_write,
- .ioctl = file_obj_ioctl,
- .is_text = true,
-};
-
-const mp_obj_type_t mp_type_vfs_fat_textio = {
- { &mp_type_type },
- .name = MP_QSTR_TextIOWrapper,
- .print = file_obj_print,
- .make_new = file_obj_make_new,
- .getiter = mp_identity_getiter,
- .iternext = mp_stream_unbuffered_iter,
- .protocol = &vfs_fat_textio_stream_p,
- .locals_dict = (mp_obj_dict_t *)&vfs_fat_rawfile_locals_dict,
-};
-
-// Factory function for I/O stream classes
-STATIC mp_obj_t fatfs_builtin_open_self(mp_obj_t self_in, mp_obj_t path, mp_obj_t mode) {
- // TODO: analyze buffering args and instantiate appropriate type
- fs_user_mount_t *self = MP_OBJ_TO_PTR(self_in);
- mp_arg_val_t arg_vals[FILE_OPEN_NUM_ARGS];
- arg_vals[0].u_obj = path;
- arg_vals[1].u_obj = mode;
- arg_vals[2].u_obj = mp_const_none;
- return file_open(self, &mp_type_vfs_fat_textio, arg_vals);
-}
-MP_DEFINE_CONST_FUN_OBJ_3(fat_vfs_open_obj, fatfs_builtin_open_self);
+MP_DEFINE_CONST_FUN_OBJ_3(fat_vfs_open_obj, fat_vfs_open);
#endif // MICROPY_VFS && MICROPY_VFS_FAT
diff --git a/extmod/vfs_lfs.c b/extmod/vfs_lfs.c
index f6a9a24623a9..4fb86b89b76c 100644
--- a/extmod/vfs_lfs.c
+++ b/extmod/vfs_lfs.c
@@ -26,12 +26,13 @@
#include "py/runtime.h"
#include "py/mphal.h"
+
+#if MICROPY_VFS && (MICROPY_VFS_LFS1 || MICROPY_VFS_LFS2)
+
#include "shared/timeutils/timeutils.h"
#include "extmod/vfs.h"
#include "extmod/vfs_lfs.h"
-#if MICROPY_VFS && (MICROPY_VFS_LFS1 || MICROPY_VFS_LFS2)
-
enum { LFS_MAKE_ARG_bdev, LFS_MAKE_ARG_readsize, LFS_MAKE_ARG_progsize, LFS_MAKE_ARG_lookahead, LFS_MAKE_ARG_mtime };
static const mp_arg_t lfs_make_allowed_args[] = {
diff --git a/extmod/vfs_lfsx.c b/extmod/vfs_lfsx.c
index dbd32338cfd9..de1f421977fd 100644
--- a/extmod/vfs_lfsx.c
+++ b/extmod/vfs_lfsx.c
@@ -24,6 +24,9 @@
* THE SOFTWARE.
*/
+// This file should be compiled when included from vfs_lfs.c.
+#if defined(LFS_BUILD_VERSION)
+
#include
#include
@@ -36,6 +39,10 @@
#include "extmod/vfs.h"
#include "shared/timeutils/timeutils.h"
+#if !MICROPY_ENABLE_FINALISER
+#error "MICROPY_VFS_LFS requires MICROPY_ENABLE_FINALISER"
+#endif
+
STATIC int MP_VFS_LFSx(dev_ioctl)(const struct LFSx_API (config) * c, int cmd, int arg, bool must_return_int) {
mp_obj_t ret = mp_vfs_blockdev_ioctl(c->context, cmd, arg);
int ret_i = 0;
@@ -155,6 +162,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_3(MP_VFS_LFSx(open_obj), MP_VFS_LFSx(file_open));
typedef struct MP_VFS_LFSx (_ilistdir_it_t) {
mp_obj_base_t base;
mp_fun_1_t iternext;
+ mp_fun_1_t finaliser;
bool is_str;
MP_OBJ_VFS_LFSx *vfs;
LFSx_API(dir_t) dir;
@@ -163,11 +171,16 @@ typedef struct MP_VFS_LFSx (_ilistdir_it_t) {
STATIC mp_obj_t MP_VFS_LFSx(ilistdir_it_iternext)(mp_obj_t self_in) {
MP_VFS_LFSx(ilistdir_it_t) * self = MP_OBJ_TO_PTR(self_in);
+ if (self->vfs == NULL) {
+ return MP_OBJ_STOP_ITERATION;
+ }
+
struct LFSx_API (info) info;
for (;;) {
int ret = LFSx_API(dir_read)(&self->vfs->lfs, &self->dir, &info);
if (ret == 0) {
LFSx_API(dir_close)(&self->vfs->lfs, &self->dir);
+ self->vfs = NULL;
return MP_OBJ_STOP_ITERATION;
}
if (!(info.name[0] == '.' && (info.name[1] == '\0'
@@ -190,6 +203,14 @@ STATIC mp_obj_t MP_VFS_LFSx(ilistdir_it_iternext)(mp_obj_t self_in) {
return MP_OBJ_FROM_PTR(t);
}
+STATIC mp_obj_t MP_VFS_LFSx(ilistdir_it_del)(mp_obj_t self_in) {
+ MP_VFS_LFSx(ilistdir_it_t) * self = MP_OBJ_TO_PTR(self_in);
+ if (self->vfs != NULL) {
+ LFSx_API(dir_close)(&self->vfs->lfs, &self->dir);
+ }
+ return mp_const_none;
+}
+
STATIC mp_obj_t MP_VFS_LFSx(ilistdir_func)(size_t n_args, const mp_obj_t *args) {
MP_OBJ_VFS_LFSx *self = MP_OBJ_TO_PTR(args[0]);
bool is_str_type = true;
@@ -203,14 +224,17 @@ STATIC mp_obj_t MP_VFS_LFSx(ilistdir_func)(size_t n_args, const mp_obj_t *args)
path = vstr_null_terminated_str(&self->cur_dir);
}
- MP_VFS_LFSx(ilistdir_it_t) * iter = mp_obj_malloc(MP_VFS_LFSx(ilistdir_it_t), &mp_type_polymorph_iter);
+ MP_VFS_LFSx(ilistdir_it_t) * iter = m_new_obj_with_finaliser(MP_VFS_LFSx(ilistdir_it_t));
+ iter->base.type = &mp_type_polymorph_iter_with_finaliser;
+
iter->iternext = MP_VFS_LFSx(ilistdir_it_iternext);
+ iter->finaliser = MP_VFS_LFSx(ilistdir_it_del);
iter->is_str = is_str_type;
- iter->vfs = self;
int ret = LFSx_API(dir_open)(&self->lfs, &iter->dir, path);
if (ret < 0) {
mp_raise_OSError(-ret);
}
+ iter->vfs = self;
return MP_OBJ_FROM_PTR(iter);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(MP_VFS_LFSx(ilistdir_obj), 1, 2, MP_VFS_LFSx(ilistdir_func));
@@ -481,14 +505,21 @@ STATIC const mp_vfs_proto_t MP_VFS_LFSx(proto) = {
.import_stat = MP_VFS_LFSx(import_stat),
};
-const mp_obj_type_t MP_TYPE_VFS_LFSx = {
- { &mp_type_type },
- #if LFS_BUILD_VERSION == 1
- .name = MP_QSTR_VfsLfs1,
- #else
- .name = MP_QSTR_VfsLfs2,
- #endif
- .make_new = MP_VFS_LFSx(make_new),
- .protocol = &MP_VFS_LFSx(proto),
- .locals_dict = (mp_obj_dict_t *)&MP_VFS_LFSx(locals_dict),
-};
+#if LFS_BUILD_VERSION == 1
+#define VFS_LFSx_QSTR MP_QSTR_VfsLfs1
+#else
+#define VFS_LFSx_QSTR MP_QSTR_VfsLfs2
+#endif
+
+MP_DEFINE_CONST_OBJ_TYPE(
+ MP_TYPE_VFS_LFSx,
+ VFS_LFSx_QSTR,
+ MP_TYPE_FLAG_NONE,
+ make_new, MP_VFS_LFSx(make_new),
+ protocol, &MP_VFS_LFSx(proto),
+ locals_dict, &MP_VFS_LFSx(locals_dict)
+ );
+
+#undef VFS_LFSx_QSTR
+
+#endif // defined(LFS_BUILD_VERSION)
diff --git a/extmod/vfs_lfsx_file.c b/extmod/vfs_lfsx_file.c
index bc1a37b90bdb..5f0155d3c5c0 100644
--- a/extmod/vfs_lfsx_file.c
+++ b/extmod/vfs_lfsx_file.c
@@ -24,6 +24,9 @@
* THE SOFTWARE.
*/
+// This file should be compiled when included from vfs_lfs.c.
+#if defined(LFS_BUILD_VERSION)
+
#include
#include
@@ -68,11 +71,9 @@ mp_obj_t MP_VFS_LFSx(file_open)(mp_obj_t self_in, mp_obj_t path_in, mp_obj_t mod
case '+':
flags |= LFSx_MACRO(_O_RDWR);
break;
- #if MICROPY_PY_IO_FILEIO
case 'b':
type = &MP_TYPE_VFS_LFSx_(_fileio);
break;
- #endif
case 't':
type = &MP_TYPE_VFS_LFSx_(_textio);
break;
@@ -216,23 +217,20 @@ STATIC const mp_rom_map_elem_t MP_VFS_LFSx(file_locals_dict_table)[] = {
};
STATIC MP_DEFINE_CONST_DICT(MP_VFS_LFSx(file_locals_dict), MP_VFS_LFSx(file_locals_dict_table));
-#if MICROPY_PY_IO_FILEIO
STATIC const mp_stream_p_t MP_VFS_LFSx(fileio_stream_p) = {
.read = MP_VFS_LFSx(file_read),
.write = MP_VFS_LFSx(file_write),
.ioctl = MP_VFS_LFSx(file_ioctl),
};
-const mp_obj_type_t MP_TYPE_VFS_LFSx_(_fileio) = {
- { &mp_type_type },
- .name = MP_QSTR_FileIO,
- .print = MP_VFS_LFSx(file_print),
- .getiter = mp_identity_getiter,
- .iternext = mp_stream_unbuffered_iter,
- .protocol = &MP_VFS_LFSx(fileio_stream_p),
- .locals_dict = (mp_obj_dict_t *)&MP_VFS_LFSx(file_locals_dict),
-};
-#endif
+MP_DEFINE_CONST_OBJ_TYPE(
+ MP_TYPE_VFS_LFSx_(_fileio),
+ MP_QSTR_FileIO,
+ MP_TYPE_FLAG_ITER_IS_STREAM,
+ print, MP_VFS_LFSx(file_print),
+ protocol, &MP_VFS_LFSx(fileio_stream_p),
+ locals_dict, &MP_VFS_LFSx(file_locals_dict)
+ );
STATIC const mp_stream_p_t MP_VFS_LFSx(textio_stream_p) = {
.read = MP_VFS_LFSx(file_read),
@@ -241,12 +239,13 @@ STATIC const mp_stream_p_t MP_VFS_LFSx(textio_stream_p) = {
.is_text = true,
};
-const mp_obj_type_t MP_TYPE_VFS_LFSx_(_textio) = {
- { &mp_type_type },
- .name = MP_QSTR_TextIOWrapper,
- .print = MP_VFS_LFSx(file_print),
- .getiter = mp_identity_getiter,
- .iternext = mp_stream_unbuffered_iter,
- .protocol = &MP_VFS_LFSx(textio_stream_p),
- .locals_dict = (mp_obj_dict_t *)&MP_VFS_LFSx(file_locals_dict),
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ MP_TYPE_VFS_LFSx_(_textio),
+ MP_QSTR_TextIOWrapper,
+ MP_TYPE_FLAG_ITER_IS_STREAM,
+ print, MP_VFS_LFSx(file_print),
+ protocol, &MP_VFS_LFSx(textio_stream_p),
+ locals_dict, &MP_VFS_LFSx(file_locals_dict)
+ );
+
+#endif // defined(LFS_BUILD_VERSION)
diff --git a/extmod/vfs_posix.c b/extmod/vfs_posix.c
index 1ada596d137c..9b856e1f01cc 100644
--- a/extmod/vfs_posix.c
+++ b/extmod/vfs_posix.c
@@ -33,9 +33,15 @@
#if MICROPY_VFS_POSIX
+#if !MICROPY_ENABLE_FINALISER
+#error "MICROPY_VFS_POSIX requires MICROPY_ENABLE_FINALISER"
+#endif
+
+#include
#include
#include
#include
+#include
#include
#ifdef _MSC_VER
#include // For mkdir etc.
@@ -138,7 +144,7 @@ STATIC mp_obj_t vfs_posix_open(mp_obj_t self_in, mp_obj_t path_in, mp_obj_t mode
if (!mp_obj_is_small_int(path_in)) {
path_in = vfs_posix_get_path_obj(self, path_in);
}
- return mp_vfs_posix_file_open(&mp_type_textio, path_in, mode_in);
+ return mp_vfs_posix_file_open(&mp_type_vfs_posix_textio, path_in, mode_in);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_3(vfs_posix_open_obj, vfs_posix_open);
@@ -162,6 +168,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(vfs_posix_getcwd_obj, vfs_posix_getcwd);
typedef struct _vfs_posix_ilistdir_it_t {
mp_obj_base_t base;
mp_fun_1_t iternext;
+ mp_fun_1_t finaliser;
bool is_str;
DIR *dir;
} vfs_posix_ilistdir_it_t;
@@ -185,7 +192,7 @@ STATIC mp_obj_t vfs_posix_ilistdir_it_iternext(mp_obj_t self_in) {
MP_THREAD_GIL_ENTER();
const char *fn = dirent->d_name;
- if (fn[0] == '.' && (fn[1] == 0 || fn[1] == '.')) {
+ if (fn[0] == '.' && (fn[1] == 0 || (fn[1] == '.' && fn[2] == 0))) {
// skip . and ..
continue;
}
@@ -226,10 +233,22 @@ STATIC mp_obj_t vfs_posix_ilistdir_it_iternext(mp_obj_t self_in) {
}
}
+STATIC mp_obj_t vfs_posix_ilistdir_it_del(mp_obj_t self_in) {
+ vfs_posix_ilistdir_it_t *self = MP_OBJ_TO_PTR(self_in);
+ if (self->dir != NULL) {
+ MP_THREAD_GIL_EXIT();
+ closedir(self->dir);
+ MP_THREAD_GIL_ENTER();
+ }
+ return mp_const_none;
+}
+
STATIC mp_obj_t vfs_posix_ilistdir(mp_obj_t self_in, mp_obj_t path_in) {
mp_obj_vfs_posix_t *self = MP_OBJ_TO_PTR(self_in);
- vfs_posix_ilistdir_it_t *iter = mp_obj_malloc(vfs_posix_ilistdir_it_t, &mp_type_polymorph_iter);
+ vfs_posix_ilistdir_it_t *iter = m_new_obj_with_finaliser(vfs_posix_ilistdir_it_t);
+ iter->base.type = &mp_type_polymorph_iter_with_finaliser;
iter->iternext = vfs_posix_ilistdir_it_iternext;
+ iter->finaliser = vfs_posix_ilistdir_it_del;
iter->is_str = mp_obj_get_type(path_in) == &mp_type_str;
const char *path = vfs_posix_get_path_str(self, path_in);
if (path[0] == '\0') {
@@ -381,12 +400,13 @@ STATIC const mp_vfs_proto_t vfs_posix_proto = {
.import_stat = mp_vfs_posix_import_stat,
};
-const mp_obj_type_t mp_type_vfs_posix = {
- { &mp_type_type },
- .name = MP_QSTR_VfsPosix,
- .make_new = vfs_posix_make_new,
- .protocol = &vfs_posix_proto,
- .locals_dict = (mp_obj_dict_t *)&vfs_posix_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ mp_type_vfs_posix,
+ MP_QSTR_VfsPosix,
+ MP_TYPE_FLAG_NONE,
+ make_new, vfs_posix_make_new,
+ protocol, &vfs_posix_proto,
+ locals_dict, &vfs_posix_locals_dict
+ );
#endif // MICROPY_VFS_POSIX
diff --git a/extmod/vfs_posix_file.c b/extmod/vfs_posix_file.c
index 837c5489b0e1..ea19de7fd04a 100644
--- a/extmod/vfs_posix_file.c
+++ b/extmod/vfs_posix_file.c
@@ -30,7 +30,7 @@
#include "py/stream.h"
#include "extmod/vfs_posix.h"
-#if MICROPY_VFS_POSIX || MICROPY_VFS_POSIX_FILE
+#if MICROPY_VFS_POSIX
#include
#include
@@ -46,7 +46,7 @@ typedef struct _mp_obj_vfs_posix_file_t {
int fd;
} mp_obj_vfs_posix_file_t;
-#ifdef MICROPY_CPYTHON_COMPAT
+#if MICROPY_CPYTHON_COMPAT
STATIC void check_fd_is_open(const mp_obj_vfs_posix_file_t *o) {
if (o->fd < 0) {
mp_raise_ValueError(MP_ERROR_TEXT("I/O operation on closed file"));
@@ -63,7 +63,7 @@ STATIC void vfs_posix_file_print(const mp_print_t *print, mp_obj_t self_in, mp_p
}
mp_obj_t mp_vfs_posix_file_open(const mp_obj_type_t *type, mp_obj_t file_in, mp_obj_t mode_in) {
- mp_obj_vfs_posix_file_t *o = m_new_obj(mp_obj_vfs_posix_file_t);
+ mp_obj_vfs_posix_file_t *o = m_new_obj_with_finaliser(mp_obj_vfs_posix_file_t);
const char *mode_s = mp_obj_str_get_str(mode_in);
int mode_rw = 0, mode_x = 0;
@@ -83,15 +83,12 @@ 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 we don't have io.FileIO, then files are in text mode implicitly
case 'b':
type = &mp_type_vfs_posix_fileio;
break;
case 't':
type = &mp_type_vfs_posix_textio;
break;
- #endif
}
}
@@ -111,17 +108,6 @@ mp_obj_t mp_vfs_posix_file_open(const mp_obj_type_t *type, mp_obj_t file_in, mp_
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_NONE} },
- { MP_QSTR_mode, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_QSTR(MP_QSTR_r)} },
- };
-
- mp_arg_val_t arg_vals[MP_ARRAY_SIZE(allowed_args)];
- mp_arg_parse_all_kw_array(n_args, n_kw, args, MP_ARRAY_SIZE(allowed_args), allowed_args, arg_vals);
- return mp_vfs_posix_file_open(type, arg_vals[0].u_obj, arg_vals[1].u_obj);
-}
-
STATIC mp_obj_t vfs_posix_file_fileno(mp_obj_t self_in) {
mp_obj_vfs_posix_file_t *self = MP_OBJ_TO_PTR(self_in);
check_fd_is_open(self);
@@ -199,12 +185,12 @@ 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
+ if (o->fd >= 0) {
+ MP_THREAD_GIL_EXIT();
+ close(o->fd);
+ MP_THREAD_GIL_ENTER();
+ }
o->fd = -1;
- #endif
return 0;
case MP_STREAM_GET_FILENO:
return o->fd;
@@ -251,30 +237,27 @@ STATIC const mp_rom_map_elem_t vfs_posix_rawfile_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_tell), MP_ROM_PTR(&mp_stream_tell_obj) },
{ MP_ROM_QSTR(MP_QSTR_flush), MP_ROM_PTR(&mp_stream_flush_obj) },
{ MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&mp_stream_close_obj) },
+ { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mp_stream_close_obj) },
{ MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&mp_identity_obj) },
{ MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&vfs_posix_file___exit___obj) },
};
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 vfs_posix_fileio_stream_p = {
.read = vfs_posix_file_read,
.write = vfs_posix_file_write,
.ioctl = vfs_posix_file_ioctl,
};
-const mp_obj_type_t mp_type_vfs_posix_fileio = {
- { &mp_type_type },
- .name = MP_QSTR_FileIO,
- .print = vfs_posix_file_print,
- .make_new = vfs_posix_file_make_new,
- .getiter = mp_identity_getiter,
- .iternext = mp_stream_unbuffered_iter,
- .protocol = &vfs_posix_fileio_stream_p,
- .locals_dict = (mp_obj_dict_t *)&vfs_posix_rawfile_locals_dict,
-};
-#endif
+MP_DEFINE_CONST_OBJ_TYPE(
+ mp_type_vfs_posix_fileio,
+ MP_QSTR_FileIO,
+ MP_TYPE_FLAG_ITER_IS_STREAM,
+ print, vfs_posix_file_print,
+ protocol, &vfs_posix_fileio_stream_p,
+ locals_dict, &vfs_posix_rawfile_locals_dict
+ );
STATIC const mp_stream_p_t vfs_posix_textio_stream_p = {
.read = vfs_posix_file_read,
@@ -283,19 +266,17 @@ STATIC const mp_stream_p_t vfs_posix_textio_stream_p = {
.is_text = true,
};
-const mp_obj_type_t mp_type_vfs_posix_textio = {
- { &mp_type_type },
- .name = MP_QSTR_TextIOWrapper,
- .print = vfs_posix_file_print,
- .make_new = vfs_posix_file_make_new,
- .getiter = mp_identity_getiter,
- .iternext = mp_stream_unbuffered_iter,
- .protocol = &vfs_posix_textio_stream_p,
- .locals_dict = (mp_obj_dict_t *)&vfs_posix_rawfile_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ mp_type_vfs_posix_textio,
+ MP_QSTR_TextIOWrapper,
+ MP_TYPE_FLAG_ITER_IS_STREAM,
+ print, vfs_posix_file_print,
+ protocol, &vfs_posix_textio_stream_p,
+ locals_dict, &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_stdout_obj = {{&mp_type_textio}, STDOUT_FILENO};
-const mp_obj_vfs_posix_file_t mp_sys_stderr_obj = {{&mp_type_textio}, STDERR_FILENO};
+const mp_obj_vfs_posix_file_t mp_sys_stdin_obj = {{&mp_type_vfs_posix_textio}, STDIN_FILENO};
+const mp_obj_vfs_posix_file_t mp_sys_stdout_obj = {{&mp_type_vfs_posix_textio}, STDOUT_FILENO};
+const mp_obj_vfs_posix_file_t mp_sys_stderr_obj = {{&mp_type_vfs_posix_textio}, STDERR_FILENO};
-#endif // MICROPY_VFS_POSIX || MICROPY_VFS_POSIX_FILE
+#endif // MICROPY_VFS_POSIX
diff --git a/extmod/virtpin.c b/extmod/virtpin.c
index 71a11232d433..cd0b9f92f830 100644
--- a/extmod/virtpin.c
+++ b/extmod/virtpin.c
@@ -28,12 +28,12 @@
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_pin_p_t *pin_p = (mp_pin_p_t *)MP_OBJ_TYPE_GET_SLOT(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_pin_p_t *pin_p = (mp_pin_p_t *)MP_OBJ_TYPE_GET_SLOT(s->type, protocol);
pin_p->ioctl(pin, MP_PIN_WRITE, value, NULL);
}
diff --git a/extmod/webrepl/manifest.py b/extmod/webrepl/manifest.py
deleted file mode 100644
index 6eceb3eeb6c5..000000000000
--- a/extmod/webrepl/manifest.py
+++ /dev/null
@@ -1 +0,0 @@
-freeze(".", ("webrepl.py", "webrepl_setup.py", "websocket_helper.py"))
diff --git a/extmod/webrepl/webrepl.py b/extmod/webrepl/webrepl.py
deleted file mode 100644
index 0de813cda18c..000000000000
--- a/extmod/webrepl/webrepl.py
+++ /dev/null
@@ -1,86 +0,0 @@
-# This module should be imported from REPL, not run from command line.
-import socket
-import uos
-import network
-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()
- listen_s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
-
- ai = socket.getaddrinfo("0.0.0.0", port)
- addr = ai[0][4]
-
- listen_s.bind(addr)
- listen_s.listen(1)
- if accept_handler:
- listen_s.setsockopt(socket.SOL_SOCKET, 20, accept_handler)
- for i in (network.AP_IF, network.STA_IF):
- iface = network.WLAN(i)
- if iface.active():
- print("WebREPL daemon started on ws://%s:%d" % (iface.ifconfig()[0], port))
- return listen_s
-
-
-def accept_conn(listen_sock):
- global client_s
- cl, remote_addr = listen_sock.accept()
- prev = uos.dupterm(None)
- uos.dupterm(prev)
- if prev:
- print("\nConcurrent WebREPL connection from", remote_addr, "rejected")
- cl.close()
- return
- print("\nWebREPL connection from:", remote_addr)
- client_s = cl
- websocket_helper.server_handshake(cl)
- ws = uwebsocket.websocket(cl, True)
- ws = _webrepl._webrepl(ws)
- cl.setblocking(False)
- # 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)
-
-
-def stop():
- global listen_s, client_s
- uos.dupterm(None)
- if client_s:
- client_s.close()
- if listen_s:
- listen_s.close()
-
-
-def start(port=8266, password=None, accept_handler=accept_conn):
- stop()
- webrepl_pass = password
- if webrepl_pass is None:
- try:
- import webrepl_cfg
-
- webrepl_pass = webrepl_cfg.PASS
- except:
- print("WebREPL is not configured, run 'import webrepl_setup'")
-
- _webrepl.password(webrepl_pass)
- s = setup_conn(port, accept_handler)
-
- if accept_handler is None:
- print("Starting webrepl in foreground mode")
- accept_conn(s)
- elif password is None:
- print("Started webrepl in normal mode")
- else:
- print("Started webrepl in manual override mode")
-
-
-def start_foreground(port=8266, password=None):
- start(port, password, None)
diff --git a/extmod/webrepl/webrepl_setup.py b/extmod/webrepl/webrepl_setup.py
deleted file mode 100644
index ffc9c77fc0de..000000000000
--- a/extmod/webrepl/webrepl_setup.py
+++ /dev/null
@@ -1,108 +0,0 @@
-import sys
-
-# 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): ")
- if len(passwd1) < 4 or len(passwd1) > 9:
- print("Invalid password length")
- continue
- passwd2 = getpass("Confirm password: ")
- if passwd1 == passwd2:
- return passwd1
- print("Passwords do not match")
-
-
-def exists(fname):
- try:
- with open(fname):
- pass
- return True
- except OSError:
- return False
-
-
-def get_daemon_status():
- with open(RC) as f:
- for l in f:
- if "webrepl" in l:
- if l.startswith("#"):
- return False
- return True
- return None
-
-
-def change_daemon(action):
- LINES = ("import webrepl", "webrepl.start()")
- with open(RC) as old_f, open(RC + ".tmp", "w") as new_f:
- found = False
- for l in old_f:
- for patt in LINES:
- if patt in l:
- found = True
- if action and l.startswith("#"):
- l = l[1:]
- elif not action and not l.startswith("#"):
- l = "#" + l
- new_f.write(l)
- if not found:
- new_f.write("import webrepl\nwebrepl.start()\n")
- # FatFs rename() is not POSIX compliant, will raise OSError if
- # dest file exists.
- os.remove(RC)
- os.rename(RC + ".tmp", RC)
-
-
-def main():
- status = get_daemon_status()
-
- print("WebREPL daemon auto-start status:", "enabled" if status else "disabled")
- print("\nWould you like to (E)nable or (D)isable it running on boot?")
- print("(Empty line to quit)")
- resp = input("> ").upper()
-
- if resp == "E":
- if exists(CONFIG):
- 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"
-
- if resp2 == "y":
- passwd = input_pass()
- 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()
-
- change_daemon(resp == "E")
-
- print("Changes will be activated after reboot")
- resp = input_choice("Would you like to reboot now? (y/n) ", ("y", "n", ""))
- if resp == "y":
- machine.reset()
-
-
-main()
diff --git a/extmod/webrepl/websocket_helper.py b/extmod/webrepl/websocket_helper.py
deleted file mode 100644
index 3260acc52f37..000000000000
--- a/extmod/webrepl/websocket_helper.py
+++ /dev/null
@@ -1,85 +0,0 @@
-try:
- import usys as sys
-except ImportError:
- import sys
-
-try:
- import ubinascii as binascii
-except:
- import binascii
-try:
- import uhashlib as hashlib
-except:
- import hashlib
-
-DEBUG = 0
-
-
-def server_handshake(sock):
- clr = sock.makefile("rwb", 0)
- l = clr.readline()
- # sys.stdout.write(repr(l))
-
- webkey = None
-
- while 1:
- l = clr.readline()
- if not l:
- raise OSError("EOF in headers")
- if l == b"\r\n":
- break
- # 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":
- webkey = v
-
- if not webkey:
- raise OSError("Not a websocket request")
-
- if DEBUG:
- print("Sec-WebSocket-Key:", webkey, len(webkey))
-
- d = hashlib.sha1(webkey)
- d.update(b"258EAFA5-E914-47DA-95CA-C5AB0DC85B11")
- respkey = d.digest()
- respkey = binascii.b2a_base64(respkey)[:-1]
- if DEBUG:
- print("respkey:", respkey)
-
- sock.send(
- b"""\
-HTTP/1.1 101 Switching Protocols\r
-Upgrade: websocket\r
-Connection: Upgrade\r
-Sec-WebSocket-Accept: """
- )
- sock.send(respkey)
- sock.send("\r\n\r\n")
-
-
-# Very simplified client handshake, works for MicroPython's
-# websocket server implementation, but probably not for other
-# servers.
-def client_handshake(sock):
- cl = sock.makefile("rwb", 0)
- 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)
- while 1:
- l = cl.readline()
- if l == b"\r\n":
- break
-
-
-# sys.stdout.write(l)
diff --git a/lib/btstack b/lib/btstack
index c8b9823f68c6..1635e36d0682 160000
--- a/lib/btstack
+++ b/lib/btstack
@@ -1 +1 @@
-Subproject commit c8b9823f68c6af0fa52e2c4e009aba4dbf257232
+Subproject commit 1635e36d06821af8b61302509e91bfcc1ade84c4
diff --git a/lib/cyw43-driver b/lib/cyw43-driver
new file mode 160000
index 000000000000..36144f94bee6
--- /dev/null
+++ b/lib/cyw43-driver
@@ -0,0 +1 @@
+Subproject commit 36144f94bee69ad5e7b46fef06ce0c2405bafee5
diff --git a/lib/libm/thumb_vfp_sqrtf.c b/lib/libm/thumb_vfp_sqrtf.c
index 12ffebf82709..25b8823163c6 100644
--- a/lib/libm/thumb_vfp_sqrtf.c
+++ b/lib/libm/thumb_vfp_sqrtf.c
@@ -3,7 +3,7 @@
#include
float sqrtf(float x) {
- asm volatile (
+ __asm__ volatile (
"vsqrt.f32 %[r], %[x]\n"
: [r] "=t" (x)
: [x] "t" (x));
diff --git a/lib/libm_dbl/thumb_vfp_sqrt.c b/lib/libm_dbl/thumb_vfp_sqrt.c
index dd37a07b053c..ccd33e97960f 100644
--- a/lib/libm_dbl/thumb_vfp_sqrt.c
+++ b/lib/libm_dbl/thumb_vfp_sqrt.c
@@ -2,7 +2,7 @@
double sqrt(double x) {
double ret;
- asm volatile (
+ __asm__ volatile (
"vsqrt.f64 %P0, %P1\n"
: "=w" (ret)
: "w" (x));
diff --git a/lib/lwip b/lib/lwip
index 159e31b68957..6ca936f6b588 160000
--- a/lib/lwip
+++ b/lib/lwip
@@ -1 +1 @@
-Subproject commit 159e31b689577dbf69cf0683bbaffbd71fa5ee10
+Subproject commit 6ca936f6b588cee702c638eee75c2436e6cf75de
diff --git a/lib/micropython-lib b/lib/micropython-lib
new file mode 160000
index 000000000000..c11361176527
--- /dev/null
+++ b/lib/micropython-lib
@@ -0,0 +1 @@
+Subproject commit c113611765278b2fc8dcf8b2f2c3513b35a69b39
diff --git a/lib/pico-sdk b/lib/pico-sdk
index 2062372d203b..f396d05f8252 160000
--- a/lib/pico-sdk
+++ b/lib/pico-sdk
@@ -1 +1 @@
-Subproject commit 2062372d203b372849d573f252cf7c6dc2800c0a
+Subproject commit f396d05f8252d4670d4ea05c8b7ac938ef0cd381
diff --git a/lib/re1.5/charclass.c b/lib/re1.5/charclass.c
index 7f6388c93d29..2553b40530c9 100644
--- a/lib/re1.5/charclass.c
+++ b/lib/re1.5/charclass.c
@@ -6,7 +6,15 @@ int _re1_5_classmatch(const char *pc, const char *sp)
int is_positive = (pc[-1] == Class);
int cnt = *pc++;
while (cnt--) {
- if (*sp >= *pc && *sp <= pc[1]) return is_positive;
+ if (*pc == RE15_CLASS_NAMED_CLASS_INDICATOR) {
+ if (_re1_5_namedclassmatch(pc + 1, sp)) {
+ return is_positive;
+ }
+ } else {
+ if (*sp >= *pc && *sp <= pc[1]) {
+ return is_positive;
+ }
+ }
pc += 2;
}
return !is_positive;
diff --git a/lib/re1.5/compilecode.c b/lib/re1.5/compilecode.c
index add4f6ac2085..513a155970ac 100644
--- a/lib/re1.5/compilecode.c
+++ b/lib/re1.5/compilecode.c
@@ -4,6 +4,9 @@
#include "re1.5.h"
+// Matches: DSWdsw
+#define MATCH_NAMED_CLASS_CHAR(c) (((c) | 0x20) == 'd' || ((c) | 0x24) == 'w')
+
#define INSERT_CODE(at, num, pc) \
((code ? memmove(code + at + num, code + at, pc - at) : 0), pc += num)
#define REL(at, to) (to - at - 2)
@@ -31,7 +34,7 @@ static const char *_compilecode(const char *re, ByteProg *prog, int sizecode)
case '\\':
re++;
if (!*re) return NULL; // Trailing backslash
- if ((*re | 0x20) == 'd' || (*re | 0x20) == 's' || (*re | 0x20) == 'w') {
+ if (MATCH_NAMED_CLASS_CHAR(*re)) {
term = PC;
EMIT(PC++, NamedClass);
EMIT(PC++, *re);
@@ -63,14 +66,21 @@ 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 == '\\') {
+ char c = *re;
+ if (c == '\\') {
++re;
+ c = *re;
+ if (MATCH_NAMED_CLASS_CHAR(c)) {
+ c = RE15_CLASS_NAMED_CLASS_INDICATOR;
+ goto emit_char_pair;
+ }
}
- if (!*re) return NULL;
- EMIT(PC++, *re);
+ if (!c) return NULL;
if (re[1] == '-' && re[2] != ']') {
re += 2;
}
+ emit_char_pair:
+ EMIT(PC++, c);
EMIT(PC++, *re);
}
EMIT_CHECKED(term + 1, cnt);
diff --git a/lib/re1.5/re1.5.h b/lib/re1.5/re1.5.h
index 81f43ed7f5fd..b1ec01cbc586 100644
--- a/lib/re1.5/re1.5.h
+++ b/lib/re1.5/re1.5.h
@@ -138,6 +138,7 @@ struct Subject {
#define NON_ANCHORED_PREFIX 5
#define HANDLE_ANCHORED(bytecode, is_anchored) ((is_anchored) ? (bytecode) + NON_ANCHORED_PREFIX : (bytecode))
+#define RE15_CLASS_NAMED_CLASS_INDICATOR 0
int re1_5_backtrack(ByteProg*, Subject*, const char**, int, int);
int re1_5_pikevm(ByteProg*, Subject*, const char**, int, int);
diff --git a/lib/stm32lib b/lib/stm32lib
index eb80f0126e50..fdb1ec6879bc 160000
--- a/lib/stm32lib
+++ b/lib/stm32lib
@@ -1 +1 @@
-Subproject commit eb80f0126e50687aac966f4c39a2b5a5deffbe78
+Subproject commit fdb1ec6879bc8b7bb54ded73bac04839003c5a07
diff --git a/lib/tinyusb b/lib/tinyusb
index 4bfab30c0227..868f2bcda092 160000
--- a/lib/tinyusb
+++ b/lib/tinyusb
@@ -1 +1 @@
-Subproject commit 4bfab30c02279a0530e1a56f4a7c539f2d35a293
+Subproject commit 868f2bcda092b0b8d5f7ac55ffaef2c81316d35e
diff --git a/mpy-cross/.gitignore b/mpy-cross/.gitignore
deleted file mode 100644
index 22bfbc75c4fd..000000000000
--- a/mpy-cross/.gitignore
+++ /dev/null
@@ -1,4 +0,0 @@
-mpy-cross
-lextab.py
-yacctab.py
-
diff --git a/mpy-cross/Makefile b/mpy-cross/Makefile
index 2189dff9058e..7a71577e2bb1 100644
--- a/mpy-cross/Makefile
+++ b/mpy-cross/Makefile
@@ -19,7 +19,7 @@ INC += -I$(TOP)
# compiler settings
CWARN = -Wall -Werror
CWARN += -Wextra -Wno-unused-parameter -Wpointer-arith
-CFLAGS = $(INC) $(CWARN) -std=gnu99 $(CFLAGS_MOD) $(COPT) $(CFLAGS_EXTRA)
+CFLAGS += $(INC) $(CWARN) -std=gnu99 $(COPT) $(CFLAGS_EXTRA)
CFLAGS += -fdata-sections -ffunction-sections -fno-asynchronous-unwind-tables
# Debugging/Optimization
@@ -42,7 +42,7 @@ else
# Use gcc syntax for map file
LDFLAGS_ARCH = -Wl,-Map=$@.map,--cref -Wl,--gc-sections
endif
-LDFLAGS = $(LDFLAGS_MOD) $(LDFLAGS_ARCH) -lm $(LDFLAGS_EXTRA)
+LDFLAGS += $(LDFLAGS_MOD) $(LDFLAGS_ARCH) -lm $(LDFLAGS_EXTRA)
# source files
SRC_C = \
diff --git a/mpy-cross/main.c b/mpy-cross/main.c
index f3ffff61fdf8..8a4dd5bcbed5 100644
--- a/mpy-cross/main.c
+++ b/mpy-cross/main.c
@@ -73,8 +73,9 @@ STATIC int compile_and_save(const char *file, const char *output_file, const cha
#endif
mp_parse_tree_t parse_tree = mp_parse(lex, MP_PARSE_FILE_INPUT);
- mp_module_context_t *ctx = m_new_obj(mp_module_context_t);
- mp_compiled_module_t cm = mp_compile_to_raw_code(&parse_tree, source_name, false, ctx);
+ mp_compiled_module_t cm;
+ cm.context = m_new_obj(mp_module_context_t);
+ mp_compile_to_raw_code(&parse_tree, source_name, false, &cm);
vstr_t vstr;
vstr_init(&vstr, 16);
@@ -181,6 +182,15 @@ STATIC void pre_process_options(int argc, char **argv) {
}
}
+STATIC char *backslash_to_forwardslash(char *path) {
+ for (char *p = path; p != NULL && *p != '\0'; ++p) {
+ if (*p == '\\') {
+ *p = '/';
+ }
+ }
+ return path;
+}
+
MP_NOINLINE int main_(int argc, char **argv) {
mp_stack_set_limit(40000 * (sizeof(void *) / 4));
@@ -203,19 +213,9 @@ MP_NOINLINE int main_(int argc, char **argv) {
// set default compiler configuration
mp_dynamic_compiler.small_int_bits = 31;
- #if defined(__i386__)
- mp_dynamic_compiler.native_arch = MP_NATIVE_ARCH_X86;
- mp_dynamic_compiler.nlr_buf_num_regs = MICROPY_NLR_NUM_REGS_X86;
- #elif defined(__x86_64__)
- mp_dynamic_compiler.native_arch = MP_NATIVE_ARCH_X64;
- mp_dynamic_compiler.nlr_buf_num_regs = MAX(MICROPY_NLR_NUM_REGS_X64, MICROPY_NLR_NUM_REGS_X64_WIN);
- #elif defined(__arm__) && !defined(__thumb2__)
- mp_dynamic_compiler.native_arch = MP_NATIVE_ARCH_ARMV6;
- mp_dynamic_compiler.nlr_buf_num_regs = MICROPY_NLR_NUM_REGS_ARM_THUMB_FP;
- #else
+ // don't support native emitter unless -march is specified
mp_dynamic_compiler.native_arch = MP_NATIVE_ARCH_NONE;
mp_dynamic_compiler.nlr_buf_num_regs = 0;
- #endif
const char *input_file = NULL;
const char *output_file = NULL;
@@ -228,7 +228,7 @@ MP_NOINLINE int main_(int argc, char **argv) {
a += 1;
} else if (strcmp(argv[a], "--version") == 0) {
printf("MicroPython " MICROPY_GIT_TAG " on " MICROPY_BUILD_DATE
- "; mpy-cross emitting mpy v" MP_STRINGIFY(MPY_VERSION) "\n");
+ "; mpy-cross emitting mpy v" MP_STRINGIFY(MPY_VERSION) "." MP_STRINGIFY(MPY_SUB_VERSION) "\n");
return 0;
} else if (strcmp(argv[a], "-v") == 0) {
mp_verbose_flag++;
@@ -251,7 +251,7 @@ MP_NOINLINE int main_(int argc, char **argv) {
exit(usage(argv));
}
a += 1;
- source_file = argv[a];
+ source_file = backslash_to_forwardslash(argv[a]);
} else if (strncmp(argv[a], "-msmall-int-bits=", sizeof("-msmall-int-bits=") - 1) == 0) {
char *end;
mp_dynamic_compiler.small_int_bits =
@@ -292,6 +292,20 @@ MP_NOINLINE int main_(int argc, char **argv) {
} else if (strcmp(arch, "xtensawin") == 0) {
mp_dynamic_compiler.native_arch = MP_NATIVE_ARCH_XTENSAWIN;
mp_dynamic_compiler.nlr_buf_num_regs = MICROPY_NLR_NUM_REGS_XTENSAWIN;
+ } else if (strcmp(arch, "host") == 0) {
+ #if defined(__i386__) || defined(_M_IX86)
+ mp_dynamic_compiler.native_arch = MP_NATIVE_ARCH_X86;
+ mp_dynamic_compiler.nlr_buf_num_regs = MICROPY_NLR_NUM_REGS_X86;
+ #elif defined(__x86_64__) || defined(_M_X64)
+ mp_dynamic_compiler.native_arch = MP_NATIVE_ARCH_X64;
+ mp_dynamic_compiler.nlr_buf_num_regs = MAX(MICROPY_NLR_NUM_REGS_X64, MICROPY_NLR_NUM_REGS_X64_WIN);
+ #elif defined(__arm__) && !defined(__thumb2__)
+ mp_dynamic_compiler.native_arch = MP_NATIVE_ARCH_ARMV6;
+ mp_dynamic_compiler.nlr_buf_num_regs = MICROPY_NLR_NUM_REGS_ARM_THUMB_FP;
+ #else
+ mp_printf(&mp_stderr_print, "unable to determine host architecture for -march=host\n");
+ exit(1);
+ #endif
} else {
return usage(argv);
}
@@ -303,7 +317,7 @@ MP_NOINLINE int main_(int argc, char **argv) {
mp_printf(&mp_stderr_print, "multiple input files\n");
exit(1);
}
- input_file = argv[a];
+ input_file = backslash_to_forwardslash(argv[a]);
}
}
@@ -330,7 +344,7 @@ int main(int argc, char **argv) {
return main_(argc, argv);
}
-uint mp_import_stat(const char *path) {
+mp_import_stat_t mp_import_stat(const char *path) {
(void)path;
return MP_IMPORT_STAT_NO_EXIST;
}
diff --git a/mpy-cross/mpconfigport.h b/mpy-cross/mpconfigport.h
index 95922d04ff7b..4304c552bc45 100644
--- a/mpy-cross/mpconfigport.h
+++ b/mpy-cross/mpconfigport.h
@@ -119,7 +119,7 @@ typedef long mp_off_t;
#define MP_PLAT_PRINT_STRN(str, len) (void)0
// We need to provide a declaration/definition of alloca()
-#ifdef __FreeBSD__
+#if defined(__FreeBSD__) || defined(__NetBSD__)
#include
#elif defined(_WIN32)
#include
@@ -135,6 +135,7 @@ typedef long mp_off_t;
#define MP_ENDIANNESS_LITTLE (1)
#define NORETURN __declspec(noreturn)
#define MP_NOINLINE __declspec(noinline)
+#define MP_ALWAYSINLINE __forceinline
#define MP_LIKELY(x) (x)
#define MP_UNLIKELY(x) (x)
#define MICROPY_PORT_CONSTANTS { MP_ROM_QSTR(MP_QSTR_dummy), MP_ROM_PTR(NULL) }
diff --git a/mpy-cross/mpy-cross.vcxproj b/mpy-cross/mpy-cross.vcxproj
index 53cb0fa1fec7..322d8c25d109 100644
--- a/mpy-cross/mpy-cross.vcxproj
+++ b/mpy-cross/mpy-cross.vcxproj
@@ -24,7 +24,6 @@
True$(MSBuildThisFileDirectory)build\$(MSBuildThisFileDirectory)
- $(MSBuildThisFileDirectory)$(MSBuildThisFileDirectory)..\ports\windows\msvc\
diff --git a/mpy-cross/mpy_cross/__init__.py b/mpy-cross/mpy_cross/__init__.py
new file mode 100644
index 000000000000..8eadbc8352c7
--- /dev/null
+++ b/mpy-cross/mpy_cross/__init__.py
@@ -0,0 +1,151 @@
+#!/usr/bin/env python3
+#
+# This file is part of the MicroPython project, http://micropython.org/
+#
+# The MIT License (MIT)
+#
+# Copyright (c) 2022 Andrew Leech
+# Copyright (c) 2022 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.
+
+from __future__ import print_function
+import os
+import re
+import stat
+import subprocess
+
+NATIVE_ARCHS = {
+ "NATIVE_ARCH_NONE": "",
+ "NATIVE_ARCH_X86": "x86",
+ "NATIVE_ARCH_X64": "x64",
+ "NATIVE_ARCH_ARMV6": "armv6",
+ "NATIVE_ARCH_ARMV6M": "armv6m",
+ "NATIVE_ARCH_ARMV7M": "armv7m",
+ "NATIVE_ARCH_ARMV7EM": "armv7em",
+ "NATIVE_ARCH_ARMV7EMSP": "armv7emsp",
+ "NATIVE_ARCH_ARMV7EMDP": "armv7emdp",
+ "NATIVE_ARCH_XTENSA": "xtensa",
+ "NATIVE_ARCH_XTENSAWIN": "xtensawin",
+}
+
+globals().update(NATIVE_ARCHS)
+
+__all__ = ["version", "compile", "run", "CrossCompileError"] + list(NATIVE_ARCHS.keys())
+
+
+class CrossCompileError(Exception):
+ pass
+
+
+_VERSION_RE = re.compile("mpy-cross emitting mpy v([0-9]+)(?:.([0-9]+))?")
+
+
+def _find_mpy_cross_binary(mpy_cross):
+ if mpy_cross:
+ return mpy_cross
+ return os.path.abspath(os.path.join(os.path.dirname(__file__), "../build/mpy-cross"))
+
+
+def mpy_version(mpy_cross=None):
+ """
+ Get the version and sub-version of the .mpy file format generated by this version of mpy-cross.
+
+ Returns: A tuple of `(mpy_version, mpy_sub_version)`
+ Optional keyword arguments:
+ - mpy_cross: Specific mpy-cross binary to use
+ """
+ version_info = run(["--version"], mpy_cross=mpy_cross)
+ match = re.search(_VERSION_RE, version_info)
+ mpy_version, mpy_sub_version = int(match.group(1)), int(match.group(2) or "0")
+ return (
+ mpy_version,
+ mpy_sub_version,
+ )
+
+
+def compile(src, dest=None, src_path=None, opt=None, march=None, mpy_cross=None, extra_args=None):
+ """
+ Compile the specified .py file with mpy-cross.
+
+ Returns: Standard output from mpy-cross as a string.
+
+ Required arguments:
+ - src: The path to the .py file
+
+ Optional keyword arguments:
+ - dest: The output .mpy file. Defaults to `src` (with .mpy extension)
+ - src_path: The path to embed in the .mpy file (defaults to `src`)
+ - opt: Optimisation level (0-3, default 0)
+ - march: One of the `NATIVE_ARCH_*` constants (defaults to NATIVE_ARCH_NONE)
+ - mpy_cross: Specific mpy-cross binary to use
+ - extra_args: Additional arguments to pass to mpy-cross (e.g. `["-X", "emit=native"]`)
+ """
+ if not src:
+ raise ValueError("src is required")
+ if not os.path.exists(src):
+ raise CrossCompileError("Input .py file not found: {}.".format(src_py))
+
+ args = []
+
+ if src_path:
+ args += ["-s", src_path]
+
+ if dest:
+ args += ["-o", dest]
+
+ if march:
+ args += ["-march=" + march]
+
+ if opt is not None:
+ args += ["-O{}".format(opt)]
+
+ if extra_args:
+ args += extra_args
+
+ args += [src]
+
+ run(args, mpy_cross)
+
+
+def run(args, mpy_cross=None):
+ """
+ Run mpy-cross with the specified command line arguments.
+ Prefer to use `compile()` instead.
+
+ Returns: Standard output from mpy-cross as a string.
+
+ Optional keyword arguments:
+ - mpy_cross: Specific mpy-cross binary to use
+ """
+ mpy_cross = _find_mpy_cross_binary(mpy_cross)
+
+ if not os.path.exists(mpy_cross):
+ raise CrossCompileError("mpy-cross binary not found at {}.".format(mpy_cross))
+
+ try:
+ st = os.stat(mpy_cross)
+ os.chmod(mpy_cross, st.st_mode | stat.S_IEXEC)
+ except OSError:
+ pass
+
+ try:
+ return subprocess.check_output([mpy_cross] + args, stderr=subprocess.STDOUT).decode()
+ except subprocess.CalledProcessError as er:
+ raise CrossCompileError(er.output.decode())
diff --git a/mpy-cross/mpy_cross/__main__.py b/mpy-cross/mpy_cross/__main__.py
new file mode 100644
index 000000000000..2b6b81c33336
--- /dev/null
+++ b/mpy-cross/mpy_cross/__main__.py
@@ -0,0 +1,38 @@
+#!/usr/bin/env python3
+#
+# This file is part of the MicroPython project, http://micropython.org/
+#
+# The MIT License (MIT)
+#
+# Copyright (c) 2022 Andrew Leech
+# Copyright (c) 2022 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.
+
+from __future__ import print_function
+import argparse
+import sys
+
+from . import run, CrossCompileError
+
+try:
+ print(run(sys.argv[1:]))
+except CrossCompileError as er:
+ print(er.args[0], file=sys.stderr)
+ raise SystemExit(1)
diff --git a/ports/cc3200/Makefile b/ports/cc3200/Makefile
index 560fc8e96def..61af0bfd9844 100644
--- a/ports/cc3200/Makefile
+++ b/ports/cc3200/Makefile
@@ -20,12 +20,14 @@ include ../../py/mkenv.mk
CROSS_COMPILE ?= arm-none-eabi-
CFLAGS_CORTEX_M4 = -mthumb -mtune=cortex-m4 -march=armv7e-m -mabi=aapcs -mcpu=cortex-m4 -msoft-float -mfloat-abi=soft -fsingle-precision-constant -Wdouble-promotion
-CFLAGS = -Wall -Wpointer-arith -Werror -std=gnu99 -nostdlib $(CFLAGS_CORTEX_M4) -Os
+CFLAGS += -Wall -Wpointer-arith -Werror -std=gnu99 -nostdlib $(CFLAGS_CORTEX_M4) -Os
CFLAGS += -g -ffunction-sections -fdata-sections -fno-common -fsigned-char -mno-unaligned-access
CFLAGS += -Iboards/$(BOARD)
-CFLAGS += $(CFLAGS_MOD)
-LDFLAGS = -Wl,-nostdlib -Wl,--gc-sections -Wl,-Map=$@.map
+# Workaround gcc 12.1 bug.
+CFLAGS += -Wno-array-bounds
+
+LDFLAGS += -Wl,-nostdlib -Wl,--gc-sections -Wl,-Map=$@.map
FLASH_SIZE_WIPY = 2M
FLASH_SIZE_LAUNCHXL = 1M
@@ -39,6 +41,7 @@ MICROPY_ROM_TEXT_COMPRESSION ?= 1
# include MicroPython make definitions
include $(TOP)/py/py.mk
+include $(TOP)/extmod/extmod.mk
include application.mk
else
ifeq ($(BTARGET), bootloader)
diff --git a/ports/cc3200/application.mk b/ports/cc3200/application.mk
index 25a9925ea00e..97e113b040aa 100644
--- a/ports/cc3200/application.mk
+++ b/ports/cc3200/application.mk
@@ -162,11 +162,11 @@ APP_STM_SRC_C = $(addprefix ports/stm32/,\
OBJ = $(PY_O) $(addprefix $(BUILD)/, $(APP_FATFS_SRC_C:.c=.o) $(APP_RTOS_SRC_C:.c=.o) $(APP_FTP_SRC_C:.c=.o) $(APP_HAL_SRC_C:.c=.o) $(APP_MISC_SRC_C:.c=.o))
OBJ += $(addprefix $(BUILD)/, $(APP_MODS_SRC_C:.c=.o) $(APP_CC3100_SRC_C:.c=.o) $(APP_SL_SRC_C:.c=.o) $(APP_TELNET_SRC_C:.c=.o) $(APP_UTIL_SRC_C:.c=.o) $(APP_UTIL_SRC_S:.s=.o))
OBJ += $(addprefix $(BUILD)/, $(APP_MAIN_SRC_C:.c=.o) $(APP_SHARED_SRC_C:.c=.o) $(APP_LIB_SRC_C:.c=.o) $(APP_STM_SRC_C:.c=.o))
-OBJ += $(BUILD)/shared/runtime/gchelper_m3.o
+OBJ += $(BUILD)/shared/runtime/gchelper_thumb2.o
OBJ += $(BUILD)/pins.o
# List of sources for qstr extraction
-SRC_QSTR += $(APP_MODS_SRC_C) $(APP_MISC_SRC_C) $(APP_STM_SRC_C) $(APP_SHARED_SRC_C)
+SRC_QSTR += $(APP_MODS_SRC_C) $(APP_MISC_SRC_C) $(APP_STM_SRC_C) $(APP_SHARED_SRC_C) $(APP_HAL_SRC_C)
# Append any auto-generated sources that are needed by sources listed in
# SRC_QSTR
SRC_QSTR_AUTO_DEPS +=
diff --git a/ports/cc3200/bootmgr/bootloader.mk b/ports/cc3200/bootmgr/bootloader.mk
index e5b817391d2f..3aeda062ce42 100644
--- a/ports/cc3200/bootmgr/bootloader.mk
+++ b/ports/cc3200/bootmgr/bootloader.mk
@@ -134,3 +134,7 @@ $(HEADER_BUILD)/mpversion.h: | $(HEADER_BUILD)
# Create an empty "moduledefs.h" needed by py/mkrules.mk
$(HEADER_BUILD)/moduledefs.h: | $(HEADER_BUILD)
touch $@
+
+# Create an empty "root_pointers.h" needed by py/mkrules.mk
+$(HEADER_BUILD)/root_pointers.h: | $(HEADER_BUILD)
+ touch $@
diff --git a/ports/cc3200/hal/cc3200_hal.c b/ports/cc3200/hal/cc3200_hal.c
index 3a35e39e1f55..4694235eebf6 100644
--- a/ports/cc3200/hal/cc3200_hal.c
+++ b/ports/cc3200/hal/cc3200_hal.c
@@ -195,3 +195,5 @@ static void hal_TickInit (void) {
MAP_SysTickEnable();
}
#endif
+
+MP_REGISTER_ROOT_POINTER(struct _os_term_dup_obj_t *os_term_dup_obj);
diff --git a/ports/cc3200/misc/mpirq.c b/ports/cc3200/misc/mpirq.c
index de30ebc49968..eb813fa4c6f2 100644
--- a/ports/cc3200/misc/mpirq.c
+++ b/ports/cc3200/misc/mpirq.c
@@ -190,10 +190,12 @@ STATIC const mp_rom_map_elem_t mp_irq_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(mp_irq_locals_dict, mp_irq_locals_dict_table);
-const mp_obj_type_t mp_irq_type = {
- { &mp_type_type },
- .name = MP_QSTR_irq,
- .call = mp_irq_call,
- .locals_dict = (mp_obj_t)&mp_irq_locals_dict,
-};
-
+MP_DEFINE_CONST_OBJ_TYPE(
+ mp_irq_type,
+ MP_QSTR_irq,
+ MP_TYPE_FLAG_NONE,
+ call, mp_irq_call,
+ locals_dict, &mp_irq_locals_dict
+ );
+
+MP_REGISTER_ROOT_POINTER(mp_obj_list_t mp_irq_obj_list);
diff --git a/ports/cc3200/mods/modmachine.c b/ports/cc3200/mods/modmachine.c
index 782ccc55a1d2..3e483e0a23d2 100644
--- a/ports/cc3200/mods/modmachine.c
+++ b/ports/cc3200/mods/modmachine.c
@@ -215,3 +215,4 @@ const mp_obj_module_t mp_module_machine = {
};
MP_REGISTER_MODULE(MP_QSTR_umachine, mp_module_machine);
+MP_REGISTER_ROOT_POINTER(mp_obj_t machine_config_main);
diff --git a/ports/cc3200/mods/modnetwork.c b/ports/cc3200/mods/modnetwork.c
index d6ccc7c6a04d..590e87268393 100644
--- a/ports/cc3200/mods/modnetwork.c
+++ b/ports/cc3200/mods/modnetwork.c
@@ -171,10 +171,11 @@ STATIC const mp_rom_map_elem_t network_server_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(network_server_locals_dict, network_server_locals_dict_table);
-STATIC const mp_obj_type_t network_server_type = {
- { &mp_type_type },
- .name = MP_QSTR_Server,
- .make_new = network_server_make_new,
- .locals_dict = (mp_obj_t)&network_server_locals_dict,
-};
+STATIC MP_DEFINE_CONST_OBJ_TYPE(
+ network_server_type,
+ MP_QSTR_Server,
+ MP_TYPE_FLAG_NONE,
+ make_new, network_server_make_new,
+ locals_dict, &network_server_locals_dict
+ );
#endif
diff --git a/ports/cc3200/mods/modnetwork.h b/ports/cc3200/mods/modnetwork.h
index 6ec90a2bac18..9bc2c71c2933 100644
--- a/ports/cc3200/mods/modnetwork.h
+++ b/ports/cc3200/mods/modnetwork.h
@@ -35,10 +35,6 @@
/******************************************************************************
DEFINE TYPES
******************************************************************************/
-typedef struct _mod_network_nic_type_t {
- mp_obj_type_t base;
-} mod_network_nic_type_t;
-
typedef struct _mod_network_socket_base_t {
union {
struct {
@@ -63,7 +59,7 @@ typedef struct _mod_network_socket_obj_t {
/******************************************************************************
EXPORTED DATA
******************************************************************************/
-extern const mod_network_nic_type_t mod_network_nic_type_wlan;
+extern const mp_obj_type_t mod_network_nic_type_wlan;
/******************************************************************************
DECLARE FUNCTIONS
diff --git a/ports/cc3200/mods/moduhashlib.c b/ports/cc3200/mods/moduhashlib.c
index fc11569b7f98..302ff335ff86 100644
--- a/ports/cc3200/mods/moduhashlib.c
+++ b/ports/cc3200/mods/moduhashlib.c
@@ -177,19 +177,21 @@ STATIC MP_DEFINE_CONST_DICT(hash_locals_dict, hash_locals_dict_table);
// .locals_dict = (mp_obj_t)&hash_locals_dict,
//};
-STATIC const mp_obj_type_t sha1_type = {
- { &mp_type_type },
- .name = MP_QSTR_sha1,
- .make_new = hash_make_new,
- .locals_dict = (mp_obj_t)&hash_locals_dict,
-};
-
-STATIC const mp_obj_type_t sha256_type = {
- { &mp_type_type },
- .name = MP_QSTR_sha256,
- .make_new = hash_make_new,
- .locals_dict = (mp_obj_t)&hash_locals_dict,
-};
+STATIC MP_DEFINE_CONST_OBJ_TYPE(
+ sha1_type,
+ MP_QSTR_sha1,
+ MP_TYPE_FLAG_NONE,
+ make_new, hash_make_new,
+ locals_dict, &hash_locals_dict
+ );
+
+STATIC MP_DEFINE_CONST_OBJ_TYPE(
+ sha256_type,
+ MP_QSTR_sha256,
+ MP_TYPE_FLAG_NONE,
+ make_new, hash_make_new,
+ locals_dict, &hash_locals_dict
+ );
STATIC const mp_rom_map_elem_t mp_module_hashlib_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uhashlib) },
diff --git a/ports/cc3200/mods/moduos.c b/ports/cc3200/mods/moduos.c
index cd01b59b35d5..e284e9eb1ffb 100644
--- a/ports/cc3200/mods/moduos.c
+++ b/ports/cc3200/mods/moduos.c
@@ -116,7 +116,7 @@ STATIC mp_obj_t os_urandom(mp_obj_t num) {
for (int i = 0; i < n; i++) {
vstr.buf[i] = rng_get();
}
- return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
+ return mp_obj_new_bytes_from_vstr(&vstr);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_urandom_obj, os_urandom);
diff --git a/ports/cc3200/mods/modusocket.c b/ports/cc3200/mods/modusocket.c
index 32849c51d47c..cd1489fb4ae5 100644
--- a/ports/cc3200/mods/modusocket.c
+++ b/ports/cc3200/mods/modusocket.c
@@ -581,7 +581,7 @@ STATIC mp_obj_t socket_recv(mp_obj_t self_in, mp_obj_t len_in) {
}
vstr.len = ret;
vstr.buf[vstr.len] = '\0';
- return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
+ return mp_obj_new_bytes_from_vstr(&vstr);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_recv_obj, socket_recv);
@@ -625,7 +625,7 @@ STATIC mp_obj_t socket_recvfrom(mp_obj_t self_in, mp_obj_t len_in) {
} else {
vstr.len = ret;
vstr.buf[vstr.len] = '\0';
- tuple[0] = mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
+ tuple[0] = mp_obj_new_bytes_from_vstr(&vstr);
}
tuple[1] = netutils_format_inet_addr(ip, port, NETUTILS_LITTLE);
return mp_obj_new_tuple(2, tuple);
@@ -759,13 +759,14 @@ const mp_stream_p_t socket_stream_p = {
.is_text = false,
};
-STATIC const mp_obj_type_t socket_type = {
- { &mp_type_type },
- .name = MP_QSTR_socket,
- .make_new = socket_make_new,
- .protocol = &socket_stream_p,
- .locals_dict = (mp_obj_t)&socket_locals_dict,
-};
+STATIC MP_DEFINE_CONST_OBJ_TYPE(
+ socket_type,
+ MP_QSTR_socket,
+ MP_TYPE_FLAG_NONE,
+ make_new, socket_make_new,
+ protocol, &socket_stream_p,
+ locals_dict, &socket_locals_dict
+ );
/******************************************************************************/
// usocket module
diff --git a/ports/cc3200/mods/modussl.c b/ports/cc3200/mods/modussl.c
index cd2c62dcb82e..118cbd06f8fa 100644
--- a/ports/cc3200/mods/modussl.c
+++ b/ports/cc3200/mods/modussl.c
@@ -60,14 +60,13 @@ STATIC const mp_obj_type_t ssl_socket_type;
// ssl sockets inherit from normal socket, so we take its
// locals and stream methods
-STATIC const mp_obj_type_t ssl_socket_type = {
- { &mp_type_type },
- .name = MP_QSTR_ussl,
- .getiter = NULL,
- .iternext = NULL,
- .protocol = &socket_stream_p,
- .locals_dict = (mp_obj_t)&socket_locals_dict,
-};
+STATIC MP_DEFINE_CONST_OBJ_TYPE(
+ ssl_socket_type,
+ MP_QSTR_ussl,
+ MP_TYPE_FLAG_NONE,
+ protocol, &socket_stream_p,
+ locals_dict, &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) {
STATIC const mp_arg_t allowed_args[] = {
diff --git a/ports/cc3200/mods/modwlan.c b/ports/cc3200/mods/modwlan.c
index 920079b589ae..ca18b34823c0 100644
--- a/ports/cc3200/mods/modwlan.c
+++ b/ports/cc3200/mods/modwlan.c
@@ -641,8 +641,8 @@ STATIC void wlan_set_security (uint8_t auth, const char *key, uint8_t len) {
if (key != NULL) {
memcpy(&wlan_obj.key, key, len);
wlan_obj.key[len] = '\0';
+ _u8 wep_key[32];
if (auth == SL_SEC_TYPE_WEP) {
- _u8 wep_key[32];
wlan_wep_key_unhexlify(key, (char *)&wep_key);
key = (const char *)&wep_key;
len /= 2;
@@ -1285,14 +1285,13 @@ STATIC const mp_rom_map_elem_t wlan_locals_dict_table[] = {
};
STATIC MP_DEFINE_CONST_DICT(wlan_locals_dict, wlan_locals_dict_table);
-const mod_network_nic_type_t mod_network_nic_type_wlan = {
- .base = {
- { &mp_type_type },
- .name = MP_QSTR_WLAN,
- .make_new = wlan_make_new,
- .locals_dict = (mp_obj_t)&wlan_locals_dict,
- },
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ mod_network_nic_type_wlan,
+ MP_QSTR_WLAN,
+ MP_TYPE_FLAG_NONE,
+ make_new, wlan_make_new,
+ locals_dict, &wlan_locals_dict
+ );
STATIC const mp_irq_methods_t wlan_irq_methods = {
.init = wlan_irq,
diff --git a/ports/cc3200/mods/pybadc.c b/ports/cc3200/mods/pybadc.c
index fbdd393cd2ec..74664282560d 100644
--- a/ports/cc3200/mods/pybadc.c
+++ b/ports/cc3200/mods/pybadc.c
@@ -233,13 +233,14 @@ STATIC const mp_rom_map_elem_t adc_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(adc_locals_dict, adc_locals_dict_table);
-const mp_obj_type_t pyb_adc_type = {
- { &mp_type_type },
- .name = MP_QSTR_ADC,
- .print = adc_print,
- .make_new = adc_make_new,
- .locals_dict = (mp_obj_t)&adc_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ pyb_adc_type,
+ MP_QSTR_ADC,
+ MP_TYPE_FLAG_NONE,
+ make_new, adc_make_new,
+ print, adc_print,
+ locals_dict, &adc_locals_dict
+ );
STATIC void adc_channel_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
pyb_adc_channel_obj_t *self = self_in;
@@ -300,10 +301,11 @@ STATIC const mp_rom_map_elem_t adc_channel_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(adc_channel_locals_dict, adc_channel_locals_dict_table);
-STATIC const mp_obj_type_t pyb_adc_channel_type = {
- { &mp_type_type },
- .name = MP_QSTR_ADCChannel,
- .print = adc_channel_print,
- .call = adc_channel_call,
- .locals_dict = (mp_obj_t)&adc_channel_locals_dict,
-};
+STATIC MP_DEFINE_CONST_OBJ_TYPE(
+ pyb_adc_channel_type,
+ MP_QSTR_ADCChannel,
+ MP_TYPE_FLAG_NONE,
+ print, adc_channel_print,
+ call, adc_channel_call,
+ locals_dict, &adc_channel_locals_dict
+ );
diff --git a/ports/cc3200/mods/pybflash.c b/ports/cc3200/mods/pybflash.c
index 9d534608becc..46b7be234f9c 100644
--- a/ports/cc3200/mods/pybflash.c
+++ b/ports/cc3200/mods/pybflash.c
@@ -84,12 +84,13 @@ STATIC const mp_rom_map_elem_t pyb_flash_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(pyb_flash_locals_dict, pyb_flash_locals_dict_table);
-const mp_obj_type_t pyb_flash_type = {
- { &mp_type_type },
- .name = MP_QSTR_Flash,
- .make_new = pyb_flash_make_new,
- .locals_dict = (mp_obj_t)&pyb_flash_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ pyb_flash_type,
+ MP_QSTR_Flash,
+ MP_TYPE_FLAG_NONE,
+ make_new, pyb_flash_make_new,
+ locals_dict, &pyb_flash_locals_dict
+ );
void pyb_flash_init_vfs(fs_user_mount_t *vfs) {
vfs->base.type = &mp_fat_vfs_type;
diff --git a/ports/cc3200/mods/pybi2c.c b/ports/cc3200/mods/pybi2c.c
index 5310176091a9..5d77dc8367c4 100644
--- a/ports/cc3200/mods/pybi2c.c
+++ b/ports/cc3200/mods/pybi2c.c
@@ -392,7 +392,7 @@ STATIC mp_obj_t pyb_i2c_readfrom(size_t n_args, const mp_obj_t *pos_args, mp_map
pyb_i2c_read_into(args, &vstr);
// return the received data
- return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
+ return mp_obj_new_bytes_from_vstr(&vstr);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_i2c_readfrom_obj, 3, pyb_i2c_readfrom);
@@ -456,7 +456,7 @@ STATIC mp_obj_t pyb_i2c_readfrom_mem(size_t n_args, const mp_obj_t *pos_args, mp
vstr_t vstr;
pyb_i2c_readmem_into (args, &vstr);
- return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
+ return mp_obj_new_bytes_from_vstr(&vstr);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_i2c_readfrom_mem_obj, 1, pyb_i2c_readfrom_mem);
@@ -521,10 +521,11 @@ STATIC const mp_rom_map_elem_t pyb_i2c_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(pyb_i2c_locals_dict, pyb_i2c_locals_dict_table);
-const mp_obj_type_t pyb_i2c_type = {
- { &mp_type_type },
- .name = MP_QSTR_I2C,
- .print = pyb_i2c_print,
- .make_new = pyb_i2c_make_new,
- .locals_dict = (mp_obj_t)&pyb_i2c_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ pyb_i2c_type,
+ MP_QSTR_I2C,
+ MP_TYPE_FLAG_NONE,
+ make_new, pyb_i2c_make_new,
+ print, pyb_i2c_print,
+ locals_dict, &pyb_i2c_locals_dict
+ );
diff --git a/ports/cc3200/mods/pybpin.c b/ports/cc3200/mods/pybpin.c
index fd2f032e8d7c..f04ca756540e 100644
--- a/ports/cc3200/mods/pybpin.c
+++ b/ports/cc3200/mods/pybpin.c
@@ -931,14 +931,15 @@ STATIC const mp_rom_map_elem_t pin_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(pin_locals_dict, pin_locals_dict_table);
-const mp_obj_type_t pin_type = {
- { &mp_type_type },
- .name = MP_QSTR_Pin,
- .print = pin_print,
- .make_new = pin_make_new,
- .call = pin_call,
- .locals_dict = (mp_obj_t)&pin_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ pin_type,
+ MP_QSTR_Pin,
+ MP_TYPE_FLAG_NONE,
+ make_new, pin_make_new,
+ print, pin_print,
+ call, pin_call,
+ locals_dict, &pin_locals_dict
+ );
STATIC const mp_irq_methods_t pin_irq_methods = {
.init = pin_irq,
@@ -952,10 +953,11 @@ STATIC void pin_named_pins_obj_print(const mp_print_t *print, mp_obj_t self_in,
mp_printf(print, "", self->name);
}
-const mp_obj_type_t pin_board_pins_obj_type = {
- { &mp_type_type },
- .name = MP_QSTR_board,
- .print = pin_named_pins_obj_print,
- .locals_dict = (mp_obj_t)&pin_board_pins_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ pin_board_pins_obj_type,
+ MP_QSTR_board,
+ MP_TYPE_FLAG_NONE,
+ print, pin_named_pins_obj_print,
+ locals_dict, &pin_board_pins_locals_dict
+ );
diff --git a/ports/cc3200/mods/pybrtc.c b/ports/cc3200/mods/pybrtc.c
index 6c1918831c8c..21e729dbf175 100644
--- a/ports/cc3200/mods/pybrtc.c
+++ b/ports/cc3200/mods/pybrtc.c
@@ -469,12 +469,13 @@ STATIC const mp_rom_map_elem_t pyb_rtc_locals_dict_table[] = {
};
STATIC MP_DEFINE_CONST_DICT(pyb_rtc_locals_dict, pyb_rtc_locals_dict_table);
-const mp_obj_type_t pyb_rtc_type = {
- { &mp_type_type },
- .name = MP_QSTR_RTC,
- .make_new = pyb_rtc_make_new,
- .locals_dict = (mp_obj_t)&pyb_rtc_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ pyb_rtc_type,
+ MP_QSTR_RTC,
+ MP_TYPE_FLAG_NONE,
+ make_new, pyb_rtc_make_new,
+ locals_dict, &pyb_rtc_locals_dict
+ );
STATIC const mp_irq_methods_t pyb_rtc_irq_methods = {
.init = pyb_rtc_irq,
diff --git a/ports/cc3200/mods/pybsd.c b/ports/cc3200/mods/pybsd.c
index 817127634d89..209c3b5a85ec 100644
--- a/ports/cc3200/mods/pybsd.c
+++ b/ports/cc3200/mods/pybsd.c
@@ -212,9 +212,10 @@ STATIC const mp_rom_map_elem_t pyb_sd_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(pyb_sd_locals_dict, pyb_sd_locals_dict_table);
-const mp_obj_type_t pyb_sd_type = {
- { &mp_type_type },
- .name = MP_QSTR_SD,
- .make_new = pyb_sd_make_new,
- .locals_dict = (mp_obj_t)&pyb_sd_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ pyb_sd_type,
+ MP_QSTR_SD,
+ MP_TYPE_FLAG_NONE,
+ make_new, pyb_sd_make_new,
+ locals_dict, &pyb_sd_locals_dict
+ );
diff --git a/ports/cc3200/mods/pybsleep.c b/ports/cc3200/mods/pybsleep.c
index 2d4b1ca8a960..ffb281e6b13d 100644
--- a/ports/cc3200/mods/pybsleep.c
+++ b/ports/cc3200/mods/pybsleep.c
@@ -125,10 +125,11 @@ STATIC pybsleep_data_t pybsleep_data = {NULL, NULL, NULL};
volatile arm_cm4_core_regs_t vault_arm_registers;
STATIC pybsleep_reset_cause_t pybsleep_reset_cause = PYB_SLP_PWRON_RESET;
STATIC pybsleep_wake_reason_t pybsleep_wake_reason = PYB_SLP_WAKED_PWRON;
-STATIC const mp_obj_type_t pyb_sleep_type = {
- { &mp_type_type },
- .name = MP_QSTR_sleep,
-};
+STATIC MP_DEFINE_CONST_OBJ_TYPE(
+ pyb_sleep_type,
+ MP_QSTR_sleep,
+ MP_TYPE_FLAG_NONE
+ );
/******************************************************************************
DECLARE PRIVATE FUNCTIONS
@@ -652,3 +653,4 @@ STATIC bool setup_timer_hibernate_wake (void) {
return false;
}
+MP_REGISTER_ROOT_POINTER(mp_obj_list_t pyb_sleep_obj_list);
diff --git a/ports/cc3200/mods/pybspi.c b/ports/cc3200/mods/pybspi.c
index 61b1a6bd11ee..61086ec2e1d8 100644
--- a/ports/cc3200/mods/pybspi.c
+++ b/ports/cc3200/mods/pybspi.c
@@ -305,7 +305,7 @@ STATIC mp_obj_t pyb_spi_read(size_t n_args, const mp_obj_t *pos_args, mp_map_t *
pybspi_transfer(self, NULL, vstr.buf, vstr.len, &write);
// return the received data
- return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
+ return mp_obj_new_bytes_from_vstr(&vstr);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_spi_read_obj, 1, pyb_spi_read);
@@ -377,10 +377,11 @@ STATIC const mp_rom_map_elem_t pyb_spi_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(pyb_spi_locals_dict, pyb_spi_locals_dict_table);
-const mp_obj_type_t pyb_spi_type = {
- { &mp_type_type },
- .name = MP_QSTR_SPI,
- .print = pyb_spi_print,
- .make_new = pyb_spi_make_new,
- .locals_dict = (mp_obj_t)&pyb_spi_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ pyb_spi_type,
+ MP_QSTR_SPI,
+ MP_TYPE_FLAG_NONE,
+ make_new, pyb_spi_make_new,
+ print, pyb_spi_print,
+ locals_dict, &pyb_spi_locals_dict
+ );
diff --git a/ports/cc3200/mods/pybtimer.c b/ports/cc3200/mods/pybtimer.c
index 55caa6de137b..be365f3c92b2 100644
--- a/ports/cc3200/mods/pybtimer.c
+++ b/ports/cc3200/mods/pybtimer.c
@@ -459,13 +459,14 @@ STATIC const mp_rom_map_elem_t pyb_timer_locals_dict_table[] = {
};
STATIC MP_DEFINE_CONST_DICT(pyb_timer_locals_dict, pyb_timer_locals_dict_table);
-const mp_obj_type_t pyb_timer_type = {
- { &mp_type_type },
- .name = MP_QSTR_Timer,
- .print = pyb_timer_print,
- .make_new = pyb_timer_make_new,
- .locals_dict = (mp_obj_t)&pyb_timer_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ pyb_timer_type,
+ MP_QSTR_Timer,
+ MP_TYPE_FLAG_NONE,
+ make_new, pyb_timer_make_new,
+ print, pyb_timer_print,
+ locals_dict, &pyb_timer_locals_dict
+ );
STATIC const mp_irq_methods_t pyb_timer_channel_irq_methods = {
.init = pyb_timer_channel_irq,
@@ -721,10 +722,12 @@ STATIC const mp_rom_map_elem_t pyb_timer_channel_locals_dict_table[] = {
};
STATIC MP_DEFINE_CONST_DICT(pyb_timer_channel_locals_dict, pyb_timer_channel_locals_dict_table);
-STATIC const mp_obj_type_t pyb_timer_channel_type = {
- { &mp_type_type },
- .name = MP_QSTR_TimerChannel,
- .print = pyb_timer_channel_print,
- .locals_dict = (mp_obj_t)&pyb_timer_channel_locals_dict,
-};
+STATIC MP_DEFINE_CONST_OBJ_TYPE(
+ pyb_timer_channel_type,
+ MP_QSTR_TimerChannel,
+ MP_TYPE_FLAG_NONE,
+ print, pyb_timer_channel_print,
+ locals_dict, &pyb_timer_channel_locals_dict
+ );
+MP_REGISTER_ROOT_POINTER(mp_obj_list_t pyb_timer_channel_obj_list);
diff --git a/ports/cc3200/mods/pybuart.c b/ports/cc3200/mods/pybuart.c
index b8e8cbb682fa..424ca251ec79 100644
--- a/ports/cc3200/mods/pybuart.c
+++ b/ports/cc3200/mods/pybuart.c
@@ -66,6 +66,7 @@
#define PYBUART_TX_MAX_TIMEOUT_MS (5)
#define PYBUART_RX_BUFFER_LEN (256)
+#define PYBUART_TX_BUFFER_LEN (17)
// interrupt triggers
#define UART_TRIGGER_RX_ANY (0x01)
@@ -558,6 +559,17 @@ STATIC mp_obj_t pyb_uart_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_t *
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_uart_irq_obj, 1, pyb_uart_irq);
+STATIC mp_obj_t machine_uart_txdone(mp_obj_t self_in) {
+ pyb_uart_obj_t *self = MP_OBJ_TO_PTR(self_in);
+
+ if (MAP_UARTBusy(self->reg) == false) {
+ return mp_const_true;
+ } else {
+ return mp_const_false;
+ }
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_uart_txdone_obj, machine_uart_txdone);
+
STATIC const mp_rom_map_elem_t pyb_uart_locals_dict_table[] = {
// instance methods
{ MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&pyb_uart_init_obj) },
@@ -565,6 +577,7 @@ STATIC const mp_rom_map_elem_t pyb_uart_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_any), MP_ROM_PTR(&pyb_uart_any_obj) },
{ MP_ROM_QSTR(MP_QSTR_sendbreak), MP_ROM_PTR(&pyb_uart_sendbreak_obj) },
{ MP_ROM_QSTR(MP_QSTR_irq), MP_ROM_PTR(&pyb_uart_irq_obj) },
+ { MP_ROM_QSTR(MP_QSTR_txdone), MP_ROM_PTR(&machine_uart_txdone_obj) },
/// \method read([nbytes])
{ MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) },
@@ -574,6 +587,7 @@ STATIC const mp_rom_map_elem_t pyb_uart_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) },
/// \method write(buf)
{ MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) },
+ { MP_ROM_QSTR(MP_QSTR_flush), MP_ROM_PTR(&mp_stream_flush_obj) },
// class constants
{ MP_ROM_QSTR(MP_QSTR_RX_ANY), MP_ROM_INT(UART_TRIGGER_RX_ANY) },
@@ -635,6 +649,21 @@ STATIC mp_uint_t pyb_uart_ioctl(mp_obj_t self_in, mp_uint_t request, mp_uint_t a
if ((flags & MP_STREAM_POLL_WR) && MAP_UARTSpaceAvail(self->reg)) {
ret |= MP_STREAM_POLL_WR;
}
+ } else if (request == MP_STREAM_FLUSH) {
+ // The timeout is estimated using the buffer size and the baudrate.
+ // Take the worst case assumptions at 13 bit symbol size times 2.
+ uint64_t timeout = mp_hal_ticks_ms() +
+ (PYBUART_TX_BUFFER_LEN) * 13000 * 2 / self->baudrate;
+
+ do {
+ if (machine_uart_txdone((mp_obj_t)self) == mp_const_true) {
+ return 0;
+ }
+ MICROPY_EVENT_POLL_HOOK
+ } while (mp_hal_ticks_ms() < timeout);
+
+ *errcode = MP_ETIMEDOUT;
+ ret = MP_STREAM_ERROR;;
} else {
*errcode = MP_EINVAL;
ret = MP_STREAM_ERROR;
@@ -656,13 +685,14 @@ STATIC const mp_irq_methods_t uart_irq_methods = {
.flags = uart_irq_flags
};
-const mp_obj_type_t pyb_uart_type = {
- { &mp_type_type },
- .name = MP_QSTR_UART,
- .print = pyb_uart_print,
- .make_new = pyb_uart_make_new,
- .getiter = mp_identity_getiter,
- .iternext = mp_stream_unbuffered_iter,
- .protocol = &uart_stream_p,
- .locals_dict = (mp_obj_t)&pyb_uart_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ pyb_uart_type,
+ MP_QSTR_UART,
+ MP_TYPE_FLAG_ITER_IS_STREAM,
+ make_new, pyb_uart_make_new,
+ print, pyb_uart_print,
+ protocol, &uart_stream_p,
+ locals_dict, &pyb_uart_locals_dict
+ );
+
+MP_REGISTER_ROOT_POINTER(struct _pyb_uart_obj_t *pyb_uart_objs[2]);
diff --git a/ports/cc3200/mods/pybwdt.c b/ports/cc3200/mods/pybwdt.c
index 8db096d6b5fc..589f53cf1275 100644
--- a/ports/cc3200/mods/pybwdt.c
+++ b/ports/cc3200/mods/pybwdt.c
@@ -150,10 +150,11 @@ STATIC const mp_rom_map_elem_t pybwdt_locals_dict_table[] = {
};
STATIC MP_DEFINE_CONST_DICT(pybwdt_locals_dict, pybwdt_locals_dict_table);
-const mp_obj_type_t pyb_wdt_type = {
- { &mp_type_type },
- .name = MP_QSTR_WDT,
- .make_new = pyb_wdt_make_new,
- .locals_dict = (mp_obj_t)&pybwdt_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ pyb_wdt_type,
+ MP_QSTR_WDT,
+ MP_TYPE_FLAG_NONE,
+ make_new, pyb_wdt_make_new,
+ locals_dict, &pybwdt_locals_dict
+ );
diff --git a/ports/cc3200/mpconfigport.h b/ports/cc3200/mpconfigport.h
index 58ec80a9f5cf..93fc291c1a4c 100644
--- a/ports/cc3200/mpconfigport.h
+++ b/ports/cc3200/mpconfigport.h
@@ -78,6 +78,7 @@
#define MICROPY_VFS_FAT (1)
#define MICROPY_PY_ASYNC_AWAIT (0)
#define MICROPY_PY_ALL_SPECIAL_METHODS (1)
+#define MICROPY_PY_BUILTINS_BYTES_HEX (1)
#define MICROPY_PY_BUILTINS_INPUT (1)
#define MICROPY_PY_BUILTINS_HELP (1)
#define MICROPY_PY_BUILTINS_HELP_TEXT cc3200_help_text
@@ -104,7 +105,6 @@
#define MICROPY_PY_SYS_STDFILES (1)
#define MICROPY_PY_CMATH (0)
#define MICROPY_PY_IO (1)
-#define MICROPY_PY_IO_FILEIO (1)
#define MICROPY_PY_UERRNO (1)
#define MICROPY_PY_UERRNO_ERRORCODE (0)
#define MICROPY_PY_THREAD (1)
@@ -131,26 +131,11 @@
X(EINVAL) \
X(ETIMEDOUT) \
-// TODO these should be generic, not bound to fatfs
-#define mp_type_fileio mp_type_vfs_fat_fileio
-#define mp_type_textio mp_type_vfs_fat_textio
-
// extra constants
#define MICROPY_PORT_CONSTANTS \
{ MP_ROM_QSTR(MP_QSTR_umachine), MP_ROM_PTR(&mp_module_machine) }, \
-// vm state and root pointers for the gc
#define MP_STATE_PORT MP_STATE_VM
-#define MICROPY_PORT_ROOT_POINTERS \
- const char *readline_hist[8]; \
- mp_obj_t mp_const_user_interrupt; \
- mp_obj_t machine_config_main; \
- mp_obj_list_t pyb_sleep_obj_list; \
- mp_obj_list_t mp_irq_obj_list; \
- mp_obj_list_t pyb_timer_channel_obj_list; \
- struct _pyb_uart_obj_t *pyb_uart_objs[2]; \
- struct _os_term_dup_obj_t *os_term_dup_obj; \
-
// type definitions for the specific machine
#define MICROPY_MAKE_POINTER_CALLABLE(p) ((void *)((mp_uint_t)(p) | 1))
diff --git a/ports/cc3200/tools/update-wipy.py b/ports/cc3200/tools/update-wipy.py
index e0e1266f7a37..8008b3860535 100644
--- a/ports/cc3200/tools/update-wipy.py
+++ b/ports/cc3200/tools/update-wipy.py
@@ -45,7 +45,7 @@ def transfer_file(args):
if "250" in ftp.cwd("/flash"):
if not ftp_directory_exists(ftp, "sys"):
print("/flash/sys directory does not exist")
- if not "550" in ftp.mkd("sys"):
+ if "550" not in ftp.mkd("sys"):
print("/flash/sys directory created")
else:
print("Error: cannot create /flash/sys directory")
diff --git a/ports/embed/README.md b/ports/embed/README.md
new file mode 100644
index 000000000000..556cfc749d37
--- /dev/null
+++ b/ports/embed/README.md
@@ -0,0 +1,18 @@
+MicroPython embed port
+======================
+
+This is a port of MicroPython that outputs a set of .c and .h files for embedding
+into a wider project. This port essentially targets the C language, instead of a
+particular hardware architecture or platform.
+
+To use this port in a project there are three main steps:
+
+1. Provide configuration for the project via an `mpconfigport.h` file.
+
+2. Build this embed port against that configuration, using the provided `embed.mk`.
+ The output is a set of self-contained source files for building MicroPython.
+ These files can be placed outside this repository.
+
+3. Build the project. This requires compiling all .c files from the above step.
+
+See `examples/embedding` for an example.
diff --git a/ports/embed/embed.mk b/ports/embed/embed.mk
new file mode 100644
index 000000000000..7fb344d70492
--- /dev/null
+++ b/ports/embed/embed.mk
@@ -0,0 +1,65 @@
+# This file is part of the MicroPython project, http://micropython.org/
+# The MIT License (MIT)
+# Copyright (c) 2022-2023 Damien P. George
+#
+# This file is intended to be included by a Makefile in a custom project.
+
+# Set the build output directory for the generated files.
+BUILD = build-embed
+
+# Include the core environment definitions; this will set $(TOP).
+include $(MICROPYTHON_TOP)/py/mkenv.mk
+
+# Include py core make definitions.
+include $(TOP)/py/py.mk
+
+# Set the location of the MicroPython embed port.
+MICROPYTHON_EMBED_PORT = $(MICROPYTHON_TOP)/ports/embed
+
+# Set default makefile-level MicroPython feature configurations.
+MICROPY_ROM_TEXT_COMPRESSION ?= 0
+
+# Set CFLAGS for the MicroPython build.
+CFLAGS += -I. -I$(TOP) -I$(BUILD) -I$(MICROPYTHON_EMBED_PORT)
+CFLAGS += -Wall -Werror -std=c99
+
+# Define the required generated header files.
+GENHDR_OUTPUT = $(addprefix $(BUILD)/genhdr/, \
+ moduledefs.h \
+ mpversion.h \
+ qstrdefs.generated.h \
+ root_pointers.h \
+ )
+
+# Define the top-level target, the generated output files.
+.PHONY: all
+all: micropython-embed-package
+
+clean: clean-micropython-embed-package
+
+.PHONY: clean-micropython-embed-package
+clean-micropython-embed-package:
+ $(RM) -rf $(PACKAGE_DIR)
+
+PACKAGE_DIR ?= micropython_embed
+PACKAGE_DIR_LIST = $(addprefix $(PACKAGE_DIR)/,py extmod shared/runtime genhdr port)
+
+.PHONY: micropython-embed-package
+micropython-embed-package: $(GENHDR_OUTPUT)
+ $(ECHO) "Generate micropython_embed output:"
+ $(Q)$(RM) -rf $(PACKAGE_DIR_LIST)
+ $(Q)$(MKDIR) -p $(PACKAGE_DIR_LIST)
+ $(ECHO) "- py"
+ $(Q)$(CP) $(TOP)/py/*.[ch] $(PACKAGE_DIR)/py
+ $(ECHO) "- extmod"
+ $(Q)$(CP) $(TOP)/extmod/moduplatform.h $(PACKAGE_DIR)/extmod
+ $(ECHO) "- shared"
+ $(Q)$(CP) $(TOP)/shared/runtime/gchelper.h $(PACKAGE_DIR)/shared/runtime
+ $(Q)$(CP) $(TOP)/shared/runtime/gchelper_generic.c $(PACKAGE_DIR)/shared/runtime
+ $(ECHO) "- genhdr"
+ $(Q)$(CP) $(GENHDR_OUTPUT) $(PACKAGE_DIR)/genhdr
+ $(ECHO) "- port"
+ $(Q)$(CP) $(MICROPYTHON_EMBED_PORT)/port/*.[ch] $(PACKAGE_DIR)/port
+
+# Include remaining core make rules.
+include $(TOP)/py/mkrules.mk
diff --git a/ports/embed/port/embed_util.c b/ports/embed/port/embed_util.c
new file mode 100644
index 000000000000..14f50897705e
--- /dev/null
+++ b/ports/embed/port/embed_util.c
@@ -0,0 +1,108 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2022-2023 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/compile.h"
+#include "py/gc.h"
+#include "py/persistentcode.h"
+#include "py/runtime.h"
+#include "py/stackctrl.h"
+#include "shared/runtime/gchelper.h"
+#include "port/micropython_embed.h"
+
+// Initialise the runtime.
+void mp_embed_init(void *gc_heap, size_t gc_heap_size) {
+ mp_stack_ctrl_init();
+ gc_init(gc_heap, (uint8_t *)gc_heap + gc_heap_size);
+ mp_init();
+}
+
+#if MICROPY_ENABLE_COMPILER
+// Compile and execute the given source script (Python text).
+void mp_embed_exec_str(const char *src) {
+ nlr_buf_t nlr;
+ if (nlr_push(&nlr) == 0) {
+ // Compile, parse and execute the given string.
+ mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, src, strlen(src), 0);
+ qstr source_name = lex->source_name;
+ mp_parse_tree_t parse_tree = mp_parse(lex, MP_PARSE_FILE_INPUT);
+ mp_obj_t module_fun = mp_compile(&parse_tree, source_name, true);
+ mp_call_function_0(module_fun);
+ nlr_pop();
+ } else {
+ // Uncaught exception: print it out.
+ mp_obj_print_exception(&mp_plat_print, (mp_obj_t)nlr.ret_val);
+ }
+}
+#endif
+
+#if MICROPY_PERSISTENT_CODE_LOAD
+void mp_embed_exec_mpy(const uint8_t *mpy, size_t len) {
+ nlr_buf_t nlr;
+ if (nlr_push(&nlr) == 0) {
+ // Execute the given .mpy data.
+ mp_module_context_t *ctx = m_new_obj(mp_module_context_t);
+ ctx->module.globals = mp_globals_get();
+ mp_compiled_module_t cm;
+ cm.context = ctx;
+ mp_raw_code_load_mem(mpy, len, &cm);
+ mp_obj_t f = mp_make_function_from_raw_code(cm.rc, ctx, MP_OBJ_NULL);
+ mp_call_function_0(f);
+ nlr_pop();
+ } else {
+ // Uncaught exception: print it out.
+ mp_obj_print_exception(&mp_plat_print, (mp_obj_t)nlr.ret_val);
+ }
+}
+#endif
+
+// Deinitialise the runtime.
+void mp_embed_deinit(void) {
+ mp_deinit();
+}
+
+#if MICROPY_ENABLE_GC
+// Run a garbage collection cycle.
+void gc_collect(void) {
+ gc_collect_start();
+ gc_helper_collect_regs_and_stack();
+ gc_collect_end();
+}
+#endif
+
+// Called if an exception is raised outside all C exception-catching handlers.
+void nlr_jump_fail(void *val) {
+ for (;;) {
+ }
+}
+
+#ifndef NDEBUG
+// Used when debugging is enabled.
+void __assert_func(const char *file, int line, const char *func, const char *expr) {
+ for (;;) {
+ }
+}
+#endif
diff --git a/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/pins.h b/ports/embed/port/micropython_embed.h
similarity index 69%
rename from ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/pins.h
rename to ports/embed/port/micropython_embed.h
index 45bee6167837..bf55d9b2b445 100644
--- a/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/pins.h
+++ b/ports/embed/port/micropython_embed.h
@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2021 Peter van der Burg
+ * Copyright (c) 2022-2023 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
@@ -22,21 +22,20 @@
* 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.
- *
- * Used by machine_pin.c & board specific pins.c. Holds Board/MCU specific Pin
- * allocations.
*/
+#ifndef MICROPY_INCLUDED_MICROPYTHON_EMBED_H
+#define MICROPY_INCLUDED_MICROPYTHON_EMBED_H
+
+#include
+#include
+
+void mp_embed_init(void *gc_heap, size_t gc_heap_size);
+void mp_embed_deinit(void);
-typedef struct _machine_pin_obj_t {
- mp_obj_base_t base;
- uint32_t id;
-} machine_pin_obj_t;
+// Only available if MICROPY_ENABLE_COMPILER is enabled.
+void mp_embed_exec_str(const char *src);
-typedef struct _machine_led_obj_t {
- mp_obj_base_t base;
- uint32_t id;
-} machine_led_obj_t;
+// Only available if MICROPY_PERSISTENT_CODE_LOAD is enabled.
+void mp_embed_exec_mpy(const uint8_t *mpy, size_t len);
-// MUST explicitly hold array # of rows, else machine_pin.c wont compile.
-extern const machine_pin_obj_t machine_pin_obj[20];
-extern const machine_led_obj_t machine_led_obj[1];
+#endif // MICROPY_INCLUDED_MICROPYTHON_EMBED_H
diff --git a/ports/unix/variants/fast/mpconfigvariant.h b/ports/embed/port/mpconfigport_common.h
similarity index 73%
rename from ports/unix/variants/fast/mpconfigvariant.h
rename to ports/embed/port/mpconfigport_common.h
index 8a531b056ab7..69216a758268 100644
--- a/ports/unix/variants/fast/mpconfigvariant.h
+++ b/ports/embed/port/mpconfigport_common.h
@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2013, 2014 Damien P. George
+ * Copyright (c) 2022-2023 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
@@ -24,11 +24,15 @@
* THE SOFTWARE.
*/
-// This config file is intended to configure artificially fast uPy build for
-// synthetic benchmarking, at the expense of features supported and memory
-// usage. This config is not intended to be used in production.
+#include
-#define MICROPY_PY___FILE__ (0)
-// 91 is a magic number proposed by @dpgeorge, which make pystone run ~ at tie
-// with CPython 3.4.
-#define MICROPY_MODULE_DICT_SIZE (91)
+// Type definitions for the specific machine
+
+typedef intptr_t mp_int_t; // must be pointer size
+typedef uintptr_t mp_uint_t; // must be pointer size
+typedef long mp_off_t;
+
+// Need to provide a declaration/definition of alloca()
+#include
+
+#define MICROPY_MPHALPORT_H "port/mphalport.h"
diff --git a/ports/unix/variants/freedos/mpconfigvariant.h b/ports/embed/port/mphalport.c
similarity index 78%
rename from ports/unix/variants/freedos/mpconfigvariant.h
rename to ports/embed/port/mphalport.c
index 562c783ca35f..8e76a8e22e1b 100644
--- a/ports/unix/variants/freedos/mpconfigvariant.h
+++ b/ports/embed/port/mphalport.c
@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2015 Damien P. George
+ * Copyright (c) 2022-2023 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
@@ -24,15 +24,10 @@
* THE SOFTWARE.
*/
-// options to control how MicroPython is built
+#include
+#include "py/mphal.h"
-#define MICROPY_PY_USELECT_POSIX (0)
-
-#define MICROPY_STREAMS_NON_BLOCK (0)
-
-#define MICROPY_PY_SYS_PLATFORM "freedos"
-
-// djgpp dirent struct does not have d_ino field
-#undef _DIRENT_HAVE_D_INO
-
-#define MICROPY_USE_INTERNAL_ERRNO (1)
+// Send string of given length to stdout, converting \n to \r\n.
+void mp_hal_stdout_tx_strn_cooked(const char *str, size_t len) {
+ printf("%.*s", (int)len, str);
+}
diff --git a/ports/embed/port/mphalport.h b/ports/embed/port/mphalport.h
new file mode 100644
index 000000000000..49928e154da3
--- /dev/null
+++ b/ports/embed/port/mphalport.h
@@ -0,0 +1,2 @@
+// Define so there's no dependency on extmod/virtpin.h
+#define mp_hal_pin_obj_t
diff --git a/ports/esp32/Makefile b/ports/esp32/Makefile
index c8ca9262c8f1..0b33fa6e5a73 100644
--- a/ports/esp32/Makefile
+++ b/ports/esp32/Makefile
@@ -2,8 +2,20 @@
#
# This is a simple, convenience wrapper around idf.py (which uses cmake).
-# Select the board to build for, defaulting to GENERIC.
+# Select the board to build for:
+ifdef BOARD_DIR
+# Custom board path - remove trailing slash and get the final component of
+# the path as the board name.
+BOARD ?= $(notdir $(BOARD_DIR:/=))
+else
+# If not given on the command line, then default to GENERIC.
BOARD ?= GENERIC
+BOARD_DIR ?= boards/$(BOARD)
+endif
+
+ifeq ($(wildcard $(BOARD_DIR)/.),)
+$(error Invalid BOARD specified: $(BOARD_DIR))
+endif
# If the build directory is not given, make it reflect the board name.
BUILD ?= build-$(BOARD)
@@ -14,7 +26,11 @@ BAUD ?= 460800
PYTHON ?= python3
-GIT_SUBMODULES = lib/berkeley-db-1.xx
+# Would be good to use cmake to discover submodules (see how rp2/Makefile does
+# it), but on ESP32 the same trick doesn't work because "idf.py build" fails
+# on berkeley-db dependency before printing out the submodule list.
+# For now just force the submodule dependencies here.
+GIT_SUBMODULES += lib/berkeley-db-1.xx lib/micropython-lib
.PHONY: all clean deploy erase submodules FORCE
@@ -24,14 +40,16 @@ ifdef USER_C_MODULES
CMAKE_ARGS += -DUSER_C_MODULES=${USER_C_MODULES}
endif
-IDFPY_FLAGS += -D MICROPY_BOARD=$(BOARD) -B $(BUILD) $(CMAKE_ARGS)
+IDFPY_FLAGS += -D MICROPY_BOARD=$(BOARD) -D MICROPY_BOARD_DIR=$(abspath $(BOARD_DIR)) -B $(BUILD) $(CMAKE_ARGS)
ifdef FROZEN_MANIFEST
IDFPY_FLAGS += -D MICROPY_FROZEN_MANIFEST=$(FROZEN_MANIFEST)
endif
+HELP_BUILD_ERROR ?= "See \033[1;31mhttps://github.com/micropython/micropython/wiki/Build-Troubleshooting\033[0m"
+
all:
- idf.py $(IDFPY_FLAGS) build
+ idf.py $(IDFPY_FLAGS) build || (echo -e $(HELP_BUILD_ERROR); false)
@$(PYTHON) makeimg.py \
$(BUILD)/sdkconfig \
$(BUILD)/bootloader/bootloader.bin \
@@ -52,4 +70,4 @@ erase:
idf.py $(IDFPY_FLAGS) -p $(PORT) -b $(BAUD) erase_flash
submodules:
- git submodule update --init $(addprefix ../../,$(GIT_SUBMODULES))
+ $(MAKE) -f ../../py/mkrules.mk GIT_SUBMODULES="$(GIT_SUBMODULES)" submodules
diff --git a/ports/esp32/boards/GENERIC_S3_SPIRAM/mpconfigboard.cmake b/ports/esp32/boards/GENERIC_S3_SPIRAM/mpconfigboard.cmake
index b7351b90fe8e..e0b92dcd2640 100644
--- a/ports/esp32/boards/GENERIC_S3_SPIRAM/mpconfigboard.cmake
+++ b/ports/esp32/boards/GENERIC_S3_SPIRAM/mpconfigboard.cmake
@@ -3,6 +3,7 @@ set(IDF_TARGET esp32s3)
set(SDKCONFIG_DEFAULTS
boards/sdkconfig.base
boards/sdkconfig.usb
+ boards/sdkconfig.ble
boards/sdkconfig.spiram_sx
boards/GENERIC_S3_SPIRAM/sdkconfig.board
)
diff --git a/ports/esp32/boards/GENERIC_S3_SPIRAM/mpconfigboard.h b/ports/esp32/boards/GENERIC_S3_SPIRAM/mpconfigboard.h
index f9126c98d76e..1a8560a2d7ea 100644
--- a/ports/esp32/boards/GENERIC_S3_SPIRAM/mpconfigboard.h
+++ b/ports/esp32/boards/GENERIC_S3_SPIRAM/mpconfigboard.h
@@ -1,7 +1,6 @@
#define MICROPY_HW_BOARD_NAME "ESP32S3 module (spiram)"
#define MICROPY_HW_MCU_NAME "ESP32S3"
-#define MICROPY_PY_BLUETOOTH (0)
#define MICROPY_PY_MACHINE_DAC (0)
// Enable UART REPL for modules that have an external USB-UART and don't use native USB.
diff --git a/ports/esp32/boards/GENERIC_S3_SPIRAM_OCT/board.json b/ports/esp32/boards/GENERIC_S3_SPIRAM_OCT/board.json
new file mode 100644
index 000000000000..f3ca177ef974
--- /dev/null
+++ b/ports/esp32/boards/GENERIC_S3_SPIRAM_OCT/board.json
@@ -0,0 +1,18 @@
+{
+ "deploy": [
+ "../deploy_s3.md"
+ ],
+ "docs": "",
+ "features": [
+ "BLE",
+ "WiFi"
+ ],
+ "images": [
+ "generic_s3.jpg"
+ ],
+ "mcu": "esp32s3",
+ "product": "Generic ESP32-S3 (SPIRAM Octal)",
+ "thumbnail": "",
+ "url": "https://www.espressif.com/en/products/modules",
+ "vendor": "Espressif"
+}
diff --git a/ports/esp32/boards/GENERIC_S3_SPIRAM_OCT/mpconfigboard.cmake b/ports/esp32/boards/GENERIC_S3_SPIRAM_OCT/mpconfigboard.cmake
new file mode 100644
index 000000000000..7a767c49d403
--- /dev/null
+++ b/ports/esp32/boards/GENERIC_S3_SPIRAM_OCT/mpconfigboard.cmake
@@ -0,0 +1,11 @@
+set(IDF_TARGET esp32s3)
+
+set(SDKCONFIG_DEFAULTS
+ boards/sdkconfig.base
+ boards/sdkconfig.usb
+ boards/sdkconfig.ble
+ boards/sdkconfig.240mhz
+ boards/sdkconfig.spiram_sx
+ boards/sdkconfig.spiram_oct
+ boards/GENERIC_S3_SPIRAM_OCT/sdkconfig.board
+)
diff --git a/ports/esp32/boards/GENERIC_S3_SPIRAM_OCT/mpconfigboard.h b/ports/esp32/boards/GENERIC_S3_SPIRAM_OCT/mpconfigboard.h
new file mode 100644
index 000000000000..88f6835c9420
--- /dev/null
+++ b/ports/esp32/boards/GENERIC_S3_SPIRAM_OCT/mpconfigboard.h
@@ -0,0 +1,10 @@
+#define MICROPY_HW_BOARD_NAME "ESP32S3 module (spiram octal)"
+#define MICROPY_HW_MCU_NAME "ESP32S3"
+
+#define MICROPY_PY_MACHINE_DAC (0)
+
+// Enable UART REPL for modules that have an external USB-UART and don't use native USB.
+#define MICROPY_HW_ENABLE_UART_REPL (1)
+
+#define MICROPY_HW_I2C0_SCL (9)
+#define MICROPY_HW_I2C0_SDA (8)
diff --git a/ports/esp32/boards/GENERIC_S3_SPIRAM_OCT/sdkconfig.board b/ports/esp32/boards/GENERIC_S3_SPIRAM_OCT/sdkconfig.board
new file mode 100644
index 000000000000..c9726d4232ed
--- /dev/null
+++ b/ports/esp32/boards/GENERIC_S3_SPIRAM_OCT/sdkconfig.board
@@ -0,0 +1,12 @@
+CONFIG_FLASHMODE_QIO=y
+CONFIG_ESPTOOLPY_FLASHFREQ_80M=y
+CONFIG_ESPTOOLPY_FLASHSIZE_DETECT=y
+CONFIG_ESPTOOLPY_AFTER_NORESET=y
+
+CONFIG_SPIRAM_MEMTEST=
+
+CONFIG_ESPTOOLPY_FLASHSIZE_4MB=
+CONFIG_ESPTOOLPY_FLASHSIZE_8MB=y
+CONFIG_ESPTOOLPY_FLASHSIZE_16MB=
+CONFIG_PARTITION_TABLE_CUSTOM=y
+CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions-8MiB.csv"
diff --git a/ports/esp32/boards/GENERIC_UNICORE/board.json b/ports/esp32/boards/GENERIC_UNICORE/board.json
new file mode 100644
index 000000000000..8fed71a018aa
--- /dev/null
+++ b/ports/esp32/boards/GENERIC_UNICORE/board.json
@@ -0,0 +1,19 @@
+{
+ "deploy": [
+ "../deploy.md"
+ ],
+ "docs": "",
+ "features": [
+ "BLE",
+ "WiFi"
+ ],
+ "id": "esp32-unicore",
+ "images": [
+ "generic_unicore.jpg"
+ ],
+ "mcu": "esp32",
+ "product": "ESP32 Unicore",
+ "thumbnail": "",
+ "url": "https://www.espressif.com/en/products/modules",
+ "vendor": "Espressif"
+}
diff --git a/ports/esp32/boards/GENERIC_UNICORE/board.md b/ports/esp32/boards/GENERIC_UNICORE/board.md
new file mode 100644
index 000000000000..b41c167498c7
--- /dev/null
+++ b/ports/esp32/boards/GENERIC_UNICORE/board.md
@@ -0,0 +1 @@
+The following files are daily firmware for single-core ESP32-based boards without external SPIRAM.
diff --git a/ports/esp32/boards/GENERIC_UNICORE/mpconfigboard.cmake b/ports/esp32/boards/GENERIC_UNICORE/mpconfigboard.cmake
new file mode 100644
index 000000000000..2f34688c8c47
--- /dev/null
+++ b/ports/esp32/boards/GENERIC_UNICORE/mpconfigboard.cmake
@@ -0,0 +1,5 @@
+set(SDKCONFIG_DEFAULTS
+ boards/sdkconfig.base
+ boards/sdkconfig.ble
+ boards/GENERIC_UNICORE/sdkconfig.board
+)
diff --git a/ports/esp32/boards/GENERIC_UNICORE/mpconfigboard.h b/ports/esp32/boards/GENERIC_UNICORE/mpconfigboard.h
new file mode 100644
index 000000000000..5d0624b9c3f9
--- /dev/null
+++ b/ports/esp32/boards/GENERIC_UNICORE/mpconfigboard.h
@@ -0,0 +1,2 @@
+#define MICROPY_HW_BOARD_NAME "ESP32 Unicore module"
+#define MICROPY_HW_MCU_NAME "ESP32-UNICORE"
diff --git a/ports/esp32/boards/GENERIC_UNICORE/sdkconfig.board b/ports/esp32/boards/GENERIC_UNICORE/sdkconfig.board
new file mode 100644
index 000000000000..f0b0b5e03dd4
--- /dev/null
+++ b/ports/esp32/boards/GENERIC_UNICORE/sdkconfig.board
@@ -0,0 +1 @@
+CONFIG_FREERTOS_UNICORE=y
diff --git a/ports/esp32/boards/LILYGO_TTGO_LORA32/manifest.py b/ports/esp32/boards/LILYGO_TTGO_LORA32/manifest.py
index 0709f8597c07..e2cd6b3d0151 100644
--- a/ports/esp32/boards/LILYGO_TTGO_LORA32/manifest.py
+++ b/ports/esp32/boards/LILYGO_TTGO_LORA32/manifest.py
@@ -1,4 +1,3 @@
include("$(PORT_DIR)/boards/manifest.py")
freeze("modules")
-
-freeze("$(MPY_DIR)/drivers/display", "ssd1306.py")
+require("ssd1306")
diff --git a/ports/esp32/boards/LILYGO_TTGO_LORA32/mpconfigboard.h b/ports/esp32/boards/LILYGO_TTGO_LORA32/mpconfigboard.h
index 1c7b6fd55767..6be22dd0ffc4 100644
--- a/ports/esp32/boards/LILYGO_TTGO_LORA32/mpconfigboard.h
+++ b/ports/esp32/boards/LILYGO_TTGO_LORA32/mpconfigboard.h
@@ -1,2 +1,3 @@
#define MICROPY_HW_BOARD_NAME "LILYGO TTGO LoRa32"
#define MICROPY_HW_MCU_NAME "ESP32"
+#define MICROPY_PY_NETWORK_HOSTNAME_DEFAULT "mpy-ttgo-lora32"
diff --git a/ports/esp32/boards/LOLIN_C3_MINI/mpconfigboard.h b/ports/esp32/boards/LOLIN_C3_MINI/mpconfigboard.h
index 5872bdc8ae5e..12fd285da175 100644
--- a/ports/esp32/boards/LOLIN_C3_MINI/mpconfigboard.h
+++ b/ports/esp32/boards/LOLIN_C3_MINI/mpconfigboard.h
@@ -1,5 +1,6 @@
#define MICROPY_HW_BOARD_NAME "LOLIN_C3_MINI"
#define MICROPY_HW_MCU_NAME "ESP32-C3FH4"
+#define MICROPY_PY_NETWORK_HOSTNAME_DEFAULT "mpy-c3-mini"
#define MICROPY_HW_ENABLE_SDCARD (0)
#define MICROPY_PY_MACHINE_DAC (0)
diff --git a/ports/esp32/boards/LOLIN_S2_MINI/mpconfigboard.h b/ports/esp32/boards/LOLIN_S2_MINI/mpconfigboard.h
index e0ef10d1db92..9776b7b478aa 100644
--- a/ports/esp32/boards/LOLIN_S2_MINI/mpconfigboard.h
+++ b/ports/esp32/boards/LOLIN_S2_MINI/mpconfigboard.h
@@ -1,5 +1,6 @@
#define MICROPY_HW_BOARD_NAME "LOLIN_S2_MINI"
#define MICROPY_HW_MCU_NAME "ESP32-S2FN4R2"
+#define MICROPY_PY_NETWORK_HOSTNAME_DEFAULT "mpy-s2-mini"
#define MICROPY_PY_BLUETOOTH (0)
#define MICROPY_HW_ENABLE_SDCARD (0)
diff --git a/ports/esp32/boards/LOLIN_S2_PICO/manifest.py b/ports/esp32/boards/LOLIN_S2_PICO/manifest.py
index 98d4247c607a..9ac8ade8275b 100644
--- a/ports/esp32/boards/LOLIN_S2_PICO/manifest.py
+++ b/ports/esp32/boards/LOLIN_S2_PICO/manifest.py
@@ -1,4 +1,3 @@
include("$(PORT_DIR)/boards/manifest.py")
freeze("./modules")
-
-freeze("$(MPY_DIR)/drivers/display", "ssd1306.py")
+require("ssd1306")
diff --git a/ports/esp32/boards/LOLIN_S2_PICO/mpconfigboard.h b/ports/esp32/boards/LOLIN_S2_PICO/mpconfigboard.h
index 549dd9847c7f..9241280dec6a 100644
--- a/ports/esp32/boards/LOLIN_S2_PICO/mpconfigboard.h
+++ b/ports/esp32/boards/LOLIN_S2_PICO/mpconfigboard.h
@@ -1,5 +1,6 @@
#define MICROPY_HW_BOARD_NAME "LOLIN_S2_PICO"
#define MICROPY_HW_MCU_NAME "ESP32-S2FN4R2"
+#define MICROPY_PY_NETWORK_HOSTNAME_DEFAULT "mpy-s2-pico"
#define MICROPY_PY_BLUETOOTH (0)
#define MICROPY_HW_ENABLE_SDCARD (0)
diff --git a/ports/esp32/boards/M5STACK_ATOM/mpconfigboard.h b/ports/esp32/boards/M5STACK_ATOM/mpconfigboard.h
index 4270b19caf96..18a59b15a50a 100644
--- a/ports/esp32/boards/M5STACK_ATOM/mpconfigboard.h
+++ b/ports/esp32/boards/M5STACK_ATOM/mpconfigboard.h
@@ -1,2 +1,3 @@
#define MICROPY_HW_BOARD_NAME "M5Stack ATOM"
#define MICROPY_HW_MCU_NAME "ESP32-PICO-D4"
+#define MICROPY_PY_NETWORK_HOSTNAME_DEFAULT "m5stack-atom"
diff --git a/ports/esp32/boards/OLIMEX_ESP32_POE/board.json b/ports/esp32/boards/OLIMEX_ESP32_POE/board.json
new file mode 100644
index 000000000000..84b6680d591b
--- /dev/null
+++ b/ports/esp32/boards/OLIMEX_ESP32_POE/board.json
@@ -0,0 +1,23 @@
+{
+ "deploy": [
+ "../deploy.md"
+ ],
+ "docs": "",
+ "features": [
+ "BLE",
+ "WiFi",
+ "MicroSD",
+ "Battery Charging",
+ "Ethernet",
+ "PoE",
+ "Breadboard friendly"
+ ],
+ "images": [
+ "ESP32-POE-ISO-1.jpg"
+ ],
+ "mcu": "esp32",
+ "product": "Olimex ESP32 POE",
+ "thumbnail": "",
+ "url": "https://www.olimex.com/",
+ "vendor": "OLIMEX"
+}
diff --git a/ports/esp32/boards/OLIMEX_ESP32_POE/board.md b/ports/esp32/boards/OLIMEX_ESP32_POE/board.md
new file mode 100644
index 000000000000..1e2dbb744a0e
--- /dev/null
+++ b/ports/esp32/boards/OLIMEX_ESP32_POE/board.md
@@ -0,0 +1,4 @@
+The following files are daily firmware for Olimex ESP32 boards with Ethernet.
+They match the boards ESP32 ETH-PoE, ESP32 ETH-PoE-ISO and ESP32 Gateway.
+
+This firmware is compiled using ESP-IDF v4.x.
diff --git a/ports/esp32/boards/OLIMEX_ESP32_POE/mpconfigboard.cmake b/ports/esp32/boards/OLIMEX_ESP32_POE/mpconfigboard.cmake
new file mode 100644
index 000000000000..c460b07d5efa
--- /dev/null
+++ b/ports/esp32/boards/OLIMEX_ESP32_POE/mpconfigboard.cmake
@@ -0,0 +1,5 @@
+set(SDKCONFIG_DEFAULTS
+ boards/sdkconfig.base
+ boards/sdkconfig.ble
+ boards/OLIMEX_ESP32_POE/sdkconfig.board
+)
diff --git a/ports/esp32/boards/OLIMEX_ESP32_POE/mpconfigboard.h b/ports/esp32/boards/OLIMEX_ESP32_POE/mpconfigboard.h
new file mode 100644
index 000000000000..c8458e35fa0d
--- /dev/null
+++ b/ports/esp32/boards/OLIMEX_ESP32_POE/mpconfigboard.h
@@ -0,0 +1,2 @@
+#define MICROPY_HW_BOARD_NAME "Olimex ESP32 ETH"
+#define MICROPY_HW_MCU_NAME "ESP32"
diff --git a/ports/esp32/boards/OLIMEX_ESP32_POE/sdkconfig.board b/ports/esp32/boards/OLIMEX_ESP32_POE/sdkconfig.board
new file mode 100644
index 000000000000..15ffbf3a67b9
--- /dev/null
+++ b/ports/esp32/boards/OLIMEX_ESP32_POE/sdkconfig.board
@@ -0,0 +1,4 @@
+CONFIG_ETH_PHY_INTERFACE_RMII=y
+CONFIG_ETH_RMII_CLK_OUTPUT=y
+CONFIG_ETH_RMII_CLK_OUT_GPIO=17
+CONFIG_LWIP_LOCAL_HOSTNAME="ESP32_POE"
diff --git a/ports/esp32/boards/UM_FEATHERS2/manifest.py b/ports/esp32/boards/UM_FEATHERS2/manifest.py
index 82ad0c7e4988..3fda1dd8272c 100644
--- a/ports/esp32/boards/UM_FEATHERS2/manifest.py
+++ b/ports/esp32/boards/UM_FEATHERS2/manifest.py
@@ -1,3 +1,3 @@
include("$(PORT_DIR)/boards/manifest.py")
-freeze("$(PORT_DIR)/boards/UM_TINYPICO/modules", "dotstar.py")
+module("dotstar.py", base_path="$(PORT_DIR)/boards/UM_TINYPICO/modules", opt=3)
freeze("modules")
diff --git a/ports/esp32/boards/UM_FEATHERS2/modules/feathers2.py b/ports/esp32/boards/UM_FEATHERS2/modules/feathers2.py
index 95e1f5268160..df3ac4d299e6 100644
--- a/ports/esp32/boards/UM_FEATHERS2/modules/feathers2.py
+++ b/ports/esp32/boards/UM_FEATHERS2/modules/feathers2.py
@@ -39,6 +39,7 @@
# Helper functions
+
# LED & Ambient Light Sensor control
def set_led(state):
l = Pin(LED, Pin.OUT)
diff --git a/ports/esp32/boards/UM_FEATHERS2/mpconfigboard.h b/ports/esp32/boards/UM_FEATHERS2/mpconfigboard.h
index 8d0c9f78c83a..d8529b6342fe 100644
--- a/ports/esp32/boards/UM_FEATHERS2/mpconfigboard.h
+++ b/ports/esp32/boards/UM_FEATHERS2/mpconfigboard.h
@@ -1,5 +1,6 @@
#define MICROPY_HW_BOARD_NAME "FeatherS2"
#define MICROPY_HW_MCU_NAME "ESP32-S2"
+#define MICROPY_PY_NETWORK_HOSTNAME_DEFAULT "FeatherS2"
#define MICROPY_PY_BLUETOOTH (0)
#define MICROPY_HW_ENABLE_SDCARD (0)
diff --git a/ports/esp32/boards/UM_FEATHERS2NEO/modules/feathers2neo.py b/ports/esp32/boards/UM_FEATHERS2NEO/modules/feathers2neo.py
index 857c7559d1ac..d0b99e2f9fe1 100644
--- a/ports/esp32/boards/UM_FEATHERS2NEO/modules/feathers2neo.py
+++ b/ports/esp32/boards/UM_FEATHERS2NEO/modules/feathers2neo.py
@@ -38,6 +38,7 @@
DAC1 = const(17)
DAC2 = const(18)
+
# Helper functions
def set_pixel_power(state):
"""Enable or Disable power to the onboard NeoPixel to either show colour, or to reduce power for deep sleep."""
diff --git a/ports/esp32/boards/UM_FEATHERS2NEO/mpconfigboard.h b/ports/esp32/boards/UM_FEATHERS2NEO/mpconfigboard.h
index 5ee6874b87ba..e7e4d37ece95 100644
--- a/ports/esp32/boards/UM_FEATHERS2NEO/mpconfigboard.h
+++ b/ports/esp32/boards/UM_FEATHERS2NEO/mpconfigboard.h
@@ -1,5 +1,6 @@
#define MICROPY_HW_BOARD_NAME "FeatherS2 Neo"
#define MICROPY_HW_MCU_NAME "ESP32-S2FN4R2"
+#define MICROPY_PY_NETWORK_HOSTNAME_DEFAULT "FeatherS2-Neo"
#define MICROPY_PY_BLUETOOTH (0)
#define MICROPY_HW_ENABLE_SDCARD (0)
diff --git a/ports/esp32/boards/UM_FEATHERS3/modules/feathers3.py b/ports/esp32/boards/UM_FEATHERS3/modules/feathers3.py
index 801f9cbf46fb..1ba919ceaeeb 100644
--- a/ports/esp32/boards/UM_FEATHERS3/modules/feathers3.py
+++ b/ports/esp32/boards/UM_FEATHERS3/modules/feathers3.py
@@ -32,6 +32,7 @@
# Helper functions
+
# LED & Ambient Light Sensor control
def led_set(state):
"""Set the state of the BLUE LED on IO13"""
diff --git a/ports/esp32/boards/UM_FEATHERS3/mpconfigboard.h b/ports/esp32/boards/UM_FEATHERS3/mpconfigboard.h
index 738b32ca1e84..91ea5056d17b 100644
--- a/ports/esp32/boards/UM_FEATHERS3/mpconfigboard.h
+++ b/ports/esp32/boards/UM_FEATHERS3/mpconfigboard.h
@@ -1,5 +1,6 @@
#define MICROPY_HW_BOARD_NAME "FeatherS3"
#define MICROPY_HW_MCU_NAME "ESP32-S3"
+#define MICROPY_PY_NETWORK_HOSTNAME_DEFAULT "FeatherS3"
#define MICROPY_PY_MACHINE_DAC (0)
diff --git a/ports/esp32/boards/UM_PROS3/modules/pros3.py b/ports/esp32/boards/UM_PROS3/modules/pros3.py
index 2edf3e42ea58..7f9590293618 100644
--- a/ports/esp32/boards/UM_PROS3/modules/pros3.py
+++ b/ports/esp32/boards/UM_PROS3/modules/pros3.py
@@ -28,6 +28,7 @@
I2C_SDA = const(8)
I2C_SCL = const(9)
+
# Helper functions
def set_ldo2_power(state):
"""Enable or Disable power to the second LDO"""
diff --git a/ports/esp32/boards/UM_PROS3/mpconfigboard.h b/ports/esp32/boards/UM_PROS3/mpconfigboard.h
index 1522e2aee3ad..ecff1e657066 100644
--- a/ports/esp32/boards/UM_PROS3/mpconfigboard.h
+++ b/ports/esp32/boards/UM_PROS3/mpconfigboard.h
@@ -1,5 +1,6 @@
#define MICROPY_HW_BOARD_NAME "ProS3"
#define MICROPY_HW_MCU_NAME "ESP32-S3"
+#define MICROPY_PY_NETWORK_HOSTNAME_DEFAULT "ProS3"
#define MICROPY_PY_MACHINE_DAC (0)
diff --git a/ports/esp32/boards/UM_TINYPICO/modules/tinypico.py b/ports/esp32/boards/UM_TINYPICO/modules/tinypico.py
index 95450788426a..f6bedfb383cb 100644
--- a/ports/esp32/boards/UM_TINYPICO/modules/tinypico.py
+++ b/ports/esp32/boards/UM_TINYPICO/modules/tinypico.py
@@ -39,6 +39,7 @@
# Helper functions
+
# Get a *rough* estimate of the current battery voltage
# If the battery is not present, the charge IC will still report it's trying to charge at X voltage
# so it will still show a voltage.
diff --git a/ports/esp32/boards/UM_TINYPICO/mpconfigboard.h b/ports/esp32/boards/UM_TINYPICO/mpconfigboard.h
index 6bf70cc13b58..0bb3fa618415 100644
--- a/ports/esp32/boards/UM_TINYPICO/mpconfigboard.h
+++ b/ports/esp32/boards/UM_TINYPICO/mpconfigboard.h
@@ -1,5 +1,6 @@
#define MICROPY_HW_BOARD_NAME "TinyPICO"
#define MICROPY_HW_MCU_NAME "ESP32-PICO-D4"
+#define MICROPY_PY_NETWORK_HOSTNAME_DEFAULT "TinyPICO"
#define MICROPY_HW_I2C0_SCL (22)
#define MICROPY_HW_I2C0_SDA (21)
diff --git a/ports/esp32/boards/UM_TINYS2/mpconfigboard.h b/ports/esp32/boards/UM_TINYS2/mpconfigboard.h
index 1052f6d79ca2..e0bde417c8a2 100644
--- a/ports/esp32/boards/UM_TINYS2/mpconfigboard.h
+++ b/ports/esp32/boards/UM_TINYS2/mpconfigboard.h
@@ -1,5 +1,6 @@
#define MICROPY_HW_BOARD_NAME "TinyS2"
#define MICROPY_HW_MCU_NAME "ESP32-S2FN4R2"
+#define MICROPY_PY_NETWORK_HOSTNAME_DEFAULT "TinyS2"
#define MICROPY_PY_BLUETOOTH (0)
#define MICROPY_HW_ENABLE_SDCARD (0)
diff --git a/ports/esp32/boards/UM_TINYS3/modules/tinys3.py b/ports/esp32/boards/UM_TINYS3/modules/tinys3.py
index 4efcfe4b5299..06bbb5ff827c 100644
--- a/ports/esp32/boards/UM_TINYS3/modules/tinys3.py
+++ b/ports/esp32/boards/UM_TINYS3/modules/tinys3.py
@@ -28,6 +28,7 @@
I2C_SDA = const(8)
I2C_SCL = const(9)
+
# Helper functions
def set_pixel_power(state):
"""Enable or Disable power to the onboard NeoPixel to either show colour, or to reduce power for deep sleep."""
diff --git a/ports/esp32/boards/UM_TINYS3/mpconfigboard.h b/ports/esp32/boards/UM_TINYS3/mpconfigboard.h
index b2638a984788..c0f81f0c447c 100644
--- a/ports/esp32/boards/UM_TINYS3/mpconfigboard.h
+++ b/ports/esp32/boards/UM_TINYS3/mpconfigboard.h
@@ -1,5 +1,6 @@
#define MICROPY_HW_BOARD_NAME "TinyS3"
#define MICROPY_HW_MCU_NAME "ESP32-S3-FN8"
+#define MICROPY_PY_NETWORK_HOSTNAME_DEFAULT "TinyS3"
#define MICROPY_PY_MACHINE_DAC (0)
diff --git a/ports/esp32/boards/manifest.py b/ports/esp32/boards/manifest.py
index 1dc1481a420d..a6df79f0a3d9 100644
--- a/ports/esp32/boards/manifest.py
+++ b/ports/esp32/boards/manifest.py
@@ -1,8 +1,14 @@
freeze("$(PORT_DIR)/modules")
-freeze("$(MPY_DIR)/tools", ("upip.py", "upip_utarfile.py"))
-freeze("$(MPY_DIR)/ports/esp8266/modules", "ntptime.py")
-freeze("$(MPY_DIR)/drivers/dht", "dht.py")
-freeze("$(MPY_DIR)/drivers/onewire")
-include("$(MPY_DIR)/extmod/uasyncio/manifest.py")
-include("$(MPY_DIR)/extmod/webrepl/manifest.py")
-include("$(MPY_DIR)/drivers/neopixel/manifest.py")
+include("$(MPY_DIR)/extmod/uasyncio")
+
+# Useful networking-related packages.
+require("bundle-networking")
+
+# Require some micropython-lib modules.
+require("dht")
+require("ds18x20")
+require("neopixel")
+require("onewire")
+require("umqtt.robust")
+require("umqtt.simple")
+require("upysh")
diff --git a/ports/esp32/boards/manifest_release.py b/ports/esp32/boards/manifest_release.py
deleted file mode 100644
index 8b9bcde6ffa7..000000000000
--- a/ports/esp32/boards/manifest_release.py
+++ /dev/null
@@ -1,7 +0,0 @@
-include("manifest.py")
-
-freeze("$(MPY_LIB_DIR)/python-ecosys/urequests", "urequests.py")
-
-freeze("$(MPY_LIB_DIR)/micropython/upysh", "upysh.py")
-freeze("$(MPY_LIB_DIR)/micropython/umqtt.simple", "umqtt/simple.py")
-freeze("$(MPY_LIB_DIR)/micropython/umqtt.robust", "umqtt/robust.py")
diff --git a/ports/esp32/boards/sdkconfig.base b/ports/esp32/boards/sdkconfig.base
index a0abaf417211..dbc674178fae 100644
--- a/ports/esp32/boards/sdkconfig.base
+++ b/ports/esp32/boards/sdkconfig.base
@@ -54,6 +54,7 @@ CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_FULL=n
# ULP coprocessor support
CONFIG_ESP32_ULP_COPROC_ENABLED=y
+CONFIG_ESP32_ULP_COPROC_RESERVE_MEM=2040
# For cmake build
CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y
diff --git a/ports/esp32/boards/sdkconfig.spiram_oct b/ports/esp32/boards/sdkconfig.spiram_oct
new file mode 100644
index 000000000000..aaea64fcd5c0
--- /dev/null
+++ b/ports/esp32/boards/sdkconfig.spiram_oct
@@ -0,0 +1,3 @@
+# MicroPython on ESP32-S2 and ESP32-PAD1_subscript_3, ESP IDF configuration with SPIRAM support in Octal mode
+CONFIG_SPIRAM_MODE_QUAD=
+CONFIG_SPIRAM_MODE_OCT=y
diff --git a/ports/esp32/esp32_nvs.c b/ports/esp32/esp32_nvs.c
index 42d65be4a63b..0b3661918c77 100644
--- a/ports/esp32/esp32_nvs.c
+++ b/ports/esp32/esp32_nvs.c
@@ -141,10 +141,11 @@ STATIC const mp_rom_map_elem_t esp32_nvs_locals_dict_table[] = {
};
STATIC MP_DEFINE_CONST_DICT(esp32_nvs_locals_dict, esp32_nvs_locals_dict_table);
-const mp_obj_type_t esp32_nvs_type = {
- { &mp_type_type },
- .name = MP_QSTR_NVS,
- .print = esp32_nvs_print,
- .make_new = esp32_nvs_make_new,
- .locals_dict = (mp_obj_dict_t *)&esp32_nvs_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ esp32_nvs_type,
+ MP_QSTR_NVS,
+ MP_TYPE_FLAG_NONE,
+ make_new, esp32_nvs_make_new,
+ print, esp32_nvs_print,
+ locals_dict, &esp32_nvs_locals_dict
+ );
diff --git a/ports/esp32/esp32_partition.c b/ports/esp32/esp32_partition.c
index 47e769486c9b..17aa34e560e8 100644
--- a/ports/esp32/esp32_partition.c
+++ b/ports/esp32/esp32_partition.c
@@ -284,10 +284,11 @@ STATIC const mp_rom_map_elem_t esp32_partition_locals_dict_table[] = {
};
STATIC MP_DEFINE_CONST_DICT(esp32_partition_locals_dict, esp32_partition_locals_dict_table);
-const mp_obj_type_t esp32_partition_type = {
- { &mp_type_type },
- .name = MP_QSTR_Partition,
- .print = esp32_partition_print,
- .make_new = esp32_partition_make_new,
- .locals_dict = (mp_obj_dict_t *)&esp32_partition_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ esp32_partition_type,
+ MP_QSTR_Partition,
+ MP_TYPE_FLAG_NONE,
+ make_new, esp32_partition_make_new,
+ print, esp32_partition_print,
+ locals_dict, &esp32_partition_locals_dict
+ );
diff --git a/ports/esp32/esp32_rmt.c b/ports/esp32/esp32_rmt.c
index ac897e33368a..3cd43e8474e6 100644
--- a/ports/esp32/esp32_rmt.c
+++ b/ports/esp32/esp32_rmt.c
@@ -326,13 +326,13 @@ STATIC mp_obj_t esp32_rmt_write_pulses(size_t n_args, const mp_obj_t *args) {
check_esp_err(rmt_wait_tx_done(self->channel_id, portMAX_DELAY));
}
- check_esp_err(rmt_write_items(self->channel_id, self->items, num_items, false));
-
if (self->loop_en) {
check_esp_err(rmt_set_tx_intr_en(self->channel_id, false));
check_esp_err(rmt_set_tx_loop_mode(self->channel_id, true));
}
+ check_esp_err(rmt_write_items(self->channel_id, self->items, num_items, false));
+
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp32_rmt_write_pulses_obj, 2, 3, esp32_rmt_write_pulses);
@@ -372,10 +372,11 @@ STATIC const mp_rom_map_elem_t esp32_rmt_locals_dict_table[] = {
};
STATIC MP_DEFINE_CONST_DICT(esp32_rmt_locals_dict, esp32_rmt_locals_dict_table);
-const mp_obj_type_t esp32_rmt_type = {
- { &mp_type_type },
- .name = MP_QSTR_RMT,
- .print = esp32_rmt_print,
- .make_new = esp32_rmt_make_new,
- .locals_dict = (mp_obj_dict_t *)&esp32_rmt_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ esp32_rmt_type,
+ MP_QSTR_RMT,
+ MP_TYPE_FLAG_NONE,
+ make_new, esp32_rmt_make_new,
+ print, esp32_rmt_print,
+ locals_dict, &esp32_rmt_locals_dict
+ );
diff --git a/ports/esp32/esp32_ulp.c b/ports/esp32/esp32_ulp.c
index 8e4ce9c5a41b..843bdb2366df 100644
--- a/ports/esp32/esp32_ulp.c
+++ b/ports/esp32/esp32_ulp.c
@@ -91,11 +91,12 @@ STATIC const mp_rom_map_elem_t esp32_ulp_locals_dict_table[] = {
};
STATIC MP_DEFINE_CONST_DICT(esp32_ulp_locals_dict, esp32_ulp_locals_dict_table);
-const mp_obj_type_t esp32_ulp_type = {
- { &mp_type_type },
- .name = MP_QSTR_ULP,
- .make_new = esp32_ulp_make_new,
- .locals_dict = (mp_obj_t)&esp32_ulp_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ esp32_ulp_type,
+ MP_QSTR_ULP,
+ MP_TYPE_FLAG_NONE,
+ make_new, esp32_ulp_make_new,
+ locals_dict, &esp32_ulp_locals_dict
+ );
#endif // CONFIG_IDF_TARGET_ESP32
diff --git a/ports/esp32/machine_adc.c b/ports/esp32/machine_adc.c
index cb45aab33910..1e20186b97be 100644
--- a/ports/esp32/machine_adc.c
+++ b/ports/esp32/machine_adc.c
@@ -256,10 +256,11 @@ STATIC const mp_rom_map_elem_t madc_locals_dict_table[] = {
};
STATIC MP_DEFINE_CONST_DICT(madc_locals_dict, madc_locals_dict_table);
-const mp_obj_type_t machine_adc_type = {
- { &mp_type_type },
- .name = MP_QSTR_ADC,
- .print = madc_print,
- .make_new = madc_make_new,
- .locals_dict = (mp_obj_t)&madc_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ machine_adc_type,
+ MP_QSTR_ADC,
+ MP_TYPE_FLAG_NONE,
+ make_new, madc_make_new,
+ print, madc_print,
+ locals_dict, &madc_locals_dict
+ );
diff --git a/ports/esp32/machine_adcblock.c b/ports/esp32/machine_adcblock.c
index 06c215f8ae73..afe8fdea40b2 100644
--- a/ports/esp32/machine_adcblock.c
+++ b/ports/esp32/machine_adcblock.c
@@ -194,10 +194,11 @@ STATIC const mp_rom_map_elem_t madcblock_locals_dict_table[] = {
};
STATIC MP_DEFINE_CONST_DICT(madcblock_locals_dict, madcblock_locals_dict_table);
-const mp_obj_type_t machine_adcblock_type = {
- { &mp_type_type },
- .name = MP_QSTR_ADCBlock,
- .print = madcblock_print,
- .make_new = madcblock_make_new,
- .locals_dict = (mp_obj_t)&madcblock_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ machine_adcblock_type,
+ MP_QSTR_ADCBlock,
+ MP_TYPE_FLAG_NONE,
+ make_new, madcblock_make_new,
+ print, madcblock_print,
+ locals_dict, &madcblock_locals_dict
+ );
diff --git a/ports/esp32/machine_dac.c b/ports/esp32/machine_dac.c
index 35826d4a99a8..0e85dc9c9bfb 100644
--- a/ports/esp32/machine_dac.c
+++ b/ports/esp32/machine_dac.c
@@ -104,12 +104,13 @@ STATIC const mp_rom_map_elem_t mdac_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(mdac_locals_dict, mdac_locals_dict_table);
-const mp_obj_type_t machine_dac_type = {
- { &mp_type_type },
- .name = MP_QSTR_DAC,
- .print = mdac_print,
- .make_new = mdac_make_new,
- .locals_dict = (mp_obj_t)&mdac_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ machine_dac_type,
+ MP_QSTR_DAC,
+ MP_TYPE_FLAG_NONE,
+ make_new, mdac_make_new,
+ print, mdac_print,
+ locals_dict, &mdac_locals_dict
+ );
#endif // MICROPY_PY_MACHINE_DAC
diff --git a/ports/esp32/machine_hw_spi.c b/ports/esp32/machine_hw_spi.c
index 3e720adb1a5e..36f8d3f06956 100644
--- a/ports/esp32/machine_hw_spi.c
+++ b/ports/esp32/machine_hw_spi.c
@@ -267,21 +267,15 @@ STATIC void machine_hw_spi_init_internal(
// Select DMA channel based on the hardware SPI host
int dma_chan = 0;
+ #if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C3
+ dma_chan = SPI_DMA_CH_AUTO;
+ #else
if (self->host == HSPI_HOST) {
- #if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C3
- dma_chan = 3;
- #else
dma_chan = 1;
- #endif
- #ifdef FSPI_HOST
- } else if (self->host == FSPI_HOST) {
- dma_chan = 1;
- #endif
- #ifdef VSPI_HOST
- } else if (self->host == VSPI_HOST) {
+ } else {
dma_chan = 2;
- #endif
}
+ #endif
ret = spi_bus_initialize(self->host, &buscfg, dma_chan);
switch (ret) {
@@ -496,7 +490,7 @@ mp_obj_t machine_hw_spi_make_new(const mp_obj_type_t *type, size_t n_args, size_
self = &machine_hw_spi_obj[1];
default_pins = &machine_hw_spi_default_pins[1];
}
- self->base.type = &machine_hw_spi_type;
+ self->base.type = &machine_spi_type;
int8_t sck, mosi, miso;
@@ -539,17 +533,26 @@ mp_obj_t machine_hw_spi_make_new(const mp_obj_type_t *type, size_t n_args, size_
return MP_OBJ_FROM_PTR(self);
}
+spi_host_device_t machine_hw_spi_get_host(mp_obj_t in) {
+ if (mp_obj_get_type(in) != &machine_spi_type) {
+ mp_raise_ValueError(MP_ERROR_TEXT("expecting a SPI object"));
+ }
+ machine_hw_spi_obj_t *self = (machine_hw_spi_obj_t *)in;
+ return self->host;
+}
+
STATIC const mp_machine_spi_p_t machine_hw_spi_p = {
.init = machine_hw_spi_init,
.deinit = machine_hw_spi_deinit,
.transfer = machine_hw_spi_transfer,
};
-const mp_obj_type_t machine_hw_spi_type = {
- { &mp_type_type },
- .name = MP_QSTR_SPI,
- .print = machine_hw_spi_print,
- .make_new = machine_hw_spi_make_new,
- .protocol = &machine_hw_spi_p,
- .locals_dict = (mp_obj_dict_t *)&mp_machine_spi_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ machine_spi_type,
+ MP_QSTR_SPI,
+ MP_TYPE_FLAG_NONE,
+ make_new, machine_hw_spi_make_new,
+ print, machine_hw_spi_print,
+ protocol, &machine_hw_spi_p,
+ locals_dict, &mp_machine_spi_locals_dict
+ );
diff --git a/ports/esp32/machine_i2c.c b/ports/esp32/machine_i2c.c
index e25cad0b60a5..9ec39e564966 100644
--- a/ports/esp32/machine_i2c.c
+++ b/ports/esp32/machine_i2c.c
@@ -32,6 +32,13 @@
#include "driver/i2c.h"
+#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 4, 0)
+#include "hal/i2c_ll.h"
+#else
+#include "soc/i2c_reg.h"
+#define I2C_LL_MAX_TIMEOUT I2C_TIME_OUT_REG_V
+#endif
+
#ifndef MICROPY_HW_I2C0_SCL
#define MICROPY_HW_I2C0_SCL (GPIO_NUM_18)
#define MICROPY_HW_I2C0_SDA (GPIO_NUM_19)
@@ -47,7 +54,15 @@
#endif
#endif
-#define I2C_DEFAULT_TIMEOUT_US (10000) // 10ms
+#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3
+#define I2C_SCLK_FREQ XTAL_CLK_FREQ
+#elif CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2
+#define I2C_SCLK_FREQ I2C_APB_CLK_FREQ
+#else
+#error "unsupported I2C for ESP32 SoC variant"
+#endif
+
+#define I2C_DEFAULT_TIMEOUT_US (50000) // 50ms
typedef struct _machine_hw_i2c_obj_t {
mp_obj_base_t base;
@@ -71,7 +86,8 @@ STATIC void machine_hw_i2c_init(machine_hw_i2c_obj_t *self, uint32_t freq, uint3
.master.clk_speed = freq,
};
i2c_param_config(self->port, &conf);
- i2c_set_timeout(self->port, I2C_APB_CLK_FREQ / 1000000 * timeout_us);
+ int timeout = I2C_SCLK_FREQ / 1000000 * timeout_us;
+ i2c_set_timeout(self->port, (timeout > I2C_LL_MAX_TIMEOUT) ? I2C_LL_MAX_TIMEOUT : timeout);
i2c_driver_install(self->port, I2C_MODE_MASTER, 0, 0, 0);
}
@@ -131,7 +147,7 @@ STATIC void machine_hw_i2c_print(const mp_print_t *print, mp_obj_t self_in, mp_p
int h, l;
i2c_get_period(self->port, &h, &l);
mp_printf(print, "I2C(%u, scl=%u, sda=%u, freq=%u)",
- self->port, self->scl, self->sda, I2C_APB_CLK_FREQ / (h + l));
+ self->port, self->scl, self->sda, I2C_SCLK_FREQ / (h + l));
}
mp_obj_t machine_hw_i2c_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
@@ -161,7 +177,7 @@ mp_obj_t machine_hw_i2c_make_new(const mp_obj_type_t *type, size_t n_args, size_
bool first_init = false;
if (self->base.type == NULL) {
// Created for the first time, set default pins
- self->base.type = &machine_hw_i2c_type;
+ self->base.type = &machine_i2c_type;
self->port = i2c_id;
if (self->port == I2C_NUM_0) {
self->scl = MICROPY_HW_I2C0_SCL;
@@ -192,11 +208,12 @@ STATIC const mp_machine_i2c_p_t machine_hw_i2c_p = {
.transfer = machine_hw_i2c_transfer,
};
-const mp_obj_type_t machine_hw_i2c_type = {
- { &mp_type_type },
- .name = MP_QSTR_I2C,
- .print = machine_hw_i2c_print,
- .make_new = machine_hw_i2c_make_new,
- .protocol = &machine_hw_i2c_p,
- .locals_dict = (mp_obj_dict_t *)&mp_machine_i2c_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ machine_i2c_type,
+ MP_QSTR_I2C,
+ MP_TYPE_FLAG_NONE,
+ make_new, machine_hw_i2c_make_new,
+ print, machine_hw_i2c_print,
+ protocol, &machine_hw_i2c_p,
+ locals_dict, &mp_machine_i2c_locals_dict
+ );
diff --git a/ports/esp32/machine_i2s.c b/ports/esp32/machine_i2s.c
index 8832ad5e9073..ce1cb59849dc 100644
--- a/ports/esp32/machine_i2s.c
+++ b/ports/esp32/machine_i2s.c
@@ -533,7 +533,8 @@ STATIC mp_obj_t machine_i2s_make_new(const mp_obj_type_t *type, size_t n_pos_arg
machine_i2s_obj_t *self;
if (MP_STATE_PORT(machine_i2s_obj)[port] == NULL) {
- self = mp_obj_malloc(machine_i2s_obj_t, &machine_i2s_type);
+ self = m_new_obj_with_finaliser(machine_i2s_obj_t);
+ self->base.type = &machine_i2s_type;
MP_STATE_PORT(machine_i2s_obj)[port] = self;
self->port = port;
} else {
@@ -688,6 +689,7 @@ STATIC const mp_rom_map_elem_t machine_i2s_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) },
{ MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_i2s_deinit_obj) },
{ MP_ROM_QSTR(MP_QSTR_irq), MP_ROM_PTR(&machine_i2s_irq_obj) },
+ { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&machine_i2s_deinit_obj) },
// Static method
{ MP_ROM_QSTR(MP_QSTR_shift), MP_ROM_PTR(&machine_i2s_shift_obj) },
@@ -829,15 +831,16 @@ STATIC const mp_stream_p_t i2s_stream_p = {
.is_text = false,
};
-const mp_obj_type_t machine_i2s_type = {
- { &mp_type_type },
- .name = MP_QSTR_I2S,
- .print = machine_i2s_print,
- .getiter = mp_identity_getiter,
- .iternext = mp_stream_unbuffered_iter,
- .protocol = &i2s_stream_p,
- .make_new = machine_i2s_make_new,
- .locals_dict = (mp_obj_dict_t *)&machine_i2s_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ machine_i2s_type,
+ MP_QSTR_I2S,
+ MP_TYPE_FLAG_ITER_IS_STREAM,
+ make_new, machine_i2s_make_new,
+ print, machine_i2s_print,
+ protocol, &i2s_stream_p,
+ locals_dict, &machine_i2s_locals_dict
+ );
+
+MP_REGISTER_ROOT_POINTER(struct _machine_i2s_obj_t *machine_i2s_obj[I2S_NUM_MAX]);
#endif // MICROPY_PY_MACHINE_I2S
diff --git a/ports/esp32/machine_pin.c b/ports/esp32/machine_pin.c
index 865face96f2a..f103b96963ce 100644
--- a/ports/esp32/machine_pin.c
+++ b/ports/esp32/machine_pin.c
@@ -64,7 +64,7 @@ typedef struct _machine_pin_irq_obj_t {
gpio_num_t id;
} machine_pin_irq_obj_t;
-STATIC const machine_pin_obj_t machine_pin_obj[] = {
+STATIC const machine_pin_obj_t machine_pin_obj[GPIO_NUM_MAX] = {
#if CONFIG_IDF_TARGET_ESP32
{{&machine_pin_type}, GPIO_NUM_0},
@@ -225,7 +225,7 @@ STATIC const machine_pin_obj_t machine_pin_obj[] = {
};
// forward declaration
-STATIC const machine_pin_irq_obj_t machine_pin_irq_object[];
+STATIC const machine_pin_irq_obj_t machine_pin_irq_object[GPIO_NUM_MAX];
void machine_pins_init(void) {
static bool did_install = false;
@@ -529,22 +529,23 @@ STATIC const mp_pin_p_t pin_pin_p = {
.ioctl = pin_ioctl,
};
-const mp_obj_type_t machine_pin_type = {
- { &mp_type_type },
- .name = MP_QSTR_Pin,
- .print = machine_pin_print,
- .make_new = mp_pin_make_new,
- .call = machine_pin_call,
- .protocol = &pin_pin_p,
- .locals_dict = (mp_obj_t)&machine_pin_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ machine_pin_type,
+ MP_QSTR_Pin,
+ MP_TYPE_FLAG_NONE,
+ make_new, mp_pin_make_new,
+ print, machine_pin_print,
+ call, machine_pin_call,
+ protocol, &pin_pin_p,
+ locals_dict, &machine_pin_locals_dict
+ );
/******************************************************************************/
// Pin IRQ object
STATIC const mp_obj_type_t machine_pin_irq_type;
-STATIC const machine_pin_irq_obj_t machine_pin_irq_object[] = {
+STATIC const machine_pin_irq_obj_t machine_pin_irq_object[GPIO_NUM_MAX] = {
#if CONFIG_IDF_TARGET_ESP32
{{&machine_pin_irq_type}, GPIO_NUM_0},
@@ -723,9 +724,12 @@ STATIC const mp_rom_map_elem_t machine_pin_irq_locals_dict_table[] = {
};
STATIC MP_DEFINE_CONST_DICT(machine_pin_irq_locals_dict, machine_pin_irq_locals_dict_table);
-STATIC const mp_obj_type_t machine_pin_irq_type = {
- { &mp_type_type },
- .name = MP_QSTR_IRQ,
- .call = machine_pin_irq_call,
- .locals_dict = (mp_obj_dict_t *)&machine_pin_irq_locals_dict,
-};
+STATIC MP_DEFINE_CONST_OBJ_TYPE(
+ machine_pin_irq_type,
+ MP_QSTR_IRQ,
+ MP_TYPE_FLAG_NONE,
+ call, machine_pin_irq_call,
+ locals_dict, &machine_pin_irq_locals_dict
+ );
+
+MP_REGISTER_ROOT_POINTER(mp_obj_t machine_pin_irq_handler[GPIO_PIN_COUNT]);
diff --git a/ports/esp32/machine_pwm.c b/ports/esp32/machine_pwm.c
index 0107187a8c98..79e11d02784e 100644
--- a/ports/esp32/machine_pwm.c
+++ b/ports/esp32/machine_pwm.c
@@ -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)
*
@@ -97,8 +97,10 @@ STATIC ledc_timer_config_t timers[PWM_TIMER_MAX];
// How much to shift from the HIGHEST_PWM_RES duty resolution to the user interface duty resolution UI_RES_16_BIT
#define UI_RES_SHIFT (UI_RES_16_BIT - HIGHEST_PWM_RES) // 0 for ESP32, 2 for S2, S3, C3
+#if SOC_LEDC_SUPPORT_REF_TICK
// If the PWM frequency is less than EMPIRIC_FREQ, then LEDC_REF_CLK_HZ(1 MHz) source is used, else LEDC_APB_CLK_HZ(80 MHz) source is used
#define EMPIRIC_FREQ (10) // Hz
+#endif
// Config of timer upon which we run all PWM'ed GPIO pins
STATIC bool pwm_inited = false;
@@ -208,9 +210,11 @@ STATIC void set_freq(machine_pwm_obj_t *self, unsigned int freq, ledc_timer_conf
if (freq != timer->freq_hz) {
// Find the highest bit resolution for the requested frequency
unsigned int i = LEDC_APB_CLK_HZ; // 80 MHz
+ #if SOC_LEDC_SUPPORT_REF_TICK
if (freq < EMPIRIC_FREQ) {
i = LEDC_REF_CLK_HZ; // 1 MHz
}
+ #endif
#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0)
// original code
@@ -243,9 +247,11 @@ STATIC void set_freq(machine_pwm_obj_t *self, unsigned int freq, ledc_timer_conf
timer->duty_resolution = res;
timer->freq_hz = freq;
timer->clk_cfg = LEDC_USE_APB_CLK;
+ #if SOC_LEDC_SUPPORT_REF_TICK
if (freq < EMPIRIC_FREQ) {
timer->clk_cfg = LEDC_USE_REF_TICK;
}
+ #endif
// Set frequency
esp_err_t err = ledc_timer_config(timer);
@@ -292,7 +298,14 @@ STATIC int duty_to_ns(machine_pwm_obj_t *self, int duty) {
#define get_duty_raw(self) ledc_get_duty(self->mode, self->channel)
+STATIC void pwm_is_active(machine_pwm_obj_t *self) {
+ if (self->active == false) {
+ mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("PWM inactive"));
+ }
+}
+
STATIC uint32_t get_duty_u16(machine_pwm_obj_t *self) {
+ pwm_is_active(self);
int resolution = timers[TIMER_IDX(self->mode, self->timer)].duty_resolution;
int duty = ledc_get_duty(self->mode, self->channel);
if (resolution <= UI_RES_16_BIT) {
@@ -304,14 +317,17 @@ STATIC uint32_t get_duty_u16(machine_pwm_obj_t *self) {
}
STATIC uint32_t get_duty_u10(machine_pwm_obj_t *self) {
+ pwm_is_active(self);
return get_duty_u16(self) >> 6; // Scale down from 16 bit to 10 bit resolution
}
STATIC uint32_t get_duty_ns(machine_pwm_obj_t *self) {
+ pwm_is_active(self);
return duty_to_ns(self, get_duty_u16(self));
}
STATIC void set_duty_u16(machine_pwm_obj_t *self, int duty) {
+ pwm_is_active(self);
if ((duty < 0) || (duty > UI_MAX_DUTY)) {
mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("duty_u16 must be from 0 to %d"), UI_MAX_DUTY);
}
@@ -350,6 +366,7 @@ STATIC void set_duty_u16(machine_pwm_obj_t *self, int duty) {
}
STATIC void set_duty_u10(machine_pwm_obj_t *self, int duty) {
+ pwm_is_active(self);
if ((duty < 0) || (duty > MAX_DUTY_U10)) {
mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("duty must be from 0 to %u"), MAX_DUTY_U10);
}
@@ -359,6 +376,7 @@ STATIC void set_duty_u10(machine_pwm_obj_t *self, int duty) {
}
STATIC void set_duty_ns(machine_pwm_obj_t *self, int ns) {
+ pwm_is_active(self);
if ((ns < 0) || (ns > duty_to_ns(self, UI_MAX_DUTY))) {
mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("duty_ns must be from 0 to %d ns"), duty_to_ns(self, UI_MAX_DUTY));
}
@@ -592,10 +610,12 @@ STATIC void mp_machine_pwm_deinit(machine_pwm_obj_t *self) {
// Set's and get's methods of PWM class
STATIC mp_obj_t mp_machine_pwm_freq_get(machine_pwm_obj_t *self) {
+ pwm_is_active(self);
return MP_OBJ_NEW_SMALL_INT(ledc_get_freq(self->mode, self->timer));
}
STATIC void mp_machine_pwm_freq_set(machine_pwm_obj_t *self, mp_int_t freq) {
+ pwm_is_active(self);
if ((freq <= 0) || (freq > 40000000)) {
mp_raise_ValueError(MP_ERROR_TEXT("freqency must be from 1Hz to 40MHz"));
}
diff --git a/ports/esp32/machine_rtc.c b/ports/esp32/machine_rtc.c
index 72d7b5c8280a..3d620336c9a9 100644
--- a/ports/esp32/machine_rtc.c
+++ b/ports/esp32/machine_rtc.c
@@ -173,9 +173,10 @@ STATIC const mp_rom_map_elem_t machine_rtc_locals_dict_table[] = {
};
STATIC MP_DEFINE_CONST_DICT(machine_rtc_locals_dict, machine_rtc_locals_dict_table);
-const mp_obj_type_t machine_rtc_type = {
- { &mp_type_type },
- .name = MP_QSTR_RTC,
- .make_new = machine_rtc_make_new,
- .locals_dict = (mp_obj_t)&machine_rtc_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ machine_rtc_type,
+ MP_QSTR_RTC,
+ MP_TYPE_FLAG_NONE,
+ make_new, machine_rtc_make_new,
+ locals_dict, &machine_rtc_locals_dict
+ );
diff --git a/ports/esp32/machine_rtc.h b/ports/esp32/machine_rtc.h
index 6e70f7438501..ce2a5482a224 100644
--- a/ports/esp32/machine_rtc.h
+++ b/ports/esp32/machine_rtc.h
@@ -34,6 +34,7 @@ typedef struct {
uint64_t ext1_pins; // set bit == pin#
int8_t ext0_pin; // just the pin#, -1 == None
bool wake_on_touch : 1;
+ bool wake_on_ulp : 1;
bool ext0_level : 1;
wake_type_t ext0_wake_types;
bool ext1_level : 1;
diff --git a/ports/esp32/machine_sdcard.c b/ports/esp32/machine_sdcard.c
index 82c2e6cd4e32..5b495f8494e7 100644
--- a/ports/esp32/machine_sdcard.c
+++ b/ports/esp32/machine_sdcard.c
@@ -211,7 +211,7 @@ STATIC mp_obj_t machine_sdcard_make_new(const mp_obj_type_t *type, size_t n_args
.gpio_cs = GPIO_NUM_34,
.gpio_cd = SDSPI_SLOT_NO_CD,
.gpio_wp = SDSPI_SLOT_NO_WP,
- .dma_channel = 2
+ .dma_channel = SPI_DMA_CH_AUTO
},
SDSPI_SLOT_CONFIG_DEFAULT()
};
@@ -283,6 +283,10 @@ STATIC mp_obj_t sd_deinit(mp_obj_t self_in) {
{
self->host.deinit();
}
+ if (self->host.flags & SDMMC_HOST_FLAG_SPI) {
+ // SD card used a (dedicated) SPI bus, so free that SPI bus.
+ spi_bus_free(self->host.slot);
+ }
self->flags &= ~SDCARD_CARD_FLAGS_HOST_INIT_DONE;
}
@@ -395,11 +399,12 @@ STATIC const mp_rom_map_elem_t machine_sdcard_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(machine_sdcard_locals_dict, machine_sdcard_locals_dict_table);
-const mp_obj_type_t machine_sdcard_type = {
- { &mp_type_type },
- .name = MP_QSTR_SDCard,
- .make_new = machine_sdcard_make_new,
- .locals_dict = (mp_obj_dict_t *)&machine_sdcard_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ machine_sdcard_type,
+ MP_QSTR_SDCard,
+ MP_TYPE_FLAG_NONE,
+ make_new, machine_sdcard_make_new,
+ locals_dict, &machine_sdcard_locals_dict
+ );
#endif // MICROPY_HW_ENABLE_SDCARD
diff --git a/ports/esp32/machine_timer.c b/ports/esp32/machine_timer.c
index 100b2aa1fb9c..c66cb2a48d90 100644
--- a/ports/esp32/machine_timer.c
+++ b/ports/esp32/machine_timer.c
@@ -68,6 +68,7 @@ typedef struct _machine_timer_obj_t {
const mp_obj_type_t machine_timer_type;
STATIC void machine_timer_disable(machine_timer_obj_t *self);
+STATIC mp_obj_t machine_timer_init_helper(machine_timer_obj_t *self, mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
void machine_timer_deinit_all(void) {
// Disable, deallocate and remove all timers from list
@@ -94,24 +95,35 @@ STATIC void machine_timer_print(const mp_print_t *print, mp_obj_t self_in, mp_pr
}
STATIC mp_obj_t machine_timer_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, 1, false);
+ mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true);
mp_uint_t group = (mp_obj_get_int(args[0]) >> 1) & 1;
mp_uint_t index = mp_obj_get_int(args[0]) & 1;
- // Check whether the timer is already initialized, if so return it
+ machine_timer_obj_t *self = NULL;
+
+ // Check whether the timer is already initialized, if so use it
for (machine_timer_obj_t *t = MP_STATE_PORT(machine_timer_obj_head); t; t = t->next) {
if (t->group == group && t->index == index) {
- return t;
+ self = t;
+ break;
}
}
+ // The timer does not exist, create it.
+ if (self == NULL) {
+ self = mp_obj_malloc(machine_timer_obj_t, &machine_timer_type);
+ self->group = group;
+ self->index = index;
+
+ // Add the timer to the linked-list of timers
+ self->next = MP_STATE_PORT(machine_timer_obj_head);
+ MP_STATE_PORT(machine_timer_obj_head) = self;
+ }
- machine_timer_obj_t *self = mp_obj_malloc(machine_timer_obj_t, &machine_timer_type);
- self->group = group;
- self->index = index;
-
- // Add the timer to the linked-list of timers
- self->next = MP_STATE_PORT(machine_timer_obj_head);
- MP_STATE_PORT(machine_timer_obj_head) = self;
+ if (n_args > 1 || n_kw > 0) {
+ mp_map_t kw_args;
+ mp_map_init_fixed_table(&kw_args, n_kw, args + n_args);
+ machine_timer_init_helper(self, n_args - 1, args + 1, &kw_args);
+ }
return self;
}
@@ -177,6 +189,9 @@ STATIC void machine_timer_enable(machine_timer_obj_t *self) {
config.divider = TIMER_DIVIDER;
config.intr_type = TIMER_INTR_LEVEL;
config.counter_en = TIMER_PAUSE;
+ #if SOC_TIMER_GROUP_SUPPORT_XTAL
+ config.clk_src = TIMER_SRC_CLK_APB;
+ #endif
check_esp_err(timer_init(self->group, self->index, &config));
check_esp_err(timer_set_counter_value(self->group, self->index, 0x00000000));
@@ -265,10 +280,13 @@ STATIC const mp_rom_map_elem_t machine_timer_locals_dict_table[] = {
};
STATIC MP_DEFINE_CONST_DICT(machine_timer_locals_dict, machine_timer_locals_dict_table);
-const mp_obj_type_t machine_timer_type = {
- { &mp_type_type },
- .name = MP_QSTR_Timer,
- .print = machine_timer_print,
- .make_new = machine_timer_make_new,
- .locals_dict = (mp_obj_t)&machine_timer_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ machine_timer_type,
+ MP_QSTR_Timer,
+ MP_TYPE_FLAG_NONE,
+ make_new, machine_timer_make_new,
+ print, machine_timer_print,
+ locals_dict, &machine_timer_locals_dict
+ );
+
+MP_REGISTER_ROOT_POINTER(struct _machine_timer_obj_t *machine_timer_obj_head);
diff --git a/ports/esp32/machine_touchpad.c b/ports/esp32/machine_touchpad.c
index 168ac16d0eef..d9f4ef3ebc7f 100644
--- a/ports/esp32/machine_touchpad.c
+++ b/ports/esp32/machine_touchpad.c
@@ -27,10 +27,10 @@
#include "py/runtime.h"
#include "py/mphal.h"
#include "modmachine.h"
+#include "driver/gpio.h"
-#if CONFIG_IDF_TARGET_ESP32
+#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
-#include "driver/gpio.h"
#if CONFIG_IDF_TARGET_ESP32
#include "driver/touch_pad.h"
#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
@@ -43,8 +43,8 @@ typedef struct _mtp_obj_t {
touch_pad_t touchpad_id;
} mtp_obj_t;
-#if CONFIG_IDF_TARGET_ESP32
STATIC const mtp_obj_t touchpad_obj[] = {
+ #if CONFIG_IDF_TARGET_ESP32
{{&machine_touchpad_type}, GPIO_NUM_4, TOUCH_PAD_NUM0},
{{&machine_touchpad_type}, GPIO_NUM_0, TOUCH_PAD_NUM1},
{{&machine_touchpad_type}, GPIO_NUM_2, TOUCH_PAD_NUM2},
@@ -55,9 +55,7 @@ STATIC const mtp_obj_t touchpad_obj[] = {
{{&machine_touchpad_type}, GPIO_NUM_27, TOUCH_PAD_NUM7},
{{&machine_touchpad_type}, GPIO_NUM_33, TOUCH_PAD_NUM8},
{{&machine_touchpad_type}, GPIO_NUM_32, TOUCH_PAD_NUM9},
-};
-#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
-STATIC const mtp_obj_t touchpad_obj[] = {
+ #elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
{{&machine_touchpad_type}, GPIO_NUM_1, TOUCH_PAD_NUM1},
{{&machine_touchpad_type}, GPIO_NUM_2, TOUCH_PAD_NUM2},
{{&machine_touchpad_type}, GPIO_NUM_3, TOUCH_PAD_NUM3},
@@ -72,12 +70,11 @@ STATIC const mtp_obj_t touchpad_obj[] = {
{{&machine_touchpad_type}, GPIO_NUM_12, TOUCH_PAD_NUM12},
{{&machine_touchpad_type}, GPIO_NUM_13, TOUCH_PAD_NUM13},
{{&machine_touchpad_type}, GPIO_NUM_14, TOUCH_PAD_NUM14},
+ #endif
};
-#endif
STATIC mp_obj_t mtp_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, 1, true);
gpio_num_t pin_id = machine_pin_get_id(args[0]);
const mtp_obj_t *self = NULL;
@@ -95,9 +92,16 @@ STATIC mp_obj_t mtp_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_
if (!initialized) {
touch_pad_init();
touch_pad_set_fsm_mode(TOUCH_FSM_MODE_TIMER);
+ #if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
+ touch_pad_fsm_start();
+ #endif
initialized = 1;
}
+ #if CONFIG_IDF_TARGET_ESP32
esp_err_t err = touch_pad_config(self->touchpad_id, 0);
+ #elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
+ esp_err_t err = touch_pad_config(self->touchpad_id);
+ #endif
if (err == ESP_OK) {
return MP_OBJ_FROM_PTR(self);
}
@@ -106,8 +110,12 @@ STATIC mp_obj_t mtp_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_
STATIC mp_obj_t mtp_config(mp_obj_t self_in, mp_obj_t value_in) {
mtp_obj_t *self = self_in;
+ #if CONFIG_IDF_TARGET_ESP32
uint16_t value = mp_obj_get_int(value_in);
esp_err_t err = touch_pad_config(self->touchpad_id, value);
+ #elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
+ esp_err_t err = touch_pad_config(self->touchpad_id);
+ #endif
if (err == ESP_OK) {
return mp_const_none;
}
@@ -117,8 +125,13 @@ MP_DEFINE_CONST_FUN_OBJ_2(mtp_config_obj, mtp_config);
STATIC mp_obj_t mtp_read(mp_obj_t self_in) {
mtp_obj_t *self = self_in;
+ #if CONFIG_IDF_TARGET_ESP32
uint16_t value;
esp_err_t err = touch_pad_read(self->touchpad_id, &value);
+ #elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
+ uint32_t value;
+ esp_err_t err = touch_pad_read_raw_data(self->touchpad_id, &value);
+ #endif
if (err == ESP_OK) {
return MP_OBJ_NEW_SMALL_INT(value);
}
@@ -134,11 +147,12 @@ STATIC const mp_rom_map_elem_t mtp_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(mtp_locals_dict, mtp_locals_dict_table);
-const mp_obj_type_t machine_touchpad_type = {
- { &mp_type_type },
- .name = MP_QSTR_TouchPad,
- .make_new = mtp_make_new,
- .locals_dict = (mp_obj_t)&mtp_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ machine_touchpad_type,
+ MP_QSTR_TouchPad,
+ MP_TYPE_FLAG_NONE,
+ make_new, mtp_make_new,
+ locals_dict, &mtp_locals_dict
+ );
-#endif // CONFIG_IDF_TARGET_ESP32
+#endif
diff --git a/ports/esp32/machine_uart.c b/ports/esp32/machine_uart.c
index c0eedb80b317..4cfa31b71de3 100644
--- a/ports/esp32/machine_uart.c
+++ b/ports/esp32/machine_uart.c
@@ -267,12 +267,18 @@ STATIC void machine_uart_init_helper(machine_uart_obj_t *self, size_t n_args, co
}
// set timeout_char
- // make sure it is at least as long as a whole character (13 bits to be safe)
+ // make sure it is at least as long as a whole character (12 bits here)
if (args[ARG_timeout_char].u_int != -1) {
self->timeout_char = args[ARG_timeout_char].u_int;
- uint32_t min_timeout_char = 13000 / baudrate + 1;
- if (self->timeout_char < min_timeout_char) {
- self->timeout_char = min_timeout_char;
+ uint32_t char_time_ms = 12000 / baudrate + 1;
+ uint32_t rx_timeout = self->timeout_char / char_time_ms;
+ if (rx_timeout < 1) {
+ #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 1, 0)
+ uart_set_rx_full_threshold(self->uart_num, 1);
+ #endif
+ uart_set_rx_timeout(self->uart_num, 1);
+ } else {
+ uart_set_rx_timeout(self->uart_num, rx_timeout);
}
}
@@ -393,42 +399,46 @@ STATIC mp_obj_t machine_uart_sendbreak(mp_obj_t self_in) {
machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in);
// Save settings
- uart_word_length_t word_length;
- uart_parity_t parity;
- uart_get_word_length(self->uart_num, &word_length);
- uart_get_parity(self->uart_num, &parity);
+ uint32_t baudrate;
+ uart_get_baudrate(self->uart_num, &baudrate);
- // Synthesise the break condition by either a longer word or using even parity
+ // Synthesise the break condition by reducing the baud rate,
+ // and cater for the worst case of 5 data bits, no parity.
uart_wait_tx_done(self->uart_num, pdMS_TO_TICKS(1000));
- if (word_length != UART_DATA_8_BITS) {
- uart_set_word_length(self->uart_num, UART_DATA_8_BITS);
- } else if (parity == UART_PARITY_DISABLE) {
- uart_set_parity(self->uart_num, UART_PARITY_EVEN);
- } else {
- // Cannot synthesise break
- mp_raise_OSError(MP_EPERM);
- }
+ uart_set_baudrate(self->uart_num, baudrate * 6 / 15);
char buf[1] = {0};
uart_write_bytes(self->uart_num, buf, 1);
uart_wait_tx_done(self->uart_num, pdMS_TO_TICKS(1000));
- // Restore original settings
- uart_set_word_length(self->uart_num, word_length);
- uart_set_parity(self->uart_num, parity);
+ // Restore original setting
+ uart_set_baudrate(self->uart_num, baudrate);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_uart_sendbreak_obj, machine_uart_sendbreak);
+STATIC mp_obj_t machine_uart_txdone(mp_obj_t self_in) {
+ machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in);
+
+ if (uart_wait_tx_done(self->uart_num, 0) == ESP_OK) {
+ return mp_const_true;
+ } else {
+ return mp_const_false;
+ }
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_uart_txdone_obj, machine_uart_txdone);
+
STATIC const mp_rom_map_elem_t machine_uart_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_uart_init_obj) },
{ MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_uart_deinit_obj) },
{ MP_ROM_QSTR(MP_QSTR_any), MP_ROM_PTR(&machine_uart_any_obj) },
+ { MP_ROM_QSTR(MP_QSTR_flush), MP_ROM_PTR(&mp_stream_flush_obj) },
{ MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) },
{ MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) },
{ MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) },
{ MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) },
{ MP_ROM_QSTR(MP_QSTR_sendbreak), MP_ROM_PTR(&machine_uart_sendbreak_obj) },
+ { MP_ROM_QSTR(MP_QSTR_txdone), MP_ROM_PTR(&machine_uart_txdone_obj) },
{ MP_ROM_QSTR(MP_QSTR_INV_TX), MP_ROM_INT(UART_INV_TX) },
{ MP_ROM_QSTR(MP_QSTR_INV_RX), MP_ROM_INT(UART_INV_RX) },
@@ -494,6 +504,18 @@ STATIC mp_uint_t machine_uart_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr
if ((flags & MP_STREAM_POLL_WR) && 1) { // FIXME: uart_tx_any_room(self->uart_num)
ret |= MP_STREAM_POLL_WR;
}
+ } else if (request == MP_STREAM_FLUSH) {
+ // The timeout is estimated using the buffer size and the baudrate.
+ // Take the worst case assumptions at 13 bit symbol size times 2.
+ uint32_t baudrate;
+ uart_get_baudrate(self->uart_num, &baudrate);
+ uint32_t timeout = (3 + self->txbuf) * 13000 * 2 / baudrate;
+ if (uart_wait_tx_done(self->uart_num, timeout) == ESP_OK) {
+ ret = 0;
+ } else {
+ *errcode = MP_ETIMEDOUT;
+ ret = MP_STREAM_ERROR;
+ }
} else {
*errcode = MP_EINVAL;
ret = MP_STREAM_ERROR;
@@ -508,13 +530,12 @@ STATIC const mp_stream_p_t uart_stream_p = {
.is_text = false,
};
-const mp_obj_type_t machine_uart_type = {
- { &mp_type_type },
- .name = MP_QSTR_UART,
- .print = machine_uart_print,
- .make_new = machine_uart_make_new,
- .getiter = mp_identity_getiter,
- .iternext = mp_stream_unbuffered_iter,
- .protocol = &uart_stream_p,
- .locals_dict = (mp_obj_dict_t *)&machine_uart_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ machine_uart_type,
+ MP_QSTR_UART,
+ MP_TYPE_FLAG_ITER_IS_STREAM,
+ make_new, machine_uart_make_new,
+ print, machine_uart_print,
+ protocol, &uart_stream_p,
+ locals_dict, &machine_uart_locals_dict
+ );
diff --git a/ports/esp32/machine_wdt.c b/ports/esp32/machine_wdt.c
index f0ec6928e05d..4ccf417b6099 100644
--- a/ports/esp32/machine_wdt.c
+++ b/ports/esp32/machine_wdt.c
@@ -83,9 +83,10 @@ STATIC const mp_rom_map_elem_t machine_wdt_locals_dict_table[] = {
};
STATIC MP_DEFINE_CONST_DICT(machine_wdt_locals_dict, machine_wdt_locals_dict_table);
-const mp_obj_type_t machine_wdt_type = {
- { &mp_type_type },
- .name = MP_QSTR_WDT,
- .make_new = machine_wdt_make_new,
- .locals_dict = (mp_obj_t)&machine_wdt_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ machine_wdt_type,
+ MP_QSTR_WDT,
+ MP_TYPE_FLAG_NONE,
+ make_new, machine_wdt_make_new,
+ locals_dict, &machine_wdt_locals_dict
+ );
diff --git a/ports/esp32/main.c b/ports/esp32/main.c
index 78bba0a9ab7d..821908d47c4c 100644
--- a/ports/esp32/main.c
+++ b/ports/esp32/main.c
@@ -161,7 +161,7 @@ void mp_task(void *pvParameter) {
#endif
// run boot-up scripts
- pyexec_frozen_module("_boot.py");
+ pyexec_frozen_module("_boot.py", false);
pyexec_file_if_exists("boot.py");
if (pyexec_mode_kind == PYEXEC_MODE_FRIENDLY_REPL) {
int ret = pyexec_file_if_exists("main.py");
@@ -215,7 +215,9 @@ void mp_task(void *pvParameter) {
// TODO: machine_rmt_deinit_all();
machine_pins_deinit();
machine_deinit();
+ #if MICROPY_PY_USOCKET_EVENTS
usocket_events_deinit();
+ #endif
mp_deinit();
fflush(stdout);
@@ -265,3 +267,5 @@ void *esp_native_code_commit(void *buf, size_t len, void *reloc) {
memcpy(p, buf, len);
return p;
}
+
+MP_REGISTER_ROOT_POINTER(mp_obj_t native_code_pointers);
diff --git a/ports/esp32/main/CMakeLists.txt b/ports/esp32/main/CMakeLists.txt
index 3a68c26ff5c0..b186cc1685bc 100644
--- a/ports/esp32/main/CMakeLists.txt
+++ b/ports/esp32/main/CMakeLists.txt
@@ -68,7 +68,7 @@ set(MICROPY_SOURCE_PORT
${PROJECT_DIR}/machine_i2s.c
${PROJECT_DIR}/machine_uart.c
${PROJECT_DIR}/modmachine.c
- ${PROJECT_DIR}/modnetwork.c
+ ${PROJECT_DIR}/network_common.c
${PROJECT_DIR}/network_lan.c
${PROJECT_DIR}/network_ppp.c
${PROJECT_DIR}/network_wlan.c
@@ -210,11 +210,15 @@ target_compile_options(${MICROPY_TARGET} PUBLIC
-Wno-missing-field-initializers
)
+# Additional include directories needed for private NimBLE headers.
+target_include_directories(${MICROPY_TARGET} PUBLIC
+ ${IDF_PATH}/components/bt/host/nimble/nimble
+)
+
# Add additional extmod and usermod components.
target_link_libraries(${MICROPY_TARGET} micropy_extmod_btree)
target_link_libraries(${MICROPY_TARGET} usermod)
-
# Collect all of the include directories and compile definitions for the IDF components.
foreach(comp ${IDF_COMPONENTS})
micropy_gather_target_properties(__idf_${comp})
diff --git a/ports/esp32/modesp.c b/ports/esp32/modesp.c
index 0c6429be7f1e..f125b614bda9 100644
--- a/ports/esp32/modesp.c
+++ b/ports/esp32/modesp.c
@@ -35,7 +35,6 @@
#include "py/runtime.h"
#include "py/mperrno.h"
#include "py/mphal.h"
-#include "drivers/dht/dht.h"
STATIC mp_obj_t esp_osdebug(size_t n_args, const mp_obj_t *args) {
esp_log_level_t level = LOG_LOCAL_LEVEL;
@@ -125,8 +124,6 @@ STATIC const mp_rom_map_elem_t esp_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_gpio_matrix_in), MP_ROM_PTR(&esp_gpio_matrix_in_obj) },
{ MP_ROM_QSTR(MP_QSTR_gpio_matrix_out), MP_ROM_PTR(&esp_gpio_matrix_out_obj) },
- { MP_ROM_QSTR(MP_QSTR_dht_readinto), MP_ROM_PTR(&dht_readinto_obj) },
-
// Constants for second arg of osdebug()
{ MP_ROM_QSTR(MP_QSTR_LOG_NONE), MP_ROM_INT((mp_uint_t)ESP_LOG_NONE)},
{ MP_ROM_QSTR(MP_QSTR_LOG_ERROR), MP_ROM_INT((mp_uint_t)ESP_LOG_ERROR)},
diff --git a/ports/esp32/modesp32.c b/ports/esp32/modesp32.c
index 0dbd7efda33b..017db36e22ad 100644
--- a/ports/esp32/modesp32.c
+++ b/ports/esp32/modesp32.c
@@ -131,6 +131,15 @@ STATIC mp_obj_t esp32_wake_on_ext1(size_t n_args, const mp_obj_t *pos_args, mp_m
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(esp32_wake_on_ext1_obj, 0, esp32_wake_on_ext1);
+STATIC mp_obj_t esp32_wake_on_ulp(const mp_obj_t wake) {
+ if (machine_rtc_config.ext0_pin != -1) {
+ mp_raise_ValueError(MP_ERROR_TEXT("no resources"));
+ }
+ machine_rtc_config.wake_on_ulp = mp_obj_is_true(wake);
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp32_wake_on_ulp_obj, esp32_wake_on_ulp);
+
STATIC mp_obj_t esp32_gpio_deep_sleep_hold(const mp_obj_t enable) {
if (mp_obj_is_true(enable)) {
gpio_deep_sleep_hold_en();
@@ -197,6 +206,7 @@ STATIC const mp_rom_map_elem_t esp32_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_wake_on_touch), MP_ROM_PTR(&esp32_wake_on_touch_obj) },
{ MP_ROM_QSTR(MP_QSTR_wake_on_ext0), MP_ROM_PTR(&esp32_wake_on_ext0_obj) },
{ MP_ROM_QSTR(MP_QSTR_wake_on_ext1), MP_ROM_PTR(&esp32_wake_on_ext1_obj) },
+ { MP_ROM_QSTR(MP_QSTR_wake_on_ulp), MP_ROM_PTR(&esp32_wake_on_ulp_obj) },
{ MP_ROM_QSTR(MP_QSTR_gpio_deep_sleep_hold), MP_ROM_PTR(&esp32_gpio_deep_sleep_hold_obj) },
#if CONFIG_IDF_TARGET_ESP32
{ MP_ROM_QSTR(MP_QSTR_raw_temperature), MP_ROM_PTR(&esp32_raw_temperature_obj) },
diff --git a/ports/esp32/modmachine.c b/ports/esp32/modmachine.c
index aee3be0e747f..37d4f424d421 100644
--- a/ports/esp32/modmachine.c
+++ b/ports/esp32/modmachine.c
@@ -49,6 +49,7 @@
#include "py/obj.h"
#include "py/runtime.h"
#include "shared/runtime/pyexec.h"
+#include "drivers/dht/dht.h"
#include "extmod/machine_bitstream.h"
#include "extmod/machine_mem.h"
#include "extmod/machine_signal.h"
@@ -82,8 +83,16 @@ STATIC mp_obj_t machine_freq(size_t n_args, const mp_obj_t *args) {
} else {
// set
mp_int_t freq = mp_obj_get_int(args[0]) / 1000000;
- if (freq != 20 && freq != 40 && freq != 80 && freq != 160 && freq != 240) {
+ if (freq != 20 && freq != 40 && freq != 80 && freq != 160
+ #if !CONFIG_IDF_TARGET_ESP32C3
+ && freq != 240
+ #endif
+ ) {
+ #if CONFIG_IDF_TARGET_ESP32C3
+ mp_raise_ValueError(MP_ERROR_TEXT("frequency must be 20MHz, 40MHz, 80Mhz or 160MHz"));
+ #else
mp_raise_ValueError(MP_ERROR_TEXT("frequency must be 20MHz, 40MHz, 80Mhz, 160MHz or 240MHz"));
+ #endif
}
#if CONFIG_IDF_TARGET_ESP32
esp_pm_config_esp32_t pm;
@@ -144,6 +153,12 @@ STATIC mp_obj_t machine_sleep_helper(wake_type_t wake_type, size_t n_args, const
}
}
+ if (machine_rtc_config.wake_on_ulp) {
+ if (esp_sleep_enable_ulp_wakeup() != ESP_OK) {
+ mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("esp_sleep_enable_ulp_wakeup() failed"));
+ }
+ }
+
#endif
switch (wake_type) {
@@ -281,6 +296,7 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = {
#if MICROPY_PY_MACHINE_PULSE
{ MP_ROM_QSTR(MP_QSTR_time_pulse_us), MP_ROM_PTR(&machine_time_pulse_us_obj) },
#endif
+ { MP_ROM_QSTR(MP_QSTR_dht_readinto), MP_ROM_PTR(&dht_readinto_obj) },
{ MP_ROM_QSTR(MP_QSTR_Timer), MP_ROM_PTR(&machine_timer_type) },
{ MP_ROM_QSTR(MP_QSTR_WDT), MP_ROM_PTR(&machine_wdt_type) },
@@ -293,7 +309,7 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_DEEPSLEEP), MP_ROM_INT(MACHINE_WAKE_DEEPSLEEP) },
{ MP_ROM_QSTR(MP_QSTR_Pin), MP_ROM_PTR(&machine_pin_type) },
{ MP_ROM_QSTR(MP_QSTR_Signal), MP_ROM_PTR(&machine_signal_type) },
- #if CONFIG_IDF_TARGET_ESP32
+ #if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
{ MP_ROM_QSTR(MP_QSTR_TouchPad), MP_ROM_PTR(&machine_touchpad_type) },
#endif
{ MP_ROM_QSTR(MP_QSTR_ADC), MP_ROM_PTR(&machine_adc_type) },
@@ -301,14 +317,14 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = {
#if MICROPY_PY_MACHINE_DAC
{ MP_ROM_QSTR(MP_QSTR_DAC), MP_ROM_PTR(&machine_dac_type) },
#endif
- { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&machine_hw_i2c_type) },
+ { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&machine_i2c_type) },
{ MP_ROM_QSTR(MP_QSTR_SoftI2C), MP_ROM_PTR(&mp_machine_soft_i2c_type) },
#if MICROPY_PY_MACHINE_I2S
{ MP_ROM_QSTR(MP_QSTR_I2S), MP_ROM_PTR(&machine_i2s_type) },
#endif
{ MP_ROM_QSTR(MP_QSTR_PWM), MP_ROM_PTR(&machine_pwm_type) },
{ MP_ROM_QSTR(MP_QSTR_RTC), MP_ROM_PTR(&machine_rtc_type) },
- { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&machine_hw_spi_type) },
+ { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&machine_spi_type) },
{ MP_ROM_QSTR(MP_QSTR_SoftSPI), MP_ROM_PTR(&mp_machine_soft_spi_type) },
{ MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&machine_uart_type) },
diff --git a/ports/esp32/modmachine.h b/ports/esp32/modmachine.h
index 4d2ab9020d16..138a89e9c33d 100644
--- a/ports/esp32/modmachine.h
+++ b/ports/esp32/modmachine.h
@@ -16,8 +16,8 @@ extern const mp_obj_type_t machine_touchpad_type;
extern const mp_obj_type_t machine_adc_type;
extern const mp_obj_type_t machine_adcblock_type;
extern const mp_obj_type_t machine_dac_type;
-extern const mp_obj_type_t machine_hw_i2c_type;
-extern const mp_obj_type_t machine_hw_spi_type;
+extern const mp_obj_type_t machine_i2c_type;
+extern const mp_obj_type_t machine_spi_type;
extern const mp_obj_type_t machine_i2s_type;
extern const mp_obj_type_t machine_uart_type;
extern const mp_obj_type_t machine_rtc_type;
diff --git a/ports/esp32/modnetwork.h b/ports/esp32/modnetwork.h
index 7bcfa0e6fcdb..5f2767ac8d4f 100644
--- a/ports/esp32/modnetwork.h
+++ b/ports/esp32/modnetwork.h
@@ -28,7 +28,8 @@
#include "esp_event.h"
-enum { PHY_LAN8720, PHY_IP101, PHY_RTL8201, PHY_DP83848, PHY_KSZ8041 };
+enum { PHY_LAN8710, PHY_LAN8720, PHY_IP101, PHY_RTL8201, PHY_DP83848, PHY_KSZ8041, PHY_KSZ8081, PHY_KSZ8851SNL = 100, PHY_DM9051, PHY_W5500 };
+#define IS_SPI_PHY(NUM) (NUM >= 100)
enum { ETH_INITIALIZED, ETH_STARTED, ETH_STOPPED, ETH_CONNECTED, ETH_DISCONNECTED, ETH_GOT_IP };
// Cases similar to ESP8266 user_interface.h
@@ -44,11 +45,13 @@ typedef struct _wlan_if_obj_t {
int if_id;
} wlan_if_obj_t;
-MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(get_wlan_obj);
-MP_DECLARE_CONST_FUN_OBJ_KW(get_lan_obj);
-MP_DECLARE_CONST_FUN_OBJ_1(ppp_make_new_obj);
-MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(esp_ifconfig_obj);
-MP_DECLARE_CONST_FUN_OBJ_KW(esp_config_obj);
+MP_DECLARE_CONST_FUN_OBJ_0(esp_network_initialize_obj);
+MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(esp_network_get_wlan_obj);
+MP_DECLARE_CONST_FUN_OBJ_KW(esp_network_get_lan_obj);
+MP_DECLARE_CONST_FUN_OBJ_1(esp_network_ppp_make_new_obj);
+MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(esp_network_ifconfig_obj);
+MP_DECLARE_CONST_FUN_OBJ_KW(esp_network_config_obj);
+MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(esp_network_phy_mode_obj);
NORETURN void esp_exceptions_helper(esp_err_t e);
diff --git a/ports/esp32/modnetwork_globals.h b/ports/esp32/modnetwork_globals.h
new file mode 100644
index 000000000000..72d1ff3afbbc
--- /dev/null
+++ b/ports/esp32/modnetwork_globals.h
@@ -0,0 +1,77 @@
+{ MP_ROM_QSTR(MP_QSTR___init__), MP_ROM_PTR(&esp_network_initialize_obj) },
+
+#if MICROPY_PY_NETWORK_WLAN
+{ MP_ROM_QSTR(MP_QSTR_WLAN), MP_ROM_PTR(&esp_network_get_wlan_obj) },
+#endif
+
+#if MICROPY_PY_NETWORK_LAN
+{ MP_ROM_QSTR(MP_QSTR_LAN), MP_ROM_PTR(&esp_network_get_lan_obj) },
+#endif
+{ MP_ROM_QSTR(MP_QSTR_PPP), MP_ROM_PTR(&esp_network_ppp_make_new_obj) },
+{ MP_ROM_QSTR(MP_QSTR_phy_mode), MP_ROM_PTR(&esp_network_phy_mode_obj) },
+
+#if MICROPY_PY_NETWORK_WLAN
+{ MP_ROM_QSTR(MP_QSTR_STA_IF), MP_ROM_INT(WIFI_IF_STA)},
+{ MP_ROM_QSTR(MP_QSTR_AP_IF), MP_ROM_INT(WIFI_IF_AP)},
+
+{ MP_ROM_QSTR(MP_QSTR_MODE_11B), MP_ROM_INT(WIFI_PROTOCOL_11B) },
+{ MP_ROM_QSTR(MP_QSTR_MODE_11G), MP_ROM_INT(WIFI_PROTOCOL_11G) },
+{ MP_ROM_QSTR(MP_QSTR_MODE_11N), MP_ROM_INT(WIFI_PROTOCOL_11N) },
+{ MP_ROM_QSTR(MP_QSTR_MODE_LR), MP_ROM_INT(WIFI_PROTOCOL_LR) },
+
+{ MP_ROM_QSTR(MP_QSTR_AUTH_OPEN), MP_ROM_INT(WIFI_AUTH_OPEN) },
+{ MP_ROM_QSTR(MP_QSTR_AUTH_WEP), MP_ROM_INT(WIFI_AUTH_WEP) },
+{ MP_ROM_QSTR(MP_QSTR_AUTH_WPA_PSK), MP_ROM_INT(WIFI_AUTH_WPA_PSK) },
+{ MP_ROM_QSTR(MP_QSTR_AUTH_WPA2_PSK), MP_ROM_INT(WIFI_AUTH_WPA2_PSK) },
+{ MP_ROM_QSTR(MP_QSTR_AUTH_WPA_WPA2_PSK), MP_ROM_INT(WIFI_AUTH_WPA_WPA2_PSK) },
+{ MP_ROM_QSTR(MP_QSTR_AUTH_WPA2_ENTERPRISE), MP_ROM_INT(WIFI_AUTH_WPA2_ENTERPRISE) },
+{ MP_ROM_QSTR(MP_QSTR_AUTH_WPA3_PSK), MP_ROM_INT(WIFI_AUTH_WPA3_PSK) },
+{ MP_ROM_QSTR(MP_QSTR_AUTH_WPA2_WPA3_PSK), MP_ROM_INT(WIFI_AUTH_WPA2_WPA3_PSK) },
+#if ESP_IDF_VERSION > ESP_IDF_VERSION_VAL(4, 3, 0)
+{ MP_ROM_QSTR(MP_QSTR_AUTH_WAPI_PSK), MP_ROM_INT(WIFI_AUTH_WAPI_PSK) },
+#endif
+{ MP_ROM_QSTR(MP_QSTR_AUTH_MAX), MP_ROM_INT(WIFI_AUTH_MAX) },
+#endif
+
+#if MICROPY_PY_NETWORK_LAN
+{ MP_ROM_QSTR(MP_QSTR_PHY_LAN8710), MP_ROM_INT(PHY_LAN8710) },
+{ MP_ROM_QSTR(MP_QSTR_PHY_LAN8720), MP_ROM_INT(PHY_LAN8720) },
+{ MP_ROM_QSTR(MP_QSTR_PHY_IP101), MP_ROM_INT(PHY_IP101) },
+{ MP_ROM_QSTR(MP_QSTR_PHY_RTL8201), MP_ROM_INT(PHY_RTL8201) },
+{ MP_ROM_QSTR(MP_QSTR_PHY_DP83848), MP_ROM_INT(PHY_DP83848) },
+#if ESP_IDF_VERSION_MINOR >= 3
+// PHY_KSZ8041 is new in ESP-IDF v4.3
+{ MP_ROM_QSTR(MP_QSTR_PHY_KSZ8041), MP_ROM_INT(PHY_KSZ8041) },
+#endif
+#if ESP_IDF_VERSION_MINOR >= 4
+// PHY_KSZ8081 is new in ESP-IDF v4.4
+{ MP_ROM_QSTR(MP_QSTR_PHY_KSZ8081), MP_ROM_INT(PHY_KSZ8081) },
+#endif
+
+#if CONFIG_ETH_SPI_ETHERNET_KSZ8851SNL
+{ MP_ROM_QSTR(MP_QSTR_PHY_KSZ8851SNL), MP_ROM_INT(PHY_KSZ8851SNL) },
+#endif
+#if CONFIG_ETH_SPI_ETHERNET_DM9051
+{ MP_ROM_QSTR(MP_QSTR_PHY_DM9051), MP_ROM_INT(PHY_DM9051) },
+#endif
+#if CONFIG_ETH_SPI_ETHERNET_W5500
+{ MP_ROM_QSTR(MP_QSTR_PHY_W5500), MP_ROM_INT(PHY_W5500) },
+#endif
+
+{ MP_ROM_QSTR(MP_QSTR_ETH_INITIALIZED), MP_ROM_INT(ETH_INITIALIZED)},
+{ MP_ROM_QSTR(MP_QSTR_ETH_STARTED), MP_ROM_INT(ETH_STARTED)},
+{ MP_ROM_QSTR(MP_QSTR_ETH_STOPPED), MP_ROM_INT(ETH_STOPPED)},
+{ MP_ROM_QSTR(MP_QSTR_ETH_CONNECTED), MP_ROM_INT(ETH_CONNECTED)},
+{ MP_ROM_QSTR(MP_QSTR_ETH_DISCONNECTED), MP_ROM_INT(ETH_DISCONNECTED)},
+{ MP_ROM_QSTR(MP_QSTR_ETH_GOT_IP), MP_ROM_INT(ETH_GOT_IP)},
+#endif
+
+{ MP_ROM_QSTR(MP_QSTR_STAT_IDLE), MP_ROM_INT(STAT_IDLE)},
+{ MP_ROM_QSTR(MP_QSTR_STAT_CONNECTING), MP_ROM_INT(STAT_CONNECTING)},
+{ MP_ROM_QSTR(MP_QSTR_STAT_GOT_IP), MP_ROM_INT(STAT_GOT_IP)},
+// Errors from the ESP-IDF
+{ MP_ROM_QSTR(MP_QSTR_STAT_NO_AP_FOUND), MP_ROM_INT(WIFI_REASON_NO_AP_FOUND)},
+{ MP_ROM_QSTR(MP_QSTR_STAT_WRONG_PASSWORD), MP_ROM_INT(WIFI_REASON_AUTH_FAIL)},
+{ MP_ROM_QSTR(MP_QSTR_STAT_BEACON_TIMEOUT), MP_ROM_INT(WIFI_REASON_BEACON_TIMEOUT)},
+{ MP_ROM_QSTR(MP_QSTR_STAT_ASSOC_FAIL), MP_ROM_INT(WIFI_REASON_ASSOC_FAIL)},
+{ MP_ROM_QSTR(MP_QSTR_STAT_HANDSHAKE_TIMEOUT), MP_ROM_INT(WIFI_REASON_HANDSHAKE_TIMEOUT)},
diff --git a/ports/esp32/modsocket.c b/ports/esp32/modsocket.c
index 819ea26e9800..9812eb347689 100644
--- a/ports/esp32/modsocket.c
+++ b/ports/esp32/modsocket.c
@@ -214,7 +214,7 @@ static int _socket_getaddrinfo2(const mp_obj_t host, const mp_obj_t portx, struc
};
mp_obj_t port = portx;
- if (mp_obj_is_small_int(port)) {
+ if (mp_obj_is_integer(port)) {
// This is perverse, because lwip_getaddrinfo promptly converts it back to an int, but
// that's the API we have to work with ...
port = mp_obj_str_binary_op(MP_BINARY_OP_MODULO, mp_obj_new_str_via_qstr("%s", 2), port);
@@ -552,7 +552,7 @@ mp_obj_t _socket_recvfrom(mp_obj_t self_in, mp_obj_t len_in,
}
vstr.len = ret;
- return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
+ return mp_obj_new_bytes_from_vstr(&vstr);
}
STATIC mp_obj_t socket_recv(mp_obj_t self_in, mp_obj_t len_in) {
@@ -785,13 +785,14 @@ STATIC const mp_stream_p_t socket_stream_p = {
.ioctl = socket_stream_ioctl
};
-STATIC const mp_obj_type_t socket_type = {
- { &mp_type_type },
- .name = MP_QSTR_socket,
- .make_new = socket_make_new,
- .protocol = &socket_stream_p,
- .locals_dict = (mp_obj_t)&socket_locals_dict,
-};
+STATIC MP_DEFINE_CONST_OBJ_TYPE(
+ socket_type,
+ MP_QSTR_socket,
+ MP_TYPE_FLAG_NONE,
+ make_new, socket_make_new,
+ protocol, &socket_stream_p,
+ locals_dict, &socket_locals_dict
+ );
STATIC mp_obj_t esp_socket_getaddrinfo(size_t n_args, const mp_obj_t *args) {
// TODO support additional args beyond the first two
diff --git a/ports/esp32/moduos.c b/ports/esp32/moduos.c
index f307a9ffe05b..bdfd19c5d20a 100644
--- a/ports/esp32/moduos.c
+++ b/ports/esp32/moduos.c
@@ -45,7 +45,7 @@ STATIC mp_obj_t mp_uos_urandom(mp_obj_t num) {
vstr.buf[i] = r;
r >>= 8;
}
- return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
+ return mp_obj_new_bytes_from_vstr(&vstr);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_uos_urandom_obj, mp_uos_urandom);
diff --git a/ports/esp32/mpconfigport.h b/ports/esp32/mpconfigport.h
index 066a19f754f5..300d8493e556 100644
--- a/ports/esp32/mpconfigport.h
+++ b/ports/esp32/mpconfigport.h
@@ -70,7 +70,11 @@
// extended modules
#ifndef MICROPY_PY_BLUETOOTH
#define MICROPY_PY_BLUETOOTH (1)
+#define MICROPY_PY_BLUETOOTH_USE_SYNC_EVENTS (1)
+#define MICROPY_PY_BLUETOOTH_USE_SYNC_EVENTS_WITH_INTERLOCK (1)
+#define MICROPY_PY_BLUETOOTH_SYNC_EVENT_STACK_SIZE (CONFIG_BT_NIMBLE_TASK_STACK_SIZE)
#define MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE (1)
+#define MICROPY_PY_BLUETOOTH_ENABLE_PAIRING_BONDING (1)
#define MICROPY_BLUETOOTH_NIMBLE (1)
#define MICROPY_BLUETOOTH_NIMBLE_BINDINGS_ONLY (1)
#endif
@@ -106,6 +110,20 @@
#ifndef MICROPY_PY_MACHINE_I2S
#define MICROPY_PY_MACHINE_I2S (1)
#endif
+#define MICROPY_PY_NETWORK (1)
+#ifndef MICROPY_PY_NETWORK_HOSTNAME_DEFAULT
+#if CONFIG_IDF_TARGET_ESP32
+#define MICROPY_PY_NETWORK_HOSTNAME_DEFAULT "mpy-esp32"
+#elif CONFIG_IDF_TARGET_ESP32S2
+#define MICROPY_PY_NETWORK_HOSTNAME_DEFAULT "mpy-esp32s2"
+#elif CONFIG_IDF_TARGET_ESP32S3
+#define MICROPY_PY_NETWORK_HOSTNAME_DEFAULT "mpy-esp32s3"
+#elif CONFIG_IDF_TARGET_ESP32C3
+#define MICROPY_PY_NETWORK_HOSTNAME_DEFAULT "mpy-esp32c3"
+#endif
+#endif
+#define MICROPY_PY_NETWORK_INCLUDEFILE "ports/esp32/modnetwork.h"
+#define MICROPY_PY_NETWORK_MODULE_GLOBALS_INCLUDEFILE "ports/esp32/modnetwork_globals.h"
#ifndef MICROPY_PY_NETWORK_WLAN
#define MICROPY_PY_NETWORK_WLAN (1)
#endif
@@ -119,7 +137,6 @@
#define MICROPY_PY_USSL_FINALISER (1)
#define MICROPY_PY_UWEBSOCKET (1)
#define MICROPY_PY_WEBREPL (1)
-#define MICROPY_PY_BTREE (1)
#define MICROPY_PY_ONEWIRE (1)
#define MICROPY_PY_UPLATFORM (1)
#define MICROPY_PY_USOCKET_EVENTS (MICROPY_PY_WEBREPL)
@@ -135,42 +152,9 @@
#define MICROPY_FATFS_RPATH (2)
#define MICROPY_FATFS_MAX_SS (4096)
#define MICROPY_FATFS_LFN_CODE_PAGE 437 /* 1=SFN/ANSI 437=LFN/U.S.(OEM) */
-#define mp_type_fileio mp_type_vfs_fat_fileio
-#define mp_type_textio mp_type_vfs_fat_textio
#define MP_STATE_PORT MP_STATE_VM
-struct _machine_timer_obj_t;
-
-#if MICROPY_PY_LVGL
-#ifndef MICROPY_INCLUDED_PY_MPSTATE_H
-#define MICROPY_INCLUDED_PY_MPSTATE_H
-#include "lib/lv_bindings/lvgl/src/misc/lv_gc.h"
-#undef MICROPY_INCLUDED_PY_MPSTATE_H
-#else
-#include "lib/lv_bindings/lvgl/src/misc/lv_gc.h"
-#endif
-#else
-#define LV_ROOTS
-#endif
-
-#if MICROPY_BLUETOOTH_NIMBLE
-struct mp_bluetooth_nimble_root_pointers_t;
-#define MICROPY_PORT_ROOT_POINTER_BLUETOOTH_NIMBLE struct _mp_bluetooth_nimble_root_pointers_t *bluetooth_nimble_root_pointers;
-#else
-#define MICROPY_PORT_ROOT_POINTER_BLUETOOTH_NIMBLE
-#endif
-
-#define MICROPY_PORT_ROOT_POINTERS \
- LV_ROOTS \
- void *mp_lv_user_data; \
- const char *readline_hist[8]; \
- mp_obj_t machine_pin_irq_handler[40]; \
- struct _machine_timer_obj_t *machine_timer_obj_head; \
- struct _machine_i2s_obj_t *machine_i2s_obj[I2S_NUM_MAX]; \
- mp_obj_t native_code_pointers; \
- MICROPY_PORT_ROOT_POINTER_BLUETOOTH_NIMBLE
-
// type definitions for the specific machine
#define MICROPY_MAKE_POINTER_CALLABLE(p) ((void *)((mp_uint_t)(p)))
@@ -251,3 +235,21 @@ typedef long mp_off_t;
#endif
void boardctrl_startup(void);
+
+#ifndef MICROPY_PY_NETWORK_LAN
+#if (ESP_IDF_VERSION_MAJOR == 4) && (ESP_IDF_VERSION_MINOR >= 1) && (CONFIG_IDF_TARGET_ESP32 || (CONFIG_ETH_USE_SPI_ETHERNET && (CONFIG_ETH_SPI_ETHERNET_KSZ8851SNL || CONFIG_ETH_SPI_ETHERNET_DM9051 || CONFIG_ETH_SPI_ETHERNET_W5500)))
+#define MICROPY_PY_NETWORK_LAN (1)
+#else
+#define MICROPY_PY_NETWORK_LAN (0)
+#endif
+#endif
+
+#if MICROPY_PY_NETWORK_LAN && CONFIG_ETH_USE_SPI_ETHERNET
+#ifndef MICROPY_PY_NETWORK_LAN_SPI_CLOCK_SPEED_MZ
+#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C2
+#define MICROPY_PY_NETWORK_LAN_SPI_CLOCK_SPEED_MZ (12)
+#else
+#define MICROPY_PY_NETWORK_LAN_SPI_CLOCK_SPEED_MZ (36)
+#endif
+#endif
+#endif
diff --git a/ports/esp32/mphalport.c b/ports/esp32/mphalport.c
index aab534937e13..b187b422d50b 100644
--- a/ports/esp32/mphalport.c
+++ b/ports/esp32/mphalport.c
@@ -88,6 +88,9 @@ uintptr_t mp_hal_stdio_poll(uintptr_t poll_flags) {
if ((poll_flags & MP_STREAM_POLL_RD) && stdin_ringbuf.iget != stdin_ringbuf.iput) {
ret |= MP_STREAM_POLL_RD;
}
+ if (poll_flags & MP_STREAM_POLL_WR) {
+ ret |= MP_STREAM_POLL_WR;
+ }
return ret;
}
@@ -130,7 +133,7 @@ uint32_t mp_hal_ticks_us(void) {
}
void mp_hal_delay_ms(uint32_t ms) {
- uint64_t us = ms * 1000;
+ uint64_t us = (uint64_t)ms * 1000ULL;
uint64_t dt;
uint64_t t0 = esp_timer_get_time();
for (;;) {
@@ -139,7 +142,7 @@ void mp_hal_delay_ms(uint32_t ms) {
MP_THREAD_GIL_EXIT();
uint64_t t1 = esp_timer_get_time();
dt = t1 - t0;
- if (dt + portTICK_PERIOD_MS * 1000 >= us) {
+ if (dt + portTICK_PERIOD_MS * 1000ULL >= us) {
// doing a vTaskDelay would take us beyond requested delay time
taskYIELD();
MP_THREAD_GIL_ENTER();
diff --git a/ports/esp32/mphalport.h b/ports/esp32/mphalport.h
index c838bd228420..672fa306f5dc 100644
--- a/ports/esp32/mphalport.h
+++ b/ports/esp32/mphalport.h
@@ -35,6 +35,8 @@
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
+#include "driver/spi_master.h"
+
#define MICROPY_PLATFORM_VERSION "IDF" IDF_VER
// The core that the MicroPython task(s) are pinned to.
@@ -42,7 +44,9 @@
// and avoid the Wifi/BLE timing problems on the same core.
// Best effort here to remain backwards compatible in rare version edge cases...
// See https://github.com/micropython/micropython/issues/5489 for history
-#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0)
+#if CONFIG_FREERTOS_UNICORE
+#define MP_TASK_COREID (0)
+#elif ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0)
#define MP_TASK_COREID (1)
#else
#define MP_TASK_COREID (0)
@@ -111,4 +115,6 @@ static inline void mp_hal_pin_write(mp_hal_pin_obj_t pin, int v) {
gpio_set_level(pin, v);
}
+spi_host_device_t machine_hw_spi_get_host(mp_obj_t in);
+
#endif // INCLUDED_MPHALPORT_H
diff --git a/ports/esp32/modnetwork.c b/ports/esp32/network_common.c
similarity index 69%
rename from ports/esp32/modnetwork.c
rename to ports/esp32/network_common.c
index 45231c42307c..1e76d679db04 100644
--- a/ports/esp32/modnetwork.c
+++ b/ports/esp32/network_common.c
@@ -48,8 +48,6 @@
#define DNS_MAIN ESP_NETIF_DNS_MAIN
#endif
-#define MODNETWORK_INCLUDE_CONSTANTS (1)
-
NORETURN void esp_exceptions_helper(esp_err_t e) {
switch (e) {
case ESP_ERR_WIFI_NOT_INIT:
@@ -144,7 +142,7 @@ STATIC mp_obj_t esp_initialize() {
}
return mp_const_none;
}
-STATIC MP_DEFINE_CONST_FUN_OBJ_0(esp_initialize_obj, esp_initialize);
+MP_DEFINE_CONST_FUN_OBJ_0(esp_network_initialize_obj, esp_initialize);
STATIC mp_obj_t esp_ifconfig(size_t n_args, const mp_obj_t *args) {
wlan_if_obj_t *self = MP_OBJ_TO_PTR(args[0]);
@@ -207,12 +205,12 @@ STATIC mp_obj_t esp_ifconfig(size_t n_args, const mp_obj_t *args) {
return mp_const_none;
}
}
-MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_ifconfig_obj, 1, 2, esp_ifconfig);
+MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_network_ifconfig_obj, 1, 2, esp_ifconfig);
STATIC mp_obj_t esp_phy_mode(size_t n_args, const mp_obj_t *args) {
return mp_const_none;
}
-STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_phy_mode_obj, 0, 1, esp_phy_mode);
+MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_network_phy_mode_obj, 0, 1, esp_phy_mode);
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 3, 0)
#define TEST_WIFI_AUTH_MAX 9
@@ -220,82 +218,3 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_phy_mode_obj, 0, 1, esp_phy_mode)
#define TEST_WIFI_AUTH_MAX 8
#endif
_Static_assert(WIFI_AUTH_MAX == TEST_WIFI_AUTH_MAX, "Synchronize WIFI_AUTH_XXX constants with the ESP-IDF. Look at esp-idf/components/esp_wifi/include/esp_wifi_types.h");
-
-STATIC const mp_rom_map_elem_t mp_module_network_globals_table[] = {
- { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_network) },
- { MP_ROM_QSTR(MP_QSTR___init__), MP_ROM_PTR(&esp_initialize_obj) },
-
- #if MICROPY_PY_NETWORK_WLAN
- { MP_ROM_QSTR(MP_QSTR_WLAN), MP_ROM_PTR(&get_wlan_obj) },
- #endif
-
- #if (ESP_IDF_VERSION_MAJOR == 4) && (ESP_IDF_VERSION_MINOR >= 1) && (CONFIG_IDF_TARGET_ESP32)
- { MP_ROM_QSTR(MP_QSTR_LAN), MP_ROM_PTR(&get_lan_obj) },
- #endif
- { MP_ROM_QSTR(MP_QSTR_PPP), MP_ROM_PTR(&ppp_make_new_obj) },
- { MP_ROM_QSTR(MP_QSTR_phy_mode), MP_ROM_PTR(&esp_phy_mode_obj) },
-
- #if MODNETWORK_INCLUDE_CONSTANTS
-
- #if MICROPY_PY_NETWORK_WLAN
- { MP_ROM_QSTR(MP_QSTR_STA_IF), MP_ROM_INT(WIFI_IF_STA)},
- { MP_ROM_QSTR(MP_QSTR_AP_IF), MP_ROM_INT(WIFI_IF_AP)},
-
- { MP_ROM_QSTR(MP_QSTR_MODE_11B), MP_ROM_INT(WIFI_PROTOCOL_11B) },
- { MP_ROM_QSTR(MP_QSTR_MODE_11G), MP_ROM_INT(WIFI_PROTOCOL_11G) },
- { MP_ROM_QSTR(MP_QSTR_MODE_11N), MP_ROM_INT(WIFI_PROTOCOL_11N) },
-
- { MP_ROM_QSTR(MP_QSTR_AUTH_OPEN), MP_ROM_INT(WIFI_AUTH_OPEN) },
- { MP_ROM_QSTR(MP_QSTR_AUTH_WEP), MP_ROM_INT(WIFI_AUTH_WEP) },
- { MP_ROM_QSTR(MP_QSTR_AUTH_WPA_PSK), MP_ROM_INT(WIFI_AUTH_WPA_PSK) },
- { MP_ROM_QSTR(MP_QSTR_AUTH_WPA2_PSK), MP_ROM_INT(WIFI_AUTH_WPA2_PSK) },
- { MP_ROM_QSTR(MP_QSTR_AUTH_WPA_WPA2_PSK), MP_ROM_INT(WIFI_AUTH_WPA_WPA2_PSK) },
- { MP_ROM_QSTR(MP_QSTR_AUTH_WPA2_ENTERPRISE), MP_ROM_INT(WIFI_AUTH_WPA2_ENTERPRISE) },
- { MP_ROM_QSTR(MP_QSTR_AUTH_WPA3_PSK), MP_ROM_INT(WIFI_AUTH_WPA3_PSK) },
- { MP_ROM_QSTR(MP_QSTR_AUTH_WPA2_WPA3_PSK), MP_ROM_INT(WIFI_AUTH_WPA2_WPA3_PSK) },
- #if ESP_IDF_VERSION > ESP_IDF_VERSION_VAL(4, 3, 0)
- { MP_ROM_QSTR(MP_QSTR_AUTH_WAPI_PSK), MP_ROM_INT(WIFI_AUTH_WAPI_PSK) },
- #endif
- { MP_ROM_QSTR(MP_QSTR_AUTH_MAX), MP_ROM_INT(WIFI_AUTH_MAX) },
- #endif
-
- #if (ESP_IDF_VERSION_MAJOR == 4) && (ESP_IDF_VERSION_MINOR >= 1) && (CONFIG_IDF_TARGET_ESP32)
- { MP_ROM_QSTR(MP_QSTR_PHY_LAN8720), MP_ROM_INT(PHY_LAN8720) },
- { MP_ROM_QSTR(MP_QSTR_PHY_IP101), MP_ROM_INT(PHY_IP101) },
- { MP_ROM_QSTR(MP_QSTR_PHY_RTL8201), MP_ROM_INT(PHY_RTL8201) },
- { MP_ROM_QSTR(MP_QSTR_PHY_DP83848), MP_ROM_INT(PHY_DP83848) },
- #if ESP_IDF_VERSION_MINOR >= 3
- // PHY_KSZ8041 is new in ESP-IDF v4.3
- { MP_ROM_QSTR(MP_QSTR_PHY_KSZ8041), MP_ROM_INT(PHY_KSZ8041) },
- #endif
-
- { MP_ROM_QSTR(MP_QSTR_ETH_INITIALIZED), MP_ROM_INT(ETH_INITIALIZED)},
- { MP_ROM_QSTR(MP_QSTR_ETH_STARTED), MP_ROM_INT(ETH_STARTED)},
- { MP_ROM_QSTR(MP_QSTR_ETH_STOPPED), MP_ROM_INT(ETH_STOPPED)},
- { MP_ROM_QSTR(MP_QSTR_ETH_CONNECTED), MP_ROM_INT(ETH_CONNECTED)},
- { MP_ROM_QSTR(MP_QSTR_ETH_DISCONNECTED), MP_ROM_INT(ETH_DISCONNECTED)},
- { MP_ROM_QSTR(MP_QSTR_ETH_GOT_IP), MP_ROM_INT(ETH_GOT_IP)},
- #endif
-
- { MP_ROM_QSTR(MP_QSTR_STAT_IDLE), MP_ROM_INT(STAT_IDLE)},
- { MP_ROM_QSTR(MP_QSTR_STAT_CONNECTING), MP_ROM_INT(STAT_CONNECTING)},
- { MP_ROM_QSTR(MP_QSTR_STAT_GOT_IP), MP_ROM_INT(STAT_GOT_IP)},
- // Errors from the ESP-IDF
- { MP_ROM_QSTR(MP_QSTR_STAT_NO_AP_FOUND), MP_ROM_INT(WIFI_REASON_NO_AP_FOUND)},
- { MP_ROM_QSTR(MP_QSTR_STAT_WRONG_PASSWORD), MP_ROM_INT(WIFI_REASON_AUTH_FAIL)},
- { MP_ROM_QSTR(MP_QSTR_STAT_BEACON_TIMEOUT), MP_ROM_INT(WIFI_REASON_BEACON_TIMEOUT)},
- { MP_ROM_QSTR(MP_QSTR_STAT_ASSOC_FAIL), MP_ROM_INT(WIFI_REASON_ASSOC_FAIL)},
- { MP_ROM_QSTR(MP_QSTR_STAT_HANDSHAKE_TIMEOUT), MP_ROM_INT(WIFI_REASON_HANDSHAKE_TIMEOUT)},
- #endif
-};
-
-STATIC MP_DEFINE_CONST_DICT(mp_module_network_globals, mp_module_network_globals_table);
-
-const mp_obj_module_t mp_module_network = {
- .base = { &mp_type_module },
- .globals = (mp_obj_dict_t *)&mp_module_network_globals,
-};
-
-// Note: This port doesn't define MICROPY_PY_NETWORK so this will not conflict
-// with the common implementation provided by extmod/modnetwork.c.
-MP_REGISTER_MODULE(MP_QSTR_network, mp_module_network);
diff --git a/ports/esp32/network_lan.c b/ports/esp32/network_lan.c
index f302d70fec1d..9b7a31cc4f9d 100644
--- a/ports/esp32/network_lan.c
+++ b/ports/esp32/network_lan.c
@@ -33,13 +33,16 @@
#include "esp_idf_version.h"
// LAN only for ESP32 (not ESP32S2) and only for ESP-IDF v4.1 and higher
-#if (ESP_IDF_VERSION_MAJOR == 4) && (ESP_IDF_VERSION_MINOR >= 1) && (CONFIG_IDF_TARGET_ESP32)
+#if MICROPY_PY_NETWORK_LAN
#include "esp_eth.h"
#include "esp_eth_mac.h"
#include "esp_event.h"
#include "esp_log.h"
#include "esp_netif.h"
+#if CONFIG_ETH_USE_SPI_ETHERNET
+#include "driver/spi_master.h"
+#endif
#include "modnetwork.h"
@@ -48,9 +51,11 @@ typedef struct _lan_if_obj_t {
int if_id; // MUST BE FIRST to match wlan_if_obj_t
bool initialized;
bool active;
- uint8_t mdc_pin;
- uint8_t mdio_pin;
+ int8_t mdc_pin;
+ int8_t mdio_pin;
int8_t phy_power_pin;
+ int8_t phy_cs_pin;
+ int8_t phy_int_pin;
uint8_t phy_addr;
uint8_t phy_type;
esp_eth_phy_t *phy;
@@ -97,14 +102,23 @@ STATIC mp_obj_t get_lan(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_ar
return MP_OBJ_FROM_PTR(&lan_obj);
}
- enum { ARG_id, ARG_mdc, ARG_mdio, ARG_power, ARG_phy_addr, ARG_phy_type };
+ enum { ARG_id, ARG_mdc, ARG_mdio, ARG_power, ARG_phy_addr, ARG_phy_type,
+ ARG_spi, ARG_cs, ARG_int, ARG_ref_clk_mode, ARG_ref_clk };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_id, MP_ARG_OBJ, {.u_obj = mp_const_none} },
- { MP_QSTR_mdc, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_OBJ },
- { MP_QSTR_mdio, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_OBJ },
+ { MP_QSTR_mdc, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
+ { MP_QSTR_mdio, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
{ MP_QSTR_power, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
{ MP_QSTR_phy_addr, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_INT },
{ MP_QSTR_phy_type, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_INT },
+ { MP_QSTR_spi, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
+ { MP_QSTR_cs, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
+ { MP_QSTR_int, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
+ #if ESP_IDF_VERSION_MINOR >= 4
+ // Dynamic ref_clk configuration available at v4.4
+ { MP_QSTR_ref_clk_mode, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
+ { MP_QSTR_ref_clk, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
+ #endif
};
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
@@ -116,36 +130,99 @@ STATIC mp_obj_t get_lan(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_ar
}
}
- self->mdc_pin = machine_pin_get_id(args[ARG_mdc].u_obj);
- self->mdio_pin = machine_pin_get_id(args[ARG_mdio].u_obj);
- self->phy_power_pin = args[ARG_power].u_obj == mp_const_none ? -1 : machine_pin_get_id(args[ARG_power].u_obj);
+ #define GET_PIN(XXX) args[XXX].u_obj == mp_const_none ? -1 : machine_pin_get_id(args[XXX].u_obj);
+
+ self->mdc_pin = GET_PIN(ARG_mdc);
+ self->mdio_pin = GET_PIN(ARG_mdio);
+ self->phy_power_pin = GET_PIN(ARG_power);
+ self->phy_cs_pin = GET_PIN(ARG_cs);
+ self->phy_int_pin = GET_PIN(ARG_int);
if (args[ARG_phy_addr].u_int < 0x00 || args[ARG_phy_addr].u_int > 0x1f) {
mp_raise_ValueError(MP_ERROR_TEXT("invalid phy address"));
}
self->phy_addr = args[ARG_phy_addr].u_int;
- if (args[ARG_phy_type].u_int != PHY_LAN8720 &&
+ if (args[ARG_phy_type].u_int != PHY_LAN8710 &&
+ args[ARG_phy_type].u_int != PHY_LAN8720 &&
args[ARG_phy_type].u_int != PHY_IP101 &&
args[ARG_phy_type].u_int != PHY_RTL8201 &&
#if ESP_IDF_VERSION_MINOR >= 3 // KSZ8041 is new in ESP-IDF v4.3
args[ARG_phy_type].u_int != PHY_KSZ8041 &&
#endif
+ #if ESP_IDF_VERSION_MINOR >= 4 // KSZ8081 is new in ESP-IDF v4.4
+ args[ARG_phy_type].u_int != PHY_KSZ8081 &&
+ #endif
+ #if CONFIG_ETH_USE_SPI_ETHERNET
+ #if CONFIG_ETH_SPI_ETHERNET_KSZ8851SNL
+ args[ARG_phy_type].u_int != PHY_KSZ8851SNL &&
+ #endif
+ #if CONFIG_ETH_SPI_ETHERNET_DM9051
+ args[ARG_phy_type].u_int != PHY_DM9051 &&
+ #endif
+ #if CONFIG_ETH_SPI_ETHERNET_W5500
+ args[ARG_phy_type].u_int != PHY_W5500 &&
+ #endif
+ #endif
args[ARG_phy_type].u_int != PHY_DP83848) {
mp_raise_ValueError(MP_ERROR_TEXT("invalid phy type"));
}
eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG();
- mac_config.smi_mdc_gpio_num = self->mdc_pin;
- mac_config.smi_mdio_gpio_num = self->mdio_pin;
- esp_eth_mac_t *mac = esp_eth_mac_new_esp32(&mac_config);
+ esp_eth_mac_t *mac = NULL;
+
+ // Dynamic ref_clk configuration available at v4.4
+ #if ESP_IDF_VERSION_MINOR >= 4
+ if (args[ARG_ref_clk_mode].u_int != -1) {
+ // Map the GPIO_MODE constants to EMAC_CLK constants.
+ mac_config.clock_config.rmii.clock_mode =
+ args[ARG_ref_clk_mode].u_int == GPIO_MODE_INPUT ? EMAC_CLK_EXT_IN : EMAC_CLK_OUT;
+ }
+ if (args[ARG_ref_clk].u_obj != mp_const_none) {
+ mac_config.clock_config.rmii.clock_gpio = machine_pin_get_id(args[ARG_ref_clk].u_obj);
+ }
+ #endif
eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG();
phy_config.phy_addr = self->phy_addr;
phy_config.reset_gpio_num = self->phy_power_pin;
self->phy = NULL;
+ #if CONFIG_ETH_USE_SPI_ETHERNET
+ spi_device_handle_t spi_handle = NULL;
+ if (IS_SPI_PHY(args[ARG_phy_type].u_int)) {
+ spi_device_interface_config_t devcfg = {
+ .mode = 0,
+ .clock_speed_hz = MICROPY_PY_NETWORK_LAN_SPI_CLOCK_SPEED_MZ * 1000 * 1000,
+ .queue_size = 20,
+ .spics_io_num = self->phy_cs_pin,
+ };
+ switch (args[ARG_phy_type].u_int) {
+ #if CONFIG_ETH_SPI_ETHERNET_DM9051
+ case PHY_DM9051: {
+ devcfg.command_bits = 1;
+ devcfg.address_bits = 7;
+ break;
+ }
+ #endif
+ #if CONFIG_ETH_SPI_ETHERNET_W5500
+ case PHY_W5500: {
+ devcfg.command_bits = 16;
+ devcfg.address_bits = 8;
+ break;
+ }
+ #endif
+ }
+ spi_host_device_t host = machine_hw_spi_get_host(args[ARG_spi].u_obj);
+ if (spi_bus_add_device(host, &devcfg, &spi_handle) != ESP_OK) {
+ mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("spi_bus_add_device failed"));
+ }
+ }
+ #endif
+
switch (args[ARG_phy_type].u_int) {
+ #if CONFIG_IDF_TARGET_ESP32
+ case PHY_LAN8710:
case PHY_LAN8720:
self->phy = esp_eth_phy_new_lan8720(&phy_config);
break;
@@ -158,15 +235,59 @@ STATIC mp_obj_t get_lan(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_ar
case PHY_DP83848:
self->phy = esp_eth_phy_new_dp83848(&phy_config);
break;
+ #if ESP_IDF_VERSION_MINOR >= 3 // KSZ8041 is new in ESP-IDF v4.3
case PHY_KSZ8041:
- #if ESP_IDF_VERSION_MINOR >= 3 // KSZ8041 is new in ESP-IDF v4.3
self->phy = esp_eth_phy_new_ksz8041(&phy_config);
break;
- #endif
- default:
- mp_raise_ValueError(MP_ERROR_TEXT("unknown phy"));
+ #endif
+ #if ESP_IDF_VERSION_MINOR >= 4 // KSZ8081 is new in ESP-IDF v4.4
+ case PHY_KSZ8081:
+ self->phy = esp_eth_phy_new_ksz8081(&phy_config);
+ break;
+ #endif
+ #endif
+ #if CONFIG_ETH_USE_SPI_ETHERNET
+ #if CONFIG_ETH_SPI_ETHERNET_KSZ8851SNL
+ case PHY_KSZ8851SNL: {
+ eth_ksz8851snl_config_t chip_config = ETH_KSZ8851SNL_DEFAULT_CONFIG(spi_handle);
+ chip_config.int_gpio_num = self->phy_int_pin;
+ mac = esp_eth_mac_new_ksz8851snl(&chip_config, &mac_config);
+ self->phy = esp_eth_phy_new_ksz8851snl(&phy_config);
+ break;
+ }
+ #endif
+ #if CONFIG_ETH_SPI_ETHERNET_DM9051
+ case PHY_DM9051: {
+ eth_dm9051_config_t chip_config = ETH_DM9051_DEFAULT_CONFIG(spi_handle);
+ chip_config.int_gpio_num = self->phy_int_pin;
+ mac = esp_eth_mac_new_dm9051(&chip_config, &mac_config);
+ self->phy = esp_eth_phy_new_dm9051(&phy_config);
+ break;
+ }
+ #endif
+ #if CONFIG_ETH_SPI_ETHERNET_W5500
+ case PHY_W5500: {
+ eth_w5500_config_t chip_config = ETH_W5500_DEFAULT_CONFIG(spi_handle);
+ chip_config.int_gpio_num = self->phy_int_pin;
+ mac = esp_eth_mac_new_w5500(&chip_config, &mac_config);
+ self->phy = esp_eth_phy_new_w5500(&phy_config);
+ break;
+ }
+ #endif
+ #endif
}
+ #if CONFIG_IDF_TARGET_ESP32
+ if (!IS_SPI_PHY(args[ARG_phy_type].u_int)) {
+ if (self->mdc_pin == -1 || self->mdio_pin == -1) {
+ mp_raise_ValueError(MP_ERROR_TEXT("mdc and mdio must be specified"));
+ }
+ mac_config.smi_mdc_gpio_num = self->mdc_pin;
+ mac_config.smi_mdio_gpio_num = self->mdio_pin;
+ mac = esp_eth_mac_new_esp32(&mac_config);
+ }
+ #endif
+
if (esp_netif_init() != ESP_OK) {
mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("esp_netif_init failed"));
}
@@ -210,7 +331,7 @@ STATIC mp_obj_t get_lan(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_ar
return MP_OBJ_FROM_PTR(&lan_obj);
}
-MP_DEFINE_CONST_FUN_OBJ_KW(get_lan_obj, 0, get_lan);
+MP_DEFINE_CONST_FUN_OBJ_KW(esp_network_get_lan_obj, 0, get_lan);
STATIC mp_obj_t lan_active(size_t n_args, const mp_obj_t *args) {
lan_if_obj_t *self = MP_OBJ_TO_PTR(args[0]);
@@ -261,7 +382,12 @@ STATIC mp_obj_t lan_config(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs
if (bufinfo.len != 6) {
mp_raise_ValueError(MP_ERROR_TEXT("invalid buffer length"));
}
- esp_eth_ioctl(self->eth_handle, ETH_CMD_S_MAC_ADDR, bufinfo.buf);
+ if (
+ (esp_eth_ioctl(self->eth_handle, ETH_CMD_S_MAC_ADDR, bufinfo.buf) != ESP_OK) ||
+ (esp_netif_set_mac(self->eth_netif, bufinfo.buf) != ESP_OK)
+ ) {
+ mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("failed setting MAC address"));
+ }
break;
}
default:
@@ -297,15 +423,16 @@ STATIC const mp_rom_map_elem_t lan_if_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_isconnected), MP_ROM_PTR(&lan_isconnected_obj) },
{ MP_ROM_QSTR(MP_QSTR_status), MP_ROM_PTR(&lan_status_obj) },
{ MP_ROM_QSTR(MP_QSTR_config), MP_ROM_PTR(&lan_config_obj) },
- { MP_ROM_QSTR(MP_QSTR_ifconfig), MP_ROM_PTR(&esp_ifconfig_obj) },
+ { MP_ROM_QSTR(MP_QSTR_ifconfig), MP_ROM_PTR(&esp_network_ifconfig_obj) },
};
STATIC MP_DEFINE_CONST_DICT(lan_if_locals_dict, lan_if_locals_dict_table);
-const mp_obj_type_t lan_if_type = {
- { &mp_type_type },
- .name = MP_QSTR_LAN,
- .locals_dict = (mp_obj_dict_t *)&lan_if_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ lan_if_type,
+ MP_QSTR_LAN,
+ MP_TYPE_FLAG_NONE,
+ locals_dict, &lan_if_locals_dict
+ );
#endif
diff --git a/ports/esp32/network_ppp.c b/ports/esp32/network_ppp.c
index d74283c19cf6..b3cab835981e 100644
--- a/ports/esp32/network_ppp.c
+++ b/ports/esp32/network_ppp.c
@@ -91,7 +91,7 @@ STATIC mp_obj_t ppp_make_new(mp_obj_t stream) {
return MP_OBJ_FROM_PTR(self);
}
-MP_DEFINE_CONST_FUN_OBJ_1(ppp_make_new_obj, ppp_make_new);
+MP_DEFINE_CONST_FUN_OBJ_1(esp_network_ppp_make_new_obj, ppp_make_new);
static u32_t ppp_output_callback(ppp_pcb *pcb, u8_t *data, u32_t len, void *ctx) {
ppp_if_obj_t *self = ctx;
@@ -278,8 +278,9 @@ STATIC const mp_rom_map_elem_t ppp_if_locals_dict_table[] = {
};
STATIC MP_DEFINE_CONST_DICT(ppp_if_locals_dict, ppp_if_locals_dict_table);
-const mp_obj_type_t ppp_if_type = {
- { &mp_type_type },
- .name = MP_QSTR_PPP,
- .locals_dict = (mp_obj_dict_t *)&ppp_if_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ ppp_if_type,
+ MP_QSTR_PPP,
+ MP_TYPE_FLAG_NONE,
+ locals_dict, &ppp_if_locals_dict
+ );
diff --git a/ports/esp32/network_wlan.c b/ports/esp32/network_wlan.c
index 58c898d9a46e..aefc4394c2ac 100644
--- a/ports/esp32/network_wlan.c
+++ b/ports/esp32/network_wlan.c
@@ -35,6 +35,8 @@
#include "py/objlist.h"
#include "py/runtime.h"
+#include "py/mphal.h"
+#include "extmod/modnetwork.h"
#include "modnetwork.h"
#include "esp_wifi.h"
@@ -47,9 +49,8 @@
#error WIFI_MODE_STA and WIFI_MODE_AP are supposed to be bitfields!
#endif
-STATIC const mp_obj_type_t wlan_if_type;
-STATIC const wlan_if_obj_t wlan_sta_obj = {{&wlan_if_type}, WIFI_IF_STA};
-STATIC const wlan_if_obj_t wlan_ap_obj = {{&wlan_if_type}, WIFI_IF_AP};
+STATIC const wlan_if_obj_t wlan_sta_obj;
+STATIC const wlan_if_obj_t wlan_ap_obj;
// Set to "true" if esp_wifi_start() was called
static bool wifi_started = false;
@@ -91,12 +92,8 @@ void network_wlan_event_handler(system_event_t *event) {
if (!mdns_initialised) {
mdns_init();
#if MICROPY_HW_ENABLE_MDNS_RESPONDER
- const char *hostname = NULL;
- if (tcpip_adapter_get_hostname(WIFI_IF_STA, &hostname) != ESP_OK || hostname == NULL) {
- hostname = "esp32";
- }
- mdns_hostname_set(hostname);
- mdns_instance_name_set(hostname);
+ mdns_hostname_set(mod_network_hostname);
+ mdns_instance_name_set(mod_network_hostname);
#endif
mdns_initialised = true;
}
@@ -182,7 +179,7 @@ STATIC mp_obj_t get_wlan(size_t n_args, const mp_obj_t *args) {
mp_raise_ValueError(MP_ERROR_TEXT("invalid WLAN interface identifier"));
}
}
-MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(get_wlan_obj, 0, 1, get_wlan);
+MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_network_get_wlan_obj, 0, 1, get_wlan);
STATIC mp_obj_t network_wlan_active(size_t n_args, const mp_obj_t *args) {
wlan_if_obj_t *self = MP_OBJ_TO_PTR(args[0]);
@@ -211,6 +208,12 @@ STATIC mp_obj_t network_wlan_active(size_t n_args, const mp_obj_t *args) {
wifi_started = true;
}
}
+ // This delay is a band-aid patch for issues #8289, #8792 and #9236,
+ // allowing the esp data structures to settle. It looks like some
+ // kind of race condition, which is not yet found. But at least
+ // this small delay seems not hurt much, since wlan.active() is
+ // usually not called in a time critical part of the code.
+ mp_hal_delay_ms(1);
}
return (mode & bit) ? mp_const_true : mp_const_false;
@@ -218,7 +221,7 @@ STATIC mp_obj_t network_wlan_active(size_t n_args, const mp_obj_t *args) {
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(network_wlan_active_obj, 1, 2, network_wlan_active);
STATIC mp_obj_t network_wlan_connect(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
- enum { ARG_ssid, ARG_password, ARG_bssid };
+ enum { ARG_ssid, ARG_key, ARG_bssid };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_, MP_ARG_OBJ, {.u_obj = mp_const_none} },
{ MP_QSTR_, MP_ARG_OBJ, {.u_obj = mp_const_none} },
@@ -239,8 +242,8 @@ STATIC mp_obj_t network_wlan_connect(size_t n_args, const mp_obj_t *pos_args, mp
p = mp_obj_str_get_data(args[ARG_ssid].u_obj, &len);
memcpy(wifi_sta_config.sta.ssid, p, MIN(len, sizeof(wifi_sta_config.sta.ssid)));
}
- if (args[ARG_password].u_obj != mp_const_none) {
- p = mp_obj_str_get_data(args[ARG_password].u_obj, &len);
+ if (args[ARG_key].u_obj != mp_const_none) {
+ p = mp_obj_str_get_data(args[ARG_key].u_obj, &len);
memcpy(wifi_sta_config.sta.password, p, MIN(len, sizeof(wifi_sta_config.sta.password)));
}
if (args[ARG_bssid].u_obj != mp_const_none) {
@@ -254,6 +257,8 @@ STATIC mp_obj_t network_wlan_connect(size_t n_args, const mp_obj_t *pos_args, mp
esp_exceptions(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_sta_config));
}
+ esp_exceptions(tcpip_adapter_set_hostname(TCPIP_ADAPTER_IF_STA, mod_network_hostname));
+
wifi_sta_reconnects = 0;
// connect to the WiFi AP
MP_THREAD_GIL_EXIT();
@@ -345,6 +350,12 @@ STATIC mp_obj_t network_wlan_scan(mp_obj_t self_in) {
if (status == 0) {
uint16_t count = 0;
esp_exceptions(esp_wifi_scan_get_ap_num(&count));
+ if (count == 0) {
+ // esp_wifi_scan_get_ap_records must be called to free internal buffers from the scan.
+ // But it returns an error if wifi_ap_records==NULL. So allocate at least 1 AP entry.
+ // esp_wifi_scan_get_ap_records will then return the actual number of APs in count.
+ count = 1;
+ }
wifi_ap_record_t *wifi_ap_records = calloc(count, sizeof(wifi_ap_record_t));
esp_exceptions(esp_wifi_scan_get_ap_records(&count, wifi_ap_records));
for (uint16_t i = 0; i < count; i++) {
@@ -410,6 +421,7 @@ STATIC mp_obj_t network_wlan_config(size_t n_args, const mp_obj_t *args, mp_map_
esp_exceptions(esp_wifi_set_mac(self->if_id, bufinfo.buf));
break;
}
+ case MP_QSTR_ssid:
case MP_QSTR_essid: {
req_if = WIFI_IF_AP;
size_t len;
@@ -424,11 +436,13 @@ STATIC mp_obj_t network_wlan_config(size_t n_args, const mp_obj_t *args, mp_map_
cfg.ap.ssid_hidden = mp_obj_is_true(kwargs->table[i].value);
break;
}
+ case MP_QSTR_security:
case MP_QSTR_authmode: {
req_if = WIFI_IF_AP;
cfg.ap.authmode = mp_obj_get_int(kwargs->table[i].value);
break;
}
+ case MP_QSTR_key:
case MP_QSTR_password: {
req_if = WIFI_IF_AP;
size_t len;
@@ -439,13 +453,33 @@ STATIC mp_obj_t network_wlan_config(size_t n_args, const mp_obj_t *args, mp_map_
break;
}
case MP_QSTR_channel: {
- req_if = WIFI_IF_AP;
- cfg.ap.channel = mp_obj_get_int(kwargs->table[i].value);
+ uint8_t primary;
+ wifi_second_chan_t secondary;
+ // Get the current value of secondary
+ esp_exceptions(esp_wifi_get_channel(&primary, &secondary));
+ primary = mp_obj_get_int(kwargs->table[i].value);
+ esp_err_t err = esp_wifi_set_channel(primary, secondary);
+ if (err == ESP_ERR_INVALID_ARG) {
+ // May need to swap secondary channel above to below or below to above
+ secondary = (
+ (secondary == WIFI_SECOND_CHAN_ABOVE)
+ ? WIFI_SECOND_CHAN_BELOW
+ : (secondary == WIFI_SECOND_CHAN_BELOW)
+ ? WIFI_SECOND_CHAN_ABOVE
+ : WIFI_SECOND_CHAN_NONE);
+ esp_exceptions(esp_wifi_set_channel(primary, secondary));
+ }
break;
}
+ case MP_QSTR_hostname:
case MP_QSTR_dhcp_hostname: {
- const char *s = mp_obj_str_get_str(kwargs->table[i].value);
- esp_exceptions(tcpip_adapter_set_hostname(self->if_id, s));
+ // TODO: Deprecated. Use network.hostname(name) instead.
+ size_t len;
+ const char *str = mp_obj_str_get_data(kwargs->table[i].value, &len);
+ if (len >= MICROPY_PY_NETWORK_HOSTNAME_MAX_LEN) {
+ mp_raise_ValueError(NULL);
+ }
+ strcpy(mod_network_hostname, str);
break;
}
case MP_QSTR_max_clients: {
@@ -466,6 +500,10 @@ STATIC mp_obj_t network_wlan_config(size_t n_args, const mp_obj_t *args, mp_map_
esp_exceptions(esp_wifi_set_max_tx_power(power));
break;
}
+ case MP_QSTR_protocol: {
+ esp_exceptions(esp_wifi_set_protocol(self->if_id, mp_obj_get_int(kwargs->table[i].value)));
+ break;
+ }
default:
goto unknown;
}
@@ -503,6 +541,7 @@ STATIC mp_obj_t network_wlan_config(size_t n_args, const mp_obj_t *args, mp_map_
goto unknown;
}
}
+ case MP_QSTR_ssid:
case MP_QSTR_essid:
switch (self->if_id) {
case WIFI_IF_STA:
@@ -519,18 +558,23 @@ STATIC mp_obj_t network_wlan_config(size_t n_args, const mp_obj_t *args, mp_map_
req_if = WIFI_IF_AP;
val = mp_obj_new_bool(cfg.ap.ssid_hidden);
break;
+ case MP_QSTR_security:
case MP_QSTR_authmode:
req_if = WIFI_IF_AP;
val = MP_OBJ_NEW_SMALL_INT(cfg.ap.authmode);
break;
- case MP_QSTR_channel:
- req_if = WIFI_IF_AP;
- val = MP_OBJ_NEW_SMALL_INT(cfg.ap.channel);
+ case MP_QSTR_channel: {
+ uint8_t channel;
+ wifi_second_chan_t second;
+ esp_exceptions(esp_wifi_get_channel(&channel, &second));
+ val = MP_OBJ_NEW_SMALL_INT(channel);
break;
+ }
+ case MP_QSTR_hostname:
case MP_QSTR_dhcp_hostname: {
- const char *s;
- esp_exceptions(tcpip_adapter_get_hostname(self->if_id, &s));
- val = mp_obj_new_str(s, strlen(s));
+ // TODO: Deprecated. Use network.hostname() instead.
+ req_if = WIFI_IF_STA;
+ val = mp_obj_new_str(mod_network_hostname, strlen(mod_network_hostname));
break;
}
case MP_QSTR_max_clients: {
@@ -548,6 +592,12 @@ STATIC mp_obj_t network_wlan_config(size_t n_args, const mp_obj_t *args, mp_map_
val = mp_obj_new_float(power * 0.25);
break;
}
+ case MP_QSTR_protocol: {
+ uint8_t protocol_bitmap;
+ esp_exceptions(esp_wifi_get_protocol(self->if_id, &protocol_bitmap));
+ val = MP_OBJ_NEW_SMALL_INT(protocol_bitmap);
+ break;
+ }
default:
goto unknown;
}
@@ -572,14 +622,18 @@ STATIC const mp_rom_map_elem_t wlan_if_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_scan), MP_ROM_PTR(&network_wlan_scan_obj) },
{ MP_ROM_QSTR(MP_QSTR_isconnected), MP_ROM_PTR(&network_wlan_isconnected_obj) },
{ MP_ROM_QSTR(MP_QSTR_config), MP_ROM_PTR(&network_wlan_config_obj) },
- { MP_ROM_QSTR(MP_QSTR_ifconfig), MP_ROM_PTR(&esp_ifconfig_obj) },
+ { MP_ROM_QSTR(MP_QSTR_ifconfig), MP_ROM_PTR(&esp_network_ifconfig_obj) },
};
STATIC MP_DEFINE_CONST_DICT(wlan_if_locals_dict, wlan_if_locals_dict_table);
-STATIC const mp_obj_type_t wlan_if_type = {
- { &mp_type_type },
- .name = MP_QSTR_WLAN,
- .locals_dict = (mp_obj_t)&wlan_if_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ wlan_if_type,
+ MP_QSTR_WLAN,
+ MP_TYPE_FLAG_NONE,
+ locals_dict, &wlan_if_locals_dict
+ );
+
+STATIC const wlan_if_obj_t wlan_sta_obj = {{&wlan_if_type}, WIFI_IF_STA};
+STATIC const wlan_if_obj_t wlan_ap_obj = {{&wlan_if_type}, WIFI_IF_AP};
#endif // MICROPY_PY_NETWORK_WLAN
diff --git a/ports/esp32/partitions-32MiB-ota.csv b/ports/esp32/partitions-32MiB-ota.csv
new file mode 100644
index 000000000000..7366a2ad8df7
--- /dev/null
+++ b/ports/esp32/partitions-32MiB-ota.csv
@@ -0,0 +1,10 @@
+# Partition table for MicroPython with OTA support using 32MB flash
+# Notes: the offset of the partition table itself is set in
+# $IDF_PATH/components/partition_table/Kconfig.projbuild.
+# Name, Type, SubType, Offset, Size, Flags
+nvs, data, nvs, 0x9000, 0x4000,
+otadata, data, ota, 0xd000, 0x2000,
+phy_init, data, phy, 0xf000, 0x1000,
+ota_0, app, ota_0, 0x10000, 0x270000,
+ota_1, app, ota_1, 0x280000, 0x270000,
+vfs, data, fat, 0x4f0000, 0x1B10000,
diff --git a/ports/esp32/partitions-32MiB.csv b/ports/esp32/partitions-32MiB.csv
new file mode 100644
index 000000000000..31591c99495f
--- /dev/null
+++ b/ports/esp32/partitions-32MiB.csv
@@ -0,0 +1,7 @@
+# Notes: the offset of the partition table itself is set in
+# $IDF_PATH/components/partition_table/Kconfig.projbuild.
+# Name, Type, SubType, Offset, Size, Flags
+nvs, data, nvs, 0x9000, 0x6000,
+phy_init, data, phy, 0xf000, 0x1000,
+factory, app, factory, 0x10000, 0x1F0000,
+vfs, data, fat, 0x200000, 0x1E00000,
diff --git a/ports/esp32/usb.c b/ports/esp32/usb.c
index 5a613d24412c..80612cd276e7 100644
--- a/ports/esp32/usb.c
+++ b/ports/esp32/usb.c
@@ -36,7 +36,6 @@
#define CDC_ITF TINYUSB_CDC_ACM_0
static uint8_t usb_rx_buf[CONFIG_USB_CDC_RX_BUFSIZE];
-static uint8_t usb_cdc_connected;
static void usb_callback_rx(int itf, cdcacm_event_t *event) {
// TODO: what happens if more chars come in during this function, are they lost?
@@ -59,13 +58,6 @@ static void usb_callback_rx(int itf, cdcacm_event_t *event) {
}
}
-void usb_callback_line_state_changed(int itf, cdcacm_event_t *event) {
- int dtr = event->line_state_changed_data.dtr;
- int rts = event->line_state_changed_data.rts;
- // If dtr && rts are both true, the CDC is connected to a HOST.
- usb_cdc_connected = dtr && rts;
-}
-
void usb_init(void) {
// Initialise the USB with defaults.
tinyusb_config_t tusb_cfg = {0};
@@ -78,17 +70,17 @@ void usb_init(void) {
.rx_unread_buf_sz = 256,
.callback_rx = &usb_callback_rx,
.callback_rx_wanted_char = NULL,
- .callback_line_state_changed = &usb_callback_line_state_changed,
+ .callback_line_state_changed = NULL,
.callback_line_coding_changed = NULL
};
- usb_cdc_connected = 0;
ESP_ERROR_CHECK(tusb_cdc_acm_init(&amc_cfg));
}
void usb_tx_strn(const char *str, size_t len) {
// Write out the data to the CDC interface, but only while the USB host is connected.
- while (usb_cdc_connected && len) {
+ uint64_t timeout = esp_timer_get_time() + (uint64_t)(MICROPY_HW_USB_CDC_TX_TIMEOUT * 1000);
+ while (tud_cdc_n_connected(CDC_ITF) && len && esp_timer_get_time() < timeout) {
size_t l = tinyusb_cdcacm_write_queue(CDC_ITF, (uint8_t *)str, len);
str += l;
len -= l;
diff --git a/ports/esp32/usb.h b/ports/esp32/usb.h
index a1037803337f..009bf42624d9 100644
--- a/ports/esp32/usb.h
+++ b/ports/esp32/usb.h
@@ -26,6 +26,8 @@
#ifndef MICROPY_INCLUDED_ESP32_USB_H
#define MICROPY_INCLUDED_ESP32_USB_H
+#define MICROPY_HW_USB_CDC_TX_TIMEOUT (500)
+
void usb_init(void);
void usb_tx_strn(const char *str, size_t len);
diff --git a/ports/esp8266/Makefile b/ports/esp8266/Makefile
index 705f4f1eeb71..fb994c752ed7 100644
--- a/ports/esp8266/Makefile
+++ b/ports/esp8266/Makefile
@@ -1,15 +1,21 @@
-# Select the board to build for: if not given on the command line,
-# then default to GENERIC.
+# Select the board to build for:
+ifdef BOARD_DIR
+# Custom board path - remove trailing slash and get the final component of
+# the path as the board name.
+BOARD ?= $(notdir $(BOARD_DIR:/=))
+else
+# If not given on the command line, then default to GENERIC.
BOARD ?= GENERIC
-
-# If the build directory is not given, make it reflect the board name.
-BUILD ?= build-$(BOARD)
-
BOARD_DIR ?= boards/$(BOARD)
+endif
+
ifeq ($(wildcard $(BOARD_DIR)/.),)
$(error Invalid BOARD specified: $(BOARD_DIR))
endif
+# If the build directory is not given, make it reflect the board name.
+BUILD ?= build-$(BOARD)
+
include ../../py/mkenv.mk
# Optional
@@ -30,8 +36,9 @@ FROZEN_MANIFEST ?= boards/manifest.py
# include py core make definitions
include $(TOP)/py/py.mk
+include $(TOP)/extmod/extmod.mk
-GIT_SUBMODULES = lib/axtls lib/berkeley-db-1.xx
+GIT_SUBMODULES += lib/axtls lib/berkeley-db-1.xx
FWBIN = $(BUILD)/firmware-combined.bin
PORT ?= /dev/ttyACM0
@@ -56,19 +63,19 @@ CFLAGS_XTENSA = -fsingle-precision-constant -Wdouble-promotion \
-Wl,-EL -mlongcalls -mtext-section-literals -mforce-l32 \
-DLWIP_OPEN_SRC
-CFLAGS = $(INC) -Wall -Wpointer-arith -Werror -std=gnu99 -nostdlib -DUART_OS=$(UART_OS) \
- $(CFLAGS_XTENSA) $(CFLAGS_MOD) $(COPT) $(CFLAGS_EXTRA) -I$(BOARD_DIR)
+CFLAGS += $(INC) -Wall -Wpointer-arith -Werror -std=gnu99 -nostdlib -DUART_OS=$(UART_OS) \
+ $(CFLAGS_XTENSA) $(COPT) $(CFLAGS_EXTRA) -I$(BOARD_DIR)
LD_FILES ?= boards/esp8266_2m.ld
-LDFLAGS = -nostdlib -T $(LD_FILES) -Map=$(@:.elf=.map) --cref
-LIBS = -L$(ESP_SDK)/lib -lmain -ljson -llwip_open -lpp -lnet80211 -lwpa -lphy -lnet80211 $(LDFLAGS_MOD)
+LDFLAGS += -nostdlib -T $(LD_FILES) -Map=$(@:.elf=.map) --cref
+LIBS += -L$(ESP_SDK)/lib -lmain -ljson -llwip_open -lpp -lnet80211 -lwpa -lphy -lnet80211
LIBGCC_FILE_NAME = $(shell $(CC) $(CFLAGS) -print-libgcc-file-name)
LIBS += -L$(dir $(LIBGCC_FILE_NAME)) -lgcc
# Debugging/Optimization
+CFLAGS += -g # always include debug info in the ELF
ifeq ($(DEBUG), 1)
-CFLAGS += -g
COPT = -O0
else
CFLAGS += -fdata-sections -ffunction-sections
@@ -99,19 +106,13 @@ SRC_C = \
machine_wdt.c \
machine_hspi.c \
modesp.c \
- modnetwork.c \
modutime.c \
+ network_wlan.c \
ets_alt_task.c \
fatfs_port.c \
posix_helpers.c \
hspi.c \
$(wildcard $(BOARD_DIR)/*.c) \
- $(SRC_MOD)
-
-EXTMOD_SRC_C = $(addprefix extmod/,\
- modlwip.c \
- modonewire.c \
- )
LIB_SRC_C = $(addprefix lib/,\
libm/math.c \
@@ -163,17 +164,15 @@ DRIVERS_SRC_C = $(addprefix drivers/,\
SRC_S = \
gchelper.s \
-OBJ =
OBJ += $(PY_O)
OBJ += $(addprefix $(BUILD)/, $(SRC_C:.c=.o))
OBJ += $(addprefix $(BUILD)/, $(SRC_S:.s=.o))
-OBJ += $(addprefix $(BUILD)/, $(EXTMOD_SRC_C:.c=.o))
OBJ += $(addprefix $(BUILD)/, $(SHARED_SRC_C:.c=.o))
OBJ += $(addprefix $(BUILD)/, $(LIB_SRC_C:.c=.o))
OBJ += $(addprefix $(BUILD)/, $(DRIVERS_SRC_C:.c=.o))
# List of sources for qstr extraction
-SRC_QSTR += $(SRC_C) $(EXTMOD_SRC_C) $(SHARED_SRC_C) $(DRIVERS_SRC_C)
+SRC_QSTR += $(SRC_C) $(SHARED_SRC_C)
# Append any auto-generated sources that are needed by sources listed in SRC_QSTR
SRC_QSTR_AUTO_DEPS +=
diff --git a/ports/esp8266/README.md b/ports/esp8266/README.md
index 15ca7f891c26..1e0cae213937 100644
--- a/ports/esp8266/README.md
+++ b/ports/esp8266/README.md
@@ -1,10 +1,9 @@
MicroPython port to ESP8266
===========================
-This is an experimental port of MicroPython for the WiFi modules based
-on Espressif ESP8266 chip.
-
-WARNING: The port is experimental and many APIs are subject to change.
+This is a port of MicroPython to the Espressif ESP8266 WiFi microcontroller.
+MicroPython runs on this chip without any underlying operating system, using
+the ESP8266 NONOS SDK.
Supported features include:
- REPL (Python prompt) over UART0.
@@ -27,52 +26,106 @@ Documentation is available at http://docs.micropython.org/en/latest/esp8266/quic
Build instructions
------------------
-You need the esp-open-sdk toolchain (which provides both the compiler and libraries), which
-you can obtain using one of the following two options:
+You need the esp-open-sdk toolchain, which provides both the compiler and libraries.
- - Use a Docker image with a pre-built toolchain (**recommended**).
- To use this, install Docker, then prepend
- `docker run --rm -v $HOME:$HOME -u $UID -w $PWD larsks/esp-open-sdk ` to the start
- of the mpy-cross and firmware `make` commands below. This will run the commands using the
- toolchain inside the container but using the files on your local filesystem.
+There are two ways to do this:
+ - By running the toolchain in [Docker](https://www.docker.com/) (**recommended**).
+ - By installing a pre-built toolchain and adding it to your `$PATH`.
- - or, install the esp-open-sdk directly on your PC, which can be found at
- . Clone this repository and
- run `make` in its directory to build and install the SDK locally. Make sure
- to add toolchain bin directory to your PATH. Read esp-open-sdk's README for
- additional important information on toolchain setup.
- If you use this approach, then the command below will work exactly.
+Regardless of which toolchain you use, the first step is to make sure required
+submodules are available:
-Add the external dependencies to the MicroPython repository checkout:
```bash
$ make -C ports/esp8266 submodules
```
+
See the README in the repository root for more information about external
dependencies.
-The MicroPython cross-compiler must be built to pre-compile some of the
-built-in scripts to bytecode. This can be done using:
+__Building with Docker__
+
+Once you have installed Docker, you can run all of the following build
+commands inside the Docker container by prefixing them with `docker
+run --rm -v $HOME:$HOME -u $UID -w $PWD larsks/esp-open-sdk ...command...`.
+This will automatically download the Docker image provided by @larsks which
+contains the full toolchain and SDK.
+
+Then you need to compile the MicroPython cross-compiler (`mpy-cross`). From
+the root of this repository, run:
+
```bash
-$ make -C mpy-cross
+$ docker run --rm -v $HOME:$HOME -u $UID -w $PWD larsks/esp-open-sdk make -C mpy-cross
+```
+
+**Note:** The `mpy-cross` binary will likely only work inside the Docker
+container. This will not be a problem if you're only building ESP8266
+firmware, but if you're also working on other ports then you will need to
+recompile for your host when switching between ports. To avoid this, use
+the local toolchain instead.
+
+Then to compile the ESP8266 firmware:
+
```
-(Prepend the Docker command if using Docker, see above)
+$ cd ports/esp8266
+$ docker run --rm -v $HOME:$HOME -u $UID -w $PWD larsks/esp-open-sdk make -j BOARD=GENERIC
+```
+
+This will produce binary images in the `build-GENERIC/` subdirectory.
+Substitute the board for whichever board you're using.
+
+__Building with a local toolchain__
+
+First download the pre-built toolchain (thanks to @jepler from Adafruit). You
+will need to find somewhere to put it in your filesystem, e.g. `~/espressif`.
+Create that directory first if necessary.
+
+```
+$ cd ~/espressif # Change as necessary
+$ wget https://github.com/jepler/esp-open-sdk/releases/download/2018-06-10/xtensa-lx106-elf-standalone.tar.gz
+$ tar zxvf xtensa-lx106-elf-standalone.tar.gz
+$ rm xtensa-lx106-elf/bin/esptool.py # Use system version of esptool.py instead.
+```
+
+Then append this to your `$PATH` variable so the compiler binaries can be
+found:
+
+```
+$ export "PATH=$HOME/espressif/xtensa-lx106-elf/bin/:$PATH"
+```
+
+(You will need to do this each time you start a new terminal)
+
+Then you need to compile the MicroPython cross-compiler (`mpy-cross`). From
+the root of this repository, run:
-Then, to build MicroPython for the ESP8266, just run:
```bash
+$ make -C mpy-cross
+```
+
+Then to compile the ESP8266 firmware:
+
+```
$ cd ports/esp8266
-$ make
+$ make -j BOARD=GENERIC
```
-(Prepend the Docker command if using Docker, see above)
-This will produce binary images in the `build-GENERIC/` subdirectory. If you
-install MicroPython to your module for the first time, or after installing any
-other firmware, you should erase flash completely:
+This will produce binary images in the `build-GENERIC/` subdirectory.
+Substitute the board for whichever board you're using.
+
+
+Installing MicroPython
+----------------------
+
+To communicate with the board you will need to install `esptool.py`. This can
+be obtained from your system package manager or from PyPi via `pip`.
+
+If you install MicroPython to your module for the first time, or after
+installing any other firmware, you should erase flash completely:
+
```bash
$ esptool.py --port /dev/ttyXXX erase_flash
```
-You can install esptool.py either from your system package manager or from PyPi.
-
Erasing the flash is also useful as a troubleshooting measure, if a module doesn't
behave as expected.
@@ -80,7 +133,9 @@ To flash MicroPython image to your ESP8266, use:
```bash
$ make deploy
```
-(This should not be run inside Docker as it will need access to the serial port.)
+
+(If using the Docker instructions above, do not run this command via Docker as
+it will need access to the serial port. Run it directly instead.)
This will use the `esptool.py` script to download the images. You must have
your ESP module in the bootloader mode, and connected to a serial port on your PC.
@@ -144,20 +199,22 @@ Python prompt over WiFi, connecting through a browser.
- GitHub repository https://github.com/micropython/webrepl.
Please follow the instructions there.
-__upip__
+__mip__
-The ESP8266 port comes with builtin `upip` package manager, which can
-be used to install additional modules (see the main README for more
-information):
+The ESP8266 port comes with the built-in `mip` package manager, which can
+be used to install additional modules:
```
->>> import upip
->>> upip.install("micropython-pystone_lowmem")
+>>> import mip
+>>> mip.install("hmac")
[...]
->>> import pystone_lowmem
->>> pystone_lowmem.main()
+>>> import hmac
+>>> hmac.new(b"1234567890", msg="hello world").hexdigest()
```
+See [Package management](https://docs.micropython.org/en/latest/reference/packages.html) for more
+information about `mip`.
+
Downloading and installing packages may requite a lot of free memory,
if you get an error, retry immediately after the hard reset.
diff --git a/ports/esp8266/boards/GENERIC/manifest.py b/ports/esp8266/boards/GENERIC/manifest.py
index 9ce3ffe3aae1..ef708846241f 100644
--- a/ports/esp8266/boards/GENERIC/manifest.py
+++ b/ports/esp8266/boards/GENERIC/manifest.py
@@ -2,20 +2,18 @@
include("$(PORT_DIR)/boards/manifest.py")
# uasyncio
-include("$(MPY_DIR)/extmod/uasyncio/manifest.py")
+include("$(MPY_DIR)/extmod/uasyncio")
# drivers
-freeze("$(MPY_DIR)/drivers/display", "ssd1306.py")
+require("ssd1306")
-# Libraries from micropython-lib, include only if the library directory exists
-if os.path.isdir(convert_path("$(MPY_LIB_DIR)")):
- # file utilities
- freeze("$(MPY_LIB_DIR)/micropython/upysh", "upysh.py")
+# micropython-lib: file utilities
+require("upysh")
- # requests
- freeze("$(MPY_LIB_DIR)/python-ecosys/urequests", "urequests.py")
- freeze("$(MPY_LIB_DIR)/micropython/urllib.urequest", "urllib/urequest.py")
+# micropython-lib: requests
+require("urequests")
+require("urllib.urequest")
- # umqtt
- freeze("$(MPY_LIB_DIR)/micropython/umqtt.simple", "umqtt/simple.py")
- freeze("$(MPY_LIB_DIR)/micropython/umqtt.robust", "umqtt/robust.py")
+# micropython-lib: umqtt
+require("umqtt.simple")
+require("umqtt.robust")
diff --git a/ports/esp8266/boards/GENERIC/mpconfigboard.h b/ports/esp8266/boards/GENERIC/mpconfigboard.h
index e4991ba97090..1d9b8e6f70dd 100644
--- a/ports/esp8266/boards/GENERIC/mpconfigboard.h
+++ b/ports/esp8266/boards/GENERIC/mpconfigboard.h
@@ -11,12 +11,4 @@
#define MICROPY_READER_VFS (MICROPY_VFS)
#define MICROPY_VFS (1)
-#define MICROPY_PY_FSTRINGS (1)
-#define MICROPY_PY_BUILTINS_SLICE_ATTRS (1)
-#define MICROPY_PY_ALL_SPECIAL_METHODS (1)
-#define MICROPY_PY_IO_FILEIO (1)
-#define MICROPY_PY_SYS_STDIO_BUFFER (1)
-#define MICROPY_PY_UASYNCIO (1)
-#define MICROPY_PY_URE_SUB (1)
#define MICROPY_PY_UCRYPTOLIB (1)
-#define MICROPY_PY_FRAMEBUF (1)
diff --git a/ports/esp8266/boards/GENERIC_1M/mpconfigboard.h b/ports/esp8266/boards/GENERIC_1M/mpconfigboard.h
index ed50729936b7..cf5127686cc2 100644
--- a/ports/esp8266/boards/GENERIC_1M/mpconfigboard.h
+++ b/ports/esp8266/boards/GENERIC_1M/mpconfigboard.h
@@ -11,10 +11,7 @@
#define MICROPY_READER_VFS (MICROPY_VFS)
#define MICROPY_VFS (1)
-#define MICROPY_PY_BUILTINS_SLICE_ATTRS (1)
-#define MICROPY_PY_ALL_SPECIAL_METHODS (1)
-#define MICROPY_PY_IO_FILEIO (1)
-#define MICROPY_PY_SYS_STDIO_BUFFER (1)
-#define MICROPY_PY_URE_SUB (1)
+#define MICROPY_PY_FSTRINGS (0)
+#define MICROPY_PY_REVERSE_SPECIAL_METHODS (0)
+#define MICROPY_PY_UASYNCIO (0)
#define MICROPY_PY_UCRYPTOLIB (1)
-#define MICROPY_PY_FRAMEBUF (1)
diff --git a/ports/esp8266/boards/GENERIC_512K/manifest.py b/ports/esp8266/boards/GENERIC_512K/manifest.py
index ee148c80892d..15f6cffc3f94 100644
--- a/ports/esp8266/boards/GENERIC_512K/manifest.py
+++ b/ports/esp8266/boards/GENERIC_512K/manifest.py
@@ -1,6 +1,9 @@
-freeze("$(BOARD_DIR)", "_boot.py", opt=3)
-freeze("$(PORT_DIR)/modules", ("apa102.py", "ntptime.py", "port_diag.py"))
-freeze("$(MPY_DIR)/drivers/dht", "dht.py")
-freeze("$(MPY_DIR)/drivers/onewire")
-include("$(MPY_DIR)/extmod/webrepl/manifest.py")
-include("$(MPY_DIR)/drivers/neopixel/manifest.py")
+module("_boot.py", opt=3)
+module("apa102.py", base_path="$(PORT_DIR)/modules", opt=3)
+module("port_diag.py", base_path="$(PORT_DIR)/modules", opt=3)
+require("ntptime")
+require("dht")
+require("onewire")
+require("ds18x20")
+require("webrepl")
+require("neopixel")
diff --git a/ports/esp8266/boards/GENERIC_512K/mpconfigboard.h b/ports/esp8266/boards/GENERIC_512K/mpconfigboard.h
index 0693232aa1fb..b0adb7081c99 100644
--- a/ports/esp8266/boards/GENERIC_512K/mpconfigboard.h
+++ b/ports/esp8266/boards/GENERIC_512K/mpconfigboard.h
@@ -2,3 +2,12 @@
#define MICROPY_HW_MCU_NAME "ESP8266"
#define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_TERSE)
+
+#define MICROPY_PY_FSTRINGS (0)
+#define MICROPY_PY_BUILTINS_SLICE_ATTRS (0)
+#define MICROPY_PY_ALL_SPECIAL_METHODS (0)
+#define MICROPY_PY_REVERSE_SPECIAL_METHODS (0)
+#define MICROPY_PY_SYS_STDIO_BUFFER (0)
+#define MICROPY_PY_UASYNCIO (0)
+#define MICROPY_PY_URE_SUB (0)
+#define MICROPY_PY_FRAMEBUF (0)
diff --git a/ports/esp8266/boards/esp8266_common.ld b/ports/esp8266/boards/esp8266_common.ld
index c2d62e9dd4ce..bccfaa261f99 100644
--- a/ports/esp8266/boards/esp8266_common.ld
+++ b/ports/esp8266/boards/esp8266_common.ld
@@ -163,12 +163,12 @@ SECTIONS
*machine_hspi.o(.literal*, .text*)
*hspi.o(.literal*, .text*)
*modesp.o(.literal* .text*)
- *modnetwork.o(.literal* .text*)
*moduos.o(.literal* .text*)
*modutime.o(.literal* .text*)
*modlwip.o(.literal* .text*)
*modsocket.o(.literal* .text*)
*modonewire.o(.literal* .text*)
+ *network_wlan.o(.literal* .text*)
*esp_mphal.o(.literal* .text*)
/* we put as much rodata as possible in this section */
diff --git a/ports/esp8266/boards/manifest.py b/ports/esp8266/boards/manifest.py
index 598572d62ad4..10fa6da2796e 100644
--- a/ports/esp8266/boards/manifest.py
+++ b/ports/esp8266/boards/manifest.py
@@ -1,6 +1,6 @@
freeze("$(PORT_DIR)/modules")
-freeze("$(MPY_DIR)/tools", ("upip.py", "upip_utarfile.py"))
-freeze("$(MPY_DIR)/drivers/dht", "dht.py")
-freeze("$(MPY_DIR)/drivers/onewire")
-include("$(MPY_DIR)/extmod/webrepl/manifest.py")
-include("$(MPY_DIR)/drivers/neopixel/manifest.py")
+require("bundle-networking")
+require("dht")
+require("ds18x20")
+require("neopixel")
+require("onewire")
diff --git a/ports/esp8266/esp_mphal.c b/ports/esp8266/esp_mphal.c
index 3cb4807333c4..219e61484126 100644
--- a/ports/esp8266/esp_mphal.c
+++ b/ports/esp8266/esp_mphal.c
@@ -62,6 +62,9 @@ uintptr_t mp_hal_stdio_poll(uintptr_t poll_flags) {
if ((poll_flags & MP_STREAM_POLL_RD) && stdin_ringbuf.iget != stdin_ringbuf.iput) {
ret |= MP_STREAM_POLL_RD;
}
+ if (poll_flags & MP_STREAM_POLL_WR) {
+ ret |= mp_uos_dupterm_poll(poll_flags);
+ }
return ret;
}
diff --git a/ports/esp8266/esppwm.c b/ports/esp8266/esppwm.c
index 6164e2fc8b11..3b705fb94e46 100644
--- a/ports/esp8266/esppwm.c
+++ b/ports/esp8266/esppwm.c
@@ -389,7 +389,6 @@ pwm_add(uint8_t pin_id, uint32_t pin_mux, uint32_t pin_func) {
pwm.duty[i] = 0;
pwm_gpio |= (1 << pin_num[channel]);
PIN_FUNC_SELECT(pin_mux, pin_func);
- GPIO_REG_WRITE(GPIO_PIN_ADDR(GPIO_ID_PIN(pin_num[channel])), GPIO_REG_READ(GPIO_PIN_ADDR(GPIO_ID_PIN(pin_num[channel]))) & (~GPIO_PIN_PAD_DRIVER_SET(GPIO_PAD_DRIVER_ENABLE))); // disable open drain;
pwm_channel_num++;
UNLOCK_PWM(critical); // leave critical
return channel;
diff --git a/ports/esp8266/help.c b/ports/esp8266/help.c
index 4dd586c1a8bb..a755a10a7617 100644
--- a/ports/esp8266/help.c
+++ b/ports/esp8266/help.c
@@ -37,11 +37,11 @@ const char esp_help_text[] =
"import network\n"
"sta_if = network.WLAN(network.STA_IF); sta_if.active(True)\n"
"sta_if.scan() # Scan for available access points\n"
- "sta_if.connect(\"\", \"\") # Connect to an AP\n"
+ "sta_if.connect(\"\", \"\") # Connect to an AP\n"
"sta_if.isconnected() # Check for successful connection\n"
"# Change name/password of ESP8266's AP:\n"
"ap_if = network.WLAN(network.AP_IF)\n"
- "ap_if.config(essid=\"\", authmode=network.AUTH_WPA_WPA2_PSK, password=\"\")\n"
+ "ap_if.config(ssid=\"\", security=network.AUTH_WPA_WPA2_PSK, key=\"\")\n"
"\n"
"Control commands:\n"
" CTRL-A -- on a blank line, enter raw REPL mode\n"
diff --git a/ports/esp8266/machine_adc.c b/ports/esp8266/machine_adc.c
index 471e14d8dfbe..f4fd32db9c76 100644
--- a/ports/esp8266/machine_adc.c
+++ b/ports/esp8266/machine_adc.c
@@ -89,10 +89,11 @@ STATIC const mp_rom_map_elem_t machine_adc_locals_dict_table[] = {
};
STATIC MP_DEFINE_CONST_DICT(machine_adc_locals_dict, machine_adc_locals_dict_table);
-const mp_obj_type_t machine_adc_type = {
- { &mp_type_type },
- .name = MP_QSTR_ADC,
- .print = machine_adc_print,
- .make_new = machine_adc_make_new,
- .locals_dict = (mp_obj_dict_t *)&machine_adc_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ machine_adc_type,
+ MP_QSTR_ADC,
+ MP_TYPE_FLAG_NONE,
+ make_new, machine_adc_make_new,
+ print, machine_adc_print,
+ locals_dict, &machine_adc_locals_dict
+ );
diff --git a/ports/esp8266/machine_hspi.c b/ports/esp8266/machine_hspi.c
index 3ff76f5a02e0..2edb294adeff 100644
--- a/ports/esp8266/machine_hspi.c
+++ b/ports/esp8266/machine_hspi.c
@@ -175,13 +175,14 @@ STATIC const mp_machine_spi_p_t machine_hspi_p = {
.transfer = machine_hspi_transfer,
};
-const mp_obj_type_t machine_hspi_type = {
- { &mp_type_type },
- .name = MP_QSTR_HSPI,
- .print = machine_hspi_print,
- .make_new = machine_hspi_make_new,
- .protocol = &machine_hspi_p,
- .locals_dict = (mp_obj_dict_t *)&mp_machine_spi_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ machine_hspi_type,
+ MP_QSTR_HSPI,
+ MP_TYPE_FLAG_NONE,
+ make_new, machine_hspi_make_new,
+ print, machine_hspi_print,
+ protocol, &machine_hspi_p,
+ locals_dict, &mp_machine_spi_locals_dict
+ );
#endif // MICROPY_PY_MACHINE_SPI
diff --git a/ports/esp8266/machine_pin.c b/ports/esp8266/machine_pin.c
index 419ee87a7332..a76f55423799 100644
--- a/ports/esp8266/machine_pin.c
+++ b/ports/esp8266/machine_pin.c
@@ -46,13 +46,15 @@
(GPIO_REG_READ(GPIO_PIN_ADDR(phys_port)) & ~GPIO_PIN_INT_TYPE_MASK) \
| GPIO_PIN_INT_TYPE_SET(trig))) \
-#define GPIO_MODE_INPUT (0)
-#define GPIO_MODE_OUTPUT (1)
-#define GPIO_MODE_OPEN_DRAIN (2) // synthesised
-#define GPIO_PULL_NONE (0)
-#define GPIO_PULL_UP (1)
-// Removed in SDK 1.1.0
-// #define GPIO_PULL_DOWN (2)
+#define ENABLE_OPEN_DRAIN(phys_port) \
+ (GPIO_REG_WRITE(GPIO_PIN_ADDR(GPIO_ID_PIN(phys_port)), \
+ GPIO_REG_READ(GPIO_PIN_ADDR(GPIO_ID_PIN(phys_port))) \
+ | GPIO_PIN_PAD_DRIVER_SET(GPIO_PAD_DRIVER_ENABLE)))
+
+#define DISABLE_OPEN_DRAIN(phys_port) \
+ (GPIO_REG_WRITE(GPIO_PIN_ADDR(GPIO_ID_PIN(phys_port)), \
+ GPIO_REG_READ(GPIO_PIN_ADDR(GPIO_ID_PIN(phys_port))) \
+ & ~GPIO_PIN_PAD_DRIVER_SET(GPIO_PAD_DRIVER_ENABLE))) \
typedef struct _pin_irq_obj_t {
mp_obj_base_t base;
@@ -84,7 +86,7 @@ const pyb_pin_obj_t pyb_pin_obj[16 + 1] = {
{{&pyb_pin_type}, 16, -1, -1},
};
-STATIC uint8_t pin_mode[16 + 1];
+uint8_t pin_mode[16 + 1];
// forward declaration
STATIC const pin_irq_obj_t pin_irq_obj[16];
@@ -173,9 +175,7 @@ void mp_hal_pin_open_drain(mp_hal_pin_obj_t pin_id) {
ETS_GPIO_INTR_DISABLE();
PIN_FUNC_SELECT(pin->periph, pin->func);
- GPIO_REG_WRITE(GPIO_PIN_ADDR(GPIO_ID_PIN(pin->phys_port)),
- GPIO_REG_READ(GPIO_PIN_ADDR(GPIO_ID_PIN(pin->phys_port)))
- | GPIO_PIN_PAD_DRIVER_SET(GPIO_PAD_DRIVER_ENABLE)); // open drain
+ ENABLE_OPEN_DRAIN(pin->phys_port);
GPIO_REG_WRITE(GPIO_ENABLE_ADDRESS,
GPIO_REG_READ(GPIO_ENABLE_ADDRESS) | (1 << pin->phys_port));
ETS_GPIO_INTR_ENABLE();
@@ -279,6 +279,7 @@ STATIC mp_obj_t pyb_pin_obj_init_helper(pyb_pin_obj_t *self, size_t n_args, cons
mp_raise_ValueError(MP_ERROR_TEXT("Pin(16) doesn't support pull"));
}
} else {
+ DISABLE_OPEN_DRAIN(self->phys_port);
PIN_FUNC_SELECT(self->periph, self->func);
#if 0
// Removed in SDK 1.1.0
@@ -450,15 +451,16 @@ STATIC const mp_pin_p_t pin_pin_p = {
.ioctl = pin_ioctl,
};
-const mp_obj_type_t pyb_pin_type = {
- { &mp_type_type },
- .name = MP_QSTR_Pin,
- .print = pyb_pin_print,
- .make_new = mp_pin_make_new,
- .call = pyb_pin_call,
- .protocol = &pin_pin_p,
- .locals_dict = (mp_obj_dict_t *)&pyb_pin_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ pyb_pin_type,
+ MP_QSTR_Pin,
+ MP_TYPE_FLAG_NONE,
+ make_new, mp_pin_make_new,
+ print, pyb_pin_print,
+ call, pyb_pin_call,
+ protocol, &pin_pin_p,
+ locals_dict, &pyb_pin_locals_dict
+ );
/******************************************************************************/
// Pin IRQ object
@@ -509,9 +511,12 @@ STATIC const mp_rom_map_elem_t pin_irq_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(pin_irq_locals_dict, pin_irq_locals_dict_table);
-STATIC const mp_obj_type_t pin_irq_type = {
- { &mp_type_type },
- .name = MP_QSTR_IRQ,
- .call = pin_irq_call,
- .locals_dict = (mp_obj_dict_t *)&pin_irq_locals_dict,
-};
+STATIC MP_DEFINE_CONST_OBJ_TYPE(
+ pin_irq_type,
+ MP_QSTR_IRQ,
+ MP_TYPE_FLAG_NONE,
+ call, pin_irq_call,
+ locals_dict, &pin_irq_locals_dict
+ );
+
+MP_REGISTER_ROOT_POINTER(mp_obj_t pin_irq_handler[16]);
diff --git a/ports/esp8266/machine_pwm.c b/ports/esp8266/machine_pwm.c
index 00547195f9a9..6b7728deadee 100644
--- a/ports/esp8266/machine_pwm.c
+++ b/ports/esp8266/machine_pwm.c
@@ -25,6 +25,7 @@
*/
#include "py/runtime.h"
+#include "py/mphal.h"
#include "modmachine.h"
#include "esppwm.h"
@@ -74,6 +75,10 @@ STATIC void mp_machine_pwm_init_helper(machine_pwm_obj_t *self, size_t n_args, c
pwm_set_duty(args[ARG_duty].u_int, self->channel);
}
+ if (pin_mode[self->pin->phys_port] == GPIO_MODE_OPEN_DRAIN) {
+ mp_hal_pin_open_drain(self->pin->phys_port);
+ }
+
pwm_start();
}
@@ -120,6 +125,10 @@ STATIC mp_obj_t mp_machine_pwm_duty_get(machine_pwm_obj_t *self) {
if (!self->active) {
pwm_add(self->pin->phys_port, self->pin->periph, self->pin->func);
self->active = 1;
+
+ if (pin_mode[self->pin->phys_port] == GPIO_MODE_OPEN_DRAIN) {
+ mp_hal_pin_open_drain(self->pin->phys_port);
+ }
}
return MP_OBJ_NEW_SMALL_INT(pwm_get_duty(self->channel));
}
diff --git a/ports/esp8266/machine_rtc.c b/ports/esp8266/machine_rtc.c
index 38049ce72493..d8cbb8f8247d 100644
--- a/ports/esp8266/machine_rtc.c
+++ b/ports/esp8266/machine_rtc.c
@@ -262,9 +262,10 @@ STATIC const mp_rom_map_elem_t pyb_rtc_locals_dict_table[] = {
};
STATIC MP_DEFINE_CONST_DICT(pyb_rtc_locals_dict, pyb_rtc_locals_dict_table);
-const mp_obj_type_t pyb_rtc_type = {
- { &mp_type_type },
- .name = MP_QSTR_RTC,
- .make_new = pyb_rtc_make_new,
- .locals_dict = (mp_obj_dict_t *)&pyb_rtc_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ pyb_rtc_type,
+ MP_QSTR_RTC,
+ MP_TYPE_FLAG_NONE,
+ make_new, pyb_rtc_make_new,
+ locals_dict, &pyb_rtc_locals_dict
+ );
diff --git a/ports/esp8266/machine_uart.c b/ports/esp8266/machine_uart.c
index b774419d2d32..873b12b2fab9 100644
--- a/ports/esp8266/machine_uart.c
+++ b/ports/esp8266/machine_uart.c
@@ -231,10 +231,20 @@ STATIC mp_obj_t pyb_uart_any(mp_obj_t self_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_uart_any_obj, pyb_uart_any);
+STATIC mp_obj_t machine_uart_txdone(mp_obj_t self_in) {
+ pyb_uart_obj_t *self = MP_OBJ_TO_PTR(self_in);
+
+ return uart_txdone(self->uart_id) == true ? mp_const_true : mp_const_false;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_uart_txdone_obj, machine_uart_txdone);
+
STATIC const mp_rom_map_elem_t pyb_uart_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&pyb_uart_init_obj) },
{ MP_ROM_QSTR(MP_QSTR_any), MP_ROM_PTR(&pyb_uart_any_obj) },
+ { MP_ROM_QSTR(MP_QSTR_txdone), MP_ROM_PTR(&machine_uart_txdone_obj) },
+
+ { MP_ROM_QSTR(MP_QSTR_flush), MP_ROM_PTR(&mp_stream_flush_obj) },
{ MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) },
{ MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) },
{ MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) },
@@ -305,6 +315,20 @@ STATIC mp_uint_t pyb_uart_ioctl(mp_obj_t self_in, mp_uint_t request, mp_uint_t a
if ((flags & MP_STREAM_POLL_WR) && uart_tx_any_room(self->uart_id)) {
ret |= MP_STREAM_POLL_WR;
}
+ } else if (request == MP_STREAM_FLUSH) {
+ // The timeout is estimated using the buffer size and the baudrate.
+ // Take the worst case assumptions at 13 bit symbol size times 2.
+ uint64_t timeout = (uint64_t)(3 + 127) * 13000000ll * 2 / self->baudrate
+ + system_get_time();
+ do {
+ if (machine_uart_txdone((mp_obj_t)self) == mp_const_true) {
+ return 0;
+ }
+ MICROPY_EVENT_POLL_HOOK
+ } while (system_get_time() < timeout);
+
+ *errcode = MP_ETIMEDOUT;
+ ret = MP_STREAM_ERROR;
} else {
*errcode = MP_EINVAL;
ret = MP_STREAM_ERROR;
@@ -319,13 +343,14 @@ STATIC const mp_stream_p_t uart_stream_p = {
.is_text = false,
};
-const mp_obj_type_t pyb_uart_type = {
- { &mp_type_type },
- .name = MP_QSTR_UART,
- .print = pyb_uart_print,
- .make_new = pyb_uart_make_new,
- .getiter = mp_identity_getiter,
- .iternext = mp_stream_unbuffered_iter,
- .protocol = &uart_stream_p,
- .locals_dict = (mp_obj_dict_t *)&pyb_uart_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ pyb_uart_type,
+ MP_QSTR_UART,
+ MP_TYPE_FLAG_ITER_IS_STREAM,
+ make_new, pyb_uart_make_new,
+ print, pyb_uart_print,
+ protocol, &uart_stream_p,
+ locals_dict, &pyb_uart_locals_dict
+ );
+
+MP_REGISTER_ROOT_POINTER(byte * uart0_rxbuf);
diff --git a/ports/esp8266/machine_wdt.c b/ports/esp8266/machine_wdt.c
index b06e75227728..39a5d51119ef 100644
--- a/ports/esp8266/machine_wdt.c
+++ b/ports/esp8266/machine_wdt.c
@@ -69,9 +69,10 @@ STATIC const mp_rom_map_elem_t machine_wdt_locals_dict_table[] = {
};
STATIC MP_DEFINE_CONST_DICT(machine_wdt_locals_dict, machine_wdt_locals_dict_table);
-const mp_obj_type_t esp_wdt_type = {
- { &mp_type_type },
- .name = MP_QSTR_WDT,
- .make_new = machine_wdt_make_new,
- .locals_dict = (mp_obj_dict_t *)&machine_wdt_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ esp_wdt_type,
+ MP_QSTR_WDT,
+ MP_TYPE_FLAG_NONE,
+ make_new, machine_wdt_make_new,
+ locals_dict, &machine_wdt_locals_dict
+ );
diff --git a/ports/esp8266/main.c b/ports/esp8266/main.c
index ded5e58abf7a..238490ebefe9 100644
--- a/ports/esp8266/main.c
+++ b/ports/esp8266/main.c
@@ -68,13 +68,13 @@ STATIC void mp_reset(void) {
mp_obj_t args[2];
args[0] = MP_OBJ_NEW_SMALL_INT(0);
args[1] = MP_OBJ_NEW_SMALL_INT(115200);
- args[0] = pyb_uart_type.make_new(&pyb_uart_type, 2, 0, args);
+ args[0] = MP_OBJ_TYPE_GET_SLOT(&pyb_uart_type, make_new)(&pyb_uart_type, 2, 0, args);
args[1] = MP_OBJ_NEW_SMALL_INT(1);
mp_uos_dupterm_obj.fun.var(2, args);
}
#if MICROPY_MODULE_FROZEN
- pyexec_frozen_module("_boot.py");
+ pyexec_frozen_module("_boot.py", false);
pyexec_file_if_exists("boot.py");
if (pyexec_mode_kind == PYEXEC_MODE_FRIENDLY_REPL) {
pyexec_file_if_exists("main.py");
diff --git a/ports/esp8266/makeimg.py b/ports/esp8266/makeimg.py
index 4d31cc079960..662e6f83204a 100644
--- a/ports/esp8266/makeimg.py
+++ b/ports/esp8266/makeimg.py
@@ -14,7 +14,6 @@
md5 = hashlib.md5()
with open(sys.argv[3], "wb") as fout:
-
with open(sys.argv[1], "rb") as f:
data_flash = f.read()
fout.write(data_flash)
diff --git a/ports/esp8266/modesp.c b/ports/esp8266/modesp.c
index 645de7fe9b0a..878d9392a16c 100644
--- a/ports/esp8266/modesp.c
+++ b/ports/esp8266/modesp.c
@@ -31,7 +31,6 @@
#include "py/persistentcode.h"
#include "py/mperrno.h"
#include "py/mphal.h"
-#include "drivers/dht/dht.h"
#include "uart.h"
#include "user_interface.h"
#include "mem.h"
@@ -355,7 +354,6 @@ STATIC const mp_rom_map_elem_t esp_module_globals_table[] = {
#if MICROPY_ESP8266_APA102
{ MP_ROM_QSTR(MP_QSTR_apa102_write), MP_ROM_PTR(&esp_apa102_write_obj) },
#endif
- { MP_ROM_QSTR(MP_QSTR_dht_readinto), MP_ROM_PTR(&dht_readinto_obj) },
{ MP_ROM_QSTR(MP_QSTR_freemem), MP_ROM_PTR(&esp_freemem_obj) },
{ MP_ROM_QSTR(MP_QSTR_meminfo), MP_ROM_PTR(&esp_meminfo_obj) },
{ MP_ROM_QSTR(MP_QSTR_check_fw), MP_ROM_PTR(&esp_check_fw_obj) },
diff --git a/ports/esp8266/modmachine.c b/ports/esp8266/modmachine.c
index 1dd87b9af8f7..3c75a2d7ffda 100644
--- a/ports/esp8266/modmachine.c
+++ b/ports/esp8266/modmachine.c
@@ -31,6 +31,7 @@
#include "py/obj.h"
#include "py/runtime.h"
#include "shared/runtime/pyexec.h"
+#include "drivers/dht/dht.h"
// This needs to be set before we include the RTOS headers
#define USE_US_TIMER 1
@@ -337,13 +338,14 @@ STATIC const mp_rom_map_elem_t esp_timer_locals_dict_table[] = {
};
STATIC MP_DEFINE_CONST_DICT(esp_timer_locals_dict, esp_timer_locals_dict_table);
-const mp_obj_type_t esp_timer_type = {
- { &mp_type_type },
- .name = MP_QSTR_Timer,
- .print = esp_timer_print,
- .make_new = esp_timer_make_new,
- .locals_dict = (mp_obj_dict_t *)&esp_timer_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ esp_timer_type,
+ MP_QSTR_Timer,
+ MP_TYPE_FLAG_NONE,
+ make_new, esp_timer_make_new,
+ print, esp_timer_print,
+ locals_dict, &esp_timer_locals_dict
+ );
// this bit is unused in the Xtensa PS register
#define ETS_LOOP_ITER_BIT (12)
@@ -417,6 +419,7 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = {
#endif
{ MP_ROM_QSTR(MP_QSTR_time_pulse_us), MP_ROM_PTR(&machine_time_pulse_us_obj) },
+ { MP_ROM_QSTR(MP_QSTR_dht_readinto), MP_ROM_PTR(&dht_readinto_obj) },
{ MP_ROM_QSTR(MP_QSTR_RTC), MP_ROM_PTR(&pyb_rtc_type) },
{ MP_ROM_QSTR(MP_QSTR_Timer), MP_ROM_PTR(&esp_timer_type) },
diff --git a/ports/esp8266/modmachine.h b/ports/esp8266/modmachine.h
index 4a73d3b8e801..9b7a5e3cb226 100644
--- a/ports/esp8266/modmachine.h
+++ b/ports/esp8266/modmachine.h
@@ -21,6 +21,16 @@ typedef struct _pyb_pin_obj_t {
const pyb_pin_obj_t pyb_pin_obj[16 + 1];
+#define GPIO_MODE_INPUT (0)
+#define GPIO_MODE_OUTPUT (1)
+#define GPIO_MODE_OPEN_DRAIN (2) // synthesised
+#define GPIO_PULL_NONE (0)
+#define GPIO_PULL_UP (1)
+// Removed in SDK 1.1.0
+// #define GPIO_PULL_DOWN (2)
+
+extern uint8_t pin_mode[16 + 1];
+
void pin_init0(void);
uint mp_obj_get_pin(mp_obj_t pin_in);
diff --git a/ports/esp8266/modnetwork.h b/ports/esp8266/modnetwork.h
new file mode 100644
index 000000000000..dc9203b0fb91
--- /dev/null
+++ b/ports/esp8266/modnetwork.h
@@ -0,0 +1,2 @@
+MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(esp_network_get_wlan_obj);
+MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(esp_network_phy_mode_obj);
diff --git a/ports/esp8266/modnetwork_globals.h b/ports/esp8266/modnetwork_globals.h
new file mode 100644
index 000000000000..f977cd14e495
--- /dev/null
+++ b/ports/esp8266/modnetwork_globals.h
@@ -0,0 +1,22 @@
+{ MP_ROM_QSTR(MP_QSTR_WLAN), MP_ROM_PTR(&esp_network_get_wlan_obj) },
+{ MP_ROM_QSTR(MP_QSTR_phy_mode), MP_ROM_PTR(&esp_network_phy_mode_obj) },
+
+{ MP_ROM_QSTR(MP_QSTR_STA_IF), MP_ROM_INT(STATION_IF)},
+{ MP_ROM_QSTR(MP_QSTR_AP_IF), MP_ROM_INT(SOFTAP_IF)},
+
+{ MP_ROM_QSTR(MP_QSTR_STAT_IDLE), MP_ROM_INT(STATION_IDLE)},
+{ MP_ROM_QSTR(MP_QSTR_STAT_CONNECTING), MP_ROM_INT(STATION_CONNECTING)},
+{ MP_ROM_QSTR(MP_QSTR_STAT_WRONG_PASSWORD), MP_ROM_INT(STATION_WRONG_PASSWORD)},
+{ MP_ROM_QSTR(MP_QSTR_STAT_NO_AP_FOUND), MP_ROM_INT(STATION_NO_AP_FOUND)},
+{ MP_ROM_QSTR(MP_QSTR_STAT_CONNECT_FAIL), MP_ROM_INT(STATION_CONNECT_FAIL)},
+{ MP_ROM_QSTR(MP_QSTR_STAT_GOT_IP), MP_ROM_INT(STATION_GOT_IP)},
+
+{ MP_ROM_QSTR(MP_QSTR_MODE_11B), MP_ROM_INT(PHY_MODE_11B) },
+{ MP_ROM_QSTR(MP_QSTR_MODE_11G), MP_ROM_INT(PHY_MODE_11G) },
+{ MP_ROM_QSTR(MP_QSTR_MODE_11N), MP_ROM_INT(PHY_MODE_11N) },
+
+{ MP_ROM_QSTR(MP_QSTR_AUTH_OPEN), MP_ROM_INT(AUTH_OPEN) },
+{ MP_ROM_QSTR(MP_QSTR_AUTH_WEP), MP_ROM_INT(AUTH_WEP) },
+{ MP_ROM_QSTR(MP_QSTR_AUTH_WPA_PSK), MP_ROM_INT(AUTH_WPA_PSK) },
+{ MP_ROM_QSTR(MP_QSTR_AUTH_WPA2_PSK), MP_ROM_INT(AUTH_WPA2_PSK) },
+{ MP_ROM_QSTR(MP_QSTR_AUTH_WPA_WPA2_PSK), MP_ROM_INT(AUTH_WPA_WPA2_PSK) },
diff --git a/ports/esp8266/modules/inisetup.py b/ports/esp8266/modules/inisetup.py
index 9500b8048c9d..e5ce00138ecc 100644
--- a/ports/esp8266/modules/inisetup.py
+++ b/ports/esp8266/modules/inisetup.py
@@ -7,8 +7,8 @@ def wifi():
import ubinascii
ap_if = network.WLAN(network.AP_IF)
- essid = b"MicroPython-%s" % ubinascii.hexlify(ap_if.config("mac")[-3:])
- ap_if.config(essid=essid, authmode=network.AUTH_WPA_WPA2_PSK, password=b"micropythoN")
+ ssid = b"MicroPython-%s" % ubinascii.hexlify(ap_if.config("mac")[-3:])
+ ap_if.config(ssid=ssid, security=network.AUTH_WPA_WPA2_PSK, key=b"micropythoN")
def check_bootsec():
diff --git a/ports/esp8266/modules/ntptime.py b/ports/esp8266/modules/ntptime.py
deleted file mode 100644
index dd07e46f1d3b..000000000000
--- a/ports/esp8266/modules/ntptime.py
+++ /dev/null
@@ -1,39 +0,0 @@
-try:
- import usocket as socket
-except:
- import socket
-try:
- import ustruct as struct
-except:
- import struct
-
-# (date(2000, 1, 1) - date(1900, 1, 1)).days * 24*60*60
-NTP_DELTA = 3155673600
-
-# The NTP host can be configured at runtime by doing: ntptime.host = 'myhost.org'
-host = "pool.ntp.org"
-
-
-def time():
- NTP_QUERY = bytearray(48)
- NTP_QUERY[0] = 0x1B
- addr = socket.getaddrinfo(host, 123)[0][-1]
- s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
- try:
- s.settimeout(1)
- res = s.sendto(NTP_QUERY, addr)
- msg = s.recv(48)
- finally:
- s.close()
- val = struct.unpack("!I", msg[40:44])[0]
- return val - NTP_DELTA
-
-
-# There's currently no timezone support in MicroPython, and the RTC is set in UTC time.
-def settime():
- t = time()
- import machine
- import utime
-
- tm = utime.gmtime(t)
- machine.RTC().datetime((tm[0], tm[1], tm[2], tm[6] + 1, tm[3], tm[4], tm[5], 0))
diff --git a/ports/esp8266/modules/port_diag.py b/ports/esp8266/modules/port_diag.py
index f2c69ecacd96..4eea6a6d90d3 100644
--- a/ports/esp8266/modules/port_diag.py
+++ b/ports/esp8266/modules/port_diag.py
@@ -5,7 +5,6 @@
def main():
-
ROM = uctypes.bytearray_at(0x40200000, 16)
fid = esp.flash_id()
diff --git a/ports/esp8266/moduos.c b/ports/esp8266/moduos.c
index 9a235e61b9b9..a023796fd3b6 100644
--- a/ports/esp8266/moduos.c
+++ b/ports/esp8266/moduos.c
@@ -48,7 +48,7 @@ STATIC mp_obj_t mp_uos_urandom(mp_obj_t num) {
for (int i = 0; i < n; i++) {
vstr.buf[i] = *WDEV_HWRNG;
}
- return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
+ return mp_obj_new_bytes_from_vstr(&vstr);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_uos_urandom_obj, mp_uos_urandom);
diff --git a/ports/esp8266/mpconfigport.h b/ports/esp8266/mpconfigport.h
index 583d3648af8d..7576c99a8775 100644
--- a/ports/esp8266/mpconfigport.h
+++ b/ports/esp8266/mpconfigport.h
@@ -6,6 +6,40 @@
#include
+// Set the rom feature level.
+#define MICROPY_CONFIG_ROM_LEVEL (MICROPY_CONFIG_ROM_LEVEL_EXTRA_FEATURES)
+
+// Disable items from the extra level that are not wanted.
+#define MICROPY_COMP_MODULE_CONST (0)
+#define MICROPY_COMP_TRIPLE_TUPLE_ASSIGN (0)
+#define MICROPY_COMP_RETURN_IF_EXPR (0)
+#define MICROPY_OPT_LOAD_ATTR_FAST_PATH (0)
+#define MICROPY_OPT_MAP_LOOKUP_CACHE (0)
+#define MICROPY_OPT_MPZ_BITWISE (0)
+#define MICROPY_OPT_MATH_FACTORIAL (0)
+#define MICROPY_REPL_EMACS_KEYS (0)
+#define MICROPY_PY_BUILTINS_COMPLEX (0)
+#define MICROPY_MODULE_ATTR_DELEGATION (0)
+#define MICROPY_PY_FUNCTION_ATTRS (0)
+#define MICROPY_PY_DELATTR_SETATTR (0)
+#define MICROPY_PY_BUILTINS_STR_CENTER (0)
+#define MICROPY_PY_BUILTINS_STR_PARTITION (0)
+#define MICROPY_PY_BUILTINS_STR_SPLITLINES (0)
+#define MICROPY_PY_BUILTINS_SLICE_INDICES (0)
+#define MICROPY_PY_BUILTINS_COMPILE (0)
+#define MICROPY_PY_BUILTINS_EXECFILE (0)
+#define MICROPY_PY_BUILTINS_NOTIMPLEMENTED (0)
+#define MICROPY_PY_BUILTINS_POW3 (0)
+#define MICROPY_PY___FILE__ (0)
+#define MICROPY_PY_MATH_CONSTANTS (0)
+#define MICROPY_PY_MATH_SPECIAL_FUNCTIONS (0)
+#define MICROPY_PY_MATH_FACTORIAL (0)
+#define MICROPY_PY_MATH_ISCLOSE (0)
+#define MICROPY_PY_SYS_PS1_PS2 (0)
+#define MICROPY_PY_UBINASCII_CRC32 (0)
+#define MICROPY_PY_URANDOM_EXTRA_FUNCS (0)
+
+// Configure other options.
#define MICROPY_OBJ_REPR (MICROPY_OBJ_REPR_C)
#define MICROPY_GC_STACK_ENTRY_TYPE uint16_t
#define MICROPY_ALLOC_PATH_MAX (128)
@@ -16,50 +50,13 @@
#define MICROPY_ALLOC_PARSE_CHUNK_INIT (64)
#define MICROPY_DEBUG_PRINTER (&mp_debug_print)
#define MICROPY_ENABLE_GC (1)
-#define MICROPY_ENABLE_FINALISER (1)
-#define MICROPY_STACK_CHECK (1)
#define MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF (1)
-#define MICROPY_KBD_EXCEPTION (1)
#define MICROPY_REPL_EVENT_DRIVEN (0)
-#define MICROPY_REPL_AUTO_INDENT (1)
-#define MICROPY_HELPER_REPL (1)
-#define MICROPY_ENABLE_SOURCE_LINE (1)
-#define MICROPY_MODULE_BUILTIN_INIT (1)
-#define MICROPY_MODULE_WEAK_LINKS (1)
-#define MICROPY_CAN_OVERRIDE_BUILTINS (1)
#define MICROPY_USE_INTERNAL_ERRNO (1)
-#define MICROPY_ENABLE_SCHEDULER (1)
-#define MICROPY_PY_DESCRIPTORS (1)
-#define MICROPY_PY_BUILTINS_COMPLEX (0)
-#define MICROPY_PY_BUILTINS_STR_UNICODE (1)
-#define MICROPY_PY_BUILTINS_MEMORYVIEW (1)
-#define MICROPY_PY_BUILTINS_FROZENSET (1)
-#define MICROPY_PY_BUILTINS_ROUND_INT (1)
-#define MICROPY_PY_BUILTINS_INPUT (1)
-#define MICROPY_PY_BUILTINS_HELP (1)
#define MICROPY_PY_BUILTINS_HELP_TEXT esp_help_text
-#define MICROPY_PY_BUILTINS_HELP_MODULES (1)
-#define MICROPY_PY___FILE__ (0)
-#define MICROPY_PY_ARRAY_SLICE_ASSIGN (1)
-#define MICROPY_PY_COLLECTIONS_DEQUE (1)
-#define MICROPY_PY_COLLECTIONS_ORDEREDDICT (1)
-#define MICROPY_PY_IO_IOBASE (1)
-#define MICROPY_PY_SYS_MAXSIZE (1)
-#define MICROPY_PY_SYS_STDFILES (1)
-#define MICROPY_PY_UERRNO (1)
-#define MICROPY_PY_UBINASCII (1)
-#define MICROPY_PY_UCTYPES (1)
-#define MICROPY_PY_UHASHLIB (1)
#define MICROPY_PY_UHASHLIB_SHA1 (MICROPY_PY_USSL && MICROPY_SSL_AXTLS)
-#define MICROPY_PY_UHEAPQ (1)
-#define MICROPY_PY_UTIMEQ (1)
-#define MICROPY_PY_UJSON (1)
-#define MICROPY_PY_URANDOM (1)
#define MICROPY_PY_URANDOM_SEED_INIT_FUNC (*WDEV_HWRNG)
-#define MICROPY_PY_URE (1)
-#define MICROPY_PY_USELECT (1)
#define MICROPY_PY_UTIME_MP_HAL (1)
-#define MICROPY_PY_UZLIB (1)
#define MICROPY_PY_LWIP (1)
#define MICROPY_PY_LWIP_SOCK_RAW (1)
#define MICROPY_PY_MACHINE (1)
@@ -74,13 +71,17 @@
#define MICROPY_PY_MACHINE_SOFTI2C (1)
#define MICROPY_PY_MACHINE_SPI (1)
#define MICROPY_PY_MACHINE_SOFTSPI (1)
+#define MICROPY_PY_NETWORK (1)
+#ifndef MICROPY_PY_NETWORK_HOSTNAME_DEFAULT
+#define MICROPY_PY_NETWORK_HOSTNAME_DEFAULT "mpy-esp8266"
+#endif
+#define MICROPY_PY_NETWORK_INCLUDEFILE "ports/esp8266/modnetwork.h"
+#define MICROPY_PY_NETWORK_MODULE_GLOBALS_INCLUDEFILE "ports/esp8266/modnetwork_globals.h"
#define MICROPY_PY_UWEBSOCKET (1)
#define MICROPY_PY_ONEWIRE (1)
#define MICROPY_PY_WEBREPL (1)
#define MICROPY_PY_WEBREPL_DELAY (20)
#define MICROPY_PY_WEBREPL_STATIC_FILEBUF (1)
-#define MICROPY_PY_MICROPYTHON_MEM_INFO (1)
-#define MICROPY_PY_UOS (1)
#define MICROPY_PY_UOS_INCLUDEFILE "ports/esp8266/moduos.c"
#define MICROPY_PY_OS_DUPTERM (2)
#define MICROPY_PY_UOS_DUPTERM_NOTIFY (1)
@@ -92,7 +93,6 @@
#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_FLOAT)
#define MICROPY_WARNINGS (1)
#define MICROPY_PY_STR_BYTES_CMP_WARN (1)
-#define MICROPY_STREAMS_NON_BLOCK (1)
#define MICROPY_STREAMS_POSIX_API (1)
#define MICROPY_MODULE_FROZEN_LEXER mp_lexer_new_from_str32
@@ -139,24 +139,8 @@ void *esp_native_code_commit(void *, size_t, void *);
// printer for debugging output, goes to UART only
extern const struct _mp_print_t mp_debug_print;
-#if MICROPY_VFS_FAT
-#define mp_type_fileio mp_type_vfs_fat_fileio
-#define mp_type_textio mp_type_vfs_fat_textio
-#elif MICROPY_VFS_LFS1
-#define mp_type_fileio mp_type_vfs_lfs1_fileio
-#define mp_type_textio mp_type_vfs_lfs1_textio
-#elif MICROPY_VFS_LFS2
-#define mp_type_fileio mp_type_vfs_lfs2_fileio
-#define mp_type_textio mp_type_vfs_lfs2_textio
-#endif
-
#define MP_STATE_PORT MP_STATE_VM
-#define MICROPY_PORT_ROOT_POINTERS \
- const char *readline_hist[8]; \
- mp_obj_t pin_irq_handler[16]; \
- byte *uart0_rxbuf; \
-
// We need an implementation of the log2 function which is not a macro
#define MP_NEED_LOG2 (1)
diff --git a/ports/esp8266/modnetwork.c b/ports/esp8266/network_wlan.c
similarity index 86%
rename from ports/esp8266/modnetwork.c
rename to ports/esp8266/network_wlan.c
index dc1b435fb98c..9f89b126f62d 100644
--- a/ports/esp8266/modnetwork.c
+++ b/ports/esp8266/network_wlan.c
@@ -31,6 +31,7 @@
#include "py/objlist.h"
#include "py/runtime.h"
#include "py/mphal.h"
+#include "extmod/modnetwork.h"
#include "shared/netutils/netutils.h"
#include "queue.h"
#include "user_interface.h"
@@ -39,8 +40,6 @@
#include "ets_alt_task.h"
#include "lwip/dns.h"
-#define MODNETWORK_INCLUDE_CONSTANTS (1)
-
typedef struct _wlan_if_obj_t {
mp_obj_base_t base;
int if_id;
@@ -71,7 +70,7 @@ STATIC mp_obj_t get_wlan(size_t n_args, const mp_obj_t *args) {
}
return MP_OBJ_FROM_PTR(&wlan_objs[idx]);
}
-STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(get_wlan_obj, 0, 1, get_wlan);
+MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_network_get_wlan_obj, 0, 1, get_wlan);
STATIC mp_obj_t esp_active(size_t n_args, const mp_obj_t *args) {
wlan_if_obj_t *self = MP_OBJ_TO_PTR(args[0]);
@@ -109,7 +108,7 @@ STATIC mp_obj_t esp_active(size_t n_args, const mp_obj_t *args) {
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_active_obj, 1, 2, esp_active);
STATIC mp_obj_t esp_connect(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
- enum { ARG_ssid, ARG_password, ARG_bssid };
+ enum { ARG_ssid, ARG_key, ARG_bssid };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_, MP_ARG_OBJ, {.u_obj = mp_const_none} },
{ MP_QSTR_, MP_ARG_OBJ, {.u_obj = mp_const_none} },
@@ -133,8 +132,8 @@ STATIC mp_obj_t esp_connect(size_t n_args, const mp_obj_t *pos_args, mp_map_t *k
memcpy(config.ssid, p, len);
set_config = true;
}
- if (args[ARG_password].u_obj != mp_const_none) {
- p = mp_obj_str_get_data(args[ARG_password].u_obj, &len);
+ if (args[ARG_key].u_obj != mp_const_none) {
+ p = mp_obj_str_get_data(args[ARG_key].u_obj, &len);
len = MIN(len, sizeof(config.password));
memcpy(config.password, p, len);
set_config = true;
@@ -152,6 +151,9 @@ STATIC mp_obj_t esp_connect(size_t n_args, const mp_obj_t *pos_args, mp_map_t *k
if (set_config) {
error_check(wifi_station_set_config(&config), "Cannot set STA config");
}
+
+ wifi_station_set_hostname(mod_network_hostname);
+
error_check(wifi_station_connect(), "Cannot connect to AP");
return mp_const_none;
@@ -361,6 +363,7 @@ STATIC mp_obj_t esp_config(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs
wifi_set_macaddr(self->if_id, bufinfo.buf);
break;
}
+ case MP_QSTR_ssid:
case MP_QSTR_essid: {
req_if = SOFTAP_IF;
size_t len;
@@ -375,11 +378,13 @@ STATIC mp_obj_t esp_config(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs
cfg.ap.ssid_hidden = mp_obj_is_true(kwargs->table[i].value);
break;
}
+ case MP_QSTR_security:
case MP_QSTR_authmode: {
req_if = SOFTAP_IF;
cfg.ap.authmode = mp_obj_get_int(kwargs->table[i].value);
break;
}
+ case MP_QSTR_key:
case MP_QSTR_password: {
req_if = SOFTAP_IF;
size_t len;
@@ -394,12 +399,24 @@ STATIC mp_obj_t esp_config(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs
cfg.ap.channel = mp_obj_get_int(kwargs->table[i].value);
break;
}
+ case MP_QSTR_hostname:
case MP_QSTR_dhcp_hostname: {
- req_if = STATION_IF;
- if (self->if_id == STATION_IF) {
- const char *s = mp_obj_str_get_str(kwargs->table[i].value);
- wifi_station_set_hostname((char *)s);
+ // TODO: Deprecated. Use network.hostname(name) instead.
+ size_t len;
+ const char *str = mp_obj_str_get_data(kwargs->table[i].value, &len);
+ if (len >= MICROPY_PY_NETWORK_HOSTNAME_MAX_LEN) {
+ mp_raise_ValueError(NULL);
}
+ strcpy(mod_network_hostname, str);
+ break;
+ }
+ case MP_QSTR_protocol: {
+ wifi_set_phy_mode(mp_obj_get_int(kwargs->table[i].value));
+ break;
+ }
+ case MP_QSTR_txpower: {
+ int8_t power = mp_obj_get_float(kwargs->table[i].value) * 4;
+ system_phy_set_max_tpw(power);
break;
}
default:
@@ -437,6 +454,7 @@ STATIC mp_obj_t esp_config(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs
wifi_get_macaddr(self->if_id, mac);
return mp_obj_new_bytes(mac, sizeof(mac));
}
+ case MP_QSTR_ssid:
case MP_QSTR_essid:
if (self->if_id == STATION_IF) {
val = mp_obj_new_str((char *)cfg.sta.ssid, strlen((char *)cfg.sta.ssid));
@@ -448,6 +466,7 @@ STATIC mp_obj_t esp_config(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs
req_if = SOFTAP_IF;
val = mp_obj_new_bool(cfg.ap.ssid_hidden);
break;
+ case MP_QSTR_security:
case MP_QSTR_authmode:
req_if = SOFTAP_IF;
val = MP_OBJ_NEW_SMALL_INT(cfg.ap.authmode);
@@ -456,14 +475,15 @@ STATIC mp_obj_t esp_config(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs
req_if = SOFTAP_IF;
val = MP_OBJ_NEW_SMALL_INT(cfg.ap.channel);
break;
+ case MP_QSTR_hostname:
case MP_QSTR_dhcp_hostname: {
req_if = STATION_IF;
- char *s = wifi_station_get_hostname();
- if (s == NULL) {
- val = MP_OBJ_NEW_QSTR(MP_QSTR_);
- } else {
- val = mp_obj_new_str(s, strlen(s));
- }
+ // TODO: Deprecated. Use network.hostname() instead.
+ val = mp_obj_new_str(mod_network_hostname, strlen(mod_network_hostname));
+ break;
+ }
+ case MP_QSTR_protocol: {
+ val = mp_obj_new_int(wifi_get_phy_mode());
break;
}
default:
@@ -495,11 +515,12 @@ STATIC const mp_rom_map_elem_t wlan_if_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(wlan_if_locals_dict, wlan_if_locals_dict_table);
-const mp_obj_type_t wlan_if_type = {
- { &mp_type_type },
- .name = MP_QSTR_WLAN,
- .locals_dict = (mp_obj_dict_t *)&wlan_if_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ wlan_if_type,
+ MP_QSTR_WLAN,
+ MP_TYPE_FLAG_NONE,
+ locals_dict, &wlan_if_locals_dict
+ );
STATIC mp_obj_t esp_phy_mode(size_t n_args, const mp_obj_t *args) {
if (n_args == 0) {
@@ -509,43 +530,4 @@ STATIC mp_obj_t esp_phy_mode(size_t n_args, const mp_obj_t *args) {
return mp_const_none;
}
}
-STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_phy_mode_obj, 0, 1, esp_phy_mode);
-
-STATIC const mp_rom_map_elem_t mp_module_network_globals_table[] = {
- { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_network) },
- { MP_ROM_QSTR(MP_QSTR_WLAN), MP_ROM_PTR(&get_wlan_obj) },
- { MP_ROM_QSTR(MP_QSTR_phy_mode), MP_ROM_PTR(&esp_phy_mode_obj) },
-
- #if MODNETWORK_INCLUDE_CONSTANTS
- { MP_ROM_QSTR(MP_QSTR_STA_IF), MP_ROM_INT(STATION_IF)},
- { MP_ROM_QSTR(MP_QSTR_AP_IF), MP_ROM_INT(SOFTAP_IF)},
-
- { MP_ROM_QSTR(MP_QSTR_STAT_IDLE), MP_ROM_INT(STATION_IDLE)},
- { MP_ROM_QSTR(MP_QSTR_STAT_CONNECTING), MP_ROM_INT(STATION_CONNECTING)},
- { MP_ROM_QSTR(MP_QSTR_STAT_WRONG_PASSWORD), MP_ROM_INT(STATION_WRONG_PASSWORD)},
- { MP_ROM_QSTR(MP_QSTR_STAT_NO_AP_FOUND), MP_ROM_INT(STATION_NO_AP_FOUND)},
- { MP_ROM_QSTR(MP_QSTR_STAT_CONNECT_FAIL), MP_ROM_INT(STATION_CONNECT_FAIL)},
- { MP_ROM_QSTR(MP_QSTR_STAT_GOT_IP), MP_ROM_INT(STATION_GOT_IP)},
-
- { MP_ROM_QSTR(MP_QSTR_MODE_11B), MP_ROM_INT(PHY_MODE_11B) },
- { MP_ROM_QSTR(MP_QSTR_MODE_11G), MP_ROM_INT(PHY_MODE_11G) },
- { MP_ROM_QSTR(MP_QSTR_MODE_11N), MP_ROM_INT(PHY_MODE_11N) },
-
- { MP_ROM_QSTR(MP_QSTR_AUTH_OPEN), MP_ROM_INT(AUTH_OPEN) },
- { MP_ROM_QSTR(MP_QSTR_AUTH_WEP), MP_ROM_INT(AUTH_WEP) },
- { MP_ROM_QSTR(MP_QSTR_AUTH_WPA_PSK), MP_ROM_INT(AUTH_WPA_PSK) },
- { MP_ROM_QSTR(MP_QSTR_AUTH_WPA2_PSK), MP_ROM_INT(AUTH_WPA2_PSK) },
- { MP_ROM_QSTR(MP_QSTR_AUTH_WPA_WPA2_PSK), MP_ROM_INT(AUTH_WPA_WPA2_PSK) },
- #endif
-};
-
-STATIC MP_DEFINE_CONST_DICT(mp_module_network_globals, mp_module_network_globals_table);
-
-const mp_obj_module_t network_module = {
- .base = { &mp_type_module },
- .globals = (mp_obj_dict_t *)&mp_module_network_globals,
-};
-
-// Note: This port doesn't define MICROPY_PY_NETWORK so this will not conflict
-// with the common implementation provided by extmod/modnetwork.c.
-MP_REGISTER_MODULE(MP_QSTR_network, network_module);
+MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_network_phy_mode_obj, 0, 1, esp_phy_mode);
diff --git a/ports/esp8266/uart.c b/ports/esp8266/uart.c
index 978a7efc38ed..117cd1bf6c93 100644
--- a/ports/esp8266/uart.c
+++ b/ports/esp8266/uart.c
@@ -111,6 +111,15 @@ void uart_tx_one_char(uint8 uart, uint8 TxChar) {
WRITE_PERI_REG(UART_FIFO(uart), TxChar);
}
+int uart_txdone(uint8 uart) {
+ uint32 fifo_cnt = READ_PERI_REG(UART_STATUS(uart)) & (UART_TXFIFO_CNT << UART_TXFIFO_CNT_S);
+ if ((fifo_cnt >> UART_TXFIFO_CNT_S & UART_TXFIFO_CNT) == 0) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
void uart_flush(uint8 uart) {
while (true) {
uint32 fifo_cnt = READ_PERI_REG(UART_STATUS(uart)) & (UART_TXFIFO_CNT << UART_TXFIFO_CNT_S);
diff --git a/ports/esp8266/uart.h b/ports/esp8266/uart.h
index de0919bde056..3c5592ff0aa8 100644
--- a/ports/esp8266/uart.h
+++ b/ports/esp8266/uart.h
@@ -101,6 +101,7 @@ bool uart_rx_wait(uint32_t timeout_us);
int uart_rx_char(void);
void uart_tx_one_char(uint8 uart, uint8 TxChar);
void uart_flush(uint8 uart);
+int uart_txdone(uint8 uart);
void uart_os_config(int uart);
void uart_setup(uint8 uart);
int uart0_get_rxbuf_len(void);
diff --git a/ports/javascript/mpconfigport.h b/ports/javascript/mpconfigport.h
deleted file mode 100644
index 4a6cb458838b..000000000000
--- a/ports/javascript/mpconfigport.h
+++ /dev/null
@@ -1,187 +0,0 @@
-/*
- * This file is part of the MicroPython project, http://micropython.org/
- *
- * The MIT License (MIT)
- *
- * Copyright (c) 2013, 2014 Damien P. George and 2017, 2018 Rami Ali
- *
- * 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
-
-// options to control how MicroPython is built
-
-// You can disable the built-in MicroPython compiler by setting the following
-// config option to 0. If you do this then you won't get a REPL prompt, but you
-// will still be able to execute pre-compiled scripts, compiled with mpy-cross.
-#define MICROPY_ENABLE_COMPILER (1)
-
-#define MICROPY_QSTR_BYTES_IN_HASH (2)
-#define MICROPY_ALLOC_PATH_MAX (256)
-#define MICROPY_ALLOC_PARSE_CHUNK_INIT (16)
-#define MICROPY_EMIT_X64 (0) // BROKEN
-#define MICROPY_EMIT_THUMB (0) // BROKEN
-#define MICROPY_EMIT_INLINE_THUMB (0)
-#define MICROPY_COMP_MODULE_CONST (0)
-#define MICROPY_COMP_CONST (1)
-#define MICROPY_COMP_DOUBLE_TUPLE_ASSIGN (1)
-#define MICROPY_COMP_TRIPLE_TUPLE_ASSIGN (0)
-#define MICROPY_MEM_STATS (0) // BROKEN
-#define MICROPY_DEBUG_PRINTERS (0)
-#define MICROPY_ENABLE_GC (1)
-#define MICROPY_GC_ALLOC_THRESHOLD (1)
-#define MICROPY_GC_USES_ALLOCATED_SIZE (1)
-#define MICROPY_REPL_EVENT_DRIVEN (1)
-#define MICROPY_HELPER_REPL (1)
-#define MICROPY_HELPER_LEXER_UNIX (0)
-#define MICROPY_ENABLE_SOURCE_LINE (1)
-#define MICROPY_ENABLE_DOC_STRING (1)
-#define MICROPY_WARNINGS (1)
-#define MICROPY_BUILTIN_METHOD_CHECK_SELF_ARG (1)
-#define MICROPY_PY_ASYNC_AWAIT (1)
-#define MICROPY_PY_BUILTINS_BYTEARRAY (1)
-#define MICROPY_PY_BUILTINS_MEMORYVIEW (1)
-#define MICROPY_PY_BUILTINS_ENUMERATE (1)
-#define MICROPY_PY_BUILTINS_FILTER (1)
-#define MICROPY_PY_BUILTINS_FROZENSET (1)
-#define MICROPY_PY_BUILTINS_REVERSED (1)
-#define MICROPY_PY_BUILTINS_SET (1)
-#define MICROPY_PY_BUILTINS_SLICE (1)
-#define MICROPY_PY_BUILTINS_PROPERTY (1)
-#define MICROPY_PY_BUILTINS_MIN_MAX (1)
-#define MICROPY_PY___FILE__ (1)
-#define MICROPY_PY_GC (1)
-#define MICROPY_PY_ARRAY (1)
-#define MICROPY_PY_ATTRTUPLE (1)
-#define MICROPY_PY_COLLECTIONS (1)
-#define MICROPY_PY_MATH (1)
-#define MICROPY_PY_MATH_SPECIAL_FUNCTIONS (1)
-#define MICROPY_PY_MATH_ISCLOSE (1)
-#define MICROPY_PY_CMATH (1)
-#define MICROPY_PY_IO (1)
-#define MICROPY_PY_STRUCT (1)
-#define MICROPY_PY_SYS (1)
-#define MICROPY_PY_SYS_MAXSIZE (1)
-#define MICROPY_CPYTHON_COMPAT (1)
-#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ)
-#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_DOUBLE)
-
-#define MICROPY_USE_INTERNAL_PRINTF (0)
-#define MICROPY_ENABLE_PYSTACK (1)
-#define MICROPY_KBD_EXCEPTION (1)
-#define MICROPY_PY_UTIME_MP_HAL (1)
-#define MICROPY_REPL_AUTO_INDENT (1)
-#define MICROPY_PY_FUNCTION_ATTRS (1)
-#define MICROPY_PY_BUILTINS_STR_UNICODE (1)
-#define MICROPY_PY_BUILTINS_STR_CENTER (1)
-#define MICROPY_PY_BUILTINS_STR_PARTITION (1)
-#define MICROPY_PY_BUILTINS_STR_SPLITLINES (1)
-#define MICROPY_PY_BUILTINS_SLICE_ATTRS (1)
-#define MICROPY_PY_ALL_SPECIAL_METHODS (1)
-#define MICROPY_PY_BUILTINS_COMPILE (1)
-#define MICROPY_PY_BUILTINS_EXECFILE (1)
-#define MICROPY_PY_BUILTINS_INPUT (1)
-#define MICROPY_PY_BUILTINS_POW3 (1)
-#define MICROPY_PY_BUILTINS_HELP (1)
-#define MICROPY_PY_BUILTINS_HELP_MODULES (1)
-#define MICROPY_PY_MICROPYTHON_MEM_INFO (1)
-#define MICROPY_PY_ARRAY_SLICE_ASSIGN (1)
-#define MICROPY_PY_COLLECTIONS_ORDEREDDICT (1)
-#define MICROPY_PY_SYS_PLATFORM "javascript"
-#define MICROPY_PY_UERRNO (1)
-#define MICROPY_PY_UCTYPES (1)
-#define MICROPY_PY_UZLIB (1)
-#define MICROPY_PY_UJSON (1)
-#define MICROPY_PY_URE (1)
-#define MICROPY_PY_UHEAPQ (1)
-#define MICROPY_PY_UHASHLIB (1)
-#define MICROPY_PY_UBINASCII (1)
-#define MICROPY_PY_URANDOM (1)
-#define MICROPY_PY_URANDOM_EXTRA_FUNCS (1)
-#define MICROPY_PY_USELECT (1)
-#define MICROPY_PY_FRAMEBUF (1)
-#define MICROPY_STREAMS_NON_BLOCK (1)
-#define MICROPY_MODULE_WEAK_LINKS (1)
-#define MICROPY_CAN_OVERRIDE_BUILTINS (1)
-#define MICROPY_USE_INTERNAL_ERRNO (1)
-#define MICROPY_ENABLE_SCHEDULER (1)
-#define MICROPY_SCHEDULER_DEPTH (1)
-
-#define MP_SSIZE_MAX (0x7fffffff)
-
-// #define MICROPY_EVENT_POLL_HOOK {ets_event_poll();}
-#if MICROPY_PY_THREAD
-#define MICROPY_EVENT_POLL_HOOK \
- do { \
- extern void mp_handle_pending(bool); \
- mp_handle_pending(true); \
- if (pyb_thread_enabled) { \
- MP_THREAD_GIL_EXIT(); \
- pyb_thread_yield(); \
- MP_THREAD_GIL_ENTER(); \
- } else { \
- } \
- } while (0);
-
-#define MICROPY_THREAD_YIELD() pyb_thread_yield()
-#else
-#define MICROPY_EVENT_POLL_HOOK \
- do { \
- extern void mp_handle_pending(bool); \
- mp_handle_pending(true); \
- } while (0);
-
-#define MICROPY_THREAD_YIELD()
-#endif
-
-#define MICROPY_VM_HOOK_COUNT (10)
-#define MICROPY_VM_HOOK_INIT static uint vm_hook_divisor = MICROPY_VM_HOOK_COUNT;
-#define MICROPY_VM_HOOK_POLL if (--vm_hook_divisor == 0) { \
- vm_hook_divisor = MICROPY_VM_HOOK_COUNT; \
- extern void mp_js_hook(void); \
- mp_js_hook(); \
-}
-#define MICROPY_VM_HOOK_LOOP MICROPY_VM_HOOK_POLL
-#define MICROPY_VM_HOOK_RETURN MICROPY_VM_HOOK_POLL
-
-// type definitions for the specific machine
-
-// #define MICROPY_MAKE_POINTER_CALLABLE(p) ((void*)((mp_uint_t)(p) | 1))
-
-// This port is intended to be 32-bit, but unfortunately, int32_t for
-// different targets may be defined in different ways - either as int
-// or as long. This requires different printf formatting specifiers
-// to print such value. So, we avoid int32_t and use int directly.
-#define UINT_FMT "%u"
-#define INT_FMT "%d"
-typedef int mp_int_t; // must be pointer size
-typedef unsigned mp_uint_t; // must be pointer size
-typedef long mp_off_t;
-
-// We need to provide a declaration/definition of alloca()
-#include
-
-#define MICROPY_HW_BOARD_NAME "JS"
-#define MICROPY_HW_MCU_NAME "Emscripten"
-
-#define MP_STATE_PORT MP_STATE_VM
-
-#define MICROPY_PORT_ROOT_POINTERS \
- const char *readline_hist[8];
diff --git a/ports/mimxrt/Makefile b/ports/mimxrt/Makefile
index cfcdb9f7d521..4e4fd1752847 100644
--- a/ports/mimxrt/Makefile
+++ b/ports/mimxrt/Makefile
@@ -1,71 +1,75 @@
+# =============================================================================
+# Parameter Configuration
+# =============================================================================
+
+# Select the board to build for:
+ifdef BOARD_DIR
+# Custom board path - remove trailing slash and get the final component of
+# the path as the board name.
+BOARD ?= $(notdir $(BOARD_DIR:/=))
+else
+# If not given on the command line, then default to TEENSY40.
BOARD ?= TEENSY40
BOARD_DIR ?= boards/$(BOARD)
-BUILD ?= build-$(BOARD)
-
-PORT ?= /dev/ttyACM0
-
-CROSS_COMPILE ?= arm-none-eabi-
+endif
ifeq ($(wildcard $(BOARD_DIR)/.),)
-$(error Invalid BOARD specified: $(BOARD_DIR))
+ $(error Invalid BOARD specified: $(BOARD_DIR))
endif
-include ../../py/mkenv.mk
-include $(BOARD_DIR)/mpconfigboard.mk
+BUILD ?= build-$(BOARD)
+PORT ?= /dev/ttyACM0
+CROSS_COMPILE ?= arm-none-eabi-
+GIT_SUBMODULES += lib/tinyusb lib/nxp_driver
-LD_MEMORY_CONFIG_DEFINES += \
- MICROPY_HW_FLASH_TYPE=$(MICROPY_HW_FLASH_TYPE) \
- MICROPY_HW_FLASH_SIZE=$(MICROPY_HW_FLASH_SIZE)
+# MicroPython feature configurations
+MICROPY_VFS_LFS2 ?= 1
+MICROPY_VFS_FAT ?= 1
-ifdef MICROPY_HW_FLASH_RESERVED
-LD_MEMORY_CONFIG_DEFINES += MICROPY_HW_FLASH_RESERVED=$(MICROPY_HW_FLASH_RESERVED)
-endif
+# qstr definitions (must come before including py.mk)
+QSTR_DEFS += qstrdefsport.h
+QSTR_GLOBAL_DEPENDENCIES = $(BOARD_DIR)/mpconfigboard.h
-ifdef MICROPY_HW_SDRAM_AVAIL
-CFLAGS += \
- -DMICROPY_HW_SDRAM_AVAIL=$(MICROPY_HW_SDRAM_AVAIL) \
- -DMICROPY_HW_SDRAM_SIZE=$(MICROPY_HW_SDRAM_SIZE)
+# Generation scripts
+MAKE_PINS = boards/make-pins.py
+MAKE_FLEXRAM_LD = boards/make-flexram-config.py
-LD_MEMORY_CONFIG_DEFINES += \
- MICROPY_HW_SDRAM_AVAIL=$(MICROPY_HW_SDRAM_AVAIL) \
- MICROPY_HW_SDRAM_SIZE=$(MICROPY_HW_SDRAM_SIZE)
-endif
+# Include py make environment
+include ../../py/mkenv.mk
-# Qstr definitions (must come before including py.mk)
-QSTR_DEFS = qstrdefsport.h
-QSTR_GLOBAL_DEPENDENCIES = $(BOARD_DIR)/mpconfigboard.h
+# Include micropython configuration board makefile
+include $(BOARD_DIR)/mpconfigboard.mk
# MicroPython feature configurations
+MICROPY_ROM_TEXT_COMPRESSION ?= 1
+
+# File containing description of content to be frozen into firmware.
FROZEN_MANIFEST ?= boards/manifest.py
-MICROPY_VFS_LFS2 ?= 1
-MICROPY_VFS_FAT ?= 1
# Include py core make definitions
include $(TOP)/py/py.mk
+include $(TOP)/extmod/extmod.mk
-GIT_SUBMODULES = lib/tinyusb lib/nxp_driver lib/lwip lib/mbedtls
-
+# Set SDK directory based on MCU_SERIES
MCU_DIR = lib/nxp_driver/sdk/devices/$(MCU_SERIES)
+
+# Select linker scripts based on MCU_SERIES
LD_FILES = boards/$(MCU_SERIES).ld boards/common.ld
-MAKE_PINS = boards/make-pins.py
-MAKE_FLEXRAM_LD = boards/make-flexram-config.py
-BOARD_PINS = $(BOARD_DIR)/pins.csv
+# Parameter configurations for generation
AF_FILE = boards/$(MCU_SERIES)_af.csv
+BOARD_PINS = $(BOARD_DIR)/pins.csv
PREFIX_FILE = boards/mimxrt_prefix.c
-GEN_PINS_SRC = $(BUILD)/pins_gen.c
-GEN_PINS_HDR = $(HEADER_BUILD)/pins.h
-GEN_PINS_QSTR = $(BUILD)/pins_qstr.h
+GEN_FLEXRAM_CONFIG_SRC = $(BUILD)/flexram_config.s
GEN_PINS_AF_CONST = $(HEADER_BUILD)/pins_af_const.h
GEN_PINS_AF_PY = $(BUILD)/pins_af.py
-GEN_FLEXRAM_CONFIG_SRC = $(BUILD)/flexram_config.s
+GEN_PINS_HDR = $(HEADER_BUILD)/pins.h
+GEN_PINS_SRC = $(BUILD)/pins_gen.c
-# mcu driver cause following warnings
-#CFLAGS += -Wno-error=float-equal -Wno-error=nested-externs
-CFLAGS += -Wno-error=unused-parameter
+# =============================================================================
+# Includes
+# =============================================================================
-INC += -I.
-INC += -Ihal
INC += -I$(BOARD_DIR)
INC += -I$(BUILD)
INC += -I$(TOP)
@@ -76,91 +80,19 @@ INC += -I$(TOP)/lib/oofatfs
INC += -I$(TOP)/lib/tinyusb/hw
INC += -I$(TOP)/lib/tinyusb/hw/bsp/teensy_40
INC += -I$(TOP)/lib/tinyusb/src
-
-CFLAGS_MCU = -mtune=cortex-m7 -mcpu=cortex-m7
-CFLAGS += $(INC) -Wall -Werror -Wdouble-promotion -Wfloat-conversion -std=c99 -nostdlib -mthumb $(CFLAGS_MCU)
-CFLAGS += -DCPU_$(MCU_SERIES) -DCPU_$(MCU_VARIANT) -DBOARD_$(BOARD)
-CFLAGS += -DXIP_EXTERNAL_FLASH=1 \
- -DXIP_BOOT_HEADER_ENABLE=1 \
- -DFSL_SDK_ENABLE_DRIVER_CACHE_CONTROL=1 \
- -DCFG_TUSB_MCU=OPT_MCU_MIMXRT10XX \
- -D__STARTUP_CLEAR_BSS \
- -D__STARTUP_INITIALIZE_RAMFUNCTION \
- -D__START=main \
- -DCPU_HEADER_H='<$(MCU_SERIES).h>' \
- -DCLOCK_CONFIG_H='' \
- -DBOARD_FLASH_SIZE=$(MICROPY_HW_FLASH_SIZE) \
- -DMICROPY_HW_FLASH_SIZE=$(MICROPY_HW_FLASH_SIZE) \
-
-CFLAGS += -DI2C_RETRY_TIMES=1000000 -DSPI_RETRY_TIMES=1000000 -DUART_RETRY_TIMES=1000000
-
-ifeq ($(MICROPY_PY_MACHINE_SDCARD),1)
-CFLAGS += -DMICROPY_PY_MACHINE_SDCARD=1
-endif
-
-CFLAGS += $(CFLAGS_MOD) $(CFLAGS_EXTRA)
-
-# Configure floating point support
-ifeq ($(MICROPY_FLOAT_IMPL),double)
-CFLAGS += -DMICROPY_FLOAT_IMPL=MICROPY_FLOAT_IMPL_DOUBLE
-CFLAGS_MCU += -mfloat-abi=hard -mfpu=fpv5-d16
-else
-ifeq ($(MICROPY_FLOAT_IMPL),none)
-CFLAGS += -DMICROPY_FLOAT_IMPL=MICROPY_FLOAT_IMPL_NONE
-else
-CFLAGS += -DMICROPY_FLOAT_IMPL=MICROPY_FLOAT_IMPL_FLOAT
-CFLAGS += -fsingle-precision-constant
-CFLAGS_MCU += -mfloat-abi=softfp -mfpu=fpv5-sp-d16
-endif
-endif
-
-SUPPORTS_HARDWARE_FP_SINGLE = 0
-SUPPORTS_HARDWARE_FP_DOUBLE = 0
-
-LDFLAGS = -Map=$@.map --cref --print-memory-usage
-LDDEFINES = $(addprefix -D, $(LD_MEMORY_CONFIG_DEFINES))
-LIBS = $(shell $(CC) $(CFLAGS) -print-libgcc-file-name)
-
-# Tune for Debugging or Optimization
-ifeq ($(DEBUG),1)
-CFLAGS += -Og -ggdb
-LDFLAGS += --gc-sections
-CFLAGS += -fdata-sections -ffunction-sections
-else
-CFLAGS += -Os -DNDEBUG
-LDFLAGS += --gc-sections
-CFLAGS += -fdata-sections -ffunction-sections
-endif
+INC += -I.
+INC += -Ihal
# All settings for Ethernet support are controller by the value of MICROPY_PY_LWIP
-ifeq ($(MICROPY_PY_LWIP), 1)
-
+ifeq ($(MICROPY_PY_LWIP),1)
INC += -Ilwip_inc
INC += -Ihal/phy
-
-SRC_MOD := $(filter-out %/mbedtls/library/error.c, $(SRC_MOD))
-
-SRC_ETH_C += \
- hal/phy/mdio/enet/fsl_enet_mdio.c \
- hal/phy/device/phydp83825/fsl_phydp83825.c \
- hal/phy/device/phydp83848/fsl_phydp83848.c \
- hal/phy/device/phyksz8081/fsl_phyksz8081.c \
- hal/phy/device/phylan8720/fsl_phylan8720.c \
- lib/mbedtls_errors/mp_mbedtls_errors.c \
- $(MCU_DIR)/drivers/fsl_enet.c \
-
-SRC_QSTR += \
- extmod/modlwip.c \
- extmod/modnetwork.c \
- extmod/moduwebsocket.c \
- extmod/modusocket.c \
- network_lan.c \
-
-CFLAGS += -DFSL_FEATURE_PHYKSZ8081_USE_RMII50M_MODE=1 \
- -DMBEDTLS_CONFIG_FILE='"mbedtls/mbedtls_config.h"'
-
endif
+# =============================================================================
+# Sources
+# =============================================================================
+
# TinyUSB Stack source
SRC_TINYUSB_C += \
lib/tinyusb/src/class/cdc/cdc_device.c \
@@ -173,12 +105,23 @@ SRC_TINYUSB_C += \
lib/tinyusb/src/common/tusb_fifo.c \
lib/tinyusb/src/device/usbd.c \
lib/tinyusb/src/device/usbd_control.c \
- lib/tinyusb/src/portable/nxp/transdimension/dcd_transdimension.c \
+ lib/tinyusb/src/portable/chipidea/ci_hs/dcd_ci_hs.c \
lib/tinyusb/src/tusb.c
+# All settings for Ethernet support are controller by the value of MICROPY_PY_LWIP
+ifeq ($(MICROPY_PY_LWIP),1)
+SRC_ETH_C += \
+ $(MCU_DIR)/drivers/fsl_enet.c \
+ hal/phy/device/phydp83825/fsl_phydp83825.c \
+ hal/phy/device/phydp83848/fsl_phydp83848.c \
+ hal/phy/device/phyksz8081/fsl_phyksz8081.c \
+ hal/phy/device/phylan8720/fsl_phylan8720.c \
+ hal/phy/device/phyrtl8211f/fsl_phyrtl8211f.c \
+ hal/phy/mdio/enet/fsl_enet_mdio.c
+endif
+
+# NXP SDK sources
SRC_HAL_IMX_C += \
- $(MCU_DIR)/drivers/fsl_adc.c \
- $(MCU_DIR)/drivers/fsl_cache.c \
$(MCU_DIR)/drivers/fsl_clock.c \
$(MCU_DIR)/drivers/fsl_common.c \
$(MCU_DIR)/drivers/fsl_dmamux.c \
@@ -195,12 +138,11 @@ SRC_HAL_IMX_C += \
$(MCU_DIR)/drivers/fsl_pwm.c \
$(MCU_DIR)/drivers/fsl_sai.c \
$(MCU_DIR)/drivers/fsl_snvs_lp.c \
- $(MCU_DIR)/drivers/fsl_trng.c \
$(MCU_DIR)/drivers/fsl_wdog.c \
- $(MCU_DIR)/system_$(MCU_SERIES).c \
+ $(MCU_DIR)/system_$(MCU_SERIES)$(MCU_CORE).c \
$(MCU_DIR)/xip/fsl_flexspi_nor_boot.c \
-ifeq ($(MICROPY_HW_SDRAM_AVAIL), 1)
+ifeq ($(MICROPY_HW_SDRAM_AVAIL),1)
SRC_HAL_IMX_C += $(MCU_DIR)/drivers/fsl_semc.c
endif
@@ -208,11 +150,31 @@ ifeq ($(MICROPY_PY_MACHINE_SDCARD),1)
SRC_HAL_IMX_C += $(MCU_DIR)/drivers/fsl_usdhc.c
endif
-ifeq ($(MCU_SERIES),$(filter $(MCU_SERIES), MIMXRT1015 MIMXRT1021 MIMXRT1052 MIMXRT1062 MIMXRT1064))
+ifeq ($(MCU_SERIES),$(filter $(MCU_SERIES), MIMXRT1015 MIMXRT1021 MIMXRT1052 MIMXRT1062 MIMXRT1064 MIMXRT1176))
SRC_HAL_IMX_C += \
- $(MCU_DIR)/drivers/fsl_qtmr.c
+ $(MCU_DIR)/drivers/fsl_qtmr.c \
+ $(MCU_DIR)/drivers/fsl_romapi.c
endif
+ifeq ($(MCU_SERIES), MIMXRT1176)
+INC += -I$(TOP)/$(MCU_DIR)/drivers/cm7
+
+SRC_HAL_IMX_C += \
+ $(MCU_DIR)/drivers/cm7/fsl_cache.c \
+ $(MCU_DIR)/drivers/fsl_dcdc.c \
+ $(MCU_DIR)/drivers/fsl_pmu.c \
+ $(MCU_DIR)/drivers/fsl_common_arm.c \
+ $(MCU_DIR)/drivers/fsl_anatop_ai.c \
+ $(MCU_DIR)/drivers/fsl_caam.c \
+ $(MCU_DIR)/drivers/fsl_lpadc.c
+else
+SRC_HAL_IMX_C += \
+ $(MCU_DIR)/drivers/fsl_adc.c \
+ $(MCU_DIR)/drivers/fsl_cache.c \
+ $(MCU_DIR)/drivers/fsl_trng.c
+endif
+
+# C source files
SRC_C += \
board_init.c \
boards/$(MCU_SERIES)_clock_config.c \
@@ -220,10 +182,6 @@ SRC_C += \
drivers/bus/softspi.c \
drivers/dht/dht.c \
eth.c \
- extmod/modnetwork.c \
- extmod/modonewire.c \
- extmod/modusocket.c \
- extmod/uos_dupterm.c \
fatfs_port.c \
hal/pwm_backport.c \
led.c \
@@ -236,7 +194,6 @@ SRC_C += \
machine_rtc.c \
machine_sdcard.c \
machine_spi.c \
- machine_timer.c \
machine_uart.c \
machine_wdt.c \
main.c \
@@ -252,140 +209,223 @@ SRC_C += \
pendsv.c \
pin.c \
sdcard.c \
+ systick.c \
+ ticks.c \
+ tusb_port.c \
+
+SHARED_SRC_C += \
shared/libc/printf.c \
shared/libc/string0.c \
+ shared/netutils/dhcpserver.c \
shared/netutils/netutils.c \
shared/netutils/trace.c \
- shared/netutils/dhcpserver.c \
shared/readline/readline.c \
shared/runtime/gchelper_native.c \
shared/runtime/interrupt_char.c \
shared/runtime/mpirq.c \
shared/runtime/pyexec.c \
+ shared/runtime/softtimer.c \
shared/runtime/stdout_helpers.c \
shared/runtime/sys_stdio_mphal.c \
shared/timeutils/timeutils.c \
- systick.c \
- ticks.c \
- tusb_port.c \
- $(SRC_TINYUSB_C) \
- $(SRC_HAL_IMX_C) \
- $(SRC_ETH_C) \
-
-ifeq ($(MICROPY_HW_FLASH_TYPE), qspi_nor)
-CFLAGS += -DBOARD_FLASH_OPS_HEADER_H=\"hal/flexspi_nor_flash.h\"
-SRC_C += hal/flexspi_nor_flash.c
-ifeq ($(MICROPY_HW_BOARD_FLASH_FILES), 1)
-CFLAGS += -DBOARD_FLASH_CONFIG_HEADER_H=\"$(BOARD)_flexspi_flash_config.h\"
-SRC_C += $(BOARD_DIR)/qspi_nor_flash_config.c
+# Set flash driver name, base address and internal flash flag, based on the flash type.
+ifeq ($(MICROPY_HW_FLASH_TYPE),$(filter $(MICROPY_HW_FLASH_TYPE),qspi_nor_flash))
+ MICROPY_HW_FLASH_BASE = 0x60000000
+ FLEXSPI_FLASH_TYPE = $(MICROPY_HW_FLASH_TYPE)
+else ifeq ($(MICROPY_HW_FLASH_TYPE),$(filter $(MICROPY_HW_FLASH_TYPE),qspi_hyper_flash))
+ MICROPY_HW_FLASH_BASE = 0x60000000
+ FLEXSPI_FLASH_TYPE = $(MICROPY_HW_FLASH_TYPE)
+else ifeq ($(MICROPY_HW_FLASH_TYPE),$(filter $(MICROPY_HW_FLASH_TYPE),internal))
+ # The internal flash is an SPI NOR Flash.
+ MICROPY_HW_FLASH_BASE = 0x70000000
+ FLEXSPI_FLASH_TYPE = qspi_nor_flash
+ CFLAGS += -DMICROPY_HW_FLASH_INTERNAL
else
-CFLAGS += -DBOARD_FLASH_CONFIG_HEADER_H=\"hal/flexspi_flash_config.h\"
-SRC_C += hal/qspi_nor_flash_config.c
+ $(error Error: Unknown board flash type $(MICROPY_HW_FLASH_TYPE))
endif
-#
-else ifeq ($(MICROPY_HW_FLASH_TYPE), hyperflash)
-CFLAGS += -DBOARD_FLASH_OPS_HEADER_H=\"hal/flexspi_hyper_flash.h\"
-SRC_C += hal/flexspi_hyper_flash.c
-ifeq ($(MICROPY_HW_BOARD_FLASH_FILES), 1)
-CFLAGS += -DBOARD_FLASH_CONFIG_HEADER_H=\"$(BOARD)_flexspi_flash_config.h\"
-SRC_C += $(BOARD_DIR)/qspi_hyper_flash_config.c
-else
-CFLAGS += -DBOARD_FLASH_CONFIG_HEADER_H=\"hal/flexspi_flash_config.h\"
-SRC_C += hal/qspi_hyper_flash_config.c
-endif
+# Add sources for respective board flash type
+# Add hal/flexspi_nor_flash.c or hal/flashspi_hyper_flash.c respectively
+SRC_HAL_C += hal/flexspi_$(subst qspi_,,$(FLEXSPI_FLASH_TYPE)).c
#
+# Add custom (board specific) or default configuration
+ifeq ($(MICROPY_HW_BOARD_FLASH_FILES),1)
+ SRC_HAL_C += $(BOARD_DIR)/$(FLEXSPI_FLASH_TYPE)_config.c
else
-$(error Error: Unknown board flash type $(MICROPY_HW_FLASH_TYPE))
+ SRC_HAL_C += hal/$(FLEXSPI_FLASH_TYPE)_config.c
endif
+# Math library source files
ifeq ($(MICROPY_FLOAT_IMPL),double)
-LIBM_SRC_C += $(addprefix lib/libm_dbl/,\
- __cos.c \
- __expo2.c \
- __fpclassify.c \
- __rem_pio2.c \
- __rem_pio2_large.c \
- __signbit.c \
- __sin.c \
- __tan.c \
- acos.c \
- acosh.c \
- asin.c \
- asinh.c \
- atan.c \
- atan2.c \
- atanh.c \
- ceil.c \
- copysign.c \
- cos.c \
- cosh.c \
- erf.c \
- exp.c \
- expm1.c \
- floor.c \
- fmod.c \
- frexp.c \
- ldexp.c \
- lgamma.c \
- log.c \
- log10.c \
- log1p.c \
- modf.c \
- nearbyint.c \
- pow.c \
- rint.c \
- round.c \
- scalbn.c \
- sin.c \
- sinh.c \
- tan.c \
- tanh.c \
- tgamma.c \
- trunc.c \
- )
-ifeq ($(SUPPORTS_HARDWARE_FP_DOUBLE),1)
-LIBM_SRC_C += lib/libm_dbl/thumb_vfp_sqrt.c
+ LIBM_SRC_C += $(addprefix lib/libm_dbl/,\
+ __cos.c __expo2.c __fpclassify.c __rem_pio2.c __rem_pio2_large.c __signbit.c __sin.c __tan.c acos.c acosh.c \
+ asin.c asinh.c atan.c atan2.c atanh.c ceil.c copysign.c cos.c cosh.c erf.c exp.c expm1.c floor.c fmod.c \
+ frexp.c ldexp.c lgamma.c log.c log10.c log1p.c modf.c nearbyint.c pow.c rint.c round.c scalbn.c sin.c \
+ sinh.c tan.c tanh.c tgamma.c trunc.c)
+ #
+ ifeq ($(SUPPORTS_HARDWARE_FP_DOUBLE),1)
+ LIBM_SRC_C += lib/libm_dbl/thumb_vfp_sqrt.c
+ else
+ LIBM_SRC_C += lib/libm_dbl/sqrt.c
+ endif
+else
+ LIBM_SRC_C += $(addprefix lib/libm/,\
+ acoshf.c asinfacosf.c asinhf.c atan2f.c atanf.c atanhf.c ef_rem_pio2.c erf_lgamma.c fmodf.c kf_cos.c \
+ kf_rem_pio2.c kf_sin.c kf_tan.c log1pf.c math.c nearbyintf.c roundf.c sf_cos.c sf_erf.c sf_frexp.c sf_ldexp.c \
+ sf_modf.c sf_sin.c sf_tan.c wf_lgamma.c wf_tgamma.c)
+ ifeq ($(SUPPORTS_HARDWARE_FP_SINGLE),1)
+ LIBM_SRC_C += lib/libm/thumb_vfp_sqrtf.c
+ else
+ LIBM_SRC_C += lib/libm/ef_sqrt.c
+ endif
+endif
+
+# Reset variables
+SUPPORTS_HARDWARE_FP_SINGLE = 0
+SUPPORTS_HARDWARE_FP_DOUBLE = 0
+
+# Assembly source files
+SRC_SS = \
+ $(MCU_DIR)/gcc/startup_$(MCU_SERIES)$(MCU_CORE).S \
+ hal/resethandler_MIMXRT10xx.S
+
+SRC_S += shared/runtime/gchelper_thumb2.s \
+
+# =============================================================================
+# QSTR Sources
+# =============================================================================
+
+# List of sources for qstr extraction
+SRC_QSTR += $(SRC_C) $(SHARED_SRC_C) $(GEN_PINS_SRC)
+
+# =============================================================================
+# Compiler Flags
+# =============================================================================
+
+CFLAGS += -g # always include debug info in the ELF
+ifeq ($(DEBUG),1)
+CFLAGS += -Og
+# Disable text compression in debug builds
+MICROPY_ROM_TEXT_COMPRESSION = 0
else
-LIBM_SRC_C += lib/libm_dbl/sqrt.c
+CFLAGS += -Os -DNDEBUG
endif
+
+# Set default values for optional variables
+MICROPY_HW_SDRAM_AVAIL ?= 0
+MICROPY_HW_SDRAM_SIZE ?= 0
+MICROPY_PY_MACHINE_SDCARD ?= 0
+
+# Configure default compiler flags
+CFLAGS += \
+ $(INC) \
+ -D__START=main \
+ -D__STARTUP_CLEAR_BSS \
+ -D__STARTUP_INITIALIZE_RAMFUNCTION \
+ -DBOARD_$(BOARD) \
+ -DBOARD_FLASH_SIZE=$(MICROPY_HW_FLASH_SIZE) \
+ -DCFG_TUSB_MCU=OPT_MCU_MIMXRT \
+ -DCLOCK_CONFIG_H='' \
+ -DCPU_$(MCU_SERIES)$(MCU_CORE) \
+ -DCPU_$(MCU_VARIANT) \
+ -DCPU_HEADER_H='<$(MCU_SERIES)$(MCU_CORE).h>' \
+ -DFSL_SDK_ENABLE_DRIVER_CACHE_CONTROL=1 \
+ -DI2C_RETRY_TIMES=1000000 \
+ -DMICROPY_HW_FLASH_SIZE=$(MICROPY_HW_FLASH_SIZE) \
+ -DMICROPY_HW_SDRAM_AVAIL=$(MICROPY_HW_SDRAM_AVAIL) \
+ -DMICROPY_HW_SDRAM_SIZE=$(MICROPY_HW_SDRAM_SIZE) \
+ -DMICROPY_PY_MACHINE_SDCARD=$(MICROPY_PY_MACHINE_SDCARD) \
+ -DSPI_RETRY_TIMES=1000000 \
+ -DUART_RETRY_TIMES=1000000 \
+ -DXIP_BOOT_HEADER_ENABLE=1 \
+ -DXIP_EXTERNAL_FLASH=1 \
+ -fdata-sections \
+ -ffunction-sections \
+ -mcpu=cortex-m7 \
+ -mthumb \
+ -mtune=cortex-m7 \
+ -nostdlib \
+ -std=c99 \
+ -Wall \
+ -Wdouble-promotion \
+ -Werror \
+ -Wfloat-conversion \
+ -Wno-error=unused-parameter
+
+# Configure respective board flash type
+# Add hal/flexspi_nor_flash.h or hal/flexspi_hyper_flash.h respectively
+CFLAGS += -DBOARD_FLASH_OPS_HEADER_H=\"hal/flexspi_$(subst qspi_,,$(FLEXSPI_FLASH_TYPE)).h\"
+#
+# Add custom (board specific) or default configuration
+ifeq ($(MICROPY_HW_BOARD_FLASH_FILES),1)
+ CFLAGS += -DBOARD_FLASH_CONFIG_HEADER_H=\"$(BOARD)_flexspi_flash_config.h\"
else
-LIBM_SRC_C += $(addprefix lib/libm/,\
- acoshf.c \
- asinfacosf.c \
- asinhf.c \
- atan2f.c \
- atanf.c \
- atanhf.c \
- ef_rem_pio2.c \
- erf_lgamma.c \
- fmodf.c \
- kf_cos.c \
- kf_rem_pio2.c \
- kf_sin.c \
- kf_tan.c \
- log1pf.c \
- math.c \
- nearbyintf.c \
- roundf.c \
- sf_cos.c \
- sf_erf.c \
- sf_frexp.c \
- sf_ldexp.c \
- sf_modf.c \
- sf_sin.c \
- sf_tan.c \
- wf_lgamma.c \
- wf_tgamma.c \
- )
-ifeq ($(SUPPORTS_HARDWARE_FP_SINGLE),1)
-LIBM_SRC_C += lib/libm/thumb_vfp_sqrtf.c
+ CFLAGS += -DBOARD_FLASH_CONFIG_HEADER_H=\"hal/flexspi_flash_config.h\"
+endif
+
+# Configure floating point support
+ifeq ($(MICROPY_FLOAT_IMPL),single)
+ CFLAGS += \
+ -DMICROPY_FLOAT_IMPL=MICROPY_FLOAT_IMPL_FLOAT \
+ -fsingle-precision-constant \
+ -mfloat-abi=softfp \
+ -mfpu=fpv5-sp-d16
+else ifeq ($(MICROPY_FLOAT_IMPL),double)
+ CFLAGS += \
+ -DMICROPY_FLOAT_IMPL=MICROPY_FLOAT_IMPL_DOUBLE \
+ -mfloat-abi=hard \
+ -mfpu=fpv5-d16
+else ifeq ($(MICROPY_FLOAT_IMPL),none)
+ CFLAGS += \
+ -DMICROPY_FLOAT_IMPL=MICROPY_FLOAT_IMPL_NONE
else
-LIBM_SRC_C += lib/libm/ef_sqrt.c
+ $(error Error: Unknown floating point implementation $(MICROPY_FLOAT_IMPL))
endif
+
+
+# All settings for Ethernet support are controller by the value of MICROPY_PY_LWIP
+ifeq ($(MICROPY_PY_LWIP),1)
+CFLAGS += \
+ -DFSL_FEATURE_PHYKSZ8081_USE_RMII50M_MODE=1
endif
+CFLAGS += $(CFLAGS_EXTRA)
+
+MPY_CROSS_FLAGS += -march=armv7m
+
+# =============================================================================
+# Linker Flags
+# =============================================================================
+
+LDFLAGS += \
+ --cref \
+ --gc-sections \
+ --print-memory-usage \
+ -Map=$@.map
+
+# LDDEFINES are used for link time adaptation of linker scripts, utilizing
+# the C preprocessor. Therefore keep LDDEFINES separated from LDFLAGS!
+
+LDDEFINES = \
+ -DMICROPY_HW_FLASH_BASE=$(MICROPY_HW_FLASH_BASE) \
+ -DMICROPY_HW_FLASH_SIZE=$(MICROPY_HW_FLASH_SIZE)
+
+ifdef MICROPY_HW_FLASH_RESERVED
+LDDEFINES += -DMICROPY_HW_FLASH_RESERVED=$(MICROPY_HW_FLASH_RESERVED)
+endif
+
+ifdef MICROPY_HW_SDRAM_AVAIL
+LDDEFINES += \
+ -DMICROPY_HW_SDRAM_AVAIL=$(MICROPY_HW_SDRAM_AVAIL) \
+ -DMICROPY_HW_SDRAM_SIZE=$(MICROPY_HW_SDRAM_SIZE)
+endif
+
+# =============================================================================
+# Library and Object files
+# =============================================================================
+
+LIBS = $(shell $(CC) $(CFLAGS) -print-libgcc-file-name)
LIBM_O = $(addprefix $(BUILD)/, $(LIBM_SRC_C:.c=.o))
# Too many warnings in libm_dbl, disable for now.
@@ -393,49 +433,29 @@ ifeq ($(MICROPY_FLOAT_IMPL),double)
$(LIBM_O): CFLAGS := $(filter-out -Wdouble-promotion -Wfloat-conversion, $(CFLAGS))
endif
-SRC_SS = \
- $(MCU_DIR)/gcc/startup_$(MCU_SERIES).S \
- hal/resethandler_MIMXRT10xx.S
-
-SRC_S += shared/runtime/gchelper_m3.s \
-
-# List of sources for qstr extraction
-SRC_QSTR += \
- extmod/modonewire.c \
- extmod/uos_dupterm.c \
- machine_adc.c \
- machine_i2s.c \
- machine_led.c \
- machine_pin.c \
- machine_pwm.c \
- machine_rtc.c \
- machine_sdcard.c \
- machine_spi.c \
- machine_timer.c \
- machine_uart.c \
- machine_wdt.c \
- mimxrt_flash.c \
- modmachine.c \
- modmimxrt.c \
- modutime.c \
- pin.c \
- shared/runtime/mpirq.c \
- shared/runtime/sys_stdio_mphal.c \
- $(GEN_PINS_SRC) \
-
OBJ += $(PY_O)
OBJ += $(LIBM_O)
OBJ += $(addprefix $(BUILD)/, $(SRC_C:.c=.o))
+OBJ += $(addprefix $(BUILD)/, $(SHARED_SRC_C:.c=.o))
OBJ += $(addprefix $(BUILD)/, $(SRC_S:.s=.o))
OBJ += $(addprefix $(BUILD)/, $(SRC_SS:.S=.o))
-OBJ += $(addprefix $(BUILD)/, $(SRC_MOD:.c=.o))
-OBJ += $(BUILD)/pins_gen.o
+OBJ += $(addprefix $(BUILD)/, $(SRC_TINYUSB_C:.c=.o))
+OBJ += $(addprefix $(BUILD)/, $(SRC_HAL_C:.c=.o))
+OBJ += $(addprefix $(BUILD)/, $(SRC_HAL_IMX_C:.c=.o))
+OBJ += $(addprefix $(BUILD)/, $(SRC_ETH_C:.c=.o))
+OBJ += $(GEN_PINS_SRC:.c=.o)
# Workaround for bug in older gcc, warning on "static usbd_device_t _usbd_dev = { 0 };"
$(BUILD)/lib/tinyusb/src/device/usbd.o: CFLAGS += -Wno-missing-braces
+# =============================================================================
+# Build targets
+# =============================================================================
+
all: $(BUILD)/firmware.hex $(BUILD)/firmware.bin
+# Process linker scripts with C preprocessor to exchange LDDEFINES and
+# aggregate output of preprocessor in a single linker script `link.ld`
$(BUILD)/firmware.elf: $(OBJ)
$(ECHO) "PREPROCESS LINK $@"
$(Q)$(CC) -E -x c $(LDDEFINES) $(LD_FILES) | grep -v '^#' > $(BUILD)/link.ld
@@ -462,9 +482,8 @@ $(HEADER_BUILD)/qstrdefs.generated.h: $(BOARD_DIR)/mpconfigboard.h
$(GEN_FLEXRAM_CONFIG_SRC):
$(ECHO) "Create $@"
- $(Q)$(PYTHON) $(MAKE_FLEXRAM_LD) -d $(TOP)/$(MCU_DIR)/$(MCU_SERIES).h \
- -f $(TOP)/$(MCU_DIR)/$(MCU_SERIES)_features.h -l boards/$(MCU_SERIES).ld -c $(MCU_SERIES) > $(GEN_FLEXRAM_CONFIG_SRC)
-
+ $(Q)$(PYTHON) $(MAKE_FLEXRAM_LD) -d $(TOP)/$(MCU_DIR)/$(MCU_SERIES)$(MCU_CORE).h \
+ -f $(TOP)/$(MCU_DIR)/$(MCU_SERIES)$(MCU_CORE)_features.h -l boards/$(MCU_SERIES).ld -c $(MCU_SERIES) > $(GEN_FLEXRAM_CONFIG_SRC)
# Use a pattern rule here so that make will only call make-pins.py once to make
# both pins_gen.c and pins.h
@@ -474,7 +493,7 @@ $(BUILD)/%_gen.c $(HEADER_BUILD)/%.h: $(BOARD_PINS) $(MAKE_PINS) $(AF_FILE) $(PR
--iomux $(abspath $(TOP)/$(MCU_DIR)/drivers/fsl_iomuxc.h) \
--prefix $(PREFIX_FILE) --hdr $(GEN_PINS_HDR) > $(GEN_PINS_SRC)
-$(BUILD)/pins_gen.o: $(BUILD)/pins_gen.c
+$(GEN_PINS_SRC:.c=.o): $(GEN_PINS_SRC)
$(call compile_c)
include $(TOP)/py/mkrules.mk
diff --git a/ports/mimxrt/README.md b/ports/mimxrt/README.md
index c8c5d989b9c8..de3de1e2817f 100644
--- a/ports/mimxrt/README.md
+++ b/ports/mimxrt/README.md
@@ -29,3 +29,47 @@ Known issues:
TODO:
- More peripherals (Counter, I2S, CAN, etc)
- More Python options
+
+## Build Instructions
+
+Before building the firmware for a given board the MicroPython cross-compiler
+must be built; it will be used to pre-compile some of the built-in scripts to
+bytecode. The cross-compiler is built and run on the host machine, using:
+
+ $ make -C mpy-cross
+
+This command should be executed from the root directory of this repository.
+All other commands below should be executed from the ports/mimxrt/ directory.
+
+An ARM compiler is required for the build, along with the associated binary
+utilities. The default compiler is `arm-none-eabi-gcc`, which is available for
+Arch Linux via the package `arm-none-eabi-gcc`, for Ubuntu via instructions
+[here](https://launchpad.net/~team-gcc-arm-embedded/+archive/ubuntu/ppa), or
+see [here](https://launchpad.net/gcc-arm-embedded) for the main GCC ARM
+Embedded page. The compiler can be changed using the `CROSS_COMPILE` variable
+when invoking `make`.
+
+In addition newlib is required which is available for Arch Linux via the
+package `arm-none-eabi-newlib`, for Ubuntu/Debian install package `libnewlib-arm-none-eabi`
+
+Next, the board to build must be selected. Any of the board names of the
+subdirectories in the `boards/` directory is a valid board. The board name
+must be passed as the argument to `BOARD=` when invoking `make`.
+
+All boards require certain submodules to be obtained before they can be built.
+The correct set of submodules can be initialised using (with `SEEED_ARCH_MIX`
+as an example of the selected board):
+
+ $ make BOARD=SEEED_ARCH_MIX submodules
+
+Then to build the board's firmware run:
+
+ $ make BOARD=SEEED_ARCH_MIX
+
+The above command should produce binary images in the `build-SEEED_ARCH_MIX/`
+subdirectory (or the equivalent directory for the board specified).
+
+## Flashing
+
+Deploy the firmware following the instructions here
+https://docs.micropython.org/en/latest/mimxrt/tutorial/intro.html#deploying-the-firmware
diff --git a/ports/mimxrt/board_init.c b/ports/mimxrt/board_init.c
index c3dbb652bc06..78001862f05d 100644
--- a/ports/mimxrt/board_init.c
+++ b/ports/mimxrt/board_init.c
@@ -40,10 +40,15 @@
#include CLOCK_CONFIG_H
#include "modmachine.h"
-
const uint8_t dcd_data[] = { 0x00 };
+void usb_phy0_init(uint8_t d_cal, uint8_t txcal45dp, uint8_t txcal45dn);
+
void board_init(void) {
+ // Clean and enable cache
+ SCB_CleanDCache();
+ SCB_EnableDCache();
+ SCB_EnableICache();
// Init clock
BOARD_BootClockRUN();
SystemCoreClockUpdate();
@@ -51,47 +56,20 @@ void board_init(void) {
// Enable IOCON clock
CLOCK_EnableClock(kCLOCK_Iomuxc);
- // ------------- SDRAM ------------ //
- #ifdef MICROPY_HW_SDRAM_AVAIL
+ // SDRAM
+ #if MICROPY_HW_SDRAM_AVAIL
mimxrt_sdram_init();
#endif
// 1ms tick timer
SysTick_Config(SystemCoreClock / 1000);
- // ------------- USB0 ------------- //
- // Clock
- CLOCK_EnableUsbhs0PhyPllClock(kCLOCK_Usbphy480M, 480000000U);
- CLOCK_EnableUsbhs0Clock(kCLOCK_Usb480M, 480000000U);
-
- #ifdef USBPHY1
- USBPHY_Type *usb_phy = USBPHY1;
- #else
- USBPHY_Type *usb_phy = USBPHY;
- #endif
-
- // Enable PHY support for Low speed device + LS via FS Hub
- usb_phy->CTRL |= USBPHY_CTRL_SET_ENUTMILEVEL2_MASK | USBPHY_CTRL_SET_ENUTMILEVEL3_MASK;
-
- // Enable all power for normal operation
- usb_phy->PWD = 0;
-
- // TX Timing
- uint32_t phytx = usb_phy->TX;
- phytx &= ~(USBPHY_TX_D_CAL_MASK | USBPHY_TX_TXCAL45DM_MASK | USBPHY_TX_TXCAL45DP_MASK);
- phytx |= USBPHY_TX_D_CAL(0x0C) | USBPHY_TX_TXCAL45DP(0x06) | USBPHY_TX_TXCAL45DM(0x06);
- usb_phy->TX = phytx;
-
- // USB1
- // CLOCK_EnableUsbhs1PhyPllClock(kCLOCK_Usbphy480M, 480000000U);
- // CLOCK_EnableUsbhs1Clock(kCLOCK_Usb480M, 480000000U);
+ // USB0
+ usb_phy0_init(0b0111, 0b0110, 0b0110); // Configure nominal values for D_CAL and TXCAL45DP/DN
// ADC
machine_adc_init();
- // PIT
- machine_timer_init_PIT();
-
// SDCard
#if MICROPY_PY_MACHINE_SDCARD
machine_sdcard_init0();
@@ -102,6 +80,49 @@ void board_init(void) {
#endif
// RTC
machine_rtc_start();
+
+ // OCRAM wait states (discarded, but code kept)
+ #if 0
+ MECC1->PIPE_ECC_EN =
+ MECC_PIPE_ECC_EN_READ_DATA_WAIT_EN(1) |
+ MECC_PIPE_ECC_EN_READ_ADDR_PIPE_EN(1) |
+ MECC_PIPE_ECC_EN_WRITE_DATA_PIPE_EN(1) |
+ MECC_PIPE_ECC_EN_WRITE_ADDR_PIPE_EN(1);
+
+ MECC2->PIPE_ECC_EN =
+ MECC_PIPE_ECC_EN_READ_DATA_WAIT_EN(1) |
+ MECC_PIPE_ECC_EN_READ_ADDR_PIPE_EN(1) |
+ MECC_PIPE_ECC_EN_WRITE_DATA_PIPE_EN(1) |
+ MECC_PIPE_ECC_EN_WRITE_ADDR_PIPE_EN(1);
+
+ FLEXRAM->FLEXRAM_CTRL =
+ FLEXRAM_FLEXRAM_CTRL_OCRAM_RDATA_WAIT_EN(1) |
+ FLEXRAM_FLEXRAM_CTRL_OCRAM_RADDR_PIPELINE_EN(1) |
+ FLEXRAM_FLEXRAM_CTRL_OCRAM_WRDATA_PIPELINE_EN(1) |
+ FLEXRAM_FLEXRAM_CTRL_OCRAM_WRADDR_PIPELINE_EN(1);
+ #endif
+}
+
+void usb_phy0_init(uint8_t d_cal, uint8_t txcal45dp, uint8_t txcal45dn) {
+ #ifdef USBPHY1
+ USBPHY_Type *usb_phy = USBPHY1;
+ #else
+ USBPHY_Type *usb_phy = USBPHY;
+ #endif
+
+ CLOCK_EnableUsbhs0PhyPllClock(kCLOCK_Usbphy480M, BOARD_XTAL0_CLK_HZ);
+ CLOCK_EnableUsbhs0Clock(kCLOCK_Usb480M, BOARD_XTAL0_CLK_HZ);
+
+ #if defined(MIMXRT117x_SERIES)
+ usb_phy->TRIM_OVERRIDE_EN = USBPHY_TRIM_OVERRIDE_EN_TRIM_DIV_SEL_OVERRIDE(1) |
+ USBPHY_TRIM_OVERRIDE_EN_TRIM_ENV_TAIL_ADJ_VD_OVERRIDE(1) |
+ USBPHY_TRIM_OVERRIDE_EN_TRIM_TX_D_CAL_OVERRIDE(1) |
+ USBPHY_TRIM_OVERRIDE_EN_TRIM_TX_CAL45DP_OVERRIDE(1) |
+ USBPHY_TRIM_OVERRIDE_EN_TRIM_TX_CAL45DN_OVERRIDE(1); // Enable override for D_CAL and TXCAL45DP/DN
+ #endif
+ usb_phy->PWD = 0U; // Set all bits in PWD register to normal operation
+ usb_phy->TX = ((usb_phy->TX & (~(USBPHY_TX_D_CAL_MASK | USBPHY_TX_TXCAL45DM_MASK | USBPHY_TX_TXCAL45DP_MASK))) |
+ (USBPHY_TX_D_CAL(d_cal) | USBPHY_TX_TXCAL45DP(txcal45dp) | USBPHY_TX_TXCAL45DM(txcal45dn))); // Configure values for D_CAL and TXCAL45DP/DN
}
void USB_OTG1_IRQHandler(void) {
diff --git a/ports/mimxrt/boards/MIMXRT1010_EVK/mpconfigboard.h b/ports/mimxrt/boards/MIMXRT1010_EVK/mpconfigboard.h
index 75fda0cad1f5..73055526a085 100644
--- a/ports/mimxrt/boards/MIMXRT1010_EVK/mpconfigboard.h
+++ b/ports/mimxrt/boards/MIMXRT1010_EVK/mpconfigboard.h
@@ -54,6 +54,7 @@
#define I2S_DMA_REQ_SRC_RX { 0, kDmaRequestMuxSai1Rx }
#define I2S_DMA_REQ_SRC_TX { 0, kDmaRequestMuxSai1Tx }
#define I2S_WM8960_RX_MODE (1)
+#define I2S_AUDIO_PLL_CLOCK (2U)
#define I2S_GPIO(_hwid, _fn, _mode, _pin, _iomux) \
{ \
@@ -74,6 +75,3 @@
I2S_GPIO(1, WS, TX, GPIO_07, IOMUXC_GPIO_07_SAI1_TX_SYNC), \
I2S_GPIO(1, SD, TX, GPIO_04, IOMUXC_GPIO_04_SAI1_TX_DATA00), \
}
-
-#define MICROPY_BOARD_ROOT_POINTERS \
- struct _machine_i2s_obj_t *machine_i2s_obj[MICROPY_HW_I2S_NUM];
diff --git a/ports/mimxrt/boards/MIMXRT1010_EVK/mpconfigboard.mk b/ports/mimxrt/boards/MIMXRT1010_EVK/mpconfigboard.mk
index c2a50d722be1..19db53c3f871 100644
--- a/ports/mimxrt/boards/MIMXRT1010_EVK/mpconfigboard.mk
+++ b/ports/mimxrt/boards/MIMXRT1010_EVK/mpconfigboard.mk
@@ -3,8 +3,8 @@ MCU_VARIANT = MIMXRT1011DAE5A
MICROPY_FLOAT_IMPL = single
MICROPY_PY_MACHINE_SDCARD = 0
-MICROPY_HW_FLASH_TYPE ?= qspi_nor
-MICROPY_HW_FLASH_SIZE ?= 0x1000000 # 16MB
+MICROPY_HW_FLASH_TYPE = qspi_nor_flash
+MICROPY_HW_FLASH_SIZE = 0x1000000 # 16MB
JLINK_PATH ?= /media/RT1010-EVK/
JLINK_COMMANDER_SCRIPT = $(BUILD)/script.jlink
diff --git a/ports/mimxrt/boards/MIMXRT1011.ld b/ports/mimxrt/boards/MIMXRT1011.ld
index 19bbc2770165..908eefffd643 100644
--- a/ports/mimxrt/boards/MIMXRT1011.ld
+++ b/ports/mimxrt/boards/MIMXRT1011.ld
@@ -3,7 +3,7 @@
reserved_size = MICROPY_HW_FLASH_RESERVED;
#endif
-#if MICROPY_HW_FLASH_TYPE==qspi_nor
+#if MICROPY_HW_FLASH_TYPE == qspi_nor_flash
flash_start = 0x60000000;
#else
#error Unknown MICROPY_HW_FLASH_TYPE
diff --git a/ports/mimxrt/boards/MIMXRT1015.ld b/ports/mimxrt/boards/MIMXRT1015.ld
index 6d34200a9f78..90336a243712 100644
--- a/ports/mimxrt/boards/MIMXRT1015.ld
+++ b/ports/mimxrt/boards/MIMXRT1015.ld
@@ -3,7 +3,7 @@
reserved_size = MICROPY_HW_FLASH_RESERVED;
#endif
-#if MICROPY_HW_FLASH_TYPE == qspi_nor
+#if MICROPY_HW_FLASH_TYPE == qspi_nor_flash
flash_start = 0x60000000;
#else
#error Unknown MICROPY_HW_FLASH_TYPE
diff --git a/ports/mimxrt/boards/MIMXRT1015_EVK/mpconfigboard.h b/ports/mimxrt/boards/MIMXRT1015_EVK/mpconfigboard.h
index 17326cb4853d..f37ba824f485 100644
--- a/ports/mimxrt/boards/MIMXRT1015_EVK/mpconfigboard.h
+++ b/ports/mimxrt/boards/MIMXRT1015_EVK/mpconfigboard.h
@@ -59,6 +59,7 @@
#define I2S_IOMUXC_GPR_MODE { 0, kIOMUXC_GPR_SAI1MClkOutputDir, kIOMUXC_GPR_SAI2MClkOutputDir }
#define I2S_DMA_REQ_SRC_RX { 0, kDmaRequestMuxSai1Rx, kDmaRequestMuxSai2Rx }
#define I2S_DMA_REQ_SRC_TX { 0, kDmaRequestMuxSai1Tx, kDmaRequestMuxSai2Tx }
+#define I2S_AUDIO_PLL_CLOCK (2U)
#define I2S_GPIO(_hwid, _fn, _mode, _pin, _iomux) \
{ \
@@ -79,6 +80,3 @@
I2S_GPIO(1, WS, TX, GPIO_EMC_27, IOMUXC_GPIO_EMC_27_SAI1_TX_SYNC), \
I2S_GPIO(1, SD, TX, GPIO_EMC_25, IOMUXC_GPIO_EMC_25_SAI1_TX_DATA00), \
}
-
-#define MICROPY_BOARD_ROOT_POINTERS \
- struct _machine_i2s_obj_t *machine_i2s_obj[MICROPY_HW_I2S_NUM];
diff --git a/ports/mimxrt/boards/MIMXRT1015_EVK/mpconfigboard.mk b/ports/mimxrt/boards/MIMXRT1015_EVK/mpconfigboard.mk
index 5d959b31d454..ba7d61f6d4f0 100644
--- a/ports/mimxrt/boards/MIMXRT1015_EVK/mpconfigboard.mk
+++ b/ports/mimxrt/boards/MIMXRT1015_EVK/mpconfigboard.mk
@@ -3,7 +3,7 @@ MCU_VARIANT = MIMXRT1015DAF5A
MICROPY_FLOAT_IMPL = single
MICROPY_PY_MACHINE_SDCARD = 0
-MICROPY_HW_FLASH_TYPE ?= qspi_nor
-MICROPY_HW_FLASH_SIZE ?= 0x1000000 # 16MB
+MICROPY_HW_FLASH_TYPE = qspi_nor_flash
+MICROPY_HW_FLASH_SIZE = 0x1000000 # 16MB
MICROPY_BOOT_BUFFER_SIZE = (32 * 1024)
diff --git a/ports/mimxrt/boards/MIMXRT1020_EVK/manifest.py b/ports/mimxrt/boards/MIMXRT1020_EVK/manifest.py
new file mode 100644
index 000000000000..107181c31ca7
--- /dev/null
+++ b/ports/mimxrt/boards/MIMXRT1020_EVK/manifest.py
@@ -0,0 +1,3 @@
+include("../manifest.py")
+
+require("bundle-networking")
diff --git a/ports/mimxrt/boards/MIMXRT1020_EVK/mpconfigboard.h b/ports/mimxrt/boards/MIMXRT1020_EVK/mpconfigboard.h
index 1dfe02b651f8..390e91814d16 100644
--- a/ports/mimxrt/boards/MIMXRT1020_EVK/mpconfigboard.h
+++ b/ports/mimxrt/boards/MIMXRT1020_EVK/mpconfigboard.h
@@ -1,6 +1,8 @@
#define MICROPY_HW_BOARD_NAME "i.MX RT1020 EVK"
#define MICROPY_HW_MCU_NAME "MIMXRT1021DAG5A"
+#define MICROPY_PY_NETWORK_HOSTNAME_DEFAULT "mpy-1020evk"
+
// i.MX RT1020 EVK has 1 board LED
// Todo: think about replacing the define with searching in the generated pins?
#define MICROPY_HW_LED1_PIN (pin_GPIO_AD_B0_05)
@@ -73,6 +75,7 @@
#define I2S_IOMUXC_GPR_MODE { 0, kIOMUXC_GPR_SAI1MClkOutputDir, kIOMUXC_GPR_SAI2MClkOutputDir }
#define I2S_DMA_REQ_SRC_RX { 0, kDmaRequestMuxSai1Rx, kDmaRequestMuxSai2Rx }
#define I2S_DMA_REQ_SRC_TX { 0, kDmaRequestMuxSai1Tx, kDmaRequestMuxSai2Tx }
+#define I2S_AUDIO_PLL_CLOCK (2U)
#define I2S_GPIO(_hwid, _fn, _mode, _pin, _iomux) \
{ \
@@ -158,8 +161,8 @@
#define ENET_PHY_OPS phyksz8081_ops
// Etherner PIN definitions
-#define ENET_RESET_PIN pin_GPIO_AD_B0_04
-#define ENET_INT_PIN pin_GPIO_AD_B1_06
+#define ENET_RESET_PIN &pin_GPIO_AD_B0_04
+#define ENET_INT_PIN &pin_GPIO_AD_B1_06
#define IOMUX_TABLE_ENET \
{ IOMUXC_GPIO_AD_B0_08_ENET_REF_CLK1, 1, 0xB0E9u }, \
@@ -172,6 +175,3 @@
{ IOMUXC_GPIO_AD_B0_15_ENET_TDATA01, 0, 0xB0E9u }, \
{ IOMUXC_GPIO_EMC_40_ENET_MDIO, 0, 0xB0E9u }, \
{ IOMUXC_GPIO_EMC_41_ENET_MDC, 0, 0xB0E9u },
-
-#define MICROPY_BOARD_ROOT_POINTERS \
- struct _machine_i2s_obj_t *machine_i2s_obj[MICROPY_HW_I2S_NUM];
diff --git a/ports/mimxrt/boards/MIMXRT1020_EVK/mpconfigboard.mk b/ports/mimxrt/boards/MIMXRT1020_EVK/mpconfigboard.mk
index c1e1678e5992..85bc1f71b606 100644
--- a/ports/mimxrt/boards/MIMXRT1020_EVK/mpconfigboard.mk
+++ b/ports/mimxrt/boards/MIMXRT1020_EVK/mpconfigboard.mk
@@ -3,8 +3,8 @@ MCU_VARIANT = MIMXRT1021DAG5A
MICROPY_FLOAT_IMPL = double
MICROPY_PY_MACHINE_SDCARD = 1
-MICROPY_HW_FLASH_TYPE ?= qspi_nor
-MICROPY_HW_FLASH_SIZE ?= 0x800000 # 8MB
+MICROPY_HW_FLASH_TYPE = qspi_nor_flash
+MICROPY_HW_FLASH_SIZE = 0x800000 # 8MB
MICROPY_HW_SDRAM_AVAIL = 1
MICROPY_HW_SDRAM_SIZE = 0x2000000 # 32MB
@@ -13,6 +13,8 @@ MICROPY_PY_LWIP = 1
MICROPY_PY_USSL = 1
MICROPY_SSL_MBEDTLS = 1
+FROZEN_MANIFEST ?= $(BOARD_DIR)/manifest.py
+
JLINK_PATH ?= /media/RT1020-EVK/
JLINK_COMMANDER_SCRIPT = $(BUILD)/script.jlink
diff --git a/ports/mimxrt/boards/MIMXRT1021.ld b/ports/mimxrt/boards/MIMXRT1021.ld
index 1263cd336c52..bef0c13df550 100644
--- a/ports/mimxrt/boards/MIMXRT1021.ld
+++ b/ports/mimxrt/boards/MIMXRT1021.ld
@@ -3,7 +3,7 @@
reserved_size = MICROPY_HW_FLASH_RESERVED;
#endif
-#if MICROPY_HW_FLASH_TYPE == qspi_nor
+#if MICROPY_HW_FLASH_TYPE == qspi_nor_flash
flash_start = 0x60000000;
#else
#error Unknown MICROPY_HW_FLASH_TYPE
@@ -27,7 +27,7 @@ dtcm_size = 0x00018000;
ocrm_start = 0x20200000;
ocrm_size = 0x00018000;
-#ifdef MICROPY_HW_SDRAM_AVAIL
+#if MICROPY_HW_SDRAM_AVAIL
sdram_start = 0x80000000;
sdram_size = MICROPY_HW_SDRAM_SIZE;
#endif
@@ -37,7 +37,7 @@ __stack_size__ = 0x6000;
_estack = __StackTop;
_sstack = __StackLimit;
-#ifdef MICROPY_HW_SDRAM_AVAIL
+#if MICROPY_HW_SDRAM_AVAIL
_gc_heap_start = ORIGIN(m_sdram);
_gc_heap_end = ORIGIN(m_sdram) + LENGTH(m_sdram);
#else
diff --git a/ports/mimxrt/boards/MIMXRT1050_EVK/manifest.py b/ports/mimxrt/boards/MIMXRT1050_EVK/manifest.py
new file mode 100644
index 000000000000..107181c31ca7
--- /dev/null
+++ b/ports/mimxrt/boards/MIMXRT1050_EVK/manifest.py
@@ -0,0 +1,3 @@
+include("../manifest.py")
+
+require("bundle-networking")
diff --git a/ports/mimxrt/boards/MIMXRT1050_EVK/mpconfigboard.h b/ports/mimxrt/boards/MIMXRT1050_EVK/mpconfigboard.h
index 613095e67fca..134c9637ea57 100644
--- a/ports/mimxrt/boards/MIMXRT1050_EVK/mpconfigboard.h
+++ b/ports/mimxrt/boards/MIMXRT1050_EVK/mpconfigboard.h
@@ -1,6 +1,8 @@
#define MICROPY_HW_BOARD_NAME "i.MX RT1050 EVKB-A1"
#define MICROPY_HW_MCU_NAME "MIMXRT1052DVL6B"
+#define MICROPY_PY_NETWORK_HOSTNAME_DEFAULT "mpy-1050evk"
+
// MIMXRT1050_EVKB has 1 user LED
#define MICROPY_HW_LED1_PIN (pin_GPIO_AD_B0_09)
#define MICROPY_HW_LED_ON(pin) (mp_hal_pin_low(pin))
@@ -62,6 +64,7 @@
#define I2S_DMA_REQ_SRC_RX { 0, kDmaRequestMuxSai1Rx, kDmaRequestMuxSai2Rx }
#define I2S_DMA_REQ_SRC_TX { 0, kDmaRequestMuxSai1Tx, kDmaRequestMuxSai2Tx }
#define I2S_WM8960_RX_MODE (1)
+#define I2S_AUDIO_PLL_CLOCK (2U)
#define I2S_GPIO(_hwid, _fn, _mode, _pin, _iomux) \
{ \
@@ -148,8 +151,8 @@
#define ENET_PHY_OPS phyksz8081_ops
// Etherner PIN definitions
-#define ENET_RESET_PIN pin_GPIO_AD_B0_09
-#define ENET_INT_PIN pin_GPIO_AD_B0_10
+#define ENET_RESET_PIN &pin_GPIO_AD_B0_09
+#define ENET_INT_PIN &pin_GPIO_AD_B0_10
#define IOMUX_TABLE_ENET \
{ IOMUXC_GPIO_B1_04_ENET_RX_DATA00, 0, 0xB0E9u }, \
@@ -162,6 +165,3 @@
{ IOMUXC_GPIO_B1_11_ENET_RX_ER, 0, 0xB0E9u }, \
{ IOMUXC_GPIO_EMC_41_ENET_MDIO, 0, 0xB0E9u }, \
{ IOMUXC_GPIO_EMC_40_ENET_MDC, 0, 0xB0E9u },
-
-#define MICROPY_BOARD_ROOT_POINTERS \
- struct _machine_i2s_obj_t *machine_i2s_obj[MICROPY_HW_I2S_NUM];
diff --git a/ports/mimxrt/boards/MIMXRT1050_EVK/mpconfigboard.mk b/ports/mimxrt/boards/MIMXRT1050_EVK/mpconfigboard.mk
index 65e3d30963d3..8e4213569a4f 100644
--- a/ports/mimxrt/boards/MIMXRT1050_EVK/mpconfigboard.mk
+++ b/ports/mimxrt/boards/MIMXRT1050_EVK/mpconfigboard.mk
@@ -3,8 +3,8 @@ MCU_VARIANT = MIMXRT1052DVL6B
MICROPY_FLOAT_IMPL = double
MICROPY_PY_MACHINE_SDCARD = 1
-MICROPY_HW_FLASH_TYPE ?= hyperflash
-MICROPY_HW_FLASH_SIZE ?= 0x4000000 # 64MB
+MICROPY_HW_FLASH_TYPE = qspi_hyper_flash
+MICROPY_HW_FLASH_SIZE = 0x4000000 # 64MB
MICROPY_HW_SDRAM_AVAIL = 1
MICROPY_HW_SDRAM_SIZE = 0x2000000 # 32MB
@@ -12,3 +12,5 @@ MICROPY_HW_SDRAM_SIZE = 0x2000000 # 32MB
MICROPY_PY_LWIP = 1
MICROPY_PY_USSL = 1
MICROPY_SSL_MBEDTLS = 1
+
+FROZEN_MANIFEST ?= $(BOARD_DIR)/manifest.py
diff --git a/ports/mimxrt/boards/MIMXRT1052.ld b/ports/mimxrt/boards/MIMXRT1052.ld
index f7c60d24f4d1..ca656711a5a7 100644
--- a/ports/mimxrt/boards/MIMXRT1052.ld
+++ b/ports/mimxrt/boards/MIMXRT1052.ld
@@ -3,9 +3,9 @@
reserved_size = MICROPY_HW_FLASH_RESERVED;
#endif
-#if MICROPY_HW_FLASH_TYPE==qspi_nor
+#if MICROPY_HW_FLASH_TYPE == qspi_nor_flash
flash_start = 0x60000000;
-#elif MICROPY_HW_FLASH_TYPE==hyperflash
+#elif MICROPY_HW_FLASH_TYPE == qspi_hyper_flash
flash_start = 0x60000000;
#else
#error Unknown MICROPY_HW_FLASH_TYPE
@@ -29,7 +29,7 @@ dtcm_size = 0x00020000;
ocrm_start = 0x20200000;
ocrm_size = 0x00040000;
-#ifdef MICROPY_HW_SDRAM_AVAIL
+#if MICROPY_HW_SDRAM_AVAIL
sdram_start = 0x80000000;
sdram_size = MICROPY_HW_SDRAM_SIZE;
#endif
@@ -39,7 +39,7 @@ __stack_size__ = 0x6000;
_estack = __StackTop;
_sstack = __StackLimit;
-#ifdef MICROPY_HW_SDRAM_AVAIL
+#if MICROPY_HW_SDRAM_AVAIL
_gc_heap_start = ORIGIN(m_sdram);
_gc_heap_end = ORIGIN(m_sdram) + LENGTH(m_sdram);
#else
diff --git a/ports/mimxrt/boards/MIMXRT1052_clock_config.c b/ports/mimxrt/boards/MIMXRT1052_clock_config.c
index 93492812977a..fa7450d487a6 100644
--- a/ports/mimxrt/boards/MIMXRT1052_clock_config.c
+++ b/ports/mimxrt/boards/MIMXRT1052_clock_config.c
@@ -465,4 +465,5 @@ void BOARD_BootClockRUN(void) {
IOMUXC_GPR->GPR5 &= ~IOMUXC_GPR_GPR5_VREF_1M_CLK_GPT2_MASK;
/* Set SystemCoreClock variable. */
SystemCoreClock = BOARD_BOOTCLOCKRUN_CORE_CLOCK;
+ CLOCK_SetMode(kCLOCK_ModeRun);
}
diff --git a/ports/mimxrt/boards/MIMXRT1060_EVK/manifest.py b/ports/mimxrt/boards/MIMXRT1060_EVK/manifest.py
new file mode 100644
index 000000000000..107181c31ca7
--- /dev/null
+++ b/ports/mimxrt/boards/MIMXRT1060_EVK/manifest.py
@@ -0,0 +1,3 @@
+include("../manifest.py")
+
+require("bundle-networking")
diff --git a/ports/mimxrt/boards/MIMXRT1060_EVK/mpconfigboard.h b/ports/mimxrt/boards/MIMXRT1060_EVK/mpconfigboard.h
index a3f0062389dd..01ae3ba303c6 100644
--- a/ports/mimxrt/boards/MIMXRT1060_EVK/mpconfigboard.h
+++ b/ports/mimxrt/boards/MIMXRT1060_EVK/mpconfigboard.h
@@ -1,6 +1,8 @@
#define MICROPY_HW_BOARD_NAME "i.MX RT1060 EVK"
#define MICROPY_HW_MCU_NAME "MIMXRT1062DVJ6A"
+#define MICROPY_PY_NETWORK_HOSTNAME_DEFAULT "mpy-1060evk"
+
// MIMXRT1060_EVK has 1 user LED
#define MICROPY_HW_LED1_PIN (pin_GPIO_AD_B0_09)
#define MICROPY_HW_LED_ON(pin) (mp_hal_pin_low(pin))
@@ -62,6 +64,7 @@
#define I2S_DMA_REQ_SRC_RX { 0, kDmaRequestMuxSai1Rx, kDmaRequestMuxSai2Rx }
#define I2S_DMA_REQ_SRC_TX { 0, kDmaRequestMuxSai1Tx, kDmaRequestMuxSai2Tx }
#define I2S_WM8960_RX_MODE (1)
+#define I2S_AUDIO_PLL_CLOCK (2U)
#define I2S_GPIO(_hwid, _fn, _mode, _pin, _iomux) \
{ \
@@ -146,8 +149,8 @@
#define ENET_PHY_OPS phyksz8081_ops
// Etherner PIN definitions
-#define ENET_RESET_PIN pin_GPIO_AD_B0_09
-#define ENET_INT_PIN pin_GPIO_AD_B0_10
+#define ENET_RESET_PIN &pin_GPIO_AD_B0_09
+#define ENET_INT_PIN &pin_GPIO_AD_B0_10
#define IOMUX_TABLE_ENET \
{ IOMUXC_GPIO_B1_04_ENET_RX_DATA00, 0, 0xB0E9u }, \
@@ -160,6 +163,3 @@
{ IOMUXC_GPIO_B1_11_ENET_RX_ER, 0, 0xB0E9u }, \
{ IOMUXC_GPIO_EMC_41_ENET_MDIO, 0, 0xB0E9u }, \
{ IOMUXC_GPIO_EMC_40_ENET_MDC, 0, 0xB0E9u },
-
-#define MICROPY_BOARD_ROOT_POINTERS \
- struct _machine_i2s_obj_t *machine_i2s_obj[MICROPY_HW_I2S_NUM];
diff --git a/ports/mimxrt/boards/MIMXRT1060_EVK/mpconfigboard.mk b/ports/mimxrt/boards/MIMXRT1060_EVK/mpconfigboard.mk
index 56ccba6e5929..22cd5356d93a 100644
--- a/ports/mimxrt/boards/MIMXRT1060_EVK/mpconfigboard.mk
+++ b/ports/mimxrt/boards/MIMXRT1060_EVK/mpconfigboard.mk
@@ -3,8 +3,8 @@ MCU_VARIANT = MIMXRT1062DVJ6A
MICROPY_FLOAT_IMPL = double
MICROPY_PY_MACHINE_SDCARD = 1
-MICROPY_HW_FLASH_TYPE ?= qspi_nor
-MICROPY_HW_FLASH_SIZE ?= 0x800000 # 8MB
+MICROPY_HW_FLASH_TYPE = qspi_nor_flash
+MICROPY_HW_FLASH_SIZE = 0x800000 # 8MB
MICROPY_HW_SDRAM_AVAIL = 1
MICROPY_HW_SDRAM_SIZE = 0x2000000 # 32MB
@@ -13,6 +13,8 @@ MICROPY_PY_LWIP = 1
MICROPY_PY_USSL = 1
MICROPY_SSL_MBEDTLS = 1
+FROZEN_MANIFEST ?= $(BOARD_DIR)/manifest.py
+
JLINK_PATH ?= /media/RT1060-EVK/
JLINK_COMMANDER_SCRIPT = $(BUILD)/script.jlink
diff --git a/ports/mimxrt/boards/MIMXRT1062.ld b/ports/mimxrt/boards/MIMXRT1062.ld
index f588e5bd9e23..5b91550d97d6 100644
--- a/ports/mimxrt/boards/MIMXRT1062.ld
+++ b/ports/mimxrt/boards/MIMXRT1062.ld
@@ -3,9 +3,9 @@
reserved_size = MICROPY_HW_FLASH_RESERVED;
#endif
-#if MICROPY_HW_FLASH_TYPE==qspi_nor
+#if MICROPY_HW_FLASH_TYPE == qspi_nor_flash
flash_start = 0x60000000;
-#elif MICROPY_HW_FLASH_TYPE==hyperflash
+#elif MICROPY_HW_FLASH_TYPE == qspi_hyper_flash
flash_start = 0x60000000;
#else
#error Unknown MICROPY_HW_FLASH_TYPE
@@ -29,7 +29,7 @@ dtcm_size = 0x00020000;
ocrm_start = 0x20200000;
ocrm_size = 0x000C0000;
-#ifdef MICROPY_HW_SDRAM_AVAIL
+#if MICROPY_HW_SDRAM_AVAIL
sdram_start = 0x80000000;
sdram_size = MICROPY_HW_SDRAM_SIZE;
#endif
@@ -39,7 +39,7 @@ __stack_size__ = 0x8000;
_estack = __StackTop;
_sstack = __StackLimit;
-#ifdef MICROPY_HW_SDRAM_AVAIL
+#if MICROPY_HW_SDRAM_AVAIL
_gc_heap_start = ORIGIN(m_sdram);
_gc_heap_end = ORIGIN(m_sdram) + LENGTH(m_sdram);
#else
diff --git a/ports/mimxrt/boards/MIMXRT1062_clock_config.c b/ports/mimxrt/boards/MIMXRT1062_clock_config.c
index 05474167bd85..589ffb0b5831 100644
--- a/ports/mimxrt/boards/MIMXRT1062_clock_config.c
+++ b/ports/mimxrt/boards/MIMXRT1062_clock_config.c
@@ -487,4 +487,5 @@ void BOARD_BootClockRUN(void) {
IOMUXC_GPR->GPR5 &= ~IOMUXC_GPR_GPR5_VREF_1M_CLK_GPT2_MASK;
/* Set SystemCoreClock variable. */
SystemCoreClock = BOARD_BOOTCLOCKRUN_CORE_CLOCK;
+ CLOCK_SetMode(kCLOCK_ModeRun);
}
diff --git a/ports/mimxrt/boards/MIMXRT1064.ld b/ports/mimxrt/boards/MIMXRT1064.ld
index b36c52845343..708dac4d515c 100644
--- a/ports/mimxrt/boards/MIMXRT1064.ld
+++ b/ports/mimxrt/boards/MIMXRT1064.ld
@@ -3,15 +3,7 @@
reserved_size = MICROPY_HW_FLASH_RESERVED;
#endif
-#if MICROPY_HW_FLASH_TYPE==qspi_nor
-flash_start = 0x60000000;
-#elif MICROPY_HW_FLASH_TYPE==hyperflash
-flash_start = 0x60000000;
-#elif MICROPY_HW_FLASH_TYPE==internal
-flash_start = 0x70000000;
-#else
-#error Unknown MICROPY_HW_FLASH_TYPE
-#endif
+flash_start = MICROPY_HW_FLASH_BASE;
flash_size = MICROPY_HW_FLASH_SIZE;
flash_end = DEFINED(reserved_size) ? ((flash_start) + (flash_size - reserved_size)) : ((flash_start) + (flash_size));
flash_config_start = flash_start;
@@ -31,7 +23,7 @@ dtcm_size = 0x00020000;
ocrm_start = 0x20200000;
ocrm_size = 0x000C0000;
-#ifdef MICROPY_HW_SDRAM_AVAIL
+#if MICROPY_HW_SDRAM_AVAIL
sdram_start = 0x80000000;
sdram_size = MICROPY_HW_SDRAM_SIZE;
#endif
@@ -41,7 +33,7 @@ __stack_size__ = 0x6000;
_estack = __StackTop;
_sstack = __StackLimit;
-#ifdef MICROPY_HW_SDRAM_AVAIL
+#if MICROPY_HW_SDRAM_AVAIL
_gc_heap_start = ORIGIN(m_sdram);
_gc_heap_end = ORIGIN(m_sdram) + LENGTH(m_sdram);
#else
diff --git a/ports/mimxrt/boards/MIMXRT1064_EVK/manifest.py b/ports/mimxrt/boards/MIMXRT1064_EVK/manifest.py
new file mode 100644
index 000000000000..107181c31ca7
--- /dev/null
+++ b/ports/mimxrt/boards/MIMXRT1064_EVK/manifest.py
@@ -0,0 +1,3 @@
+include("../manifest.py")
+
+require("bundle-networking")
diff --git a/ports/mimxrt/boards/MIMXRT1064_EVK/mpconfigboard.h b/ports/mimxrt/boards/MIMXRT1064_EVK/mpconfigboard.h
index fe1fb532b8c2..b6752c3e1ba3 100644
--- a/ports/mimxrt/boards/MIMXRT1064_EVK/mpconfigboard.h
+++ b/ports/mimxrt/boards/MIMXRT1064_EVK/mpconfigboard.h
@@ -1,6 +1,8 @@
#define MICROPY_HW_BOARD_NAME "i.MX RT1064 EVK"
#define MICROPY_HW_MCU_NAME "MIMXRT1064DVL6A"
+#define MICROPY_PY_NETWORK_HOSTNAME_DEFAULT "mpy-1064evk"
+
// MIMXRT1064_EVK has 1 user LED
#define MICROPY_HW_LED1_PIN (pin_GPIO_AD_B0_09)
#define MICROPY_HW_LED_ON(pin) (mp_hal_pin_low(pin))
@@ -62,6 +64,7 @@
#define I2S_DMA_REQ_SRC_RX { 0, kDmaRequestMuxSai1Rx, kDmaRequestMuxSai2Rx }
#define I2S_DMA_REQ_SRC_TX { 0, kDmaRequestMuxSai1Tx, kDmaRequestMuxSai2Tx }
#define I2S_WM8960_RX_MODE (1)
+#define I2S_AUDIO_PLL_CLOCK (2U)
#define I2S_GPIO(_hwid, _fn, _mode, _pin, _iomux) \
{ \
@@ -146,8 +149,8 @@
#define ENET_PHY_OPS phyksz8081_ops
// Etherner PIN definitions
-#define ENET_RESET_PIN pin_GPIO_AD_B0_09
-#define ENET_INT_PIN pin_GPIO_AD_B0_10
+#define ENET_RESET_PIN &pin_GPIO_AD_B0_09
+#define ENET_INT_PIN &pin_GPIO_AD_B0_10
#define IOMUX_TABLE_ENET \
{ IOMUXC_GPIO_B1_04_ENET_RX_DATA00, 0, 0xB0E9u }, \
@@ -160,6 +163,3 @@
{ IOMUXC_GPIO_B1_11_ENET_RX_ER, 0, 0xB0E9u }, \
{ IOMUXC_GPIO_EMC_41_ENET_MDIO, 0, 0xB0E9u }, \
{ IOMUXC_GPIO_EMC_40_ENET_MDC, 0, 0xB0E9u },
-
-#define MICROPY_BOARD_ROOT_POINTERS \
- struct _machine_i2s_obj_t *machine_i2s_obj[MICROPY_HW_I2S_NUM];
diff --git a/ports/mimxrt/boards/MIMXRT1064_EVK/mpconfigboard.mk b/ports/mimxrt/boards/MIMXRT1064_EVK/mpconfigboard.mk
index 5cd7d49abd58..b0bd7ec6ace4 100644
--- a/ports/mimxrt/boards/MIMXRT1064_EVK/mpconfigboard.mk
+++ b/ports/mimxrt/boards/MIMXRT1064_EVK/mpconfigboard.mk
@@ -3,8 +3,8 @@ MCU_VARIANT = MIMXRT1064DVL6A
MICROPY_FLOAT_IMPL = double
MICROPY_PY_MACHINE_SDCARD = 1
-MICROPY_HW_FLASH_TYPE ?= hyperflash
-MICROPY_HW_FLASH_SIZE ?= 0x4000000 # 64MB
+MICROPY_HW_FLASH_TYPE = internal
+MICROPY_HW_FLASH_SIZE = 0x400000 # 4MB
MICROPY_HW_SDRAM_AVAIL = 1
MICROPY_HW_SDRAM_SIZE = 0x2000000 # 32MB
@@ -13,6 +13,8 @@ MICROPY_PY_LWIP = 1
MICROPY_PY_USSL = 1
MICROPY_SSL_MBEDTLS = 1
+FROZEN_MANIFEST ?= $(BOARD_DIR)/manifest.py
+
JLINK_PATH ?= /media/RT1064-EVK/
deploy: $(BUILD)/firmware.bin
diff --git a/ports/mimxrt/boards/MIMXRT1064_clock_config.c b/ports/mimxrt/boards/MIMXRT1064_clock_config.c
index 5e49a2fff80e..56dd75d7fbf6 100644
--- a/ports/mimxrt/boards/MIMXRT1064_clock_config.c
+++ b/ports/mimxrt/boards/MIMXRT1064_clock_config.c
@@ -487,4 +487,5 @@ void BOARD_BootClockRUN(void) {
IOMUXC_GPR->GPR5 &= ~IOMUXC_GPR_GPR5_VREF_1M_CLK_GPT2_MASK;
/* Set SystemCoreClock variable. */
SystemCoreClock = BOARD_BOOTCLOCKRUN_CORE_CLOCK;
+ CLOCK_SetMode(kCLOCK_ModeRun);
}
diff --git a/ports/mimxrt/boards/MIMXRT1170_EVK/board.json b/ports/mimxrt/boards/MIMXRT1170_EVK/board.json
new file mode 100644
index 000000000000..01e554751b46
--- /dev/null
+++ b/ports/mimxrt/boards/MIMXRT1170_EVK/board.json
@@ -0,0 +1,28 @@
+{
+ "deploy": [
+ "../deploy_mimxrt.md"
+ ],
+ "docs": "",
+ "features": [
+ "Ethernet",
+ "SDRAM",
+ "MicroSD",
+ "MicroUSB",
+ "Microphone",
+ "AudioCodec",
+ "SPDIF",
+ "CAN",
+ "Camera",
+ "SIM Socket",
+ "OpenSDA",
+ "JLink"
+ ],
+ "images": [
+ "IMX-RT1170-EVK-TOP.jpg"
+ ],
+ "mcu": "mimxrt",
+ "product": "MIMXRT1170_EVK",
+ "thumbnail": "",
+ "url": "https://www.nxp.com/design/development-boards/i-mx-evaluation-and-development-boards/i-mx-rt1170-evaluation-kit:MIMXRT1170-EVK",
+ "vendor": "NXP"
+}
diff --git a/ports/mimxrt/boards/MIMXRT1170_EVK/manifest.py b/ports/mimxrt/boards/MIMXRT1170_EVK/manifest.py
new file mode 100644
index 000000000000..107181c31ca7
--- /dev/null
+++ b/ports/mimxrt/boards/MIMXRT1170_EVK/manifest.py
@@ -0,0 +1,3 @@
+include("../manifest.py")
+
+require("bundle-networking")
diff --git a/ports/mimxrt/boards/MIMXRT1170_EVK/mpconfigboard.h b/ports/mimxrt/boards/MIMXRT1170_EVK/mpconfigboard.h
new file mode 100644
index 000000000000..d37050eb5604
--- /dev/null
+++ b/ports/mimxrt/boards/MIMXRT1170_EVK/mpconfigboard.h
@@ -0,0 +1,257 @@
+#define MICROPY_HW_BOARD_NAME "i.MX RT1170 EVK"
+#define MICROPY_HW_MCU_NAME "MIMXRT1176DVMAA"
+
+#define MICROPY_PY_NETWORK_HOSTNAME_DEFAULT "mpy-1070evk"
+
+#define MICROPY_EVENT_POLL_HOOK \
+ do { \
+ extern void mp_handle_pending(bool); \
+ mp_handle_pending(true); \
+ } while (0);
+
+// MIMXRT1170_EVK has 2 user LEDs
+#define MICROPY_HW_LED1_PIN (pin_GPIO_AD_04)
+#define MICROPY_HW_LED2_PIN (pin_GPIO_AD_26)
+#define MICROPY_HW_LED_OFF(pin) (mp_hal_pin_low(pin))
+#define MICROPY_HW_LED_ON(pin) (mp_hal_pin_high(pin))
+
+#define MICROPY_HW_NUM_PIN_IRQS (6 * 32)
+
+// Define mapping hardware UART # to logical UART #
+// LPUART2 on D0/D1 -> 1
+// LPUART3 on D12/D11 -> 2
+// LPUART5 on D10/D13 -> 3
+// LPUART11 on D15/D14 -> 4
+// LPUART12 on D25/D26 -> 5
+// LPUART8 on D33/D34 -> 6
+// LPUART7 on D35/D36 -> 7
+
+#define MICROPY_HW_UART_NUM (sizeof(uart_index_table) / sizeof(uart_index_table)[0])
+#define MICROPY_HW_UART_INDEX { 1, 2, 3, 5, 11, 12, 8, 7 }
+
+#define IOMUX_TABLE_UART \
+ { IOMUXC_GPIO_AD_24_LPUART1_TXD }, { IOMUXC_GPIO_AD_25_LPUART1_RXD }, \
+ { IOMUXC_GPIO_DISP_B2_10_LPUART2_TXD }, { IOMUXC_GPIO_DISP_B2_11_LPUART2_RXD }, \
+ { IOMUXC_GPIO_AD_30_LPUART3_TXD }, { IOMUXC_GPIO_AD_31_LPUART3_RXD }, \
+ { 0 }, { 0 }, \
+ { IOMUXC_GPIO_AD_28_LPUART5_TXD }, { IOMUXC_GPIO_AD_29_LPUART5_RXD }, \
+ { 0 }, { 0 }, \
+ { IOMUXC_GPIO_AD_00_LPUART7_TXD }, { IOMUXC_GPIO_AD_01_LPUART7_RXD }, \
+ { IOMUXC_GPIO_AD_02_LPUART8_TXD }, { IOMUXC_GPIO_AD_03_LPUART8_RXD }, \
+ { 0 }, { 0 }, \
+ { 0 }, { 0 }, \
+ { IOMUXC_GPIO_LPSR_04_LPUART11_TXD }, { IOMUXC_GPIO_LPSR_05_LPUART11_RXD }, \
+ { IOMUXC_GPIO_LPSR_10_LPUART12_TXD }, { IOMUXC_GPIO_LPSR_11_LPUART12_RXD },
+
+// Define the mapping hardware SPI # to logical SPI #
+// SCK/CS/SDO/SDI HW-SPI Logical SPI
+// D13/D10/D11/D12 LPSPI1 -> 0
+// D26/D28/D25/D24 LPSPI6 -> 1
+// D24/ - /D14/D15 LPSPI5 -> 2
+
+#define MICROPY_HW_SPI_INDEX { 1, 6, 5 }
+
+#define IOMUX_TABLE_SPI \
+ { IOMUXC_GPIO_AD_28_LPSPI1_SCK }, { IOMUXC_GPIO_AD_29_LPSPI1_PCS0 }, \
+ { IOMUXC_GPIO_AD_30_LPSPI1_SOUT }, { IOMUXC_GPIO_AD_31_LPSPI1_SIN }, \
+ { 0 }, { 0 }, \
+ { 0 }, { 0 }, \
+ { 0 }, { 0 }, \
+ { 0 }, { 0 }, \
+ { 0 }, { 0 }, \
+ { 0 }, { 0 }, \
+ { IOMUXC_GPIO_LPSR_12_LPSPI5_SCK }, { IOMUXC_GPIO_LPSR_13_LPSPI5_PCS0 }, \
+ { IOMUXC_GPIO_LPSR_04_LPSPI5_SOUT }, { IOMUXC_GPIO_LPSR_05_LPSPI5_SIN }, \
+ { IOMUXC_GPIO_LPSR_10_LPSPI6_SCK }, { IOMUXC_GPIO_LPSR_09_LPSPI6_PCS0 }, \
+ { IOMUXC_GPIO_LPSR_11_LPSPI6_SOUT }, { IOMUXC_GPIO_LPSR_12_LPSPI6_SIN },
+
+
+#define DMA_REQ_SRC_RX { 0, kDmaRequestMuxLPSPI1Rx, kDmaRequestMuxLPSPI2Rx, \
+ kDmaRequestMuxLPSPI3Rx, kDmaRequestMuxLPSPI4Rx }
+
+#define DMA_REQ_SRC_TX { 0, kDmaRequestMuxLPSPI1Tx, kDmaRequestMuxLPSPI2Tx, \
+ kDmaRequestMuxLPSPI3Tx, kDmaRequestMuxLPSPI4Tx }
+
+// Define the mapping hardware I2C # to logical I2C #
+// SDA/SCL HW-I2C Logical I2C
+// D14/D15 LPI2C5 -> 0
+// D1/D0 LPI2C3 -> 1
+// A4/A5 LPI2C1 -> 2
+// D26/D25 LPI2C6 -> 3
+// D19/D18 LPI2C2 -> 4
+
+#define MICROPY_HW_I2C_INDEX { 5, 3, 1, 6, 2 }
+
+#define IOMUX_TABLE_I2C \
+ { IOMUXC_GPIO_AD_08_LPI2C1_SCL }, { IOMUXC_GPIO_AD_09_LPI2C1_SDA }, \
+ { IOMUXC_GPIO_AD_18_LPI2C2_SCL }, { IOMUXC_GPIO_AD_19_LPI2C2_SDA }, \
+ { IOMUXC_GPIO_DISP_B2_10_LPI2C3_SCL }, { IOMUXC_GPIO_DISP_B2_11_LPI2C3_SDA }, \
+ { 0 }, { 0 }, \
+ { IOMUXC_GPIO_LPSR_05_LPI2C5_SCL }, { IOMUXC_GPIO_LPSR_04_LPI2C5_SDA }, \
+ { IOMUXC_GPIO_LPSR_11_LPI2C6_SCL }, { IOMUXC_GPIO_LPSR_10_LPI2C6_SDA },
+
+#define MICROPY_PY_MACHINE_I2S (1)
+#define MICROPY_HW_I2S_NUM (1)
+#define I2S_CLOCK_MUX { 0, kCLOCK_Root_Sai1, kCLOCK_Root_Sai2, kCLOCK_Root_Sai3, kCLOCK_Root_Sai4 }
+#define I2S_DMA_REQ_SRC_RX { 0, kDmaRequestMuxSai1Rx, kDmaRequestMuxSai2Rx, kDmaRequestMuxSai3Rx, kDmaRequestMuxSai4Rx }
+#define I2S_DMA_REQ_SRC_TX { 0, kDmaRequestMuxSai1Tx, kDmaRequestMuxSai2Tx, kDmaRequestMuxSai3Tx, kDmaRequestMuxSai4Tx }
+#define I2S_WM8960_RX_MODE (1)
+#define I2S_AUDIO_PLL_CLOCK (4U)
+#define DMAMUX DMAMUX0
+
+#define I2S_GPIO(_hwid, _fn, _mode, _pin, _iomux) \
+ { \
+ .hw_id = _hwid, \
+ .fn = _fn, \
+ .mode = _mode, \
+ .name = MP_QSTR_##_pin, \
+ .iomux = {_iomux}, \
+ }
+
+#define I2S_GPIO_MAP \
+ { \
+ I2S_GPIO(1, MCK, TX, GPIO_AD_17, IOMUXC_GPIO_AD_17_SAI1_MCLK), \
+ I2S_GPIO(1, SCK, RX, GPIO_AD_19, IOMUXC_GPIO_AD_19_SAI1_RX_BCLK), \
+ I2S_GPIO(1, WS, RX, GPIO_AD_18, IOMUXC_GPIO_AD_18_SAI1_RX_SYNC), \
+ I2S_GPIO(1, SD, RX, GPIO_AD_20, IOMUXC_GPIO_AD_20_SAI1_RX_DATA00), \
+ I2S_GPIO(1, SCK, TX, GPIO_AD_22, IOMUXC_GPIO_AD_22_SAI1_TX_BCLK), \
+ I2S_GPIO(1, WS, TX, GPIO_AD_23, IOMUXC_GPIO_AD_23_SAI1_TX_SYNC), \
+ I2S_GPIO(1, SD, TX, GPIO_AD_21, IOMUXC_GPIO_AD_21_SAI1_TX_DATA00), \
+ }
+
+// USDHC1
+
+#define USDHC_DUMMY_PIN NULL, 0
+#define MICROPY_USDHC1 \
+ { \
+ .cmd = {GPIO_SD_B1_00_USDHC1_CMD}, \
+ .clk = { GPIO_SD_B1_01_USDHC1_CLK }, \
+ .cd_b = { USDHC_DUMMY_PIN }, \
+ .data0 = { GPIO_SD_B1_02_USDHC1_DATA0 }, \
+ .data1 = { GPIO_SD_B1_03_USDHC1_DATA1 }, \
+ .data2 = { GPIO_SD_B1_04_USDHC1_DATA2 }, \
+ .data3 = { GPIO_SD_B1_05_USDHC1_DATA3 }, \
+ }
+#define USDHC_DATA3_PULL_DOWN_ON_BOARD (1)
+
+// Network definitions
+
+// Transceiver Phy Parameters
+#define ENET_PHY_ADDRESS (2)
+#define ENET_PHY KSZ8081
+#define ENET_PHY_OPS phyksz8081_ops
+
+// 10/100 Ethernet PIN definitions
+#define ENET_RESET_PIN &pin_GPIO_LPSR_12
+#define ENET_INT_PIN &pin_GPIO_AD_12
+
+#define IOMUX_TABLE_ENET \
+ { IOMUXC_GPIO_DISP_B2_06_ENET_RX_DATA00, 0, 0x06u }, \
+ { IOMUXC_GPIO_DISP_B2_07_ENET_RX_DATA01, 0, 0x06u }, \
+ { IOMUXC_GPIO_DISP_B2_08_ENET_RX_EN, 0, 0x06u }, \
+ { IOMUXC_GPIO_DISP_B2_02_ENET_TX_DATA00, 0, 0x02u }, \
+ { IOMUXC_GPIO_DISP_B2_03_ENET_TX_DATA01, 0, 0x02u }, \
+ { IOMUXC_GPIO_DISP_B2_04_ENET_TX_EN, 0, 0x06u }, \
+ { IOMUXC_GPIO_DISP_B2_05_ENET_REF_CLK, 1, 0x03u }, \
+ { IOMUXC_GPIO_DISP_B2_09_ENET_RX_ER, 0, 0x06u }, \
+ { IOMUXC_GPIO_AD_33_ENET_MDIO, 0, 0x06u }, \
+ { IOMUXC_GPIO_AD_32_ENET_MDC, 0, 0x06u },
+
+// A second ETH port is present.
+#define ENET_DUAL_PORT (1)
+// 1G Transceiver Phy Parameters
+#define ENET_1_PHY_ADDRESS (1)
+#define ENET_1_PHY RTL8211F
+#define ENET_1_PHY_OPS phyrtl8211f_ops
+
+// 1G Ethernet PIN definitions
+// No INT pin for ENET_1G
+#define ENET_1_RESET_PIN &pin_GPIO_DISP_B2_13
+#define ENET_1_INT_PIN NULL
+
+#define IOMUX_TABLE_ENET_1 \
+ { IOMUXC_GPIO_DISP_B1_00_ENET_1G_RX_EN, 0, 0x08U }, \
+ { IOMUXC_GPIO_DISP_B1_01_ENET_1G_RX_CLK, 0, 0x08U }, \
+ { IOMUXC_GPIO_DISP_B1_02_ENET_1G_RX_DATA00, 0, 0x08U }, \
+ { IOMUXC_GPIO_DISP_B1_03_ENET_1G_RX_DATA01, 0, 0x08U }, \
+ { IOMUXC_GPIO_DISP_B1_04_ENET_1G_RX_DATA02, 0, 0x08U }, \
+ { IOMUXC_GPIO_DISP_B1_05_ENET_1G_RX_DATA03, 0, 0x08U }, \
+ { IOMUXC_GPIO_DISP_B1_06_ENET_1G_TX_DATA03, 0, 0x0CU }, \
+ { IOMUXC_GPIO_DISP_B1_07_ENET_1G_TX_DATA02, 0, 0x0CU }, \
+ { IOMUXC_GPIO_DISP_B1_08_ENET_1G_TX_DATA01, 0, 0x0CU }, \
+ { IOMUXC_GPIO_DISP_B1_09_ENET_1G_TX_DATA00, 0, 0x0CU }, \
+ { IOMUXC_GPIO_DISP_B1_10_ENET_1G_TX_EN, 0, 0x0CU }, \
+ { IOMUXC_GPIO_DISP_B1_11_ENET_1G_TX_CLK_IO, 0, 0x0CU }, \
+ { IOMUXC_GPIO_EMC_B2_20_ENET_1G_MDIO, 0, 0x06u }, \
+ { IOMUXC_GPIO_EMC_B2_19_ENET_1G_MDC, 0, 0x06u },
+
+// --- SEMC --- //
+#define MIMXRT_IOMUXC_SEMC_DATA00 IOMUXC_GPIO_EMC_B1_00_SEMC_DATA00
+#define MIMXRT_IOMUXC_SEMC_DATA01 IOMUXC_GPIO_EMC_B1_01_SEMC_DATA01
+#define MIMXRT_IOMUXC_SEMC_DATA02 IOMUXC_GPIO_EMC_B1_02_SEMC_DATA02
+#define MIMXRT_IOMUXC_SEMC_DATA03 IOMUXC_GPIO_EMC_B1_03_SEMC_DATA03
+#define MIMXRT_IOMUXC_SEMC_DATA04 IOMUXC_GPIO_EMC_B1_04_SEMC_DATA04
+#define MIMXRT_IOMUXC_SEMC_DATA05 IOMUXC_GPIO_EMC_B1_05_SEMC_DATA05
+#define MIMXRT_IOMUXC_SEMC_DATA06 IOMUXC_GPIO_EMC_B1_06_SEMC_DATA06
+#define MIMXRT_IOMUXC_SEMC_DATA07 IOMUXC_GPIO_EMC_B1_07_SEMC_DATA07
+#define MIMXRT_IOMUXC_SEMC_DATA08 IOMUXC_GPIO_EMC_B1_30_SEMC_DATA08
+#define MIMXRT_IOMUXC_SEMC_DATA09 IOMUXC_GPIO_EMC_B1_31_SEMC_DATA09
+#define MIMXRT_IOMUXC_SEMC_DATA10 IOMUXC_GPIO_EMC_B1_32_SEMC_DATA10
+#define MIMXRT_IOMUXC_SEMC_DATA11 IOMUXC_GPIO_EMC_B1_33_SEMC_DATA11
+#define MIMXRT_IOMUXC_SEMC_DATA12 IOMUXC_GPIO_EMC_B1_34_SEMC_DATA12
+#define MIMXRT_IOMUXC_SEMC_DATA13 IOMUXC_GPIO_EMC_B1_35_SEMC_DATA13
+#define MIMXRT_IOMUXC_SEMC_DATA14 IOMUXC_GPIO_EMC_B1_36_SEMC_DATA14
+#define MIMXRT_IOMUXC_SEMC_DATA15 IOMUXC_GPIO_EMC_B1_37_SEMC_DATA15
+
+#define MIMXRT_IOMUXC_SEMC_ADDR00 IOMUXC_GPIO_EMC_B1_09_SEMC_ADDR00
+#define MIMXRT_IOMUXC_SEMC_ADDR01 IOMUXC_GPIO_EMC_B1_10_SEMC_ADDR01
+#define MIMXRT_IOMUXC_SEMC_ADDR02 IOMUXC_GPIO_EMC_B1_11_SEMC_ADDR02
+#define MIMXRT_IOMUXC_SEMC_ADDR03 IOMUXC_GPIO_EMC_B1_12_SEMC_ADDR03
+#define MIMXRT_IOMUXC_SEMC_ADDR04 IOMUXC_GPIO_EMC_B1_13_SEMC_ADDR04
+#define MIMXRT_IOMUXC_SEMC_ADDR05 IOMUXC_GPIO_EMC_B1_14_SEMC_ADDR05
+#define MIMXRT_IOMUXC_SEMC_ADDR06 IOMUXC_GPIO_EMC_B1_15_SEMC_ADDR06
+#define MIMXRT_IOMUXC_SEMC_ADDR07 IOMUXC_GPIO_EMC_B1_16_SEMC_ADDR07
+#define MIMXRT_IOMUXC_SEMC_ADDR08 IOMUXC_GPIO_EMC_B1_17_SEMC_ADDR08
+#define MIMXRT_IOMUXC_SEMC_ADDR09 IOMUXC_GPIO_EMC_B1_18_SEMC_ADDR09
+#define MIMXRT_IOMUXC_SEMC_ADDR10 IOMUXC_GPIO_EMC_B1_23_SEMC_ADDR10
+#define MIMXRT_IOMUXC_SEMC_ADDR11 IOMUXC_GPIO_EMC_B1_19_SEMC_ADDR11
+#define MIMXRT_IOMUXC_SEMC_ADDR12 IOMUXC_GPIO_EMC_B1_20_SEMC_ADDR12
+
+#define MIMXRT_IOMUXC_SEMC_BA0 IOMUXC_GPIO_EMC_B1_21_SEMC_BA0
+#define MIMXRT_IOMUXC_SEMC_BA1 IOMUXC_GPIO_EMC_B1_22_SEMC_BA1
+#define MIMXRT_IOMUXC_SEMC_CAS IOMUXC_GPIO_EMC_B1_24_SEMC_CAS
+#define MIMXRT_IOMUXC_SEMC_RAS IOMUXC_GPIO_EMC_B1_25_SEMC_RAS
+#define MIMXRT_IOMUXC_SEMC_CLK IOMUXC_GPIO_EMC_B1_26_SEMC_CLK
+#define MIMXRT_IOMUXC_SEMC_CKE IOMUXC_GPIO_EMC_B1_27_SEMC_CKE
+#define MIMXRT_IOMUXC_SEMC_WE IOMUXC_GPIO_EMC_B1_28_SEMC_WE
+#define MIMXRT_IOMUXC_SEMC_DM00 IOMUXC_GPIO_EMC_B1_08_SEMC_DM00
+#define MIMXRT_IOMUXC_SEMC_DM01 IOMUXC_GPIO_EMC_B1_38_SEMC_DM01
+#define MIMXRT_IOMUXC_SEMC_DQS IOMUXC_GPIO_EMC_B1_39_SEMC_DQS
+
+#define MIMXRT_IOMUXC_SEMC_CS0 IOMUXC_GPIO_EMC_B1_29_SEMC_CS0
+
+#define MIMXRT_IOMUXC_SEMC_DATA16 IOMUXC_GPIO_EMC_B2_00_SEMC_DATA16
+#define MIMXRT_IOMUXC_SEMC_DATA17 IOMUXC_GPIO_EMC_B2_01_SEMC_DATA17
+#define MIMXRT_IOMUXC_SEMC_DATA18 IOMUXC_GPIO_EMC_B2_02_SEMC_DATA18
+#define MIMXRT_IOMUXC_SEMC_DATA19 IOMUXC_GPIO_EMC_B2_03_SEMC_DATA19
+#define MIMXRT_IOMUXC_SEMC_DATA20 IOMUXC_GPIO_EMC_B2_04_SEMC_DATA20
+#define MIMXRT_IOMUXC_SEMC_DATA21 IOMUXC_GPIO_EMC_B2_05_SEMC_DATA21
+#define MIMXRT_IOMUXC_SEMC_DATA22 IOMUXC_GPIO_EMC_B2_06_SEMC_DATA22
+#define MIMXRT_IOMUXC_SEMC_DATA23 IOMUXC_GPIO_EMC_B2_07_SEMC_DATA23
+#define MIMXRT_IOMUXC_SEMC_DM02 IOMUXC_GPIO_EMC_B2_08_SEMC_DM02
+
+#define MIMXRT_IOMUXC_SEMC_DATA24 IOMUXC_GPIO_EMC_B2_09_SEMC_DATA24
+#define MIMXRT_IOMUXC_SEMC_DATA25 IOMUXC_GPIO_EMC_B2_10_SEMC_DATA25
+#define MIMXRT_IOMUXC_SEMC_DATA26 IOMUXC_GPIO_EMC_B2_11_SEMC_DATA26
+#define MIMXRT_IOMUXC_SEMC_DATA27 IOMUXC_GPIO_EMC_B2_12_SEMC_DATA27
+#define MIMXRT_IOMUXC_SEMC_DATA28 IOMUXC_GPIO_EMC_B2_13_SEMC_DATA28
+#define MIMXRT_IOMUXC_SEMC_DATA29 IOMUXC_GPIO_EMC_B2_14_SEMC_DATA29
+#define MIMXRT_IOMUXC_SEMC_DATA30 IOMUXC_GPIO_EMC_B2_15_SEMC_DATA30
+#define MIMXRT_IOMUXC_SEMC_DATA31 IOMUXC_GPIO_EMC_B2_16_SEMC_DATA31
+#define MIMXRT_IOMUXC_SEMC_DM03 IOMUXC_GPIO_EMC_B2_17_SEMC_DM03
+#define MIMXRT_IOMUXC_SEMC_DQS4 IOMUXC_GPIO_EMC_B2_18_SEMC_DQS4
+
+#if MICROPY_PY_MACHINE_I2S
+#define MICROPY_BOARD_ROOT_POINTERS \
+ struct _machine_i2s_obj_t *machine_i2s_obj[MICROPY_HW_I2S_NUM];
+#endif
diff --git a/ports/mimxrt/boards/MIMXRT1170_EVK/mpconfigboard.mk b/ports/mimxrt/boards/MIMXRT1170_EVK/mpconfigboard.mk
new file mode 100644
index 000000000000..dc44b93bd073
--- /dev/null
+++ b/ports/mimxrt/boards/MIMXRT1170_EVK/mpconfigboard.mk
@@ -0,0 +1,25 @@
+MCU_SERIES = MIMXRT1176
+MCU_VARIANT = MIMXRT1176DVMAA
+MCU_CORE = _cm7
+
+MICROPY_FLOAT_IMPL = double
+MICROPY_PY_MACHINE_SDCARD = 1
+MICROPY_HW_FLASH_TYPE ?= qspi_nor_flash
+MICROPY_HW_FLASH_SIZE ?= 0x1000000 # 16MB
+MICROPY_HW_FLASH_RESERVED ?= 0x100000 # 1MB CM4 Code address space
+
+MICROPY_HW_SDRAM_AVAIL = 1
+MICROPY_HW_SDRAM_SIZE = 0x4000000 # 64MB
+
+MICROPY_PY_LWIP = 1
+MICROPY_PY_USSL = 1
+MICROPY_SSL_MBEDTLS = 1
+
+FROZEN_MANIFEST ?= $(BOARD_DIR)/manifest.py
+
+CFLAGS += -DCPU_MIMXRT1176DVMAA_cm7 \
+ -DMIMXRT117x_SERIES \
+ -DENET_ENHANCEDBUFFERDESCRIPTOR_MODE=1 \
+ -DCPU_HEADER_H='<$(MCU_SERIES)$(MCU_CORE).h>' \
+ -DUSB1_BASE=USB_OTG1_BASE \
+ -DUSB2_BASE=USB_OTG2_BASE
diff --git a/ports/mimxrt/boards/MIMXRT1170_EVK/pins.csv b/ports/mimxrt/boards/MIMXRT1170_EVK/pins.csv
new file mode 100644
index 000000000000..77f87e8ba15c
--- /dev/null
+++ b/ports/mimxrt/boards/MIMXRT1170_EVK/pins.csv
@@ -0,0 +1,59 @@
+D0,GPIO_DISP_B2_11
+D1,GPIO_DISP_B2_10
+D2,GPIO_DISP_B2_12
+D3,GPIO_AD_04
+D4,GPIO_AD_06
+D5,GPIO_AD_05
+D6,GPIO_AD_00
+D7,GPIO_AD_14
+D8,GPIO_AD_07
+D9,GPIO_AD_01
+D10,GPIO_AD_29
+D11,GPIO_AD_30
+D12,GPIO_AD_31
+D13,GPIO_AD_28
+D14,GPIO_LPSR_04
+D15,GPIO_LPSR_05
+D16,GPIO_AD_19
+D17,GPIO_DISP_B2_12
+D18,GPIO_AD_18
+D19,GPIO_AD_20
+D20,GPIO_AD_21
+D21,GPIO_AD_22
+D22,GPIO_AD_23
+D23,GPIO_AD_17
+D24,GPIO_LPSR_12
+D25,GPIO_LPSR_11
+D26,GPIO_LPSR_10
+D27,GPIO_LPSR_09
+D29,GPIO_DISP_B2_11
+D30,GPIO_DISP_B2_10
+D31,GPIO_AD_05
+D32,GPIO_AD_04
+D33,GPIO_AD_03
+D34,GPIO_AD_02
+D35,GPIO_AD_01
+D36,GPIO_AD_00
+A0,GPIO_AD_10
+A1,GPIO_AD_11
+A2,GPIO_AD_12
+A3,GPIO_AD_13
+A4,GPIO_AD_09
+A5,GPIO_AD_08
+RX,GPIO_DISP_B2_11
+TX,GPIO_DISP_B2_10
+SCL,GPIO_LPSR_05
+SDA,GPIO_LPSR_04
+SCK,GPIO_AD_28
+SDI,GPIO_AD_31
+SDO,GPIO_AD_30
+CS,GPIO_AD_29
+LED1,GPIO_AD_04
+LED2,GPIO_AD_26
+MCK,GPIO_AD_17
+SCK_RX,GPIO_AD_19
+WS_RX,GPIO_AD_18
+SD_RX,GPIO_AD_20
+SCK_TX,GPIO_AD_22
+WS_TX,GPIO_AD_23
+SD_TX,GPIO_AD_21
diff --git a/ports/mimxrt/boards/MIMXRT1176.ld b/ports/mimxrt/boards/MIMXRT1176.ld
new file mode 100644
index 000000000000..2408977b9410
--- /dev/null
+++ b/ports/mimxrt/boards/MIMXRT1176.ld
@@ -0,0 +1,59 @@
+/* Memory configuration */
+
+/* Reserved Area
+ * Users can create a reserved area at the end of the flash memory via
+ * 'reserved_size' variable. The size of the reserved area should be a multiple
+ * of the sector size of the flash memory!
+ */
+#if defined MICROPY_HW_FLASH_RESERVED
+reserved_size = MICROPY_HW_FLASH_RESERVED;
+#endif
+
+#if MICROPY_HW_FLASH_TYPE == qspi_nor
+flash_start = 0x30000000;
+#else
+#error Unknown MICROPY_HW_FLASH_TYPE
+#endif
+flash_size = MICROPY_HW_FLASH_SIZE;
+flash_end = DEFINED(reserved_size) ? ((flash_start) + (flash_size - reserved_size)) : ((flash_start) + (flash_size));
+flash_config_start = flash_start + 0x400; /* TODO: check why config_start is on 0x400 instead of 0x0 offset */
+flash_config_size = 0x00000C00;
+ivt_start = flash_start + 0x00001000;
+ivt_size = 0x00001000;
+interrupts_start = flash_start + 0x00002000;
+interrupts_size = 0x00000400;
+text_start = flash_start + 0x00002400;
+vfs_start = flash_start + 0x00200000;
+
+#if defined MULTI_CORE
+m_core1_image_start = vfs_start - 0x00040000;
+m_core1_image_size = 0x00040000;
+#endif
+
+text_size = ((vfs_start) - (text_start));
+vfs_size = ((flash_end) - (vfs_start));
+itcm_start = 0x00000000;
+itcm_size = 0x00020000;
+dtcm_start = 0x20000000;
+dtcm_size = 0x00020000;
+ocrm_start = 0x20240000;
+ocrm_size = 0x00100000;
+
+#ifdef MICROPY_HW_SDRAM_AVAIL
+sdram_start = 0x80000000;
+sdram_size = MICROPY_HW_SDRAM_SIZE;
+#endif
+
+/* 32kiB stack. */
+__stack_size__ = 0x8000;
+_estack = __StackTop;
+_sstack = __StackLimit;
+
+#ifdef MICROPY_HW_SDRAM_AVAIL
+_gc_heap_start = ORIGIN(m_sdram);
+_gc_heap_end = ORIGIN(m_sdram) + LENGTH(m_sdram);
+#else
+/* Use second OCRAM bank for GC heap. */
+_gc_heap_start = ORIGIN(m_ocrm);
+_gc_heap_end = ORIGIN(m_ocrm) + LENGTH(m_ocrm);
+#endif
diff --git a/ports/mimxrt/boards/MIMXRT1176_af.csv b/ports/mimxrt/boards/MIMXRT1176_af.csv
new file mode 100644
index 000000000000..fe31f502e4ed
--- /dev/null
+++ b/ports/mimxrt/boards/MIMXRT1176_af.csv
@@ -0,0 +1,173 @@
+Pad,ALT0,ALT1,ALT2,ALT3,ALT4,ALT5,ALT6,ALT7,ALT8,ALT9,ALT10,ADC,ACMP,Default
+GPIO_SD_B1_00,USDHC1_CMD,,XBAR1_INOUT20,GPT4_CAPTURE1,,GPIO4_IO03,FLEXSPI2_A_SS0_B,,KPP_ROW07,,GPIO10_IO03,,,
+GPIO_SD_B1_01,USDHC1_CLK,,XBAR1_INOUT21,GPT4_CAPTURE2,,GPIO4_IO04,FLEXSPI2_A_SCLK,,KPP_COL07,,GPIO10_IO04,,,
+GPIO_SD_B1_02,USDHC1_DATA0,,XBAR1_INOUT22,GPT4_COMPARE1,,GPIO4_IO05,FLEXSPI2_A_DATA00,,KPP_ROW06,FLEXSPI1_A_SS1_B,GPIO10_IO05,,,
+GPIO_SD_B1_03,USDHC1_DATA1,,XBAR1_INOUT23,GPT4_COMPARE2,,GPIO4_IO06,FLEXSPI2_A_DATA01,,KPP_COL06,FLEXSPI1_B_SS1_B,GPIO10_IO06,,,
+GPIO_SD_B1_04,USDHC1_DATA2,,XBAR1_INOUT24,GPT4_COMPARE3,,GPIO4_IO07,FLEXSPI2_A_DATA02,,FLEXSPI1_B_SS0_B,ENET_QOS_1588_EVENT2_AUX_IN,GPIO10_IO07,,,
+GPIO_SD_B1_05,USDHC1_DATA3,,XBAR1_INOUT25,GPT4_CLK,,GPIO4_IO08,FLEXSPI2_A_DATA03,,FLEXSPI1_B_DQS,ENET_QOS_1588_EVENT3_AUX_IN,GPIO10_IO08,,,
+GPIO_SD_B2_00,USDHC2_DATA3,FLEXSPI1_B_DATA03,ENET_1G_RX_EN,LPUART9_TXD,LPSPI4_SCK,GPIO4_IO09,,,,,GPIO10_IO09,,,
+GPIO_SD_B2_01,USDHC2_DATA2,FLEXSPI1_B_DATA02,ENET_1G_RX_CLK,LPUART9_RXD,LPSPI4_PCS0,GPIO4_IO10,,,,,GPIO10_IO10,,,
+GPIO_SD_B2_02,USDHC2_DATA1,FLEXSPI1_B_DATA01,ENET_1G_RX_DATA00,LPUART9_CTS_B,LPSPI4_SOUT,GPIO4_IO11,,,,,GPIO10_IO11,,,
+GPIO_SD_B2_03,USDHC2_DATA0,FLEXSPI1_B_DATA00,ENET_1G_RX_DATA01,LPUART9_RTS_B,LPSPI4_SIN,GPIO4_IO12,,,,,GPIO10_IO12,,,
+GPIO_SD_B2_04,USDHC2_CLK,FLEXSPI1_B_SCLK,ENET_1G_RX_DATA02,FLEXSPI1_A_SS1_B,LPSPI4_PCS1,GPIO4_IO13,,,,,GPIO10_IO13,,,
+GPIO_SD_B2_05,USDHC2_CMD,FLEXSPI1_A_DQS,ENET_1G_RX_DATA03,FLEXSPI1_B_SS0_B,LPSPI4_PCS2,GPIO4_IO14,,,,,GPIO10_IO14,,,
+GPIO_SD_B2_06,USDHC2_RESET_B,FLEXSPI1_A_SS0_B,ENET_1G_TX_DATA03,LPSPI4_PCS3,GPT6_CAPTURE1,GPIO4_IO15,,,,,GPIO10_IO15,,,
+GPIO_SD_B2_07,USDHC2_STROBE,FLEXSPI1_A_SCLK,ENET_1G_TX_DATA02,LPUART3_CTS_B,GPT6_CAPTURE2,GPIO4_IO16,LPSPI2_SCK,,ENET_TX_ER,ENET_QOS_REF_CLK,GPIO10_IO16,,,
+GPIO_SD_B2_08,USDHC2_DATA4,FLEXSPI1_A_DATA00,ENET_1G_TX_DATA01,LPUART3_RTS_B,GPT6_COMPARE1,GPIO4_IO17,LPSPI2_PCS0,,,,GPIO10_IO17,,,
+GPIO_SD_B2_09,USDHC2_DATA5,FLEXSPI1_A_DATA01,ENET_1G_TX_DATA00,LPUART5_CTS_B,GPT6_COMPARE2,GPIO4_IO18,LPSPI2_SOUT,,,,GPIO10_IO18,,,
+GPIO_SD_B2_10,USDHC2_DATA6,FLEXSPI1_A_DATA02,ENET_1G_TX_EN,LPUART5_RTS_B,GPT6_COMPARE3,GPIO4_IO19,LPSPI2_SIN,,,,GPIO10_IO19,,,
+GPIO_SD_B2_11,USDHC2_DATA7,FLEXSPI1_A_DATA03,ENET_1G_TX_CLK_IO,ENET_1G_REF_CLK,GPT6_CLK,GPIO4_IO20,LPSPI2_PCS1,,,,GPIO10_IO20,,,
+GPIO_EMC_B1_00,SEMC_DATA00,FLEXPWM4_PWM0_A,,,,GPIO1_IO00,,,FLEXIO1_D00,,GPIO7_IO00,,,
+GPIO_EMC_B1_01,SEMC_DATA01,FLEXPWM4_PWM0_B,,,,GPIO1_IO01,,,FLEXIO1_D01,,GPIO7_IO01,,,
+GPIO_EMC_B1_02,SEMC_DATA02,FLEXPWM4_PWM1_A,,,,GPIO1_IO02,,,FLEXIO1_D02,,GPIO7_IO02,,,
+GPIO_EMC_B1_03,SEMC_DATA03,FLEXPWM4_PWM1_B,,,,GPIO1_IO03,,,FLEXIO1_D03,,GPIO7_IO03,,,
+GPIO_EMC_B1_04,SEMC_DATA04,FLEXPWM4_PWM2_A,,,,GPIO1_IO04,,,FLEXIO1_D04,,GPIO7_IO04,,,
+GPIO_EMC_B1_05,SEMC_DATA05,FLEXPWM4_PWM2_B,,,,GPIO1_IO05,,,FLEXIO1_D05,,GPIO7_IO05,,,
+GPIO_EMC_B1_06,SEMC_DATA06,FLEXPWM2_PWM0_A,,,,GPIO1_IO06,,,FLEXIO1_D06,,GPIO7_IO06,,,
+GPIO_EMC_B1_07,SEMC_DATA07,FLEXPWM2_PWM0_B,,,,GPIO1_IO07,,,FLEXIO1_D07,,GPIO7_IO07,,,
+GPIO_EMC_B1_08,SEMC_DM00,FLEXPWM2_PWM1_A,,,,GPIO1_IO08,,,FLEXIO1_D08,,GPIO7_IO08,,,
+GPIO_EMC_B1_09,SEMC_ADDR00,FLEXPWM2_PWM1_B,GPT5_CAPTURE1,,,GPIO1_IO09,,,FLEXIO1_D09,,GPIO7_IO09,,,
+GPIO_EMC_B1_10,SEMC_ADDR01,FLEXPWM2_PWM2_A,GPT5_CAPTURE2,,,GPIO1_IO10,,,FLEXIO1_D10,,GPIO7_IO10,,,
+GPIO_EMC_B1_11,SEMC_ADDR02,FLEXPWM2_PWM2_B,GPT5_COMPARE1,,,GPIO1_IO11,,,FLEXIO1_D11,,GPIO7_IO11,,,
+GPIO_EMC_B1_12,SEMC_ADDR03,XBAR1_INOUT04,GPT5_COMPARE2,,,GPIO1_IO12,,,FLEXIO1_D12,,GPIO7_IO12,,,
+GPIO_EMC_B1_13,SEMC_ADDR04,XBAR1_INOUT05,GPT5_COMPARE3,,,GPIO1_IO13,,,FLEXIO1_D13,,GPIO7_IO13,,,
+GPIO_EMC_B1_14,SEMC_ADDR05,XBAR1_INOUT06,GPT5_CLK,,,GPIO1_IO14,,,FLEXIO1_D14,,GPIO7_IO14,,,
+GPIO_EMC_B1_15,SEMC_ADDR06,XBAR1_INOUT07,,,,GPIO1_IO15,,,FLEXIO1_D15,,GPIO7_IO15,,,
+GPIO_EMC_B1_16,SEMC_ADDR07,XBAR1_INOUT08,,,,GPIO1_IO16,,,FLEXIO1_D16,,GPIO7_IO16,,,
+GPIO_EMC_B1_17,SEMC_ADDR08,FLEXPWM4_PWM3_A,TMR1_TIMER0,,,GPIO1_IO17,,,FLEXIO1_D17,,GPIO7_IO17,,,
+GPIO_EMC_B1_18,SEMC_ADDR09,FLEXPWM4_PWM3_B,TMR2_TIMER0,,,GPIO1_IO18,,,FLEXIO1_D18,,GPIO7_IO18,,,
+GPIO_EMC_B1_19,SEMC_ADDR11,FLEXPWM2_PWM3_A,TMR3_TIMER0,,,GPIO1_IO19,,,FLEXIO1_D19,,GPIO7_IO19,,,
+GPIO_EMC_B1_20,SEMC_ADDR12,FLEXPWM2_PWM3_B,TMR4_TIMER0,,,GPIO1_IO20,,,FLEXIO1_D20,,GPIO7_IO20,,,
+GPIO_EMC_B1_21,SEMC_BA0,FLEXPWM3_PWM3_A,,,,GPIO1_IO21,,,FLEXIO1_D21,,GPIO7_IO21,,,
+GPIO_EMC_B1_22,SEMC_BA1,FLEXPWM3_PWM3_B,,,,GPIO1_IO22,,,FLEXIO1_D22,,GPIO7_IO22,,,
+GPIO_EMC_B1_23,SEMC_ADDR10,FLEXPWM1_PWM0_A,,,,GPIO1_IO23,,,FLEXIO1_D23,,GPIO7_IO23,,,
+GPIO_EMC_B1_24,SEMC_CAS,FLEXPWM1_PWM0_B,,,,GPIO1_IO24,,,FLEXIO1_D24,,GPIO7_IO24,,,
+GPIO_EMC_B1_25,SEMC_RAS,FLEXPWM1_PWM1_A,,,,GPIO1_IO25,,,FLEXIO1_D25,,GPIO7_IO25,,,
+GPIO_EMC_B1_26,SEMC_CLK,FLEXPWM1_PWM1_B,,,,GPIO1_IO26,,,FLEXIO1_D26,,GPIO7_IO26,,,
+GPIO_EMC_B1_27,SEMC_CKE,FLEXPWM1_PWM2_A,,,,GPIO1_IO27,,,FLEXIO1_D27,,GPIO7_IO27,,,
+GPIO_EMC_B1_28,SEMC_WE,FLEXPWM1_PWM2_B,,,,GPIO1_IO28,,,FLEXIO1_D28,,GPIO7_IO28,,,
+GPIO_EMC_B1_29,SEMC_CS0,FLEXPWM3_PWM0_A,,,,GPIO1_IO29,,,FLEXIO1_D29,,GPIO7_IO29,,,
+GPIO_EMC_B1_30,SEMC_DATA08,FLEXPWM3_PWM0_B,,,,GPIO1_IO30,,,FLEXIO1_D30,,GPIO7_IO30,,,
+GPIO_EMC_B1_31,SEMC_DATA09,FLEXPWM3_PWM1_A,,,,GPIO1_IO31,,,FLEXIO1_D31,,GPIO7_IO31,,,
+GPIO_EMC_B1_32,SEMC_DATA10,FLEXPWM3_PWM1_B,,,,GPIO2_IO00,,,,,GPIO8_IO00,,,
+GPIO_EMC_B1_33,SEMC_DATA11,FLEXPWM3_PWM2_A,,,,GPIO2_IO01,,,,,GPIO8_IO01,,,
+GPIO_EMC_B1_34,SEMC_DATA12,FLEXPWM3_PWM2_B,,,,GPIO2_IO02,,,,,GPIO8_IO02,,,
+GPIO_EMC_B1_35,SEMC_DATA13,XBAR1_INOUT09,,,,GPIO2_IO03,,,,,GPIO8_IO03,,,
+GPIO_EMC_B1_36,SEMC_DATA14,XBAR1_INOUT10,,,,GPIO2_IO04,,,,,GPIO8_IO04,,,
+GPIO_EMC_B1_37,SEMC_DATA15,XBAR1_INOUT11,,,,GPIO2_IO05,,,,,GPIO8_IO05,,,
+GPIO_EMC_B1_38,SEMC_DM01,FLEXPWM1_PWM3_A,TMR1_TIMER1,,,GPIO2_IO06,,,,,GPIO8_IO06,,,
+GPIO_EMC_B1_39,SEMC_DQS,FLEXPWM1_PWM3_B,TMR2_TIMER1,,,GPIO2_IO07,,,,,GPIO8_IO07,,,
+GPIO_EMC_B1_40,SEMC_RDY,XBAR1_INOUT12,MQS_RIGHT,LPUART6_TXD,,GPIO2_IO08,,ENET_1G_MDC,,CCM_CLKO1,GPIO8_IO08,,,
+GPIO_EMC_B1_41,SEMC_CSX00,XBAR1_INOUT13,MQS_LEFT,LPUART6_RXD,FLEXSPI2_B_DATA07,GPIO2_IO09,,ENET_1G_MDIO,,CCM_CLKO2,GPIO8_IO09,,,
+GPIO_EMC_B2_00,SEMC_DATA16,CCM_ENET_REF_CLK_25M,TMR3_TIMER1,LPUART6_CTS_B,FLEXSPI2_B_DATA06,GPIO2_IO10,XBAR1_INOUT20,ENET_QOS_1588_EVENT1_OUT,LPSPI1_SCK,LPI2C2_SCL,GPIO8_IO10,,,
+GPIO_EMC_B2_01,SEMC_DATA17,USDHC2_CD_B,TMR4_TIMER1,LPUART6_RTS_B,FLEXSPI2_B_DATA05,GPIO2_IO11,XBAR1_INOUT21,ENET_QOS_1588_EVENT1_IN,LPSPI1_PCS0,LPI2C2_SDA,GPIO8_IO11,,,
+GPIO_EMC_B2_02,SEMC_DATA18,USDHC2_WP,,VIDEO_MUX_CSI_DATA23,FLEXSPI2_B_DATA04,GPIO2_IO12,XBAR1_INOUT22,ENET_QOS_1588_EVENT1_AUX_IN,LPSPI1_SOUT,,GPIO8_IO12,,,
+GPIO_EMC_B2_03,SEMC_DATA19,USDHC2_VSELECT,,VIDEO_MUX_CSI_DATA22,FLEXSPI2_B_DATA03,GPIO2_IO13,XBAR1_INOUT23,ENET_1G_TX_DATA03,LPSPI1_SIN,,GPIO8_IO13,,,
+GPIO_EMC_B2_04,SEMC_DATA20,USDHC2_RESET_B,SAI2_MCLK,VIDEO_MUX_CSI_DATA21,FLEXSPI2_B_DATA02,GPIO2_IO14,XBAR1_INOUT24,ENET_1G_TX_DATA02,LPSPI3_SCK,,GPIO8_IO14,,,
+GPIO_EMC_B2_05,SEMC_DATA21,GPT3_CLK,SAI2_RX_SYNC,VIDEO_MUX_CSI_DATA20,FLEXSPI2_B_DATA01,GPIO2_IO15,XBAR1_INOUT25,ENET_1G_RX_CLK,LPSPI3_PCS0,PIT1_TRIGGER0,GPIO8_IO15,,,
+GPIO_EMC_B2_06,SEMC_DATA22,GPT3_CAPTURE1,SAI2_RX_BCLK,VIDEO_MUX_CSI_DATA19,FLEXSPI2_B_DATA00,GPIO2_IO16,XBAR1_INOUT26,ENET_1G_TX_ER,LPSPI3_SOUT,PIT1_TRIGGER1,GPIO8_IO16,,,
+GPIO_EMC_B2_07,SEMC_DATA23,GPT3_CAPTURE2,SAI2_RX_DATA,VIDEO_MUX_CSI_DATA18,FLEXSPI2_B_DQS,GPIO2_IO17,XBAR1_INOUT27,ENET_1G_RX_DATA03,LPSPI3_SIN,PIT1_TRIGGER2,GPIO8_IO17,,,
+GPIO_EMC_B2_08,SEMC_DM02,GPT3_COMPARE1,SAI2_TX_DATA,VIDEO_MUX_CSI_DATA17,FLEXSPI2_B_SS0_B,GPIO2_IO18,XBAR1_INOUT28,ENET_1G_RX_DATA02,LPSPI3_PCS1,PIT1_TRIGGER3,GPIO8_IO18,,,
+GPIO_EMC_B2_09,SEMC_DATA24,GPT3_COMPARE2,SAI2_TX_BCLK,VIDEO_MUX_CSI_DATA16,FLEXSPI2_B_SCLK,GPIO2_IO19,XBAR1_INOUT29,ENET_1G_CRS,LPSPI3_PCS2,TMR1_TIMER0,GPIO8_IO19,,,
+GPIO_EMC_B2_10,SEMC_DATA25,GPT3_COMPARE3,SAI2_TX_SYNC,VIDEO_MUX_CSI_FIELD,FLEXSPI2_A_SCLK,GPIO2_IO20,XBAR1_INOUT30,ENET_1G_COL,LPSPI3_PCS3,TMR1_TIMER1,GPIO8_IO20,,,
+GPIO_EMC_B2_11,SEMC_DATA26,SPDIF_IN,ENET_1G_TX_DATA00,SAI3_RX_SYNC,FLEXSPI2_A_SS0_B,GPIO2_IO21,XBAR1_INOUT31,,EMVSIM1_IO,TMR1_TIMER2,GPIO8_IO21,,,
+GPIO_EMC_B2_12,SEMC_DATA27,SPDIF_OUT,ENET_1G_TX_DATA01,SAI3_RX_BCLK,FLEXSPI2_A_DQS,GPIO2_IO22,XBAR1_INOUT32,,EMVSIM1_CLK,TMR1_TIMER3,GPIO8_IO22,,,
+GPIO_EMC_B2_13,SEMC_DATA28,,ENET_1G_TX_EN,SAI3_RX_DATA,FLEXSPI2_A_DATA00,GPIO2_IO23,XBAR1_INOUT33,,EMVSIM1_RST,TMR2_TIMER0,GPIO8_IO23,,,
+GPIO_EMC_B2_14,SEMC_DATA29,,ENET_1G_TX_CLK_IO,SAI3_TX_DATA,FLEXSPI2_A_DATA01,GPIO2_IO24,XBAR1_INOUT34,SFA_ipp_do_atx_clk_under_test,EMVSIM1_SVEN,TMR2_TIMER1,GPIO8_IO24,,,
+GPIO_EMC_B2_15,SEMC_DATA30,,ENET_1G_RX_DATA00,SAI3_TX_BCLK,FLEXSPI2_A_DATA02,GPIO2_IO25,XBAR1_INOUT35,,EMVSIM1_PD,TMR2_TIMER2,GPIO8_IO25,,,
+GPIO_EMC_B2_16,SEMC_DATA31,XBAR1_INOUT14,ENET_1G_RX_DATA01,SAI3_TX_SYNC,FLEXSPI2_A_DATA03,GPIO2_IO26,,,EMVSIM1_POWER_FAIL,TMR2_TIMER3,GPIO8_IO26,,,
+GPIO_EMC_B2_17,SEMC_DM03,XBAR1_INOUT15,ENET_1G_RX_EN,SAI3_MCLK,FLEXSPI2_A_DATA04,GPIO2_IO27,,,WDOG1_ANY,TMR3_TIMER0,GPIO8_IO27,,,
+GPIO_EMC_B2_18,SEMC_DQS4,XBAR1_INOUT16,ENET_1G_RX_ER,EWM_OUT_B,FLEXSPI2_A_DATA05,GPIO2_IO28,FLEXSPI1_A_DQS,,WDOG1_B,TMR3_TIMER1,GPIO8_IO28,,,
+GPIO_EMC_B2_19,SEMC_CLKX00,ENET_MDC,ENET_1G_MDC,ENET_1G_REF_CLK,FLEXSPI2_A_DATA06,GPIO2_IO29,,,ENET_QOS_MDC,TMR3_TIMER2,GPIO8_IO29,,,
+GPIO_EMC_B2_20,SEMC_CLKX01,ENET_MDIO,ENET_1G_MDIO,ENET_QOS_REF_CLK,FLEXSPI2_A_DATA07,GPIO2_IO30,,,ENET_QOS_MDIO,TMR3_TIMER3,GPIO8_IO30,,,
+GPIO_SNVS_00,SNVS_TAMPER0,,,,,GPIO13_IO03,,,,,,,,
+GPIO_SNVS_01,SNVS_TAMPER1,,,,,GPIO13_IO04,,,,,,,,
+GPIO_SNVS_02,SNVS_TAMPER2,,,,,GPIO13_IO05,,,,,,,,
+GPIO_SNVS_03,SNVS_TAMPER3,,,,,GPIO13_IO06,,,,,,,,
+GPIO_SNVS_04,SNVS_TAMPER4,,,,,GPIO13_IO07,,,,,,,,
+GPIO_SNVS_05,SNVS_TAMPER5,,,,,GPIO13_IO08,,,,,,,,
+GPIO_SNVS_06,SNVS_TAMPER6,,,,,GPIO13_IO09,,,,,,,,
+GPIO_SNVS_07,SNVS_TAMPER7,,,,,GPIO13_IO10,,,,,,,,
+GPIO_SNVS_08,SNVS_TAMPER8,,,,,GPIO13_IO11,,,,,,,,
+GPIO_SNVS_09,SNVS_TAMPER9,,,,,GPIO13_IO12,,,,,,,,
+GPIO_LPSR_00,FLEXCAN3_TX,MIC_CLK,MQS_RIGHT,ARM_CM4_EVENTO,,GPIO6_IO00,LPUART12_TXD,SAI4_MCLK,,,GPIO12_IO00,,,
+GPIO_LPSR_01,FLEXCAN3_RX,MIC_BITSTREAM0,MQS_LEFT,ARM_CM4_EVENTI,,GPIO6_IO01,LPUART12_RXD,,,,GPIO12_IO01,,,
+GPIO_LPSR_02,SRC_BOOT_MODE00,LPSPI5_SCK,SAI4_TX_DATA,MQS_RIGHT,,GPIO6_IO02,,,,,GPIO12_IO02,,,
+GPIO_LPSR_03,SRC_BOOT_MODE01,LPSPI5_PCS0,SAI4_TX_SYNC,MQS_LEFT,,GPIO6_IO03,,,,,GPIO12_IO03,,,
+GPIO_LPSR_04,LPI2C5_SDA,LPSPI5_SOUT,SAI4_TX_BCLK,LPUART12_RTS_B,,GPIO6_IO04,LPUART11_TXD,,,,GPIO12_IO04,,,
+GPIO_LPSR_05,LPI2C5_SCL,LPSPI5_SIN,SAI4_MCLK,LPUART12_CTS_B,,GPIO6_IO05,LPUART11_RXD,NMI_GLUE_NMI,,,GPIO12_IO05,,,
+GPIO_LPSR_06,LPI2C6_SDA,,SAI4_RX_DATA,LPUART12_TXD,LPSPI6_PCS3,GPIO6_IO06,FLEXCAN3_TX,PIT2_TRIGGER3,LPSPI5_PCS1,,GPIO12_IO06,,,
+GPIO_LPSR_07,LPI2C6_SCL,,SAI4_RX_BCLK,LPUART12_RXD,LPSPI6_PCS2,GPIO6_IO07,FLEXCAN3_RX,PIT2_TRIGGER2,LPSPI5_PCS2,,GPIO12_IO07,,,
+GPIO_LPSR_08,LPUART11_TXD,FLEXCAN3_TX,SAI4_RX_SYNC,MIC_CLK,LPSPI6_PCS1,GPIO6_IO08,LPI2C5_SDA,PIT2_TRIGGER1,LPSPI5_PCS3,,GPIO12_IO08,,,
+GPIO_LPSR_09,LPUART11_RXD,FLEXCAN3_RX,PIT2_TRIGGER0,MIC_BITSTREAM0,LPSPI6_PCS0,GPIO6_IO09,LPI2C5_SCL,SAI4_TX_DATA,,,GPIO12_IO09,,,
+GPIO_LPSR_10,JTAG_MUX_TRSTB,LPUART11_CTS_B,LPI2C6_SDA,MIC_BITSTREAM1,LPSPI6_SCK,GPIO6_IO10,LPI2C5_SCLS,SAI4_TX_SYNC,LPUART12_TXD,,GPIO12_IO10,,,
+GPIO_LPSR_11,JTAG_MUX_TDO,LPUART11_RTS_B,LPI2C6_SCL,MIC_BITSTREAM2,LPSPI6_SOUT,GPIO6_IO11,LPI2C5_SDAS,ARM_TRACE_SWO,LPUART12_RXD,,GPIO12_IO11,,,
+GPIO_LPSR_12,JTAG_MUX_TDI,PIT2_TRIGGER0,,MIC_BITSTREAM3,LPSPI6_SIN,GPIO6_IO12,LPI2C5_HREQ,SAI4_TX_BCLK,LPSPI5_SCK,,GPIO12_IO12,,,
+GPIO_LPSR_13,JTAG_MUX_MOD,MIC_BITSTREAM1,PIT2_TRIGGER1,,,GPIO6_IO13,,SAI4_RX_DATA,LPSPI5_PCS0,,GPIO12_IO13,,,
+GPIO_LPSR_14,JTAG_MUX_TCK,MIC_BITSTREAM2,PIT2_TRIGGER2,,,GPIO6_IO14,,SAI4_RX_BCLK,LPSPI5_SOUT,,GPIO12_IO14,,,
+GPIO_LPSR_15,JTAG_MUX_TMS,MIC_BITSTREAM3,PIT2_TRIGGER3,,,GPIO6_IO15,,SAI4_RX_SYNC,LPSPI5_SIN,,GPIO12_IO15,,,
+WAKEUP_DIG,,,,,,GPIO13_IO00,,NMI_GLUE_NMI,,,,,,
+GPIO_DISP_B1_00,VIDEO_MUX_LCDIF_CLK,ENET_1G_RX_EN,,TMR1_TIMER0,XBAR1_INOUT26,GPIO4_IO21,,,ENET_QOS_RX_EN,,GPIO10_IO21,,,
+GPIO_DISP_B1_01,VIDEO_MUX_LCDIF_ENABLE,ENET_1G_RX_CLK,ENET_1G_RX_ER,TMR1_TIMER1,XBAR1_INOUT27,GPIO4_IO22,,,ENET_QOS_RX_CLK,ENET_QOS_RX_ER,GPIO10_IO22,,,
+GPIO_DISP_B1_02,VIDEO_MUX_LCDIF_HSYNC,ENET_1G_RX_DATA00,LPI2C3_SCL,TMR1_TIMER2,XBAR1_INOUT28,GPIO4_IO23,,,ENET_QOS_RX_DATA00,LPUART1_TXD,GPIO10_IO23,,,
+GPIO_DISP_B1_03,VIDEO_MUX_LCDIF_VSYNC,ENET_1G_RX_DATA01,LPI2C3_SDA,TMR2_TIMER0,XBAR1_INOUT29,GPIO4_IO24,,,ENET_QOS_RX_DATA01,LPUART1_RXD,GPIO10_IO24,,,
+GPIO_DISP_B1_04,VIDEO_MUX_LCDIF_DATA00,ENET_1G_RX_DATA02,LPUART4_RXD,TMR2_TIMER1,XBAR1_INOUT30,GPIO4_IO25,,,ENET_QOS_RX_DATA02,LPSPI3_SCK,GPIO10_IO25,,,
+GPIO_DISP_B1_05,VIDEO_MUX_LCDIF_DATA01,ENET_1G_RX_DATA03,LPUART4_CTS_B,TMR2_TIMER2,XBAR1_INOUT31,GPIO4_IO26,,,ENET_QOS_RX_DATA03,LPSPI3_SIN,GPIO10_IO26,,,
+GPIO_DISP_B1_06,VIDEO_MUX_LCDIF_DATA02,ENET_1G_TX_DATA03,LPUART4_TXD,TMR3_TIMER0,XBAR1_INOUT32,GPIO4_IO27,SRC_BT_CFG00,,ENET_QOS_TX_DATA03,LPSPI3_SOUT,GPIO10_IO27,,,
+GPIO_DISP_B1_07,VIDEO_MUX_LCDIF_DATA03,ENET_1G_TX_DATA02,LPUART4_RTS_B,TMR3_TIMER1,XBAR1_INOUT33,GPIO4_IO28,SRC_BT_CFG01,,ENET_QOS_TX_DATA02,LPSPI3_PCS0,GPIO10_IO28,,,
+GPIO_DISP_B1_08,VIDEO_MUX_LCDIF_DATA04,ENET_1G_TX_DATA01,USDHC1_CD_B,TMR3_TIMER2,XBAR1_INOUT34,GPIO4_IO29,SRC_BT_CFG02,,ENET_QOS_TX_DATA01,LPSPI3_PCS1,GPIO10_IO29,,,
+GPIO_DISP_B1_09,VIDEO_MUX_LCDIF_DATA05,ENET_1G_TX_DATA00,USDHC1_WP,TMR4_TIMER0,XBAR1_INOUT35,GPIO4_IO30,SRC_BT_CFG03,,ENET_QOS_TX_DATA00,LPSPI3_PCS2,GPIO10_IO30,,,
+GPIO_DISP_B1_10,VIDEO_MUX_LCDIF_DATA06,ENET_1G_TX_EN,USDHC1_RESET_B,TMR4_TIMER1,XBAR1_INOUT36,GPIO4_IO31,SRC_BT_CFG04,,ENET_QOS_TX_EN,LPSPI3_PCS3,GPIO10_IO31,,,
+GPIO_DISP_B1_11,VIDEO_MUX_LCDIF_DATA07,ENET_1G_TX_CLK_IO,ENET_1G_REF_CLK,TMR4_TIMER2,XBAR1_INOUT37,GPIO5_IO00,SRC_BT_CFG05,,ENET_QOS_TX_CLK,ENET_QOS_REF_CLK,GPIO11_IO00,,,
+GPIO_DISP_B2_00,VIDEO_MUX_LCDIF_DATA08,WDOG1_B,MQS_RIGHT,ENET_1G_TX_ER,SAI1_TX_DATA03,GPIO5_IO01,SRC_BT_CFG06,,ENET_QOS_TX_ER,,GPIO11_IO01,,,
+GPIO_DISP_B2_01,VIDEO_MUX_LCDIF_DATA09,USDHC1_VSELECT,MQS_LEFT,WDOG2_B,SAI1_TX_DATA02,GPIO5_IO02,SRC_BT_CFG07,,EWM_OUT_B,CCM_ENET_REF_CLK_25M,GPIO11_IO02,,,
+GPIO_DISP_B2_02,VIDEO_MUX_LCDIF_DATA10,ENET_TX_DATA00,PIT1_TRIGGER3,ARM_TRACE00,SAI1_TX_DATA01,GPIO5_IO03,SRC_BT_CFG08,,ENET_QOS_TX_DATA00,,GPIO11_IO03,,,
+GPIO_DISP_B2_03,VIDEO_MUX_LCDIF_DATA11,ENET_TX_DATA01,PIT1_TRIGGER2,ARM_TRACE01,SAI1_MCLK,GPIO5_IO04,SRC_BT_CFG09,,ENET_QOS_TX_DATA01,,GPIO11_IO04,,,
+GPIO_DISP_B2_04,VIDEO_MUX_LCDIF_DATA12,ENET_TX_EN,PIT1_TRIGGER1,ARM_TRACE02,SAI1_RX_SYNC,GPIO5_IO05,SRC_BT_CFG10,,ENET_QOS_TX_EN,,GPIO11_IO05,,,
+GPIO_DISP_B2_05,VIDEO_MUX_LCDIF_DATA13,ENET_TX_CLK,ENET_REF_CLK,ARM_TRACE03,SAI1_RX_BCLK,GPIO5_IO06,SRC_BT_CFG11,,ENET_QOS_TX_CLK,,GPIO11_IO06,,,
+GPIO_DISP_B2_06,VIDEO_MUX_LCDIF_DATA14,ENET_RX_DATA00,LPUART7_TXD,ARM_TRACE_CLK,SAI1_RX_DATA00,GPIO5_IO07,,,ENET_QOS_RX_DATA00,,GPIO11_IO07,,,
+GPIO_DISP_B2_07,VIDEO_MUX_LCDIF_DATA15,ENET_RX_DATA01,LPUART7_RXD,ARM_TRACE_SWO,SAI1_TX_DATA00,GPIO5_IO08,,,ENET_QOS_RX_DATA01,,GPIO11_IO08,,,
+GPIO_DISP_B2_08,VIDEO_MUX_LCDIF_DATA16,ENET_RX_EN,LPUART8_TXD,ARM_CM7_EVENTO,SAI1_TX_BCLK,GPIO5_IO09,,,ENET_QOS_RX_EN,LPUART1_TXD,GPIO11_IO09,,,
+GPIO_DISP_B2_09,VIDEO_MUX_LCDIF_DATA17,ENET_RX_ER,LPUART8_RXD,ARM_CM7_EVENTI,SAI1_TX_SYNC,GPIO5_IO10,,,ENET_QOS_RX_ER,LPUART1_RXD,GPIO11_IO10,,,
+GPIO_DISP_B2_10,VIDEO_MUX_LCDIF_DATA18,EMVSIM2_IO,LPUART2_TXD,WDOG2_RESET_B_DEB,XBAR1_INOUT38,GPIO5_IO11,LPI2C3_SCL,,ENET_QOS_RX_ER,SPDIF_IN,GPIO11_IO11,,,
+GPIO_DISP_B2_11,VIDEO_MUX_LCDIF_DATA19,EMVSIM2_CLK,LPUART2_RXD,WDOG1_RESET_B_DEB,XBAR1_INOUT39,GPIO5_IO12,LPI2C3_SDA,,ENET_QOS_CRS,SPDIF_OUT,GPIO11_IO12,,,
+GPIO_DISP_B2_12,VIDEO_MUX_LCDIF_DATA20,EMVSIM2_RST,FLEXCAN1_TX,LPUART2_CTS_B,XBAR1_INOUT40,GPIO5_IO13,LPI2C4_SCL,,ENET_QOS_COL,LPSPI4_SCK,GPIO11_IO13,,,
+GPIO_DISP_B2_13,VIDEO_MUX_LCDIF_DATA21,EMVSIM2_SVEN,FLEXCAN1_RX,LPUART2_RTS_B,ENET_REF_CLK,GPIO5_IO14,LPI2C4_SDA,,ENET_QOS_1588_EVENT0_OUT,LPSPI4_SIN,GPIO11_IO14,,,
+GPIO_DISP_B2_14,VIDEO_MUX_LCDIF_DATA22,EMVSIM2_PD,WDOG2_B,VIDEO_MUX_EXT_DCIC1,ENET_1G_REF_CLK,GPIO5_IO15,FLEXCAN1_TX,,ENET_QOS_1588_EVENT0_IN,LPSPI4_SOUT,GPIO11_IO15,,,
+GPIO_DISP_B2_15,VIDEO_MUX_LCDIF_DATA23,EMVSIM2_POWER_FAIL,WDOG1_B,VIDEO_MUX_EXT_DCIC2,PIT1_TRIGGER0,GPIO5_IO16,FLEXCAN1_RX,,ENET_QOS_1588_EVENT0_AUX_IN,LPSPI4_PCS0,GPIO11_IO16,,,
+GPIO_AD_00,EMVSIM1_IO,FLEXCAN2_TX,ENET_1G_1588_EVENT1_IN,GPT2_CAPTURE1,FLEXPWM1_PWM0_A,GPIO2_IO31,LPUART7_TXD,,FLEXIO2_D00,FLEXSPI2_B_SS1_B,GPIO8_IO31,,ACMP1_IN1,
+GPIO_AD_01,EMVSIM1_CLK,FLEXCAN2_RX,ENET_1G_1588_EVENT1_OUT,GPT2_CAPTURE2,FLEXPWM1_PWM0_B,GPIO3_IO00,LPUART7_RXD,,FLEXIO2_D01,FLEXSPI2_A_SS1_B,GPIO9_IO00,,ACMP1_IN2,
+GPIO_AD_02,EMVSIM1_RST,LPUART7_CTS_B,ENET_1G_1588_EVENT2_IN,GPT2_COMPARE1,FLEXPWM1_PWM1_A,GPIO3_IO01,LPUART8_TXD,,FLEXIO2_D02,VIDEO_MUX_EXT_DCIC1,GPIO9_IO01,,ACMP1_IN3,
+GPIO_AD_03,EMVSIM1_SVEN,LPUART7_RTS_B,ENET_1G_1588_EVENT2_OUT,GPT2_COMPARE2,FLEXPWM1_PWM1_B,GPIO3_IO02,LPUART8_RXD,,FLEXIO2_D03,VIDEO_MUX_EXT_DCIC2,GPIO9_IO02,,ACMP1_IN4,
+GPIO_AD_04,EMVSIM1_PD,LPUART8_CTS_B,ENET_1G_1588_EVENT3_IN,GPT2_COMPARE3,FLEXPWM1_PWM2_A,GPIO3_IO03,WDOG1_B,,FLEXIO2_D04,TMR4_TIMER0,GPIO9_IO03,,ACMP2_IN1,
+GPIO_AD_05,EMVSIM1_POWER_FAIL,LPUART8_RTS_B,ENET_1G_1588_EVENT3_OUT,GPT2_CLK,FLEXPWM1_PWM2_B,GPIO3_IO04,WDOG2_B,,FLEXIO2_D05,TMR4_TIMER1,GPIO9_IO04,,ACMP2_IN2,
+GPIO_AD_06,USB_OTG2_OC,FLEXCAN1_TX,EMVSIM2_IO,GPT3_CAPTURE1,VIDEO_MUX_CSI_DATA15,GPIO3_IO05,ENET_1588_EVENT1_IN,,FLEXIO2_D06,TMR4_TIMER2,GPIO9_IO05,ADC1_CH0A,,
+GPIO_AD_07,USB_OTG2_PWR,FLEXCAN1_RX,EMVSIM2_CLK,GPT3_CAPTURE2,VIDEO_MUX_CSI_DATA14,GPIO3_IO06,ENET_1588_EVENT1_OUT,,FLEXIO2_D07,TMR4_TIMER3,GPIO9_IO06,ADC1_CH0B,,
+GPIO_AD_08,USBPHY2_OTG_ID,LPI2C1_SCL,EMVSIM2_RST,GPT3_COMPARE1,VIDEO_MUX_CSI_DATA13,GPIO3_IO07,ENET_1588_EVENT2_IN,,FLEXIO2_D08,,GPIO9_IO07,ADC1_CH1A,,
+GPIO_AD_09,USBPHY1_OTG_ID,LPI2C1_SDA,EMVSIM2_SVEN,GPT3_COMPARE2,VIDEO_MUX_CSI_DATA12,GPIO3_IO08,ENET_1588_EVENT2_OUT,,FLEXIO2_D09,,GPIO9_IO08,ADC1_CH1B,,
+GPIO_AD_10,USB_OTG1_PWR,LPI2C1_SCLS,EMVSIM2_PD,GPT3_COMPARE3,VIDEO_MUX_CSI_DATA11,GPIO3_IO09,ENET_1588_EVENT3_IN,,FLEXIO2_D10,,GPIO9_IO09,ADC1_CH2A,,
+GPIO_AD_11,USB_OTG1_OC,LPI2C1_SDAS,EMVSIM2_POWER_FAIL,GPT3_CLK,VIDEO_MUX_CSI_DATA10,GPIO3_IO10,ENET_1588_EVENT3_OUT,,FLEXIO2_D11,,GPIO9_IO10,ADC1_CH2B,,
+GPIO_AD_12,SPDIF_LOCK,LPI2C1_HREQ,GPT1_CAPTURE1,FLEXSPI1_B_DATA03,VIDEO_MUX_CSI_PIXCLK,GPIO3_IO11,ENET_TX_DATA03,,FLEXIO2_D12,EWM_OUT_B,GPIO9_IO11,"ADC1_CH3A,ADC2_CH3A",,
+GPIO_AD_13,SPDIF_SR_CLK,PIT1_TRIGGER0,GPT1_CAPTURE2,FLEXSPI1_B_DATA02,VIDEO_MUX_CSI_MCLK,GPIO3_IO12,ENET_TX_DATA02,,FLEXIO2_D13,REF_CLK_32K,GPIO9_IO12,"ADC1_CH3B,ADC2_CH3B",,
+GPIO_AD_14,SPDIF_EXT_CLK,REF_CLK_24M,GPT1_COMPARE1,FLEXSPI1_B_DATA01,VIDEO_MUX_CSI_VSYNC,GPIO3_IO13,ENET_RX_CLK,,FLEXIO2_D14,CCM_ENET_REF_CLK_25M,GPIO9_IO13,"ADC1_CH4A,ADC2_CH4A",,
+GPIO_AD_15,SPDIF_IN,LPUART10_TXD,GPT1_COMPARE2,FLEXSPI1_B_DATA00,VIDEO_MUX_CSI_HSYNC,GPIO3_IO14,ENET_TX_ER,,FLEXIO2_D15,,GPIO9_IO14,"ADC1_CH4B,ADC2_CH4B",,
+GPIO_AD_16,SPDIF_OUT,LPUART10_RXD,GPT1_COMPARE3,FLEXSPI1_B_SCLK,VIDEO_MUX_CSI_DATA09,GPIO3_IO15,ENET_RX_DATA03,,FLEXIO2_D16,ENET_1G_MDC,GPIO9_IO15,"ADC1_CH5A,ADC2_CH5A",,
+GPIO_AD_17,SAI1_MCLK,ACMP1_OUT,GPT1_CLK,FLEXSPI1_A_DQS,VIDEO_MUX_CSI_DATA08,GPIO3_IO16,ENET_RX_DATA02,,FLEXIO2_D17,ENET_1G_MDIO,GPIO9_IO16,"ADC1_CH5B,ADC2_CH5B",ACMP1_OUT,
+GPIO_AD_18,SAI1_RX_SYNC,ACMP2_OUT,LPSPI1_PCS1,FLEXSPI1_A_SS0_B,VIDEO_MUX_CSI_DATA07,GPIO3_IO17,ENET_CRS,,FLEXIO2_D18,LPI2C2_SCL,GPIO9_IO17,ADC2_CH0A,ACMP2_OUT,
+GPIO_AD_19,SAI1_RX_BCLK,ACMP3_OUT,LPSPI1_PCS2,FLEXSPI1_A_SCLK,VIDEO_MUX_CSI_DATA06,GPIO3_IO18,ENET_COL,,FLEXIO2_D19,LPI2C2_SDA,GPIO9_IO18,ADC2_CH0B,ACMP3_OUT,
+GPIO_AD_20,SAI1_RX_DATA00,ACMP4_OUT,LPSPI1_PCS3,FLEXSPI1_A_DATA00,VIDEO_MUX_CSI_DATA05,GPIO3_IO19,KPP_ROW07,,FLEXIO2_D20,ENET_QOS_1588_EVENT2_OUT,GPIO9_IO19,ADC2_CH1A,ACMP4_OUT,
+GPIO_AD_21,SAI1_TX_DATA00,,LPSPI2_PCS1,FLEXSPI1_A_DATA01,VIDEO_MUX_CSI_DATA04,GPIO3_IO20,KPP_COL07,,FLEXIO2_D21,ENET_QOS_1588_EVENT2_IN,GPIO9_IO20,ADC2_CH1B,,
+GPIO_AD_22,SAI1_TX_BCLK,,LPSPI2_PCS2,FLEXSPI1_A_DATA02,VIDEO_MUX_CSI_DATA03,GPIO3_IO21,KPP_ROW06,,FLEXIO2_D22,ENET_QOS_1588_EVENT3_OUT,GPIO9_IO21,ADC2_CH2A,,
+GPIO_AD_23,SAI1_TX_SYNC,,LPSPI2_PCS3,FLEXSPI1_A_DATA03,VIDEO_MUX_CSI_DATA02,GPIO3_IO22,KPP_COL06,,FLEXIO2_D23,ENET_QOS_1588_EVENT3_IN,GPIO9_IO22,ADC2_CH2B,,
+GPIO_AD_24,LPUART1_TXD,LPSPI2_SCK,VIDEO_MUX_CSI_DATA00,ENET_RX_EN,FLEXPWM2_PWM0_A,GPIO3_IO23,KPP_ROW05,,FLEXIO2_D24,LPI2C4_SCL,GPIO9_IO23,ADC2_CH6A,,
+GPIO_AD_25,LPUART1_RXD,LPSPI2_PCS0,VIDEO_MUX_CSI_DATA01,ENET_RX_ER,FLEXPWM2_PWM0_B,GPIO3_IO24,KPP_COL05,,FLEXIO2_D25,LPI2C4_SDA,GPIO9_IO24,ADC2_CH6B,,
+GPIO_AD_26,LPUART1_CTS_B,LPSPI2_SOUT,SEMC_CSX01,ENET_RX_DATA00,FLEXPWM2_PWM1_A,GPIO3_IO25,KPP_ROW04,,FLEXIO2_D26,ENET_QOS_MDC,GPIO9_IO25,,ACMP2_IN3,
+GPIO_AD_27,LPUART1_RTS_B,LPSPI2_SIN,SEMC_CSX02,ENET_RX_DATA01,FLEXPWM2_PWM1_B,GPIO3_IO26,KPP_COL04,,FLEXIO2_D27,ENET_QOS_MDIO,GPIO9_IO26,,ACMP2_IN4,
+GPIO_AD_28,LPSPI1_SCK,LPUART5_TXD,SEMC_CSX03,ENET_TX_EN,FLEXPWM2_PWM2_A,GPIO3_IO27,KPP_ROW03,,FLEXIO2_D28,VIDEO_MUX_EXT_DCIC1,GPIO9_IO27,,ACMP3_IN1,
+GPIO_AD_29,LPSPI1_PCS0,LPUART5_RXD,ENET_REF_CLK,ENET_TX_CLK,FLEXPWM2_PWM2_B,GPIO3_IO28,KPP_COL03,,FLEXIO2_D29,VIDEO_MUX_EXT_DCIC2,GPIO9_IO28,,ACMP3_IN2,
+GPIO_AD_30,LPSPI1_SOUT,USB_OTG2_OC,FLEXCAN2_TX,ENET_TX_DATA00,LPUART3_TXD,GPIO3_IO29,KPP_ROW02,,FLEXIO2_D30,WDOG2_RESET_B_DEB,GPIO9_IO29,,ACMP3_IN3,
+GPIO_AD_31,LPSPI1_SIN,USB_OTG2_PWR,FLEXCAN2_RX,ENET_TX_DATA01,LPUART3_RXD,GPIO3_IO30,KPP_COL02,,FLEXIO2_D31,WDOG1_RESET_B_DEB,GPIO9_IO30,,ACMP3_IN4,
+GPIO_AD_32,LPI2C1_SCL,USBPHY2_OTG_ID,PGMC_PMIC_RDY,ENET_MDC,USDHC1_CD_B,GPIO3_IO31,KPP_ROW01,,LPUART10_TXD,ENET_1G_MDC,GPIO9_IO31,,ACMP4_IN1,
+GPIO_AD_33,LPI2C1_SDA,USBPHY1_OTG_ID,XBAR1_INOUT17,ENET_MDIO,USDHC1_WP,GPIO4_IO00,KPP_COL01,,LPUART10_RXD,ENET_1G_MDIO,GPIO10_IO00,,ACMP4_IN2,
+GPIO_AD_34,ENET_1G_1588_EVENT0_IN,USB_OTG1_PWR,XBAR1_INOUT18,ENET_1588_EVENT0_IN,USDHC1_VSELECT,GPIO4_IO01,KPP_ROW00,,LPUART10_CTS_B,WDOG1_ANY,GPIO10_IO01,,ACMP4_IN3,
+GPIO_AD_35,ENET_1G_1588_EVENT0_OUT,USB_OTG1_OC,XBAR1_INOUT19,ENET_1588_EVENT0_OUT,USDHC1_RESET_B,GPIO4_IO02,KPP_COL00,,LPUART10_RTS_B,FLEXSPI1_B_SS1_B,GPIO10_IO02,,ACMP4_IN4,
diff --git a/ports/mimxrt/boards/MIMXRT1176_clock_config.c b/ports/mimxrt/boards/MIMXRT1176_clock_config.c
new file mode 100644
index 000000000000..4e01448ba3bd
--- /dev/null
+++ b/ports/mimxrt/boards/MIMXRT1176_clock_config.c
@@ -0,0 +1,693 @@
+/*
+ * Copyright 2020 NXP
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*
+ * How to setup clock using clock driver functions:
+ *
+ * 1. Call CLOCK_InitXXXPLL() to configure corresponding PLL clock.
+ *
+ * 2. Call CLOCK_InitXXXpfd() to configure corresponding PLL pfd clock.
+ *
+ * 3. Call CLOCK_SetRootClock() to configure corresponding module clock source and divider.
+ *
+ */
+
+#include CLOCK_CONFIG_H
+#include "fsl_iomuxc.h"
+#include "fsl_dcdc.h"
+#include "fsl_pmu.h"
+#include "fsl_clock.h"
+
+/*******************************************************************************
+ * Definitions
+ ******************************************************************************/
+
+/*******************************************************************************
+ * Variables
+ ******************************************************************************/
+/* System clock frequency. */
+extern uint32_t SystemCoreClock;
+
+/*******************************************************************************
+ ************************ BOARD_InitBootClocks function ************************
+ ******************************************************************************/
+void BOARD_InitBootClocks(void) {
+ BOARD_BootClockRUN();
+}
+
+#if defined(XIP_BOOT_HEADER_ENABLE) && (XIP_BOOT_HEADER_ENABLE == 1)
+#if defined(XIP_BOOT_HEADER_DCD_ENABLE) && (XIP_BOOT_HEADER_DCD_ENABLE == 1)
+/* This function should not run from SDRAM since it will change SEMC configuration. */
+AT_QUICKACCESS_SECTION_CODE(void UpdateSemcClock(void));
+void UpdateSemcClock(void) {
+ /* Enable self-refresh mode and update semc clock root to 200MHz. */
+ SEMC->IPCMD = 0xA55A000D;
+ while ((SEMC->INTR & 0x3) == 0) {
+ ;
+ }
+ SEMC->INTR = 0x3;
+ SEMC->DCCR = 0x0B;
+ /*
+ * Currently we are using SEMC parameter which fit both 166MHz and 200MHz, only
+ * need to change the SEMC clock root here. If customer is using their own DCD and
+ * want to switch from 166MHz to 200MHz, extra SEMC configuration might need to be
+ * adjusted here to fine tune the SDRAM performance
+ */
+ CCM->CLOCK_ROOT[kCLOCK_Root_Semc].CONTROL = 0x602;
+}
+#endif
+#endif
+
+/*******************************************************************************
+ ********************** Configuration BOARD_BootClockRUN ***********************
+ ******************************************************************************/
+
+/*******************************************************************************
+ * Variables for BOARD_BootClockRUN configuration
+ ******************************************************************************/
+
+#ifndef SKIP_POWER_ADJUSTMENT
+#if __CORTEX_M == 7
+#define BYPASS_LDO_LPSR 1
+#define SKIP_LDO_ADJUSTMENT 1
+#elif __CORTEX_M == 4
+#define SKIP_DCDC_ADJUSTMENT 1
+#define SKIP_FBB_ENABLE 1
+#endif
+#endif
+
+const clock_arm_pll_config_t armPllConfig_BOARD_BootClockRUN = {
+ .postDivider = kCLOCK_PllPostDiv2, /* Post divider, 0 - DIV by 2, 1 - DIV by 4, 2 - DIV by 8, 3 - DIV by 1 */
+ .loopDivider = 166, /* PLL Loop divider, Fout = Fin * ( loopDivider / ( 2 * postDivider ) ) */
+};
+
+const clock_sys_pll1_config_t sysPll1Config_BOARD_BootClockRUN = {
+ .pllDiv2En = true,
+};
+
+const clock_sys_pll2_config_t sysPll2Config_BOARD_BootClockRUN = {
+ .mfd = 268435455, /* Denominator of spread spectrum */
+ .ss = NULL, /* Spread spectrum parameter */
+ .ssEnable = false, /* Enable spread spectrum or not */
+};
+
+const clock_video_pll_config_t videoPllConfig_BOARD_BootClockRUN = {
+ .loopDivider = 41, /* PLL Loop divider, valid range for DIV_SELECT divider value: 27 ~ 54. */
+ .postDivider = 0, /* Divider after PLL, should only be 1, 2, 4, 8, 16, 32 */
+ .numerator = 1, /* 30 bit numerator of fractional loop divider, Fout = Fin * ( loopDivider + numerator / denominator ) */
+ .denominator = 960000, /* 30 bit denominator of fractional loop divider, Fout = Fin * ( loopDivider + numerator / denominator ) */
+ .ss = NULL, /* Spread spectrum parameter */
+ .ssEnable = false, /* Enable spread spectrum or not */
+};
+
+/*******************************************************************************
+ * Code for BOARD_BootClockRUN configuration
+ ******************************************************************************/
+void BOARD_BootClockRUN(void) {
+ clock_root_config_t rootCfg = {0};
+
+ #if !defined(SKIP_DCDC_ADJUSTMENT) || (!SKIP_DCDC_ADJUSTMENT)
+ if ((OCOTP->FUSEN[16].FUSE == 0x57AC5969U) && ((OCOTP->FUSEN[17].FUSE & 0xFFU) == 0x0BU)) {
+ DCDC_SetVDD1P0BuckModeTargetVoltage(DCDC, kDCDC_1P0BuckTarget1P15V);
+ } else {
+ /* Set 1.125V for production samples to align with data sheet requirement */
+ DCDC_SetVDD1P0BuckModeTargetVoltage(DCDC, kDCDC_1P0BuckTarget1P125V);
+ }
+ #endif
+
+ #if !defined(SKIP_FBB_ENABLE) || (!SKIP_FBB_ENABLE)
+ /* Check if FBB need to be enabled in OverDrive(OD) mode */
+ if (((OCOTP->FUSEN[7].FUSE & 0x10U) >> 4U) != 1) {
+ PMU_EnableBodyBias(ANADIG_PMU, kPMU_FBB_CM7, true);
+ } else {
+ PMU_EnableBodyBias(ANADIG_PMU, kPMU_FBB_CM7, false);
+ }
+ #endif
+
+ #if defined(BYPASS_LDO_LPSR) && BYPASS_LDO_LPSR
+ PMU_StaticEnableLpsrAnaLdoBypassMode(ANADIG_LDO_SNVS, true);
+ PMU_StaticEnableLpsrDigLdoBypassMode(ANADIG_LDO_SNVS, true);
+ #endif
+
+ #if !defined(SKIP_LDO_ADJUSTMENT) || (!SKIP_LDO_ADJUSTMENT)
+ pmu_static_lpsr_ana_ldo_config_t lpsrAnaConfig;
+ pmu_static_lpsr_dig_config_t lpsrDigConfig;
+
+ if ((ANADIG_LDO_SNVS->PMU_LDO_LPSR_ANA & ANADIG_LDO_SNVS_PMU_LDO_LPSR_ANA_BYPASS_MODE_EN_MASK) == 0UL) {
+ PMU_StaticGetLpsrAnaLdoDefaultConfig(&lpsrAnaConfig);
+ PMU_StaticLpsrAnaLdoInit(ANADIG_LDO_SNVS, &lpsrAnaConfig);
+ }
+
+ if ((ANADIG_LDO_SNVS->PMU_LDO_LPSR_DIG & ANADIG_LDO_SNVS_PMU_LDO_LPSR_DIG_BYPASS_MODE_MASK) == 0UL) {
+ PMU_StaticGetLpsrDigLdoDefaultConfig(&lpsrDigConfig);
+ lpsrDigConfig.targetVoltage = kPMU_LpsrDigTargetStableVoltage1P117V;
+ PMU_StaticLpsrDigLdoInit(ANADIG_LDO_SNVS, &lpsrDigConfig);
+ }
+ #endif
+
+ /* PLL LDO shall be enabled first before enable PLLs */
+
+ /* Config CLK_1M */
+ CLOCK_OSC_Set1MHzOutputBehavior(kCLOCK_1MHzOutEnableFreeRunning1Mhz);
+
+ /* Init OSC RC 16M */
+ ANADIG_OSC->OSC_16M_CTRL |= ANADIG_OSC_OSC_16M_CTRL_EN_IRC4M16M_MASK;
+
+ /* Init OSC RC 400M */
+ CLOCK_OSC_EnableOscRc400M();
+ CLOCK_OSC_GateOscRc400M(true);
+
+ /* Init OSC RC 48M */
+ CLOCK_OSC_EnableOsc48M(true);
+ CLOCK_OSC_EnableOsc48MDiv2(true);
+
+ /* Config OSC 24M */
+ ANADIG_OSC->OSC_24M_CTRL |= ANADIG_OSC_OSC_24M_CTRL_OSC_EN(1) | ANADIG_OSC_OSC_24M_CTRL_BYPASS_EN(0) | ANADIG_OSC_OSC_24M_CTRL_BYPASS_CLK(0) | ANADIG_OSC_OSC_24M_CTRL_LP_EN(1) | ANADIG_OSC_OSC_24M_CTRL_OSC_24M_GATE(0);
+ /* Wait for 24M OSC to be stable. */
+ while (ANADIG_OSC_OSC_24M_CTRL_OSC_24M_STABLE_MASK !=
+ (ANADIG_OSC->OSC_24M_CTRL & ANADIG_OSC_OSC_24M_CTRL_OSC_24M_STABLE_MASK)) {
+ }
+
+ /* Swicth both core, M7 Systick and Bus_Lpsr to OscRC48MDiv2 first */
+ rootCfg.mux = kCLOCK_M7_ClockRoot_MuxOscRc48MDiv2;
+ rootCfg.div = 1;
+ #if __CORTEX_M == 7
+ CLOCK_SetRootClock(kCLOCK_Root_M7, &rootCfg);
+ CLOCK_SetRootClock(kCLOCK_Root_M7_Systick, &rootCfg);
+ #endif
+ #if __CORTEX_M == 4
+ CLOCK_SetRootClock(kCLOCK_Root_M4, &rootCfg);
+ CLOCK_SetRootClock(kCLOCK_Root_Bus_Lpsr, &rootCfg);
+ #endif
+
+ /*
+ * if DCD is used, please make sure the clock source of SEMC is not changed in the following PLL/PFD configuration code.
+ */
+ /* Init Arm Pll. */
+ CLOCK_InitArmPll(&armPllConfig_BOARD_BootClockRUN);
+
+ /* Bypass Sys Pll1. */
+ // CLOCK_SetPllBypass(kCLOCK_PllSys1, true);
+
+ /* Init Sys Pll1 and enable PllSys1_Div2 output */
+ CLOCK_InitSysPll1(&sysPll1Config_BOARD_BootClockRUN);
+
+
+ /* Init Sys Pll2. */
+ CLOCK_InitSysPll2(&sysPll2Config_BOARD_BootClockRUN);
+
+ /* Init System Pll2 pfd0. */
+ CLOCK_InitPfd(kCLOCK_PllSys2, kCLOCK_Pfd0, 27);
+
+ /* Init System Pll2 pfd1. */
+ CLOCK_InitPfd(kCLOCK_PllSys2, kCLOCK_Pfd1, 16);
+
+ /* Init System Pll2 pfd2. */
+ CLOCK_InitPfd(kCLOCK_PllSys2, kCLOCK_Pfd2, 24);
+
+ /* Init System Pll2 pfd3. */
+ CLOCK_InitPfd(kCLOCK_PllSys2, kCLOCK_Pfd3, 32);
+
+ /* Init Sys Pll3. */
+ CLOCK_InitSysPll3();
+
+ /* Init System Pll3 pfd0. */
+ CLOCK_InitPfd(kCLOCK_PllSys3, kCLOCK_Pfd0, 13);
+
+ /* Init System Pll3 pfd1. */
+ CLOCK_InitPfd(kCLOCK_PllSys3, kCLOCK_Pfd1, 17);
+
+ /* Init System Pll3 pfd2. */
+ CLOCK_InitPfd(kCLOCK_PllSys3, kCLOCK_Pfd2, 32);
+
+ /* Init System Pll3 pfd3. */
+ CLOCK_InitPfd(kCLOCK_PllSys3, kCLOCK_Pfd3, 22);
+
+ /* Bypass Audio Pll. */
+ CLOCK_SetPllBypass(kCLOCK_PllAudio, true);
+
+ /* DeInit Audio Pll. */
+ CLOCK_DeinitAudioPll();
+
+ /* Init Video Pll. */
+ CLOCK_InitVideoPll(&videoPllConfig_BOARD_BootClockRUN);
+
+ /* Module clock root configurations. */
+ /* Configure M7 using ARM_PLL_CLK */
+ #if __CORTEX_M == 7
+ rootCfg.mux = kCLOCK_M7_ClockRoot_MuxArmPllOut;
+ rootCfg.div = 1;
+ CLOCK_SetRootClock(kCLOCK_Root_M7, &rootCfg);
+ #endif
+
+ /* Configure M4 using SYS_PLL3_PFD3_CLK */
+ #if __CORTEX_M == 4
+ rootCfg.mux = kCLOCK_M4_ClockRoot_MuxSysPll3Pfd3;
+ rootCfg.div = 1;
+ CLOCK_SetRootClock(kCLOCK_Root_M4, &rootCfg);
+ #endif
+
+ /* Configure BUS using SYS_PLL3_CLK */
+ rootCfg.mux = kCLOCK_BUS_ClockRoot_MuxSysPll3Out;
+ rootCfg.div = 3;
+ CLOCK_SetRootClock(kCLOCK_Root_Bus, &rootCfg);
+
+ /* Configure BUS_LPSR using SYS_PLL3_CLK */
+ /* BUS_LPSR must not be more than 120MHz */
+ rootCfg.mux = kCLOCK_BUS_LPSR_ClockRoot_MuxSysPll3Out;
+ rootCfg.div = 4;
+ CLOCK_SetRootClock(kCLOCK_Root_Bus_Lpsr, &rootCfg);
+
+ /* Configure SEMC using SYS_PLL2_PFD1_CLK */
+ #ifndef SKIP_SEMC_INIT
+ rootCfg.mux = kCLOCK_SEMC_ClockRoot_MuxSysPll2Pfd1;
+ rootCfg.div = 3;
+ CLOCK_SetRootClock(kCLOCK_Root_Semc, &rootCfg);
+ #endif
+
+ #if defined(XIP_BOOT_HEADER_ENABLE) && (XIP_BOOT_HEADER_ENABLE == 1)
+ #if defined(XIP_BOOT_HEADER_DCD_ENABLE) && (XIP_BOOT_HEADER_DCD_ENABLE == 1)
+ UpdateSemcClock();
+ #endif
+ #endif
+
+ /* Configure CSSYS using OSC_RC_48M_DIV2 */
+ rootCfg.mux = kCLOCK_CSSYS_ClockRoot_MuxOscRc48MDiv2;
+ rootCfg.div = 1;
+ CLOCK_SetRootClock(kCLOCK_Root_Cssys, &rootCfg);
+
+ /* Configure CSTRACE using SYS_PLL2_CLK */
+ rootCfg.mux = kCLOCK_CSTRACE_ClockRoot_MuxSysPll2Out;
+ rootCfg.div = 4;
+ CLOCK_SetRootClock(kCLOCK_Root_Cstrace, &rootCfg);
+
+ // Strange settings for SYSTICK: 24MHz for M4, 100kHz for M7 ?
+ /* Configure M4_SYSTICK using OSC_RC_48M_DIV2 */
+ #if __CORTEX_M == 4
+ rootCfg.mux = kCLOCK_M4_SYSTICK_ClockRoot_MuxOscRc48MDiv2;
+ rootCfg.div = 1;
+ CLOCK_SetRootClock(kCLOCK_Root_M4_Systick, &rootCfg);
+ #endif
+
+ /* Configure M7_SYSTICK using OSC_RC_48M_DIV2 */
+ #if __CORTEX_M == 7
+ rootCfg.mux = kCLOCK_M7_SYSTICK_ClockRoot_MuxOscRc48MDiv2;
+ rootCfg.div = 240;
+ CLOCK_SetRootClock(kCLOCK_Root_M7_Systick, &rootCfg);
+ #endif
+
+ /* Configure ADC1 using OSC_RC_48M_DIV2 */
+ rootCfg.mux = kCLOCK_ADC1_ClockRoot_MuxOscRc48MDiv2;
+ rootCfg.div = 1;
+ CLOCK_SetRootClock(kCLOCK_Root_Adc1, &rootCfg);
+
+ /* Configure ADC2 using OSC_RC_48M_DIV2 */
+ rootCfg.mux = kCLOCK_ADC2_ClockRoot_MuxOscRc48MDiv2;
+ rootCfg.div = 1;
+ CLOCK_SetRootClock(kCLOCK_Root_Adc2, &rootCfg);
+
+ /* Configure ACMP using OSC_RC_48M_DIV2 */
+ rootCfg.mux = kCLOCK_ACMP_ClockRoot_MuxOscRc48MDiv2;
+ rootCfg.div = 1;
+ CLOCK_SetRootClock(kCLOCK_Root_Acmp, &rootCfg);
+
+ /* Configure FLEXIO1 using OSC_RC_48M_DIV2 */
+ rootCfg.mux = kCLOCK_FLEXIO1_ClockRoot_MuxOscRc48MDiv2;
+ rootCfg.div = 1;
+ CLOCK_SetRootClock(kCLOCK_Root_Flexio1, &rootCfg);
+
+ /* Configure FLEXIO2 using OSC_RC_48M_DIV2 */
+ rootCfg.mux = kCLOCK_FLEXIO2_ClockRoot_MuxOscRc48MDiv2;
+ rootCfg.div = 1;
+ CLOCK_SetRootClock(kCLOCK_Root_Flexio2, &rootCfg);
+
+ /* Configure GPT1 using OSC_24M*/
+ rootCfg.mux = kCLOCK_GPT1_ClockRoot_MuxOsc24MOut;
+ rootCfg.div = 1;
+ CLOCK_SetRootClock(kCLOCK_Root_Gpt1, &rootCfg);
+
+ /* Configure GPT2 using OSC_24M */
+ rootCfg.mux = kCLOCK_GPT2_ClockRoot_MuxOsc24MOut;
+ rootCfg.div = 1;
+ CLOCK_SetRootClock(kCLOCK_Root_Gpt2, &rootCfg);
+
+ /* Configure GPT3 using OSC_24M */
+ rootCfg.mux = kCLOCK_GPT3_ClockRoot_MuxOsc24MOut;
+ rootCfg.div = 1;
+ CLOCK_SetRootClock(kCLOCK_Root_Gpt3, &rootCfg);
+
+ /* Configure GPT4 using OSC_24M */
+ rootCfg.mux = kCLOCK_GPT4_ClockRoot_MuxOsc24MOut;
+ rootCfg.div = 1;
+ CLOCK_SetRootClock(kCLOCK_Root_Gpt4, &rootCfg);
+
+ /* Configure GPT5 using OSC_24M */
+ rootCfg.mux = kCLOCK_GPT5_ClockRoot_MuxOsc24MOut;
+ rootCfg.div = 1;
+ CLOCK_SetRootClock(kCLOCK_Root_Gpt5, &rootCfg);
+
+ /* Configure GPT6 using OSC_24M */
+ rootCfg.mux = kCLOCK_GPT6_ClockRoot_MuxOsc24MOut;
+ rootCfg.div = 1;
+ CLOCK_SetRootClock(kCLOCK_Root_Gpt6, &rootCfg);
+
+ /* Configure FLEXSPI1 using OSC_RC_48M_DIV2 */
+ #if !(defined(XIP_EXTERNAL_FLASH) && (XIP_EXTERNAL_FLASH == 1))
+ rootCfg.mux = kCLOCK_FLEXSPI1_ClockRoot_MuxOscRc48MDiv2;
+ rootCfg.div = 1;
+ CLOCK_SetRootClock(kCLOCK_Root_Flexspi1, &rootCfg);
+ #endif
+
+ /* Configure FLEXSPI2 using OSC_RC_48M_DIV2 */
+ rootCfg.mux = kCLOCK_FLEXSPI2_ClockRoot_MuxOscRc48MDiv2;
+ rootCfg.div = 1;
+ CLOCK_SetRootClock(kCLOCK_Root_Flexspi2, &rootCfg);
+
+ /* Configure CAN1 using OSC_RC_48M_DIV2 */
+ rootCfg.mux = kCLOCK_CAN1_ClockRoot_MuxOscRc48MDiv2;
+ rootCfg.div = 1;
+ CLOCK_SetRootClock(kCLOCK_Root_Can1, &rootCfg);
+
+ /* Configure CAN2 using OSC_RC_48M_DIV2 */
+ rootCfg.mux = kCLOCK_CAN2_ClockRoot_MuxOscRc48MDiv2;
+ rootCfg.div = 1;
+ CLOCK_SetRootClock(kCLOCK_Root_Can2, &rootCfg);
+
+ /* Configure CAN3 using OSC_RC_48M_DIV2 */
+ rootCfg.mux = kCLOCK_CAN3_ClockRoot_MuxOscRc48MDiv2;
+ rootCfg.div = 1;
+ CLOCK_SetRootClock(kCLOCK_Root_Can3, &rootCfg);
+
+ /* Configure LPUART1 using SYS_PLL3_PFD3_CLK */
+ rootCfg.mux = kCLOCK_LPUART1_ClockRoot_MuxSysPll2Pfd3;
+ rootCfg.div = 4;
+ CLOCK_SetRootClock(kCLOCK_Root_Lpuart1, &rootCfg);
+
+ /* Configure LPUART2 using SYS_PLL3_PFD3_CLK */
+ rootCfg.mux = kCLOCK_LPUART2_ClockRoot_MuxSysPll2Pfd3;
+ rootCfg.div = 4;
+ CLOCK_SetRootClock(kCLOCK_Root_Lpuart2, &rootCfg);
+
+ /* Configure LPUART3 using SYS_PLL3_PFD3_CLK */
+ rootCfg.mux = kCLOCK_LPUART3_ClockRoot_MuxSysPll2Pfd3;
+ rootCfg.div = 4;
+ CLOCK_SetRootClock(kCLOCK_Root_Lpuart3, &rootCfg);
+
+ /* Configure LPUART4 using SYS_PLL3_PFD3_CLK */
+ rootCfg.mux = kCLOCK_LPUART4_ClockRoot_MuxSysPll2Pfd3;
+ rootCfg.div = 4;
+ CLOCK_SetRootClock(kCLOCK_Root_Lpuart4, &rootCfg);
+
+ /* Configure LPUART5 using SYS_PLL3_PFD3_CLK */
+ rootCfg.mux = kCLOCK_LPUART5_ClockRoot_MuxSysPll2Pfd3;
+ rootCfg.div = 4;
+ CLOCK_SetRootClock(kCLOCK_Root_Lpuart5, &rootCfg);
+
+ /* Configure LPUART6 using SYS_PLL3_PFD3_CLK */
+ rootCfg.mux = kCLOCK_LPUART6_ClockRoot_MuxSysPll2Pfd3;
+ rootCfg.div = 4;
+ CLOCK_SetRootClock(kCLOCK_Root_Lpuart6, &rootCfg);
+
+ /* Configure LPUART7 using SYS_PLL3_PFD3_CLK */
+ rootCfg.mux = kCLOCK_LPUART7_ClockRoot_MuxSysPll2Pfd3;
+ rootCfg.div = 4;
+ CLOCK_SetRootClock(kCLOCK_Root_Lpuart7, &rootCfg);
+
+ /* Configure LPUART8 using SYS_PLL3_PFD3_CLK */
+ rootCfg.mux = kCLOCK_LPUART8_ClockRoot_MuxSysPll2Pfd3;
+ rootCfg.div = 4;
+ CLOCK_SetRootClock(kCLOCK_Root_Lpuart8, &rootCfg);
+
+ /* Configure LPUART9 using SYS_PLL3_PFD3_CLK */
+ rootCfg.mux = kCLOCK_LPUART9_ClockRoot_MuxSysPll2Pfd3;
+ rootCfg.div = 4;
+ CLOCK_SetRootClock(kCLOCK_Root_Lpuart9, &rootCfg);
+
+ /* Configure LPUART10 using SYS_PLL3_PFD3_CLK */
+ rootCfg.mux = kCLOCK_LPUART10_ClockRoot_MuxSysPll2Pfd3;
+ rootCfg.div = 4;
+ CLOCK_SetRootClock(kCLOCK_Root_Lpuart10, &rootCfg);
+
+ /* Configure LPUART11 using SYS_PLL3_PFD3_CLK */
+ rootCfg.mux = kCLOCK_LPUART11_ClockRoot_MuxSysPll2Pfd3;
+ rootCfg.div = 4;
+ CLOCK_SetRootClock(kCLOCK_Root_Lpuart11, &rootCfg);
+
+ /* Configure LPUART12 using SYS_PLL3_PFD3_CLK */
+ rootCfg.mux = kCLOCK_LPUART12_ClockRoot_MuxSysPll2Pfd3;
+ rootCfg.div = 4;
+ CLOCK_SetRootClock(kCLOCK_Root_Lpuart12, &rootCfg);
+
+
+ /* Configure LPI2C1 using SYS_PLL3_DIV2 (240MHz) */
+ rootCfg.mux = kCLOCK_LPI2C1_ClockRoot_MuxSysPll3Div2;
+ rootCfg.div = 4;
+ CLOCK_SetRootClock(kCLOCK_Root_Lpi2c1, &rootCfg);
+
+ /* Configure LPI2C2 using SYS_PLL3_DIV2 (240MHz) */
+ rootCfg.mux = kCLOCK_LPI2C2_ClockRoot_MuxSysPll3Div2;
+ rootCfg.div = 4;
+ CLOCK_SetRootClock(kCLOCK_Root_Lpi2c2, &rootCfg);
+
+ /* Configure LPI2C3 using SYS_PLL3_DIV2 (240MHz) */
+ rootCfg.mux = kCLOCK_LPI2C3_ClockRoot_MuxSysPll3Div2;
+ rootCfg.div = 4;
+ CLOCK_SetRootClock(kCLOCK_Root_Lpi2c3, &rootCfg);
+
+ /* Configure LPI2C4 using SYS_PLL3_DIV2 (240MHz) */
+ rootCfg.mux = kCLOCK_LPI2C4_ClockRoot_MuxSysPll3Div2;
+ rootCfg.div = 4;
+ CLOCK_SetRootClock(kCLOCK_Root_Lpi2c4, &rootCfg);
+
+ /* Configure LPI2C5 using SYS_PLL3_OUT (480MHz) */
+ rootCfg.mux = kCLOCK_LPI2C5_ClockRoot_MuxSysPll3Out;
+ rootCfg.div = 8;
+ CLOCK_SetRootClock(kCLOCK_Root_Lpi2c5, &rootCfg);
+
+ /* Configure LPI2C6 using SYS_PLL3_OUT (480MHz) */
+ rootCfg.mux = kCLOCK_LPI2C6_ClockRoot_MuxSysPll3Out;
+ rootCfg.div = 8;
+ CLOCK_SetRootClock(kCLOCK_Root_Lpi2c6, &rootCfg);
+
+
+ /* Configure LPSPI1 using SYS_PLL_3_PDF2 (270MHz) */
+ rootCfg.mux = kCLOCK_LPSPI1_ClockRoot_MuxSysPll3Pfd2;
+ rootCfg.div = 2;
+ CLOCK_SetRootClock(kCLOCK_Root_Lpspi1, &rootCfg);
+
+ /* Configure LPSPI2 using SYS_PLL_3_PDF2 (270MHz) */
+ rootCfg.mux = kCLOCK_LPSPI2_ClockRoot_MuxSysPll3Pfd2;
+ rootCfg.div = 2;
+ CLOCK_SetRootClock(kCLOCK_Root_Lpspi2, &rootCfg);
+
+ /* Configure LPSPI3 using SYS_PLL_3_PDF2 (270MHz) */
+ rootCfg.mux = kCLOCK_LPSPI3_ClockRoot_MuxSysPll3Pfd2;
+ rootCfg.div = 2;
+ CLOCK_SetRootClock(kCLOCK_Root_Lpspi3, &rootCfg);
+
+ /* Configure LPSPI4 using SYS_PLL_3_PDF2 (270MHz) */
+ rootCfg.mux = kCLOCK_LPSPI4_ClockRoot_MuxSysPll3Pfd2;
+ rootCfg.div = 2;
+ CLOCK_SetRootClock(kCLOCK_Root_Lpspi4, &rootCfg);
+
+ /* Configure LPSPI5 using SYS_PLL_3_PDF2 (270MHz) */
+ rootCfg.mux = kCLOCK_LPSPI5_ClockRoot_MuxSysPll3Pfd2;
+ rootCfg.div = 2;
+ CLOCK_SetRootClock(kCLOCK_Root_Lpspi5, &rootCfg);
+
+ /* Configure LPSPI6 using SYS_PLL_3_PDF2 (270MHz) */
+ rootCfg.mux = kCLOCK_LPSPI6_ClockRoot_MuxSysPll3Pfd2;
+ rootCfg.div = 2;
+ CLOCK_SetRootClock(kCLOCK_Root_Lpspi6, &rootCfg);
+
+
+ /* Configure EMV1 using OSC_RC_48M_DIV2 */
+ rootCfg.mux = kCLOCK_EMV1_ClockRoot_MuxOscRc48MDiv2;
+ rootCfg.div = 1;
+ CLOCK_SetRootClock(kCLOCK_Root_Emv1, &rootCfg);
+
+ /* Configure EMV2 using OSC_RC_48M_DIV2 */
+ rootCfg.mux = kCLOCK_EMV2_ClockRoot_MuxOscRc48MDiv2;
+ rootCfg.div = 1;
+ CLOCK_SetRootClock(kCLOCK_Root_Emv2, &rootCfg);
+
+ /* Configure ENET1 using OSC_RC_48M_DIV2 */
+ rootCfg.mux = kCLOCK_ENET1_ClockRoot_MuxOscRc48MDiv2;
+ rootCfg.div = 1;
+ CLOCK_SetRootClock(kCLOCK_Root_Enet1, &rootCfg);
+
+ /* Configure ENET2 using OSC_RC_48M_DIV2 */
+ rootCfg.mux = kCLOCK_ENET2_ClockRoot_MuxOscRc48MDiv2;
+ rootCfg.div = 1;
+ CLOCK_SetRootClock(kCLOCK_Root_Enet2, &rootCfg);
+
+ /* Configure ENET_QOS using OSC_RC_48M_DIV2 */
+ rootCfg.mux = kCLOCK_ENET_QOS_ClockRoot_MuxOscRc48MDiv2;
+ rootCfg.div = 1;
+ CLOCK_SetRootClock(kCLOCK_Root_Enet_Qos, &rootCfg);
+
+ /* Configure ENET_25M using OSC_RC_48M_DIV2 */
+ rootCfg.mux = kCLOCK_ENET_25M_ClockRoot_MuxOscRc48MDiv2;
+ rootCfg.div = 1;
+ CLOCK_SetRootClock(kCLOCK_Root_Enet_25m, &rootCfg);
+
+ /* Configure ENET_TIMER1 using OSC_RC_48M_DIV2 */
+ rootCfg.mux = kCLOCK_ENET_TIMER1_ClockRoot_MuxOscRc48MDiv2;
+ rootCfg.div = 1;
+ CLOCK_SetRootClock(kCLOCK_Root_Enet_Timer1, &rootCfg);
+
+ /* Configure ENET_TIMER2 using OSC_RC_48M_DIV2 */
+ rootCfg.mux = kCLOCK_ENET_TIMER2_ClockRoot_MuxOscRc48MDiv2;
+ rootCfg.div = 1;
+ CLOCK_SetRootClock(kCLOCK_Root_Enet_Timer2, &rootCfg);
+
+ /* Configure ENET_TIMER3 using OSC_RC_48M_DIV2 */
+ rootCfg.mux = kCLOCK_ENET_TIMER3_ClockRoot_MuxOscRc48MDiv2;
+ rootCfg.div = 1;
+ CLOCK_SetRootClock(kCLOCK_Root_Enet_Timer3, &rootCfg);
+
+ /* Configure USDHC1 using OSC_RC_48M_DIV2 */
+ rootCfg.mux = kCLOCK_USDHC1_ClockRoot_MuxOscRc48MDiv2;
+ rootCfg.div = 1;
+ CLOCK_SetRootClock(kCLOCK_Root_Usdhc1, &rootCfg);
+
+ /* Configure USDHC2 using OSC_RC_48M_DIV2 */
+ rootCfg.mux = kCLOCK_USDHC2_ClockRoot_MuxOscRc48MDiv2;
+ rootCfg.div = 1;
+ CLOCK_SetRootClock(kCLOCK_Root_Usdhc2, &rootCfg);
+
+ /* Configure ASRC using OSC_RC_48M_DIV2 */
+ rootCfg.mux = kCLOCK_ASRC_ClockRoot_MuxOscRc48MDiv2;
+ rootCfg.div = 1;
+ CLOCK_SetRootClock(kCLOCK_Root_Asrc, &rootCfg);
+
+ /* Configure MQS using OSC_RC_48M_DIV2 */
+ rootCfg.mux = kCLOCK_MQS_ClockRoot_MuxOscRc48MDiv2;
+ rootCfg.div = 1;
+ CLOCK_SetRootClock(kCLOCK_Root_Mqs, &rootCfg);
+
+ /* Configure MIC using OSC_RC_48M_DIV2 */
+ rootCfg.mux = kCLOCK_MIC_ClockRoot_MuxOscRc48MDiv2;
+ rootCfg.div = 1;
+ CLOCK_SetRootClock(kCLOCK_Root_Mic, &rootCfg);
+
+ /* Configure SPDIF using OSC_RC_48M_DIV2 */
+ rootCfg.mux = kCLOCK_SPDIF_ClockRoot_MuxOscRc48MDiv2;
+ rootCfg.div = 1;
+ CLOCK_SetRootClock(kCLOCK_Root_Spdif, &rootCfg);
+
+ /* Configure SAI1 using OSC_RC_48M_DIV2 */
+ rootCfg.mux = kCLOCK_SAI1_ClockRoot_MuxOsc24MOut;
+ rootCfg.div = 1;
+ CLOCK_SetRootClock(kCLOCK_Root_Sai1, &rootCfg);
+
+ /* Configure SAI2 using OSC_RC_48M_DIV2 */
+ rootCfg.mux = kCLOCK_SAI2_ClockRoot_MuxOscRc48MDiv2;
+ rootCfg.div = 1;
+ CLOCK_SetRootClock(kCLOCK_Root_Sai2, &rootCfg);
+
+ /* Configure SAI3 using OSC_RC_48M_DIV2 */
+ rootCfg.mux = kCLOCK_SAI3_ClockRoot_MuxOscRc48MDiv2;
+ rootCfg.div = 1;
+ CLOCK_SetRootClock(kCLOCK_Root_Sai3, &rootCfg);
+
+ /* Configure SAI4 using OSC_RC_48M_DIV2 */
+ rootCfg.mux = kCLOCK_SAI4_ClockRoot_MuxOscRc48MDiv2;
+ rootCfg.div = 1;
+ CLOCK_SetRootClock(kCLOCK_Root_Sai4, &rootCfg);
+
+ /* Configure GC355 using PLL_VIDEO_CLK */
+ rootCfg.mux = kCLOCK_GC355_ClockRoot_MuxVideoPllOut;
+ rootCfg.div = 2;
+ CLOCK_SetRootClock(kCLOCK_Root_Gc355, &rootCfg);
+
+ /* Configure LCDIF using OSC_RC_48M_DIV2 */
+ rootCfg.mux = kCLOCK_LCDIF_ClockRoot_MuxOscRc48MDiv2;
+ rootCfg.div = 1;
+ CLOCK_SetRootClock(kCLOCK_Root_Lcdif, &rootCfg);
+
+ /* Configure LCDIFV2 using OSC_RC_48M_DIV2 */
+ rootCfg.mux = kCLOCK_LCDIFV2_ClockRoot_MuxOscRc48MDiv2;
+ rootCfg.div = 1;
+ CLOCK_SetRootClock(kCLOCK_Root_Lcdifv2, &rootCfg);
+
+ /* Configure MIPI_REF using OSC_RC_48M_DIV2 */
+ rootCfg.mux = kCLOCK_MIPI_REF_ClockRoot_MuxOscRc48MDiv2;
+ rootCfg.div = 1;
+ CLOCK_SetRootClock(kCLOCK_Root_Mipi_Ref, &rootCfg);
+
+ /* Configure MIPI_ESC using OSC_RC_48M_DIV2 */
+ rootCfg.mux = kCLOCK_MIPI_ESC_ClockRoot_MuxOscRc48MDiv2;
+ rootCfg.div = 1;
+ CLOCK_SetRootClock(kCLOCK_Root_Mipi_Esc, &rootCfg);
+
+ /* Configure CSI2 using OSC_RC_48M_DIV2 */
+ rootCfg.mux = kCLOCK_CSI2_ClockRoot_MuxOscRc48MDiv2;
+ rootCfg.div = 1;
+ CLOCK_SetRootClock(kCLOCK_Root_Csi2, &rootCfg);
+
+ /* Configure CSI2_ESC using OSC_RC_48M_DIV2 */
+ rootCfg.mux = kCLOCK_CSI2_ESC_ClockRoot_MuxOscRc48MDiv2;
+ rootCfg.div = 1;
+ CLOCK_SetRootClock(kCLOCK_Root_Csi2_Esc, &rootCfg);
+
+ /* Configure CSI2_UI using OSC_RC_48M_DIV2 */
+ rootCfg.mux = kCLOCK_CSI2_UI_ClockRoot_MuxOscRc48MDiv2;
+ rootCfg.div = 1;
+ CLOCK_SetRootClock(kCLOCK_Root_Csi2_Ui, &rootCfg);
+
+ /* Configure CSI using OSC_RC_48M_DIV2 */
+ rootCfg.mux = kCLOCK_CSI_ClockRoot_MuxOscRc48MDiv2;
+ rootCfg.div = 1;
+ CLOCK_SetRootClock(kCLOCK_Root_Csi, &rootCfg);
+
+ /* Configure CKO1 using OSC_RC_48M_DIV2 */
+ rootCfg.mux = kCLOCK_CKO1_ClockRoot_MuxOscRc48MDiv2;
+ rootCfg.div = 1;
+ CLOCK_SetRootClock(kCLOCK_Root_Cko1, &rootCfg);
+
+ /* Configure CKO2 using OSC_RC_48M_DIV2 */
+ rootCfg.mux = kCLOCK_CKO2_ClockRoot_MuxOscRc48MDiv2;
+ rootCfg.div = 1;
+ CLOCK_SetRootClock(kCLOCK_Root_Cko2, &rootCfg);
+
+ /* Set SAI1 MCLK1 clock source. */
+ IOMUXC_SetSaiMClkClockSource(IOMUXC_GPR, kIOMUXC_GPR_SAI1MClk1Sel, 0);
+ /* Set SAI1 MCLK2 clock source. */
+ IOMUXC_SetSaiMClkClockSource(IOMUXC_GPR, kIOMUXC_GPR_SAI1MClk2Sel, 3);
+ /* Set SAI1 MCLK3 clock source. */
+ IOMUXC_SetSaiMClkClockSource(IOMUXC_GPR, kIOMUXC_GPR_SAI1MClk3Sel, 0);
+ /* Set SAI2 MCLK3 clock source. */
+ IOMUXC_SetSaiMClkClockSource(IOMUXC_GPR, kIOMUXC_GPR_SAI2MClk3Sel, 0);
+ /* Set SAI3 MCLK3 clock source. */
+ IOMUXC_SetSaiMClkClockSource(IOMUXC_GPR, kIOMUXC_GPR_SAI3MClk3Sel, 0);
+
+ /* Set MQS configuration. */
+ IOMUXC_MQSConfig(IOMUXC_GPR, kIOMUXC_MqsPwmOverSampleRate32, 0);
+ /* Set ENET Tx clock source. */
+ IOMUXC_GPR->GPR4 &= ~IOMUXC_GPR_GPR4_ENET_TX_CLK_SEL_MASK;
+ /* Set ENET_1G Tx clock source. */
+ IOMUXC_GPR->GPR5 = ((IOMUXC_GPR->GPR5 & ~IOMUXC_GPR_GPR5_ENET1G_TX_CLK_SEL_MASK) | IOMUXC_GPR_GPR5_ENET1G_RGMII_EN_MASK);
+ /* Set GPT1 High frequency reference clock source. */
+ IOMUXC_GPR->GPR22 &= ~IOMUXC_GPR_GPR22_REF_1M_CLK_GPT1_MASK;
+ /* Set GPT2 High frequency reference clock source. */
+ IOMUXC_GPR->GPR23 &= ~IOMUXC_GPR_GPR23_REF_1M_CLK_GPT2_MASK;
+ /* Set GPT3 High frequency reference clock source. */
+ IOMUXC_GPR->GPR24 &= ~IOMUXC_GPR_GPR24_REF_1M_CLK_GPT3_MASK;
+ /* Set GPT4 High frequency reference clock source. */
+ IOMUXC_GPR->GPR25 &= ~IOMUXC_GPR_GPR25_REF_1M_CLK_GPT4_MASK;
+ /* Set GPT5 High frequency reference clock source. */
+ IOMUXC_GPR->GPR26 &= ~IOMUXC_GPR_GPR26_REF_1M_CLK_GPT5_MASK;
+ /* Set GPT6 High frequency reference clock source. */
+ IOMUXC_GPR->GPR27 &= ~IOMUXC_GPR_GPR27_REF_1M_CLK_GPT6_MASK;
+
+ #if __CORTEX_M == 7
+ SystemCoreClock = CLOCK_GetRootClockFreq(kCLOCK_Root_M7);
+ #else
+ SystemCoreClock = CLOCK_GetRootClockFreq(kCLOCK_Root_M4);
+ #endif
+}
diff --git a/ports/mimxrt/boards/MIMXRT1176_clock_config.h b/ports/mimxrt/boards/MIMXRT1176_clock_config.h
new file mode 100644
index 000000000000..df2748a65811
--- /dev/null
+++ b/ports/mimxrt/boards/MIMXRT1176_clock_config.h
@@ -0,0 +1,210 @@
+/*
+ * Copyright 2020 NXP
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef _CLOCK_CONFIG_H_
+#define _CLOCK_CONFIG_H_
+
+#include "fsl_common.h"
+
+/*******************************************************************************
+ * Definitions
+ ******************************************************************************/
+
+#define BOARD_XTAL0_CLK_HZ 24000000U /*!< Board xtal0 frequency in Hz */
+
+#define BOARD_XTAL32K_CLK_HZ 32768U /*!< Board xtal32k frequency in Hz */
+
+/*******************************************************************************
+ ************************ BOARD_InitBootClocks function ************************
+ ******************************************************************************/
+
+#if defined(__cplusplus)
+extern "C" {
+#endif /* __cplusplus*/
+
+/*!
+ * @brief This function executes default configuration of clocks.
+ *
+ */
+void BOARD_InitBootClocks(void);
+
+#if defined(__cplusplus)
+}
+#endif /* __cplusplus*/
+
+/*******************************************************************************
+ ********************** Configuration BOARD_BootClockRUN ***********************
+ ******************************************************************************/
+/*******************************************************************************
+ * Definitions for BOARD_BootClockRUN configuration
+ ******************************************************************************/
+#if __CORTEX_M == 7
+ #define BOARD_BOOTCLOCKRUN_CORE_CLOCK 996000000UL /*!< CM7 Core clock frequency: 996000000Hz */
+#else
+ #define BOARD_BOOTCLOCKRUN_CORE_CLOCK 392727272UL /*!< CM4 Core clock frequency: 392727272Hz */
+#endif
+
+/* Clock outputs (values are in Hz): */
+#define BOARD_BOOTCLOCKRUN_ACMP_CLK_ROOT 24000000UL
+#define BOARD_BOOTCLOCKRUN_ADC1_CLK_ROOT 24000000UL
+#define BOARD_BOOTCLOCKRUN_ADC2_CLK_ROOT 24000000UL
+#define BOARD_BOOTCLOCKRUN_ARM_PLL_CLK 996000000UL
+#define BOARD_BOOTCLOCKRUN_ASRC_CLK_ROOT 24000000UL
+#define BOARD_BOOTCLOCKRUN_AXI_CLK_ROOT 996000000UL
+#define BOARD_BOOTCLOCKRUN_BUS_CLK_ROOT 160000000UL // 160MHz
+#define BOARD_BOOTCLOCKRUN_BUS_LPSR_CLK_ROOT 120000000UL // 120MHz
+#define BOARD_BOOTCLOCKRUN_CAN1_CLK_ROOT 24000000UL
+#define BOARD_BOOTCLOCKRUN_CAN2_CLK_ROOT 24000000UL
+#define BOARD_BOOTCLOCKRUN_CAN3_CLK_ROOT 24000000UL
+#define BOARD_BOOTCLOCKRUN_CCM_CLKO1_CLK_ROOT 24000000UL
+#define BOARD_BOOTCLOCKRUN_CCM_CLKO2_CLK_ROOT 24000000UL
+#define BOARD_BOOTCLOCKRUN_CLK_1M 1000000UL
+#define BOARD_BOOTCLOCKRUN_CSI2_CLK_ROOT 24000000UL
+#define BOARD_BOOTCLOCKRUN_CSI2_ESC_CLK_ROOT 24000000UL
+#define BOARD_BOOTCLOCKRUN_CSI2_UI_CLK_ROOT 24000000UL
+#define BOARD_BOOTCLOCKRUN_CSI_CLK_ROOT 24000000UL
+#define BOARD_BOOTCLOCKRUN_CSSYS_CLK_ROOT 24000000UL
+#define BOARD_BOOTCLOCKRUN_CSTRACE_CLK_ROOT 132000000UL
+#define BOARD_BOOTCLOCKRUN_ELCDIF_CLK_ROOT 24000000UL
+#define BOARD_BOOTCLOCKRUN_EMV1_CLK_ROOT 24000000UL
+#define BOARD_BOOTCLOCKRUN_EMV2_CLK_ROOT 24000000UL
+#define BOARD_BOOTCLOCKRUN_ENET1_CLK_ROOT 24000000UL
+#define BOARD_BOOTCLOCKRUN_ENET2_CLK_ROOT 24000000UL
+#define BOARD_BOOTCLOCKRUN_ENET_1G_TX_CLK 24000000UL
+#define BOARD_BOOTCLOCKRUN_ENET_25M_CLK_ROOT 24000000UL
+#define BOARD_BOOTCLOCKRUN_ENET_QOS_CLK_ROOT 24000000UL
+#define BOARD_BOOTCLOCKRUN_ENET_TIMER1_CLK_ROOT 24000000UL
+#define BOARD_BOOTCLOCKRUN_ENET_TIMER2_CLK_ROOT 24000000UL
+#define BOARD_BOOTCLOCKRUN_ENET_TIMER3_CLK_ROOT 24000000UL
+#define BOARD_BOOTCLOCKRUN_ENET_TX_CLK 24000000UL
+#define BOARD_BOOTCLOCKRUN_FLEXIO1_CLK_ROOT 24000000UL
+#define BOARD_BOOTCLOCKRUN_FLEXIO2_CLK_ROOT 24000000UL
+#define BOARD_BOOTCLOCKRUN_FLEXSPI1_CLK_ROOT 24000000UL
+#define BOARD_BOOTCLOCKRUN_FLEXSPI2_CLK_ROOT 24000000UL
+#define BOARD_BOOTCLOCKRUN_GC355_CLK_ROOT 492000012UL
+#define BOARD_BOOTCLOCKRUN_GPT1_CLK_ROOT 24000000UL
+#define BOARD_BOOTCLOCKRUN_GPT1_IPG_CLK_HIGHFREQ 24000000UL
+#define BOARD_BOOTCLOCKRUN_GPT2_CLK_ROOT 24000000UL
+#define BOARD_BOOTCLOCKRUN_GPT2_IPG_CLK_HIGHFREQ 24000000UL
+#define BOARD_BOOTCLOCKRUN_GPT3_CLK_ROOT 24000000UL
+#define BOARD_BOOTCLOCKRUN_GPT3_IPG_CLK_HIGHFREQ 24000000UL
+#define BOARD_BOOTCLOCKRUN_GPT4_CLK_ROOT 24000000UL
+#define BOARD_BOOTCLOCKRUN_GPT4_IPG_CLK_HIGHFREQ 24000000UL
+#define BOARD_BOOTCLOCKRUN_GPT5_CLK_ROOT 24000000UL
+#define BOARD_BOOTCLOCKRUN_GPT5_IPG_CLK_HIGHFREQ 24000000UL
+#define BOARD_BOOTCLOCKRUN_GPT6_CLK_ROOT 24000000UL
+#define BOARD_BOOTCLOCKRUN_GPT6_IPG_CLK_HIGHFREQ 24000000UL
+#define BOARD_BOOTCLOCKRUN_LCDIFV2_CLK_ROOT 24000000UL
+#define BOARD_BOOTCLOCKRUN_LPI2C1_CLK_ROOT 60000000UL // 60MHz
+#define BOARD_BOOTCLOCKRUN_LPI2C2_CLK_ROOT 60000000UL // 60MHz
+#define BOARD_BOOTCLOCKRUN_LPI2C3_CLK_ROOT 60000000UL // 60MHz
+#define BOARD_BOOTCLOCKRUN_LPI2C4_CLK_ROOT 60000000UL // 60MHz
+#define BOARD_BOOTCLOCKRUN_LPI2C5_CLK_ROOT 60000000UL // 60MHz
+#define BOARD_BOOTCLOCKRUN_LPI2C6_CLK_ROOT 60000000UL // 60MHz
+#define BOARD_BOOTCLOCKRUN_LPSPI1_CLK_ROOT 13500000UL // 135MHz
+#define BOARD_BOOTCLOCKRUN_LPSPI2_CLK_ROOT 13500000UL // 135MHz
+#define BOARD_BOOTCLOCKRUN_LPSPI3_CLK_ROOT 13500000UL // 135MHz
+#define BOARD_BOOTCLOCKRUN_LPSPI4_CLK_ROOT 13500000UL // 135MHz
+#define BOARD_BOOTCLOCKRUN_LPSPI5_CLK_ROOT 13500000UL // 135MHz
+#define BOARD_BOOTCLOCKRUN_LPSPI6_CLK_ROOT 13500000UL // 135MHz
+#define BOARD_BOOTCLOCKRUN_LPUART10_CLK_ROOT 74250000UL
+#define BOARD_BOOTCLOCKRUN_LPUART11_CLK_ROOT 74250000UL
+#define BOARD_BOOTCLOCKRUN_LPUART12_CLK_ROOT 74250000UL
+#define BOARD_BOOTCLOCKRUN_LPUART1_CLK_ROOT 74250000UL
+#define BOARD_BOOTCLOCKRUN_LPUART2_CLK_ROOT 74250000UL
+#define BOARD_BOOTCLOCKRUN_LPUART3_CLK_ROOT 74250000UL
+#define BOARD_BOOTCLOCKRUN_LPUART4_CLK_ROOT 74250000UL
+#define BOARD_BOOTCLOCKRUN_LPUART5_CLK_ROOT 74250000UL
+#define BOARD_BOOTCLOCKRUN_LPUART6_CLK_ROOT 74250000UL
+#define BOARD_BOOTCLOCKRUN_LPUART7_CLK_ROOT 74250000UL
+#define BOARD_BOOTCLOCKRUN_LPUART8_CLK_ROOT 74250000UL
+#define BOARD_BOOTCLOCKRUN_LPUART9_CLK_ROOT 74250000UL
+#define BOARD_BOOTCLOCKRUN_M4_CLK_ROOT 392727272UL
+#define BOARD_BOOTCLOCKRUN_M4_SYSTICK_CLK_ROOT 24000000UL
+#define BOARD_BOOTCLOCKRUN_M7_CLK_ROOT 996000000UL
+#define BOARD_BOOTCLOCKRUN_M7_SYSTICK_CLK_ROOT 100000UL
+#define BOARD_BOOTCLOCKRUN_MIC_CLK_ROOT 24000000UL
+#define BOARD_BOOTCLOCKRUN_MIPI_DSI_TX_CLK_ESC_ROOT 24000000UL
+#define BOARD_BOOTCLOCKRUN_MIPI_ESC_CLK_ROOT 24000000UL
+#define BOARD_BOOTCLOCKRUN_MIPI_REF_CLK_ROOT 24000000UL
+#define BOARD_BOOTCLOCKRUN_MQS_CLK_ROOT 24000000UL
+#define BOARD_BOOTCLOCKRUN_MQS_MCLK 24000000UL
+#define BOARD_BOOTCLOCKRUN_OSC_24M 24000000UL
+#define BOARD_BOOTCLOCKRUN_OSC_32K 32768UL
+#define BOARD_BOOTCLOCKRUN_OSC_RC_16M 16000000UL
+#define BOARD_BOOTCLOCKRUN_OSC_RC_400M 400000000UL
+#define BOARD_BOOTCLOCKRUN_OSC_RC_48M 48000000UL
+#define BOARD_BOOTCLOCKRUN_OSC_RC_48M_DIV2 24000000UL
+#define BOARD_BOOTCLOCKRUN_PLL_AUDIO_CLK 0UL
+#define BOARD_BOOTCLOCKRUN_PLL_AUDIO_SS_MODULATION 0UL
+#define BOARD_BOOTCLOCKRUN_PLL_AUDIO_SS_RANGE 0UL
+#define BOARD_BOOTCLOCKRUN_PLL_VIDEO_CLK 984000025UL
+#define BOARD_BOOTCLOCKRUN_PLL_VIDEO_SS_MODULATION 0UL
+#define BOARD_BOOTCLOCKRUN_PLL_VIDEO_SS_RANGE 0UL
+#define BOARD_BOOTCLOCKRUN_SAI1_CLK_ROOT 24000000UL
+#define BOARD_BOOTCLOCKRUN_SAI1_MCLK1 24000000UL
+#define BOARD_BOOTCLOCKRUN_SAI1_MCLK2 0UL
+#define BOARD_BOOTCLOCKRUN_SAI1_MCLK3 24000000UL
+#define BOARD_BOOTCLOCKRUN_SAI2_CLK_ROOT 24000000UL
+#define BOARD_BOOTCLOCKRUN_SAI2_MCLK1 24000000UL
+#define BOARD_BOOTCLOCKRUN_SAI2_MCLK2 0UL
+#define BOARD_BOOTCLOCKRUN_SAI2_MCLK3 24000000UL
+#define BOARD_BOOTCLOCKRUN_SAI3_CLK_ROOT 24000000UL
+#define BOARD_BOOTCLOCKRUN_SAI3_MCLK1 24000000UL
+#define BOARD_BOOTCLOCKRUN_SAI3_MCLK2 0UL
+#define BOARD_BOOTCLOCKRUN_SAI3_MCLK3 24000000UL
+#define BOARD_BOOTCLOCKRUN_SAI4_CLK_ROOT 24000000UL
+#define BOARD_BOOTCLOCKRUN_SAI4_MCLK1 24000000UL
+#define BOARD_BOOTCLOCKRUN_SAI4_MCLK2 0UL
+#define BOARD_BOOTCLOCKRUN_SEMC_CLK_ROOT 198000000UL
+#define BOARD_BOOTCLOCKRUN_SPDIF_CLK_ROOT 24000000UL
+#define BOARD_BOOTCLOCKRUN_SPDIF_EXTCLK_OUT 0UL
+#define BOARD_BOOTCLOCKRUN_SYS_PLL1_CLK 0UL
+#define BOARD_BOOTCLOCKRUN_SYS_PLL1_DIV2_CLK 0UL
+#define BOARD_BOOTCLOCKRUN_SYS_PLL1_DIV5_CLK 0UL
+#define BOARD_BOOTCLOCKRUN_SYS_PLL1_SS_MODULATION 0UL
+#define BOARD_BOOTCLOCKRUN_SYS_PLL1_SS_RANGE 0UL
+#define BOARD_BOOTCLOCKRUN_SYS_PLL2_CLK 528000000UL
+#define BOARD_BOOTCLOCKRUN_SYS_PLL2_PFD0_CLK 352000000UL
+#define BOARD_BOOTCLOCKRUN_SYS_PLL2_PFD1_CLK 594000000UL
+#define BOARD_BOOTCLOCKRUN_SYS_PLL2_PFD2_CLK 396000000UL
+#define BOARD_BOOTCLOCKRUN_SYS_PLL2_PFD3_CLK 297000000UL
+#define BOARD_BOOTCLOCKRUN_SYS_PLL2_SS_MODULATION 0UL
+#define BOARD_BOOTCLOCKRUN_SYS_PLL2_SS_RANGE 0UL
+#define BOARD_BOOTCLOCKRUN_SYS_PLL3_CLK 480000000UL
+#define BOARD_BOOTCLOCKRUN_SYS_PLL3_DIV2_CLK 240000000UL
+#define BOARD_BOOTCLOCKRUN_SYS_PLL3_PFD0_CLK 664615384UL
+#define BOARD_BOOTCLOCKRUN_SYS_PLL3_PFD1_CLK 508235294UL
+#define BOARD_BOOTCLOCKRUN_SYS_PLL3_PFD2_CLK 270000000UL
+#define BOARD_BOOTCLOCKRUN_SYS_PLL3_PFD3_CLK 392727272UL
+#define BOARD_BOOTCLOCKRUN_USDHC1_CLK_ROOT 24000000UL
+#define BOARD_BOOTCLOCKRUN_USDHC2_CLK_ROOT 24000000UL
+
+
+// Configuration for all instances of peripherals are identical
+#define BOARD_BOOTCLOCKRUN_LPI2C_CLK_ROOT 60000000UL // 60MHz
+#define BOARD_BOOTCLOCKRUN_LPSPI_CLK_ROOT 135000000UL // 135MHz
+#define BOARD_BOOTCLOCKRUN_PERCLK_CLK_ROOT 160000000UL // 160MHz
+#define BOARD_BOOTCLOCKRUN_UART_CLK_ROOT 74250000UL // 74.25MHz
+/*******************************************************************************
+ * API for BOARD_BootClockRUN configuration
+ ******************************************************************************/
+#if defined(__cplusplus)
+extern "C" {
+#endif /* __cplusplus*/
+
+/*!
+ * @brief This function executes configuration of clocks.
+ *
+ */
+void BOARD_BootClockRUN(void);
+
+#if defined(__cplusplus)
+}
+#endif /* __cplusplus*/
+
+#endif /* _CLOCK_CONFIG_H_ */
diff --git a/ports/mimxrt/boards/OLIMEX_RT1010/mpconfigboard.h b/ports/mimxrt/boards/OLIMEX_RT1010/mpconfigboard.h
index c30caa047075..d63c0dc40390 100644
--- a/ports/mimxrt/boards/OLIMEX_RT1010/mpconfigboard.h
+++ b/ports/mimxrt/boards/OLIMEX_RT1010/mpconfigboard.h
@@ -1,6 +1,6 @@
#define MICROPY_HW_BOARD_NAME "RT1010-Py-DevKIT"
#define MICROPY_HW_MCU_NAME "MIMXRT1011DAE5A"
-#define MICROPY_HW_USB_STR_MANUF "Olimex Ltd."
+#define MICROPY_HW_USB_MANUFACTURER_STRING "Olimex Ltd."
#define MICROPY_HW_USB_VID 0x15ba
#define MICROPY_HW_USB_PID 0x0046
#define MICROPY_PY_UOS_DUPTERM_BUILTIN_STREAM (0)
@@ -57,6 +57,7 @@
#define I2S_IOMUXC_GPR_MODE { 0, kIOMUXC_GPR_SAI1MClkOutputDir, 0, kIOMUXC_GPR_SAI3MClkOutputDir }
#define I2S_DMA_REQ_SRC_RX { 0, kDmaRequestMuxSai1Rx, 0, kDmaRequestMuxSai3Rx }
#define I2S_DMA_REQ_SRC_TX { 0, kDmaRequestMuxSai1Tx, 0, kDmaRequestMuxSai3Tx }
+#define I2S_AUDIO_PLL_CLOCK (2U)
#define I2S_GPIO(_hwid, _fn, _mode, _pin, _iomux) \
{ \
@@ -80,7 +81,3 @@
I2S_GPIO(3, WS, TX, GPIO_SD_00, IOMUXC_GPIO_SD_00_SAI3_TX_SYNC), /* pin D9 */ \
I2S_GPIO(3, SD, TX, GPIO_SD_02, IOMUXC_GPIO_SD_02_SAI3_TX_DATA) /* pin D11 */ \
}
-
-
-#define MICROPY_BOARD_ROOT_POINTERS \
- struct _machine_i2s_obj_t *machine_i2s_obj[MICROPY_HW_I2S_NUM];
diff --git a/ports/mimxrt/boards/OLIMEX_RT1010/mpconfigboard.mk b/ports/mimxrt/boards/OLIMEX_RT1010/mpconfigboard.mk
index e4f904903de7..135c43257c95 100644
--- a/ports/mimxrt/boards/OLIMEX_RT1010/mpconfigboard.mk
+++ b/ports/mimxrt/boards/OLIMEX_RT1010/mpconfigboard.mk
@@ -3,8 +3,8 @@ MCU_VARIANT = MIMXRT1011DAE5A
MICROPY_FLOAT_IMPL = single
MICROPY_PY_MACHINE_SDCARD ?= 0
-MICROPY_HW_FLASH_TYPE ?= qspi_nor
-MICROPY_HW_FLASH_SIZE ?= 0x200000 # 2MB
+MICROPY_HW_FLASH_TYPE = qspi_nor_flash
+MICROPY_HW_FLASH_SIZE = 0x200000 # 2MB
MICROPY_HW_FLASH_RESERVED ?= 0x1000 # 4KB
CFLAGS += -DMICROPY_HW_FLASH_DQS=kFlexSPIReadSampleClk_LoopbackInternally
diff --git a/ports/mimxrt/boards/SEEED_ARCH_MIX/manifest.py b/ports/mimxrt/boards/SEEED_ARCH_MIX/manifest.py
new file mode 100644
index 000000000000..107181c31ca7
--- /dev/null
+++ b/ports/mimxrt/boards/SEEED_ARCH_MIX/manifest.py
@@ -0,0 +1,3 @@
+include("../manifest.py")
+
+require("bundle-networking")
diff --git a/ports/mimxrt/boards/SEEED_ARCH_MIX/mpconfigboard.h b/ports/mimxrt/boards/SEEED_ARCH_MIX/mpconfigboard.h
index a6502d3353d8..c98cdcb0a749 100644
--- a/ports/mimxrt/boards/SEEED_ARCH_MIX/mpconfigboard.h
+++ b/ports/mimxrt/boards/SEEED_ARCH_MIX/mpconfigboard.h
@@ -1,6 +1,8 @@
#define MICROPY_HW_BOARD_NAME "Seeed ARCH MIX"
#define MICROPY_HW_MCU_NAME "MIMXRT1052DVL5B"
+#define MICROPY_PY_NETWORK_HOSTNAME_DEFAULT "mpy-arch-mix"
+
// MIMXRT1050_EVKB has 1 user LED
#define MICROPY_HW_LED1_PIN (pin_GPIO_AD_B0_09)
#define MICROPY_HW_LED2_PIN (pin_GPIO_AD_B0_10)
@@ -73,6 +75,7 @@
#define I2S_IOMUXC_GPR_MODE { 0, kIOMUXC_GPR_SAI1MClkOutputDir }
#define I2S_DMA_REQ_SRC_RX { 0, kDmaRequestMuxSai1Rx }
#define I2S_DMA_REQ_SRC_TX { 0, kDmaRequestMuxSai1Tx }
+#define I2S_AUDIO_PLL_CLOCK (2U)
#define I2S_GPIO(_hwid, _fn, _mode, _pin, _iomux) \
{ \
@@ -116,6 +119,8 @@
// Etherner PIN definitions
// No reset and interrupt pin by intention
+#define ENET_RESET_PIN NULL
+#define ENET_INT_PIN NULL
#define IOMUX_TABLE_ENET \
{ IOMUXC_GPIO_B1_04_ENET_RX_DATA00, 0, 0xB0E9u }, \
@@ -173,6 +178,3 @@
#define MIMXRT_IOMUXC_SEMC_WE IOMUXC_GPIO_EMC_28_SEMC_WE
#define MIMXRT_IOMUXC_SEMC_CS0 IOMUXC_GPIO_EMC_29_SEMC_CS0
-
-#define MICROPY_BOARD_ROOT_POINTERS \
- struct _machine_i2s_obj_t *machine_i2s_obj[MICROPY_HW_I2S_NUM];
diff --git a/ports/mimxrt/boards/SEEED_ARCH_MIX/mpconfigboard.mk b/ports/mimxrt/boards/SEEED_ARCH_MIX/mpconfigboard.mk
index 90edc5d51782..8e530ac55892 100644
--- a/ports/mimxrt/boards/SEEED_ARCH_MIX/mpconfigboard.mk
+++ b/ports/mimxrt/boards/SEEED_ARCH_MIX/mpconfigboard.mk
@@ -3,8 +3,8 @@ MCU_VARIANT = MIMXRT1052DVL6B
MICROPY_FLOAT_IMPL = double
MICROPY_PY_MACHINE_SDCARD = 1
-MICROPY_HW_FLASH_TYPE ?= qspi_nor
-MICROPY_HW_FLASH_SIZE ?= 0x800000 # 8MB
+MICROPY_HW_FLASH_TYPE = qspi_nor_flash
+MICROPY_HW_FLASH_SIZE = 0x800000 # 8MB
MICROPY_HW_SDRAM_AVAIL = 1
MICROPY_HW_SDRAM_SIZE = 0x2000000 # 32MB
@@ -12,3 +12,7 @@ MICROPY_HW_SDRAM_SIZE = 0x2000000 # 32MB
MICROPY_PY_LWIP = 1
MICROPY_PY_USSL = 1
MICROPY_SSL_MBEDTLS = 1
+
+FROZEN_MANIFEST ?= $(BOARD_DIR)/manifest.py
+
+CFLAGS += -DSPI_RETRY_TIMES=1000000
diff --git a/ports/mimxrt/boards/TEENSY40/mpconfigboard.h b/ports/mimxrt/boards/TEENSY40/mpconfigboard.h
index f2ea86bd0ec6..07da87db10fc 100644
--- a/ports/mimxrt/boards/TEENSY40/mpconfigboard.h
+++ b/ports/mimxrt/boards/TEENSY40/mpconfigboard.h
@@ -66,6 +66,7 @@
#define I2S_IOMUXC_GPR_MODE { 0, kIOMUXC_GPR_SAI1MClkOutputDir, kIOMUXC_GPR_SAI2MClkOutputDir }
#define I2S_DMA_REQ_SRC_RX { 0, kDmaRequestMuxSai1Rx, kDmaRequestMuxSai2Rx }
#define I2S_DMA_REQ_SRC_TX { 0, kDmaRequestMuxSai1Tx, kDmaRequestMuxSai2Tx }
+#define I2S_AUDIO_PLL_CLOCK (2U)
#define I2S_GPIO(_hwid, _fn, _mode, _pin, _iomux) \
{ \
@@ -104,6 +105,3 @@
.data2 = { GPIO_SD_B0_04_USDHC1_DATA2 }, \
.data3 = { GPIO_SD_B0_05_USDHC1_DATA3 }, \
}
-
-#define MICROPY_BOARD_ROOT_POINTERS \
- struct _machine_i2s_obj_t *machine_i2s_obj[MICROPY_HW_I2S_NUM];
diff --git a/ports/mimxrt/boards/TEENSY40/mpconfigboard.mk b/ports/mimxrt/boards/TEENSY40/mpconfigboard.mk
index 94e427cc168a..4482c629f7dc 100644
--- a/ports/mimxrt/boards/TEENSY40/mpconfigboard.mk
+++ b/ports/mimxrt/boards/TEENSY40/mpconfigboard.mk
@@ -3,8 +3,8 @@ MCU_VARIANT = MIMXRT1062DVJ6A
MICROPY_FLOAT_IMPL = double
MICROPY_PY_MACHINE_SDCARD = 1
-MICROPY_HW_FLASH_TYPE ?= qspi_nor
-MICROPY_HW_FLASH_SIZE ?= 0x200000 # 2MB
+MICROPY_HW_FLASH_TYPE = qspi_nor_flash
+MICROPY_HW_FLASH_SIZE = 0x200000 # 2MB
MICROPY_HW_FLASH_RESERVED ?= 0x1000 # 4KB
deploy: $(BUILD)/firmware.hex
diff --git a/ports/mimxrt/boards/TEENSY41/manifest.py b/ports/mimxrt/boards/TEENSY41/manifest.py
new file mode 100644
index 000000000000..107181c31ca7
--- /dev/null
+++ b/ports/mimxrt/boards/TEENSY41/manifest.py
@@ -0,0 +1,3 @@
+include("../manifest.py")
+
+require("bundle-networking")
diff --git a/ports/mimxrt/boards/TEENSY41/mpconfigboard.h b/ports/mimxrt/boards/TEENSY41/mpconfigboard.h
index 7d75f62f36cf..56740f48ea3d 100644
--- a/ports/mimxrt/boards/TEENSY41/mpconfigboard.h
+++ b/ports/mimxrt/boards/TEENSY41/mpconfigboard.h
@@ -1,6 +1,8 @@
#define MICROPY_HW_BOARD_NAME "Teensy 4.1"
#define MICROPY_HW_MCU_NAME "MIMXRT1062DVJ6A"
+#define MICROPY_PY_NETWORK_HOSTNAME_DEFAULT "mpy-teensy41"
+
// Teensy 4.1 has 1 board LED
#define MICROPY_HW_LED1_PIN (pin_GPIO_B0_03)
#define MICROPY_HW_LED_ON(pin) (mp_hal_pin_high(pin))
@@ -66,6 +68,7 @@
#define I2S_IOMUXC_GPR_MODE { 0, kIOMUXC_GPR_SAI1MClkOutputDir, kIOMUXC_GPR_SAI2MClkOutputDir }
#define I2S_DMA_REQ_SRC_RX { 0, kDmaRequestMuxSai1Rx, kDmaRequestMuxSai2Rx }
#define I2S_DMA_REQ_SRC_TX { 0, kDmaRequestMuxSai1Tx, kDmaRequestMuxSai2Tx }
+#define I2S_AUDIO_PLL_CLOCK (2U)
#define I2S_GPIO(_hwid, _fn, _mode, _pin, _iomux) \
{ \
@@ -113,8 +116,8 @@
#define ENET_PHY_OPS phydp83825_ops
// Ethernet PIN definitions
-#define ENET_RESET_PIN pin_GPIO_B0_14
-#define ENET_INT_PIN pin_GPIO_B0_15
+#define ENET_RESET_PIN &pin_GPIO_B0_14
+#define ENET_INT_PIN &pin_GPIO_B0_15
#define IOMUX_TABLE_ENET \
{ IOMUXC_GPIO_B1_04_ENET_RX_DATA00, 0, 0xB0E9u }, \
@@ -127,6 +130,3 @@
{ IOMUXC_GPIO_B1_11_ENET_RX_ER, 0, 0xB0E9u }, \
{ IOMUXC_GPIO_B1_15_ENET_MDIO, 0, 0xB0E9u }, \
{ IOMUXC_GPIO_B1_14_ENET_MDC, 0, 0xB0E9u },
-
-#define MICROPY_BOARD_ROOT_POINTERS \
- struct _machine_i2s_obj_t *machine_i2s_obj[MICROPY_HW_I2S_NUM];
diff --git a/ports/mimxrt/boards/TEENSY41/mpconfigboard.mk b/ports/mimxrt/boards/TEENSY41/mpconfigboard.mk
index a012444caaa9..ca7e10b5e4c3 100755
--- a/ports/mimxrt/boards/TEENSY41/mpconfigboard.mk
+++ b/ports/mimxrt/boards/TEENSY41/mpconfigboard.mk
@@ -3,13 +3,15 @@ MCU_VARIANT = MIMXRT1062DVJ6A
MICROPY_FLOAT_IMPL = double
MICROPY_PY_MACHINE_SDCARD = 1
-MICROPY_HW_FLASH_TYPE ?= qspi_nor
-MICROPY_HW_FLASH_SIZE ?= 0x800000 # 8MB
+MICROPY_HW_FLASH_TYPE = qspi_nor_flash
+MICROPY_HW_FLASH_SIZE = 0x800000 # 8MB
MICROPY_HW_FLASH_RESERVED ?= 0x1000 # 4KB
MICROPY_PY_LWIP = 1
MICROPY_PY_USSL = 1
MICROPY_SSL_MBEDTLS = 1
+FROZEN_MANIFEST ?= $(BOARD_DIR)/manifest.py
+
deploy: $(BUILD)/firmware.hex
teensy_loader_cli --mcu=imxrt1062 -v -w $<
diff --git a/ports/mimxrt/boards/common.ld b/ports/mimxrt/boards/common.ld
index 7aee66e2e8e1..c2aa369f66b3 100644
--- a/ports/mimxrt/boards/common.ld
+++ b/ports/mimxrt/boards/common.ld
@@ -46,7 +46,7 @@ MEMORY
m_dtcm (RW) : ORIGIN = dtcm_start, LENGTH = dtcm_size
m_ocrm (RW) : ORIGIN = ocrm_start, LENGTH = ocrm_size
- #ifdef MICROPY_HW_SDRAM_AVAIL
+ #if MICROPY_HW_SDRAM_AVAIL
m_sdram (RX) : ORIGIN = sdram_start, LENGTH = sdram_size
#endif
}
@@ -55,7 +55,7 @@ MEMORY
SECTIONS
{
__flash_start = flash_start;
- #ifdef MICROPY_HW_SDRAM_AVAIL
+ #if MICROPY_HW_SDRAM_AVAIL
__sdram_start = sdram_start;
#endif
__vfs_start = ORIGIN(m_vfs);
@@ -96,7 +96,7 @@ SECTIONS
.text :
{
. = ALIGN(4);
- *(EXCLUDE_FILE(*fsl_flexspi.o *gc*.o *vm.o *parse.o *runtime*.o *mpirq.o *map.o) .text*) /* .text* sections (code) */
+ *(EXCLUDE_FILE(*fsl_flexspi.o *gc.o *vm.o *parse*.o *runtime*.o *map.o *mpirq.o ) .text*) /* .text* sections (code) */
*(.rodata) /* .rodata sections (constants, strings, etc.) */
*(.rodata*) /* .rodata* sections (constants, strings, etc.) */
*(.glue_7) /* glue arm to thumb code */
@@ -207,7 +207,7 @@ SECTIONS
__ram_function_end__ = .;
} > m_itcm
- __NDATA_ROM = __DATA_ROM + (__ram_function_end__ - __data_start__);
+ __NDATA_ROM = __RAM_FUNCTIONS_ROM + (__ram_function_end__ - __ram_function_start__);
.ncache.init : AT(__NDATA_ROM)
{
__noncachedata_start__ = .; /* create a global symbol at ncache data start */
@@ -223,7 +223,8 @@ SECTIONS
__noncachedata_end__ = .; /* define a global symbol at ncache data end */
} > m_dtcm
- __DATA_END = __NDATA_ROM + (__noncachedata_init_end__ - __noncachedata_start__);
+ __DATA_END = __NDATA_ROM + (__noncachedata_end__ - __noncachedata_start__);
+ __FLASH_DATA_END = __NDATA_ROM + (__noncachedata_init_end__ - __noncachedata_start__);
text_end = ORIGIN(m_text) + LENGTH(m_text);
ASSERT(__DATA_END <= text_end, "region m_text overflowed with text and data")
@@ -262,6 +263,8 @@ SECTIONS
. += STACK_SIZE;
} > m_dtcm
+ _flashimagelen = __FLASH_DATA_END - flash_start;
+
/* Initializes stack on the end of block */
__StackTop = ORIGIN(m_dtcm) + LENGTH(m_dtcm);
__StackLimit = __StackTop - STACK_SIZE;
diff --git a/ports/mimxrt/boards/make-flexram-config.py b/ports/mimxrt/boards/make-flexram-config.py
index 5d9c1a8c7c02..4a80fb1d2476 100644
--- a/ports/mimxrt/boards/make-flexram-config.py
+++ b/ports/mimxrt/boards/make-flexram-config.py
@@ -53,6 +53,7 @@
"""
ocram_min_size = 0x00010000 # 64 KB
+
# Value parser
def mimxrt_default_parser(defines_file, features_file, ld_script):
with open(ld_script, "r") as input_file:
@@ -169,6 +170,43 @@ def mimxrt_106x_gen_code(extract_dict):
)
+def mimxrt_1176_gen_code(extract_dict):
+ flexram_bank_cfg = "0b"
+ avail_flexram = extract_dict["fsl_ram_bank_size"] * extract_dict["fsl_bank_nbr"]
+ flexram_configurable_ocram = (
+ extract_dict["ocram_size"] % 524288
+ ) # 512kB OCRAM are not part of FlexRAM configurable memory
+
+ if (
+ flexram_configurable_ocram + extract_dict["dtcm_size"] + extract_dict["itcm_size"]
+ ) > avail_flexram:
+ raise ValueError("Configuration exceeds available FlexRAM!")
+
+ for size, pattern in (
+ (flexram_configurable_ocram, "01"),
+ (extract_dict["dtcm_size"], "10"),
+ (extract_dict["itcm_size"], "11"),
+ ):
+ for _ in range(0, size, extract_dict["fsl_ram_bank_size"]):
+ flexram_bank_cfg += pattern
+
+ # Generate GPR Register config
+ print(".equ __iomux_gpr14_adr, 0x{:08X}".format(extract_dict["gpr_base_addr"] + 0x38))
+ print(".equ __iomux_gpr16_adr, 0x{:08X}".format(extract_dict["gpr_base_addr"] + 0x40))
+ print(".equ __iomux_gpr17_adr, 0x{:08X}".format(extract_dict["gpr_base_addr"] + 0x44))
+ print(".equ __iomux_gpr18_adr, 0x{:08X}".format(extract_dict["gpr_base_addr"] + 0x48))
+ print(
+ ".equ __iomux_gpr17_value, 0x{:08X} /* {}k OCRAM (512k OCRAM, {}k from FlexRAM), {}k DTCM, {}k ITCM */".format(
+ int(flexram_bank_cfg, 2) & 0xFFFF,
+ extract_dict["ocram_size"] // 1024,
+ flexram_configurable_ocram // 1024,
+ extract_dict["dtcm_size"] // 1024,
+ extract_dict["itcm_size"] // 1024,
+ )
+ )
+ print(".equ __iomux_gpr18_value, 0x{:08X}".format((int(flexram_bank_cfg, 2) >> 16) & 0xFFFF))
+
+
def main(defines_file, features_file, ld_script, controller):
dispatcher = {
"MIMXRT1011": (mimxrt_default_parser, mimxrt_default_gen_code),
@@ -177,6 +215,7 @@ def main(defines_file, features_file, ld_script, controller):
"MIMXRT1052": (mimxrt_default_parser, mimxrt_default_gen_code),
"MIMXRT1062": (mimxrt_default_parser, mimxrt_106x_gen_code),
"MIMXRT1064": (mimxrt_default_parser, mimxrt_106x_gen_code),
+ "MIMXRT1176": (mimxrt_default_parser, mimxrt_1176_gen_code),
}
extractor, code_generator = dispatcher[controller]
diff --git a/ports/mimxrt/boards/make-pins.py b/ports/mimxrt/boards/make-pins.py
index 441676adde62..9d11feb13ac9 100644
--- a/ports/mimxrt/boards/make-pins.py
+++ b/ports/mimxrt/boards/make-pins.py
@@ -21,6 +21,9 @@
r"IOMUXC_(?PGPIO_\d\d)_(?P\w+) (?P\w+), (?P\w+), (?P\w+), (?P\w+), (?P\w+)",
r"IOMUXC_(?PGPIO_AD_\d\d)_(?P\w+) (?P\w+), (?P\w+), (?P\w+), (?P\w+), (?P\w+)",
r"IOMUXC_(?PGPIO_SD_\d\d)_(?P\w+) (?P\w+), (?P\w+), (?P\w+), (?P\w+), (?P\w+)",
+ r"IOMUXC_(?PGPIO_EMC_B\d_\d\d)_(?P\w+) (?P\w+), (?P\w+), (?P\w+), (?P\w+), (?P\w+)",
+ r"IOMUXC_(?PGPIO_DISP_B\d_\d\d)_(?P\w+) (?P\w+), (?P\w+), (?P\w+), (?P\w+), (?P\w+)",
+ r"IOMUXC_(?PGPIO_LPSR_\d\d)_(?P\w+) (?P\w+), (?P\w+), (?P\w+), (?P\w+), (?P\w+)",
]
@@ -62,6 +65,7 @@ def is_board_pin(self):
def parse_adc(self, adc_str):
adc_regex = r"ADC(?P\d*)_IN(?P\d*)"
+ lpadc_regex = r"ADC(?P\d*)_CH(?P\d*)" # LPADC for MIMXRT11xx chips
matches = re.finditer(adc_regex, adc_str, re.MULTILINE)
for match in matches:
@@ -69,6 +73,16 @@ def parse_adc(self, adc_str):
AdcFunction(instance=match.group("instance"), channel=match.group("channel"))
)
+ matches = re.finditer(lpadc_regex, adc_str, re.MULTILINE)
+ for match in matches:
+ self.adc_fns.append(
+ AdcFunction(
+ peripheral="LPADC",
+ instance=match.group("instance"),
+ channel=match.group("channel"),
+ )
+ )
+
def parse_af(self, af_idx, af_strs_in):
pass
@@ -104,18 +118,16 @@ def print(self):
self.print_pin_af()
self.print_pin_adc()
- if self.adc_fns:
- print(
- "const machine_pin_obj_t pin_{0} = PIN({0}, {1}, {2}, pin_{0}_af, {3}, pin_{0}_adc);\n".format(
- self.name, self.gpio, int(self.pin), len(self.adc_fns)
- )
- )
- else:
- print(
- "const machine_pin_obj_t pin_{0} = PIN({0}, {1}, {2}, pin_{0}_af, {3}, NULL);\n".format(
- self.name, self.gpio, int(self.pin), len(self.adc_fns)
- )
+ print(
+ "const machine_pin_obj_t pin_{0} = {1}({0}, {2}, {3}, pin_{0}_af, {4}, {5});\n".format(
+ self.name,
+ "PIN_LPSR" if "LPSR" in self.name else "PIN",
+ self.gpio,
+ int(self.pin),
+ len(self.adc_fns),
+ "pin_{}_adc".format(self.name) if self.adc_fns else "NULL",
)
+ )
else:
raise ValueError("Pin '{}' has no alternative functions".format(self.name))
@@ -126,13 +138,14 @@ def print_header(self, hdr_file):
class AdcFunction(object):
"""Holds the information associated with a pins ADC function."""
- def __init__(self, instance, channel):
+ def __init__(self, instance, channel, peripheral="ADC"):
+ self.peripheral = peripheral
self.instance = instance
self.channel = channel
def print(self):
"""Prints the C representation of this AF."""
- print(f" PIN_ADC(ADC{self.instance}, {self.channel}),")
+ print(f" PIN_ADC({self.peripheral}{self.instance}, {self.channel}),")
class AlternateFunction(object):
@@ -190,11 +203,8 @@ def parse_board_file(self, filename):
if pin and row[0]: # Only add board pins that have a name
self.board_pins.append(NamedPin(row[0], pin.pad, pin.idx))
- def parse_af_file(self, filename, iomux_filename, pad_col, af_start_col):
- af_end_col = af_start_col + MAX_AF
-
+ def parse_af_file(self, filename, iomux_filename):
iomux_pin_config = dict()
-
with open(iomux_filename, "r") as ipt:
input_str = ipt.read()
for regex in regexes:
@@ -213,16 +223,23 @@ def parse_af_file(self, filename, iomux_filename, pad_col, af_start_col):
with open(filename, "r") as csvfile:
rows = csv.reader(csvfile)
header = next(rows)
+ # Extract indexes from header row
+ pad_col = header.index("Pad")
+ adc_col = header.index("ADC")
+ acmp_col = header.index("ACMP")
+ #
for idx, row in enumerate(rows):
pad = row[pad_col]
gpio, pin = row[6].split("_")
pin_number = pin.lstrip("IO")
-
pin = Pin(pad, gpio, pin_number, idx=idx)
+ if any(s in pad for s in ("SNVS", "WAKEUP")):
+ continue
+
# Parse alternate functions
af_idx = 0
- for af_idx, af in enumerate(row[af_start_col:af_end_col]):
+ for af_idx, af in enumerate(row[(pad_col + 1) : adc_col]):
if af and af_supported(af):
pin.add_af(
AlternateFunction(
@@ -235,7 +252,7 @@ def parse_af_file(self, filename, iomux_filename, pad_col, af_start_col):
)
)
- pin.parse_adc(row[ADC_COL])
+ pin.parse_adc(row[adc_col])
self.cpu_pins.append(pin)
@@ -363,7 +380,7 @@ def main():
if args.af_filename:
print("// --af {:s}".format(args.af_filename))
- pins.parse_af_file(args.af_filename, args.iomux_filename, 0, 1)
+ pins.parse_af_file(args.af_filename, args.iomux_filename)
if args.board_filename:
print("// --board {:s}".format(args.board_filename))
diff --git a/ports/mimxrt/boards/manifest.py b/ports/mimxrt/boards/manifest.py
index 2e1a1d63d4e7..e4e5a236a357 100644
--- a/ports/mimxrt/boards/manifest.py
+++ b/ports/mimxrt/boards/manifest.py
@@ -1,8 +1,5 @@
freeze("$(PORT_DIR)/modules")
-freeze("$(MPY_DIR)/drivers/onewire")
-freeze("$(MPY_DIR)/drivers/dht", "dht.py")
-include("$(MPY_DIR)/extmod/uasyncio/manifest.py")
-try:
- include("$(BOARD_DIR)/manifest.py")
-except FileNotFoundError:
- pass
+include("$(MPY_DIR)/extmod/uasyncio")
+require("onewire")
+require("ds18x20")
+require("dht")
diff --git a/ports/mimxrt/boards/mimxrt_prefix.c b/ports/mimxrt/boards/mimxrt_prefix.c
index 938efc810456..09c0aa109ebf 100644
--- a/ports/mimxrt/boards/mimxrt_prefix.c
+++ b/ports/mimxrt/boards/mimxrt_prefix.c
@@ -35,3 +35,17 @@
.adc_list = (_adc_list), \
} \
+#define PIN_LPSR(_name, _gpio, _pin, _af_list, _adc_list_len, _adc_list) \
+ { \
+ .base = { &machine_pin_type }, \
+ .name = MP_QSTR_##_name, \
+ .gpio = (_gpio), \
+ .pin = (uint32_t)(_pin), \
+ .muxRegister = (uint32_t)&(IOMUXC_LPSR->SW_MUX_CTL_PAD[kIOMUXC_LPSR_SW_MUX_CTL_PAD_##_name]), \
+ .configRegister = (uint32_t)&(IOMUXC_LPSR->SW_PAD_CTL_PAD[kIOMUXC_LPSR_SW_PAD_CTL_PAD_##_name]), \
+ .af_list_len = (uint8_t)(sizeof((_af_list)) / sizeof(machine_pin_af_obj_t)), \
+ .adc_list_len = (_adc_list_len), \
+ .af_list = (_af_list), \
+ .adc_list = (_adc_list), \
+ } \
+
diff --git a/ports/mimxrt/eth.c b/ports/mimxrt/eth.c
index 50e1cbb0fe82..d0df7610cc27 100644
--- a/ports/mimxrt/eth.c
+++ b/ports/mimxrt/eth.c
@@ -31,7 +31,7 @@
#include "py/mperrno.h"
#include "ticks.h"
-#if defined(MICROPY_HW_ETH_MDC)
+#if defined(IOMUX_TABLE_ENET)
#include "pin.h"
#include "shared/netutils/netutils.h"
@@ -43,7 +43,9 @@
#include "hal/phy/mdio/enet/fsl_enet_mdio.h"
#include "hal/phy/device/phyksz8081/fsl_phyksz8081.h"
#include "hal/phy/device/phydp83825/fsl_phydp83825.h"
+#include "hal/phy/device/phydp83848/fsl_phydp83848.h"
#include "hal/phy/device/phylan8720/fsl_phylan8720.h"
+#include "hal/phy/device/phyrtl8211f/fsl_phyrtl8211f.h"
#include "eth.h"
#include "lwip/etharp.h"
@@ -53,50 +55,9 @@
#include "ticks.h"
-// Configuration values
-enet_config_t enet_config;
-phy_config_t phyConfig = {0};
-
-// Prepare the buffer configuration.
-
#define ENET_RXBD_NUM (5)
#define ENET_TXBD_NUM (5)
-AT_NONCACHEABLE_SECTION_ALIGN(enet_rx_bd_struct_t g_rxBuffDescrip[ENET_RXBD_NUM], ENET_BUFF_ALIGNMENT);
-AT_NONCACHEABLE_SECTION_ALIGN(enet_tx_bd_struct_t g_txBuffDescrip[ENET_TXBD_NUM], ENET_BUFF_ALIGNMENT);
-SDK_ALIGN(uint8_t g_rxDataBuff[ENET_RXBD_NUM][SDK_SIZEALIGN(ENET_FRAME_MAX_FRAMELEN, ENET_BUFF_ALIGNMENT)],
- ENET_BUFF_ALIGNMENT);
-SDK_ALIGN(uint8_t g_txDataBuff[ENET_TXBD_NUM][SDK_SIZEALIGN(ENET_FRAME_MAX_FRAMELEN, ENET_BUFF_ALIGNMENT)],
- ENET_BUFF_ALIGNMENT);
-
-// ENET Handles & Buffers
-enet_handle_t g_handle;
-
-static mdio_handle_t mdioHandle = {.ops = &enet_ops};
-static phy_handle_t phyHandle = {.phyAddr = ENET_PHY_ADDRESS, .mdioHandle = &mdioHandle, .ops = &ENET_PHY_OPS};
-
-enet_buffer_config_t buffConfig[] = {{
- ENET_RXBD_NUM,
- ENET_TXBD_NUM,
- SDK_SIZEALIGN(ENET_FRAME_MAX_FRAMELEN, ENET_BUFF_ALIGNMENT),
- SDK_SIZEALIGN(ENET_FRAME_MAX_FRAMELEN, ENET_BUFF_ALIGNMENT),
- &g_rxBuffDescrip[0],
- &g_txBuffDescrip[0],
- &g_rxDataBuff[0][0],
- &g_txDataBuff[0][0],
- #if FSL_ENET_DRIVER_VERSION >= 0x020300
- 0,
- 0,
- NULL
- #endif
- }};
-
-static uint8_t hw_addr[6]; // The MAC address field
-eth_t eth_instance;
-
-#define PHY_INIT_TIMEOUT_MS (10000)
-#define PHY_AUTONEGO_TIMEOUT_US (5000000)
-
typedef struct _eth_t {
uint32_t trace_flags;
struct netif netif;
@@ -113,16 +74,108 @@ typedef struct _iomux_table_t {
uint32_t configValue;
} iomux_table_t;
+// ETH0 buffers and handles
+static AT_NONCACHEABLE_SECTION_ALIGN(enet_rx_bd_struct_t g_rxBuffDescrip[ENET_RXBD_NUM], ENET_BUFF_ALIGNMENT);
+static AT_NONCACHEABLE_SECTION_ALIGN(enet_tx_bd_struct_t g_txBuffDescrip[ENET_TXBD_NUM], ENET_BUFF_ALIGNMENT);
+static SDK_ALIGN(uint8_t g_rxDataBuff[ENET_RXBD_NUM][SDK_SIZEALIGN(ENET_FRAME_MAX_FRAMELEN, ENET_BUFF_ALIGNMENT)],
+ ENET_BUFF_ALIGNMENT);
+static SDK_ALIGN(uint8_t g_txDataBuff[ENET_TXBD_NUM][SDK_SIZEALIGN(ENET_FRAME_MAX_FRAMELEN, ENET_BUFF_ALIGNMENT)],
+ ENET_BUFF_ALIGNMENT);
+
+// ENET Handles & Buffers
+static enet_handle_t g_handle;
+static mdio_handle_t mdioHandle = {.ops = &enet_ops};
+static phy_handle_t phyHandle;
+eth_t eth_instance0;
+
+static enet_buffer_config_t buffConfig[] = {{
+ ENET_RXBD_NUM,
+ ENET_TXBD_NUM,
+ SDK_SIZEALIGN(ENET_FRAME_MAX_FRAMELEN, ENET_BUFF_ALIGNMENT),
+ SDK_SIZEALIGN(ENET_FRAME_MAX_FRAMELEN, ENET_BUFF_ALIGNMENT),
+ &g_rxBuffDescrip[0],
+ &g_txBuffDescrip[0],
+ &g_rxDataBuff[0][0],
+ &g_txDataBuff[0][0],
+ #if FSL_ENET_DRIVER_VERSION >= 0x020300
+ true,
+ true,
+ NULL,
+ #endif
+ }};
+
static const iomux_table_t iomux_table_enet[] = {
IOMUX_TABLE_ENET
};
-#define IOTE (iomux_table_enet[i])
+static uint8_t hw_addr[6]; // The MAC address field
+
+#if defined(ENET_DUAL_PORT)
+
+// ETH1 buffers and handles
+static AT_NONCACHEABLE_SECTION_ALIGN(enet_rx_bd_struct_t g_rxBuffDescrip_1[ENET_RXBD_NUM], ENET_BUFF_ALIGNMENT);
+static AT_NONCACHEABLE_SECTION_ALIGN(enet_tx_bd_struct_t g_txBuffDescrip_1[ENET_TXBD_NUM], ENET_BUFF_ALIGNMENT);
+static SDK_ALIGN(uint8_t g_rxDataBuff_1[ENET_RXBD_NUM][SDK_SIZEALIGN(ENET_FRAME_MAX_FRAMELEN, ENET_BUFF_ALIGNMENT)],
+ ENET_BUFF_ALIGNMENT);
+static SDK_ALIGN(uint8_t g_txDataBuff_1[ENET_TXBD_NUM][SDK_SIZEALIGN(ENET_FRAME_MAX_FRAMELEN, ENET_BUFF_ALIGNMENT)],
+ ENET_BUFF_ALIGNMENT);
+
+static enet_handle_t g_handle_1;
+static mdio_handle_t mdioHandle_1 = {.ops = &enet_ops};
+static phy_handle_t phyHandle_1;
+eth_t eth_instance1;
+
+static enet_buffer_config_t buffConfig_1[] = {{
+ ENET_RXBD_NUM,
+ ENET_TXBD_NUM,
+ SDK_SIZEALIGN(ENET_FRAME_MAX_FRAMELEN, ENET_BUFF_ALIGNMENT),
+ SDK_SIZEALIGN(ENET_FRAME_MAX_FRAMELEN, ENET_BUFF_ALIGNMENT),
+ &g_rxBuffDescrip_1[0],
+ &g_txBuffDescrip_1[0],
+ &g_rxDataBuff_1[0][0],
+ &g_txDataBuff_1[0][0],
+ #if FSL_ENET_DRIVER_VERSION >= 0x020300
+ true,
+ true,
+ NULL,
+ #endif
+ }};
+
+static const iomux_table_t iomux_table_enet_1[] = {
+ IOMUX_TABLE_ENET_1
+};
+
+static uint8_t hw_addr_1[6]; // The MAC address field
+
+#endif
+
+#if defined(ENET_DUAL_PORT)
+#if defined MIMXRT117x_SERIES
+#define ENET_1 ENET_1G
+#else
+#define ENET_1 ENET2
+#endif
+#else
+#define ENET_1 ENET
+#endif
+
+#define PHY_AUTONEGO_TIMEOUT_US (5000000)
+#define PHY_SETTLE_TIME_US (1000)
+// Settle time must be 500000 for the 1G interface
+#define PHY_SETTLE_TIME_US_1 (500000)
+#define ENET_RESET_LOW_TIME_US (10000)
+#define ENET_RESET_WAIT_TIME_US (30000)
+
+#define IOTE (iomux_table[i])
+
+#ifndef ENET_TX_CLK_OUTPUT
+#define ENET_TX_CLK_OUTPUT true
+#endif
-#define TRACE_ASYNC_EV (0x0001)
-#define TRACE_ETH_TX (0x0002)
-#define TRACE_ETH_RX (0x0004)
-#define TRACE_ETH_FULL (0x0008)
+#define TRACE_ASYNC_EV (0x0001)
+#define TRACE_ETH_TX (0x0002)
+#define TRACE_ETH_RX (0x0004)
+#define TRACE_ETH_FULL (0x0008)
STATIC void eth_trace(eth_t *self, size_t len, const void *data, unsigned int flags) {
if (((flags & NETUTILS_TRACE_IS_TX) && (self->trace_flags & TRACE_ETH_TX))
@@ -186,106 +239,146 @@ void eth_irq_handler(ENET_Type *base, enet_handle_t *handle,
}
}
-// eth_init: Set up GPIO and the transceiver
-void eth_init(eth_t *self, int mac_idx, const phy_operations_t *phy_ops, int phy_addr, bool phy_clock) {
-
- self->netif.num = mac_idx; // Set the interface number
+// Configure the ethernet clock
+STATIC uint32_t eth_clock_init(int eth_id, bool phy_clock) {
CLOCK_EnableClock(kCLOCK_Iomuxc);
- gpio_pin_config_t gpio_config = {kGPIO_DigitalOutput, 0, kGPIO_NoIntmode};
- (void)gpio_config;
+ #if defined MIMXRT117x_SERIES
- #ifdef ENET_RESET_PIN
- // Configure the Reset Pin
- const machine_pin_obj_t *reset_pin = &ENET_RESET_PIN;
- const machine_pin_af_obj_t *af_obj = pin_find_af(reset_pin, PIN_AF_MODE_ALT5);
+ clock_root_config_t rootCfg = {0};
- IOMUXC_SetPinMux(reset_pin->muxRegister, af_obj->af_mode, 0, 0, reset_pin->configRegister, 0U);
- IOMUXC_SetPinConfig(reset_pin->muxRegister, af_obj->af_mode, 0, 0, reset_pin->configRegister,
- pin_generate_config(PIN_PULL_DISABLED, PIN_MODE_OUT, PIN_DRIVE_5, reset_pin->configRegister));
- GPIO_PinInit(reset_pin->gpio, reset_pin->pin, &gpio_config);
- #endif
+ if (eth_id == MP_HAL_MAC_ETH0) {
+ // Generate 50M root clock.
+ rootCfg.mux = kCLOCK_ENET1_ClockRoot_MuxSysPll1Div2; // 500 MHz
+ rootCfg.div = 10;
+ CLOCK_SetRootClock(kCLOCK_Root_Enet1, &rootCfg);
+ // 50M ENET_REF_CLOCK output to PHY and ENET module.
+ // if required, handle phy_clock direction here
+ IOMUXC_GPR->GPR4 |= 0x3;
+ } else {
+ // Generate 125M root clock.
+ rootCfg.mux = kCLOCK_ENET1_ClockRoot_MuxSysPll1Div2; // 500 MHz
+ rootCfg.div = 4;
+ CLOCK_SetRootClock(kCLOCK_Root_Enet2, &rootCfg);
+ IOMUXC_GPR->GPR5 |= IOMUXC_GPR_GPR5_ENET1G_RGMII_EN_MASK; /* bit1:iomuxc_gpr_enet_clk_dir
+ bit0:GPR_ENET_TX_CLK_SEL(internal or OSC) */
+ }
+ return CLOCK_GetRootClockFreq(kCLOCK_Root_Bus);
- #ifdef ENET_INT_PIN
- // Configure the Int Pin
- const machine_pin_obj_t *int_pin = &ENET_INT_PIN;
- af_obj = pin_find_af(int_pin, PIN_AF_MODE_ALT5);
+ #else
+
+ const clock_enet_pll_config_t config = {
+ .enableClkOutput = phy_clock, .enableClkOutput25M = false, .loopDivider = 1
+ };
+ CLOCK_InitEnetPll(&config);
+
+ IOMUXC_EnableMode(IOMUXC_GPR, kIOMUXC_GPR_ENET1RefClkMode, false); // Drive ENET_REF_CLK from PAD
+ IOMUXC_EnableMode(IOMUXC_GPR, kIOMUXC_GPR_ENET1TxClkOutputDir, phy_clock); // Enable output driver
+
+ return CLOCK_GetFreq(kCLOCK_IpgClk);
- IOMUXC_SetPinMux(int_pin->muxRegister, af_obj->af_mode, 0, 0, int_pin->configRegister, 0U);
- IOMUXC_SetPinConfig(int_pin->muxRegister, af_obj->af_mode, 0, 0, int_pin->configRegister,
- pin_generate_config(PIN_PULL_UP_47K, PIN_MODE_IN, PIN_DRIVE_5, int_pin->configRegister));
- GPIO_PinInit(int_pin->gpio, int_pin->pin, &gpio_config);
#endif
+}
+
+// eth_gpio_init: Configure the GPIO pins
+STATIC void eth_gpio_init(const iomux_table_t iomux_table[], size_t iomux_table_size,
+ const machine_pin_obj_t *reset_pin, const machine_pin_obj_t *int_pin) {
+
+ gpio_pin_config_t gpio_config = {kGPIO_DigitalOutput, 1, kGPIO_NoIntmode};
+ (void)gpio_config;
+ const machine_pin_af_obj_t *af_obj;
+
+ if (reset_pin != NULL) {
+ // Configure the Reset Pin
+ af_obj = pin_find_af(reset_pin, PIN_AF_MODE_ALT5);
+
+ IOMUXC_SetPinMux(reset_pin->muxRegister, af_obj->af_mode, 0, 0, reset_pin->configRegister, 0U);
+ IOMUXC_SetPinConfig(reset_pin->muxRegister, af_obj->af_mode, 0, 0, reset_pin->configRegister,
+ pin_generate_config(PIN_PULL_DISABLED, PIN_MODE_OUT, PIN_DRIVE_5, reset_pin->configRegister));
+ GPIO_PinInit(reset_pin->gpio, reset_pin->pin, &gpio_config);
+ }
+
+ if (int_pin != NULL) {
+ // Configure the Int Pin
+ af_obj = pin_find_af(int_pin, PIN_AF_MODE_ALT5);
+
+ IOMUXC_SetPinMux(int_pin->muxRegister, af_obj->af_mode, 0, 0, int_pin->configRegister, 0U);
+ IOMUXC_SetPinConfig(int_pin->muxRegister, af_obj->af_mode, 0, 0, int_pin->configRegister,
+ pin_generate_config(PIN_PULL_UP_47K, PIN_MODE_IN, PIN_DRIVE_5, int_pin->configRegister));
+ GPIO_PinInit(int_pin->gpio, int_pin->pin, &gpio_config);
+ }
// Configure the Transceiver Pins, Settings except for CLK:
// Slew Rate Field: Fast Slew Rate, Drive Strength, R0/5, Speed max(200MHz)
// Open Drain Disabled, Pull Enabled, Pull 100K Ohm Pull Up
// Hysteresis Disabled
-
- for (int i = 0; i < ARRAY_SIZE(iomux_table_enet); i++) {
+ for (int i = 0; i < iomux_table_size; i++) {
IOMUXC_SetPinMux(IOTE.muxRegister, IOTE.muxMode, IOTE.inputRegister, IOTE.inputDaisy, IOTE.configRegister, IOTE.inputOnfield);
IOMUXC_SetPinConfig(IOTE.muxRegister, IOTE.muxMode, IOTE.inputRegister, IOTE.inputDaisy, IOTE.configRegister, IOTE.configValue);
}
- const clock_enet_pll_config_t config = {
- .enableClkOutput = phy_clock, .enableClkOutput25M = false, .loopDivider = 1
- };
- CLOCK_InitEnetPll(&config);
-
- IOMUXC_EnableMode(IOMUXC_GPR, kIOMUXC_GPR_ENET1RefClkMode, false); // Do not use the 25 MHz MII clock
- IOMUXC_EnableMode(IOMUXC_GPR, kIOMUXC_GPR_ENET1TxClkOutputDir, phy_clock); // Set the clock pad direction
-
- // Reset transceiver
- // pull up the ENET_INT before RESET.
- #ifdef ENET_INT_PIN
- GPIO_WritePinOutput(int_pin->gpio, int_pin->pin, 1);
- #endif
-
- #ifdef ENET_RESET_PIN
- GPIO_WritePinOutput(reset_pin->gpio, reset_pin->pin, 0);
- mp_hal_delay_us(1000);
- GPIO_WritePinOutput(reset_pin->gpio, reset_pin->pin, 1);
- mp_hal_delay_us(1000);
- #endif
+ // Reset the transceiver
+ if (reset_pin != NULL) {
+ GPIO_PinWrite(reset_pin->gpio, reset_pin->pin, 0);
+ mp_hal_delay_us(ENET_RESET_LOW_TIME_US);
+ GPIO_PinWrite(reset_pin->gpio, reset_pin->pin, 1);
+ mp_hal_delay_us(ENET_RESET_WAIT_TIME_US);
+ }
+}
- mp_hal_get_mac(0, hw_addr);
+// eth_phy_init: Initilaize the PHY interface
+STATIC void eth_phy_init(phy_handle_t *phyHandle, phy_config_t *phy_config,
+ phy_speed_t *speed, phy_duplex_t *duplex, uint32_t phy_settle_time) {
- phyHandle.ops = phy_ops;
- phyConfig.phyAddr = phy_addr;
- phyConfig.autoNeg = true;
- mdioHandle.resource.base = ENET;
- mdioHandle.resource.csrClock_Hz = CLOCK_GetFreq(kCLOCK_IpgClk);
-
- // Init the PHY interface & negotiate the speed
bool link = false;
bool autonego = false;
- phy_speed_t speed = kENET_MiiSpeed100M;
- phy_duplex_t duplex = kENET_MiiFullDuplex;
+ phy_config->autoNeg = true;
-
- status_t status = PHY_Init(&phyHandle, &phyConfig);
+ status_t status = PHY_Init(phyHandle, phy_config);
if (status == kStatus_Success) {
- if (phyConfig.autoNeg) {
- uint64_t t = ticks_us64() + PHY_AUTONEGO_TIMEOUT_US;
- // Wait for auto-negotiation success and link up
- do {
- PHY_GetAutoNegotiationStatus(&phyHandle, &autonego);
- PHY_GetLinkStatus(&phyHandle, &link);
- if (autonego && link) {
- break;
- }
- } while (ticks_us64() < t);
- if (!autonego) {
- mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("PHY Auto-negotiation failed."));
+ uint64_t t = ticks_us64() + PHY_AUTONEGO_TIMEOUT_US;
+ // Wait for auto-negotiation success and link up
+ do {
+ PHY_GetAutoNegotiationStatus(phyHandle, &autonego);
+ PHY_GetLinkStatus(phyHandle, &link);
+ if (autonego && link) {
+ break;
}
- PHY_GetLinkSpeedDuplex(&phyHandle, &speed, &duplex);
- } else {
- PHY_SetLinkSpeedDuplex(&phyHandle, speed, duplex);
+ } while (ticks_us64() < t);
+ if (!autonego) {
+ mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("PHY Auto-negotiation failed."));
}
+ PHY_GetLinkSpeedDuplex(phyHandle, speed, duplex);
} else {
mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("PHY Init failed."));
}
+ mp_hal_delay_us(phy_settle_time);
+}
+
+// eth_init: Set up GPIO and the transceiver
+void eth_init_0(eth_t *self, int eth_id, const phy_operations_t *phy_ops, int phy_addr, bool phy_clock) {
+ // Configuration values
+ enet_config_t enet_config;
+
+ phy_config_t phy_config = {0};
+
+ uint32_t source_clock = eth_clock_init(eth_id, phy_clock);
+
+ eth_gpio_init(iomux_table_enet, ARRAY_SIZE(iomux_table_enet), ENET_RESET_PIN, ENET_INT_PIN);
+
+ mp_hal_get_mac(0, hw_addr);
+
+ // Init the PHY interface & negotiate the speed
+ phyHandle.ops = phy_ops;
+ phy_config.phyAddr = phy_addr;
+ phyHandle.mdioHandle = &mdioHandle;
+ mdioHandle.resource.base = ENET;
+ mdioHandle.resource.csrClock_Hz = source_clock;
+
+ phy_speed_t speed = kENET_MiiSpeed100M;
+ phy_duplex_t duplex = kENET_MiiFullDuplex;
+ eth_phy_init(&phyHandle, &phy_config, &speed, &duplex, PHY_SETTLE_TIME_US);
ENET_Reset(ENET);
ENET_GetDefaultConfig(&enet_config);
@@ -297,14 +390,70 @@ void eth_init(eth_t *self, int mac_idx, const phy_operations_t *phy_ops, int phy
// Set interrupt
enet_config.interrupt |= ENET_TX_INTERRUPT | ENET_RX_INTERRUPT;
- ENET_Init(ENET, &g_handle, &enet_config, &buffConfig[0], hw_addr, CLOCK_GetFreq(kCLOCK_IpgClk));
+ ENET_Init(ENET, &g_handle, &enet_config, &buffConfig[0], hw_addr, source_clock);
ENET_SetCallback(&g_handle, eth_irq_handler, (void *)self);
NVIC_SetPriority(ENET_IRQn, IRQ_PRI_PENDSV);
ENET_EnableInterrupts(ENET, ENET_RX_INTERRUPT);
ENET_ClearInterruptStatus(ENET, ENET_TX_INTERRUPT | ENET_RX_INTERRUPT | ENET_ERR_INTERRUPT);
+ NVIC_SetPriority(ENET_IRQn, IRQ_PRI_PENDSV);
+ ENET_EnableInterrupts(ENET, ENET_RX_INTERRUPT);
ENET_ActiveRead(ENET);
}
+#if defined(ENET_DUAL_PORT)
+
+// eth_init: Set up GPIO and the transceiver
+void eth_init_1(eth_t *self, int eth_id, const phy_operations_t *phy_ops, int phy_addr, bool phy_clock) {
+ // Configuration values
+ enet_config_t enet_config;
+
+ phy_config_t phy_config = {0};
+
+ uint32_t source_clock = eth_clock_init(eth_id, phy_clock);
+
+ eth_gpio_init(iomux_table_enet_1, ARRAY_SIZE(iomux_table_enet_1), ENET_1_RESET_PIN, ENET_1_INT_PIN);
+
+ #if defined MIMXRT117x_SERIES
+ NVIC_SetPriority(ENET_1G_MAC0_Tx_Rx_1_IRQn, IRQ_PRI_PENDSV);
+ NVIC_SetPriority(ENET_1G_MAC0_Tx_Rx_2_IRQn, IRQ_PRI_PENDSV);
+ NVIC_SetPriority(ENET_1G_IRQn, IRQ_PRI_PENDSV);
+ EnableIRQ(ENET_1G_MAC0_Tx_Rx_1_IRQn);
+ EnableIRQ(ENET_1G_MAC0_Tx_Rx_2_IRQn);
+ phy_speed_t speed = kENET_MiiSpeed1000M;
+ #else
+ NVIC_SetPriority(ENET2_IRQn, IRQ_PRI_PENDSV);
+ phy_speed_t speed = kENET_MiiSpeed100M;
+ #endif
+
+ mp_hal_get_mac(1, hw_addr_1);
+
+ // Init the PHY interface & negotiate the speed
+ phyHandle_1.ops = phy_ops;
+ phy_config.phyAddr = phy_addr;
+ phyHandle_1.mdioHandle = &mdioHandle_1;
+ mdioHandle_1.resource.base = ENET_1;
+ mdioHandle_1.resource.csrClock_Hz = source_clock;
+
+ phy_duplex_t duplex = kENET_MiiFullDuplex;
+ eth_phy_init(&phyHandle_1, &phy_config, &speed, &duplex, PHY_SETTLE_TIME_US_1);
+
+ ENET_Reset(ENET_1);
+ ENET_GetDefaultConfig(&enet_config);
+ enet_config.miiSpeed = (enet_mii_speed_t)speed;
+ enet_config.miiDuplex = (enet_mii_duplex_t)duplex;
+ // Enable checksum generation by the ENET controller
+ enet_config.txAccelerConfig = kENET_TxAccelIpCheckEnabled | kENET_TxAccelProtoCheckEnabled;
+ // Set interrupt
+ enet_config.interrupt = ENET_TX_INTERRUPT | ENET_RX_INTERRUPT;
+
+ ENET_Init(ENET_1, &g_handle_1, &enet_config, &buffConfig_1[0], hw_addr_1, source_clock);
+ ENET_SetCallback(&g_handle_1, eth_irq_handler, (void *)self);
+ ENET_ClearInterruptStatus(ENET_1, ENET_TX_INTERRUPT | ENET_RX_INTERRUPT | ENET_ERR_INTERRUPT);
+ ENET_EnableInterrupts(ENET_1, ENET_RX_INTERRUPT);
+ ENET_ActiveRead(ENET_1);
+}
+
+#endif
// Initialize the phy interface
STATIC int eth_mac_init(eth_t *self) {
return 0;
@@ -312,6 +461,8 @@ STATIC int eth_mac_init(eth_t *self) {
// Deinit the interface
STATIC void eth_mac_deinit(eth_t *self) {
+ // Just as a reminder: Calling ENET_Deinit() twice causes the board to stall
+ // with a bus error. Reason unclear. So don't do that for now (or ever).
}
void eth_set_trace(eth_t *self, uint32_t value) {
@@ -332,7 +483,7 @@ STATIC err_t eth_send_frame_blocking(ENET_Type *base, enet_handle_t *handle, uin
if (status != kStatus_ENET_TxFrameBusy) {
break;
}
- ticks_delay_us64(100);
+ ticks_delay_us64(base == ENET ? 100 : 20);
}
return status;
}
@@ -340,12 +491,20 @@ STATIC err_t eth_send_frame_blocking(ENET_Type *base, enet_handle_t *handle, uin
STATIC err_t eth_netif_output(struct netif *netif, struct pbuf *p) {
// This function should always be called from a context where PendSV-level IRQs are disabled
status_t status;
+ ENET_Type *enet = ENET;
+ enet_handle_t *handle = &g_handle;
+
+ #if defined ENET_DUAL_PORT
+ if (netif->state == ð_instance1) {
+ enet = ENET_1;
+ handle = &g_handle_1;
+ }
+ #endif
- LINK_STATS_INC(link.xmit);
eth_trace(netif->state, (size_t)-1, p, NETUTILS_TRACE_IS_TX | NETUTILS_TRACE_NEWLINE);
if (p->next == NULL) {
- status = eth_send_frame_blocking(ENET, &g_handle, p->payload, p->len);
+ status = eth_send_frame_blocking(enet, handle, p->payload, p->len);
} else {
// frame consists of several parts. Copy them together and send them
size_t length = 0;
@@ -356,7 +515,7 @@ STATIC err_t eth_netif_output(struct netif *netif, struct pbuf *p) {
length += p->len;
p = p->next;
}
- status = eth_send_frame_blocking(ENET, &g_handle, tx_frame, length);
+ status = eth_send_frame_blocking(enet, handle, tx_frame, length);
}
return status == kStatus_Success ? ERR_OK : ERR_BUF;
}
@@ -378,22 +537,29 @@ STATIC err_t eth_netif_init(struct netif *netif) {
}
STATIC void eth_lwip_init(eth_t *self) {
+ struct netif *n = &self->netif;
ip_addr_t ipconfig[4];
- IP4_ADDR(&ipconfig[0], 192, 168, 0, 2);
+
+ self->netif.hwaddr_len = 6;
+ if (self == ð_instance0) {
+ memcpy(self->netif.hwaddr, hw_addr, 6);
+ IP4_ADDR(&ipconfig[0], 192, 168, 0, 2);
+ #if defined ENET_DUAL_PORT
+ } else {
+ memcpy(self->netif.hwaddr, hw_addr_1, 6);
+ IP4_ADDR(&ipconfig[0], 192, 168, 0, 3);
+ #endif
+ }
IP4_ADDR(&ipconfig[1], 255, 255, 255, 0);
IP4_ADDR(&ipconfig[2], 192, 168, 0, 1);
IP4_ADDR(&ipconfig[3], 8, 8, 8, 8);
- self->netif.hwaddr_len = 6;
- memcpy(self->netif.hwaddr, hw_addr, 6);
-
MICROPY_PY_LWIP_ENTER
- struct netif *n = &self->netif;
n->name[0] = 'e';
- n->name[1] = '0';
+ n->name[1] = (self == ð_instance0 ? '0' : '1');
netif_add(n, &ipconfig[0], &ipconfig[1], &ipconfig[2], self, eth_netif_init, ethernet_input);
- netif_set_hostname(n, "MPY");
+ netif_set_hostname(n, mod_network_hostname);
netif_set_default(n);
netif_set_up(n);
@@ -433,7 +599,11 @@ int eth_link_status(eth_t *self) {
}
} else {
bool link;
+ #if defined ENET_DUAL_PORT
+ PHY_GetLinkStatus(self == ð_instance0 ? &phyHandle : &phyHandle_1, &link);
+ #else
PHY_GetLinkStatus(&phyHandle, &link);
+ #endif
if (link) {
return 1; // link up
} else {
@@ -463,6 +633,10 @@ int eth_stop(eth_t *self) {
}
void eth_low_power_mode(eth_t *self, bool enable) {
+ #if defined ENET_DUAL_PORT
+ ENET_EnableSleepMode(self == ð_instance0 ? ENET : ENET_1, enable);
+ #else
ENET_EnableSleepMode(ENET, enable);
+ #endif
}
-#endif // defined(MICROPY_HW_ETH_MDC)
+#endif // defined(IOMUX_TABLE_ENET)
diff --git a/ports/mimxrt/eth.h b/ports/mimxrt/eth.h
index b225d0049248..afb5d5edf375 100644
--- a/ports/mimxrt/eth.h
+++ b/ports/mimxrt/eth.h
@@ -28,9 +28,14 @@
#define MICROPY_INCLUDED_MIMXRT_ETH_H
typedef struct _eth_t eth_t;
-extern eth_t eth_instance;
+extern eth_t eth_instance0;
+extern eth_t eth_instance1;
+void eth_init_0(eth_t *self, int mac_idx, const phy_operations_t *phy_ops, int phy_addr, bool phy_clock);
+
+#if defined(ENET_DUAL_PORT)
+void eth_init_1(eth_t *self, int mac_idx, const phy_operations_t *phy_ops, int phy_addr, bool phy_clock);
+#endif
-void eth_init(eth_t *self, int mac_idx, const phy_operations_t *phy_ops, int phy_addr, bool phy_clock);
void eth_set_trace(eth_t *self, uint32_t value);
struct netif *eth_netif(eth_t *self);
int eth_link_status(eth_t *self);
@@ -43,6 +48,7 @@ enum {
PHY_DP83825,
PHY_DP83848,
PHY_LAN8720,
+ PHY_RTL8211F,
};
enum {
diff --git a/ports/mimxrt/hal/flexspi_flash_config.h b/ports/mimxrt/hal/flexspi_flash_config.h
index 3c21eb609a77..80526880be0b 100644
--- a/ports/mimxrt/hal/flexspi_flash_config.h
+++ b/ports/mimxrt/hal/flexspi_flash_config.h
@@ -18,7 +18,7 @@
#define FSL_XIP_BOARD_DRIVER_VERSION (MAKE_VERSION(2, 0, 0))
/*@}*/
-/* FLEXSPI memory config block related defintions */
+/* FLEXSPI memory config block related definitions */
#define FLEXSPI_CFG_BLK_TAG (0x42464346UL) // ascii "FCFB" Big Endian
#define FLEXSPI_CFG_BLK_VERSION (0x56010400UL) // V1.4.0
#define FLEXSPI_CFG_BLK_SIZE (512)
@@ -26,7 +26,7 @@
/* FLEXSPI Feature related definitions */
#define FLEXSPI_FEATURE_HAS_PARALLEL_MODE 1
-/* Lookup table related defintions */
+/* Lookup table related definitions */
#define CMD_INDEX_READ 0
#define CMD_INDEX_READSTATUS 1
#define CMD_INDEX_WRITEENABLE 2
diff --git a/ports/mimxrt/hal/flexspi_hyper_flash.c b/ports/mimxrt/hal/flexspi_hyper_flash.c
index c7b41658a498..a9f17f2d1c19 100644
--- a/ports/mimxrt/hal/flexspi_hyper_flash.c
+++ b/ports/mimxrt/hal/flexspi_hyper_flash.c
@@ -51,11 +51,11 @@ __attribute__((always_inline)) static inline void clock_disable_clock(clock_ip_n
static void SetFlexSPIDiv(uint32_t div) __attribute__((section(".ram_functions")));
static void SetFlexSPIDiv(uint32_t div) {
- FLEXSPI_Enable(FLEXSPI, false);
+ FLEXSPI_Enable(BOARD_FLEX_SPI, false);
clock_disable_clock(kCLOCK_FlexSpi);
clock_set_div(kCLOCK_FlexspiDiv, div); /* flexspi clock 332M, DDR mode, internal clock 166M. */
clock_enable_clock(kCLOCK_FlexSpi);
- FLEXSPI_Enable(FLEXSPI, true);
+ FLEXSPI_Enable(BOARD_FLEX_SPI, true);
}
status_t flexspi_nor_hyperbus_read(FLEXSPI_Type *base, uint32_t addr, uint32_t *buffer, uint32_t bytes) __attribute__((section(".ram_functions")));
diff --git a/ports/mimxrt/hal/flexspi_hyper_flash.h b/ports/mimxrt/hal/flexspi_hyper_flash.h
index dbd028fd6f71..3c016bc78e33 100644
--- a/ports/mimxrt/hal/flexspi_hyper_flash.h
+++ b/ports/mimxrt/hal/flexspi_hyper_flash.h
@@ -26,14 +26,27 @@
#ifndef MICROPY_INCLUDED_MIMXRT_HAL_FLEXSPI_HYPER_FLASH_H
#define MICROPY_INCLUDED_MIMXRT_HAL_FLEXSPI_HYPER_FLASH_H
-#include "fsl_flexspi.h"
#include "mpconfigboard.h"
-#include BOARD_FLASH_CONFIG_HEADER_H
+#include "flexspi_flash_config.h"
+#include "fsl_flexspi.h"
+// #include BOARD_FLASH_CONFIG_HEADER_H
+
+#if defined MICROPY_HW_FLASH_INTERNAL
+#define BOARD_FLEX_SPI FLEXSPI2
+#define BOARD_FLEX_SPI_ADDR_BASE FlexSPI2_AMBA_BASE
+#elif defined MIMXRT117x_SERIES
+#define BOARD_FLEX_SPI FLEXSPI1
+#define BOARD_FLEX_SPI_ADDR_BASE FlexSPI1_AMBA_BASE
+#else
+#define BOARD_FLEX_SPI FLEXSPI
+#define BOARD_FLEX_SPI_ADDR_BASE FlexSPI_AMBA_BASE
+#endif
// Defined in boards flash_config.c
extern flexspi_nor_config_t qspiflash_config;
status_t flexspi_nor_hyperflash_cfi(FLEXSPI_Type *base);
+void flexspi_hyper_flash_init(void);
void flexspi_nor_update_lut(void);
status_t flexspi_nor_flash_erase_sector(FLEXSPI_Type *base, uint32_t address);
status_t flexspi_nor_flash_page_program(FLEXSPI_Type *base, uint32_t address, const uint32_t *src, uint32_t size);
diff --git a/ports/mimxrt/hal/flexspi_nor_flash.c b/ports/mimxrt/hal/flexspi_nor_flash.c
index 8c04150d1273..48792ec487eb 100644
--- a/ports/mimxrt/hal/flexspi_nor_flash.c
+++ b/ports/mimxrt/hal/flexspi_nor_flash.c
@@ -193,7 +193,7 @@ status_t flexspi_nor_flash_page_program(FLEXSPI_Type *base, uint32_t dstAddr, co
status = flexspi_nor_wait_bus_busy(base);
- flexspi_nor_reset(FLEXSPI);
+ flexspi_nor_reset(BOARD_FLEX_SPI);
return status;
}
diff --git a/ports/mimxrt/hal/flexspi_nor_flash.h b/ports/mimxrt/hal/flexspi_nor_flash.h
index f8c31488a988..edc81e37f129 100644
--- a/ports/mimxrt/hal/flexspi_nor_flash.h
+++ b/ports/mimxrt/hal/flexspi_nor_flash.h
@@ -30,33 +30,24 @@
#include "mpconfigboard.h"
#include BOARD_FLASH_CONFIG_HEADER_H
+#if defined MICROPY_HW_FLASH_INTERNAL
+#define BOARD_FLEX_SPI FLEXSPI2
+#define BOARD_FLEX_SPI_ADDR_BASE FlexSPI2_AMBA_BASE
+#elif defined MIMXRT117x_SERIES
+#define BOARD_FLEX_SPI FLEXSPI1
+#define BOARD_FLEX_SPI_ADDR_BASE FlexSPI1_AMBA_BASE
+#else
+#define BOARD_FLEX_SPI FLEXSPI
+#define BOARD_FLEX_SPI_ADDR_BASE FlexSPI_AMBA_BASE
+#endif
+
// Defined in boards flash_config.c
extern flexspi_nor_config_t qspiflash_config;
status_t flexspi_nor_get_vendor_id(FLEXSPI_Type *base, uint8_t *vendorId);
+status_t flexspi_nor_init(void);
void flexspi_nor_update_lut(void);
status_t flexspi_nor_flash_erase_sector(FLEXSPI_Type *base, uint32_t address);
status_t flexspi_nor_flash_page_program(FLEXSPI_Type *base, uint32_t address, const uint32_t *src, uint32_t size);
-static inline uint32_t flexspi_get_frequency(void) {
- uint32_t div;
- uint32_t fre;
-
- /* Clock divider:
- 000 divided by 1
- 001 divided by 2
- 010 divided by 3
- 011 divided by 4
- 100 divided by 5
- 101 divided by 6
- 110 divided by 7
- 111 divided by 8
- */
- div = CLOCK_GetDiv(kCLOCK_FlexspiDiv);
- /* Get frequency */
- fre = CLOCK_GetFreq(kCLOCK_Usb1PllPfd0Clk) / (div + 0x01U);
-
- return fre;
-}
-
#endif // MICROPY_INCLUDED_MIMXRT_HAL_FLEXSPI_NOR_FLASH_H
diff --git a/ports/mimxrt/hal/fsl_flexspi_nor_boot.c b/ports/mimxrt/hal/fsl_flexspi_nor_boot.c
new file mode 100644
index 000000000000..5786f37e7ab8
--- /dev/null
+++ b/ports/mimxrt/hal/fsl_flexspi_nor_boot.c
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2017 NXP
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "fsl_flexspi_nor_boot.h"
+extern unsigned long _flashimagelen;
+extern unsigned long __etext;
+
+/* Component ID definition, used by tools. */
+#ifndef FSL_COMPONENT_ID
+#define FSL_COMPONENT_ID "platform.drivers.xip_device"
+#endif
+
+#if defined(XIP_BOOT_HEADER_ENABLE) && (XIP_BOOT_HEADER_ENABLE == 1)
+#if defined(__CC_ARM) || defined(__ARMCC_VERSION) || defined(__GNUC__)
+__attribute__((section(".boot_hdr.ivt")))
+#elif defined(__ICCARM__)
+#pragma location=".boot_hdr.ivt"
+#endif
+
+
+/*************************************
+ * IVT Data
+ *************************************/
+const ivt image_vector_table = {
+ IVT_HEADER, /* IVT Header */
+ IMAGE_ENTRY_ADDRESS, /* Image Entry Function */
+ IVT_RSVD, /* Reserved = 0 */
+ (uint32_t)DCD_ADDRESS, /* Address where DCD information is stored */
+ (uint32_t)BOOT_DATA_ADDRESS, /* Address where BOOT Data Structure is stored */
+ (uint32_t)&image_vector_table, /* Pointer to IVT Self (absolute address */
+ (uint32_t)CSF_ADDRESS, /* Address where CSF file is stored */
+ IVT_RSVD /* Reserved = 0 */
+};
+
+#if defined(__CC_ARM) || defined(__ARMCC_VERSION) || defined(__GNUC__)
+__attribute__((section(".boot_hdr.boot_data")))
+#elif defined(__ICCARM__)
+#pragma location=".boot_hdr.boot_data"
+#endif
+/*************************************
+ * Boot Data
+ *************************************/
+const BOOT_DATA_T boot_data = {
+ FLASH_BASE, /* boot start location */
+ (uint32_t)&_flashimagelen, /* Image size */
+ PLUGIN_FLAG, /* Plugin flag*/
+ 0xFFFFFFFF /* empty - extra data word */
+};
+#endif
diff --git a/ports/mimxrt/hal/fsl_flexspi_nor_boot.h b/ports/mimxrt/hal/fsl_flexspi_nor_boot.h
new file mode 100644
index 000000000000..fbb8a574f3ea
--- /dev/null
+++ b/ports/mimxrt/hal/fsl_flexspi_nor_boot.h
@@ -0,0 +1,114 @@
+/*
+ * Copyright 2017 NXP
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __FLEXSPI_NOR_BOOT_H__
+#define __FLEXSPI_NOR_BOOT_H__
+
+#include
+#include "board.h"
+
+/*! @name Driver version */
+/*@{*/
+/*! @brief XIP_DEVICE driver version 2.0.0. */
+#define FSL_XIP_DEVICE_DRIVER_VERSION (MAKE_VERSION(2, 0, 0))
+/*@}*/
+
+/*************************************
+ * IVT Data
+ *************************************/
+typedef struct _ivt_ {
+ /** @ref hdr with tag #HAB_TAG_IVT, length and HAB version fields
+ * (see @ref data)
+ */
+ uint32_t hdr;
+ /** Absolute address of the first instruction to execute from the
+ * image
+ */
+ uint32_t entry;
+ /** Reserved in this version of HAB: should be NULL. */
+ uint32_t reserved1;
+ /** Absolute address of the image DCD: may be NULL. */
+ uint32_t dcd;
+ /** Absolute address of the Boot Data: may be NULL, but not interpreted
+ * any further by HAB
+ */
+ uint32_t boot_data;
+ /** Absolute address of the IVT.*/
+ uint32_t self;
+ /** Absolute address of the image CSF.*/
+ uint32_t csf;
+ /** Reserved in this version of HAB: should be zero. */
+ uint32_t reserved2;
+} ivt;
+
+#define IVT_MAJOR_VERSION 0x4
+#define IVT_MAJOR_VERSION_SHIFT 0x4
+#define IVT_MAJOR_VERSION_MASK 0xF
+#define IVT_MINOR_VERSION 0x3
+#define IVT_MINOR_VERSION_SHIFT 0x0
+#define IVT_MINOR_VERSION_MASK 0xF
+
+#define IVT_VERSION(major, minor) \
+ ((((major) & IVT_MAJOR_VERSION_MASK) << IVT_MAJOR_VERSION_SHIFT) | \
+ (((minor) & IVT_MINOR_VERSION_MASK) << IVT_MINOR_VERSION_SHIFT))
+
+/* IVT header */
+#define IVT_TAG_HEADER 0xD1 /**< Image Vector Table */
+#define IVT_SIZE 0x2000
+#define IVT_PAR IVT_VERSION(IVT_MAJOR_VERSION, IVT_MINOR_VERSION)
+#define IVT_HEADER (IVT_TAG_HEADER | (IVT_SIZE << 8) | (IVT_PAR << 24))
+
+/* Set resume entry */
+#if defined(__CC_ARM) || defined(__ARMCC_VERSION)
+extern uint32_t __Vectors[];
+extern uint32_t Image$$RW_m_config_text$$Base[];
+#define IMAGE_ENTRY_ADDRESS ((uint32_t)__Vectors)
+#define FLASH_BASE ((uint32_t)Image$$RW_m_config_text$$Base)
+#elif defined(__MCUXPRESSO)
+extern uint32_t __Vectors[];
+extern uint32_t __boot_hdr_start__[];
+#define IMAGE_ENTRY_ADDRESS ((uint32_t)__Vectors)
+#define FLASH_BASE ((uint32_t)__boot_hdr_start__)
+#elif defined(__ICCARM__)
+extern uint32_t __VECTOR_TABLE[];
+extern uint32_t m_boot_hdr_conf_start[];
+#define IMAGE_ENTRY_ADDRESS ((uint32_t)__VECTOR_TABLE)
+#define FLASH_BASE ((uint32_t)m_boot_hdr_conf_start)
+#elif defined(__GNUC__)
+extern uint32_t __VECTOR_TABLE[];
+extern uint32_t __FLASH_BASE[];
+#define IMAGE_ENTRY_ADDRESS ((uint32_t)__VECTOR_TABLE)
+#define FLASH_BASE ((uint32_t)__FLASH_BASE)
+#endif
+
+#define DCD_ADDRESS dcd_data
+#define BOOT_DATA_ADDRESS &boot_data
+#define CSF_ADDRESS 0
+#define IVT_RSVD (uint32_t)(0x00000000)
+
+/*************************************
+ * Boot Data
+ *************************************/
+typedef struct _boot_data_ {
+ uint32_t start; /* boot start location */
+ uint32_t size; /* size */
+ uint32_t plugin; /* plugin flag - 1 if downloaded application is plugin */
+ uint32_t placeholder; /* placehoder to make even 0x10 size */
+}BOOT_DATA_T;
+
+#if defined(BOARD_FLASH_SIZE)
+#define FLASH_SIZE BOARD_FLASH_SIZE
+#else
+#error "Please define macro BOARD_FLASH_SIZE"
+#endif
+#define PLUGIN_FLAG (uint32_t)0
+
+/* External Variables */
+const BOOT_DATA_T boot_data;
+extern const uint8_t dcd_data[];
+
+#endif /* __FLEXSPI_NOR_BOOT_H__ */
diff --git a/ports/mimxrt/hal/phy/device/phyrtl8211f/fsl_phyrtl8211f.c b/ports/mimxrt/hal/phy/device/phyrtl8211f/fsl_phyrtl8211f.c
new file mode 100644
index 000000000000..0c6cf82dae4a
--- /dev/null
+++ b/ports/mimxrt/hal/phy/device/phyrtl8211f/fsl_phyrtl8211f.c
@@ -0,0 +1,387 @@
+/*
+ * Copyright 2020 NXP
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "fsl_phyrtl8211f.h"
+
+/*******************************************************************************
+ * Definitions
+ ******************************************************************************/
+
+/*! @brief Defines the PHY RTL8211F vendor defined registers. */
+#define PHY_SPECIFIC_STATUS_REG 0x1AU /*!< The PHY specific status register. */
+#define PHY_PAGE_SELECT_REG 0x1FU /*!< The PHY page select register. */
+
+/*! @brief Defines the PHY RTL8211F ID number. */
+#define PHY_CONTROL_ID1 0x001CU /*!< The PHY ID1 . */
+
+/*! @brief Defines the mask flag in specific status register. */
+#define PHY_SSTATUS_LINKSTATUS_MASK 0x04U /*!< The PHY link status mask. */
+#define PHY_SSTATUS_LINKSPEED_MASK 0x30U /*!< The PHY link speed mask. */
+#define PHY_SSTATUS_LINKDUPLEX_MASK 0x08U /*!< The PHY link duplex mask. */
+#define PHY_SSTATUS_LINKSPEED_SHIFT 4U /*!< The link speed shift */
+
+/*! @brief Defines the PHY RTL8211F extra page and the registers in specified page. */
+#define PHY_PAGE_RGMII_TXRX_DELAY_ADDR 0xD08U /*!< The register page including RGMII TX/RX delay setting. */
+#define PHY_RGMII_TX_DELAY_REG 0x11U /*!< The RGMII TXC delay register. */
+#define PHY_RGMII_RX_DELAY_REG 0x15U /*!< The RGMII RXC delay register. */
+#define PHY_RGMII_TX_DELAY_MASK 0x100U /*!< The RGMII TXC delay mask. */
+#define PHY_RGMII_RX_DELAY_MASK 0x8U /*!< The RGMII RXC delay mask. */
+
+/*! @brief MDIO MMD Devices .*/
+#define PHY_MDIO_MMD_PCS 3U
+#define PHY_MDIO_MMD_AN 7U
+
+/*! @brief MDIO MMD Physical Coding layer device registers .*/
+#define PHY_MDIO_PCS_EEE_CAP 0x14U /* EEE capability */
+
+/*! @brief MDIO MMD AutoNegotiation device registers .*/
+#define PHY_MDIO_AN_EEE_ADV 0x3CU /* EEE advertisement */
+
+/*! @brief MDIO MMD EEE mask flags. (common for adv and cap) */
+#define PHY_MDIO_EEE_100TX 0x2U
+#define PHY_MDIO_EEE_1000T 0x4U
+
+/*! @brief Defines the timeout macro. */
+#define PHY_READID_TIMEOUT_COUNT 1000U
+
+/*******************************************************************************
+ * Prototypes
+ ******************************************************************************/
+
+static status_t PHY_RTL8211F_MMD_SetDevice(phy_handle_t *handle,
+ uint8_t device,
+ uint16_t addr,
+ phy_mmd_access_mode_t mode);
+static inline status_t PHY_RTL8211F_MMD_ReadData(phy_handle_t *handle, uint32_t *data);
+static inline status_t PHY_RTL8211F_MMD_WriteData(phy_handle_t *handle, uint32_t data);
+static status_t PHY_RTL8211F_MMD_Read(phy_handle_t *handle, uint8_t device, uint16_t addr, uint32_t *data);
+static status_t PHY_RTL8211F_MMD_Write(phy_handle_t *handle, uint8_t device, uint16_t addr, uint32_t data);
+
+/*******************************************************************************
+ * Variables
+ ******************************************************************************/
+
+const phy_operations_t phyrtl8211f_ops = {.phyInit = PHY_RTL8211F_Init,
+ .phyWrite = PHY_RTL8211F_Write,
+ .phyRead = PHY_RTL8211F_Read,
+ .getAutoNegoStatus = PHY_RTL8211F_GetAutoNegotiationStatus,
+ .getLinkStatus = PHY_RTL8211F_GetLinkStatus,
+ .getLinkSpeedDuplex = PHY_RTL8211F_GetLinkSpeedDuplex,
+ .setLinkSpeedDuplex = PHY_RTL8211F_SetLinkSpeedDuplex,
+ .enableLoopback = PHY_RTL8211F_EnableLoopback};
+
+/*******************************************************************************
+ * Code
+ ******************************************************************************/
+
+status_t PHY_RTL8211F_Init(phy_handle_t *handle, const phy_config_t *config) {
+ uint32_t counter = PHY_READID_TIMEOUT_COUNT;
+ status_t result;
+ uint32_t regValue = 0U;
+
+ /* Init MDIO interface. */
+ MDIO_Init(handle->mdioHandle);
+
+ /* Assign phy address. */
+ handle->phyAddr = config->phyAddr;
+
+ /* Check PHY ID. */
+ do
+ {
+ result = MDIO_Read(handle->mdioHandle, handle->phyAddr, PHY_ID1_REG, ®Value);
+ if (result != kStatus_Success) {
+ return result;
+ }
+ counter--;
+ } while ((regValue != PHY_CONTROL_ID1) && (counter != 0U));
+
+ if (counter == 0U) {
+ return kStatus_Fail;
+ }
+
+ /* Reset PHY. */
+ result = MDIO_Write(handle->mdioHandle, handle->phyAddr, PHY_BASICCONTROL_REG, PHY_BCTL_RESET_MASK);
+ if (result != kStatus_Success) {
+ return result;
+ }
+
+ /* The RGMII specifies output TXC/RXC and TXD/RXD without any clock skew. Need to add skew on clock line
+ to make sure the other side sample right data. This can also be done in PCB traces. */
+ result = MDIO_Write(handle->mdioHandle, handle->phyAddr, PHY_PAGE_SELECT_REG, PHY_PAGE_RGMII_TXRX_DELAY_ADDR);
+ if (result != kStatus_Success) {
+ return result;
+ }
+ /* Set Tx Delay. */
+ result = MDIO_Read(handle->mdioHandle, handle->phyAddr, PHY_RGMII_TX_DELAY_REG, ®Value);
+ if (result == kStatus_Success) {
+ regValue |= PHY_RGMII_TX_DELAY_MASK;
+ result = MDIO_Write(handle->mdioHandle, handle->phyAddr, PHY_RGMII_TX_DELAY_REG, regValue);
+ if (result != kStatus_Success) {
+ return result;
+ }
+ } else {
+ return result;
+ }
+ /* Set Rx Delay. */
+ result = MDIO_Read(handle->mdioHandle, handle->phyAddr, PHY_RGMII_RX_DELAY_REG, ®Value);
+ if (result == kStatus_Success) {
+ regValue |= PHY_RGMII_RX_DELAY_MASK;
+ result = MDIO_Write(handle->mdioHandle, handle->phyAddr, PHY_RGMII_RX_DELAY_REG, regValue);
+ if (result != kStatus_Success) {
+ return result;
+ }
+ } else {
+ return result;
+ }
+ /* Restore to default page 0 */
+ result = MDIO_Write(handle->mdioHandle, handle->phyAddr, PHY_PAGE_SELECT_REG, 0x0);
+ if (result != kStatus_Success) {
+ return result;
+ }
+
+ /* Energy Efficient Ethernet configuration */
+ if (config->enableEEE) {
+ /* Get capabilities */
+ result = PHY_RTL8211F_MMD_Read(handle, PHY_MDIO_MMD_PCS, PHY_MDIO_PCS_EEE_CAP, ®Value);
+ if (result == kStatus_Success) {
+ /* Enable EEE for 100TX and 1000T */
+ result = PHY_RTL8211F_MMD_Write(handle, PHY_MDIO_MMD_AN, PHY_MDIO_AN_EEE_ADV,
+ regValue & (PHY_MDIO_EEE_1000T | PHY_MDIO_EEE_100TX));
+ }
+ } else {
+ result = PHY_RTL8211F_MMD_Write(handle, PHY_MDIO_MMD_AN, PHY_MDIO_AN_EEE_ADV, 0);
+ }
+ if (result != kStatus_Success) {
+ return result;
+ }
+
+ if (config->autoNeg) {
+ /* Set the auto-negotiation. */
+ result =
+ MDIO_Write(handle->mdioHandle, handle->phyAddr, PHY_AUTONEG_ADVERTISE_REG,
+ PHY_100BASETX_FULLDUPLEX_MASK | PHY_100BASETX_HALFDUPLEX_MASK | PHY_10BASETX_FULLDUPLEX_MASK |
+ PHY_10BASETX_HALFDUPLEX_MASK | PHY_IEEE802_3_SELECTOR_MASK);
+ if (result == kStatus_Success) {
+ result = MDIO_Write(handle->mdioHandle, handle->phyAddr, PHY_1000BASET_CONTROL_REG,
+ PHY_1000BASET_FULLDUPLEX_MASK);
+ if (result == kStatus_Success) {
+ result = MDIO_Read(handle->mdioHandle, handle->phyAddr, PHY_BASICCONTROL_REG, ®Value);
+ if (result == kStatus_Success) {
+ result = MDIO_Write(handle->mdioHandle, handle->phyAddr, PHY_BASICCONTROL_REG,
+ (regValue | PHY_BCTL_AUTONEG_MASK | PHY_BCTL_RESTART_AUTONEG_MASK));
+ }
+ }
+ }
+ } else {
+ /* Disable isolate mode */
+ result = MDIO_Read(handle->mdioHandle, handle->phyAddr, PHY_BASICCONTROL_REG, ®Value);
+ if (result != kStatus_Success) {
+ return result;
+ }
+ regValue &= PHY_BCTL_ISOLATE_MASK;
+ result = MDIO_Write(handle->mdioHandle, handle->phyAddr, PHY_BASICCONTROL_REG, regValue);
+ if (result != kStatus_Success) {
+ return result;
+ }
+
+ /* Disable the auto-negotiation and set user-defined speed/duplex configuration. */
+ result = PHY_RTL8211F_SetLinkSpeedDuplex(handle, config->speed, config->duplex);
+ }
+ return result;
+}
+
+status_t PHY_RTL8211F_Write(phy_handle_t *handle, uint32_t phyReg, uint32_t data) {
+ return MDIO_Write(handle->mdioHandle, handle->phyAddr, phyReg, data);
+}
+
+status_t PHY_RTL8211F_Read(phy_handle_t *handle, uint32_t phyReg, uint32_t *dataPtr) {
+ return MDIO_Read(handle->mdioHandle, handle->phyAddr, phyReg, dataPtr);
+}
+
+status_t PHY_RTL8211F_GetAutoNegotiationStatus(phy_handle_t *handle, bool *status) {
+ assert(status);
+
+ status_t result;
+ uint32_t regValue;
+
+ *status = false;
+
+ /* Check auto negotiation complete. */
+ result = MDIO_Read(handle->mdioHandle, handle->phyAddr, PHY_BASICSTATUS_REG, ®Value);
+ if (result == kStatus_Success) {
+ if ((regValue & PHY_BSTATUS_AUTONEGCOMP_MASK) != 0U) {
+ *status = true;
+ }
+ }
+ return result;
+}
+
+status_t PHY_RTL8211F_GetLinkStatus(phy_handle_t *handle, bool *status) {
+ assert(status);
+
+ status_t result;
+ uint32_t regValue;
+
+ /* Read the basic status register. */
+ result = MDIO_Read(handle->mdioHandle, handle->phyAddr, PHY_SPECIFIC_STATUS_REG, ®Value);
+ if (result == kStatus_Success) {
+ if ((PHY_SSTATUS_LINKSTATUS_MASK & regValue) != 0U) {
+ /* Link up. */
+ *status = true;
+ } else {
+ /* Link down. */
+ *status = false;
+ }
+ }
+ return result;
+}
+
+status_t PHY_RTL8211F_GetLinkSpeedDuplex(phy_handle_t *handle, phy_speed_t *speed, phy_duplex_t *duplex) {
+ assert(!((speed == NULL) && (duplex == NULL)));
+
+ status_t result;
+ uint32_t regValue;
+
+ /* Read the status register. */
+ result = MDIO_Read(handle->mdioHandle, handle->phyAddr, PHY_SPECIFIC_STATUS_REG, ®Value);
+ if (result == kStatus_Success) {
+ if (speed != NULL) {
+ switch ((regValue & PHY_SSTATUS_LINKSPEED_MASK) >> PHY_SSTATUS_LINKSPEED_SHIFT)
+ {
+ case (uint32_t)kPHY_Speed10M:
+ *speed = kPHY_Speed10M;
+ break;
+ case (uint32_t)kPHY_Speed100M:
+ *speed = kPHY_Speed100M;
+ break;
+ case (uint32_t)kPHY_Speed1000M:
+ *speed = kPHY_Speed1000M;
+ break;
+ default:
+ *speed = kPHY_Speed10M;
+ break;
+ }
+ }
+
+ if (duplex != NULL) {
+ if ((regValue & PHY_SSTATUS_LINKDUPLEX_MASK) != 0U) {
+ *duplex = kPHY_FullDuplex;
+ } else {
+ *duplex = kPHY_HalfDuplex;
+ }
+ }
+ }
+ return result;
+}
+
+status_t PHY_RTL8211F_SetLinkSpeedDuplex(phy_handle_t *handle, phy_speed_t speed, phy_duplex_t duplex) {
+ status_t result;
+ uint32_t regValue;
+
+ result = MDIO_Read(handle->mdioHandle, handle->phyAddr, PHY_BASICCONTROL_REG, ®Value);
+ if (result == kStatus_Success) {
+ /* Disable the auto-negotiation and set according to user-defined configuration. */
+ regValue &= ~PHY_BCTL_AUTONEG_MASK;
+ if (speed == kPHY_Speed1000M) {
+ regValue &= PHY_BCTL_SPEED0_MASK;
+ regValue |= PHY_BCTL_SPEED1_MASK;
+ } else if (speed == kPHY_Speed100M) {
+ regValue |= PHY_BCTL_SPEED0_MASK;
+ regValue &= ~PHY_BCTL_SPEED1_MASK;
+ } else {
+ regValue &= ~PHY_BCTL_SPEED0_MASK;
+ regValue &= ~PHY_BCTL_SPEED1_MASK;
+ }
+ if (duplex == kPHY_FullDuplex) {
+ regValue |= PHY_BCTL_DUPLEX_MASK;
+ } else {
+ regValue &= ~PHY_BCTL_DUPLEX_MASK;
+ }
+ result = MDIO_Write(handle->mdioHandle, handle->phyAddr, PHY_BASICCONTROL_REG, regValue);
+ }
+ return result;
+}
+
+status_t PHY_RTL8211F_EnableLoopback(phy_handle_t *handle, phy_loop_t mode, phy_speed_t speed, bool enable) {
+ /* This PHY only supports local loopback. */
+ assert(mode == kPHY_LocalLoop);
+
+ status_t result;
+ uint32_t regValue;
+
+ /* Set the loop mode. */
+ if (enable) {
+ if (speed == kPHY_Speed1000M) {
+ regValue = PHY_BCTL_SPEED1_MASK | PHY_BCTL_DUPLEX_MASK | PHY_BCTL_LOOP_MASK;
+ } else if (speed == kPHY_Speed100M) {
+ regValue = PHY_BCTL_SPEED0_MASK | PHY_BCTL_DUPLEX_MASK | PHY_BCTL_LOOP_MASK;
+ } else {
+ regValue = PHY_BCTL_DUPLEX_MASK | PHY_BCTL_LOOP_MASK;
+ }
+ result = MDIO_Write(handle->mdioHandle, handle->phyAddr, PHY_BASICCONTROL_REG, regValue);
+ } else {
+ /* First read the current status in control register. */
+ result = MDIO_Read(handle->mdioHandle, handle->phyAddr, PHY_BASICCONTROL_REG, ®Value);
+ if (result == kStatus_Success) {
+ regValue &= ~PHY_BCTL_LOOP_MASK;
+ result = MDIO_Write(handle->mdioHandle, handle->phyAddr, PHY_BASICCONTROL_REG,
+ (regValue | PHY_BCTL_RESTART_AUTONEG_MASK));
+ }
+ }
+ return result;
+}
+
+static status_t PHY_RTL8211F_MMD_SetDevice(phy_handle_t *handle,
+ uint8_t device,
+ uint16_t addr,
+ phy_mmd_access_mode_t mode) {
+ status_t result = kStatus_Success;
+
+ /* Set Function mode of address access(b00) and device address. */
+ result = MDIO_Write(handle->mdioHandle, handle->phyAddr, PHY_MMD_ACCESS_CONTROL_REG, device);
+ if (result != kStatus_Success) {
+ return result;
+ }
+
+ /* Set register address. */
+ result = MDIO_Write(handle->mdioHandle, handle->phyAddr, PHY_MMD_ACCESS_DATA_REG, addr);
+ if (result != kStatus_Success) {
+ return result;
+ }
+
+ /* Set Function mode of data access(b01~11) and device address. */
+ result =
+ MDIO_Write(handle->mdioHandle, handle->phyAddr, PHY_MMD_ACCESS_CONTROL_REG, (uint32_t)mode | (uint32_t)device);
+ return result;
+}
+
+static inline status_t PHY_RTL8211F_MMD_ReadData(phy_handle_t *handle, uint32_t *data) {
+ return MDIO_Read(handle->mdioHandle, handle->phyAddr, PHY_MMD_ACCESS_DATA_REG, data);
+}
+
+static inline status_t PHY_RTL8211F_MMD_WriteData(phy_handle_t *handle, uint32_t data) {
+ return MDIO_Write(handle->mdioHandle, handle->phyAddr, PHY_MMD_ACCESS_DATA_REG, data);
+}
+
+static status_t PHY_RTL8211F_MMD_Read(phy_handle_t *handle, uint8_t device, uint16_t addr, uint32_t *data) {
+ status_t result = kStatus_Success;
+ result = PHY_RTL8211F_MMD_SetDevice(handle, device, addr, kPHY_MMDAccessNoPostIncrement);
+ if (result == kStatus_Success) {
+ result = PHY_RTL8211F_MMD_ReadData(handle, data);
+ }
+ return result;
+}
+
+static status_t PHY_RTL8211F_MMD_Write(phy_handle_t *handle, uint8_t device, uint16_t addr, uint32_t data) {
+ status_t result = kStatus_Success;
+
+ result = PHY_RTL8211F_MMD_SetDevice(handle, device, addr, kPHY_MMDAccessNoPostIncrement);
+ if (result == kStatus_Success) {
+ result = PHY_RTL8211F_MMD_WriteData(handle, data);
+ }
+ return result;
+}
diff --git a/ports/mimxrt/hal/phy/device/phyrtl8211f/fsl_phyrtl8211f.h b/ports/mimxrt/hal/phy/device/phyrtl8211f/fsl_phyrtl8211f.h
new file mode 100644
index 000000000000..225c249a6e3d
--- /dev/null
+++ b/ports/mimxrt/hal/phy/device/phyrtl8211f/fsl_phyrtl8211f.h
@@ -0,0 +1,163 @@
+/*
+ * Copyright 2020 NXP
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/*****************************************************************************
+ * PHY RTL8211F driver change log
+ *****************************************************************************/
+
+/*!
+@page driver_log Driver Change Log
+
+@section phyrtl8211 PHYRTL8211F
+ The current PHYRTL8211F driver version is 2.0.0.
+
+ - 2.0.0
+ - Initial version.
+*/
+
+#ifndef _FSL_PHYRTL8211F_H_
+#define _FSL_PHYRTL8211F_H_
+
+#include "fsl_phy.h"
+
+/*!
+ * @addtogroup phy_driver
+ * @{
+ */
+
+/*******************************************************************************
+ * Definitions
+ ******************************************************************************/
+
+/*! @brief PHY driver version */
+#define FSL_PHY_DRIVER_VERSION (MAKE_VERSION(2, 0, 0))
+
+/*! @brief PHY operations structure. */
+extern const phy_operations_t phyrtl8211f_ops;
+
+/*******************************************************************************
+ * API
+ ******************************************************************************/
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/*!
+ * @name PHY Driver
+ * @{
+ */
+
+/*!
+ * @brief Initializes PHY.
+ *
+ * This function initialize PHY.
+ *
+ * @param handle PHY device handle.
+ * @param config Pointer to structure of phy_config_t.
+ * @retval kStatus_Success PHY initialization succeeds
+ * @retval kStatus_Fail PHY initialization fails
+ * @retval kStatus_PHY_SMIVisitTimeout PHY SMI visit time out
+ */
+status_t PHY_RTL8211F_Init(phy_handle_t *handle, const phy_config_t *config);
+
+/*!
+ * @brief PHY Write function. This function writes data over the SMI to
+ * the specified PHY register. This function is called by all PHY interfaces.
+ *
+ * @param handle PHY device handle.
+ * @param phyReg The PHY register.
+ * @param data The data written to the PHY register.
+ * @retval kStatus_Success PHY write success
+ * @retval kStatus_PHY_SMIVisitTimeout PHY SMI visit time out
+ */
+status_t PHY_RTL8211F_Write(phy_handle_t *handle, uint32_t phyReg, uint32_t data);
+
+/*!
+ * @brief PHY Read function. This interface reads data over the SMI from the
+ * specified PHY register. This function is called by all PHY interfaces.
+ *
+ * @param handle PHY device handle.
+ * @param phyReg The PHY register.
+ * @param dataPtr The address to store the data read from the PHY register.
+ * @retval kStatus_Success PHY read success
+ * @retval kStatus_PHY_SMIVisitTimeout PHY SMI visit time out
+ */
+status_t PHY_RTL8211F_Read(phy_handle_t *handle, uint32_t phyReg, uint32_t *dataPtr);
+
+/*!
+ * @brief Gets the PHY auto-negotiation status.
+ *
+ * @param handle PHY device handle.
+ * @param status The auto-negotiation status of the PHY.
+ * - true the auto-negotiation is over.
+ * - false the auto-negotiation is on-going or not started.
+ * @retval kStatus_Success PHY gets status success
+ * @retval kStatus_PHY_SMIVisitTimeout PHY SMI visit time out
+ */
+status_t PHY_RTL8211F_GetAutoNegotiationStatus(phy_handle_t *handle, bool *status);
+
+/*!
+ * @brief Gets the PHY link status.
+ *
+ * @param handle PHY device handle.
+ * @param status The link up or down status of the PHY.
+ * - true the link is up.
+ * - false the link is down.
+ * @retval kStatus_Success PHY gets link status success
+ * @retval kStatus_PHY_SMIVisitTimeout PHY SMI visit time out
+ */
+status_t PHY_RTL8211F_GetLinkStatus(phy_handle_t *handle, bool *status);
+
+/*!
+ * @brief Gets the PHY link speed and duplex.
+ *
+ * @brief This function gets the speed and duplex mode of PHY. User can give one of speed
+ * and duplex address paramter and set the other as NULL if only wants to get one of them.
+ *
+ * @param handle PHY device handle.
+ * @param speed The address of PHY link speed.
+ * @param duplex The link duplex of PHY.
+ * @retval kStatus_Success PHY gets link speed and duplex success
+ * @retval kStatus_PHY_SMIVisitTimeout PHY SMI visit time out
+ */
+status_t PHY_RTL8211F_GetLinkSpeedDuplex(phy_handle_t *handle, phy_speed_t *speed, phy_duplex_t *duplex);
+
+/*!
+ * @brief Sets the PHY link speed and duplex.
+ *
+ * @param handle PHY device handle.
+ * @param speed Specified PHY link speed.
+ * @param duplex Specified PHY link duplex.
+ * @retval kStatus_Success PHY gets status success
+ * @retval kStatus_PHY_SMIVisitTimeout PHY SMI visit time out
+ */
+status_t PHY_RTL8211F_SetLinkSpeedDuplex(phy_handle_t *handle, phy_speed_t speed, phy_duplex_t duplex);
+
+/*!
+ * @brief Enables/disables PHY loopback.
+ *
+ * @param handle PHY device handle.
+ * @param mode The loopback mode to be enabled, please see "phy_loop_t".
+ * All loopback modes should not be set together, when one loopback mode is set
+ * another should be disabled.
+ * @param speed PHY speed for loopback mode.
+ * @param enable True to enable, false to disable.
+ * @retval kStatus_Success PHY loopback success
+ * @retval kStatus_PHY_SMIVisitTimeout PHY SMI visit time out
+ */
+status_t PHY_RTL8211F_EnableLoopback(phy_handle_t *handle, phy_loop_t mode, phy_speed_t speed, bool enable);
+
+/* @} */
+
+#if defined(__cplusplus)
+}
+#endif
+
+/*! @}*/
+
+#endif /* _FSL_PHY_H_ */
diff --git a/ports/mimxrt/hal/resethandler_MIMXRT10xx.S b/ports/mimxrt/hal/resethandler_MIMXRT10xx.S
index 8fe061103388..efca1a7ec6d4 100644
--- a/ports/mimxrt/hal/resethandler_MIMXRT10xx.S
+++ b/ports/mimxrt/hal/resethandler_MIMXRT10xx.S
@@ -37,6 +37,13 @@ Reset_Handler:
str r1,[r0] /* store FLEXRAM configuration value to IOMUXC_GPR17 */
dsb
isb
+#if defined MIMXRT117x_SERIES
+ ldr r0, =__iomux_gpr18_adr /* load IOMUXC_GPR18 register address to R0 */
+ ldr r1, =__iomux_gpr18_value /* move FlexRAM configuration value to R1 */
+ str r1,[r0] /* store FLEXRAM configuration value to IOMUXC_GPR18 */
+ dsb
+ isb
+#endif
ldr r0, =__iomux_gpr16_adr /* load IOMUXC_GPR16 register address to R0 */
ldr r1,[r0] /* load IOMUXC_GPR16 register value to R1 */
orr r1, r1, #4 /* set corresponding FLEXRAM_BANK_CFG_SEL bit */
diff --git a/ports/mimxrt/machine_adc.c b/ports/mimxrt/machine_adc.c
index aa4cc831e561..36e5fafc984b 100644
--- a/ports/mimxrt/machine_adc.c
+++ b/ports/mimxrt/machine_adc.c
@@ -29,7 +29,12 @@
#include "py/runtime.h"
#include "py/mphal.h"
+#if defined(MIMXRT117x_SERIES)
+#include "fsl_lpadc.h"
+#else
#include "fsl_adc.h"
+#endif
+
#include "fsl_gpio.h"
#include "fsl_iomuxc.h"
@@ -72,12 +77,14 @@ STATIC mp_obj_t adc_obj_make_new(const mp_obj_type_t *type, size_t n_args, size_
ADC_Type *adc_instance = pin->adc_list[0].instance; // NOTE: we only use the first ADC assignment - multiple assignments are not supported for now
uint8_t channel = pin->adc_list[0].channel;
+ #if 0 // done in adc_read_u16
// Configure ADC peripheral channel
adc_channel_config_t channel_config = {
.channelNumber = (uint32_t)channel,
.enableInterruptOnConversionCompleted = false,
};
ADC_SetChannelConfig(adc_instance, 0UL, &channel_config); // NOTE: we always choose channel group '0' since we only perform software triggered conversion
+ #endif
// Create ADC Instance
machine_adc_obj_t *o = mp_obj_malloc(machine_adc_obj_t, &machine_adc_type);
@@ -90,6 +97,43 @@ STATIC mp_obj_t adc_obj_make_new(const mp_obj_type_t *type, size_t n_args, size_
}
// read_u16()
+#if defined(MIMXRT117x_SERIES)
+STATIC mp_obj_t machine_adc_read_u16(mp_obj_t self_in) {
+ machine_adc_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ lpadc_conv_command_config_t adc_config;
+ lpadc_conv_trigger_config_t trigger_config;
+
+ // Set ADC configuration
+ LPADC_GetDefaultConvCommandConfig(&adc_config);
+ adc_config.channelNumber = self->channel;
+ adc_config.sampleScaleMode = kLPADC_SamplePartScale;
+ LPADC_SetConvCommandConfig(self->adc, 1, &adc_config);
+
+ // Set Trigger mode
+ LPADC_GetDefaultConvTriggerConfig(&trigger_config);
+ trigger_config.targetCommandId = 1;
+ LPADC_SetConvTriggerConfig(self->adc, 0U, &trigger_config);
+
+ // Measure input voltage
+ LPADC_DoSoftwareTrigger(self->adc, 1U);
+ lpadc_conv_result_t result_struct;
+ while (!LPADC_GetConvResult(self->adc, &result_struct)) {
+ }
+
+ return MP_OBJ_NEW_SMALL_INT(result_struct.convValue * 2);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_adc_read_u16_obj, machine_adc_read_u16);
+
+void machine_adc_init(void) {
+ lpadc_config_t adc_config; // Set ADC configuration
+ LPADC_GetDefaultConfig(&adc_config);
+ adc_config.enableAnalogPreliminary = true;
+ adc_config.referenceVoltageSource = kLPADC_ReferenceVoltageAlt1;
+ LPADC_Init(LPADC1, &adc_config);
+}
+
+#else
+
STATIC mp_obj_t machine_adc_read_u16(mp_obj_t self_in) {
machine_adc_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -111,20 +155,6 @@ STATIC mp_obj_t machine_adc_read_u16(mp_obj_t self_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_adc_read_u16_obj, machine_adc_read_u16);
-STATIC const mp_rom_map_elem_t adc_locals_dict_table[] = {
- { MP_ROM_QSTR(MP_QSTR_read_u16), MP_ROM_PTR(&machine_adc_read_u16_obj) },
-};
-
-STATIC MP_DEFINE_CONST_DICT(adc_locals_dict, adc_locals_dict_table);
-
-const mp_obj_type_t machine_adc_type = {
- {&mp_type_type},
- .name = MP_QSTR_ADC,
- .print = adc_obj_print,
- .make_new = adc_obj_make_new,
- .locals_dict = (mp_obj_dict_t *)&adc_locals_dict,
-};
-
void machine_adc_init(void) {
for (int i = 1; i < sizeof(adc_bases) / sizeof(ADC_Type *); ++i) {
ADC_Type *adc_instance = adc_bases[i];
@@ -142,3 +172,19 @@ void machine_adc_init(void) {
}
}
}
+#endif
+
+STATIC const mp_rom_map_elem_t adc_locals_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_read_u16), MP_ROM_PTR(&machine_adc_read_u16_obj) },
+};
+
+STATIC MP_DEFINE_CONST_DICT(adc_locals_dict, adc_locals_dict_table);
+
+MP_DEFINE_CONST_OBJ_TYPE(
+ machine_adc_type,
+ MP_QSTR_ADC,
+ MP_TYPE_FLAG_NONE,
+ make_new, adc_obj_make_new,
+ print, adc_obj_print,
+ locals_dict, &adc_locals_dict
+ );
diff --git a/ports/mimxrt/machine_i2c.c b/ports/mimxrt/machine_i2c.c
index c10fcaddbe38..c0a3dee98a40 100644
--- a/ports/mimxrt/machine_i2c.c
+++ b/ports/mimxrt/machine_i2c.c
@@ -30,6 +30,7 @@
#include "extmod/machine_i2c.h"
#include "modmachine.h"
#include CLOCK_CONFIG_H
+#include "pin.h"
#include "fsl_iomuxc.h"
#include "fsl_lpi2c.h"
@@ -37,13 +38,6 @@
#define DEFAULT_I2C_FREQ (400000)
#define DEFAULT_I2C_DRIVE (6)
-// Select USB1 PLL (480 MHz) as master lpi2c clock source
-#define LPI2C_CLOCK_SOURCE_SELECT (0U)
-// Clock divider for master lpi2c clock source
-#define LPI2C_CLOCK_SOURCE_DIVIDER (1U)
-// Get frequency of lpi2c clock = 30 MHz
-#define LPI2C_CLOCK_FREQUENCY ((CLOCK_GetFreq(kCLOCK_Usb1PllClk) / 8) / (LPI2C_CLOCK_SOURCE_DIVIDER + 1U))
-
typedef struct _machine_i2c_obj_t {
mp_obj_base_t base;
LPI2C_Type *i2c_inst;
@@ -197,11 +191,12 @@ STATIC const mp_machine_i2c_p_t machine_i2c_p = {
.transfer_single = machine_i2c_transfer_single,
};
-const mp_obj_type_t machine_i2c_type = {
- { &mp_type_type },
- .name = MP_QSTR_I2C,
- .print = machine_i2c_print,
- .make_new = machine_i2c_make_new,
- .protocol = &machine_i2c_p,
- .locals_dict = (mp_obj_dict_t *)&mp_machine_i2c_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ machine_i2c_type,
+ MP_QSTR_I2C,
+ MP_TYPE_FLAG_NONE,
+ make_new, machine_i2c_make_new,
+ print, machine_i2c_print,
+ protocol, &machine_i2c_p,
+ locals_dict, &mp_machine_i2c_locals_dict
+ );
diff --git a/ports/mimxrt/machine_i2s.c b/ports/mimxrt/machine_i2s.c
index 11a203baea16..32daad0853ab 100644
--- a/ports/mimxrt/machine_i2s.c
+++ b/ports/mimxrt/machine_i2s.c
@@ -99,7 +99,6 @@
#define NUM_I2S_USER_FORMATS (4)
#define I2S_RX_FRAME_SIZE_IN_BYTES (8)
-#define AUDIO_PLL_CLOCK (2U)
#define SAI_CHANNEL_0 (0)
#define SAI_NUM_AUDIO_CHANNELS (2U)
@@ -208,42 +207,69 @@ STATIC const int8_t i2s_frame_map[NUM_I2S_USER_FORMATS][I2S_RX_FRAME_SIZE_IN_BYT
// PLL output frequency = 24MHz * (.loopDivider + .numerator/.denominator)
// Configuration 1: for sampling frequencies [Hz]: 8000, 12000, 16000, 24000, 32000, 48000
-// Clock frequency = 786,432,480 Hz
+// Clock frequency = 786,432,000 Hz = 48000 * 64 * 256
STATIC const clock_audio_pll_config_t audioPllConfig_8000_48000 = {
.loopDivider = 32, // PLL loop divider. Valid range for DIV_SELECT divider value: 27~54
.postDivider = 1, // Divider after the PLL, should only be 1, 2, 4, 8, 16
- .numerator = 76802, // 30 bit numerator of fractional loop divider
+ .numerator = 76800, // 30 bit numerator of fractional loop divider
.denominator = 100000, // 30 bit denominator of fractional loop divider
+ #if !defined(MIMXRT117x_SERIES)
.src = kCLOCK_PllClkSrc24M // Pll clock source
+ #endif
};
// Configuration 2: for sampling frequencies [Hz]: 11025, 22050, 44100
-// Clock frequency = 722,534,880
+// Clock frequency = 722,534,400 = 44100 * 64 * 256
STATIC const clock_audio_pll_config_t audioPllConfig_11025_44100 = {
.loopDivider = 30, // PLL loop divider. Valid range for DIV_SELECT divider value: 27~54
.postDivider = 1, // Divider after the PLL, should only be 1, 2, 4, 8, 16
- .numerator = 10562, // 30 bit numerator of fractional loop divider
+ .numerator = 10560, // 30 bit numerator of fractional loop divider
.denominator = 100000, // 30 bit denominator of fractional loop divider
+ #if !defined(MIMXRT117x_SERIES)
.src = kCLOCK_PllClkSrc24M // Pll clock source
+ #endif
};
+#if defined(MIMXRT117x_SERIES)
+// for 1176 the pre_div value is used for post_div of the Audio PLL,
+// which is 2**n: 0->1, 1->2, 2->4, 3->8, 4->16, 5->32
+// The divider is 8 bit and must be given as n (not n-1)
+// So the total division factor is given by (2**p) * d
STATIC const i2s_clock_config_t clock_config_map[] = {
- {kSAI_SampleRate8KHz, &audioPllConfig_8000_48000, 5, 63},
- {kSAI_SampleRate11025Hz, &audioPllConfig_11025_44100, 3, 63},
- {kSAI_SampleRate12KHz, &audioPllConfig_8000_48000, 3, 63},
- {kSAI_SampleRate16KHz, &audioPllConfig_8000_48000, 2, 63},
- {kSAI_SampleRate22050Hz, &audioPllConfig_11025_44100, 1, 63},
- {kSAI_SampleRate24KHz, &audioPllConfig_8000_48000, 1, 63},
- {kSAI_SampleRate32KHz, &audioPllConfig_8000_48000, 1, 47},
- {kSAI_SampleRate44100Hz, &audioPllConfig_11025_44100, 0, 63},
- {kSAI_SampleRate48KHz, &audioPllConfig_8000_48000, 0, 63}
+ {kSAI_SampleRate8KHz, &audioPllConfig_8000_48000, 1, 192}, // 384
+ {kSAI_SampleRate11025Hz, &audioPllConfig_11025_44100, 1, 128}, // 256
+ {kSAI_SampleRate12KHz, &audioPllConfig_8000_48000, 1, 128}, // 256
+ {kSAI_SampleRate16KHz, &audioPllConfig_8000_48000, 0, 192}, // 192
+ {kSAI_SampleRate22050Hz, &audioPllConfig_11025_44100, 0, 128}, // 128
+ {kSAI_SampleRate24KHz, &audioPllConfig_8000_48000, 0, 128}, // 128
+ {kSAI_SampleRate32KHz, &audioPllConfig_8000_48000, 0, 96}, // 96
+ {kSAI_SampleRate44100Hz, &audioPllConfig_11025_44100, 0, 64}, // 64
+ {kSAI_SampleRate48KHz, &audioPllConfig_8000_48000, 0, 64} // 64
+};
+
+STATIC const clock_root_t i2s_clock_mux[] = I2S_CLOCK_MUX;
+#else
+// for 10xx the total division factor is given by (p + 1) * (d + 1)
+STATIC const i2s_clock_config_t clock_config_map[] = {
+ {kSAI_SampleRate8KHz, &audioPllConfig_8000_48000, 5, 63}, // 384
+ {kSAI_SampleRate11025Hz, &audioPllConfig_11025_44100, 3, 63}, // 256
+ {kSAI_SampleRate12KHz, &audioPllConfig_8000_48000, 3, 63}, // 256
+ {kSAI_SampleRate16KHz, &audioPllConfig_8000_48000, 2, 63}, // 192
+ {kSAI_SampleRate22050Hz, &audioPllConfig_11025_44100, 1, 63}, // 128
+ {kSAI_SampleRate24KHz, &audioPllConfig_8000_48000, 1, 63}, // 128
+ {kSAI_SampleRate32KHz, &audioPllConfig_8000_48000, 1, 47}, // 96
+ {kSAI_SampleRate44100Hz, &audioPllConfig_11025_44100, 0, 63}, // 64
+ {kSAI_SampleRate48KHz, &audioPllConfig_8000_48000, 0, 63} // 64
};
-STATIC const I2S_Type *i2s_base_ptr[] = I2S_BASE_PTRS;
STATIC const clock_mux_t i2s_clock_mux[] = I2S_CLOCK_MUX;
STATIC const clock_div_t i2s_clock_pre_div[] = I2S_CLOCK_PRE_DIV;
STATIC const clock_div_t i2s_clock_div[] = I2S_CLOCK_DIV;
STATIC const iomuxc_gpr_mode_t i2s_iomuxc_gpr_mode[] = I2S_IOMUXC_GPR_MODE;
+#endif
+
+STATIC const I2S_Type *i2s_base_ptr[] = I2S_BASE_PTRS;
+
STATIC const dma_request_source_t i2s_dma_req_src_tx[] = I2S_DMA_REQ_SRC_TX;
STATIC const dma_request_source_t i2s_dma_req_src_rx[] = I2S_DMA_REQ_SRC_RX;
STATIC const gpio_map_t i2s_gpio_map[] = I2S_GPIO_MAP;
@@ -674,10 +700,24 @@ STATIC void edma_i2s_callback(edma_handle_t *handle, void *userData, bool transf
STATIC bool i2s_init(machine_i2s_obj_t *self) {
+ #if defined(MIMXRT117x_SERIES)
+ clock_audio_pll_config_t pll_config = *get_pll_config(self->rate);
+ pll_config.postDivider = get_clock_pre_divider(self->rate);
+ CLOCK_InitAudioPll(&pll_config);
+ CLOCK_SetRootClockMux(i2s_clock_mux[self->i2s_id], I2S_AUDIO_PLL_CLOCK);
+ CLOCK_SetRootClockDiv(i2s_clock_mux[self->i2s_id], get_clock_divider(self->rate));
+ uint32_t clock_freq = CLOCK_GetFreq(kCLOCK_AudioPllOut) / get_clock_divider(self->rate);
+
+ #else
+
CLOCK_InitAudioPll(get_pll_config(self->rate));
- CLOCK_SetMux(i2s_clock_mux[self->i2s_id], AUDIO_PLL_CLOCK);
+ CLOCK_SetMux(i2s_clock_mux[self->i2s_id], I2S_AUDIO_PLL_CLOCK);
CLOCK_SetDiv(i2s_clock_pre_div[self->i2s_id], get_clock_pre_divider(self->rate));
CLOCK_SetDiv(i2s_clock_div[self->i2s_id], get_clock_divider(self->rate));
+ uint32_t clock_freq =
+ (CLOCK_GetFreq(kCLOCK_AudioPllClk) / (get_clock_divider(self->rate) + 1U) /
+ (get_clock_pre_divider(self->rate) + 1U));
+ #endif
if (!set_iomux(self->sck, SCK, self->i2s_id)) {
return false;
@@ -695,7 +735,24 @@ STATIC bool i2s_init(machine_i2s_obj_t *self) {
if (!set_iomux(self->mck, MCK, self->i2s_id)) {
return false;
}
+ #if defined(MIMXRT117x_SERIES)
+ switch (self->i2s_id) {
+ case 1:
+ IOMUXC_GPR->GPR0 |= IOMUXC_GPR_GPR0_SAI1_MCLK_DIR_MASK;
+ break;
+ case 2:
+ IOMUXC_GPR->GPR1 |= IOMUXC_GPR_GPR1_SAI2_MCLK_DIR_MASK;
+ break;
+ case 3:
+ IOMUXC_GPR->GPR2 |= IOMUXC_GPR_GPR2_SAI3_MCLK_DIR_MASK;
+ break;
+ case 4:
+ IOMUXC_GPR->GPR2 |= IOMUXC_GPR_GPR2_SAI4_MCLK_DIR_MASK;
+ break;
+ }
+ #else
IOMUXC_EnableMode(IOMUXC_GPR, i2s_iomuxc_gpr_mode[self->i2s_id], true);
+ #endif
}
self->dma_channel = allocate_dma_channel();
@@ -743,10 +800,6 @@ STATIC bool i2s_init(machine_i2s_obj_t *self) {
return false; // should never happen
}
- uint32_t clock_freq =
- (CLOCK_GetFreq(kCLOCK_AudioPllClk) / (get_clock_divider(self->rate) + 1U) /
- (get_clock_pre_divider(self->rate) + 1U));
-
SAI_TxSetBitClockRate(self->i2s_inst, clock_freq, self->rate, get_dma_bits(self->mode, self->bits),
SAI_NUM_AUDIO_CHANNELS);
SAI_RxSetBitClockRate(self->i2s_inst, clock_freq, self->rate, get_dma_bits(self->mode, self->bits),
@@ -1213,15 +1266,16 @@ STATIC const mp_stream_p_t i2s_stream_p = {
.is_text = false,
};
-const mp_obj_type_t machine_i2s_type = {
- { &mp_type_type },
- .name = MP_QSTR_I2S,
- .print = machine_i2s_print,
- .getiter = mp_identity_getiter,
- .iternext = mp_stream_unbuffered_iter,
- .protocol = &i2s_stream_p,
- .make_new = machine_i2s_make_new,
- .locals_dict = (mp_obj_dict_t *)&machine_i2s_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ machine_i2s_type,
+ MP_QSTR_I2S,
+ MP_TYPE_FLAG_ITER_IS_STREAM,
+ make_new, machine_i2s_make_new,
+ print, machine_i2s_print,
+ protocol, &i2s_stream_p,
+ locals_dict, &machine_i2s_locals_dict
+ );
+
+MP_REGISTER_ROOT_POINTER(struct _machine_i2s_obj_t *machine_i2s_obj[MICROPY_HW_I2S_NUM]);
#endif // MICROPY_PY_MACHINE_I2S
diff --git a/ports/mimxrt/machine_led.c b/ports/mimxrt/machine_led.c
index 4082eb34bbbf..35743697f2cf 100644
--- a/ports/mimxrt/machine_led.c
+++ b/ports/mimxrt/machine_led.c
@@ -44,7 +44,7 @@ STATIC mp_obj_t led_obj_make_new(const mp_obj_type_t *type, size_t n_args, size_
// Check led id is in range
if (!(1 <= led_id && led_id <= NUM_LEDS)) {
- mp_raise_msg_varg(&mp_type_ValueError, "LED(%d) doesn't exist", led_id);
+ mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("LED(%d) doesn't exist"), led_id);
}
// Return reference to static object
@@ -80,12 +80,13 @@ STATIC const mp_rom_map_elem_t led_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(led_locals_dict, led_locals_dict_table);
-const mp_obj_type_t machine_led_type = {
- {&mp_type_type},
- .name = MP_QSTR_LED,
- .print = led_obj_print,
- .make_new = led_obj_make_new,
- .locals_dict = (mp_obj_dict_t *)&led_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ machine_led_type,
+ MP_QSTR_LED,
+ MP_TYPE_FLAG_NONE,
+ make_new, led_obj_make_new,
+ print, led_obj_print,
+ locals_dict, &led_locals_dict
+ );
#endif
diff --git a/ports/mimxrt/machine_pin.c b/ports/mimxrt/machine_pin.c
index 2424088f02ef..d44e649964f7 100644
--- a/ports/mimxrt/machine_pin.c
+++ b/ports/mimxrt/machine_pin.c
@@ -58,17 +58,19 @@ enum {
};
// Pin mapping dictionaries
-const mp_obj_type_t machine_pin_cpu_pins_obj_type = {
- { &mp_type_type },
- .name = MP_QSTR_cpu,
- .locals_dict = (mp_obj_t)&machine_pin_cpu_pins_locals_dict,
-};
-
-const mp_obj_type_t machine_pin_board_pins_obj_type = {
- { &mp_type_type },
- .name = MP_QSTR_board,
- .locals_dict = (mp_obj_t)&machine_pin_board_pins_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ machine_pin_cpu_pins_obj_type,
+ MP_QSTR_cpu,
+ MP_TYPE_FLAG_NONE,
+ locals_dict, &machine_pin_cpu_pins_locals_dict
+ );
+
+MP_DEFINE_CONST_OBJ_TYPE(
+ machine_pin_board_pins_obj_type,
+ MP_QSTR_board,
+ MP_TYPE_FLAG_NONE,
+ locals_dict, &machine_pin_board_pins_locals_dict
+ );
STATIC const mp_irq_methods_t machine_pin_irq_methods;
@@ -147,6 +149,16 @@ void GPIO5_Combined_16_31_IRQHandler(void) {
call_handler(gpiobases[5], 5, 16);
}
+#if defined(MIMXRT117x_SERIES)
+void GPIO6_Combined_0_15_IRQHandler(void) {
+ call_handler(gpiobases[6], 6, 0);
+}
+
+void GPIO6_Combined_16_31_IRQHandler(void) {
+ call_handler(gpiobases[6], 6, 16);
+}
+#endif
+
// Deinit all pin IRQ handlers.
void machine_pin_irq_deinit(void) {
for (int i = 0; i < ARRAY_SIZE(MP_STATE_PORT(machine_pin_irq_objects)); ++i) {
@@ -283,6 +295,14 @@ STATIC mp_obj_t machine_pin_on(mp_obj_t self_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_pin_on_obj, machine_pin_on);
+// pin.toggle()
+STATIC mp_obj_t machine_pin_toggle(mp_obj_t self_in) {
+ machine_pin_obj_t *self = self_in;
+ mp_hal_pin_toggle(self);
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_pin_toggle_obj, machine_pin_toggle);
+
// pin.value([value])
STATIC mp_obj_t machine_pin_value(size_t n_args, const mp_obj_t *args) {
return machine_pin_obj_call(args[0], (n_args - 1), 0, args + 1);
@@ -364,6 +384,7 @@ STATIC const mp_rom_map_elem_t machine_pin_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_on), MP_ROM_PTR(&machine_pin_on_obj) },
{ MP_ROM_QSTR(MP_QSTR_low), MP_ROM_PTR(&machine_pin_off_obj) },
{ MP_ROM_QSTR(MP_QSTR_high), MP_ROM_PTR(&machine_pin_on_obj) },
+ { MP_ROM_QSTR(MP_QSTR_toggle), MP_ROM_PTR(&machine_pin_toggle_obj) },
{ MP_ROM_QSTR(MP_QSTR_value), MP_ROM_PTR(&machine_pin_value_obj) },
{ MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_pin_init_obj) },
{ MP_ROM_QSTR(MP_QSTR_irq), MP_ROM_PTR(&machine_pin_irq_obj) },
@@ -396,7 +417,6 @@ STATIC const mp_rom_map_elem_t machine_pin_locals_dict_table[] = {
};
STATIC MP_DEFINE_CONST_DICT(machine_pin_locals_dict, machine_pin_locals_dict_table);
-
STATIC mp_uint_t machine_pin_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode) {
(void)errcode;
machine_pin_obj_t *self = self_in;
@@ -417,24 +437,26 @@ STATIC const mp_pin_p_t machine_pin_obj_protocol = {
.ioctl = machine_pin_ioctl,
};
-const mp_obj_type_t machine_pin_type = {
- {&mp_type_type},
- .name = MP_QSTR_Pin,
- .print = machine_pin_obj_print,
- .call = machine_pin_obj_call,
- .make_new = mp_pin_make_new,
- .protocol = &machine_pin_obj_protocol,
- .locals_dict = (mp_obj_dict_t *)&machine_pin_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ machine_pin_type,
+ MP_QSTR_Pin,
+ MP_TYPE_FLAG_NONE,
+ make_new, mp_pin_make_new,
+ print, machine_pin_obj_print,
+ call, machine_pin_obj_call,
+ protocol, &machine_pin_obj_protocol,
+ locals_dict, &machine_pin_locals_dict
+ );
// FIXME: Create actual pin_af type!!!
-const mp_obj_type_t machine_pin_af_type = {
- {&mp_type_type},
- .name = MP_QSTR_PinAF,
- .print = machine_pin_obj_print,
- .make_new = mp_pin_make_new,
- .locals_dict = (mp_obj_dict_t *)&machine_pin_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ machine_pin_af_type,
+ MP_QSTR_PinAF,
+ MP_TYPE_FLAG_NONE,
+ make_new, mp_pin_make_new,
+ print, machine_pin_obj_print,
+ locals_dict, &machine_pin_locals_dict
+ );
STATIC mp_uint_t machine_pin_irq_trigger(mp_obj_t self_in, mp_uint_t new_trigger) {
machine_pin_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -469,3 +491,5 @@ STATIC const mp_irq_methods_t machine_pin_irq_methods = {
.trigger = machine_pin_irq_trigger,
.info = machine_pin_irq_info,
};
+
+MP_REGISTER_ROOT_POINTER(void *machine_pin_irq_objects[MICROPY_HW_NUM_PIN_IRQS]);
diff --git a/ports/mimxrt/machine_pwm.c b/ports/mimxrt/machine_pwm.c
index d5bb029e689e..661ec1665894 100644
--- a/ports/mimxrt/machine_pwm.c
+++ b/ports/mimxrt/machine_pwm.c
@@ -214,7 +214,11 @@ STATIC void configure_flexpwm(machine_pwm_obj_t *self) {
pwm_signal_param_u16_t pwmSignal;
// Initialize PWM module.
+ #if defined(MIMXRT117x_SERIES)
+ uint32_t pwmSourceClockInHz = CLOCK_GetRootClockFreq(kCLOCK_Root_Bus);
+ #else
uint32_t pwmSourceClockInHz = CLOCK_GetFreq(kCLOCK_IpgClk);
+ #endif
int prescale = calc_prescaler(pwmSourceClockInHz, self->freq);
if (prescale < 0) {
@@ -296,10 +300,15 @@ STATIC void configure_flexpwm(machine_pwm_obj_t *self) {
STATIC void configure_qtmr(machine_pwm_obj_t *self) {
qtmr_config_t qtmrConfig;
int prescale;
+ #if defined(MIMXRT117x_SERIES)
+ uint32_t pwmSourceClockInHz = CLOCK_GetRootClockFreq(kCLOCK_Root_Bus);
+ #else
+ uint32_t pwmSourceClockInHz = CLOCK_GetFreq(kCLOCK_IpgClk);
+ #endif
TMR_Type *instance = (TMR_Type *)self->instance;
- prescale = calc_prescaler(CLOCK_GetFreq(kCLOCK_IpgClk), self->freq);
+ prescale = calc_prescaler(pwmSourceClockInHz, self->freq);
if (prescale < 0) {
mp_raise_ValueError(MP_ERROR_TEXT(ERRMSG_FREQ));
}
@@ -311,7 +320,7 @@ STATIC void configure_qtmr(machine_pwm_obj_t *self) {
}
// Set up the PWM channel
if (QTMR_SetupPwm_u16(instance, self->channel1, self->freq, self->duty_u16,
- self->invert, CLOCK_GetFreq(kCLOCK_IpgClk) / (1 << prescale), self->is_init) == kStatus_Fail) {
+ self->invert, pwmSourceClockInHz / (1 << prescale), self->is_init) == kStatus_Fail) {
mp_raise_ValueError(MP_ERROR_TEXT(ERRMSG_INIT));
}
// Start the output
@@ -325,7 +334,9 @@ STATIC void configure_pwm(machine_pwm_obj_t *self) {
static bool set_frequency = true;
// set the frequency only once
if (set_frequency) {
+ #if !defined(MIMXRT117x_SERIES)
CLOCK_SetDiv(kCLOCK_IpgDiv, 0x3); // Set IPG PODF to 3, divide by 4
+ #endif
set_frequency = false;
}
diff --git a/ports/mimxrt/machine_rtc.c b/ports/mimxrt/machine_rtc.c
index e0d33554b559..702c1b903e50 100644
--- a/ports/mimxrt/machine_rtc.c
+++ b/ports/mimxrt/machine_rtc.c
@@ -38,7 +38,6 @@ typedef struct _machine_rtc_obj_t {
// Singleton RTC object.
STATIC const machine_rtc_obj_t machine_rtc_obj = {{&machine_rtc_type}};
-uint32_t us_offset = 0;
// Start the RTC Timer.
void machine_rtc_start(void) {
@@ -83,7 +82,7 @@ STATIC mp_obj_t machine_rtc_datetime_helper(size_t n_args, const mp_obj_t *args)
mp_obj_new_int(srtc_date.hour),
mp_obj_new_int(srtc_date.minute),
mp_obj_new_int(srtc_date.second),
- mp_obj_new_int((ticks_us64() + us_offset) % 1000000),
+ mp_obj_new_int(0),
};
return mp_obj_new_tuple(8, tuple);
} else {
@@ -104,7 +103,6 @@ STATIC mp_obj_t machine_rtc_datetime_helper(size_t n_args, const mp_obj_t *args)
if (SNVS_LP_SRTC_SetDatetime(SNVS, &srtc_date) != kStatus_Success) {
mp_raise_ValueError(NULL);
}
- us_offset = (1000000 + mp_obj_get_int(items[7]) - ticks_us64() % 1000000) % 1000000;
return mp_const_none;
}
@@ -127,7 +125,7 @@ STATIC mp_obj_t machine_rtc_now(mp_obj_t self_in) {
mp_obj_new_int(srtc_date.hour),
mp_obj_new_int(srtc_date.minute),
mp_obj_new_int(srtc_date.second),
- mp_obj_new_int((ticks_us64() + us_offset) % 1000000),
+ mp_obj_new_int(0),
mp_const_none,
};
return mp_obj_new_tuple(8, tuple);
@@ -166,9 +164,10 @@ STATIC const mp_rom_map_elem_t machine_rtc_locals_dict_table[] = {
};
STATIC MP_DEFINE_CONST_DICT(machine_rtc_locals_dict, machine_rtc_locals_dict_table);
-const mp_obj_type_t machine_rtc_type = {
- { &mp_type_type },
- .name = MP_QSTR_RTC,
- .make_new = machine_rtc_make_new,
- .locals_dict = (mp_obj_t)&machine_rtc_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ machine_rtc_type,
+ MP_QSTR_RTC,
+ MP_TYPE_FLAG_NONE,
+ make_new, machine_rtc_make_new,
+ locals_dict, &machine_rtc_locals_dict
+ );
diff --git a/ports/mimxrt/machine_sdcard.c b/ports/mimxrt/machine_sdcard.c
index 4a92aae00cef..496eb9353388 100644
--- a/ports/mimxrt/machine_sdcard.c
+++ b/ports/mimxrt/machine_sdcard.c
@@ -30,7 +30,12 @@
#include "py/mperrno.h"
#include "extmod/vfs.h"
#include "ticks.h"
+
+#if defined(MIMXRT1170x_SERIES)
+#include "cm7/fsl_cache.h"
+#else
#include "fsl_cache.h"
+#endif
#include "sdcard.h"
@@ -62,7 +67,7 @@ STATIC mp_obj_t sdcard_obj_make_new(const mp_obj_type_t *type, size_t n_args, si
mp_int_t sdcard_id = args[SDCARD_INIT_ARG_ID].u_int;
if (!(1 <= sdcard_id && sdcard_id <= MP_ARRAY_SIZE(mimxrt_sdcard_objs))) {
- nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "SDCard(%d) doesn't exist", sdcard_id));
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("SDCard(%d) doesn't exist"), sdcard_id));
}
mimxrt_sdcard_obj_t *self = &mimxrt_sdcard_objs[(sdcard_id - 1)];
@@ -208,12 +213,13 @@ STATIC const mp_rom_map_elem_t sdcard_locals_dict_table[] = {
};
STATIC MP_DEFINE_CONST_DICT(sdcard_locals_dict, sdcard_locals_dict_table);
-const mp_obj_type_t machine_sdcard_type = {
- { &mp_type_type },
- .name = MP_QSTR_SDCard,
- .make_new = sdcard_obj_make_new,
- .locals_dict = (mp_obj_dict_t *)&sdcard_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ machine_sdcard_type,
+ MP_QSTR_SDCard,
+ MP_TYPE_FLAG_NONE,
+ make_new, sdcard_obj_make_new,
+ locals_dict, &sdcard_locals_dict
+ );
void machine_sdcard_init0(void) {
return;
diff --git a/ports/mimxrt/machine_spi.c b/ports/mimxrt/machine_spi.c
index 805ed9a0ac54..d6aff2a329a0 100644
--- a/ports/mimxrt/machine_spi.c
+++ b/ports/mimxrt/machine_spi.c
@@ -45,6 +45,14 @@
#define DEFAULT_SPI_FIRSTBIT (kLPSPI_MsbFirst)
#define DEFAULT_SPI_DRIVE (6)
+#define CLOCK_DIVIDER (1)
+
+#if defined(MIMXRT117x_SERIES)
+#define LPSPI_DMAMUX DMAMUX0
+#else
+#define LPSPI_DMAMUX DMAMUX
+#endif
+
#define MICROPY_HW_SPI_NUM MP_ARRAY_SIZE(spi_index_table)
#define SCK (iomux_table[index])
@@ -77,7 +85,7 @@ static const iomux_table_t iomux_table[] = {
IOMUX_TABLE_SPI
};
-bool lpspi_set_iomux(int8_t spi, uint8_t drive, uint8_t cs) {
+bool lpspi_set_iomux(int8_t spi, uint8_t drive, int8_t cs) {
int index = (spi - 1) * 5;
if (SCK.muxRegister != 0) {
@@ -93,7 +101,7 @@ bool lpspi_set_iomux(int8_t spi, uint8_t drive, uint8_t cs) {
IOMUXC_SetPinMux(CS1.muxRegister, CS1.muxMode, CS1.inputRegister, CS1.inputDaisy, CS1.configRegister, 0U);
IOMUXC_SetPinConfig(CS1.muxRegister, CS1.muxMode, CS1.inputRegister, CS1.inputDaisy, CS1.configRegister,
pin_generate_config(PIN_PULL_UP_100K, PIN_MODE_OUT, drive, CS1.configRegister));
- } else {
+ } else if (cs != -1) {
mp_raise_ValueError(MP_ERROR_TEXT("The chosen CS is not available"));
}
@@ -131,7 +139,7 @@ mp_obj_t machine_spi_make_new(const mp_obj_type_t *type, size_t n_args, size_t n
{ MP_QSTR_firstbit, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = DEFAULT_SPI_FIRSTBIT} },
{ MP_QSTR_gap_ns, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
{ MP_QSTR_drive, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = DEFAULT_SPI_DRIVE} },
- { MP_QSTR_cs, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
+ { MP_QSTR_cs, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
};
// Parse the arguments.
@@ -173,8 +181,11 @@ mp_obj_t machine_spi_make_new(const mp_obj_type_t *type, size_t n_args, size_t n
}
self->master_config->lastSckToPcsDelayInNanoSec = self->master_config->betweenTransferDelayInNanoSec;
self->master_config->pcsToSckDelayInNanoSec = self->master_config->betweenTransferDelayInNanoSec;
- uint8_t cs = args[ARG_cs].u_int;
- if (cs <= 1) {
+ int8_t cs = args[ARG_cs].u_int;
+ // In the SPI master_config for automatic CS the value cs=0 is set already,
+ // so only cs=1 has to be addressed here. The case cs == -1 for manual CS is handled
+ // in the function spi_set_iomux() and the value in the master_config can stay at 0.
+ if (cs == 1) {
self->master_config->whichPcs = cs;
}
LPSPI_MasterInit(self->spi_inst, self->master_config, BOARD_BOOTCLOCKRUN_LPSPI_CLK_ROOT);
@@ -248,11 +259,12 @@ STATIC const mp_machine_spi_p_t machine_spi_p = {
.transfer = machine_spi_transfer,
};
-const mp_obj_type_t machine_spi_type = {
- { &mp_type_type },
- .name = MP_QSTR_SPI,
- .print = machine_spi_print,
- .make_new = machine_spi_make_new,
- .protocol = &machine_spi_p,
- .locals_dict = (mp_obj_dict_t *)&mp_machine_spi_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ machine_spi_type,
+ MP_QSTR_SPI,
+ MP_TYPE_FLAG_NONE,
+ make_new, machine_spi_make_new,
+ print, machine_spi_print,
+ protocol, &machine_spi_p,
+ locals_dict, &mp_machine_spi_locals_dict
+ );
diff --git a/ports/mimxrt/machine_timer.c b/ports/mimxrt/machine_timer.c
deleted file mode 100644
index c47d9dca24c6..000000000000
--- a/ports/mimxrt/machine_timer.c
+++ /dev/null
@@ -1,220 +0,0 @@
-/*
- * This file is part of the MicroPython project, http://micropython.org/
- *
- * The MIT License (MIT)
- *
- * Copyright (c) 2020-2021 Damien P. George
- * Copyright (c) 2021 Robert Hammelrath
- *
- * 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"
-#include "fsl_pit.h"
-#include "modmachine.h"
-#include CLOCK_CONFIG_H
-
-#define TIMER_MODE_ONE_SHOT (0)
-#define TIMER_MODE_PERIODIC (1)
-#define TIMER_MIN_PERIOD 1
-
-#define alarm_callback PIT_IRQHandler
-#define PIT_IRQ_ID PIT_IRQn
-
-typedef struct _machine_timer_obj_t {
- mp_obj_base_t base;
- int8_t id;
- int8_t channel;
- uint32_t mode;
- uint32_t tick_hz;
- uint32_t delta_us; // for periodic mode
- mp_obj_t callback;
-} machine_timer_obj_t;
-
-static const int8_t channel_no[MICROPY_HW_PIT_NUM_CHANNELS] = {0, 2, 3}; // no channel 1
-static pit_config_t pit_config;
-
-// This is the interrupt handler
-// To tell which channel fired one has to poll the flags
-void alarm_callback(void) {
- for (uint8_t index = 0; index < MICROPY_HW_PIT_NUM_CHANNELS; index++) {
- uint32_t flag;
- machine_timer_obj_t *self = MP_STATE_PORT(timer_table)[index];
- if (self != NULL) {
- flag = PIT_GetStatusFlags(PIT, self->channel);
- if (flag & kPIT_TimerFlag) { // channel fired
- PIT_ClearStatusFlags(PIT, self->channel, kPIT_TimerFlag);
- __DSB();
-
- mp_sched_schedule(self->callback, MP_OBJ_FROM_PTR(self));
-
- if (self->mode == TIMER_MODE_ONE_SHOT) {
- PIT_StopTimer(PIT, self->channel);
- }
- }
- }
- }
-}
-
-STATIC void machine_timer_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
- machine_timer_obj_t *self = MP_OBJ_TO_PTR(self_in);
- qstr mode = self->mode == TIMER_MODE_ONE_SHOT ? MP_QSTR_ONE_SHOT : MP_QSTR_PERIODIC;
- mp_printf(print, "Timer(channel=%d, mode=%q, period=%d, tick_hz=%d)",
- self->id, mode, self->delta_us / self->tick_hz, self->tick_hz);
-}
-
-STATIC mp_obj_t machine_timer_init_helper(machine_timer_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
- enum { ARG_mode, ARG_callback, ARG_period, ARG_tick_hz, ARG_freq, };
- static const mp_arg_t allowed_args[] = {
- { MP_QSTR_mode, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = TIMER_MODE_PERIODIC} },
- { MP_QSTR_callback, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
- { MP_QSTR_period, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0xffffffff} },
- { MP_QSTR_tick_hz, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1000} },
- { MP_QSTR_freq, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
- };
-
- // Parse args
- mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
- mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
-
- self->mode = args[ARG_mode].u_int;
- if (args[ARG_freq].u_obj != mp_const_none) {
- // Frequency specified in Hz
- #if MICROPY_PY_BUILTINS_FLOAT
- self->delta_us = (uint32_t)(MICROPY_FLOAT_CONST(1000000.0) / mp_obj_get_float(args[ARG_freq].u_obj));
- #else
- self->delta_us = 1000000 / mp_obj_get_int(args[ARG_freq].u_obj);
- #endif
- } else {
- // Period specified
- self->tick_hz = args[ARG_tick_hz].u_int;
- self->delta_us = (uint64_t)args[ARG_period].u_int * 1000000 / self->tick_hz;
- }
- if (self->delta_us < TIMER_MIN_PERIOD) {
- self->delta_us = TIMER_MIN_PERIOD;
- }
-
- self->callback = args[ARG_callback].u_obj;
-
- // Set timer period for channel id
- PIT_SetTimerPeriod(PIT, self->channel, USEC_TO_COUNT(self->delta_us, BOARD_BOOTCLOCKRUN_IPG_CLK_ROOT));
-
- // Enable timer interrupts for the channel
- PIT_EnableInterrupts(PIT, self->channel, kPIT_TimerInterruptEnable);
-
- // Enable at the NVIC
- EnableIRQ(PIT_IRQ_ID);
-
- // Start channel 0
- PIT_StartTimer(PIT, self->channel);
-
- return mp_const_none;
-}
-
-STATIC mp_obj_t machine_timer_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
- machine_timer_obj_t *self;
-
- // Get timer id in the range of 0..2
- mp_int_t id = 0;
- if (n_args > 0) {
- id = mp_obj_get_int(args[0]);
- --n_args;
- ++args;
- }
- if (id < 0 || id >= MICROPY_HW_PIT_NUM_CHANNELS) {
- mp_raise_ValueError(MP_ERROR_TEXT("Timer does not exist"));
- }
-
- // check, if a timer exists at that channel and stop it first
- if (MP_STATE_PORT(timer_table)[id] != NULL) {
- PIT_StopTimer(PIT, channel_no[id]);
- self = MP_STATE_PORT(timer_table)[id];
- } else {
- self = m_new_obj_with_finaliser(machine_timer_obj_t);
- self->base.type = &machine_timer_type;
- MP_STATE_PORT(timer_table)[id] = self;
- }
-
- // Set initial values
- self->id = id;
- self->channel = channel_no[id];
-
- if (n_args > 0 || n_kw > 0) {
- // Start the timer
- mp_map_t kw_args;
- mp_map_init_fixed_table(&kw_args, n_kw, args + n_args);
- machine_timer_init_helper(self, n_args, args, &kw_args);
- }
-
- return MP_OBJ_FROM_PTR(self);
-}
-
-STATIC mp_obj_t machine_timer___del__(mp_obj_t self_in) {
- machine_timer_obj_t *self = MP_OBJ_TO_PTR(self_in);
- PIT_StopTimer(PIT, self->channel);
- MP_STATE_PORT(timer_table)[self->id] = NULL;
- return mp_const_none;
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_timer___del___obj, machine_timer___del__);
-
-STATIC mp_obj_t machine_timer_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
- machine_timer_obj_t *self = MP_OBJ_TO_PTR(args[0]);
- PIT_StopTimer(PIT, self->channel);
- return machine_timer_init_helper(self, n_args - 1, args + 1, kw_args);
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_timer_init_obj, 1, machine_timer_init);
-
-STATIC mp_obj_t machine_timer_deinit(mp_obj_t self_in) {
- machine_timer_obj_t *self = MP_OBJ_TO_PTR(self_in);
- PIT_StopTimer(PIT, self->channel);
- return mp_const_none;
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_timer_deinit_obj, machine_timer_deinit);
-
-// Initialize clock an first config
-void machine_timer_init_PIT(void) {
- // PIT timer
- // Enable clock gate for GPIO1
- CLOCK_EnableClock(kCLOCK_Gpio1); // ?
- // Set PERCLK_CLK divider to 1
- CLOCK_SetDiv(kCLOCK_PerclkDiv, 0U);
-
- PIT_GetDefaultConfig(&pit_config);
- PIT_Init(PIT, &pit_config);
-}
-
-STATIC const mp_rom_map_elem_t machine_timer_locals_dict_table[] = {
- { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&machine_timer___del___obj) },
- { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_timer_init_obj) },
- { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_timer_deinit_obj) },
-
- { MP_ROM_QSTR(MP_QSTR_ONE_SHOT), MP_ROM_INT(TIMER_MODE_ONE_SHOT) },
- { MP_ROM_QSTR(MP_QSTR_PERIODIC), MP_ROM_INT(TIMER_MODE_PERIODIC) },
-};
-STATIC MP_DEFINE_CONST_DICT(machine_timer_locals_dict, machine_timer_locals_dict_table);
-
-const mp_obj_type_t machine_timer_type = {
- { &mp_type_type },
- .name = MP_QSTR_Timer,
- .print = machine_timer_print,
- .make_new = machine_timer_make_new,
- .locals_dict = (mp_obj_dict_t *)&machine_timer_locals_dict,
-};
diff --git a/ports/mimxrt/machine_uart.c b/ports/mimxrt/machine_uart.c
index 115d9226bf8b..ac9351da8a30 100644
--- a/ports/mimxrt/machine_uart.c
+++ b/ports/mimxrt/machine_uart.c
@@ -33,6 +33,7 @@
#include "fsl_lpuart.h"
#include "fsl_iomuxc.h"
#include CLOCK_CONFIG_H
+#include "pin.h"
#define DEFAULT_UART_BAUDRATE (115200)
#define DEFAULT_BUFFER_SIZE (256)
@@ -221,7 +222,7 @@ STATIC mp_obj_t machine_uart_init_helper(machine_uart_obj_t *self, size_t n_args
self->timeout_char = min_timeout_char;
}
- LPUART_Init(self->lpuart, &self->config, BOARD_BOOTCLOCKRUN_UART_CLK_ROOT); // ??
+ LPUART_Init(self->lpuart, &self->config, BOARD_BOOTCLOCKRUN_UART_CLK_ROOT);
LPUART_TransferCreateHandle(self->lpuart, &self->handle, LPUART_UserCallback, self);
uint8_t *buffer = m_new(uint8_t, rxbuf_len + 1);
LPUART_TransferStartRingBuffer(self->lpuart, &self->handle, buffer, rxbuf_len);
@@ -244,12 +245,6 @@ STATIC mp_obj_t machine_uart_init_helper(machine_uart_obj_t *self, size_t n_args
LPUART_EnableTx(self->lpuart, false);
self->lpuart->STAT |= 1 << LPUART_STAT_BRK13_SHIFT;
LPUART_EnableTx(self->lpuart, true);
-
- // Allocate the TX ring buffer. Not used yet, but maybe later.
-
- // ringbuf_alloc(&(self->write_buffer), txbuf_len + 1);
- // MP_STATE_PORT(rp2_uart_tx_buffer[uart_id]) = self->write_buffer.buf;
-
}
return MP_OBJ_FROM_PTR(self);
@@ -308,17 +303,30 @@ STATIC mp_obj_t machine_uart_sendbreak(mp_obj_t self_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_uart_sendbreak_obj, machine_uart_sendbreak);
+STATIC mp_obj_t machine_uart_txdone(mp_obj_t self_in) {
+ machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in);
+
+ if (self->tx_status == kStatus_LPUART_TxIdle) {
+ return mp_const_true;
+ } else {
+ return mp_const_false;
+ }
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_uart_txdone_obj, machine_uart_txdone);
+
STATIC const mp_rom_map_elem_t machine_uart_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_uart_init_obj) },
{ MP_ROM_QSTR(MP_QSTR_any), MP_ROM_PTR(&machine_uart_any_obj) },
+ { MP_ROM_QSTR(MP_QSTR_flush), MP_ROM_PTR(&mp_stream_flush_obj) },
{ MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) },
{ MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) },
{ MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) },
{ MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) },
{ MP_ROM_QSTR(MP_QSTR_sendbreak), MP_ROM_PTR(&machine_uart_sendbreak_obj) },
+ { MP_ROM_QSTR(MP_QSTR_txdone), MP_ROM_PTR(&machine_uart_txdone_obj) },
{ MP_ROM_QSTR(MP_QSTR_INV_TX), MP_ROM_INT(UART_INVERT_TX) },
{ MP_ROM_QSTR(MP_QSTR_INV_RX), MP_ROM_INT(UART_INVERT_RX) },
@@ -388,7 +396,7 @@ STATIC mp_uint_t machine_uart_write(mp_obj_t self_in, const void *buf_in, mp_uin
// Wait at least the number of character times for this chunk.
t = ticks_us64() + (uint64_t)xfer.dataSize * (13000000 / self->config.baudRate_Bps + 1000);
- while (self->handle.txDataSize) {
+ while (self->tx_status != kStatus_LPUART_TxIdle) {
// Wait for the first/next character to be sent.
if (ticks_us64() > t) { // timed out
if (self->handle.txDataSize >= size) {
@@ -430,9 +438,24 @@ STATIC mp_uint_t machine_uart_ioctl(mp_obj_t self_in, mp_uint_t request, mp_uint
ret |= MP_STREAM_POLL_RD;
}
}
- if ((flags & MP_STREAM_POLL_WR)) {
+ if ((flags & MP_STREAM_POLL_WR) && (self->tx_status == kStatus_LPUART_TxIdle)) {
ret |= MP_STREAM_POLL_WR;
}
+ } else if (request == MP_STREAM_FLUSH) {
+ // The timeout is estimated using the buffer size and the baudrate.
+ // Take the worst case assumptions at 13 bit symbol size times 2.
+ uint64_t timeout = (uint64_t)(3 + self->txbuf_len) * 13000000ll * 2 /
+ self->config.baudRate_Bps + ticks_us64();
+
+ do {
+ if (machine_uart_txdone((mp_obj_t)self) == mp_const_true) {
+ return 0;
+ }
+ MICROPY_EVENT_POLL_HOOK
+ } while (ticks_us64() < timeout);
+
+ *errcode = MP_ETIMEDOUT;
+ ret = MP_STREAM_ERROR;
} else {
*errcode = MP_EINVAL;
ret = MP_STREAM_ERROR;
@@ -447,13 +470,12 @@ STATIC const mp_stream_p_t uart_stream_p = {
.is_text = false,
};
-const mp_obj_type_t machine_uart_type = {
- { &mp_type_type },
- .name = MP_QSTR_UART,
- .print = machine_uart_print,
- .make_new = machine_uart_make_new,
- .getiter = mp_identity_getiter,
- .iternext = mp_stream_unbuffered_iter,
- .protocol = &uart_stream_p,
- .locals_dict = (mp_obj_dict_t *)&machine_uart_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ machine_uart_type,
+ MP_QSTR_UART,
+ MP_TYPE_FLAG_ITER_IS_STREAM,
+ make_new, machine_uart_make_new,
+ print, machine_uart_print,
+ protocol, &uart_stream_p,
+ locals_dict, &machine_uart_locals_dict
+ );
diff --git a/ports/mimxrt/machine_wdt.c b/ports/mimxrt/machine_wdt.c
index d09c464f69a3..f5f14f9ef7b2 100644
--- a/ports/mimxrt/machine_wdt.c
+++ b/ports/mimxrt/machine_wdt.c
@@ -99,9 +99,10 @@ STATIC const mp_rom_map_elem_t machine_wdt_locals_dict_table[] = {
};
STATIC MP_DEFINE_CONST_DICT(machine_wdt_locals_dict, machine_wdt_locals_dict_table);
-const mp_obj_type_t machine_wdt_type = {
- { &mp_type_type },
- .name = MP_QSTR_WDT,
- .make_new = machine_wdt_make_new,
- .locals_dict = (mp_obj_dict_t *)&machine_wdt_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ machine_wdt_type,
+ MP_QSTR_WDT,
+ MP_TYPE_FLAG_NONE,
+ make_new, machine_wdt_make_new,
+ locals_dict, &machine_wdt_locals_dict
+ );
diff --git a/ports/mimxrt/main.c b/ports/mimxrt/main.c
index 82e07868a1d4..1a85f21c6d13 100644
--- a/ports/mimxrt/main.c
+++ b/ports/mimxrt/main.c
@@ -33,6 +33,7 @@
#include "shared/readline/readline.h"
#include "shared/runtime/gchelper.h"
#include "shared/runtime/pyexec.h"
+#include "shared/runtime/softtimer.h"
#include "ticks.h"
#include "tusb.h"
#include "led.h"
@@ -57,9 +58,6 @@ int main(void) {
led_init();
pendsv_init();
- mp_stack_set_top(&_estack);
- mp_stack_set_limit(&_estack - &_sstack - 1024);
-
#if MICROPY_PY_LWIP
// lwIP doesn't allow to reinitialise itself by subsequent calls to this function
// because the system timeout list (next_timeout) is only ever reset by BSS clearing.
@@ -68,10 +66,14 @@ int main(void) {
#if LWIP_MDNS_RESPONDER
mdns_resp_init();
#endif
+
systick_enable_dispatch(SYSTICK_DISPATCH_LWIP, mod_network_lwip_poll_wrapper);
#endif
for (;;) {
+ mp_stack_set_top(&_estack);
+ mp_stack_set_limit(&_estack - &_sstack - 1024);
+
gc_init(&_gc_heap_start, &_gc_heap_end);
mp_init();
@@ -83,7 +85,7 @@ int main(void) {
readline_init0();
// Execute _boot.py to set up the filesystem.
- pyexec_frozen_module("_boot.py");
+ pyexec_frozen_module("_boot.py", false);
// Execute user scripts.
int ret = pyexec_file_if_exists("boot.py");
@@ -120,6 +122,7 @@ int main(void) {
mod_network_deinit();
#endif
machine_pwm_deinit_all();
+ soft_timer_deinit();
gc_sweep_all();
mp_deinit();
}
diff --git a/ports/mimxrt/mbedtls/mbedtls_config.h b/ports/mimxrt/mbedtls/mbedtls_config.h
index 8e054ed51713..4140bb514555 100644
--- a/ports/mimxrt/mbedtls/mbedtls_config.h
+++ b/ports/mimxrt/mbedtls/mbedtls_config.h
@@ -26,74 +26,10 @@
#ifndef MICROPY_INCLUDED_MBEDTLS_CONFIG_H
#define MICROPY_INCLUDED_MBEDTLS_CONFIG_H
-// Set mbedtls configuration
-#define MBEDTLS_PLATFORM_MEMORY
-#define MBEDTLS_PLATFORM_NO_STD_FUNCTIONS
-#define MBEDTLS_DEPRECATED_REMOVED
-#define MBEDTLS_ENTROPY_HARDWARE_ALT
-#define MBEDTLS_AES_ROM_TABLES
-#define MBEDTLS_CIPHER_MODE_CBC
-#define MBEDTLS_ECP_DP_SECP192R1_ENABLED
-#define MBEDTLS_ECP_DP_SECP224R1_ENABLED
-#define MBEDTLS_ECP_DP_SECP256R1_ENABLED
-#define MBEDTLS_ECP_DP_SECP384R1_ENABLED
-#define MBEDTLS_ECP_DP_SECP521R1_ENABLED
-#define MBEDTLS_ECP_DP_SECP192K1_ENABLED
-#define MBEDTLS_ECP_DP_SECP224K1_ENABLED
-#define MBEDTLS_ECP_DP_SECP256K1_ENABLED
-#define MBEDTLS_ECP_DP_BP256R1_ENABLED
-#define MBEDTLS_ECP_DP_BP384R1_ENABLED
-#define MBEDTLS_ECP_DP_BP512R1_ENABLED
-#define MBEDTLS_ECP_DP_CURVE25519_ENABLED
-#define MBEDTLS_KEY_EXCHANGE_RSA_ENABLED
-#define MBEDTLS_NO_PLATFORM_ENTROPY
-#define MBEDTLS_PKCS1_V15
-#define MBEDTLS_SHA256_SMALLER
-#define MBEDTLS_SSL_PROTO_TLS1
-#define MBEDTLS_SSL_PROTO_TLS1_1
-#define MBEDTLS_SSL_PROTO_TLS1_2
-#define MBEDTLS_SSL_SERVER_NAME_INDICATION
+// Set MicroPython-specific options.
+#define MICROPY_MBEDTLS_CONFIG_BARE_METAL (1)
-// Use a smaller output buffer to reduce size of SSL context
-#define MBEDTLS_SSL_MAX_CONTENT_LEN (16384)
-#define MBEDTLS_SSL_IN_CONTENT_LEN (MBEDTLS_SSL_MAX_CONTENT_LEN)
-#define MBEDTLS_SSL_OUT_CONTENT_LEN (4096)
-
-// Enable mbedtls modules
-#define MBEDTLS_AES_C
-#define MBEDTLS_ASN1_PARSE_C
-#define MBEDTLS_BIGNUM_C
-#define MBEDTLS_CIPHER_C
-#define MBEDTLS_CTR_DRBG_C
-// #define MBEDTLS_ECP_C
-#define MBEDTLS_ENTROPY_C
-#define MBEDTLS_ERROR_C
-#define MBEDTLS_MD_C
-#define MBEDTLS_MD5_C
-#define MBEDTLS_OID_C
-#define MBEDTLS_PKCS5_C
-#define MBEDTLS_PK_C
-#define MBEDTLS_PK_PARSE_C
-#define MBEDTLS_PLATFORM_C
-#define MBEDTLS_RSA_C
-#define MBEDTLS_SHA1_C
-#define MBEDTLS_SHA256_C
-#define MBEDTLS_SHA512_C
-#define MBEDTLS_SSL_CLI_C
-#define MBEDTLS_SSL_SRV_C
-#define MBEDTLS_SSL_TLS_C
-#define MBEDTLS_X509_CRT_PARSE_C
-#define MBEDTLS_X509_USE_C
-
-// Memory allocation hooks
-#include
-#include
-void *m_tracked_calloc(size_t nmemb, size_t size);
-void m_tracked_free(void *ptr);
-#define MBEDTLS_PLATFORM_STD_CALLOC m_tracked_calloc
-#define MBEDTLS_PLATFORM_STD_FREE m_tracked_free
-#define MBEDTLS_PLATFORM_SNPRINTF_MACRO snprintf
-
-#include "mbedtls/check_config.h"
+// Include common mbedtls configuration.
+#include "extmod/mbedtls/mbedtls_config_common.h"
#endif /* MICROPY_INCLUDED_MBEDTLS_CONFIG_H */
diff --git a/ports/mimxrt/mbedtls/mbedtls_port.c b/ports/mimxrt/mbedtls/mbedtls_port.c
index e2002274b1c4..a9db174726ad 100644
--- a/ports/mimxrt/mbedtls/mbedtls_port.c
+++ b/ports/mimxrt/mbedtls/mbedtls_port.c
@@ -26,14 +26,14 @@
#ifdef MICROPY_SSL_MBEDTLS
-#include "fsl_trng.h"
#include "mbedtls_config.h"
+void trng_random_data(unsigned char *output, size_t len);
int mbedtls_hardware_poll(void *data, unsigned char *output, size_t len, size_t *olen) {
// assumes that TRNG_Init was called during startup
*olen = len;
- TRNG_GetRandomData(TRNG, output, len);
+ trng_random_data(output, len);
return 0;
}
diff --git a/ports/mimxrt/mimxrt_flash.c b/ports/mimxrt/mimxrt_flash.c
index 27ab987ed17f..536fb6098170 100644
--- a/ports/mimxrt/mimxrt_flash.c
+++ b/ports/mimxrt/mimxrt_flash.c
@@ -68,7 +68,7 @@ status_t flash_erase_block(uint32_t erase_addr) {
SCB_CleanInvalidateDCache();
SCB_DisableDCache();
__disable_irq();
- status = flexspi_nor_flash_erase_sector(FLEXSPI, erase_addr);
+ status = flexspi_nor_flash_erase_sector(BOARD_FLEX_SPI, erase_addr);
__enable_irq();
SCB_EnableDCache();
return status;
@@ -93,7 +93,7 @@ status_t flash_write_block(uint32_t dest_addr, const uint8_t *src, uint32_t leng
size = length;
}
__disable_irq();
- status = flexspi_nor_flash_page_program(FLEXSPI, dest_addr, (uint32_t *)src, size);
+ status = flexspi_nor_flash_page_program(BOARD_FLEX_SPI, dest_addr, (uint32_t *)src, size);
__enable_irq();
if (status != kStatus_Success) {
break;
@@ -112,15 +112,15 @@ STATIC mp_obj_t mimxrt_flash_make_new(const mp_obj_type_t *type, size_t n_args,
// Upload the custom flash configuration
// This should be performed by the boot ROM but for some reason it is not.
- FLEXSPI_UpdateLUT(FLEXSPI, 0,
+ FLEXSPI_UpdateLUT(BOARD_FLEX_SPI, 0,
qspiflash_config.memConfig.lookupTable,
ARRAY_SIZE(qspiflash_config.memConfig.lookupTable));
- // Configure FLEXSPI IP FIFO access.
- FLEXSPI->MCR0 &= ~(FLEXSPI_MCR0_ARDFEN_MASK);
- FLEXSPI->MCR0 &= ~(FLEXSPI_MCR0_ATDFEN_MASK);
- FLEXSPI->MCR0 |= FLEXSPI_MCR0_ARDFEN(0);
- FLEXSPI->MCR0 |= FLEXSPI_MCR0_ATDFEN(0);
+ // Configure BOARD_FLEX_SPI IP FIFO access.
+ BOARD_FLEX_SPI->MCR0 &= ~(FLEXSPI_MCR0_ARDFEN_MASK);
+ BOARD_FLEX_SPI->MCR0 &= ~(FLEXSPI_MCR0_ATDFEN_MASK);
+ BOARD_FLEX_SPI->MCR0 |= FLEXSPI_MCR0_ARDFEN(0);
+ BOARD_FLEX_SPI->MCR0 |= FLEXSPI_MCR0_ATDFEN(0);
// Update information based on linker symbols.
mimxrt_flash_obj.flash_base = MICROPY_HW_FLASH_STORAGE_BASE;
@@ -142,7 +142,7 @@ STATIC mp_obj_t mimxrt_flash_readblocks(size_t n_args, const mp_obj_t *args) {
if (n_args == 4) {
offset += mp_obj_get_int(args[3]);
}
- memcpy(bufinfo.buf, (uint8_t *)(FlexSPI_AMBA_BASE + self->flash_base + offset), bufinfo.len);
+ memcpy(bufinfo.buf, (uint8_t *)(BOARD_FLEX_SPI_ADDR_BASE + self->flash_base + offset), bufinfo.len);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mimxrt_flash_readblocks_obj, 3, 4, mimxrt_flash_readblocks);
@@ -215,9 +215,10 @@ STATIC const mp_rom_map_elem_t mimxrt_flash_locals_dict_table[] = {
};
STATIC MP_DEFINE_CONST_DICT(mimxrt_flash_locals_dict, mimxrt_flash_locals_dict_table);
-const mp_obj_type_t mimxrt_flash_type = {
- { &mp_type_type },
- .name = MP_QSTR_Flash,
- .make_new = mimxrt_flash_make_new,
- .locals_dict = (mp_obj_dict_t *)&mimxrt_flash_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ mimxrt_flash_type,
+ MP_QSTR_Flash,
+ MP_TYPE_FLAG_NONE,
+ make_new, mimxrt_flash_make_new,
+ locals_dict, &mimxrt_flash_locals_dict
+ );
diff --git a/ports/mimxrt/mimxrt_sdram.c b/ports/mimxrt/mimxrt_sdram.c
index 8c336bb607ef..c6c1776a554c 100644
--- a/ports/mimxrt/mimxrt_sdram.c
+++ b/ports/mimxrt/mimxrt_sdram.c
@@ -29,123 +29,176 @@
#include "modmachine.h"
#include "fsl_semc.h"
#include "fsl_iomuxc.h"
+#include "fsl_clock.h"
// Linker symbols
extern uint8_t __sdram_start;
+#if defined(MIMXRT117x_SERIES)
+// Pull Up, High drive strength
+#define SDRAM_PIN_CONFIG (0x07UL)
+#else
+// Pull up 22K, high slew rate
+#define SDRAM_PIN_CONFIG (0xE1UL)
+#endif
void mimxrt_sdram_init(void) {
+
+ #if !defined(MIMXRT117x_SERIES)
// Set Clocks
CLOCK_InitSysPfd(kCLOCK_Pfd2, 29); // '29' PLL2 PFD2 frequency = 528MHz * 18 / 29 = 327.72MHz (with 528MHz = PLL2 frequency)
CLOCK_SetMux(kCLOCK_SemcAltMux, 0); // '0' PLL2 PFD2 will be selected as alternative clock for SEMC root clock
CLOCK_SetMux(kCLOCK_SemcMux, 1); // '1' SEMC alternative clock will be used as SEMC clock root
CLOCK_SetDiv(kCLOCK_SemcDiv, 1); // '1' divide by 2 -> SEMC clock = 163.86 MHz
+ #endif
// Set Pins
- // Data Pins
+ // Data Pins 0..15
IOMUXC_SetPinMux(MIMXRT_IOMUXC_SEMC_DATA00, 0UL);
- IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_DATA00, 0xE1UL);
+ IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_DATA00, SDRAM_PIN_CONFIG);
IOMUXC_SetPinMux(MIMXRT_IOMUXC_SEMC_DATA01, 0UL);
- IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_DATA01, 0xE1UL);
+ IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_DATA01, SDRAM_PIN_CONFIG);
IOMUXC_SetPinMux(MIMXRT_IOMUXC_SEMC_DATA02, 0UL);
- IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_DATA02, 0xE1UL);
+ IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_DATA02, SDRAM_PIN_CONFIG);
IOMUXC_SetPinMux(MIMXRT_IOMUXC_SEMC_DATA03, 0UL);
- IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_DATA03, 0xE1UL);
+ IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_DATA03, SDRAM_PIN_CONFIG);
IOMUXC_SetPinMux(MIMXRT_IOMUXC_SEMC_DATA04, 0UL);
- IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_DATA04, 0xE1UL);
+ IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_DATA04, SDRAM_PIN_CONFIG);
IOMUXC_SetPinMux(MIMXRT_IOMUXC_SEMC_DATA05, 0UL);
- IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_DATA05, 0xE1UL);
+ IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_DATA05, SDRAM_PIN_CONFIG);
IOMUXC_SetPinMux(MIMXRT_IOMUXC_SEMC_DATA06, 0UL);
- IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_DATA06, 0xE1UL);
+ IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_DATA06, SDRAM_PIN_CONFIG);
IOMUXC_SetPinMux(MIMXRT_IOMUXC_SEMC_DATA07, 0UL);
- IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_DATA07, 0xE1UL);
+ IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_DATA07, SDRAM_PIN_CONFIG);
IOMUXC_SetPinMux(MIMXRT_IOMUXC_SEMC_DATA08, 0UL);
- IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_DATA08, 0xE1UL);
+ IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_DATA08, SDRAM_PIN_CONFIG);
IOMUXC_SetPinMux(MIMXRT_IOMUXC_SEMC_DATA09, 0UL);
- IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_DATA09, 0xE1UL);
+ IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_DATA09, SDRAM_PIN_CONFIG);
IOMUXC_SetPinMux(MIMXRT_IOMUXC_SEMC_DATA10, 0UL);
- IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_DATA10, 0xE1UL);
+ IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_DATA10, SDRAM_PIN_CONFIG);
IOMUXC_SetPinMux(MIMXRT_IOMUXC_SEMC_DATA11, 0UL);
- IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_DATA11, 0xE1UL);
+ IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_DATA11, SDRAM_PIN_CONFIG);
IOMUXC_SetPinMux(MIMXRT_IOMUXC_SEMC_DATA12, 0UL);
- IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_DATA12, 0xE1UL);
+ IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_DATA12, SDRAM_PIN_CONFIG);
IOMUXC_SetPinMux(MIMXRT_IOMUXC_SEMC_DATA13, 0UL);
- IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_DATA13, 0xE1UL);
+ IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_DATA13, SDRAM_PIN_CONFIG);
IOMUXC_SetPinMux(MIMXRT_IOMUXC_SEMC_DATA14, 0UL);
- IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_DATA14, 0xE1UL);
+ IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_DATA14, SDRAM_PIN_CONFIG);
IOMUXC_SetPinMux(MIMXRT_IOMUXC_SEMC_DATA15, 0UL);
- IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_DATA15, 0xE1UL);
+ IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_DATA15, SDRAM_PIN_CONFIG);
// Address Pins
IOMUXC_SetPinMux(MIMXRT_IOMUXC_SEMC_ADDR00, 0UL);
- IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_ADDR00, 0xE1UL);
+ IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_ADDR00, SDRAM_PIN_CONFIG);
IOMUXC_SetPinMux(MIMXRT_IOMUXC_SEMC_ADDR01, 0UL);
- IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_ADDR01, 0xE1UL);
+ IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_ADDR01, SDRAM_PIN_CONFIG);
IOMUXC_SetPinMux(MIMXRT_IOMUXC_SEMC_ADDR02, 0UL);
- IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_ADDR02, 0xE1UL);
+ IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_ADDR02, SDRAM_PIN_CONFIG);
IOMUXC_SetPinMux(MIMXRT_IOMUXC_SEMC_ADDR03, 0UL);
- IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_ADDR03, 0xE1UL);
+ IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_ADDR03, SDRAM_PIN_CONFIG);
IOMUXC_SetPinMux(MIMXRT_IOMUXC_SEMC_ADDR04, 0UL);
- IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_ADDR04, 0xE1UL);
+ IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_ADDR04, SDRAM_PIN_CONFIG);
IOMUXC_SetPinMux(MIMXRT_IOMUXC_SEMC_ADDR05, 0UL);
- IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_ADDR05, 0xE1UL);
+ IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_ADDR05, SDRAM_PIN_CONFIG);
IOMUXC_SetPinMux(MIMXRT_IOMUXC_SEMC_ADDR06, 0UL);
- IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_ADDR06, 0xE1UL);
+ IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_ADDR06, SDRAM_PIN_CONFIG);
IOMUXC_SetPinMux(MIMXRT_IOMUXC_SEMC_ADDR07, 0UL);
- IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_ADDR07, 0xE1UL);
+ IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_ADDR07, SDRAM_PIN_CONFIG);
IOMUXC_SetPinMux(MIMXRT_IOMUXC_SEMC_ADDR08, 0UL);
- IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_ADDR08, 0xE1UL);
+ IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_ADDR08, SDRAM_PIN_CONFIG);
IOMUXC_SetPinMux(MIMXRT_IOMUXC_SEMC_ADDR09, 0UL);
- IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_ADDR09, 0xE1UL);
+ IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_ADDR09, SDRAM_PIN_CONFIG);
IOMUXC_SetPinMux(MIMXRT_IOMUXC_SEMC_ADDR10, 0UL);
- IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_ADDR10, 0xE1UL);
+ IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_ADDR10, SDRAM_PIN_CONFIG);
IOMUXC_SetPinMux(MIMXRT_IOMUXC_SEMC_ADDR11, 0UL);
- IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_ADDR11, 0xE1UL);
+ IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_ADDR11, SDRAM_PIN_CONFIG);
IOMUXC_SetPinMux(MIMXRT_IOMUXC_SEMC_ADDR12, 0UL);
- IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_ADDR12, 0xE1UL);
+ IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_ADDR12, SDRAM_PIN_CONFIG);
IOMUXC_SetPinMux(MIMXRT_IOMUXC_SEMC_DM00, 0UL);
- IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_DM00, 0xE1UL);
+ IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_DM00, SDRAM_PIN_CONFIG);
IOMUXC_SetPinMux(MIMXRT_IOMUXC_SEMC_BA0, 0UL);
- IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_BA0, 0xE1UL);
+ IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_BA0, SDRAM_PIN_CONFIG);
IOMUXC_SetPinMux(MIMXRT_IOMUXC_SEMC_BA1, 0UL);
- IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_BA1, 0xE1UL);
+ IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_BA1, SDRAM_PIN_CONFIG);
IOMUXC_SetPinMux(MIMXRT_IOMUXC_SEMC_CAS, 0UL);
- IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_CAS, 0xE1UL);
+ IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_CAS, SDRAM_PIN_CONFIG);
IOMUXC_SetPinMux(MIMXRT_IOMUXC_SEMC_RAS, 0UL);
- IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_RAS, 0xE1UL);
+ IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_RAS, SDRAM_PIN_CONFIG);
IOMUXC_SetPinMux(MIMXRT_IOMUXC_SEMC_CLK, 0UL);
- IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_CLK, 0xE1UL);
+ IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_CLK, SDRAM_PIN_CONFIG);
IOMUXC_SetPinMux(MIMXRT_IOMUXC_SEMC_CKE, 0UL);
- IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_CKE, 0xE1UL);
+ IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_CKE, SDRAM_PIN_CONFIG);
IOMUXC_SetPinMux(MIMXRT_IOMUXC_SEMC_WE, 0UL);
- IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_WE, 0xE1UL);
+ IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_WE, SDRAM_PIN_CONFIG);
IOMUXC_SetPinMux(MIMXRT_IOMUXC_SEMC_DM01, 0UL);
- IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_DM01, 0xE1UL);
+ IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_DM01, SDRAM_PIN_CONFIG);
IOMUXC_SetPinMux(MIMXRT_IOMUXC_SEMC_DQS, 1UL);
- IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_DQS, 0xE1UL);
+ IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_DQS, SDRAM_PIN_CONFIG);
+
+ #if defined(MIMXRT117x_SERIES)
+ // Data Pins 16..31
+ IOMUXC_SetPinMux(MIMXRT_IOMUXC_SEMC_DATA16, 0UL);
+ IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_DATA16, SDRAM_PIN_CONFIG);
+ IOMUXC_SetPinMux(MIMXRT_IOMUXC_SEMC_DATA17, 0UL);
+ IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_DATA17, SDRAM_PIN_CONFIG);
+ IOMUXC_SetPinMux(MIMXRT_IOMUXC_SEMC_DATA18, 0UL);
+ IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_DATA18, SDRAM_PIN_CONFIG);
+ IOMUXC_SetPinMux(MIMXRT_IOMUXC_SEMC_DATA19, 0UL);
+ IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_DATA19, SDRAM_PIN_CONFIG);
+ IOMUXC_SetPinMux(MIMXRT_IOMUXC_SEMC_DATA20, 0UL);
+ IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_DATA20, SDRAM_PIN_CONFIG);
+ IOMUXC_SetPinMux(MIMXRT_IOMUXC_SEMC_DATA21, 0UL);
+ IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_DATA21, SDRAM_PIN_CONFIG);
+ IOMUXC_SetPinMux(MIMXRT_IOMUXC_SEMC_DATA22, 0UL);
+ IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_DATA22, SDRAM_PIN_CONFIG);
+ IOMUXC_SetPinMux(MIMXRT_IOMUXC_SEMC_DATA23, 0UL);
+ IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_DATA23, SDRAM_PIN_CONFIG);
+ IOMUXC_SetPinMux(MIMXRT_IOMUXC_SEMC_DATA24, 0UL);
+ IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_DATA24, SDRAM_PIN_CONFIG);
+ IOMUXC_SetPinMux(MIMXRT_IOMUXC_SEMC_DATA25, 0UL);
+ IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_DATA25, SDRAM_PIN_CONFIG);
+ IOMUXC_SetPinMux(MIMXRT_IOMUXC_SEMC_DATA26, 0UL);
+ IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_DATA26, SDRAM_PIN_CONFIG);
+ IOMUXC_SetPinMux(MIMXRT_IOMUXC_SEMC_DATA27, 0UL);
+ IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_DATA27, SDRAM_PIN_CONFIG);
+ IOMUXC_SetPinMux(MIMXRT_IOMUXC_SEMC_DATA28, 0UL);
+ IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_DATA28, SDRAM_PIN_CONFIG);
+ IOMUXC_SetPinMux(MIMXRT_IOMUXC_SEMC_DATA29, 0UL);
+ IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_DATA29, SDRAM_PIN_CONFIG);
+ IOMUXC_SetPinMux(MIMXRT_IOMUXC_SEMC_DATA30, 0UL);
+ IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_DATA30, SDRAM_PIN_CONFIG);
+ IOMUXC_SetPinMux(MIMXRT_IOMUXC_SEMC_DATA31, 0UL);
+ IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_DATA31, SDRAM_PIN_CONFIG);
+
+ IOMUXC_SetPinMux(MIMXRT_IOMUXC_SEMC_DM02, 0UL);
+ IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_DM02, SDRAM_PIN_CONFIG);
+ IOMUXC_SetPinMux(MIMXRT_IOMUXC_SEMC_DM03, 0UL);
+ IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_DM03, SDRAM_PIN_CONFIG);
+
+ #endif
// Chip Select Pins
#ifndef MIMXRT_IOMUXC_SEMC_CS0
#error No SEMC CS0 defined!
#endif
IOMUXC_SetPinMux(MIMXRT_IOMUXC_SEMC_CS0, 0UL);
- IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_CS0, 0xE1UL);
+ IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_CS0, SDRAM_PIN_CONFIG);
#ifdef MIMXRT_IOMUXC_SEMC_CS1
IOMUXC_SetPinMux(MIMXRT_IOMUXC_SEMC_CS1, 0UL);
- IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_CS1, 0xE1UL);
+ IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_CS1, SDRAM_PIN_CONFIG);
#endif
#ifdef MIMXRT_IOMUXC_SEMC_CS2
IOMUXC_SetPinMux(MIMXRT_IOMUXC_SEMC_CS2, 0UL);
- IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_CS2, 0xE1UL);
+ IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_CS2, SDRAM_PIN_CONFIG);
#endif
#ifdef MIMXRT_IOMUXC_SEMC_CS3
IOMUXC_SetPinMux(MIMXRT_IOMUXC_SEMC_CS3, 0UL);
- IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_CS3, 0xE1UL);
+ IOMUXC_SetPinConfig(MIMXRT_IOMUXC_SEMC_CS3, SDRAM_PIN_CONFIG);
#endif
// Configure SEMC
@@ -155,6 +208,36 @@ void mimxrt_sdram_init(void) {
semc_cfg.dqsMode = kSEMC_Loopbackdqspad; // For more accurate timing.
SEMC_Init(SEMC, &semc_cfg);
+ #if defined(MIMXRT117x_SERIES)
+
+ uint32_t clock_freq = CLOCK_GetRootClockFreq(kCLOCK_Root_Semc);
+
+ semc_sdram_config_t sdram_cfg = {
+ .csxPinMux = kSEMC_MUXCSX0,
+ .address = 0x80000000,
+ .memsize_kbytes = (MICROPY_HW_SDRAM_SIZE >> 10),
+ .portSize = kSEMC_PortSize32Bit, // two 16-bit SDRAMs make up 32-bit portsize
+ .burstLen = kSEMC_Sdram_BurstLen8,
+ .columnAddrBitNum = kSEMC_SdramColunm_9bit,
+ .casLatency = kSEMC_LatencyThree,
+ .tPrecharge2Act_Ns = 15, // tRP 15ns
+ .tAct2ReadWrite_Ns = 15, // tRCD 15ns
+ .tRefreshRecovery_Ns = 70, // Use the maximum of the (Trfc , Txsr).
+ .tWriteRecovery_Ns = 2, // tWR 2ns
+ .tCkeOff_Ns = 42, // The minimum cycle of SDRAM CLK off state. CKE is off in self refresh at a minimum period tRAS.
+ .tAct2Prechage_Ns = 40, // tRAS 40ns
+ .tSelfRefRecovery_Ns = 70,
+ .tRefresh2Refresh_Ns = 60,
+ .tAct2Act_Ns = 2, // tRC/tRDD 2ns
+ .tPrescalePeriod_Ns = 160 * (1000000000 / clock_freq),
+ .refreshPeriod_nsPerRow = 64 * 1000000 / 8192, // 64ms/8192
+ .refreshUrgThreshold = sdram_cfg.refreshPeriod_nsPerRow,
+ .refreshBurstLen = 1,
+ .delayChain = 2,
+ };
+
+ #else
+
uint32_t clock_freq = CLOCK_GetFreq(kCLOCK_SemcClk);
semc_sdram_config_t sdram_cfg = {
.csxPinMux = kSEMC_MUXCSX0,
@@ -180,6 +263,8 @@ void mimxrt_sdram_init(void) {
.refreshBurstLen = 1
};
+ #endif
+
(status_t)SEMC_ConfigureSDRAM(SEMC, kSEMC_SDRAM_CS0, &sdram_cfg, clock_freq);
}
diff --git a/ports/mimxrt/modmachine.c b/ports/mimxrt/modmachine.c
index ad4e4a59412e..049499cb2ed0 100644
--- a/ports/mimxrt/modmachine.c
+++ b/ports/mimxrt/modmachine.c
@@ -26,6 +26,7 @@
*/
#include "py/runtime.h"
+#include "drivers/dht/dht.h"
#include "extmod/machine_bitstream.h"
#include "extmod/machine_mem.h"
#include "extmod/machine_i2c.h"
@@ -36,8 +37,10 @@
#include "led.h"
#include "pin.h"
#include "modmachine.h"
-#include "fsl_clock.h"
#include "fsl_wdog.h"
+#if FSL_FEATURE_BOOT_ROM_HAS_ROMAPI
+#include "fsl_romapi.h"
+#endif
#if MICROPY_PY_MACHINE
@@ -108,6 +111,24 @@ STATIC mp_obj_t machine_enable_irq(mp_obj_t state_in) {
}
MP_DEFINE_CONST_FUN_OBJ_1(machine_enable_irq_obj, machine_enable_irq);
+NORETURN mp_obj_t machine_bootloader(size_t n_args, const mp_obj_t *args) {
+ #if defined(MICROPY_BOARD_ENTER_BOOTLOADER)
+ // If a board has a custom bootloader, call it first.
+ MICROPY_BOARD_ENTER_BOOTLOADER(n_args, args);
+ #elif FSL_ROM_HAS_RUNBOOTLOADER_API
+ // If not, enter ROM bootloader in serial downloader / USB mode.
+ uint32_t arg = 0xEB110000;
+ ROM_RunBootloader(&arg);
+ #else
+ // No custom bootloader, or run bootloader API, then just reset.
+ WDOG_TriggerSystemSoftwareReset(WDOG1);
+ #endif
+ while (1) {
+ ;
+ }
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_bootloader_obj, 0, 1, machine_bootloader);
+
STATIC const mp_rom_map_elem_t machine_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_umachine) },
{ MP_ROM_QSTR(MP_QSTR_unique_id), MP_ROM_PTR(&machine_unique_id_obj) },
@@ -144,11 +165,13 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_disable_irq), MP_ROM_PTR(&machine_disable_irq_obj) },
{ MP_ROM_QSTR(MP_QSTR_enable_irq), MP_ROM_PTR(&machine_enable_irq_obj) },
+ { MP_ROM_QSTR(MP_QSTR_bootloader), MP_ROM_PTR(&machine_bootloader_obj) },
#if MICROPY_PY_MACHINE_BITSTREAM
{ MP_ROM_QSTR(MP_QSTR_bitstream), MP_ROM_PTR(&machine_bitstream_obj) },
#endif
{ MP_ROM_QSTR(MP_QSTR_time_pulse_us), MP_ROM_PTR(&machine_time_pulse_us_obj) },
+ { MP_ROM_QSTR(MP_QSTR_dht_readinto), MP_ROM_PTR(&dht_readinto_obj) },
// Reset reasons
{ MP_ROM_QSTR(MP_QSTR_PWRON_RESET), MP_ROM_INT(MP_PWRON_RESET) },
diff --git a/ports/mimxrt/modmimxrt.c b/ports/mimxrt/modmimxrt.c
index 9dd38ee07f30..4756efc0a27e 100644
--- a/ports/mimxrt/modmimxrt.c
+++ b/ports/mimxrt/modmimxrt.c
@@ -26,14 +26,11 @@
#include "py/mperrno.h"
#include "py/runtime.h"
-#include "drivers/dht/dht.h"
#include "modmimxrt.h"
STATIC const mp_rom_map_elem_t mimxrt_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_mimxrt) },
{ MP_ROM_QSTR(MP_QSTR_Flash), MP_ROM_PTR(&mimxrt_flash_type) },
-
- { MP_ROM_QSTR(MP_QSTR_dht_readinto), MP_ROM_PTR(&dht_readinto_obj) },
};
STATIC MP_DEFINE_CONST_DICT(mimxrt_module_globals, mimxrt_module_globals_table);
diff --git a/ports/mimxrt/moduos.c b/ports/mimxrt/moduos.c
index 34bd2b424876..b3f97693fa5a 100644
--- a/ports/mimxrt/moduos.c
+++ b/ports/mimxrt/moduos.c
@@ -30,10 +30,44 @@
#include "py/runtime.h"
#include "py/mphal.h"
+
+#if defined(MIMXRT117x_SERIES)
+#include "fsl_caam.h"
+#else
#include "fsl_trng.h"
+#endif
static bool initialized = false;
+#if defined(MIMXRT117x_SERIES)
+STATIC caam_handle_t caam_handle;
+STATIC caam_rng_state_handle_t caam_state_handle = kCAAM_RngStateHandle0;
+
+#if defined(FSL_FEATURE_HAS_L1CACHE) || defined(__DCACHE_PRESENT)
+AT_NONCACHEABLE_SECTION(static caam_job_ring_interface_t s_jrif0);
+#else
+static caam_job_ring_interface_t s_jrif0;
+#endif
+
+STATIC void trng_start(void) {
+ caam_config_t config;
+
+ if (!initialized) {
+ CAAM_GetDefaultConfig(&config);
+ config.jobRingInterface[0] = &s_jrif0;
+ CAAM_Init(CAAM, &config);
+ initialized = true;
+ }
+}
+
+void trng_random_data(unsigned char *output, size_t len) {
+ trng_start();
+ CAAM_RNG_GetRandomData(CAAM, &caam_handle, caam_state_handle, output, len,
+ kCAAM_RngDataAny, NULL);
+}
+
+#else
+
STATIC void trng_start(void) {
trng_config_t trngConfig;
@@ -46,11 +80,18 @@ STATIC void trng_start(void) {
}
}
+void trng_random_data(unsigned char *output, size_t len) {
+ trng_start();
+ TRNG_GetRandomData(TRNG, output, len);
+}
+
+#endif
+
uint32_t trng_random_u32(void) {
uint32_t rngval;
trng_start();
- TRNG_GetRandomData(TRNG, (uint8_t *)&rngval, 4);
+ trng_random_data((uint8_t *)&rngval, 4);
return rngval;
}
@@ -61,9 +102,9 @@ STATIC mp_obj_t mp_uos_urandom(mp_obj_t num) {
vstr_init_len(&vstr, n);
trng_start();
- TRNG_GetRandomData(TRNG, vstr.buf, n);
+ trng_random_data((uint8_t *)vstr.buf, n);
- return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
+ return mp_obj_new_bytes_from_vstr(&vstr);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_uos_urandom_obj, mp_uos_urandom);
#endif
diff --git a/ports/mimxrt/mpconfigport.h b/ports/mimxrt/mpconfigport.h
index 1dcaccad4795..13b456932c71 100644
--- a/ports/mimxrt/mpconfigport.h
+++ b/ports/mimxrt/mpconfigport.h
@@ -29,12 +29,19 @@
// Board specific definitions
#include "mpconfigboard.h"
#include "fsl_common.h"
+#include "lib/nxp_driver/sdk/CMSIS/Include/core_cm7.h"
uint32_t trng_random_u32(void);
+// Config level
+#define MICROPY_CONFIG_ROM_LEVEL (MICROPY_CONFIG_ROM_LEVEL_FULL_FEATURES)
+
// Memory allocation policies
+#if MICROPY_HW_SDRAM_AVAIL
+#define MICROPY_GC_STACK_ENTRY_TYPE uint32_t
+#else
#define MICROPY_GC_STACK_ENTRY_TYPE uint16_t
-#define MICROPY_GC_ALLOC_THRESHOLD (0)
+#endif
#define MICROPY_ALLOC_PARSE_CHUNK_INIT (32)
#define MICROPY_ALLOC_PATH_MAX (256)
@@ -44,94 +51,31 @@ uint32_t trng_random_u32(void);
#define MICROPY_EMIT_INLINE_THUMB (1)
// Optimisations
-#define MICROPY_OPT_LOAD_ATTR_FAST_PATH (1)
-#define MICROPY_OPT_MAP_LOOKUP_CACHE (1)
// Python internal features
#define MICROPY_TRACKED_ALLOC (MICROPY_SSL_MBEDTLS)
#define MICROPY_READER_VFS (1)
#define MICROPY_ENABLE_GC (1)
-#define MICROPY_ENABLE_FINALISER (1)
-#define MICROPY_STACK_CHECK (1)
#define MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF (1)
-#define MICROPY_KBD_EXCEPTION (1)
-#define MICROPY_HELPER_REPL (1)
-#define MICROPY_REPL_AUTO_INDENT (1)
#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ)
-#define MICROPY_ENABLE_SOURCE_LINE (1)
-#define MICROPY_STREAMS_NON_BLOCK (1)
-#define MICROPY_MODULE_BUILTIN_INIT (1)
-#define MICROPY_MODULE_WEAK_LINKS (1)
-#define MICROPY_CAN_OVERRIDE_BUILTINS (1)
-#define MICROPY_ENABLE_SCHEDULER (1)
#define MICROPY_SCHEDULER_DEPTH (8)
#define MICROPY_VFS (1)
#define MICROPY_MODULE_FROZEN_MPY (1)
#define MICROPY_QSTR_EXTRA_POOL mp_qstr_frozen_const_pool
// Control over Python builtins
-#define MICROPY_PY_FUNCTION_ATTRS (1)
-#define MICROPY_PY_DESCRIPTORS (1)
-#define MICROPY_PY_DELATTR_SETATTR (1)
-#define MICROPY_PY_FSTRINGS (1)
-#define MICROPY_PY_BUILTINS_STR_UNICODE (1)
-#define MICROPY_PY_BUILTINS_STR_CENTER (1)
-#define MICROPY_PY_BUILTINS_STR_PARTITION (1)
-#define MICROPY_PY_BUILTINS_STR_SPLITLINES (1)
-#define MICROPY_PY_BUILTINS_MEMORYVIEW (1)
-#define MICROPY_PY_BUILTINS_SLICE_ATTRS (1)
-#define MICROPY_PY_BUILTINS_SLICE_INDICES (1)
-#define MICROPY_PY_BUILTINS_FROZENSET (1)
-#define MICROPY_PY_BUILTINS_ROUND_INT (1)
-#define MICROPY_PY_ALL_SPECIAL_METHODS (1)
-#define MICROPY_PY_REVERSE_SPECIAL_METHODS (1)
-#define MICROPY_PY_BUILTINS_COMPILE (1)
-#define MICROPY_PY_BUILTINS_INPUT (1)
-#define MICROPY_PY_BUILTINS_POW3 (1)
-#define MICROPY_PY_BUILTINS_HELP (1)
-#define MICROPY_PY_BUILTINS_HELP_MODULES (1)
#define MICROPY_PY_BUILTINS_HELP_TEXT mimxrt_help_text
-#define MICROPY_PY_MICROPYTHON_MEM_INFO (1)
-#define MICROPY_PY_ARRAY_SLICE_ASSIGN (1)
-#define MICROPY_PY_COLLECTIONS_DEQUE (1)
-#define MICROPY_PY_COLLECTIONS_ORDEREDDICT (1)
-#define MICROPY_PY_MATH_SPECIAL_FUNCTIONS (1)
-#define MICROPY_PY_MATH_FACTORIAL (1)
-#define MICROPY_PY_MATH_ISCLOSE (1)
-#define MICROPY_PY_CMATH (1)
-#define MICROPY_PY_IO_IOBASE (1)
-#define MICROPY_PY_IO_FILEIO (1)
-#define MICROPY_PY_SYS_MAXSIZE (1)
#define MICROPY_PY_SYS_PLATFORM "mimxrt"
-#define MICROPY_PY_SYS_STDFILES (1)
-#define MICROPY_PY_SYS_STDIO_BUFFER (1)
-#define MICROPY_PY_UERRNO (1)
// Extended modules
#define MICROPY_EPOCH_IS_1970 (1)
-#define MICROPY_PY_UASYNCIO (1)
-#define MICROPY_PY_UCTYPES (1)
-#define MICROPY_PY_UZLIB (1)
-#define MICROPY_PY_UJSON (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 (1)
#define MICROPY_PY_USSL_FINALISER (MICROPY_PY_USSL)
-#define MICROPY_PY_UHASHLIB (1)
-#define MICROPY_PY_UBINASCII (1)
-#define MICROPY_PY_UBINASCII_CRC32 (1)
#define MICROPY_PY_UTIME_MP_HAL (1)
-#define MICROPY_PY_UOS (1)
#define MICROPY_PY_UOS_INCLUDEFILE "ports/mimxrt/moduos.c"
#define MICROPY_PY_OS_DUPTERM (3)
#define MICROPY_PY_UOS_DUPTERM_NOTIFY (1)
#define MICROPY_PY_UOS_UNAME (1)
-#define MICROPY_PY_UOS_URANDOM (1)
-#define MICROPY_PY_URANDOM (1)
-#define MICROPY_PY_URANDOM_EXTRA_FUNCS (1)
#define MICROPY_PY_URANDOM_SEED_INIT_FUNC (trng_random_u32())
-#define MICROPY_PY_USELECT (1)
#define MICROPY_PY_MACHINE (1)
#define MICROPY_PY_MACHINE_PIN_MAKE_NEW mp_pin_make_new
#define MICROPY_PY_MACHINE_BITSTREAM (1)
@@ -147,7 +91,8 @@ uint32_t trng_random_u32(void);
#define MICROPY_PY_MACHINE_SOFTI2C (1)
#define MICROPY_PY_MACHINE_SPI (1)
#define MICROPY_PY_MACHINE_SOFTSPI (1)
-#define MICROPY_PY_FRAMEBUF (1)
+#define MICROPY_PY_MACHINE_TIMER (1)
+#define MICROPY_SOFT_TIMER_TICKS_MS systick_ms
#define MICROPY_PY_ONEWIRE (1)
#define MICROPY_PY_UPLATFORM (1)
@@ -157,22 +102,27 @@ uint32_t trng_random_u32(void);
#define MICROPY_FATFS_MAX_SS (4096)
#define MICROPY_FATFS_LFN_CODE_PAGE 437 /* 1=SFN/ANSI 437=LFN/U.S.(OEM) */
-// If MICROPY_PY_LWIP is defined, add network support
-#if MICROPY_PY_LWIP
-
+#ifndef MICROPY_PY_NETWORK
#define MICROPY_PY_NETWORK (1)
+#endif
+#ifndef MICROPY_PY_USOCKET
#define MICROPY_PY_USOCKET (1)
-#define MICROPY_PY_UWEBSOCKET (1)
-#define MICROPY_PY_WEBREPL (1)
-#define MICROPY_PY_UHASHLIB_SHA1 (1)
-#define MICROPY_PY_LWIP_SOCK_RAW (1)
-#define MICROPY_HW_ETH_MDC (1)
+#endif
+#define MICROPY_PY_UWEBSOCKET (MICROPY_PY_LWIP)
+#define MICROPY_PY_WEBREPL (MICROPY_PY_LWIP)
+#define MICROPY_PY_LWIP_SOCK_RAW (MICROPY_PY_LWIP)
+#define MICROPY_PY_USSL_FINALISER (MICROPY_PY_USSL)
+// #define MICROPY_PY_UHASHLIB_MD5 (MICROPY_PY_USSL)
+#define MICROPY_PY_UHASHLIB_SHA1 (MICROPY_PY_USSL)
+// #define MICROPY_PY_UCRYPTOLIB (MICROPY_PY_USSL)
// Prevent the "LWIP task" from running.
#define MICROPY_PY_LWIP_ENTER MICROPY_PY_PENDSV_ENTER
#define MICROPY_PY_LWIP_REENTER MICROPY_PY_PENDSV_REENTER
#define MICROPY_PY_LWIP_EXIT MICROPY_PY_PENDSV_EXIT
+#ifndef MICROPY_PY_NETWORK_HOSTNAME_DEFAULT
+#define MICROPY_PY_NETWORK_HOSTNAME_DEFAULT "mpy-mimxrt"
#endif
// For regular code that wants to prevent "background tasks" from running.
@@ -184,10 +134,6 @@ uint32_t trng_random_u32(void);
#define MICROPY_PY_PENDSV_REENTER atomic_state = raise_irq_pri(IRQ_PRI_PENDSV);
#define MICROPY_PY_PENDSV_EXIT restore_irq_pri(atomic_state);
-// Use VfsLfs2's types for fileio/textio
-#define mp_type_fileio mp_type_vfs_lfs2_fileio
-#define mp_type_textio mp_type_vfs_lfs2_textio
-
// Hooks to add builtins
__attribute__((always_inline)) static inline void enable_irq(uint32_t state) {
@@ -220,7 +166,7 @@ static inline void restore_irq_pri(uint32_t basepri) {
#define MICROPY_BEGIN_ATOMIC_SECTION() disable_irq()
#define MICROPY_END_ATOMIC_SECTION(state) enable_irq(state)
-#if defined(MICROPY_HW_ETH_MDC)
+#if defined(IOMUX_TABLE_ENET)
extern const struct _mp_obj_type_t network_lan_type;
#define MICROPY_HW_NIC_ETH { MP_ROM_QSTR(MP_QSTR_LAN), MP_ROM_PTR(&network_lan_type) },
#else
@@ -241,24 +187,22 @@ extern const struct _mp_obj_type_t network_lan_type;
#define MICROPY_BOARD_ROOT_POINTERS
#endif
-#define MICROPY_PORT_ROOT_POINTERS \
- const char *readline_hist[8]; \
- struct _machine_timer_obj_t *timer_table[MICROPY_HW_PIT_NUM_CHANNELS]; \
- void *machine_pin_irq_objects[MICROPY_HW_NUM_PIN_IRQS]; \
- /* list of registered NICs */ \
- mp_obj_list_t mod_network_nic_list; \
- /* root pointers defined by a board */ \
- MICROPY_BOARD_ROOT_POINTERS \
+// Additional entries for use with pendsv_schedule_dispatch.
+#ifndef MICROPY_BOARD_PENDSV_ENTRIES
+#define MICROPY_BOARD_PENDSV_ENTRIES
+#endif
#define MP_STATE_PORT MP_STATE_VM
// Miscellaneous settings
-
+#ifndef MICROPY_EVENT_POLL_HOOK
#define MICROPY_EVENT_POLL_HOOK \
do { \
extern void mp_handle_pending(bool); \
mp_handle_pending(true); \
+ __WFE(); \
} while (0);
+#endif
#define MICROPY_MAKE_POINTER_CALLABLE(p) ((void *)((mp_uint_t)(p) | 1))
diff --git a/ports/mimxrt/mphalport.c b/ports/mimxrt/mphalport.c
index 87741e0b5cf9..beb471ab801e 100644
--- a/ports/mimxrt/mphalport.c
+++ b/ports/mimxrt/mphalport.c
@@ -86,6 +86,9 @@ uintptr_t mp_hal_stdio_poll(uintptr_t poll_flags) {
if ((poll_flags & MP_STREAM_POLL_RD) && ringbuf_peek(&stdin_ringbuf) != -1) {
ret |= MP_STREAM_POLL_RD;
}
+ if ((poll_flags & MP_STREAM_POLL_WR) && tud_cdc_connected() && tud_cdc_write_available() > 0) {
+ ret |= MP_STREAM_POLL_WR;
+ }
#if MICROPY_PY_OS_DUPTERM
ret |= mp_uos_dupterm_poll(poll_flags);
#endif
@@ -116,9 +119,15 @@ void mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) {
if (n > CFG_TUD_CDC_EP_BUFSIZE) {
n = CFG_TUD_CDC_EP_BUFSIZE;
}
- while (n > tud_cdc_write_available()) {
- __WFE();
+ uint64_t timeout = ticks_us64() + (uint64_t)(MICROPY_HW_USB_CDC_TX_TIMEOUT * 1000);
+ // Wait with a max of USC_CDC_TIMEOUT ms
+ while (n > tud_cdc_write_available() && ticks_us64() < timeout) {
+ MICROPY_EVENT_POLL_HOOK
+ }
+ if (ticks_us64() >= timeout) {
+ break;
}
+
uint32_t n2 = tud_cdc_write(str + i, n);
tud_cdc_write_flush();
i += n2;
@@ -140,8 +149,13 @@ uint64_t mp_hal_time_ns(void) {
// MAC address
void mp_hal_get_unique_id(uint8_t id[]) {
+ #if defined CPU_MIMXRT1176_cm7
+ *(uint32_t *)id = OCOTP->FUSEN[0x10].FUSE;
+ *(uint32_t *)(id + 4) = OCOTP->FUSEN[0x11].FUSE;
+ #else
*(uint32_t *)id = OCOTP->CFG0;
*(uint32_t *)(id + 4) = OCOTP->CFG1;
+ #endif
}
// Generate a random locally administered MAC address (LAA)
diff --git a/ports/mimxrt/mphalport.h b/ports/mimxrt/mphalport.h
index 124b905604d0..5136a36b3805 100644
--- a/ports/mimxrt/mphalport.h
+++ b/ports/mimxrt/mphalport.h
@@ -35,9 +35,15 @@
#define MICROPY_HAL_VERSION "2.8.0"
+#define MICROPY_HW_USB_CDC_TX_TIMEOUT (500)
+
#define MP_HAL_PIN_FMT "%q"
extern ringbuf_t stdin_ringbuf;
+// Define an alias fo systick_ms, because the shared softtimer.c uses
+// the symbol uwTick for the systick ms counter.
+#define uwTick systick_ms
+
#define mp_hal_pin_obj_t const machine_pin_obj_t *
#define mp_hal_get_pin_obj(o) pin_find(o)
#define mp_hal_pin_name(p) ((p)->name)
diff --git a/ports/mimxrt/network_lan.c b/ports/mimxrt/network_lan.c
index 5517b54bd02f..355698e0b588 100644
--- a/ports/mimxrt/network_lan.c
+++ b/ports/mimxrt/network_lan.c
@@ -28,7 +28,7 @@
#include "py/mphal.h"
#include "extmod/modnetwork.h"
-#if defined(MICROPY_HW_ETH_MDC)
+#if defined(IOMUX_TABLE_ENET)
#include "fsl_phy.h"
#include "eth.h"
@@ -36,25 +36,36 @@
#include "hal/phy/device/phydp83825/fsl_phydp83825.h"
#include "hal/phy/device/phydp83848/fsl_phydp83848.h"
#include "hal/phy/device/phylan8720/fsl_phylan8720.h"
+#include "hal/phy/device/phyrtl8211f/fsl_phyrtl8211f.h"
#include "lwip/netif.h"
+#include "lwip/apps/mdns.h"
#ifndef ENET_TX_CLK_OUTPUT
#define ENET_TX_CLK_OUTPUT true
#endif
+#ifndef ENET_1_TX_CLK_OUTPUT
+#define ENET_1_TX_CLK_OUTPUT true
+#endif
+
typedef struct _network_lan_obj_t {
mp_obj_base_t base;
eth_t *eth;
} network_lan_obj_t;
-STATIC const network_lan_obj_t network_lan_eth0 = { { &network_lan_type }, ð_instance };
+
+STATIC const network_lan_obj_t network_lan_eth0 = { { &network_lan_type }, ð_instance0 };
+#if defined(ENET_DUAL_PORT)
+STATIC const network_lan_obj_t network_lan_eth1 = { { &network_lan_type }, ð_instance1 };
+#endif
STATIC void network_lan_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
network_lan_obj_t *self = MP_OBJ_TO_PTR(self_in);
struct netif *netif = eth_netif(self->eth);
int status = eth_link_status(self->eth);
- mp_printf(print, "",
+ mp_printf(print, "",
+ self->eth == ð_instance0 ? 0 : 1,
status,
netif->ip_addr.addr & 0xff,
netif->ip_addr.addr >> 8 & 0xff,
@@ -64,18 +75,34 @@ STATIC void network_lan_print(const mp_print_t *print, mp_obj_t self_in, mp_prin
}
STATIC mp_obj_t network_lan_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
- enum { ARG_id, ARG_phy_type, ARG_phy_addr, ARG_phy_clock};
+ enum { ARG_id, ARG_phy_type, ARG_phy_addr, ARG_ref_clk_mode};
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_id, MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_phy_type, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
- { MP_QSTR_phy_addr, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = ENET_PHY_ADDRESS} },
- { MP_QSTR_phy_clock, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = ENET_TX_CLK_OUTPUT} },
+ { MP_QSTR_phy_addr, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
+ { MP_QSTR_ref_clk_mode, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
};
// Parse args.
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
- const phy_operations_t *phy_ops = &ENET_PHY_OPS;
+ const phy_operations_t *phy_ops;
+ int phy_addr;
+ bool phy_clock;
+
+ int mac_id = args[ARG_id].u_int;
+ // set default
+ if (mac_id == 0) {
+ phy_ops = &ENET_PHY_OPS;
+ phy_addr = ENET_PHY_ADDRESS;
+ phy_clock = ENET_TX_CLK_OUTPUT;
+ #if defined(ENET_DUAL_PORT)
+ } else {
+ phy_ops = &ENET_1_PHY_OPS;
+ phy_addr = ENET_1_PHY_ADDRESS;
+ phy_clock = ENET_1_TX_CLK_OUTPUT;
+ #endif
+ }
// Select PHY driver
int phy_type = args[ARG_phy_type].u_int;
@@ -88,28 +115,34 @@ STATIC mp_obj_t network_lan_make_new(const mp_obj_type_t *type, size_t n_args, s
phy_ops = &phydp83848_ops;
} else if (phy_type == PHY_LAN8720) {
phy_ops = &phylan8720_ops;
+ } else if (phy_type == PHY_RTL8211F) {
+ phy_ops = &phyrtl8211f_ops;
} else {
mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("Invalid value %d for phy"), phy_type);
}
}
- int phy_addr = args[ARG_phy_addr].u_int;
+ if (args[ARG_phy_addr].u_int != -1) {
+ phy_addr = args[ARG_phy_addr].u_int;
+ }
- bool phy_clock = args[ARG_phy_clock].u_int;
+ if (args[ARG_ref_clk_mode].u_int != -1) {
+ phy_clock = args[ARG_ref_clk_mode].u_int;
+ }
// Prepare for two ETH interfaces.
const network_lan_obj_t *self;
- int mac_id = args[ARG_id].u_int;
if (mac_id == 0) {
self = &network_lan_eth0;
- mac_id = MP_HAL_MAC_ETH0;
+ eth_init_0(self->eth, MP_HAL_MAC_ETH0, phy_ops, phy_addr, phy_clock);
+ #if defined(ENET_DUAL_PORT)
} else if (mac_id == 1) {
- self = &network_lan_eth0;
- mac_id = MP_HAL_MAC_ETH1;
+ self = &network_lan_eth1;
+ eth_init_1(self->eth, MP_HAL_MAC_ETH1, phy_ops, phy_addr, phy_clock);
+ #endif
} else {
mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("Invalid LAN interface %d"), mac_id);
}
- eth_init(self->eth, mac_id, phy_ops, phy_addr, phy_clock);
// register with network module
mod_network_register_nic((mp_obj_t *)self);
return MP_OBJ_FROM_PTR(self);
@@ -215,17 +248,20 @@ STATIC const mp_rom_map_elem_t network_lan_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_PHY_DP83825), MP_ROM_INT(PHY_DP83825) },
{ MP_ROM_QSTR(MP_QSTR_PHY_DP83848), MP_ROM_INT(PHY_DP83848) },
{ MP_ROM_QSTR(MP_QSTR_PHY_LAN8720), MP_ROM_INT(PHY_LAN8720) },
+ { MP_ROM_QSTR(MP_QSTR_PHY_RTL8211F), MP_ROM_INT(PHY_RTL8211F) },
{ MP_ROM_QSTR(MP_QSTR_IN), MP_ROM_INT(PHY_TX_CLK_IN) },
{ MP_ROM_QSTR(MP_QSTR_OUT), MP_ROM_INT(PHY_TX_CLK_OUT) },
};
STATIC MP_DEFINE_CONST_DICT(network_lan_locals_dict, network_lan_locals_dict_table);
-const mp_obj_type_t network_lan_type = {
- { &mp_type_type },
- .name = MP_QSTR_LAN,
- .print = network_lan_print,
- .make_new = network_lan_make_new,
- .locals_dict = (mp_obj_dict_t *)&network_lan_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ network_lan_type,
+ MP_QSTR_LAN,
+ MP_TYPE_FLAG_NONE,
+ make_new, network_lan_make_new,
+ print, network_lan_print,
+ locals_dict, &network_lan_locals_dict
+ );
+
-#endif // defined(MICROPY_HW_ETH_MDC)
+#endif // defined(IOMUX_TABLE_ENET)
diff --git a/ports/mimxrt/pendsv.c b/ports/mimxrt/pendsv.c
index 7638b160d861..11f2ef5e1c86 100644
--- a/ports/mimxrt/pendsv.c
+++ b/ports/mimxrt/pendsv.c
@@ -27,23 +27,16 @@
#include
#include "py/runtime.h"
-#include "shared/runtime/interrupt_char.h"
#include "pendsv.h"
-#include "lib/nxp_driver/sdk/CMSIS/Include/core_cm7.h"
#define NVIC_PRIORITYGROUP_4 ((uint32_t)0x00000003)
#define IRQ_PRI_PENDSV NVIC_EncodePriority(NVIC_PRIORITYGROUP_4, 15, 0)
#if defined(PENDSV_DISPATCH_NUM_SLOTS)
-uint32_t pendsv_dispatch_active;
pendsv_dispatch_t pendsv_dispatch_table[PENDSV_DISPATCH_NUM_SLOTS];
#endif
void pendsv_init(void) {
- #if defined(PENDSV_DISPATCH_NUM_SLOTS)
- pendsv_dispatch_active = false;
- #endif
-
// set PendSV interrupt at lowest priority
NVIC_SetPriority(PendSV_IRQn, IRQ_PRI_PENDSV);
}
@@ -51,11 +44,10 @@ void pendsv_init(void) {
#if defined(PENDSV_DISPATCH_NUM_SLOTS)
void pendsv_schedule_dispatch(size_t slot, pendsv_dispatch_t f) {
pendsv_dispatch_table[slot] = f;
- pendsv_dispatch_active = true;
SCB->ICSR = SCB_ICSR_PENDSVSET_Msk;
}
-void pendsv_dispatch_handler(void) {
+void PendSV_Handler(void) {
for (size_t i = 0; i < PENDSV_DISPATCH_NUM_SLOTS; ++i) {
if (pendsv_dispatch_table[i] != NULL) {
pendsv_dispatch_t f = pendsv_dispatch_table[i];
@@ -64,10 +56,4 @@ void pendsv_dispatch_handler(void) {
}
}
}
-
-void PendSV_Handler(void) {
- if (pendsv_dispatch_active) {
- pendsv_dispatch_handler();
- }
-}
#endif
diff --git a/ports/mimxrt/pendsv.h b/ports/mimxrt/pendsv.h
index 64883c903137..e68f487fb4a1 100644
--- a/ports/mimxrt/pendsv.h
+++ b/ports/mimxrt/pendsv.h
@@ -31,6 +31,7 @@ enum {
#if MICROPY_PY_NETWORK && MICROPY_PY_LWIP
PENDSV_DISPATCH_LWIP,
#endif
+ MICROPY_BOARD_PENDSV_ENTRIES
PENDSV_DISPATCH_MAX
};
diff --git a/ports/mimxrt/pin.h b/ports/mimxrt/pin.h
index 583d1c30231c..63db55f8a7c5 100644
--- a/ports/mimxrt/pin.h
+++ b/ports/mimxrt/pin.h
@@ -69,6 +69,7 @@ enum {
PIN_AF_MODE_ALT7,
PIN_AF_MODE_ALT8,
PIN_AF_MODE_ALT9,
+ PIN_AF_MODE_ALT10,
};
enum {
diff --git a/ports/mimxrt/sdcard.c b/ports/mimxrt/sdcard.c
index 20f76cc88f31..1d548599016c 100644
--- a/ports/mimxrt/sdcard.c
+++ b/ports/mimxrt/sdcard.c
@@ -31,10 +31,6 @@
#include "fsl_iomuxc.h"
#include "pin.h"
-#if FSL_USDHC_DRIVER_VERSION == 0x020208
-#define USHDC_USE_TRANSFER_NONBLOCKING_10XX (1)
-#endif
-
#define SDCARD_VOLTAGE_WINDOW_SD (0x80100000U)
#define SDCARD_HIGH_CAPACITY (0x40000000U)
#define SDCARD_SWITCH_1_8V_CAPACITY ((uint32_t)0x01000000U)
@@ -143,16 +139,6 @@ enum
SDCARD_STATE_DISCONNECT = 8U,
};
-// ---
-// SD Card transfer status
-// ---
-typedef enum
-{
- SDCARD_TRANSFER_SUCCESS = 0,
- SDCARD_TRANSFER_ERROR,
- SDCARD_TRANSFER_PENDING
-} sdcard_transfer_status_t;
-
// ---
// SD Card type definitions
// ---
@@ -220,9 +206,6 @@ mimxrt_sdcard_obj_t mimxrt_sdcard_objs[] =
#endif
};
-volatile status_t sdcard_transfer_status;
-volatile bool sdcard_transfer_done;
-
// ---
// Local function declarations
// ---
@@ -286,16 +269,6 @@ void sdcard_card_removed_callback(USDHC_Type *base, void *userData) {
USDHC_ClearInterruptStatusFlags(base, kUSDHC_CardRemovalFlag);
}
-#if USHDC_USE_TRANSFER_NONBLOCKING_10XX
-
-void sdcard_transfer_complete_callback(USDHC_Type *base, usdhc_handle_t *handle, status_t status, void *userData) {
- sdcard_transfer_status = status;
- sdcard_transfer_done = true;
- USDHC_ClearInterruptStatusFlags(base, kUSDHC_CommandCompleteFlag | kUSDHC_DataCompleteFlag);
-}
-
-#endif
-
void sdcard_dummy_callback(USDHC_Type *base, void *userData) {
return;
}
@@ -331,36 +304,12 @@ static status_t sdcard_transfer_blocking(USDHC_Type *base, usdhc_handle_t *handl
dma_config.admaTable = sdcard_adma_descriptor_table;
dma_config.admaTableWords = DMA_DESCRIPTOR_BUFFER_SIZE;
- #if USHDC_USE_TRANSFER_NONBLOCKING_10XX
-
- uint32_t retry_ctr = 0UL;
-
- do {
- status = USDHC_TransferNonBlocking(base, handle, &dma_config, transfer);
- retry_ctr++;
- } while (!(status == kStatus_Success) && (retry_ctr < 1000000UL));
-
- if (status == kStatus_Success) {
- for (int i = 0; i < timeout_ms * 100; i++) {
- if ((sdcard_transfer_done == true) && (sdcard_transfer_status == kStatus_Success)) {
- sdcard_transfer_done = false;
- return kStatus_Success;
- }
- ticks_delay_us64(10);
- }
- return kStatus_Timeout;
- } else {
- sdcard_error_recovery(base);
- return status;
- }
-
- #else // USHDC_USE_TRANSFER_NONBLOCKING_10XX
-
// Wait while the card is busy before a transfer
status = kStatus_Timeout;
for (int i = 0; i < timeout_ms * 100; i++) {
// Wait until Data0 is low any more. Low indicates "Busy".
- if ((transfer->data->txData == NULL) || (USDHC_GetPresentStatusFlags(base) & (uint32_t)kUSDHC_Data0LineLevelFlag) != 0) {
+ if (((transfer->data->txData == NULL) && (transfer->data->rxData == NULL)) ||
+ (USDHC_GetPresentStatusFlags(base) & (uint32_t)kUSDHC_Data0LineLevelFlag) != 0) {
// Not busy anymore or no TX-Data
status = USDHC_TransferBlocking(base, &dma_config, transfer);
if (status != kStatus_Success) {
@@ -372,7 +321,6 @@ static status_t sdcard_transfer_blocking(USDHC_Type *base, usdhc_handle_t *handl
}
return status;
- #endif // USHDC_USE_TRANSFER_NONBLOCKING_11XX
}
static void sdcard_decode_csd(mimxrt_sdcard_obj_t *card, csd_t *csd) {
@@ -770,18 +718,15 @@ void sdcard_init(mimxrt_sdcard_obj_t *card, uint32_t base_clk) {
(void)sdcard_reset(card);
card->base_clk = base_clk;
- #if USHDC_USE_TRANSFER_NONBLOCKING_10XX
usdhc_transfer_callback_t callbacks = {
.CardInserted = sdcard_card_inserted_callback,
.CardRemoved = sdcard_card_removed_callback,
.SdioInterrupt = sdcard_dummy_callback,
.BlockGap = sdcard_dummy_callback,
- .TransferComplete = sdcard_transfer_complete_callback,
.ReTuning = sdcard_dummy_callback,
};
USDHC_TransferCreateHandle(card->usdhc_inst, &card->handle, &callbacks, NULL);
- #endif // USHDC_USE_TRANSFER_NONBLOCKING_10XX
}
void sdcard_deinit(mimxrt_sdcard_obj_t *card) {
@@ -1052,8 +997,6 @@ bool sdcard_power_off(mimxrt_sdcard_obj_t *card) {
bool sdcard_detect(mimxrt_sdcard_obj_t *card) {
bool detect = false;
- #if USHDC_USE_TRANSFER_NONBLOCKING_10XX
-
#if defined MICROPY_USDHC1 && USDHC1_AVAIL
if ((card->usdhc_inst == USDHC1) && (sdcard_usdhc1_state.inserted == true)) {
return true;
@@ -1065,8 +1008,6 @@ bool sdcard_detect(mimxrt_sdcard_obj_t *card) {
}
#endif
- #endif // USHDC_USE_TRANSFER_NONBLOCKING_10XX
-
if (card->pins->cd_b.pin) {
detect = USDHC_DetectCardInsert(card->usdhc_inst);
} else {
diff --git a/ports/mimxrt/systick.c b/ports/mimxrt/systick.c
index 086bf1670161..8b0f5eb7b2de 100644
--- a/ports/mimxrt/systick.c
+++ b/ports/mimxrt/systick.c
@@ -28,6 +28,9 @@
#include "py/mphal.h"
#include "systick.h"
+#include "pendsv.h"
+#include "shared/runtime/softtimer.h"
+
volatile uint32_t systick_ms = 0;
systick_dispatch_t systick_dispatch_table[SYSTICK_DISPATCH_NUM_SLOTS];
@@ -44,6 +47,10 @@ void SysTick_Handler(void) {
if (f != NULL) {
f(uw_tick);
}
+
+ if (soft_timer_next == uw_tick) {
+ pendsv_schedule_dispatch(PENDSV_DISPATCH_SOFT_TIMER, soft_timer_handler);
+ }
}
bool systick_has_passed(uint32_t start_tick, uint32_t delay_ms) {
diff --git a/ports/mimxrt/ticks.c b/ports/mimxrt/ticks.c
index 0fc9babc04b4..858a5c574f82 100644
--- a/ports/mimxrt/ticks.c
+++ b/ports/mimxrt/ticks.c
@@ -41,7 +41,11 @@ void ticks_init(void) {
ticks_ms_upper = 0;
gpt_config_t config;
+ #if defined MIMXRT117x_SERIES
+ config.clockSource = kGPT_ClockSource_HighFreq;
+ #else
config.clockSource = kGPT_ClockSource_Osc;
+ #endif
config.divider = 24; // XTAL is 24MHz
config.enableFreeRun = true;
config.enableRunInWait = true;
diff --git a/ports/mimxrt/tusb_port.c b/ports/mimxrt/tusb_port.c
index 55855674c629..f359d44e4d27 100644
--- a/ports/mimxrt/tusb_port.c
+++ b/ports/mimxrt/tusb_port.c
@@ -35,8 +35,8 @@
#define MICROPY_HW_USB_PID (0x9802)
#endif
-#ifndef MICROPY_HW_USB_STR_MANUF
-#define MICROPY_HW_USB_STR_MANUF ("MicroPython")
+#ifndef MICROPY_HW_USB_MANUFACTURER_STRING
+#define MICROPY_HW_USB_MANUFACTURER_STRING ("MicroPython")
#endif
#define USBD_DESC_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN)
@@ -85,7 +85,7 @@ static const uint8_t usbd_desc_cfg[USBD_DESC_LEN] = {
};
static const char *const usbd_desc_str[] = {
- [USBD_STR_MANUF] = MICROPY_HW_USB_STR_MANUF,
+ [USBD_STR_MANUF] = MICROPY_HW_USB_MANUFACTURER_STRING,
[USBD_STR_PRODUCT] = MICROPY_HW_BOARD_NAME,
[USBD_STR_SERIAL] = "00000000000000000000",
[USBD_STR_CDC] = "Board CDC",
diff --git a/ports/minimal/Makefile b/ports/minimal/Makefile
index fc3730e700b0..050c4ddf526a 100644
--- a/ports/minimal/Makefile
+++ b/ports/minimal/Makefile
@@ -23,19 +23,20 @@ ifeq ($(CROSS), 1)
DFU = $(TOP)/tools/dfu.py
PYDFU = $(TOP)/tools/pydfu.py
CFLAGS_CORTEX_M4 = -mthumb -mtune=cortex-m4 -mcpu=cortex-m4 -msoft-float -fsingle-precision-constant -Wdouble-promotion -Wfloat-conversion
-CFLAGS = $(INC) -Wall -Werror -std=c99 -nostdlib $(CFLAGS_CORTEX_M4) $(COPT)
-LDFLAGS = -nostdlib -T stm32f405.ld -Map=$@.map --cref --gc-sections
+CFLAGS += $(INC) -Wall -Werror -std=c99 -nostdlib $(CFLAGS_CORTEX_M4) $(COPT)
+LDFLAGS += -nostdlib -T stm32f405.ld -Map=$@.map --cref --gc-sections
else
-LD = gcc
-CFLAGS = $(INC) -Wall -Werror -Wdouble-promotion -Wfloat-conversion -std=c99 $(COPT)
-LDFLAGS = -Wl,-Map=$@.map,--cref -Wl,--gc-sections
+LD = $(CC)
+CFLAGS += $(INC) -Wall -Werror -Wdouble-promotion -Wfloat-conversion -std=c99 $(COPT)
+LDFLAGS += -Wl,-Map=$@.map,--cref -Wl,--gc-sections
endif
CSUPEROPT = -Os # save some code space
# Tune for Debugging or Optimization
+CFLAGS += -g # always include debug info in the ELF
ifeq ($(DEBUG), 1)
-CFLAGS += -O0 -ggdb
+CFLAGS += -O0
else
CFLAGS += -Os -DNDEBUG
CFLAGS += -fdata-sections -ffunction-sections
@@ -43,11 +44,6 @@ endif
# Flags for optional C++ source code
CXXFLAGS += $(filter-out -std=c99,$(CFLAGS))
-CXXFLAGS += $(CXXFLAGS_MOD)
-
-# Flags for user C modules
-CFLAGS += $(CFLAGS_MOD)
-LDFLAGS += $(LDFLAGS_MOD)
LIBS =
@@ -64,13 +60,10 @@ ifeq ($(CROSS), 1)
SRC_C += shared/libc/string0.c
endif
-SRC_C += $(SRC_MOD)
-
-SRC_CXX += $(SRC_MOD_CXX)
-
-SRC_QSTR += $(SRC_MOD) $(SRC_MOD_CXX)
+SRC_QSTR += shared/readline/readline.c shared/runtime/pyexec.c
-OBJ += $(PY_CORE_O) $(addprefix $(BUILD)/, $(SRC_C:.c=.o))
+OBJ += $(PY_CORE_O)
+OBJ += $(addprefix $(BUILD)/, $(SRC_C:.c=.o))
OBJ += $(addprefix $(BUILD)/, $(SRC_CXX:.cpp=.o))
ifeq ($(CROSS), 1)
@@ -79,7 +72,7 @@ else
all: $(BUILD)/firmware.elf
endif
-$(BUILD)/_frozen_mpy.c: frozentest.mpy $(BUILD)/genhdr/qstrdefs.generated.h
+$(BUILD)/_frozen_mpy.c: $(TOP)/tests/frozen/frozentest.mpy $(BUILD)/genhdr/qstrdefs.generated.h
$(ECHO) "MISC freezing bytecode"
$(Q)$(TOP)/tools/mpy-tool.py -f -q $(BUILD)/genhdr/qstrdefs.preprocessed.h -mlongint-impl=none $< > $@
@@ -101,12 +94,11 @@ deploy: $(BUILD)/firmware.dfu
# Run emulation build on a POSIX system with suitable terminal settings
run:
- stty raw opost -echo
- build/firmware.elf
- @echo Resetting terminal...
-# This sleep is useful to spot segfaults
- sleep 1
- reset
+ @saved_=`stty -g`; \
+ stty raw opost -echo; \
+ $(BUILD)/firmware.elf; \
+ echo "Exit status: $$?"; \
+ stty $$saved_
test: $(BUILD)/firmware.elf
$(Q)/bin/echo -e "print('hello world!', list(x+1 for x in range(10)), end='eol\\\\n')\\r\\n\\x04" | $(BUILD)/firmware.elf | tail -n2 | grep "^hello world! \\[1, 2, 3, 4, 5, 6, 7, 8, 9, 10\\]eol"
diff --git a/ports/minimal/main.c b/ports/minimal/main.c
index 289327658626..499099753184 100644
--- a/ports/minimal/main.c
+++ b/ports/minimal/main.c
@@ -29,7 +29,7 @@ void do_str(const char *src, mp_parse_input_kind_t input_kind) {
static char *stack_top;
#if MICROPY_ENABLE_GC
-static char heap[2048];
+static char heap[MICROPY_HEAP_SIZE];
#endif
int main(int argc, char **argv) {
@@ -55,7 +55,7 @@ int main(int argc, char **argv) {
// do_str("print('hello world!', list(x+1 for x in range(10)), end='eol\\n')", MP_PARSE_SINGLE_INPUT);
// do_str("for i in range(10):\r\n print(i)", MP_PARSE_FILE_INPUT);
#else
- pyexec_frozen_module("frozentest.py");
+ pyexec_frozen_module("frozentest.py", false);
#endif
mp_deinit();
return 0;
@@ -69,7 +69,7 @@ void gc_collect(void) {
gc_collect_start();
gc_collect_root(&dummy, ((mp_uint_t)stack_top - (mp_uint_t)&dummy) / sizeof(mp_uint_t));
gc_collect_end();
- gc_dump_info();
+ gc_dump_info(&mp_plat_print);
}
#endif
diff --git a/ports/minimal/mpconfigport.h b/ports/minimal/mpconfigport.h
index 7d6a3adedceb..0f50f8d389cd 100644
--- a/ports/minimal/mpconfigport.h
+++ b/ports/minimal/mpconfigport.h
@@ -33,14 +33,13 @@ typedef long mp_off_t;
#ifdef __linux__
#define MICROPY_MIN_USE_STDOUT (1)
+#define MICROPY_HEAP_SIZE (25600) // heap size 25 kilobytes
#endif
#ifdef __thumb__
#define MICROPY_MIN_USE_CORTEX_CPU (1)
#define MICROPY_MIN_USE_STM32_MCU (1)
+#define MICROPY_HEAP_SIZE (2048) // heap size 2 kilobytes
#endif
#define MP_STATE_PORT MP_STATE_VM
-
-#define MICROPY_PORT_ROOT_POINTERS \
- const char *readline_hist[8];
diff --git a/ports/nrf/Makefile b/ports/nrf/Makefile
index c32e09d2c9ce..54b69b63707a 100644
--- a/ports/nrf/Makefile
+++ b/ports/nrf/Makefile
@@ -1,12 +1,18 @@
-# Select the board to build for: if not given on the command line,
-# then default to pca10040.
+# Select the board to build for:
+ifdef BOARD_DIR
+# Custom board path - remove trailing slash and get the final component of
+# the path as the board name.
+BOARD ?= $(notdir $(BOARD_DIR:/=))
+else
+# If not given on the command line, then default to pca10040.
BOARD ?= pca10040
+BOARD_DIR ?= boards/$(BOARD)
+endif
+
ifeq ($(wildcard boards/$(BOARD)/.),)
$(error Invalid BOARD specified)
endif
-BOARD_DIR ?= boards/$(BOARD)
-
# If SoftDevice is selected, try to use that one.
SD ?=
SD_LOWER = $(shell echo $(SD) | tr '[:upper:]' '[:lower:]')
@@ -45,7 +51,7 @@ endif
-include boards/$(BOARD)/modules/boardmodules.mk
# qstr definitions (must come before including py.mk)
-QSTR_DEFS = qstrdefsport.h $(BUILD)/pins_qstr.h
+QSTR_DEFS = qstrdefsport.h $(GEN_PINS_QSTR)
# MicroPython feature configurations
ifeq ($(DEBUG), 0)
@@ -56,12 +62,11 @@ FROZEN_MANIFEST ?= modules/manifest.py
# include py core make definitions
include ../../py/py.mk
+include ../../extmod/extmod.mk
-GIT_SUBMODULES = lib/nrfx lib/tinyusb
+GIT_SUBMODULES += lib/nrfx lib/tinyusb
MICROPY_VFS_FAT ?= 0
-MPY_CROSS = ../../mpy-cross/mpy-cross
-MPY_TOOL = ../../tools/mpy-tool.py
CROSS_COMPILE ?= arm-none-eabi-
@@ -107,6 +112,16 @@ endif
NRF_DEFINES += -D$(MCU_SUB_VARIANT_UPPER)
NRF_DEFINES += -DCONFIG_GPIO_AS_PINRESET
+MAKE_PINS = boards/make-pins.py
+BOARD_PINS = boards/$(BOARD)/pins.csv
+AF_FILE = $(MCU_VARIANT)_af.csv
+PREFIX_FILE = boards/$(MCU_VARIANT)_prefix.c
+GEN_PINS_SRC = $(BUILD)/pins_gen.c
+GEN_PINS_HDR = $(HEADER_BUILD)/pins.h
+GEN_PINS_QSTR = $(BUILD)/pins_qstr.h
+GEN_PINS_AF_CONST = $(HEADER_BUILD)/pins_af_const.h
+GEN_PINS_AF_PY = $(BUILD)/pins_af.py
+
CFLAGS_CORTEX_M = -mthumb -mabi=aapcs -fsingle-precision-constant -Wdouble-promotion
CFLAGS_MCU_m33 = $(CFLAGS_CORTEX_M) -mcpu=cortex-m33 -march=armv8-m.main+dsp -mcmse -mfpu=fpv5-sp-d16 -mfloat-abi=hard
@@ -123,14 +138,13 @@ CFLAGS += -ffunction-sections -fdata-sections
LDFLAGS += -Wl,--gc-sections
endif
-
CFLAGS += $(CFLAGS_MCU_$(MCU_SERIES))
-CFLAGS += $(INC) -Wall -Werror -g -ansi -std=c11 -nostdlib $(COPT) $(NRF_DEFINES) $(CFLAGS_MOD) $(CFLAGS_EXTRA)
+CFLAGS += $(INC) -Wall -Werror -ansi -std=c11 -nostdlib $(COPT) $(NRF_DEFINES) $(CFLAGS_EXTRA)
CFLAGS += -fno-strict-aliasing
CFLAGS += -Iboards/$(BOARD)
CFLAGS += -DNRF5_HAL_H='<$(MCU_VARIANT)_hal.h>'
-LDFLAGS = $(CFLAGS)
+LDFLAGS += $(CFLAGS)
LDFLAGS += -Xlinker -Map=$(@:.elf=.map)
LDFLAGS += -mthumb -mabi=aapcs $(addprefix -T,$(LD_FILES)) -L boards/
@@ -141,9 +155,12 @@ endif
#Debugging/Optimization
ifeq ($(DEBUG), 1)
#ASMFLAGS += -g -gtabs+
-CFLAGS += -O0 -ggdb
+CFLAGS += -g -O0
LDFLAGS += -O0
else
+ifneq ($(LTO), 1)
+CFLAGS += -g # always include debug info in the ELF, unless LTO is on
+endif
CFLAGS += -Os -DNDEBUG
LDFLAGS += -Os
endif
@@ -152,7 +169,7 @@ LIBS = \
ifeq ($(MCU_VARIANT), nrf52)
-SRC_LIB += $(addprefix lib/,\
+SRC_LIB_C += $(addprefix lib/,\
libm/math.c \
libm/fmodf.c \
libm/nearbyintf.c \
@@ -186,7 +203,7 @@ endif
ifeq ($(MCU_VARIANT), nrf91)
-SRC_LIB += $(addprefix lib/,\
+SRC_LIB_C += $(addprefix lib/,\
libm/math.c \
libm/fmodf.c \
libm/nearbyintf.c \
@@ -216,26 +233,22 @@ SRC_LIB += $(addprefix lib/,\
libm/roundf.c \
)
-SRC_NRFX += $(addprefix lib/nrfx/drivers/src/,\
- nrfx_uarte.c \
- nrfx_twim.c \
- )
-
include drivers/secureboot/secureboot.mk
endif
-SRC_LIB += $(addprefix shared/,\
+SRC_SHARED_C += $(addprefix shared/,\
libc/string0.c \
readline/readline.c \
runtime/pyexec.c \
runtime/sys_stdio_mphal.c \
runtime/interrupt_char.c \
+ tinyusb/mp_cdc_common.c \
timeutils/timeutils.c \
)
ifeq ($(MICROPY_FATFS), 1)
-SRC_LIB += $(addprefix lib/,\
+SRC_LIB_C += $(addprefix lib/,\
oofatfs/ff.c \
oofatfs/ffunicode.c \
)
@@ -245,11 +258,13 @@ endif
SRC_NRFX += $(addprefix lib/nrfx/drivers/src/,\
prs/nrfx_prs.c \
nrfx_uart.c \
+ nrfx_uarte.c \
nrfx_adc.c \
nrfx_saadc.c \
nrfx_temp.c \
nrfx_rng.c \
nrfx_twi.c \
+ nrfx_twim.c \
nrfx_spi.c \
nrfx_spim.c \
nrfx_rtc.c \
@@ -274,6 +289,7 @@ SRC_C += \
drivers/ticker.c \
drivers/bluetooth/ble_drv.c \
drivers/bluetooth/ble_uart.c \
+ $(wildcard $(BOARD_DIR)/*.c) \
ifeq ($(MCU_SUB_VARIANT), nrf52840)
@@ -300,6 +316,7 @@ SRC_C += $(addprefix lib/tinyusb/src/,\
tusb.c \
portable/nordic/nrf5x/dcd_nrf5x.c \
)
+
endif
DRIVERS_SRC_C += $(addprefix modules/,\
@@ -311,7 +328,6 @@ DRIVERS_SRC_C += $(addprefix modules/,\
machine/pin.c \
machine/timer.c \
machine/rtcounter.c \
- machine/pwm.c \
machine/temp.c \
uos/moduos.c \
uos/microbitfs.c \
@@ -343,14 +359,15 @@ SRC_C += \
LIBGCC_FILE_NAME = $(shell $(CC) $(CFLAGS) -print-libgcc-file-name)
LIBS += -L $(dir $(LIBGCC_FILE_NAME)) -lgcc
-OBJ += $(PY_O) $(addprefix $(BUILD)/, $(SRC_C:.c=.o))
-OBJ += $(addprefix $(BUILD)/, $(SRC_MOD:.c=.o))
+OBJ += $(PY_O)
+OBJ += $(addprefix $(BUILD)/, $(SRC_C:.c=.o))
OBJ += $(addprefix $(BUILD)/, $(SRC_NRFX:.c=.o))
OBJ += $(addprefix $(BUILD)/, $(SRC_NRFX_HAL:.c=.o))
OBJ += $(addprefix $(BUILD)/, $(DRIVERS_SRC_C:.c=.o))
OBJ += $(addprefix $(BUILD)/, $(SYSTEM_C_SRC:.c=.o))
-OBJ += $(addprefix $(BUILD)/, $(SRC_LIB:.c=.o))
-OBJ += $(BUILD)/pins_gen.o
+OBJ += $(addprefix $(BUILD)/, $(SRC_LIB_C:.c=.o))
+OBJ += $(addprefix $(BUILD)/, $(SRC_SHARED_C:.c=.o))
+OBJ += $(GEN_PINS_SRC:.c=.o)
$(BUILD)/$(OOFATFS_DIR)/ff.o: COPT += -Os
$(filter $(PY_BUILD)/../extmod/vfs_fat_%.o, $(PY_O)): COPT += -Os
@@ -495,17 +512,26 @@ nrfutil_dfu_deploy: $(BUILD)/$(OUTPUT_FILENAME).hex
$(Q)nrfutil dfu usb-serial -pkg $(BUILD)/$(OUTPUT_FILENAME)_dfu.zip -p $(NRFUTIL_PORT) -t 0
deploy: nrfutil_dfu_deploy
+
+else ifeq ($(FLASHER), bossac)
+
+BOSSAC_PORT ?= /dev/ttyACM0
+BOSSAC_OFFSET ?= 0x16000
+
+deploy: $(BUILD)/$(OUTPUT_FILENAME).bin
+ $(Q)bossac -e -w --offset=$(BOSSAC_OFFSET) --port=$(BOSSAC_PORT) -i -d -U -R $<
+
endif
flash: deploy
$(BUILD)/$(OUTPUT_FILENAME).elf: $(OBJ)
$(ECHO) "LINK $@"
- $(Q)$(CC) $(LDFLAGS) -o $@ $(OBJ) $(LDFLAGS_MOD) $(LIBS)
+ $(Q)$(CC) $(LDFLAGS) -o $@ $(OBJ) $(LIBS)
$(Q)$(SIZE) $@
# List of sources for qstr extraction
-SRC_QSTR += $(SRC_C) $(SRC_LIB) $(DRIVERS_SRC_C) $(SRC_BOARD_MODULES) $(SRC_MOD)
+SRC_QSTR += $(SRC_C) $(SRC_SHARED_C) $(DRIVERS_SRC_C) $(SRC_BOARD_MODULES)
# Append any auto-generated sources that are needed by sources listed in
# SRC_QSTR
@@ -524,19 +550,9 @@ $(BUILD)/%_gen.c $(HEADER_BUILD)/%.h $(HEADER_BUILD)/%_af_const.h $(BUILD)/%_qst
$(ECHO) "Create $@"
$(Q)$(PYTHON) $(MAKE_PINS) --board $(BOARD_PINS) --af $(AF_FILE) --prefix $(PREFIX_FILE) --hdr $(GEN_PINS_HDR) --qstr $(GEN_PINS_QSTR) --af-const $(GEN_PINS_AF_CONST) --af-py $(GEN_PINS_AF_PY) > $(GEN_PINS_SRC)
-$(BUILD)/pins_gen.o: $(BUILD)/pins_gen.c
+$(GEN_PINS_SRC:.c=.o): $(GEN_PINS_SRC)
$(call compile_c)
-MAKE_PINS = boards/make-pins.py
-BOARD_PINS = boards/$(BOARD)/pins.csv
-AF_FILE = $(MCU_VARIANT)_af.csv
-PREFIX_FILE = boards/$(MCU_VARIANT)_prefix.c
-GEN_PINS_SRC = $(BUILD)/pins_gen.c
-GEN_PINS_HDR = $(HEADER_BUILD)/pins.h
-GEN_PINS_QSTR = $(BUILD)/pins_qstr.h
-GEN_PINS_AF_CONST = $(HEADER_BUILD)/pins_af_const.h
-GEN_PINS_AF_PY = $(BUILD)/pins_af.py
-
ifneq ($(FROZEN_MANIFEST),)
CFLAGS += -DMICROPY_QSTR_EXTRA_POOL=mp_qstr_frozen_const_pool
CFLAGS += -DMICROPY_MODULE_FROZEN_MPY
diff --git a/ports/nrf/boards/actinius_icarus/mpconfigboard.h b/ports/nrf/boards/actinius_icarus/mpconfigboard.h
index e99d731df941..46960cab83bb 100644
--- a/ports/nrf/boards/actinius_icarus/mpconfigboard.h
+++ b/ports/nrf/boards/actinius_icarus/mpconfigboard.h
@@ -33,7 +33,6 @@
#define MICROPY_PY_MACHINE_UART (1)
#define MICROPY_PY_MACHINE_HW_PWM (0)
#define MICROPY_PY_MACHINE_HW_SPI (1)
-#define MICROPY_PY_MACHINE_TIMER (1)
#define MICROPY_PY_MACHINE_RTCOUNTER (1)
#define MICROPY_PY_MACHINE_I2C (1)
#define MICROPY_PY_MACHINE_ADC (0)
diff --git a/ports/nrf/boards/arduino_nano_33_ble_sense/board.c b/ports/nrf/boards/arduino_nano_33_ble_sense/board.c
new file mode 100644
index 000000000000..954639756bc2
--- /dev/null
+++ b/ports/nrf/boards/arduino_nano_33_ble_sense/board.c
@@ -0,0 +1,67 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2022 Arduino SA
+ *
+ * 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 "nrf.h"
+#include "nrf_gpio.h"
+#include "nrf_rtc.h"
+
+#define PIN_ENABLE_SENSORS_3V3 (22u)
+#define PIN_ENABLE_I2C_PULLUP (32u)
+#define DFU_MAGIC_SERIAL_ONLY_RESET (0xb0)
+
+void NANO33_board_early_init(void) {
+ // Errata Nano33BLE - I2C pullup is on SWO line, need to disable TRACE
+ // was being enabled by nrfx_clock_anomaly_132
+ CoreDebug->DEMCR = 0;
+ NRF_CLOCK->TRACECONFIG = 0;
+
+ // Bootloader enables interrupt on COMPARE[0], which we don't handle
+ // Disable it here to avoid getting stuck when OVERFLOW irq is triggered
+ nrf_rtc_event_disable(NRF_RTC1, NRF_RTC_INT_COMPARE0_MASK);
+ nrf_rtc_int_disable(NRF_RTC1, NRF_RTC_INT_COMPARE0_MASK);
+
+ // Always enable I2C pullup and power on startup
+ // Change for maximum powersave
+ nrf_gpio_cfg_output(PIN_ENABLE_SENSORS_3V3);
+ nrf_gpio_cfg_output(PIN_ENABLE_I2C_PULLUP);
+
+ nrf_gpio_pin_set(PIN_ENABLE_SENSORS_3V3);
+ nrf_gpio_pin_set(PIN_ENABLE_I2C_PULLUP);
+}
+
+void NANO33_board_deinit(void) {
+ nrf_gpio_cfg_output(PIN_ENABLE_SENSORS_3V3);
+ nrf_gpio_cfg_output(PIN_ENABLE_I2C_PULLUP);
+
+ nrf_gpio_pin_clear(PIN_ENABLE_SENSORS_3V3);
+ nrf_gpio_pin_clear(PIN_ENABLE_I2C_PULLUP);
+}
+
+void NANO33_board_enter_bootloader(void) {
+ __disable_irq();
+ NRF_POWER->GPREGRET = DFU_MAGIC_SERIAL_ONLY_RESET;
+ NVIC_SystemReset();
+}
diff --git a/ports/nrf/boards/arduino_nano_33_ble_sense/board.json b/ports/nrf/boards/arduino_nano_33_ble_sense/board.json
new file mode 100644
index 000000000000..65a8e2435059
--- /dev/null
+++ b/ports/nrf/boards/arduino_nano_33_ble_sense/board.json
@@ -0,0 +1,25 @@
+{
+ "deploy": [
+ "./deploy.md"
+ ],
+ "docs": "",
+ "features": [
+ "Bluetooth 5.0",
+ "IMU LSM9DS1",
+ "Humidity sensor HTS221",
+ "Pressure sensor LPS22H",
+ "Proximity, Light, RGB sensor APDS-9960",
+ "Microphone MPM3610",
+ "Crypto IC ARM CC310",
+ "USB-MICRO",
+ "Breadboard Friendly"
+ ],
+ "images": [
+ "ABX00031_01.iso_998x749.jpg"
+ ],
+ "mcu": "nrf52",
+ "product": "Arduino Nano 33 BLE Sense",
+ "thumbnail": "",
+ "url": "https://store.arduino.cc/products/arduino-nano-33-ble-sense",
+ "vendor": "Arduino"
+}
diff --git a/ports/nrf/boards/arduino_nano_33_ble_sense/deploy.md b/ports/nrf/boards/arduino_nano_33_ble_sense/deploy.md
new file mode 100644
index 000000000000..0d94a537bbad
--- /dev/null
+++ b/ports/nrf/boards/arduino_nano_33_ble_sense/deploy.md
@@ -0,0 +1,27 @@
+### Update the bootloader
+
+Before deploying any firmware images, make sure the board is running the
+updated Arduino Nano 33 BLE bootloader (which is relocated to the end of
+the flash), otherwise the bootloader will be overwritten by the softdevice.
+For more information on how to update the bootloader, see the
+[Getting Started with OpenMV/MicroPython](https://docs.arduino.cc/tutorials/nano-33-ble/getting-started-omv) tutorial.
+
+### Via Arduino bootloader and BOSSA
+
+Download the latest BOSSA flash programmer from the
+[Arduino BOSSA fork](https://github.com/arduino/BOSSA/releases/latest).
+Note this version adds support for nRF devices, and must be used with the
+Nano 33 BLE. Double tap the reset button to enter the bootloader, and run
+the following command:
+
+```bash
+bossac -e -w --offset=0x16000 --port=ttyACM0 -i -d -U -R build-arduino_nano_33_ble_sense-s140/firmware.bin
+```
+
+### Via nrfprog
+
+This board can also be programmed via nrfjprog (with Jlink for example), from MicroPython source repository:
+
+```bash
+make -j8 BOARD=arduino_nano_33_ble_sense SD=s140 deploy
+```
diff --git a/ports/nrf/boards/arduino_nano_33_ble_sense/manifest.py b/ports/nrf/boards/arduino_nano_33_ble_sense/manifest.py
new file mode 100644
index 000000000000..1e35ae8c4dd3
--- /dev/null
+++ b/ports/nrf/boards/arduino_nano_33_ble_sense/manifest.py
@@ -0,0 +1,8 @@
+include("$(PORT_DIR)/modules/manifest.py")
+require("hts221")
+require("lps22h")
+require("lsm9ds1")
+require("bmm150")
+require("bmi270")
+require("hs3003")
+freeze("./modules")
diff --git a/ports/nrf/boards/arduino_nano_33_ble_sense/modules/imu.py b/ports/nrf/boards/arduino_nano_33_ble_sense/modules/imu.py
new file mode 100644
index 000000000000..50a36a197603
--- /dev/null
+++ b/ports/nrf/boards/arduino_nano_33_ble_sense/modules/imu.py
@@ -0,0 +1,45 @@
+"""
+IMU module for Arduino Nano BLE 33 SENSE (REV1 and REV2).
+
+Example usage:
+
+import time
+import imu
+from machine import Pin, I2C
+
+bus = I2C(1, scl=Pin(15), sda=Pin(14))
+imu = imu.IMU(bus)
+
+while (True):
+ print('Accelerometer: x:{:>8.3f} y:{:>8.3f} z:{:>8.3f}'.format(*imu.accel()))
+ print('Gyroscope: x:{:>8.3f} y:{:>8.3f} z:{:>8.3f}'.format(*imu.gyro()))
+ print('Magnetometer: x:{:>8.3f} y:{:>8.3f} z:{:>8.3f}'.format(*imu.magnet()))
+ print("")
+ time.sleep_ms(100)
+"""
+
+import time
+
+
+class IMU:
+ def __init__(self, bus):
+ """Initalizes Gyro, Accelerometer and Magnetometer using default values."""
+ if 0x68 in bus.scan():
+ from bmm150 import BMM150
+ from bmi270 import BMI270
+
+ magnet = BMM150(bus)
+ self.imu = BMI270(bus, bmm_magnet=magnet)
+ else:
+ from lsm9ds1 import LSM9DS1
+
+ self.imu = LSM9DS1(bus)
+
+ def gyro(self):
+ return self.imu.gyro()
+
+ def accel(self):
+ return self.imu.accel()
+
+ def magnet(self):
+ return self.imu.magnet()
diff --git a/ports/nrf/boards/arduino_nano_33_ble_sense/mpconfigboard.h b/ports/nrf/boards/arduino_nano_33_ble_sense/mpconfigboard.h
new file mode 100644
index 000000000000..71349e08c4c8
--- /dev/null
+++ b/ports/nrf/boards/arduino_nano_33_ble_sense/mpconfigboard.h
@@ -0,0 +1,75 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ * The MIT License (MIT)
+ * Copyright (c) 2022 Arduino SA
+ */
+
+#define MICROPY_HW_BOARD_NAME "Arduino Nano 33 BLE Sense"
+#define MICROPY_HW_MCU_NAME "NRF52840"
+
+#define MICROPY_MBFS (1)
+
+#define MICROPY_BOARD_EARLY_INIT NANO33_board_early_init
+#define MICROPY_BOARD_DEINIT NANO33_board_deinit
+#define MICROPY_BOARD_ENTER_BOOTLOADER(nargs, args) NANO33_board_enter_bootloader()
+
+#define MICROPY_PY_MACHINE_UART (1)
+#define MICROPY_PY_MACHINE_PWM (1)
+#define MICROPY_PY_MACHINE_HW_PWM (1)
+#define MICROPY_PY_MACHINE_HW_SPI (1)
+#define MICROPY_PY_MACHINE_RTCOUNTER (1)
+#define MICROPY_PY_MACHINE_I2C (1)
+#define MICROPY_PY_MACHINE_ADC (1)
+#define MICROPY_PY_MACHINE_TEMP (1)
+
+#define MICROPY_HW_USB_CDC (1)
+#define MICROPY_HW_HAS_LED (1)
+#define MICROPY_HW_HAS_SWITCH (0)
+#define MICROPY_HW_HAS_FLASH (0)
+#define MICROPY_HW_HAS_SDCARD (0)
+#define MICROPY_HW_HAS_MMA7660 (0)
+#define MICROPY_HW_HAS_LIS3DSH (0)
+#define MICROPY_HW_HAS_LCD (0)
+#define MICROPY_HW_ENABLE_RNG (1)
+#define MICROPY_HW_ENABLE_RTC (1)
+#define MICROPY_HW_ENABLE_TIMER (0)
+#define MICROPY_HW_ENABLE_SERVO (0)
+#define MICROPY_HW_ENABLE_DAC (0)
+#define MICROPY_HW_ENABLE_CAN (0)
+
+// LEDs config
+#define MICROPY_HW_LED_COUNT (4) // 3 RGB + 1 Yellow
+#define MICROPY_HW_LED_PULLUP (1) // RGB LED is active low
+#define MICROPY_HW_LED4_PULLUP (0) // Yellow is active high
+#define MICROPY_HW_LED1 (24) // RED
+#define MICROPY_HW_LED2 (16) // GREEN
+#define MICROPY_HW_LED3 (6) // BLUE
+#define MICROPY_HW_LED4 (13) // Yellow
+#define HELP_TEXT_BOARD_LED "1,2,3,4"
+
+// UART config
+#define MICROPY_HW_UART1_TX (32 + 3)
+#define MICROPY_HW_UART1_RX (32 + 10)
+// #define MICROPY_HW_UART1_CTS (7)
+// #define MICROPY_HW_UART1_RTS (5)
+// #define MICROPY_HW_UART1_HWFC (1)
+
+// SPI0 config
+#define MICROPY_HW_SPI0_NAME "SPI0"
+#define MICROPY_HW_SPI0_SCK (13)
+#define MICROPY_HW_SPI0_MOSI (32 + 1)
+#define MICROPY_HW_SPI0_MISO (32 + 8)
+
+// PWM config
+#define MICROPY_HW_PWM0_NAME "PWM0"
+#define MICROPY_HW_PWM1_NAME "PWM1"
+#define MICROPY_HW_PWM2_NAME "PWM2"
+#define MICROPY_HW_PWM3_NAME "PWM3"
+
+#define MICROPY_HW_USB_VID (0x2341)
+#define MICROPY_HW_USB_PID (0x025A)
+#define MICROPY_HW_USB_CDC_1200BPS_TOUCH (1)
+
+void NANO33_board_early_init(void);
+void NANO33_board_deinit(void);
+void NANO33_board_enter_bootloader(void);
diff --git a/ports/nrf/boards/arduino_nano_33_ble_sense/mpconfigboard.mk b/ports/nrf/boards/arduino_nano_33_ble_sense/mpconfigboard.mk
new file mode 100644
index 000000000000..cb2ff5c6b81c
--- /dev/null
+++ b/ports/nrf/boards/arduino_nano_33_ble_sense/mpconfigboard.mk
@@ -0,0 +1,12 @@
+MCU_SERIES = m4
+MCU_VARIANT = nrf52
+MCU_SUB_VARIANT = nrf52840
+SOFTDEV_VERSION = 6.1.1
+SD=s140
+
+LD_FILES += boards/arduino_nano_33_ble_sense/nano_bootloader.ld boards/nrf52840_1M_256k.ld
+
+NRF_DEFINES += -DNRF52840_XXAA
+
+MICROPY_VFS_LFS2 = 1
+FROZEN_MANIFEST ?= $(BOARD_DIR)/manifest.py
diff --git a/ports/nrf/boards/arduino_nano_33_ble_sense/nano_bootloader.ld b/ports/nrf/boards/arduino_nano_33_ble_sense/nano_bootloader.ld
new file mode 100644
index 000000000000..209a1d447afb
--- /dev/null
+++ b/ports/nrf/boards/arduino_nano_33_ble_sense/nano_bootloader.ld
@@ -0,0 +1 @@
+_flash_start = 0xe0000;
diff --git a/ports/nrf/boards/arduino_nano_33_ble_sense/pins.csv b/ports/nrf/boards/arduino_nano_33_ble_sense/pins.csv
new file mode 100644
index 000000000000..9d931634f627
--- /dev/null
+++ b/ports/nrf/boards/arduino_nano_33_ble_sense/pins.csv
@@ -0,0 +1,50 @@
+P0,P0
+P1,P1
+P2,P2,ADC0_IN0
+P3,P3,ADC0_IN1
+P4,P4,ADC0_IN2
+P5,P5,ADC0_IN3
+P6,P6
+P7,P7
+P8,P8
+P9,P9
+P10,P10
+P11,P11
+P12,P12
+P13,P13
+P14,P14
+P15,P15
+P16,P16
+P17,P17
+P18,P18
+P19,P19
+P20,P20
+P21,P21
+P22,P22
+P23,P23
+P24,P24
+P25,P25
+P26,P26
+P27,P27
+P28,P28,ADC0_IN4
+P29,P29,ADC0_IN5
+P30,P30,ADC0_IN6
+P31,P31,ADC0_IN7
+P32,P32
+P33,P33
+P34,P34
+P35,P35
+P36,P36
+P37,P37
+P38,P38
+P39,P39
+P40,P40
+P41,P41
+P42,P42
+P43,P43
+P44,P44
+P45,P45
+P46,P46
+P47,P47
+I2C_SCL,P2
+I2C_SDA,P31
diff --git a/ports/nrf/boards/arduino_primo/mpconfigboard.h b/ports/nrf/boards/arduino_primo/mpconfigboard.h
index 639b6869c098..271cef0323df 100644
--- a/ports/nrf/boards/arduino_primo/mpconfigboard.h
+++ b/ports/nrf/boards/arduino_primo/mpconfigboard.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)
*
@@ -32,9 +32,9 @@
#define MICROPY_PY_MUSIC (1)
#define MICROPY_PY_MACHINE_UART (1)
+#define MICROPY_PY_MACHINE_PWM (1)
#define MICROPY_PY_MACHINE_HW_PWM (1)
#define MICROPY_PY_MACHINE_HW_SPI (1)
-#define MICROPY_PY_MACHINE_TIMER (1)
#define MICROPY_PY_MACHINE_RTCOUNTER (1)
#define MICROPY_PY_MACHINE_I2C (1)
#define MICROPY_PY_MACHINE_ADC (1)
diff --git a/ports/nrf/boards/blueio_tag_evim/mpconfigboard.h b/ports/nrf/boards/blueio_tag_evim/mpconfigboard.h
index 2ceeadf8eb93..0ca3ca16127a 100644
--- a/ports/nrf/boards/blueio_tag_evim/mpconfigboard.h
+++ b/ports/nrf/boards/blueio_tag_evim/mpconfigboard.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)
*
@@ -32,9 +32,9 @@
#define MICROPY_PY_MUSIC (1)
#define MICROPY_PY_MACHINE_UART (1)
+#define MICROPY_PY_MACHINE_PWM (1)
#define MICROPY_PY_MACHINE_HW_PWM (1)
#define MICROPY_PY_MACHINE_HW_SPI (1)
-#define MICROPY_PY_MACHINE_TIMER (1)
#define MICROPY_PY_MACHINE_RTCOUNTER (1)
#define MICROPY_PY_MACHINE_I2C (1)
#define MICROPY_PY_MACHINE_ADC (1)
diff --git a/ports/nrf/boards/dvk_bl652/mpconfigboard.h b/ports/nrf/boards/dvk_bl652/mpconfigboard.h
index d0b19a318453..e83e555178ff 100644
--- a/ports/nrf/boards/dvk_bl652/mpconfigboard.h
+++ b/ports/nrf/boards/dvk_bl652/mpconfigboard.h
@@ -31,7 +31,6 @@
#define MICROPY_PY_MACHINE_UART (1)
#define MICROPY_PY_MACHINE_PWM (1)
#define MICROPY_PY_MACHINE_HW_SPI (1)
-#define MICROPY_PY_MACHINE_TIMER (1)
#define MICROPY_PY_MACHINE_RTCOUNTER (1)
#define MICROPY_PY_MACHINE_I2C (1)
#define MICROPY_PY_MACHINE_ADC (1)
diff --git a/ports/nrf/boards/evk_nina_b1/mpconfigboard.h b/ports/nrf/boards/evk_nina_b1/mpconfigboard.h
index f0629b3a2303..72aeb449285f 100644
--- a/ports/nrf/boards/evk_nina_b1/mpconfigboard.h
+++ b/ports/nrf/boards/evk_nina_b1/mpconfigboard.h
@@ -32,7 +32,6 @@
#define MICROPY_PY_MACHINE_UART (1)
#define MICROPY_PY_MACHINE_HW_SPI (1)
-#define MICROPY_PY_MACHINE_TIMER (1)
#define MICROPY_PY_MACHINE_RTCOUNTER (1)
#define MICROPY_PY_MACHINE_I2C (1)
#define MICROPY_PY_MACHINE_ADC (1)
diff --git a/ports/nrf/boards/evk_nina_b3/mpconfigboard.h b/ports/nrf/boards/evk_nina_b3/mpconfigboard.h
index eaca796be4d6..eab232848bce 100644
--- a/ports/nrf/boards/evk_nina_b3/mpconfigboard.h
+++ b/ports/nrf/boards/evk_nina_b3/mpconfigboard.h
@@ -46,9 +46,9 @@
// Peripherals Config
#define MICROPY_PY_MACHINE_UART (1)
+#define MICROPY_PY_MACHINE_PWM (1)
#define MICROPY_PY_MACHINE_HW_PWM (1)
#define MICROPY_PY_MACHINE_HW_SPI (1)
-#define MICROPY_PY_MACHINE_TIMER (1)
#define MICROPY_PY_MACHINE_RTCOUNTER (1)
#define MICROPY_PY_MACHINE_I2C (1)
#define MICROPY_PY_MACHINE_ADC (1)
diff --git a/ports/nrf/boards/feather52/mpconfigboard.h b/ports/nrf/boards/feather52/mpconfigboard.h
index 10e0d999cebc..cef44ca4032f 100644
--- a/ports/nrf/boards/feather52/mpconfigboard.h
+++ b/ports/nrf/boards/feather52/mpconfigboard.h
@@ -29,9 +29,9 @@
#define MICROPY_PY_SYS_PLATFORM "nrf52"
#define MICROPY_PY_MACHINE_UART (1)
+#define MICROPY_PY_MACHINE_PWM (1)
#define MICROPY_PY_MACHINE_HW_PWM (1)
#define MICROPY_PY_MACHINE_HW_SPI (1)
-#define MICROPY_PY_MACHINE_TIMER (1)
#define MICROPY_PY_MACHINE_RTCOUNTER (1)
#define MICROPY_PY_MACHINE_I2C (1)
#define MICROPY_PY_MACHINE_ADC (1)
diff --git a/ports/nrf/boards/ibk_blyst_nano/mpconfigboard.h b/ports/nrf/boards/ibk_blyst_nano/mpconfigboard.h
index 4897471ea56c..63d2944f6c25 100644
--- a/ports/nrf/boards/ibk_blyst_nano/mpconfigboard.h
+++ b/ports/nrf/boards/ibk_blyst_nano/mpconfigboard.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)
*
@@ -32,9 +32,9 @@
#define MICROPY_PY_MUSIC (1)
#define MICROPY_PY_MACHINE_UART (1)
+#define MICROPY_PY_MACHINE_PWM (1)
#define MICROPY_PY_MACHINE_HW_PWM (1)
#define MICROPY_PY_MACHINE_HW_SPI (1)
-#define MICROPY_PY_MACHINE_TIMER (1)
#define MICROPY_PY_MACHINE_RTCOUNTER (1)
#define MICROPY_PY_MACHINE_I2C (1)
#define MICROPY_PY_MACHINE_ADC (1)
diff --git a/ports/nrf/boards/idk_blyst_nano/mpconfigboard.h b/ports/nrf/boards/idk_blyst_nano/mpconfigboard.h
index 06c16477387c..73b1c6ff7459 100644
--- a/ports/nrf/boards/idk_blyst_nano/mpconfigboard.h
+++ b/ports/nrf/boards/idk_blyst_nano/mpconfigboard.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)
*
@@ -32,9 +32,9 @@
#define MICROPY_PY_MUSIC (1)
#define MICROPY_PY_MACHINE_UART (1)
+#define MICROPY_PY_MACHINE_PWM (1)
#define MICROPY_PY_MACHINE_HW_PWM (1)
#define MICROPY_PY_MACHINE_HW_SPI (1)
-#define MICROPY_PY_MACHINE_TIMER (1)
#define MICROPY_PY_MACHINE_RTCOUNTER (1)
#define MICROPY_PY_MACHINE_I2C (1)
#define MICROPY_PY_MACHINE_ADC (1)
diff --git a/ports/nrf/boards/microbit/modules/iters.c b/ports/nrf/boards/microbit/modules/iters.c
index 8ae4b698fe92..b16a4c665837 100644
--- a/ports/nrf/boards/microbit/modules/iters.c
+++ b/ports/nrf/boards/microbit/modules/iters.c
@@ -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)
*
@@ -43,21 +43,12 @@ static mp_obj_t microbit_repeat_iter_next(mp_obj_t iter_in) {
return mp_obj_subscr(iter->iterable, MP_OBJ_NEW_SMALL_INT(iter->index), MP_OBJ_SENTINEL);
}
-const mp_obj_type_t microbit_repeat_iterator_type = {
- { &mp_type_type },
- .name = MP_QSTR_iterator,
- .print = NULL,
- .make_new = NULL,
- .call = NULL,
- .unary_op = NULL,
- .binary_op = NULL,
- .attr = NULL,
- .subscr = NULL,
- .getiter = mp_identity_getiter,
- .iternext = microbit_repeat_iter_next,
- .buffer_p = {NULL},
- MP_OBJ_NULL
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ microbit_repeat_iterator_type,
+ MP_QSTR_iterator,
+ MP_TYPE_FLAG_ITER_IS_ITERNEXT,
+ iter, microbit_repeat_iter_next
+ );
mp_obj_t microbit_repeat_iterator(mp_obj_t iterable) {
repeat_iterator_t *result = mp_obj_malloc(repeat_iterator_t, µbit_repeat_iterator_type);
diff --git a/ports/nrf/boards/microbit/modules/microbitconstimage.c b/ports/nrf/boards/microbit/modules/microbitconstimage.c
index fa079845974d..d6f6ab0a9d80 100644
--- a/ports/nrf/boards/microbit/modules/microbitconstimage.c
+++ b/ports/nrf/boards/microbit/modules/microbitconstimage.c
@@ -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)
*
diff --git a/ports/nrf/boards/microbit/modules/microbitconstimage.h b/ports/nrf/boards/microbit/modules/microbitconstimage.h
index ca67b5c467ff..45d58c4a094f 100644
--- a/ports/nrf/boards/microbit/modules/microbitconstimage.h
+++ b/ports/nrf/boards/microbit/modules/microbitconstimage.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)
*
diff --git a/ports/nrf/boards/microbit/modules/microbitdisplay.c b/ports/nrf/boards/microbit/modules/microbitdisplay.c
index a0508886d796..ff3c499fa325 100644
--- a/ports/nrf/boards/microbit/modules/microbitdisplay.c
+++ b/ports/nrf/boards/microbit/modules/microbitdisplay.c
@@ -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)
*
@@ -542,21 +542,12 @@ STATIC const mp_rom_map_elem_t microbit_display_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(microbit_display_locals_dict, microbit_display_locals_dict_table);
-const mp_obj_type_t microbit_display_type = {
- { &mp_type_type },
- .name = MP_QSTR_MicroBitDisplay,
- .print = NULL,
- .make_new = NULL,
- .call = NULL,
- .unary_op = NULL,
- .binary_op = NULL,
- .attr = NULL,
- .subscr = NULL,
- .getiter = NULL,
- .iternext = NULL,
- .buffer_p = {NULL},
- .locals_dict = (mp_obj_dict_t*)µbit_display_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ microbit_display_type,
+ MP_QSTR_MicroBitDisplay,
+ MP_TYPE_FLAG_NONE,
+ locals_dict, µbit_display_locals_dict
+ );
microbit_display_obj_t microbit_display_obj = {
{µbit_display_type},
@@ -574,3 +565,5 @@ void microbit_display_init(void) {
nrf_gpio_cfg_output(i);
}
}
+
+MP_REGISTER_ROOT_POINTER(void *async_data[2]);
diff --git a/ports/nrf/boards/microbit/modules/microbitimage.c b/ports/nrf/boards/microbit/modules/microbitimage.c
index a028df8282a9..fc6b18870bdc 100644
--- a/ports/nrf/boards/microbit/modules/microbitimage.c
+++ b/ports/nrf/boards/microbit/modules/microbitimage.c
@@ -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)
*
@@ -678,21 +678,15 @@ STATIC mp_obj_t image_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs
}
-const mp_obj_type_t microbit_image_type = {
- { &mp_type_type },
- .name = MP_QSTR_MicroBitImage,
- .print = microbit_image_print,
- .make_new = microbit_image_make_new,
- .call = NULL,
- .unary_op = NULL,
- .binary_op = image_binary_op,
- .attr = NULL,
- .subscr = NULL,
- .getiter = NULL,
- .iternext = NULL,
- .buffer_p = {NULL},
- .locals_dict = (mp_obj_dict_t*)µbit_image_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ microbit_image_type,
+ MP_QSTR_MicroBitImage,
+ MP_TYPE_FLAG_NONE,
+ make_new, microbit_image_make_new,
+ print, microbit_image_print,
+ binary_op, image_binary_op,
+ locals_dict, µbit_image_locals_dict
+ );
typedef struct _scrolling_string_t {
mp_obj_base_t base;
@@ -827,37 +821,19 @@ STATIC mp_obj_t microbit_scrolling_string_iter_next(mp_obj_t o_in) {
return iter->img;
}
-const mp_obj_type_t microbit_scrolling_string_type = {
- { &mp_type_type },
- .name = MP_QSTR_ScrollingString,
- .print = NULL,
- .make_new = NULL,
- .call = NULL,
- .unary_op = NULL,
- .binary_op = NULL,
- .attr = NULL,
- .subscr = NULL,
- .getiter = get_microbit_scrolling_string_iter,
- .iternext = NULL,
- .buffer_p = {NULL},
- .locals_dict = NULL,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ microbit_scrolling_string_type,
+ MP_QSTR_ScrollingString,
+ MP_TYPE_FLAG_ITER_IS_GETITER,
+ iter, get_microbit_scrolling_string_iter
+ );
-const mp_obj_type_t microbit_scrolling_string_iterator_type = {
- { &mp_type_type },
- .name = MP_QSTR_iterator,
- .print = NULL,
- .make_new = NULL,
- .call = NULL,
- .unary_op = NULL,
- .binary_op = NULL,
- .attr = NULL,
- .subscr = NULL,
- .getiter = mp_identity_getiter,
- .iternext = microbit_scrolling_string_iter_next,
- .buffer_p = {NULL},
- .locals_dict = NULL,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ microbit_scrolling_string_iterator_type,
+ MP_QSTR_iterator,
+ MP_TYPE_FLAG_ITER_IS_ITERNEXT,
+ iter, microbit_scrolling_string_iter_next
+ );
/** Facade types to present a string as a sequence of images.
* These are necessary to avoid allocation during iteration,
@@ -895,21 +871,14 @@ static mp_obj_t facade_unary_op(mp_unary_op_t op, mp_obj_t self_in) {
static mp_obj_t microbit_facade_iterator(mp_obj_t iterable_in, mp_obj_iter_buf_t *iter_buf);
-const mp_obj_type_t string_image_facade_type = {
- { &mp_type_type },
- .name = MP_QSTR_Facade,
- .print = NULL,
- .make_new = NULL,
- .call = NULL,
- .unary_op = facade_unary_op,
- .binary_op = NULL,
- .attr = NULL,
- .subscr = string_image_facade_subscr,
- .getiter = microbit_facade_iterator,
- .iternext = NULL,
- .buffer_p = {NULL},
- NULL
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ string_image_facade_type,
+ MP_QSTR_Facade,
+ MP_TYPE_FLAG_ITER_IS_GETITER,
+ unary_op, facade_unary_op,
+ subscr, string_image_facade_subscr,
+ iter, microbit_facade_iterator
+ );
typedef struct _facade_iterator_t {
@@ -938,21 +907,12 @@ static mp_obj_t microbit_facade_iter_next(mp_obj_t iter_in) {
return iter->image;
}
-const mp_obj_type_t microbit_facade_iterator_type = {
- { &mp_type_type },
- .name = MP_QSTR_iterator,
- .print = NULL,
- .make_new = NULL,
- .call = NULL,
- .unary_op = NULL,
- .binary_op = NULL,
- .attr = NULL,
- .subscr = NULL,
- .getiter = mp_identity_getiter,
- .iternext = microbit_facade_iter_next,
- .buffer_p = {NULL},
- NULL
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ microbit_facade_iterator_type,
+ MP_QSTR_iterator,
+ MP_TYPE_FLAG_ITER_IS_ITERNEXT,
+ iter, microbit_facade_iter_next
+ );
mp_obj_t microbit_facade_iterator(mp_obj_t iterable_in, mp_obj_iter_buf_t *iter_buf) {
(void)iter_buf;
diff --git a/ports/nrf/boards/microbit/modules/modmicrobit.c b/ports/nrf/boards/microbit/modules/modmicrobit.c
index c6aa445b1c9a..06b3e5f6ab91 100644
--- a/ports/nrf/boards/microbit/modules/modmicrobit.c
+++ b/ports/nrf/boards/microbit/modules/modmicrobit.c
@@ -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)
*
diff --git a/ports/nrf/boards/microbit/mpconfigboard.h b/ports/nrf/boards/microbit/mpconfigboard.h
index f05317fb5910..4c6e05120db8 100644
--- a/ports/nrf/boards/microbit/mpconfigboard.h
+++ b/ports/nrf/boards/microbit/mpconfigboard.h
@@ -30,9 +30,9 @@
#define MICROPY_PY_MACHINE_UART (1)
#define MICROPY_PY_MUSIC (1)
+#define MICROPY_PY_MACHINE_PWM (1)
#define MICROPY_PY_MACHINE_SOFT_PWM (1)
#define MICROPY_PY_MACHINE_HW_SPI (1)
-#define MICROPY_PY_MACHINE_TIMER (1)
#define MICROPY_PY_MACHINE_RTCOUNTER (1)
#define MICROPY_PY_MACHINE_I2C (1)
#define MICROPY_PY_MACHINE_ADC (1)
diff --git a/ports/nrf/boards/nrf52840-mdk-usb-dongle/mpconfigboard.h b/ports/nrf/boards/nrf52840-mdk-usb-dongle/mpconfigboard.h
index f048c39e0efd..feafe8a14314 100644
--- a/ports/nrf/boards/nrf52840-mdk-usb-dongle/mpconfigboard.h
+++ b/ports/nrf/boards/nrf52840-mdk-usb-dongle/mpconfigboard.h
@@ -29,9 +29,9 @@
#define MICROPY_PY_SYS_PLATFORM "nrf52840-MDK-USB-Dongle"
#define MICROPY_PY_MACHINE_UART (1)
+#define MICROPY_PY_MACHINE_PWM (1)
#define MICROPY_PY_MACHINE_HW_PWM (1)
#define MICROPY_PY_MACHINE_HW_SPI (1)
-#define MICROPY_PY_MACHINE_TIMER (1)
#define MICROPY_PY_MACHINE_RTCOUNTER (1)
#define MICROPY_PY_MACHINE_I2C (1)
#define MICROPY_PY_MACHINE_ADC (1)
diff --git a/ports/nrf/boards/particle_xenon/mpconfigboard.h b/ports/nrf/boards/particle_xenon/mpconfigboard.h
index 7c814e377f60..012a04458eeb 100644
--- a/ports/nrf/boards/particle_xenon/mpconfigboard.h
+++ b/ports/nrf/boards/particle_xenon/mpconfigboard.h
@@ -29,9 +29,9 @@
#define MICROPY_PY_SYS_PLATFORM "PARTICLE-XENON"
#define MICROPY_PY_MACHINE_UART (1)
+#define MICROPY_PY_MACHINE_PWM (1)
#define MICROPY_PY_MACHINE_HW_PWM (1)
#define MICROPY_PY_MACHINE_HW_SPI (1)
-#define MICROPY_PY_MACHINE_TIMER (1)
#define MICROPY_PY_MACHINE_RTCOUNTER (1)
#define MICROPY_PY_MACHINE_I2C (1)
#define MICROPY_PY_MACHINE_ADC (1)
diff --git a/ports/nrf/boards/pca10000/mpconfigboard.h b/ports/nrf/boards/pca10000/mpconfigboard.h
index f61405d0480b..e56e0edf8373 100644
--- a/ports/nrf/boards/pca10000/mpconfigboard.h
+++ b/ports/nrf/boards/pca10000/mpconfigboard.h
@@ -30,12 +30,14 @@
#define MICROPY_PY_MACHINE_UART (1)
#define MICROPY_PY_MACHINE_HW_SPI (0)
-#define MICROPY_PY_MACHINE_TIMER (1)
#define MICROPY_PY_MACHINE_RTCOUNTER (1)
#define MICROPY_PY_MACHINE_I2C (0)
#define MICROPY_PY_MACHINE_ADC (0)
#define MICROPY_PY_MACHINE_TEMP (1)
+#define MICROPY_PY_MACHINE_PWM (1)
+#define MICROPY_PY_MACHINE_SOFT_PWM (1)
+
#define MICROPY_HW_ENABLE_RNG (1)
#define MICROPY_HW_HAS_LED (1)
diff --git a/ports/nrf/boards/pca10001/mpconfigboard.h b/ports/nrf/boards/pca10001/mpconfigboard.h
index c101b0886aad..a2e845539847 100644
--- a/ports/nrf/boards/pca10001/mpconfigboard.h
+++ b/ports/nrf/boards/pca10001/mpconfigboard.h
@@ -30,12 +30,14 @@
#define MICROPY_PY_MACHINE_UART (1)
#define MICROPY_PY_MACHINE_HW_SPI (0)
-#define MICROPY_PY_MACHINE_TIMER (1)
#define MICROPY_PY_MACHINE_RTCOUNTER (1)
#define MICROPY_PY_MACHINE_I2C (1)
#define MICROPY_PY_MACHINE_ADC (1)
#define MICROPY_PY_MACHINE_TEMP (1)
+#define MICROPY_PY_MACHINE_PWM (1)
+#define MICROPY_PY_MACHINE_SOFT_PWM (1)
+
#define MICROPY_HW_ENABLE_RNG (1)
#define MICROPY_HW_HAS_LED (1)
diff --git a/ports/nrf/boards/pca10028/mpconfigboard.h b/ports/nrf/boards/pca10028/mpconfigboard.h
index 5488b4ba534c..7abb5845e3f8 100644
--- a/ports/nrf/boards/pca10028/mpconfigboard.h
+++ b/ports/nrf/boards/pca10028/mpconfigboard.h
@@ -30,12 +30,14 @@
#define MICROPY_PY_MACHINE_UART (1)
#define MICROPY_PY_MACHINE_HW_SPI (1)
-#define MICROPY_PY_MACHINE_TIMER (1)
#define MICROPY_PY_MACHINE_RTCOUNTER (1)
#define MICROPY_PY_MACHINE_I2C (1)
#define MICROPY_PY_MACHINE_ADC (1)
#define MICROPY_PY_MACHINE_TEMP (1)
+#define MICROPY_PY_MACHINE_PWM (1)
+#define MICROPY_PY_MACHINE_SOFT_PWM (1)
+
#define MICROPY_HW_ENABLE_RNG (1)
#define MICROPY_HW_HAS_LED (1)
diff --git a/ports/nrf/boards/pca10031/mpconfigboard.h b/ports/nrf/boards/pca10031/mpconfigboard.h
index f16ffd7057ff..f162366233fd 100644
--- a/ports/nrf/boards/pca10031/mpconfigboard.h
+++ b/ports/nrf/boards/pca10031/mpconfigboard.h
@@ -30,12 +30,14 @@
#define MICROPY_PY_MACHINE_UART (1)
#define MICROPY_PY_MACHINE_HW_SPI (1)
-#define MICROPY_PY_MACHINE_TIMER (1)
#define MICROPY_PY_MACHINE_RTCOUNTER (1)
#define MICROPY_PY_MACHINE_I2C (1)
#define MICROPY_PY_MACHINE_ADC (1)
#define MICROPY_PY_MACHINE_TEMP (1)
+#define MICROPY_PY_MACHINE_PWM (1)
+#define MICROPY_PY_MACHINE_SOFT_PWM (1)
+
#define MICROPY_HW_ENABLE_RNG (1)
#define MICROPY_HW_HAS_LED (1)
diff --git a/ports/nrf/boards/pca10040/mpconfigboard.h b/ports/nrf/boards/pca10040/mpconfigboard.h
index 1dd01d66a048..00a56c2ea2c5 100644
--- a/ports/nrf/boards/pca10040/mpconfigboard.h
+++ b/ports/nrf/boards/pca10040/mpconfigboard.h
@@ -29,9 +29,9 @@
#define MICROPY_PY_SYS_PLATFORM "nrf52-DK"
#define MICROPY_PY_MACHINE_UART (1)
+#define MICROPY_PY_MACHINE_PWM (1)
#define MICROPY_PY_MACHINE_HW_PWM (1)
#define MICROPY_PY_MACHINE_HW_SPI (1)
-#define MICROPY_PY_MACHINE_TIMER (1)
#define MICROPY_PY_MACHINE_RTCOUNTER (1)
#define MICROPY_PY_MACHINE_I2C (1)
#define MICROPY_PY_MACHINE_ADC (1)
diff --git a/ports/nrf/boards/pca10056/mpconfigboard.h b/ports/nrf/boards/pca10056/mpconfigboard.h
index c037e2ecf5b2..fa39764a7eb9 100644
--- a/ports/nrf/boards/pca10056/mpconfigboard.h
+++ b/ports/nrf/boards/pca10056/mpconfigboard.h
@@ -29,9 +29,9 @@
#define MICROPY_PY_SYS_PLATFORM "nrf52840-PDK"
#define MICROPY_PY_MACHINE_UART (1)
+#define MICROPY_PY_MACHINE_PWM (1)
#define MICROPY_PY_MACHINE_HW_PWM (1)
#define MICROPY_PY_MACHINE_HW_SPI (1)
-#define MICROPY_PY_MACHINE_TIMER (1)
#define MICROPY_PY_MACHINE_RTCOUNTER (1)
#define MICROPY_PY_MACHINE_I2C (1)
#define MICROPY_PY_MACHINE_ADC (1)
diff --git a/ports/nrf/boards/pca10059/mpconfigboard.h b/ports/nrf/boards/pca10059/mpconfigboard.h
index 3db599f2c35d..904a0871e4da 100644
--- a/ports/nrf/boards/pca10059/mpconfigboard.h
+++ b/ports/nrf/boards/pca10059/mpconfigboard.h
@@ -29,9 +29,9 @@
#define MICROPY_PY_SYS_PLATFORM "nrf52840-Dongle"
#define MICROPY_PY_MACHINE_UART (1)
+#define MICROPY_PY_MACHINE_PWM (1)
#define MICROPY_PY_MACHINE_HW_PWM (1)
#define MICROPY_PY_MACHINE_HW_SPI (1)
-#define MICROPY_PY_MACHINE_TIMER (1)
#define MICROPY_PY_MACHINE_RTCOUNTER (1)
#define MICROPY_PY_MACHINE_I2C (1)
#define MICROPY_PY_MACHINE_ADC (1)
diff --git a/ports/nrf/boards/pca10090/mpconfigboard.h b/ports/nrf/boards/pca10090/mpconfigboard.h
index 28381c40d1e6..95cf8d6544b0 100644
--- a/ports/nrf/boards/pca10090/mpconfigboard.h
+++ b/ports/nrf/boards/pca10090/mpconfigboard.h
@@ -33,7 +33,7 @@
#define MICROPY_PY_MACHINE_UART (1)
#define MICROPY_PY_MACHINE_HW_PWM (0)
#define MICROPY_PY_MACHINE_HW_SPI (1)
-#define MICROPY_PY_MACHINE_TIMER (0)
+#define MICROPY_PY_MACHINE_TIMER_NRF (0)
#define MICROPY_PY_MACHINE_RTCOUNTER (1)
#define MICROPY_PY_MACHINE_I2C (1)
#define MICROPY_PY_MACHINE_ADC (0)
diff --git a/ports/nrf/boards/s140_7.3.0.ld b/ports/nrf/boards/s140_7.3.0.ld
new file mode 100644
index 000000000000..47b7665c95ff
--- /dev/null
+++ b/ports/nrf/boards/s140_7.3.0.ld
@@ -0,0 +1,4 @@
+/* GNU linker script for s140 SoftDevice version 7.3.0 */
+
+_sd_size = 0x00027000;
+_sd_ram = 0x0000e000;
diff --git a/ports/nrf/boards/seeed_xiao_nrf52/XIAO_bootloader.ld b/ports/nrf/boards/seeed_xiao_nrf52/XIAO_bootloader.ld
new file mode 100644
index 000000000000..0ff02f2182c2
--- /dev/null
+++ b/ports/nrf/boards/seeed_xiao_nrf52/XIAO_bootloader.ld
@@ -0,0 +1,4 @@
+/* GNU linker script for Adafruit nrf52840 Bootloader */
+
+_bootloader_head_size = 0x1000; /* MBR */
+_bootloader_tail_size = 0xC000; /* Bootloader start address 0x000F4000 */
diff --git a/ports/nrf/boards/seeed_xiao_nrf52/board.c b/ports/nrf/boards/seeed_xiao_nrf52/board.c
new file mode 100644
index 000000000000..25c9e1721598
--- /dev/null
+++ b/ports/nrf/boards/seeed_xiao_nrf52/board.c
@@ -0,0 +1,68 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2022 Arduino SA
+ *
+ * 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 "nrf.h"
+#include "nrf_gpio.h"
+#include "nrf_rtc.h"
+
+#define PIN_ENABLE_SENSORS_3V3 (40)
+#define DFU_MAGIC_SERIAL_ONLY_RESET 0x4e
+#define DFU_MAGIC_UF2_RESET 0x57
+#define DFU_MAGIC_OTA_RESET 0xA8
+
+void XIAO_board_early_init(void) {
+ // Errata XIAOBLE - I2C pullup is on SWO line, need to disable TRACE
+ // was being enabled by nrfx_clock_anomaly_132
+ CoreDebug->DEMCR = 0;
+ NRF_CLOCK->TRACECONFIG = 0;
+
+ // Bootloader enables interrupt on COMPARE[0], which we don't handle
+ // Disable it here to avoid getting stuck when OVERFLOW irq is triggered
+ nrf_rtc_event_disable(NRF_RTC1, NRF_RTC_INT_COMPARE0_MASK);
+ nrf_rtc_int_disable(NRF_RTC1, NRF_RTC_INT_COMPARE0_MASK);
+
+ // Always enable IMU power and I2C Pull-up on startup
+ nrf_gpio_cfg(PIN_ENABLE_SENSORS_3V3,
+ NRF_GPIO_PIN_DIR_OUTPUT,
+ NRF_GPIO_PIN_INPUT_DISCONNECT,
+ NRF_GPIO_PIN_NOPULL,
+ GPIO_PIN_CNF_DRIVE_S0H1,
+ NRF_GPIO_PIN_NOSENSE);
+
+ nrf_gpio_pin_set(PIN_ENABLE_SENSORS_3V3);
+}
+
+void XIAO_board_deinit(void) {
+ nrf_gpio_cfg_output(PIN_ENABLE_SENSORS_3V3);
+
+ nrf_gpio_pin_clear(PIN_ENABLE_SENSORS_3V3);
+}
+
+void XIAO_board_enter_bootloader(void) {
+ __disable_irq();
+ NRF_POWER->GPREGRET = DFU_MAGIC_UF2_RESET;
+ NVIC_SystemReset();
+}
diff --git a/ports/nrf/boards/seeed_xiao_nrf52/board.json b/ports/nrf/boards/seeed_xiao_nrf52/board.json
new file mode 100644
index 000000000000..619a7c23b9e8
--- /dev/null
+++ b/ports/nrf/boards/seeed_xiao_nrf52/board.json
@@ -0,0 +1,24 @@
+{
+ "deploy": [
+ "deploy.md"
+ ],
+ "docs": "",
+ "features": [
+ "Bluetooth 5.0",
+ "IMU LSM6DS3TR",
+ "Microphone MSM261D3526H1CPM",
+ "USB-C",
+ "Breadboard Friendly",
+ "Battery Management",
+ "RGB LED",
+ "QSPI Flash"
+ ],
+ "images": [
+ "XIAO_nrf52840_front.jpg"
+ ],
+ "mcu": "nrf52",
+ "product": "SEEED XIAO nRF52840 Sense",
+ "thumbnail": "",
+ "url": "https://www.seeedstudio.com",
+ "vendor": "Seeed Studio"
+}
diff --git a/ports/nrf/boards/seeed_xiao_nrf52/deploy.md b/ports/nrf/boards/seeed_xiao_nrf52/deploy.md
new file mode 100644
index 000000000000..a66731c30946
--- /dev/null
+++ b/ports/nrf/boards/seeed_xiao_nrf52/deploy.md
@@ -0,0 +1,31 @@
+The steps below let you create and install the firmware file. For
+a .uf2 type file taken from the MicroPython downloads source only
+step 4 is needed. For the .hex version of the firmware file, steps
+1, 3 and 4 are required.
+
+1. Download and install u2fconv.py. It is available e.g. in the tools
+ directory of MicroPython.
+
+2. Create a firmware for the SEEED nrf52840 if needed, with the command
+
+ `make BOARD=SEEED_XIAO_NRF52 -j5`
+
+ in the directory build-SEEED_XIAO_NRF52-s140. The firmware file will have the
+ name firmware.uf2.
+
+3. Create the .uf2 file if needed in the build directory with the command:
+
+ `uf2conv.py -c -f 0xADA52840 -o firmware.uf2 firmware.hex`
+
+ It must report the start address as 0x27000. If you omit the -o option,
+ the output file will have the name flash.uf2.
+
+4. Enable the upload mode by pushing reset twice or calling
+ machine.bootloader() and copy the file firmware.uf2 to the board drive,
+ which will pop up on your PC.
+
+In case the XIAO bootloader is lost or overwritten, it can be found
+at https://github.com/Seeed-Studio/Adafruit_nRF52_Arduino.git in different
+formats. Using a JLINK adapter or interface, it can be uploaded as hex version.
+The bootloader is as well available through the Arduino IDE.
+
diff --git a/ports/nrf/boards/seeed_xiao_nrf52/mpconfigboard.h b/ports/nrf/boards/seeed_xiao_nrf52/mpconfigboard.h
new file mode 100644
index 000000000000..18fbe327d08c
--- /dev/null
+++ b/ports/nrf/boards/seeed_xiao_nrf52/mpconfigboard.h
@@ -0,0 +1,83 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2016 Glenn Ruben Bakke
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#define MICROPY_HW_BOARD_NAME "XIAO nRF52840 Sense"
+#define MICROPY_HW_MCU_NAME "NRF52840"
+#define MICROPY_PY_SYS_PLATFORM "nrf52"
+
+#define MICROPY_BOARD_EARLY_INIT XIAO_board_early_init
+#define MICROPY_BOARD_DEINIT XIAO_board_deinit
+#define MICROPY_BOARD_ENTER_BOOTLOADER(nargs, args) XIAO_board_enter_bootloader()
+
+#define MICROPY_HW_USB_CDC (1)
+#define MICROPY_PY_MACHINE_UART (1)
+#define MICROPY_PY_MACHINE_PWM (1)
+#define MICROPY_PY_MACHINE_HW_PWM (1)
+#define MICROPY_PY_MACHINE_HW_SPI (1)
+#define MICROPY_PY_MACHINE_RTCOUNTER (1)
+#define MICROPY_PY_MACHINE_I2C (1)
+#define MICROPY_PY_MACHINE_ADC (1)
+#define MICROPY_PY_MACHINE_TEMP (1)
+#define MICROPY_HW_HAS_FLASH (1)
+
+#define MICROPY_HW_ENABLE_RNG (1)
+
+#define MICROPY_HW_HAS_LED (1)
+#define MICROPY_HW_LED_COUNT (4)
+#define MICROPY_HW_LED_PULLUP (1)
+
+#define MICROPY_HW_LED1 (17) // LED1
+#define MICROPY_HW_LED2 (26) // LED2
+#define MICROPY_HW_LED3 (30) // LED3
+#define MICROPY_HW_LED4 (6) // LED4
+
+// UART config
+#define MICROPY_HW_UART1_TX (32 + 11)
+#define MICROPY_HW_UART1_RX (32 + 12)
+
+// SPI0 config
+#define MICROPY_HW_SPI0_NAME "SPI0"
+
+#define MICROPY_HW_SPI0_SCK (32 + 13)
+#define MICROPY_HW_SPI0_MISO (32 + 14)
+#define MICROPY_HW_SPI0_MOSI (32 + 15)
+
+#define MICROPY_HW_PWM0_NAME "PWM0"
+#define MICROPY_HW_PWM1_NAME "PWM1"
+#define MICROPY_HW_PWM2_NAME "PWM2"
+
+#define HELP_TEXT_BOARD_LED "1,2,3,4"
+
+// Enabling these VID/PID values require to include mpconfigboard.h into usb_descriptors.c.
+// But there is an open discussion on whether specific VID/PID values are wanted.
+// 1200BPS touch is not supported at the moment in the USB driver, but at least the flag is set.
+#define MICROPY_HW_USB_VID (0x2886)
+#define MICROPY_HW_USB_PID (0x0045)
+#define MICROPY_HW_USB_CDC_1200BPS_TOUCH (1)
+
+void XIAO_board_early_init(void);
+void XIAO_board_deinit(void);
+void XIAO_board_enter_bootloader(void);
diff --git a/ports/nrf/boards/seeed_xiao_nrf52/mpconfigboard.mk b/ports/nrf/boards/seeed_xiao_nrf52/mpconfigboard.mk
new file mode 100644
index 000000000000..c2fc219187e3
--- /dev/null
+++ b/ports/nrf/boards/seeed_xiao_nrf52/mpconfigboard.mk
@@ -0,0 +1,16 @@
+MCU_SERIES = m4
+MCU_VARIANT = nrf52
+MCU_SUB_VARIANT = nrf52840
+SOFTDEV_VERSION = 7.3.0
+SD=s140
+LD_FILES += boards/seeed_xiao_nrf52/XIAO_bootloader.ld boards/nrf52840_1M_256k.ld
+
+NRF_DEFINES += -DNRF52840_XXAA
+
+MICROPY_VFS_LFS2 = 1
+FS_SIZE = 256k
+
+# DEBUG ?= 1
+
+uf2: hex
+ python3 $(TOP)/tools/uf2conv.py -c -o $(BUILD)/firmware.uf2 -f 0xADA52840 $(BUILD)/firmware.hex
diff --git a/ports/nrf/boards/seeed_xiao_nrf52/pins.csv b/ports/nrf/boards/seeed_xiao_nrf52/pins.csv
new file mode 100644
index 000000000000..6cb050c578a5
--- /dev/null
+++ b/ports/nrf/boards/seeed_xiao_nrf52/pins.csv
@@ -0,0 +1,48 @@
+P0,P0
+P1,P1
+D0_A0,P2
+D1_A1,P3
+D4_A4,P4
+D5_A5,P5
+P6,P6
+IMU_SDA,P7
+P8,P8
+NFC1,P9
+NFC2,P10
+IMU_INT1,P11
+P12,P12
+P13,P13
+READ_BAT,P14
+P15,P15
+PDM_DATA,P16
+P17,P17
+P18,P18
+P19,P19
+QSPI_D0,P20
+QSPI_SCK,P21
+QSPI_D2,P22
+QSPI_D3,P23
+QSPI_D1,P24
+QSPI_CS,P25
+P26,P26
+IMU_SCL,P27
+D2_A2,P28
+D3_A3,P29
+P30,P30
+ADC0_BAT,P31
+PDM_CLK,P32
+P33,P33
+P34,P34
+P35,P35
+P36,P36
+P37,P37
+P38,P38
+P39,P39
+IMU_PWR,P40
+P41,P41
+P42,P42
+UART1_TX,P43
+UART1_RX,P44
+SPI0_SCK,P45
+SPI0_MISO,P46
+SPI0_MOSI,P47
diff --git a/ports/nrf/boards/wt51822_s4at/mpconfigboard.h b/ports/nrf/boards/wt51822_s4at/mpconfigboard.h
index 8117bbd2a6c1..7997aa2697dc 100644
--- a/ports/nrf/boards/wt51822_s4at/mpconfigboard.h
+++ b/ports/nrf/boards/wt51822_s4at/mpconfigboard.h
@@ -32,7 +32,6 @@
#define MICROPY_PY_MACHINE_UART (1)
#define MICROPY_PY_MACHINE_HW_SPI (1)
-#define MICROPY_PY_MACHINE_TIMER (1)
#define MICROPY_PY_MACHINE_RTCOUNTER (1)
#define MICROPY_PY_MACHINE_I2C (1)
#define MICROPY_PY_MACHINE_ADC (1)
diff --git a/ports/nrf/drivers/bluetooth/ble_drv.c b/ports/nrf/drivers/bluetooth/ble_drv.c
index 004058093331..173d3eda0152 100644
--- a/ports/nrf/drivers/bluetooth/ble_drv.c
+++ b/ports/nrf/drivers/bluetooth/ble_drv.c
@@ -1136,6 +1136,24 @@ static void ble_evt_handler(ble_evt_t * p_ble_evt) {
sd_ble_gap_data_length_update(p_ble_evt->evt.gap_evt.conn_handle, NULL, NULL);
break;
+ case BLE_GAP_EVT_PHY_UPDATE_REQUEST:
+ BLE_DRIVER_LOG("BLE_GAP_EVT_PHY_UPDATE_REQUEST\n");
+ ble_gap_phys_t const phys =
+ {
+ BLE_GAP_PHY_AUTO,
+ BLE_GAP_PHY_AUTO,
+ };
+ sd_ble_gap_phy_update(p_ble_evt->evt.gap_evt.conn_handle, &phys);
+ break;
+
+ case BLE_GAP_EVT_PHY_UPDATE:
+ BLE_DRIVER_LOG("BLE_GAP_EVT_PHY_UPDATE -- unhandled!\n");
+ break;
+
+ case BLE_GAP_EVT_DATA_LENGTH_UPDATE:
+ BLE_DRIVER_LOG("BLE_GAP_EVT_DATA_LENGTH_UPDATE -- unhandled!\n");
+ break;
+
#endif // (BLUETOOTH_SD == 132) || (BLUETOOTH_SD == 140)
default:
diff --git a/ports/nrf/drivers/bluetooth/ble_uart.c b/ports/nrf/drivers/bluetooth/ble_uart.c
index c3712fe8c978..320657370335 100644
--- a/ports/nrf/drivers/bluetooth/ble_uart.c
+++ b/ports/nrf/drivers/bluetooth/ble_uart.c
@@ -164,6 +164,9 @@ uintptr_t mp_hal_stdio_poll(uintptr_t poll_flags) {
&& !isBufferEmpty(mp_rx_ring_buffer)) {
ret |= MP_STREAM_POLL_RD;
}
+ if ((poll_flags & MP_STREAM_POLL_WR) && ble_uart_enabled()) {
+ ret |= MP_STREAM_POLL_WR;
+ }
return ret;
}
#endif
@@ -193,9 +196,9 @@ STATIC void gatts_event_handler(mp_obj_t self_in, uint16_t event_id, uint16_t at
for (uint16_t i = 0; i < length; i++) {
#if MICROPY_KBD_EXCEPTION
if (data[i] == mp_interrupt_char) {
- mp_sched_keyboard_interrupt();
m_rx_ring_buffer.start = 0;
m_rx_ring_buffer.end = 0;
+ mp_sched_keyboard_interrupt();
} else
#endif
{
diff --git a/ports/nrf/drivers/bluetooth/download_ble_stack.sh b/ports/nrf/drivers/bluetooth/download_ble_stack.sh
index 2c3201858399..6498278f496c 100755
--- a/ports/nrf/drivers/bluetooth/download_ble_stack.sh
+++ b/ports/nrf/drivers/bluetooth/download_ble_stack.sh
@@ -57,6 +57,25 @@ function download_s140_nrf52_6_1_1
cd -
}
+function download_s140_nrf52_7_3_0
+{
+ echo ""
+ echo "####################################"
+ echo "### Downloading s140_nrf52_7.3.0 ###"
+ echo "####################################"
+ echo ""
+
+ mkdir -p $1/s140_nrf52_7.3.0
+ cd $1/s140_nrf52_7.3.0
+ wget --post-data="fileName=DeviceDownload&ids=59452FDD13BA46EEAD0810A57359F294" https://www.nordicsemi.com/api/sitecore/Products/MedialibraryZipDownload2
+ mv MedialibraryZipDownload2 temp.zip
+ unzip -u temp.zip
+ unzip -u s140_nrf52_7.3.0.zip
+ rm s140_nrf52_7.3.0.zip
+ rm temp.zip
+ cd -
+}
+
SCRIPT_DIR="$(cd -P "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
if [ $# -eq 0 ]; then
@@ -64,6 +83,7 @@ if [ $# -eq 0 ]; then
download_s110_nrf51_8_0_0 ${SCRIPT_DIR}
download_s132_nrf52_6_1_1 ${SCRIPT_DIR}
download_s140_nrf52_6_1_1 ${SCRIPT_DIR}
+ download_s140_nrf52_7_3_0 ${SCRIPT_DIR}
else
case $1 in
"s110_nrf51" )
@@ -72,6 +92,8 @@ else
download_s132_nrf52_6_1_1 ${SCRIPT_DIR} ;;
"s140_nrf52_6_1_1" )
download_s140_nrf52_6_1_1 ${SCRIPT_DIR} ;;
+ "s140_nrf52_7_3_0" )
+ download_s140_nrf52_7_3_0 ${SCRIPT_DIR} ;;
esac
fi
diff --git a/ports/nrf/drivers/softpwm.c b/ports/nrf/drivers/softpwm.c
index 517880c8c9da..6acdf7aa76d5 100644
--- a/ports/nrf/drivers/softpwm.c
+++ b/ports/nrf/drivers/softpwm.c
@@ -255,4 +255,7 @@ void pwm_release(int32_t pin) {
nrf_gpio_pin_clear(pin);
}
+MP_REGISTER_ROOT_POINTER(const struct _pwm_events *pwm_active_events);
+MP_REGISTER_ROOT_POINTER(const struct _pwm_events *pwm_pending_events);
+
#endif // MICROPY_PY_MACHINE_SOFT_PWM
diff --git a/ports/nrf/drivers/usb/usb_cdc.c b/ports/nrf/drivers/usb/usb_cdc.c
index a1d411a256f1..e33a42548271 100644
--- a/ports/nrf/drivers/usb/usb_cdc.c
+++ b/ports/nrf/drivers/usb/usb_cdc.c
@@ -35,6 +35,8 @@
#include "nrfx_uart.h"
#include "py/ringbuf.h"
#include "py/stream.h"
+#include "py/runtime.h"
+#include "shared/runtime/interrupt_char.h"
#ifdef BLUETOOTH_SD
#include "nrf_sdm.h"
@@ -44,7 +46,7 @@
extern void tusb_hal_nrf_power_event(uint32_t event);
-static void cdc_task(void);
+static void cdc_task(bool tx);
static uint8_t rx_ringbuf_array[1024];
static uint8_t tx_ringbuf_array[1024];
@@ -119,35 +121,45 @@ static int cdc_tx_char(void) {
return ringbuf_get((ringbuf_t*)&tx_ringbuf);
}
-static void cdc_task(void)
+static void cdc_task(bool tx)
{
if ( tud_cdc_connected() ) {
// connected and there are data available
while (tud_cdc_available()) {
- int c;
- uint32_t count = tud_cdc_read(&c, 1);
- (void)count;
- ringbuf_put((ringbuf_t*)&rx_ringbuf, c);
- }
-
- int chars = 0;
- while (cdc_tx_any()) {
- if (chars < 64) {
- tud_cdc_write_char(cdc_tx_char());
- chars++;
+ int c = tud_cdc_read_char();
+ if (c == mp_interrupt_char) {
+ rx_ringbuf.iget = 0;
+ rx_ringbuf.iput = 0;
+ mp_sched_keyboard_interrupt();
} else {
- chars = 0;
- tud_cdc_write_flush();
+ ringbuf_put((ringbuf_t*)&rx_ringbuf, c);
}
}
- tud_cdc_write_flush();
+ if (tx) {
+ int chars = 0;
+ while (cdc_tx_any()) {
+ if (chars < 64) {
+ tud_cdc_write_char(cdc_tx_char());
+ chars++;
+ } else {
+ chars = 0;
+ tud_cdc_write_flush();
+ }
+ }
+
+ tud_cdc_write_flush();
+ }
}
}
static void usb_cdc_loop(void) {
tud_task();
- cdc_task();
+ cdc_task(true);
+}
+
+void tud_cdc_rx_cb(uint8_t itf) {
+ cdc_task(false);
}
int usb_cdc_init(void)
@@ -201,6 +213,9 @@ uintptr_t mp_hal_stdio_poll(uintptr_t poll_flags) {
ret |= MP_STREAM_POLL_RD;
}
}
+ if (poll_flags & MP_STREAM_POLL_WR) {
+ ret |= MP_STREAM_POLL_WR;
+ }
return ret;
}
diff --git a/ports/nrf/examples/powerup.py b/ports/nrf/examples/powerup.py
index 2ecc63971c40..156193d002f8 100644
--- a/ports/nrf/examples/powerup.py
+++ b/ports/nrf/examples/powerup.py
@@ -120,13 +120,13 @@ def battery_level(self):
return int(self.char_batt_lvl.read()[0])
def speed(self, new_speed=None):
- if new_speed == None:
+ if new_speed is None:
return int(self.char_control_speed.read()[0])
else:
self.char_control_speed.write(bytearray([new_speed]))
def angle(self, new_angle=None):
- if new_angle == None:
+ if new_angle is None:
return int(self.char_control_angle.read()[0])
else:
self.char_control_angle.write(bytearray([new_angle]))
@@ -187,7 +187,6 @@ def loop(self):
self.old_speed = 0
while True:
-
time.sleep_ms(100)
# read out new angle
diff --git a/ports/nrf/main.c b/ports/nrf/main.c
index 2ec16194cb57..f64107f8907f 100644
--- a/ports/nrf/main.c
+++ b/ports/nrf/main.c
@@ -107,9 +107,14 @@ extern uint32_t _heap_start;
extern uint32_t _heap_end;
int main(int argc, char **argv) {
+ // Hook for a board to run code at start up, for example check if a
+ // bootloader should be entered instead of the main application.
+ MICROPY_BOARD_STARTUP();
+ MICROPY_BOARD_EARLY_INIT();
soft_reset:
+
#if MICROPY_PY_TIME_TICKS
rtc1_init_time_ticks();
#endif
@@ -151,7 +156,7 @@ int main(int argc, char **argv) {
rtc_init0();
#endif
- #if MICROPY_PY_MACHINE_TIMER
+ #if MICROPY_PY_MACHINE_TIMER_NRF
timer_init0();
#endif
@@ -165,7 +170,7 @@ int main(int argc, char **argv) {
MP_OBJ_NEW_SMALL_INT(0),
MP_OBJ_NEW_SMALL_INT(115200),
};
- MP_STATE_PORT(board_stdio_uart) = machine_hard_uart_type.make_new((mp_obj_t)&machine_hard_uart_type, MP_ARRAY_SIZE(args), 0, args);
+ MP_STATE_PORT(board_stdio_uart) = MP_OBJ_TYPE_GET_SLOT(&machine_uart_type, make_new)((mp_obj_t)&machine_uart_type, MP_ARRAY_SIZE(args), 0, args);
}
#endif
@@ -179,7 +184,7 @@ int main(int argc, char **argv) {
int ret = mp_vfs_mount_and_chdir_protected((mp_obj_t)&nrf_flash_obj, mount_point);
if ((ret == -MP_ENODEV) || (ret == -MP_EIO)) {
- pyexec_frozen_module("_mkfs.py"); // Frozen script for formatting flash filesystem.
+ pyexec_frozen_module("_mkfs.py", false); // Frozen script for formatting flash filesystem.
ret = mp_vfs_mount_and_chdir_protected((mp_obj_t)&nrf_flash_obj, mount_point);
}
@@ -252,16 +257,16 @@ int main(int argc, char **argv) {
led_state(1, 0);
+ #if MICROPY_HW_USB_CDC
+ usb_cdc_init();
+ #endif
+
#if MICROPY_VFS || MICROPY_MBFS || MICROPY_MODULE_FROZEN
// run boot.py and main.py if they exist.
pyexec_file_if_exists("boot.py");
pyexec_file_if_exists("main.py");
#endif
- #if MICROPY_HW_USB_CDC
- usb_cdc_init();
- #endif
-
for (;;) {
if (pyexec_mode_kind == PYEXEC_MODE_RAW_REPL) {
if (pyexec_raw_repl() != 0) {
@@ -275,6 +280,10 @@ int main(int argc, char **argv) {
}
}
+ #if MICROPY_PY_MACHINE_HW_PWM
+ pwm_deinit_all();
+ #endif
+
mp_deinit();
printf("MPY: soft reboot\n");
diff --git a/ports/nrf/modules/board/led.c b/ports/nrf/modules/board/led.c
index cbfc330d6330..57065a48517a 100644
--- a/ports/nrf/modules/board/led.c
+++ b/ports/nrf/modules/board/led.c
@@ -194,13 +194,14 @@ STATIC const mp_rom_map_elem_t led_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(led_locals_dict, led_locals_dict_table);
-const mp_obj_type_t board_led_type = {
- { &mp_type_type },
- .name = MP_QSTR_LED,
- .print = led_obj_print,
- .make_new = led_obj_make_new,
- .locals_dict = (mp_obj_dict_t*)&led_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ board_led_type,
+ MP_QSTR_LED,
+ MP_TYPE_FLAG_NONE,
+ make_new, led_obj_make_new,
+ print, led_obj_print,
+ locals_dict, &led_locals_dict
+ );
#else
// For boards with no LEDs, we leave an empty function here so that we don't
diff --git a/ports/nrf/modules/machine/adc.c b/ports/nrf/modules/machine/adc.c
index 54870d2c18ee..df9d23465a8d 100644
--- a/ports/nrf/modules/machine/adc.c
+++ b/ports/nrf/modules/machine/adc.c
@@ -294,12 +294,13 @@ STATIC const mp_rom_map_elem_t machine_adc_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(machine_adc_locals_dict, machine_adc_locals_dict_table);
-const mp_obj_type_t machine_adc_type = {
- { &mp_type_type },
- .name = MP_QSTR_ADC,
- .make_new = machine_adc_make_new,
- .locals_dict = (mp_obj_dict_t*)&machine_adc_locals_dict,
- .print = machine_adc_print,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ machine_adc_type,
+ MP_QSTR_ADC,
+ MP_TYPE_FLAG_NONE,
+ make_new, machine_adc_make_new,
+ locals_dict, &machine_adc_locals_dict,
+ print, machine_adc_print
+ );
#endif // MICROPY_PY_MACHINE_ADC
diff --git a/ports/nrf/modules/machine/i2c.c b/ports/nrf/modules/machine/i2c.c
index aac932087320..fad1b7336c95 100644
--- a/ports/nrf/modules/machine/i2c.c
+++ b/ports/nrf/modules/machine/i2c.c
@@ -48,6 +48,7 @@
#define nrfx_twi_config_t nrfx_twim_config_t
#define nrfx_twi_init nrfx_twim_init
+#define nrfx_twi_uninit nrfx_twim_uninit
#define nrfx_twi_enable nrfx_twim_enable
#define nrfx_twi_xfer nrfx_twim_xfer
#define nrfx_twi_disable nrfx_twim_disable
@@ -59,6 +60,8 @@
#define NRFX_TWI_INSTANCE NRFX_TWIM_INSTANCE
+#define NRF_TWI_FREQ_100K NRF_TWIM_FREQ_100K
+#define NRF_TWI_FREQ_250K NRF_TWIM_FREQ_250K
#define NRF_TWI_FREQ_400K NRF_TWIM_FREQ_400K
#endif
@@ -69,8 +72,8 @@ typedef struct _machine_hard_i2c_obj_t {
} machine_hard_i2c_obj_t;
STATIC const machine_hard_i2c_obj_t machine_hard_i2c_obj[] = {
- {{&machine_hard_i2c_type}, .p_twi = NRFX_TWI_INSTANCE(0)},
- {{&machine_hard_i2c_type}, .p_twi = NRFX_TWI_INSTANCE(1)},
+ {{&machine_i2c_type}, .p_twi = NRFX_TWI_INSTANCE(0)},
+ {{&machine_i2c_type}, .p_twi = NRFX_TWI_INSTANCE(1)},
};
void i2c_init0(void) {
@@ -96,11 +99,12 @@ STATIC void machine_hard_i2c_print(const mp_print_t *print, mp_obj_t self_in, mp
mp_obj_t machine_hard_i2c_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
MP_MACHINE_I2C_CHECK_FOR_LEGACY_SOFTI2C_CONSTRUCTION(n_args, n_kw, all_args);
- enum { ARG_id, ARG_scl, ARG_sda };
+ enum { ARG_id, ARG_scl, ARG_sda, ARG_freq };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_id, MP_ARG_REQUIRED | MP_ARG_OBJ },
{ MP_QSTR_scl, MP_ARG_REQUIRED | MP_ARG_OBJ },
{ MP_QSTR_sda, MP_ARG_REQUIRED | MP_ARG_OBJ },
+ { MP_QSTR_freq, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
};
// parse args
@@ -115,10 +119,21 @@ mp_obj_t machine_hard_i2c_make_new(const mp_obj_type_t *type, size_t n_args, siz
config.scl = mp_hal_get_pin_obj(args[ARG_scl].u_obj)->pin;
config.sda = mp_hal_get_pin_obj(args[ARG_sda].u_obj)->pin;
- config.frequency = NRF_TWI_FREQ_400K;
+ int freq = NRF_TWI_FREQ_400K;
+ if (args[ARG_freq].u_int != -1) {
+ if (args[ARG_freq].u_int <= 150000) {
+ freq = NRF_TWI_FREQ_100K;
+ } else if (args[ARG_freq].u_int < 320000) {
+ freq = NRF_TWI_FREQ_250K;
+ }
+ }
+ config.frequency = freq;
config.hold_bus_uninit = false;
+ // First reset the TWI
+ nrfx_twi_uninit(&self->p_twi);
+
// Set context to this object.
nrfx_twi_init(&self->p_twi, &config, NULL, (void *)self);
@@ -161,13 +176,14 @@ STATIC const mp_machine_i2c_p_t machine_hard_i2c_p = {
.transfer_single = machine_hard_i2c_transfer_single,
};
-const mp_obj_type_t machine_hard_i2c_type = {
- { &mp_type_type },
- .name = MP_QSTR_I2C,
- .print = machine_hard_i2c_print,
- .make_new = machine_hard_i2c_make_new,
- .protocol = &machine_hard_i2c_p,
- .locals_dict = (mp_obj_dict_t*)&mp_machine_i2c_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ machine_i2c_type,
+ MP_QSTR_I2C,
+ MP_TYPE_FLAG_NONE,
+ make_new, machine_hard_i2c_make_new,
+ print, machine_hard_i2c_print,
+ protocol, &machine_hard_i2c_p,
+ locals_dict, &mp_machine_i2c_locals_dict
+ );
#endif // MICROPY_PY_MACHINE_I2C
diff --git a/ports/nrf/modules/machine/i2c.h b/ports/nrf/modules/machine/i2c.h
index 1dfb1f077a44..5c5befc28535 100644
--- a/ports/nrf/modules/machine/i2c.h
+++ b/ports/nrf/modules/machine/i2c.h
@@ -29,7 +29,7 @@
#include "extmod/machine_i2c.h"
-extern const mp_obj_type_t machine_hard_i2c_type;
+extern const mp_obj_type_t machine_i2c_type;
void i2c_init0(void);
diff --git a/ports/nrf/modules/machine/modmachine.c b/ports/nrf/modules/machine/modmachine.c
index 1378ba8f4be3..b080a526cf7b 100644
--- a/ports/nrf/modules/machine/modmachine.c
+++ b/ports/nrf/modules/machine/modmachine.c
@@ -42,7 +42,7 @@
#include "spi.h"
#include "i2c.h"
#include "timer.h"
-#if MICROPY_PY_MACHINE_HW_PWM
+#if MICROPY_PY_MACHINE_HW_PWM || MICROPY_PY_MACHINE_SOFT_PWM
#include "pwm.h"
#endif
#if MICROPY_PY_MACHINE_ADC
@@ -133,7 +133,7 @@ STATIC mp_obj_t machine_info(mp_uint_t n_args, const mp_obj_t *args) {
if (n_args == 1) {
// arg given means dump gc allocation table
- gc_dump_alloc_table();
+ gc_dump_alloc_table(&mp_plat_print);
}
return mp_const_none;
@@ -153,6 +153,19 @@ STATIC mp_obj_t machine_soft_reset(void) {
}
MP_DEFINE_CONST_FUN_OBJ_0(machine_soft_reset_obj, machine_soft_reset);
+NORETURN mp_obj_t machine_bootloader(size_t n_args, const mp_obj_t *args) {
+ MICROPY_BOARD_ENTER_BOOTLOADER(n_args, args);
+ for (;;) {
+ }
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_bootloader_obj, 0, 1, machine_bootloader);
+
+STATIC mp_obj_t machine_idle(void) {
+ MICROPY_EVENT_POLL_HOOK;
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_idle_obj, machine_idle);
+
STATIC mp_obj_t machine_lightsleep(void) {
__WFE();
return mp_const_none;
@@ -196,8 +209,10 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_info), MP_ROM_PTR(&machine_info_obj) },
{ MP_ROM_QSTR(MP_QSTR_reset), MP_ROM_PTR(&machine_reset_obj) },
{ MP_ROM_QSTR(MP_QSTR_soft_reset), MP_ROM_PTR(&machine_soft_reset_obj) },
+ { MP_ROM_QSTR(MP_QSTR_bootloader), MP_ROM_PTR(&machine_bootloader_obj) },
{ MP_ROM_QSTR(MP_QSTR_enable_irq), MP_ROM_PTR(&machine_enable_irq_obj) },
{ MP_ROM_QSTR(MP_QSTR_disable_irq), MP_ROM_PTR(&machine_disable_irq_obj) },
+ { MP_ROM_QSTR(MP_QSTR_idle), MP_ROM_PTR(&machine_idle_obj) },
{ MP_ROM_QSTR(MP_QSTR_sleep), MP_ROM_PTR(&machine_lightsleep_obj) },
{ MP_ROM_QSTR(MP_QSTR_lightsleep), MP_ROM_PTR(&machine_lightsleep_obj) },
{ MP_ROM_QSTR(MP_QSTR_deepsleep), MP_ROM_PTR(&machine_deepsleep_obj) },
@@ -208,13 +223,13 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_mem32), MP_ROM_PTR(&machine_mem32_obj) },
#if MICROPY_PY_MACHINE_UART
- { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&machine_hard_uart_type) },
+ { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&machine_uart_type) },
#endif
#if MICROPY_PY_MACHINE_HW_SPI
- { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&machine_hard_spi_type) },
+ { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&machine_spi_type) },
#endif
#if MICROPY_PY_MACHINE_I2C
- { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&machine_hard_i2c_type) },
+ { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&machine_i2c_type) },
{ MP_ROM_QSTR(MP_QSTR_SoftI2C), MP_ROM_PTR(&mp_machine_soft_i2c_type) },
#endif
#if MICROPY_PY_MACHINE_ADC
@@ -223,11 +238,11 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = {
#if MICROPY_PY_MACHINE_RTCOUNTER
{ MP_ROM_QSTR(MP_QSTR_RTCounter), MP_ROM_PTR(&machine_rtcounter_type) },
#endif
-#if MICROPY_PY_MACHINE_TIMER
+#if MICROPY_PY_MACHINE_TIMER_NRF
{ MP_ROM_QSTR(MP_QSTR_Timer), MP_ROM_PTR(&machine_timer_type) },
#endif
-#if MICROPY_PY_MACHINE_HW_PWM
- { MP_ROM_QSTR(MP_QSTR_PWM), MP_ROM_PTR(&machine_hard_pwm_type) },
+#if MICROPY_PY_MACHINE_HW_PWM || MICROPY_PY_MACHINE_SOFT_PWM
+ { MP_ROM_QSTR(MP_QSTR_PWM), MP_ROM_PTR(&machine_pwm_type) },
#endif
#if MICROPY_PY_MACHINE_TEMP
{ MP_ROM_QSTR(MP_QSTR_Temp), MP_ROM_PTR(&machine_temp_type) },
diff --git a/ports/nrf/modules/machine/modmachine.h b/ports/nrf/modules/machine/modmachine.h
index 1ea6959eabab..e5412673f822 100644
--- a/ports/nrf/modules/machine/modmachine.h
+++ b/ports/nrf/modules/machine/modmachine.h
@@ -38,5 +38,6 @@ MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(machine_info_obj);
MP_DECLARE_CONST_FUN_OBJ_0(machine_reset_obj);
MP_DECLARE_CONST_FUN_OBJ_0(machine_lightsleep_obj);
MP_DECLARE_CONST_FUN_OBJ_0(machine_deepsleep_obj);
+NORETURN mp_obj_t machine_bootloader(size_t n_args, const mp_obj_t *args);
#endif // __MICROPY_INCLUDED_NRF5_MODMACHINE_H__
diff --git a/ports/nrf/modules/machine/pin.c b/ports/nrf/modules/machine/pin.c
index 170caf6dde4c..db5cc9cbb136 100644
--- a/ports/nrf/modules/machine/pin.c
+++ b/ports/nrf/modules/machine/pin.c
@@ -37,6 +37,12 @@
#include "nrf_gpio.h"
#include "nrfx_gpiote.h"
+#if defined(NRF52840_XXAA)
+#define NUM_OF_PINS 48
+#else
+#define NUM_OF_PINS 32
+#endif
+
extern const pin_obj_t machine_board_pin_obj[];
extern const uint8_t machine_pin_num_of_board_pins;
@@ -590,14 +596,15 @@ STATIC const mp_rom_map_elem_t pin_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(pin_locals_dict, pin_locals_dict_table);
-const mp_obj_type_t pin_type = {
- { &mp_type_type },
- .name = MP_QSTR_Pin,
- .print = pin_print,
- .make_new = pin_make_new,
- .call = pin_call,
- .locals_dict = (mp_obj_dict_t*)&pin_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ pin_type,
+ MP_QSTR_Pin,
+ MP_TYPE_FLAG_NONE,
+ make_new, pin_make_new,
+ print, pin_print,
+ call, pin_call,
+ locals_dict, &pin_locals_dict
+ );
/// \moduleref machine
/// \class PinAF - Pin Alternate Functions
@@ -665,9 +672,14 @@ STATIC const mp_rom_map_elem_t pin_af_locals_dict_table[] = {
};
STATIC MP_DEFINE_CONST_DICT(pin_af_locals_dict, pin_af_locals_dict_table);
-const mp_obj_type_t pin_af_type = {
- { &mp_type_type },
- .name = MP_QSTR_PinAF,
- .print = pin_af_obj_print,
- .locals_dict = (mp_obj_dict_t*)&pin_af_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ pin_af_type,
+ MP_QSTR_PinAF,
+ MP_TYPE_FLAG_NONE,
+ print, pin_af_obj_print,
+ locals_dict, &pin_af_locals_dict
+ );
+
+MP_REGISTER_ROOT_POINTER(mp_obj_t pin_class_mapper);
+MP_REGISTER_ROOT_POINTER(mp_obj_t pin_class_map_dict);
+MP_REGISTER_ROOT_POINTER(mp_obj_t pin_irq_handlers[NUM_OF_PINS]);
diff --git a/ports/nrf/modules/machine/pwm.c b/ports/nrf/modules/machine/pwm.c
index a750285841e2..96917769eed4 100644
--- a/ports/nrf/modules/machine/pwm.c
+++ b/ports/nrf/modules/machine/pwm.c
@@ -4,6 +4,7 @@
* The MIT License (MIT)
*
* Copyright (c) 2016-2018 Glenn Ruben Bakke
+ * Copyright (c) 2023 Robert Hammelrath
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -42,309 +43,355 @@
#include "nrfx_pwm.h"
#endif
+#define PWM_MAX_BASE_FREQ (16000000)
+#define PWM_MIN_BASE_FREQ (125000)
+#define PWM_MAX_PERIOD (32768)
+
typedef enum {
- MODE_LOW_HIGH,
- MODE_HIGH_LOW
+ MODE_HIGH_LOW = 0,
+ MODE_LOW_HIGH
} pwm_mode_t;
+typedef enum {
+ DUTY_NOT_SET = 0,
+ DUTY_PERCENT,
+ DUTY_U16,
+ DUTY_NS
+} pwm_duty_t;
+
+typedef enum {
+ FREE = 0,
+ STOPPED,
+ RUNNING
+} pwm_run_t;
+
typedef struct {
- uint8_t pwm_pin;
- uint8_t duty;
- uint16_t pulse_width;
- uint16_t period;
- nrf_pwm_clk_t freq;
- pwm_mode_t mode;
+ uint8_t pwm_pin[NRF_PWM_CHANNEL_COUNT];
+ pwm_mode_t mode[NRF_PWM_CHANNEL_COUNT];
+ pwm_duty_t duty_mode[NRF_PWM_CHANNEL_COUNT];
+ uint32_t duty[NRF_PWM_CHANNEL_COUNT];
+ uint16_t pwm_seq[4];
+ pwm_run_t active;
+ bool defer_start;
+ int8_t freq_div;
+ uint32_t freq;
} machine_pwm_config_t;
-typedef struct _machine_hard_pwm_obj_t {
- mp_obj_base_t base;
- const nrfx_pwm_t * p_pwm;
- machine_pwm_config_t * p_config;
-} machine_hard_pwm_obj_t;
+typedef struct _machine_pwm_obj_t {
+ mp_obj_base_t base;
+ const nrfx_pwm_t *p_pwm;
+ machine_pwm_config_t *p_config;
+ uint8_t id;
+ uint8_t channel;
+} machine_pwm_obj_t;
STATIC const nrfx_pwm_t machine_hard_pwm_instances[] = {
-#if defined(NRF52_SERIES)
+ #if defined(NRF52_SERIES)
NRFX_PWM_INSTANCE(0),
NRFX_PWM_INSTANCE(1),
NRFX_PWM_INSTANCE(2),
-#if NRF52840
+ #if NRF52840
NRFX_PWM_INSTANCE(3),
-#endif
-#endif
+ #endif
+ #endif
};
STATIC machine_pwm_config_t hard_configs[MP_ARRAY_SIZE(machine_hard_pwm_instances)];
-STATIC const machine_hard_pwm_obj_t machine_hard_pwm_obj[] = {
-#if defined(NRF52_SERIES)
- {{&machine_hard_pwm_type}, .p_pwm = &machine_hard_pwm_instances[0], .p_config = &hard_configs[0]},
- {{&machine_hard_pwm_type}, .p_pwm = &machine_hard_pwm_instances[1], .p_config = &hard_configs[1]},
- {{&machine_hard_pwm_type}, .p_pwm = &machine_hard_pwm_instances[2], .p_config = &hard_configs[2]},
-#if NRF52840
- {{&machine_hard_pwm_type}, .p_pwm = &machine_hard_pwm_instances[3], .p_config = &hard_configs[3]},
-#endif
-#endif
+STATIC const machine_pwm_obj_t machine_hard_pwm_obj[] = {
+ #if defined(NRF52_SERIES)
+ {{&machine_pwm_type}, .p_pwm = &machine_hard_pwm_instances[0], .p_config = &hard_configs[0], 0, 0},
+ {{&machine_pwm_type}, .p_pwm = &machine_hard_pwm_instances[0], .p_config = &hard_configs[0], 0, 1},
+ {{&machine_pwm_type}, .p_pwm = &machine_hard_pwm_instances[0], .p_config = &hard_configs[0], 0, 2},
+ {{&machine_pwm_type}, .p_pwm = &machine_hard_pwm_instances[0], .p_config = &hard_configs[0], 0, 3},
+ {{&machine_pwm_type}, .p_pwm = &machine_hard_pwm_instances[1], .p_config = &hard_configs[1], 1, 0},
+ {{&machine_pwm_type}, .p_pwm = &machine_hard_pwm_instances[1], .p_config = &hard_configs[1], 1, 1},
+ {{&machine_pwm_type}, .p_pwm = &machine_hard_pwm_instances[1], .p_config = &hard_configs[1], 1, 2},
+ {{&machine_pwm_type}, .p_pwm = &machine_hard_pwm_instances[1], .p_config = &hard_configs[1], 1, 3},
+ {{&machine_pwm_type}, .p_pwm = &machine_hard_pwm_instances[2], .p_config = &hard_configs[2], 2, 0},
+ {{&machine_pwm_type}, .p_pwm = &machine_hard_pwm_instances[2], .p_config = &hard_configs[2], 2, 1},
+ {{&machine_pwm_type}, .p_pwm = &machine_hard_pwm_instances[2], .p_config = &hard_configs[2], 2, 2},
+ {{&machine_pwm_type}, .p_pwm = &machine_hard_pwm_instances[2], .p_config = &hard_configs[2], 2, 3},
+ #if NRF52840
+ {{&machine_pwm_type}, .p_pwm = &machine_hard_pwm_instances[3], .p_config = &hard_configs[3], 3, 0},
+ {{&machine_pwm_type}, .p_pwm = &machine_hard_pwm_instances[3], .p_config = &hard_configs[3], 3, 1},
+ {{&machine_pwm_type}, .p_pwm = &machine_hard_pwm_instances[3], .p_config = &hard_configs[3], 3, 2},
+ {{&machine_pwm_type}, .p_pwm = &machine_hard_pwm_instances[3], .p_config = &hard_configs[3], 3, 3},
+ #endif
+ #endif
};
void pwm_init0(void) {
+ for (int i = 0; i < MP_ARRAY_SIZE(hard_configs); i++) {
+ hard_configs[i].active = FREE;
+ hard_configs[i].freq_div = -1;
+ hard_configs[i].freq = 0;
+ memset(hard_configs[i].duty_mode, DUTY_NOT_SET, NRF_PWM_CHANNEL_COUNT);
+ }
}
-
-STATIC int hard_pwm_find(mp_obj_t id) {
- if (mp_obj_is_int(id)) {
- // given an integer id
- int pwm_id = mp_obj_get_int(id);
- if (pwm_id >= 0 && pwm_id < MP_ARRAY_SIZE(machine_hard_pwm_obj)) {
- return pwm_id;
+// Find a free PWM object
+STATIC int hard_pwm_find() {
+ // look for a free module.
+ for (int j = 0; j < MP_ARRAY_SIZE(hard_configs); j++) {
+ if (hard_configs[j].active == FREE) {
+ return j * NRF_PWM_CHANNEL_COUNT;
}
- mp_raise_ValueError(MP_ERROR_TEXT("PWM doesn't exist"));
}
- return -1;
+ mp_raise_ValueError(MP_ERROR_TEXT("all PWM devices in use"));
}
-STATIC void machine_pwm_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
- machine_hard_pwm_obj_t *self = self_in;
- mp_printf(print, "PWM(%u)", self->p_pwm->drv_inst_idx);
+STATIC void mp_machine_pwm_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
+ machine_pwm_obj_t *self = self_in;
+ static char *duty_suffix[] = { "", "", "_u16", "_ns" };
+ mp_printf(print, "",
+ self->p_config->pwm_pin[self->channel], self->p_config->freq,
+ duty_suffix[self->p_config->duty_mode[self->channel]], self->p_config->duty[self->channel],
+ self->p_config->mode[self->channel], self->id, self->channel);
}
/******************************************************************************/
/* MicroPython bindings for machine API */
-STATIC mp_obj_t machine_hard_pwm_make_new(mp_arg_val_t *args);
-STATIC void machine_hard_pwm_init(mp_obj_t self, mp_arg_val_t *args);
-STATIC void machine_hard_pwm_deinit(mp_obj_t self);
-STATIC mp_obj_t machine_hard_pwm_freq(mp_obj_t self, mp_arg_val_t *args);
-
-/* common code for both soft and hard implementations *************************/
-
-STATIC mp_obj_t machine_pwm_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
- enum { ARG_id, ARG_pin, ARG_freq, ARG_period, ARG_duty, ARG_pulse_width, ARG_mode };
- static const mp_arg_t allowed_args[] = {
- { MP_QSTR_id, MP_ARG_OBJ, {.u_obj = MP_OBJ_NEW_SMALL_INT(-1)} },
- { MP_QSTR_pin, MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
- { MP_QSTR_freq, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
- { MP_QSTR_period, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
- { MP_QSTR_duty, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
- { MP_QSTR_pulse_width, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
- { MP_QSTR_mode, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
- };
-
- // parse args
- mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
- mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
-
- if (args[ARG_id].u_obj == MP_OBJ_NEW_SMALL_INT(-1)) {
- // TODO: implement soft PWM
- // return machine_soft_pwm_make_new(args);
- return mp_const_none;
- } else {
- // hardware peripheral id given
- return machine_hard_pwm_make_new(args);
- }
-}
+STATIC void machine_hard_pwm_start(const machine_pwm_obj_t *self);
+STATIC void mp_machine_pwm_deinit(const machine_pwm_obj_t *self);
+STATIC void mp_machine_pwm_freq_set(const machine_pwm_obj_t *self, mp_int_t freq);
+STATIC void mp_machine_pwm_duty_set(const machine_pwm_obj_t *self, mp_int_t duty);
+STATIC void mp_machine_pwm_duty_set_u16(const machine_pwm_obj_t *self, mp_int_t duty_u16);
+STATIC void mp_machine_pwm_duty_set_ns(const machine_pwm_obj_t *self, mp_int_t duty_ns);
+
+static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_pin, MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
+ { MP_QSTR_freq, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
+ { MP_QSTR_duty, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
+ { MP_QSTR_duty_u16, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
+ { MP_QSTR_duty_ns, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
+ { MP_QSTR_invert, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
+ { MP_QSTR_device, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
+ { MP_QSTR_channel, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
+};
-STATIC mp_obj_t machine_pwm_init(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
- enum { ARG_INIT_pin };
- static const mp_arg_t allowed_args[] = {
- { MP_QSTR_pin, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }
- };
+STATIC void mp_machine_pwm_init_helper(const machine_pwm_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ enum { ARG_pin, ARG_freq, ARG_duty, ARG_duty_u16, ARG_duty_ns, ARG_invert, ARG_device, ARG_channel };
- // parse args
- mp_obj_t self = pos_args[0];
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
- mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
+ mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
- // dispatch to specific implementation
- if (mp_obj_get_type(self) == &machine_hard_pwm_type) {
- machine_hard_pwm_init(self, args);
+ self->p_config->defer_start = true;
+ if (args[ARG_freq].u_int != -1) {
+ mp_machine_pwm_freq_set(self, args[ARG_freq].u_int);
+ }
+ if (args[ARG_duty].u_int != -1) {
+ mp_machine_pwm_duty_set(self, args[ARG_duty].u_int);
+ }
+ if (args[ARG_duty_u16].u_int != -1) {
+ mp_machine_pwm_duty_set_u16(self, args[ARG_duty_u16].u_int);
+ }
+ if (args[ARG_duty_ns].u_int != -1) {
+ mp_machine_pwm_duty_set_ns(self, args[ARG_duty_ns].u_int);
}
+ if (args[ARG_invert].u_int != -1) {
+ self->p_config->mode[self->channel] = args[ARG_invert].u_int ? MODE_LOW_HIGH : MODE_HIGH_LOW;
+ }
+ self->p_config->defer_start = false;
- return mp_const_none;
+ machine_hard_pwm_start(self);
}
-STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_pwm_init_obj, 1, machine_pwm_init);
-STATIC mp_obj_t machine_pwm_deinit(mp_obj_t self) {
- // dispatch to specific implementation
- if (mp_obj_get_type(self) == &machine_hard_pwm_type) {
- machine_hard_pwm_deinit(self);
- }
- return mp_const_none;
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_pwm_deinit_obj, machine_pwm_deinit);
-STATIC mp_obj_t machine_pwm_freq(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
- enum { ARG_FREQ_freq };
- static const mp_arg_t allowed_args[] = {
- { MP_QSTR_freq, MP_ARG_INT, {.u_int = -1} },
- };
+STATIC mp_obj_t mp_machine_pwm_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
+ enum { ARG_pin, ARG_freq, ARG_duty, ARG_duty_u16, ARG_duty_ns, ARG_invert, ARG_device, ARG_channel };
- mp_obj_t self = pos_args[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(allowed_args), allowed_args, args);
+ mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
- if (mp_obj_get_type(self) == &machine_hard_pwm_type) {
- machine_hard_pwm_freq(self, args);
+ // check if the PWM pin is given.
+ int pwm_pin;
+ if (args[ARG_pin].u_obj != MP_OBJ_NULL) {
+ pwm_pin = mp_hal_get_pin_obj(args[ARG_pin].u_obj)->pin;
} else {
- // soft pwm
+ mp_raise_ValueError(MP_ERROR_TEXT("Pin missing"));
}
- return mp_const_none;
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mp_machine_pwm_freq_obj, 1, machine_pwm_freq);
+ // Get the PWM object number
+ // If just the ID is given, use channel 0
+ // If none is given, attempt to find an unused object.
+ int pwm_id = -1;
+ if (args[ARG_device].u_int != -1) {
+ if (args[ARG_device].u_int >= 0 && args[ARG_device].u_int < MP_ARRAY_SIZE(machine_hard_pwm_instances)) {
+ pwm_id = args[ARG_device].u_int * NRF_PWM_CHANNEL_COUNT;
+ if (args[ARG_channel].u_int != -1) {
+ if (args[ARG_channel].u_int >= 0 && args[ARG_channel].u_int < NRF_PWM_CHANNEL_COUNT) {
+ pwm_id += args[ARG_channel].u_int;
+ }
+ }
+ }
+ } else {
+ // no ID given, search for a free ID.
+ pwm_id = hard_pwm_find();
+ }
+ if (pwm_id < 0) {
+ mp_raise_ValueError(MP_ERROR_TEXT("invalid PWM id"));
+ }
+ const machine_pwm_obj_t *self = &machine_hard_pwm_obj[pwm_id];
+ int pwm_channel = pwm_id % NRF_PWM_CHANNEL_COUNT;
+ self->p_config->pwm_pin[pwm_channel] = pwm_pin;
+ self->p_config->duty_mode[pwm_channel] = DUTY_NOT_SET;
+ self->p_config->duty[pwm_channel] = 0;
+ self->p_config->mode[pwm_channel] = MODE_HIGH_LOW;
+ self->p_config->defer_start = false;
+
+ // start the PWM running for this channel
+ mp_map_t kw_args;
+ mp_map_init_fixed_table(&kw_args, n_kw, all_args + n_args);
+ mp_machine_pwm_init_helper(self, n_args, all_args, &kw_args);
-STATIC mp_obj_t machine_pwm_period(size_t n_args, const mp_obj_t *args) {
- return mp_const_none;
+ return MP_OBJ_FROM_PTR(self);
}
-STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_machine_pwm_period_obj, 1, 2, machine_pwm_period);
-STATIC mp_obj_t machine_pwm_duty(size_t n_args, const mp_obj_t *args) {
- return mp_const_none;
+// Stop all PWM modules and release them
+void pwm_deinit_all(void) {
+ for (int i = 0; i < MP_ARRAY_SIZE(machine_hard_pwm_instances); i++) {
+ mp_machine_pwm_deinit(&machine_hard_pwm_obj[i * NRF_PWM_CHANNEL_COUNT]);
+ }
+ pwm_init0();
}
-STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_machine_pwm_duty_obj, 1, 2, machine_pwm_duty);
-
-STATIC const mp_rom_map_elem_t machine_pwm_locals_dict_table[] = {
- { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_pwm_init_obj) },
- { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_pwm_deinit_obj) },
-
- { MP_ROM_QSTR(MP_QSTR_freq), MP_ROM_PTR(&mp_machine_pwm_freq_obj) },
- { MP_ROM_QSTR(MP_QSTR_period), MP_ROM_PTR(&mp_machine_pwm_period_obj) },
- { MP_ROM_QSTR(MP_QSTR_duty), MP_ROM_PTR(&mp_machine_pwm_duty_obj) },
-
- { MP_ROM_QSTR(MP_QSTR_FREQ_16MHZ), MP_ROM_INT(NRF_PWM_CLK_16MHz) },
- { MP_ROM_QSTR(MP_QSTR_FREQ_8MHZ), MP_ROM_INT(NRF_PWM_CLK_8MHz) },
- { MP_ROM_QSTR(MP_QSTR_FREQ_4MHZ), MP_ROM_INT(NRF_PWM_CLK_4MHz) },
- { MP_ROM_QSTR(MP_QSTR_FREQ_2MHZ), MP_ROM_INT(NRF_PWM_CLK_2MHz) },
- { MP_ROM_QSTR(MP_QSTR_FREQ_1MHZ), MP_ROM_INT(NRF_PWM_CLK_1MHz) },
- { MP_ROM_QSTR(MP_QSTR_FREQ_500KHZ), MP_ROM_INT(NRF_PWM_CLK_500kHz) },
- { MP_ROM_QSTR(MP_QSTR_FREQ_250KHZ), MP_ROM_INT(NRF_PWM_CLK_250kHz) },
- { MP_ROM_QSTR(MP_QSTR_FREQ_125KHZ), MP_ROM_INT(NRF_PWM_CLK_125kHz) },
-
- { MP_ROM_QSTR(MP_QSTR_MODE_LOW_HIGH), MP_ROM_INT(MODE_LOW_HIGH) },
- { MP_ROM_QSTR(MP_QSTR_MODE_HIGH_LOW), MP_ROM_INT(MODE_HIGH_LOW) },
-};
-STATIC MP_DEFINE_CONST_DICT(machine_pwm_locals_dict, machine_pwm_locals_dict_table);
+// Stop the PWM module, but do not release it.
+STATIC void mp_machine_pwm_deinit(const machine_pwm_obj_t *self) {
+ self->p_config->active = STOPPED;
+ nrfx_pwm_stop(self->p_pwm, true);
+ nrfx_pwm_uninit(self->p_pwm);
+}
-/* code for hard implementation ***********************************************/
+STATIC mp_obj_t mp_machine_pwm_freq_get(const machine_pwm_obj_t *self) {
+ return MP_OBJ_NEW_SMALL_INT(self->p_config->freq);
+}
-STATIC mp_obj_t machine_hard_pwm_make_new(mp_arg_val_t *args) {
- enum { ARG_id, ARG_pin, ARG_freq, ARG_period, ARG_duty, ARG_pulse_width, ARG_mode };
- // get static peripheral object
- int pwm_id = hard_pwm_find(args[ARG_id].u_obj);
- const machine_hard_pwm_obj_t *self = &machine_hard_pwm_obj[pwm_id];
+STATIC void mp_machine_pwm_freq_set(const machine_pwm_obj_t *self, mp_int_t freq) {
- // check if PWM pin is set
- if (args[ARG_pin].u_obj != MP_OBJ_NULL) {
- self->p_config->pwm_pin = mp_hal_get_pin_obj(args[ARG_pin].u_obj)->pin;
- } else {
- // TODO: raise exception.
+ uint8_t div = 0;
+ if (freq > (PWM_MAX_BASE_FREQ / 3) || freq <= (PWM_MIN_BASE_FREQ / PWM_MAX_PERIOD)) {
+ mp_raise_ValueError(MP_ERROR_TEXT("frequency out of range"));
}
-
- if (args[ARG_freq].u_obj != MP_OBJ_NULL) {
- self->p_config->freq = mp_obj_get_int(args[ARG_freq].u_obj);
- } else {
- self->p_config->freq = 50; // 50 Hz by default.
+ for (div = 0; div < 8; div++) {
+ if (PWM_MAX_BASE_FREQ / (1 << div) / freq < PWM_MAX_PERIOD) {
+ break;
+ }
}
+ self->p_config->freq_div = div;
+ self->p_config->freq = freq;
+ machine_hard_pwm_start(self);
+}
- if (args[ARG_period].u_obj != MP_OBJ_NULL) {
- self->p_config->period = mp_obj_get_int(args[ARG_period].u_obj);
+STATIC mp_obj_t mp_machine_pwm_duty_get(const machine_pwm_obj_t *self) {
+ if (self->p_config->duty_mode[self->channel] == DUTY_PERCENT) {
+ return MP_OBJ_NEW_SMALL_INT(self->p_config->duty[self->channel]);
+ } else if (self->p_config->duty_mode[self->channel] == DUTY_U16) {
+ return MP_OBJ_NEW_SMALL_INT(self->p_config->duty[self->channel] * 100 / 65536);
} else {
- mp_raise_ValueError(MP_ERROR_TEXT("PWM period must be within 16000 cycles"));
+ return MP_OBJ_NEW_SMALL_INT(-1);
}
+}
- if (args[ARG_duty].u_obj != MP_OBJ_NULL) {
- self->p_config->duty = mp_obj_get_int(args[ARG_duty].u_obj);
- } else {
- self->p_config->duty = 50; // 50% by default.
- }
+STATIC void mp_machine_pwm_duty_set(const machine_pwm_obj_t *self, mp_int_t duty) {
+ self->p_config->duty[self->channel] = duty;
+ self->p_config->duty_mode[self->channel] = DUTY_PERCENT;
+ machine_hard_pwm_start(self);
+}
- if (args[ARG_pulse_width].u_obj != MP_OBJ_NULL) {
- self->p_config->pulse_width = mp_obj_get_int(args[ARG_pulse_width].u_obj);
+STATIC mp_obj_t mp_machine_pwm_duty_get_u16(const machine_pwm_obj_t *self) {
+ if (self->p_config->duty_mode[self->channel] == DUTY_U16) {
+ return MP_OBJ_NEW_SMALL_INT(self->p_config->duty[self->channel]);
+ } else if (self->p_config->duty_mode[self->channel] == DUTY_PERCENT) {
+ return MP_OBJ_NEW_SMALL_INT(self->p_config->duty[self->channel] * 65536 / 100);
} else {
- self->p_config->pulse_width = 0;
+ return MP_OBJ_NEW_SMALL_INT(-1);
}
+}
- if (args[ARG_mode].u_obj != MP_OBJ_NULL) {
- self->p_config->mode = mp_obj_get_int(args[ARG_mode].u_obj);
+STATIC void mp_machine_pwm_duty_set_u16(const machine_pwm_obj_t *self, mp_int_t duty) {
+ self->p_config->duty[self->channel] = duty;
+ self->p_config->duty_mode[self->channel] = DUTY_U16;
+ machine_hard_pwm_start(self);
+}
+
+STATIC mp_obj_t mp_machine_pwm_duty_get_ns(const machine_pwm_obj_t *self) {
+ if (self->p_config->duty_mode[self->channel] == DUTY_NS) {
+ return MP_OBJ_NEW_SMALL_INT(self->p_config->duty[self->channel]);
} else {
- self->p_config->mode = MODE_HIGH_LOW;
+ return MP_OBJ_NEW_SMALL_INT(-1);
}
+}
- return MP_OBJ_FROM_PTR(self);
+STATIC void mp_machine_pwm_duty_set_ns(const machine_pwm_obj_t *self, mp_int_t duty) {
+ self->p_config->duty[self->channel] = duty;
+ self->p_config->duty_mode[self->channel] = DUTY_NS;
+ machine_hard_pwm_start(self);
}
-STATIC void machine_hard_pwm_init(mp_obj_t self_in, mp_arg_val_t *args) {
- machine_hard_pwm_obj_t *self = self_in;
+/* code for hard implementation ***********************************************/
+
+STATIC void machine_hard_pwm_start(const machine_pwm_obj_t *self) {
nrfx_pwm_config_t config;
- config.output_pins[0] = self->p_config->pwm_pin;
- config.output_pins[1] = NRFX_PWM_PIN_NOT_USED;
- config.output_pins[2] = NRFX_PWM_PIN_NOT_USED;
- config.output_pins[3] = NRFX_PWM_PIN_NOT_USED;
+ // check if ready to go
+ if (self->p_config->defer_start == true || self->p_config->freq_div < 0 || self->p_config->duty_mode[self->channel] == DUTY_NOT_SET) {
+ return; // Not ready yet.
+ }
- config.irq_priority = 6;
- config.base_clock = self->p_config->freq;
- config.count_mode = NRF_PWM_MODE_UP;
- config.top_value = self->p_config->period;
- config.load_mode = NRF_PWM_LOAD_INDIVIDUAL;
- config.step_mode = NRF_PWM_STEP_AUTO;
+ self->p_config->active = RUNNING;
- nrfx_pwm_init(self->p_pwm, &config, NULL, NULL);
+ config.output_pins[0] = self->p_config->duty_mode[0] != DUTY_NOT_SET ? self->p_config->pwm_pin[0] : NRFX_PWM_PIN_NOT_USED;
+ config.output_pins[1] = self->p_config->duty_mode[1] != DUTY_NOT_SET ? self->p_config->pwm_pin[1] : NRFX_PWM_PIN_NOT_USED;
+ config.output_pins[2] = self->p_config->duty_mode[2] != DUTY_NOT_SET ? self->p_config->pwm_pin[2] : NRFX_PWM_PIN_NOT_USED;
+ config.output_pins[3] = self->p_config->duty_mode[3] != DUTY_NOT_SET ? self->p_config->pwm_pin[3] : NRFX_PWM_PIN_NOT_USED;
- uint16_t pulse_width = ((self->p_config->period * self->p_config->duty) / 100);
+ uint32_t tick_freq = PWM_MAX_BASE_FREQ / (1 << self->p_config->freq_div);
+ uint32_t period = tick_freq / self->p_config->freq;
- // If manual period has been set, override duty-cycle.
- if (self->p_config->pulse_width > 0) {
- pulse_width = self->p_config->pulse_width;
- }
+ config.irq_priority = 6;
+ config.base_clock = self->p_config->freq_div;
+ config.count_mode = NRF_PWM_MODE_UP;
+ config.top_value = period;
+ config.load_mode = NRF_PWM_LOAD_INDIVIDUAL;
+ config.step_mode = NRF_PWM_STEP_AUTO;
- // TODO: Move DMA buffer to global memory.
- volatile static uint16_t pwm_seq[4];
+ nrfx_pwm_stop(self->p_pwm, true);
+ nrfx_pwm_uninit(self->p_pwm);
- if (self->p_config->mode == MODE_HIGH_LOW) {
- pwm_seq[0] = self->p_config->period - pulse_width;
- pwm_seq[1] = self->p_config->period - pulse_width;
- } else {
- pwm_seq[0] = self->p_config->period - pulse_width;
- pwm_seq[1] = self->p_config->period - pulse_width;
- }
+ nrfx_pwm_init(self->p_pwm, &config, NULL, NULL);
- pwm_seq[2] = self->p_config->period - pulse_width;
- pwm_seq[3] = self->p_config->period - pulse_width;
+ for (int i = 0; i < NRF_PWM_CHANNEL_COUNT; i++) {
+ uint16_t pulse_width = 0;
+ if (self->p_config->duty_mode[i] == DUTY_PERCENT) {
+ pulse_width = ((period * self->p_config->duty[i]) / 100);
+ } else if (self->p_config->duty_mode[i] == DUTY_U16) {
+ pulse_width = ((period * self->p_config->duty[i]) / 65536);
+ } else if (self->p_config->duty_mode[i] == DUTY_NS) {
+ pulse_width = (uint64_t)self->p_config->duty[i] * tick_freq / 1000000000ULL;
+ }
+
+ if (self->p_config->mode[i] == MODE_HIGH_LOW) {
+ self->p_config->pwm_seq[i] = 0x8000 | pulse_width;
+ } else {
+ self->p_config->pwm_seq[i] = pulse_width;
+ }
+ }
const nrf_pwm_sequence_t pwm_sequence = {
- .values.p_raw = (const uint16_t *)&pwm_seq,
+ .values.p_raw = (const uint16_t *)&self->p_config->pwm_seq,
.length = 4,
.repeats = 0,
.end_delay = 0
};
nrfx_pwm_simple_playback(self->p_pwm,
- &pwm_sequence,
- 0, // Loop disabled.
- 0);
-}
-
-STATIC void machine_hard_pwm_deinit(mp_obj_t self_in) {
- machine_hard_pwm_obj_t *self = self_in;
- (void)self;
- nrfx_pwm_stop(self->p_pwm, true);
- nrfx_pwm_uninit(self->p_pwm);
-}
-
-STATIC mp_obj_t machine_hard_pwm_freq(mp_obj_t self_in, mp_arg_val_t *args) {
- machine_hard_pwm_obj_t *self = self_in;
- (void)self;
- return mp_const_none;
+ &pwm_sequence,
+ 0, // Loop disabled.
+ 0);
}
-const mp_obj_type_t machine_hard_pwm_type = {
- { &mp_type_type },
- .name = MP_QSTR_PWM,
- .print = machine_pwm_print,
- .make_new = machine_pwm_make_new,
- .locals_dict = (mp_obj_dict_t*)&machine_pwm_locals_dict,
-};
-
#endif // MICROPY_PY_MACHINE_HW_PWM
diff --git a/ports/nrf/modules/machine/pwm.h b/ports/nrf/modules/machine/pwm.h
index 7a5b72e0e84f..4c0528fb4cf3 100644
--- a/ports/nrf/modules/machine/pwm.h
+++ b/ports/nrf/modules/machine/pwm.h
@@ -25,5 +25,6 @@
*/
void pwm_init0(void);
+void pwm_deinit_all(void);
-extern const mp_obj_type_t machine_hard_pwm_type;
+extern const mp_obj_type_t machine_pwm_type;
diff --git a/ports/nrf/modules/machine/rtcounter.c b/ports/nrf/modules/machine/rtcounter.c
index c9f907774e6a..d52ca3e9a336 100644
--- a/ports/nrf/modules/machine/rtcounter.c
+++ b/ports/nrf/modules/machine/rtcounter.c
@@ -262,12 +262,13 @@ STATIC const mp_rom_map_elem_t machine_rtc_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(machine_rtc_locals_dict, machine_rtc_locals_dict_table);
-const mp_obj_type_t machine_rtcounter_type = {
- { &mp_type_type },
- .name = MP_QSTR_RTCounter,
- .print = rtc_print,
- .make_new = machine_rtc_make_new,
- .locals_dict = (mp_obj_dict_t*)&machine_rtc_locals_dict
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ machine_rtcounter_type,
+ MP_QSTR_RTCounter,
+ MP_TYPE_FLAG_NONE,
+ make_new, machine_rtc_make_new,
+ print, rtc_print,
+ locals_dict, &machine_rtc_locals_dict
+ );
#endif // MICROPY_PY_MACHINE_RTCOUNTER
diff --git a/ports/nrf/modules/machine/soft_pwm.c b/ports/nrf/modules/machine/soft_pwm.c
new file mode 100644
index 000000000000..27783328eb8c
--- /dev/null
+++ b/ports/nrf/modules/machine/soft_pwm.c
@@ -0,0 +1,214 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2023 Robert Hammelrath
+ *
+ * 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/runtime.h"
+#include "py/mphal.h"
+
+#if MICROPY_PY_MACHINE_SOFT_PWM
+
+#include "softpwm.h"
+
+typedef enum {
+ DUTY_NOT_SET = 0,
+ DUTY,
+ DUTY_U16,
+ DUTY_NS
+} pwm_duty_t;
+
+typedef struct _machine_pwm_obj_t {
+ mp_obj_base_t base;
+ uint8_t pwm_pin;
+ bool defer_start;
+ uint8_t duty_mode;
+ uint32_t duty;
+ uint32_t freq;
+} machine_pwm_obj_t;
+
+#define SOFT_PWM_BASE_FREQ (1000000)
+#define DUTY_FULL_SCALE (1024)
+
+STATIC void mp_machine_pwm_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
+ machine_pwm_obj_t *self = self_in;
+ static char *duty_suffix[] = { "", "", "_u16", "_ns" };
+ mp_printf(print, "",
+ self->pwm_pin, self->freq,
+ duty_suffix[self->duty_mode], self->duty);
+}
+
+// MicroPython bindings for machine API
+
+STATIC void machine_soft_pwm_start(machine_pwm_obj_t *self);
+STATIC void mp_machine_pwm_deinit(machine_pwm_obj_t *self);
+STATIC void mp_machine_pwm_freq_set(machine_pwm_obj_t *self, mp_int_t freq);
+STATIC void mp_machine_pwm_duty_set(machine_pwm_obj_t *self, mp_int_t duty);
+STATIC void mp_machine_pwm_duty_set_u16(machine_pwm_obj_t *self, mp_int_t duty_u16);
+STATIC void mp_machine_pwm_duty_set_ns(machine_pwm_obj_t *self, mp_int_t duty_ns);
+
+STATIC void mp_machine_pwm_init_helper(machine_pwm_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ enum { ARG_freq, ARG_duty, ARG_duty_u16, ARG_duty_ns };
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_freq, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
+ { MP_QSTR_duty, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
+ { MP_QSTR_duty_u16, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
+ { MP_QSTR_duty_ns, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
+ };
+
+ mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
+ mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
+
+ self->defer_start = true;
+ if (args[ARG_freq].u_int != -1) {
+ mp_machine_pwm_freq_set(self, args[ARG_freq].u_int);
+ }
+ if (args[ARG_duty].u_int != -1) {
+ mp_machine_pwm_duty_set(self, args[ARG_duty].u_int);
+ }
+ if (args[ARG_duty_u16].u_int != -1) {
+ mp_machine_pwm_duty_set_u16(self, args[ARG_duty_u16].u_int);
+ }
+ if (args[ARG_duty_ns].u_int != -1) {
+ mp_machine_pwm_duty_set_ns(self, args[ARG_duty_ns].u_int);
+ }
+ self->defer_start = false;
+ // (Re-)start the PWM.
+ machine_soft_pwm_start(self);
+}
+
+STATIC mp_obj_t mp_machine_pwm_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
+ enum { ARG_pin, ARG_freq, ARG_duty, ARG_duty_u16, ARG_duty_ns, ARG_id };
+
+ mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true);
+
+ // check if the PWM pin is valid.
+ int pwm_pin = mp_hal_get_pin_obj(args[0])->pin;
+ if (pwm_pin > 31) {
+ mp_raise_ValueError(MP_ERROR_TEXT("Pin number >31"));
+ }
+
+ machine_pwm_obj_t *self = mp_obj_malloc(machine_pwm_obj_t, &machine_pwm_type);;
+ self->defer_start = false;
+ self->pwm_pin = pwm_pin;
+ self->duty_mode = DUTY_NOT_SET;
+ self->duty = 0;
+ self->freq = 0;
+
+ // parse the remaining arguments and start the PWM
+ mp_map_t kw_args;
+ mp_map_init_fixed_table(&kw_args, n_kw, args + n_args);
+ mp_machine_pwm_init_helper(self, n_args - 1, args + 1, &kw_args);
+
+ return MP_OBJ_FROM_PTR(self);
+}
+
+STATIC void mp_machine_pwm_deinit(machine_pwm_obj_t *self) {
+ pwm_release(self->pwm_pin);
+}
+
+STATIC mp_obj_t mp_machine_pwm_freq_get(machine_pwm_obj_t *self) {
+ return MP_OBJ_NEW_SMALL_INT(self->freq);
+}
+
+STATIC void mp_machine_pwm_freq_set(machine_pwm_obj_t *self, mp_int_t freq) {
+
+ if (freq > (SOFT_PWM_BASE_FREQ / 256)) {
+ mp_raise_ValueError(MP_ERROR_TEXT("frequency out of range"));
+ }
+ self->freq = freq;
+ machine_soft_pwm_start(self);
+}
+
+STATIC mp_obj_t mp_machine_pwm_duty_get(machine_pwm_obj_t *self) {
+ if (self->duty_mode) {
+ return MP_OBJ_NEW_SMALL_INT(self->duty);
+ } else if (self->duty_mode == DUTY_U16) {
+ return MP_OBJ_NEW_SMALL_INT(self->duty * 100 / 65536);
+ } else {
+ return MP_OBJ_NEW_SMALL_INT(-1);
+ }
+}
+
+STATIC void mp_machine_pwm_duty_set(machine_pwm_obj_t *self, mp_int_t duty) {
+ self->duty = duty;
+ self->duty_mode = DUTY;
+ machine_soft_pwm_start(self);
+}
+
+STATIC mp_obj_t mp_machine_pwm_duty_get_u16(machine_pwm_obj_t *self) {
+ if (self->duty_mode == DUTY_U16) {
+ return MP_OBJ_NEW_SMALL_INT(self->duty);
+ } else if (self->duty_mode == DUTY) {
+ return MP_OBJ_NEW_SMALL_INT(self->duty * 65536 / 100);
+ } else {
+ return MP_OBJ_NEW_SMALL_INT(-1);
+ }
+}
+
+STATIC void mp_machine_pwm_duty_set_u16(machine_pwm_obj_t *self, mp_int_t duty) {
+ self->duty = duty;
+ self->duty_mode = DUTY_U16;
+ machine_soft_pwm_start(self);
+}
+
+STATIC mp_obj_t mp_machine_pwm_duty_get_ns(machine_pwm_obj_t *self) {
+ if (self->duty_mode == DUTY_NS) {
+ return MP_OBJ_NEW_SMALL_INT(self->duty);
+ } else {
+ return MP_OBJ_NEW_SMALL_INT(-1);
+ }
+}
+
+STATIC void mp_machine_pwm_duty_set_ns(machine_pwm_obj_t *self, mp_int_t duty) {
+ self->duty = duty;
+ self->duty_mode = DUTY_NS;
+ machine_soft_pwm_start(self);
+}
+
+/* Interface for the implementation */
+
+STATIC void machine_soft_pwm_start(machine_pwm_obj_t *self) {
+
+ // check if ready to go
+ if (self->defer_start == true || self->freq == 0 || self->duty_mode == DUTY_NOT_SET) {
+ return; // Not ready yet.
+ }
+
+ int ret = pwm_set_period_us(SOFT_PWM_BASE_FREQ / self->freq);
+
+ if (ret >= 0) {
+ int duty_width;
+ if (self->duty_mode == DUTY) {
+ duty_width = self->duty * DUTY_FULL_SCALE / 100;
+ } else if (self->duty_mode == DUTY_U16) {
+ duty_width = self->duty * DUTY_FULL_SCALE / 65536;
+ }if (self->duty_mode == DUTY_NS) {
+ duty_width = (uint64_t)self->duty * self->freq * DUTY_FULL_SCALE / 1000000000ULL;
+ }
+ pwm_set_duty_cycle(self->pwm_pin, duty_width);
+ }
+}
+
+#endif // MICROPY_PY_MACHINE_HW_PWM
diff --git a/ports/nrf/modules/machine/spi.c b/ports/nrf/modules/machine/spi.c
index 880d946a29f9..0dee20027b2d 100644
--- a/ports/nrf/modules/machine/spi.c
+++ b/ports/nrf/modules/machine/spi.c
@@ -117,12 +117,12 @@ STATIC const nrfx_spi_t machine_spi_instances[] = {
STATIC nrfx_spi_config_t configs[MP_ARRAY_SIZE(machine_spi_instances)];
STATIC const machine_hard_spi_obj_t machine_hard_spi_obj[] = {
- {{&machine_hard_spi_type}, .p_spi = &machine_spi_instances[0], .p_config = &configs[0]},
- {{&machine_hard_spi_type}, .p_spi = &machine_spi_instances[1], .p_config = &configs[1]},
+ {{&machine_spi_type}, .p_spi = &machine_spi_instances[0], .p_config = &configs[0]},
+ {{&machine_spi_type}, .p_spi = &machine_spi_instances[1], .p_config = &configs[1]},
#if defined(NRF52_SERIES)
- {{&machine_hard_spi_type}, .p_spi = &machine_spi_instances[2], .p_config = &configs[2]},
+ {{&machine_spi_type}, .p_spi = &machine_spi_instances[2], .p_config = &configs[2]},
#if defined(NRF52840_XXAA) && NRFX_SPIM_ENABLED
- {{&machine_hard_spi_type}, .p_spi = &machine_spi_instances[3], .p_config = &configs[3]},
+ {{&machine_spi_type}, .p_spi = &machine_spi_instances[3], .p_config = &configs[3]},
#endif // NRF52840_XXAA && NRFX_SPIM_ENABLED
#endif // NRF52_SERIES
};
@@ -235,7 +235,7 @@ STATIC mp_obj_t machine_spi_init(size_t n_args, const mp_obj_t *pos_args, mp_map
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
// dispatch to specific implementation
- if (mp_obj_get_type(self) == &machine_hard_spi_type) {
+ if (mp_obj_get_type(self) == &machine_spi_type) {
machine_hard_spi_init(self, args);
}
@@ -245,7 +245,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_spi_init_obj, 1, machine_spi_init);
STATIC mp_obj_t machine_spi_deinit(mp_obj_t self) {
// dispatch to specific implementation
- if (mp_obj_get_type(self) == &machine_hard_spi_type) {
+ if (mp_obj_get_type(self) == &machine_spi_type) {
machine_hard_spi_deinit(self);
}
return mp_const_none;
@@ -388,7 +388,7 @@ STATIC mp_obj_t mp_machine_spi_read(size_t n_args, const mp_obj_t *args) {
vstr_init_len(&vstr, mp_obj_get_int(args[1]));
memset(vstr.buf, n_args == 3 ? mp_obj_get_int(args[2]) : 0, vstr.len);
spi_transfer(args[0], vstr.len, vstr.buf, vstr.buf);
- return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
+ return mp_obj_new_bytes_from_vstr(&vstr);
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_machine_spi_read_obj, 2, 3, mp_machine_spi_read);
@@ -427,13 +427,14 @@ STATIC const mp_machine_spi_p_t machine_hard_spi_p = {
.transfer = machine_hard_spi_transfer,
};
-const mp_obj_type_t machine_hard_spi_type = {
- { &mp_type_type },
- .name = MP_QSTR_SPI,
- .print = machine_hard_spi_print,
- .make_new = machine_spi_make_new,
- .protocol = &machine_hard_spi_p,
- .locals_dict = (mp_obj_dict_t*)&machine_spi_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ machine_spi_type,
+ MP_QSTR_SPI,
+ MP_TYPE_FLAG_NONE,
+ make_new, machine_spi_make_new,
+ print, machine_hard_spi_print,
+ protocol, &machine_hard_spi_p,
+ locals_dict, &machine_spi_locals_dict
+ );
#endif // MICROPY_PY_MACHINE_HW_SPI
diff --git a/ports/nrf/modules/machine/spi.h b/ports/nrf/modules/machine/spi.h
index c6f64a19da2a..e1505781ac38 100644
--- a/ports/nrf/modules/machine/spi.h
+++ b/ports/nrf/modules/machine/spi.h
@@ -27,7 +27,7 @@
#include "py/obj.h"
typedef struct _machine_hard_spi_obj_t machine_hard_spi_obj_t;
-extern const mp_obj_type_t machine_hard_spi_type;
+extern const mp_obj_type_t machine_spi_type;
void spi_init0(void);
void spi_transfer(const machine_hard_spi_obj_t * self,
diff --git a/ports/nrf/modules/machine/temp.c b/ports/nrf/modules/machine/temp.c
index 1eb38c08d0bd..dff15a9d1497 100644
--- a/ports/nrf/modules/machine/temp.c
+++ b/ports/nrf/modules/machine/temp.c
@@ -112,12 +112,13 @@ STATIC const mp_rom_map_elem_t machine_temp_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(machine_temp_locals_dict, machine_temp_locals_dict_table);
-const mp_obj_type_t machine_temp_type = {
- { &mp_type_type },
- .name = MP_QSTR_Temp,
- .make_new = machine_temp_make_new,
- .locals_dict = (mp_obj_dict_t*)&machine_temp_locals_dict,
- .print = machine_temp_print,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ machine_temp_type,
+ MP_QSTR_Temp,
+ MP_TYPE_FLAG_NONE,
+ make_new, machine_temp_make_new,
+ locals_dict, &machine_temp_locals_dict,
+ print, machine_temp_print
+ );
#endif // MICROPY_PY_MACHINE_TEMP
diff --git a/ports/nrf/modules/machine/timer.c b/ports/nrf/modules/machine/timer.c
index c99713ef52c5..f6a0e544636d 100644
--- a/ports/nrf/modules/machine/timer.c
+++ b/ports/nrf/modules/machine/timer.c
@@ -29,7 +29,7 @@
#include "timer.h"
#include "nrfx_timer.h"
-#if MICROPY_PY_MACHINE_TIMER
+#if MICROPY_PY_MACHINE_TIMER_NRF
enum {
TIMER_MODE_ONESHOT,
@@ -234,12 +234,13 @@ STATIC const mp_rom_map_elem_t machine_timer_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(machine_timer_locals_dict, machine_timer_locals_dict_table);
-const mp_obj_type_t machine_timer_type = {
- { &mp_type_type },
- .name = MP_QSTR_Timer,
- .print = timer_print,
- .make_new = machine_timer_make_new,
- .locals_dict = (mp_obj_dict_t*)&machine_timer_locals_dict
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ machine_timer_type,
+ MP_QSTR_Timer,
+ MP_TYPE_FLAG_NONE,
+ make_new, machine_timer_make_new,
+ print, timer_print,
+ locals_dict, &machine_timer_locals_dict
+ );
-#endif // MICROPY_PY_MACHINE_TIMER
+#endif // MICROPY_PY_MACHINE_TIMER_NRF
diff --git a/ports/nrf/modules/machine/uart.c b/ports/nrf/modules/machine/uart.c
index 2cc421aa1f33..fd176549d0f9 100644
--- a/ports/nrf/modules/machine/uart.c
+++ b/ports/nrf/modules/machine/uart.c
@@ -77,6 +77,7 @@ typedef struct _machine_hard_uart_buf_t {
#define NRF_UART_HWFC_DISABLED NRF_UARTE_HWFC_DISABLED
#define NRF_UART_PARITY_EXCLUDED NRF_UARTE_PARITY_EXCLUDED
#define NRFX_UART_EVT_RX_DONE NRFX_UARTE_EVT_RX_DONE
+#define NRFX_UART_EVT_ERROR NRFX_UARTE_EVT_ERROR
#define NRF_UART_BAUDRATE_1200 NRF_UARTE_BAUDRATE_1200
#define NRF_UART_BAUDRATE_2400 NRF_UARTE_BAUDRATE_2400
@@ -98,15 +99,15 @@ typedef struct _machine_hard_uart_buf_t {
typedef struct _machine_hard_uart_obj_t {
mp_obj_base_t base;
const nrfx_uart_t * p_uart; // Driver instance
- machine_hard_uart_buf_t *buf;
+ machine_hard_uart_buf_t buf;
+ uint16_t timeout; // timeout waiting for first char (in ms)
+ uint16_t timeout_char; // timeout waiting between chars (in ms)
} machine_hard_uart_obj_t;
static const nrfx_uart_t instance0 = NRFX_UART_INSTANCE(0);
-STATIC machine_hard_uart_buf_t machine_hard_uart_buf[1];
-
-STATIC const machine_hard_uart_obj_t machine_hard_uart_obj[] = {
- {{&machine_hard_uart_type}, .p_uart = &instance0, .buf = &machine_hard_uart_buf[0]},
+STATIC machine_hard_uart_obj_t machine_hard_uart_obj[] = {
+ {{&machine_uart_type}, .p_uart = &instance0}
};
void uart_init0(void) {
@@ -124,43 +125,48 @@ STATIC int uart_find(mp_obj_t id) {
STATIC void uart_event_handler(nrfx_uart_event_t const *p_event, void *p_context) {
machine_hard_uart_obj_t *self = p_context;
if (p_event->type == NRFX_UART_EVT_RX_DONE) {
- int chr = self->buf->rx_buf[0];
- nrfx_uart_rx(self->p_uart, &self->buf->rx_buf[0], 1);
+ nrfx_uart_rx(self->p_uart, &self->buf.rx_buf[0], 1);
+ int chr = self->buf.rx_buf[0];
#if !MICROPY_PY_BLE_NUS && MICROPY_KBD_EXCEPTION
if (chr == mp_interrupt_char) {
+ self->buf.rx_ringbuf.iget = 0;
+ self->buf.rx_ringbuf.iput = 0;
mp_sched_keyboard_interrupt();
} else
#endif
{
- ringbuf_put((ringbuf_t*)&self->buf->rx_ringbuf, chr);
+ ringbuf_put((ringbuf_t *)&self->buf.rx_ringbuf, chr);
}
+ } else if (p_event->type == NRFX_UART_EVT_ERROR) {
+ // Perform a read to unlock UART in case of an error
+ nrfx_uart_rx(self->p_uart, &self->buf.rx_buf[0], 1);
}
}
-bool uart_rx_any(const machine_hard_uart_obj_t *self) {
- return self->buf->rx_ringbuf.iput != self->buf->rx_ringbuf.iget;
+bool uart_rx_any(machine_hard_uart_obj_t *self) {
+ return self->buf.rx_ringbuf.iput != self->buf.rx_ringbuf.iget;
}
-int uart_rx_char(const machine_hard_uart_obj_t * self) {
- return ringbuf_get((ringbuf_t*)&self->buf->rx_ringbuf);
+int uart_rx_char(machine_hard_uart_obj_t *self) {
+ return ringbuf_get((ringbuf_t *)&self->buf.rx_ringbuf);
}
-STATIC nrfx_err_t uart_tx_char(const machine_hard_uart_obj_t * self, int c) {
+STATIC nrfx_err_t uart_tx_char(machine_hard_uart_obj_t *self, int c) {
while (nrfx_uart_tx_in_progress(self->p_uart)) {
;
}
- self->buf->tx_buf[0] = c;
- return nrfx_uart_tx(self->p_uart, &self->buf->tx_buf[0], 1);
+ self->buf.tx_buf[0] = c;
+ return nrfx_uart_tx(self->p_uart, &self->buf.tx_buf[0], 1);
}
-void uart_tx_strn(const machine_hard_uart_obj_t *uart_obj, const char *str, uint len) {
+void uart_tx_strn(machine_hard_uart_obj_t *uart_obj, const char *str, uint len) {
for (const char *top = str + len; str < top; str++) {
uart_tx_char(uart_obj, *str);
}
}
-void uart_tx_strn_cooked(const machine_hard_uart_obj_t *uart_obj, const char *str, uint len) {
+void uart_tx_strn_cooked(machine_hard_uart_obj_t *uart_obj, const char *str, uint len) {
for (const char *top = str + len; str < top; str++) {
if (*str == '\n') {
uart_tx_char(uart_obj, '\r');
@@ -182,10 +188,12 @@ STATIC void machine_hard_uart_print(const mp_print_t *print, mp_obj_t self_in, m
/// - `id`is bus id.
/// - `baudrate` is the clock rate.
STATIC mp_obj_t machine_hard_uart_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
- enum { ARG_id, ARG_baudrate };
+ enum { ARG_id, ARG_baudrate, ARG_timeout, ARG_timeout_char };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_id, MP_ARG_REQUIRED | MP_ARG_OBJ },
{ MP_QSTR_baudrate, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 9600} },
+ { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1} },
+ { MP_QSTR_timeout_char, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1} },
};
// parse args
@@ -194,7 +202,7 @@ STATIC mp_obj_t machine_hard_uart_make_new(const mp_obj_type_t *type, size_t n_a
// get static peripheral object
int uart_id = uart_find(args[ARG_id].u_obj);
- const machine_hard_uart_obj_t * self = &machine_hard_uart_obj[uart_id];
+ machine_hard_uart_obj_t *self = &machine_hard_uart_obj[uart_id];
nrfx_uart_config_t config;
@@ -236,19 +244,21 @@ STATIC mp_obj_t machine_hard_uart_make_new(const mp_obj_type_t *type, size_t n_a
config.pselrts = MICROPY_HW_UART1_RTS;
config.pselcts = MICROPY_HW_UART1_CTS;
#endif
+ self->timeout = args[ARG_timeout].u_int;
+ self->timeout_char = args[ARG_timeout_char].u_int;
// Set context to this instance of UART
config.p_context = (void *)self;
// Initialise ring buffer
- self->buf->rx_ringbuf.buf = self->buf->rx_ringbuf_array;
- self->buf->rx_ringbuf.size = sizeof(self->buf->rx_ringbuf_array);
- self->buf->rx_ringbuf.iget = 0;
- self->buf->rx_ringbuf.iput = 0;
+ self->buf.rx_ringbuf.buf = self->buf.rx_ringbuf_array;
+ self->buf.rx_ringbuf.size = sizeof(self->buf.rx_ringbuf_array);
+ self->buf.rx_ringbuf.iget = 0;
+ self->buf.rx_ringbuf.iput = 0;
// Enable event callback and start asynchronous receive
nrfx_uart_init(self->p_uart, &config, uart_event_handler);
- nrfx_uart_rx(self->p_uart, &self->buf->rx_buf[0], 1);
+ nrfx_uart_rx(self->p_uart, &self->buf.rx_buf[0], 1);
#if NRFX_UART_ENABLED
nrfx_uart_rx_enable(self->p_uart);
@@ -284,14 +294,29 @@ STATIC mp_obj_t machine_hard_uart_readchar(mp_obj_t self_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hard_uart_readchar_obj, machine_hard_uart_readchar);
+// uart.any()
+STATIC mp_obj_t machine_uart_any(mp_obj_t self_in) {
+ machine_hard_uart_obj_t *self = self_in;
+ return MP_OBJ_NEW_SMALL_INT(ringbuf_avail((ringbuf_t *)&self->buf.rx_ringbuf));
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_uart_any_obj, machine_uart_any);
+
// uart.sendbreak()
STATIC mp_obj_t machine_hard_uart_sendbreak(mp_obj_t self_in) {
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hard_uart_sendbreak_obj, machine_hard_uart_sendbreak);
+// uart.txdone()
+STATIC mp_obj_t machine_uart_txdone(mp_obj_t self_in) {
+ machine_hard_uart_obj_t *self = self_in;
+ return mp_obj_new_bool(!nrfx_uart_tx_in_progress(self->p_uart));
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_uart_txdone_obj, machine_uart_txdone);
+
STATIC const mp_rom_map_elem_t machine_hard_uart_locals_dict_table[] = {
// instance methods
+ { MP_ROM_QSTR(MP_QSTR_any), MP_ROM_PTR(&machine_uart_any_obj) },
{ MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) },
{ MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) },
{ MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) },
@@ -300,6 +325,8 @@ STATIC const mp_rom_map_elem_t machine_hard_uart_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_writechar), MP_ROM_PTR(&machine_hard_uart_writechar_obj) },
{ MP_ROM_QSTR(MP_QSTR_readchar), MP_ROM_PTR(&machine_hard_uart_readchar_obj) },
{ MP_ROM_QSTR(MP_QSTR_sendbreak), MP_ROM_PTR(&machine_hard_uart_sendbreak_obj) },
+ { MP_ROM_QSTR(MP_QSTR_flush), MP_ROM_PTR(&mp_stream_flush_obj) },
+ { MP_ROM_QSTR(MP_QSTR_txdone), MP_ROM_PTR(&machine_uart_txdone_obj) },
// class constants
/*
@@ -311,14 +338,25 @@ STATIC const mp_rom_map_elem_t machine_hard_uart_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(machine_hard_uart_locals_dict, machine_hard_uart_locals_dict_table);
STATIC mp_uint_t machine_hard_uart_read(mp_obj_t self_in, void *buf_in, mp_uint_t size, int *errcode) {
- const machine_hard_uart_obj_t *self = self_in;
+ machine_hard_uart_obj_t *self = self_in;
byte *buf = buf_in;
+ uint32_t t = self->timeout + mp_hal_ticks_ms();
// read the data
for (size_t i = 0; i < size; i++) {
while (!uart_rx_any(self)) {
+ if ((int32_t)(mp_hal_ticks_ms() - t) >= 0) { // timed out
+ if (i == 0) {
+ *errcode = MP_EAGAIN;
+ return MP_STREAM_ERROR;
+ } else {
+ return i;
+ }
+ }
+ MICROPY_EVENT_POLL_HOOK;
}
buf[i] = uart_rx_char(self);
+ t = self->timeout_char + mp_hal_ticks_ms();
}
return size;
@@ -326,14 +364,12 @@ STATIC mp_uint_t machine_hard_uart_read(mp_obj_t self_in, void *buf_in, mp_uint_
STATIC mp_uint_t machine_hard_uart_write(mp_obj_t self_in, const void *buf_in, mp_uint_t size, int *errcode) {
machine_hard_uart_obj_t *self = self_in;
- const byte *buf = buf_in;
-
- nrfx_err_t err = NRFX_SUCCESS;
- for (int i = 0; i < size; i++) {
- err = uart_tx_char(self, (int)((uint8_t *)buf)[i]);
- }
+ nrfx_err_t err = nrfx_uart_tx(self->p_uart, buf_in, size);
if (err == NRFX_SUCCESS) {
+ while (nrfx_uart_tx_in_progress(self->p_uart)) {
+ MICROPY_EVENT_POLL_HOOK;
+ }
// return number of bytes written
return size;
} else {
@@ -345,6 +381,22 @@ STATIC mp_uint_t machine_hard_uart_write(mp_obj_t self_in, const void *buf_in, m
STATIC mp_uint_t machine_hard_uart_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode) {
machine_hard_uart_obj_t *self = self_in;
(void)self;
+ mp_uint_t ret = 0;
+
+ if (request == MP_STREAM_POLL) {
+ uintptr_t flags = arg;
+ if ((flags & MP_STREAM_POLL_RD) && uart_rx_any(self) != 0) {
+ ret |= MP_STREAM_POLL_RD;
+ }
+ if ((flags & MP_STREAM_POLL_WR) && !nrfx_uart_tx_in_progress(self->p_uart)) {
+ ret |= MP_STREAM_POLL_WR;
+ }
+ } else if (request == MP_STREAM_FLUSH) {
+ while (nrfx_uart_tx_in_progress(self->p_uart)) {
+ MICROPY_EVENT_POLL_HOOK;
+ }
+ return 0;
+ }
return MP_STREAM_ERROR;
}
@@ -355,15 +407,14 @@ STATIC const mp_stream_p_t uart_stream_p = {
.is_text = false,
};
-const mp_obj_type_t machine_hard_uart_type = {
- { &mp_type_type },
- .name = MP_QSTR_UART,
- .print = machine_hard_uart_print,
- .make_new = machine_hard_uart_make_new,
- .getiter = mp_identity_getiter,
- .iternext = mp_stream_unbuffered_iter,
- .protocol = &uart_stream_p,
- .locals_dict = (mp_obj_dict_t*)&machine_hard_uart_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ machine_uart_type,
+ MP_QSTR_UART,
+ MP_TYPE_FLAG_ITER_IS_STREAM,
+ make_new, machine_hard_uart_make_new,
+ print, machine_hard_uart_print,
+ protocol, &uart_stream_p,
+ locals_dict, &machine_hard_uart_locals_dict
+ );
#endif // MICROPY_PY_MACHINE_UART
diff --git a/ports/nrf/modules/machine/uart.h b/ports/nrf/modules/machine/uart.h
index 121f83cd39b3..eee0738fe1f9 100644
--- a/ports/nrf/modules/machine/uart.h
+++ b/ports/nrf/modules/machine/uart.h
@@ -32,15 +32,15 @@
#include "genhdr/pins.h"
typedef struct _machine_hard_uart_obj_t machine_hard_uart_obj_t;
-extern const mp_obj_type_t machine_hard_uart_type;
+extern const mp_obj_type_t machine_uart_type;
void uart_init0(void);
void uart_deinit(void);
void uart_irq_handler(mp_uint_t uart_id);
-bool uart_rx_any(const machine_hard_uart_obj_t * uart_obj);
-int uart_rx_char(const machine_hard_uart_obj_t * uart_obj);
-void uart_tx_strn(const machine_hard_uart_obj_t * uart_obj, const char *str, uint len);
-void uart_tx_strn_cooked(const machine_hard_uart_obj_t *uart_obj, const char *str, uint len);
+bool uart_rx_any(machine_hard_uart_obj_t *uart_obj);
+int uart_rx_char(machine_hard_uart_obj_t *uart_obj);
+void uart_tx_strn(machine_hard_uart_obj_t *uart_obj, const char *str, uint len);
+void uart_tx_strn_cooked(machine_hard_uart_obj_t *uart_obj, const char *str, uint len);
#endif
diff --git a/ports/nrf/modules/manifest.py b/ports/nrf/modules/manifest.py
index b27d4648b7ea..6efaf62d79d6 100644
--- a/ports/nrf/modules/manifest.py
+++ b/ports/nrf/modules/manifest.py
@@ -1,2 +1,2 @@
-freeze("$(PORT_DIR)/modules/scripts", "_mkfs.py")
-include("$(MPY_DIR)/extmod/uasyncio/manifest.py")
+module("_mkfs.py", base_path="$(PORT_DIR)/modules/scripts", opt=3)
+include("$(MPY_DIR)/extmod/uasyncio")
diff --git a/ports/nrf/modules/music/modmusic.c b/ports/nrf/modules/music/modmusic.c
index a950b03920c2..a0ae7f7c8e86 100644
--- a/ports/nrf/modules/music/modmusic.c
+++ b/ports/nrf/modules/music/modmusic.c
@@ -70,7 +70,7 @@ enum {
ASYNC_MUSIC_STATE_ARTICULATE,
};
-#define music_data MP_STATE_PORT(music_data)
+#define music_data MP_STATE_PORT(modmusic_music_data)
extern volatile uint32_t ticks;
@@ -510,5 +510,6 @@ const mp_obj_module_t music_module = {
};
MP_REGISTER_MODULE(MP_QSTR_music, music_module);
+MP_REGISTER_ROOT_POINTER(struct _music_data_t *modmusic_music_data);
#endif // MICROPY_PY_MUSIC
diff --git a/ports/nrf/modules/nrf/flashbdev.c b/ports/nrf/modules/nrf/flashbdev.c
index f63a9b46b29c..e92919cac5a2 100644
--- a/ports/nrf/modules/nrf/flashbdev.c
+++ b/ports/nrf/modules/nrf/flashbdev.c
@@ -183,13 +183,14 @@ STATIC mp_obj_t nrf_flashbdev_make_new(const mp_obj_type_t *type, size_t n_args,
return MP_OBJ_FROM_PTR(self);
}
-const mp_obj_type_t nrf_flashbdev_type = {
- { &mp_type_type },
- .name = MP_QSTR_Flash,
- .print = nrf_flashbdev_print,
- .make_new = nrf_flashbdev_make_new,
- .locals_dict = (mp_obj_dict_t *)&nrf_flashbdev_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ nrf_flashbdev_type,
+ MP_QSTR_Flash,
+ MP_TYPE_FLAG_NONE,
+ make_new, nrf_flashbdev_make_new,
+ print, nrf_flashbdev_print,
+ locals_dict, &nrf_flashbdev_locals_dict
+ );
void flashbdev_init(void) {
// Set start to first aligned page from _fs_start.
diff --git a/ports/nrf/modules/ubluepy/ubluepy_characteristic.c b/ports/nrf/modules/ubluepy/ubluepy_characteristic.c
index a66483f60dad..7b9e3af6a317 100644
--- a/ports/nrf/modules/ubluepy/ubluepy_characteristic.c
+++ b/ports/nrf/modules/ubluepy/ubluepy_characteristic.c
@@ -209,12 +209,13 @@ STATIC const mp_rom_map_elem_t ubluepy_characteristic_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(ubluepy_characteristic_locals_dict, ubluepy_characteristic_locals_dict_table);
-const mp_obj_type_t ubluepy_characteristic_type = {
- { &mp_type_type },
- .name = MP_QSTR_Characteristic,
- .print = ubluepy_characteristic_print,
- .make_new = ubluepy_characteristic_make_new,
- .locals_dict = (mp_obj_dict_t*)&ubluepy_characteristic_locals_dict
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ ubluepy_characteristic_type,
+ MP_QSTR_Characteristic,
+ MP_TYPE_FLAG_NONE,
+ make_new, ubluepy_characteristic_make_new,
+ print, ubluepy_characteristic_print,
+ locals_dict, &ubluepy_characteristic_locals_dict
+ );
#endif // MICROPY_PY_UBLUEPY_PERIPHERAL || MICROPY_PY_UBLUEPY_CENTRAL
diff --git a/ports/nrf/modules/ubluepy/ubluepy_constants.c b/ports/nrf/modules/ubluepy/ubluepy_constants.c
index 14e433e6ebff..cad9adbb0325 100644
--- a/ports/nrf/modules/ubluepy/ubluepy_constants.c
+++ b/ports/nrf/modules/ubluepy/ubluepy_constants.c
@@ -69,11 +69,12 @@ STATIC const mp_rom_map_elem_t ubluepy_constants_ad_types_locals_dict_table[] =
STATIC MP_DEFINE_CONST_DICT(ubluepy_constants_ad_types_locals_dict, ubluepy_constants_ad_types_locals_dict_table);
-const mp_obj_type_t ubluepy_constants_ad_types_type = {
- { &mp_type_type },
- .name = MP_QSTR_ad_types,
- .locals_dict = (mp_obj_dict_t*)&ubluepy_constants_ad_types_locals_dict
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ ubluepy_constants_ad_types_type,
+ MP_QSTR_ad_types,
+ MP_TYPE_FLAG_NONE,
+ locals_dict, &ubluepy_constants_ad_types_locals_dict
+ );
STATIC const mp_rom_map_elem_t ubluepy_constants_locals_dict_table[] = {
// GAP events
@@ -90,10 +91,11 @@ STATIC const mp_rom_map_elem_t ubluepy_constants_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(ubluepy_constants_locals_dict, ubluepy_constants_locals_dict_table);
-const mp_obj_type_t ubluepy_constants_type = {
- { &mp_type_type },
- .name = MP_QSTR_constants,
- .locals_dict = (mp_obj_dict_t*)&ubluepy_constants_locals_dict
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ ubluepy_constants_type,
+ MP_QSTR_constants,
+ MP_TYPE_FLAG_NONE,
+ locals_dict, &ubluepy_constants_locals_dict
+ );
#endif // MICROPY_PY_UBLUEPY
diff --git a/ports/nrf/modules/ubluepy/ubluepy_delegate.c b/ports/nrf/modules/ubluepy/ubluepy_delegate.c
index 736bfbc9dd23..43720b4186b0 100644
--- a/ports/nrf/modules/ubluepy/ubluepy_delegate.c
+++ b/ports/nrf/modules/ubluepy/ubluepy_delegate.c
@@ -77,12 +77,13 @@ STATIC const mp_rom_map_elem_t ubluepy_delegate_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(ubluepy_delegate_locals_dict, ubluepy_delegate_locals_dict_table);
-const mp_obj_type_t ubluepy_delegate_type = {
- { &mp_type_type },
- .name = MP_QSTR_DefaultDelegate,
- .print = ubluepy_delegate_print,
- .make_new = ubluepy_delegate_make_new,
- .locals_dict = (mp_obj_dict_t*)&ubluepy_delegate_locals_dict
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ ubluepy_delegate_type,
+ MP_QSTR_DefaultDelegate,
+ MP_TYPE_FLAG_NONE,
+ make_new, ubluepy_delegate_make_new,
+ print, ubluepy_delegate_print,
+ locals_dict, &ubluepy_delegate_locals_dict
+ );
#endif // MICROPY_PY_UBLUEPY_PERIPHERAL || MICROPY_PY_UBLUEPY_CENTRAL
diff --git a/ports/nrf/modules/ubluepy/ubluepy_descriptor.c b/ports/nrf/modules/ubluepy/ubluepy_descriptor.c
index 370188f7fc7a..062b4210941f 100644
--- a/ports/nrf/modules/ubluepy/ubluepy_descriptor.c
+++ b/ports/nrf/modules/ubluepy/ubluepy_descriptor.c
@@ -70,12 +70,13 @@ STATIC const mp_rom_map_elem_t ubluepy_descriptor_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(ubluepy_descriptor_locals_dict, ubluepy_descriptor_locals_dict_table);
-const mp_obj_type_t ubluepy_descriptor_type = {
- { &mp_type_type },
- .name = MP_QSTR_Descriptor,
- .print = ubluepy_descriptor_print,
- .make_new = ubluepy_descriptor_make_new,
- .locals_dict = (mp_obj_dict_t*)&ubluepy_descriptor_locals_dict
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ ubluepy_descriptor_type,
+ MP_QSTR_Descriptor,
+ MP_TYPE_FLAG_NONE,
+ make_new, ubluepy_descriptor_make_new,
+ print, ubluepy_descriptor_print,
+ locals_dict, &ubluepy_descriptor_locals_dict
+ );
#endif // MICROPY_PY_UBLUEPY
diff --git a/ports/nrf/modules/ubluepy/ubluepy_peripheral.c b/ports/nrf/modules/ubluepy/ubluepy_peripheral.c
index 05a72b1de63d..d2a9e0011d12 100644
--- a/ports/nrf/modules/ubluepy/ubluepy_peripheral.c
+++ b/ports/nrf/modules/ubluepy/ubluepy_peripheral.c
@@ -193,9 +193,8 @@ STATIC mp_obj_t peripheral_advertise(mp_uint_t n_args, const mp_obj_t *pos_args,
memset(&adv_data, 0, sizeof(ubluepy_advertise_data_t));
if (device_name_obj != mp_const_none && mp_obj_is_str(device_name_obj)) {
- GET_STR_DATA_LEN(device_name_obj, str_data, str_len);
-
- adv_data.p_device_name = (uint8_t *)str_data;
+ size_t str_len;
+ adv_data.p_device_name = (uint8_t *)mp_obj_str_get_data(device_name_obj, &str_len);
adv_data.device_name_len = str_len;
}
@@ -357,7 +356,8 @@ STATIC mp_obj_t peripheral_connect(mp_uint_t n_args, const mp_obj_t *pos_args, m
ble_drv_gap_event_handler_set(MP_OBJ_FROM_PTR(self), gap_event_handler);
if (mp_obj_is_str(dev_addr)) {
- GET_STR_DATA_LEN(dev_addr, str_data, str_len);
+ size_t str_len;
+ const byte *str_data = (const byte *)mp_obj_str_get_data(dev_addr, &str_len);
if (str_len == 17) { // Example "11:22:33:aa:bb:cc"
uint8_t * p_addr = m_new(uint8_t, 6);
@@ -482,12 +482,13 @@ STATIC const mp_rom_map_elem_t ubluepy_peripheral_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(ubluepy_peripheral_locals_dict, ubluepy_peripheral_locals_dict_table);
-const mp_obj_type_t ubluepy_peripheral_type = {
- { &mp_type_type },
- .name = MP_QSTR_Peripheral,
- .print = ubluepy_peripheral_print,
- .make_new = ubluepy_peripheral_make_new,
- .locals_dict = (mp_obj_dict_t*)&ubluepy_peripheral_locals_dict
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ ubluepy_peripheral_type,
+ MP_QSTR_Peripheral,
+ MP_TYPE_FLAG_NONE,
+ make_new, ubluepy_peripheral_make_new,
+ print, ubluepy_peripheral_print,
+ locals_dict, &ubluepy_peripheral_locals_dict
+ );
#endif // MICROPY_PY_UBLUEPY
diff --git a/ports/nrf/modules/ubluepy/ubluepy_scan_entry.c b/ports/nrf/modules/ubluepy/ubluepy_scan_entry.c
index 773070b08907..2dd4f57860fc 100644
--- a/ports/nrf/modules/ubluepy/ubluepy_scan_entry.c
+++ b/ports/nrf/modules/ubluepy/ubluepy_scan_entry.c
@@ -91,7 +91,7 @@ STATIC mp_obj_t scan_entry_get_scan_data(mp_obj_t self_in) {
mp_obj_t description = mp_const_none;
- mp_map_t *constant_map = mp_obj_dict_get_map(ubluepy_constants_ad_types_type.locals_dict);
+ mp_map_t *constant_map = mp_obj_dict_get_map(MP_OBJ_TYPE_GET_SLOT(&ubluepy_constants_ad_types_type, locals_dict));
mp_map_elem_t *ad_types_table = MP_OBJ_TO_PTR(constant_map->table);
uint16_t num_of_elements = constant_map->used;
@@ -136,11 +136,12 @@ STATIC const mp_rom_map_elem_t ubluepy_scan_entry_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(ubluepy_scan_entry_locals_dict, ubluepy_scan_entry_locals_dict_table);
-const mp_obj_type_t ubluepy_scan_entry_type = {
- { &mp_type_type },
- .name = MP_QSTR_ScanEntry,
- .print = ubluepy_scan_entry_print,
- .locals_dict = (mp_obj_dict_t*)&ubluepy_scan_entry_locals_dict
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ ubluepy_scan_entry_type,
+ MP_QSTR_ScanEntry,
+ MP_TYPE_FLAG_NONE,
+ print, ubluepy_scan_entry_print,
+ locals_dict, &ubluepy_scan_entry_locals_dict
+ );
#endif // MICROPY_PY_UBLUEPY_CENTRAL
diff --git a/ports/nrf/modules/ubluepy/ubluepy_scanner.c b/ports/nrf/modules/ubluepy/ubluepy_scanner.c
index 60895a3da93f..ffb7e946717b 100644
--- a/ports/nrf/modules/ubluepy/ubluepy_scanner.c
+++ b/ports/nrf/modules/ubluepy/ubluepy_scanner.c
@@ -114,12 +114,13 @@ STATIC const mp_rom_map_elem_t ubluepy_scanner_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(ubluepy_scanner_locals_dict, ubluepy_scanner_locals_dict_table);
-const mp_obj_type_t ubluepy_scanner_type = {
- { &mp_type_type },
- .name = MP_QSTR_Scanner,
- .print = ubluepy_scanner_print,
- .make_new = ubluepy_scanner_make_new,
- .locals_dict = (mp_obj_dict_t*)&ubluepy_scanner_locals_dict
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ ubluepy_scanner_type,
+ MP_QSTR_Scanner,
+ MP_TYPE_FLAG_NONE,
+ make_new, ubluepy_scanner_make_new,
+ print, ubluepy_scanner_print,
+ locals_dict, &ubluepy_scanner_locals_dict
+ );
#endif // MICROPY_PY_UBLUEPY_CENTRAL
diff --git a/ports/nrf/modules/ubluepy/ubluepy_service.c b/ports/nrf/modules/ubluepy/ubluepy_service.c
index 6dac23177925..bf336d04c58a 100644
--- a/ports/nrf/modules/ubluepy/ubluepy_service.c
+++ b/ports/nrf/modules/ubluepy/ubluepy_service.c
@@ -171,12 +171,13 @@ STATIC const mp_rom_map_elem_t ubluepy_service_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(ubluepy_service_locals_dict, ubluepy_service_locals_dict_table);
-const mp_obj_type_t ubluepy_service_type = {
- { &mp_type_type },
- .name = MP_QSTR_Service,
- .print = ubluepy_service_print,
- .make_new = ubluepy_service_make_new,
- .locals_dict = (mp_obj_dict_t*)&ubluepy_service_locals_dict
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ ubluepy_service_type,
+ MP_QSTR_Service,
+ MP_TYPE_FLAG_NONE,
+ make_new, ubluepy_service_make_new,
+ print, ubluepy_service_print,
+ locals_dict, &ubluepy_service_locals_dict
+ );
#endif // MICROPY_PY_UBLUEPY_PERIPHERAL || MICROPY_PY_UBLUEPY_CENTRAL
diff --git a/ports/nrf/modules/ubluepy/ubluepy_uuid.c b/ports/nrf/modules/ubluepy/ubluepy_uuid.c
index 594d0d9130c3..abfe3cadd525 100644
--- a/ports/nrf/modules/ubluepy/ubluepy_uuid.c
+++ b/ports/nrf/modules/ubluepy/ubluepy_uuid.c
@@ -70,7 +70,8 @@ STATIC mp_obj_t ubluepy_uuid_make_new(const mp_obj_type_t *type, size_t n_args,
s->value[1] = (((uint16_t)mp_obj_get_int(uuid_obj)) >> 8) & 0xFF;
s->value[0] = ((uint8_t)mp_obj_get_int(uuid_obj)) & 0xFF;
} else if (mp_obj_is_str(uuid_obj)) {
- GET_STR_DATA_LEN(uuid_obj, str_data, str_len);
+ size_t str_len;
+ const byte *str_data = (const byte *)mp_obj_str_get_data(uuid_obj, &str_len);
if (str_len == 6) { // Assume hex digit prefixed with 0x
s->type = UBLUEPY_UUID_16_BIT;
s->value[0] = unichar_xdigit_value(str_data[5]);
@@ -159,12 +160,13 @@ STATIC const mp_rom_map_elem_t ubluepy_uuid_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(ubluepy_uuid_locals_dict, ubluepy_uuid_locals_dict_table);
-const mp_obj_type_t ubluepy_uuid_type = {
- { &mp_type_type },
- .name = MP_QSTR_UUID,
- .print = ubluepy_uuid_print,
- .make_new = ubluepy_uuid_make_new,
- .locals_dict = (mp_obj_dict_t*)&ubluepy_uuid_locals_dict
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ ubluepy_uuid_type,
+ MP_QSTR_UUID,
+ MP_TYPE_FLAG_NONE,
+ make_new, ubluepy_uuid_make_new,
+ print, ubluepy_uuid_print,
+ locals_dict, &ubluepy_uuid_locals_dict
+ );
#endif // MICROPY_PY_UBLUEPY
diff --git a/ports/nrf/modules/uos/microbitfs.c b/ports/nrf/modules/uos/microbitfs.c
index 6c8ffb0925d0..fb88d47cc910 100644
--- a/ports/nrf/modules/uos/microbitfs.c
+++ b/ports/nrf/modules/uos/microbitfs.c
@@ -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)
*
@@ -626,12 +626,13 @@ STATIC const mp_stream_p_t textio_stream_p = {
.is_text = true,
};
-const mp_obj_type_t uos_mbfs_textio_type = {
- { &mp_type_type },
- .name = MP_QSTR_TextIO,
- .protocol = &textio_stream_p,
- .locals_dict = (mp_obj_dict_t*)&uos_mbfs_file_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ uos_mbfs_textio_type,
+ MP_QSTR_TextIO,
+ MP_TYPE_FLAG_NONE,
+ protocol, &textio_stream_p,
+ locals_dict, &uos_mbfs_file_locals_dict
+ );
STATIC const mp_stream_p_t fileio_stream_p = {
@@ -639,12 +640,13 @@ STATIC const mp_stream_p_t fileio_stream_p = {
.write = microbit_file_write,
};
-const mp_obj_type_t uos_mbfs_fileio_type = {
- { &mp_type_type },
- .name = MP_QSTR_FileIO,
- .protocol = &fileio_stream_p,
- .locals_dict = (mp_obj_dict_t*)&uos_mbfs_file_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ uos_mbfs_fileio_type,
+ MP_QSTR_FileIO,
+ MP_TYPE_FLAG_NONE,
+ protocol, &fileio_stream_p,
+ locals_dict, &uos_mbfs_file_locals_dict
+ );
// From micro:bit fileobj.c
mp_obj_t uos_mbfs_open(size_t n_args, const mp_obj_t *args) {
diff --git a/ports/nrf/modules/uos/microbitfs.h b/ports/nrf/modules/uos/microbitfs.h
index d9efaabf10ae..645a1e328961 100644
--- a/ports/nrf/modules/uos/microbitfs.h
+++ b/ports/nrf/modules/uos/microbitfs.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)
*
diff --git a/ports/nrf/modules/uos/moduos.c b/ports/nrf/modules/uos/moduos.c
index 184f833ef5df..402096aacd78 100644
--- a/ports/nrf/modules/uos/moduos.c
+++ b/ports/nrf/modules/uos/moduos.c
@@ -108,7 +108,7 @@ STATIC mp_obj_t os_urandom(mp_obj_t num) {
for (int i = 0; i < n; i++) {
vstr.buf[i] = (uint8_t)(rng_generate_random_word() & 0xFF);
}
- return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
+ return mp_obj_new_bytes_from_vstr(&vstr);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_urandom_obj, os_urandom);
#endif
@@ -126,7 +126,7 @@ STATIC mp_obj_t os_dupterm(mp_uint_t n_args, const mp_obj_t *args) {
} else {
if (args[0] == mp_const_none) {
MP_STATE_PORT(board_stdio_uart) = NULL;
- } else if (mp_obj_get_type(args[0]) == &machine_hard_uart_type) {
+ } else if (mp_obj_get_type(args[0]) == &machine_uart_type) {
MP_STATE_PORT(board_stdio_uart) = args[0];
} else {
mp_raise_ValueError(MP_ERROR_TEXT("need a UART object"));
diff --git a/ports/nrf/mpconfigport.h b/ports/nrf/mpconfigport.h
index 29bdd3f80ca4..8875e3faaf7c 100644
--- a/ports/nrf/mpconfigport.h
+++ b/ports/nrf/mpconfigport.h
@@ -133,23 +133,6 @@
#define MICROPY_FATFS_MAX_SS (4096)
#endif
-#if MICROPY_VFS
-// TODO these should be generic, not bound to a particular FS implementation
-#if MICROPY_VFS_FAT
-#define mp_type_fileio mp_type_vfs_fat_fileio
-#define mp_type_textio mp_type_vfs_fat_textio
-#elif MICROPY_VFS_LFS1
-#define mp_type_fileio mp_type_vfs_lfs1_fileio
-#define mp_type_textio mp_type_vfs_lfs1_textio
-#elif MICROPY_VFS_LFS2
-#define mp_type_fileio mp_type_vfs_lfs2_fileio
-#define mp_type_textio mp_type_vfs_lfs2_textio
-#endif
-#else // !MICROPY_VFS_FAT
-#define mp_type_fileio fatfs_type_fileio
-#define mp_type_textio fatfs_type_textio
-#endif
-
// Use port specific uos module rather than extmod variant.
#define MICROPY_PY_UOS (0)
@@ -157,6 +140,11 @@
#define MICROPY_MODULE_WEAK_LINKS (1)
#define MICROPY_CAN_OVERRIDE_BUILTINS (1)
#define MICROPY_USE_INTERNAL_ERRNO (1)
+#if MICROPY_HW_USB_CDC_1200BPS_TOUCH
+#define MICROPY_HW_ENABLE_USBDEV (1)
+#define MICROPY_ENABLE_SCHEDULER (1)
+#define MICROPY_SCHEDULER_STATIC_NODES (1)
+#endif
#define MICROPY_PY_FUNCTION_ATTRS (1)
#define MICROPY_PY_BUILTINS_STR_UNICODE (1)
#define MICROPY_PY_BUILTINS_MEMORYVIEW (1)
@@ -168,7 +156,6 @@
#define MICROPY_MODULE_BUILTIN_INIT (1)
#define MICROPY_PY_MICROPYTHON_MEM_INFO (1)
#define MICROPY_PY_SYS_MAXSIZE (1)
-#define MICROPY_PY_IO_FILEIO (MICROPY_VFS_FAT || MICROPY_VFS_LFS1 || MICROPY_VFS_LFS2)
#define MICROPY_PY_URANDOM (1)
#define MICROPY_PY_URANDOM_EXTRA_FUNCS (1)
#define MICROPY_PY_UTIME_MP_HAL (1)
@@ -210,8 +197,18 @@
#define MICROPY_PY_MACHINE_SOFT_PWM (0)
#endif
-#ifndef MICROPY_PY_MACHINE_TIMER
-#define MICROPY_PY_MACHINE_TIMER (0)
+#define MICROPY_PY_MACHINE_PWM_INIT (1)
+#define MICROPY_PY_MACHINE_PWM_DUTY (1)
+#define MICROPY_PY_MACHINE_PWM_DUTY_U16_NS (1)
+
+#if MICROPY_PY_MACHINE_HW_PWM
+#define MICROPY_PY_MACHINE_PWM_INCLUDEFILE "ports/nrf/modules/machine/pwm.c"
+#elif MICROPY_PY_MACHINE_SOFT_PWM
+#define MICROPY_PY_MACHINE_PWM_INCLUDEFILE "ports/nrf/modules/machine/soft_pwm.c"
+#endif
+
+#ifndef MICROPY_PY_MACHINE_TIMER_NRF
+#define MICROPY_PY_MACHINE_TIMER_NRF (1)
#endif
#ifndef MICROPY_PY_MACHINE_RTCOUNTER
@@ -291,13 +288,10 @@ typedef int mp_int_t; // must be pointer size
typedef unsigned int mp_uint_t; // must be pointer size
typedef long mp_off_t;
-// extra built in modules to add to the list of known ones
-extern const struct _mp_obj_module_t board_module;
-extern const struct _mp_obj_module_t nrf_module;
-extern const struct _mp_obj_module_t mp_module_utime;
-extern const struct _mp_obj_module_t mp_module_uos;
-extern const struct _mp_obj_module_t mp_module_ubluepy;
-extern const struct _mp_obj_module_t music_module;
+#if MICROPY_HW_ENABLE_RNG
+#define MICROPY_PY_URANDOM_SEED_INIT_FUNC (rng_generate_random_word())
+long unsigned int rng_generate_random_word(void);
+#endif
#if BOARD_SPECIFIC_MODULES
#include "boardmodules.h"
@@ -310,49 +304,20 @@ extern const struct _mp_obj_module_t music_module;
// extra constants
#define MICROPY_PORT_CONSTANTS \
- { MP_ROM_QSTR(MP_QSTR_board), MP_ROM_PTR(&board_module) }, \
{ MP_ROM_QSTR(MP_QSTR_machine), MP_ROM_PTR(&mp_module_machine) }, \
#define MP_STATE_PORT MP_STATE_VM
-#if MICROPY_PY_MUSIC
-#define ROOT_POINTERS_MUSIC \
- struct _music_data_t *music_data;
-#else
-#define ROOT_POINTERS_MUSIC
-#endif
-
-#if MICROPY_PY_MACHINE_SOFT_PWM
-#define ROOT_POINTERS_SOFTPWM \
- const struct _pwm_events *pwm_active_events; \
- const struct _pwm_events *pwm_pending_events;
+#if MICROPY_HW_USB_CDC
+#include "device/usbd.h"
+#define MICROPY_HW_USBDEV_TASK_HOOK extern void tud_task(void); tud_task();
#else
-#define ROOT_POINTERS_SOFTPWM
+#define MICROPY_HW_USBDEV_TASK_HOOK ;
#endif
-#if defined(NRF52840_XXAA)
-#define NUM_OF_PINS 48
-#else
-#define NUM_OF_PINS 32
-#endif
-
-#define MICROPY_PORT_ROOT_POINTERS \
- const char *readline_hist[8]; \
- mp_obj_t pin_class_mapper; \
- mp_obj_t pin_class_map_dict; \
- mp_obj_t pin_irq_handlers[NUM_OF_PINS]; \
- \
- /* stdio is repeated on this UART object if it's not null */ \
- struct _machine_hard_uart_obj_t *board_stdio_uart; \
- \
- ROOT_POINTERS_MUSIC \
- ROOT_POINTERS_SOFTPWM \
- \
- /* micro:bit root pointers */ \
- void *async_data[2]; \
-
#define MICROPY_EVENT_POLL_HOOK \
do { \
+ MICROPY_HW_USBDEV_TASK_HOOK \
extern void mp_handle_pending(bool); \
mp_handle_pending(true); \
__WFI(); \
@@ -366,3 +331,15 @@ extern const struct _mp_obj_module_t music_module;
#ifndef MP_NEED_LOG2
#define MP_NEED_LOG2 (1)
#endif
+
+#ifndef MICROPY_BOARD_STARTUP
+#define MICROPY_BOARD_STARTUP()
+#endif
+
+#ifndef MICROPY_BOARD_ENTER_BOOTLOADER
+#define MICROPY_BOARD_ENTER_BOOTLOADER(nargs, args)
+#endif
+
+#ifndef MICROPY_BOARD_EARLY_INIT
+#define MICROPY_BOARD_EARLY_INIT()
+#endif
diff --git a/ports/nrf/mphalport.c b/ports/nrf/mphalport.c
index 1b31ad5accdf..a2eec7fceb1d 100644
--- a/ports/nrf/mphalport.c
+++ b/ports/nrf/mphalport.c
@@ -179,6 +179,9 @@ uintptr_t mp_hal_stdio_poll(uintptr_t poll_flags) {
&& uart_rx_any(MP_STATE_PORT(board_stdio_uart))) {
ret |= MP_STREAM_POLL_RD;
}
+ if ((poll_flags & MP_STREAM_POLL_WR) && MP_STATE_PORT(board_stdio_uart) != NULL) {
+ ret |= MP_STREAM_POLL_WR;
+ }
return ret;
}
@@ -374,3 +377,5 @@ const char *nrfx_error_code_lookup(uint32_t err_code) {
}
#endif // NRFX_LOG_ENABLED
+
+MP_REGISTER_ROOT_POINTER(struct _machine_hard_uart_obj_t *board_stdio_uart);
diff --git a/ports/nrf/nrfx_config.h b/ports/nrf/nrfx_config.h
index 2b0555dda077..4669a0905641 100644
--- a/ports/nrf/nrfx_config.h
+++ b/ports/nrf/nrfx_config.h
@@ -74,10 +74,16 @@
#endif
#endif
-#if defined(NRF51) || defined(NRF52_SERIES)
+#if defined(NRF51)
#define NRFX_UART_ENABLED 1
#define NRFX_UART0_ENABLED 1
#define NRFX_UART1_ENABLED 1
+#elif defined(NRF52_SERIES)
+ #define NRFX_UARTE_ENABLED 1
+ #define NRFX_UARTE0_ENABLED 1
+ #if NRF52840 || NRF52840_XXAA
+ #define NRFX_UARTE1_ENABLED 1
+ #endif
#else
#define NRFX_UARTE_ENABLED 1
#define NRFX_UARTE0_ENABLED 1
@@ -132,7 +138,7 @@
#define NRFX_RTC1_ENABLED 1
#define NRFX_RTC2_ENABLED (!NRF51) && (!NRF9160_XXAA)
-#define NRFX_TIMER_ENABLED (MICROPY_PY_MACHINE_TIMER)
+#define NRFX_TIMER_ENABLED (MICROPY_PY_MACHINE_TIMER_NRF)
#define NRFX_TIMER0_ENABLED 1
#define NRFX_TIMER1_ENABLED (!MICROPY_PY_MACHINE_SOFT_PWM)
#define NRFX_TIMER2_ENABLED 1
diff --git a/ports/nrf/pin_named_pins.c b/ports/nrf/pin_named_pins.c
index e1d8736b9cf2..30e60692f741 100644
--- a/ports/nrf/pin_named_pins.c
+++ b/ports/nrf/pin_named_pins.c
@@ -36,19 +36,21 @@ STATIC void pin_named_pins_obj_print(const mp_print_t *print, mp_obj_t self_in,
mp_printf(print, "", self->name);
}
-const mp_obj_type_t pin_cpu_pins_obj_type = {
- { &mp_type_type },
- .name = MP_QSTR_cpu,
- .print = pin_named_pins_obj_print,
- .locals_dict = (mp_obj_t)&pin_cpu_pins_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ pin_cpu_pins_obj_type,
+ MP_QSTR_cpu,
+ MP_TYPE_FLAG_NONE,
+ print, pin_named_pins_obj_print,
+ locals_dict, &pin_cpu_pins_locals_dict
+ );
-const mp_obj_type_t pin_board_pins_obj_type = {
- { &mp_type_type },
- .name = MP_QSTR_board,
- .print = pin_named_pins_obj_print,
- .locals_dict = (mp_obj_t)&pin_board_pins_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ pin_board_pins_obj_type,
+ MP_QSTR_board,
+ MP_TYPE_FLAG_NONE,
+ print, pin_named_pins_obj_print,
+ locals_dict, &pin_board_pins_locals_dict
+ );
const pin_obj_t *pin_find_named_pin(const mp_obj_dict_t *named_pins, mp_obj_t name) {
mp_map_t *named_map = mp_obj_dict_get_map((mp_obj_t)named_pins);
diff --git a/ports/pic16bit/Makefile b/ports/pic16bit/Makefile
index f0d55ec875e3..d2c8df4707e0 100644
--- a/ports/pic16bit/Makefile
+++ b/ports/pic16bit/Makefile
@@ -5,6 +5,7 @@ QSTR_DEFS = qstrdefsport.h
# include py core make definitions
include $(TOP)/py/py.mk
+include $(TOP)/extmod/extmod.mk
XCVERSION ?= 1.35
XC16 ?= /opt/microchip/xc16/v$(XCVERSION)
@@ -20,7 +21,7 @@ INC += -I$(XC16)/include
INC += -I$(XC16)/support/$(PARTFAMILY)/h
CFLAGS_PIC16BIT = -mcpu=$(PART) -mlarge-code
-CFLAGS = $(INC) -Wall -Werror -std=gnu99 -nostdlib $(CFLAGS_PIC16BIT) $(COPT)
+CFLAGS += $(INC) -Wall -Werror -std=gnu99 -nostdlib $(CFLAGS_PIC16BIT) $(COPT)
#Debugging/Optimization
ifeq ($(DEBUG), 1)
@@ -29,8 +30,8 @@ else
CFLAGS += -O1 -DNDEBUG
endif
-LDFLAGS = --heap=0 -nostdlib -T $(XC16)/support/$(PARTFAMILY)/gld/p$(PART).gld -Map=$@.map --cref -p$(PART)
-LIBS = -L$(XC16)/lib -L$(XC16)/lib/$(PARTFAMILY) -lc -lm -lpic30
+LDFLAGS += --heap=0 -nostdlib -T $(XC16)/support/$(PARTFAMILY)/gld/p$(PART).gld -Map=$@.map --cref -p$(PART)
+LIBS += -L$(XC16)/lib -L$(XC16)/lib/$(PARTFAMILY) -lc -lm -lpic30
SRC_C = \
main.c \
diff --git a/ports/pic16bit/modpybled.c b/ports/pic16bit/modpybled.c
index 6adb2fda3126..47e83e040921 100644
--- a/ports/pic16bit/modpybled.c
+++ b/ports/pic16bit/modpybled.c
@@ -84,10 +84,11 @@ STATIC const mp_rom_map_elem_t pyb_led_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(pyb_led_locals_dict, pyb_led_locals_dict_table);
-const mp_obj_type_t pyb_led_type = {
- { &mp_type_type },
- .name = MP_QSTR_LED,
- .print = pyb_led_print,
- .make_new = pyb_led_make_new,
- .locals_dict = (mp_obj_t)&pyb_led_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ pyb_led_type,
+ MP_QSTR_LED,
+ MP_TYPE_FLAG_NONE,
+ make_new, pyb_led_make_new,
+ print, pyb_led_print,
+ locals_dict, &pyb_led_locals_dict
+ );
diff --git a/ports/pic16bit/modpybswitch.c b/ports/pic16bit/modpybswitch.c
index 7b3d0f5f527b..b7192c5bba69 100644
--- a/ports/pic16bit/modpybswitch.c
+++ b/ports/pic16bit/modpybswitch.c
@@ -71,11 +71,12 @@ STATIC const mp_rom_map_elem_t pyb_switch_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(pyb_switch_locals_dict, pyb_switch_locals_dict_table);
-const mp_obj_type_t pyb_switch_type = {
- { &mp_type_type },
- .name = MP_QSTR_Switch,
- .print = pyb_switch_print,
- .make_new = pyb_switch_make_new,
- .call = pyb_switch_call,
- .locals_dict = (mp_obj_t)&pyb_switch_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ pyb_switch_type,
+ MP_QSTR_Switch,
+ MP_TYPE_FLAG_NONE,
+ make_new, pyb_switch_make_new,
+ print, pyb_switch_print,
+ call, pyb_switch_call,
+ locals_dict, &pyb_switch_locals_dict
+ );
diff --git a/ports/pic16bit/mpconfigport.h b/ports/pic16bit/mpconfigport.h
index e97a46502828..f1bfa4cd6f16 100644
--- a/ports/pic16bit/mpconfigport.h
+++ b/ports/pic16bit/mpconfigport.h
@@ -91,10 +91,6 @@ typedef int mp_off_t;
#define MP_STATE_PORT MP_STATE_VM
-#define MICROPY_PORT_ROOT_POINTERS \
- char *readline_hist[8]; \
- mp_obj_t keyboard_interrupt_obj; \
-
#define MICROPY_MPHALPORT_H "pic16bit_mphal.h"
#define MICROPY_HW_BOARD_NAME "dsPICSK"
#define MICROPY_HW_MCU_NAME "dsPIC33"
diff --git a/ports/pic16bit/pic16bit_mphal.c b/ports/pic16bit/pic16bit_mphal.c
index adab3819348b..b2c80ba1be78 100644
--- a/ports/pic16bit/pic16bit_mphal.c
+++ b/ports/pic16bit/pic16bit_mphal.c
@@ -57,6 +57,9 @@ uintptr_t mp_hal_stdio_poll(uintptr_t poll_flags) {
if ((poll_flags & MP_STREAM_POLL_RD) && uart_rx_any()) {
ret |= MP_STREAM_POLL_RD;
}
+ if (poll_flags & MP_STREAM_POLL_WR) {
+ ret |= MP_STREAM_POLL_WR;
+ }
return ret;
}
@@ -86,3 +89,5 @@ void mp_hal_stdout_tx_strn_cooked(const char *str, size_t len) {
uart_tx_char(*str++);
}
}
+
+MP_REGISTER_ROOT_POINTER(mp_obj_t keyboard_interrupt_obj);
diff --git a/ports/powerpc/Makefile b/ports/powerpc/Makefile
index cca170dc022d..8fc9b11166e6 100644
--- a/ports/powerpc/Makefile
+++ b/ports/powerpc/Makefile
@@ -5,6 +5,7 @@ QSTR_DEFS = qstrdefsport.h
# include py core make definitions
include $(TOP)/py/py.mk
+include $(TOP)/extmod/extmod.mk
# potato or lpc_serial
UART ?= potato
@@ -20,14 +21,14 @@ INC += -I.
INC += -I$(TOP)
INC += -I$(BUILD)
-CFLAGS = $(INC) -g -Wall -Wdouble-promotion -Wfloat-conversion -std=c99 $(COPT)
+CFLAGS += $(INC) -g -Wall -Wdouble-promotion -Wfloat-conversion -std=c99 $(COPT)
CFLAGS += -mno-string -mno-multiple -mno-vsx -mno-altivec -nostdlib
CFLAGS += -mlittle-endian -mstrict-align -msoft-float
CFLAGS += -Os
CFLAGS += -fdata-sections -ffunction-sections -fno-stack-protector -ffreestanding
CFLAGS += -U_FORTIFY_SOURCE
-LDFLAGS = -N -T powerpc.lds -nostdlib
+LDFLAGS += -N -T powerpc.lds -nostdlib
LIBS =
@@ -41,13 +42,15 @@ SRC_C = \
shared/runtime/stdout_helpers.c \
$(BUILD)/_frozen_mpy.c \
+SRC_QSTR += shared/readline/readline.c shared/runtime/pyexec.c
+
OBJ = $(PY_CORE_O)
OBJ += $(addprefix $(BUILD)/, $(SRC_C:.c=.o))
OBJ += $(BUILD)/head.o
all: $(BUILD)/firmware.elf $(BUILD)/firmware.map $(BUILD)/firmware.bin
-$(BUILD)/_frozen_mpy.c: frozentest.mpy $(BUILD)/genhdr/qstrdefs.generated.h
+$(BUILD)/_frozen_mpy.c: $(TOP)/tests/frozen/frozentest.mpy $(BUILD)/genhdr/qstrdefs.generated.h
$(ECHO) "MISC freezing bytecode"
$(Q)$(MPY_TOOL) -f -q $(BUILD)/genhdr/qstrdefs.preprocessed.h -mlongint-impl=mpz $< > $@
diff --git a/ports/powerpc/frozentest.mpy b/ports/powerpc/frozentest.mpy
deleted file mode 100644
index 99581617ac3d..000000000000
Binary files a/ports/powerpc/frozentest.mpy and /dev/null differ
diff --git a/ports/powerpc/frozentest.py b/ports/powerpc/frozentest.py
deleted file mode 100644
index 78cdd60bf043..000000000000
--- a/ports/powerpc/frozentest.py
+++ /dev/null
@@ -1,7 +0,0 @@
-print("uPy")
-print("a long string that is not interned")
-print("a string that has unicode αβγ chars")
-print(b"bytes 1234\x01")
-print(123456789)
-for i in range(4):
- print(i)
diff --git a/ports/powerpc/main.c b/ports/powerpc/main.c
index ed82c517ebc1..f3abc64aa739 100644
--- a/ports/powerpc/main.c
+++ b/ports/powerpc/main.c
@@ -95,7 +95,7 @@ int main(int argc, char **argv) {
pyexec_friendly_repl();
#endif
#else
- pyexec_frozen_module("frozentest.py");
+ pyexec_frozen_module("frozentest.py", false);
#endif
mp_deinit();
return 0;
@@ -108,7 +108,7 @@ void gc_collect(void) {
gc_collect_start();
gc_collect_root(&dummy, ((mp_uint_t)stack_top - (mp_uint_t)&dummy) / sizeof(mp_uint_t));
gc_collect_end();
- gc_dump_info();
+ gc_dump_info(&mp_plat_print);
}
mp_lexer_t *mp_lexer_new_from_file(const char *filename) {
diff --git a/ports/powerpc/mpconfigport.h b/ports/powerpc/mpconfigport.h
index 0b868e3dafab..084a461a4a73 100644
--- a/ports/powerpc/mpconfigport.h
+++ b/ports/powerpc/mpconfigport.h
@@ -112,9 +112,6 @@ typedef long mp_off_t;
#define MP_STATE_PORT MP_STATE_VM
-#define MICROPY_PORT_ROOT_POINTERS \
- const char *readline_hist[8];
-
// powerpc64 gcc doesn't seem to define these
// These are pointers, so make them 64 bit types
typedef long intptr_t;
diff --git a/ports/qemu-arm/Makefile b/ports/qemu-arm/Makefile
index 08c2d82498f2..40b3062ae4c4 100644
--- a/ports/qemu-arm/Makefile
+++ b/ports/qemu-arm/Makefile
@@ -9,6 +9,7 @@ MICROPY_ROM_TEXT_COMPRESSION ?= 1
# include py core make definitions
include $(TOP)/py/py.mk
+include $(TOP)/extmod/extmod.mk
BOARD ?= mps2-an385
@@ -16,7 +17,7 @@ ifeq ($(BOARD),netduino2)
CFLAGS += -mthumb -mcpu=cortex-m3 -mfloat-abi=soft
CFLAGS += -DQEMU_SOC_STM32
LDSCRIPT = stm32.ld
-SRC_BOARD_O = shared/runtime/gchelper_native.o shared/runtime/gchelper_m3.o
+SRC_BOARD_O = shared/runtime/gchelper_native.o shared/runtime/gchelper_thumb2.o
MPY_CROSS_FLAGS += -march=armv7m
endif
@@ -25,7 +26,7 @@ CFLAGS += -mthumb -mcpu=cortex-m0 -mfloat-abi=soft
CFLAGS += -DQEMU_SOC_NRF51
LDSCRIPT = nrf51.ld
QEMU_EXTRA = -global nrf51-soc.flash-size=1048576 -global nrf51-soc.sram-size=262144
-SRC_BOARD_O = shared/runtime/gchelper_native.o shared/runtime/gchelper_m0.o
+SRC_BOARD_O = shared/runtime/gchelper_native.o shared/runtime/gchelper_thumb1.o
MPY_CROSS_FLAGS += -march=armv7m
endif
@@ -33,7 +34,7 @@ ifeq ($(BOARD),mps2-an385)
CFLAGS += -mthumb -mcpu=cortex-m3 -mfloat-abi=soft
CFLAGS += -DQEMU_SOC_MPS2
LDSCRIPT = mps2.ld
-SRC_BOARD_O = shared/runtime/gchelper_native.o shared/runtime/gchelper_m3.o
+SRC_BOARD_O = shared/runtime/gchelper_native.o shared/runtime/gchelper_thumb2.o
MPY_CROSS_FLAGS += -march=armv7m
endif
diff --git a/ports/qemu-arm/README.md b/ports/qemu-arm/README.md
index 2c815c54b088..f821c4d1e28f 100644
--- a/ports/qemu-arm/README.md
+++ b/ports/qemu-arm/README.md
@@ -16,7 +16,7 @@ The purposes of this port are to enable:
process in terms of plugging things together, pressing buttons, etc.
This port will only work with the [GNU ARM Embedded Toolchain](
-https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-rm)
+https://developer.arm.com/downloads/-/arm-gnu-toolchain-downloads
and not with CodeSourcery toolchain. You will need to modify
`LDFLAGS` if you want to use CodeSourcery's version of `arm-none-eabi`.
The difference is that CodeSourcery needs `-T generic-m-hosted.ld` while
diff --git a/ports/qemu-arm/mpconfigport.h b/ports/qemu-arm/mpconfigport.h
index 8809d17154fd..972dce61b498 100644
--- a/ports/qemu-arm/mpconfigport.h
+++ b/ports/qemu-arm/mpconfigport.h
@@ -28,6 +28,7 @@
#define MICROPY_PY_ALL_SPECIAL_METHODS (1)
#define MICROPY_PY_REVERSE_SPECIAL_METHODS (1)
#define MICROPY_PY_ARRAY_SLICE_ASSIGN (1)
+#define MICROPY_PY_BUILTINS_BYTES_HEX (1)
#define MICROPY_PY_BUILTINS_FROZENSET (1)
#define MICROPY_PY_BUILTINS_MEMORYVIEW (1)
#define MICROPY_PY_BUILTINS_POW3 (1)
diff --git a/ports/renesas-ra/Makefile b/ports/renesas-ra/Makefile
index efbcb5f70f07..dc4b15848349 100644
--- a/ports/renesas-ra/Makefile
+++ b/ports/renesas-ra/Makefile
@@ -1,15 +1,21 @@
-# Select the board to build for: if not given on the command line,
-# then default to RA6M2_EK.
+# Select the board to build for:
+ifdef BOARD_DIR
+# Custom board path - remove trailing slash and get the final component of
+# the path as the board name.
+BOARD ?= $(notdir $(BOARD_DIR:/=))
+else
+# If not given on the command line, then default to RA6M2_EK.
BOARD ?= RA6M2_EK
-
-# If the build directory is not given, make it reflect the board name.
-BUILD ?= build-$(BOARD)
-
BOARD_DIR ?= boards/$(BOARD)
+endif
+
ifeq ($(wildcard $(BOARD_DIR)/.),)
$(error Invalid BOARD specified: $(BOARD_DIR))
endif
+# If the build directory is not given, make it reflect the board name.
+BUILD ?= build-$(BOARD)
+
ifeq ($(BOARD),RA4M1_CLICKER)
BOARD_LOW = ra4m1_ek
CMSIS_MCU_LOW = ra4m1
@@ -67,6 +73,7 @@ FROZEN_MANIFEST ?= boards/manifest.py
# include py core make definitions
include $(TOP)/py/py.mk
+include $(TOP)/extmod/extmod.mk
GIT_SUBMODULES += lib/fsp
@@ -120,7 +127,7 @@ CFLAGS_MCU_RA4W1 = $(CFLAGS_CORTEX_M) -mtune=cortex-m4 -mcpu=cortex-m4
CFLAGS_MCU_RA6M1 = $(CFLAGS_CORTEX_M) -mtune=cortex-m4 -mcpu=cortex-m4
CFLAGS_MCU_RA6M2 = $(CFLAGS_CORTEX_M) -mtune=cortex-m4 -mcpu=cortex-m4
-CFLAGS += $(INC) -Wall -Wpointer-arith -Werror -Wdouble-promotion -Wfloat-conversion -std=gnu99 -nostdlib $(CFLAGS_MOD) $(CFLAGS_EXTRA)
+CFLAGS += $(INC) -Wall -Wpointer-arith -Werror -Wdouble-promotion -Wfloat-conversion -std=gnu99 -nostdlib $(CFLAGS_EXTRA)
#CFLAGS += -D$(CMSIS_MCU)
CFLAGS += $(CFLAGS_MCU_$(CMSIS_MCU))
CFLAGS += $(COPT)
@@ -138,7 +145,7 @@ CFLAGS += -fsingle-precision-constant
endif
endif
-LDFLAGS = -nostdlib -L $(LD_DIR) $(addprefix -T,$(LD_FILES)) -Map=$(@:.elf=.map) --cref
+LDFLAGS += -nostdlib -L $(LD_DIR) $(addprefix -T,$(LD_FILES)) -Map=$(@:.elf=.map) --cref
LDFLAGS += --defsym=_estack_reserve=8
LIBS += "$(shell $(CC) $(CFLAGS) -print-libgcc-file-name)"
@@ -147,8 +154,9 @@ CFLAGS += -fdata-sections -ffunction-sections
LDFLAGS += --gc-sections
# Debugging/Optimization
+CFLAGS += -g # always include debug info in the ELF
ifeq ($(DEBUG), 1)
-CFLAGS += -g -DPENDSV_DEBUG
+CFLAGS += -DPENDSV_DEBUG
#COPT = -Og
COPT = -Os
# Disable text compression in debug builds
@@ -159,8 +167,9 @@ endif
# Flags for optional C++ source code
CXXFLAGS += $(filter-out -Wmissing-prototypes -Wold-style-definition -std=gnu99,$(CFLAGS))
-CXXFLAGS += $(CXXFLAGS_MOD)
-ifneq ($(SRC_CXX)$(SRC_MOD_CXX),)
+
+# TODO make this common -- shouldn't be using these "private" vars from py.mk
+ifneq ($(SRC_CXX)$(SRC_USERMOD_CXX)$(SRC_USERMOD_LIB_CXX),)
LIBSTDCPP_FILE_NAME = "$(shell $(CXX) $(CXXFLAGS) -print-file-name=libstdc++.a)"
LDFLAGS += -L"$(shell dirname $(LIBSTDCPP_FILE_NAME))"
endif
@@ -178,6 +187,7 @@ SHARED_SRC_C += $(addprefix shared/,\
runtime/interrupt_char.c \
runtime/mpirq.c \
runtime/pyexec.c \
+ runtime/softtimer.c \
runtime/stdout_helpers.c \
runtime/sys_stdio_mphal.c \
timeutils/timeutils.c \
@@ -276,10 +286,6 @@ ifeq ($(MICROPY_FLOAT_IMPL),double)
$(LIBM_O): CFLAGS := $(filter-out -Wdouble-promotion -Wfloat-conversion, $(CFLAGS))
endif
-EXTMOD_SRC_C += $(addprefix extmod/,\
- modonewire.c \
- )
-
DRIVERS_SRC_C += $(addprefix drivers/,\
bus/softspi.c \
bus/softqspi.c \
@@ -296,7 +302,6 @@ SRC_C += \
irq.c \
pendsv.c \
systick.c \
- softtimer.c \
powerctrl.c \
powerctrlboot.c \
pybthread.c \
@@ -309,7 +314,6 @@ SRC_C += \
machine_adc.c \
machine_i2c.c \
machine_spi.c \
- machine_timer.c \
machine_uart.c \
machine_pin.c \
machine_rtc.c \
@@ -332,15 +336,12 @@ SRC_C += $(addprefix $(BOARD_DIR)/ra_gen/,\
vector_data.c \
)
-SRC_CXX += \
- $(SRC_MOD_CXX)
-
SRC_O += \
$(STARTUP_FILE) \
$(SYSTEM_FILE)
SRC_O += \
- shared/runtime/gchelper_m3.o
+ shared/runtime/gchelper_thumb2.o
HAL_SRC_C += $(addprefix $(HAL_DIR)/ra/board/$(BOARD_LOW)/,\
board_init.c \
@@ -406,13 +407,11 @@ OBJ += $(PY_O)
OBJ += $(addprefix $(BUILD)/, $(LIB_SRC_C:.c=.o))
OBJ += $(LIBM_O)
OBJ += $(addprefix $(BUILD)/, $(SHARED_SRC_C:.c=.o))
-OBJ += $(addprefix $(BUILD)/, $(EXTMOD_SRC_C:.c=.o))
OBJ += $(addprefix $(BUILD)/, $(DRIVERS_SRC_C:.c=.o))
OBJ += $(addprefix $(BUILD)/, $(HAL_SRC_C:.c=.o))
OBJ += $(addprefix $(BUILD)/, $(SRC_C:.c=.o))
OBJ += $(addprefix $(BUILD)/, $(SRC_CXX:.cpp=.o))
OBJ += $(addprefix $(BUILD)/, $(SRC_O))
-OBJ += $(addprefix $(BUILD)/, $(SRC_MOD:.c=.o))
OBJ += $(BUILD)/pins_$(BOARD).o
# This file contains performance critical functions so turn up the optimisation
@@ -512,7 +511,7 @@ GEN_PINS_AF_PY = $(BUILD)/pins_af.py
FILE2H = $(TOP)/tools/file2h.py
# List of sources for qstr extraction
-SRC_QSTR += $(SRC_C) $(SRC_CXX) $(SRC_MOD) $(SHARED_SRC_C) $(EXTMOD_SRC_C)
+SRC_QSTR += $(SRC_C) $(SRC_CXX) $(SHARED_SRC_C)
# Making OBJ use an order-only depenedency on the generated pins.h file
# has the side effect of making the pins.h file before we actually compile
diff --git a/ports/renesas-ra/README.md b/ports/renesas-ra/README.md
index 482870e1c036..c75a9e13d1ed 100644
--- a/ports/renesas-ra/README.md
+++ b/ports/renesas-ra/README.md
@@ -36,7 +36,7 @@ All other commands below should be executed from the ports/renesas-ra/ directory
* Arm compiler
An `Arm compiler` is required for the build, along with the associated binary
utilities. The default compiler is `arm-none-eabi-gcc`, which is available for
-Arch Linux and Windows hosts via https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-rm/downloads.
+Linux, Mac and Windows hosts via https://developer.arm.com/downloads/-/arm-gnu-toolchain-downloads.
The compiler can be changed using the `CROSS_COMPILE` variable
when invoking `make`.
diff --git a/ports/renesas-ra/boardctrl.h b/ports/renesas-ra/boardctrl.h
index cc7918c35f90..1fc572a34ec3 100644
--- a/ports/renesas-ra/boardctrl.h
+++ b/ports/renesas-ra/boardctrl.h
@@ -37,6 +37,10 @@
#define MICROPY_BOARD_STARTUP powerctrl_check_enter_bootloader
#endif
+#ifndef MICROPY_BOARD_ENTER_BOOTLOADER
+#define MICROPY_BOARD_ENTER_BOOTLOADER(nargs, args)
+#endif
+
#ifndef MICROPY_BOARD_EARLY_INIT
#define MICROPY_BOARD_EARLY_INIT()
#endif
diff --git a/ports/renesas-ra/boards/RA4M1_CLICKER/manifest.py b/ports/renesas-ra/boards/RA4M1_CLICKER/manifest.py
index 4a387915d37e..99b9c94051ed 100644
--- a/ports/renesas-ra/boards/RA4M1_CLICKER/manifest.py
+++ b/ports/renesas-ra/boards/RA4M1_CLICKER/manifest.py
@@ -1,2 +1,2 @@
# We do not want to include default frozen modules,
-freeze("$(MPY_DIR)/drivers/sdcard", "sdcard.py")
+require("sdcard")
diff --git a/ports/renesas-ra/boards/RA4M1_CLICKER/mpconfigboard.h b/ports/renesas-ra/boards/RA4M1_CLICKER/mpconfigboard.h
index ec67d68b6584..f39cf8f80e39 100644
--- a/ports/renesas-ra/boards/RA4M1_CLICKER/mpconfigboard.h
+++ b/ports/renesas-ra/boards/RA4M1_CLICKER/mpconfigboard.h
@@ -47,8 +47,8 @@
// Switch
#define MICROPY_HW_HAS_SWITCH (1)
#define MICROPY_HW_USRSW_PIN (pin_P304)
-#define MICROPY_HW_USRSW_PULL (GPIO_NOPULL)
-#define MICROPY_HW_USRSW_EXTI_MODE (GPIO_MODE_IT_FALLING)
+#define MICROPY_HW_USRSW_PULL (MP_HAL_PIN_PULL_NONE)
+#define MICROPY_HW_USRSW_EXTI_MODE (MP_HAL_PIN_TRIGGER_FALLING)
#define MICROPY_HW_USRSW_PRESSED (0)
// LEDs
diff --git a/ports/renesas-ra/boards/RA4M1_CLICKER/ra4m1_clicker.ld b/ports/renesas-ra/boards/RA4M1_CLICKER/ra4m1_clicker.ld
index 0ce4e9267160..52f8acf93eb3 100644
--- a/ports/renesas-ra/boards/RA4M1_CLICKER/ra4m1_clicker.ld
+++ b/ports/renesas-ra/boards/RA4M1_CLICKER/ra4m1_clicker.ld
@@ -5,7 +5,8 @@
/* Linker script to configure memory regions. */
MEMORY
{
- FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x00040000 /* 256KB */
+ FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x00037000 /* 220KB/256KB */
+ FLASH_FS (r) : ORIGIN = 0x00037000, LENGTH = 0x00009000 /* 36KB/256KB */
RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000 /* 32KB */
DATA_FLASH (rx) : ORIGIN = 0x40100000, LENGTH = 0x00002000 /* 8KB */
ID_CODE (rx) : ORIGIN = 0x01010018, LENGTH = 0x00000020 /* 32bytes */
@@ -296,3 +297,6 @@ _ram_start = ORIGIN(RAM);
_ram_end = ORIGIN(RAM) + LENGTH(RAM);
_heap_start = __HeapBase; /* heap starts just after statically allocated memory */
_heap_end = __HeapLimit; /* tunable */
+
+_micropy_hw_internal_flash_storage_start = ORIGIN(FLASH_FS);
+_micropy_hw_internal_flash_storage_end = ORIGIN(FLASH_FS) + LENGTH(FLASH_FS);
diff --git a/ports/renesas-ra/boards/RA4M1_EK/manifest.py b/ports/renesas-ra/boards/RA4M1_EK/manifest.py
index 4a387915d37e..99b9c94051ed 100644
--- a/ports/renesas-ra/boards/RA4M1_EK/manifest.py
+++ b/ports/renesas-ra/boards/RA4M1_EK/manifest.py
@@ -1,2 +1,2 @@
# We do not want to include default frozen modules,
-freeze("$(MPY_DIR)/drivers/sdcard", "sdcard.py")
+require("sdcard")
diff --git a/ports/renesas-ra/boards/RA4M1_EK/mpconfigboard.h b/ports/renesas-ra/boards/RA4M1_EK/mpconfigboard.h
index 500fe78b9e12..2874142890c1 100644
--- a/ports/renesas-ra/boards/RA4M1_EK/mpconfigboard.h
+++ b/ports/renesas-ra/boards/RA4M1_EK/mpconfigboard.h
@@ -59,8 +59,8 @@
// Switch
#define MICROPY_HW_HAS_SWITCH (1)
#define MICROPY_HW_USRSW_PIN (pin_P105)
-#define MICROPY_HW_USRSW_PULL (GPIO_NOPULL)
-#define MICROPY_HW_USRSW_EXTI_MODE (GPIO_MODE_IT_FALLING)
+#define MICROPY_HW_USRSW_PULL (MP_HAL_PIN_PULL_NONE)
+#define MICROPY_HW_USRSW_EXTI_MODE (MP_HAL_PIN_TRIGGER_FALLING)
#define MICROPY_HW_USRSW_PRESSED (0)
// LEDs
diff --git a/ports/renesas-ra/boards/RA4M1_EK/ra4m1_ek.ld b/ports/renesas-ra/boards/RA4M1_EK/ra4m1_ek.ld
index 0ce4e9267160..52f8acf93eb3 100644
--- a/ports/renesas-ra/boards/RA4M1_EK/ra4m1_ek.ld
+++ b/ports/renesas-ra/boards/RA4M1_EK/ra4m1_ek.ld
@@ -5,7 +5,8 @@
/* Linker script to configure memory regions. */
MEMORY
{
- FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x00040000 /* 256KB */
+ FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x00037000 /* 220KB/256KB */
+ FLASH_FS (r) : ORIGIN = 0x00037000, LENGTH = 0x00009000 /* 36KB/256KB */
RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000 /* 32KB */
DATA_FLASH (rx) : ORIGIN = 0x40100000, LENGTH = 0x00002000 /* 8KB */
ID_CODE (rx) : ORIGIN = 0x01010018, LENGTH = 0x00000020 /* 32bytes */
@@ -296,3 +297,6 @@ _ram_start = ORIGIN(RAM);
_ram_end = ORIGIN(RAM) + LENGTH(RAM);
_heap_start = __HeapBase; /* heap starts just after statically allocated memory */
_heap_end = __HeapLimit; /* tunable */
+
+_micropy_hw_internal_flash_storage_start = ORIGIN(FLASH_FS);
+_micropy_hw_internal_flash_storage_end = ORIGIN(FLASH_FS) + LENGTH(FLASH_FS);
diff --git a/ports/renesas-ra/boards/RA4W1_EK/mpconfigboard.h b/ports/renesas-ra/boards/RA4W1_EK/mpconfigboard.h
index 0e0dff14755c..0bf907a48c7c 100644
--- a/ports/renesas-ra/boards/RA4W1_EK/mpconfigboard.h
+++ b/ports/renesas-ra/boards/RA4W1_EK/mpconfigboard.h
@@ -58,8 +58,8 @@
// Switch
#define MICROPY_HW_HAS_SWITCH (1)
#define MICROPY_HW_USRSW_PIN (pin_P402)
-#define MICROPY_HW_USRSW_PULL (GPIO_NOPULL)
-#define MICROPY_HW_USRSW_EXTI_MODE (GPIO_MODE_IT_FALLING)
+#define MICROPY_HW_USRSW_PULL (MP_HAL_PIN_PULL_NONE)
+#define MICROPY_HW_USRSW_EXTI_MODE (MP_HAL_PIN_TRIGGER_FALLING)
#define MICROPY_HW_USRSW_PRESSED (0)
// LEDs
diff --git a/ports/renesas-ra/boards/RA4W1_EK/ra4w1_ek.ld b/ports/renesas-ra/boards/RA4W1_EK/ra4w1_ek.ld
index 172f124fc8de..1241b5bc2302 100644
--- a/ports/renesas-ra/boards/RA4W1_EK/ra4w1_ek.ld
+++ b/ports/renesas-ra/boards/RA4W1_EK/ra4w1_ek.ld
@@ -5,7 +5,8 @@
/* Linker script to configure memory regions. */
MEMORY
{
- FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x00080000 /* 512KB */
+ FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x00070000 /* 448KB/512KB */
+ FLASH_FS (r) : ORIGIN = 0x00070000, LENGTH = 0x00010000 /* 64KB/512KB */
RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00018000 /* 96KB */
DATA_FLASH (rx) : ORIGIN = 0x40100000, LENGTH = 0x00002000 /* 8KB */
ID_CODE (rx) : ORIGIN = 0x01010018, LENGTH = 0x00000020 /* 32bytes */
@@ -296,3 +297,6 @@ _ram_start = ORIGIN(RAM);
_ram_end = ORIGIN(RAM) + LENGTH(RAM);
_heap_start = __HeapBase; /* heap starts just after statically allocated memory */
_heap_end = __HeapLimit; /* tunable */
+
+_micropy_hw_internal_flash_storage_start = ORIGIN(FLASH_FS);
+_micropy_hw_internal_flash_storage_end = ORIGIN(FLASH_FS) + LENGTH(FLASH_FS);
diff --git a/ports/renesas-ra/boards/RA6M1_EK/mpconfigboard.h b/ports/renesas-ra/boards/RA6M1_EK/mpconfigboard.h
index 0693e404fd8f..59db4bc218a8 100644
--- a/ports/renesas-ra/boards/RA6M1_EK/mpconfigboard.h
+++ b/ports/renesas-ra/boards/RA6M1_EK/mpconfigboard.h
@@ -64,8 +64,8 @@
// Switch
#define MICROPY_HW_HAS_SWITCH (1)
#define MICROPY_HW_USRSW_PIN (pin_P415)
-#define MICROPY_HW_USRSW_PULL (GPIO_NOPULL)
-#define MICROPY_HW_USRSW_EXTI_MODE (GPIO_MODE_IT_FALLING)
+#define MICROPY_HW_USRSW_PULL (MP_HAL_PIN_PULL_NONE)
+#define MICROPY_HW_USRSW_EXTI_MODE (MP_HAL_PIN_TRIGGER_FALLING)
#define MICROPY_HW_USRSW_PRESSED (0)
// LEDs
diff --git a/ports/renesas-ra/boards/RA6M1_EK/ra6m1_ek.ld b/ports/renesas-ra/boards/RA6M1_EK/ra6m1_ek.ld
index 10ec87aaa60c..c7d85ed3db0a 100644
--- a/ports/renesas-ra/boards/RA6M1_EK/ra6m1_ek.ld
+++ b/ports/renesas-ra/boards/RA6M1_EK/ra6m1_ek.ld
@@ -5,7 +5,8 @@
/* Linker script to configure memory regions. */
MEMORY
{
- FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x00080000 /* 512KB */
+ FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x00070000 /* 448KB/512KB */
+ FLASH_FS (r) : ORIGIN = 0x00070000, LENGTH = 0x00010000 /* 64KB/512KB */
RAM (rwx) : ORIGIN = 0x1FFE0000, LENGTH = 0x00040000 /* 256KB */
DATA_FLASH (rx) : ORIGIN = 0x40100000, LENGTH = 0x00002000 /* 8KB */
ID_CODE (rx) : ORIGIN = 0x0100A150, LENGTH = 0x00000010 /* 32bytes */
@@ -296,3 +297,6 @@ _ram_start = ORIGIN(RAM);
_ram_end = ORIGIN(RAM) + LENGTH(RAM);
_heap_start = __HeapBase; /* heap starts just after statically allocated memory */
_heap_end = __HeapLimit; /* tunable */
+
+_micropy_hw_internal_flash_storage_start = ORIGIN(FLASH_FS);
+_micropy_hw_internal_flash_storage_end = ORIGIN(FLASH_FS) + LENGTH(FLASH_FS);
diff --git a/ports/renesas-ra/boards/RA6M2_EK/mpconfigboard.h b/ports/renesas-ra/boards/RA6M2_EK/mpconfigboard.h
index 2d2dc326d338..9988e0ed25d0 100644
--- a/ports/renesas-ra/boards/RA6M2_EK/mpconfigboard.h
+++ b/ports/renesas-ra/boards/RA6M2_EK/mpconfigboard.h
@@ -77,8 +77,8 @@
// Switch
#define MICROPY_HW_HAS_SWITCH (1)
#define MICROPY_HW_USRSW_PIN (pin_P105)
-#define MICROPY_HW_USRSW_PULL (GPIO_NOPULL)
-#define MICROPY_HW_USRSW_EXTI_MODE (GPIO_MODE_IT_FALLING)
+#define MICROPY_HW_USRSW_PULL (MP_HAL_PIN_PULL_NONE)
+#define MICROPY_HW_USRSW_EXTI_MODE (MP_HAL_PIN_TRIGGER_FALLING)
#define MICROPY_HW_USRSW_PRESSED (0)
// LEDs
diff --git a/ports/renesas-ra/boards/RA6M2_EK/ra6m2_ek.ld b/ports/renesas-ra/boards/RA6M2_EK/ra6m2_ek.ld
index 4ad1b1ac1b8b..086f6630c110 100644
--- a/ports/renesas-ra/boards/RA6M2_EK/ra6m2_ek.ld
+++ b/ports/renesas-ra/boards/RA6M2_EK/ra6m2_ek.ld
@@ -5,7 +5,8 @@
/* Linker script to configure memory regions. */
MEMORY
{
- FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x00100000 /* 1MB */
+ FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x000e0000 /* 896KB/1MB */
+ FLASH_FS (r) : ORIGIN = 0x000e0000, LENGTH = 0x00020000 /* 128KB/1MB */
RAM (rwx) : ORIGIN = 0x1FFE0000, LENGTH = 0x00060000 /* 384KB */
DATA_FLASH (rx) : ORIGIN = 0x40100000, LENGTH = 0x00008000 /* 32KB */
ID_CODE (rx) : ORIGIN = 0x0100A150, LENGTH = 0x00000010 /* 32bytes */
@@ -296,3 +297,6 @@ _ram_start = ORIGIN(RAM);
_ram_end = ORIGIN(RAM) + LENGTH(RAM);
_heap_start = __HeapBase; /* heap starts just after statically allocated memory */
_heap_end = __HeapLimit; /* tunable */
+
+_micropy_hw_internal_flash_storage_start = ORIGIN(FLASH_FS);
+_micropy_hw_internal_flash_storage_end = ORIGIN(FLASH_FS) + LENGTH(FLASH_FS);
diff --git a/ports/renesas-ra/boards/manifest.py b/ports/renesas-ra/boards/manifest.py
index 836bf7ccc24d..01699c3d6e6a 100644
--- a/ports/renesas-ra/boards/manifest.py
+++ b/ports/renesas-ra/boards/manifest.py
@@ -1,4 +1,4 @@
-include("$(MPY_DIR)/extmod/uasyncio/manifest.py")
-freeze("$(MPY_DIR)/drivers/dht", "dht.py")
-freeze("$(MPY_DIR)/drivers/onewire", "onewire.py")
-freeze("$(MPY_DIR)/drivers/sdcard", "sdcard.py")
+include("$(MPY_DIR)/extmod/uasyncio")
+require("dht")
+require("onewire")
+require("sdcard")
diff --git a/ports/renesas-ra/build_all_boards.sh b/ports/renesas-ra/build_all_boards.sh
index 49b1cab85d21..351047e079a0 100644
--- a/ports/renesas-ra/build_all_boards.sh
+++ b/ports/renesas-ra/build_all_boards.sh
@@ -2,8 +2,8 @@
set -eu -o pipefail
export BOARD="RA4M1_CLICKER"
DT=`date +%Y%m%d%H%M`
-make DEBUG=1 BOARD=${BOARD} clean 2>&1 | tee ${BOARD}_build_${DT}.log
-make DEBUG=1 BOARD=${BOARD} 2>&1 | tee -a ${BOARD}_build_${DT}.log
+make DEBUG=0 BOARD=${BOARD} clean 2>&1 | tee ${BOARD}_build_${DT}.log
+make DEBUG=0 BOARD=${BOARD} 2>&1 | tee -a ${BOARD}_build_${DT}.log
#
export BOARD="RA6M2_EK"
DT=`date +%Y%m%d%H%M`
@@ -12,13 +12,13 @@ make DEBUG=1 BOARD=${BOARD} 2>&1 | tee -a ${BOARD}_build_${DT}.log
#
export BOARD="RA4M1_EK"
DT=`date +%Y%m%d%H%M`
-make DEBUG=1 BOARD=${BOARD} clean 2>&1 | tee ${BOARD}_build_${DT}.log
-make DEBUG=1 BOARD=${BOARD} 2>&1 | tee -a ${BOARD}_build_${DT}.log
+make DEBUG=0 BOARD=${BOARD} clean 2>&1 | tee ${BOARD}_build_${DT}.log
+make DEBUG=0 BOARD=${BOARD} 2>&1 | tee -a ${BOARD}_build_${DT}.log
#
export BOARD="RA4W1_EK"
DT=`date +%Y%m%d%H%M`
-make DEBUG=1 BOARD=${BOARD} clean 2>&1 | tee ${BOARD}_build_${DT}.log
-make DEBUG=1 BOARD=${BOARD} 2>&1 | tee -a ${BOARD}_build_${DT}.log
+make DEBUG=0 BOARD=${BOARD} clean 2>&1 | tee ${BOARD}_build_${DT}.log
+make DEBUG=0 BOARD=${BOARD} 2>&1 | tee -a ${BOARD}_build_${DT}.log
#
export BOARD="RA6M1_EK"
DT=`date +%Y%m%d%H%M`
diff --git a/ports/renesas-ra/extint.c b/ports/renesas-ra/extint.c
index 05e99eb655b4..915c23e3cd85 100644
--- a/ports/renesas-ra/extint.c
+++ b/ports/renesas-ra/extint.c
@@ -138,8 +138,8 @@ uint extint_register(mp_obj_t pin_obj, uint32_t mode, uint32_t pull, mp_obj_t ca
mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("The Pin object(%d) doesn't have EXTINT feature"), pin_idx);
}
}
- if (pull != GPIO_NOPULL &&
- pull != GPIO_PULLUP) {
+ if ((pull != MP_HAL_PIN_PULL_NONE) &&
+ (pull != MP_HAL_PIN_PULL_UP)) {
mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid ExtInt Pull: %d"), pull);
}
mp_obj_t *cb = &MP_STATE_PORT(pyb_extint_callback)[v_line];
@@ -153,7 +153,6 @@ uint extint_register(mp_obj_t pin_obj, uint32_t mode, uint32_t pull, mp_obj_t ca
extint_disable(v_line);
*cb = callback_obj;
- // ToDo: mode should be handled
pyb_extint_mode[v_line] = mode;
pyb_extint_callback_arg[v_line] = MP_OBJ_NEW_SMALL_INT(v_line);
if (*cb != mp_const_none) {
@@ -200,7 +199,6 @@ void extint_register_pin(const machine_pin_obj_t *pin, uint32_t mode, bool hard_
extint_disable(line);
*cb = callback_obj;
- // ToDo: mode should be handled
pyb_extint_mode[line] = mode;
if (*cb != mp_const_none) {
@@ -255,16 +253,16 @@ void extint_trigger_mode(uint line, uint32_t mode) {
// cond: 0: falling, 1: rising, 2: both edge, 3 low level
// Enable or disable the rising detector
uint32_t cond = 0;
- if ((mode == GPIO_MODE_IT_RISING) || (mode == GPIO_MODE_EVT_RISING)) {
- cond = 1;
- } else if ((mode == GPIO_MODE_IT_FALLING) || (mode == GPIO_MODE_EVT_FALLING)) {
- cond = 0;
- } else if ((mode == GPIO_MODE_IT_RISING_FALLING) || (mode == GPIO_MODE_EVT_RISING_FALLING)) {
- cond = 2;
- } else if (mode == GPIO_IRQ_LOWLEVEL) {
+ if (mode & MP_HAL_PIN_TRIGGER_LOWLEVEL) {
cond = 3;
+ } else if (mode & MP_HAL_PIN_TRIGGER_FALLING) {
+ if (mode & MP_HAL_PIN_TRIGGER_RISING) {
+ cond = 2;
+ } else {
+ cond = 0;
+ }
} else {
- mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("The device doesn't have (%d) feature"), (uint32_t)mode);
+ cond = 1;
}
ra_icu_trigger_irq_no((uint8_t)line, cond);
enable_irq(irq_state);
@@ -372,25 +370,18 @@ STATIC const mp_rom_map_elem_t extint_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_disable), MP_ROM_PTR(&extint_obj_disable_obj) },
{ MP_ROM_QSTR(MP_QSTR_swint), MP_ROM_PTR(&extint_obj_swint_obj) },
{ MP_ROM_QSTR(MP_QSTR_regs), MP_ROM_PTR(&extint_regs_obj) },
-
- // class constants
- /// \constant IRQ_RISING - interrupt on a rising edge
- /// \constant IRQ_FALLING - interrupt on a falling edge
- /// \constant IRQ_RISING_FALLING - interrupt on a rising or falling edge
- { MP_ROM_QSTR(MP_QSTR_IRQ_RISING), MP_ROM_INT(GPIO_MODE_IT_RISING) },
- { MP_ROM_QSTR(MP_QSTR_IRQ_FALLING), MP_ROM_INT(GPIO_MODE_IT_FALLING) },
- { MP_ROM_QSTR(MP_QSTR_IRQ_RISING_FALLING), MP_ROM_INT(GPIO_MODE_IT_RISING_FALLING) },
};
STATIC MP_DEFINE_CONST_DICT(extint_locals_dict, extint_locals_dict_table);
-const mp_obj_type_t extint_type = {
- { &mp_type_type },
- .name = MP_QSTR_ExtInt,
- .print = extint_obj_print,
- .make_new = extint_make_new,
- .locals_dict = (mp_obj_dict_t *)&extint_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ extint_type,
+ MP_QSTR_ExtInt,
+ MP_TYPE_FLAG_NONE,
+ make_new, extint_make_new,
+ locals_dict, &extint_locals_dict,
+ print, extint_obj_print
+ );
void extint_init0(void) {
ra_icu_init();
@@ -399,3 +390,5 @@ void extint_init0(void) {
MP_STATE_PORT(pyb_extint_callback)[i] = mp_const_none;
}
}
+
+MP_REGISTER_ROOT_POINTER(mp_obj_t pyb_extint_callback[PYB_EXTI_NUM_VECTORS]);
diff --git a/ports/renesas-ra/flashbdev.c b/ports/renesas-ra/flashbdev.c
index 8fb20c66eada..3e890d31d9ca 100644
--- a/ports/renesas-ra/flashbdev.c
+++ b/ports/renesas-ra/flashbdev.c
@@ -34,65 +34,30 @@
#include "led.h"
#include "flash.h"
#include "storage.h"
-#if defined(RA4M1) | defined(RA4M3) | defined(RA4W1) | defined(RA6M1) | defined(RA6M2) | defined(RA6M3)
#include "ra_flash.h"
-#endif
#if MICROPY_HW_ENABLE_INTERNAL_FLASH_STORAGE
-// #define DEBUG_FLASH_BDEV
-
-// Here we try to automatically configure the location and size of the flash
-// pages to use for the internal storage. We also configure the location of the
-// cache used for writing.
-
-#if defined(RA4M1)
-
-STATIC byte flash_cache_mem[0x800] __attribute__((aligned(16))); // 2K
-#define CACHE_MEM_START_ADDR (&flash_cache_mem[0])
-#define FLASH_SECTOR_SIZE_MAX (0x800) // 2k max
-#define FLASH_MEM_SEG1_START_ADDR (0x37000) // sector 1
-#define FLASH_MEM_SEG1_NUM_BLOCKS (72) // sectors 1,2,...,72
+// The linker script specifies flash storage locations.
+extern uint8_t _micropy_hw_internal_flash_storage_start;
+extern uint8_t _micropy_hw_internal_flash_storage_end;
-#elif defined(RA4M3)
-STATIC byte flash_cache_mem[0x800] __attribute__((aligned(16))); // 2K
-#define CACHE_MEM_START_ADDR (&flash_cache_mem[0])
-#define FLASH_SECTOR_SIZE_MAX (0x800) // 2k max
-#define FLASH_MEM_SEG1_START_ADDR (0x37000) // sector 1
-#define FLASH_MEM_SEG1_NUM_BLOCKS (72) // sectors 1,2,...,72
+#define FLASH_MEM_SEG1_START_ADDR \
+ ((long)&_micropy_hw_internal_flash_storage_start)
+#define FLASH_MEM_SEG1_NUM_BLOCKS \
+ ((&_micropy_hw_internal_flash_storage_end - &_micropy_hw_internal_flash_storage_start) / 512)
-#elif defined(RA4W1)
-STATIC byte flash_cache_mem[0x800] __attribute__((aligned(16))); // 2K
-#define CACHE_MEM_START_ADDR (&flash_cache_mem[0])
+#if defined(RA4M1) | defined(RA4M3) | defined(RA4W1)
#define FLASH_SECTOR_SIZE_MAX (0x800) // 2k max
-#define FLASH_MEM_SEG1_START_ADDR (0x70000) // sector 1
-#define FLASH_MEM_SEG1_NUM_BLOCKS (128) // sectors 1,2,...,128
-
-#elif defined(RA6M1)
-STATIC byte flash_cache_mem[0x8000] __attribute__((aligned(16))); // 32K
-#define CACHE_MEM_START_ADDR (&flash_cache_mem[0])
-#define FLASH_SECTOR_SIZE_MAX (0x8000) // 32k max
-#define FLASH_MEM_SEG1_START_ADDR (0x60000) // sector 1
-#define FLASH_MEM_SEG1_NUM_BLOCKS (256) // sectors 1,2,...,256
-
-#elif defined(RA6M2)
-STATIC byte flash_cache_mem[0x8000] __attribute__((aligned(16))); // 32K
-#define CACHE_MEM_START_ADDR (&flash_cache_mem[0])
-#define FLASH_SECTOR_SIZE_MAX (0x8000) // 32k max
-#define FLASH_MEM_SEG1_START_ADDR (0xe0000) // sector 1
-#define FLASH_MEM_SEG1_NUM_BLOCKS (512) // sectors 1,2,...,512
-
-#elif defined(RA6M3)
-STATIC byte flash_cache_mem[0x8000] __attribute__((aligned(16))); // 32K
-#define CACHE_MEM_START_ADDR (&flash_cache_mem[0])
+#elif defined(RA6M1) | defined(RA6M2) | defined(RA6M3)
#define FLASH_SECTOR_SIZE_MAX (0x8000) // 32k max
-#define FLASH_MEM_SEG1_START_ADDR (0x60000) // sector 1
-#define FLASH_MEM_SEG1_NUM_BLOCKS (256) // sectors 1,2,...,256
-
#else
#error "no internal flash storage support for this MCU"
#endif
+STATIC byte flash_cache_mem[FLASH_SECTOR_SIZE_MAX] __attribute__((aligned(16)));
+#define CACHE_MEM_START_ADDR (&flash_cache_mem[0])
+
#if !defined(FLASH_MEM_SEG2_START_ADDR)
#define FLASH_MEM_SEG2_START_ADDR (0) // no second segment
#define FLASH_MEM_SEG2_NUM_BLOCKS (0) // no second segment
diff --git a/ports/renesas-ra/gccollect.c b/ports/renesas-ra/gccollect.c
index bd697a2af3b5..667bbc43277a 100644
--- a/ports/renesas-ra/gccollect.c
+++ b/ports/renesas-ra/gccollect.c
@@ -31,8 +31,8 @@
#include "py/gc.h"
#include "py/mpthread.h"
#include "shared/runtime/gchelper.h"
+#include "shared/runtime/softtimer.h"
#include "gccollect.h"
-#include "softtimer.h"
#include "systick.h"
void gc_collect(void) {
diff --git a/ports/renesas-ra/led.c b/ports/renesas-ra/led.c
index efc09d9de1b0..a2284c5339b9 100644
--- a/ports/renesas-ra/led.c
+++ b/ports/renesas-ra/led.c
@@ -170,13 +170,14 @@ STATIC const mp_rom_map_elem_t led_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(led_locals_dict, led_locals_dict_table);
-const mp_obj_type_t ra_led_type = {
- { &mp_type_type },
- .name = MP_QSTR_LED,
- .print = led_obj_print,
- .make_new = led_obj_make_new,
- .locals_dict = (mp_obj_dict_t *)&led_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ ra_led_type,
+ MP_QSTR_LED,
+ MP_TYPE_FLAG_NONE,
+ make_new, led_obj_make_new,
+ locals_dict, &led_locals_dict,
+ print, led_obj_print
+ );
#else
// For boards with no LEDs, we leave an empty function here so that we don't
diff --git a/ports/renesas-ra/machine_adc.c b/ports/renesas-ra/machine_adc.c
index adeebeb4c4ac..b71c3db4b025 100644
--- a/ports/renesas-ra/machine_adc.c
+++ b/ports/renesas-ra/machine_adc.c
@@ -126,10 +126,11 @@ STATIC const mp_rom_map_elem_t machine_adc_locals_dict_table[] = {
};
STATIC MP_DEFINE_CONST_DICT(machine_adc_locals_dict, machine_adc_locals_dict_table);
-const mp_obj_type_t machine_adc_type = {
- { &mp_type_type },
- .name = MP_QSTR_ADC,
- .print = machine_adc_print,
- .make_new = machine_adc_make_new,
- .locals_dict = (mp_obj_dict_t *)&machine_adc_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ machine_adc_type,
+ MP_QSTR_ADC,
+ MP_TYPE_FLAG_NONE,
+ make_new, machine_adc_make_new,
+ locals_dict, &machine_adc_locals_dict,
+ print, machine_adc_print
+ );
diff --git a/ports/renesas-ra/machine_i2c.c b/ports/renesas-ra/machine_i2c.c
index 5f385f363e6d..16bd58996498 100644
--- a/ports/renesas-ra/machine_i2c.c
+++ b/ports/renesas-ra/machine_i2c.c
@@ -150,31 +150,20 @@ STATIC int machine_i2c_transfer_single(mp_obj_base_t *self_in, uint16_t addr, si
return ret;
}
-STATIC int machine_i2c_start(mp_obj_base_t *self) {
- mp_raise_NotImplementedError(MP_ERROR_TEXT("start is not supported."));
- return 0;
-}
-
-STATIC int machine_i2c_stop(mp_obj_base_t *self) {
- mp_raise_NotImplementedError(MP_ERROR_TEXT("start is not supported."));
- return 0;
-}
-
STATIC const mp_machine_i2c_p_t machine_i2c_p = {
.init = machine_i2c_init,
.transfer = mp_machine_i2c_transfer_adaptor,
.transfer_single = machine_i2c_transfer_single,
- .start = machine_i2c_start,
- .stop = machine_i2c_stop,
};
-const mp_obj_type_t machine_i2c_type = {
- { &mp_type_type },
- .name = MP_QSTR_I2C,
- .print = machine_i2c_print,
- .make_new = machine_i2c_make_new,
- .protocol = &machine_i2c_p,
- .locals_dict = (mp_obj_dict_t *)&mp_machine_i2c_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ machine_i2c_type,
+ MP_QSTR_I2C,
+ MP_TYPE_FLAG_NONE,
+ make_new, machine_i2c_make_new,
+ locals_dict, &mp_machine_i2c_locals_dict,
+ print, machine_i2c_print,
+ protocol, &machine_i2c_p
+ );
#endif // MICROPY_HW_ENABLE_HW_I2C
diff --git a/ports/renesas-ra/machine_pin.c b/ports/renesas-ra/machine_pin.c
index 6e852e9cbf1d..0e393b64e554 100644
--- a/ports/renesas-ra/machine_pin.c
+++ b/ports/renesas-ra/machine_pin.c
@@ -78,7 +78,7 @@ STATIC void machine_pin_print(const mp_print_t *print, mp_obj_t self_in, mp_prin
uint32_t mode = pin_get_mode(self);
- if (mode == GPIO_MODE_ANALOG) {
+ if (mode == MP_HAL_PIN_MODE_ANALOG) {
// analog
mp_print_str(print, "ANALOG)");
@@ -86,15 +86,15 @@ STATIC void machine_pin_print(const mp_print_t *print, mp_obj_t self_in, mp_prin
// IO mode
bool af = false;
qstr mode_qst;
- if (mode == GPIO_MODE_INPUT) {
+ if (mode == MP_HAL_PIN_MODE_INPUT) {
mode_qst = MP_QSTR_IN;
- } else if (mode == GPIO_MODE_OUTPUT_PP) {
+ } else if (mode == MP_HAL_PIN_MODE_OUTPUT) {
mode_qst = MP_QSTR_OUT;
- } else if (mode == GPIO_MODE_OUTPUT_OD) {
+ } else if (mode == MP_HAL_PIN_MODE_OPEN_DRAIN) {
mode_qst = MP_QSTR_OPEN_DRAIN;
} else {
af = true;
- if (mode == GPIO_MODE_AF_PP) {
+ if (mode == MP_HAL_PIN_MODE_ALT) {
mode_qst = MP_QSTR_ALT;
} else {
mode_qst = MP_QSTR_ALT_OPEN_DRAIN;
@@ -105,9 +105,9 @@ STATIC void machine_pin_print(const mp_print_t *print, mp_obj_t self_in, mp_prin
// pull mode
qstr pull_qst = MP_QSTRnull;
uint32_t pull = pin_get_pull(self);
- if (pull == GPIO_PULLUP) {
+ if (pull == MP_HAL_PIN_PULL_UP) {
pull_qst = MP_QSTR_PULL_UP;
- } else if (pull == GPIO_NOPULL) {
+ } else if (pull == MP_HAL_PIN_PULL_NONE) {
pull_qst = MP_QSTR_PULL_NONE;
}
if (pull_qst != MP_QSTRnull) {
@@ -117,12 +117,14 @@ STATIC void machine_pin_print(const mp_print_t *print, mp_obj_t self_in, mp_prin
// drive
qstr drive_qst = MP_QSTRnull;
uint32_t drive = pin_get_drive(self);
- if (drive == GPIO_HIGH_POWER) {
- drive_qst = MP_QSTR_HIGH_POWER;
- } else if (drive == GPIO_MED_POWER) {
- drive_qst = MP_QSTR_MED_POWER;
- } else if (drive == GPIO_LOW_POWER) {
- drive_qst = MP_QSTR_LOW_POWER;
+ if (drive == MP_HAL_PIN_DRIVE_3) {
+ drive_qst = MP_QSTR_DRIVE_3;
+ } else if (drive == MP_HAL_PIN_DRIVE_2) {
+ drive_qst = MP_QSTR_DRIVE_2;
+ } else if (drive == MP_HAL_PIN_DRIVE_1) {
+ drive_qst = MP_QSTR_DRIVE_1;
+ } else if (drive == MP_HAL_PIN_DRIVE_0) {
+ drive_qst = MP_QSTR_DRIVE_0;
}
if (drive_qst != MP_QSTRnull) {
mp_printf(print, ", drive=Pin.%q", drive_qst);
@@ -143,14 +145,14 @@ STATIC void machine_pin_print(const mp_print_t *print, mp_obj_t self_in, mp_prin
}
}
-// pin.init(mode, pull=None, *, value=None, driver=None, alt=FUNC_SIO)
+// pin.init(mode=-1, pull=-1, *, value=None, drive=0, alt=-1)
STATIC mp_obj_t machine_pin_obj_init_helper(const machine_pin_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ enum { ARG_mode, ARG_pull, ARG_value, ARG_drive, ARG_alt };
static const mp_arg_t allowed_args[] = {
- { MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT },
+ { MP_QSTR_mode, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE}},
{ MP_QSTR_pull, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE}},
- { MP_QSTR_af, MP_ARG_INT, {.u_int = -1}}, // legacy
- { MP_QSTR_value, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL}},
- { MP_QSTR_drive, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = GPIO_LOW_POWER}},
+ { MP_QSTR_value, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE}},
+ { MP_QSTR_drive, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE}},
{ MP_QSTR_alt, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1}},
};
@@ -159,29 +161,50 @@ STATIC mp_obj_t machine_pin_obj_init_helper(const machine_pin_obj_t *self, size_
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
// get io mode
- uint mode = args[0].u_int;
- if (!IS_GPIO_MODE(mode)) {
- mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid pin mode: %d"), mode);
+ uint32_t mode;
+ if (args[ARG_mode].u_obj != mp_const_none) {
+ mode = mp_obj_get_int(args[ARG_mode].u_obj);
+ if (!IS_GPIO_MODE(mode)) {
+ mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid pin mode: %d"), mode);
+ }
+ } else {
+ mode = ra_gpio_get_mode(self->pin);
}
// get pull mode
- uint pull = 0;
- if (args[1].u_obj != mp_const_none) {
- pull = mp_obj_get_int(args[1].u_obj);
+ uint32_t pull;
+ if (args[ARG_pull].u_obj != mp_const_none) {
+ pull = mp_obj_get_int(args[ARG_pull].u_obj);
+ if (!IS_GPIO_PULL(pull)) {
+ mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid pull mode: %d"), pull);
+ }
+ if (pull == MP_HAL_PIN_PULL_DOWN) {
+ mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("%q is not supported"), MP_QSTR_PULL_DOWN);
+ }
+ } else {
+ pull = ra_gpio_get_pull(self->pin);
}
// get drive
- uint drive = args[4].u_int;
- if (!IS_GPIO_DRIVE(drive)) {
- mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid pin drive: %d"), drive);
+ uint32_t drive;
+ if (args[ARG_drive].u_obj != mp_const_none) {
+ drive = mp_obj_get_int(args[ARG_drive].u_obj);
+ if (!IS_GPIO_DRIVE(drive)) {
+ mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid pin drive: %d"), drive);
+ }
+ } else {
+ drive = ra_gpio_get_drive(self->pin);
}
- mp_hal_pin_config(self, mode, pull, drive, -1);
+ // get alt
+ if (args[ARG_alt].u_int != (-1)) {
+ mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("alt is not supported"));
+ }
+ mp_hal_pin_config(self, mode, pull, drive, 0);
// if given, set the pin value before initialising to prevent glitches
- if (args[3].u_obj != MP_OBJ_NULL) {
- mp_hal_pin_write(self, mp_obj_is_true(args[3].u_obj));
+ if (args[ARG_value].u_obj != mp_const_none) {
+ mp_hal_pin_write(self, mp_obj_is_true(args[ARG_value].u_obj));
}
-
return mp_const_none;
}
@@ -249,13 +272,17 @@ STATIC mp_obj_t machine_pin_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_
enum { ARG_handler, ARG_trigger, ARG_hard };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_handler, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
- { MP_QSTR_trigger, MP_ARG_INT, {.u_int = GPIO_MODE_IT_RISING | GPIO_MODE_IT_FALLING} },
+ { MP_QSTR_trigger, MP_ARG_INT, {.u_int = MP_HAL_PIN_TRIGGER_RISING | MP_HAL_PIN_TRIGGER_FALLING} },
{ MP_QSTR_hard, MP_ARG_BOOL, {.u_bool = false} },
};
machine_pin_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);
+ if (args[ARG_trigger].u_int & MP_HAL_PIN_TRIGGER_HIGHLEVEL) {
+ mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("%q is not supported"), MP_QSTR_IRQ_HIGH_LEVEL);
+ }
+
if (n_args > 1 || kw_args->used != 0) {
// configure irq
extint_register_pin(self, args[ARG_trigger].u_int,
@@ -282,27 +309,23 @@ STATIC const mp_rom_map_elem_t machine_pin_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_cpu), MP_ROM_PTR(&pin_cpu_pins_obj_type) },
// class constants
- { MP_ROM_QSTR(MP_QSTR_IN), MP_ROM_INT(GPIO_MODE_INPUT) },
- { MP_ROM_QSTR(MP_QSTR_OUT), MP_ROM_INT(GPIO_MODE_OUTPUT_PP) },
- { MP_ROM_QSTR(MP_QSTR_OPEN_DRAIN), MP_ROM_INT(GPIO_MODE_OUTPUT_OD) },
- { MP_ROM_QSTR(MP_QSTR_ALT), MP_ROM_INT(GPIO_MODE_AF_PP) },
- { MP_ROM_QSTR(MP_QSTR_ALT_OPEN_DRAIN), MP_ROM_INT(GPIO_MODE_AF_OD) },
- { MP_ROM_QSTR(MP_QSTR_ANALOG), MP_ROM_INT(GPIO_MODE_ANALOG) },
- { MP_ROM_QSTR(MP_QSTR_PULL_UP), MP_ROM_INT(GPIO_PULLUP) },
- { MP_ROM_QSTR(MP_QSTR_PULL_DOWN), MP_ROM_INT(GPIO_PULLDOWN) },
- { MP_ROM_QSTR(MP_QSTR_PULL_HOLD), MP_ROM_INT(GPIO_PULLHOLD) },
- { MP_ROM_QSTR(MP_QSTR_PULL_NONE), MP_ROM_INT(GPIO_NOPULL) },
- { MP_ROM_QSTR(MP_QSTR_LOW_POWER), MP_ROM_INT(GPIO_LOW_POWER) },
- { MP_ROM_QSTR(MP_QSTR_MED_POWER), MP_ROM_INT(GPIO_MED_POWER) },
- { MP_ROM_QSTR(MP_QSTR_HIGH_POWER), MP_ROM_INT(GPIO_HIGH_POWER) },
- { MP_ROM_QSTR(MP_QSTR_IRQ_RISING), MP_ROM_INT(GPIO_MODE_IT_RISING) },
- { MP_ROM_QSTR(MP_QSTR_IRQ_FALLING), MP_ROM_INT(GPIO_MODE_IT_FALLING) },
- { MP_ROM_QSTR(MP_QSTR_IRQ_RISING_FALLING), MP_ROM_INT(GPIO_MODE_IT_RISING_FALLING) },
- { MP_ROM_QSTR(MP_QSTR_EVT_RISING), MP_ROM_INT(GPIO_MODE_EVT_RISING) },
- { MP_ROM_QSTR(MP_QSTR_EVT_FALLING), MP_ROM_INT(GPIO_MODE_EVT_FALLING) },
- { MP_ROM_QSTR(MP_QSTR_EVT_RISING_FALLING), MP_ROM_INT(GPIO_MODE_EVT_RISING_FALLING) },
- { MP_ROM_QSTR(MP_QSTR_IRQ_LOWLEVEL), MP_ROM_INT(GPIO_IRQ_LOWLEVEL) },
- { MP_ROM_QSTR(MP_QSTR_IRQ_HIGHLEVEL), MP_ROM_INT(GPIO_IRQ_HIGHLEVEL) },
+ { MP_ROM_QSTR(MP_QSTR_IN), MP_ROM_INT(MP_HAL_PIN_MODE_INPUT) },
+ { MP_ROM_QSTR(MP_QSTR_OUT), MP_ROM_INT(MP_HAL_PIN_MODE_OUTPUT) },
+ { MP_ROM_QSTR(MP_QSTR_OPEN_DRAIN), MP_ROM_INT(MP_HAL_PIN_MODE_OPEN_DRAIN) },
+ { MP_ROM_QSTR(MP_QSTR_ALT), MP_ROM_INT(MP_HAL_PIN_MODE_ALT) },
+ { MP_ROM_QSTR(MP_QSTR_ALT_OPEN_DRAIN), MP_ROM_INT(MP_HAL_PIN_MODE_ALT_OPEN_DRAIN) },
+ { MP_ROM_QSTR(MP_QSTR_ANALOG), MP_ROM_INT(MP_HAL_PIN_MODE_ANALOG) },
+ { MP_ROM_QSTR(MP_QSTR_PULL_NONE), MP_ROM_INT(MP_HAL_PIN_PULL_NONE) },
+ { MP_ROM_QSTR(MP_QSTR_PULL_UP), MP_ROM_INT(MP_HAL_PIN_PULL_UP) },
+ { MP_ROM_QSTR(MP_QSTR_PULL_DOWN), MP_ROM_INT(MP_HAL_PIN_PULL_DOWN) },
+ { MP_ROM_QSTR(MP_QSTR_DRIVE_0), MP_ROM_INT(MP_HAL_PIN_DRIVE_0) },
+ { MP_ROM_QSTR(MP_QSTR_DRIVE_1), MP_ROM_INT(MP_HAL_PIN_DRIVE_1) },
+ { MP_ROM_QSTR(MP_QSTR_DRIVE_2), MP_ROM_INT(MP_HAL_PIN_DRIVE_2) },
+ { MP_ROM_QSTR(MP_QSTR_DRIVE_3), MP_ROM_INT(MP_HAL_PIN_DRIVE_3) },
+ { MP_ROM_QSTR(MP_QSTR_IRQ_FALLING), MP_ROM_INT(MP_HAL_PIN_TRIGGER_FALLING) },
+ { MP_ROM_QSTR(MP_QSTR_IRQ_RISING), MP_ROM_INT(MP_HAL_PIN_TRIGGER_RISING) },
+ { MP_ROM_QSTR(MP_QSTR_IRQ_LOW_LEVEL), MP_ROM_INT(MP_HAL_PIN_TRIGGER_LOWLEVEL) },
+ { MP_ROM_QSTR(MP_QSTR_IRQ_HIGH_LEVEL), MP_ROM_INT(MP_HAL_PIN_TRIGGER_HIGHLEVEL) },
};
STATIC MP_DEFINE_CONST_DICT(machine_pin_locals_dict, machine_pin_locals_dict_table);
@@ -326,15 +349,16 @@ STATIC const mp_pin_p_t machine_pin_pin_p = {
.ioctl = machine_pin_ioctl,
};
-const mp_obj_type_t machine_pin_type = {
- { &mp_type_type },
- .name = MP_QSTR_Pin,
- .print = machine_pin_print,
- .make_new = mp_pin_make_new,
- .call = machine_pin_call,
- .protocol = &machine_pin_pin_p,
- .locals_dict = (mp_obj_t)&machine_pin_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ machine_pin_type,
+ MP_QSTR_Pin,
+ MP_TYPE_FLAG_NONE,
+ make_new, mp_pin_make_new,
+ locals_dict, &machine_pin_locals_dict,
+ print, machine_pin_print,
+ call, machine_pin_call,
+ protocol, &machine_pin_pin_p
+ );
// Returns the pin mode. This value returned by this macro should be one of:
// GPIO_MODE_INPUT, GPIO_MODE_OUTPUT_PP, GPIO_MODE_OUTPUT_OD,
@@ -352,7 +376,8 @@ uint32_t pin_get_pull(const machine_pin_obj_t *pin) {
}
// Returns the pin drive. The value returned by this macro should
-// be one of GPIO_HIGH_POWER, GPIO_MED_POWER, or GPIO_LOW_POWER.
+// be one of GPIO_HIGH_POWER, GPIO_MID_FAST_POWER, GPIO_MID_POWER,
+// or GPIO_LOW_POWER.
uint32_t pin_get_drive(const machine_pin_obj_t *pin) {
return (uint32_t)ra_gpio_get_drive(pin->pin);
@@ -364,17 +389,19 @@ uint32_t pin_get_af(const machine_pin_obj_t *pin) {
return (uint32_t)ra_gpio_get_af(pin->pin);
}
-const mp_obj_type_t pin_cpu_pins_obj_type = {
- { &mp_type_type },
- .name = MP_QSTR_cpu,
- .locals_dict = (mp_obj_dict_t *)&pin_cpu_pins_locals_dict,
-};
-
-const mp_obj_type_t pin_board_pins_obj_type = {
- { &mp_type_type },
- .name = MP_QSTR_board,
- .locals_dict = (mp_obj_dict_t *)&pin_board_pins_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ pin_cpu_pins_obj_type,
+ MP_QSTR_cpu,
+ MP_TYPE_FLAG_NONE,
+ locals_dict, &pin_cpu_pins_locals_dict
+ );
+
+MP_DEFINE_CONST_OBJ_TYPE(
+ pin_board_pins_obj_type,
+ MP_QSTR_board,
+ MP_TYPE_FLAG_NONE,
+ locals_dict, &pin_board_pins_locals_dict
+ );
const machine_pin_obj_t *pin_find_named_pin(const mp_obj_dict_t *named_pins, mp_obj_t name) {
const mp_map_t *named_map = &named_pins->map;
diff --git a/ports/renesas-ra/machine_rtc.c b/ports/renesas-ra/machine_rtc.c
index 9ddc90213774..e699bea0bcc0 100644
--- a/ports/renesas-ra/machine_rtc.c
+++ b/ports/renesas-ra/machine_rtc.c
@@ -341,9 +341,10 @@ STATIC const mp_rom_map_elem_t machine_rtc_locals_dict_table[] = {
};
STATIC MP_DEFINE_CONST_DICT(machine_rtc_locals_dict, machine_rtc_locals_dict_table);
-const mp_obj_type_t machine_rtc_type = {
- { &mp_type_type },
- .name = MP_QSTR_RTC,
- .make_new = machine_rtc_make_new,
- .locals_dict = (mp_obj_dict_t *)&machine_rtc_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ machine_rtc_type,
+ MP_QSTR_RTC,
+ MP_TYPE_FLAG_NONE,
+ make_new, machine_rtc_make_new,
+ locals_dict, &machine_rtc_locals_dict
+ );
diff --git a/ports/renesas-ra/machine_spi.c b/ports/renesas-ra/machine_spi.c
index 01972ad45761..2c71c83b666c 100644
--- a/ports/renesas-ra/machine_spi.c
+++ b/ports/renesas-ra/machine_spi.c
@@ -70,7 +70,7 @@ typedef struct _machine_hard_spi_obj_t {
STATIC machine_hard_spi_obj_t machine_hard_spi_obj[] = {
#if defined(MICROPY_HW_SPI0_RSPCK)
{
- {&machine_hard_spi_type}, 0,
+ {&machine_spi_type}, 0,
DEFAULT_SPI_POLARITY, DEFAULT_SPI_PHASE, DEFAULT_SPI_BITS,
DEFAULT_SPI_FIRSTBIT, DEFAULT_SPI_BAUDRATE,
MICROPY_HW_SPI0_RSPCK, MICROPY_HW_SPI0_MOSI, MICROPY_HW_SPI0_MISO,
@@ -78,7 +78,7 @@ STATIC machine_hard_spi_obj_t machine_hard_spi_obj[] = {
#endif
#if defined(MICROPY_HW_SPI1_RSPCK)
{
- {&machine_hard_spi_type}, 1,
+ {&machine_spi_type}, 1,
DEFAULT_SPI_POLARITY, DEFAULT_SPI_PHASE, DEFAULT_SPI_BITS,
DEFAULT_SPI_FIRSTBIT, DEFAULT_SPI_BAUDRATE,
MICROPY_HW_SPI1_RSPCK, MICROPY_HW_SPI1_MOSI, MICROPY_HW_SPI1_MISO,
@@ -297,14 +297,15 @@ STATIC const mp_machine_spi_p_t machine_hard_spi_p = {
.transfer = machine_hard_spi_transfer,
};
-const mp_obj_type_t machine_hard_spi_type = {
- { &mp_type_type },
- .name = MP_QSTR_SPI,
- .print = machine_hard_spi_print,
- .make_new = machine_hard_spi_make_new,
- .protocol = &machine_hard_spi_p,
- .locals_dict = (mp_obj_dict_t *)&mp_machine_spi_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ machine_spi_type,
+ MP_QSTR_SPI,
+ MP_TYPE_FLAG_NONE,
+ make_new, machine_hard_spi_make_new,
+ locals_dict, &mp_machine_spi_locals_dict,
+ print, machine_hard_spi_print,
+ protocol, &machine_hard_spi_p
+ );
void spi_init0(void) {
}
diff --git a/ports/renesas-ra/machine_timer.c b/ports/renesas-ra/machine_timer.c
deleted file mode 100644
index c94532218773..000000000000
--- a/ports/renesas-ra/machine_timer.c
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * 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.
- */
-
-#include "py/runtime.h"
-#include "py/mphal.h"
-#include "softtimer.h"
-
-typedef soft_timer_entry_t machine_timer_obj_t;
-
-const mp_obj_type_t machine_timer_type;
-
-STATIC void machine_timer_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
- machine_timer_obj_t *self = MP_OBJ_TO_PTR(self_in);
- qstr mode = self->mode == SOFT_TIMER_MODE_ONE_SHOT ? MP_QSTR_ONE_SHOT : MP_QSTR_PERIODIC;
- mp_printf(print, "Timer(mode=%q, period=%u)", mode, self->delta_ms);
-}
-
-STATIC mp_obj_t machine_timer_init_helper(machine_timer_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
- enum { ARG_mode, ARG_callback, ARG_period, ARG_tick_hz, ARG_freq, };
- static const mp_arg_t allowed_args[] = {
- { MP_QSTR_mode, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = SOFT_TIMER_MODE_PERIODIC} },
- { MP_QSTR_callback, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
- { MP_QSTR_period, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0xffffffff} },
- { MP_QSTR_tick_hz, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1000} },
- { MP_QSTR_freq, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
- };
-
- // Parse args
- mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
- mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
-
- self->mode = args[ARG_mode].u_int;
-
- uint64_t delta_ms = self->delta_ms;
- if (args[ARG_freq].u_obj != mp_const_none) {
- // Frequency specified in Hz
- #if MICROPY_PY_BUILTINS_FLOAT
- delta_ms = (uint32_t)(MICROPY_FLOAT_CONST(1000.0) / mp_obj_get_float(args[ARG_freq].u_obj));
- #else
- delta_ms = 1000 / mp_obj_get_int(args[ARG_freq].u_obj);
- #endif
- } else if (args[ARG_period].u_int != 0xffffffff) {
- // Period specified
- delta_ms = (uint64_t)args[ARG_period].u_int * 1000 / args[ARG_tick_hz].u_int;
- }
-
- if (delta_ms < 1) {
- delta_ms = 1;
- } else if (delta_ms >= 0x40000000) {
- mp_raise_ValueError(MP_ERROR_TEXT("period too large"));
- }
- self->delta_ms = (uint32_t)delta_ms;
-
- if (args[ARG_callback].u_obj != MP_OBJ_NULL) {
- self->py_callback = args[ARG_callback].u_obj;
- }
-
- if (self->py_callback != mp_const_none) {
- soft_timer_insert(self, self->delta_ms);
- }
-
- return mp_const_none;
-}
-
-STATIC mp_obj_t machine_timer_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
- machine_timer_obj_t *self = m_new_obj(machine_timer_obj_t);
- self->pairheap.base.type = &machine_timer_type;
- self->flags = SOFT_TIMER_FLAG_PY_CALLBACK | SOFT_TIMER_FLAG_GC_ALLOCATED;
- self->delta_ms = 1000;
- self->py_callback = mp_const_none;
-
- // Get timer id (only soft timer (-1) supported at the moment)
- mp_int_t id = -1;
- if (n_args > 0) {
- id = mp_obj_get_int(args[0]);
- --n_args;
- ++args;
- }
- if (id != -1) {
- mp_raise_ValueError(MP_ERROR_TEXT("Timer doesn't exist"));
- }
-
- if (n_args > 0 || n_kw > 0) {
- // Start the timer
- mp_map_t kw_args;
- mp_map_init_fixed_table(&kw_args, n_kw, args + n_args);
- machine_timer_init_helper(self, n_args, args, &kw_args);
- }
-
- return MP_OBJ_FROM_PTR(self);
-}
-
-STATIC mp_obj_t machine_timer_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
- machine_timer_obj_t *self = MP_OBJ_TO_PTR(args[0]);
- soft_timer_remove(self);
- return machine_timer_init_helper(self, n_args - 1, args + 1, kw_args);
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_timer_init_obj, 1, machine_timer_init);
-
-STATIC mp_obj_t machine_timer_deinit(mp_obj_t self_in) {
- machine_timer_obj_t *self = MP_OBJ_TO_PTR(self_in);
- soft_timer_remove(self);
- return mp_const_none;
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_timer_deinit_obj, machine_timer_deinit);
-
-STATIC const mp_rom_map_elem_t machine_timer_locals_dict_table[] = {
- { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_timer_init_obj) },
- { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_timer_deinit_obj) },
-
- { MP_ROM_QSTR(MP_QSTR_ONE_SHOT), MP_ROM_INT(SOFT_TIMER_MODE_ONE_SHOT) },
- { MP_ROM_QSTR(MP_QSTR_PERIODIC), MP_ROM_INT(SOFT_TIMER_MODE_PERIODIC) },
-};
-STATIC MP_DEFINE_CONST_DICT(machine_timer_locals_dict, machine_timer_locals_dict_table);
-
-const mp_obj_type_t machine_timer_type = {
- { &mp_type_type },
- .name = MP_QSTR_Timer,
- .print = machine_timer_print,
- .make_new = machine_timer_make_new,
- .locals_dict = (mp_obj_dict_t *)&machine_timer_locals_dict,
-};
diff --git a/ports/renesas-ra/machine_uart.c b/ports/renesas-ra/machine_uart.c
index d71562f2018b..f365223afaba 100644
--- a/ports/renesas-ra/machine_uart.c
+++ b/ports/renesas-ra/machine_uart.c
@@ -409,6 +409,14 @@ STATIC mp_obj_t machine_uart_sendbreak(mp_obj_t self_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_uart_sendbreak_obj, machine_uart_sendbreak);
+// \method uart.txdone()
+// Return `True` if all characters have been sent.
+STATIC mp_obj_t machine_uart_txdone(mp_obj_t self_in) {
+ machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ return uart_tx_busy(self) ? mp_const_false : mp_const_true;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_uart_txdone_obj, machine_uart_txdone);
+
// irq(handler, trigger, hard)
STATIC mp_obj_t machine_uart_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
mp_arg_val_t args[MP_IRQ_ARG_INIT_NUM_ARGS];
@@ -452,6 +460,8 @@ STATIC const mp_rom_map_elem_t machine_uart_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_uart_init_obj) },
{ MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_uart_deinit_obj) },
{ MP_ROM_QSTR(MP_QSTR_any), MP_ROM_PTR(&machine_uart_any_obj) },
+ { MP_ROM_QSTR(MP_QSTR_txdone), MP_ROM_PTR(&machine_uart_txdone_obj) },
+ { MP_ROM_QSTR(MP_QSTR_flush), MP_ROM_PTR(&mp_stream_flush_obj) },
/// \method read([nbytes])
{ MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) },
@@ -557,6 +567,19 @@ STATIC mp_uint_t machine_uart_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr
if ((flags & MP_STREAM_POLL_WR) && uart_tx_avail(self)) {
ret |= MP_STREAM_POLL_WR;
}
+ } else if (request == MP_STREAM_FLUSH) {
+ // The timeout is estimated using the buffer size and the baudrate.
+ // Take the worst case assumptions at 13 bit symbol size times 2.
+ uint32_t timeout = mp_hal_ticks_ms() +
+ (uint32_t)(uart_tx_txbuf(self)) * 13000ll * 2 / self->baudrate;
+ do {
+ if (!uart_tx_busy(self)) {
+ return 0;
+ }
+ MICROPY_EVENT_POLL_HOOK
+ } while (mp_hal_ticks_ms() < timeout);
+ *errcode = MP_ETIMEDOUT;
+ ret = MP_STREAM_ERROR;
} else {
*errcode = MP_EINVAL;
ret = MP_STREAM_ERROR;
@@ -571,13 +594,14 @@ STATIC const mp_stream_p_t uart_stream_p = {
.is_text = false,
};
-const mp_obj_type_t machine_uart_type = {
- { &mp_type_type },
- .name = MP_QSTR_UART,
- .print = machine_uart_print,
- .make_new = machine_uart_make_new,
- .getiter = mp_identity_getiter,
- .iternext = mp_stream_unbuffered_iter,
- .protocol = &uart_stream_p,
- .locals_dict = (mp_obj_dict_t *)&machine_uart_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ machine_uart_type,
+ MP_QSTR_UART,
+ MP_TYPE_FLAG_ITER_IS_STREAM,
+ make_new, machine_uart_make_new,
+ locals_dict, &machine_uart_locals_dict,
+ print, machine_uart_print,
+ protocol, &uart_stream_p
+ );
+
+MP_REGISTER_ROOT_POINTER(struct _machine_uart_obj_t *machine_uart_obj_all[MICROPY_HW_MAX_UART + MICROPY_HW_MAX_LPUART]);
diff --git a/ports/renesas-ra/main.c b/ports/renesas-ra/main.c
index 6f4584b6856d..6ba26cd7baba 100644
--- a/ports/renesas-ra/main.c
+++ b/ports/renesas-ra/main.c
@@ -35,6 +35,7 @@
#include "py/mphal.h"
#include "shared/readline/readline.h"
#include "shared/runtime/pyexec.h"
+#include "shared/runtime/softtimer.h"
#include "lib/oofatfs/ff.h"
#include "lib/littlefs/lfs1.h"
#include "lib/littlefs/lfs1_util.h"
@@ -52,7 +53,6 @@
#include "gccollect.h"
#include "factoryreset.h"
#include "modmachine.h"
-#include "softtimer.h"
#include "spi.h"
#include "uart.h"
#include "timer.h"
@@ -182,7 +182,7 @@ MP_NOINLINE STATIC bool init_flash_fs(uint reset_mode) {
if (len != -1) {
// Detected a littlefs filesystem so create correct block device for it
mp_obj_t args[] = { MP_OBJ_NEW_QSTR(MP_QSTR_len), MP_OBJ_NEW_SMALL_INT(len) };
- bdev = pyb_flash_type.make_new(&pyb_flash_type, 0, 1, args);
+ bdev = MP_OBJ_TYPE_GET_SLOT(&pyb_flash_type, make_new)(&pyb_flash_type, 0, 1, args);
}
#endif
@@ -325,7 +325,7 @@ void ra_main(uint32_t reset_mode) {
// Run optional frozen boot code.
#ifdef MICROPY_BOARD_FROZEN_BOOT_FILE
- pyexec_frozen_module(MICROPY_BOARD_FROZEN_BOOT_FILE);
+ pyexec_frozen_module(MICROPY_BOARD_FROZEN_BOOT_FILE, false);
#endif
// Run boot.py (or whatever else a board configures at this stage).
@@ -397,3 +397,5 @@ void ra_main(uint32_t reset_mode) {
goto soft_reset;
}
+
+MP_REGISTER_ROOT_POINTER(mp_obj_t pyb_config_main);
diff --git a/ports/renesas-ra/modmachine.c b/ports/renesas-ra/modmachine.c
index cd6e750340cf..ecb028983c6c 100644
--- a/ports/renesas-ra/modmachine.c
+++ b/ports/renesas-ra/modmachine.c
@@ -47,6 +47,7 @@
#include "gccollect.h"
#include "irq.h"
#include "powerctrl.h"
+#include "boardctrl.h"
#include "pybthread.h"
#include "storage.h"
#include "pin.h"
@@ -153,7 +154,7 @@ STATIC mp_obj_t machine_info(size_t n_args, const mp_obj_t *args) {
if (n_args == 1) {
// arg given means dump gc allocation table
- gc_dump_alloc_table();
+ gc_dump_alloc_table(&mp_plat_print);
}
return mp_const_none;
@@ -182,13 +183,15 @@ STATIC mp_obj_t machine_soft_reset(void) {
MP_DEFINE_CONST_FUN_OBJ_0(machine_soft_reset_obj, machine_soft_reset);
// Activate the bootloader without BOOT* pins.
-STATIC NORETURN mp_obj_t machine_bootloader(size_t n_args, const mp_obj_t *args) {
+NORETURN mp_obj_t machine_bootloader(size_t n_args, const mp_obj_t *args) {
#if MICROPY_HW_ENABLE_STORAGE
storage_flush();
#endif
__disable_irq();
+ MICROPY_BOARD_ENTER_BOOTLOADER(n_args, args);
+
#if MICROPY_HW_USES_BOOTLOADER
// ToDo: need to review how to implement
@@ -283,7 +286,7 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_SoftI2C), MP_ROM_PTR(&mp_machine_soft_i2c_type) },
#endif
#if MICROPY_PY_MACHINE_SPI
- { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&machine_hard_spi_type) },
+ { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&machine_spi_type) },
{ MP_ROM_QSTR(MP_QSTR_SoftSPI), MP_ROM_PTR(&mp_machine_soft_spi_type) },
#endif
{ MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&machine_uart_type) },
diff --git a/ports/renesas-ra/modmachine.h b/ports/renesas-ra/modmachine.h
index 65077220df5e..5dbda6bda8ae 100644
--- a/ports/renesas-ra/modmachine.h
+++ b/ports/renesas-ra/modmachine.h
@@ -37,7 +37,7 @@ extern const mp_obj_type_t machine_adc_type;
extern const mp_obj_type_t machine_adcblock_type;
extern const mp_obj_type_t machine_dac_type;
extern const mp_obj_type_t machine_i2c_type;
-extern const mp_obj_type_t machine_hard_spi_type;
+extern const mp_obj_type_t machine_spi_type;
extern const mp_obj_type_t machine_i2s_type;
extern const mp_obj_type_t machine_uart_type;
extern const mp_obj_type_t machine_rtc_type;
@@ -49,6 +49,7 @@ void machine_deinit(void);
void machine_pin_init(void);
void machine_pin_deinit(void);
void machine_i2s_init0(void);
+NORETURN mp_obj_t machine_bootloader(size_t n_args, const mp_obj_t *args);
MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(machine_info_obj);
MP_DECLARE_CONST_FUN_OBJ_0(machine_unique_id_obj);
diff --git a/ports/renesas-ra/mpconfigport.h b/ports/renesas-ra/mpconfigport.h
index 64caa69fd26a..6d40ac8fac48 100644
--- a/ports/renesas-ra/mpconfigport.h
+++ b/ports/renesas-ra/mpconfigport.h
@@ -83,7 +83,6 @@
#ifndef MICROPY_PY_BUILTINS_HELP_TEXT
#define MICROPY_PY_BUILTINS_HELP_TEXT ra_help_text
#endif
-#define MICROPY_PY_IO_FILEIO (MICROPY_VFS_FAT || MICROPY_VFS_LFS1 || MICROPY_VFS_LFS2)
#ifndef MICROPY_PY_SYS_PLATFORM // let boards override it if they want
#define MICROPY_PY_SYS_PLATFORM "renesas-ra"
#endif
@@ -120,6 +119,8 @@
#define MICROPY_PY_MACHINE_SPI_MSB (SPI_FIRSTBIT_MSB)
#define MICROPY_PY_MACHINE_SPI_LSB (SPI_FIRSTBIT_LSB)
#define MICROPY_PY_MACHINE_SOFTSPI (1)
+#define MICROPY_PY_MACHINE_TIMER (1)
+#define MICROPY_SOFT_TIMER_TICKS_MS uwTick
#endif
#define MICROPY_HW_SOFTSPI_MIN_DELAY (0)
#define MICROPY_HW_SOFTSPI_MAX_BAUDRATE (48000000 / 48)
@@ -137,18 +138,6 @@
#define MICROPY_FATFS_RPATH (2)
#define MICROPY_FATFS_MULTI_PARTITION (1)
-// TODO these should be generic, not bound to a particular FS implementation
-#if MICROPY_VFS_FAT
-#define mp_type_fileio mp_type_vfs_fat_fileio
-#define mp_type_textio mp_type_vfs_fat_textio
-#elif MICROPY_VFS_LFS1
-#define mp_type_fileio mp_type_vfs_lfs1_fileio
-#define mp_type_textio mp_type_vfs_lfs1_textio
-#elif MICROPY_VFS_LFS2
-#define mp_type_fileio mp_type_vfs_lfs2_fileio
-#define mp_type_textio mp_type_vfs_lfs2_textio
-#endif
-
#if MICROPY_PY_MACHINE
#define MACHINE_BUILTIN_MODULE_CONSTANTS \
{ MP_ROM_QSTR(MP_QSTR_umachine), MP_ROM_PTR(&mp_module_machine) }, \
@@ -163,38 +152,6 @@
#define MP_STATE_PORT MP_STATE_VM
-#ifndef MICROPY_BOARD_ROOT_POINTERS
-#define MICROPY_BOARD_ROOT_POINTERS
-#endif
-
-#define MICROPY_PORT_ROOT_POINTERS \
- const char *readline_hist[8]; \
- \
- mp_obj_t pyb_hid_report_desc; \
- \
- mp_obj_t pyb_config_main; \
- \
- mp_obj_t pyb_switch_callback; \
- \
- mp_obj_t pyb_extint_callback[PYB_EXTI_NUM_VECTORS]; \
- \
- /* pointers to all Timer objects (if they have been created) */ \
- struct _pyb_timer_obj_t *pyb_timer_obj_all[MICROPY_HW_MAX_TIMER]; \
- \
- /* stdio is repeated on this UART object if it's not null */ \
- struct _machine_uart_obj_t *pyb_stdio_uart; \
- \
- /* pointers to all UART objects (if they have been created) */ \
- struct _machine_uart_obj_t *machine_uart_obj_all[MICROPY_HW_MAX_UART + MICROPY_HW_MAX_LPUART]; \
- \
- /* list of registered NICs */ \
- /* mp_obj_list_t mod_network_nic_list; */ \
- \
- /* root pointers for sub-systems */ \
- \
- /* root pointers defined by a board */ \
- MICROPY_BOARD_ROOT_POINTERS \
-
// type definitions for the specific machine
#define MICROPY_MAKE_POINTER_CALLABLE(p) ((void *)((uint32_t)(p) | 1))
diff --git a/ports/renesas-ra/mphalport.c b/ports/renesas-ra/mphalport.c
index 6a416f431adb..6e6a83aa2648 100644
--- a/ports/renesas-ra/mphalport.c
+++ b/ports/renesas-ra/mphalport.c
@@ -118,3 +118,5 @@ void mp_hal_get_mac_ascii(int idx, size_t chr_off, size_t chr_len, char *dest) {
*dest++ = hexchr[mac[chr_off >> 1] >> (4 * (1 - (chr_off & 1))) & 0xf];
}
}
+
+MP_REGISTER_ROOT_POINTER(struct _machine_uart_obj_t *pyb_stdio_uart);
diff --git a/ports/renesas-ra/mphalport.h b/ports/renesas-ra/mphalport.h
index c489d1b966a7..2648e22f994c 100644
--- a/ports/renesas-ra/mphalport.h
+++ b/ports/renesas-ra/mphalport.h
@@ -4,7 +4,7 @@
* The MIT License (MIT)
*
* Copyright (c) 2018 Damien P. George
- * Copyright (c) 2021 Renesas Electronics Corporation
+ * Copyright (c) 2021-2022 Renesas Electronics Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -69,13 +69,21 @@ static inline mp_uint_t mp_hal_ticks_cpu(void) {
#define MP_HAL_PIN_PULL_NONE (GPIO_NOPULL)
#define MP_HAL_PIN_PULL_UP (GPIO_PULLUP)
#define MP_HAL_PIN_PULL_DOWN (GPIO_PULLDOWN)
+#define MP_HAL_PIN_TRIGGER_FALLING (GPIO_IRQ_FALLING)
+#define MP_HAL_PIN_TRIGGER_RISING (GPIO_IRQ_RISING)
+#define MP_HAL_PIN_TRIGGER_LOWLEVEL (GPIO_IRQ_LOWLEVEL)
+#define MP_HAL_PIN_TRIGGER_HIGHLEVEL (GPIO_IRQ_HIGHLEVEL)
+#define MP_HAL_PIN_DRIVE_0 (GPIO_LOW_POWER)
+#define MP_HAL_PIN_DRIVE_1 (GPIO_MID_POWER)
+#define MP_HAL_PIN_DRIVE_2 (GPIO_MID_FAST_POWER)
+#define MP_HAL_PIN_DRIVE_3 (GPIO_HIGH_POWER)
#define mp_hal_pin_obj_t const machine_pin_obj_t *
#define mp_hal_get_pin_obj(o) machine_pin_find(o)
#define mp_hal_pin_name(p) ((p)->name)
#define mp_hal_pin_input(p) ra_gpio_mode_input((p)->pin)
#define mp_hal_pin_output(p) ra_gpio_mode_output((p)->pin)
-#define mp_hal_pin_open_drain(p) ra_gpio_config((p)->pin, GPIO_MODE_OUTPUT_OD, 0, 0, 0)
+#define mp_hal_pin_open_drain(p) ra_gpio_config((p)->pin, MP_HAL_PIN_MODE_OPEN_DRAIN, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_DRIVE_0, 0)
#define mp_hal_pin_high(p) ra_gpio_write((p)->pin, 1)
#define mp_hal_pin_low(p) ra_gpio_write((p)->pin, 0)
#define mp_hal_pin_toggle(p) ra_gpio_toggle((p)->pin)
diff --git a/ports/renesas-ra/ra/ra_gpio.c b/ports/renesas-ra/ra/ra_gpio.c
index 598546cb9349..a01131953c1f 100644
--- a/ports/renesas-ra/ra/ra_gpio.c
+++ b/ports/renesas-ra/ra/ra_gpio.c
@@ -31,23 +31,17 @@ void ra_gpio_config(uint32_t pin, uint32_t mode, uint32_t pull, uint32_t drive,
uint32_t port = GPIO_PORT(pin);
uint32_t bit = GPIO_BIT(pin);
pwpr_unprotect();
+ _PXXPFS(port, bit) &= ~(PMR_MASK | ASEL_MASK | NCODR_MASK | PCR_MASK | PDR_MASK | DSCR1_MASK | DSCR_MASK);
switch (mode) {
case GPIO_MODE_INPUT:
- _PXXPFS(port, bit) &= ~(PMR_MASK | ASEL_MASK); // GPIO
- _PXXPFS(port, bit) &= ~PDR_MASK; // input
- if (pull != 0) {
+ if (pull == GPIO_PULLUP) {
_PXXPFS(port, bit) |= PCR_MASK; // set pullup
- } else {
- _PXXPFS(port, bit) &= ~PCR_MASK; // clear pullup
}
break;
case GPIO_MODE_OUTPUT_PP:
- _PXXPFS(port, bit) &= ~(PMR_MASK | ASEL_MASK); // GPIO
_PXXPFS(port, bit) |= PDR_MASK; // output
- _PXXPFS(port, bit) &= ~PCR_MASK; // pullup clear
break;
case GPIO_MODE_OUTPUT_OD:
- _PXXPFS(port, bit) &= ~(PMR_MASK | ASEL_MASK); // GPIO
_PXXPFS(port, bit) |= (PDR_MASK | NCODR_MASK);
break;
case GPIO_MODE_AF_PP:
@@ -56,20 +50,23 @@ void ra_gpio_config(uint32_t pin, uint32_t mode, uint32_t pull, uint32_t drive,
case GPIO_MODE_AF_OD:
_PXXPFS(port, bit) |= (PMR_MASK | PDR_MASK | NCODR_MASK);
break;
+ case GPIO_MODE_ANALOG:
+ _PXXPFS(port, bit) |= ASEL_MASK;
+ break;
}
switch (drive) {
case GPIO_HIGH_POWER:
_PXXPFS(port, bit) |= (DSCR1_MASK | DSCR_MASK);
break;
- case GPIO_MED_POWER:
- _PXXPFS(port, bit) &= ~DSCR1_MASK;
+ case GPIO_MID_FAST_POWER:
+ _PXXPFS(port, bit) |= DSCR1_MASK;
+ break;
+ case GPIO_MID_POWER:
_PXXPFS(port, bit) |= DSCR_MASK;
break;
case GPIO_LOW_POWER:
- _PXXPFS(port, bit) &= ~(DSCR1_MASK | DSCR_MASK);
- break;
- default: /* GPIO_NOTOUCH_POWER */
- /* do not modify */
+ default:
+ /* Bits are already cleared */
break;
}
_PXXPFS(port, bit) &= ~(uint32_t)(0x1f000000);
@@ -102,7 +99,6 @@ void ra_gpio_toggle(uint32_t pin) {
uint32_t port = GPIO_PORT(pin);
uint32_t bit = GPIO_BIT(pin);
pwpr_unprotect();
- _PXXPFS(port, bit) &= ~(PMR_MASK | ASEL_MASK); // GPIO
_PXXPFS(port, bit) ^= 1;
pwpr_protect();
}
@@ -111,7 +107,6 @@ void ra_gpio_write(uint32_t pin, uint32_t value) {
uint32_t port = GPIO_PORT(pin);
uint32_t bit = GPIO_BIT(pin);
pwpr_unprotect();
- _PXXPFS(port, bit) &= ~(PMR_MASK | ASEL_MASK); // GPIO
if (value != 0) {
_PXXPFS(port, bit) |= 1;
} else {
@@ -123,15 +118,26 @@ void ra_gpio_write(uint32_t pin, uint32_t value) {
uint32_t ra_gpio_read(uint32_t pin) {
uint32_t port = GPIO_PORT(pin);
uint32_t bit = GPIO_BIT(pin);
- return ((_PXXPFS(port, bit) &= PIDR_MASK) != 0) ? 1 : 0;
+ return ((_PXXPFS(port, bit) & PIDR_MASK) != 0) ? 1 : 0;
}
uint32_t ra_gpio_get_mode(uint32_t pin) {
uint8_t mode = 0;
- uint32_t port = GPIO_PORT(pin);
- uint32_t bit = GPIO_BIT(pin);
- if ((_PXXPFS(port, bit) &= PDR_MASK) != 0) {
- mode = GPIO_MODE_OUTPUT_PP;
+ uint32_t pfs = _PXXPFS(GPIO_PORT(pin), GPIO_BIT(pin));
+ if ((pfs & ASEL_MASK) != 0) {
+ mode = GPIO_MODE_ANALOG;
+ } else if ((pfs & PMR_MASK) != 0) {
+ if ((pfs & NCODR_MASK) != 0) {
+ mode = GPIO_MODE_AF_OD;
+ } else {
+ mode = GPIO_MODE_AF_PP;
+ }
+ } else if ((pfs & PDR_MASK) != 0) {
+ if ((pfs & NCODR_MASK) != 0) {
+ mode = GPIO_MODE_OUTPUT_OD;
+ } else {
+ mode = GPIO_MODE_OUTPUT_PP;
+ }
} else {
mode = GPIO_MODE_INPUT;
}
@@ -142,7 +148,7 @@ uint32_t ra_gpio_get_pull(uint32_t pin) {
uint8_t pull = 0;
uint32_t port = GPIO_PORT(pin);
uint32_t bit = GPIO_BIT(pin);
- if ((_PXXPFS(port, bit) &= PCR_MASK) != 0) {
+ if ((_PXXPFS(port, bit) & PCR_MASK) != 0) {
pull = GPIO_PULLUP;
} else {
pull = GPIO_NOPULL;
@@ -153,19 +159,22 @@ uint32_t ra_gpio_get_pull(uint32_t pin) {
uint32_t ra_gpio_get_af(uint32_t pin) {
uint32_t port = GPIO_PORT(pin);
uint32_t bit = GPIO_BIT(pin);
- return (_PXXPFS(port, bit) &= PMR_MASK) != 0;
+ return (_PXXPFS(port, bit) & PMR_MASK) != 0;
}
uint32_t ra_gpio_get_drive(uint32_t pin) {
uint8_t drive = 0;
uint32_t port = GPIO_PORT(pin);
uint32_t bit = GPIO_BIT(pin);
- switch (_PXXPFS(port, bit) &= (DSCR1_MASK | DSCR_MASK)) {
+ switch (_PXXPFS(port, bit) & (DSCR1_MASK | DSCR_MASK)) {
case (DSCR1_MASK | DSCR_MASK):
drive = GPIO_HIGH_POWER;
break;
+ case DSCR1_MASK:
+ drive = GPIO_MID_FAST_POWER;
+ break;
case DSCR_MASK:
- drive = GPIO_MED_POWER;
+ drive = GPIO_MID_POWER;
break;
case 0:
default:
diff --git a/ports/renesas-ra/ra/ra_gpio.h b/ports/renesas-ra/ra/ra_gpio.h
index 7b7601663534..8c16fe3ba18c 100644
--- a/ports/renesas-ra/ra/ra_gpio.h
+++ b/ports/renesas-ra/ra/ra_gpio.h
@@ -1,7 +1,7 @@
/*
* The MIT License (MIT)
*
- * Copyright (c) 2021 Renesas Electronics Corporation
+ * Copyright (c) 2021,2022 Renesas Electronics Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -69,47 +69,42 @@ enum AF_INDEX {
AF_END = 0xff,
};
-#define GPIO_MODE_INPUT 1
-#define GPIO_MODE_OUTPUT_PP 2
-#define GPIO_MODE_OUTPUT_OD 3
-#define GPIO_MODE_AF_PP 4
-#define GPIO_MODE_AF_OD 5
-#define GPIO_MODE_ANALOG 6
-#define GPIO_MODE_IT_RISING 7
-#define GPIO_MODE_IT_FALLING 8
-#define GPIO_MODE_IT_RISING_FALLING 9
-#define GPIO_MODE_EVT_RISING 10
-#define GPIO_MODE_EVT_FALLING 11
-#define GPIO_MODE_EVT_RISING_FALLING 12
-#define GPIO_NOPULL 13
-#define GPIO_PULLUP 14
-#define GPIO_PULLDOWN 15
-#define GPIO_PULLHOLD 16
-#define GPIO_LOW_POWER 17
-#define GPIO_MED_POWER 18
-#define GPIO_HIGH_POWER 19
-#define GPIO_NOTOUCH_POWER 20
-#define GPIO_IRQ_LOWLEVEL 21
-#define GPIO_IRQ_HIGHLEVEL 22
+#define GPIO_MODE_INPUT 0
+#define GPIO_MODE_OUTPUT_PP 1
+#define GPIO_MODE_OUTPUT_OD 2
+#define GPIO_MODE_AF_PP 3
+#define GPIO_MODE_AF_OD 4
+#define GPIO_MODE_ANALOG 5
+
+#define GPIO_IRQ_FALLING 0x1
+#define GPIO_IRQ_RISING 0x2
+#define GPIO_IRQ_LOWLEVEL 0x4
+#define GPIO_IRQ_HIGHLEVEL 0x8
+
+#define GPIO_NOPULL 0
+#define GPIO_PULLUP 1
+#define GPIO_PULLDOWN 2
+
+#define GPIO_LOW_POWER 0
+#define GPIO_MID_POWER 1
+#define GPIO_MID_FAST_POWER 2
+#define GPIO_HIGH_POWER 3
#define IS_GPIO_MODE(MODE) (((MODE) == GPIO_MODE_INPUT) || \
((MODE) == GPIO_MODE_OUTPUT_PP) || \
((MODE) == GPIO_MODE_OUTPUT_OD) || \
((MODE) == GPIO_MODE_AF_PP) || \
((MODE) == GPIO_MODE_AF_OD) || \
- ((MODE) == GPIO_MODE_IT_RISING) || \
- ((MODE) == GPIO_MODE_IT_FALLING) || \
- ((MODE) == GPIO_MODE_IT_RISING_FALLING) || \
- ((MODE) == GPIO_MODE_EVT_RISING) || \
- ((MODE) == GPIO_MODE_EVT_FALLING) || \
- ((MODE) == GPIO_MODE_EVT_RISING_FALLING) || \
((MODE) == GPIO_MODE_ANALOG))
#define IS_GPIO_DRIVE(DRIVE) (((DRIVE) == GPIO_LOW_POWER) || \
- ((DRIVE) == GPIO_MED_POWER) || \
+ ((DRIVE) == GPIO_MID_POWER) || \
+ ((DRIVE) == GPIO_MID_FAST_POWER) || \
((DRIVE) == GPIO_HIGH_POWER))
-#define IS_GPIO_PULL(PULL) (((PULL) == GPIO_NOPULL) || ((PULL) == GPIO_PULLUP))
+#define IS_GPIO_PULL(PULL) (((PULL) == GPIO_NOPULL) || \
+ ((PULL) == GPIO_PULLUP) || \
+ ((PULL) == GPIO_PULLDOWN))
#define IS_GPIO_AF(AF) ((AF) <= (uint8_t)0x1F)
diff --git a/ports/renesas-ra/ra/ra_i2c.c b/ports/renesas-ra/ra/ra_i2c.c
index 64bbd6f501b4..ad1e3a74e0de 100644
--- a/ports/renesas-ra/ra/ra_i2c.c
+++ b/ports/renesas-ra/ra/ra_i2c.c
@@ -362,8 +362,8 @@ void ra_i2c_set_baudrate(R_IIC0_Type *i2c_inst, uint32_t baudrate) {
void ra_i2c_init(R_IIC0_Type *i2c_inst, uint32_t scl, uint32_t sda, uint32_t baudrate) {
ra_i2c_module_start(i2c_inst);
- ra_gpio_config(scl, GPIO_MODE_AF_OD, 0, GPIO_NOTOUCH_POWER, AF_I2C);
- ra_gpio_config(sda, GPIO_MODE_AF_OD, 0, GPIO_NOTOUCH_POWER, AF_I2C);
+ ra_gpio_config(scl, GPIO_MODE_AF_OD, GPIO_NOPULL, GPIO_LOW_POWER, AF_I2C);
+ ra_gpio_config(sda, GPIO_MODE_AF_OD, GPIO_NOPULL, GPIO_LOW_POWER, AF_I2C);
ra_i2c_priority(i2c_inst, RA_PRI_I2C);
i2c_inst->ICCR1_b.ICE = 0; // I2C disable
i2c_inst->ICCR1_b.IICRST = 1; // I2C internal reset
diff --git a/ports/renesas-ra/ra/ra_sci.c b/ports/renesas-ra/ra/ra_sci.c
index 8cf26680cc6e..3f8bf2444401 100644
--- a/ports/renesas-ra/ra/ra_sci.c
+++ b/ports/renesas-ra/ra/ra_sci.c
@@ -788,7 +788,7 @@ static void ra_sci_tx_set_pin(uint32_t pin) {
uint32_t af;
find = ra_af_find_ch_af((ra_af_pin_t *)&ra_sci_tx_pins, SCI_TX_PINS_SIZE, pin, &ch, &af);
if (find) {
- ra_gpio_config(pin, GPIO_MODE_AF_PP, 0, 0, af);
+ ra_gpio_config(pin, GPIO_MODE_AF_PP, GPIO_NOPULL, GPIO_LOW_POWER, af);
}
}
@@ -798,7 +798,7 @@ static void ra_sci_rx_set_pin(uint32_t pin) {
uint32_t af;
find = ra_af_find_ch_af((ra_af_pin_t *)&ra_sci_rx_pins, SCI_RX_PINS_SIZE, pin, &ch, &af);
if (find) {
- ra_gpio_config(pin, GPIO_MODE_INPUT, 1, 0, af);
+ ra_gpio_config(pin, GPIO_MODE_INPUT, GPIO_PULLUP, GPIO_LOW_POWER, af);
}
}
@@ -808,7 +808,7 @@ static void ra_sci_cts_set_pin(uint32_t pin) {
uint32_t af;
find = ra_af_find_ch_af((ra_af_pin_t *)&ra_sci_cts_pins, SCI_CTS_PINS_SIZE, pin, &ch, &af);
if (find) {
- ra_gpio_config(pin, GPIO_MODE_INPUT, 1, 0, af);
+ ra_gpio_config(pin, GPIO_MODE_INPUT, GPIO_PULLUP, GPIO_LOW_POWER, af);
}
}
@@ -1026,6 +1026,16 @@ int ra_sci_tx_wait(uint32_t ch) {
return (int)(tx_fifo[idx].len != (tx_fifo[idx].size - 1));
}
+int ra_sci_tx_busy(uint32_t ch) {
+ uint32_t idx = ch_to_idx[ch];
+ return (int)(tx_fifo[idx].busy);
+}
+
+int ra_sci_tx_bufsize(uint32_t ch) {
+ uint32_t idx = ch_to_idx[ch];
+ return (int)(tx_fifo[idx].size - 1);
+}
+
void ra_sci_tx_break(uint32_t ch) {
uint32_t idx = ch_to_idx[ch];
R_SCI0_Type *sci_reg = sci_regs[idx];
@@ -1134,7 +1144,7 @@ void ra_sci_init_with_flow(uint32_t ch, uint32_t tx_pin, uint32_t rx_pin, uint32
}
if (rts_pin != (uint32_t)PIN_END) {
m_rts_pin[idx] = rts_pin;
- ra_gpio_config(rts_pin, GPIO_MODE_OUTPUT_PP, false, 0, 0);
+ ra_gpio_config(rts_pin, GPIO_MODE_OUTPUT_PP, GPIO_NOPULL, GPIO_LOW_POWER, 0);
ra_gpio_write(rts_pin, 0);
}
}
diff --git a/ports/renesas-ra/ra/ra_sci.h b/ports/renesas-ra/ra/ra_sci.h
index 0a672f3672d1..87e4154e8ee0 100644
--- a/ports/renesas-ra/ra/ra_sci.h
+++ b/ports/renesas-ra/ra/ra_sci.h
@@ -52,6 +52,8 @@ bool ra_sci_is_rxirq_enable(uint32_t ch);
void ra_sci_isr_te(uint32_t ch);
int ra_sci_rx_ch(uint32_t ch);
int ra_sci_rx_any(uint32_t ch);
+int ra_sci_tx_busy(uint32_t ch);
+int ra_sci_tx_bufsize(uint32_t ch);
void ra_sci_tx_ch(uint32_t ch, int c);
int ra_sci_tx_wait(uint32_t ch);
void ra_sci_tx_break(uint32_t ch);
diff --git a/ports/renesas-ra/ra/ra_spi.c b/ports/renesas-ra/ra/ra_spi.c
index b7f78cd6dead..096519ffd640 100644
--- a/ports/renesas-ra/ra/ra_spi.c
+++ b/ports/renesas-ra/ra/ra_spi.c
@@ -196,9 +196,9 @@ static void ra_spi_module_stop(uint32_t ch) {
static void ra_spi_set_pin(uint32_t pin, bool miso) {
if (miso) {
- ra_gpio_config(pin, GPIO_MODE_INPUT, 1, 0, AF_SPI);
+ ra_gpio_config(pin, GPIO_MODE_INPUT, GPIO_PULLUP, GPIO_LOW_POWER, AF_SPI);
} else {
- ra_gpio_config(pin, GPIO_MODE_AF_PP, 0, 0, AF_SPI);
+ ra_gpio_config(pin, GPIO_MODE_AF_PP, GPIO_NOPULL, GPIO_LOW_POWER, AF_SPI);
}
}
diff --git a/ports/renesas-ra/softtimer.c b/ports/renesas-ra/softtimer.c
deleted file mode 100644
index c9c59cab0eed..000000000000
--- a/ports/renesas-ra/softtimer.c
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * 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.
- */
-
-#include
-#include "py/gc.h"
-#include "py/mphal.h"
-#include "py/runtime.h"
-#include "irq.h"
-#include "softtimer.h"
-
-#define TICKS_PERIOD 0x80000000
-#define TICKS_DIFF(t1, t0) ((int32_t)(((t1 - t0 + TICKS_PERIOD / 2) & (TICKS_PERIOD - 1)) - TICKS_PERIOD / 2))
-
-extern __IO uint32_t uwTick;
-
-volatile uint32_t soft_timer_next;
-
-// Pointer to the pairheap of soft timer objects.
-// This may contain bss/data pointers as well as GC-heap pointers,
-// and is explicitly GC traced by soft_timer_gc_mark_all().
-STATIC soft_timer_entry_t *soft_timer_heap;
-
-STATIC int soft_timer_lt(mp_pairheap_t *n1, mp_pairheap_t *n2) {
- soft_timer_entry_t *e1 = (soft_timer_entry_t *)n1;
- soft_timer_entry_t *e2 = (soft_timer_entry_t *)n2;
- return TICKS_DIFF(e1->expiry_ms, e2->expiry_ms) < 0;
-}
-
-STATIC void soft_timer_schedule_systick(uint32_t ticks_ms) {
- uint32_t irq_state = disable_irq();
- uint32_t uw_tick = uwTick;
- if (TICKS_DIFF(ticks_ms, uw_tick) <= 0) {
- soft_timer_next = uw_tick + 1;
- } else {
- soft_timer_next = ticks_ms;
- }
- enable_irq(irq_state);
-}
-
-void soft_timer_deinit(void) {
- // Pop off all the nodes which are allocated on the GC-heap.
- uint32_t irq_state = raise_irq_pri(IRQ_PRI_PENDSV);
- soft_timer_entry_t *heap_from = soft_timer_heap;
- soft_timer_entry_t *heap_to = (soft_timer_entry_t *)mp_pairheap_new(soft_timer_lt);
- while (heap_from != NULL) {
- soft_timer_entry_t *entry = (soft_timer_entry_t *)mp_pairheap_peek(soft_timer_lt, &heap_from->pairheap);
- heap_from = (soft_timer_entry_t *)mp_pairheap_pop(soft_timer_lt, &heap_from->pairheap);
- if (!(entry->flags & SOFT_TIMER_FLAG_GC_ALLOCATED)) {
- heap_to = (soft_timer_entry_t *)mp_pairheap_push(soft_timer_lt, &heap_to->pairheap, &entry->pairheap);
- }
- }
- soft_timer_heap = heap_to;
- restore_irq_pri(irq_state);
-}
-
-// Must be executed at IRQ_PRI_PENDSV
-void soft_timer_handler(void) {
- uint32_t ticks_ms = uwTick;
- soft_timer_entry_t *heap = soft_timer_heap;
- while (heap != NULL && TICKS_DIFF(heap->expiry_ms, ticks_ms) <= 0) {
- soft_timer_entry_t *entry = heap;
- heap = (soft_timer_entry_t *)mp_pairheap_pop(soft_timer_lt, &heap->pairheap);
- if (entry->flags & SOFT_TIMER_FLAG_PY_CALLBACK) {
- mp_sched_schedule(entry->py_callback, MP_OBJ_FROM_PTR(entry));
- } else {
- entry->c_callback(entry);
- }
- if (entry->mode == SOFT_TIMER_MODE_PERIODIC) {
- entry->expiry_ms += entry->delta_ms;
- heap = (soft_timer_entry_t *)mp_pairheap_push(soft_timer_lt, &heap->pairheap, &entry->pairheap);
- }
- }
- soft_timer_heap = heap;
- if (heap == NULL) {
- // No more timers left, set largest delay possible
- soft_timer_next = uwTick;
- } else {
- // Set soft_timer_next so SysTick calls us back at the correct time
- soft_timer_schedule_systick(heap->expiry_ms);
- }
-}
-
-void soft_timer_gc_mark_all(void) {
- // Mark all soft timer nodes that are allocated on the GC-heap.
- // To avoid deep C recursion, pop and recreate the pairheap as nodes are marked.
- uint32_t irq_state = raise_irq_pri(IRQ_PRI_PENDSV);
- soft_timer_entry_t *heap_from = soft_timer_heap;
- soft_timer_entry_t *heap_to = (soft_timer_entry_t *)mp_pairheap_new(soft_timer_lt);
- while (heap_from != NULL) {
- soft_timer_entry_t *entry = (soft_timer_entry_t *)mp_pairheap_peek(soft_timer_lt, &heap_from->pairheap);
- heap_from = (soft_timer_entry_t *)mp_pairheap_pop(soft_timer_lt, &heap_from->pairheap);
- if (entry->flags & SOFT_TIMER_FLAG_GC_ALLOCATED) {
- gc_collect_root((void **)&entry, 1);
- }
- heap_to = (soft_timer_entry_t *)mp_pairheap_push(soft_timer_lt, &heap_to->pairheap, &entry->pairheap);
- }
- soft_timer_heap = heap_to;
- restore_irq_pri(irq_state);
-}
-
-void soft_timer_static_init(soft_timer_entry_t *entry, uint16_t mode, uint32_t delta_ms, void (*cb)(soft_timer_entry_t *)) {
- mp_pairheap_init_node(soft_timer_lt, &entry->pairheap);
- entry->flags = 0;
- entry->mode = mode;
- entry->delta_ms = delta_ms;
- entry->c_callback = cb;
-}
-
-void soft_timer_insert(soft_timer_entry_t *entry, uint32_t initial_delta_ms) {
- mp_pairheap_init_node(soft_timer_lt, &entry->pairheap);
- entry->expiry_ms = mp_hal_ticks_ms() + initial_delta_ms;
- uint32_t irq_state = raise_irq_pri(IRQ_PRI_PENDSV);
- soft_timer_heap = (soft_timer_entry_t *)mp_pairheap_push(soft_timer_lt, &soft_timer_heap->pairheap, &entry->pairheap);
- if (entry == soft_timer_heap) {
- // This new timer became the earliest one so set soft_timer_next
- soft_timer_schedule_systick(entry->expiry_ms);
- }
- restore_irq_pri(irq_state);
-}
-
-void soft_timer_remove(soft_timer_entry_t *entry) {
- uint32_t irq_state = raise_irq_pri(IRQ_PRI_PENDSV);
- soft_timer_heap = (soft_timer_entry_t *)mp_pairheap_delete(soft_timer_lt, &soft_timer_heap->pairheap, &entry->pairheap);
- restore_irq_pri(irq_state);
-}
diff --git a/ports/renesas-ra/storage.c b/ports/renesas-ra/storage.c
index 8d94f6fb9c3b..18dff9780078 100644
--- a/ports/renesas-ra/storage.c
+++ b/ports/renesas-ra/storage.c
@@ -400,13 +400,14 @@ STATIC const mp_rom_map_elem_t pyb_flash_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(pyb_flash_locals_dict, pyb_flash_locals_dict_table);
-const mp_obj_type_t pyb_flash_type = {
- { &mp_type_type },
- .name = MP_QSTR_Flash,
- .print = pyb_flash_print,
- .make_new = pyb_flash_make_new,
- .locals_dict = (mp_obj_dict_t *)&pyb_flash_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ pyb_flash_type,
+ MP_QSTR_Flash,
+ MP_TYPE_FLAG_NONE,
+ make_new, pyb_flash_make_new,
+ locals_dict, &pyb_flash_locals_dict,
+ print, pyb_flash_print
+ );
void pyb_flash_init_vfs(fs_user_mount_t *vfs) {
vfs->base.type = &mp_fat_vfs_type;
diff --git a/ports/renesas-ra/systick.c b/ports/renesas-ra/systick.c
index e88166b110bf..95ca8083011a 100644
--- a/ports/renesas-ra/systick.c
+++ b/ports/renesas-ra/systick.c
@@ -27,10 +27,10 @@
#include "py/runtime.h"
#include "py/mphal.h"
+#include "shared/runtime/softtimer.h"
#include "irq.h"
#include "pendsv.h"
#include "systick.h"
-#include "softtimer.h"
#include "pybthread.h"
#include "hal_data.h"
diff --git a/ports/renesas-ra/timer.c b/ports/renesas-ra/timer.c
index 93b378ac3f67..04bd752b98cc 100644
--- a/ports/renesas-ra/timer.c
+++ b/ports/renesas-ra/timer.c
@@ -410,13 +410,14 @@ STATIC const mp_rom_map_elem_t pyb_timer_locals_dict_table[] = {
};
STATIC MP_DEFINE_CONST_DICT(pyb_timer_locals_dict, pyb_timer_locals_dict_table);
-const mp_obj_type_t pyb_timer_type = {
- { &mp_type_type },
- .name = MP_QSTR_Timer,
- .print = pyb_timer_print,
- .make_new = pyb_timer_make_new,
- .locals_dict = (mp_obj_dict_t *)&pyb_timer_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ pyb_timer_type,
+ MP_QSTR_Timer,
+ MP_TYPE_FLAG_NONE,
+ make_new, pyb_timer_make_new,
+ locals_dict, &pyb_timer_locals_dict,
+ print, pyb_timer_print
+ );
#if defined(TIMER_CHANNEL)
/*
@@ -502,12 +503,13 @@ STATIC const mp_rom_map_elem_t pyb_timer_channel_locals_dict_table[] = {
};
STATIC MP_DEFINE_CONST_DICT(pyb_timer_channel_locals_dict, pyb_timer_channel_locals_dict_table);
-STATIC const mp_obj_type_t pyb_timer_channel_type = {
- { &mp_type_type },
- .name = MP_QSTR_TimerChannel,
- .print = pyb_timer_channel_print,
- .locals_dict = (mp_obj_dict_t *)&pyb_timer_channel_locals_dict,
-};
+STATIC MP_DEFINE_CONST_OBJ_TYPE(
+ pyb_timer_channel_type,
+ MP_QSTR_TimerChannel,
+ MP_TYPE_FLAG_NONE,
+ locals_dict, &pyb_timer_channel_locals_dict,
+ print, pyb_timer_channel_print
+ );
#endif
STATIC void timer_handle_irq_channel(pyb_timer_obj_t *tim, uint8_t channel, mp_obj_t callback) {
@@ -567,3 +569,5 @@ void timer_irq_handler(void *param) {
// }
}
}
+
+MP_REGISTER_ROOT_POINTER(struct _pyb_timer_obj_t *pyb_timer_obj_all[MICROPY_HW_MAX_TIMER]);
diff --git a/ports/renesas-ra/uart.c b/ports/renesas-ra/uart.c
index 0e2e9004cd41..e41c68f0c442 100644
--- a/ports/renesas-ra/uart.c
+++ b/ports/renesas-ra/uart.c
@@ -420,6 +420,16 @@ mp_uint_t uart_tx_avail(machine_uart_obj_t *self) {
return ra_sci_tx_wait(ch);
}
+mp_uint_t uart_tx_busy(machine_uart_obj_t *self) {
+ int ch = (int)self->uart_id;
+ return ra_sci_tx_busy(ch);
+}
+
+mp_uint_t uart_tx_txbuf(machine_uart_obj_t *self) {
+ int ch = (int)self->uart_id;
+ return ra_sci_tx_bufsize(ch);
+}
+
// Waits at most timeout milliseconds for at least 1 char to become ready for
// reading (from buf or for direct reading).
// Returns true if something available, false if not.
diff --git a/ports/renesas-ra/uart.h b/ports/renesas-ra/uart.h
index 9c7aea737dab..245be24d1a4d 100644
--- a/ports/renesas-ra/uart.h
+++ b/ports/renesas-ra/uart.h
@@ -106,6 +106,8 @@ void uart_attach_to_repl(machine_uart_obj_t *self, bool attached);
uint32_t uart_get_baudrate(machine_uart_obj_t *self);
mp_uint_t uart_rx_any(machine_uart_obj_t *uart_obj);
mp_uint_t uart_tx_avail(machine_uart_obj_t *uart_obj);
+mp_uint_t uart_tx_busy(machine_uart_obj_t *uart_obj);
+mp_uint_t uart_tx_txbuf(machine_uart_obj_t *self);
bool uart_rx_wait(machine_uart_obj_t *self, uint32_t timeout);
int uart_rx_char(machine_uart_obj_t *uart_obj);
bool uart_tx_wait(machine_uart_obj_t *self, uint32_t timeout);
diff --git a/ports/renesas-ra/usrsw.c b/ports/renesas-ra/usrsw.c
index b0e2396cde46..edbe51968301 100644
--- a/ports/renesas-ra/usrsw.c
+++ b/ports/renesas-ra/usrsw.c
@@ -54,7 +54,7 @@
// this function inits the switch GPIO so that it can be used
void switch_init0(void) {
- mp_hal_pin_config(MICROPY_HW_USRSW_PIN, MP_HAL_PIN_MODE_INPUT, MICROPY_HW_USRSW_PULL, GPIO_LOW_POWER, 0);
+ mp_hal_pin_config(MICROPY_HW_USRSW_PIN, MP_HAL_PIN_MODE_INPUT, MICROPY_HW_USRSW_PULL, MP_HAL_PIN_DRIVE_0, 0);
}
int switch_get(void) {
@@ -135,13 +135,16 @@ STATIC const mp_rom_map_elem_t pyb_switch_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(pyb_switch_locals_dict, pyb_switch_locals_dict_table);
-const mp_obj_type_t pyb_switch_type = {
- { &mp_type_type },
- .name = MP_QSTR_Switch,
- .print = pyb_switch_print,
- .make_new = pyb_switch_make_new,
- .call = pyb_switch_call,
- .locals_dict = (mp_obj_dict_t *)&pyb_switch_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ pyb_switch_type,
+ MP_QSTR_Switch,
+ MP_TYPE_FLAG_NONE,
+ make_new, pyb_switch_make_new,
+ locals_dict, &pyb_switch_locals_dict,
+ print, pyb_switch_print,
+ call, pyb_switch_call
+ );
+
+MP_REGISTER_ROOT_POINTER(mp_obj_t pyb_switch_callback);
#endif // MICROPY_HW_HAS_SWITCH
diff --git a/ports/rp2/CMakeLists.txt b/ports/rp2/CMakeLists.txt
index a7a192ea3369..094031c6852a 100644
--- a/ports/rp2/CMakeLists.txt
+++ b/ports/rp2/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.12)
+cmake_minimum_required(VERSION 3.13)
# Set build type to reduce firmware size
if(NOT CMAKE_BUILD_TYPE)
@@ -16,6 +16,8 @@ endif()
# Use the local tinyusb instead of the one in pico-sdk
set(PICO_TINYUSB_PATH ${MICROPY_DIR}/lib/tinyusb)
+# Use the local lwip instead of the one in pico-sdk
+set(PICO_LWIP_PATH ${MICROPY_DIR}/lib/lwip)
# Set the location of this port's directory.
set(MICROPY_PORT_DIR ${CMAKE_SOURCE_DIR})
@@ -43,10 +45,25 @@ if(NOT PICO_BOARD)
string(TOLOWER ${MICROPY_BOARD} PICO_BOARD)
endif()
+# Set the amount of C heap, if it's not already set.
+# If a board uses malloc then it must set this to at least 4096.
+if(NOT MICROPY_C_HEAP_SIZE)
+ set(MICROPY_C_HEAP_SIZE 0)
+endif()
+
# Enable extmod components that will be configured by extmod.cmake.
# A board may also have enabled additional components.
set(MICROPY_SSL_MBEDTLS ON)
+# Use the local cyw43_driver instead of the one in pico-sdk
+if (MICROPY_PY_NETWORK_CYW43)
+ set(PICO_CYW43_DRIVER_PATH ${MICROPY_DIR}/lib/cyw43-driver)
+endif()
+
+# Necessary submodules for all boards.
+string(CONCAT GIT_SUBMODULES "${GIT_SUBMODULES} " lib/mbedtls)
+string(CONCAT GIT_SUBMODULES "${GIT_SUBMODULES} " lib/tinyusb)
+
# Include component cmake fragments
include(${MICROPY_DIR}/py/py.cmake)
include(${MICROPY_DIR}/extmod/extmod.cmake)
@@ -70,13 +87,13 @@ set(MICROPY_SOURCE_LIB
${MICROPY_DIR}/lib/littlefs/lfs1_util.c
${MICROPY_DIR}/lib/littlefs/lfs2.c
${MICROPY_DIR}/lib/littlefs/lfs2_util.c
- ${MICROPY_DIR}/lib/mbedtls_errors/mp_mbedtls_errors.c
${MICROPY_DIR}/lib/oofatfs/ff.c
${MICROPY_DIR}/lib/oofatfs/ffunicode.c
+ ${MICROPY_DIR}/shared/netutils/dhcpserver.c
${MICROPY_DIR}/shared/netutils/netutils.c
${MICROPY_DIR}/shared/netutils/trace.c
${MICROPY_DIR}/shared/readline/readline.c
- ${MICROPY_DIR}/shared/runtime/gchelper_m0.s
+ ${MICROPY_DIR}/shared/runtime/gchelper_thumb1.s
${MICROPY_DIR}/shared/runtime/gchelper_native.c
${MICROPY_DIR}/shared/runtime/interrupt_char.c
${MICROPY_DIR}/shared/runtime/mpirq.c
@@ -84,6 +101,9 @@ set(MICROPY_SOURCE_LIB
${MICROPY_DIR}/shared/runtime/stdout_helpers.c
${MICROPY_DIR}/shared/runtime/sys_stdio_mphal.c
${MICROPY_DIR}/shared/timeutils/timeutils.c
+ ${MICROPY_DIR}/shared/tinyusb/mp_cdc_common.c
+ ${MICROPY_DIR}/shared/tinyusb/mp_usbd.c
+ ${MICROPY_DIR}/shared/tinyusb/mp_usbd_descriptor.c
)
set(MICROPY_SOURCE_DRIVERS
@@ -110,16 +130,19 @@ set(MICROPY_SOURCE_PORT
mphalport.c
mpnetworkport.c
mpthreadport.c
+ pendsv.c
rp2_flash.c
rp2_pio.c
- tusb_port.c
uart.c
+ usbd.c
msc_disk.c
mbedtls/mbedtls_port.c
+ ${CMAKE_BINARY_DIR}/pins_${MICROPY_BOARD}.c
)
set(MICROPY_SOURCE_QSTR
${MICROPY_SOURCE_PY}
+ ${MICROPY_DIR}/shared/readline/readline.c
${MICROPY_DIR}/shared/runtime/mpirq.c
${MICROPY_DIR}/shared/runtime/sys_stdio_mphal.c
${PROJECT_SOURCE_DIR}/machine_adc.c
@@ -137,9 +160,11 @@ set(MICROPY_SOURCE_QSTR
${PROJECT_SOURCE_DIR}/modutime.c
${PROJECT_SOURCE_DIR}/rp2_flash.c
${PROJECT_SOURCE_DIR}/rp2_pio.c
+ ${CMAKE_BINARY_DIR}/pins_${MICROPY_BOARD}.c
)
set(PICO_SDK_COMPONENTS
+ cmsis_core
hardware_adc
hardware_base
hardware_clocks
@@ -149,6 +174,7 @@ set(PICO_SDK_COMPONENTS
hardware_i2c
hardware_irq
hardware_pio
+ hardware_pll
hardware_pwm
hardware_regs
hardware_rtc
@@ -158,6 +184,7 @@ set(PICO_SDK_COMPONENTS
hardware_timer
hardware_uart
hardware_watchdog
+ hardware_xosc
pico_base_headers
pico_binary_info
pico_bootrom
@@ -182,12 +209,6 @@ if (MICROPY_PY_LWIP)
target_compile_definitions(${MICROPY_TARGET} PRIVATE
MICROPY_PY_LWIP=1
)
-
- list(APPEND MICROPY_SOURCE_EXTMOD
- ${MICROPY_EXTMOD_DIR}/modlwip.c
- )
-
- string(CONCAT GIT_SUBMODULES "${GIT_SUBMODULES} " lib/lwip)
endif()
if(MICROPY_PY_BLUETOOTH)
@@ -202,6 +223,11 @@ if(MICROPY_PY_BLUETOOTH)
endif()
if(MICROPY_BLUETOOTH_NIMBLE)
+ string(CONCAT GIT_SUBMODULES "${GIT_SUBMODULES} " lib/mynewt-nimble)
+ if(NOT (${ECHO_SUBMODULES}) AND NOT EXISTS ${MICROPY_DIR}/lib/mynewt-nimble/nimble/host/include/host/ble_hs.h)
+ message(FATAL_ERROR " mynewt-nimble not initialized.\n Run 'make BOARD=${MICROPY_BOARD} submodules'")
+ endif()
+
list(APPEND MICROPY_SOURCE_PORT mpnimbleport.c)
target_compile_definitions(${MICROPY_TARGET} PRIVATE
MICROPY_BLUETOOTH_NIMBLE=1
@@ -217,6 +243,37 @@ if(MICROPY_BLUETOOTH_NIMBLE)
list(APPEND MICROPY_INC_CORE ${NIMBLE_INCLUDE})
endif()
+# tinyusb helper
+target_include_directories(${MICROPY_TARGET} PRIVATE
+ ${MICROPY_DIR}/shared/tinyusb/
+)
+
+if (MICROPY_PY_NETWORK_CYW43)
+ string(CONCAT GIT_SUBMODULES "${GIT_SUBMODULES} " lib/cyw43-driver)
+ if((NOT (${ECHO_SUBMODULES})) AND NOT EXISTS ${MICROPY_DIR}/lib/cyw43-driver/src/cyw43.h)
+ message(FATAL_ERROR " cyw43-driver not initialized.\n Run 'make BOARD=${MICROPY_BOARD} submodules'")
+ endif()
+
+ target_compile_definitions(${MICROPY_TARGET} PRIVATE
+ MICROPY_PY_NETWORK_CYW43=1
+ MICROPY_PY_SOCKET_DEFAULT_TIMEOUT_MS=30000 # default socket timeout
+ )
+ if (CMAKE_BUILD_TYPE MATCHES Debug)
+ target_compile_definitions(${MICROPY_TARGET} PRIVATE
+ CYW43_USE_STATS=1
+ )
+ endif()
+
+ list(APPEND MICROPY_SOURCE_PORT
+ machine_pin_cyw43.c
+ )
+
+ target_link_libraries(${MICROPY_TARGET}
+ cyw43_driver_picow
+ cmsis_core
+ )
+endif()
+
if (MICROPY_PY_NETWORK_NINAW10)
target_compile_definitions(${MICROPY_TARGET} PRIVATE
MICROPY_PY_NETWORK_NINAW10=1
@@ -231,14 +288,16 @@ if (MICROPY_PY_NETWORK_NINAW10)
${MICROPY_DIR}/drivers/ninaw10/nina_bt_hci.c
${MICROPY_DIR}/drivers/ninaw10/nina_wifi_drv.c
${MICROPY_DIR}/drivers/ninaw10/nina_wifi_bsp.c
- )
-
- list(APPEND MICROPY_SOURCE_EXTMOD
- ${MICROPY_DIR}/extmod/network_ninaw10.c
+ ${MICROPY_DIR}/drivers/ninaw10/machine_pin_nina.c
)
endif()
if (MICROPY_PY_NETWORK_WIZNET5K)
+ string(CONCAT GIT_SUBMODULES "${GIT_SUBMODULES} " lib/wiznet5k)
+ if((NOT (${ECHO_SUBMODULES})) AND NOT EXISTS ${MICROPY_DIR}/lib/wiznet5k/README.md)
+ message(FATAL_ERROR " wiznet5k not initialized.\n Run 'make BOARD=${MICROPY_BOARD} submodules'")
+ endif()
+
target_compile_definitions(${MICROPY_TARGET} PRIVATE
MICROPY_PY_NETWORK_WIZNET5K=1
WIZCHIP_PREFIXED_EXPORTS=1
@@ -269,12 +328,6 @@ if (MICROPY_PY_NETWORK_WIZNET5K)
${MICROPY_DIR}/lib/wiznet5k/Internet/DNS/dns.c
${MICROPY_DIR}/lib/wiznet5k/Internet/DHCP/dhcp.c
)
-
- list(APPEND MICROPY_SOURCE_EXTMOD
- ${MICROPY_DIR}/extmod/network_wiznet5k.c
- )
-
- string(CONCAT GIT_SUBMODULES "${GIT_SUBMODULES} " lib/wiznet5k)
endif()
# Add qstr sources for extmod and usermod, in case they are modified by components above.
@@ -284,7 +337,7 @@ list(APPEND MICROPY_SOURCE_QSTR
)
# Define mpy-cross flags
-set(MICROPY_CROSS_FLAGS -march=armv7m)
+set(MICROPY_CROSS_FLAGS -march=armv6m)
# Set the frozen manifest file
if (MICROPY_USER_FROZEN_MANIFEST)
@@ -303,12 +356,6 @@ target_sources(${MICROPY_TARGET} PRIVATE
target_link_libraries(${MICROPY_TARGET} micropy_lib_mbedtls)
-# Filter out library/error.c as we're using mp_mbedtls_errors.c instead.
-set_source_files_properties(${MICROPY_LIB_MBEDTLS_DIR}/library/error.c
- TARGET_DIRECTORY micropy_lib_mbedtls
- PROPERTIES HEADER_FILE_ONLY ON
-)
-
target_link_libraries(${MICROPY_TARGET} usermod)
target_include_directories(${MICROPY_TARGET} PRIVATE
@@ -324,6 +371,10 @@ target_compile_options(${MICROPY_TARGET} PRIVATE
-Werror
)
+target_link_options(${MICROPY_TARGET} PRIVATE
+ -Wl,--defsym=__micropy_c_heap_size__=${MICROPY_C_HEAP_SIZE}
+)
+
set_source_files_properties(
${PICO_SDK_PATH}/src/rp2_common/pico_double/double_math.c
${PICO_SDK_PATH}/src/rp2_common/pico_float/float_math.c
@@ -372,9 +423,11 @@ endif()
pico_add_extra_outputs(${MICROPY_TARGET})
+pico_find_compiler(PICO_COMPILER_SIZE ${PICO_GCC_TRIPLE}-size)
+
add_custom_command(TARGET ${MICROPY_TARGET}
POST_BUILD
- COMMAND arm-none-eabi-size --format=berkeley ${PROJECT_BINARY_DIR}/${MICROPY_TARGET}.elf
+ COMMAND ${PICO_COMPILER_SIZE} --format=berkeley ${PROJECT_BINARY_DIR}/${MICROPY_TARGET}.elf
VERBATIM
)
@@ -386,3 +439,37 @@ endforeach()
# Include the main MicroPython cmake rules.
include(${MICROPY_DIR}/py/mkrules.cmake)
+
+set(MICROPY_BOARDS_DIR "${MICROPY_PORT_DIR}/boards")
+set(GEN_PINS_AF_CSV "${MICROPY_BOARDS_DIR}/rp2_af.csv")
+set(GEN_PINS_PREFIX "${MICROPY_BOARDS_DIR}/rp2_prefix.c")
+set(GEN_PINS_MKPINS "${MICROPY_BOARDS_DIR}/make-pins.py")
+set(GEN_PINS_SRC "${CMAKE_BINARY_DIR}/pins_${MICROPY_BOARD}.c")
+set(GEN_PINS_HDR "${MICROPY_GENHDR_DIR}/pins.h")
+set(GEN_PINS_QSTR "${CMAKE_BINARY_DIR}/pins_qstr.h")
+set(GEN_PINS_AF_CONST "${MICROPY_GENHDR_DIR}/pins_af_const.h")
+set(GEN_PINS_AF_PY "${CMAKE_BINARY_DIR}/pins_af.py")
+
+if(EXISTS "${MICROPY_BOARDS_DIR}/${MICROPY_BOARD}/pins.csv")
+ set(GEN_PINS_BOARD_CSV "${MICROPY_BOARDS_DIR}/${MICROPY_BOARD}/pins.csv")
+ set(GEN_PINS_CSV_ARG --board "${GEN_PINS_BOARD_CSV}")
+endif()
+
+target_sources(${MICROPY_TARGET} PRIVATE
+ ${GEN_PINS_HDR}
+)
+
+# Generate pins
+add_custom_command(
+ OUTPUT ${GEN_PINS_HDR} ${GEN_PINS_SRC} ${GEN_PINS_QSTR}
+ COMMAND ${Python3_EXECUTABLE} ${GEN_PINS_MKPINS} ${GEN_PINS_CSV_ARG} --af ${GEN_PINS_AF_CSV} --prefix ${GEN_PINS_PREFIX}
+ --hdr ${GEN_PINS_HDR} --qstr ${GEN_PINS_QSTR} --af-const ${GEN_PINS_AF_CONST} --af-py ${GEN_PINS_AF_PY} > ${GEN_PINS_SRC}
+ DEPENDS
+ ${GEN_PINS_AF_CSV}
+ ${GEN_PINS_BOARD_CSV}
+ ${GEN_PINS_MKPINS}
+ ${GEN_PINS_PREFIX}
+ ${MICROPY_MPVERSION}
+ VERBATIM
+ COMMAND_EXPAND_LISTS
+)
diff --git a/ports/rp2/Makefile b/ports/rp2/Makefile
index c2138a340a1f..4f5b4728ecbc 100644
--- a/ports/rp2/Makefile
+++ b/ports/rp2/Makefile
@@ -2,13 +2,26 @@
#
# This is a simple wrapper around cmake
+# Select the board to build for:
+ifdef BOARD_DIR
+# Custom board path - remove trailing slash and get the final component of
+# the path as the board name.
+BOARD ?= $(notdir $(BOARD_DIR:/=))
+else
+# If not given on the command line, then default to PICO.
BOARD ?= PICO
+BOARD_DIR ?= boards/$(BOARD)
+endif
+
+ifeq ($(wildcard $(BOARD_DIR)/.),)
+$(error Invalid BOARD specified: $(BOARD_DIR))
+endif
BUILD ?= build-$(BOARD)
$(VERBOSE)MAKESILENT = -s
-CMAKE_ARGS = -DMICROPY_BOARD=$(BOARD)
+CMAKE_ARGS = -DMICROPY_BOARD=$(BOARD) -DMICROPY_BOARD_DIR=$(abspath $(BOARD_DIR))
ifdef USER_C_MODULES
CMAKE_ARGS += -DUSER_C_MODULES=${USER_C_MODULES}
@@ -22,22 +35,28 @@ ifeq ($(DEBUG),1)
CMAKE_ARGS += -DCMAKE_BUILD_TYPE=Debug
endif
+ifdef BOARD_VARIANT
+CMAKE_ARGS += -DBOARD_VARIANT=${BOARD_VARIANT}
+endif
+
+HELP_BUILD_ERROR ?= "See \033[1;31mhttps://github.com/micropython/micropython/wiki/Build-Troubleshooting\033[0m"
+
all:
- [ -e $(BUILD)/CMakeCache.txt ] || cmake -S . -B $(BUILD) -DPICO_BUILD_DOCS=0 ${CMAKE_ARGS}
- $(MAKE) $(MAKESILENT) -C $(BUILD)
+ [ -e $(BUILD)/Makefile ] || cmake -S . -B $(BUILD) -DPICO_BUILD_DOCS=0 ${CMAKE_ARGS}
+ $(MAKE) $(MAKESILENT) -C $(BUILD) || (echo -e $(HELP_BUILD_ERROR); false)
clean:
$(RM) -rf $(BUILD)
-GIT_SUBMODULES += lib/mbedtls lib/pico-sdk lib/tinyusb
-
+# First ensure that pico-sdk is initialised, then use cmake to pick everything
+# else (including board-specific dependencies).
submodules:
-ifeq ($(BOARD),PICO)
- # Run the standard submodules target with minimum required submodules above
- $(MAKE) -f ../../py/mkrules.mk GIT_SUBMODULES="$(GIT_SUBMODULES)" submodules
-else
- # Run submodules task through cmake interface to pick up any board specific dependencies.
- GIT_SUBMODULES=$$(cmake -B $(BUILD)/submodules -DECHO_SUBMODULES=1 -DGIT_SUBMODULES="$(GIT_SUBMODULES)" ${CMAKE_ARGS} -S . 2>&1 | \
- grep 'GIT_SUBMODULES=' | cut -d= -f2); \
+ $(MAKE) -f ../../py/mkrules.mk GIT_SUBMODULES="lib/pico-sdk" submodules
+ GIT_SUBMODULES=$$(cmake -B $(BUILD)/submodules -DECHO_SUBMODULES=1 ${CMAKE_ARGS} -S . 2>&1 | \
+ grep '^GIT_SUBMODULES=' | cut -d= -f2); \
$(MAKE) -f ../../py/mkrules.mk GIT_SUBMODULES="$${GIT_SUBMODULES}" submodules
-endif
+
+query-variants:
+ @BOARD_VARIANTS=$$(cmake -B $(BUILD)/variants -DECHO_BOARD_VARIANTS=1 ${CMAKE_ARGS} -S . 2>&1 | \
+ grep '^BOARD_VARIANTS=' | cut -d= -f2); \
+ echo "VARIANTS: $${BOARD_VARIANTS}"
diff --git a/ports/rp2/README.md b/ports/rp2/README.md
index 4b929c25c621..3ca96360c68b 100644
--- a/ports/rp2/README.md
+++ b/ports/rp2/README.md
@@ -37,6 +37,13 @@ You can also build the standard CMake way. The final firmware is found in
the top-level of the CMake build directory (`build` by default) and is
called `firmware.uf2`.
+If you are using a different board other than a Rasoberry Pi Pico, then you should
+pass the board name to the build; e.g. for Raspberry Pi Pico W:
+
+ $ make BOARD=PICO_W submodules
+ $ make BOARD=PICO_W clean
+ $ make BOARD=PICO_W
+
## Deploying firmware to the device
Firmware can be deployed to the device by putting it into bootloader mode
diff --git a/ports/rp2/boards/ADAFRUIT_FEATHER_RP2040/mpconfigboard.h b/ports/rp2/boards/ADAFRUIT_FEATHER_RP2040/mpconfigboard.h
index 84d2bf20dbc6..f9cd030d46ce 100644
--- a/ports/rp2/boards/ADAFRUIT_FEATHER_RP2040/mpconfigboard.h
+++ b/ports/rp2/boards/ADAFRUIT_FEATHER_RP2040/mpconfigboard.h
@@ -7,14 +7,6 @@
#define MICROPY_HW_USB_VID (0x239A)
#define MICROPY_HW_USB_PID (0x80F2)
-// STEMMA QT / Qwiic on I2C1
-#define MICROPY_HW_I2C1_SCL (3)
-#define MICROPY_HW_I2C1_SDA (2)
-
-#define MICROPY_HW_SPI0_SCK (18)
-#define MICROPY_HW_SPI0_MOSI (19)
-#define MICROPY_HW_SPI0_MISO (20)
-
// NeoPixel GPIO16, power not toggleable
// Red user LED GPIO13
diff --git a/ports/rp2/boards/ADAFRUIT_FEATHER_RP2040/pins.csv b/ports/rp2/boards/ADAFRUIT_FEATHER_RP2040/pins.csv
new file mode 100644
index 000000000000..ee6fd99feefd
--- /dev/null
+++ b/ports/rp2/boards/ADAFRUIT_FEATHER_RP2040/pins.csv
@@ -0,0 +1 @@
+LED,GPIO13
diff --git a/ports/rp2/boards/ADAFRUIT_ITSYBITSY_RP2040/mpconfigboard.h b/ports/rp2/boards/ADAFRUIT_ITSYBITSY_RP2040/mpconfigboard.h
index 8f5551172bf9..be950f4f99d4 100644
--- a/ports/rp2/boards/ADAFRUIT_ITSYBITSY_RP2040/mpconfigboard.h
+++ b/ports/rp2/boards/ADAFRUIT_ITSYBITSY_RP2040/mpconfigboard.h
@@ -7,13 +7,6 @@
#define MICROPY_HW_USB_VID (0x239A)
#define MICROPY_HW_USB_PID (0x80FE)
-#define MICROPY_HW_I2C0_SCL (3)
-#define MICROPY_HW_I2C0_SDA (2)
-
-#define MICROPY_HW_SPI0_SCK (18)
-#define MICROPY_HW_SPI0_MOSI (19)
-#define MICROPY_HW_SPI0_MISO (20)
-
// NeoPixel data GPIO17, power GPIO16
// Red user LED GPIO11
diff --git a/ports/rp2/boards/ADAFRUIT_ITSYBITSY_RP2040/pins.csv b/ports/rp2/boards/ADAFRUIT_ITSYBITSY_RP2040/pins.csv
new file mode 100644
index 000000000000..1b7e7c3c73ed
--- /dev/null
+++ b/ports/rp2/boards/ADAFRUIT_ITSYBITSY_RP2040/pins.csv
@@ -0,0 +1 @@
+LED,GPIO11
diff --git a/ports/rp2/boards/ADAFRUIT_QTPY_RP2040/mpconfigboard.h b/ports/rp2/boards/ADAFRUIT_QTPY_RP2040/mpconfigboard.h
index ca341cedd8d2..6d834fd4f5d6 100644
--- a/ports/rp2/boards/ADAFRUIT_QTPY_RP2040/mpconfigboard.h
+++ b/ports/rp2/boards/ADAFRUIT_QTPY_RP2040/mpconfigboard.h
@@ -12,17 +12,10 @@
#define MICROPY_HW_UART1_CTS (10)
#define MICROPY_HW_UART1_RTS (7)
-#define MICROPY_HW_I2C0_SCL (25)
-#define MICROPY_HW_I2C0_SDA (24)
-
-// STEMMA QT / Qwiic on I2C1
+// STEMMA QT / Qwiic on (non-default) I2C1
#define MICROPY_HW_I2C1_SCL (23)
#define MICROPY_HW_I2C1_SDA (22)
-#define MICROPY_HW_SPI0_SCK (6)
-#define MICROPY_HW_SPI0_MOSI (3)
-#define MICROPY_HW_SPI0_MISO (4)
-
// NeoPixel data GPIO12, power GPIO11
// Boot button GPIO21
diff --git a/ports/rp2/boards/ARDUINO_NANO_RP2040_CONNECT/board.json b/ports/rp2/boards/ARDUINO_NANO_RP2040_CONNECT/board.json
index ca7ba089b894..5bd03e1e0b7e 100644
--- a/ports/rp2/boards/ARDUINO_NANO_RP2040_CONNECT/board.json
+++ b/ports/rp2/boards/ARDUINO_NANO_RP2040_CONNECT/board.json
@@ -17,7 +17,7 @@
"images": [
"ABX00052_01.iso_999x750.jpg"
],
- "mcu": "RP2040",
+ "mcu": "rp2040",
"product": "Arduino Nano RP2040 Connect",
"thumbnail": "",
"url": "https://store-usa.arduino.cc/products/arduino-nano-rp2040-connect",
diff --git a/ports/rp2/boards/ARDUINO_NANO_RP2040_CONNECT/manifest.py b/ports/rp2/boards/ARDUINO_NANO_RP2040_CONNECT/manifest.py
index 1becb3dfe118..7c9b37e4b55d 100644
--- a/ports/rp2/boards/ARDUINO_NANO_RP2040_CONNECT/manifest.py
+++ b/ports/rp2/boards/ARDUINO_NANO_RP2040_CONNECT/manifest.py
@@ -1,10 +1,16 @@
include("$(PORT_DIR)/boards/manifest.py")
-include("$(MPY_DIR)/extmod/webrepl/manifest.py")
-freeze("$(MPY_DIR)/drivers/lsm6dsox/", "lsm6dsox.py")
-include(
- "$(MPY_LIB_DIR)/micropython/bluetooth/aioble/manifest.py",
- client=True,
- central=True,
- l2cap=True,
- security=True,
-)
+
+# Networking
+require("bundle-networking")
+
+# Drivers
+require("lsm6dsox")
+require("espflash")
+
+# Utils
+require("time")
+require("senml")
+require("logging")
+
+# Bluetooth
+require("aioble")
diff --git a/ports/rp2/boards/ARDUINO_NANO_RP2040_CONNECT/mpconfigboard.h b/ports/rp2/boards/ARDUINO_NANO_RP2040_CONNECT/mpconfigboard.h
index 6d04e3e1d06b..a4fb8b7c8c9e 100644
--- a/ports/rp2/boards/ARDUINO_NANO_RP2040_CONNECT/mpconfigboard.h
+++ b/ports/rp2/boards/ARDUINO_NANO_RP2040_CONNECT/mpconfigboard.h
@@ -4,21 +4,23 @@
#define MICROPY_HW_BOARD_NAME "Arduino Nano RP2040 Connect"
#define MICROPY_HW_FLASH_STORAGE_BYTES (8 * 1024 * 1024)
-// Enable networking and sockets.
+// Enable networking.
#define MICROPY_PY_NETWORK (1)
-#define MICROPY_PY_USOCKET (1)
-#define MICROPY_PY_WEBREPL (1)
-#define MICROPY_PY_UWEBSOCKET (1)
-#define MICROPY_PY_UHASHLIB_SHA1 (1)
-#define MICROPY_PY_OS_DUPTERM (1)
+
+// Enable MD5 hash.
+#define MICROPY_PY_UHASHLIB_MD5 (1)
// Disable internal error numbers.
#define MICROPY_USE_INTERNAL_ERRNO (0)
+// Enable externally controlled pins.
+#define MICROPY_HW_PIN_EXT_COUNT (7)
+
// Enable USB Mass Storage with FatFS filesystem.
#define MICROPY_HW_USB_MSC (1)
#define MICROPY_HW_USB_VID (0x2341)
#define MICROPY_HW_USB_PID (0x025e)
+#define MICROPY_HW_USB_CDC_1200BPS_TOUCH (1)
// UART 1 config.
#define MICROPY_HW_UART1_TX (8)
@@ -26,16 +28,12 @@
#define MICROPY_HW_UART1_CTS (10)
#define MICROPY_HW_UART1_RTS (11)
-// SPI 1 config.
+// SPI 1 config (non-default).
#define MICROPY_HW_SPI1_SCK (14)
#define MICROPY_HW_SPI1_MOSI (11)
#define MICROPY_HW_SPI1_MISO (8)
-// I2C0 config.
-#define MICROPY_HW_I2C0_SCL (13)
-#define MICROPY_HW_I2C0_SDA (12)
-
-// I2C1 config.
+// I2C1 config (non-default).
#define MICROPY_HW_I2C1_SCL (27)
#define MICROPY_HW_I2C1_SDA (26)
diff --git a/ports/rp2/boards/ARDUINO_NANO_RP2040_CONNECT/pins.csv b/ports/rp2/boards/ARDUINO_NANO_RP2040_CONNECT/pins.csv
new file mode 100644
index 000000000000..1e42a4f8def2
--- /dev/null
+++ b/ports/rp2/boards/ARDUINO_NANO_RP2040_CONNECT/pins.csv
@@ -0,0 +1,28 @@
+TX,GPIO0
+RX,GPIO1
+D2,GPIO25
+D3,GPIO15
+D4,GPIO16
+D5,GPIO17
+D6,GPIO18
+D7,GPIO19
+D8,GPIO20
+D9,GPIO21
+D10,GPIO5
+D11,GPIO7
+D12,GPIO4
+D13,GPIO6
+LED,GPIO6
+A0,GPIO26
+A1,GPIO27
+A2,GPIO28
+A3,GPIO29
+SDA,GPIO12
+SCL,GPIO13
+LEDR,EXT_GPIO0
+LEDG,EXT_GPIO1
+LEDB,EXT_GPIO2
+D18,EXT_GPIO3
+D19,EXT_GPIO4
+D20,EXT_GPIO5
+D21,EXT_GPIO6
diff --git a/ports/rp2/boards/GARATRONIC_PYBSTICK26_RP2040/mpconfigboard.cmake b/ports/rp2/boards/GARATRONIC_PYBSTICK26_RP2040/mpconfigboard.cmake
index 9add51a78b43..11fcb3d087ec 100644
--- a/ports/rp2/boards/GARATRONIC_PYBSTICK26_RP2040/mpconfigboard.cmake
+++ b/ports/rp2/boards/GARATRONIC_PYBSTICK26_RP2040/mpconfigboard.cmake
@@ -1,3 +1 @@
# cmake file
-
-set(PICO_BOARD pybstick26_rp2040)
diff --git a/ports/rp2/boards/GARATRONIC_PYBSTICK26_RP2040/pins.csv b/ports/rp2/boards/GARATRONIC_PYBSTICK26_RP2040/pins.csv
new file mode 100644
index 000000000000..6b3bedc0e138
--- /dev/null
+++ b/ports/rp2/boards/GARATRONIC_PYBSTICK26_RP2040/pins.csv
@@ -0,0 +1 @@
+LED,GPIO23
diff --git a/ports/rp2/boards/NULLBITS_BIT_C_PRO/README.md b/ports/rp2/boards/NULLBITS_BIT_C_PRO/README.md
new file mode 100644
index 000000000000..084910841321
--- /dev/null
+++ b/ports/rp2/boards/NULLBITS_BIT_C_PRO/README.md
@@ -0,0 +1,17 @@
+# nullbits Bit-C PRO
+
+The nullbits Bit-C PRO Board is based on the Raspberry Pi RP2040, and comes in the Arduino Pro Micro footprint.
+
+
+## Board-specific modules
+
+The `board` module contains definitions for the onboard RGB LED.
+
+Example:
+
+```python
+>>> import board
+>>> board.led_red.on()
+>>> board.led_green.on()
+>>> board.led_blue.on()
+```
diff --git a/ports/rp2/boards/NULLBITS_BIT_C_PRO/board.json b/ports/rp2/boards/NULLBITS_BIT_C_PRO/board.json
new file mode 100644
index 000000000000..2aff0580d879
--- /dev/null
+++ b/ports/rp2/boards/NULLBITS_BIT_C_PRO/board.json
@@ -0,0 +1,20 @@
+{
+ "deploy": [
+ "../deploy.md"
+ ],
+ "docs": "",
+ "features": [
+ "Breadboard Friendly",
+ "RGB LED",
+ "USB-C",
+ "SPI Flash"
+ ],
+ "images": [
+ "nullbits_bit_c_pro.jpg"
+ ],
+ "mcu": "rp2040",
+ "product": "Bit-C PRO",
+ "thumbnail": "",
+ "url": "https://nullbits.co/bit-c-pro",
+ "vendor": "nullbits"
+}
diff --git a/ports/rp2/boards/NULLBITS_BIT_C_PRO/board.py b/ports/rp2/boards/NULLBITS_BIT_C_PRO/board.py
new file mode 100644
index 000000000000..9ee8cc806faa
--- /dev/null
+++ b/ports/rp2/boards/NULLBITS_BIT_C_PRO/board.py
@@ -0,0 +1,7 @@
+from machine import Pin, Signal
+
+led_red = Signal("LED_RED", Pin.OUT, invert=True, value=0)
+led_green = Signal("LED_GREEN", Pin.OUT, invert=True, value=0)
+led_blue = Signal("LED_BLUE", Pin.OUT, invert=True, value=0)
+
+del Pin
diff --git a/ports/rp2/boards/NULLBITS_BIT_C_PRO/manifest.py b/ports/rp2/boards/NULLBITS_BIT_C_PRO/manifest.py
new file mode 100644
index 000000000000..3a6af47a16b1
--- /dev/null
+++ b/ports/rp2/boards/NULLBITS_BIT_C_PRO/manifest.py
@@ -0,0 +1,2 @@
+include("$(PORT_DIR)/boards/manifest.py")
+module("board.py")
diff --git a/ports/rp2/boards/NULLBITS_BIT_C_PRO/mpconfigboard.cmake b/ports/rp2/boards/NULLBITS_BIT_C_PRO/mpconfigboard.cmake
new file mode 100644
index 000000000000..050ca347be48
--- /dev/null
+++ b/ports/rp2/boards/NULLBITS_BIT_C_PRO/mpconfigboard.cmake
@@ -0,0 +1,10 @@
+# cmake file for nullbits Bit-C PRO
+
+# The Bit-C PRO is not yet in upstream pico-sdk, so define it here
+# See also: https://github.com/raspberrypi/pico-sdk/tree/master/src/boards/include/boards
+list(APPEND PICO_BOARD_HEADER_DIRS ${MICROPY_BOARD_DIR})
+
+set(PICO_BOARD "nullbits_bit_c_pro")
+
+# Freeze board.py
+set(MICROPY_FROZEN_MANIFEST ${MICROPY_BOARD_DIR}/manifest.py)
diff --git a/ports/rp2/boards/NULLBITS_BIT_C_PRO/mpconfigboard.h b/ports/rp2/boards/NULLBITS_BIT_C_PRO/mpconfigboard.h
new file mode 100644
index 000000000000..e28c379fa70e
--- /dev/null
+++ b/ports/rp2/boards/NULLBITS_BIT_C_PRO/mpconfigboard.h
@@ -0,0 +1,9 @@
+// https://nullbits.co/bit-c-pro
+
+#define MICROPY_HW_BOARD_NAME "nullbits Bit-C PRO"
+#define MICROPY_HW_FLASH_STORAGE_BYTES (PICO_FLASH_SIZE_BYTES - (1 * 512 * 1024)) // 512K reserved
+
+// RGB LED, active low
+// Red LED 16
+// Green LED 17
+// Blue LED 18
diff --git a/ports/rp2/boards/NULLBITS_BIT_C_PRO/nullbits_bit_c_pro.h b/ports/rp2/boards/NULLBITS_BIT_C_PRO/nullbits_bit_c_pro.h
new file mode 100644
index 000000000000..2e8b03a43037
--- /dev/null
+++ b/ports/rp2/boards/NULLBITS_BIT_C_PRO/nullbits_bit_c_pro.h
@@ -0,0 +1,96 @@
+// Board definition for the nullbits Bit-C PRO
+
+#ifndef _BOARDS_NULLBITS_BIT_C_PRO_H
+#define _BOARDS_NULLBITS_BIT_C_PRO_H
+
+// For board detection
+#define NULLBITS_BIT_C_PRO
+
+// On some samples, the xosc can take longer to stabilize than is usual
+#ifndef PICO_XOSC_STARTUP_DELAY_MULTIPLIER
+#define PICO_XOSC_STARTUP_DELAY_MULTIPLIER 64
+#endif
+
+// --- BOARD SPECIFIC ---
+#define BIT_C_PRO_LED_R_PIN 16
+#define BIT_C_PRO_LED_G_PIN 17
+#define BIT_C_PRO_LED_B_PIN 18
+
+// ------------- UART -------------//
+#ifndef PICO_DEFAULT_UART
+#define PICO_DEFAULT_UART 0
+#endif
+
+#ifndef PICO_DEFAULT_UART_TX_PIN
+#define PICO_DEFAULT_UART_TX_PIN 0
+#endif
+
+#ifndef PICO_DEFAULT_UART_RX_PIN
+#define PICO_DEFAULT_UART_RX_PIN 1
+#endif
+
+// --- LED ---
+// Set the default LED to the Bit-C PRO's B led
+#ifndef PICO_DEFAULT_LED_PIN
+#define PICO_DEFAULT_LED_PIN BIT_C_PRO_LED_B_PIN
+#endif
+
+#ifndef PICO_DEFAULT_LED_PIN_INVERTED
+#define PICO_DEFAULT_LED_PIN_INVERTED 1
+#endif
+// no PICO_DEFAULT_WS2812_PIN
+
+// ------------- I2C -------------//
+#ifndef PICO_DEFAULT_I2C
+#define PICO_DEFAULT_I2C 0
+#endif
+
+#ifndef PICO_DEFAULT_I2C_SDA_PIN
+#define PICO_DEFAULT_I2C_SDA_PIN 2
+#endif
+
+#ifndef PICO_DEFAULT_I2C_SCL_PIN
+#define PICO_DEFAULT_I2C_SCL_PIN 3
+#endif
+
+// ------------- SPI -------------//
+#ifndef PICO_DEFAULT_SPI
+#define PICO_DEFAULT_SPI 0
+#endif
+
+#ifndef PICO_DEFAULT_SPI_TX_PIN
+#define PICO_DEFAULT_SPI_TX_PIN 23
+#endif
+
+#ifndef PICO_DEFAULT_SPI_RX_PIN
+#define PICO_DEFAULT_SPI_RX_PIN 20
+#endif
+
+#ifndef PICO_DEFAULT_SPI_SCK_PIN
+#define PICO_DEFAULT_SPI_SCK_PIN 22
+#endif
+
+#ifndef PICO_DEFAULT_SPI_CSN_PIN
+#define PICO_DEFAULT_SPI_CSN_PIN 21
+#endif
+
+// ------------- FLASH -------------//
+
+// Best performance/compatibility with selected flash
+#define PICO_BOOT_STAGE2_CHOOSE_W25X10CL 1
+
+#ifndef PICO_FLASH_SPI_CLKDIV
+#define PICO_FLASH_SPI_CLKDIV 2
+#endif
+
+// Bit-C PRO has 4MB SPI flash
+#ifndef PICO_FLASH_SIZE_BYTES
+#define PICO_FLASH_SIZE_BYTES (4 * 1024 * 1024)
+#endif
+
+// All boards have B1+ RP2040
+#ifndef PICO_RP2040_B0_SUPPORTED
+#define PICO_RP2040_B0_SUPPORTED 0
+#endif
+
+#endif
diff --git a/ports/rp2/boards/NULLBITS_BIT_C_PRO/pins.csv b/ports/rp2/boards/NULLBITS_BIT_C_PRO/pins.csv
new file mode 100644
index 000000000000..1274effaef83
--- /dev/null
+++ b/ports/rp2/boards/NULLBITS_BIT_C_PRO/pins.csv
@@ -0,0 +1,4 @@
+LED,GPIO16
+LED_RED,GPIO16
+LED_GREEN,GPIO17
+LED_BLUE,GPIO18
diff --git a/ports/rp2/boards/PICO/mpconfigboard.h b/ports/rp2/boards/PICO/mpconfigboard.h
index 608be5355dae..7f34cffced8b 100644
--- a/ports/rp2/boards/PICO/mpconfigboard.h
+++ b/ports/rp2/boards/PICO/mpconfigboard.h
@@ -3,6 +3,3 @@
// Modified from MPY origin to reduce flash storage to accommodate larger program flash requirement
// of lvgl and its bindings. Developers should review this setting when adding additional features
#define MICROPY_HW_FLASH_STORAGE_BYTES (1024 * 1024)
-
-// Enable USB Mass Storage with FatFS filesystem.
-// #define MICROPY_HW_USB_MSC (1)
diff --git a/ports/rp2/boards/PICO/pins.csv b/ports/rp2/boards/PICO/pins.csv
new file mode 100644
index 000000000000..16e334026424
--- /dev/null
+++ b/ports/rp2/boards/PICO/pins.csv
@@ -0,0 +1,28 @@
+GP0,GPIO0
+GP1,GPIO1
+GP2,GPIO2
+GP3,GPIO3
+GP4,GPIO4
+GP5,GPIO5
+GP6,GPIO6
+GP7,GPIO7
+GP8,GPIO8
+GP9,GPIO9
+GP10,GPIO10
+GP11,GPIO11
+GP12,GPIO12
+GP13,GPIO13
+GP14,GPIO14
+GP15,GPIO15
+GP16,GPIO16
+GP17,GPIO17
+GP18,GPIO18
+GP19,GPIO19
+GP20,GPIO20
+GP21,GPIO21
+GP22,GPIO22
+GP25,GPIO25
+GP26,GPIO26
+GP27,GPIO27
+GP28,GPIO28
+LED,GPIO25
diff --git a/ports/rp2/boards/PICO_W/board.json b/ports/rp2/boards/PICO_W/board.json
new file mode 100644
index 000000000000..755ba1037011
--- /dev/null
+++ b/ports/rp2/boards/PICO_W/board.json
@@ -0,0 +1,21 @@
+{
+ "deploy": [
+ "../deploy.md"
+ ],
+ "docs": "",
+ "features": [
+ "Breadboard friendly",
+ "Castellated Pads",
+ "Micro USB",
+ "WiFi"
+ ],
+ "id": "rp2-pico-w",
+ "images": [
+ "rp2-pico-w.jpg"
+ ],
+ "mcu": "rp2040",
+ "product": "Pico W",
+ "thumbnail": "",
+ "url": "https://www.raspberrypi.com/products/raspberry-pi-pico/",
+ "vendor": "Raspberry Pi"
+}
diff --git a/ports/rp2/boards/PICO_W/manifest.py b/ports/rp2/boards/PICO_W/manifest.py
new file mode 100644
index 000000000000..02d1874b52b9
--- /dev/null
+++ b/ports/rp2/boards/PICO_W/manifest.py
@@ -0,0 +1,3 @@
+include("$(PORT_DIR)/boards/manifest.py")
+
+require("bundle-networking")
diff --git a/ports/rp2/boards/PICO_W/mpconfigboard.cmake b/ports/rp2/boards/PICO_W/mpconfigboard.cmake
new file mode 100644
index 000000000000..df9d70c016ea
--- /dev/null
+++ b/ports/rp2/boards/PICO_W/mpconfigboard.cmake
@@ -0,0 +1,6 @@
+# cmake file for Raspberry Pi Pico W
+set(MICROPY_PY_LWIP ON)
+set(MICROPY_PY_NETWORK_CYW43 ON)
+
+# Board specific version of the frozen manifest
+set(MICROPY_FROZEN_MANIFEST ${MICROPY_BOARD_DIR}/manifest.py)
diff --git a/ports/rp2/boards/PICO_W/mpconfigboard.h b/ports/rp2/boards/PICO_W/mpconfigboard.h
new file mode 100644
index 000000000000..ef812b630135
--- /dev/null
+++ b/ports/rp2/boards/PICO_W/mpconfigboard.h
@@ -0,0 +1,23 @@
+// Board and hardware specific configuration
+#define MICROPY_HW_BOARD_NAME "Raspberry Pi Pico W"
+
+// todo: We need something to check our binary size
+#define MICROPY_HW_FLASH_STORAGE_BYTES (848 * 1024)
+
+// Enable networking.
+#define MICROPY_PY_NETWORK 1
+#define MICROPY_PY_NETWORK_HOSTNAME_DEFAULT "PicoW"
+
+// CYW43 driver configuration.
+#define CYW43_USE_SPI (1)
+#define CYW43_LWIP (1)
+#define CYW43_GPIO (1)
+#define CYW43_SPI_PIO (1)
+
+// For debugging mbedtls - also set
+// Debug level (0-4) 1=warning, 2=info, 3=debug, 4=verbose
+// #define MODUSSL_MBEDTLS_DEBUG_LEVEL 1
+
+#define MICROPY_HW_PIN_EXT_COUNT CYW43_WL_GPIO_COUNT
+
+#define MICROPY_HW_PIN_RESERVED(i) ((i) == CYW43_PIN_WL_HOST_WAKE || (i) == CYW43_PIN_WL_REG_ON)
diff --git a/ports/rp2/boards/PICO_W/pins.csv b/ports/rp2/boards/PICO_W/pins.csv
new file mode 100644
index 000000000000..8debb6326e07
--- /dev/null
+++ b/ports/rp2/boards/PICO_W/pins.csv
@@ -0,0 +1,30 @@
+GP0,GPIO0
+GP1,GPIO1
+GP2,GPIO2
+GP3,GPIO3
+GP4,GPIO4
+GP5,GPIO5
+GP6,GPIO6
+GP7,GPIO7
+GP8,GPIO8
+GP9,GPIO9
+GP10,GPIO10
+GP11,GPIO11
+GP12,GPIO12
+GP13,GPIO13
+GP14,GPIO14
+GP15,GPIO15
+GP16,GPIO16
+GP17,GPIO17
+GP18,GPIO18
+GP19,GPIO19
+GP20,GPIO20
+GP21,GPIO21
+GP22,GPIO22
+GP26,GPIO26
+GP27,GPIO27
+GP28,GPIO28
+WL_GPIO0,EXT_GPIO0
+WL_GPIO1,EXT_GPIO1
+WL_GPIO2,EXT_GPIO2
+LED,EXT_GPIO0
diff --git a/ports/rp2/boards/PIMORONI_PICOLIPO_16MB/mpconfigboard.h b/ports/rp2/boards/PIMORONI_PICOLIPO_16MB/mpconfigboard.h
index 134c2ff78495..a90ef6783d66 100644
--- a/ports/rp2/boards/PIMORONI_PICOLIPO_16MB/mpconfigboard.h
+++ b/ports/rp2/boards/PIMORONI_PICOLIPO_16MB/mpconfigboard.h
@@ -11,14 +11,6 @@
#define MICROPY_HW_UART1_CTS (10)
#define MICROPY_HW_UART1_RTS (11)
-// Qwiic on I2C0
-#define MICROPY_HW_I2C0_SCL (4)
-#define MICROPY_HW_I2C0_SDA (5)
-
-#define MICROPY_HW_SPI0_SCK (18)
-#define MICROPY_HW_SPI0_MOSI (19)
-#define MICROPY_HW_SPI0_MISO (16)
-
// User LED GPIO25
// VBUS_SENSE GPIO24
diff --git a/ports/rp2/boards/PIMORONI_PICOLIPO_16MB/pins.csv b/ports/rp2/boards/PIMORONI_PICOLIPO_16MB/pins.csv
new file mode 100644
index 000000000000..e75354485d94
--- /dev/null
+++ b/ports/rp2/boards/PIMORONI_PICOLIPO_16MB/pins.csv
@@ -0,0 +1 @@
+LED,GPIO25
diff --git a/ports/rp2/boards/PIMORONI_PICOLIPO_4MB/mpconfigboard.h b/ports/rp2/boards/PIMORONI_PICOLIPO_4MB/mpconfigboard.h
index fd45547e1b28..53ade7291532 100644
--- a/ports/rp2/boards/PIMORONI_PICOLIPO_4MB/mpconfigboard.h
+++ b/ports/rp2/boards/PIMORONI_PICOLIPO_4MB/mpconfigboard.h
@@ -11,14 +11,6 @@
#define MICROPY_HW_UART1_CTS (10)
#define MICROPY_HW_UART1_RTS (11)
-// Qwiic on I2C0
-#define MICROPY_HW_I2C0_SCL (4)
-#define MICROPY_HW_I2C0_SDA (5)
-
-#define MICROPY_HW_SPI0_SCK (18)
-#define MICROPY_HW_SPI0_MOSI (19)
-#define MICROPY_HW_SPI0_MISO (16)
-
// User LED GPIO25
// VBUS_SENSE GPIO24
diff --git a/ports/rp2/boards/PIMORONI_PICOLIPO_4MB/pins.csv b/ports/rp2/boards/PIMORONI_PICOLIPO_4MB/pins.csv
new file mode 100644
index 000000000000..e75354485d94
--- /dev/null
+++ b/ports/rp2/boards/PIMORONI_PICOLIPO_4MB/pins.csv
@@ -0,0 +1 @@
+LED,GPIO25
diff --git a/ports/rp2/boards/PIMORONI_TINY2040/mpconfigboard.h b/ports/rp2/boards/PIMORONI_TINY2040/mpconfigboard.h
index 50cb2bd59936..ea40a8071b77 100644
--- a/ports/rp2/boards/PIMORONI_TINY2040/mpconfigboard.h
+++ b/ports/rp2/boards/PIMORONI_TINY2040/mpconfigboard.h
@@ -6,6 +6,7 @@
#define MICROPY_HW_USB_VID (0x16D0)
#define MICROPY_HW_USB_PID (0x08C7)
+// I2C0 (non-default)
#define MICROPY_HW_I2C0_SCL (4)
#define MICROPY_HW_I2C0_SDA (5)
diff --git a/ports/rp2/boards/PIMORONI_TINY2040/pins.csv b/ports/rp2/boards/PIMORONI_TINY2040/pins.csv
new file mode 100644
index 000000000000..e4add1b0be89
--- /dev/null
+++ b/ports/rp2/boards/PIMORONI_TINY2040/pins.csv
@@ -0,0 +1 @@
+LED,GPIO19
diff --git a/ports/rp2/boards/SPARKFUN_PROMICRO/mpconfigboard.h b/ports/rp2/boards/SPARKFUN_PROMICRO/mpconfigboard.h
index 65b29eecd151..72a9aeb373e4 100644
--- a/ports/rp2/boards/SPARKFUN_PROMICRO/mpconfigboard.h
+++ b/ports/rp2/boards/SPARKFUN_PROMICRO/mpconfigboard.h
@@ -11,12 +11,4 @@
#define MICROPY_HW_UART1_CTS (10)
#define MICROPY_HW_UART1_RTS (11)
-// Qwiic on I2C0
-#define MICROPY_HW_I2C0_SCL (17)
-#define MICROPY_HW_I2C0_SDA (16)
-
-#define MICROPY_HW_SPI0_SCK (22)
-#define MICROPY_HW_SPI0_MOSI (23)
-#define MICROPY_HW_SPI0_MISO (20)
-
// NeoPixel data GPIO25, power not toggleable
diff --git a/ports/rp2/boards/SPARKFUN_THINGPLUS/mpconfigboard.h b/ports/rp2/boards/SPARKFUN_THINGPLUS/mpconfigboard.h
index f88ba5dd63c8..c2ca90b96835 100644
--- a/ports/rp2/boards/SPARKFUN_THINGPLUS/mpconfigboard.h
+++ b/ports/rp2/boards/SPARKFUN_THINGPLUS/mpconfigboard.h
@@ -9,15 +9,7 @@
#define MICROPY_HW_I2C0_SCL (17)
#define MICROPY_HW_I2C0_SDA (16)
-// Qwiic on I2C1
-#define MICROPY_HW_I2C1_SCL (7)
-#define MICROPY_HW_I2C1_SDA (6)
-
-#define MICROPY_HW_SPI0_SCK (2)
-#define MICROPY_HW_SPI0_MOSI (3)
-#define MICROPY_HW_SPI0_MISO (4)
-
-// MicroSD on SPI1
+// MicroSD on SPI1 (non-default)
#define MICROPY_HW_SPI1_SCK (14)
#define MICROPY_HW_SPI1_MOSI (15)
#define MICROPY_HW_SPI1_MISO (12)
diff --git a/ports/rp2/boards/SPARKFUN_THINGPLUS/pins.csv b/ports/rp2/boards/SPARKFUN_THINGPLUS/pins.csv
new file mode 100644
index 000000000000..e75354485d94
--- /dev/null
+++ b/ports/rp2/boards/SPARKFUN_THINGPLUS/pins.csv
@@ -0,0 +1 @@
+LED,GPIO25
diff --git a/ports/rp2/boards/W5100S_EVB_PICO/manifest.py b/ports/rp2/boards/W5100S_EVB_PICO/manifest.py
new file mode 100644
index 000000000000..02d1874b52b9
--- /dev/null
+++ b/ports/rp2/boards/W5100S_EVB_PICO/manifest.py
@@ -0,0 +1,3 @@
+include("$(PORT_DIR)/boards/manifest.py")
+
+require("bundle-networking")
diff --git a/ports/rp2/boards/W5100S_EVB_PICO/mpconfigboard.cmake b/ports/rp2/boards/W5100S_EVB_PICO/mpconfigboard.cmake
index bc5d1ea65e8b..5de986fabc4e 100644
--- a/ports/rp2/boards/W5100S_EVB_PICO/mpconfigboard.cmake
+++ b/ports/rp2/boards/W5100S_EVB_PICO/mpconfigboard.cmake
@@ -1,4 +1,5 @@
# cmake file for Wiznet W5100S-EVB-Pico.
-set(PICO_BOARD pico)
+set(PICO_BOARD wiznet_w5100s_evb_pico)
set(MICROPY_PY_NETWORK_WIZNET5K W5100S)
set(MICROPY_PY_LWIP 1)
+set(MICROPY_FROZEN_MANIFEST ${MICROPY_BOARD_DIR}/manifest.py)
diff --git a/ports/rp2/boards/W5100S_EVB_PICO/mpconfigboard.h b/ports/rp2/boards/W5100S_EVB_PICO/mpconfigboard.h
index 3816e40138b7..323cee7a69f5 100644
--- a/ports/rp2/boards/W5100S_EVB_PICO/mpconfigboard.h
+++ b/ports/rp2/boards/W5100S_EVB_PICO/mpconfigboard.h
@@ -1,21 +1,20 @@
// Board config for Wiznet W5100S-EVB-Pico.
// Board and hardware specific configuration
-#define MICROPY_HW_BOARD_NAME "W5100S-EVB-Pico"
-#define MICROPY_HW_FLASH_STORAGE_BYTES (1408 * 1024)
+#define MICROPY_HW_BOARD_NAME "W5100S-EVB-Pico"
+#define MICROPY_HW_FLASH_STORAGE_BYTES (1408 * 1024)
-// Enable networking and sockets.
-#define MICROPY_PY_NETWORK (1)
-#define MICROPY_PY_USOCKET (1)
-#define MICROPY_PY_USSL (1)
+// Enable networking.
+#define MICROPY_PY_NETWORK (1)
+#define MICROPY_PY_NETWORK_HOSTNAME_DEFAULT "W5100S-EVB"
// Wiznet HW config.
-#define MICROPY_HW_WIZNET_SPI_ID (0)
-#define MICROPY_HW_WIZNET_SPI_BAUDRATE (20 * 1000 * 1000)
-#define MICROPY_HW_WIZNET_SPI_SCK (18)
-#define MICROPY_HW_WIZNET_SPI_MOSI (19)
-#define MICROPY_HW_WIZNET_SPI_MISO (16)
-#define MICROPY_HW_WIZNET_PIN_CS (17)
-#define MICROPY_HW_WIZNET_PIN_RST (20)
+#define MICROPY_HW_WIZNET_SPI_ID (0)
+#define MICROPY_HW_WIZNET_SPI_BAUDRATE (20 * 1000 * 1000)
+#define MICROPY_HW_WIZNET_SPI_SCK (18)
+#define MICROPY_HW_WIZNET_SPI_MOSI (19)
+#define MICROPY_HW_WIZNET_SPI_MISO (16)
+#define MICROPY_HW_WIZNET_PIN_CS (17)
+#define MICROPY_HW_WIZNET_PIN_RST (20)
// Connecting the INTN pin enables RECV interrupt handling of incoming data.
-#define MICROPY_HW_WIZNET_PIN_INTN (21)
+#define MICROPY_HW_WIZNET_PIN_INTN (21)
diff --git a/ports/rp2/boards/W5100S_EVB_PICO/pins.csv b/ports/rp2/boards/W5100S_EVB_PICO/pins.csv
new file mode 100644
index 000000000000..e75354485d94
--- /dev/null
+++ b/ports/rp2/boards/W5100S_EVB_PICO/pins.csv
@@ -0,0 +1 @@
+LED,GPIO25
diff --git a/ports/rp2/boards/W5500_EVB_PICO/board.json b/ports/rp2/boards/W5500_EVB_PICO/board.json
new file mode 100644
index 000000000000..90b3186cd6b1
--- /dev/null
+++ b/ports/rp2/boards/W5500_EVB_PICO/board.json
@@ -0,0 +1,20 @@
+{
+ "deploy": [
+ "../deploy.md"
+ ],
+ "docs": "",
+ "features": [
+ "Breadboard Friendly",
+ "Castellated Pads",
+ "Ethernet",
+ "Micro USB"
+ ],
+ "images": [
+ "W5500-EVB-Pico.jpg"
+ ],
+ "mcu": "rp2040",
+ "product": "Wiznet W5500-EVB-Pico",
+ "thumbnail": "",
+ "url": "https://www.wiznet.io/product-item/w5500-evb-pico/",
+ "vendor": "Wiznet"
+}
diff --git a/ports/rp2/boards/W5500_EVB_PICO/manifest.py b/ports/rp2/boards/W5500_EVB_PICO/manifest.py
new file mode 100644
index 000000000000..02d1874b52b9
--- /dev/null
+++ b/ports/rp2/boards/W5500_EVB_PICO/manifest.py
@@ -0,0 +1,3 @@
+include("$(PORT_DIR)/boards/manifest.py")
+
+require("bundle-networking")
diff --git a/ports/rp2/boards/W5500_EVB_PICO/mpconfigboard.cmake b/ports/rp2/boards/W5500_EVB_PICO/mpconfigboard.cmake
new file mode 100644
index 000000000000..dda5ba4e325b
--- /dev/null
+++ b/ports/rp2/boards/W5500_EVB_PICO/mpconfigboard.cmake
@@ -0,0 +1,5 @@
+# cmake file for Wiznet W5500-EVB-Pico.
+set(PICO_BOARD wiznet_w5100s_evb_pico)
+set(MICROPY_PY_NETWORK_WIZNET5K W5500)
+set(MICROPY_PY_LWIP 1)
+set(MICROPY_FROZEN_MANIFEST ${MICROPY_BOARD_DIR}/manifest.py)
diff --git a/ports/rp2/boards/W5500_EVB_PICO/mpconfigboard.h b/ports/rp2/boards/W5500_EVB_PICO/mpconfigboard.h
new file mode 100644
index 000000000000..e8526cdba491
--- /dev/null
+++ b/ports/rp2/boards/W5500_EVB_PICO/mpconfigboard.h
@@ -0,0 +1,20 @@
+// Board config for Wiznet W5500-EVB-Pico.
+
+// Board and hardware specific configuration
+#define MICROPY_HW_BOARD_NAME "W5500-EVB-Pico"
+#define MICROPY_HW_FLASH_STORAGE_BYTES (1408 * 1024)
+
+// Enable networking.
+#define MICROPY_PY_NETWORK (1)
+#define MICROPY_PY_NETWORK_HOSTNAME_DEFAULT "W5500-EVB"
+
+// Wiznet HW config.
+#define MICROPY_HW_WIZNET_SPI_ID (0)
+#define MICROPY_HW_WIZNET_SPI_BAUDRATE (20 * 1000 * 1000)
+#define MICROPY_HW_WIZNET_SPI_SCK (18)
+#define MICROPY_HW_WIZNET_SPI_MOSI (19)
+#define MICROPY_HW_WIZNET_SPI_MISO (16)
+#define MICROPY_HW_WIZNET_PIN_CS (17)
+#define MICROPY_HW_WIZNET_PIN_RST (20)
+// Connecting the INTN pin enables RECV interrupt handling of incoming data.
+#define MICROPY_HW_WIZNET_PIN_INTN (21)
diff --git a/ports/rp2/boards/W5500_EVB_PICO/pins.csv b/ports/rp2/boards/W5500_EVB_PICO/pins.csv
new file mode 100644
index 000000000000..e75354485d94
--- /dev/null
+++ b/ports/rp2/boards/W5500_EVB_PICO/pins.csv
@@ -0,0 +1 @@
+LED,GPIO25
diff --git a/ports/rp2/boards/W5500_EVB_PICO/readme.md b/ports/rp2/boards/W5500_EVB_PICO/readme.md
new file mode 100644
index 000000000000..be28286695fa
--- /dev/null
+++ b/ports/rp2/boards/W5500_EVB_PICO/readme.md
@@ -0,0 +1,18 @@
+# Wiznet W5500-EVB-Pico
+
+## Network Example
+
+To use network / socket based code, connect ethernet port to network with DHCP running:
+
+```
+>>> import network
+>>> nic = network.WIZNET5K()
+>>> nic.active(True)
+>>> nic.ifconfig()
+('0.0.0.0', '0.0.0.0', '0.0.0.0', '0.0.0.0')
+>>> nic.ifconfig("dhcp")
+('192.168.0.10', '255.255.255.0', '192.168.0.1', '192.168.0.1')
+>>> nic.isconnected()
+True
+```
+At this point standard network communications libraries should work.
diff --git a/ports/rp2/boards/WEACTSTUDIO/README.md b/ports/rp2/boards/WEACTSTUDIO/README.md
new file mode 100644
index 000000000000..ae0acfd2c7b0
--- /dev/null
+++ b/ports/rp2/boards/WEACTSTUDIO/README.md
@@ -0,0 +1,34 @@
+# WeAct Studio RP2040
+
+The WeAct Studio RP2040 Board is based on the Raspberry Pi RP2040 and can be
+purchased with 2/4/8/16 MiB of flash.
+
+These boards are available from a number of resellers and often have the name
+"Pico Board RP2040". WeAct maintain the [WeActStudio.RP2040CoreBoard](https://github.com/WeActTC/WeActStudio.RP2040CoreBoard/tree/master)
+repository containing information on the board.
+
+## Build notes
+
+Builds can be configured with the `BOARD_VARIANT` parameter. Valid variants
+can be displayed with the `query-variant` target. An example:
+
+```bash
+> cd ports/rp2
+> make BOARD=WEACTSTUDIO query-variants
+VARIANTS: flash_2mb flash_4mb flash_8mb flash_16mb
+> make BOARD=WEACTSTUDIO BOARD_VARIANT=flash_8mb submodules all # Build the 8 MiB variant
+```
+
+`flash_16mb` is the default if `BOARD_VARIANT` is not supplied.
+
+## Board-specific modules
+
+The `board` module contains definitions for the onboard LED and user button.
+
+Example:
+
+```python
+> import board
+> board.led.toggle() # Toggles the state of the on-board LED
+> board.key.value() # Returns 0 or 1 corresponding to the state of the user key
+```
diff --git a/ports/rp2/boards/WEACTSTUDIO/board.json b/ports/rp2/boards/WEACTSTUDIO/board.json
new file mode 100644
index 000000000000..bac5263627ba
--- /dev/null
+++ b/ports/rp2/boards/WEACTSTUDIO/board.json
@@ -0,0 +1,23 @@
+{
+ "deploy": [
+ "deploy.md"
+ ],
+ "docs": "",
+ "features": [
+ "Breadboard Friendly",
+ "SPI Flash",
+ "USB-C"
+ ],
+ "images": [
+ "weact_rp2040.jpg"
+ ],
+ "mcu": "rp2040",
+ "product": "WeAct Studio RP2040",
+ "url": "https://github.com/WeActTC/WeActStudio.RP2040CoreBoard",
+ "variants": {
+ "flash_2mb": "2 MiB Flash",
+ "flash_4mb": "4 MiB Flash",
+ "flash_8mb": "8 MiB Flash"
+ },
+ "vendor": "WeAct"
+}
diff --git a/ports/rp2/boards/WEACTSTUDIO/deploy.md b/ports/rp2/boards/WEACTSTUDIO/deploy.md
new file mode 100644
index 000000000000..b4db7675ebb5
--- /dev/null
+++ b/ports/rp2/boards/WEACTSTUDIO/deploy.md
@@ -0,0 +1,8 @@
+### Flashing via UF2 bootloader
+
+To get the board in bootloader mode ready for the firmware update, execute
+`machine.bootloader()` at the MicroPython REPL. Alternatively, hold
+down the BOOTSEL button while pressing reset (NRST). The uf2 file below
+should then be copied to the USB mass storage device that appears. Once
+programming of the new firmware is complete the device will automatically reset
+and be ready for use.
diff --git a/ports/rp2/boards/WEACTSTUDIO/manifest.py b/ports/rp2/boards/WEACTSTUDIO/manifest.py
new file mode 100644
index 000000000000..f993d4fa6bd2
--- /dev/null
+++ b/ports/rp2/boards/WEACTSTUDIO/manifest.py
@@ -0,0 +1,2 @@
+include("$(PORT_DIR)/boards/manifest.py")
+freeze("./modules")
diff --git a/ports/rp2/boards/WEACTSTUDIO/modules/board.py b/ports/rp2/boards/WEACTSTUDIO/modules/board.py
new file mode 100644
index 000000000000..dd3b31b805fd
--- /dev/null
+++ b/ports/rp2/boards/WEACTSTUDIO/modules/board.py
@@ -0,0 +1,4 @@
+from machine import Pin
+
+led = Pin(25, Pin.OUT, value=0)
+key = Pin(23, Pin.IN, Pin.PULL_UP)
diff --git a/ports/rp2/boards/WEACTSTUDIO/mpconfigboard.cmake b/ports/rp2/boards/WEACTSTUDIO/mpconfigboard.cmake
new file mode 100644
index 000000000000..5fd3eec897b3
--- /dev/null
+++ b/ports/rp2/boards/WEACTSTUDIO/mpconfigboard.cmake
@@ -0,0 +1,26 @@
+# CMake file for WeAct Studio RP2040 boards
+
+# The WeAct Studio boards don't have official pico-sdk support so we define it
+# See also: https://github.com/raspberrypi/pico-sdk/tree/master/src/boards/include/boards
+list(APPEND PICO_BOARD_HEADER_DIRS ${MICROPY_BOARD_DIR})
+
+# Freeze board.py
+set(MICROPY_FROZEN_MANIFEST ${MICROPY_BOARD_DIR}/manifest.py)
+
+# Provide different variants for the downloads page
+set(BOARD_VARIANTS "flash_2mb flash_4mb flash_8mb flash_16mb")
+
+# Select the 16MB variant as the default
+set(PICO_BOARD "weactstudio_16mb")
+
+if("${BOARD_VARIANT}" STREQUAL "flash_2mb")
+ set(PICO_BOARD "weactstudio_2mb")
+endif()
+
+if("${BOARD_VARIANT}" STREQUAL "flash_4mb")
+set(PICO_BOARD "weactstudio_4mb")
+endif()
+
+if("${BOARD_VARIANT}" STREQUAL "flash_8mb")
+set(PICO_BOARD "weactstudio_8mb")
+endif()
diff --git a/ports/rp2/boards/WEACTSTUDIO/mpconfigboard.h b/ports/rp2/boards/WEACTSTUDIO/mpconfigboard.h
new file mode 100644
index 000000000000..3c72ef4fca0b
--- /dev/null
+++ b/ports/rp2/boards/WEACTSTUDIO/mpconfigboard.h
@@ -0,0 +1,4 @@
+#define MICROPY_HW_BOARD_NAME "WeAct Studio RP2040"
+
+// Allow 1MB for the firmware image itself, allocate the remainder to the filesystem
+#define MICROPY_HW_FLASH_STORAGE_BYTES (PICO_FLASH_SIZE_BYTES - (1 * 1024 * 1024))
diff --git a/ports/rp2/boards/WEACTSTUDIO/pins.csv b/ports/rp2/boards/WEACTSTUDIO/pins.csv
new file mode 100644
index 000000000000..e75354485d94
--- /dev/null
+++ b/ports/rp2/boards/WEACTSTUDIO/pins.csv
@@ -0,0 +1 @@
+LED,GPIO25
diff --git a/ports/rp2/boards/WEACTSTUDIO/weactstudio_16mb.h b/ports/rp2/boards/WEACTSTUDIO/weactstudio_16mb.h
new file mode 100644
index 000000000000..b6208c68972c
--- /dev/null
+++ b/ports/rp2/boards/WEACTSTUDIO/weactstudio_16mb.h
@@ -0,0 +1,18 @@
+// A pico-sdk board definition is required since the WeAct Studio boards are
+// not officially supported.
+//
+// Officially supported boards:
+// https://github.com/raspberrypi/pico-sdk/tree/master/src/boards/include/boards
+
+#ifndef _BOARDS_WEACTSTUDIO_16MB_H
+#define _BOARDS_WEACTSTUDIO_16MB_H
+
+#include "weactstudio_common.h"
+
+#define WEACTSTUDIO_16MB
+
+#ifndef PICO_FLASH_SIZE_BYTES
+#define PICO_FLASH_SIZE_BYTES (16 * 1024 * 1024)
+#endif
+
+#endif
diff --git a/ports/rp2/boards/WEACTSTUDIO/weactstudio_2mb.h b/ports/rp2/boards/WEACTSTUDIO/weactstudio_2mb.h
new file mode 100644
index 000000000000..e6a21ea3bc3f
--- /dev/null
+++ b/ports/rp2/boards/WEACTSTUDIO/weactstudio_2mb.h
@@ -0,0 +1,18 @@
+// A pico-sdk board definition is required since the WeAct Studio boards are
+// not officially supported.
+//
+// Officially supported boards:
+// https://github.com/raspberrypi/pico-sdk/tree/master/src/boards/include/boards
+
+#ifndef _BOARDS_WEACTSTUDIO_2MB_H
+#define _BOARDS_WEACTSTUDIO_2MB_H
+
+#include "weactstudio_common.h"
+
+#define WEACTSTUDIO_2MB
+
+#ifndef PICO_FLASH_SIZE_BYTES
+#define PICO_FLASH_SIZE_BYTES (2 * 1024 * 1024)
+#endif
+
+#endif
diff --git a/ports/rp2/boards/WEACTSTUDIO/weactstudio_4mb.h b/ports/rp2/boards/WEACTSTUDIO/weactstudio_4mb.h
new file mode 100644
index 000000000000..7a2836ab4a3f
--- /dev/null
+++ b/ports/rp2/boards/WEACTSTUDIO/weactstudio_4mb.h
@@ -0,0 +1,18 @@
+// A pico-sdk board definition is required since the WeAct Studio boards are
+// not officially supported.
+//
+// Officially supported boards:
+// https://github.com/raspberrypi/pico-sdk/tree/master/src/boards/include/boards
+
+#ifndef _BOARDS_WEACTSTUDIO_4MB_H
+#define _BOARDS_WEACTSTUDIO_4MB_H
+
+#include "weactstudio_common.h"
+
+#define WEACTSTUDIO_4MB
+
+#ifndef PICO_FLASH_SIZE_BYTES
+#define PICO_FLASH_SIZE_BYTES (4 * 1024 * 1024)
+#endif
+
+#endif
diff --git a/ports/rp2/boards/WEACTSTUDIO/weactstudio_8mb.h b/ports/rp2/boards/WEACTSTUDIO/weactstudio_8mb.h
new file mode 100644
index 000000000000..82baf6688e83
--- /dev/null
+++ b/ports/rp2/boards/WEACTSTUDIO/weactstudio_8mb.h
@@ -0,0 +1,18 @@
+// A pico-sdk board definition is required since the WeAct Studio boards are
+// not officially supported.
+//
+// Officially supported boards:
+// https://github.com/raspberrypi/pico-sdk/tree/master/src/boards/include/boards
+
+#ifndef _BOARDS_WEACTSTUDIO_8MB_H
+#define _BOARDS_WEACTSTUDIO_8MB_H
+
+#include "weactstudio_common.h"
+
+#define WEACTSTUDIO_8MB
+
+#ifndef PICO_FLASH_SIZE_BYTES
+#define PICO_FLASH_SIZE_BYTES (8 * 1024 * 1024)
+#endif
+
+#endif
diff --git a/ports/rp2/boards/WEACTSTUDIO/weactstudio_common.h b/ports/rp2/boards/WEACTSTUDIO/weactstudio_common.h
new file mode 100644
index 000000000000..f1c690360133
--- /dev/null
+++ b/ports/rp2/boards/WEACTSTUDIO/weactstudio_common.h
@@ -0,0 +1,62 @@
+// Common configuration to all WeAct Studio boards (only flash size differs)
+
+#ifndef _BOARDS_WEACTSTUDIO_COMMON_H
+#define _BOARDS_WEACTSTUDIO_COMMON_H
+
+// --- UART ---
+#ifndef PICO_DEFAULT_UART
+#define PICO_DEFAULT_UART 0
+#endif
+#ifndef PICO_DEFAULT_UART_TX_PIN
+#define PICO_DEFAULT_UART_TX_PIN 0
+#endif
+#ifndef PICO_DEFAULT_UART_RX_PIN
+#define PICO_DEFAULT_UART_RX_PIN 1
+#endif
+
+// --- LED ---
+#ifndef PICO_DEFAULT_LED_PIN
+#define PICO_DEFAULT_LED_PIN 25
+#endif
+
+// --- I2C ---
+#ifndef PICO_DEFAULT_I2C
+#define PICO_DEFAULT_I2C 0
+#endif
+#ifndef PICO_DEFAULT_I2C_SDA_PIN
+#define PICO_DEFAULT_I2C_SDA_PIN 4
+#endif
+#ifndef PICO_DEFAULT_I2C_SCL_PIN
+#define PICO_DEFAULT_I2C_SCL_PIN 5
+#endif
+
+// --- SPI ---
+#ifndef PICO_DEFAULT_SPI
+#define PICO_DEFAULT_SPI 0
+#endif
+#ifndef PICO_DEFAULT_SPI_SCK_PIN
+#define PICO_DEFAULT_SPI_SCK_PIN 18
+#endif
+#ifndef PICO_DEFAULT_SPI_TX_PIN
+#define PICO_DEFAULT_SPI_TX_PIN 19
+#endif
+#ifndef PICO_DEFAULT_SPI_RX_PIN
+#define PICO_DEFAULT_SPI_RX_PIN 16
+#endif
+#ifndef PICO_DEFAULT_SPI_CSN_PIN
+#define PICO_DEFAULT_SPI_CSN_PIN 17
+#endif
+
+// --- FLASH ---
+#define PICO_BOOT_STAGE2_CHOOSE_W25Q080 1
+
+#ifndef PICO_FLASH_SPI_CLKDIV
+#define PICO_FLASH_SPI_CLKDIV 2
+#endif
+
+// All boards have B1 RP2040
+#ifndef PICO_RP2040_B0_SUPPORTED
+#define PICO_RP2040_B0_SUPPORTED 0
+#endif
+
+#endif
diff --git a/ports/rp2/boards/make-pins.py b/ports/rp2/boards/make-pins.py
new file mode 100755
index 000000000000..55e7ebe01fe6
--- /dev/null
+++ b/ports/rp2/boards/make-pins.py
@@ -0,0 +1,428 @@
+#!/usr/bin/env python
+"""Creates the pin file for the RP2."""
+
+from __future__ import print_function
+
+import argparse
+import sys
+import csv
+import re
+
+SUPPORTED_FN = {
+ "SPI": ["TX", "RX", "SCK", "CS"],
+ "UART": ["TX", "RX", "CTS", "RTS"],
+ "I2C": ["SCL", "SDA"],
+ "PWM": ["A", "B"],
+ "SIO": [""],
+ "PIO0": [""],
+ "PIO1": [""],
+ "GPCK": ["GPIN0", "GPOUT0", "GPIN1", "GPOUT1", "GPOUT2", "GPOUT3"],
+ "USB": ["OVCUR_DET", "VBUS_DET", "VBUS_EN"],
+}
+
+
+def parse_pin(name_str):
+ """Parses a string and returns a pin number."""
+ if len(name_str) < 2:
+ raise ValueError("Expecting pin name to be at least 2 charcters.")
+ if not name_str.startswith("GPIO") and not name_str.startswith("EXT_GPIO"):
+ raise ValueError("Expecting pin name to start with EXT_/GPIO")
+ return int(re.findall(r"\d+$", name_str)[0])
+
+
+def split_name_num(name_num):
+ num = None
+ for num_idx in range(len(name_num) - 1, -1, -1):
+ if not name_num[num_idx].isdigit():
+ name = name_num[0 : num_idx + 1]
+ num_str = name_num[num_idx + 1 :]
+ if len(num_str) > 0:
+ num = int(num_str)
+ break
+ if name == "PIO":
+ name += str(num)
+ return name, num
+
+
+class AlternateFunction(object):
+ """Holds the information associated with a pins alternate function."""
+
+ def __init__(self, idx, af_str):
+ self.idx = idx
+ self.af_str = af_str
+
+ self.func = ""
+ self.fn_num = None
+ self.pin_type = ""
+ self.supported = False
+
+ af_words = af_str.split("_", 1)
+ self.func, self.fn_num = split_name_num(af_words[0])
+ if len(af_words) > 1:
+ self.pin_type = af_words[1]
+ if self.func in SUPPORTED_FN:
+ pin_types = SUPPORTED_FN[self.func]
+ if self.pin_type in pin_types:
+ self.supported = True
+
+ def is_supported(self):
+ return self.supported
+
+ def ptr(self):
+ """Returns the numbered function (i.e. USART6) for this AF."""
+ if self.fn_num is None:
+ return self.func
+ return "{:s}{:d}".format(self.func, self.fn_num)
+
+ def mux_name(self):
+ return "AF{:d}_{:s}".format(self.idx, self.ptr())
+
+ def print(self):
+ """Prints the C representation of this AF."""
+ if self.supported:
+ print(" AF", end="")
+ else:
+ print(" //", end="")
+ fn_num = self.fn_num
+ if fn_num is None:
+ fn_num = 0
+ print("({:d}, {:4s}, {:d}), // {:s}".format(self.idx, self.func, fn_num, self.af_str))
+
+ def qstr_list(self):
+ return [self.mux_name()]
+
+
+class Pin(object):
+ """Holds the information associated with a pin."""
+
+ def __init__(self, pin, is_ext=False):
+ self.pin = pin
+ self.alt_fn = []
+ self.alt_fn_count = 0
+ self.is_board = False
+ self.is_ext = is_ext
+
+ def cpu_pin_name(self):
+ return "{:s}GPIO{:d}".format("EXT_" if self.is_ext else "", self.pin)
+
+ def is_board_pin(self):
+ return self.is_board
+
+ def set_is_board_pin(self):
+ self.is_board = True
+
+ def parse_af(self, af_idx, af_strs_in):
+ if len(af_strs_in) == 0:
+ return
+ # If there is a slash, then the slash separates 2 aliases for the
+ # same alternate function.
+ af_strs = af_strs_in.split("/")
+ for af_str in af_strs:
+ alt_fn = AlternateFunction(af_idx, af_str)
+ self.alt_fn.append(alt_fn)
+ if alt_fn.is_supported():
+ self.alt_fn_count += 1
+
+ def alt_fn_name(self, null_if_0=False):
+ if null_if_0 and self.alt_fn_count == 0:
+ return "NULL"
+ return "pin_{:s}_af".format(self.cpu_pin_name())
+
+ def print(self):
+ if self.is_ext:
+ print("#if (MICROPY_HW_PIN_EXT_COUNT > {:d})".format(self.pin))
+
+ if self.alt_fn_count == 0:
+ print("// ", end="")
+ print("const machine_pin_af_obj_t {:s}[] = {{".format(self.alt_fn_name()))
+ for alt_fn in self.alt_fn:
+ alt_fn.print()
+ if self.alt_fn_count == 0:
+ print("// ", end="")
+ print("};")
+ print("")
+ print(
+ "{:s}machine_pin_obj_t pin_{:s} = PIN({:d}, {:s}, {:d}, {:d}, {:s});".format(
+ "" if self.is_ext else "const ",
+ self.cpu_pin_name(),
+ self.pin,
+ self.cpu_pin_name(),
+ self.is_ext,
+ self.alt_fn_count,
+ self.alt_fn_name(null_if_0=True),
+ )
+ )
+ if self.is_ext:
+ print("#endif")
+ print("")
+
+ def print_header(self, hdr_file):
+ n = self.cpu_pin_name()
+ hdr_file.write(
+ "extern{:s}machine_pin_obj_t pin_{:s};\n".format(" " if self.is_ext else " const ", n)
+ )
+ if self.alt_fn_count > 0:
+ hdr_file.write("extern const machine_pin_af_obj_t pin_{:s}_af[];\n".format(n))
+
+ def qstr_list(self):
+ result = []
+ for alt_fn in self.alt_fn:
+ if alt_fn.is_supported():
+ result += alt_fn.qstr_list()
+ return result
+
+
+class NamedPin(object):
+ def __init__(self, name, pin):
+ self._name = name
+ self._pin = pin
+
+ def pin(self):
+ return self._pin
+
+ def name(self):
+ return self._name
+
+
+class Pins(object):
+ def __init__(self):
+ self.cpu_pins = [] # list of NamedPin objects
+ self.board_pins = [] # list of NamedPin objects
+ self.ext_pins = [] # list of NamedPin objects
+ for i in range(0, 10):
+ self.ext_pins.append(NamedPin("EXT_GPIO{:d}".format(i), Pin(i, True)))
+
+ def find_pin(self, pin_name):
+ for pin in self.cpu_pins:
+ if pin.name() == pin_name:
+ return pin.pin()
+
+ for pin in self.ext_pins:
+ if pin.name() == pin_name:
+ return pin.pin()
+
+ def parse_af_file(self, filename, pinname_col, af_col):
+ with open(filename, "r") as csvfile:
+ rows = csv.reader(csvfile)
+ for row in rows:
+ try:
+ pin_num = parse_pin(row[pinname_col])
+ except Exception as e:
+ # import traceback; traceback.print_exc()
+ continue
+ pin = Pin(pin_num)
+ for af_idx in range(af_col, len(row)):
+ if af_idx >= af_col:
+ pin.parse_af(af_idx, row[af_idx])
+ self.cpu_pins.append(NamedPin(pin.cpu_pin_name(), pin))
+
+ def parse_board_file(self, filename):
+ with open(filename, "r") as csvfile:
+ rows = csv.reader(csvfile)
+ for row in rows:
+ if len(row) == 0 or row[0].startswith("#"):
+ # Skip empty lines, and lines starting with "#"
+ continue
+ if len(row) != 2:
+ raise ValueError("Expecting two entries in a row")
+
+ cpu_pin_name = row[1]
+ try:
+ pin_num = parse_pin(cpu_pin_name)
+ except:
+ # import traceback; traceback.print_exc()
+ continue
+ pin = self.find_pin(cpu_pin_name)
+ if pin:
+ pin.set_is_board_pin()
+ if row[0]: # Only add board pins that have a name
+ self.board_pins.append(NamedPin(row[0], pin))
+
+ def print_table(self, label, named_pins):
+ print("")
+ print("const machine_pin_obj_t *machine_pin_{:s}_pins[] = {{".format(label))
+ for pin in named_pins:
+ if not pin.pin().is_ext:
+ print(" &pin_{},".format(pin.name()))
+ print("};")
+ print("")
+
+ def print_named(self, label, named_pins):
+ print("")
+ print(
+ "STATIC const mp_rom_map_elem_t pin_{:s}_pins_locals_dict_table[] = {{".format(label)
+ )
+ for named_pin in named_pins:
+ pin = named_pin.pin()
+ if pin.is_ext:
+ print(" #if (MICROPY_HW_PIN_EXT_COUNT > {:d})".format(pin.pin))
+ print(
+ " {{ MP_ROM_QSTR(MP_QSTR_{:s}), MP_ROM_PTR(&pin_{:s}) }},".format(
+ named_pin.name(), pin.cpu_pin_name()
+ )
+ )
+ if pin.is_ext:
+ print(" #endif")
+
+ print("};")
+ print(
+ "MP_DEFINE_CONST_DICT(pin_{:s}_pins_locals_dict, pin_{:s}_pins_locals_dict_table);".format(
+ label, label
+ )
+ )
+ print("")
+
+ def print(self):
+ for pin in self.cpu_pins:
+ pin.pin().print()
+
+ for pin in self.ext_pins:
+ if pin.pin().is_ext:
+ pin.pin().print()
+
+ self.print_table("cpu", self.cpu_pins)
+ self.print_named("cpu", self.cpu_pins + self.ext_pins)
+ self.print_named("board", self.board_pins)
+
+ def print_header(self, hdr_filename, obj_decls):
+ with open(hdr_filename, "wt") as hdr_file:
+ if obj_decls:
+ for named_pin in self.cpu_pins:
+ pin = named_pin.pin()
+ pin.print_header(hdr_file)
+ for named_pin in self.board_pins:
+ pin = named_pin.pin()
+ if pin.is_ext:
+ pin.print_header(hdr_file)
+ # provide #define's mapping board to cpu name
+ for named_pin in self.board_pins:
+ if named_pin.pin().is_board_pin():
+ hdr_file.write(
+ "#define pin_{:s} pin_{:s}\n".format(
+ named_pin.name(), named_pin.pin().cpu_pin_name()
+ )
+ )
+
+ def print_qstr(self, qstr_filename):
+ with open(qstr_filename, "wt") as qstr_file:
+ qstr_set = set([])
+ for named_pin in self.cpu_pins:
+ pin = named_pin.pin()
+ if pin.is_board_pin():
+ qstr_set |= set(pin.qstr_list())
+ qstr_set |= set([named_pin.name()])
+ for named_pin in self.board_pins:
+ qstr_set |= set([named_pin.name()])
+ for qstr in sorted(qstr_set):
+ print("Q({})".format(qstr), file=qstr_file)
+
+ def print_af_hdr(self, af_const_filename):
+ with open(af_const_filename, "wt") as af_const_file:
+ af_hdr_set = set([])
+ mux_name_width = 0
+ for named_pin in self.cpu_pins:
+ pin = named_pin.pin()
+ if pin.is_board_pin():
+ for af in pin.alt_fn:
+ if af.is_supported():
+ mux_name = af.mux_name()
+ af_hdr_set |= set([mux_name])
+ if len(mux_name) > mux_name_width:
+ mux_name_width = len(mux_name)
+ for mux_name in sorted(af_hdr_set):
+ key = "MP_OBJ_NEW_QSTR(MP_QSTR_{}),".format(mux_name)
+ val = "MP_OBJ_NEW_SMALL_INT(GPIO_{})".format(mux_name)
+ print(" { %-*s %s }," % (mux_name_width + 26, key, val), file=af_const_file)
+
+ def print_af_py(self, af_py_filename):
+ with open(af_py_filename, "wt") as af_py_file:
+ print("PINS_AF = (", file=af_py_file)
+ for named_pin in self.board_pins:
+ print(" ('%s', " % named_pin.name(), end="", file=af_py_file)
+ for af in named_pin.pin().alt_fn:
+ if af.is_supported():
+ print("(%d, '%s'), " % (af.idx, af.af_str), end="", file=af_py_file)
+ print("),", file=af_py_file)
+ print(")", file=af_py_file)
+
+
+def main():
+ parser = argparse.ArgumentParser(
+ prog="make-pins.py",
+ usage="%(prog)s [options] [command]",
+ description="Generate board specific pin file",
+ )
+ parser.add_argument(
+ "-a",
+ "--af",
+ dest="af_filename",
+ help="Specifies the alternate function file for the chip",
+ default="rp2_af.csv",
+ )
+ parser.add_argument(
+ "--af-const",
+ dest="af_const_filename",
+ help="Specifies header file for alternate function constants.",
+ default="build/pins_af_const.h",
+ )
+ parser.add_argument(
+ "--af-py",
+ dest="af_py_filename",
+ help="Specifies the filename for the python alternate function mappings.",
+ default="build/pins_af.py",
+ )
+ parser.add_argument(
+ "-b",
+ "--board",
+ dest="board_filename",
+ help="Specifies the board file",
+ )
+ parser.add_argument(
+ "-p",
+ "--prefix",
+ dest="prefix_filename",
+ help="Specifies beginning portion of generated pins file",
+ default="rp2_prefix.c",
+ )
+ parser.add_argument(
+ "-q",
+ "--qstr",
+ dest="qstr_filename",
+ help="Specifies name of generated qstr header file",
+ default="build/pins_qstr.h",
+ )
+ parser.add_argument(
+ "-r",
+ "--hdr",
+ dest="hdr_filename",
+ help="Specifies name of generated pin header file",
+ default="build/pins.h",
+ )
+ args = parser.parse_args(sys.argv[1:])
+
+ pins = Pins()
+
+ print("// This file was automatically generated by make-pins.py")
+ print("//")
+ if args.af_filename:
+ print("// --af {:s}".format(args.af_filename))
+ pins.parse_af_file(args.af_filename, 0, 1)
+
+ if args.board_filename:
+ print("// --board {:s}".format(args.board_filename))
+ pins.parse_board_file(args.board_filename)
+
+ if args.prefix_filename:
+ print("// --prefix {:s}".format(args.prefix_filename))
+ print("")
+ with open(args.prefix_filename, "r") as prefix_file:
+ print(prefix_file.read())
+ pins.print()
+ pins.print_header(args.hdr_filename, True)
+ pins.print_qstr(args.qstr_filename)
+ pins.print_af_hdr(args.af_const_filename)
+ pins.print_af_py(args.af_py_filename)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/ports/rp2/boards/manifest.py b/ports/rp2/boards/manifest.py
index b0e5e315544f..e62d02f30857 100644
--- a/ports/rp2/boards/manifest.py
+++ b/ports/rp2/boards/manifest.py
@@ -1,5 +1,6 @@
freeze("$(PORT_DIR)/modules")
-freeze("$(MPY_DIR)/drivers/onewire")
-freeze("$(MPY_DIR)/drivers/dht", "dht.py")
-include("$(MPY_DIR)/extmod/uasyncio/manifest.py")
-include("$(MPY_DIR)/drivers/neopixel/manifest.py")
+include("$(MPY_DIR)/extmod/uasyncio")
+require("onewire")
+require("ds18x20")
+require("dht")
+require("neopixel")
diff --git a/ports/rp2/boards/rp2_af.csv b/ports/rp2/boards/rp2_af.csv
new file mode 100644
index 000000000000..454f7ed2d12a
--- /dev/null
+++ b/ports/rp2/boards/rp2_af.csv
@@ -0,0 +1,31 @@
+Pin,AF1,AF2,AF3,AF4,AF5,AF6,AF7,AF8,AF9
+GPIO0,SPI0_RX,UART0_TX,I2C0_SDA,PWM0_A,SIO,PIO0,PIO1,,USB_OVCUR_DET
+GPIO1,SPI0_CS,UART0_RX,I2C0_SCL,PWM0_B,SIO,PIO0,PIO1,,USB_VBUS_DET
+GPIO2,SPI0_SCK,UART0_CTS,I2C1_SDA,PWM1_A,SIO,PIO0,PIO1,,USB_VBUS_EN
+GPIO3,SPI0_TX,UART0_RTS,I2C1_SCL,PWM1_B,SIO,PIO0,PIO1,,USB_OVCUR_DET
+GPIO4,SPI0_RX,UART1_TX,I2C0_SDA,PWM2_A,SIO,PIO0,PIO1,,USB_VBUS_DET
+GPIO5,SPI0_CS,UART1_RX,I2C0_SCL,PWM2_B,SIO,PIO0,PIO1,,USB_VBUS_EN
+GPIO6,SPI0_SCK,UART1_CTS,I2C1_SDA,PWM3_A,SIO,PIO0,PIO1,,USB_OVCUR_DET
+GPIO7,SPI0_TX,UART1_RTS,I2C1_SCL,PWM3_B,SIO,PIO0,PIO1,,USB_VBUS_DET
+GPIO8,SPI1_RX,UART1_TX,I2C0_SDA,PWM4_A,SIO,PIO0,PIO1,,USB_VBUS_EN
+GPIO9,SPI1_CS,UART1_RX,I2C0_SCL,PWM4_B,SIO,PIO0,PIO1,,USB_OVCUR_DET
+GPIO10,SPI1_SCK,UART1_CTS,I2C1_SDA,PWM5_A,SIO,PIO0,PIO1,,USB_VBUS_DET
+GPIO11,SPI1_TX,UART1_RTS,I2C1_SCL,PWM5_B,SIO,PIO0,PIO1,,USB_VBUS_EN
+GPIO12,SPI1_RX,UART0_TX,I2C0_SDA,PWM6_A,SIO,PIO0,PIO1,,USB_OVCUR_DET
+GPIO13,SPI1_CS,UART0_RX,I2C0_SCL,PWM6_B,SIO,PIO0,PIO1,,USB_VBUS_DET
+GPIO14,SPI1_SCK,UART0_CTS,I2C1_SDA,PWM7_A,SIO,PIO0,PIO1,,USB_VBUS_EN
+GPIO15,SPI1_TX,UART0_RTS,I2C1_SCL,PWM7_B,SIO,PIO0,PIO1,,USB_OVCUR_DET
+GPIO16,SPI0_RX,UART0_TX,I2C0_SDA,PWM0_A,SIO,PIO0,PIO1,,USB_VBUS_DET
+GPIO17,SPI0_CS,UART0_RX,I2C0_SCL,PWM0_B,SIO,PIO0,PIO1,,USB_VBUS_EN
+GPIO18,SPI0_SCK,UART0_CTS,I2C1_SDA,PWM1_A,SIO,PIO0,PIO1,,USB_OVCUR_DET
+GPIO19,SPI0_TX,UART0_RTS,I2C1_SCL,PWM1_B,SIO,PIO0,PIO1,,USB_VBUS_DET
+GPIO20,SPI0_RX,UART1_TX,I2C0_SDA,PWM2_A,SIO,PIO0,PIO1,GPCK_GPIN0,USB_VBUS_EN
+GPIO21,SPI0_CS,UART1_RX,I2C0_SCL,PWM2_B,SIO,PIO0,PIO1,GPCK_GPOUT0,USB_OVCUR_DET
+GPIO22,SPI0_SCK,UART1_CTS,I2C1_SDA,PWM3_A,SIO,PIO0,PIO1,GPCK_GPIN1,USB_VBUS_DET
+GPIO23,SPI0_TX,UART1_RTS,I2C1_SCL,PWM3_B,SIO,PIO0,PIO1,GPCK_GPOUT1,USB_VBUS_EN
+GPIO24,SPI1_RX,UART1_TX,I2C0_SDA,PWM4_A,SIO,PIO0,PIO1,GPCK_GPOUT2,USB_OVCUR_DET
+GPIO25,SPI1_CS,UART1_RX,I2C0_SCL,PWM4_B,SIO,PIO0,PIO1,GPCK_GPOUT3,USB_VBUS_DET
+GPIO26,SPI1_SCK,UART1_CTS,I2C1_SDA,PWM5_A,SIO,PIO0,PIO1,,USB_VBUS_EN
+GPIO27,SPI1_TX,UART1_RTS,I2C1_SCL,PWM5_B,SIO,PIO0,PIO1,,USB_OVCUR_DET
+GPIO28,SPI1_RX,UART0_TX,I2C0_SDA,PWM6_A,SIO,PIO0,PIO1,,USB_VBUS_DET
+GPIO29,SPI1_CS,UART0_RX,I2C0_SCL,PWM6_B,SIO,PIO0,PIO1,,USB_VBUS_EN
diff --git a/ports/rp2/boards/rp2_prefix.c b/ports/rp2/boards/rp2_prefix.c
new file mode 100644
index 000000000000..50f2852a8ac9
--- /dev/null
+++ b/ports/rp2/boards/rp2_prefix.c
@@ -0,0 +1,36 @@
+#include
+#include "py/obj.h"
+#include "py/mphal.h"
+#include "machine_pin.h"
+
+#define AF(af_idx, af_fn, af_unit) \
+ { \
+ .base = { &machine_pin_af_type }, \
+ .name = MP_QSTR_##af_fn, \
+ .idx = (af_idx), \
+ .fn = GPIO_FUNC_##af_fn, \
+ .unit = (af_unit), \
+ }
+
+#if MICROPY_HW_PIN_EXT_COUNT
+#define PIN(_id, _name, _is_ext, _af_num, _af_list) \
+ { \
+ .base = { &machine_pin_type }, \
+ .name = MP_QSTR_##_name, \
+ .id = (uint8_t)(_id), \
+ .is_ext = (_is_ext), \
+ .is_output = false, \
+ .last_output_value = 0, \
+ .af_num = (_af_num), \
+ .af = (_af_list), \
+ }
+#else
+#define PIN(_id, _name, _is_ext, _af_num, _af_list) \
+ { \
+ .base = { &machine_pin_type }, \
+ .name = MP_QSTR_##_name, \
+ .id = (uint8_t)(_id), \
+ .af_num = (_af_num), \
+ .af = (_af_list), \
+ }
+#endif
diff --git a/ports/rp2/cyw43_configport.h b/ports/rp2/cyw43_configport.h
new file mode 100644
index 000000000000..08cded6f1f15
--- /dev/null
+++ b/ports/rp2/cyw43_configport.h
@@ -0,0 +1,122 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2022 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_RP2_CYW43_CONFIGPORT_H
+#define MICROPY_INCLUDED_RP2_CYW43_CONFIGPORT_H
+
+// The board-level config will be included here, so it can set some CYW43 values.
+#include "py/mpconfig.h"
+#include "py/mperrno.h"
+#include "py/mphal.h"
+#include "extmod/modnetwork.h"
+#include "pendsv.h"
+
+#define CYW43_CHIPSET_FIRMWARE_INCLUDE_FILE "w43439A0_7_95_49_00_combined.h"
+#define CYW43_WIFI_NVRAM_INCLUDE_FILE "wifi_nvram_43439.h"
+#define CYW43_IOCTL_TIMEOUT_US (1000000)
+#define CYW43_SLEEP_MAX (10)
+#define CYW43_NETUTILS (1)
+#define CYW43_USE_OTP_MAC (1)
+
+#define CYW43_EPERM MP_EPERM // Operation not permitted
+#define CYW43_EIO MP_EIO // I/O error
+#define CYW43_EINVAL MP_EINVAL // Invalid argument
+#define CYW43_ETIMEDOUT MP_ETIMEDOUT // Connection timed out
+
+#define CYW43_THREAD_ENTER MICROPY_PY_LWIP_ENTER
+#define CYW43_THREAD_EXIT MICROPY_PY_LWIP_EXIT
+#define CYW43_THREAD_LOCK_CHECK
+
+#define CYW43_HOST_NAME mod_network_hostname
+
+#define CYW43_SDPCM_SEND_COMMON_WAIT \
+ if (get_core_num() == 0) { \
+ cyw43_yield(); \
+ } \
+
+#define CYW43_DO_IOCTL_WAIT \
+ if (get_core_num() == 0) { \
+ cyw43_yield(); \
+ } \
+
+#define CYW43_ARRAY_SIZE(a) MP_ARRAY_SIZE(a)
+
+#define CYW43_HAL_PIN_MODE_INPUT MP_HAL_PIN_MODE_INPUT
+#define CYW43_HAL_PIN_MODE_OUTPUT MP_HAL_PIN_MODE_OUTPUT
+#define CYW43_HAL_PIN_PULL_NONE MP_HAL_PIN_PULL_NONE
+#define CYW43_HAL_PIN_PULL_UP MP_HAL_PIN_PULL_UP
+#define CYW43_HAL_PIN_PULL_DOWN MP_HAL_PIN_PULL_DOWN
+
+#define CYW43_HAL_MAC_WLAN0 MP_HAL_MAC_WLAN0
+
+// set in SDK board header
+#define CYW43_NUM_GPIOS CYW43_WL_GPIO_COUNT
+
+#define CYW43_POST_POLL_HOOK cyw43_post_poll_hook();
+
+#define cyw43_hal_ticks_us mp_hal_ticks_us
+#define cyw43_hal_ticks_ms mp_hal_ticks_ms
+
+#define cyw43_hal_pin_obj_t mp_hal_pin_obj_t
+#define cyw43_hal_pin_config mp_hal_pin_config
+#define cyw43_hal_pin_read mp_hal_pin_read
+#define cyw43_hal_pin_low mp_hal_pin_low
+#define cyw43_hal_pin_high mp_hal_pin_high
+
+#define cyw43_hal_get_mac mp_hal_get_mac
+#define cyw43_hal_get_mac_ascii mp_hal_get_mac_ascii
+#define cyw43_hal_generate_laa_mac mp_hal_generate_laa_mac
+
+#define cyw43_schedule_internal_poll_dispatch(func) pendsv_schedule_dispatch(PENDSV_DISPATCH_CYW43, func)
+
+void cyw43_post_poll_hook(void);
+extern volatile int cyw43_has_pending;
+
+static inline void cyw43_yield(void) {
+ uint32_t my_interrupts = save_and_disable_interrupts();
+ if (!cyw43_has_pending) {
+ __WFI();
+ }
+ restore_interrupts(my_interrupts);
+}
+
+static inline void cyw43_delay_us(uint32_t us) {
+ uint32_t start = mp_hal_ticks_us();
+ while (mp_hal_ticks_us() - start < us) {
+ }
+}
+
+static inline void cyw43_delay_ms(uint32_t ms) {
+ uint32_t us = ms * 1000;
+ int32_t start = mp_hal_ticks_us();
+ while (mp_hal_ticks_us() - start < us) {
+ cyw43_yield();
+ MICROPY_EVENT_POLL_HOOK_FAST;
+ }
+}
+
+#define CYW43_EVENT_POLL_HOOK MICROPY_EVENT_POLL_HOOK_FAST
+
+#endif // MICROPY_INCLUDED_RP2_CYW43_CONFIGPORT_H
diff --git a/ports/rp2/fatfs_port.c b/ports/rp2/fatfs_port.c
index 3821d6586c13..9706b6fe7dc7 100644
--- a/ports/rp2/fatfs_port.c
+++ b/ports/rp2/fatfs_port.c
@@ -30,5 +30,5 @@
MP_WEAK DWORD get_fattime(void) {
datetime_t t;
rtc_get_datetime(&t);
- return ((2000 + t.year - 1980) << 25) | ((t.month) << 21) | ((t.day) << 16) | ((t.hour) << 11) | ((t.min) << 5) | (t.sec / 2);
+ return ((t.year - 1980) << 25) | ((t.month) << 21) | ((t.day) << 16) | ((t.hour) << 11) | ((t.min) << 5) | (t.sec / 2);
}
diff --git a/ports/rp2/lwip_inc/lwipopts.h b/ports/rp2/lwip_inc/lwipopts.h
index 55926af7e53d..691b228db5c9 100644
--- a/ports/rp2/lwip_inc/lwipopts.h
+++ b/ports/rp2/lwip_inc/lwipopts.h
@@ -24,6 +24,7 @@
#define LWIP_STATS 0
#define LWIP_NETIF_HOSTNAME 1
#define LWIP_NETIF_EXT_STATUS_CALLBACK 1
+#define LWIP_NETIF_STATUS_CALLBACK 1
#define LWIP_IPV6 0
#define LWIP_DHCP 1
diff --git a/ports/rp2/machine_adc.c b/ports/rp2/machine_adc.c
index 5f91392e142d..9e3d7f57a86e 100644
--- a/ports/rp2/machine_adc.c
+++ b/ports/rp2/machine_adc.c
@@ -113,10 +113,11 @@ STATIC const mp_rom_map_elem_t machine_adc_locals_dict_table[] = {
};
STATIC MP_DEFINE_CONST_DICT(machine_adc_locals_dict, machine_adc_locals_dict_table);
-const mp_obj_type_t machine_adc_type = {
- { &mp_type_type },
- .name = MP_QSTR_ADC,
- .print = machine_adc_print,
- .make_new = machine_adc_make_new,
- .locals_dict = (mp_obj_dict_t *)&machine_adc_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ machine_adc_type,
+ MP_QSTR_ADC,
+ MP_TYPE_FLAG_NONE,
+ make_new, machine_adc_make_new,
+ print, machine_adc_print,
+ locals_dict, &machine_adc_locals_dict
+ );
diff --git a/ports/rp2/machine_i2c.c b/ports/rp2/machine_i2c.c
index f785ad7dedf3..fc4c0723a50a 100644
--- a/ports/rp2/machine_i2c.c
+++ b/ports/rp2/machine_i2c.c
@@ -33,16 +33,27 @@
#include "hardware/i2c.h"
#define DEFAULT_I2C_FREQ (400000)
+#define DEFAULT_I2C_TIMEOUT (50000)
#ifndef MICROPY_HW_I2C0_SCL
+#if PICO_DEFAULT_I2C == 0
+#define MICROPY_HW_I2C0_SCL (PICO_DEFAULT_I2C_SCL_PIN)
+#define MICROPY_HW_I2C0_SDA (PICO_DEFAULT_I2C_SDA_PIN)
+#else
#define MICROPY_HW_I2C0_SCL (9)
#define MICROPY_HW_I2C0_SDA (8)
#endif
+#endif
#ifndef MICROPY_HW_I2C1_SCL
+#if PICO_DEFAULT_I2C == 1
+#define MICROPY_HW_I2C1_SCL (PICO_DEFAULT_I2C_SCL_PIN)
+#define MICROPY_HW_I2C1_SDA (PICO_DEFAULT_I2C_SDA_PIN)
+#else
#define MICROPY_HW_I2C1_SCL (7)
#define MICROPY_HW_I2C1_SDA (6)
#endif
+#endif
// SDA/SCL on even/odd pins, I2C0/I2C1 on even/odd pairs of pins.
#define IS_VALID_SCL(i2c, pin) (((pin) & 1) == 1 && (((pin) & 2) >> 1) == (i2c))
@@ -55,26 +66,28 @@ typedef struct _machine_i2c_obj_t {
uint8_t scl;
uint8_t sda;
uint32_t freq;
+ uint32_t timeout;
} machine_i2c_obj_t;
STATIC machine_i2c_obj_t machine_i2c_obj[] = {
- {{&machine_hw_i2c_type}, i2c0, 0, MICROPY_HW_I2C0_SCL, MICROPY_HW_I2C0_SDA, 0},
- {{&machine_hw_i2c_type}, i2c1, 1, MICROPY_HW_I2C1_SCL, MICROPY_HW_I2C1_SDA, 0},
+ {{&machine_i2c_type}, i2c0, 0, MICROPY_HW_I2C0_SCL, MICROPY_HW_I2C0_SDA, 0},
+ {{&machine_i2c_type}, i2c1, 1, MICROPY_HW_I2C1_SCL, MICROPY_HW_I2C1_SDA, 0},
};
STATIC void machine_i2c_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
machine_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in);
- mp_printf(print, "I2C(%u, freq=%u, scl=%u, sda=%u)",
- self->i2c_id, self->freq, self->scl, self->sda);
+ mp_printf(print, "I2C(%u, freq=%u, scl=%u, sda=%u, timeout=%u)",
+ self->i2c_id, self->freq, self->scl, self->sda, self->timeout);
}
mp_obj_t machine_i2c_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
- enum { ARG_id, ARG_freq, ARG_scl, ARG_sda };
+ enum { ARG_id, ARG_freq, ARG_scl, ARG_sda, ARG_timeout };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_id, MP_ARG_REQUIRED | MP_ARG_OBJ },
{ MP_QSTR_freq, MP_ARG_INT, {.u_int = DEFAULT_I2C_FREQ} },
{ MP_QSTR_scl, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
{ MP_QSTR_sda, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
+ { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = DEFAULT_I2C_TIMEOUT} },
};
// Parse args.
@@ -111,6 +124,7 @@ mp_obj_t machine_i2c_make_new(const mp_obj_type_t *type, size_t n_args, size_t n
self->freq = args[ARG_freq].u_int;
i2c_init(self->i2c_inst, self->freq);
self->freq = i2c_set_baudrate(self->i2c_inst, self->freq);
+ self->timeout = args[ARG_timeout].u_int;
gpio_set_function(self->scl, GPIO_FUNC_I2C);
gpio_set_function(self->sda, GPIO_FUNC_I2C);
gpio_set_pulls(self->scl, true, 0);
@@ -125,14 +139,14 @@ STATIC int machine_i2c_transfer_single(mp_obj_base_t *self_in, uint16_t addr, si
int ret;
bool nostop = !(flags & MP_MACHINE_I2C_FLAG_STOP);
if (flags & MP_MACHINE_I2C_FLAG_READ) {
- ret = i2c_read_blocking(self->i2c_inst, addr, buf, len, nostop);
+ ret = i2c_read_timeout_us(self->i2c_inst, addr, buf, len, nostop, self->timeout);
} else {
if (len == 0) {
// Workaround issue with hardware I2C not accepting zero-length writes.
mp_machine_soft_i2c_obj_t soft_i2c = {
.base = { &mp_machine_soft_i2c_type },
.us_delay = 500000 / self->freq + 1,
- .us_timeout = 50000,
+ .us_timeout = self->timeout,
.scl = self->scl,
.sda = self->sda,
};
@@ -147,7 +161,7 @@ STATIC int machine_i2c_transfer_single(mp_obj_base_t *self_in, uint16_t addr, si
gpio_set_function(self->sda, GPIO_FUNC_I2C);
return ret;
} else {
- ret = i2c_write_blocking(self->i2c_inst, addr, buf, len, nostop);
+ ret = i2c_write_timeout_us(self->i2c_inst, addr, buf, len, nostop, self->timeout);
}
}
if (ret < 0) {
@@ -166,11 +180,12 @@ STATIC const mp_machine_i2c_p_t machine_i2c_p = {
.transfer_single = machine_i2c_transfer_single,
};
-const mp_obj_type_t machine_hw_i2c_type = {
- { &mp_type_type },
- .name = MP_QSTR_I2C,
- .print = machine_i2c_print,
- .make_new = machine_i2c_make_new,
- .protocol = &machine_i2c_p,
- .locals_dict = (mp_obj_dict_t *)&mp_machine_i2c_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ machine_i2c_type,
+ MP_QSTR_I2C,
+ MP_TYPE_FLAG_NONE,
+ make_new, machine_i2c_make_new,
+ print, machine_i2c_print,
+ protocol, &machine_i2c_p,
+ locals_dict, &mp_machine_i2c_locals_dict
+ );
diff --git a/ports/rp2/machine_i2s.c b/ports/rp2/machine_i2s.c
index 988e88d36ffb..d5175471ae80 100644
--- a/ports/rp2/machine_i2s.c
+++ b/ports/rp2/machine_i2s.c
@@ -1137,13 +1137,14 @@ STATIC const mp_stream_p_t i2s_stream_p = {
.is_text = false,
};
-const mp_obj_type_t machine_i2s_type = {
- { &mp_type_type },
- .name = MP_QSTR_I2S,
- .print = machine_i2s_print,
- .getiter = mp_identity_getiter,
- .iternext = mp_stream_unbuffered_iter,
- .protocol = &i2s_stream_p,
- .make_new = machine_i2s_make_new,
- .locals_dict = (mp_obj_dict_t *)&machine_i2s_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ machine_i2s_type,
+ MP_QSTR_I2S,
+ MP_TYPE_FLAG_ITER_IS_STREAM,
+ make_new, machine_i2s_make_new,
+ print, machine_i2s_print,
+ protocol, &i2s_stream_p,
+ locals_dict, &machine_i2s_locals_dict
+ );
+
+MP_REGISTER_ROOT_POINTER(void *machine_i2s_obj[2]);
diff --git a/ports/rp2/machine_pin.c b/ports/rp2/machine_pin.c
index ca8de6ce253f..71eda316da1d 100644
--- a/ports/rp2/machine_pin.c
+++ b/ports/rp2/machine_pin.c
@@ -31,6 +31,7 @@
#include "py/mphal.h"
#include "shared/runtime/mpirq.h"
#include "modmachine.h"
+#include "machine_pin.h"
#include "extmod/virtpin.h"
#include "hardware/irq.h"
@@ -38,11 +39,6 @@
#include "hardware/structs/iobank0.h"
#include "hardware/structs/padsbank0.h"
-#define GPIO_MODE_IN (0)
-#define GPIO_MODE_OUT (1)
-#define GPIO_MODE_OPEN_DRAIN (2)
-#define GPIO_MODE_ALT (3)
-
// These can be or'd together.
#define GPIO_PULL_UP (1)
#define GPIO_PULL_DOWN (2)
@@ -58,10 +54,29 @@
// Open drain behaviour is simulated.
#define GPIO_IS_OPEN_DRAIN(id) (machine_pin_open_drain_mask & (1 << (id)))
-typedef struct _machine_pin_obj_t {
- mp_obj_base_t base;
- uint32_t id;
-} machine_pin_obj_t;
+#ifndef MICROPY_HW_PIN_RESERVED
+#define MICROPY_HW_PIN_RESERVED(i) (0)
+#endif
+
+MP_DEFINE_CONST_OBJ_TYPE(
+ machine_pin_af_type,
+ MP_QSTR_PinAF,
+ MP_TYPE_FLAG_NONE
+ );
+
+MP_DEFINE_CONST_OBJ_TYPE(
+ pin_cpu_pins_obj_type,
+ MP_QSTR_cpu,
+ MP_TYPE_FLAG_NONE,
+ locals_dict, &pin_cpu_pins_locals_dict
+ );
+
+MP_DEFINE_CONST_OBJ_TYPE(
+ pin_board_pins_obj_type,
+ MP_QSTR_board,
+ MP_TYPE_FLAG_NONE,
+ locals_dict, &pin_board_pins_locals_dict
+ );
typedef struct _machine_pin_irq_obj_t {
mp_irq_obj_t base;
@@ -70,43 +85,19 @@ typedef struct _machine_pin_irq_obj_t {
} machine_pin_irq_obj_t;
STATIC const mp_irq_methods_t machine_pin_irq_methods;
-
-STATIC const machine_pin_obj_t machine_pin_obj[NUM_BANK0_GPIOS] = {
- {{&machine_pin_type}, 0},
- {{&machine_pin_type}, 1},
- {{&machine_pin_type}, 2},
- {{&machine_pin_type}, 3},
- {{&machine_pin_type}, 4},
- {{&machine_pin_type}, 5},
- {{&machine_pin_type}, 6},
- {{&machine_pin_type}, 7},
- {{&machine_pin_type}, 8},
- {{&machine_pin_type}, 9},
- {{&machine_pin_type}, 10},
- {{&machine_pin_type}, 11},
- {{&machine_pin_type}, 12},
- {{&machine_pin_type}, 13},
- {{&machine_pin_type}, 14},
- {{&machine_pin_type}, 15},
- {{&machine_pin_type}, 16},
- {{&machine_pin_type}, 17},
- {{&machine_pin_type}, 18},
- {{&machine_pin_type}, 19},
- {{&machine_pin_type}, 20},
- {{&machine_pin_type}, 21},
- {{&machine_pin_type}, 22},
- {{&machine_pin_type}, 23},
- {{&machine_pin_type}, 24},
- {{&machine_pin_type}, 25},
- {{&machine_pin_type}, 26},
- {{&machine_pin_type}, 27},
- {{&machine_pin_type}, 28},
- {{&machine_pin_type}, 29},
-};
+extern const machine_pin_obj_t *machine_pin_cpu_pins[NUM_BANK0_GPIOS];
// Mask with "1" indicating that the corresponding pin is in simulated open-drain mode.
uint32_t machine_pin_open_drain_mask;
+#if MICROPY_HW_PIN_EXT_COUNT
+STATIC inline bool is_ext_pin(__unused const machine_pin_obj_t *self) {
+ return self->is_ext;
+}
+#else
+#define is_ext_pin(x) false
+#endif
+
STATIC void gpio_irq(void) {
for (int i = 0; i < 4; ++i) {
uint32_t intr = iobank0_hw->intr[i];
@@ -129,107 +120,196 @@ STATIC void gpio_irq(void) {
void machine_pin_init(void) {
memset(MP_STATE_PORT(machine_pin_irq_obj), 0, sizeof(MP_STATE_PORT(machine_pin_irq_obj)));
- irq_set_exclusive_handler(IO_IRQ_BANK0, gpio_irq);
+ irq_add_shared_handler(IO_IRQ_BANK0, gpio_irq, PICO_SHARED_IRQ_HANDLER_DEFAULT_ORDER_PRIORITY);
irq_set_enabled(IO_IRQ_BANK0, true);
+ #if MICROPY_HW_PIN_EXT_COUNT
+ machine_pin_ext_init();
+ #endif
}
void machine_pin_deinit(void) {
for (int i = 0; i < NUM_BANK0_GPIOS; ++i) {
+ if (MICROPY_HW_PIN_RESERVED(i)) {
+ continue;
+ }
gpio_set_irq_enabled(i, GPIO_IRQ_ALL, false);
}
- irq_set_enabled(IO_IRQ_BANK0, false);
irq_remove_handler(IO_IRQ_BANK0, gpio_irq);
}
+const machine_pin_obj_t *machine_pin_find_named(const mp_obj_dict_t *named_pins, mp_obj_t name) {
+ const mp_map_t *named_map = &named_pins->map;
+ mp_map_elem_t *named_elem = mp_map_lookup((mp_map_t *)named_map, name, MP_MAP_LOOKUP);
+ if (named_elem != NULL && named_elem->value != NULL) {
+ return MP_OBJ_TO_PTR(named_elem->value);
+ }
+ return NULL;
+}
+
+const machine_pin_af_obj_t *machine_pin_find_alt(const machine_pin_obj_t *pin, uint8_t fn) {
+ const machine_pin_af_obj_t *af = pin->af;
+ for (mp_uint_t i = 0; i < pin->af_num; i++, af++) {
+ if (af->fn == fn) {
+ return af;
+ }
+ }
+ return NULL;
+}
+
+const machine_pin_af_obj_t *machine_pin_find_alt_by_index(const machine_pin_obj_t *pin, mp_uint_t af_idx) {
+ const machine_pin_af_obj_t *af = pin->af;
+ for (mp_uint_t i = 0; i < pin->af_num; i++, af++) {
+ if (af->idx == af_idx) {
+ return af;
+ }
+ }
+ return NULL;
+}
+
STATIC void machine_pin_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
machine_pin_obj_t *self = self_in;
uint funcsel = GPIO_GET_FUNCSEL(self->id);
qstr mode_qst;
- if (funcsel == GPIO_FUNC_SIO) {
- if (GPIO_IS_OPEN_DRAIN(self->id)) {
- mode_qst = MP_QSTR_OPEN_DRAIN;
- } else if (GPIO_IS_OUT(self->id)) {
- mode_qst = MP_QSTR_OUT;
+ if (!is_ext_pin(self)) {
+ if (funcsel == GPIO_FUNC_SIO) {
+ if (GPIO_IS_OPEN_DRAIN(self->id)) {
+ mode_qst = MP_QSTR_OPEN_DRAIN;
+ } else if (GPIO_IS_OUT(self->id)) {
+ mode_qst = MP_QSTR_OUT;
+ } else {
+ mode_qst = MP_QSTR_IN;
+ }
} else {
- mode_qst = MP_QSTR_IN;
+ mode_qst = MP_QSTR_ALT;
}
- } else {
- mode_qst = MP_QSTR_ALT;
- }
- mp_printf(print, "Pin(%u, mode=%q", self->id, mode_qst);
- bool pull_up = false;
- if (GPIO_IS_PULL_UP(self->id)) {
- mp_printf(print, ", pull=%q", MP_QSTR_PULL_UP);
- pull_up = true;
- }
- if (GPIO_IS_PULL_DOWN(self->id)) {
- if (pull_up) {
- mp_printf(print, "|%q", MP_QSTR_PULL_DOWN);
- } else {
- mp_printf(print, ", pull=%q", MP_QSTR_PULL_DOWN);
+ mp_printf(print, "Pin(%q, mode=%q", self->name, mode_qst);
+ bool pull_up = false;
+ if (GPIO_IS_PULL_UP(self->id)) {
+ mp_printf(print, ", pull=%q", MP_QSTR_PULL_UP);
+ pull_up = true;
}
- }
- if (funcsel != GPIO_FUNC_SIO) {
- mp_printf(print, ", alt=%u", funcsel);
+ if (GPIO_IS_PULL_DOWN(self->id)) {
+ if (pull_up) {
+ mp_printf(print, "|%q", MP_QSTR_PULL_DOWN);
+ } else {
+ mp_printf(print, ", pull=%q", MP_QSTR_PULL_DOWN);
+ }
+ }
+ if (funcsel != GPIO_FUNC_SIO) {
+ const machine_pin_af_obj_t *af = machine_pin_find_alt_by_index(self, funcsel);
+ if (af == NULL) {
+ mp_printf(print, ", alt=%u", funcsel);
+ } else {
+ mp_printf(print, ", alt=%q", af->name);
+ }
+ }
+ } else {
+ #if MICROPY_HW_PIN_EXT_COUNT
+ mode_qst = (self->is_output) ? MP_QSTR_OUT : MP_QSTR_IN;
+ mp_printf(print, "Pin(%q, mode=%q", self->name, mode_qst);
+ #endif
}
mp_printf(print, ")");
}
-// pin.init(mode, pull=None, *, value=None, alt=FUNC_SIO)
+enum {
+ ARG_mode, ARG_pull, ARG_value, ARG_alt
+};
+static const mp_arg_t allowed_args[] = {
+ {MP_QSTR_mode, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE}},
+ {MP_QSTR_pull, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE}},
+ {MP_QSTR_value, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE}},
+ {MP_QSTR_alt, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = GPIO_FUNC_SIO}},
+};
+
STATIC mp_obj_t machine_pin_obj_init_helper(const machine_pin_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
- enum { ARG_mode, ARG_pull, ARG_value, ARG_alt };
- static const mp_arg_t allowed_args[] = {
- { MP_QSTR_mode, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE}},
- { MP_QSTR_pull, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE}},
- { MP_QSTR_value, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE}},
- { MP_QSTR_alt, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = GPIO_FUNC_SIO}},
- };
// parse args
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
- // set initial value (do this before configuring mode/pull)
+ if (is_ext_pin(self) && args[ARG_pull].u_obj != mp_const_none) {
+ mp_raise_ValueError("pulls are not supported for external pins");
+ }
+
+ if (is_ext_pin(self) && args[ARG_alt].u_int != GPIO_FUNC_SIO) {
+ mp_raise_ValueError("alternate functions are not supported for external pins");
+ }
+
+ // get initial value of pin (only valid for OUT and OPEN_DRAIN modes)
+ int value = -1;
if (args[ARG_value].u_obj != mp_const_none) {
- gpio_put(self->id, mp_obj_is_true(args[ARG_value].u_obj));
+ value = mp_obj_is_true(args[ARG_value].u_obj);
}
// configure mode
if (args[ARG_mode].u_obj != mp_const_none) {
mp_int_t mode = mp_obj_get_int(args[ARG_mode].u_obj);
- if (mode == GPIO_MODE_IN) {
+ if (is_ext_pin(self)) {
+ #if MICROPY_HW_PIN_EXT_COUNT
+ // The regular Pins are const, but the external pins are mutable.
+ machine_pin_obj_t *mutable_self = (machine_pin_obj_t *)self;
+ machine_pin_ext_config(mutable_self, mode, value);
+ #endif
+ } else if (mode == MACHINE_PIN_MODE_IN) {
mp_hal_pin_input(self->id);
- } else if (mode == GPIO_MODE_OUT) {
+ } else if (mode == MACHINE_PIN_MODE_OUT) {
+ if (value != -1) {
+ // set initial output value before configuring mode
+ gpio_put(self->id, value);
+ }
mp_hal_pin_output(self->id);
- } else if (mode == GPIO_MODE_OPEN_DRAIN) {
- mp_hal_pin_open_drain(self->id);
+ } else if (mode == MACHINE_PIN_MODE_OPEN_DRAIN) {
+ mp_hal_pin_open_drain_with_value(self->id, value == -1 ? 1 : value);
} else {
- // Alternate function.
- gpio_set_function(self->id, args[ARG_alt].u_int);
+ // Configure alternate function.
+ mp_uint_t af = args[ARG_alt].u_int;
+ if (machine_pin_find_alt(self, af) == NULL) {
+ mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid pin af: %d"), af);
+ }
+ gpio_set_function(self->id, af);
machine_pin_open_drain_mask &= ~(1 << self->id);
}
}
- // configure pull (unconditionally because None means no-pull)
- uint32_t pull = 0;
- if (args[ARG_pull].u_obj != mp_const_none) {
- pull = mp_obj_get_int(args[ARG_pull].u_obj);
+ if (!is_ext_pin(self)) {
+ // Configure pull (unconditionally because None means no-pull).
+ uint32_t pull = 0;
+ if (args[ARG_pull].u_obj != mp_const_none) {
+ pull = mp_obj_get_int(args[ARG_pull].u_obj);
+ }
+ gpio_set_pulls(self->id, pull & GPIO_PULL_UP, pull & GPIO_PULL_DOWN);
}
- gpio_set_pulls(self->id, pull & GPIO_PULL_UP, pull & GPIO_PULL_DOWN);
-
return mp_const_none;
}
// constructor(id, ...)
mp_obj_t mp_pin_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, MP_OBJ_FUN_ARGS_MAX, true);
-
- // get the wanted pin object
- int wanted_pin = mp_obj_get_int(args[0]);
- if (!(0 <= wanted_pin && wanted_pin < MP_ARRAY_SIZE(machine_pin_obj))) {
+ const machine_pin_obj_t *self = NULL;
+
+ if (mp_obj_is_str(args[0])) {
+ const char *name = mp_obj_str_get_str(args[0]);
+ // Try to find the pin in the board pins first.
+ self = machine_pin_find_named(&pin_board_pins_locals_dict, args[0]);
+ if (!self) {
+ // If not found, try to find the pin in the cpu pins which include
+ // CPU and and externally controlled pins (if any).
+ self = machine_pin_find_named(&pin_cpu_pins_locals_dict, args[0]);
+ }
+ if (!self) {
+ mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("unknown named pin \"%s\""), name);
+ }
+ } else if (mp_obj_is_int(args[0])) {
+ // get the wanted pin object
+ int wanted_pin = mp_obj_get_int(args[0]);
+ if (0 <= wanted_pin && wanted_pin < MP_ARRAY_SIZE(machine_pin_cpu_pins)) {
+ self = machine_pin_cpu_pins[wanted_pin];
+ }
+ }
+ if (!self) {
mp_raise_ValueError("invalid pin");
}
- const machine_pin_obj_t *self = &machine_pin_obj[wanted_pin];
if (n_args > 1 || n_kw > 0) {
// pin mode given, so configure this GPIO
@@ -237,7 +317,6 @@ mp_obj_t mp_pin_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw,
mp_map_init_fixed_table(&kw_args, n_kw, args + n_args);
machine_pin_obj_init_helper(self, n_args - 1, args + 1, &kw_args);
}
-
return MP_OBJ_FROM_PTR(self);
}
@@ -247,18 +326,28 @@ STATIC mp_obj_t machine_pin_call(mp_obj_t self_in, size_t n_args, size_t n_kw, c
machine_pin_obj_t *self = self_in;
if (n_args == 0) {
// get pin
- return MP_OBJ_NEW_SMALL_INT(gpio_get(self->id));
+ if (is_ext_pin(self)) {
+ #if MICROPY_HW_PIN_EXT_COUNT
+ return MP_OBJ_NEW_SMALL_INT(machine_pin_ext_get(self));
+ #endif
+ } else {
+ return MP_OBJ_NEW_SMALL_INT(gpio_get(self->id));
+ }
} else {
// set pin
bool value = mp_obj_is_true(args[0]);
- if (GPIO_IS_OPEN_DRAIN(self->id)) {
+ if (is_ext_pin(self)) {
+ #if MICROPY_HW_PIN_EXT_COUNT
+ machine_pin_ext_set(self, value);
+ #endif
+ } else if (GPIO_IS_OPEN_DRAIN(self->id)) {
MP_STATIC_ASSERT(GPIO_IN == 0 && GPIO_OUT == 1);
gpio_set_dir(self->id, 1 - value);
} else {
gpio_put(self->id, value);
}
- return mp_const_none;
}
+ return mp_const_none;
}
// pin.init(mode, pull)
@@ -276,7 +365,11 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_pin_value_obj, 1, 2, machine_
// pin.low()
STATIC mp_obj_t machine_pin_low(mp_obj_t self_in) {
machine_pin_obj_t *self = MP_OBJ_TO_PTR(self_in);
- if (GPIO_IS_OPEN_DRAIN(self->id)) {
+ if (is_ext_pin(self)) {
+ #if MICROPY_HW_PIN_EXT_COUNT
+ machine_pin_ext_set(self, 0);
+ #endif
+ } else if (GPIO_IS_OPEN_DRAIN(self->id)) {
gpio_set_dir(self->id, GPIO_OUT);
} else {
gpio_clr_mask(1u << self->id);
@@ -288,19 +381,28 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_pin_low_obj, machine_pin_low);
// pin.high()
STATIC mp_obj_t machine_pin_high(mp_obj_t self_in) {
machine_pin_obj_t *self = MP_OBJ_TO_PTR(self_in);
- if (GPIO_IS_OPEN_DRAIN(self->id)) {
+ if (is_ext_pin(self)) {
+ #if MICROPY_HW_PIN_EXT_COUNT
+ machine_pin_ext_set(self, 1);
+ #endif
+ } else if (GPIO_IS_OPEN_DRAIN(self->id)) {
gpio_set_dir(self->id, GPIO_IN);
} else {
gpio_set_mask(1u << self->id);
}
return mp_const_none;
}
+
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_pin_high_obj, machine_pin_high);
// pin.toggle()
STATIC mp_obj_t machine_pin_toggle(mp_obj_t self_in) {
machine_pin_obj_t *self = MP_OBJ_TO_PTR(self_in);
- if (GPIO_IS_OPEN_DRAIN(self->id)) {
+ if (is_ext_pin(self)) {
+ #if MICROPY_HW_PIN_EXT_COUNT
+ machine_pin_ext_set(self, self->last_output_value ^ 1);
+ #endif
+ } else if (GPIO_IS_OPEN_DRAIN(self->id)) {
if (GPIO_IS_OUT(self->id)) {
gpio_set_dir(self->id, GPIO_IN);
} else {
@@ -322,7 +424,7 @@ STATIC machine_pin_irq_obj_t *machine_pin_get_irq(mp_hal_pin_obj_t pin) {
irq = m_new_obj(machine_pin_irq_obj_t);
irq->base.base.type = &mp_irq_type;
irq->base.methods = (mp_irq_methods_t *)&machine_pin_irq_methods;
- irq->base.parent = MP_OBJ_FROM_PTR(&machine_pin_obj[pin]);
+ irq->base.parent = MP_OBJ_FROM_PTR(machine_pin_cpu_pins[pin]);
irq->base.handler = mp_const_none;
irq->base.ishard = false;
MP_STATE_PORT(machine_pin_irq_obj[pin]) = irq;
@@ -357,6 +459,10 @@ STATIC mp_obj_t machine_pin_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_
{ MP_QSTR_hard, MP_ARG_BOOL, {.u_bool = false} },
};
machine_pin_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
+ if (is_ext_pin(self)) {
+ mp_raise_ValueError(MP_ERROR_TEXT("expecting a regular GPIO Pin"));
+ }
+
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);
@@ -384,15 +490,30 @@ STATIC const mp_rom_map_elem_t machine_pin_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_toggle), MP_ROM_PTR(&machine_pin_toggle_obj) },
{ MP_ROM_QSTR(MP_QSTR_irq), MP_ROM_PTR(&machine_pin_irq_obj) },
+ // class attributes
+ { MP_ROM_QSTR(MP_QSTR_board), MP_ROM_PTR(&pin_board_pins_obj_type) },
+ { MP_ROM_QSTR(MP_QSTR_cpu), MP_ROM_PTR(&pin_cpu_pins_obj_type) },
+
// class constants
- { MP_ROM_QSTR(MP_QSTR_IN), MP_ROM_INT(GPIO_MODE_IN) },
- { MP_ROM_QSTR(MP_QSTR_OUT), MP_ROM_INT(GPIO_MODE_OUT) },
- { MP_ROM_QSTR(MP_QSTR_OPEN_DRAIN), MP_ROM_INT(GPIO_MODE_OPEN_DRAIN) },
- { MP_ROM_QSTR(MP_QSTR_ALT), MP_ROM_INT(GPIO_MODE_ALT) },
+ { MP_ROM_QSTR(MP_QSTR_IN), MP_ROM_INT(MACHINE_PIN_MODE_IN) },
+ { MP_ROM_QSTR(MP_QSTR_OUT), MP_ROM_INT(MACHINE_PIN_MODE_OUT) },
+ { MP_ROM_QSTR(MP_QSTR_OPEN_DRAIN), MP_ROM_INT(MACHINE_PIN_MODE_OPEN_DRAIN) },
+ { MP_ROM_QSTR(MP_QSTR_ALT), MP_ROM_INT(MACHINE_PIN_MODE_ALT) },
{ MP_ROM_QSTR(MP_QSTR_PULL_UP), MP_ROM_INT(GPIO_PULL_UP) },
{ MP_ROM_QSTR(MP_QSTR_PULL_DOWN), MP_ROM_INT(GPIO_PULL_DOWN) },
{ MP_ROM_QSTR(MP_QSTR_IRQ_RISING), MP_ROM_INT(GPIO_IRQ_EDGE_RISE) },
{ MP_ROM_QSTR(MP_QSTR_IRQ_FALLING), MP_ROM_INT(GPIO_IRQ_EDGE_FALL) },
+
+ // Pins alternate functions
+ { MP_ROM_QSTR(MP_QSTR_ALT_SPI), MP_ROM_INT(GPIO_FUNC_SPI) },
+ { MP_ROM_QSTR(MP_QSTR_ALT_UART), MP_ROM_INT(GPIO_FUNC_UART) },
+ { MP_ROM_QSTR(MP_QSTR_ALT_I2C), MP_ROM_INT(GPIO_FUNC_I2C) },
+ { MP_ROM_QSTR(MP_QSTR_ALT_PWM), MP_ROM_INT(GPIO_FUNC_PWM) },
+ { MP_ROM_QSTR(MP_QSTR_ALT_SIO), MP_ROM_INT(GPIO_FUNC_SIO) },
+ { MP_ROM_QSTR(MP_QSTR_ALT_PIO0), MP_ROM_INT(GPIO_FUNC_PIO0) },
+ { MP_ROM_QSTR(MP_QSTR_ALT_PIO1), MP_ROM_INT(GPIO_FUNC_PIO1) },
+ { MP_ROM_QSTR(MP_QSTR_ALT_GPCK), MP_ROM_INT(GPIO_FUNC_GPCK) },
+ { MP_ROM_QSTR(MP_QSTR_ALT_USB), MP_ROM_INT(GPIO_FUNC_USB) },
};
STATIC MP_DEFINE_CONST_DICT(machine_pin_locals_dict, machine_pin_locals_dict_table);
@@ -402,10 +523,22 @@ STATIC mp_uint_t pin_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, i
switch (request) {
case MP_PIN_READ: {
- return gpio_get(self->id);
+ if (is_ext_pin(self)) {
+ #if MICROPY_HW_PIN_EXT_COUNT
+ return machine_pin_ext_get(self);
+ #endif
+ } else {
+ return gpio_get(self->id);
+ }
}
case MP_PIN_WRITE: {
- gpio_put(self->id, arg);
+ if (is_ext_pin(self)) {
+ #if MICROPY_HW_PIN_EXT_COUNT
+ machine_pin_ext_set(self, arg);
+ #endif
+ } else {
+ gpio_put(self->id, arg);
+ }
return 0;
}
}
@@ -416,15 +549,16 @@ STATIC const mp_pin_p_t pin_pin_p = {
.ioctl = pin_ioctl,
};
-const mp_obj_type_t machine_pin_type = {
- { &mp_type_type },
- .name = MP_QSTR_Pin,
- .print = machine_pin_print,
- .make_new = mp_pin_make_new,
- .call = machine_pin_call,
- .protocol = &pin_pin_p,
- .locals_dict = (mp_obj_t)&machine_pin_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ machine_pin_type,
+ MP_QSTR_Pin,
+ MP_TYPE_FLAG_NONE,
+ make_new, mp_pin_make_new,
+ print, machine_pin_print,
+ call, machine_pin_call,
+ protocol, &pin_pin_p,
+ locals_dict, &machine_pin_locals_dict
+ );
STATIC mp_uint_t machine_pin_irq_trigger(mp_obj_t self_in, mp_uint_t new_trigger) {
machine_pin_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -457,5 +591,10 @@ mp_hal_pin_obj_t mp_hal_get_pin_obj(mp_obj_t obj) {
mp_raise_ValueError(MP_ERROR_TEXT("expecting a Pin"));
}
machine_pin_obj_t *pin = MP_OBJ_TO_PTR(obj);
+ if (is_ext_pin(pin)) {
+ mp_raise_ValueError(MP_ERROR_TEXT("expecting a regular GPIO Pin"));
+ }
return pin->id;
}
+
+MP_REGISTER_ROOT_POINTER(void *machine_pin_irq_obj[30]);
diff --git a/ports/rp2/machine_pin.h b/ports/rp2/machine_pin.h
new file mode 100644
index 000000000000..c10dc4f9e82f
--- /dev/null
+++ b/ports/rp2/machine_pin.h
@@ -0,0 +1,82 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2022 Ibrahim Abdelkader
+ *
+ * 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_RP2_MACHINE_PIN_H
+#define MICROPY_INCLUDED_RP2_MACHINE_PIN_H
+
+#include
+#include "py/obj.h"
+#include "py/mphal.h"
+
+enum {
+ MACHINE_PIN_MODE_IN = 0,
+ MACHINE_PIN_MODE_OUT = 1,
+ MACHINE_PIN_MODE_OPEN_DRAIN = 2,
+ MACHINE_PIN_MODE_ALT = 3
+};
+
+typedef struct _machine_pin_af_obj_t {
+ mp_obj_base_t base;
+ qstr name;
+ uint8_t idx : 4;
+ uint8_t fn : 4;
+ uint8_t unit : 8;
+} machine_pin_af_obj_t;
+
+typedef struct _machine_pin_obj_t {
+ mp_obj_base_t base;
+ qstr name;
+ uint8_t id : 5;
+ #if MICROPY_HW_PIN_EXT_COUNT
+ uint8_t is_ext : 1;
+ uint8_t is_output : 1;
+ uint8_t last_output_value : 1;
+ #endif
+ uint8_t af_num : 4;
+ const machine_pin_af_obj_t *af;
+} machine_pin_obj_t;
+
+extern const mp_obj_type_t machine_pin_type;
+extern const mp_obj_type_t machine_pin_af_type;
+
+// Include all of the individual pin objects
+#include "genhdr/pins.h"
+
+extern const mp_obj_type_t pin_cpu_pins_obj_type;
+extern const mp_obj_dict_t pin_cpu_pins_locals_dict;
+
+extern const mp_obj_type_t pin_board_pins_obj_type;
+extern const mp_obj_dict_t pin_board_pins_locals_dict;
+
+void machine_pin_ext_init(void);
+void machine_pin_ext_set(machine_pin_obj_t *self, bool value);
+bool machine_pin_ext_get(machine_pin_obj_t *self);
+void machine_pin_ext_config(machine_pin_obj_t *self, int mode, int value);
+
+const machine_pin_obj_t *machine_pin_find_named(const mp_obj_dict_t *named_pins, mp_obj_t name);
+const machine_pin_af_obj_t *machine_pin_find_alt(const machine_pin_obj_t *pin, uint8_t fn);
+const machine_pin_af_obj_t *machine_pin_find_alt_by_index(const machine_pin_obj_t *pin, mp_uint_t af_idx);
+
+#endif // MICROPY_INCLUDED_RP2_MACHINE_PIN_H
diff --git a/ports/rp2/machine_pin_cyw43.c b/ports/rp2/machine_pin_cyw43.c
new file mode 100644
index 000000000000..c09561461f18
--- /dev/null
+++ b/ports/rp2/machine_pin_cyw43.c
@@ -0,0 +1,86 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2016-2022 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"
+
+#if defined(MICROPY_PY_NETWORK_CYW43) && defined(MICROPY_HW_PIN_EXT_COUNT)
+
+#include "modmachine.h"
+#include "machine_pin.h"
+#include "lib/cyw43-driver/src/cyw43.h"
+
+void machine_pin_ext_init(void) {
+}
+
+void machine_pin_ext_set(machine_pin_obj_t *self, bool value) {
+ if (value != self->last_output_value || !self->is_output) {
+ cyw43_gpio_set(&cyw43_state, self->id, value);
+ }
+ self->last_output_value = value;
+}
+
+bool machine_pin_ext_get(machine_pin_obj_t *self) {
+ bool value = false;
+ cyw43_gpio_get(&cyw43_state, self->id, &value);
+ return value;
+}
+
+void machine_pin_ext_config(machine_pin_obj_t *self, int mode, int value) {
+ if (mode == MACHINE_PIN_MODE_IN) {
+ if (self->is_output) {
+ // TODO need to disable output
+ }
+ self->is_output = false;
+ } else if (mode == MACHINE_PIN_MODE_OUT) {
+ if (!self->is_output) {
+ // TODO need to enable output
+ // for now we just set the value
+ if (value == -1) {
+ value = self->last_output_value;
+ }
+ self->last_output_value = !self->last_output_value; // defeat shortcircuit
+ machine_pin_ext_set(self, value);
+ self->is_output = true;
+ }
+ } else {
+ mp_raise_ValueError("only Pin.OUT and Pin.IN are supported for this pin");
+ }
+
+ if (value != -1) {
+ if (self->is_output) {
+ machine_pin_ext_set(self, value);
+ } else {
+ // figure if you pass a value to IN it should still remember it (this is what regular GPIO does)
+ self->last_output_value = value;
+ }
+ }
+}
+
+#endif // defined(MICROPY_PY_NETWORK_CYW43) && defined(MICROPY_HW_PIN_EXT_COUNT)
diff --git a/ports/rp2/machine_pwm.c b/ports/rp2/machine_pwm.c
index 41dc3ab4761e..0c840eca9436 100644
--- a/ports/rp2/machine_pwm.c
+++ b/ports/rp2/machine_pwm.c
@@ -100,11 +100,33 @@ STATIC void mp_machine_pwm_deinit(machine_pwm_obj_t *self) {
pwm_set_enabled(self->slice, false);
}
-STATIC mp_obj_t mp_machine_pwm_freq_get(machine_pwm_obj_t *self) {
+// Returns: floor((16*F + offset) / div16)
+// Avoids overflow in the numerator that would occur if
+// 16*F + offset > 2**32
+// F + offset/16 > 2**28 = 268435456 (approximately, due to flooring)
+uint32_t get_slice_hz(uint32_t offset, uint32_t div16) {
uint32_t source_hz = clock_get_hz(clk_sys);
+ if (source_hz + offset / 16 > 268000000) {
+ return (16 * (uint64_t)source_hz + offset) / div16;
+ } else {
+ return (16 * source_hz + offset) / div16;
+ }
+}
+
+// Returns 16*F / denom, rounded.
+uint32_t get_slice_hz_round(uint32_t div16) {
+ return get_slice_hz(div16 / 2, div16);
+}
+
+// Returns ceil(16*F / denom).
+uint32_t get_slice_hz_ceil(uint32_t div16) {
+ return get_slice_hz(div16 - 1, div16);
+}
+
+STATIC mp_obj_t mp_machine_pwm_freq_get(machine_pwm_obj_t *self) {
uint32_t div16 = pwm_hw->slice[self->slice].div;
uint32_t top = pwm_hw->slice[self->slice].top;
- uint32_t pwm_freq = 16 * source_hz / div16 / (top + 1);
+ uint32_t pwm_freq = get_slice_hz_round(div16 * (top + 1));
return MP_OBJ_NEW_SMALL_INT(pwm_freq);
}
@@ -113,30 +135,36 @@ STATIC void mp_machine_pwm_freq_set(machine_pwm_obj_t *self, mp_int_t freq) {
// Maximum "top" is set at 65534 to be able to achieve 100% duty with 65535.
#define TOP_MAX 65534
uint32_t source_hz = clock_get_hz(clk_sys);
- uint32_t div16_top = 16 * source_hz / freq;
- uint32_t top = 1;
- for (;;) {
- // Try a few small prime factors to get close to the desired frequency.
- if (div16_top >= 16 * 5 && div16_top % 5 == 0 && top * 5 <= TOP_MAX) {
- div16_top /= 5;
- top *= 5;
- } else if (div16_top >= 16 * 3 && div16_top % 3 == 0 && top * 3 <= TOP_MAX) {
- div16_top /= 3;
- top *= 3;
- } else if (div16_top >= 16 * 2 && top * 2 <= TOP_MAX) {
- div16_top /= 2;
- top *= 2;
- } else {
- break;
- }
+ uint32_t div16;
+ uint32_t top;
+
+ if ((source_hz + freq / 2) / freq < TOP_MAX) {
+ // If possible (based on the formula for TOP below), use a DIV of 1.
+ // This also prevents overflow in the DIV calculation.
+ div16 = 16;
+
+ // Same as get_slice_hz_round() below but canceling the 16s
+ // to avoid overflow for high freq.
+ top = (source_hz + freq / 2) / freq - 1;
+ } else {
+ // Otherwise, choose the smallest possible DIV for maximum
+ // duty cycle resolution.
+ // Constraint: 16*F/(div16*freq) < TOP_MAX
+ // So:
+ div16 = get_slice_hz_ceil(TOP_MAX * freq);
+
+ // Set TOP as accurately as possible using rounding.
+ top = get_slice_hz_round(div16 * freq) - 1;
}
- if (div16_top < 16) {
+
+
+ if (div16 < 16) {
mp_raise_ValueError(MP_ERROR_TEXT("freq too large"));
- } else if (div16_top >= 256 * 16) {
+ } else if (div16 >= 256 * 16) {
mp_raise_ValueError(MP_ERROR_TEXT("freq too small"));
}
- pwm_hw->slice[self->slice].div = div16_top;
- pwm_hw->slice[self->slice].top = top - 1;
+ pwm_hw->slice[self->slice].div = div16;
+ pwm_hw->slice[self->slice].top = top;
if (self->duty_type == DUTY_U16) {
mp_machine_pwm_duty_set_u16(self, self->duty);
} else if (self->duty_type == DUTY_NS) {
@@ -148,12 +176,17 @@ STATIC mp_obj_t mp_machine_pwm_duty_get_u16(machine_pwm_obj_t *self) {
uint32_t top = pwm_hw->slice[self->slice].top;
uint32_t cc = pwm_hw->slice[self->slice].cc;
cc = (cc >> (self->channel ? PWM_CH0_CC_B_LSB : PWM_CH0_CC_A_LSB)) & 0xffff;
- return MP_OBJ_NEW_SMALL_INT(cc * 65535 / (top + 1));
+
+ // Use rounding (instead of flooring) here to give as accurate an
+ // estimate as possible.
+ return MP_OBJ_NEW_SMALL_INT((cc * 65535 + (top + 1) / 2) / (top + 1));
}
STATIC void mp_machine_pwm_duty_set_u16(machine_pwm_obj_t *self, mp_int_t duty_u16) {
uint32_t top = pwm_hw->slice[self->slice].top;
- uint32_t cc = duty_u16 * (top + 1) / 65535;
+
+ // Use rounding here to set it as accurately as possible.
+ uint32_t cc = (duty_u16 * (top + 1) + 65535 / 2) / 65535;
pwm_set_chan_level(self->slice, self->channel, cc);
pwm_set_enabled(self->slice, true);
self->duty = duty_u16;
@@ -161,17 +194,15 @@ STATIC void mp_machine_pwm_duty_set_u16(machine_pwm_obj_t *self, mp_int_t duty_u
}
STATIC mp_obj_t mp_machine_pwm_duty_get_ns(machine_pwm_obj_t *self) {
- uint32_t source_hz = clock_get_hz(clk_sys);
- uint32_t slice_hz = 16 * source_hz / pwm_hw->slice[self->slice].div;
+ uint32_t slice_hz = get_slice_hz_round(pwm_hw->slice[self->slice].div);
uint32_t cc = pwm_hw->slice[self->slice].cc;
cc = (cc >> (self->channel ? PWM_CH0_CC_B_LSB : PWM_CH0_CC_A_LSB)) & 0xffff;
- return MP_OBJ_NEW_SMALL_INT((uint64_t)cc * 1000000000ULL / slice_hz);
+ return MP_OBJ_NEW_SMALL_INT(((uint64_t)cc * 1000000000ULL + slice_hz / 2) / slice_hz);
}
STATIC void mp_machine_pwm_duty_set_ns(machine_pwm_obj_t *self, mp_int_t duty_ns) {
- uint32_t source_hz = clock_get_hz(clk_sys);
- uint32_t slice_hz = 16 * source_hz / pwm_hw->slice[self->slice].div;
- uint32_t cc = (uint64_t)duty_ns * slice_hz / 1000000000ULL;
+ uint32_t slice_hz = get_slice_hz_round(pwm_hw->slice[self->slice].div);
+ uint32_t cc = ((uint64_t)duty_ns * slice_hz + 500000000ULL) / 1000000000ULL;
if (cc > 65535) {
mp_raise_ValueError(MP_ERROR_TEXT("duty larger than period"));
}
diff --git a/ports/rp2/machine_rtc.c b/ports/rp2/machine_rtc.c
index 9d59124a66e1..a9d3426cf838 100644
--- a/ports/rp2/machine_rtc.c
+++ b/ports/rp2/machine_rtc.c
@@ -115,9 +115,10 @@ STATIC const mp_rom_map_elem_t machine_rtc_locals_dict_table[] = {
};
STATIC MP_DEFINE_CONST_DICT(machine_rtc_locals_dict, machine_rtc_locals_dict_table);
-const mp_obj_type_t machine_rtc_type = {
- { &mp_type_type },
- .name = MP_QSTR_RTC,
- .make_new = machine_rtc_make_new,
- .locals_dict = (mp_obj_t)&machine_rtc_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ machine_rtc_type,
+ MP_QSTR_RTC,
+ MP_TYPE_FLAG_NONE,
+ make_new, machine_rtc_make_new,
+ locals_dict, &machine_rtc_locals_dict
+ );
diff --git a/ports/rp2/machine_spi.c b/ports/rp2/machine_spi.c
index 742a3cfddf44..b2b879c9a8ed 100644
--- a/ports/rp2/machine_spi.c
+++ b/ports/rp2/machine_spi.c
@@ -40,20 +40,36 @@
#define DEFAULT_SPI_FIRSTBIT (SPI_MSB_FIRST)
#ifndef MICROPY_HW_SPI0_SCK
+#if PICO_DEFAULT_SPI == 0
+#define MICROPY_HW_SPI0_SCK (PICO_DEFAULT_SPI_SCK_PIN)
+#define MICROPY_HW_SPI0_MOSI (PICO_DEFAULT_SPI_TX_PIN)
+#define MICROPY_HW_SPI0_MISO (PICO_DEFAULT_SPI_RX_PIN)
+#else
#define MICROPY_HW_SPI0_SCK (6)
#define MICROPY_HW_SPI0_MOSI (7)
#define MICROPY_HW_SPI0_MISO (4)
#endif
+#endif
#ifndef MICROPY_HW_SPI1_SCK
+#if PICO_DEFAULT_SPI == 1
+#define MICROPY_HW_SPI1_SCK (PICO_DEFAULT_SPI_SCK_PIN)
+#define MICROPY_HW_SPI1_MOSI (PICO_DEFAULT_SPI_TX_PIN)
+#define MICROPY_HW_SPI1_MISO (PICO_DEFAULT_SPI_RX_PIN)
+#else
#define MICROPY_HW_SPI1_SCK (10)
#define MICROPY_HW_SPI1_MOSI (11)
#define MICROPY_HW_SPI1_MISO (8)
#endif
+#endif
+// SPI0 can be GP{0..7,16..23}, SPI1 can be GP{8..15,24..29}.
#define IS_VALID_PERIPH(spi, pin) ((((pin) & 8) >> 3) == (spi))
+// GP{2,6,10,14,...}
#define IS_VALID_SCK(spi, pin) (((pin) & 3) == 2 && IS_VALID_PERIPH(spi, pin))
+// GP{3,7,11,15,...}
#define IS_VALID_MOSI(spi, pin) (((pin) & 3) == 3 && IS_VALID_PERIPH(spi, pin))
+// GP{0,4,8,10,...}
#define IS_VALID_MISO(spi, pin) (((pin) & 3) == 0 && IS_VALID_PERIPH(spi, pin))
typedef struct _machine_spi_obj_t {
@@ -269,25 +285,31 @@ STATIC void machine_spi_transfer(mp_obj_base_t *self_in, size_t len, const uint8
}
}
-machine_spi_obj_t *spi_from_mp_obj(mp_obj_t o) {
- if (mp_obj_is_type(o, &machine_spi_type)) {
- machine_spi_obj_t *self = MP_OBJ_TO_PTR(o);
- return self;
- } else {
- mp_raise_TypeError(MP_ERROR_TEXT("expecting an SPI object"));
- }
-}
-
STATIC const mp_machine_spi_p_t machine_spi_p = {
.init = machine_spi_init,
.transfer = machine_spi_transfer,
};
-const mp_obj_type_t machine_spi_type = {
- { &mp_type_type },
- .name = MP_QSTR_SPI,
- .print = machine_spi_print,
- .make_new = machine_spi_make_new,
- .protocol = &machine_spi_p,
- .locals_dict = (mp_obj_dict_t *)&mp_machine_spi_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ machine_spi_type,
+ MP_QSTR_SPI,
+ MP_TYPE_FLAG_NONE,
+ make_new, machine_spi_make_new,
+ print, machine_spi_print,
+ protocol, &machine_spi_p,
+ locals_dict, &mp_machine_spi_locals_dict
+ );
+
+mp_obj_base_t *mp_hal_get_spi_obj(mp_obj_t o) {
+ if (mp_obj_is_type(o, &machine_spi_type)) {
+ return MP_OBJ_TO_PTR(o);
+ }
+ #if MICROPY_PY_MACHINE_SOFTSPI
+ else if (mp_obj_is_type(o, &mp_machine_soft_spi_type)) {
+ return MP_OBJ_TO_PTR(o);
+ }
+ #endif
+ else {
+ mp_raise_TypeError(MP_ERROR_TEXT("expecting an SPI object"));
+ }
+}
diff --git a/ports/rp2/machine_timer.c b/ports/rp2/machine_timer.c
index e7e8f02d5517..e4fbb03af437 100644
--- a/ports/rp2/machine_timer.c
+++ b/ports/rp2/machine_timer.c
@@ -156,10 +156,11 @@ STATIC const mp_rom_map_elem_t machine_timer_locals_dict_table[] = {
};
STATIC MP_DEFINE_CONST_DICT(machine_timer_locals_dict, machine_timer_locals_dict_table);
-const mp_obj_type_t machine_timer_type = {
- { &mp_type_type },
- .name = MP_QSTR_Timer,
- .print = machine_timer_print,
- .make_new = machine_timer_make_new,
- .locals_dict = (mp_obj_dict_t *)&machine_timer_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ machine_timer_type,
+ MP_QSTR_Timer,
+ MP_TYPE_FLAG_NONE,
+ make_new, machine_timer_make_new,
+ print, machine_timer_print,
+ locals_dict, &machine_timer_locals_dict
+ );
diff --git a/ports/rp2/machine_uart.c b/ports/rp2/machine_uart.c
index fafa3c1b5678..09870e78f0d7 100644
--- a/ports/rp2/machine_uart.c
+++ b/ports/rp2/machine_uart.c
@@ -336,7 +336,9 @@ STATIC void machine_uart_init_helper(machine_uart_obj_t *self, size_t n_args, co
uart_init(self->uart, self->baudrate);
uart_set_format(self->uart, self->bits, self->stop, self->parity);
+ __DSB(); // make sure UARTLCR_H register is written to
uart_set_fifo_enabled(self->uart, true);
+ __DSB(); // make sure UARTLCR_H register is written to
gpio_set_function(self->tx, GPIO_FUNC_UART);
gpio_set_function(self->rx, GPIO_FUNC_UART);
if (self->invert & UART_INVERT_RX) {
@@ -435,17 +437,31 @@ STATIC mp_obj_t machine_uart_sendbreak(mp_obj_t self_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_uart_sendbreak_obj, machine_uart_sendbreak);
+STATIC mp_obj_t machine_uart_txdone(mp_obj_t self_in) {
+ machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in);
+
+ if (ringbuf_avail(&self->write_buffer) == 0 &&
+ uart_get_hw(self->uart)->fr & UART_UARTFR_TXFE_BITS) {
+ return mp_const_true;
+ } else {
+ return mp_const_false;
+ }
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_uart_txdone_obj, machine_uart_txdone);
+
STATIC const mp_rom_map_elem_t machine_uart_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_uart_init_obj) },
{ MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_uart_deinit_obj) },
{ MP_ROM_QSTR(MP_QSTR_any), MP_ROM_PTR(&machine_uart_any_obj) },
+ { MP_ROM_QSTR(MP_QSTR_flush), MP_ROM_PTR(&mp_stream_flush_obj) },
{ MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) },
{ MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) },
{ MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) },
{ MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) },
{ MP_ROM_QSTR(MP_QSTR_sendbreak), MP_ROM_PTR(&machine_uart_sendbreak_obj) },
+ { MP_ROM_QSTR(MP_QSTR_txdone), MP_ROM_PTR(&machine_uart_txdone_obj) },
{ MP_ROM_QSTR(MP_QSTR_INV_TX), MP_ROM_INT(UART_INVERT_TX) },
{ MP_ROM_QSTR(MP_QSTR_INV_RX), MP_ROM_INT(UART_INVERT_RX) },
@@ -538,6 +554,19 @@ STATIC mp_uint_t machine_uart_ioctl(mp_obj_t self_in, mp_uint_t request, mp_uint
if ((flags & MP_STREAM_POLL_WR) && ringbuf_free(&self->write_buffer) > 0) {
ret |= MP_STREAM_POLL_WR;
}
+ } else if (request == MP_STREAM_FLUSH) {
+ // The timeout is estimated using the buffer size and the baudrate.
+ // Take the worst case assumptions at 13 bit symbol size times 2.
+ uint64_t timeout = time_us_64() +
+ (uint64_t)(33 + self->write_buffer.size) * 13000000ll * 2 / self->baudrate;
+ do {
+ if (machine_uart_txdone((mp_obj_t)self) == mp_const_true) {
+ return 0;
+ }
+ MICROPY_EVENT_POLL_HOOK
+ } while (time_us_64() < timeout);
+ *errcode = MP_ETIMEDOUT;
+ ret = MP_STREAM_ERROR;
} else {
*errcode = MP_EINVAL;
ret = MP_STREAM_ERROR;
@@ -552,13 +581,15 @@ STATIC const mp_stream_p_t uart_stream_p = {
.is_text = false,
};
-const mp_obj_type_t machine_uart_type = {
- { &mp_type_type },
- .name = MP_QSTR_UART,
- .print = machine_uart_print,
- .make_new = machine_uart_make_new,
- .getiter = mp_identity_getiter,
- .iternext = mp_stream_unbuffered_iter,
- .protocol = &uart_stream_p,
- .locals_dict = (mp_obj_dict_t *)&machine_uart_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ machine_uart_type,
+ MP_QSTR_UART,
+ MP_TYPE_FLAG_ITER_IS_STREAM,
+ make_new, machine_uart_make_new,
+ print, machine_uart_print,
+ protocol, &uart_stream_p,
+ locals_dict, &machine_uart_locals_dict
+ );
+
+MP_REGISTER_ROOT_POINTER(void *rp2_uart_rx_buffer[2]);
+MP_REGISTER_ROOT_POINTER(void *rp2_uart_tx_buffer[2]);
diff --git a/ports/rp2/machine_wdt.c b/ports/rp2/machine_wdt.c
index 38e0597018d6..6574a6180f8a 100644
--- a/ports/rp2/machine_wdt.c
+++ b/ports/rp2/machine_wdt.c
@@ -29,6 +29,9 @@
#include "hardware/watchdog.h"
+// The maximum timeout in milliseconds is: 0xffffff / 2 / 1000
+#define WDT_TIMEOUT_MAX 8388
+
typedef struct _machine_wdt_obj_t {
mp_obj_base_t base;
} machine_wdt_obj_t;
@@ -53,7 +56,11 @@ STATIC mp_obj_t machine_wdt_make_new(const mp_obj_type_t *type, size_t n_args, s
}
// Start the watchdog (timeout is in milliseconds).
- watchdog_enable(args[ARG_timeout].u_int, false);
+ uint32_t timeout = args[ARG_timeout].u_int;
+ if (timeout > WDT_TIMEOUT_MAX) {
+ mp_raise_ValueError(MP_ERROR_TEXT("timeout exceeds " MP_STRINGIFY(WDT_TIMEOUT_MAX)));
+ }
+ watchdog_enable(timeout, false);
return MP_OBJ_FROM_PTR(&machine_wdt);
}
@@ -70,9 +77,10 @@ STATIC const mp_rom_map_elem_t machine_wdt_locals_dict_table[] = {
};
STATIC MP_DEFINE_CONST_DICT(machine_wdt_locals_dict, machine_wdt_locals_dict_table);
-const mp_obj_type_t machine_wdt_type = {
- { &mp_type_type },
- .name = MP_QSTR_WDT,
- .make_new = machine_wdt_make_new,
- .locals_dict = (mp_obj_dict_t *)&machine_wdt_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ machine_wdt_type,
+ MP_QSTR_WDT,
+ MP_TYPE_FLAG_NONE,
+ make_new, machine_wdt_make_new,
+ locals_dict, &machine_wdt_locals_dict
+ );
diff --git a/ports/rp2/main.c b/ports/rp2/main.c
index da21e0b39479..059449695cb6 100644
--- a/ports/rp2/main.c
+++ b/ports/rp2/main.c
@@ -42,27 +42,25 @@
#include "modmachine.h"
#include "modrp2.h"
#include "mpbthciport.h"
+#include "mpnetworkport.h"
#include "genhdr/mpversion.h"
+#include "mp_usbd.h"
#include "pico/stdlib.h"
#include "pico/binary_info.h"
+#include "pico/unique_id.h"
#include "hardware/rtc.h"
#include "hardware/structs/rosc.h"
#if MICROPY_PY_LWIP
#include "lwip/init.h"
#include "lwip/apps/mdns.h"
#endif
-
-#ifndef MICROPY_GC_HEAP_SIZE
-#if MICROPY_PY_LWIP
-#define MICROPY_GC_HEAP_SIZE 166 * 1024
-#else
-#define MICROPY_GC_HEAP_SIZE 192 * 1024
-#endif
+#if MICROPY_PY_NETWORK_CYW43
+#include "lib/cyw43-driver/src/cyw43.h"
#endif
extern uint8_t __StackTop, __StackBottom;
-static char gc_heap[MICROPY_GC_HEAP_SIZE];
+extern uint8_t __GcHeapStart, __GcHeapEnd;
// Embed version info in the binary in machine readable form
bi_decl(bi_program_version_string(MICROPY_GIT_TAG));
@@ -78,10 +76,16 @@ int main(int argc, char **argv) {
bi_decl(bi_program_feature("UART REPL"))
setup_default_uart();
mp_uart_init();
+ #else
+ #ifndef NDEBUG
+ stdio_init_all();
+ #endif
#endif
#if MICROPY_HW_ENABLE_USBDEV
+ #if MICROPY_HW_USB_CDC
bi_decl(bi_program_feature("USB REPL"))
+ #endif
tusb_init();
#endif
@@ -106,7 +110,7 @@ int main(int argc, char **argv) {
// Initialise stack extents and GC heap.
mp_stack_set_top(&__StackTop);
mp_stack_set_limit(&__StackTop - &__StackBottom - 256);
- gc_init(&gc_heap[0], &gc_heap[MP_ARRAY_SIZE(gc_heap)]);
+ gc_init(&__GcHeapStart, &__GcHeapEnd);
#if MICROPY_PY_LWIP
// lwIP doesn't allow to reinitialise itself by subsequent calls to this function
@@ -118,6 +122,28 @@ int main(int argc, char **argv) {
#endif
#endif
+ #if MICROPY_PY_NETWORK_CYW43
+ {
+ cyw43_init(&cyw43_state);
+ cyw43_irq_init();
+ cyw43_post_poll_hook(); // enable the irq
+ uint8_t buf[8];
+ memcpy(&buf[0], "PICO", 4);
+
+ // MAC isn't loaded from OTP yet, so use unique id to generate the default AP ssid.
+ const char hexchr[16] = "0123456789ABCDEF";
+ pico_unique_board_id_t pid;
+ pico_get_unique_board_id(&pid);
+ buf[4] = hexchr[pid.id[7] >> 4];
+ buf[5] = hexchr[pid.id[6] & 0xf];
+ buf[6] = hexchr[pid.id[5] >> 4];
+ buf[7] = hexchr[pid.id[4] & 0xf];
+ cyw43_wifi_ap_set_ssid(&cyw43_state, 8, buf);
+ cyw43_wifi_ap_set_auth(&cyw43_state, CYW43_AUTH_WPA2_AES_PSK);
+ cyw43_wifi_ap_set_password(&cyw43_state, 8, (const uint8_t *)"picoW123");
+ }
+ #endif
+
for (;;) {
// Initialise MicroPython runtime.
@@ -142,9 +168,9 @@ int main(int argc, char **argv) {
// Execute _boot.py to set up the filesystem.
#if MICROPY_VFS_FAT && MICROPY_HW_USB_MSC
- pyexec_frozen_module("_boot_fat.py");
+ pyexec_frozen_module("_boot_fat.py", false);
#else
- pyexec_frozen_module("_boot.py");
+ pyexec_frozen_module("_boot.py", false);
#endif
// Execute user scripts.
@@ -201,7 +227,7 @@ void gc_collect(void) {
}
void nlr_jump_fail(void *val) {
- printf("FATAL: uncaught exception %p\n", val);
+ mp_printf(&mp_plat_print, "FATAL: uncaught exception %p\n", val);
mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(val));
for (;;) {
__breakpoint();
diff --git a/ports/rp2/mbedtls/mbedtls_config.h b/ports/rp2/mbedtls/mbedtls_config.h
index 8e054ed51713..1b6d3dd43a65 100644
--- a/ports/rp2/mbedtls/mbedtls_config.h
+++ b/ports/rp2/mbedtls/mbedtls_config.h
@@ -27,73 +27,23 @@
#define MICROPY_INCLUDED_MBEDTLS_CONFIG_H
// Set mbedtls configuration
-#define MBEDTLS_PLATFORM_MEMORY
-#define MBEDTLS_PLATFORM_NO_STD_FUNCTIONS
-#define MBEDTLS_DEPRECATED_REMOVED
-#define MBEDTLS_ENTROPY_HARDWARE_ALT
-#define MBEDTLS_AES_ROM_TABLES
-#define MBEDTLS_CIPHER_MODE_CBC
-#define MBEDTLS_ECP_DP_SECP192R1_ENABLED
-#define MBEDTLS_ECP_DP_SECP224R1_ENABLED
-#define MBEDTLS_ECP_DP_SECP256R1_ENABLED
-#define MBEDTLS_ECP_DP_SECP384R1_ENABLED
-#define MBEDTLS_ECP_DP_SECP521R1_ENABLED
-#define MBEDTLS_ECP_DP_SECP192K1_ENABLED
-#define MBEDTLS_ECP_DP_SECP224K1_ENABLED
-#define MBEDTLS_ECP_DP_SECP256K1_ENABLED
-#define MBEDTLS_ECP_DP_BP256R1_ENABLED
-#define MBEDTLS_ECP_DP_BP384R1_ENABLED
-#define MBEDTLS_ECP_DP_BP512R1_ENABLED
-#define MBEDTLS_ECP_DP_CURVE25519_ENABLED
-#define MBEDTLS_KEY_EXCHANGE_RSA_ENABLED
-#define MBEDTLS_NO_PLATFORM_ENTROPY
-#define MBEDTLS_PKCS1_V15
-#define MBEDTLS_SHA256_SMALLER
-#define MBEDTLS_SSL_PROTO_TLS1
-#define MBEDTLS_SSL_PROTO_TLS1_1
-#define MBEDTLS_SSL_PROTO_TLS1_2
-#define MBEDTLS_SSL_SERVER_NAME_INDICATION
-
-// Use a smaller output buffer to reduce size of SSL context
-#define MBEDTLS_SSL_MAX_CONTENT_LEN (16384)
-#define MBEDTLS_SSL_IN_CONTENT_LEN (MBEDTLS_SSL_MAX_CONTENT_LEN)
-#define MBEDTLS_SSL_OUT_CONTENT_LEN (4096)
+#define MBEDTLS_ECP_NIST_OPTIM
+#define MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED
// Enable mbedtls modules
-#define MBEDTLS_AES_C
-#define MBEDTLS_ASN1_PARSE_C
-#define MBEDTLS_BIGNUM_C
-#define MBEDTLS_CIPHER_C
-#define MBEDTLS_CTR_DRBG_C
-// #define MBEDTLS_ECP_C
-#define MBEDTLS_ENTROPY_C
-#define MBEDTLS_ERROR_C
-#define MBEDTLS_MD_C
-#define MBEDTLS_MD5_C
-#define MBEDTLS_OID_C
-#define MBEDTLS_PKCS5_C
-#define MBEDTLS_PK_C
-#define MBEDTLS_PK_PARSE_C
-#define MBEDTLS_PLATFORM_C
-#define MBEDTLS_RSA_C
-#define MBEDTLS_SHA1_C
-#define MBEDTLS_SHA256_C
-#define MBEDTLS_SHA512_C
-#define MBEDTLS_SSL_CLI_C
-#define MBEDTLS_SSL_SRV_C
-#define MBEDTLS_SSL_TLS_C
-#define MBEDTLS_X509_CRT_PARSE_C
-#define MBEDTLS_X509_USE_C
+#define MBEDTLS_GCM_C
+#define MBEDTLS_HAVE_TIME
+#define MBEDTLS_HAVE_TIME_DATE
+
+// Time hook
+#include
+time_t rp2_rtctime_seconds(time_t *timer);
+#define MBEDTLS_PLATFORM_TIME_MACRO rp2_rtctime_seconds
-// Memory allocation hooks
-#include
-#include
-void *m_tracked_calloc(size_t nmemb, size_t size);
-void m_tracked_free(void *ptr);
-#define MBEDTLS_PLATFORM_STD_CALLOC m_tracked_calloc
-#define MBEDTLS_PLATFORM_STD_FREE m_tracked_free
-#define MBEDTLS_PLATFORM_SNPRINTF_MACRO snprintf
+// Set MicroPython-specific options.
+#define MICROPY_MBEDTLS_CONFIG_BARE_METAL (1)
-#include "mbedtls/check_config.h"
+// Include common mbedtls configuration.
+#include "extmod/mbedtls/mbedtls_config_common.h"
#endif /* MICROPY_INCLUDED_MBEDTLS_CONFIG_H */
diff --git a/ports/rp2/mbedtls/mbedtls_port.c b/ports/rp2/mbedtls/mbedtls_port.c
index aa0f9a36e0ea..9067eca90ee5 100644
--- a/ports/rp2/mbedtls/mbedtls_port.c
+++ b/ports/rp2/mbedtls/mbedtls_port.c
@@ -29,6 +29,9 @@
#include "mbedtls_config.h"
+#include "hardware/rtc.h"
+#include "shared/timeutils/timeutils.h"
+
extern uint8_t rosc_random_u8(size_t cycles);
int mbedtls_hardware_poll(void *data, unsigned char *output, size_t len, size_t *olen) {
@@ -39,4 +42,10 @@ int mbedtls_hardware_poll(void *data, unsigned char *output, size_t len, size_t
return 0;
}
+time_t rp2_rtctime_seconds(time_t *timer) {
+ datetime_t t;
+ rtc_get_datetime(&t);
+ return timeutils_seconds_since_epoch(t.year, t.month, t.day, t.hour, t.min, t.sec);
+}
+
#endif
diff --git a/ports/rp2/memmap_mp.ld b/ports/rp2/memmap_mp.ld
index 0dc96743ea5c..9db74ce9c975 100644
--- a/ports/rp2/memmap_mp.ld
+++ b/ports/rp2/memmap_mp.ld
@@ -180,6 +180,12 @@ SECTIONS
*(.uninitialized_data*)
} > RAM
+ /* bss without zero init on startup */
+ .uninitialized_bss (NOLOAD): {
+ . = ALIGN(4);
+ *(.uninitialized_bss*)
+ } > RAM
+
/* Start and end symbols must be word-aligned */
.scratch_x : {
__scratch_x_start__ = .;
@@ -237,17 +243,23 @@ SECTIONS
} > FLASH
/* stack limit is poorly named, but historically is maximum heap ptr */
- __StackLimit = ORIGIN(RAM) + LENGTH(RAM);
+ __StackLimit = __bss_end__ + __micropy_c_heap_size__;
+
+ /* Define start and end of GC heap */
+ __GcHeapStart = __StackLimit; /* after the C heap (sbrk limit) */
+ __GcHeapEnd = ORIGIN(RAM) + LENGTH(RAM);
+
+ /* Define memory for the C stack */
__StackOneTop = ORIGIN(SCRATCH_X) + LENGTH(SCRATCH_X);
__StackTop = ORIGIN(SCRATCH_Y) + LENGTH(SCRATCH_Y);
__StackOneBottom = __StackOneTop - SIZEOF(.stack1_dummy);
__StackBottom = __StackTop - SIZEOF(.stack_dummy);
PROVIDE(__stack = __StackTop);
- /* Check if data + heap + stack exceeds RAM limit */
- ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed")
+ /* Check GC heap is at least 128 KB */
+ /* On a RP2040 using all SRAM this should always be the case. */
+ ASSERT((__GcHeapEnd - __GcHeapStart) > 128*1024, "GcHeap is too small")
ASSERT( __binary_info_header_end - __logical_binary_start <= 256, "Binary info must be in first 256 bytes of the binary")
/* todo assert on extra code */
}
-
diff --git a/ports/rp2/modmachine.c b/ports/rp2/modmachine.c
index fbaf29ee1641..81154c94ceca 100644
--- a/ports/rp2/modmachine.c
+++ b/ports/rp2/modmachine.c
@@ -26,6 +26,7 @@
#include "py/runtime.h"
#include "py/mphal.h"
+#include "drivers/dht/dht.h"
#include "shared/runtime/pyexec.h"
#include "extmod/machine_bitstream.h"
#include "extmod/machine_i2c.h"
@@ -38,10 +39,18 @@
#include "modmachine.h"
#include "uart.h"
#include "hardware/clocks.h"
+#include "hardware/pll.h"
+#include "hardware/structs/rosc.h"
+#include "hardware/structs/scb.h"
+#include "hardware/structs/syscfg.h"
#include "hardware/watchdog.h"
+#include "hardware/xosc.h"
#include "pico/bootrom.h"
#include "pico/stdlib.h"
#include "pico/unique_id.h"
+#if MICROPY_PY_NETWORK_CYW43
+#include "lib/cyw43-driver/src/cyw43.h"
+#endif
#if MICROPY_PY_MACHINE
@@ -81,11 +90,14 @@ STATIC mp_obj_t machine_reset_cause(void) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_reset_cause_obj, machine_reset_cause);
-STATIC mp_obj_t machine_bootloader(void) {
+NORETURN mp_obj_t machine_bootloader(size_t n_args, const mp_obj_t *args) {
+ MICROPY_BOARD_ENTER_BOOTLOADER(n_args, args);
+ rosc_hw->ctrl = ROSC_CTRL_ENABLE_VALUE_ENABLE << ROSC_CTRL_ENABLE_LSB;
reset_usb_boot(0, 0);
- return mp_const_none;
+ for (;;) {
+ }
}
-MP_DEFINE_CONST_FUN_OBJ_0(machine_bootloader_obj, machine_bootloader);
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_bootloader_obj, 0, 1, machine_bootloader);
STATIC mp_obj_t machine_freq(size_t n_args, const mp_obj_t *args) {
if (n_args == 0) {
@@ -111,13 +123,88 @@ STATIC mp_obj_t machine_idle(void) {
STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_idle_obj, machine_idle);
STATIC mp_obj_t machine_lightsleep(size_t n_args, const mp_obj_t *args) {
- if (n_args == 0) {
- for (;;) {
- MICROPY_EVENT_POLL_HOOK
+ mp_int_t delay_ms = 0;
+ bool use_timer_alarm = false;
+
+ if (n_args == 1) {
+ delay_ms = mp_obj_get_int(args[0]);
+ if (delay_ms <= 1) {
+ // Sleep is too small, just use standard delay.
+ mp_hal_delay_ms(delay_ms);
+ return mp_const_none;
+ }
+ use_timer_alarm = delay_ms < (1ULL << 32) / 1000;
+ if (use_timer_alarm) {
+ // Use timer alarm to wake.
+ } else {
+ // TODO: Use RTC alarm to wake.
+ mp_raise_ValueError(MP_ERROR_TEXT("sleep too long"));
}
+ }
+
+ const uint32_t xosc_hz = XOSC_MHZ * 1000000;
+
+ uint32_t my_interrupts = save_and_disable_interrupts();
+ #if MICROPY_PY_NETWORK_CYW43
+ if (cyw43_has_pending) {
+ restore_interrupts(my_interrupts);
+ return mp_const_none;
+ }
+ #endif
+ // Disable USB and ADC clocks.
+ clock_stop(clk_usb);
+ clock_stop(clk_adc);
+
+ // CLK_REF = XOSC
+ clock_configure(clk_ref, CLOCKS_CLK_REF_CTRL_SRC_VALUE_XOSC_CLKSRC, 0, xosc_hz, xosc_hz);
+
+ // CLK_SYS = CLK_REF
+ clock_configure(clk_sys, CLOCKS_CLK_SYS_CTRL_SRC_VALUE_CLK_REF, 0, xosc_hz, xosc_hz);
+
+ // CLK_RTC = XOSC / 256
+ clock_configure(clk_rtc, 0, CLOCKS_CLK_RTC_CTRL_AUXSRC_VALUE_XOSC_CLKSRC, xosc_hz, xosc_hz / 256);
+
+ // CLK_PERI = CLK_SYS
+ clock_configure(clk_peri, 0, CLOCKS_CLK_PERI_CTRL_AUXSRC_VALUE_CLK_SYS, xosc_hz, xosc_hz);
+
+ // Disable PLLs.
+ pll_deinit(pll_sys);
+ pll_deinit(pll_usb);
+
+ // Disable ROSC.
+ rosc_hw->ctrl = ROSC_CTRL_ENABLE_VALUE_DISABLE << ROSC_CTRL_ENABLE_LSB;
+
+ if (n_args == 0) {
+ #if MICROPY_PY_NETWORK_CYW43
+ gpio_set_dormant_irq_enabled(CYW43_PIN_WL_HOST_WAKE, GPIO_IRQ_LEVEL_HIGH, true);
+ #endif
+ xosc_dormant();
} else {
- mp_hal_delay_ms(mp_obj_get_int(args[0]));
+ uint32_t sleep_en0 = clocks_hw->sleep_en0;
+ uint32_t sleep_en1 = clocks_hw->sleep_en1;
+ clocks_hw->sleep_en0 = CLOCKS_SLEEP_EN0_CLK_RTC_RTC_BITS;
+ if (use_timer_alarm) {
+ // Use timer alarm to wake.
+ clocks_hw->sleep_en1 = CLOCKS_SLEEP_EN1_CLK_SYS_TIMER_BITS;
+ timer_hw->alarm[3] = timer_hw->timerawl + delay_ms * 1000;
+ } else {
+ // TODO: Use RTC alarm to wake.
+ clocks_hw->sleep_en1 = 0;
+ }
+ scb_hw->scr |= M0PLUS_SCR_SLEEPDEEP_BITS;
+ __wfi();
+ scb_hw->scr &= ~M0PLUS_SCR_SLEEPDEEP_BITS;
+ clocks_hw->sleep_en0 = sleep_en0;
+ clocks_hw->sleep_en1 = sleep_en1;
}
+
+ // Enable ROSC.
+ rosc_hw->ctrl = ROSC_CTRL_ENABLE_VALUE_ENABLE << ROSC_CTRL_ENABLE_LSB;
+
+ // Bring back all clocks.
+ clocks_init();
+ restore_interrupts(my_interrupts);
+
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_lightsleep_obj, 0, 1, machine_lightsleep);
@@ -161,13 +248,14 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_bitstream), MP_ROM_PTR(&machine_bitstream_obj) },
#endif
{ MP_ROM_QSTR(MP_QSTR_time_pulse_us), MP_ROM_PTR(&machine_time_pulse_us_obj) },
+ { MP_ROM_QSTR(MP_QSTR_dht_readinto), MP_ROM_PTR(&dht_readinto_obj) },
{ MP_ROM_QSTR(MP_QSTR_mem8), MP_ROM_PTR(&machine_mem8_obj) },
{ MP_ROM_QSTR(MP_QSTR_mem16), MP_ROM_PTR(&machine_mem16_obj) },
{ MP_ROM_QSTR(MP_QSTR_mem32), MP_ROM_PTR(&machine_mem32_obj) },
{ MP_ROM_QSTR(MP_QSTR_ADC), MP_ROM_PTR(&machine_adc_type) },
- { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&machine_hw_i2c_type) },
+ { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&machine_i2c_type) },
{ MP_ROM_QSTR(MP_QSTR_SoftI2C), MP_ROM_PTR(&mp_machine_soft_i2c_type) },
{ MP_ROM_QSTR(MP_QSTR_I2S), MP_ROM_PTR(&machine_i2s_type) },
{ MP_ROM_QSTR(MP_QSTR_Pin), MP_ROM_PTR(&machine_pin_type) },
diff --git a/ports/rp2/modmachine.h b/ports/rp2/modmachine.h
index 0635ff248706..6ea4def91d97 100644
--- a/ports/rp2/modmachine.h
+++ b/ports/rp2/modmachine.h
@@ -4,7 +4,7 @@
#include "py/obj.h"
extern const mp_obj_type_t machine_adc_type;
-extern const mp_obj_type_t machine_hw_i2c_type;
+extern const mp_obj_type_t machine_i2c_type;
extern const mp_obj_type_t machine_i2s_type;
extern const mp_obj_type_t machine_pin_type;
extern const mp_obj_type_t machine_rtc_type;
@@ -18,5 +18,6 @@ void machine_pin_deinit(void);
void machine_i2s_init0(void);
struct _machine_spi_obj_t *spi_from_mp_obj(mp_obj_t o);
+NORETURN mp_obj_t machine_bootloader(size_t n_args, const mp_obj_t *args);
#endif // MICROPY_INCLUDED_RP2_MODMACHINE_H
diff --git a/ports/rp2/modrp2.c b/ports/rp2/modrp2.c
index 5dc066d651fc..94d49489c09b 100644
--- a/ports/rp2/modrp2.c
+++ b/ports/rp2/modrp2.c
@@ -27,14 +27,72 @@
#include "py/runtime.h"
#include "drivers/dht/dht.h"
#include "modrp2.h"
+#include "pico/stdlib.h"
+#include "hardware/gpio.h"
+#include "hardware/sync.h"
+#include "hardware/structs/ioqspi.h"
+#include "hardware/structs/sio.h"
+
+#if MICROPY_PY_NETWORK_CYW43
+#include "extmod/modnetwork.h"
+#endif
+
+#if MICROPY_PY_NETWORK_CYW43
+MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mod_network_country_obj);
+#endif
+
+// Improved version of
+// https://github.com/raspberrypi/pico-examples/blob/master/picoboard/button/button.c
+STATIC bool __no_inline_not_in_flash_func(bootsel_button)(void) {
+ const uint CS_PIN_INDEX = 1;
+
+ // Disable interrupts and the other core since they might be
+ // executing code from flash and we are about to temporarily
+ // disable flash access.
+ mp_uint_t atomic_state = MICROPY_BEGIN_ATOMIC_SECTION();
+
+ // Set the CS pin to high impedance.
+ hw_write_masked(&ioqspi_hw->io[CS_PIN_INDEX].ctrl,
+ (GPIO_OVERRIDE_LOW << IO_QSPI_GPIO_QSPI_SS_CTRL_OEOVER_LSB),
+ IO_QSPI_GPIO_QSPI_SS_CTRL_OEOVER_BITS);
+
+ // Delay without calling any functions in flash.
+ uint32_t start = timer_hw->timerawl;
+ while ((uint32_t)(timer_hw->timerawl - start) <= MICROPY_HW_BOOTSEL_DELAY_US) {
+ ;
+ }
+
+ // The HI GPIO registers in SIO can observe and control the 6 QSPI pins.
+ // The button pulls the QSPI_SS pin *low* when pressed.
+ bool button_state = !(sio_hw->gpio_hi_in & (1 << CS_PIN_INDEX));
+
+ // Restore the QSPI_SS pin so we can use flash again.
+ hw_write_masked(&ioqspi_hw->io[CS_PIN_INDEX].ctrl,
+ (GPIO_OVERRIDE_NORMAL << IO_QSPI_GPIO_QSPI_SS_CTRL_OEOVER_LSB),
+ IO_QSPI_GPIO_QSPI_SS_CTRL_OEOVER_BITS);
+
+ MICROPY_END_ATOMIC_SECTION(atomic_state);
+
+ return button_state;
+}
+
+STATIC mp_obj_t rp2_bootsel_button(void) {
+ return MP_OBJ_NEW_SMALL_INT(bootsel_button());
+}
+MP_DEFINE_CONST_FUN_OBJ_0(rp2_bootsel_button_obj, rp2_bootsel_button);
+
STATIC const mp_rom_map_elem_t rp2_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_rp2) },
{ MP_ROM_QSTR(MP_QSTR_Flash), MP_ROM_PTR(&rp2_flash_type) },
{ MP_ROM_QSTR(MP_QSTR_PIO), MP_ROM_PTR(&rp2_pio_type) },
{ MP_ROM_QSTR(MP_QSTR_StateMachine), MP_ROM_PTR(&rp2_state_machine_type) },
+ { MP_ROM_QSTR(MP_QSTR_bootsel_button), MP_ROM_PTR(&rp2_bootsel_button_obj) },
- { MP_ROM_QSTR(MP_QSTR_dht_readinto), MP_ROM_PTR(&dht_readinto_obj) },
+ #if MICROPY_PY_NETWORK_CYW43
+ // Deprecated (use network.country instead).
+ { MP_ROM_QSTR(MP_QSTR_country), MP_ROM_PTR(&mod_network_country_obj) },
+ #endif
};
STATIC MP_DEFINE_CONST_DICT(rp2_module_globals, rp2_module_globals_table);
diff --git a/ports/rp2/modules/rp2.py b/ports/rp2/modules/rp2.py
index 1e4bb26cf0f3..f145cbd60771 100644
--- a/ports/rp2/modules/rp2.py
+++ b/ports/rp2/modules/rp2.py
@@ -116,7 +116,7 @@ def word(self, instr, label=None):
if label is None:
label = 0
else:
- if not label in self.labels:
+ if label not in self.labels:
raise PIOASMError("unknown label {}".format(label))
label = self.labels[label]
self.prog[_PROG_DATA].append(instr | label)
diff --git a/ports/rp2/moduos.c b/ports/rp2/moduos.c
index 6288ff5696e4..398ec28d9210 100644
--- a/ports/rp2/moduos.c
+++ b/ports/rp2/moduos.c
@@ -35,6 +35,6 @@ STATIC mp_obj_t mp_uos_urandom(mp_obj_t num) {
for (int i = 0; i < n; i++) {
vstr.buf[i] = rosc_random_u8(8);
}
- return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
+ return mp_obj_new_bytes_from_vstr(&vstr);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_uos_urandom_obj, mp_uos_urandom);
diff --git a/ports/rp2/mpbthciport.c b/ports/rp2/mpbthciport.c
index 58639fd5b004..8840fe52f124 100644
--- a/ports/rp2/mpbthciport.c
+++ b/ports/rp2/mpbthciport.c
@@ -100,8 +100,10 @@ int mp_bluetooth_hci_uart_init(uint32_t port, uint32_t baudrate) {
MP_OBJ_NEW_QSTR(MP_QSTR_timeout), MP_OBJ_NEW_SMALL_INT(1000),
};
- mp_bthci_uart = machine_uart_type.make_new((mp_obj_t)&machine_uart_type, 2, 2, args);
- MP_STATE_PORT(mp_bthci_uart) = mp_bthci_uart;
+ // This is a statically-allocated UART (see machine_uart.c), and doesn't
+ // contain any heap pointers other than the ringbufs (which are already
+ // root pointers), so no need to track this as a root pointer.
+ mp_bthci_uart = MP_OBJ_TYPE_GET_SLOT(&machine_uart_type, make_new)((mp_obj_t)&machine_uart_type, 2, 2, args);
// Start the HCI polling to process any initial events/packets.
mp_bluetooth_hci_start_polling();
@@ -126,7 +128,7 @@ int mp_bluetooth_hci_uart_set_baudrate(uint32_t baudrate) {
int mp_bluetooth_hci_uart_any(void) {
int errcode = 0;
- const mp_stream_p_t *proto = (mp_stream_p_t *)machine_uart_type.protocol;
+ const mp_stream_p_t *proto = (mp_stream_p_t *)MP_OBJ_TYPE_GET_SLOT(&machine_uart_type, protocol);
mp_uint_t ret = proto->ioctl(mp_bthci_uart, MP_STREAM_POLL, MP_STREAM_POLL_RD, &errcode);
if (errcode != 0) {
@@ -140,7 +142,7 @@ int mp_bluetooth_hci_uart_write(const uint8_t *buf, size_t len) {
debug_printf("mp_bluetooth_hci_uart_write\n");
int errcode = 0;
- const mp_stream_p_t *proto = (mp_stream_p_t *)machine_uart_type.protocol;
+ const mp_stream_p_t *proto = (mp_stream_p_t *)MP_OBJ_TYPE_GET_SLOT(&machine_uart_type, protocol);
mp_bluetooth_hci_controller_wakeup();
@@ -157,7 +159,7 @@ int mp_bluetooth_hci_uart_readchar(void) {
if (mp_bluetooth_hci_uart_any()) {
int errcode = 0;
uint8_t buf = 0;
- const mp_stream_p_t *proto = (mp_stream_p_t *)machine_uart_type.protocol;
+ const mp_stream_p_t *proto = (mp_stream_p_t *)MP_OBJ_TYPE_GET_SLOT(&machine_uart_type, protocol);
if (proto->read(mp_bthci_uart, (void *)&buf, 1, &errcode) < 0) {
error_printf("mp_bluetooth_hci_uart_readchar: failed to read UART %d\n", errcode);
return -1;
diff --git a/ports/rp2/mpconfigport.h b/ports/rp2/mpconfigport.h
index d46ac05ee541..61b951221145 100644
--- a/ports/rp2/mpconfigport.h
+++ b/ports/rp2/mpconfigport.h
@@ -27,20 +27,34 @@
// Options controlling how MicroPython is built, overriding defaults in py/mpconfig.h
#include
+#include "hardware/flash.h"
#include "hardware/spi.h"
#include "hardware/sync.h"
#include "pico/binary_info.h"
+#include "pico/multicore.h"
#include "mpconfigboard.h"
-#if MICROPY_HW_USB_MSC
-#include "hardware/flash.h"
-#endif
#define MICROPY_PY_LVGL (1)
// Board and hardware specific configuration
#define MICROPY_HW_MCU_NAME "RP2040"
+#ifndef MICROPY_HW_ENABLE_UART_REPL
#define MICROPY_HW_ENABLE_UART_REPL (0) // useful if there is no USB
+#endif
+#ifndef MICROPY_HW_ENABLE_USBDEV
#define MICROPY_HW_ENABLE_USBDEV (1)
+#endif
+
+#if MICROPY_HW_ENABLE_USBDEV
+// Enable USB-CDC serial port
+#ifndef MICROPY_HW_USB_CDC
+#define MICROPY_HW_USB_CDC (1)
+#endif
+// Enable USB Mass Storage with FatFS filesystem.
+#ifndef MICROPY_HW_USB_MSC
+#define MICROPY_HW_USB_MSC (0)
+#endif
+#endif
#ifndef MICROPY_CONFIG_ROM_LEVEL
#define MICROPY_CONFIG_ROM_LEVEL (MICROPY_CONFIG_ROM_LEVEL_EXTRA_FEATURES)
@@ -62,7 +76,7 @@
#define MICROPY_OPT_COMPUTED_GOTO (1)
// Python internal features
-#define MICROPY_TRACKED_ALLOC (MICROPY_SSL_MBEDTLS)
+#define MICROPY_TRACKED_ALLOC (MICROPY_SSL_MBEDTLS || MICROPY_BLUETOOTH_BTSTACK)
#define MICROPY_READER_VFS (1)
#define MICROPY_ENABLE_GC (1)
#define MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF (1)
@@ -84,10 +98,14 @@
// Extended modules
#define MICROPY_EPOCH_IS_1970 (1)
#define MICROPY_PY_UOS_INCLUDEFILE "ports/rp2/moduos.c"
+#ifndef MICROPY_PY_OS_DUPTERM
+#define MICROPY_PY_OS_DUPTERM (1)
+#endif
#define MICROPY_PY_UOS_UNAME (1)
#define MICROPY_PY_UOS_URANDOM (1)
#define MICROPY_PY_URE_MATCH_GROUPS (1)
#define MICROPY_PY_URE_MATCH_SPAN_START_END (1)
+#define MICROPY_PY_UHASHLIB_SHA1 (1)
#define MICROPY_PY_UCRYPTOLIB (1)
#define MICROPY_PY_UTIME_MP_HAL (1)
#define MICROPY_PY_URANDOM_SEED_INIT_FUNC (rosc_random_u32())
@@ -123,33 +141,42 @@
#define MICROPY_FATFS_MAX_SS (FLASH_SECTOR_SIZE)
#endif
-#if MICROPY_VFS_FAT && MICROPY_HW_USB_MSC
-#define mp_type_fileio mp_type_vfs_fat_fileio
-#define mp_type_textio mp_type_vfs_fat_textio
-#elif MICROPY_VFS_LFS2
-// Use VfsLfs2's types for fileio/textio
-#define mp_type_fileio mp_type_vfs_lfs2_fileio
-#define mp_type_textio mp_type_vfs_lfs2_textio
+#ifndef MICROPY_BOARD_ENTER_BOOTLOADER
+#define MICROPY_BOARD_ENTER_BOOTLOADER(nargs, args)
#endif
+// By default networking should include sockets, ssl, websockets, webrepl, dupterm.
#if MICROPY_PY_NETWORK
-#define NETWORK_ROOT_POINTERS mp_obj_list_t mod_network_nic_list;
-#else
-#define NETWORK_ROOT_POINTERS
+#ifndef MICROPY_PY_NETWORK_HOSTNAME_DEFAULT
+#define MICROPY_PY_NETWORK_HOSTNAME_DEFAULT "mpy-rp2"
#endif
-#if MICROPY_PY_BLUETOOTH
-#define MICROPY_PORT_ROOT_POINTER_BLUETOOTH struct _machine_uart_obj_t *mp_bthci_uart;
-#else
-#define MICROPY_PORT_ROOT_POINTER_BLUETOOTH
+#ifndef MICROPY_PY_USOCKET
+#define MICROPY_PY_USOCKET (1)
+#endif
+#ifndef MICROPY_PY_USSL
+#define MICROPY_PY_USSL (1)
+#endif
+#ifndef MICROPY_PY_UWEBSOCKET
+#define MICROPY_PY_UWEBSOCKET (1)
+#endif
+#ifndef MICROPY_PY_WEBREPL
+#define MICROPY_PY_WEBREPL (1)
+#endif
#endif
-#if MICROPY_BLUETOOTH_NIMBLE
-struct _mp_bluetooth_nimble_root_pointers_t;
-struct _mp_bluetooth_nimble_malloc_t;
-#define MICROPY_PORT_ROOT_POINTER_BLUETOOTH_NIMBLE struct _mp_bluetooth_nimble_malloc_t *bluetooth_nimble_memory; struct _mp_bluetooth_nimble_root_pointers_t *bluetooth_nimble_root_pointers;
+#if MICROPY_PY_NETWORK_CYW43
+extern const struct _mp_obj_type_t mp_network_cyw43_type;
+#define MICROPY_HW_NIC_CYW43 \
+ { MP_ROM_QSTR(MP_QSTR_WLAN), MP_ROM_PTR(&mp_network_cyw43_type) }, \
+ { MP_ROM_QSTR(MP_QSTR_STAT_IDLE), MP_ROM_INT(CYW43_LINK_DOWN) }, \
+ { MP_ROM_QSTR(MP_QSTR_STAT_CONNECTING), MP_ROM_INT(CYW43_LINK_JOIN) }, \
+ { MP_ROM_QSTR(MP_QSTR_STAT_WRONG_PASSWORD), MP_ROM_INT(CYW43_LINK_BADAUTH) }, \
+ { MP_ROM_QSTR(MP_QSTR_STAT_NO_AP_FOUND), MP_ROM_INT(CYW43_LINK_NONET) }, \
+ { MP_ROM_QSTR(MP_QSTR_STAT_CONNECT_FAIL), MP_ROM_INT(CYW43_LINK_FAIL) }, \
+ { MP_ROM_QSTR(MP_QSTR_STAT_GOT_IP), MP_ROM_INT(CYW43_LINK_UP) },
#else
-#define MICROPY_PORT_ROOT_POINTER_BLUETOOTH_NIMBLE
+#define MICROPY_HW_NIC_CYW43
#endif
#if MICROPY_PY_NETWORK_NINAW10
@@ -157,21 +184,14 @@ struct _mp_bluetooth_nimble_malloc_t;
#ifndef MICROPY_PY_USOCKET_EXTENDED_STATE
#define MICROPY_PY_USOCKET_EXTENDED_STATE (1)
#endif
-// It also requires an additional root pointer for the SPI object.
-#define MICROPY_PORT_ROOT_POINTER_NINAW10 struct _machine_spi_obj_t *mp_wifi_spi; struct _machine_timer_obj_t *mp_wifi_timer; struct _mp_obj_list_t *mp_wifi_sockpoll_list;
-extern const struct _mod_network_nic_type_t mod_network_nic_type_nina;
+extern const struct _mp_obj_type_t mod_network_nic_type_nina;
#define MICROPY_HW_NIC_NINAW10 { MP_ROM_QSTR(MP_QSTR_WLAN), MP_ROM_PTR(&mod_network_nic_type_nina) },
#else
#define MICROPY_HW_NIC_NINAW10
-#define MICROPY_PORT_ROOT_POINTER_NINAW10
#endif
#if MICROPY_PY_NETWORK_WIZNET5K
-#if MICROPY_PY_LWIP
extern const struct _mp_obj_type_t mod_network_nic_type_wiznet5k;
-#else
-extern const struct _mod_network_nic_type_t mod_network_nic_type_wiznet5k;
-#endif
#define MICROPY_HW_NIC_WIZNET5K { MP_ROM_QSTR(MP_QSTR_WIZNET5K), MP_ROM_PTR(&mod_network_nic_type_wiznet5k) },
#else
#define MICROPY_HW_NIC_WIZNET5K
@@ -194,37 +214,36 @@ extern const struct _mod_network_nic_type_t mod_network_nic_type_wiznet5k;
#endif
#define MICROPY_PORT_NETWORK_INTERFACES \
+ MICROPY_HW_NIC_CYW43 \
MICROPY_HW_NIC_NINAW10 \
MICROPY_HW_NIC_WIZNET5K \
MICROPY_BOARD_NETWORK_INTERFACES \
-#ifndef MICROPY_BOARD_ROOT_POINTERS
-#define MICROPY_BOARD_ROOT_POINTERS
+// Additional entries for use with pendsv_schedule_dispatch.
+#ifndef MICROPY_BOARD_PENDSV_ENTRIES
+#define MICROPY_BOARD_PENDSV_ENTRIES
#endif
-#define MICROPY_PORT_ROOT_POINTERS \
- LV_ROOTS \
- void *mp_lv_user_data; \
- const char *readline_hist[8]; \
- void *machine_pin_irq_obj[30]; \
- void *rp2_pio_irq_obj[2]; \
- void *rp2_state_machine_irq_obj[8]; \
- void *rp2_uart_rx_buffer[2]; \
- void *rp2_uart_tx_buffer[2]; \
- void *machine_i2s_obj[2]; \
- NETWORK_ROOT_POINTERS \
- MICROPY_BOARD_ROOT_POINTERS \
- MICROPY_PORT_ROOT_POINTER_NINAW10 \
- MICROPY_PORT_ROOT_POINTER_BLUETOOTH \
- MICROPY_PORT_ROOT_POINTER_BLUETOOTH_NIMBLE \
-
#define MP_STATE_PORT MP_STATE_VM
// Miscellaneous settings
-// TODO need to look and see if these could/should be spinlock/mutex
-#define MICROPY_BEGIN_ATOMIC_SECTION() save_and_disable_interrupts()
-#define MICROPY_END_ATOMIC_SECTION(state) restore_interrupts(state)
+#ifndef MICROPY_HW_USB_VID
+#define MICROPY_HW_USB_VID (0x2E8A) // Raspberry Pi
+#endif
+#ifndef MICROPY_HW_USB_PID
+#define MICROPY_HW_USB_PID (0x0005) // RP2 MicroPython
+#endif
+
+#ifndef MICROPY_HW_BOOTSEL_DELAY_US
+#define MICROPY_HW_BOOTSEL_DELAY_US 8
+#endif
+
+// Entering a critical section.
+extern uint32_t mp_thread_begin_atomic_section(void);
+extern void mp_thread_end_atomic_section(uint32_t);
+#define MICROPY_BEGIN_ATOMIC_SECTION() mp_thread_begin_atomic_section()
+#define MICROPY_END_ATOMIC_SECTION(state) mp_thread_end_atomic_section(state)
// Prevent the "lwIP task" from running when unsafe to do so.
#define MICROPY_PY_LWIP_ENTER lwip_lock_acquire();
@@ -232,10 +251,10 @@ extern const struct _mod_network_nic_type_t mod_network_nic_type_wiznet5k;
#define MICROPY_PY_LWIP_EXIT lwip_lock_release();
#if MICROPY_HW_ENABLE_USBDEV
-#define MICROPY_HW_USBDEV_TASK_HOOK extern void tud_task(void); tud_task();
+#define MICROPY_HW_USBDEV_TASK_HOOK extern void usbd_task(void); usbd_task();
#define MICROPY_VM_HOOK_COUNT (10)
#define MICROPY_VM_HOOK_INIT static uint vm_hook_divisor = MICROPY_VM_HOOK_COUNT;
-#define MICROPY_VM_HOOK_POLL if (--vm_hook_divisor == 0) { \
+#define MICROPY_VM_HOOK_POLL if (get_core_num() == 0 && --vm_hook_divisor == 0) { \
vm_hook_divisor = MICROPY_VM_HOOK_COUNT; \
MICROPY_HW_USBDEV_TASK_HOOK \
}
@@ -245,12 +264,17 @@ extern const struct _mod_network_nic_type_t mod_network_nic_type_wiznet5k;
#define MICROPY_HW_USBDEV_TASK_HOOK
#endif
-#define MICROPY_EVENT_POLL_HOOK \
+#define MICROPY_EVENT_POLL_HOOK_FAST \
do { \
+ if (get_core_num() == 0) { MICROPY_HW_USBDEV_TASK_HOOK } \
extern void mp_handle_pending(bool); \
mp_handle_pending(true); \
+ } while (0)
+
+#define MICROPY_EVENT_POLL_HOOK \
+ do { \
+ MICROPY_EVENT_POLL_HOOK_FAST; \
best_effort_wfe_or_timeout(make_timeout_time_ms(1)); \
- MICROPY_HW_USBDEV_TASK_HOOK \
} while (0);
#define MICROPY_MAKE_POINTER_CALLABLE(p) ((void *)((mp_uint_t)(p) | 1))
diff --git a/ports/rp2/mphalport.c b/ports/rp2/mphalport.c
index 4ed648de0751..f56c2bda1362 100644
--- a/ports/rp2/mphalport.c
+++ b/ports/rp2/mphalport.c
@@ -35,7 +35,11 @@
#include "hardware/rtc.h"
#include "pico/unique_id.h"
-#if MICROPY_HW_ENABLE_UART_REPL || MICROPY_HW_ENABLE_USBDEV
+#if MICROPY_PY_NETWORK_CYW43
+#include "lib/cyw43-driver/src/cyw43.h"
+#endif
+
+#if MICROPY_HW_ENABLE_UART_REPL || MICROPY_HW_USB_CDC
#ifndef MICROPY_HW_STDIN_BUFFER_LEN
#define MICROPY_HW_STDIN_BUFFER_LEN 512
@@ -46,7 +50,7 @@ ringbuf_t stdin_ringbuf = { stdin_ringbuf_array, sizeof(stdin_ringbuf_array) };
#endif
-#if MICROPY_HW_ENABLE_USBDEV
+#if MICROPY_HW_USB_CDC
uint8_t cdc_itf_pending; // keep track of cdc interfaces which need attention to poll
@@ -87,13 +91,22 @@ void tud_cdc_rx_cb(uint8_t itf) {
uintptr_t mp_hal_stdio_poll(uintptr_t poll_flags) {
uintptr_t ret = 0;
- #if MICROPY_HW_ENABLE_USBDEV
+ #if MICROPY_HW_USB_CDC
poll_cdc_interfaces();
#endif
- #if MICROPY_HW_ENABLE_UART_REPL || MICROPY_HW_ENABLE_USBDEV
+ #if MICROPY_HW_ENABLE_UART_REPL || MICROPY_HW_USB_CDC
if ((poll_flags & MP_STREAM_POLL_RD) && ringbuf_peek(&stdin_ringbuf) != -1) {
ret |= MP_STREAM_POLL_RD;
}
+ if (poll_flags & MP_STREAM_POLL_WR) {
+ #if MICROPY_HW_ENABLE_UART_REPL
+ ret |= MP_STREAM_POLL_WR;
+ #else
+ if (tud_cdc_connected() && tud_cdc_write_available() > 0) {
+ ret |= MP_STREAM_POLL_WR;
+ }
+ #endif
+ }
#endif
#if MICROPY_PY_OS_DUPTERM
ret |= mp_uos_dupterm_poll(poll_flags);
@@ -104,7 +117,7 @@ uintptr_t mp_hal_stdio_poll(uintptr_t poll_flags) {
// Receive single character
int mp_hal_stdin_rx_chr(void) {
for (;;) {
- #if MICROPY_HW_ENABLE_USBDEV
+ #if MICROPY_HW_USB_CDC
poll_cdc_interfaces();
#endif
@@ -128,16 +141,21 @@ void mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) {
mp_uart_write_strn(str, len);
#endif
- #if MICROPY_HW_ENABLE_USBDEV
+ #if MICROPY_HW_USB_CDC
if (tud_cdc_connected()) {
for (size_t i = 0; i < len;) {
uint32_t n = len - i;
if (n > CFG_TUD_CDC_EP_BUFSIZE) {
n = CFG_TUD_CDC_EP_BUFSIZE;
}
- while (n > tud_cdc_write_available()) {
+ int timeout = 0;
+ // Wait with a max of USC_CDC_TIMEOUT ms
+ while (n > tud_cdc_write_available() && timeout++ < MICROPY_HW_USB_CDC_TX_TIMEOUT) {
MICROPY_EVENT_POLL_HOOK
}
+ if (timeout >= MICROPY_HW_USB_CDC_TX_TIMEOUT) {
+ break;
+ }
uint32_t n2 = tud_cdc_write(str + i, n);
tud_cdc_write_flush();
i += n2;
@@ -153,9 +171,8 @@ void mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) {
void mp_hal_delay_ms(mp_uint_t ms) {
absolute_time_t t = make_timeout_time_ms(ms);
while (!time_reached(t)) {
- mp_handle_pending(true);
+ MICROPY_EVENT_POLL_HOOK_FAST;
best_effort_wfe_or_timeout(t);
- MICROPY_HW_USBDEV_TASK_HOOK
}
}
@@ -168,6 +185,9 @@ uint64_t mp_hal_time_ns(void) {
// Generate a random locally administered MAC address (LAA)
void mp_hal_generate_laa_mac(int idx, uint8_t buf[6]) {
+ #ifndef NDEBUG
+ printf("Warning: No MAC in OTP, generating MAC from board id\n");
+ #endif
pico_unique_board_id_t pid;
pico_get_unique_board_id(&pid);
buf[0] = 0x02; // LAA range
@@ -180,5 +200,26 @@ void mp_hal_generate_laa_mac(int idx, uint8_t buf[6]) {
// A board can override this if needed
MP_WEAK void mp_hal_get_mac(int idx, uint8_t buf[6]) {
+ #if MICROPY_PY_NETWORK_CYW43
+ // The mac should come from cyw43 otp when CYW43_USE_OTP_MAC is defined
+ // This is loaded into the state after the driver is initialised
+ // cyw43_hal_generate_laa_mac is only called by the driver to generate a mac if otp is not set
+ memcpy(buf, cyw43_state.mac, 6);
+ #else
mp_hal_generate_laa_mac(idx, buf);
+ #endif
+}
+
+void mp_hal_get_mac_ascii(int idx, size_t chr_off, size_t chr_len, char *dest) {
+ static const char hexchr[16] = "0123456789ABCDEF";
+ uint8_t mac[6];
+ mp_hal_get_mac(idx, mac);
+ for (; chr_len; ++chr_off, --chr_len) {
+ *dest++ = hexchr[mac[chr_off >> 1] >> (4 * (1 - (chr_off & 1))) & 0xf];
+ }
+}
+
+// Shouldn't be used, needed by cyw43-driver in debug build.
+uint32_t storage_read_blocks(uint8_t *dest, uint32_t block_num, uint32_t num_blocks) {
+ panic_unsupported();
}
diff --git a/ports/rp2/mphalport.h b/ports/rp2/mphalport.h
index 88eef1308dcd..8b4a5b609377 100644
--- a/ports/rp2/mphalport.h
+++ b/ports/rp2/mphalport.h
@@ -30,8 +30,10 @@
#include "pico/time.h"
#include "hardware/clocks.h"
#include "hardware/structs/systick.h"
+#include "RP2040.h" // cmsis, for __WFI
#define SYSTICK_MAX (0xffffff)
+#define MICROPY_HW_USB_CDC_TX_TIMEOUT (500)
extern int mp_interrupt_char;
extern ringbuf_t stdin_ringbuf;
@@ -74,6 +76,11 @@ static inline mp_uint_t mp_hal_get_cpu_freq(void) {
#define MP_HAL_PIN_FMT "%u"
#define mp_hal_pin_obj_t uint
+#define MP_HAL_PIN_MODE_INPUT (GPIO_IN)
+#define MP_HAL_PIN_MODE_OUTPUT (GPIO_OUT)
+#define MP_HAL_PIN_PULL_NONE (0)
+#define MP_HAL_PIN_PULL_UP (1)
+#define MP_HAL_PIN_PULL_DOWN (2)
extern uint32_t machine_pin_open_drain_mask;
@@ -84,22 +91,37 @@ static inline unsigned int mp_hal_pin_name(mp_hal_pin_obj_t pin) {
}
static inline void mp_hal_pin_input(mp_hal_pin_obj_t pin) {
- gpio_set_function(pin, GPIO_FUNC_SIO);
gpio_set_dir(pin, GPIO_IN);
machine_pin_open_drain_mask &= ~(1 << pin);
+ gpio_set_function(pin, GPIO_FUNC_SIO);
}
static inline void mp_hal_pin_output(mp_hal_pin_obj_t pin) {
- gpio_set_function(pin, GPIO_FUNC_SIO);
gpio_set_dir(pin, GPIO_OUT);
machine_pin_open_drain_mask &= ~(1 << pin);
+ gpio_set_function(pin, GPIO_FUNC_SIO);
}
-static inline void mp_hal_pin_open_drain(mp_hal_pin_obj_t pin) {
- gpio_set_function(pin, GPIO_FUNC_SIO);
- gpio_set_dir(pin, GPIO_IN);
- gpio_put(pin, 0);
+static inline void mp_hal_pin_open_drain_with_value(mp_hal_pin_obj_t pin, int v) {
+ if (v) {
+ gpio_set_dir(pin, GPIO_IN);
+ gpio_put(pin, 0);
+ } else {
+ gpio_put(pin, 0);
+ gpio_set_dir(pin, GPIO_OUT);
+ }
machine_pin_open_drain_mask |= 1 << pin;
+ gpio_set_function(pin, GPIO_FUNC_SIO);
+}
+
+static inline void mp_hal_pin_open_drain(mp_hal_pin_obj_t pin) {
+ mp_hal_pin_open_drain_with_value(pin, 1);
+}
+
+static inline void mp_hal_pin_config(mp_hal_pin_obj_t pin, uint32_t mode, uint32_t pull, uint32_t alt) {
+ assert((mode == MP_HAL_PIN_MODE_INPUT || mode == MP_HAL_PIN_MODE_OUTPUT) && alt == 0);
+ gpio_set_dir(pin, mode);
+ gpio_set_pulls(pin, pull == MP_HAL_PIN_PULL_UP, pull == MP_HAL_PIN_PULL_DOWN);
}
static inline int mp_hal_pin_read(mp_hal_pin_obj_t pin) {
@@ -136,6 +158,8 @@ enum mp_hal_pin_interrupt_trigger {
void mp_hal_pin_interrupt(mp_hal_pin_obj_t pin, mp_obj_t handler, mp_uint_t trigger, bool hard);
+mp_obj_base_t *mp_hal_get_spi_obj(mp_obj_t spi_in);
+
enum {
MP_HAL_MAC_WLAN0 = 0,
MP_HAL_MAC_BDADDR,
@@ -143,6 +167,7 @@ enum {
};
void mp_hal_get_mac(int idx, uint8_t buf[6]);
+void mp_hal_get_mac_ascii(int idx, size_t chr_off, size_t chr_len, char *dest);
void mp_hal_generate_laa_mac(int idx, uint8_t buf[6]);
#endif // MICROPY_INCLUDED_RP2_MPHALPORT_H
diff --git a/ports/rp2/mpnetworkport.c b/ports/rp2/mpnetworkport.c
index 124907f53870..d8e33e229d9f 100644
--- a/ports/rp2/mpnetworkport.c
+++ b/ports/rp2/mpnetworkport.c
@@ -26,6 +26,7 @@
#include "py/runtime.h"
#include "py/mphal.h"
+#include "pendsv.h"
#if MICROPY_PY_LWIP
@@ -36,14 +37,50 @@
#define LWIP_TICK_RATE_MS 64
static alarm_id_t lwip_alarm_id = -1;
-static bool lwip_can_poll = true;
-static bool lwip_poll_pending = false;
-#if MICROPY_PY_NETWORK_WIZNET5K
-static bool wiznet_poll_pending = false;
+#if MICROPY_PY_NETWORK_CYW43
+#include "lib/cyw43-driver/src/cyw43.h"
+#include "lib/cyw43-driver/src/cyw43_stats.h"
+#include "hardware/irq.h"
+
+#define CYW43_IRQ_LEVEL GPIO_IRQ_LEVEL_HIGH
+#define CYW43_SHARED_IRQ_HANDLER_PRIORITY PICO_SHARED_IRQ_HANDLER_HIGHEST_ORDER_PRIORITY
+
+volatile int cyw43_has_pending = 0;
+
+static void gpio_irq_handler(void) {
+ uint32_t events = gpio_get_irq_event_mask(CYW43_PIN_WL_HOST_WAKE);
+ if (events & CYW43_IRQ_LEVEL) {
+ // As we use a high level interrupt, it will go off forever until it's serviced.
+ // So disable the interrupt until this is done. It's re-enabled again by
+ // CYW43_POST_POLL_HOOK which is called at the end of cyw43_poll_func.
+ gpio_set_irq_enabled(CYW43_PIN_WL_HOST_WAKE, CYW43_IRQ_LEVEL, false);
+ cyw43_has_pending = 1;
+ pendsv_schedule_dispatch(PENDSV_DISPATCH_CYW43, cyw43_poll);
+ CYW43_STAT_INC(IRQ_COUNT);
+ }
+}
+
+void cyw43_irq_init(void) {
+ gpio_add_raw_irq_handler_with_order_priority(IO_IRQ_BANK0, gpio_irq_handler, CYW43_SHARED_IRQ_HANDLER_PRIORITY);
+ irq_set_enabled(IO_IRQ_BANK0, true);
+ NVIC_SetPriority(PendSV_IRQn, PICO_LOWEST_IRQ_PRIORITY);
+}
+
+void cyw43_post_poll_hook(void) {
+ cyw43_has_pending = 0;
+ gpio_set_irq_enabled(CYW43_PIN_WL_HOST_WAKE, CYW43_IRQ_LEVEL, true);
+}
+#endif
+
+#if MICROPY_PY_NETWORK_WIZNET5K
void wiznet5k_poll(void);
void wiznet5k_deinit(void);
+
+void wiznet5k_try_poll(void) {
+ pendsv_schedule_dispatch(PENDSV_DISPATCH_WIZNET, wiznet5k_poll);
+}
#endif
u32_t sys_now(void) {
@@ -51,62 +88,27 @@ u32_t sys_now(void) {
return mp_hal_ticks_ms();
}
-STATIC uint32_t lwip_poll(void) {
+STATIC void lwip_poll(void) {
// Run the lwIP internal updates
sys_check_timeouts();
-
- return MAX(5, MIN(sys_timeouts_sleeptime(), LWIP_TICK_RATE_MS));
}
void lwip_lock_acquire(void) {
- lwip_can_poll = false;
+ // Prevent PendSV from running.
+ pendsv_suspend();
}
void lwip_lock_release(void) {
- lwip_can_poll = false;
- #if MICROPY_PY_NETWORK_WIZNET5K
- if (wiznet_poll_pending) {
- wiznet5k_poll();
- wiznet_poll_pending = false;
- }
- #endif
-
- if (lwip_poll_pending) {
- lwip_poll();
- lwip_poll_pending = false;
- }
- lwip_can_poll = true;
-}
-
-uint32_t lwip_try_poll(void) {
- uint32_t ret = LWIP_TICK_RATE_MS;
- if (lwip_can_poll) {
- lwip_can_poll = false;
- ret = lwip_poll();
- lwip_can_poll = true;
- } else {
- lwip_poll_pending = true;
- }
- return ret;
+ // Allow PendSV to run again.
+ pendsv_resume();
}
-#if MICROPY_PY_NETWORK_WIZNET5K
-void wiznet5k_try_poll(void) {
- if (lwip_can_poll) {
- lwip_can_poll = false;
- wiznet5k_poll();
- lwip_can_poll = true;
- } else {
- wiznet_poll_pending = true;
- }
-}
-#endif
-
STATIC int64_t alarm_callback(alarm_id_t id, void *user_data) {
+ pendsv_schedule_dispatch(PENDSV_DISPATCH_LWIP, lwip_poll);
#if MICROPY_PY_NETWORK_WIZNET5K
- wiznet5k_try_poll();
+ pendsv_schedule_dispatch(PENDSV_DISPATCH_WIZNET, wiznet5k_poll);
#endif
- return (int64_t)lwip_try_poll() * 1000;
+ return LWIP_TICK_RATE_MS * 1000;
}
void mod_network_lwip_init(void) {
diff --git a/ports/rp2/mpnetworkport.h b/ports/rp2/mpnetworkport.h
new file mode 100644
index 000000000000..88c190f45e27
--- /dev/null
+++ b/ports/rp2/mpnetworkport.h
@@ -0,0 +1,33 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2022 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_RP2_MPNETWORKPORT_H
+#define MICROPY_INCLUDED_RP2_MPNETWORKPORT_H
+
+#if MICROPY_PY_NETWORK_CYW43
+extern void cyw43_irq_init(void);
+#endif
+
+#endif // MICROPY_INCLUDED_RP2_MPNETWORKPORT_H
diff --git a/ports/rp2/mpthreadport.c b/ports/rp2/mpthreadport.c
index cdb5945d2198..252f7b01fa88 100644
--- a/ports/rp2/mpthreadport.c
+++ b/ports/rp2/mpthreadport.c
@@ -36,19 +36,60 @@ extern uint8_t __StackTop, __StackBottom;
void *core_state[2];
+// This will be non-NULL while Python code is execting.
STATIC void *(*core1_entry)(void *) = NULL;
+
STATIC void *core1_arg = NULL;
STATIC uint32_t *core1_stack = NULL;
STATIC size_t core1_stack_num_words = 0;
+// Thread mutex.
+STATIC mp_thread_mutex_t atomic_mutex;
+
+uint32_t mp_thread_begin_atomic_section(void) {
+ if (core1_entry) {
+ // When both cores are executing, we also need to provide
+ // full mutual exclusion.
+ mp_thread_mutex_lock(&atomic_mutex, 1);
+ // In case this atomic section is for flash access, then
+ // suspend the other core.
+ multicore_lockout_start_blocking();
+ }
+
+ return save_and_disable_interrupts();
+}
+
+void mp_thread_end_atomic_section(uint32_t state) {
+ restore_interrupts(state);
+
+ if (core1_entry) {
+ multicore_lockout_end_blocking();
+ mp_thread_mutex_unlock(&atomic_mutex);
+ }
+}
+
+// Initialise threading support.
void mp_thread_init(void) {
+ assert(get_core_num() == 0);
+
+ mp_thread_mutex_init(&atomic_mutex);
+
+ // Allow MICROPY_BEGIN_ATOMIC_SECTION to be invoked from core1.
+ multicore_lockout_victim_init();
+
mp_thread_set_state(&mp_state_ctx.thread);
core1_entry = NULL;
}
+// Shutdown threading support -- stops the second thread.
void mp_thread_deinit(void) {
+ assert(get_core_num() == 0);
+ // Must ensure that core1 is not currently holding the GC lock, otherwise
+ // it will be terminated while holding the lock.
+ mp_thread_mutex_lock(&MP_STATE_MEM(gc_mutex), 1);
multicore_reset_core1();
core1_entry = NULL;
+ mp_thread_mutex_unlock(&MP_STATE_MEM(gc_mutex));
}
void mp_thread_gc_others(void) {
@@ -64,9 +105,13 @@ void mp_thread_gc_others(void) {
}
STATIC void core1_entry_wrapper(void) {
+ // Allow MICROPY_BEGIN_ATOMIC_SECTION to be invoked from core0.
+ multicore_lockout_victim_init();
+
if (core1_entry) {
core1_entry(core1_arg);
}
+
core1_entry = NULL;
// returning from here will loop the core forever (WFI)
}
diff --git a/ports/rp2/pendsv.c b/ports/rp2/pendsv.c
new file mode 100644
index 000000000000..e4f662715f1c
--- /dev/null
+++ b/ports/rp2/pendsv.c
@@ -0,0 +1,84 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2022 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/mpconfig.h"
+#include "pendsv.h"
+#include "RP2040.h"
+
+#if MICROPY_PY_NETWORK_CYW43
+#include "lib/cyw43-driver/src/cyw43_stats.h"
+#endif
+
+static pendsv_dispatch_t pendsv_dispatch_table[PENDSV_DISPATCH_NUM_SLOTS];
+static int pendsv_lock;
+
+void pendsv_suspend(void) {
+ pendsv_lock++;
+}
+
+void pendsv_resume(void) {
+ pendsv_lock--;
+ assert(pendsv_lock >= 0);
+ // Run pendsv if needed. Find an entry with a dispatch and call pendsv dispatch
+ // with it. If pendsv runs it will service all slots.
+ int count = PENDSV_DISPATCH_NUM_SLOTS;
+ while (count--) {
+ if (pendsv_dispatch_table[count]) {
+ pendsv_schedule_dispatch(count, pendsv_dispatch_table[count]);
+ break;
+ }
+ }
+}
+
+void pendsv_schedule_dispatch(size_t slot, pendsv_dispatch_t f) {
+ assert(pendsv_lock >= 0);
+ pendsv_dispatch_table[slot] = f;
+ if (pendsv_lock == 0) {
+ SCB->ICSR = SCB_ICSR_PENDSVSET_Msk;
+ } else {
+ #if MICROPY_PY_NETWORK_CYW43
+ CYW43_STAT_INC(PENDSV_DISABLED_COUNT);
+ #endif
+ }
+}
+
+// PendSV interrupt handler to perform background processing.
+void PendSV_Handler(void) {
+ assert(pendsv_lock == 0);
+
+ #if MICROPY_PY_NETWORK_CYW43
+ CYW43_STAT_INC(PENDSV_RUN_COUNT);
+ #endif
+
+ for (size_t i = 0; i < PENDSV_DISPATCH_NUM_SLOTS; ++i) {
+ if (pendsv_dispatch_table[i] != NULL) {
+ pendsv_dispatch_t f = pendsv_dispatch_table[i];
+ pendsv_dispatch_table[i] = NULL;
+ f();
+ }
+ }
+}
diff --git a/ports/samd/boards/ADAFRUIT_TRINKET_M0/pins.c b/ports/rp2/pendsv.h
similarity index 64%
rename from ports/samd/boards/ADAFRUIT_TRINKET_M0/pins.c
rename to ports/rp2/pendsv.h
index 9fecddb6cd87..294cef3c70b6 100644
--- a/ports/samd/boards/ADAFRUIT_TRINKET_M0/pins.c
+++ b/ports/rp2/pendsv.h
@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2021 Peter van der Burg
+ * Copyright (c) 2022 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
@@ -22,22 +22,32 @@
* 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.
- *
- * Used by machine_pin.c. Holds Board/MCU specific Pin allocations.
*/
+#ifndef MICROPY_INCLUDED_RP2_PENDSV_H
+#define MICROPY_INCLUDED_RP2_PENDSV_H
-#include "modmachine.h"
-#include "pins.h"
+#include
-// Ensure Declaration in 'pins.h' reflects # of Pins defined here.
-const machine_pin_obj_t machine_pin_obj[] = {
- {{&machine_pin_type}, PIN_PA08}, // D0
- {{&machine_pin_type}, PIN_PA02}, // D1
- {{&machine_pin_type}, PIN_PA09}, // D2
- {{&machine_pin_type}, PIN_PA07}, // D3/ RxD
- {{&machine_pin_type}, PIN_PA06}, // D4/ TxD
+enum {
+ #if MICROPY_PY_LWIP
+ PENDSV_DISPATCH_LWIP,
+ #endif
+ #if MICROPY_PY_NETWORK_CYW43
+ PENDSV_DISPATCH_CYW43,
+ #endif
+ #if MICROPY_PY_NETWORK_WIZNET5K
+ PENDSV_DISPATCH_WIZNET,
+ #endif
+ MICROPY_BOARD_PENDSV_ENTRIES
+ PENDSV_DISPATCH_MAX
};
-const machine_led_obj_t machine_led_obj[] = {
- {{&machine_led_type}, PIN_PA10}, // user LED
-};
+#define PENDSV_DISPATCH_NUM_SLOTS PENDSV_DISPATCH_MAX
+
+typedef void (*pendsv_dispatch_t)(void);
+
+void pendsv_suspend(void);
+void pendsv_resume(void);
+void pendsv_schedule_dispatch(size_t slot, pendsv_dispatch_t f);
+
+#endif // MICROPY_INCLUDED_RP2_PENDSV_H
diff --git a/ports/rp2/rp2_flash.c b/ports/rp2/rp2_flash.c
index 80bc1dc1df12..26ec41949e9d 100644
--- a/ports/rp2/rp2_flash.c
+++ b/ports/rp2/rp2_flash.c
@@ -37,6 +37,7 @@
#ifndef MICROPY_HW_FLASH_STORAGE_BYTES
#define MICROPY_HW_FLASH_STORAGE_BYTES (1408 * 1024)
#endif
+static_assert(MICROPY_HW_FLASH_STORAGE_BYTES % 4096 == 0, "Flash storage size must be a multiple of 4K");
#ifndef MICROPY_HW_FLASH_STORAGE_BASE
#define MICROPY_HW_FLASH_STORAGE_BASE (PICO_FLASH_SIZE_BYTES - MICROPY_HW_FLASH_STORAGE_BYTES)
@@ -69,11 +70,45 @@ bi_decl(bi_block_device(
BINARY_INFO_BLOCK_DEV_FLAG_PT_UNKNOWN));
STATIC mp_obj_t rp2_flash_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
- // Check args.
- mp_arg_check_num(n_args, n_kw, 0, 0, false);
+ // Parse arguments
+ enum { ARG_start, ARG_len };
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_start, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
+ { MP_QSTR_len, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
+ };
+ mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
+ mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
+
+ if (args[ARG_start].u_int == -1 && args[ARG_len].u_int == -1) {
+ #ifndef NDEBUG
+ extern char __flash_binary_end;
+ assert((uintptr_t)&__flash_binary_end - XIP_BASE <= MICROPY_HW_FLASH_STORAGE_BASE);
+ #endif
+
+ // Default singleton object that accesses entire flash
+ return MP_OBJ_FROM_PTR(&rp2_flash_obj);
+ }
+
+ rp2_flash_obj_t *self = mp_obj_malloc(rp2_flash_obj_t, &rp2_flash_type);
+
+ mp_int_t start = args[ARG_start].u_int;
+ if (start == -1) {
+ start = 0;
+ } else if (!(0 <= start && start < MICROPY_HW_FLASH_STORAGE_BYTES && start % BLOCK_SIZE_BYTES == 0)) {
+ mp_raise_ValueError(NULL);
+ }
- // Return singleton object.
- return MP_OBJ_FROM_PTR(&rp2_flash_obj);
+ mp_int_t len = args[ARG_len].u_int;
+ if (len == -1) {
+ len = MICROPY_HW_FLASH_STORAGE_BYTES - start;
+ } else if (!(0 < len && start + len <= MICROPY_HW_FLASH_STORAGE_BYTES && len % BLOCK_SIZE_BYTES == 0)) {
+ mp_raise_ValueError(NULL);
+ }
+
+ self->flash_base = MICROPY_HW_FLASH_STORAGE_BASE + start;
+ self->flash_size = len;
+
+ return MP_OBJ_FROM_PTR(self);
}
STATIC mp_obj_t rp2_flash_readblocks(size_t n_args, const mp_obj_t *args) {
@@ -85,6 +120,11 @@ STATIC mp_obj_t rp2_flash_readblocks(size_t n_args, const mp_obj_t *args) {
offset += mp_obj_get_int(args[3]);
}
memcpy(bufinfo.buf, (void *)(XIP_BASE + self->flash_base + offset), bufinfo.len);
+ // MICROPY_EVENT_POLL_HOOK_FAST is called here to avoid a fail in registering
+ // USB at boot time, if the board is busy loading files or scanning the file
+ // system. MICROPY_EVENT_POLL_HOOK_FAST calls tud_task(). As the alternative
+ // tud_task() should be called in the USB IRQ. See discussion in PR #10423.
+ MICROPY_EVENT_POLL_HOOK_FAST;
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(rp2_flash_readblocks_obj, 3, 4, rp2_flash_readblocks);
@@ -99,7 +139,7 @@ STATIC mp_obj_t rp2_flash_writeblocks(size_t n_args, const mp_obj_t *args) {
mp_uint_t atomic_state = MICROPY_BEGIN_ATOMIC_SECTION();
flash_range_erase(self->flash_base + offset, bufinfo.len);
MICROPY_END_ATOMIC_SECTION(atomic_state);
- MICROPY_EVENT_POLL_HOOK
+ MICROPY_EVENT_POLL_HOOK_FAST;
// TODO check return value
} else {
offset += mp_obj_get_int(args[3]);
@@ -108,7 +148,7 @@ STATIC mp_obj_t rp2_flash_writeblocks(size_t n_args, const mp_obj_t *args) {
mp_uint_t atomic_state = MICROPY_BEGIN_ATOMIC_SECTION();
flash_range_program(self->flash_base + offset, bufinfo.buf, bufinfo.len);
MICROPY_END_ATOMIC_SECTION(atomic_state);
- MICROPY_EVENT_POLL_HOOK
+ MICROPY_EVENT_POLL_HOOK_FAST;
// TODO check return value
return mp_const_none;
}
@@ -150,9 +190,10 @@ STATIC const mp_rom_map_elem_t rp2_flash_locals_dict_table[] = {
};
STATIC MP_DEFINE_CONST_DICT(rp2_flash_locals_dict, rp2_flash_locals_dict_table);
-const mp_obj_type_t rp2_flash_type = {
- { &mp_type_type },
- .name = MP_QSTR_Flash,
- .make_new = rp2_flash_make_new,
- .locals_dict = (mp_obj_dict_t *)&rp2_flash_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ rp2_flash_type,
+ MP_QSTR_Flash,
+ MP_TYPE_FLAG_NONE,
+ make_new, rp2_flash_make_new,
+ locals_dict, &rp2_flash_locals_dict
+ );
diff --git a/ports/rp2/rp2_pio.c b/ports/rp2/rp2_pio.c
index fe09ebe249e5..3ece26bd41c7 100644
--- a/ports/rp2/rp2_pio.c
+++ b/ports/rp2/rp2_pio.c
@@ -68,6 +68,11 @@ typedef struct _rp2_state_machine_irq_obj_t {
STATIC const rp2_state_machine_obj_t rp2_state_machine_obj[8];
STATIC uint8_t rp2_state_machine_initial_pc[8];
+// These masks keep track of PIO instruction memory used by this module.
+STATIC uint32_t rp2_pio_instruction_memory_usage_mask[2];
+
+STATIC const rp2_state_machine_obj_t *rp2_state_machine_get_object(mp_int_t sm_id);
+STATIC void rp2_state_machine_reset_all(void);
STATIC mp_obj_t rp2_state_machine_init_helper(const rp2_state_machine_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
STATIC void pio_irq0(PIO pio) {
@@ -101,11 +106,42 @@ STATIC void pio1_irq0(void) {
pio_irq0(pio1);
}
-void rp2_pio_init(void) {
- // Reset all PIO instruction memory.
- pio_clear_instruction_memory(pio0);
- pio_clear_instruction_memory(pio1);
+// Calls pio_add_program() and keeps track of used instruction memory.
+STATIC uint rp2_pio_add_managed_program(PIO pio, struct pio_program *pio_program) {
+ uint offset = pio_add_program(pio, pio_program);
+ uint32_t mask = ((1 << pio_program->length) - 1) << offset;
+ rp2_pio_instruction_memory_usage_mask[pio_get_index(pio)] |= mask;
+ return offset;
+}
+
+// Calls pio_remove_program() and keeps track of used instruction memory.
+STATIC void rp2_pio_remove_managed_program(PIO pio, struct pio_program *pio_program, uint offset) {
+ pio_remove_program(pio, pio_program, offset);
+ uint32_t mask = ((1 << pio_program->length) - 1) << offset;
+ rp2_pio_instruction_memory_usage_mask[pio_get_index(pio)] &= ~mask;
+}
+
+// Calls pio_remove_program() for all programs registered with rp2_pio_add_managed_program(),
+// that weren't already removed via rp2_pio_remove_managed_program().
+STATIC void rp2_pio_remove_all_managed_programs(PIO pio) {
+ uint32_t mask = rp2_pio_instruction_memory_usage_mask[pio_get_index(pio)];
+ for (size_t i = 0; i < 32; ++i) {
+ if (mask & (1 << i)) {
+ size_t j;
+ for (j = i + 1; j < 32; ++j) {
+ if (!(mask & (1 << j))) {
+ break;
+ }
+ }
+ struct pio_program pio_program = { NULL, j - i, -1 };
+ pio_remove_program(pio, &pio_program, i);
+ i = j; // i indexes an unused bit, or is 32
+ }
+ }
+ rp2_pio_instruction_memory_usage_mask[pio_get_index(pio)] = 0;
+}
+void rp2_pio_init(void) {
// Set up interrupts.
memset(MP_STATE_PORT(rp2_pio_irq_obj), 0, sizeof(MP_STATE_PORT(rp2_pio_irq_obj)));
memset(MP_STATE_PORT(rp2_state_machine_irq_obj), 0, sizeof(MP_STATE_PORT(rp2_state_machine_irq_obj)));
@@ -118,6 +154,14 @@ void rp2_pio_deinit(void) {
irq_set_mask_enabled((1u << PIO0_IRQ_0) | (1u << PIO0_IRQ_1), false);
irq_remove_handler(PIO0_IRQ_0, pio0_irq0);
irq_remove_handler(PIO1_IRQ_0, pio1_irq0);
+
+ rp2_state_machine_reset_all();
+
+ // Reset all PIO instruction memory allocated by this module.
+ // Note: other subsystems (eg the CYW43 driver) may use the PIO,
+ // and their PIO programs should remain intact.
+ rp2_pio_remove_all_managed_programs(pio0);
+ rp2_pio_remove_all_managed_programs(pio1);
}
/******************************************************************************/
@@ -233,7 +277,7 @@ STATIC mp_obj_t rp2_pio_add_program(mp_obj_t self_in, mp_obj_t prog_in) {
if (!pio_can_add_program(self->pio, &pio_program)) {
mp_raise_OSError(MP_ENOMEM);
}
- uint offset = pio_add_program(self->pio, &pio_program);
+ uint offset = rp2_pio_add_managed_program(self->pio, &pio_program);
// Store the program offset in the program object.
prog[PROG_OFFSET_PIO0 + PIO_NUM(self->pio)] = MP_OBJ_NEW_SMALL_INT(offset);
@@ -267,7 +311,7 @@ STATIC mp_obj_t rp2_pio_remove_program(size_t n_args, const mp_obj_t *args) {
// Remove the program from the instruction memory.
struct pio_program pio_program = { NULL, length, -1 };
- pio_remove_program(self->pio, &pio_program, offset);
+ rp2_pio_remove_managed_program(self->pio, &pio_program, offset);
return mp_const_none;
}
@@ -280,11 +324,11 @@ STATIC mp_obj_t rp2_pio_state_machine(size_t n_args, const mp_obj_t *pos_args, m
// Get and verify the state machine id.
mp_int_t sm_id = mp_obj_get_int(pos_args[1]);
if (!(0 <= sm_id && sm_id < 4)) {
- mp_raise_ValueError("invalide state machine");
+ mp_raise_ValueError("invalid StateMachine");
}
// Return the correct StateMachine object.
- const rp2_state_machine_obj_t *sm = &rp2_state_machine_obj[(self->pio == pio0 ? 0 : 4) + sm_id];
+ const rp2_state_machine_obj_t *sm = rp2_state_machine_get_object((self->pio == pio0 ? 0 : 4) + sm_id);
if (n_args > 2 || kw_args->used > 0) {
// Configuration arguments given so init this StateMachine.
@@ -371,13 +415,14 @@ STATIC const mp_rom_map_elem_t rp2_pio_locals_dict_table[] = {
};
STATIC MP_DEFINE_CONST_DICT(rp2_pio_locals_dict, rp2_pio_locals_dict_table);
-const mp_obj_type_t rp2_pio_type = {
- { &mp_type_type },
- .name = MP_QSTR_PIO,
- .print = rp2_pio_print,
- .make_new = rp2_pio_make_new,
- .locals_dict = (mp_obj_dict_t *)&rp2_pio_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ rp2_pio_type,
+ MP_QSTR_PIO,
+ MP_TYPE_FLAG_NONE,
+ make_new, rp2_pio_make_new,
+ print, rp2_pio_print,
+ locals_dict, &rp2_pio_locals_dict
+ );
STATIC mp_uint_t rp2_pio_irq_trigger(mp_obj_t self_in, mp_uint_t new_trigger) {
rp2_pio_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -408,6 +453,9 @@ STATIC const mp_irq_methods_t rp2_pio_irq_methods = {
/******************************************************************************/
// StateMachine object
+// This mask keeps track of state machines claimed by this module.
+STATIC uint32_t rp2_state_machine_claimed_mask;
+
STATIC const mp_irq_methods_t rp2_state_machine_irq_methods;
STATIC const rp2_state_machine_obj_t rp2_state_machine_obj[] = {
@@ -421,6 +469,35 @@ STATIC const rp2_state_machine_obj_t rp2_state_machine_obj[] = {
{ { &rp2_state_machine_type }, pio1, PIO1_IRQ_0, 3, 7 },
};
+STATIC const rp2_state_machine_obj_t *rp2_state_machine_get_object(mp_int_t sm_id) {
+ if (!(0 <= sm_id && sm_id < MP_ARRAY_SIZE(rp2_state_machine_obj))) {
+ mp_raise_ValueError("invalid StateMachine");
+ }
+
+ const rp2_state_machine_obj_t *sm_obj = &rp2_state_machine_obj[sm_id];
+
+ if (!(rp2_state_machine_claimed_mask & (1 << sm_id))) {
+ if (pio_sm_is_claimed(sm_obj->pio, sm_obj->sm)) {
+ mp_raise_ValueError("StateMachine claimed by external resource");
+ }
+ pio_sm_claim(sm_obj->pio, sm_obj->sm);
+ rp2_state_machine_claimed_mask |= 1 << sm_id;
+ }
+
+ return sm_obj;
+}
+
+STATIC void rp2_state_machine_reset_all(void) {
+ for (size_t i = 0; i < MP_ARRAY_SIZE(rp2_state_machine_obj); ++i) {
+ if (rp2_state_machine_claimed_mask & (1 << i)) {
+ const rp2_state_machine_obj_t *sm_obj = &rp2_state_machine_obj[i];
+ pio_sm_unclaim(sm_obj->pio, sm_obj->sm);
+ pio_sm_set_enabled(sm_obj->pio, sm_obj->sm, false);
+ }
+ }
+ rp2_state_machine_claimed_mask = 0;
+}
+
STATIC void rp2_state_machine_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
rp2_state_machine_obj_t *self = MP_OBJ_TO_PTR(self_in);
mp_printf(print, "StateMachine(%u)", self->id);
@@ -464,8 +541,8 @@ STATIC mp_obj_t rp2_state_machine_init_helper(const rp2_state_machine_obj_t *sel
if (offset < 0) {
rp2_pio_add_program(&rp2_pio_obj[PIO_NUM(self->pio)], args[ARG_prog].u_obj);
offset = mp_obj_get_int(prog[PROG_OFFSET_PIO0 + PIO_NUM(self->pio)]);
- rp2_state_machine_initial_pc[self->id] = offset;
}
+ rp2_state_machine_initial_pc[self->id] = offset;
// Compute the clock divider.
uint16_t clkdiv_int;
@@ -567,10 +644,7 @@ STATIC mp_obj_t rp2_state_machine_make_new(const mp_obj_type_t *type, size_t n_a
// Get the StateMachine object.
mp_int_t sm_id = mp_obj_get_int(args[0]);
- if (!(0 <= sm_id && sm_id < MP_ARRAY_SIZE(rp2_state_machine_obj))) {
- mp_raise_ValueError("invalid StateMachine");
- }
- const rp2_state_machine_obj_t *self = &rp2_state_machine_obj[sm_id];
+ const rp2_state_machine_obj_t *self = rp2_state_machine_get_object(sm_id);
if (n_args > 1 || n_kw > 0) {
// Configuration arguments given so init this StateMachine.
@@ -652,8 +726,7 @@ STATIC mp_obj_t rp2_state_machine_get(size_t n_args, const mp_obj_t *args) {
for (;;) {
while (pio_sm_is_rx_fifo_empty(self->pio, self->sm)) {
// This delay must be fast.
- mp_handle_pending(true);
- MICROPY_HW_USBDEV_TASK_HOOK
+ MICROPY_EVENT_POLL_HOOK_FAST;
}
uint32_t value = pio_sm_get(self->pio, self->sm) >> shift;
if (dest == NULL) {
@@ -711,8 +784,7 @@ STATIC mp_obj_t rp2_state_machine_put(size_t n_args, const mp_obj_t *args) {
}
while (pio_sm_is_tx_fifo_full(self->pio, self->sm)) {
// This delay must be fast.
- mp_handle_pending(true);
- MICROPY_HW_USBDEV_TASK_HOOK
+ MICROPY_EVENT_POLL_HOOK_FAST;
}
pio_sm_put(self->pio, self->sm, value << shift);
}
@@ -803,13 +875,14 @@ STATIC const mp_rom_map_elem_t rp2_state_machine_locals_dict_table[] = {
};
STATIC MP_DEFINE_CONST_DICT(rp2_state_machine_locals_dict, rp2_state_machine_locals_dict_table);
-const mp_obj_type_t rp2_state_machine_type = {
- { &mp_type_type },
- .name = MP_QSTR_StateMachine,
- .print = rp2_state_machine_print,
- .make_new = rp2_state_machine_make_new,
- .locals_dict = (mp_obj_dict_t *)&rp2_state_machine_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ rp2_state_machine_type,
+ MP_QSTR_StateMachine,
+ MP_TYPE_FLAG_NONE,
+ make_new, rp2_state_machine_make_new,
+ print, rp2_state_machine_print,
+ locals_dict, &rp2_state_machine_locals_dict
+ );
STATIC mp_uint_t rp2_state_machine_irq_trigger(mp_obj_t self_in, mp_uint_t new_trigger) {
rp2_state_machine_obj_t *self = MP_OBJ_TO_PTR(self_in);
@@ -836,3 +909,6 @@ STATIC const mp_irq_methods_t rp2_state_machine_irq_methods = {
.trigger = rp2_state_machine_irq_trigger,
.info = rp2_state_machine_irq_info,
};
+
+MP_REGISTER_ROOT_POINTER(void *rp2_pio_irq_obj[2]);
+MP_REGISTER_ROOT_POINTER(void *rp2_state_machine_irq_obj[8]);
diff --git a/ports/rp2/tusb_config.h b/ports/rp2/tusb_config.h
deleted file mode 100644
index ce321616a6bc..000000000000
--- a/ports/rp2/tusb_config.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * The MIT License (MIT)
- *
- * Copyright (c) 2020-2021 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_RP2_TUSB_CONFIG_H
-#define MICROPY_INCLUDED_RP2_TUSB_CONFIG_H
-
-#include "mpconfigport.h"
-
-#define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE)
-
-#define CFG_TUD_CDC (1)
-#define CFG_TUD_CDC_EP_BUFSIZE (256)
-#define CFG_TUD_CDC_RX_BUFSIZE (256)
-#define CFG_TUD_CDC_TX_BUFSIZE (256)
-
-#if MICROPY_HW_USB_MSC
-// Board and hardware specific configuration
-#define CFG_TUD_MSC (1)
-// Set MSC EP buffer size to FatFS block size to avoid partial read/writes (offset arg).
-#define CFG_TUD_MSC_BUFSIZE (MICROPY_FATFS_MAX_SS)
-#endif
-
-#endif // MICROPY_INCLUDED_RP2_TUSB_CONFIG_H
diff --git a/ports/rp2/tusb_port.c b/ports/rp2/tusb_port.c
deleted file mode 100644
index 4aac08791e94..000000000000
--- a/ports/rp2/tusb_port.c
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * 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.
- */
-
-#include "tusb.h"
-#include "pico/unique_id.h"
-
-#ifndef MICROPY_HW_USB_VID
-#define MICROPY_HW_USB_VID (0x2E8A) // Raspberry Pi
-#endif
-#ifndef MICROPY_HW_USB_PID
-#define MICROPY_HW_USB_PID (0x0005) // RP2 MicroPython
-#endif
-
-#if CFG_TUD_MSC
-#define USBD_DESC_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN + TUD_MSC_DESC_LEN)
-#else
-#define USBD_DESC_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN)
-#endif
-#define USBD_MAX_POWER_MA (250)
-
-#define USBD_ITF_CDC (0) // needs 2 interfaces
-#define USBD_ITF_MSC (2)
-#if CFG_TUD_MSC
-#define USBD_ITF_MAX (3)
-#else
-#define USBD_ITF_MAX (2)
-#endif
-
-#define USBD_CDC_EP_CMD (0x81)
-#define USBD_CDC_EP_OUT (0x02)
-#define USBD_CDC_EP_IN (0x82)
-#define USBD_CDC_CMD_MAX_SIZE (8)
-#define USBD_CDC_IN_OUT_MAX_SIZE (64)
-
-#define EPNUM_MSC_OUT (0x03)
-#define EPNUM_MSC_IN (0x83)
-
-#define USBD_STR_0 (0x00)
-#define USBD_STR_MANUF (0x01)
-#define USBD_STR_PRODUCT (0x02)
-#define USBD_STR_SERIAL (0x03)
-#define USBD_STR_CDC (0x04)
-#define USBD_STR_MSC (0x05)
-
-// Note: descriptors returned from callbacks must exist long enough for transfer to complete
-
-static const tusb_desc_device_t usbd_desc_device = {
- .bLength = sizeof(tusb_desc_device_t),
- .bDescriptorType = TUSB_DESC_DEVICE,
- .bcdUSB = 0x0200,
- .bDeviceClass = TUSB_CLASS_MISC,
- .bDeviceSubClass = MISC_SUBCLASS_COMMON,
- .bDeviceProtocol = MISC_PROTOCOL_IAD,
- .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE,
- .idVendor = MICROPY_HW_USB_VID,
- .idProduct = MICROPY_HW_USB_PID,
- .bcdDevice = 0x0100,
- .iManufacturer = USBD_STR_MANUF,
- .iProduct = USBD_STR_PRODUCT,
- .iSerialNumber = USBD_STR_SERIAL,
- .bNumConfigurations = 1,
-};
-
-static const uint8_t usbd_desc_cfg[USBD_DESC_LEN] = {
- TUD_CONFIG_DESCRIPTOR(1, USBD_ITF_MAX, USBD_STR_0, USBD_DESC_LEN,
- 0, USBD_MAX_POWER_MA),
-
- TUD_CDC_DESCRIPTOR(USBD_ITF_CDC, USBD_STR_CDC, USBD_CDC_EP_CMD,
- USBD_CDC_CMD_MAX_SIZE, USBD_CDC_EP_OUT, USBD_CDC_EP_IN, USBD_CDC_IN_OUT_MAX_SIZE),
- #if CFG_TUD_MSC
- TUD_MSC_DESCRIPTOR(USBD_ITF_MSC, 5, EPNUM_MSC_OUT, EPNUM_MSC_IN, 64),
- #endif
-};
-
-static const char *const usbd_desc_str[] = {
- [USBD_STR_MANUF] = "MicroPython",
- [USBD_STR_PRODUCT] = "Board in FS mode",
- [USBD_STR_SERIAL] = NULL, // generated dynamically
- [USBD_STR_CDC] = "Board CDC",
- #if CFG_TUD_MSC
- [USBD_STR_MSC] = "Board MSC",
- #endif
-};
-
-const uint8_t *tud_descriptor_device_cb(void) {
- return (const uint8_t *)&usbd_desc_device;
-}
-
-const uint8_t *tud_descriptor_configuration_cb(uint8_t index) {
- (void)index;
- return usbd_desc_cfg;
-}
-
-const uint16_t *tud_descriptor_string_cb(uint8_t index, uint16_t langid) {
- #define DESC_STR_MAX (20)
- static uint16_t desc_str[DESC_STR_MAX];
-
- uint8_t len;
- if (index == 0) {
- desc_str[1] = 0x0409; // supported language is English
- len = 1;
- } else {
- if (index >= sizeof(usbd_desc_str) / sizeof(usbd_desc_str[0])) {
- return NULL;
- }
- // check, if serial is requested
- if (index == USBD_STR_SERIAL) {
- pico_unique_board_id_t id;
- pico_get_unique_board_id(&id);
- // byte by byte conversion
- for (len = 0; len < 16; len += 2) {
- const char *hexdig = "0123456789abcdef";
- desc_str[1 + len] = hexdig[id.id[len >> 1] >> 4];
- desc_str[1 + len + 1] = hexdig[id.id[len >> 1] & 0x0f];
- }
- } else {
- const char *str = usbd_desc_str[index];
- for (len = 0; len < DESC_STR_MAX - 1 && str[len]; ++len) {
- desc_str[1 + len] = str[len];
- }
- }
- }
-
- // first byte is length (including header), second byte is string type
- desc_str[0] = (TUSB_DESC_STRING << 8) | (2 * len + 2);
-
- return desc_str;
-}
diff --git a/ports/rp2/usbd.c b/ports/rp2/usbd.c
new file mode 100644
index 000000000000..568b6284169b
--- /dev/null
+++ b/ports/rp2/usbd.c
@@ -0,0 +1,50 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2022 Blake W. Felt & Angus Gratton
+ *
+ * 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/mpconfig.h"
+
+#if MICROPY_HW_ENABLE_USBDEV
+
+#include "mp_usbd.h"
+#include "string.h"
+#include "tusb.h"
+#include "pico/unique_id.h"
+
+void mp_usbd_port_get_serial_number(char *serial_buf) {
+ pico_unique_board_id_t id;
+ pico_get_unique_board_id(&id);
+ // convert to hex
+ int hexlen = sizeof(id.id) * 2;
+ MP_STATIC_ASSERT(hexlen <= MICROPY_HW_USB_DESC_STR_MAX);
+ for (int i = 0; i < hexlen; i += 2) {
+ static const char *hexdig = "0123456789abcdef";
+ serial_buf[i] = hexdig[id.id[i / 2] >> 4];
+ serial_buf[i + 1] = hexdig[id.id[i / 2] & 0x0f];
+ }
+ serial_buf[hexlen] = 0;
+}
+
+#endif
diff --git a/ports/samd/Makefile b/ports/samd/Makefile
index ab74b80c161f..465a70a6171a 100644
--- a/ports/samd/Makefile
+++ b/ports/samd/Makefile
@@ -1,34 +1,46 @@
+# Select the board to build for:
+ifdef BOARD_DIR
+# Custom board path - remove trailing slash and get the final component of
+# the path as the board name.
+BOARD ?= $(notdir $(BOARD_DIR:/=))
+else
+# If not given on the command line, then default to ADAFRUIT_ITSYBITSY_M4_EXPRESS.
BOARD ?= ADAFRUIT_ITSYBITSY_M4_EXPRESS
BOARD_DIR ?= boards/$(BOARD)
+endif
+
+ifeq ($(wildcard $(BOARD_DIR)/.),)
+$(error Invalid BOARD specified: $(BOARD_DIR))
+endif
+
BUILD ?= build-$(BOARD)
CROSS_COMPILE ?= arm-none-eabi-
UF2CONV ?= $(TOP)/tools/uf2conv.py
-ifeq ($(wildcard $(BOARD_DIR)/.),)
-$(error Invalid BOARD specified: $(BOARD_DIR))
-endif
+MCU_SERIES_LOWER = $(shell echo $(MCU_SERIES) | tr '[:upper:]' '[:lower:]')
include ../../py/mkenv.mk
include $(BOARD_DIR)/mpconfigboard.mk
+include mcu/$(MCU_SERIES_LOWER)/mpconfigmcu.mk
# Qstr definitions (must come before including py.mk)
QSTR_DEFS = qstrdefsport.h
-QSTR_GLOBAL_DEPENDENCIES = $(BOARD_DIR)/mpconfigboard.h
-
-MCU_SERIES_LOWER = $(shell echo $(MCU_SERIES) | tr '[:upper:]' '[:lower:]')
+QSTR_GLOBAL_DEPENDENCIES = $(BOARD_DIR)/mpconfigboard.h mcu/$(MCU_SERIES_LOWER)/mpconfigmcu.h
FROZEN_MANIFEST ?= boards/manifest.py
# Include py core make definitions
include $(TOP)/py/py.mk
+include $(TOP)/extmod/extmod.mk
-GIT_SUBMODULES = lib/asf4 lib/tinyusb
+GIT_SUBMODULES += lib/asf4 lib/tinyusb
INC += -I.
INC += -I$(TOP)
INC += -I$(BUILD)
INC += -I$(BOARD_DIR)
+INC += -Imcu/$(MCU_SERIES_LOWER)
INC += -I$(TOP)/lib/cmsis/inc
INC += -I$(TOP)/lib/asf4/$(MCU_SERIES_LOWER)/hal/include
INC += -I$(TOP)/lib/asf4/$(MCU_SERIES_LOWER)/hal/utils/include
@@ -44,20 +56,23 @@ INC += -I$(TOP)/lib/asf4/$(MCU_SERIES_LOWER)/include
INC += -I$(TOP)/lib/asf4/$(MCU_SERIES_LOWER)/include/pio
INC += -I$(TOP)/lib/tinyusb/src
-CFLAGS_MCU_SAMD21 = -mtune=cortex-m0plus -mcpu=cortex-m0plus -msoft-float
-CFLAGS_MCU_SAMD51 = -mtune=cortex-m4 -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard
-CFLAGS = $(INC) -Wall -Werror -std=c99 -nostdlib -mthumb $(CFLAGS_MCU_$(MCU_SERIES)) -fsingle-precision-constant -Wdouble-promotion
+MAKE_PIN_AF = boards/make-pin-table.py
+PIN_AF_TABLE_CSV = mcu/$(MCU_SERIES_LOWER)/pin-af-table.csv
+BOARD_PINS = $(BOARD_DIR)/pins.csv
+GEN_PIN_AF = pin_af_table.c
+
+CFLAGS += $(INC) -Wall -Werror -std=c99 -nostdlib -mthumb $(CFLAGS_MCU) -fsingle-precision-constant -Wdouble-promotion
CFLAGS += -DMCU_$(MCU_SERIES) -D__$(CMSIS_MCU)__
-CFLAGS += $(CFLAGS_MOD) $(CFLAGS_EXTRA)
+CFLAGS += $(CFLAGS_EXTRA)
-LDFLAGS = -nostdlib $(addprefix -T,$(LD_FILES)) -Map=$@.map --cref
-LDFLAGS += $(LDFLAGS_MOD)
+LDFLAGS += -nostdlib $(addprefix -T,$(LD_FILES)) -Map=$@.map --cref
-LIBS = $(shell $(CC) $(CFLAGS) -print-libgcc-file-name)
+LIBS += $(shell $(CC) $(CFLAGS) -print-libgcc-file-name)
# Tune for Debugging or Optimization
+CFLAGS += -g # always include debug info in the ELF
ifeq ($(DEBUG),1)
-CFLAGS += -O0 -ggdb
+CFLAGS += -O0
else
CFLAGS += -Os -DNDEBUG
LDFLAGS += --gc-sections
@@ -66,74 +81,90 @@ endif
# Flags for optional C++ source code
CXXFLAGS += $(filter-out -std=c99,$(CFLAGS))
-CXXFLAGS += $(CXXFLAGS_MOD)
-ifneq ($(SRC_CXX)$(SRC_MOD_CXX),)
+
+# TODO make this common -- shouldn't be using these "private" vars from py.mk
+ifneq ($(SRC_CXX)$(SRC_USERMOD_CXX)$(SRC_USERMOD_LIB_CXX),)
LIBSTDCPP_FILE_NAME = "$(shell $(CXX) $(CXXFLAGS) -print-file-name=libstdc++.a)"
LDFLAGS += -L"$(shell dirname $(LIBSTDCPP_FILE_NAME))"
endif
-SRC_C = \
- main.c \
+MPY_CROSS_FLAGS += -march=$(MPY_CROSS_MCU_ARCH)
+
+SRC_C += \
+ mcu/$(MCU_SERIES_LOWER)/clock_config.c \
help.c \
+ machine_adc.c \
+ machine_bitstream.c \
+ machine_dac.c \
+ machine_i2c.c \
+ machine_pin.c \
+ machine_rtc.c \
+ machine_spi.c \
+ machine_uart.c \
+ machine_wdt.c \
+ main.c \
modutime.c \
modmachine.c \
- $(BOARD_DIR)/pins.c \
- machine_pin.c \
- machine_led.c \
modsamd.c \
- samd_flash.c \
mphalport.c \
+ pendsv.c \
+ pin_af.c \
+ samd_flash.c \
samd_isr.c \
samd_soc.c \
tusb_port.c \
- lib/asf4/$(MCU_SERIES_LOWER)/hal/src/hal_atomic.c \
- lib/asf4/$(MCU_SERIES_LOWER)/hal/src/hal_flash.c \
- lib/asf4/$(MCU_SERIES_LOWER)/hpl/nvmctrl/hpl_nvmctrl.c \
- lib/libm/ef_sqrt.c \
- lib/libm/fmodf.c \
- lib/libm/math.c \
- lib/libm/nearbyintf.c \
- lib/tinyusb/src/class/cdc/cdc_device.c \
- lib/tinyusb/src/common/tusb_fifo.c \
- lib/tinyusb/src/device/usbd.c \
- lib/tinyusb/src/device/usbd_control.c \
- lib/tinyusb/src/portable/microchip/samd/dcd_samd.c \
- lib/tinyusb/src/tusb.c \
+
+SHARED_SRC_C += \
+ shared/runtime/mpirq.c \
shared/libc/printf.c \
shared/libc/string0.c \
shared/readline/readline.c \
shared/runtime/gchelper_native.c \
+ shared/runtime/interrupt_char.c \
shared/runtime/pyexec.c \
+ shared/runtime/softtimer.c \
shared/runtime/stdout_helpers.c \
shared/runtime/sys_stdio_mphal.c \
shared/timeutils/timeutils.c \
-
-SRC_C += $(SRC_MOD)
-
-SRC_CXX += $(SRC_MOD_CXX)
-
-ifeq ($(MCU_SERIES),SAMD21)
-SRC_S = shared/runtime/gchelper_m0.s
-else
-SRC_S = shared/runtime/gchelper_m3.s
-endif
+ shared/tinyusb/mp_cdc_common.c \
+
+ASF4_SRC_C += $(addprefix lib/asf4/$(MCU_SERIES_LOWER)/,\
+ hal/src/hal_atomic.c \
+ hal/src/hal_flash.c \
+ hpl/nvmctrl/hpl_nvmctrl.c \
+ )
+
+LIBM_SRC_C += $(addprefix lib/libm/,\
+ ef_sqrt.c \
+ fmodf.c \
+ math.c \
+ nearbyintf.c \
+ )
+
+TINYUSB_SRC_C += $(addprefix lib/tinyusb/src/,\
+ class/cdc/cdc_device.c \
+ common/tusb_fifo.c \
+ device/usbd.c \
+ device/usbd_control.c \
+ portable/microchip/samd/dcd_samd.c \
+ tusb.c \
+ )
+
+DRIVERS_SRC_C += \
+ drivers/bus/softspi.c \
# List of sources for qstr extraction
-SRC_QSTR += \
- modutime.c \
- modmachine.c \
- machine_pin.c \
- machine_led.c \
- modsamd.c \
- samd_flash.c \
-
-SRC_QSTR += $(SRC_MOD) $(SRC_CXX)
+SRC_QSTR += $(SRC_C) $(SHARED_SRC_C) $(SRC_CXX)
OBJ += $(PY_O)
OBJ += $(addprefix $(BUILD)/, $(SRC_C:.c=.o))
OBJ += $(addprefix $(BUILD)/, $(SRC_CXX:.cpp=.o))
OBJ += $(addprefix $(BUILD)/, $(SRC_S:.s=.o))
-OBJ += $(addprefix $(BUILD)/, $(SRC_MOD:.c=.o))
+OBJ += $(addprefix $(BUILD)/, $(SHARED_SRC_C:.c=.o))
+OBJ += $(addprefix $(BUILD)/, $(ASF4_SRC_C:.c=.o))
+OBJ += $(addprefix $(BUILD)/, $(LIBM_SRC_C:.c=.o))
+OBJ += $(addprefix $(BUILD)/, $(DRIVERS_SRC_C:.c=.o))
+OBJ += $(addprefix $(BUILD)/, $(TINYUSB_SRC_C:.c=.o))
ifneq ($(FROZEN_MANIFEST),)
CFLAGS += -DMICROPY_MODULE_FROZEN_MPY
@@ -141,9 +172,6 @@ CFLAGS += -DMICROPY_MODULE_FROZEN_STR
CFLAGS += -DMICROPY_QSTR_EXTRA_POOL=mp_qstr_frozen_const_pool
endif
-# Workaround for bug in older gcc, warning on "static usbd_device_t _usbd_dev = { 0 };"
-$(BUILD)/lib/tinyusb/src/device/usbd.o: CFLAGS += -Wno-missing-braces
-
all: $(BUILD)/firmware.uf2
$(BUILD)/firmware.elf: $(OBJ)
@@ -157,4 +185,10 @@ $(BUILD)/firmware.bin: $(BUILD)/firmware.elf
$(BUILD)/firmware.uf2: $(BUILD)/firmware.bin
$(Q)$(PYTHON) $(UF2CONV) -b $(TEXT0) -c -o $@ $<
+pin_af.c: $(BUILD)/$(GEN_PIN_AF) | $(HEADER_BUILD)
+
+$(BUILD)/$(GEN_PIN_AF): $(PIN_AF_TABLE_CSV) $(BOARD_PINS) | $(HEADER_BUILD)
+ $(ECHO) "Create $@"
+ $(Q)$(PYTHON) $(MAKE_PIN_AF) --csv $(PIN_AF_TABLE_CSV) --board $(BOARD_PINS) --table $(BUILD)/$(GEN_PIN_AF) --mcu $(MCU_SERIES)
+
include $(TOP)/py/mkrules.mk
diff --git a/ports/samd/README.md b/ports/samd/README.md
index 4b434963d979..49e967102ecd 100644
--- a/ports/samd/README.md
+++ b/ports/samd/README.md
@@ -1,146 +1,61 @@
Port of MicroPython to Microchip SAMD MCUs
==========================================
-Supports SAMD21 and SAMD51.
-
-## Features:
-
-### REPL
-
-- REPL over USB VCP
-- REPL over USART using board specified USART pins (initialised on startup).
- - The USART Pins are board specific, defined in `boards/$(BOARD)/mpconfigboard.h`,
- and set at compile time. See the table below. At this stage, the USART cannot be
- moved to different pins unless `mpconfigboard.h` is edited and the port recompiled.
- - Two USART functions are accessible through MicroPython:
- - `uart_init()`. The 'C' function behind this function is what initialises the
- USART on startup. Calling this function in MicroPython resets any other peripheral
- operating on these pins and reconnects the USART SERCOM to the designated pins.
- - `uart_deinit()`. This simply 'disconnects' the SERCOM from the pins. The USART
- remains operating over USB VCP to maintain access to the REPL.
-
-### Boards
-
-| Board | USART | LFS1 Flash size | Tested |
-| ------------------------------------------------------------ | ----------------------------------------------------------- | --------------- | ------ |
-| ADAFRUIT_FEATHER_M0_EXPRESS | Tx=PA10=SERCOM0/PAD[2], Rx=PA11=SERCOM0/PAD[3] | 64k | No |
-| ADAFRUIT_ITSYBITSY_M4_EXPRESS | Tx=TX_D1=PA17=SERCOM3/PAD[0], Rx=RX_D0=PA16=SERCOM3/PAD[1] | 128k | No |
-| ADAFRUIT_TRINKET_M0 | Tx=D4=PA06=SERCOM0/PAD[2], Rx=D3=PA07=SERCOM0/PAD[3] | 64k | No |
-| MINISAM_M4 | Tx=TX_D1=PA17=SERCOM3/PAD[0], Rx=RX_D0=PA16=SERCOM3/PAD[1] | 128k | No |
-| SAMD21_XPLAINED_PRO | Tx=PA10=SERCOM0/PAD[2], Rx=PA11=SERCOM0/PAD[3] | 64k | No |
-| SEEED_WIO_TERMINAL | Tx=BCM14=PB27=SERCOM2/PAD[0], Rx=BCM15=PB26=SERCOM2/PAD[1] | 128k | Yes |
-| SEEED_XIAO | Tx=A6=PB8=SERCOM4/PAD[0], Rx=A7=PB9=SERCOM4/PAD[1] | 64k | Yes |
-
-Note: all USARTs are set to: async, 8 bit, 1 stop bit, no parity, 115200 bps.
-
-### Modules
-
-- Internal modules and functions:
-
-`>>>help('modules')`
-`__main__ micropython uheapq ustruct`
-`_boot samd uio usys`
-`_uasyncio uarray ujson utime`
-`builtins uasyncio uos uzlib`
-`gc ubinascii urandom`
-`machine uctypes ure`
-`Plus any modules on the filesystem`
-
-#### Flash
-
-- Internal Flash Block Device `samd.Flash()` initialised with littlefs1 in frozen module '`_boot.py`'.
-
-- **No external SPI Flash driver** (ToDo).
-
-- Block Device size is set in `ports/samd/boards/$(BOARD)/mpconfigboard.h` :
-
- - SAMD21: (eg; SEEED_XIAO): 64k `0xFFFF`
-
- * SAMD51: (eg; M4's): 128k `0x1FFFF`
-
-#### Pins & LEDs
-
-##### `machine.Pin()` class.
-
-- GPIO methods & constants:
-
- value IN OUT PULL_DOWN
- PULL_UP high init low
- off on toggle
-
-- Each board has its own pin numbering scheme, so please see the table below (the
- structure is defined in`boards/$(BOARD)/pins.c`) for pin numbers referenced
- (index) by 'Pin'. Eg; `SEEED_XIAO/pins.c`: `{{&machine_pin_type}, PIN_PA02}, // A0/D0`
- means MicroPython `Pin(0)` is SEEED_XIAO pin "A0/D0" on SAMD21G18A PortA, Pin2.
-
-- Note: on the SEEED_XIAO, if the TX & TX pins are used by the `Pin()` class, the `Pin()`
- initialisation disconnects the pins from the SERCOM similar to the way
- `machine.uart_deinit()` does.
-
-| MicroPython Pin() | SAMD51 Pin#/ ItsyBitsy_M4 | SAMD21 Pin#/ Feather_M0 | SAMD21 Pin#/ Xplained Pro | SAMD21 Pin#/ Trinket_M0 | SAMD51 Pin#/ Minisam | SAMD21 Pin#/ SEEED_XIAO | SAMD51 Pin#/ SEEED_WIO_TERMINAL |
-| ----------------- | -------------------------- | ------------------------ | ----------------------------------- | ------------------------ | -------------------- | ----------------------- | ------------------------------------- |
-| Pin(0) | PA16/ RX_D0 | PA11/ D0 | PB00/ PIN3_ADC(+) (ext1) | PA08/ D0 | PA02/ A0,D9 | PA02 / A0/D0 | PB08 / A0/D0 |
-| Pin(1) | PA17/ TX_D1 | PA10/ D1 | PB01/ PIN4_ADC(-) (ext1) | PA02/ D1 | PB08/ A1,D10 | PA04 / A1/D1 | PB09 / A1/D1 |
-| Pin(2) | PA07/ D2 | PA14/ D2 | PB06/ PIN5_GPIO (ext1) | PA09/ D2 | PB09/ A2,D11 | PA10 / A2/D2 | PA07 / A2/D2 |
-| Pin(3) | PB22/ D3 | PA09/ D3/ | PB07/ PIN6_GPIO (ext1) | PA07/ D3/ RxD | PA04/ A3,D12 | PA11 / A3/D3 | PB04 / A3/D3 |
-| Pin(4) | PA14/ D4 | PA08/ D4/ | PB02/ PIN7_PWM(+) (ext1) | PA06/ D4/ TxD | PA05/ A4,D13 | PA08 / A4/D4 | PB05 / A4/D4 |
-| Pin(5) | PA15/ D5 | PA15/ D5 | PB03/ PIN8_PWM(-) (ext1) | | PA06/ A5 | PA09 / A5/D5 | PB06 / A5/D5 |
-| Pin(6) | -1/ D6 | PA20/ D6 | PB04/ PIN9_IRQ/GPIO (ext1) | | PA16/ RX_D0 | PB08 / A6/D6/TX | PA04 / A6/D6 |
-| Pin(7) | PA18/ D7 | PA21/ D7 | PB05/ PIN10_SPI_SS_B/GPIO (ext1) | | PA17/ TX_D1 | PB09 / A7/D7/RX | PB07 / A7/D7 |
-| Pin(8) | -1/ D8 | PA06/ D8/ | PA08/ PIN11_TWI_SDA (ext1) | | PA07/ D2,A6 | PA07 / A8/D8 | PA06 / A8/D8 |
-| Pin(9) | PA19/ D9 | PA07/ D9/ | PA09/ PIN12_TWI_SCL (ext1) | | PA19/ D3 | PA05 / A9/D9 | PD08 / SWITCH_X |
-| Pin(10) | PA20/ D10 | PA18/ D10 | PB09/ PIN13_UART_RX (ext1) | | PA20/ D4 | PA06 / A10/D10 | PD09 / SWITCH_Y |
-| Pin(11) | PA21/ D11 | PA16/ D11 | PB08/ PIN14_UART_TX (ext1) | | PA21/ D5 | | PD10 / SWITCH_Z |
-| Pin(12) | PA23/ D12 | PA19/ D12 | PA05/ PIN15_SPI_SS_A (ext1) | | PA00/ BUTTON | | PD12 / SWITCH_B |
-| Pin(13) | PA22/ D13 | PA17/ D13/ | PA06/ PIN16_SPI_MOSI (ext1) | | | | PD20 / SWITCH_U |
-| Pin(14) | PA02/ A0 | PA02/ A0 | PA04/ PIN17_SPI_MISO (ext1) | | | | PC26 / BUTTON_1 |
-| Pin(15) | PA05/ A1 | PB08/ A1 | PA07/ PIN18_SPI_SCK (ext1) | | | | PC27 / BUTTON_2 |
-| Pin(16) | PB08/ A2 | PB09/ A2 | PA10/ PIN3_ADC(+) (ext2) | | | | PC28 / BUTTON_3 |
-| Pin(17) | PB09/ A3 | PA04/ A3/ | PA11/ PIN4_ADC(-) (ext2) | | | | PD11 / BUZZER_CTR |
-| Pin(18) | PA04/ A4 | PA05/ A4/ | PA20/ PIN5_GPIO (ext2) | | | | PC14/ 5V_OUTPUT_CTR- '1'= 5V on hdr |
-| Pin(19) | PA06/ A5 | PB02/ A5 | PA21/ PIN6_GPIO (ext2) | | | | PC15/ 3V3_OUTPUT_CTR- '0'= 3V3 on hdr |
-| Pin(20) | | | PB12/ PIN7_PWM(+) (ext2) | | | | |
-| Pin(21) | | | PB13/ PIN8_PWM(-) (ext2) | | | | |
-| Pin(22) | | | PB14/ PIN9_IRQ/GPIO (ext2) | | | | |
-| Pin(23) | | | PB15/ PIN10_SPI_SS_B/GPIO (ext2) | | | | |
-| Pin(24) | | | -1 / PIN11_TWI_SDA already defined | | | | |
-| Pin(25) | | | -1 / PIN12_TWI_SCL already defined | | | | |
-| Pin(26) | | | PB11/ PIN13_UART_RX (ext2) | | | | |
-| Pin(27) | | | PB10/ PIN14_UART_TX (ext2) | | | | |
-| Pin(28) | | | PA17/ PIN15_SPI_SS_A (ext2) | | | | |
-| Pin(29) | | | PA18/ PIN16_SPI_MOSI (ext2) | | | | |
-| Pin(30) | | | PA16/ PIN17_SPI_MISO (ext2) | | | | |
-| Pin(31) | | | PA19/ PIN18_SPI_SCK (ext2) | | | | |
-| Pin(32) | | | PA02/ PIN3_ADC(+) (ext3) | | | | |
-| Pin(33) | | | PA03/ PIN4_ADC(-) (ext3) | | | | |
-| Pin(34) | | | -1/ PIN5_GPIO already defined | | | | |
-| Pin(35) | | | PA15/ PIN6_GPIO; USER_BUTTON (ext3) | | | | |
-| Pin(36) | | | PA12/ PIN7_PWM(+) (ext3) | | | | |
-| Pin(37) | | | PA13/ PIN8_PWM(-) (ext3) | | | | |
-| Pin(38) | | | PA28/ PIN9_IRQ/GPIO (ext3) | | | | |
-| Pin(39) | | | PA27/ PIN10_SPI_SS_B/GPIO (ext3) | | | | |
-| Pin(40) | | | -1/ PIN11_TWI_SDA already defined | | | | |
-| Pin(41) | | | -1/ PIN12_TWI_SCL already defined | | | | |
-| Pin(42) | | | -1/ PIN13_UART_RX already defined | | | | |
-| Pin(43) | | | -1/ PIN14_UART_TX already defined | | | | |
-| Pin(44) | | | PA15/ PIN6_GPIO; USER_BUTTON (ext3) | | | | |
-| Pin(45) | | | PB22/ PIN16_SPI_MOSI (ext3) | | | | |
-| Pin(46) | | | PB16/ PIN17_SPI_MISO (ext3) | | | | |
-| Pin(47) | | | PB23/ PIN18_SPI_SCK (ext3) | | | | |
-
-##### `machine.LED()` class.
-
-- GPIO methods & constants:
-
-`value OUT high low`
-`off on toggle`
-
-- As above, please see `boards/$(BOARD)/pins.c` for pin numbers referenced by 'LED'.
-Eg; `SEEED_XIAO/pins.c`: `{{&machine_led_type}, PIN_PA17}, // W13` means MicroPython
-`LED(0)` is SEEED_XIAO LED "W13" connected to SAMD21G18A PortA, Pin17.
-
-| MicroPython LED() | SAMD51 Pin#/ ItsyBitsy_M4 | SAMD21 Pin#/ Feather_M0 | SAMD21 Pin#/ Xplained Pro | SAMD21 Pin#/ Trinket_M0 | SAMD51 Pin#/ Minisam | SAMD21 Pin#/ SEEED_XIAO | SAMD51 Pin#/ SEEED_WIO_TERMINAL |
-| ------------------ | -------------------------- | ------------------------ | -------------------------- | ------------------------ | --------------------- | ------------------------ | -------------------------------- |
-| LED(0) | PA22/ D13/ user LED | PA17/ D13/ user LED | PB30/ USER_LED | PA10/ USER_LED | PA15/ LED | PA17 / W13 | PA15 / USER_LED (Blue) |
-| LED(1) | | | | | | PA18 / RX_LED | PC05 / LCD_BACKLIGHT_CTR |
-| LED(2) | | | | | | PA19 / TX_LED | |
+Supports SAMD21 and SAMD51. For each supported device there is a
+subdirectory in the `boards/` directory.
+
+The entry point for the specific port documentation is at
+https://docs.micropython.org/en/latest/samd/quickref.html, which also
+shows the assignment of IO-Functions to pins. The generic MicroPython
+documentation applies for anything not specific for the SAM port.
+
+Due to the different flash sizes of SAMD21 and SAMD51 devices, the
+coverage of MicroPython modules differ. Use help("modules") to tell,
+which MicroPython modules are provided.
+
+Build instructions
+------------------
+
+Before building the firmware for a given board the MicroPython cross-compiler
+must be built; it will be used to pre-compile some of the built-in scripts to
+bytecode. The cross-compiler is built and run on the host machine, using:
+
+ $ make -C mpy-cross
+
+This command should be executed from the root directory of this repository.
+All other commands below should be executed from the ports/stm32/ directory.
+
+An ARM compiler is required for the build, along with the associated binary
+utilities. The default compiler is `arm-none-eabi-gcc`, which is available for
+Arch Linux via the package `arm-none-eabi-gcc`, for Ubuntu via instructions
+[here](https://launchpad.net/~team-gcc-arm-embedded/+archive/ubuntu/ppa), or
+see [here](https://launchpad.net/gcc-arm-embedded) for the main GCC ARM
+Embedded page. The compiler can be changed using the `CROSS_COMPILE` variable
+when invoking `make`.
+
+Next, the board to build must be selected. There is no default board. Any
+of the names of the subdirectories in the `boards/` directory is a valid board.
+The board name must be passed as the argument to `BOARD=` when invoking `make`.
+
+All boards require certain submodules to be obtained before they can be built.
+The correct set of submodules can be initialised using (with
+`ADAFRUIT_ITSYBITSY_M4_EXPRESS` as an example of the selected board):
+
+ $ make BOARD=ADAFRUIT_ITSYBITSY_M4_EXPRESS submodules
+
+Then to build the board's firmware run:
+
+ $ make BOARD=ADAFRUIT_ITSYBITSY_M4_EXPRESS clean
+ $ make BOARD=ADAFRUIT_ITSYBITSY_M4_EXPRESS
+
+The above command produces binary images in the
+`build-ADAFRUIT_ITSYBITSY_M4_EXPRESS/` subdirectory (or the equivalent
+directory for the board specified).
+
+### Flashing the Firmware
+
+Most SAMD21 and SAMD51 boards have a built in firmware loader. To start it, push
+the reset button of the boards twice. The speed varies a little bit. If the
+firmware loader starts, a drive will appear in the file manager of your PC.
+Copy the created `firmware.uf2` file to that drive. If the upload is finished, the
+drive will disappear and the board will reboot.
diff --git a/ports/samd/boards/ADAFRUIT_FEATHER_M0_EXPRESS/mpconfigboard.h b/ports/samd/boards/ADAFRUIT_FEATHER_M0_EXPRESS/mpconfigboard.h
index 6d3b7987e39d..815597899c4a 100644
--- a/ports/samd/boards/ADAFRUIT_FEATHER_M0_EXPRESS/mpconfigboard.h
+++ b/ports/samd/boards/ADAFRUIT_FEATHER_M0_EXPRESS/mpconfigboard.h
@@ -1,28 +1,4 @@
#define MICROPY_HW_BOARD_NAME "Feather M0 Express"
#define MICROPY_HW_MCU_NAME "SAMD21G18A"
-// MicroPython configs
-// samd_flash.c flash parameters
-// Build a 64k Flash storage at top. 256k-64k=196k
-// 256*1024=262144 minus 64*1024=65536 = 196608 = 0x30000
-#define MICROPY_HW_FLASH_STORAGE_BASE (0x30000)
-#define MICROPY_HW_FLASH_STORAGE_BYTES (0xFFFF)
-#define VFS_BLOCK_SIZE_BYTES (1536) // 24x 64B flash pages;
-
-// ASF4 MCU package specific Pin definitions
-#include "samd21g18a.h"
-
-// Please consult the SAM_D21 Datasheet, I/O Multiplexing and Considerations.
-// On this board (see https://learn.adafruit.com/assets/40553) TX is D1 (PA10) and RX is D0 (PA11)
-// USART pin assignments: Tx=PA10=SERCOM0/PAD[2], Rx=PA11==SERCOM0/PAD[3]
-#define CPU_FREQ (48000000) // For selecting Baud from clock.
-#define MP_PIN_GRP 0 // A=0, B=1
-#define MP_TX_PIN 10 // 'n'
-#define MP_RX_PIN 11
-#define MP_PERIPHERAL_MUX 5 // 'n'th group of 2 pins
-#define USARTx SERCOM0 // SERCOM0: tx/rx
-#define MP_PORT_FUNC 0x22 // Sets PMUXE & PMUXO to the Alternative Function.(A-H=0-7)
-#define MP_RXPO_PAD 3 // RXPO- Receive Data Pinout
-#define MP_TXPO_PAD 1 // TXPO- Transmit Data Pinout
-#define MP_SERCOMx SERCOM0_ // APBCMASK
-#define MP_SERCOM_GCLK_ID_x_CORE GCLK_CLKCTRL_ID_SERCOM0_CORE // Generic Clock Control
+#define MICROPY_HW_XOSC32K (1)
diff --git a/ports/samd/boards/ADAFRUIT_FEATHER_M0_EXPRESS/pins.c b/ports/samd/boards/ADAFRUIT_FEATHER_M0_EXPRESS/pins.c
deleted file mode 100644
index e0dd752ec900..000000000000
--- a/ports/samd/boards/ADAFRUIT_FEATHER_M0_EXPRESS/pins.c
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * This file is part of the MicroPython project, http://micropython.org/
- *
- * The MIT License (MIT)
- *
- * Copyright (c) 2021 Peter van der Burg
- *
- * 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.
- *
- * Used by machine_pin.c. Holds Board/MCU specific Pin allocations.
- */
-
-#include "modmachine.h"
-#include "pins.h"
-
-// Ensure Declaration in 'pins.h' reflects # of Pins defined here.
-const machine_pin_obj_t machine_pin_obj[] = {
- {{&machine_pin_type}, PIN_PA11}, // D0
- {{&machine_pin_type}, PIN_PA10}, // D1
- {{&machine_pin_type}, PIN_PA14}, // D2
- {{&machine_pin_type}, PIN_PA09}, // D3/
- {{&machine_pin_type}, PIN_PA08}, // D4/
- {{&machine_pin_type}, PIN_PA15}, // D5
- {{&machine_pin_type}, PIN_PA20}, // D6
- {{&machine_pin_type}, PIN_PA21}, // D7
- {{&machine_pin_type}, PIN_PA06}, // D8/
- {{&machine_pin_type}, PIN_PA07}, // D9/
- {{&machine_pin_type}, PIN_PA18}, // D10
- {{&machine_pin_type}, PIN_PA16}, // D11
- {{&machine_pin_type}, PIN_PA19}, // D12
- {{&machine_pin_type}, PIN_PA17}, // D13/
- {{&machine_pin_type}, PIN_PA02}, // A0
- {{&machine_pin_type}, PIN_PB08}, // A1
- {{&machine_pin_type}, PIN_PB09}, // A2
- {{&machine_pin_type}, PIN_PA04}, // A3/
- {{&machine_pin_type}, PIN_PA05}, // A4/
- {{&machine_pin_type}, PIN_PB02}, // A5
-};
-
-const machine_led_obj_t machine_led_obj[] = {
- {{&machine_led_type}, PIN_PA17}, // D13/ user LED
-};
diff --git a/ports/samd/boards/ADAFRUIT_FEATHER_M0_EXPRESS/pins.csv b/ports/samd/boards/ADAFRUIT_FEATHER_M0_EXPRESS/pins.csv
new file mode 100644
index 000000000000..35b6d1fd4e07
--- /dev/null
+++ b/ports/samd/boards/ADAFRUIT_FEATHER_M0_EXPRESS/pins.csv
@@ -0,0 +1,43 @@
+# Pin rows contain Pin number and pin name.
+# Pin rows start with PIN_
+# If the pin name is omitted, the pin number is added as name.
+# Empty lines and lines starting with # are ignored
+
+PIN_PA27,LED_TX
+PIN_PB03,LED_RX
+
+PIN_PA11,D0
+PIN_PA10,D1
+PIN_PA14,D2
+PIN_PA09,D3
+PIN_PA08,D4
+PIN_PA15,D5
+PIN_PA20,D6
+PIN_PA21,D7
+PIN_PA06,D8
+PIN_PA07,D9
+PIN_PA18,D10
+PIN_PA16,D11
+PIN_PA19,D12
+PIN_PA17,D13
+PIN_PA02,A0
+PIN_PB08,A1
+PIN_PB09,A2
+PIN_PA04,A3
+PIN_PA05,A4
+PIN_PB02,A5
+PIN_PB22,TX
+PIN_PB23,RX
+PIN_PA23,SCL
+PIN_PA22,SDA
+PIN_PB10,MOSI
+PIN_PA12,MISO
+PIN_PB11,SCK
+PIN_PA06,NEOPIXEL
+PIN_PA13,FLASH_CS
+
+PIN_PA24,USB_DM
+PIN_PA25,USB_DP
+
+PIN_PA30,SWCLK
+PIN_PA31,SWDIO
diff --git a/ports/samd/boards/ADAFRUIT_FEATHER_M4_EXPRESS/board.json b/ports/samd/boards/ADAFRUIT_FEATHER_M4_EXPRESS/board.json
new file mode 100644
index 000000000000..c8042aa25473
--- /dev/null
+++ b/ports/samd/boards/ADAFRUIT_FEATHER_M4_EXPRESS/board.json
@@ -0,0 +1,22 @@
+{
+ "deploy": [
+ "../deploy.md"
+ ],
+ "docs": "",
+ "features": [
+ "Battery Charging",
+ "Breadboard Friendly",
+ "Feather",
+ "Micro USB",
+ "RGB LED",
+ "SPI Flash"
+ ],
+ "images": [
+ "feather_m4_express.jpg"
+ ],
+ "mcu": "samd51",
+ "product": "Feather M4 Express",
+ "thumbnail": "",
+ "url": "https://www.adafruit.com/product/3857",
+ "vendor": "Adafruit"
+}
diff --git a/ports/samd/boards/ADAFRUIT_FEATHER_M4_EXPRESS/mpconfigboard.h b/ports/samd/boards/ADAFRUIT_FEATHER_M4_EXPRESS/mpconfigboard.h
new file mode 100644
index 000000000000..b78c003b19a5
--- /dev/null
+++ b/ports/samd/boards/ADAFRUIT_FEATHER_M4_EXPRESS/mpconfigboard.h
@@ -0,0 +1,5 @@
+#define MICROPY_HW_BOARD_NAME "Feather M4 Express"
+#define MICROPY_HW_MCU_NAME "SAMD51J19A"
+
+#define MICROPY_HW_XOSC32K (1)
+#define MICROPY_HW_MCU_OSC32KULP (1)
diff --git a/ports/samd/boards/ADAFRUIT_FEATHER_M4_EXPRESS/mpconfigboard.mk b/ports/samd/boards/ADAFRUIT_FEATHER_M4_EXPRESS/mpconfigboard.mk
new file mode 100644
index 000000000000..781faa24106d
--- /dev/null
+++ b/ports/samd/boards/ADAFRUIT_FEATHER_M4_EXPRESS/mpconfigboard.mk
@@ -0,0 +1,8 @@
+MCU_SERIES = SAMD51
+CMSIS_MCU = SAMD51J19A
+LD_FILES = boards/samd51x19a.ld sections.ld
+TEXT0 = 0x4000
+
+# The ?='s allow overriding in mpconfigboard.mk.
+# MicroPython settings
+MICROPY_VFS_LFS1 ?= 1
diff --git a/ports/samd/boards/ADAFRUIT_FEATHER_M4_EXPRESS/pins.csv b/ports/samd/boards/ADAFRUIT_FEATHER_M4_EXPRESS/pins.csv
new file mode 100644
index 000000000000..ad8449ac9ec7
--- /dev/null
+++ b/ports/samd/boards/ADAFRUIT_FEATHER_M4_EXPRESS/pins.csv
@@ -0,0 +1,43 @@
+# Pin rows contain Pin number and pin name.
+# Pin rows start with PIN_
+# If the pin name is omitted, the pin number is added as name.
+# Empty lines and lines not starting with PIN_ are ignored
+
+PIN_PB17,D0
+PIN_PB16,D1
+PIN_PA14,D4
+PIN_PA16,D5
+PIN_PA18,D6
+PIN_PB03,D8
+PIN_PA19,D9
+PIN_PA20,D10
+PIN_PA21,D11
+PIN_PA22,D12
+PIN_PA23,D13
+PIN_PA02,A0
+PIN_PA05,A1
+PIN_PB08,A2
+PIN_PB09,A3
+PIN_PA04,A4
+PIN_PB06,A5
+PIN_PA13,SCL
+PIN_PA12,SDA
+PIN_PB23,MOSI
+PIN_PB22,MISO
+PIN_PA17,SCK
+PIN_PB01,VDIV
+PIN_PA03,AREF
+PIN_PB03,NEOPIXEL
+PIN_PB11,FLASH_CS
+PIN_PB10,FLASH_SCK
+PIN_PA08,FLASH_MOSI
+PIN_PA09,FLASH_MISO
+PIN_PA10,FLASH_WP
+PIN_PA11,FLASH_HOLD
+
+PIN_PA24,USB_DM
+PIN_PA25,USB_DP
+PIN_PA26,USB_SOF
+
+PIN_PA30,SWCLK
+PIN_PA31,SWDIO
diff --git a/ports/samd/boards/ADAFRUIT_ITSYBITSY_M0_EXPRESS/board.json b/ports/samd/boards/ADAFRUIT_ITSYBITSY_M0_EXPRESS/board.json
new file mode 100644
index 000000000000..f99d19ca87f8
--- /dev/null
+++ b/ports/samd/boards/ADAFRUIT_ITSYBITSY_M0_EXPRESS/board.json
@@ -0,0 +1,20 @@
+{
+ "deploy": [
+ "../deploy.md"
+ ],
+ "docs": "",
+ "features": [
+ "Breadboard Friendly",
+ "Micro USB",
+ "RGB LED",
+ "SPI Flash"
+ ],
+ "images": [
+ "itsybitsy_m0_express.jpg"
+ ],
+ "mcu": "samd21",
+ "product": "ItsyBitsy M0 Express",
+ "thumbnail": "",
+ "url": "https://www.adafruit.com/product/3727",
+ "vendor": "Adafruit"
+}
diff --git a/ports/samd/boards/ADAFRUIT_ITSYBITSY_M0_EXPRESS/mpconfigboard.h b/ports/samd/boards/ADAFRUIT_ITSYBITSY_M0_EXPRESS/mpconfigboard.h
new file mode 100644
index 000000000000..160c61ea2aaa
--- /dev/null
+++ b/ports/samd/boards/ADAFRUIT_ITSYBITSY_M0_EXPRESS/mpconfigboard.h
@@ -0,0 +1,4 @@
+#define MICROPY_HW_BOARD_NAME "ItsyBitsy M0 Express"
+#define MICROPY_HW_MCU_NAME "SAMD21G18A"
+
+#define MICROPY_HW_DFLL_USB_SYNC (1)
diff --git a/ports/samd/boards/ADAFRUIT_ITSYBITSY_M0_EXPRESS/mpconfigboard.mk b/ports/samd/boards/ADAFRUIT_ITSYBITSY_M0_EXPRESS/mpconfigboard.mk
new file mode 100644
index 000000000000..a760cf047e62
--- /dev/null
+++ b/ports/samd/boards/ADAFRUIT_ITSYBITSY_M0_EXPRESS/mpconfigboard.mk
@@ -0,0 +1,8 @@
+MCU_SERIES = SAMD21
+CMSIS_MCU = SAMD21G18A
+LD_FILES = boards/samd21x18a.ld sections.ld
+TEXT0 = 0x2000
+
+# The ?='s allow overriding in mpconfigboard.mk.
+# MicroPython settings
+MICROPY_VFS_LFS1 ?= 1
diff --git a/ports/samd/boards/ADAFRUIT_ITSYBITSY_M0_EXPRESS/pins.csv b/ports/samd/boards/ADAFRUIT_ITSYBITSY_M0_EXPRESS/pins.csv
new file mode 100644
index 000000000000..04b1a717bd2c
--- /dev/null
+++ b/ports/samd/boards/ADAFRUIT_ITSYBITSY_M0_EXPRESS/pins.csv
@@ -0,0 +1,40 @@
+# Pin rows contain Pin number and pin name.
+# Pin rows start with PIN_
+# If the pin name is omitted, the pin number is added as name.
+# Empty lines and lines not starting with PIN_ are ignored
+
+PIN_PA11,D0
+PIN_PA10,D1
+PIN_PA14,D2
+PIN_PA09,D3
+PIN_PA08,D4
+PIN_PA15,D5
+PIN_PA21,D7
+PIN_PA07,D9
+PIN_PA18,D10
+PIN_PA16,D11
+PIN_PA19,D12
+PIN_PA17,D13
+PIN_PA02,A0
+PIN_PB08,A1
+PIN_PB09,A2
+PIN_PA04,A3
+PIN_PA05,A4
+PIN_PB02,A5
+PIN_PA22,SDA
+PIN_PA23,SCL
+PIN_PB10,MOSI
+PIN_PA12,MISO
+PIN_PB11,SCK
+PIN_PA00,DOTSTAR_CLK
+PIN_PA01,DOTSTAR_DATA
+PIN_PB22,FLASH_MOSI
+PIN_PB03,FLASH_MISO
+PIN_PB23,FLASH_SCK
+PIN_PA27,FLASH_CS
+
+PIN_PA24,USB_DM
+PIN_PA25,USB_DP
+
+PIN_PA30,SWCLK
+PIN_PA31,SWDIO
diff --git a/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/mpconfigboard.h b/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/mpconfigboard.h
index c1c4fd8cad4c..f53481d63191 100644
--- a/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/mpconfigboard.h
+++ b/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/mpconfigboard.h
@@ -1,32 +1,4 @@
#define MICROPY_HW_BOARD_NAME "ItsyBitsy M4 Express"
#define MICROPY_HW_MCU_NAME "SAMD51G19A"
-#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_FLOAT)
-#define MICROPY_PY_BUILTINS_COMPLEX (0)
-#define MICROPY_PY_MATH (0)
-#define MICROPY_PY_CMATH (0)
-
-// MicroPython configs
-// samd_flash.c flash parameters
-// Build a 128k Flash storage at top. 512k-128k=384k=0x60000
-// 512*1024= 0x80000 minus 128*1024= 0x20000 = 0x60000
-#define MICROPY_HW_FLASH_STORAGE_BASE (0x60000)
-#define MICROPY_HW_FLASH_STORAGE_BYTES (0x1FFFF)
-#define VFS_BLOCK_SIZE_BYTES (1536) //
-
-// ASF4 MCU package specific Pin definitions
-#include "samd51g19a.h"
-
-// Please consult the SAM_D51 Datasheet, I/O Multiplexing and Considerations.
-// USART pin assignments: Tx=TX_D1=PA17=SERCOM3/PAD[0], Rx=RX_D0=PA16=SERCOM3/PAD[1]
-#define CPU_FREQ (48000000) // For selecting Baud from clock.
-#define MP_PIN_GRP 1 // A-D=0-3
-#define MP_TX_PIN 17
-#define MP_RX_PIN 16 // 'n'
-#define MP_PERIPHERAL_MUX 8 // 'n'th group of 2 pins
-#define USARTx SERCOM3 //
-#define MP_PORT_FUNC 0x33 // Sets PMUXE & PMUXO to the Alternative Function.A-N=0-13
-#define MP_RXPO_PAD 1 // RXPO- Receive Data Pinout
-#define MP_TXPO_PAD 0 // TXPO- Tranmit Data Pinout
-#define MP_SERCOMx SERCOM3_ // APBCMASK
-#define MP_SERCOM_GCLK_ID_x_CORE SERCOM3_GCLK_ID_CORE
+#define MICROPY_HW_DFLL_USB_SYNC (1)
diff --git a/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/mpconfigboard.mk b/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/mpconfigboard.mk
index 6b0192c77b9e..da3e47589ad0 100644
--- a/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/mpconfigboard.mk
+++ b/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/mpconfigboard.mk
@@ -1,6 +1,6 @@
MCU_SERIES = SAMD51
CMSIS_MCU = SAMD51G19A
-LD_FILES = boards/samd51g19a.ld sections.ld
+LD_FILES = boards/samd51x19a.ld sections.ld
TEXT0 = 0x4000
# The ?='s allow overriding in mpconfigboard.mk.
diff --git a/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/pins.c b/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/pins.c
deleted file mode 100644
index 82948ccbc4f1..000000000000
--- a/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/pins.c
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * This file is part of the MicroPython project, http://micropython.org/
- *
- * The MIT License (MIT)
- *
- * Copyright (c) 2021 Peter van der Burg
- *
- * 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.
- *
- * Used by machine_pin.c. Holds Board/MCU specific Pin allocations.
- */
-
-#include "modmachine.h"
-#include "pins.h"
-
-// Ensure Declaration in 'pins.h' reflects # of Pins defined here.
-const machine_pin_obj_t machine_pin_obj[] = {
- {{&machine_pin_type}, PIN_PA16}, // RX_D0
- {{&machine_pin_type}, PIN_PA17}, // TX_D1
- {{&machine_pin_type}, PIN_PA07}, // D2
- {{&machine_pin_type}, PIN_PB22}, // D3
- {{&machine_pin_type}, PIN_PA14}, // D4
- {{&machine_pin_type}, PIN_PA15}, // D5
- {{NULL}, -1}, // D6- not terminated on breakout.
- {{&machine_pin_type}, PIN_PA18}, // D7
- {{NULL}, -1}, // D8- not terminated on breakout.
- {{&machine_pin_type}, PIN_PA19}, // D9
- {{&machine_pin_type}, PIN_PA20}, // D10
- {{&machine_pin_type}, PIN_PA21}, // D11
- {{&machine_pin_type}, PIN_PA23}, // D12
- {{&machine_pin_type}, PIN_PA22}, // D13
- {{&machine_pin_type}, PIN_PA02}, // A0
- {{&machine_pin_type}, PIN_PA05}, // A1
- {{&machine_pin_type}, PIN_PB08}, // A2
- {{&machine_pin_type}, PIN_PB09}, // A3
- {{&machine_pin_type}, PIN_PA04}, // A4
- {{&machine_pin_type}, PIN_PA06}, // A5
-};
-
-const machine_led_obj_t machine_led_obj[] = {
- {{&machine_led_type}, PIN_PA22}, // D13
-};
diff --git a/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/pins.csv b/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/pins.csv
new file mode 100644
index 000000000000..43c8e9a64a97
--- /dev/null
+++ b/ports/samd/boards/ADAFRUIT_ITSYBITSY_M4_EXPRESS/pins.csv
@@ -0,0 +1,43 @@
+# Pin rows contain Pin number and pin name.
+# Pin rows start with PIN_
+# If the pin name is omitted, the pin number is added as name.
+# Empty lines and lines not starting with PIN_ are ignored
+
+PIN_PA16,D0
+PIN_PA17,D1
+PIN_PA07,D2
+PIN_PB22,D3
+PIN_PA14,D4
+PIN_PA15,D5
+PIN_PA18,D7
+PIN_PA19,D9
+PIN_PA20,D10
+PIN_PA21,D11
+PIN_PA23,D12
+PIN_PA22,D13
+PIN_PA02,A0
+PIN_PA05,A1
+PIN_PB08,A2
+PIN_PB09,A3
+PIN_PA04,A4
+PIN_PA06,A5
+PIN_PA12,SDA
+PIN_PA13,SCL
+PIN_PA00,MOSI
+PIN_PB23,MISO
+PIN_PA01,SCK
+PIN_PB02,DOTSTAR_CLK
+PIN_PB03,DOTSTAR_DATA
+PIN_PB11,FLASH_CS
+PIN_PB10,FLASH_SCK
+PIN_PA08,FLASH_MOSI
+PIN_PA09,FLASH_MISO
+PIN_PA10,FLASH_WP
+PIN_PA11,FLASH_HOLD
+
+PIN_PA24,USB_DM
+PIN_PA25,USB_DP
+PIN_PA26,USB_SOF
+
+PIN_PA30,SWCLK
+PIN_PA31,SWDIO
diff --git a/ports/samd/boards/ADAFRUIT_TRINKET_M0/mpconfigboard.h b/ports/samd/boards/ADAFRUIT_TRINKET_M0/mpconfigboard.h
index 128689f4f74a..d3a6ba2d8687 100644
--- a/ports/samd/boards/ADAFRUIT_TRINKET_M0/mpconfigboard.h
+++ b/ports/samd/boards/ADAFRUIT_TRINKET_M0/mpconfigboard.h
@@ -1,27 +1,2 @@
#define MICROPY_HW_BOARD_NAME "Trinket M0"
#define MICROPY_HW_MCU_NAME "SAMD21E18A"
-
-// MicroPython configs
-// samd_flash.c flash parameters
-// Build a 64k Flash storage at top. 256k-64k=196k
-// 256*1024=262144 minus 64*1024=65536 = 196608 = 0x30000
-#define MICROPY_HW_FLASH_STORAGE_BASE (0x30000)
-#define MICROPY_HW_FLASH_STORAGE_BYTES (0xFFFF)
-#define VFS_BLOCK_SIZE_BYTES (1536) // 24x 64B flash pages;
-
-// ASF4 MCU package specific Pin definitions
-#include "samd21e18a.h"
-
-// Please consult the SAM_D21 Datasheet, I/O Multiplexing and Considerations.
-// USART pin assignments: Tx=D4=PA06=SERCOM0/PAD[2], Rx=D3=PA07=SERCOM0/PAD[3]
-#define CPU_FREQ (48000000) // For selecting Baud from clock.
-#define MP_PIN_GRP 1 // A=0, B=1
-#define MP_TX_PIN 6 // 'n'
-#define MP_RX_PIN 7
-#define MP_PERIPHERAL_MUX 3 // 'n'th group of 2 pins
-#define USARTx SERCOM0 // SERCOM0: tx/rx
-#define MP_PORT_FUNC 0x33 // Sets PMUXE & PMUXO to the Alternative Function.A-H=0-7
-#define MP_RXPO_PAD 3 // RXPO- Receive Data Pinout
-#define MP_TXPO_PAD 2 // TXPO- Tranmit Data Pinout
-#define MP_SERCOMx SERCOM0_ // APBCMASK
-#define MP_SERCOM_GCLK_ID_x_CORE GCLK_CLKCTRL_ID_SERCOM0_CORE // Generic Clock Control
diff --git a/ports/samd/boards/ADAFRUIT_TRINKET_M0/pins.csv b/ports/samd/boards/ADAFRUIT_TRINKET_M0/pins.csv
new file mode 100644
index 000000000000..b5f1c9801b15
--- /dev/null
+++ b/ports/samd/boards/ADAFRUIT_TRINKET_M0/pins.csv
@@ -0,0 +1,20 @@
+# Pin rows contain Pin number and pin name.
+# Pin rows start with PIN_
+# If the pin name is omitted, the pin number is added as name.
+# Empty lines and lines not starting with PIN_ are ignored
+
+PIN_PA08,D0
+PIN_PA02,D1
+PIN_PA09,D2
+PIN_PA07,D3
+PIN_PA06,D4
+PIN_PA00,DOTSTAR_DATA
+PIN_PA01,DOTSTAR_CLK
+
+PIN_PA10,LED
+
+PIN_PA24,USB_DM
+PIN_PA25,USB_DP
+
+PIN_PA30,SWCLK
+PIN_PA31,SWDIO
diff --git a/ports/samd/boards/MINISAM_M4/mpconfigboard.h b/ports/samd/boards/MINISAM_M4/mpconfigboard.h
index a65eb54b495f..6715a16f0145 100644
--- a/ports/samd/boards/MINISAM_M4/mpconfigboard.h
+++ b/ports/samd/boards/MINISAM_M4/mpconfigboard.h
@@ -1,32 +1,2 @@
#define MICROPY_HW_BOARD_NAME "Mini SAM M4"
#define MICROPY_HW_MCU_NAME "SAMD51G19A"
-
-#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_FLOAT)
-#define MICROPY_PY_BUILTINS_COMPLEX (0)
-#define MICROPY_PY_MATH (0)
-#define MICROPY_PY_CMATH (0)
-
-// MicroPython configs
-// samd_flash.c flash parameters
-// Build a 128k Flash storage at top. 512k-128k=384k=0x60000
-// 512*1024= 0x80000 minus 128*1024= 0x20000 = 0x60000
-#define MICROPY_HW_FLASH_STORAGE_BASE (0x60000)
-#define MICROPY_HW_FLASH_STORAGE_BYTES (0x1FFFF)
-#define VFS_BLOCK_SIZE_BYTES (1536) //
-
-// ASF4 MCU package specific Pin definitions
-#include "samd51g19a.h"
-
-// Please consult the SAM_D51 Datasheet, I/O Multiplexing and Considerations.
-// USART pin assignments: Tx=TX_D1=PA17=SERCOM3/PAD[0], Rx=RX_D0=PA16=SERCOM3/PAD[1]
-#define CPU_FREQ (48000000) // For selecting Baud from clock.
-#define MP_PIN_GRP 0 // A-D=0-3
-#define MP_TX_PIN 17
-#define MP_RX_PIN 16 // 'n'
-#define MP_PERIPHERAL_MUX 8 // 'n'th group of 2 pins
-#define USARTx SERCOM3 //
-#define MP_PORT_FUNC 0x33 // Sets PMUXE & PMUXO to the Alternative Function.A-N=0-13
-#define MP_RXPO_PAD 1 // RXPO- Receive Data Pinout
-#define MP_TXPO_PAD 0 // TXPO- Tranmit Data Pinout
-#define MP_SERCOMx SERCOM3_ // APBCMASK
-#define MP_SERCOM_GCLK_ID_x_CORE SERCOM3_GCLK_ID_CORE
diff --git a/ports/samd/boards/MINISAM_M4/mpconfigboard.mk b/ports/samd/boards/MINISAM_M4/mpconfigboard.mk
index 6ed0ff552b01..73afb0210446 100644
--- a/ports/samd/boards/MINISAM_M4/mpconfigboard.mk
+++ b/ports/samd/boards/MINISAM_M4/mpconfigboard.mk
@@ -1,7 +1,7 @@
# https://www.minifigboards.com/mini-sam-m4/mini-sam-m4-hardware/
MCU_SERIES = SAMD51
CMSIS_MCU = SAMD51G19A
-LD_FILES = boards/samd51g19a.ld sections.ld
+LD_FILES = boards/samd51x19a.ld sections.ld
TEXT0 = 0x4000
# The ?='s allow overriding in mpconfigboard.mk.
diff --git a/ports/samd/boards/MINISAM_M4/pins.c b/ports/samd/boards/MINISAM_M4/pins.c
deleted file mode 100644
index 6cdd840b6bc7..000000000000
--- a/ports/samd/boards/MINISAM_M4/pins.c
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * This file is part of the MicroPython project, http://micropython.org/
- *
- * The MIT License (MIT)
- *
- * Copyright (c) 2021 Peter van der Burg
- *
- * 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.
- *
- * Used by machine_pin.c. Holds Board/MCU specific Pin allocations.
- */
-
-#include "modmachine.h"
-#include "pins.h"
-
-// Ensure Declaration in 'pins.h' reflects # of Pins defined here.
-const machine_pin_obj_t machine_pin_obj[] = {
- {{&machine_pin_type}, PIN_PA02}, // A0,D9
- {{&machine_pin_type}, PIN_PB08}, // A1,D10
- {{&machine_pin_type}, PIN_PB09}, // A2,D11
- {{&machine_pin_type}, PIN_PA04}, // A3,D12
- {{&machine_pin_type}, PIN_PA05}, // A4,D13
- {{&machine_pin_type}, PIN_PA06}, // A5
- {{&machine_pin_type}, PIN_PA16}, // RX_D0
- {{&machine_pin_type}, PIN_PA17}, // TX_D1
- {{&machine_pin_type}, PIN_PA07}, // D2,A6
- {{&machine_pin_type}, PIN_PA19}, // D3
- {{&machine_pin_type}, PIN_PA20}, // D4
- {{&machine_pin_type}, PIN_PA21}, // D5
- {{&machine_pin_type}, PIN_PA00}, // BUTTON
-};
-
-const machine_led_obj_t machine_led_obj[] = {
- {{&machine_led_type}, PIN_PA15}, // LED
-};
diff --git a/ports/samd/boards/MINISAM_M4/pins.csv b/ports/samd/boards/MINISAM_M4/pins.csv
new file mode 100644
index 000000000000..f676c290a05f
--- /dev/null
+++ b/ports/samd/boards/MINISAM_M4/pins.csv
@@ -0,0 +1,35 @@
+# Pin rows contain Pin number and pin name.
+# Pin rows start with PIN_
+# If the pin name is omitted, the pin number is added as name.
+# Empty lines and lines not starting with PIN_ are ignored
+
+PIN_PA02,A0_D9
+PIN_PB08,A1_D10
+PIN_PB09,A2_D11
+PIN_PA04,A3_D12
+PIN_PA05,A4_D13
+PIN_PA06,A5
+PIN_PA16,D0
+PIN_PA17,D1
+PIN_PA07,A6_D2
+PIN_PA19,D3
+PIN_PA20,D4
+PIN_PA21,D5
+PIN_PA00,BUTTON
+PIN_PA03,AREF
+PIN_PA12,SDA
+PIN_PA13,SCL
+PIN_PB22,MOSI
+PIN_PB23,MISO
+PIN_PA01,SCK
+PIN_PB03,DOTSTAR_DATA
+PIN_PB02,DOTSTAR_CLK
+
+PIN_PA15,LED
+
+PIN_PA24,USB_DM
+PIN_PA25,USB_DP
+PIN_PA26,USB_SOF
+
+PIN_PA30,SWCLK
+PIN_PA31,SWDIO
diff --git a/ports/samd/boards/MINISAM_M4/pins.h b/ports/samd/boards/MINISAM_M4/pins.h
deleted file mode 100644
index 892b0e7b9763..000000000000
--- a/ports/samd/boards/MINISAM_M4/pins.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * This file is part of the MicroPython project, http://micropython.org/
- *
- * The MIT License (MIT)
- *
- * Copyright (c) 2021 Peter van der Burg
- *
- * 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.
- *
- * Used by machine_pin.c & board specific pins.c. Holds Board/MCU specific Pin
- * allocations.
- */
-
-typedef struct _machine_pin_obj_t {
- mp_obj_base_t base;
- uint32_t id;
-} machine_pin_obj_t;
-
-typedef struct _machine_led_obj_t {
- mp_obj_base_t base;
- uint32_t id;
-} machine_led_obj_t;
-
-// MUST explicitly hold array # of rows, else machine_pin.c wont compile.
-extern const machine_pin_obj_t machine_pin_obj[13];
-extern const machine_led_obj_t machine_led_obj[1];
diff --git a/ports/samd/boards/SAMD21_XPLAINED_PRO/mpconfigboard.h b/ports/samd/boards/SAMD21_XPLAINED_PRO/mpconfigboard.h
index a7dbf76144bc..064d1ecc0d03 100644
--- a/ports/samd/boards/SAMD21_XPLAINED_PRO/mpconfigboard.h
+++ b/ports/samd/boards/SAMD21_XPLAINED_PRO/mpconfigboard.h
@@ -1,28 +1,4 @@
#define MICROPY_HW_BOARD_NAME "SAMD21-XPLAINED-PRO"
#define MICROPY_HW_MCU_NAME "SAMD21J18A"
-// MicroPython configs
-// samd_flash.c flash parameters
-// Build a 64k Flash storage at top. 256k-64k=196k
-// 256*1024=262144 minus 64*1024=65536 = 196608 = 0x30000
-#define MICROPY_HW_FLASH_STORAGE_BASE (0x30000)
-#define MICROPY_HW_FLASH_STORAGE_BYTES (0xFFFF)
-#define VFS_BLOCK_SIZE_BYTES (1536) // 24x 64B flash pages;
-
-// ASF4 MCU package specific Pin definitions
-#include "samd21j18a.h"
-
-// Please consult the SAM_D21 Datasheet, I/O Multiplexing and Considerations.
-// USART pin assignments: (This board has 3 USARTS brought out to the pins. See https://docs.zephyrproject.org/1.14.1/boards/arm/atsamd21_xpro/doc/index.html#serial-port )
-// Tx=PA10=SERCOM0/PAD[2], Rx=PA11=SERCOM0/PAD[3]
-#define CPU_FREQ (48000000) // For selecting Baud from clock.
-#define MP_PIN_GRP 1 // A=0, B=1
-#define MP_TX_PIN 10 // 'n'
-#define MP_RX_PIN 11
-#define MP_PERIPHERAL_MUX 5 // 'n'th group of 2 pins
-#define USARTx SERCOM0 // SERCOM0: tx/rx
-#define MP_PORT_FUNC 0x22 // Sets PMUXE & PMUXO to the Alternative Function.(A-H=0-7)
-#define MP_RXPO_PAD 3 // RXPO- Receive Data Pinout
-#define MP_TXPO_PAD 2 // TXPO- Tranmit Data Pinout
-#define MP_SERCOMx SERCOM0_ // APBCMASK
-#define MP_SERCOM_GCLK_ID_x_CORE GCLK_CLKCTRL_ID_SERCOM0_CORE // Generic Clock Control
+#define MICROPY_HW_XOSC32K (1)
diff --git a/ports/samd/boards/SAMD21_XPLAINED_PRO/pins.c b/ports/samd/boards/SAMD21_XPLAINED_PRO/pins.c
deleted file mode 100644
index 2a2d50eb48fc..000000000000
--- a/ports/samd/boards/SAMD21_XPLAINED_PRO/pins.c
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * This file is part of the MicroPython project, http://micropython.org/
- *
- * The MIT License (MIT)
- *
- * Copyright (c) 2021 Peter van der Burg
- *
- * 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.
- *
- * Used by machine_pin.c. Holds Board/MCU specific Pin allocations.
- */
-
-#include "modmachine.h"
-#include "pins.h"
-
-// Ensure Declaration in 'pins.h' reflects # of Pins defined here.
-const machine_pin_obj_t machine_pin_obj[] = {
- // EXT1
- {{&machine_pin_type}, PIN_PB00}, // PIN3_ADC(+)
- {{&machine_pin_type}, PIN_PB01}, // PIN4_ADC(-)
- {{&machine_pin_type}, PIN_PB06}, // PIN5_GPIO
- {{&machine_pin_type}, PIN_PB07}, // PIN6_GPIO
- {{&machine_pin_type}, PIN_PB02}, // PIN7_PWM(+)
- {{&machine_pin_type}, PIN_PB03}, // PIN8_PWM(-)
- {{&machine_pin_type}, PIN_PB04}, // PIN9_IRQ/GPIO
- {{&machine_pin_type}, PIN_PB05}, // PIN10_SPI_SS_B/GPIO
- {{&machine_pin_type}, PIN_PA08}, // PIN11_TWI_SDA
- {{&machine_pin_type}, PIN_PA09}, // PIN12_TWI_SCL
- {{&machine_pin_type}, PIN_PB09}, // PIN13_UART_RX
- {{&machine_pin_type}, PIN_PB08}, // PIN14_UART_TX
- {{&machine_pin_type}, PIN_PA05}, // PIN15_SPI_SS_A
- {{&machine_pin_type}, PIN_PA06}, // PIN16_SPI_MOSI
- {{&machine_pin_type}, PIN_PA04}, // PIN17_SPI_MISO
- {{&machine_pin_type}, PIN_PA07}, // PIN18_SPI_SCK
-
- // EXT2
- {{&machine_pin_type}, PIN_PA10}, // PIN3_ADC(+)
- {{&machine_pin_type}, PIN_PA11}, // PIN4_ADC(-)
- {{&machine_pin_type}, PIN_PA20}, // PIN5_GPIO
- {{&machine_pin_type}, PIN_PA21}, // PIN6_GPIO
- {{&machine_pin_type}, PIN_PB12}, // PIN7_PWM(+)
- {{&machine_pin_type}, PIN_PB13}, // PIN8_PWM(-)
- {{&machine_pin_type}, PIN_PB14}, // PIN9_IRQ/GPIO
- {{&machine_pin_type}, PIN_PB15}, // PIN10_SPI_SS_B/GPIO
- {{NULL}, -1}, // PIN_PA08/ PIN11_TWI_SDA already defined
- {{NULL}, -1}, // PIN_PA09/ PIN12_TWI_SCL already defined
- {{&machine_pin_type}, PIN_PB11}, // PIN13_UART_RX
- {{&machine_pin_type}, PIN_PB10}, // PIN14_UART_TX
- {{&machine_pin_type}, PIN_PA17}, // PIN15_SPI_SS_A
- {{&machine_pin_type}, PIN_PA18}, // PIN16_SPI_MOSI
- {{&machine_pin_type}, PIN_PA16}, // PIN17_SPI_MISO
- {{&machine_pin_type}, PIN_PA19}, // PIN18_SPI_SCK
-
- // EXT3
- {{&machine_pin_type}, PIN_PA02}, // PIN3_ADC(+)
- {{&machine_pin_type}, PIN_PA03}, // PIN4_ADC(-)
- {{NULL}, -1}, // PIN_PB30/ PIN5_GPIO already defined
- {{&machine_pin_type}, PIN_PA15}, // PIN6_GPIO; USER_BUTTON
- {{&machine_pin_type}, PIN_PA12}, // PIN7_PWM(+)
- {{&machine_pin_type}, PIN_PA13}, // PIN8_PWM(-)
- {{&machine_pin_type}, PIN_PA28}, // PIN9_IRQ/GPIO
- {{&machine_pin_type}, PIN_PA27}, // PIN10_SPI_SS_B/GPIO
- {{NULL}, -1}, // PIN_PA08/ PIN11_TWI_SDA already defined
- {{NULL}, -1}, // PIN_PA09/ PIN12_TWI_SCL already defined
- {{NULL}, -1}, // PIN_PB11/ PIN13_UART_RX already defined
- {{NULL}, -1}, // PIN_PB10/ PIN14_UART_TX already defined
- {{&machine_pin_type}, PIN_PB17}, // PIN15_SPI_SS_A
- {{&machine_pin_type}, PIN_PB22}, // PIN16_SPI_MOSI
- {{&machine_pin_type}, PIN_PB16}, // PIN17_SPI_MISO
- {{&machine_pin_type}, PIN_PB23}, // PIN18_SPI_SCK
-};
-
-const machine_led_obj_t machine_led_obj[] = {
- {{&machine_led_type}, PIN_PB30}, // USER_LED
-};
diff --git a/ports/samd/boards/SAMD21_XPLAINED_PRO/pins.csv b/ports/samd/boards/SAMD21_XPLAINED_PRO/pins.csv
new file mode 100644
index 000000000000..5990c373bf93
--- /dev/null
+++ b/ports/samd/boards/SAMD21_XPLAINED_PRO/pins.csv
@@ -0,0 +1,60 @@
+# Pin rows contain Pin number and pin name.
+# Pin rows start with PIN_
+# If the pin name is omitted, the pin number is added as name.
+# Empty lines and lines not starting with PIN_ are ignored
+
+# EXT1
+PIN_PB00,EXT1_PIN3
+PIN_PB01,EXT1_PIN4
+PIN_PB06,EXT1_PIN5
+PIN_PB07,EXT1_PIN6
+PIN_PB02,EXT1_PIN7
+PIN_PB03,EXT1_PIN8
+PIN_PB04,EXT1_PIN9
+PIN_PB05,EXT1_PIN10
+PIN_PA08,EXT1_PIN11
+PIN_PA09,EXT1_PIN12
+PIN_PB09,EXT1_PIN13
+PIN_PB08,EXT1_PIN14
+PIN_PA05,EXT1_PIN15
+PIN_PA06,EXT1_PIN16
+PIN_PA04,EXT1_PIN17
+PIN_PA07,EXT1_PIN18
+
+# EXT2
+PIN_PA10,EXT2_PIN3
+PIN_PA11,EXT2_PIN4
+PIN_PA20,EXT2_PIN5
+PIN_PA21,EXT2_PIN6
+PIN_PB12,EXT2_PIN7
+PIN_PB13,EXT2_PIN8
+PIN_PB14,EXT2_PIN9
+PIN_PB15,EXT2_PIN10
+PIN_PB11,EXT2_PIN13
+PIN_PB10,EXT2_PIN14
+PIN_PA17,EXT2_PIN15
+PIN_PA18,EXT2_PIN16
+PIN_PA16,EXT2_PIN17
+PIN_PA19,EXT2_PIN18
+
+# EXT3
+PIN_PA02,EXT3_PIN3
+PIN_PA03,EXT3_PIN4
+PIN_PA15,EXT3_PIN6
+PIN_PA12,EXT3_PIN7
+PIN_PA13,EXT3_PIN8
+PIN_PA28,EXT3_PIN9
+PIN_PA27,EXT3_PIN10
+PIN_PB17,EXT3_PIN15
+PIN_PB22,EXT3_PIN16
+PIN_PB16,EXT3_PIN17
+PIN_PB23,EXT3_PIN18
+
+PIN_PB30,LED
+
+PIN_PA24,USB_DM
+PIN_PA25,USB_DP
+
+PIN_PA30,SWCLK
+PIN_PA31,SWDIO
+
diff --git a/ports/samd/boards/SAMD21_XPLAINED_PRO/pins.h b/ports/samd/boards/SAMD21_XPLAINED_PRO/pins.h
deleted file mode 100644
index 0b0e878b43e1..000000000000
--- a/ports/samd/boards/SAMD21_XPLAINED_PRO/pins.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * This file is part of the MicroPython project, http://micropython.org/
- *
- * The MIT License (MIT)
- *
- * Copyright (c) 2021 Peter van der Burg
- *
- * 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.
- *
- * Used by machine_pin.c & board specific pins.c. Holds Board/MCU specific Pin
- * allocations.
- */
-
-typedef struct _machine_pin_obj_t {
- mp_obj_base_t base;
- uint32_t id;
-} machine_pin_obj_t;
-
-typedef struct _machine_led_obj_t {
- mp_obj_base_t base;
- uint32_t id;
-} machine_led_obj_t;
-
-// MUST explicitly hold array # of rows, else machine_pin.c wont compile.
-extern const machine_pin_obj_t machine_pin_obj[48];
-extern const machine_led_obj_t machine_led_obj[1];
diff --git a/ports/samd/boards/SEEED_WIO_TERMINAL/mpconfigboard.h b/ports/samd/boards/SEEED_WIO_TERMINAL/mpconfigboard.h
index 290bd802b8a0..8260992101c5 100644
--- a/ports/samd/boards/SEEED_WIO_TERMINAL/mpconfigboard.h
+++ b/ports/samd/boards/SEEED_WIO_TERMINAL/mpconfigboard.h
@@ -1,32 +1,4 @@
#define MICROPY_HW_BOARD_NAME "Wio Terminal D51R"
#define MICROPY_HW_MCU_NAME "SAMD51P19A"
-#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_FLOAT)
-#define MICROPY_PY_BUILTINS_COMPLEX (0)
-#define MICROPY_PY_MATH (0)
-#define MICROPY_PY_CMATH (0)
-
-// MicroPython configs
-// samd_flash.c flash parameters
-// Build a 128k Flash storage at top. 512k-128k=384k=0x60000
-// 512*1024= 0x80000 minus 128*1024= 0x20000 = 0x60000
-#define MICROPY_HW_FLASH_STORAGE_BASE (0x60000)
-#define MICROPY_HW_FLASH_STORAGE_BYTES (0x1FFFF)
-#define VFS_BLOCK_SIZE_BYTES (1536) // 24x 64B flash pages;
-
-// ASF4 MCU package specific Pin definitions
-#include "samd51p19a.h"
-
-// Please consult the SAM_D51 Datasheet, I/O Multiplexing and Considerations.
-// WIO_Terminal USART pin assignments: Tx=BCM14=PB27=SERCOM2/PAD[0], Rx=BCM15=PB26=SERCOM2/PAD[1]
-#define CPU_FREQ (48000000) // For selecting Baud from clock.
-#define MP_PIN_GRP 1 // A-D=0-3
-#define MP_TX_PIN 27
-#define MP_RX_PIN 26 // 'n'
-#define MP_PERIPHERAL_MUX 13 // 'n'th group of 2 pins
-#define USARTx SERCOM2 //
-#define MP_PORT_FUNC 0x22 // Sets PMUXE & PMUXO to the Alternative Function.A-N=0-13
-#define MP_RXPO_PAD 1 // RXPO- Receive Data Pinout
-#define MP_TXPO_PAD 0 // TXPO- Tranmit Data Pinout
-#define MP_SERCOMx SERCOM2_ // APBCMASK
-#define MP_SERCOM_GCLK_ID_x_CORE SERCOM2_GCLK_ID_CORE
+#define MICROPY_HW_XOSC32K (1)
diff --git a/ports/samd/boards/SEEED_WIO_TERMINAL/mpconfigboard.mk b/ports/samd/boards/SEEED_WIO_TERMINAL/mpconfigboard.mk
index 90fb7f2dd076..c2c4da615273 100644
--- a/ports/samd/boards/SEEED_WIO_TERMINAL/mpconfigboard.mk
+++ b/ports/samd/boards/SEEED_WIO_TERMINAL/mpconfigboard.mk
@@ -1,6 +1,6 @@
MCU_SERIES = SAMD51
CMSIS_MCU = SAMD51P19A
-LD_FILES = boards/samd51p19a.ld sections.ld
+LD_FILES = boards/samd51x19a.ld sections.ld
TEXT0 = 0x4000
# The ?='s allow overriding in mpconfigboard.mk.
diff --git a/ports/samd/boards/SEEED_WIO_TERMINAL/pins.c b/ports/samd/boards/SEEED_WIO_TERMINAL/pins.c
deleted file mode 100644
index 9862552fa3d8..000000000000
--- a/ports/samd/boards/SEEED_WIO_TERMINAL/pins.c
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * This file is part of the MicroPython project, http://micropython.org/
- *
- * The MIT License (MIT)
- *
- * Copyright (c) 2021 Peter van der Burg
- *
- * 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.
- *
- * Used by machine_pin.c. Holds Board/MCU specific Pin allocations.
- */
-
-#include "modmachine.h"
-#include "pins.h"
-
-// Ensure Declaration in "pins.h" reflects # of Pins defined here.
-const machine_pin_obj_t machine_pin_obj[] = {
- {{&machine_pin_type}, PIN_PB08}, // A0/D0
- {{&machine_pin_type}, PIN_PB09}, // A1/D1
- {{&machine_pin_type}, PIN_PA07}, // A2/D2
- {{&machine_pin_type}, PIN_PB04}, // A3/D3
- {{&machine_pin_type}, PIN_PB05}, // A4/D4
- {{&machine_pin_type}, PIN_PB06}, // A5/D5
- {{&machine_pin_type}, PIN_PA04}, // A6/D6
- {{&machine_pin_type}, PIN_PB07}, // A7/D7
- {{&machine_pin_type}, PIN_PA06}, // A8/D8
- {{&machine_pin_type}, PIN_PD08}, // SWITCH_X
- {{&machine_pin_type}, PIN_PD09}, // SWITCH_Y
- {{&machine_pin_type}, PIN_PD10}, // SWITCH_Z
- {{&machine_pin_type}, PIN_PD12}, // SWITCH_B
- {{&machine_pin_type}, PIN_PD20}, // SWITCH_U
- {{&machine_pin_type}, PIN_PC26}, // BUTTON_1
- {{&machine_pin_type}, PIN_PC27}, // BUTTON_2
- {{&machine_pin_type}, PIN_PC28}, // BUTTON_3
- {{&machine_pin_type}, PIN_PD11}, // BUZZER_CTR
- {{&machine_pin_type}, PIN_PC14}, // 5V_OUTPUT_CTR- enable 5V on hdr
- {{&machine_pin_type}, PIN_PC15}, // 3V3_OUTPUT_CTR- enable 3V3 on hdr
-};
-
-// Ensure Declaration in 'pins.h' reflects # of Pins defined here.
-const machine_led_obj_t machine_led_obj[] = {
- {{&machine_led_type}, PIN_PA15}, // USER_LED (Blue)
- {{&machine_led_type}, PIN_PC05}, // LCD_BACKLIGHT_CTR
-};
diff --git a/ports/samd/boards/SEEED_WIO_TERMINAL/pins.csv b/ports/samd/boards/SEEED_WIO_TERMINAL/pins.csv
new file mode 100644
index 000000000000..622de4c6c5bb
--- /dev/null
+++ b/ports/samd/boards/SEEED_WIO_TERMINAL/pins.csv
@@ -0,0 +1,69 @@
+# Pin rows contain Pin number and pin name.
+# Pin rows start with PIN_
+# If the pin name is omitted, the pin number is added as name.
+# Empty lines and lines not starting with PIN_ are ignored
+
+PIN_PB08,A0_D0
+PIN_PB09,A1_D1
+PIN_PA07,A2_D2
+PIN_PB04,A3_D3
+PIN_PB05,A4_D4
+PIN_PB06,A5_D5
+PIN_PA04,A6_D6
+PIN_PB07,A7_D7
+PIN_PA06,A8_D8
+PIN_PD08,SWITCH_X
+PIN_PD09,SWITCH_Y
+PIN_PD10,SWITCH_Z
+PIN_PD12,SWITCH_B
+PIN_PD20,SWITCH_U
+PIN_PC26,BUTTON_1
+PIN_PC27,BUTTON_2
+PIN_PC28,BUTTON_3
+PIN_PC14,5V_ENABLE
+PIN_PC15,3V3_ENABLE
+PIN_PB26,TX
+PIN_PB27,RX
+PIN_PA13,SDA0
+PIN_PA12,SCL0
+PIN_PA17,SDA1
+PIN_PA16,SCL1
+PIN_PB02,MOSI
+PIN_PB00,MISO
+PIN_PB03,SCK
+PIN_PB01,CS
+PIN_PB15,GPCLK0
+PIN_PB12,GPCLK1
+PIN_PB13,GPCLK2
+PIN_PC16,SD_MOSI
+PIN_PC18,SD_MISO
+PIN_PC17,SD_SCK
+PIN_PC19,SD_CS
+PIN_PD21,SD_DET
+PIN_PA20,I2S_LRCLK
+PIN_PA21,I2S_SDIN
+PIN_PA22,I2S_SDOUT
+PIN_PB16,I2C_BCLK
+PIN_PB18,LCD_MISO
+PIN_PB19,LCD_MOSI
+PIN_PB20,LCD_SCK
+PIN_PB21,LCD_CS
+PIN_PC05,LCD_BACKLIGHT
+PIN_PC06,LCD_D_C
+PIN_PC07,LCD_RESET
+PIN_PC10,LCD_XL
+PIN_PC11,LCD_YU
+PIN_PC12,LCD_XR
+PIN_PC13,LCD_YD
+PIN_PC30,MIC
+PIN_PD11,BUZZER
+
+PIN_PA15,LED_BLUE
+PIN_PC05,LED_LCD
+
+PIN_PA24,USB_DM
+PIN_PA25,USB_DP
+PIN_PA26,USB_SOF
+
+PIN_PA30,SWCLK
+PIN_PA31,SWDIO
diff --git a/ports/samd/boards/SEEED_WIO_TERMINAL/pins.h b/ports/samd/boards/SEEED_WIO_TERMINAL/pins.h
deleted file mode 100644
index 45ecc254f11e..000000000000
--- a/ports/samd/boards/SEEED_WIO_TERMINAL/pins.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * This file is part of the MicroPython project, http://micropython.org/
- *
- * The MIT License (MIT)
- *
- * Copyright (c) 2021 Peter van der Burg
- *
- * 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.
- *
- * Used by machine_pin.c & board specific pins.c. Holds Board/MCU specific Pin
- * allocations.
- */
-
-typedef struct _machine_pin_obj_t {
- mp_obj_base_t base;
- uint32_t id;
-} machine_pin_obj_t;
-
-typedef struct _machine_led_obj_t {
- mp_obj_base_t base;
- uint32_t id;
-} machine_led_obj_t;
-
-// MUST explicitly hold array # of rows, else machine_pin.c wont compile.
-extern const machine_pin_obj_t machine_pin_obj[20];
-extern const machine_led_obj_t machine_led_obj[2];
diff --git a/ports/samd/boards/SEEED_XIAO/mpconfigboard.h b/ports/samd/boards/SEEED_XIAO/mpconfigboard.h
deleted file mode 100644
index 6422d7ea0232..000000000000
--- a/ports/samd/boards/SEEED_XIAO/mpconfigboard.h
+++ /dev/null
@@ -1,27 +0,0 @@
-#define MICROPY_HW_BOARD_NAME "Seeed Xiao"
-#define MICROPY_HW_MCU_NAME "SAMD21G18A"
-
-// MicroPython configs
-// samd_flash.c flash parameters
-// Build a 64k Flash storage at top. 256k-64k=196k
-// 256*1024=262144 minus 64*1024=65536 = 196608 = 0x30000
-#define MICROPY_HW_FLASH_STORAGE_BASE (0x30000)
-#define MICROPY_HW_FLASH_STORAGE_BYTES (0xFFFF)
-#define VFS_BLOCK_SIZE_BYTES (1536) // 24x 64B flash pages;
-
-// ASF4 MCU package specific Pin definitions
-#include "samd21g18a.h"
-
-// Please consult the SAM_D21 Datasheet, I/O Multiplexing and Considerations.
-// XIAO_M0 USART pin assignments: Tx=A6=PB8=SERCOM4/PAD[0], Rx=PB9=A7=SERCOM4/PAD[1]
-#define CPU_FREQ (48000000) // For selecting Baud from clock.
-#define MP_PIN_GRP 1 // A=0, B=1
-#define MP_TX_PIN 8 // 'n'
-#define MP_RX_PIN 9
-#define MP_PERIPHERAL_MUX 4 // 'n'th group of 2 pins
-#define USARTx SERCOM4 // SERCOM4:XIAO_M0 tx/rx
-#define MP_PORT_FUNC 0x33 // Sets PMUXE & PMUXO to the Alternative Function.A-H=0-7
-#define MP_RXPO_PAD 1 // RXPO- Receive Data Pinout
-#define MP_TXPO_PAD 0 // TXPO- Tranmit Data Pinout
-#define MP_SERCOMx SERCOM4_ // APBCMASK
-#define MP_SERCOM_GCLK_ID_x_CORE GCLK_CLKCTRL_ID_SERCOM4_CORE // Generic Clock Control
diff --git a/ports/samd/boards/SEEED_XIAO/pins.c b/ports/samd/boards/SEEED_XIAO/pins.c
deleted file mode 100644
index 6043913d2bad..000000000000
--- a/ports/samd/boards/SEEED_XIAO/pins.c
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * This file is part of the MicroPython project, http://micropython.org/
- *
- * The MIT License (MIT)
- *
- * Copyright (c) 2021 Peter van der Burg
- *
- * 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.
- *
- * Used by machine_pin.c. Holds Board/MCU specific Pin allocations.
- */
-
-#include "modmachine.h"
-#include "pins.h"
-
-// Ensure Declaration in 'pins.h' reflects # of Pins defined here.
-const machine_pin_obj_t machine_pin_obj[] = {
- {{&machine_pin_type}, PIN_PA02}, // A0/D0
- {{&machine_pin_type}, PIN_PA04}, // A1/D1
- {{&machine_pin_type}, PIN_PA10}, // A2/D2
- {{&machine_pin_type}, PIN_PA11}, // A3/D3
- {{&machine_pin_type}, PIN_PA08}, // A4/D4
- {{&machine_pin_type}, PIN_PA09}, // A5/D5
- {{&machine_pin_type}, PIN_PB08}, // A6/D6
- {{&machine_pin_type}, PIN_PB09}, // A7/D7
- {{&machine_pin_type}, PIN_PA07}, // A8/D8
- {{&machine_pin_type}, PIN_PA05}, // A9/D9
- {{&machine_pin_type}, PIN_PA06}, // A10/D10
-};
-
-const machine_led_obj_t machine_led_obj[] = {
-// XIAO: Just the available LED Pins: User LED (PA17), Rx & Tx.
- {{&machine_led_type}, PIN_PA17}, // W13
- {{&machine_led_type}, PIN_PA18}, // RX_LED
- {{&machine_led_type}, PIN_PA19}, // TX_LED
-};
diff --git a/ports/samd/boards/SEEED_XIAO/pins.h b/ports/samd/boards/SEEED_XIAO/pins.h
deleted file mode 100644
index 226b3f1d7b07..000000000000
--- a/ports/samd/boards/SEEED_XIAO/pins.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * This file is part of the MicroPython project, http://micropython.org/
- *
- * The MIT License (MIT)
- *
- * Copyright (c) 2021 Peter van der Burg
- *
- * 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.
- *
- * Used by machine_pin.c & board specific pins.c. Holds Board/MCU specific Pin
- * allocations.
- */
-
-typedef struct _machine_pin_obj_t {
- mp_obj_base_t base;
- uint32_t id;
-} machine_pin_obj_t;
-
-typedef struct _machine_led_obj_t {
- mp_obj_base_t base;
- uint32_t id;
-} machine_led_obj_t;
-
-// MUST explicitly hold array # of rows, else machine_pin.c wont compile.
-extern const machine_pin_obj_t machine_pin_obj[11];
-extern const machine_led_obj_t machine_led_obj[3];
diff --git a/ports/samd/boards/SEEED_XIAO/board.json b/ports/samd/boards/SEEED_XIAO_SAMD21/board.json
similarity index 88%
rename from ports/samd/boards/SEEED_XIAO/board.json
rename to ports/samd/boards/SEEED_XIAO_SAMD21/board.json
index f5fe27184724..4e6217e19e4a 100644
--- a/ports/samd/boards/SEEED_XIAO/board.json
+++ b/ports/samd/boards/SEEED_XIAO_SAMD21/board.json
@@ -8,7 +8,7 @@
],
"images": ["seeeduino-xiao.jpg"],
"mcu": "samd21",
- "product": "Seeeduino XIAO",
+ "product": "Seeeduino XIAO (SAMD21)",
"thumbnail": "",
"url": "https://www.seeedstudio.com/Seeeduino-XIAO-Arduino-Microcontroller-SAMD21-Cortex-M0+-p-4426.html",
"vendor": "Seeed Studio"
diff --git a/ports/samd/boards/SEEED_XIAO_SAMD21/mpconfigboard.h b/ports/samd/boards/SEEED_XIAO_SAMD21/mpconfigboard.h
new file mode 100644
index 000000000000..7447c5c3acf7
--- /dev/null
+++ b/ports/samd/boards/SEEED_XIAO_SAMD21/mpconfigboard.h
@@ -0,0 +1,5 @@
+#define MICROPY_HW_BOARD_NAME "Seeed Xiao"
+#define MICROPY_HW_MCU_NAME "SAMD21G18A"
+
+#define MICROPY_HW_XOSC32K (1)
+#define MICROPY_HW_ADC_VREF (2)
diff --git a/ports/samd/boards/SEEED_XIAO/mpconfigboard.mk b/ports/samd/boards/SEEED_XIAO_SAMD21/mpconfigboard.mk
similarity index 100%
rename from ports/samd/boards/SEEED_XIAO/mpconfigboard.mk
rename to ports/samd/boards/SEEED_XIAO_SAMD21/mpconfigboard.mk
diff --git a/ports/samd/boards/SEEED_XIAO_SAMD21/pins.csv b/ports/samd/boards/SEEED_XIAO_SAMD21/pins.csv
new file mode 100644
index 000000000000..2f1c180e8ac6
--- /dev/null
+++ b/ports/samd/boards/SEEED_XIAO_SAMD21/pins.csv
@@ -0,0 +1,26 @@
+# Pin rows contain Pin number and pin name.
+# Pin rows start with PIN_
+# If the pin name is omitted, the pin number is added as name.
+# Empty lines and lines not starting with PIN_ are ignored
+
+PIN_PA02,A0_D0
+PIN_PA04,A1_D1
+PIN_PA10,A2_D2
+PIN_PA11,A3_D3
+PIN_PA08,A4_D4
+PIN_PA09,A5_D5
+PIN_PB08,A6_D6
+PIN_PB09,A7_D7
+PIN_PA07,A8_D8
+PIN_PA05,A9_D9
+PIN_PA06,A10_D10
+
+PIN_PA17,USER_LED
+PIN_PA18,RX_LED
+PIN_PA19,TX_LED
+
+PIN_PA24,USB_DM
+PIN_PA25,USB_DP
+
+PIN_PA30,SWCLK
+PIN_PA31,SWDIO
diff --git a/ports/samd/boards/SPARKFUN_SAMD51_THING_PLUS/board.json b/ports/samd/boards/SPARKFUN_SAMD51_THING_PLUS/board.json
new file mode 100644
index 000000000000..af643f5c5f3c
--- /dev/null
+++ b/ports/samd/boards/SPARKFUN_SAMD51_THING_PLUS/board.json
@@ -0,0 +1,21 @@
+{
+ "deploy": [
+ "../deploy.md"
+ ],
+ "docs": "",
+ "features": [
+ "Battery Charging",
+ "Breadboard Friendly",
+ "Micro USB",
+ "QWIIC",
+ "SPI Flash"
+ ],
+ "images": [
+ "sparkfun_samd51_thing_plus.jpg"
+ ],
+ "mcu": "samd51",
+ "product": "Sparkfun SAMD51 Thing Plus",
+ "thumbnail": "",
+ "url": "https://www.sparkfun.com/products/14713",
+ "vendor": "Sparkfun"
+}
diff --git a/ports/samd/boards/SPARKFUN_SAMD51_THING_PLUS/mpconfigboard.h b/ports/samd/boards/SPARKFUN_SAMD51_THING_PLUS/mpconfigboard.h
new file mode 100644
index 000000000000..a51b71c363e1
--- /dev/null
+++ b/ports/samd/boards/SPARKFUN_SAMD51_THING_PLUS/mpconfigboard.h
@@ -0,0 +1,10 @@
+#define MICROPY_HW_BOARD_NAME "Sparkfun SAMD51 Thing Plus"
+#define MICROPY_HW_MCU_NAME "SAMD51J20A"
+
+#define MICROPY_HW_XOSC32K (1)
+
+// There seems to be an inconsistency in the SAMD51 Thing bootloader in that
+// the bootloader magic address is at the end of a 192k RAM area, instead of
+// 256k. Since the SAMD51x20A has 256k RAM, the loader symbol is at that address
+// and so there is a fix here using the previous definition.
+#define DBL_TAP_ADDR_ALT ((volatile uint32_t *)(HSRAM_ADDR + HSRAM_SIZE - 0x10000 - 4))
diff --git a/ports/samd/boards/SPARKFUN_SAMD51_THING_PLUS/mpconfigboard.mk b/ports/samd/boards/SPARKFUN_SAMD51_THING_PLUS/mpconfigboard.mk
new file mode 100644
index 000000000000..9e5cf887dfce
--- /dev/null
+++ b/ports/samd/boards/SPARKFUN_SAMD51_THING_PLUS/mpconfigboard.mk
@@ -0,0 +1,8 @@
+MCU_SERIES = SAMD51
+CMSIS_MCU = SAMD51J20A
+LD_FILES = boards/samd51x20a.ld sections.ld
+TEXT0 = 0x4000
+
+# The ?='s allow overriding in mpconfigboard.mk.
+# MicroPython settings
+MICROPY_VFS_LFS1 ?= 1
diff --git a/ports/samd/boards/SPARKFUN_SAMD51_THING_PLUS/pins.csv b/ports/samd/boards/SPARKFUN_SAMD51_THING_PLUS/pins.csv
new file mode 100644
index 000000000000..d807b505a704
--- /dev/null
+++ b/ports/samd/boards/SPARKFUN_SAMD51_THING_PLUS/pins.csv
@@ -0,0 +1,41 @@
+# Pin rows contain Pin number and pin name.
+# Pin rows start with PIN_
+# If the pin name is omitted, the pin number is added as name.
+# Empty lines and lines not starting with PIN_ are ignored
+
+PIN_PA13,D0
+PIN_PA12,D1
+PIN_PA06,D4
+PIN_PA15,D5
+PIN_PA20,D6
+PIN_PA21,D7
+PIN_PA07,D9
+PIN_PA18,D10
+PIN_PA16,D11
+PIN_PA19,D12
+PIN_PA17,D13
+PIN_PA02,A0
+PIN_PB08,A1
+PIN_PB09,A2
+PIN_PA04,A3
+PIN_PA05,A4
+PIN_PB02,A5
+PIN_PA22,SDA
+PIN_PA23,SCL
+PIN_PB12,MOSI
+PIN_PB11,MISO
+PIN_PB13,SCK
+PIN_PA08,FLASH_MOSI
+PIN_PA09,FLASH_SCK
+PIN_PA10,FLASH_CS
+PIN_PA11,FLASH_MISO
+
+PIN_PB03,RXLED
+PIN_PA27,TXLED
+
+PIN_PA24,USB_DM
+PIN_PA25,USB_DP
+PIN_PA26,USB_SOF
+
+PIN_PA30,SWCLK
+PIN_PA31,SWDIO
diff --git a/ports/samd/boards/make-pin-table.py b/ports/samd/boards/make-pin-table.py
new file mode 100644
index 000000000000..a187f2a711aa
--- /dev/null
+++ b/ports/samd/boards/make-pin-table.py
@@ -0,0 +1,201 @@
+#!/usr/bin/env python
+"""Generates the pin_cap table file for the SAMD port."""
+
+from __future__ import print_function
+
+import argparse
+import sys
+import csv
+
+table_header = """// This file was automatically generated by make-pin-cap.py
+//
+
+// The Pin objects which are available on a board
+
+"""
+
+
+class Pins:
+ def __init__(self):
+ self.board_pins = [] # list of pin objects
+ self.pin_names = {}
+
+ def parse_csv_file(self, filename):
+ with open(filename, "r") as csvfile:
+ rows = csv.reader(csvfile)
+ for row in rows:
+ # Pin numbers must start with "PA", "PB", "PC" or "PD"
+ if len(row) > 0 and row[0].strip().upper()[:2] in ("PA", "PB", "PC", "PD"):
+ self.board_pins.append(row)
+
+ def parse_pin_file(self, filename):
+ with open(filename, "r") as csvfile:
+ rows = csv.reader(csvfile, skipinitialspace=True)
+ for row in rows:
+ # Pin numbers must start with "PIN_"
+ # LED numbers must start with "LED_"
+ if len(row) > 0:
+ # for compatibility, map LED_ to PIN_
+ if row[0].startswith("LED_"):
+ row[0] = "PIN_" + row[0][4:]
+ if row[0].startswith("PIN_"):
+ if len(row) == 1:
+ self.pin_names[row[0]] = (row[0][4:], "{&machine_pin_type}")
+ else:
+ self.pin_names[row[0]] = (row[1], "{&machine_pin_type}")
+
+ def print_table(self, table_filename, mcu_name):
+ with open(table_filename, "wt") as table_file:
+ table_file.write(table_header)
+
+ # Create the Pin objects
+
+ if mcu_name == "SAMD21":
+ for row in self.board_pins:
+ pin = "PIN_" + row[0].upper()
+ table_file.write("#ifdef " + pin + "\n")
+ table_file.write("static const machine_pin_obj_t %s_obj = " % pin)
+ eic = row[1] if row[1] else "0xff"
+ adc = row[2] if row[2] else "0xff"
+ if pin in self.pin_names:
+ name = "MP_QSTR_%s" % self.pin_names[pin][0]
+ type = self.pin_names[pin][1]
+ else:
+ name = "MP_QSTR_"
+ type = "{&machine_pin_type}"
+ table_file.write("{%s, %s, %s, %s, %s" % (type, pin, name, eic, adc))
+ for cell in row[3:]:
+ if cell:
+ table_file.write(
+ ", 0x%s" % cell if len(cell) == 2 else ", 0x0%s" % cell
+ )
+ else:
+ table_file.write(", 0xff")
+ table_file.write("};\n")
+ table_file.write("#endif\n")
+ else:
+ for row in self.board_pins:
+ pin = "PIN_" + row[0].upper()
+ table_file.write("#ifdef " + pin + "\n")
+ table_file.write("const machine_pin_obj_t %s_obj = " % pin)
+ eic = row[1] if row[1] else "0xff"
+ adc0 = row[2] if row[2] else "0xff"
+ adc1 = row[3] if row[3] else "0xff"
+ if pin in self.pin_names:
+ name = "MP_QSTR_%s" % self.pin_names[pin][0]
+ type = self.pin_names[pin][1]
+ else:
+ name = "MP_QSTR_"
+ type = "{&machine_pin_type}"
+ table_file.write(
+ "{%s, %s, %s, %s, %s, %s" % (type, pin, name, eic, adc0, adc1)
+ )
+ for cell in row[4:]:
+ if cell:
+ table_file.write(
+ ", 0x%s" % cell if len(cell) == 2 else ", 0x0%s" % cell
+ )
+ else:
+ table_file.write(", 0xff")
+ table_file.write("};\n")
+ table_file.write("#endif\n")
+
+ # Create the Pin table
+
+ table_file.write("\n// The table of references to the pin objects.\n\n")
+ table_file.write("static const machine_pin_obj_t *pin_af_table[] = {\n")
+ for row in self.board_pins:
+ pin = "PIN_" + row[0].upper()
+ table_file.write(" #ifdef " + pin + "\n")
+ table_file.write(" &%s_obj,\n" % pin)
+ table_file.write(" #endif\n")
+ table_file.write("};\n")
+
+ # Create the CPU pins dictionary table
+
+ table_file.write("\n#if MICROPY_PY_MACHINE_PIN_BOARD_CPU\n")
+ table_file.write("\n// The cpu pins dictionary\n\n")
+ table_file.write(
+ "STATIC const mp_rom_map_elem_t pin_cpu_pins_locals_dict_table[] = {\n"
+ )
+ for row in self.board_pins:
+ pin = "PIN_" + row[0].upper()
+ table_file.write(" #ifdef " + pin + "\n")
+ table_file.write(
+ " { MP_ROM_QSTR(MP_QSTR_%s), MP_ROM_PTR(&%s_obj) },\n"
+ % (row[0].upper(), pin)
+ )
+ table_file.write(" #endif\n")
+ table_file.write("};\n")
+ table_file.write(
+ "MP_DEFINE_CONST_DICT(machine_pin_cpu_pins_locals_dict, pin_cpu_pins_locals_dict_table);\n"
+ )
+
+ # Create the board pins dictionary table
+
+ table_file.write("\n// The board pins dictionary\n\n")
+ table_file.write(
+ "STATIC const mp_rom_map_elem_t pin_board_pins_locals_dict_table[] = {\n"
+ )
+ for row in self.board_pins:
+ pin = "PIN_" + row[0].upper()
+ if pin in self.pin_names:
+ table_file.write(" #ifdef " + pin + "\n")
+ table_file.write(
+ " { MP_ROM_QSTR(MP_QSTR_%s), MP_ROM_PTR(&%s_obj) },\n"
+ % (self.pin_names[pin][0], pin)
+ )
+ table_file.write(" #endif\n")
+ table_file.write("};\n")
+ table_file.write(
+ "MP_DEFINE_CONST_DICT(machine_pin_board_pins_locals_dict, pin_board_pins_locals_dict_table);\n"
+ )
+ table_file.write("#endif\n")
+
+
+def main():
+ parser = argparse.ArgumentParser(
+ prog="make-pin-af.py",
+ usage="%(prog)s [options] [command]",
+ description="Generate MCU-specific pin cap table file",
+ )
+ parser.add_argument(
+ "-c",
+ "--csv",
+ dest="csv_filename",
+ help="Specifies the pin-af-table.csv filename",
+ )
+ parser.add_argument(
+ "-b",
+ "--board",
+ dest="pin_filename",
+ help="Specifies the pins.csv filename",
+ )
+ parser.add_argument(
+ "-t",
+ "--table",
+ dest="table_filename",
+ help="Specifies the name of the generated pin cap table file",
+ )
+ parser.add_argument(
+ "-m",
+ "--mcu",
+ dest="mcu_name",
+ help="Specifies type of the MCU (SAMD21 or SAMD51)",
+ )
+ args = parser.parse_args(sys.argv[1:])
+
+ pins = Pins()
+
+ if args.csv_filename:
+ pins.parse_csv_file(args.csv_filename)
+
+ if args.pin_filename:
+ pins.parse_pin_file(args.pin_filename)
+
+ if args.table_filename:
+ pins.print_table(args.table_filename, args.mcu_name)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/ports/samd/boards/samd21x18a.ld b/ports/samd/boards/samd21x18a.ld
index b7d59c315b64..81a84a15d7d7 100644
--- a/ports/samd/boards/samd21x18a.ld
+++ b/ports/samd/boards/samd21x18a.ld
@@ -13,5 +13,8 @@ MEMORY
_estack = ORIGIN(RAM) + LENGTH(RAM) - 8;
_sstack = _estack - 8K;
+_oflash_fs = ORIGIN(FLASH) + 192K - 8K;
+_sflash_fs = LENGTH(FLASH) - 192K + 8K - 1;
+
_sheap = _ebss;
_eheap = _sstack;
diff --git a/ports/samd/boards/samd51p19a.ld b/ports/samd/boards/samd51p19a.ld
deleted file mode 100644
index e0baa9bba028..000000000000
--- a/ports/samd/boards/samd51p19a.ld
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- GNU linker script for SAMD51
-*/
-
-/* Specify the memory areas */
-MEMORY
-{
- FLASH (rx) : ORIGIN = 0x00004000, LENGTH = 512K - 16K
- RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 192K
-}
-
-/* Top end of the stack, with room for double-tap variable */
-_estack = ORIGIN(RAM) + LENGTH(RAM) - 8;
-_sstack = _estack - 16K;
-
-_sheap = _ebss;
-_eheap = _sstack;
diff --git a/ports/samd/boards/samd51g19a.ld b/ports/samd/boards/samd51x19a.ld
similarity index 80%
rename from ports/samd/boards/samd51g19a.ld
rename to ports/samd/boards/samd51x19a.ld
index e0baa9bba028..cd03320ba43d 100644
--- a/ports/samd/boards/samd51g19a.ld
+++ b/ports/samd/boards/samd51x19a.ld
@@ -13,5 +13,8 @@ MEMORY
_estack = ORIGIN(RAM) + LENGTH(RAM) - 8;
_sstack = _estack - 16K;
+_oflash_fs = ORIGIN(FLASH) + 384K - 16K;
+_sflash_fs = LENGTH(FLASH) - 384K + 16K - 1;
+
_sheap = _ebss;
_eheap = _sstack;
diff --git a/ports/samd/boards/samd51x20a.ld b/ports/samd/boards/samd51x20a.ld
new file mode 100644
index 000000000000..f0d5e5c6aeb6
--- /dev/null
+++ b/ports/samd/boards/samd51x20a.ld
@@ -0,0 +1,20 @@
+/*
+ GNU linker script for SAMD51x20
+*/
+
+/* Specify the memory areas */
+MEMORY
+{
+ FLASH (rx) : ORIGIN = 0x00004000, LENGTH = 1024K - 16K
+ RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 256K
+}
+
+/* Top end of the stack, with room for double-tap variable */
+_estack = ORIGIN(RAM) + LENGTH(RAM) - 8;
+_sstack = _estack - 16K;
+
+_oflash_fs = ORIGIN(FLASH) + 384K - 16K;
+_sflash_fs = LENGTH(FLASH) - 384K + 16K - 1;
+
+_sheap = _ebss;
+_eheap = _sstack;
diff --git a/ports/samd/boards/ADAFRUIT_TRINKET_M0/pins.h b/ports/samd/clock_config.h
similarity index 70%
rename from ports/samd/boards/ADAFRUIT_TRINKET_M0/pins.h
rename to ports/samd/clock_config.h
index 843d69addc0f..35b7e532814b 100644
--- a/ports/samd/boards/ADAFRUIT_TRINKET_M0/pins.h
+++ b/ports/samd/clock_config.h
@@ -1,9 +1,11 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
+ * This file provides functions for configuring the clocks.
+ *
* The MIT License (MIT)
*
- * Copyright (c) 2021 Peter van der Burg
+ * Copyright (c) 2022 Robert Hammelrath
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,21 +24,11 @@
* 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.
- *
- * Used by machine_pin.c & board specific pins.c. Holds Board/MCU specific Pin
- * allocations.
*/
-typedef struct _machine_pin_obj_t {
- mp_obj_base_t base;
- uint32_t id;
-} machine_pin_obj_t;
-
-typedef struct _machine_led_obj_t {
- mp_obj_base_t base;
- uint32_t id;
-} machine_led_obj_t;
-
-// MUST explicitly hold array # of rows, else machine_pin.c wont compile.
-extern const machine_pin_obj_t machine_pin_obj[5];
-extern const machine_led_obj_t machine_led_obj[1];
+void init_clocks(uint32_t cpu_freq);
+void set_cpu_freq(uint32_t cpu_freq);
+uint32_t get_cpu_freq(void);
+uint32_t get_peripheral_freq(void);
+void check_usb_recovery_mode(void);
+void enable_sercom_clock(int id);
diff --git a/ports/samd/boards/ADAFRUIT_FEATHER_M0_EXPRESS/pins.h b/ports/samd/fatfs_port.c
similarity index 62%
rename from ports/samd/boards/ADAFRUIT_FEATHER_M0_EXPRESS/pins.h
rename to ports/samd/fatfs_port.c
index 45bee6167837..a3e3f1b67b3a 100644
--- a/ports/samd/boards/ADAFRUIT_FEATHER_M0_EXPRESS/pins.h
+++ b/ports/samd/fatfs_port.c
@@ -3,7 +3,8 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2021 Peter van der Burg
+ * Copyright (c) 2013, 2014 Damien P. George
+ * Copyright (c) 2021 Robert Hammelrath
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,21 +23,23 @@
* 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.
- *
- * Used by machine_pin.c & board specific pins.c. Holds Board/MCU specific Pin
- * allocations.
*/
-typedef struct _machine_pin_obj_t {
- mp_obj_base_t base;
- uint32_t id;
-} machine_pin_obj_t;
+#include "mphalport.h"
+#include "py/runtime.h"
+#include "shared/timeutils/timeutils.h"
+#include "lib/oofatfs/ff.h"
-typedef struct _machine_led_obj_t {
- mp_obj_base_t base;
- uint32_t id;
-} machine_led_obj_t;
+extern uint32_t time_offset;
-// MUST explicitly hold array # of rows, else machine_pin.c wont compile.
-extern const machine_pin_obj_t machine_pin_obj[20];
-extern const machine_led_obj_t machine_led_obj[1];
+MP_WEAK DWORD get_fattime(void) {
+ #if MICROPY_PY_MACHINE_RTC
+ return (RTC->MODE2.CLOCK.reg >> 1) + (20 << 25);
+ #else
+ extern void rtc_gettime(timeutils_struct_time_t *tm);
+ timeutils_struct_time_t tm;
+ timeutils_seconds_since_epoch_to_struct_time(mp_hal_ticks_ms_64() / 1000 + time_offset, &tm);
+ return ((tm.tm_year - 1980) << 25) | ((tm.tm_mon) << 21) | ((tm.tm_mday) << 16) |
+ ((tm.tm_hour) << 11) | ((tm.tm_min) << 5) | (tm.tm_sec / 2);
+ #endif
+}
diff --git a/ports/samd/machine_adc.c b/ports/samd/machine_adc.c
new file mode 100644
index 000000000000..d4078825297f
--- /dev/null
+++ b/ports/samd/machine_adc.c
@@ -0,0 +1,276 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2021 Philipp Ebensberger
+ * Copyright (c) 2022 Robert Hammelrath
+ *
+ * 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/obj.h"
+#include "py/runtime.h"
+#include "py/mphal.h"
+
+#include "sam.h"
+#include "pin_af.h"
+#include "modmachine.h"
+
+typedef struct _machine_adc_obj_t {
+ mp_obj_base_t base;
+ adc_config_t adc_config;
+ uint8_t id;
+ uint8_t avg;
+ uint8_t bits;
+ uint8_t vref;
+} machine_adc_obj_t;
+
+#define DEFAULT_ADC_BITS 12
+#define DEFAULT_ADC_AVG 16
+
+#if defined(MCU_SAMD21)
+static uint8_t adc_vref_table[] = {
+ ADC_REFCTRL_REFSEL_INT1V_Val, ADC_REFCTRL_REFSEL_INTVCC0_Val,
+ ADC_REFCTRL_REFSEL_INTVCC1_Val, ADC_REFCTRL_REFSEL_AREFA_Val, ADC_REFCTRL_REFSEL_AREFB_Val
+};
+#if MICROPY_HW_ADC_VREF
+#define DEFAULT_ADC_VREF MICROPY_HW_ADC_VREF
+#else
+#define DEFAULT_ADC_VREF (3)
+#endif
+
+#define ADC_EVSYS_CHANNEL 0
+
+#elif defined(MCU_SAMD51)
+
+static uint8_t adc_vref_table[] = {
+ ADC_REFCTRL_REFSEL_INTREF_Val, ADC_REFCTRL_REFSEL_INTVCC1_Val,
+ ADC_REFCTRL_REFSEL_INTVCC0_Val, ADC_REFCTRL_REFSEL_AREFA_Val,
+ ADC_REFCTRL_REFSEL_AREFB_Val, ADC_REFCTRL_REFSEL_AREFC_Val
+};
+#if MICROPY_HW_ADC_VREF
+#define DEFAULT_ADC_VREF MICROPY_HW_ADC_VREF
+#else
+#define DEFAULT_ADC_VREF (3)
+#endif
+
+#endif // defined(MCU_SAMD21)
+
+Adc *const adc_bases[] = ADC_INSTS;
+uint32_t busy_flags = 0;
+bool init_flags[2] = {false, false};
+static void adc_init(machine_adc_obj_t *self);
+static uint8_t resolution[] = {
+ ADC_CTRLB_RESSEL_8BIT_Val, ADC_CTRLB_RESSEL_10BIT_Val, ADC_CTRLB_RESSEL_12BIT_Val
+};
+
+// Calculate the floor value of log2(n)
+mp_int_t log2i(mp_int_t num) {
+ mp_int_t res = 0;
+ for (; num > 1; num >>= 1) {
+ res += 1;
+ }
+ return res;
+}
+
+STATIC void adc_obj_print(const mp_print_t *print, mp_obj_t o, mp_print_kind_t kind) {
+ (void)kind;
+ machine_adc_obj_t *self = MP_OBJ_TO_PTR(o);
+
+ mp_printf(print, "ADC(%s, device=%u, channel=%u, bits=%u, average=%u, vref=%d)",
+ pin_name(self->id), self->adc_config.device,
+ self->adc_config.channel, self->bits, 1 << self->avg, self->vref);
+}
+
+STATIC mp_obj_t adc_obj_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
+ enum { ARG_id, ARG_bits, ARG_average, ARG_vref };
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_id, MP_ARG_REQUIRED | MP_ARG_OBJ },
+ { MP_QSTR_bits, MP_ARG_INT, {.u_int = DEFAULT_ADC_BITS} },
+ { MP_QSTR_average, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = DEFAULT_ADC_AVG} },
+ { MP_QSTR_vref, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = DEFAULT_ADC_VREF} },
+ };
+
+ // Parse the arguments.
+ mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
+ mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
+
+ // Unpack and check, whther the pin has ADC capability
+ int id = mp_hal_get_pin_obj(args[ARG_id].u_obj);
+ adc_config_t adc_config = get_adc_config(id, busy_flags);
+
+ // Now that we have a valid device and channel, create and populate the ADC instance
+ machine_adc_obj_t *self = mp_obj_malloc(machine_adc_obj_t, &machine_adc_type);
+ self->id = id;
+ self->adc_config = adc_config;
+ self->bits = DEFAULT_ADC_BITS;
+ uint16_t bits = args[ARG_bits].u_int;
+ if (bits >= 8 && bits <= 12) {
+ self->bits = bits;
+ }
+ uint32_t avg = log2i(args[ARG_average].u_int);
+ self->avg = (avg <= 10 ? avg : 10);
+
+ uint8_t vref = args[ARG_vref].u_int;
+ if (0 <= vref && vref < sizeof(adc_vref_table)) {
+ self->vref = vref;
+ }
+
+ // flag the device/channel as being in use.
+ busy_flags |= (1 << (self->adc_config.device * 16 + self->adc_config.channel));
+ init_flags[self->adc_config.device] = false;
+
+ adc_init(self);
+
+ return MP_OBJ_FROM_PTR(self);
+}
+
+// read_u16()
+STATIC mp_obj_t machine_adc_read_u16(mp_obj_t self_in) {
+ machine_adc_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ Adc *adc = adc_bases[self->adc_config.device];
+ // Set the reference voltage. Default: external AREFA.
+ adc->REFCTRL.reg = adc_vref_table[self->vref];
+ // Set Input channel and resolution
+ // Select the pin as positive input and gnd as negative input reference, non-diff mode by default
+ adc->INPUTCTRL.reg = ADC_INPUTCTRL_MUXNEG_GND | self->adc_config.channel;
+ // set resolution. Scale 8-16 to 0 - 4 for table access.
+ adc->CTRLB.bit.RESSEL = resolution[(self->bits - 8) / 2];
+ // Measure input voltage
+ adc->SWTRIG.bit.START = 1;
+ while (adc->INTFLAG.bit.RESRDY == 0) {
+ }
+ // Get and return the result
+ return MP_OBJ_NEW_SMALL_INT(adc->RESULT.reg * (65536 / (1 << self->bits)));
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_adc_read_u16_obj, machine_adc_read_u16);
+
+// deinit() : release the ADC channel
+STATIC mp_obj_t machine_adc_deinit(mp_obj_t self_in) {
+ machine_adc_obj_t *self = MP_OBJ_TO_PTR(self_in);
+
+ busy_flags &= ~((1 << (self->adc_config.device * 16 + self->adc_config.channel)));
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_adc_deinit_obj, machine_adc_deinit);
+
+void adc_deinit_all(void) {
+ busy_flags = 0;
+ init_flags[0] = 0;
+ init_flags[1] = 0;
+}
+
+STATIC const mp_rom_map_elem_t adc_locals_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_read_u16), MP_ROM_PTR(&machine_adc_read_u16_obj) },
+ { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_adc_deinit_obj) },
+};
+
+STATIC MP_DEFINE_CONST_DICT(adc_locals_dict, adc_locals_dict_table);
+
+MP_DEFINE_CONST_OBJ_TYPE(
+ machine_adc_type,
+ MP_QSTR_ADC,
+ MP_TYPE_FLAG_NONE,
+ make_new, adc_obj_make_new,
+ print, adc_obj_print,
+ locals_dict, &adc_locals_dict
+ );
+
+static void adc_init(machine_adc_obj_t *self) {
+ // ADC & clock init is done only once per ADC
+ if (init_flags[self->adc_config.device] == false) {
+ Adc *adc = adc_bases[self->adc_config.device];
+
+ init_flags[self->adc_config.device] = true;
+
+ #if defined(MCU_SAMD21)
+ // Configuration SAMD21
+ // Enable APBD clocks and PCHCTRL clocks; GCLK2 at 48 MHz
+ PM->APBCMASK.reg |= PM_APBCMASK_ADC;
+ GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK2 | GCLK_CLKCTRL_ID_ADC;
+ while (GCLK->STATUS.bit.SYNCBUSY) {
+ }
+ // Reset ADC registers
+ adc->CTRLA.bit.SWRST = 1;
+ while (adc->CTRLA.bit.SWRST) {
+ }
+ // Get the calibration data
+ uint32_t bias = (*((uint32_t *)ADC_FUSES_BIASCAL_ADDR) & ADC_FUSES_BIASCAL_Msk) >> ADC_FUSES_BIASCAL_Pos;
+ uint32_t linearity = (*((uint32_t *)ADC_FUSES_LINEARITY_0_ADDR) & ADC_FUSES_LINEARITY_0_Msk) >> ADC_FUSES_LINEARITY_0_Pos;
+ linearity |= ((*((uint32_t *)ADC_FUSES_LINEARITY_1_ADDR) & ADC_FUSES_LINEARITY_1_Msk) >> ADC_FUSES_LINEARITY_1_Pos) << 5;
+ /* Write the calibration data. */
+ ADC->CALIB.reg = ADC_CALIB_BIAS_CAL(bias) | ADC_CALIB_LINEARITY_CAL(linearity);
+ // Divide 48MHz clock by 32 to obtain 1.5 MHz clock to adc
+ adc->CTRLB.reg = ADC_CTRLB_PRESCALER_DIV32;
+ // Select external AREFA as reference voltage.
+ adc->REFCTRL.reg = adc_vref_table[self->vref];
+ // Average: Accumulate samples and scale them down accordingly
+ adc->AVGCTRL.reg = self->avg | ADC_AVGCTRL_ADJRES(self->avg);
+ // Enable ADC and wait to be ready
+ adc->CTRLA.bit.ENABLE = 1;
+ while (adc->STATUS.bit.SYNCBUSY) {
+ }
+
+ #elif defined(MCU_SAMD51)
+ // Configuration SAMD51
+ // Enable APBD clocks and PCHCTRL clocks; GCLK2 at 48 MHz
+ if (self->adc_config.device == 0) {
+ GCLK->PCHCTRL[ADC0_GCLK_ID].reg = GCLK_PCHCTRL_GEN_GCLK2 | GCLK_PCHCTRL_CHEN;
+ MCLK->APBDMASK.bit.ADC0_ = 1;
+ } else {
+ GCLK->PCHCTRL[ADC1_GCLK_ID].reg = GCLK_PCHCTRL_GEN_GCLK2 | GCLK_PCHCTRL_CHEN;
+ MCLK->APBDMASK.bit.ADC1_ = 1;
+ }
+ // Reset ADC registers
+ adc->CTRLA.bit.SWRST = 1;
+ while (adc->CTRLA.bit.SWRST) {
+ }
+ // Get the calibration data
+ uint32_t biascomp;
+ uint32_t biasr2r;
+ uint32_t biasrefbuf;
+ if (self->adc_config.device == 0) {
+ biascomp = (*((uint32_t *)ADC0_FUSES_BIASCOMP_ADDR) & ADC0_FUSES_BIASCOMP_Msk) >> ADC0_FUSES_BIASCOMP_Pos;
+ biasr2r = (*((uint32_t *)ADC0_FUSES_BIASR2R_ADDR) & ADC0_FUSES_BIASR2R_Msk) >> ADC0_FUSES_BIASR2R_Pos;
+ biasrefbuf = (*((uint32_t *)ADC0_FUSES_BIASREFBUF_ADDR) & ADC0_FUSES_BIASREFBUF_Msk) >> ADC0_FUSES_BIASREFBUF_Pos;
+ } else {
+ biascomp = (*((uint32_t *)ADC1_FUSES_BIASCOMP_ADDR) & ADC1_FUSES_BIASCOMP_Msk) >> ADC1_FUSES_BIASCOMP_Pos;
+ biasr2r = (*((uint32_t *)ADC1_FUSES_BIASR2R_ADDR) & ADC1_FUSES_BIASR2R_Msk) >> ADC1_FUSES_BIASR2R_Pos;
+ biasrefbuf = (*((uint32_t *)ADC1_FUSES_BIASREFBUF_ADDR) & ADC1_FUSES_BIASREFBUF_Msk) >> ADC1_FUSES_BIASREFBUF_Pos;
+ }
+ /* Write the calibration data. */
+ adc->CALIB.reg = ADC_CALIB_BIASCOMP(biascomp) | ADC_CALIB_BIASR2R(biasr2r) | ADC_CALIB_BIASREFBUF(biasrefbuf);
+ // Divide 48MHz clock by 32 to obtain 1.5 MHz clock to adc
+ adc->CTRLA.reg = ADC_CTRLA_PRESCALER_DIV32;
+ // Set the reference voltage. Default: external AREFA.
+ adc->REFCTRL.reg = adc_vref_table[self->vref];
+ // Average: Accumulate samples and scale them down accordingly
+ adc->AVGCTRL.reg = self->avg | ADC_AVGCTRL_ADJRES(self->avg);
+ // Enable ADC and wait to be ready
+ adc->CTRLA.bit.ENABLE = 1;
+ while (adc->SYNCBUSY.bit.ENABLE) {
+ }
+
+ #endif
+ }
+ // Set the port as given in self->id as ADC
+ mp_hal_set_pin_mux(self->id, ALT_FCT_ADC);
+}
diff --git a/ports/samd/machine_bitstream.c b/ports/samd/machine_bitstream.c
new file mode 100644
index 000000000000..9959d947cb44
--- /dev/null
+++ b/ports/samd/machine_bitstream.c
@@ -0,0 +1,206 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2021 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.
+ */
+
+// This is a translation of the cycle counter implementation in ports/stm32/machine_bitstream.c.
+
+#include "py/mpconfig.h"
+#include "py/mphal.h"
+#include "clock_config.h"
+
+#if MICROPY_PY_MACHINE_BITSTREAM
+
+#if __CORTEX_M == 0
+
+// No cycle counter on M0, do manual cycle counting instead.
+
+// STM32F091 @ 48MHz
+#define NS_CYCLES_PER_ITER_HIGH (3)
+#define NS_CYCLES_PER_ITER_LOW (3)
+#define NS_OVERHEAD_CYCLES_HIGH (12)
+#define NS_OVERHEAD_CYCLES_LOW (15)
+
+uint32_t mp_hal_delay_ns_calc(uint32_t ns, bool high) {
+ uint32_t ncycles = (get_cpu_freq() / 1000000 * ns + 500) / 1000; // + 500 for proper rounding
+ uint32_t overhead = MIN(ncycles, high ? NS_OVERHEAD_CYCLES_HIGH : NS_OVERHEAD_CYCLES_LOW);
+ return MAX(1, MP_ROUND_DIVIDE(ncycles - overhead, high ? NS_CYCLES_PER_ITER_HIGH : NS_CYCLES_PER_ITER_LOW));
+}
+
+void machine_bitstream_high_low(mp_hal_pin_obj_t pin, uint32_t *timing_ns, const uint8_t *buf, size_t len) {
+ volatile const uint32_t mask = 1 << (pin % 32);
+ volatile uint32_t *outclr = &PORT->Group[pin / 32].OUTCLR.reg;
+ volatile uint32_t *outset = &PORT->Group[pin / 32].OUTSET.reg;
+
+ // Convert ns to loop iterations [high_time_0, low_time_0, high_time_1, low_time_1].
+ for (size_t i = 0; i < 4; ++i) {
+ timing_ns[i] = mp_hal_delay_ns_calc(timing_ns[i], i % 2 == 0);
+ }
+
+ mp_uint_t atomic_state = MICROPY_BEGIN_ATOMIC_SECTION();
+
+ // Measured timing for SAMD21 at 48MHz (cycle=20.83ns)
+ // timing_ns = (1,1,1,1)
+ // high: 310
+ // low: 375
+ // high0: 375
+ // low0: 400
+ // timing_ns = (500, 500, 500, 500)
+ // high: 500
+ // low: 500
+ // high0: 565
+ // low0: 540
+ // timing_ns = (1000, 1000, 1000, 1000)
+ // high: 1000
+ // low: 1000
+ // high0: 1065
+ // low0: 1040
+
+ // --> high is 12 + n*3 cycles
+ // low is 15 + n*3 cycles
+
+ // NeoPixel timing (400, 850, 800, 450) (+/-150ns) gives timing_ns=(2, 9, 8, 3) which in cycles is
+ // (12 + 6, 15 + 27, 15 + 24, 12 + 9) = (18, 42, 39, 21)
+ // --> (375, 875, 812, 437) nanoseconds.
+ // Measured output on logic analyser is (375, 875, 815, 435) (+/-5ns at 200MHz)
+
+ // Note: the first high/low cycle is longer by 2-3 cycles (40-60ns).
+ // This is slightly outside spec, but doesn't seem to cause a problem.
+
+ __asm volatile (
+ // Force consistent register assignment.
+ // r6 = len
+ "ldr r6, %0\n"
+ // r4 = buf
+ "ldr r4, %1\n"
+ // r5 = timing_ms
+ "ldr r5, %2\n"
+
+ // Must align for consistent timing.
+ ".align 4\n"
+
+ // Don't increment/decrement before first iteration.
+ "b .outer2\n"
+ ".outer:\n"
+ // ++buf, --len
+ " add r4, #1\n"
+ " sub r6, #1\n"
+
+ // len iterations
+ ".outer2:\n"
+ " cmp r6, #0\n"
+ " beq .done\n"
+
+ // r0 = *buf
+ " ldrb r0, [r4, #0]\n"
+
+ // 8 bits in byte
+ " mov r7, #8\n"
+ " .inner:\n"
+ // *outset = mask
+ " ldr r2, %3\n"
+ " ldr r1, %5\n"
+ " str r1, [r2, #0]\n"
+
+ // r3 = (r0 >> 4) & 8 (r0 is 8 if high bit is 1 else 0)
+ " mov r8, r6\n"
+ " lsr r3, r0, #4\n"
+ " mov r6, #8\n"
+ " and r3, r6\n"
+ " mov r6, r8\n"
+
+ // r2 = timing_ns[r2]
+ " ldr r2, [r5, r3]\n"
+ " .loop1:\n sub r2, #1\n bne .loop1\n"
+
+ // *outclr = mask
+ " ldr r2, %4\n"
+ " str r1, [r2, #0]\n"
+
+ // r2 = timing_ns[r3 + 4]
+ " add r3, #4\n"
+ " ldr r2, [r5, r3]\n"
+ " .loop2:\n sub r2, #1\n bne .loop2\n"
+
+ // b >>= 1
+ " lsl r0, r0, #1\n"
+
+ " sub r7, #1\n"
+ // end of inner loop
+ " beq .outer\n"
+ // continue inner loop
+ " b .inner\n"
+
+ ".done:\n"
+ :
+ : "m" (len), "m" (buf), "m" (timing_ns), "m" (outset), "m" (outclr), "m" (mask)
+ : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8"
+ );
+
+ MICROPY_END_ATOMIC_SECTION(atomic_state);
+}
+
+#else // > CORTEX_M0
+
+#define NS_TICKS_OVERHEAD (70)
+
+void machine_bitstream_high_low(mp_hal_pin_obj_t pin, uint32_t *timing_ns, const uint8_t *buf, size_t len) {
+ uint32_t fcpu_mhz = get_cpu_freq() / 1000000;
+ uint32_t ticks_overhead = fcpu_mhz * NS_TICKS_OVERHEAD / 1000;
+ // Convert ns to us ticks [high_time_0, period_0, high_time_1, period_1].
+ for (size_t i = 0; i < 4; ++i) {
+ timing_ns[i] = fcpu_mhz * timing_ns[i] / 1000;
+ if (timing_ns[i] > ticks_overhead) {
+ timing_ns[i] -= ticks_overhead;
+ }
+ if (i % 2 == 1) {
+ // Convert low_time to period (i.e. add high_time).
+ timing_ns[i] += timing_ns[i - 1] - ticks_overhead;
+ }
+ }
+
+ mp_uint_t atomic_state = MICROPY_BEGIN_ATOMIC_SECTION();
+ DWT->CYCCNT = 0;
+
+ for (size_t i = 0; i < len; ++i) {
+ uint8_t b = buf[i];
+ for (size_t j = 0; j < 8; ++j) {
+ uint32_t start_ticks = mp_hal_ticks_cpu();
+ uint32_t *t = &timing_ns[b >> 6 & 2];
+ mp_hal_pin_high(pin);
+ while ((mp_hal_ticks_cpu() - start_ticks) < t[0]) {
+ }
+ b <<= 1;
+ mp_hal_pin_low(pin);
+ while ((mp_hal_ticks_cpu() - start_ticks) < t[1]) {
+ }
+ }
+ }
+ MICROPY_END_ATOMIC_SECTION(atomic_state);
+
+}
+
+#endif // > CORTEX_M0
+
+#endif // MICROPY_PY_MACHINE_BITSTREAM
diff --git a/ports/samd/machine_dac.c b/ports/samd/machine_dac.c
new file mode 100644
index 000000000000..a1da9285e5fb
--- /dev/null
+++ b/ports/samd/machine_dac.c
@@ -0,0 +1,185 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2017 Nick Moore
+ * Copyright (c) 2022 Robert Hammelrath
+ *
+ * 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/obj.h"
+#include "py/runtime.h"
+#include "py/mphal.h"
+
+#include "sam.h"
+#include "pin_af.h"
+#include "modmachine.h"
+
+typedef struct _dac_obj_t {
+ mp_obj_base_t base;
+ uint8_t id;
+ mp_hal_pin_obj_t gpio_id;
+ uint8_t vref;
+} dac_obj_t;
+
+STATIC dac_obj_t dac_obj[] = {
+ #if defined(MCU_SAMD21)
+ {{&machine_dac_type}, 0, PIN_PA02},
+ #elif defined(MCU_SAMD51)
+ {{&machine_dac_type}, 0, PIN_PA02},
+ {{&machine_dac_type}, 1, PIN_PA05},
+ #endif
+};
+Dac *const dac_bases[] = DAC_INSTS;
+
+#if defined(MCU_SAMD21)
+
+#define MAX_DAC_VALUE (1023)
+#define DEFAULT_DAC_VREF (1)
+#define MAX_DAC_VREF (2)
+
+#elif defined(MCU_SAMD51)
+
+// According to Errata 2.9.2, VDDANA as ref value is not available. However it worked
+// in tests. So I keep the selection here but set the default to Aref, which is usually
+// connected at the Board to VDDANA
+static uint8_t dac_vref_table[] = {
+ DAC_CTRLB_REFSEL_INTREF_Val, DAC_CTRLB_REFSEL_VDDANA_Val,
+ DAC_CTRLB_REFSEL_VREFPU_Val, DAC_CTRLB_REFSEL_VREFPB_Val
+};
+#define MAX_DAC_VALUE (4095)
+#define DEFAULT_DAC_VREF (2)
+#define MAX_DAC_VREF (3)
+static bool dac_init = false;
+#endif
+
+
+STATIC mp_obj_t dac_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw,
+ const mp_obj_t *all_args) {
+
+ enum { ARG_id, ARG_vref };
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_id, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },
+ { MP_QSTR_vref, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = DEFAULT_DAC_VREF} },
+ };
+
+ // Parse the arguments.
+ mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
+ mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
+
+ uint8_t id = args[ARG_id].u_int;
+ dac_obj_t *self = NULL;
+ if (0 <= id && id <= MP_ARRAY_SIZE(dac_obj)) {
+ self = &dac_obj[id];
+ } else {
+ mp_raise_ValueError(MP_ERROR_TEXT("invalid Pin for DAC"));
+ }
+
+ uint8_t vref = args[ARG_vref].u_int;
+ if (0 <= vref && vref <= MAX_DAC_VREF) {
+ self->vref = vref;
+ }
+
+ Dac *dac = dac_bases[0]; // Just one DAC
+
+ // Init DAC
+ #if defined(MCU_SAMD21)
+
+ // Configuration SAMD21
+ // Enable APBC clocks and PCHCTRL clocks; GCLK3 at 1 MHz
+ PM->APBCMASK.reg |= PM_APBCMASK_DAC;
+ GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK3 | GCLK_CLKCTRL_ID_DAC;
+ while (GCLK->STATUS.bit.SYNCBUSY) {
+ }
+ // Reset DAC registers
+ dac->CTRLA.bit.SWRST = 1;
+ while (dac->CTRLA.bit.SWRST) {
+ }
+ dac->CTRLB.reg = DAC_CTRLB_EOEN | DAC_CTRLB_REFSEL(self->vref);
+ // Enable DAC and wait to be ready
+ dac->CTRLA.bit.ENABLE = 1;
+ while (dac->STATUS.bit.SYNCBUSY) {
+ }
+
+ #elif defined(MCU_SAMD51)
+
+ // Configuration SAMD51
+ // Enable APBD clocks and PCHCTRL clocks; GCLK3 at 8 MHz
+ dac_init = true;
+ MCLK->APBDMASK.reg |= MCLK_APBDMASK_DAC;
+ GCLK->PCHCTRL[DAC_GCLK_ID].reg = GCLK_PCHCTRL_GEN_GCLK3 | GCLK_PCHCTRL_CHEN;
+
+ // Reset DAC registers
+ dac->CTRLA.bit.SWRST = 1;
+ while (dac->CTRLA.bit.SWRST) {
+ }
+ dac->CTRLB.reg = DAC_CTRLB_REFSEL(dac_vref_table[self->vref]);
+ dac->DACCTRL[self->id].reg = DAC_DACCTRL_ENABLE | DAC_DACCTRL_REFRESH(2) | DAC_DACCTRL_CCTRL_CC12M;
+
+ // Enable DAC and wait to be ready
+ dac->CTRLA.bit.ENABLE = 1;
+ while (dac->SYNCBUSY.bit.ENABLE) {
+ }
+ #endif
+
+ // Set the port as given in self->gpio_id as DAC
+ mp_hal_set_pin_mux(self->gpio_id, ALT_FCT_DAC);
+
+ return MP_OBJ_FROM_PTR(self);
+}
+
+STATIC void dac_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
+ dac_obj_t *self = self_in;
+ mp_printf(print, "DAC(%u, Pin=%s, vref=%d)", self->id, pin_name(self->gpio_id), self->vref);
+}
+
+STATIC mp_obj_t dac_write(mp_obj_t self_in, mp_obj_t value_in) {
+ Dac *dac = dac_bases[0]; // Just one DAC
+ int value = mp_obj_get_int(value_in);
+ if (value < 0 || value > MAX_DAC_VALUE) {
+ mp_raise_ValueError(MP_ERROR_TEXT("value out of range"));
+ }
+ #if defined(MCU_SAMD21)
+ dac->DATA.reg = value;
+ #elif defined(MCU_SAMD51)
+ dac_obj_t *self = self_in;
+ dac->DATA[self->id].reg = value;
+ #endif
+
+ return mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_2(dac_write_obj, dac_write);
+
+STATIC const mp_rom_map_elem_t dac_locals_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&dac_write_obj) },
+};
+
+STATIC MP_DEFINE_CONST_DICT(dac_locals_dict, dac_locals_dict_table);
+
+MP_DEFINE_CONST_OBJ_TYPE(
+ machine_dac_type,
+ MP_QSTR_DAC,
+ MP_TYPE_FLAG_NONE,
+ make_new, dac_make_new,
+ print, dac_print,
+ locals_dict, &dac_locals_dict
+ );
diff --git a/ports/samd/machine_i2c.c b/ports/samd/machine_i2c.c
new file mode 100644
index 000000000000..76d24674f002
--- /dev/null
+++ b/ports/samd/machine_i2c.c
@@ -0,0 +1,276 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2020-2021 Damien P. George
+ * Copyright (c) 2022 Robert Hammelrath
+ *
+ * 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 "py/mperrno.h"
+#include "extmod/machine_i2c.h"
+#include "modmachine.h"
+#include "samd_soc.h"
+#include "pin_af.h"
+#include "clock_config.h"
+
+#define DEFAULT_I2C_FREQ (400000)
+#define RISETIME_NS (200)
+#define I2C_TIMEOUT (100)
+
+#define IS_BUS_BUSY (i2c->I2CM.STATUS.bit.BUSSTATE == 3)
+#define NACK_RECVD (i2c->I2CM.STATUS.bit.RXNACK == 1)
+#define IRQ_DATA_SENT (i2c->I2CM.INTFLAG.bit.MB == 1)
+#define IRQ_DATA_RECVD (i2c->I2CM.INTFLAG.bit.SB == 1)
+#define READ_MODE ((flags & MP_MACHINE_I2C_FLAG_READ) != 0)
+
+#define PREPARE_ACK i2c->I2CM.CTRLB.bit.ACKACT = 0
+#define PREPARE_NACK i2c->I2CM.CTRLB.bit.ACKACT = 1
+#define SET_STOP_STATE i2c_send_command(i2c, 0x03)
+
+enum state_t {
+ state_done = 0,
+ state_busy,
+ state_buserr,
+ state_nack
+};
+
+typedef struct _machine_i2c_obj_t {
+ mp_obj_base_t base;
+ Sercom *instance;
+ uint8_t id;
+ uint8_t scl;
+ uint8_t sda;
+ uint8_t state;
+ uint32_t freq;
+ uint32_t timeout;
+ size_t len;
+ uint8_t *buf;
+} machine_i2c_obj_t;
+
+extern Sercom *sercom_instance[];
+
+STATIC void i2c_send_command(Sercom *i2c, uint8_t command) {
+ i2c->I2CM.CTRLB.bit.CMD = command;
+ while (i2c->I2CM.SYNCBUSY.bit.SYSOP) {
+ }
+}
+
+void common_i2c_irq_handler(int i2c_id) {
+ // handle Sercom I2C IRQ
+ machine_i2c_obj_t *self = MP_STATE_PORT(sercom_table[i2c_id]);
+ // Handle IRQ
+ if (self != NULL) {
+ Sercom *i2c = self->instance;
+ // For now, clear all interrupts
+ if (IRQ_DATA_RECVD) {
+ if (self->len > 0) {
+ *(self->buf)++ = i2c->I2CM.DATA.reg;
+ self->len--;
+ self->timeout = I2C_TIMEOUT;
+ }
+ if (self->len > 0) { // no ACK at the last byte
+ PREPARE_ACK; // Send ACK
+ i2c_send_command(i2c, 0x02);
+ } else {
+ PREPARE_NACK; // Send NACK after the last byte
+ self->state = state_done;
+ i2c->I2CM.INTFLAG.reg |= SERCOM_I2CM_INTFLAG_SB;
+ }
+ } else if (IRQ_DATA_SENT) {
+ if (NACK_RECVD) { // e.g. NACK after adress for both read and write.
+ self->state = state_nack; // force stop of transmission
+ i2c->I2CM.INTFLAG.reg |= SERCOM_I2CM_INTFLAG_MB;
+ } else if (self->len > 0) { // data to be sent
+ i2c->I2CM.DATA.bit.DATA = *(self->buf)++;
+ self->len--;
+ self->timeout = I2C_TIMEOUT;
+ } else { // No data left, if there was any.
+ self->state = state_done;
+ i2c->I2CM.INTFLAG.reg |= SERCOM_I2CM_INTFLAG_MB;
+ }
+ } else { // On any error, e.g. ARBLOST or BUSERROR, stop the transmission
+ self->len = 0;
+ self->state = state_buserr;
+ i2c->I2CM.INTFLAG.reg |= SERCOM_I2CM_INTFLAG_ERROR;
+ }
+ }
+}
+
+STATIC void machine_i2c_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
+ machine_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ mp_printf(print, "I2C(%u, freq=%u, scl=%u, sda=%u)",
+ self->id, self->freq, self->scl, self->sda);
+}
+
+mp_obj_t machine_i2c_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
+ enum { ARG_id, ARG_freq, ARG_scl, ARG_sda };
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_id, MP_ARG_REQUIRED | MP_ARG_OBJ },
+ { MP_QSTR_freq, MP_ARG_INT, {.u_int = DEFAULT_I2C_FREQ} },
+ { MP_QSTR_scl, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
+ { MP_QSTR_sda, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
+ };
+
+ // Parse args.
+ mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
+ mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
+
+ // Get I2C bus.
+ int id = mp_obj_get_int(args[ARG_id].u_obj);
+ if (id < 0 || id >= SERCOM_INST_NUM) {
+ mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("I2C(%d) doesn't exist"), id);
+ }
+
+ // Get the peripheral object.
+ machine_i2c_obj_t *self = mp_obj_malloc(machine_i2c_obj_t, &machine_i2c_type);
+ self->id = id;
+ self->instance = sercom_instance[self->id];
+
+ // Set SCL/SDA pins.
+ sercom_pad_config_t scl_pad_config;
+ self->scl = mp_hal_get_pin_obj(args[ARG_scl].u_obj);
+ scl_pad_config = get_sercom_config(self->scl, self->id);
+
+ sercom_pad_config_t sda_pad_config;
+ self->sda = mp_hal_get_pin_obj(args[ARG_sda].u_obj);
+ sda_pad_config = get_sercom_config(self->sda, self->id);
+ if (sda_pad_config.pad_nr != 0 || scl_pad_config.pad_nr != 1) {
+ mp_raise_ValueError(MP_ERROR_TEXT("invalid pin for sda or scl"));
+ }
+ MP_STATE_PORT(sercom_table[self->id]) = self;
+ self->freq = args[ARG_freq].u_int;
+
+ // Configure the Pin mux.
+ mp_hal_set_pin_mux(self->scl, scl_pad_config.alt_fct);
+ mp_hal_set_pin_mux(self->sda, sda_pad_config.alt_fct);
+
+ // Set up the clocks
+ enable_sercom_clock(self->id);
+
+ // Initialise the I2C peripheral
+ Sercom *i2c = self->instance;
+
+ // Reset the device
+ i2c->I2CM.CTRLA.reg = SERCOM_I2CM_CTRLA_SWRST;
+ while (i2c->I2CM.SYNCBUSY.bit.SWRST == 1) {
+ }
+ // Set to master mode, inactivity timeout of 20 SCL cycles and speed.
+ i2c->I2CM.CTRLA.reg = SERCOM_I2CM_CTRLA_MODE(0x05)
+ | SERCOM_I2CM_CTRLA_INACTOUT(3)
+ | SERCOM_I2CM_CTRLA_SPEED(self->freq > 400000 ? 1 : 0);
+
+ // I2C is driven by the clock of GCLK Generator 2, with it's freq in variable bus_freq
+ // baud = peripheral_freq / (2 * baudrate) - 5 - (rise_time * peripheral_freq) / 2
+ // Just set the minimal configuration for standard and fast mode.
+ // Set Baud. Assume ~300ns rise time. Maybe set later by a keyword argument.
+ int32_t baud = get_peripheral_freq() / (2 * self->freq) - 5 - (get_peripheral_freq() / 1000000) * RISETIME_NS / 2000;
+ if (baud < 0) {
+ baud = 0;
+ }
+ if (baud > 255) {
+ baud = 255;
+ }
+ i2c->I2CM.BAUD.reg = baud;
+
+ // Enable interrupts
+ sercom_register_irq(self->id, &common_i2c_irq_handler);
+ #if defined(MCU_SAMD21)
+ NVIC_EnableIRQ(SERCOM0_IRQn + self->id);
+ #elif defined(MCU_SAMD51)
+ NVIC_EnableIRQ(SERCOM0_0_IRQn + 4 * self->id); // MB interrupt
+ NVIC_EnableIRQ(SERCOM0_0_IRQn + 4 * self->id + 1); // SB interrupt
+ NVIC_EnableIRQ(SERCOM0_0_IRQn + 4 * self->id + 3); // ERRROR interrupt
+ #endif
+
+ // Now enable I2C.
+ sercom_enable(i2c, 1);
+
+ // Force the bus state to idle
+ i2c->I2CM.STATUS.bit.BUSSTATE = 1;
+
+ return MP_OBJ_FROM_PTR(self);
+}
+
+STATIC int machine_i2c_transfer_single(mp_obj_base_t *self_in, uint16_t addr, size_t len, uint8_t *buf, unsigned int flags) {
+ machine_i2c_obj_t *self = (machine_i2c_obj_t *)self_in;
+ Sercom *i2c = self->instance;
+
+ self->timeout = I2C_TIMEOUT;
+ self->len = len;
+ self->buf = buf;
+ // Wait a while if the bus is busy
+ while (IS_BUS_BUSY && self->timeout) {
+ MICROPY_EVENT_POLL_HOOK
+ if (--self->timeout == 0) {
+ return -MP_ETIMEDOUT;
+ }
+ }
+ // Enable interrupts and set the state
+ i2c->I2CM.INTENSET.reg = SERCOM_I2CM_INTENSET_MB | SERCOM_I2CM_INTENSET_SB | SERCOM_I2CM_INTENSET_ERROR;
+ self->state = state_busy;
+
+ // Send the adress, which kicks off the transfer
+ i2c->I2CM.ADDR.bit.ADDR = (addr << 1) | READ_MODE;
+
+ // Transfer the data
+ self->timeout = I2C_TIMEOUT;
+ while (self->state == state_busy && self->timeout) {
+ self->timeout--;
+ MICROPY_EVENT_POLL_HOOK
+ }
+ i2c->I2CM.INTENCLR.reg = SERCOM_I2CM_INTENSET_MB | SERCOM_I2CM_INTENSET_SB | SERCOM_I2CM_INTENSET_ERROR;
+
+ // Check the error states after the transfer is stopped
+ if (self->state == state_nack) {
+ SET_STOP_STATE;
+ return self->len == len ? -MP_ENODEV : -MP_EIO;
+ } else if (self->state == state_buserr) {
+ SET_STOP_STATE;
+ return -MP_EIO;
+ } else if (self->timeout == 0) {
+ SET_STOP_STATE;
+ return -MP_ETIMEDOUT;
+ }
+
+ if (flags & MP_MACHINE_I2C_FLAG_STOP) {
+ SET_STOP_STATE;
+ }
+
+ return len;
+}
+
+STATIC const mp_machine_i2c_p_t machine_i2c_p = {
+ .transfer = mp_machine_i2c_transfer_adaptor,
+ .transfer_single = machine_i2c_transfer_single,
+};
+
+MP_DEFINE_CONST_OBJ_TYPE(
+ machine_i2c_type,
+ MP_QSTR_I2C,
+ MP_TYPE_FLAG_NONE,
+ make_new, machine_i2c_make_new,
+ print, machine_i2c_print,
+ protocol, &machine_i2c_p,
+ locals_dict, &mp_machine_i2c_locals_dict
+ );
diff --git a/ports/samd/machine_led.c b/ports/samd/machine_led.c
deleted file mode 100644
index f4dd1aeb3c65..000000000000
--- a/ports/samd/machine_led.c
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * This is part of the MicroPython project, http://micropython.org/
- *
- * The MIT License (MIT)
- *
- * Copyright (c) 2016-2021 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.
- *
- * Uses pins.h & pins.c to create board (MCU package) specific 'machine_led_obj' array.
- */
-
-#include "py/runtime.h"
-#include "py/mphal.h"
-#include "extmod/virtpin.h"
-#include "modmachine.h"
-#include "pins.h" // boards//
-
-// ASF4 (MCU package specific pin defs in 'boards')
-#include "hal_gpio.h"
-#include "hpl_gpio.h"
-#include "hal_atomic.h"
-
-STATIC void machine_led_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
- machine_led_obj_t *self = self_in;
- mp_printf(print, "LED(%u)", self->id);
-}
-
-// LED.init(mode, *, value=None)
-STATIC mp_obj_t machine_led_obj_init_helper(const machine_led_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
- enum { ARG_mode, ARG_value };
- static const mp_arg_t allowed_args[] = {
- { MP_QSTR_mode, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
- { MP_QSTR_value, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
- };
-
- // parse args
- mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
- mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
-
- // set initial value (do this before configuring mode/pull)
- if (args[ARG_value].u_obj != mp_const_none) {
- gpio_set_pin_level(self->id, mp_obj_is_true(args[ARG_value].u_obj));
- }
-
- // configure mode
- gpio_set_pin_direction(self->id, GPIO_DIRECTION_OUT);
-
- return mp_const_none;
-}
-
-// constructor(id, ...)
-mp_obj_t mp_led_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, MP_OBJ_FUN_ARGS_MAX, true);
-
- // get the wanted LED object
- int wanted_led = mp_obj_get_int(args[0]);
- const machine_led_obj_t *self = NULL;
- if (0 <= wanted_led && wanted_led < MP_ARRAY_SIZE(machine_led_obj)) {
- self = (machine_led_obj_t *)&machine_led_obj[wanted_led];
- }
-
- // the array could be padded with 'nulls' (see other Ports).
- // Will also error if the asked for LED (index) is greater than the array row size.
- if (self == NULL || self->base.type == NULL) {
- mp_raise_ValueError(MP_ERROR_TEXT("invalid LED"));
- }
-
- if (n_args > 1 || n_kw > 0) {
- // mode given, so configure this GPIO
- mp_map_t kw_args;
- mp_map_init_fixed_table(&kw_args, n_kw, args + n_args);
- machine_led_obj_init_helper(self, n_args - 1, args + 1, &kw_args);
- }
-
- return MP_OBJ_FROM_PTR(self);
-}
-
-// fast method for getting/setting pin value
-STATIC mp_obj_t machine_led_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {
- mp_arg_check_num(n_args, n_kw, 0, 1, false);
- machine_led_obj_t *self = self_in;
- if (n_args == 0) {
- // get pin
- return MP_OBJ_NEW_SMALL_INT(gpio_get_pin_level(self->id));
- } else {
- // set pin
- bool value = mp_obj_is_true(args[0]);
- gpio_set_pin_level(self->id, value);
-
- return mp_const_none;
- }
-}
-
-// pin.init(mode)
-STATIC mp_obj_t machine_led_obj_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
- return machine_led_obj_init_helper(args[0], n_args - 1, args + 1, kw_args);
-}
-MP_DEFINE_CONST_FUN_OBJ_KW(machine_led_init_obj, 1, machine_led_obj_init);
-
-// pin.value([value])
-STATIC mp_obj_t machine_led_value(size_t n_args, const mp_obj_t *args) {
- return machine_led_call(args[0], n_args - 1, 0, args + 1);
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_led_value_obj, 1, 2, machine_led_value);
-
-// pin.low()
-STATIC mp_obj_t machine_led_low(mp_obj_t self_in) {
- machine_led_obj_t *self = MP_OBJ_TO_PTR(self_in);
- gpio_set_pin_direction(self->id, GPIO_DIRECTION_OUT);
- gpio_set_pin_level(self->id, false);
-
- return mp_const_none;
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_led_low_obj, machine_led_low);
-
-// pin.high()
-STATIC mp_obj_t machine_led_high(mp_obj_t self_in) {
- machine_led_obj_t *self = MP_OBJ_TO_PTR(self_in);
- gpio_set_pin_direction(self->id, GPIO_DIRECTION_OUT);
- gpio_set_pin_level(self->id, true);
-
- return mp_const_none;
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_led_high_obj, machine_led_high);
-
-// pin.toggle()
-STATIC mp_obj_t machine_led_toggle(mp_obj_t self_in) {
- machine_led_obj_t *self = MP_OBJ_TO_PTR(self_in);
- gpio_set_pin_direction(self->id, GPIO_DIRECTION_OUT);
- gpio_toggle_pin_level(self->id);
-
- return mp_const_none;
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_led_toggle_obj, machine_led_toggle);
-
-STATIC const mp_rom_map_elem_t machine_led_locals_dict_table[] = {
- // instance methods
- { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_led_init_obj) },
- { MP_ROM_QSTR(MP_QSTR_value), MP_ROM_PTR(&machine_led_value_obj) },
- { MP_ROM_QSTR(MP_QSTR_low), MP_ROM_PTR(&machine_led_low_obj) },
- { MP_ROM_QSTR(MP_QSTR_high), MP_ROM_PTR(&machine_led_high_obj) },
- { MP_ROM_QSTR(MP_QSTR_off), MP_ROM_PTR(&machine_led_low_obj) },
- { MP_ROM_QSTR(MP_QSTR_on), MP_ROM_PTR(&machine_led_high_obj) },
- { MP_ROM_QSTR(MP_QSTR_toggle), MP_ROM_PTR(&machine_led_toggle_obj) },
-};
-STATIC MP_DEFINE_CONST_DICT(machine_led_locals_dict, machine_led_locals_dict_table);
-
-const mp_obj_type_t machine_led_type = {
- { &mp_type_type },
- .name = MP_QSTR_LED,
- .print = machine_led_print,
- .make_new = mp_led_make_new,
- .call = machine_led_call,
- .locals_dict = (mp_obj_t)&machine_led_locals_dict,
-};
diff --git a/ports/samd/machine_pin.c b/ports/samd/machine_pin.c
index 161a3ccddd2a..f8e1b962804c 100644
--- a/ports/samd/machine_pin.c
+++ b/ports/samd/machine_pin.c
@@ -4,6 +4,7 @@
* The MIT License (MIT)
*
* Copyright (c) 2016-2021 Damien P. George
+ * Copyright (c) 2022 Robert Hammelrath (pin.irq)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -26,40 +27,74 @@
* Uses pins.h & pins.c to create board (MCU package) specific 'machine_pin_obj' array.
*/
+#include "string.h"
#include "py/runtime.h"
#include "py/mphal.h"
+#include "shared/runtime/mpirq.h"
#include "extmod/virtpin.h"
#include "modmachine.h"
#include "samd_soc.h"
-#include "pins.h" // boards//
+#include "pin_af.h"
-// ASF4 (MCU package specific pin defs in 'boards')
#include "hal_gpio.h"
-#include "hpl_gpio.h"
-#include "hal_atomic.h"
#define GPIO_MODE_IN (0)
#define GPIO_MODE_OUT (1)
-// #define GPIO_MODE_ALT (3)
+#define GPIO_MODE_OPEN_DRAIN (2)
#define GPIO_STRENGTH_2MA (0)
#define GPIO_STRENGTH_8MA (1)
+#define GPIO_IRQ_EDGE_RISE (1)
+#define GPIO_IRQ_EDGE_FALL (2)
-// asf4 hpl_gpio.h gpio_pull_mode
-
-/*
typedef struct _machine_pin_irq_obj_t {
mp_irq_obj_t base;
uint32_t flags;
uint32_t trigger;
+ uint8_t pin_id;
} machine_pin_irq_obj_t;
+#if MICROPY_PY_MACHINE_PIN_BOARD_CPU
+// Pin mapping dictionaries
+MP_DEFINE_CONST_OBJ_TYPE(
+ machine_pin_cpu_pins_obj_type,
+ MP_QSTR_cpu,
+ MP_TYPE_FLAG_NONE,
+ locals_dict, &machine_pin_cpu_pins_locals_dict
+ );
+
+MP_DEFINE_CONST_OBJ_TYPE(
+ machine_pin_board_pins_obj_type,
+ MP_QSTR_board,
+ MP_TYPE_FLAG_NONE,
+ locals_dict, &machine_pin_board_pins_locals_dict
+ );
+#endif // MICROPY_PY_MACHINE_PIN_BOARD_CPU
+
STATIC const mp_irq_methods_t machine_pin_irq_methods;
-*/
+
+bool EIC_occured;
+
+uint32_t machine_pin_open_drain_mask[4];
+
+// Open drain behaviour is simulated.
+#define GPIO_IS_OPEN_DRAIN(id) (machine_pin_open_drain_mask[id / 32] & (1 << (id % 32)))
STATIC void machine_pin_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
machine_pin_obj_t *self = self_in;
- mp_printf(print, "Pin(%u)", self->id);
+ char *mode_str;
+ char *pull_str[] = {"PULL_OFF", "PULL_UP", "PULL_DOWN"};
+ if (GPIO_IS_OPEN_DRAIN(self->pin_id)) {
+ mode_str = "OPEN_DRAIN";
+ } else {
+ mode_str = (mp_hal_get_pin_direction(self->pin_id) == GPIO_DIRECTION_OUT) ? "OUT" : "IN";
+ }
+
+ mp_printf(print, "Pin(\"%s\", mode=%s, pull=%s, GPIO=P%c%02u)",
+ pin_name(self->pin_id),
+ mode_str,
+ pull_str[mp_hal_get_pull_mode(self->pin_id)],
+ "ABCD"[self->pin_id / 32], self->pin_id % 32);
}
STATIC void pin_validate_drive(bool strength) {
@@ -82,30 +117,34 @@ STATIC mp_obj_t machine_pin_obj_init_helper(const machine_pin_obj_t *self, size_
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
+ // clear any existing mux setting
+ mp_hal_clr_pin_mux(self->pin_id);
// set initial value (do this before configuring mode/pull)
if (args[ARG_value].u_obj != mp_const_none) {
- gpio_set_pin_level(self->id, mp_obj_is_true(args[ARG_value].u_obj));
+ mp_hal_pin_write(self->pin_id, mp_obj_is_true(args[ARG_value].u_obj));
}
// configure mode
if (args[ARG_mode].u_obj != mp_const_none) {
mp_int_t mode = mp_obj_get_int(args[ARG_mode].u_obj);
if (mode == GPIO_MODE_IN) {
- gpio_set_pin_direction(self->id, GPIO_DIRECTION_IN);
+ mp_hal_pin_input(self->pin_id);
} else if (mode == GPIO_MODE_OUT) {
- gpio_set_pin_direction(self->id, GPIO_DIRECTION_OUT);
+ mp_hal_pin_output(self->pin_id);
+ } else if (mode == GPIO_MODE_OPEN_DRAIN) {
+ mp_hal_pin_open_drain(self->pin_id);
} else {
- gpio_set_pin_direction(self->id, GPIO_DIRECTION_IN); // If no args are given, the Pin is 'input'.
+ mp_hal_pin_input(self->pin_id); // If no args are given, the Pin is 'input'.
}
}
// configure pull. Only to be used with IN mode. The function sets the pin to INPUT.
uint32_t pull = 0;
- mp_int_t mode = mp_obj_get_int(args[ARG_mode].u_obj);
- if (mode == GPIO_MODE_OUT && args[ARG_pull].u_obj != mp_const_none) {
+ mp_int_t dir = mp_hal_get_pin_direction(self->pin_id);
+ if (dir == GPIO_DIRECTION_OUT && args[ARG_pull].u_obj != mp_const_none) {
mp_raise_ValueError(MP_ERROR_TEXT("OUT incompatible with pull"));
} else if (args[ARG_pull].u_obj != mp_const_none) {
pull = mp_obj_get_int(args[ARG_pull].u_obj);
- gpio_set_pin_pull_mode(self->id, pull); // hal_gpio.h
+ gpio_set_pin_pull_mode(self->pin_id, pull); // hal_gpio.h
}
// get the strength
@@ -118,19 +157,10 @@ STATIC mp_obj_t machine_pin_obj_init_helper(const machine_pin_obj_t *self, size_
// constructor(id, ...)
mp_obj_t mp_pin_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, MP_OBJ_FUN_ARGS_MAX, true);
+ const machine_pin_obj_t *self;
// get the wanted pin object
- int wanted_pin = mp_obj_get_int(args[0]);
-
- const machine_pin_obj_t *self = NULL;
- if (0 <= wanted_pin && wanted_pin < MP_ARRAY_SIZE(machine_pin_obj)) {
- self = (machine_pin_obj_t *)&machine_pin_obj[wanted_pin];
- }
-
- if (self == NULL || self->base.type == NULL) {
- mp_raise_ValueError(MP_ERROR_TEXT("invalid pin"));
- }
- self = (machine_pin_obj_t *)&machine_pin_obj[wanted_pin];
+ self = pin_find(args[0]);
if (n_args > 1 || n_kw > 0) {
// pin mode given, so configure this GPIO
@@ -143,17 +173,24 @@ mp_obj_t mp_pin_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw,
}
// fast method for getting/setting pin value
-STATIC mp_obj_t machine_pin_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {
+mp_obj_t machine_pin_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {
mp_arg_check_num(n_args, n_kw, 0, 1, false);
machine_pin_obj_t *self = self_in;
if (n_args == 0) {
// get pin
- return MP_OBJ_NEW_SMALL_INT(gpio_get_pin_level(self->id));
+ return MP_OBJ_NEW_SMALL_INT(mp_hal_pin_read(self->pin_id));
} else {
// set pin
bool value = mp_obj_is_true(args[0]);
- gpio_set_pin_level(self->id, value);
-
+ if (GPIO_IS_OPEN_DRAIN(self->pin_id)) {
+ if (value == 0) {
+ mp_hal_pin_od_low(self->pin_id);
+ } else {
+ mp_hal_pin_od_high(self->pin_id);
+ }
+ } else {
+ mp_hal_pin_write(self->pin_id, value);
+ }
return mp_const_none;
}
}
@@ -165,7 +202,7 @@ STATIC mp_obj_t machine_pin_obj_init(size_t n_args, const mp_obj_t *args, mp_map
MP_DEFINE_CONST_FUN_OBJ_KW(machine_pin_init_obj, 1, machine_pin_obj_init);
// Pin.value([value])
-STATIC mp_obj_t machine_pin_value(size_t n_args, const mp_obj_t *args) {
+mp_obj_t machine_pin_value(size_t n_args, const mp_obj_t *args) {
return machine_pin_call(args[0], n_args - 1, 0, args + 1);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_pin_value_obj, 1, 2, machine_pin_value);
@@ -173,7 +210,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_pin_value_obj, 1, 2, machine_
// Pin.disable(pin)
STATIC mp_obj_t machine_pin_disable(mp_obj_t self_in) {
machine_pin_obj_t *self = MP_OBJ_TO_PTR(self_in);
- gpio_set_pin_direction(self->id, GPIO_DIRECTION_OFF); // Disables the pin (low power state)
+ gpio_set_pin_direction(self->pin_id, GPIO_DIRECTION_OFF); // Disables the pin (low power state)
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_pin_disable_obj, machine_pin_disable);
@@ -181,22 +218,26 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_pin_disable_obj, machine_pin_disable);
// Pin.low() Totem-pole (push-pull)
STATIC mp_obj_t machine_pin_low(mp_obj_t self_in) {
machine_pin_obj_t *self = MP_OBJ_TO_PTR(self_in);
- gpio_set_pin_direction(self->id, GPIO_DIRECTION_OUT);
- gpio_set_pin_level(self->id, false);
-
+ if (GPIO_IS_OPEN_DRAIN(self->pin_id)) {
+ mp_hal_pin_od_low(self->pin_id);
+ } else {
+ mp_hal_pin_low(self->pin_id);
+ }
return mp_const_none;
}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_pin_low_obj, machine_pin_low);
+MP_DEFINE_CONST_FUN_OBJ_1(machine_pin_low_obj, machine_pin_low);
// Pin.high() Totem-pole (push-pull)
STATIC mp_obj_t machine_pin_high(mp_obj_t self_in) {
machine_pin_obj_t *self = MP_OBJ_TO_PTR(self_in);
- gpio_set_pin_direction(self->id, GPIO_DIRECTION_OUT);
- gpio_set_pin_level(self->id, true);
-
+ if (GPIO_IS_OPEN_DRAIN(self->pin_id)) {
+ mp_hal_pin_od_high(self->pin_id);
+ } else {
+ mp_hal_pin_high(self->pin_id);
+ }
return mp_const_none;
}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_pin_high_obj, machine_pin_high);
+MP_DEFINE_CONST_FUN_OBJ_1(machine_pin_high_obj, machine_pin_high);
// Pin.toggle(). Only TOGGLE pins set as OUTPUT.
STATIC mp_obj_t machine_pin_toggle(mp_obj_t self_in) {
@@ -205,20 +246,20 @@ STATIC mp_obj_t machine_pin_toggle(mp_obj_t self_in) {
// Determine DIRECTION of PIN.
bool pin_dir;
- pin_dir = (PORT->Group[(enum gpio_port)GPIO_PORT(self->id)].DIR.reg // Get PORT#
- & (1 << GPIO_PIN(self->id))) // Isolate the Pin in question
- >> GPIO_PIN(self->id); // Shift to LSB for binary result.
-
- if (pin_dir) {
- // Pin is OUTPUT
- gpio_set_pin_direction(self->id, GPIO_DIRECTION_OUT);
- gpio_toggle_pin_level(self->id);
+ if (GPIO_IS_OPEN_DRAIN(self->pin_id)) {
+ pin_dir = mp_hal_get_pin_direction(self->pin_id);
+ if (pin_dir) {
+ // Pin is output, thus low, switch to high
+ mp_hal_pin_od_high(self->pin_id);
+ } else {
+ mp_hal_pin_od_low(self->pin_id);
+ }
} else {
- mp_raise_ValueError(MP_ERROR_TEXT("Cannot TOGGLE INPUT pin!\n"));
+ gpio_toggle_pin_level(self->pin_id);
}
- return mp_const_true;
+ return mp_const_none;
}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_pin_toggle_obj, machine_pin_toggle);
+MP_DEFINE_CONST_FUN_OBJ_1(machine_pin_toggle_obj, machine_pin_toggle);
// Pin.drive(). Normal (0) is 2mA, High (1) allows 8mA.
STATIC mp_obj_t machine_pin_drive(size_t n_args, const mp_obj_t *args) {
@@ -230,14 +271,150 @@ STATIC mp_obj_t machine_pin_drive(size_t n_args, const mp_obj_t *args) {
pin_validate_drive(strength);
// Set the DRVSTR bit (ASF hri/hri_port_dxx.h
hri_port_write_PINCFG_DRVSTR_bit(PORT,
- (enum gpio_port)GPIO_PORT(self->id),
- GPIO_PIN(self->id),
+ (enum gpio_port)GPIO_PORT(self->pin_id),
+ GPIO_PIN(self->pin_id),
strength);
return mp_const_none;
}
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_pin_drive_obj, 1, 2, machine_pin_drive);
+// pin.irq(handler=None, trigger=IRQ_FALLING|IRQ_RISING, hard=False)
+STATIC mp_obj_t machine_pin_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ enum { ARG_handler, ARG_trigger, ARG_hard };
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_handler, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
+ { MP_QSTR_trigger, MP_ARG_INT, {.u_int = 3} },
+ { MP_QSTR_hard, MP_ARG_BOOL, {.u_bool = false} },
+ };
+ machine_pin_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);
+
+ // Get the IRQ object.
+ uint8_t eic_id = get_pin_obj_ptr(self->pin_id)->eic;
+ machine_pin_irq_obj_t *irq = MP_STATE_PORT(machine_pin_irq_objects[eic_id]);
+ if (irq != NULL && irq->pin_id != self->pin_id) {
+ mp_raise_ValueError(MP_ERROR_TEXT("IRQ already used"));
+ }
+
+ // Allocate the IRQ object if it doesn't already exist.
+ if (irq == NULL) {
+ irq = m_new_obj(machine_pin_irq_obj_t);
+ irq->base.base.type = &mp_irq_type;
+ irq->base.methods = (mp_irq_methods_t *)&machine_pin_irq_methods;
+ irq->base.parent = MP_OBJ_FROM_PTR(self);
+ irq->base.handler = mp_const_none;
+ irq->base.ishard = false;
+ irq->pin_id = 0xff;
+ MP_STATE_PORT(machine_pin_irq_objects[eic_id]) = irq;
+ }
+ // (Re-)configure the irq.
+ if (n_args > 1 || kw_args->used != 0) {
+
+ // set the mux config of the pin.
+ mp_hal_set_pin_mux(self->pin_id, ALT_FCT_EIC);
+
+ // Configure IRQ.
+ #if defined(MCU_SAMD21)
+
+ uint32_t irq_num = 4;
+ // Disable all IRQs from the affected source while data is updated.
+ NVIC_DisableIRQ(irq_num);
+ // Disable EIC
+ EIC->CTRL.bit.ENABLE = 0;
+ while (EIC->STATUS.bit.SYNCBUSY != 0) {
+ }
+ EIC->INTENCLR.reg = (1 << eic_id);
+ // Enable the clocks
+ PM->APBAMASK.bit.EIC_ |= 1;
+ GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK2 | EIC_GCLK_ID;
+
+ #elif defined(MCU_SAMD51)
+
+ uint32_t irq_num = eic_id + 12;
+ // Disable all IRQs from the affected source while data is updated.
+ NVIC_DisableIRQ(irq_num);
+ // Disable EIC
+ EIC->CTRLA.bit.ENABLE = 0;
+ while (EIC->SYNCBUSY.bit.ENABLE != 0) {
+ }
+ EIC->INTENCLR.reg = (1 << eic_id);
+ // Enable the clocks
+ MCLK->APBAMASK.bit.EIC_ |= 1;
+ GCLK->PCHCTRL[EIC_GCLK_ID].reg = GCLK_PCHCTRL_CHEN | GCLK_PCHCTRL_GEN_GCLK2;
+
+ #endif
+ // Clear the pending interrupts flag
+ EIC->INTENCLR.reg = (1 << eic_id);
+
+ // Update IRQ data.
+ irq->base.handler = args[ARG_handler].u_obj;
+ irq->base.ishard = args[ARG_hard].u_bool;
+ irq->flags = 0;
+ irq->trigger = args[ARG_trigger].u_int;
+ irq->pin_id = self->pin_id;
+
+ // Enable IRQ if a handler is given.
+ if (args[ARG_handler].u_obj != mp_const_none) {
+ // Set EIC channel mode
+ EIC->CONFIG[eic_id / 8].reg |= irq->trigger << ((eic_id % 8) * 4);
+ EIC->INTENSET.reg = (1 << eic_id);
+ EIC->INTFLAG.reg |= (1 << eic_id);
+ }
+
+ // Enable EIC (again)
+ #if defined(MCU_SAMD21)
+ EIC->CTRL.bit.ENABLE = 1;
+ while (EIC->STATUS.bit.SYNCBUSY != 0) {
+ }
+ #elif defined(MCU_SAMD51)
+ EIC->CTRLA.bit.ENABLE = 1;
+ while (EIC->SYNCBUSY.bit.ENABLE != 0) {
+ }
+ #endif
+ // Enable interrupt again
+ NVIC_EnableIRQ(irq_num);
+ }
+ return MP_OBJ_FROM_PTR(irq);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_pin_irq_obj, 1, machine_pin_irq);
+
+void pin_irq_deinit_all(void) {
+
+ EIC->INTENCLR.reg = 0xffff; // Disable all interrupts from the EIC.
+ for (int i = 0; i < 16; i++) { // Clear all irq object pointers
+ MP_STATE_PORT(machine_pin_irq_objects[i]) = NULL;
+ }
+ // Disable all irq's at the NVIC controller
+ #if defined(MCU_SAMD21)
+ NVIC_DisableIRQ(4);
+ #elif defined(MCU_SAMD51)
+ for (int i = 12; i < 20; i++) {
+ NVIC_DisableIRQ(i);
+ }
+ #endif
+}
+
+// Common EIC handler for all events.
+void EIC_Handler() {
+ uint32_t mask = 1;
+ uint32_t isr = EIC->INTFLAG.reg;
+ for (int eic_id = 0; eic_id < 16; eic_id++, mask <<= 1) {
+ // Did the ISR fire?
+ if (isr & mask) {
+ EIC_occured = true;
+ EIC->INTFLAG.reg |= mask; // clear the ISR flag
+ machine_pin_irq_obj_t *irq = MP_STATE_PORT(machine_pin_irq_objects[eic_id]);
+ if (irq != NULL) {
+ irq->flags = irq->trigger;
+ mp_irq_handler(&irq->base);
+ break;
+ }
+ }
+ }
+}
+
STATIC const mp_rom_map_elem_t machine_pin_locals_dict_table[] = {
// instance methods
{ MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_pin_init_obj) },
@@ -249,21 +426,25 @@ STATIC const mp_rom_map_elem_t machine_pin_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_toggle), MP_ROM_PTR(&machine_pin_toggle_obj) },
{ MP_ROM_QSTR(MP_QSTR_disable), MP_ROM_PTR(&machine_pin_disable_obj) },
{ MP_ROM_QSTR(MP_QSTR_drive), MP_ROM_PTR(&machine_pin_drive_obj) },
+ { MP_ROM_QSTR(MP_QSTR_irq), MP_ROM_PTR(&machine_pin_irq_obj) },
-
- // { MP_ROM_QSTR(MP_QSTR_irq), MP_ROM_PTR(&machine_pin_irq_obj) },
+ #if MICROPY_PY_MACHINE_PIN_BOARD_CPU
+ // class attributes
+ { MP_ROM_QSTR(MP_QSTR_board), MP_ROM_PTR(&machine_pin_board_pins_obj_type) },
+ { MP_ROM_QSTR(MP_QSTR_cpu), MP_ROM_PTR(&machine_pin_cpu_pins_obj_type) },
+ #endif // MICROPY_PY_MACHINE_PIN_BOARD_CPU
// class constants
{ MP_ROM_QSTR(MP_QSTR_IN), MP_ROM_INT(GPIO_MODE_IN) },
{ MP_ROM_QSTR(MP_QSTR_OUT), MP_ROM_INT(GPIO_MODE_OUT) },
- // { MP_ROM_QSTR(MP_QSTR_ALT), MP_ROM_INT(GPIO_MODE_ALT) },
+ { MP_ROM_QSTR(MP_QSTR_OPEN_DRAIN), MP_ROM_INT(GPIO_MODE_OPEN_DRAIN) },
{ MP_ROM_QSTR(MP_QSTR_PULL_OFF), MP_ROM_INT(GPIO_PULL_OFF) },
{ MP_ROM_QSTR(MP_QSTR_PULL_UP), MP_ROM_INT(GPIO_PULL_UP) },
{ MP_ROM_QSTR(MP_QSTR_PULL_DOWN), MP_ROM_INT(GPIO_PULL_DOWN) },
{ MP_ROM_QSTR(MP_QSTR_LOW_POWER), MP_ROM_INT(GPIO_STRENGTH_2MA) },
{ MP_ROM_QSTR(MP_QSTR_HIGH_POWER), MP_ROM_INT(GPIO_STRENGTH_8MA) },
- // { MP_ROM_QSTR(MP_QSTR_IRQ_RISING), MP_ROM_INT(GPIO_IRQ_EDGE_RISE) },
- // { MP_ROM_QSTR(MP_QSTR_IRQ_FALLING), MP_ROM_INT(GPIO_IRQ_EDGE_FALL) },
+ { MP_ROM_QSTR(MP_QSTR_IRQ_RISING), MP_ROM_INT(GPIO_IRQ_EDGE_RISE) },
+ { MP_ROM_QSTR(MP_QSTR_IRQ_FALLING), MP_ROM_INT(GPIO_IRQ_EDGE_FALL) },
};
STATIC MP_DEFINE_CONST_DICT(machine_pin_locals_dict, machine_pin_locals_dict_table);
@@ -273,10 +454,10 @@ STATIC mp_uint_t pin_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, i
switch (request) {
case MP_PIN_READ: {
- return gpio_get_pin_level(self->id);
+ return mp_hal_pin_read(self->pin_id);
}
case MP_PIN_WRITE: {
- gpio_set_pin_level(self->id, arg);
+ mp_hal_pin_write(self->pin_id, arg);
return 0;
}
}
@@ -287,34 +468,50 @@ STATIC const mp_pin_p_t pin_pin_p = {
.ioctl = pin_ioctl,
};
-const mp_obj_type_t machine_pin_type = {
- { &mp_type_type },
- .name = MP_QSTR_Pin,
- .print = machine_pin_print,
- .make_new = mp_pin_make_new,
- .call = machine_pin_call,
- .protocol = &pin_pin_p,
- .locals_dict = (mp_obj_t)&machine_pin_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ machine_pin_type,
+ MP_QSTR_Pin,
+ MP_TYPE_FLAG_NONE,
+ make_new, mp_pin_make_new,
+ print, machine_pin_print,
+ call, machine_pin_call,
+ protocol, &pin_pin_p,
+ locals_dict, &machine_pin_locals_dict
+ );
+
+static uint8_t find_eic_id(int pin) {
+ for (int eic_id = 0; eic_id < 16; eic_id++) {
+ machine_pin_irq_obj_t *irq = MP_STATE_PORT(machine_pin_irq_objects[eic_id]);
+ if (irq != NULL && irq->pin_id == pin) {
+ return eic_id;
+ }
+ }
+ return 0xff;
+}
-/*
STATIC mp_uint_t machine_pin_irq_trigger(mp_obj_t self_in, mp_uint_t new_trigger) {
machine_pin_obj_t *self = MP_OBJ_TO_PTR(self_in);
- machine_pin_irq_obj_t *irq = MP_STATE_PORT(machine_pin_irq_obj[self->id]);
- gpio_set_irq_enabled(self->id, GPIO_IRQ_ALL, false);
- irq->flags = 0;
- irq->trigger = new_trigger;
- gpio_set_irq_enabled(self->id, new_trigger, true);
+ uint8_t eic_id = find_eic_id(self->pin_id);
+ if (eic_id != 0xff) {
+ machine_pin_irq_obj_t *irq = MP_STATE_PORT(machine_pin_irq_objects[eic_id]);
+ EIC->INTENCLR.reg |= (1 << eic_id);
+ irq->flags = 0;
+ irq->trigger = new_trigger;
+ EIC->INTENSET.reg |= (1 << eic_id);
+ }
return 0;
}
STATIC mp_uint_t machine_pin_irq_info(mp_obj_t self_in, mp_uint_t info_type) {
machine_pin_obj_t *self = MP_OBJ_TO_PTR(self_in);
- machine_pin_irq_obj_t *irq = MP_STATE_PORT(machine_pin_irq_obj[self->id]);
- if (info_type == MP_IRQ_INFO_FLAGS) {
- return irq->flags;
- } else if (info_type == MP_IRQ_INFO_TRIGGERS) {
- return irq->trigger;
+ uint8_t eic_id = find_eic_id(self->pin_id);
+ if (eic_id != 0xff) {
+ machine_pin_irq_obj_t *irq = MP_STATE_PORT(machine_pin_irq_objects[eic_id]);
+ if (info_type == MP_IRQ_INFO_FLAGS) {
+ return irq->flags;
+ } else if (info_type == MP_IRQ_INFO_TRIGGERS) {
+ return irq->trigger;
+ }
}
return 0;
}
@@ -323,12 +520,10 @@ STATIC const mp_irq_methods_t machine_pin_irq_methods = {
.trigger = machine_pin_irq_trigger,
.info = machine_pin_irq_info,
};
-*/
mp_hal_pin_obj_t mp_hal_get_pin_obj(mp_obj_t obj) {
- if (!mp_obj_is_type(obj, &machine_pin_type)) {
- mp_raise_ValueError(MP_ERROR_TEXT("expecting a Pin"));
- }
- machine_pin_obj_t *pin = MP_OBJ_TO_PTR(obj);
- return pin->id;
+ const machine_pin_obj_t *pin = pin_find(obj);
+ return pin->pin_id;
}
+
+MP_REGISTER_ROOT_POINTER(void *machine_pin_irq_objects[16]);
diff --git a/ports/samd/machine_pwm.c b/ports/samd/machine_pwm.c
new file mode 100644
index 000000000000..f6b417631e1d
--- /dev/null
+++ b/ports/samd/machine_pwm.c
@@ -0,0 +1,404 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2020-2021 Damien P. George
+ * Copyright (c) 2022 Robert Hammelrath
+ *
+ * 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/runtime.h"
+#include "py/mphal.h"
+#include "modmachine.h"
+#include "clock_config.h"
+
+#include "sam.h"
+#include "pin_af.h"
+
+/******************************************************************************/
+// MicroPython bindings for machine.PWM
+
+typedef struct _machine_pwm_obj_t {
+ mp_obj_base_t base;
+ Tcc *instance;
+ uint8_t pin_id;
+ uint8_t alt_fct;
+ uint8_t device;
+ uint8_t channel;
+ uint8_t output;
+ uint16_t prescaler;
+ uint32_t period; // full period count ticks
+ uint32_t duty_ns; // just for reporting
+ uint16_t duty_u16; // just for reporting
+} machine_pwm_obj_t;
+
+#define PWM_NOT_INIT (0)
+#define PWM_CLK_READY (1)
+#define PWM_TCC_ENABLED (2)
+#define PWM_MASTER_CLK (get_peripheral_freq())
+#define PWM_FULL_SCALE (65536)
+#define PWM_UPDATE_TIMEOUT (2000)
+
+static Tcc *tcc_instance[] = TCC_INSTS;
+
+#if defined(MCU_SAMD21)
+
+static const int tcc_gclk_id[] = {
+ GCLK_CLKCTRL_ID_TCC0_TCC1, GCLK_CLKCTRL_ID_TCC0_TCC1, GCLK_CLKCTRL_ID_TCC2_TC3
+};
+const uint8_t tcc_channel_count[] = {4, 2, 2};
+const static uint8_t tcc_channel_offset[] = {0, 4, 6};
+static uint32_t pwm_duty_values[8];
+
+#define PERBUF PERB
+#define CCBUF CCB
+
+#elif defined(MCU_SAMD51)
+
+static const int tcc_gclk_id[] = {
+ TCC0_GCLK_ID, TCC1_GCLK_ID, TCC2_GCLK_ID,
+ #if TCC_INST_NUM > 3
+ TCC3_GCLK_ID, TCC4_GCLK_ID
+ #endif
+};
+
+#if TCC_INST_NUM > 3
+const uint8_t tcc_channel_count[] = {6, 4, 3, 2, 2};
+const static uint8_t tcc_channel_offset[] = {0, 6, 10, 13, 15};
+static uint32_t pwm_duty_values[17];
+#else
+const uint8_t tcc_channel_count[] = {6, 4, 3};
+const static uint8_t tcc_channel_offset[] = {0, 6, 10};
+static uint32_t pwm_duty_values[13];
+#endif // TCC_INST_NUM > 3
+
+#endif // defined(MCU_SAMD51)
+
+#define put_duty_value(device, channel, duty) \
+ pwm_duty_values[tcc_channel_offset[device] + channel] = duty;
+
+#define get_duty_value(device, channel) \
+ pwm_duty_values[tcc_channel_offset[device] + channel]
+
+static uint8_t duty_type_flags[TCC_INST_NUM];
+static uint8_t device_status[TCC_INST_NUM];
+static uint8_t output_active[TCC_INST_NUM];
+const uint16_t prescaler_table[] = {1, 2, 4, 8, 16, 64, 256, 1024};
+
+STATIC void pwm_stop_device(int device);
+STATIC void mp_machine_pwm_freq_set(machine_pwm_obj_t *self, mp_int_t freq);
+STATIC void mp_machine_pwm_duty_set_u16(machine_pwm_obj_t *self, mp_int_t duty_u16);
+STATIC void mp_machine_pwm_duty_set_ns(machine_pwm_obj_t *self, mp_int_t duty_ns);
+
+STATIC void mp_machine_pwm_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
+ machine_pwm_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ mp_printf(print, "PWM(%s, device=%u, channel=%u, output=%u)",
+ pin_name(self->pin_id), self->device, self->channel, self->output);
+}
+
+// PWM(pin)
+STATIC mp_obj_t mp_machine_pwm_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
+ enum { ARG_pin, ARG_freq, ARG_duty_u16, ARG_duty_ns, ARG_invert, ARG_device };
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_pin, MP_ARG_REQUIRED | MP_ARG_OBJ },
+ { MP_QSTR_freq, MP_ARG_INT, {.u_int = -1} },
+ { MP_QSTR_duty_u16, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
+ { MP_QSTR_duty_ns, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
+ { MP_QSTR_invert, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
+ { MP_QSTR_device, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
+ };
+
+ // Parse the arguments.
+ mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
+ mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
+
+ // Get GPIO and optional device to connect to PWM.
+ uint32_t pin_id = mp_hal_get_pin_obj(args[ARG_pin].u_obj);
+ int32_t wanted_dev = args[ARG_device].u_int; // -1 = any
+
+ // Get the peripheral object and populate it
+
+ pwm_config_t config = get_pwm_config(pin_id, wanted_dev, device_status);
+ uint8_t device = config.device_channel >> 4;
+ if (device >= TCC_INST_NUM) {
+ mp_raise_ValueError(MP_ERROR_TEXT("wrong device"));
+ }
+
+ machine_pwm_obj_t *self = mp_obj_malloc(machine_pwm_obj_t, &machine_pwm_type);
+ self->instance = tcc_instance[device];
+ self->device = device;
+ self->pin_id = pin_id;
+ self->alt_fct = config.alt_fct;
+ self->channel = (config.device_channel & 0x0f) % tcc_channel_count[device];
+ self->output = config.device_channel & 0x0f;
+ self->prescaler = 1;
+ self->period = 1; // Use an invalid but safe value
+ self->duty_u16 = self->duty_ns = 0;
+ put_duty_value(self->device, self->channel, 0);
+
+ Tcc *tcc = self->instance;
+
+ if (device_status[device] == PWM_NOT_INIT) {
+ // Enable the device clock at first use.
+ #if defined(MCU_SAMD21)
+ // Enable synchronous clock. The bits are nicely arranged
+ PM->APBCMASK.reg |= PM_APBCMASK_TCC0 << device;
+ // Select multiplexer generic clock source and enable.
+ GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK2 | tcc_gclk_id[device];
+ // Wait while it updates synchronously.
+ while (GCLK->STATUS.bit.SYNCBUSY) {
+ }
+ #elif defined(MCU_SAMD51)
+ // GenClk2 to the tcc
+ GCLK->PCHCTRL[tcc_gclk_id[device]].reg = GCLK_PCHCTRL_CHEN | GCLK_PCHCTRL_GEN(2);
+ while (GCLK->SYNCBUSY.reg & GCLK_SYNCBUSY_GENCTRL_GCLK2) {
+ }
+ // Enable MCLK
+ switch (device) {
+ case 0:
+ MCLK->APBBMASK.reg |= MCLK_APBBMASK_TCC0;
+ break;
+ case 1:
+ MCLK->APBBMASK.reg |= MCLK_APBBMASK_TCC1;
+ break;
+ case 2:
+ MCLK->APBCMASK.reg |= MCLK_APBCMASK_TCC2;
+ break;
+ #if TCC_INST_NUM > 3
+ case 3:
+ MCLK->APBCMASK.reg |= MCLK_APBCMASK_TCC3;
+ break;
+ case 4:
+ MCLK->APBDMASK.reg |= MCLK_APBDMASK_TCC4;
+ break;
+ #endif
+ }
+ #endif
+ // Reset the device
+ tcc->CTRLA.reg = TCC_CTRLA_SWRST;
+ while (tcc->SYNCBUSY.reg & TCC_SYNCBUSY_SWRST) {
+ }
+ tcc->CTRLA.reg = TCC_CTRLA_PRESCALER_DIV1;
+ tcc->WAVE.reg = TCC_WAVE_WAVEGEN_NPWM;
+ // Flag the clock as initialized, but not the device as enabled.
+ device_status[device] = PWM_CLK_READY;
+ }
+
+ if (args[ARG_invert].u_int != -1) {
+ bool invert = !!args[ARG_invert].u_int;
+ if (device_status[device] != PWM_CLK_READY) {
+ pwm_stop_device(device);
+ }
+ uint32_t mask = 1 << (self->output + TCC_DRVCTRL_INVEN0_Pos);
+ if (invert) {
+ tcc->DRVCTRL.reg |= mask;
+ } else {
+ tcc->DRVCTRL.reg &= ~(mask);
+ }
+ }
+ if (args[ARG_duty_u16].u_int != -1) {
+ mp_machine_pwm_duty_set_u16(self, args[ARG_duty_u16].u_int);
+ }
+ if (args[ARG_duty_ns].u_int != -1) {
+ mp_machine_pwm_duty_set_ns(self, args[ARG_duty_ns].u_int);
+ }
+ if (args[ARG_freq].u_int != -1) {
+ mp_machine_pwm_freq_set(self, args[ARG_freq].u_int);
+ }
+ return MP_OBJ_FROM_PTR(self);
+}
+
+STATIC void pwm_stop_device(int device) {
+ Tcc *tcc = tcc_instance[device];
+ tcc->CTRLA.bit.ENABLE = 0;
+ while (tcc->SYNCBUSY.reg & TCC_SYNCBUSY_ENABLE) {
+ }
+ device_status[device] = PWM_CLK_READY;
+}
+
+// Stop all TTC devices
+void pwm_deinit_all(void) {
+ for (int i = 0; i < TCC_INST_NUM; i++) {
+ Tcc *tcc = tcc_instance[i];
+ tcc->CTRLA.reg = TCC_CTRLA_SWRST;
+ while (tcc->SYNCBUSY.reg & TCC_SYNCBUSY_SWRST) {
+ }
+ device_status[i] = PWM_NOT_INIT;
+ duty_type_flags[i] = 0;
+ output_active[i] = 0;
+ memset(pwm_duty_values, 0, sizeof(pwm_duty_values));
+ }
+}
+
+// Switch off an output. If all outputs of a device are off,
+// switch off that device.
+// This stops all channels, but keeps the configuration
+// Calling pwm.freq(n) will start an instance again.
+STATIC void mp_machine_pwm_deinit(machine_pwm_obj_t *self) {
+ mp_hal_clr_pin_mux(self->pin_id); // Switch the output off
+ output_active[self->device] &= ~(1 << self->output); // clear output flasg
+ // Stop the device, if no output is active.
+ if (output_active[self->device] == 0) {
+ pwm_stop_device(self->device);
+ }
+}
+
+STATIC void wait_for_register_update(Tcc *tcc) {
+ // Wait for a period's end (may be long) to have the change settled
+ // Each loop cycle takes at least 1 ms, giving an implicit timeout.
+ for (int i = 0; i < PWM_UPDATE_TIMEOUT; i++) {
+ if (tcc->INTFLAG.reg & TCC_INTFLAG_OVF) {
+ break;
+ }
+ MICROPY_EVENT_POLL_HOOK
+ }
+ // Clear the flag, telling that a cycle has been handled.
+ tcc->INTFLAG.reg = TCC_INTFLAG_OVF;
+}
+
+STATIC mp_obj_t mp_machine_pwm_freq_get(machine_pwm_obj_t *self) {
+ if (self->instance->CTRLA.reg & TCC_CTRLA_ENABLE) {
+ return MP_OBJ_NEW_SMALL_INT(PWM_MASTER_CLK / self->prescaler / self->period);
+ } else {
+ return MP_OBJ_NEW_SMALL_INT(0);
+ }
+}
+
+STATIC void mp_machine_pwm_freq_set(machine_pwm_obj_t *self, mp_int_t freq) {
+ // Set the frequency. The period counter is 24 bit or 16 bit with a pre-scaling
+ // of up to 1024, allowing a range from 24 MHz down to 1 Hz.
+ static const uint32_t max_period[5] = {1 << 24, 1 << 24, 1 << 16, 1 << 16, 1 << 16};
+
+ Tcc *tcc = self->instance;
+ if (freq < 1) {
+ pwm_stop_device(self->device);
+ return;
+ }
+
+ // Get the actual settings of prescaler & period from the unit
+ // To be able for cope for changes.
+ uint32_t prev_period = tcc->PER.reg + 1;
+
+ // Check for the right prescaler
+ uint8_t index;
+ for (index = 0; index < 8; index++) {
+ uint32_t temp = PWM_MASTER_CLK / prescaler_table[index] / freq;
+ if (temp < max_period[self->device]) {
+ break;
+ }
+ }
+ self->prescaler = prescaler_table[index];
+
+ uint32_t period = PWM_MASTER_CLK / self->prescaler / freq;
+ if (period < 2) {
+ mp_raise_ValueError(MP_ERROR_TEXT("freq too large"));
+ }
+ // If the PWM is running, ensure that a cycle has passed since the
+ // previous setting before setting a new frequency/duty value
+ if (tcc->CTRLA.reg & TCC_CTRLA_ENABLE) {
+ wait_for_register_update(tcc);
+ }
+ // Check, if the prescaler has to be changed and stop the device if so.
+ if (index != tcc->CTRLA.bit.PRESCALER) {
+ // stop the device
+ pwm_stop_device(self->device);
+ // update the prescaler
+ tcc->CTRLA.bit.PRESCALER = index;
+ }
+ // Lock the update to get a glitch-free change of period and duty cycle
+ tcc->CTRLBSET.reg = TCC_CTRLBSET_LUPD;
+ tcc->PERBUF.reg = period - 1;
+ self->period = period;
+
+ // Check if the Duty rate has to be aligned again when freq or prescaler were changed.
+ // This condition is as well true on first call after instantiation. So (re-)configure
+ // all channels with a duty_u16 setting.
+ if (period != prev_period) {
+ for (uint16_t ch = 0; ch < tcc_channel_count[self->device]; ch++) {
+ if ((duty_type_flags[self->device] & (1 << ch)) != 0) { // duty_u16 type?
+ tcc->CCBUF[ch].reg = (uint64_t)get_duty_value(self->device, ch) * period /
+ PWM_FULL_SCALE;
+ }
+ }
+ }
+ // If the prescaler was changed, the device is disabled. So this condition is true
+ // after the instantiation and after a prescaler change.
+ // (re-)configure all channels with a duty_ns setting.
+ if (!(tcc->CTRLA.reg & TCC_CTRLA_ENABLE)) {
+ for (uint16_t ch = 0; ch < tcc_channel_count[self->device]; ch++) {
+ if ((duty_type_flags[self->device] & (1 << ch)) == 0) { // duty_ns type?
+ tcc->CCBUF[ch].reg = (uint64_t)get_duty_value(self->device, ch) * PWM_MASTER_CLK /
+ self->prescaler / 1000000000ULL;
+ }
+ }
+ }
+ // Remember the output as active.
+ output_active[self->device] |= 1 << self->output; // set output flag
+ // (Re-)Select PWM function for given GPIO.
+ mp_hal_set_pin_mux(self->pin_id, self->alt_fct);
+ // Enable the device, if required.
+ if ((device_status[self->device] & PWM_TCC_ENABLED) == 0) {
+ tcc->CTRLBSET.reg = TCC_CTRLBSET_CMD_UPDATE;
+ tcc->CTRLA.reg |= TCC_CTRLA_ENABLE;
+ while (tcc->SYNCBUSY.reg & TCC_SYNCBUSY_ENABLE) {
+ }
+ device_status[self->device] |= PWM_TCC_ENABLED;
+ }
+ // Unlock the register update, now that the settings are complete
+ tcc->CTRLBCLR.reg = TCC_CTRLBCLR_LUPD;
+}
+
+STATIC mp_obj_t mp_machine_pwm_duty_get_u16(machine_pwm_obj_t *self) {
+ return MP_OBJ_NEW_SMALL_INT(self->duty_u16);
+}
+
+STATIC void mp_machine_pwm_duty_set_u16(machine_pwm_obj_t *self, mp_int_t duty_u16) {
+ // Remember the values for update & reporting
+ put_duty_value(self->device, self->channel, duty_u16);
+ self->duty_u16 = duty_u16;
+ self->duty_ns = 0;
+ // If the device is enabled, than the period is set and we get a reasonable value for
+ // the duty cycle, set to the CCBUF register. Otherwise, PWM does not start.
+ if (self->instance->CTRLA.reg & TCC_CTRLA_ENABLE) {
+ // Ensure that a cycle has passed updating the registers
+ // since the previous setting before setting a new duty value
+ wait_for_register_update(self->instance);
+ self->instance->CCBUF[self->channel].reg = (uint64_t)duty_u16 * (self->period) / PWM_FULL_SCALE;
+ }
+ duty_type_flags[self->device] |= 1 << self->channel;
+}
+
+STATIC mp_obj_t mp_machine_pwm_duty_get_ns(machine_pwm_obj_t *self) {
+ return MP_OBJ_NEW_SMALL_INT(self->duty_ns);
+}
+
+STATIC void mp_machine_pwm_duty_set_ns(machine_pwm_obj_t *self, mp_int_t duty_ns) {
+ // Remember the values for update & reporting
+ put_duty_value(self->device, self->channel, duty_ns);
+ self->duty_ns = duty_ns;
+ self->duty_u16 = 0;
+ // Ensure that a cycle has passed updating the registers
+ // since the previous setting before setting a new duty value
+ wait_for_register_update(self->instance);
+ self->instance->CCBUF[self->channel].reg = (uint64_t)duty_ns * PWM_MASTER_CLK / self->prescaler / 1000000000ULL;
+ duty_type_flags[self->device] &= ~(1 << self->channel);
+}
diff --git a/ports/samd/machine_rtc.c b/ports/samd/machine_rtc.c
new file mode 100644
index 000000000000..57bfa998e583
--- /dev/null
+++ b/ports/samd/machine_rtc.c
@@ -0,0 +1,181 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2021 Damien P. George
+ * Copyright (c) 2022 "Robert Hammelrath"
+ *
+ * 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 "shared/timeutils/timeutils.h"
+#include "modmachine.h"
+#include "py/mphal.h"
+#include "sam.h"
+
+#if MICROPY_PY_MACHINE_RTC
+
+typedef struct _machine_rtc_obj_t {
+ mp_obj_base_t base;
+ mp_obj_t callback;
+} machine_rtc_obj_t;
+
+// Singleton RTC object.
+STATIC const machine_rtc_obj_t machine_rtc_obj = {{&machine_rtc_type}};
+
+// Start the RTC Timer.
+void machine_rtc_start(bool force) {
+ #if defined(MCU_SAMD21)
+
+ if (RTC->MODE2.CTRL.bit.ENABLE == 0 || force) {
+ // Enable the 1k Clock
+ GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK8 | GCLK_CLKCTRL_ID_RTC;
+
+ RTC->MODE2.CTRL.reg = RTC_MODE2_CTRL_SWRST;
+ while (RTC->MODE2.STATUS.bit.SYNCBUSY) {
+ }
+ RTC->MODE2.CTRL.reg =
+ RTC_MODE2_CTRL_MODE_CLOCK |
+ RTC_MODE2_CTRL_PRESCALER_DIV1024 |
+ RTC_MODE2_CTRL_ENABLE;
+ while (RTC->MODE2.STATUS.bit.SYNCBUSY) {
+ }
+ }
+
+ #elif defined(MCU_SAMD51)
+
+ if (RTC->MODE2.CTRLA.bit.ENABLE == 0 || force) {
+ RTC->MODE2.CTRLA.reg = RTC_MODE2_CTRLA_SWRST;
+ while (RTC->MODE2.SYNCBUSY.bit.SWRST) {
+ }
+ RTC->MODE2.CTRLA.reg =
+ RTC_MODE2_CTRLA_MODE_CLOCK |
+ RTC_MODE2_CTRLA_CLOCKSYNC |
+ RTC_MODE2_CTRLA_PRESCALER_DIV1024 |
+ RTC_MODE2_CTRLA_ENABLE;
+ while (RTC->MODE2.SYNCBUSY.bit.ENABLE) {
+ }
+ }
+ #endif
+}
+
+// Get the time from the RTC and put it into a tm struct.
+void rtc_gettime(timeutils_struct_time_t *tm) {
+ tm->tm_year = RTC->MODE2.CLOCK.bit.YEAR + 2000;
+ tm->tm_mon = RTC->MODE2.CLOCK.bit.MONTH;
+ tm->tm_mday = RTC->MODE2.CLOCK.bit.DAY;
+ tm->tm_hour = RTC->MODE2.CLOCK.bit.HOUR;
+ tm->tm_min = RTC->MODE2.CLOCK.bit.MINUTE;
+ tm->tm_sec = RTC->MODE2.CLOCK.bit.SECOND;
+}
+
+STATIC mp_obj_t machine_rtc_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
+ // Check arguments.
+ mp_arg_check_num(n_args, n_kw, 0, 0, false);
+ // RTC was already started at boot time. So nothing to do here.
+ // Return constant object.
+ return (mp_obj_t)&machine_rtc_obj;
+}
+
+STATIC mp_obj_t machine_rtc_datetime_helper(size_t n_args, const mp_obj_t *args) {
+ // Rtc *rtc = RTC;
+ if (n_args == 1) {
+ // Get date and time.
+ timeutils_struct_time_t tm;
+ rtc_gettime(&tm);
+
+ mp_obj_t tuple[8] = {
+ mp_obj_new_int(tm.tm_year),
+ mp_obj_new_int(tm.tm_mon),
+ mp_obj_new_int(tm.tm_mday),
+ mp_obj_new_int(timeutils_calc_weekday(tm.tm_year, tm.tm_mon, tm.tm_mday)),
+ mp_obj_new_int(tm.tm_hour),
+ mp_obj_new_int(tm.tm_min),
+ mp_obj_new_int(tm.tm_sec),
+ mp_obj_new_int(0),
+ };
+ return mp_obj_new_tuple(8, tuple);
+ } else {
+ // Set date and time.
+ mp_obj_t *items;
+ mp_obj_get_array_fixed_n(args[1], 8, &items);
+
+ uint32_t date =
+ RTC_MODE2_CLOCK_YEAR(mp_obj_get_int(items[0]) % 100) |
+ RTC_MODE2_CLOCK_MONTH(mp_obj_get_int(items[1])) |
+ RTC_MODE2_CLOCK_DAY(mp_obj_get_int(items[2])) |
+ RTC_MODE2_CLOCK_HOUR(mp_obj_get_int(items[4])) |
+ RTC_MODE2_CLOCK_MINUTE(mp_obj_get_int(items[5])) |
+ RTC_MODE2_CLOCK_SECOND(mp_obj_get_int(items[6]));
+
+ RTC->MODE2.CLOCK.reg = date;
+ #if defined(MCU_SAMD21)
+ while (RTC->MODE2.STATUS.bit.SYNCBUSY) {
+ }
+ #elif defined(MCU_SAMD51)
+ while (RTC->MODE2.SYNCBUSY.bit.CLOCKSYNC) {
+ }
+ #endif
+
+ return mp_const_none;
+ }
+}
+
+STATIC mp_obj_t machine_rtc_datetime(mp_uint_t n_args, const mp_obj_t *args) {
+ return machine_rtc_datetime_helper(n_args, args);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_rtc_datetime_obj, 1, 2, machine_rtc_datetime);
+
+STATIC mp_obj_t machine_rtc_init(mp_obj_t self_in, mp_obj_t date) {
+ mp_obj_t args[2] = {self_in, date};
+ machine_rtc_datetime_helper(2, args);
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(machine_rtc_init_obj, machine_rtc_init);
+
+// calibration(cal)
+// When the argument is a number in the range [-16 to 15], set the calibration value.
+STATIC mp_obj_t machine_rtc_calibration(mp_obj_t self_in, mp_obj_t cal_in) {
+ int8_t cal = 0;
+ // Make it negative for a "natural" behavior:
+ // value > 0: faster, value < 0: slower
+ cal = -mp_obj_get_int(cal_in);
+ RTC->MODE2.FREQCORR.reg = (uint8_t)cal;
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(machine_rtc_calibration_obj, machine_rtc_calibration);
+
+STATIC const mp_rom_map_elem_t machine_rtc_locals_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_rtc_init_obj) },
+ { MP_ROM_QSTR(MP_QSTR_datetime), MP_ROM_PTR(&machine_rtc_datetime_obj) },
+ { MP_ROM_QSTR(MP_QSTR_calibration), MP_ROM_PTR(&machine_rtc_calibration_obj) },
+};
+STATIC MP_DEFINE_CONST_DICT(machine_rtc_locals_dict, machine_rtc_locals_dict_table);
+
+MP_DEFINE_CONST_OBJ_TYPE(
+ machine_rtc_type,
+ MP_QSTR_RTC,
+ MP_TYPE_FLAG_NONE,
+ make_new, machine_rtc_make_new,
+ locals_dict, &machine_rtc_locals_dict
+ );
+
+#endif // MICROPY_PY_MACHINE_RTC
diff --git a/ports/samd/machine_spi.c b/ports/samd/machine_spi.c
new file mode 100644
index 000000000000..bbd7031e940e
--- /dev/null
+++ b/ports/samd/machine_spi.c
@@ -0,0 +1,343 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2020-2021 Damien P. George
+ * Copyright (c) 2022 Robert Hammelrath
+ *
+ * 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 "extmod/machine_spi.h"
+#include "modmachine.h"
+#include "samd_soc.h"
+#include "pin_af.h"
+#include "clock_config.h"
+
+#define DEFAULT_SPI_BAUDRATE (1000000)
+#define DEFAULT_SPI_POLARITY (0)
+#define DEFAULT_SPI_PHASE (0)
+#define DEFAULT_SPI_BITS (8)
+#define DEFAULT_SPI_FIRSTBIT (0)
+
+typedef struct _machine_spi_obj_t {
+ mp_obj_base_t base;
+ uint8_t id;
+ uint8_t polarity;
+ uint8_t phase;
+ uint8_t firstbit;
+ uint8_t sck;
+ uint8_t mosi;
+ uint8_t miso;
+ uint8_t new;
+ uint32_t baudrate;
+ sercom_pad_config_t sck_pad_config;
+ sercom_pad_config_t mosi_pad_config;
+ sercom_pad_config_t miso_pad_config;
+ uint8_t *dest;
+ size_t rxlen;
+} machine_spi_obj_t;
+
+extern Sercom *sercom_instance[];
+MP_REGISTER_ROOT_POINTER(void *sercom_table[SERCOM_INST_NUM]);
+
+void common_spi_irq_handler(int spi_id) {
+ // handle Sercom IRQ RXC
+ machine_spi_obj_t *self = MP_STATE_PORT(sercom_table[spi_id]);
+ // Handle IRQ
+ if (self != NULL) {
+ Sercom *spi = sercom_instance[self->id];
+ if (spi->SPI.INTFLAG.bit.RXC != 0) {
+ if (self->rxlen > 0) {
+ *(self->dest)++ = spi->SPI.DATA.bit.DATA;
+ self->rxlen--;
+ } else {
+ // Just in the unlikely case there is data but no space in the buffer
+ // discard the data and clear the intflag
+ uint32_t temp;
+ (void)temp;
+ temp = spi->SPI.DATA.bit.DATA;
+ }
+ }
+ }
+}
+
+STATIC void machine_spi_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
+ machine_spi_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ mp_printf(print, "SPI(%u, baudrate=%u, firstbit=%u, polarity=%u, phase=%u, bits=8)",
+ self->id, self->baudrate, self->firstbit, self->polarity, self->phase);
+}
+
+STATIC void machine_spi_init(mp_obj_base_t *self_in, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ enum { ARG_baudrate, ARG_polarity, ARG_phase, ARG_firstbit,
+ ARG_sck, ARG_mosi, ARG_miso};
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_baudrate, MP_ARG_INT, {.u_int = -1} },
+ { MP_QSTR_polarity, MP_ARG_INT, {.u_int = -1} },
+ { MP_QSTR_phase, MP_ARG_INT, {.u_int = -1} },
+ { MP_QSTR_firstbit, MP_ARG_INT, {.u_int = -1} },
+ { MP_QSTR_sck, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
+ { MP_QSTR_mosi, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
+ { MP_QSTR_miso, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
+ };
+
+ machine_spi_obj_t *self = MP_OBJ_TO_PTR(self_in);
+
+ // Parse args
+ mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
+ mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
+
+ // Set baudrate if configured.
+ if (args[ARG_baudrate].u_int >= 0) {
+ self->baudrate = args[ARG_baudrate].u_int;
+ }
+
+ // Set polarity if configured.
+ if (args[ARG_polarity].u_int >= 0) {
+ self->polarity = args[ARG_polarity].u_int;
+ }
+
+ // Set phase if configured.
+ if (args[ARG_phase].u_int >= 0) {
+ self->phase = args[ARG_phase].u_int;
+ }
+
+ // Set firstbit if configured.
+ if (args[ARG_firstbit].u_int >= 0) {
+ self->firstbit = args[ARG_firstbit].u_int;
+ }
+
+ // Set SCK/MOSI/MISO pins if configured.
+ if (args[ARG_sck].u_obj != mp_const_none) {
+ self->sck = mp_hal_get_pin_obj(args[ARG_sck].u_obj);
+ }
+ if (args[ARG_mosi].u_obj != mp_const_none) {
+ self->mosi = mp_hal_get_pin_obj(args[ARG_mosi].u_obj);
+ }
+ if (args[ARG_miso].u_obj != mp_const_none) {
+ self->miso = mp_hal_get_pin_obj(args[ARG_miso].u_obj);
+ }
+
+ // Initialise the SPI peripheral if any arguments given, or it was not initialised previously.
+ if (n_args > 0 || kw_args->used > 0 || self->new) {
+ self->new = false;
+
+ // Get the pad and alt-fct numbers.
+ self->sck_pad_config = get_sercom_config(self->sck, self->id);
+ self->mosi_pad_config = get_sercom_config(self->mosi, self->id);
+
+ uint8_t dopo = 0;
+ #if defined(MCU_SAMD21)
+ if (self->mosi_pad_config.pad_nr == 0 && self->sck_pad_config.pad_nr == 1) {
+ dopo = 0;
+ } else if (self->mosi_pad_config.pad_nr == 2 && self->sck_pad_config.pad_nr == 3) {
+ dopo = 1;
+ } else if (self->mosi_pad_config.pad_nr == 3 && self->sck_pad_config.pad_nr == 1) {
+ dopo = 2;
+ } else if (self->mosi_pad_config.pad_nr == 0 && self->sck_pad_config.pad_nr == 3) {
+ dopo = 3;
+ } else {
+ mp_raise_ValueError(MP_ERROR_TEXT("invalid pin for sck or mosi"));
+ }
+ #elif defined(MCU_SAMD51)
+ if (self->mosi_pad_config.pad_nr == 0 && self->sck_pad_config.pad_nr == 1) {
+ dopo = 0;
+ } else if (self->mosi_pad_config.pad_nr == 3 && self->sck_pad_config.pad_nr == 1) {
+ dopo = 2;
+ } else {
+ mp_raise_ValueError(MP_ERROR_TEXT("invalid pin for sck or mosi"));
+ }
+ #endif
+
+ if (self->miso != 0xff) { // Miso may be undefined
+ self->miso_pad_config = get_sercom_config(self->miso, self->id);
+ mp_hal_set_pin_mux(self->miso, self->miso_pad_config.alt_fct);
+ }
+ // Configure the Pin mux.
+ mp_hal_set_pin_mux(self->sck, self->sck_pad_config.alt_fct);
+ mp_hal_set_pin_mux(self->mosi, self->mosi_pad_config.alt_fct);
+
+ // Set up the clocks
+ enable_sercom_clock(self->id);
+
+ // Configure the SPI
+ Sercom *spi = sercom_instance[self->id];
+ // Reset (clear) the peripheral registers.
+ while (spi->SPI.SYNCBUSY.bit.SWRST) {
+ }
+ spi->SPI.CTRLA.bit.SWRST = 1;
+ while (spi->SPI.SYNCBUSY.bit.SWRST) {
+ }
+
+ // Set the registers
+ spi->SPI.CTRLA.bit.MODE = 0x03; // SPI master mode
+ spi->SPI.CTRLA.bit.CPOL = self->polarity;
+ spi->SPI.CTRLA.bit.CPHA = self->phase;
+ spi->SPI.CTRLA.bit.DIPO = self->miso_pad_config.pad_nr;
+ spi->SPI.CTRLA.bit.DOPO = dopo;
+ spi->SPI.CTRLA.bit.DORD = self->firstbit;
+
+ // Enable receive only if miso is defined
+ if (self->miso != 0xff) {
+ spi->SPI.CTRLB.reg = SERCOM_SPI_CTRLB_RXEN;
+ while (spi->SPI.SYNCBUSY.bit.CTRLB) {
+ }
+ }
+
+ #if defined(MCU_SAMD51)
+ spi->SPI.CTRLC.reg = 1; // 1 clock cycle character spacing
+ #endif
+
+ // SPI is driven by the clock of GCLK Generator 2, freq by get_peripheral_freq()
+ // baud = bus_freq / (2 * baudrate) - 1
+ uint32_t baud = get_peripheral_freq() / (2 * self->baudrate);
+ if (baud > 0) { // Avoid underflow
+ baud -= 1;
+ }
+ if (baud > 255) { // Avoid overflow
+ baud = 255;
+ }
+ spi->SPI.BAUD.reg = baud; // Set Baud
+
+ // Enable RXC interrupt only if miso is defined
+ if (self->miso != 0xff) {
+ #if defined(MCU_SAMD21)
+ NVIC_EnableIRQ(SERCOM0_IRQn + self->id);
+ #elif defined(MCU_SAMD51)
+ NVIC_EnableIRQ(SERCOM0_0_IRQn + 4 * self->id + 2);
+ #endif
+ sercom_register_irq(self->id, &common_spi_irq_handler);
+ }
+
+ sercom_enable(spi, 1);
+ }
+}
+
+STATIC mp_obj_t machine_spi_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
+ mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true);
+
+ // Get SPI bus.
+ int spi_id = mp_obj_get_int(args[0]);
+ if (spi_id < 0 || spi_id > SERCOM_INST_NUM) {
+ mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("SPI(%d) doesn't exist"), spi_id);
+ }
+
+ // Create the SPI object and fill it with defaults.
+ machine_spi_obj_t *self = mp_obj_malloc(machine_spi_obj_t, &machine_spi_type);
+ self->id = spi_id;
+ self->baudrate = DEFAULT_SPI_BAUDRATE;
+ self->polarity = DEFAULT_SPI_POLARITY;
+ self->phase = DEFAULT_SPI_PHASE;
+ self->firstbit = DEFAULT_SPI_FIRSTBIT;
+ self->mosi = 0xff; // 0xff: pin not defined (yet)
+ self->miso = 0xff;
+ self->sck = 0xff;
+
+ self->new = true;
+ MP_STATE_PORT(sercom_table[spi_id]) = self;
+
+ mp_map_t kw_args;
+ mp_map_init_fixed_table(&kw_args, n_kw, args + n_args);
+ machine_spi_init((mp_obj_base_t *)self, n_args - 1, args + 1, &kw_args);
+ return self;
+}
+
+STATIC void machine_sercom_deinit(mp_obj_base_t *self_in) {
+ machine_spi_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ Sercom *spi = sercom_instance[self->id];
+ // Disable interrupts (if any)
+ spi->SPI.INTENCLR.reg = 0xff;
+ sercom_enable(spi, 0);
+ // clear table entry of spi
+ MP_STATE_PORT(sercom_table[self->id]) = NULL;
+}
+
+void sercom_deinit_all(void) {
+ for (int i = 0; i < SERCOM_INST_NUM; i++) {
+ Sercom *spi = sercom_instance[i];
+ spi->SPI.INTENCLR.reg = 0xff;
+ sercom_register_irq(i, NULL);
+ sercom_enable(spi, 0);
+ MP_STATE_PORT(sercom_table[i]) = NULL;
+ }
+}
+
+STATIC void machine_spi_transfer(mp_obj_base_t *self_in, size_t len, const uint8_t *src, uint8_t *dest) {
+ machine_spi_obj_t *self = (machine_spi_obj_t *)self_in;
+
+ Sercom *spi = sercom_instance[self->id];
+ size_t txlen = len;
+ // Clear the input queue, if needed
+ while (dest && spi->SPI.INTFLAG.bit.RXC) {
+ uint32_t temp;
+ (void)temp;
+ temp = spi->SPI.DATA.bit.DATA;
+ }
+ // Set up the irq data pointers and enable IRQ
+ if (dest) {
+ if (self->miso == 0xff) {
+ mp_raise_ValueError(MP_ERROR_TEXT("read is not enabled"));
+ }
+ spi->SPI.INTENSET.reg = SERCOM_SPI_INTENSET_RXC;
+ self->dest = dest;
+ self->rxlen = len;
+ }
+
+ // Send by polling & receive by IRQ
+ while (txlen) {
+ if (spi->SPI.INTFLAG.bit.DRE) {
+ spi->SPI.DATA.bit.DATA = *src;
+ src += 1;
+ txlen--;
+ }
+ }
+ // Receive the remaining data, if any and clear IRQ
+ // Do no wait forever.
+ if (dest) {
+ int32_t timeout = 1000;
+ while (self->rxlen > 0 && timeout) {
+ timeout--;
+ MICROPY_EVENT_POLL_HOOK
+ }
+ spi->SPI.INTENCLR.reg = SERCOM_SPI_INTENCLR_RXC;
+ } else {
+ // Wait for the data being shifted out.
+ while (!spi->SPI.INTFLAG.bit.TXC) {
+ }
+ }
+}
+
+
+STATIC const mp_machine_spi_p_t machine_spi_p = {
+ .init = machine_spi_init,
+ .deinit = machine_sercom_deinit,
+ .transfer = machine_spi_transfer,
+};
+
+MP_DEFINE_CONST_OBJ_TYPE(
+ machine_spi_type,
+ MP_QSTR_SPI,
+ MP_TYPE_FLAG_NONE,
+ make_new, machine_spi_make_new,
+ print, machine_spi_print,
+ protocol, &machine_spi_p,
+ locals_dict, &mp_machine_spi_locals_dict
+ );
diff --git a/ports/samd/machine_uart.c b/ports/samd/machine_uart.c
new file mode 100644
index 000000000000..7917529fb9ad
--- /dev/null
+++ b/ports/samd/machine_uart.c
@@ -0,0 +1,546 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2020-2021 Damien P. George
+ * Copyright (c) 2022 Robert Hammelrath
+ *
+ * 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 "py/stream.h"
+#include "py/ringbuf.h"
+#include "modmachine.h"
+#include "samd_soc.h"
+#include "pin_af.h"
+#include "clock_config.h"
+
+#define DEFAULT_UART_BAUDRATE (115200)
+#define DEFAULT_BUFFER_SIZE (256)
+#define MIN_BUFFER_SIZE (32)
+#define MAX_BUFFER_SIZE (32766)
+
+typedef struct _machine_uart_obj_t {
+ mp_obj_base_t base;
+ uint8_t id;
+ uint32_t baudrate;
+ uint8_t bits;
+ uint8_t parity;
+ uint8_t stop;
+ uint8_t tx;
+ sercom_pad_config_t tx_pad_config;
+ uint8_t rx;
+ sercom_pad_config_t rx_pad_config;
+ uint16_t timeout; // timeout waiting for first char (in ms)
+ uint16_t timeout_char; // timeout waiting between chars (in ms)
+ bool new;
+ ringbuf_t read_buffer;
+ #if MICROPY_HW_UART_TXBUF
+ ringbuf_t write_buffer;
+ #endif
+} machine_uart_obj_t;
+
+Sercom *sercom_instance[] = SERCOM_INSTS;
+
+STATIC const char *_parity_name[] = {"None", "", "0", "1"}; // Is defined as 0, 2, 3
+
+// Irq handler
+
+// take all bytes from the fifo and store them in the buffer
+STATIC void uart_drain_rx_fifo(machine_uart_obj_t *self, Sercom *uart) {
+ while (uart->USART.INTFLAG.bit.RXC != 0) {
+ if (ringbuf_free(&self->read_buffer) > 0) {
+ // get a byte from uart and put into the buffer
+ ringbuf_put(&(self->read_buffer), uart->USART.DATA.bit.DATA);
+ } else {
+ // if the buffer is full, discard the data for now
+ // t.b.d.: flow control
+ uint32_t temp;
+ (void)temp;
+ temp = uart->USART.DATA.bit.DATA;
+ }
+ }
+}
+
+void common_uart_irq_handler(int uart_id) {
+ machine_uart_obj_t *self = MP_STATE_PORT(sercom_table[uart_id]);
+ // Handle IRQ
+ if (self != NULL) {
+ Sercom *uart = sercom_instance[self->id];
+ if (uart->USART.INTFLAG.bit.RXC != 0) {
+ // Now handler the incoming data
+ uart_drain_rx_fifo(self, uart);
+ } else if (uart->USART.INTFLAG.bit.DRE != 0) {
+ #if MICROPY_HW_UART_TXBUF
+ // handle the outgoing data
+ if (ringbuf_avail(&self->write_buffer) > 0) {
+ uart->USART.DATA.bit.DATA = ringbuf_get(&self->write_buffer);
+ } else {
+ // Stop the interrupt if there is no more data
+ uart->USART.INTENCLR.reg = SERCOM_USART_INTENCLR_DRE;
+ }
+ #endif
+ } else {
+ // Disable the other interrupts, if set by error
+ uart->USART.INTENCLR.reg = (uint8_t) ~(SERCOM_USART_INTENCLR_DRE | SERCOM_USART_INTENCLR_RXC);
+ }
+ }
+}
+
+void sercom_enable(Sercom *uart, int state) {
+ uart->USART.CTRLA.bit.ENABLE = state; // Set the state on/off
+ // Wait for the Registers to update.
+ while (uart->USART.SYNCBUSY.bit.ENABLE) {
+ }
+}
+
+STATIC void machine_uart_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
+ machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ mp_printf(print, "UART(%u, baudrate=%u, bits=%u, parity=%s, stop=%u, "
+ "timeout=%u, timeout_char=%u, rxbuf=%d"
+ #if MICROPY_HW_UART_TXBUF
+ ", txbuf=%d"
+ #endif
+ ")",
+ self->id, self->baudrate, self->bits, _parity_name[self->parity],
+ self->stop + 1, self->timeout, self->timeout_char, self->read_buffer.size - 1
+ #if MICROPY_HW_UART_TXBUF
+ , self->write_buffer.size - 1
+ #endif
+ );
+}
+
+STATIC mp_obj_t machine_uart_init_helper(machine_uart_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ enum { ARG_baudrate, ARG_bits, ARG_parity, ARG_stop, ARG_tx, ARG_rx,
+ ARG_timeout, ARG_timeout_char, ARG_rxbuf, ARG_txbuf};
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_baudrate, MP_ARG_INT, {.u_int = -1} },
+ { MP_QSTR_bits, MP_ARG_INT, {.u_int = -1} },
+ { MP_QSTR_parity, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_INT(-1)} },
+ { MP_QSTR_stop, MP_ARG_INT, {.u_int = -1} },
+ { MP_QSTR_tx, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
+ { MP_QSTR_rx, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
+ { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
+ { MP_QSTR_timeout_char, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
+ { MP_QSTR_rxbuf, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
+ #if MICROPY_HW_UART_TXBUF
+ { MP_QSTR_txbuf, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
+ #endif
+ };
+
+ // Parse args
+ mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
+ mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
+
+ // Set baudrate if configured.
+ if (args[ARG_baudrate].u_int > 0) {
+ self->baudrate = args[ARG_baudrate].u_int;
+ }
+
+ // Set bits if configured.
+ if (args[ARG_bits].u_int > 0) {
+ self->bits = args[ARG_bits].u_int;
+ }
+
+ // Set parity if configured.
+ if (args[ARG_parity].u_obj != MP_OBJ_NEW_SMALL_INT(-1)) {
+ if (args[ARG_parity].u_obj == mp_const_none) {
+ self->parity = 0;
+ } else if (mp_obj_get_int(args[ARG_parity].u_obj) & 1) {
+ self->parity = 1; // odd
+ } else {
+ self->parity = 2; // even
+ }
+ }
+
+ // Set stop bits if configured.
+ if (args[ARG_stop].u_int > 0) {
+ self->stop = (args[ARG_stop].u_int - 1) & 1;
+ }
+
+ // Set TX/RX pins if configured.
+ if (args[ARG_tx].u_obj != mp_const_none) {
+ self->tx = mp_hal_get_pin_obj(args[ARG_tx].u_obj);
+ }
+ if (args[ARG_rx].u_obj != mp_const_none) {
+ self->rx = mp_hal_get_pin_obj(args[ARG_rx].u_obj);
+ }
+
+ // Set timeout if configured.
+ if (args[ARG_timeout].u_int >= 0) {
+ self->timeout = args[ARG_timeout].u_int;
+ }
+
+ // Set timeout_char if configured.
+ if (args[ARG_timeout_char].u_int >= 0) {
+ self->timeout_char = args[ARG_timeout_char].u_int;
+ }
+
+ // Set the RX buffer size if configured.
+ size_t rxbuf_len = DEFAULT_BUFFER_SIZE;
+ if (args[ARG_rxbuf].u_int > 0) {
+ rxbuf_len = args[ARG_rxbuf].u_int;
+ if (rxbuf_len < MIN_BUFFER_SIZE) {
+ rxbuf_len = MIN_BUFFER_SIZE;
+ } else if (rxbuf_len > MAX_BUFFER_SIZE) {
+ mp_raise_ValueError(MP_ERROR_TEXT("rxbuf too large"));
+ }
+ }
+
+ #if MICROPY_HW_UART_TXBUF
+ // Set the TX buffer size if configured.
+ size_t txbuf_len = DEFAULT_BUFFER_SIZE;
+ if (args[ARG_txbuf].u_int > 0) {
+ txbuf_len = args[ARG_txbuf].u_int;
+ if (txbuf_len < MIN_BUFFER_SIZE) {
+ txbuf_len = MIN_BUFFER_SIZE;
+ } else if (txbuf_len > MAX_BUFFER_SIZE) {
+ mp_raise_ValueError(MP_ERROR_TEXT("txbuf too large"));
+ }
+ }
+ #endif
+ // Initialise the UART peripheral if any arguments given, or it was not initialised previously.
+ if (n_args > 0 || kw_args->used > 0 || self->new) {
+ self->new = false;
+
+ // Check the rx/tx pin assignments
+ if (self->tx == 0xff || self->rx == 0xff || (self->tx / 4) != (self->rx / 4)) {
+ mp_raise_ValueError(MP_ERROR_TEXT("Non-matching or missing rx/tx"));
+ }
+ self->rx_pad_config = get_sercom_config(self->rx, self->id);
+ self->tx_pad_config = get_sercom_config(self->tx, self->id);
+
+ // Make sure timeout_char is at least as long as a whole character (13 bits to be safe).
+ uint32_t min_timeout_char = 13000 / self->baudrate + 1;
+ if (self->timeout_char < min_timeout_char) {
+ self->timeout_char = min_timeout_char;
+ }
+
+ // Allocate the RX/TX buffers.
+ ringbuf_alloc(&(self->read_buffer), rxbuf_len + 1);
+
+ #if MICROPY_HW_UART_TXBUF
+ ringbuf_alloc(&(self->write_buffer), txbuf_len + 1);
+ #endif
+
+ // Step 1: Configure the Pin mux.
+ mp_hal_set_pin_mux(self->rx, self->rx_pad_config.alt_fct);
+ mp_hal_set_pin_mux(self->tx, self->tx_pad_config.alt_fct);
+
+ // Next: Set up the clocks
+ enable_sercom_clock(self->id);
+
+ // Next: Configure the USART
+ Sercom *uart = sercom_instance[self->id];
+ // Reset (clear) the peripheral registers.
+ while (uart->USART.SYNCBUSY.bit.SWRST) {
+ }
+ uart->USART.CTRLA.bit.SWRST = 1; // Reset all Registers, disable peripheral
+ while (uart->USART.SYNCBUSY.bit.SWRST) {
+ }
+
+ uint8_t txpo = self->tx_pad_config.pad_nr;
+ #if defined(MCU_SAMD21)
+ if (self->tx_pad_config.pad_nr == 2) { // Map pad 2 to TXPO = 1
+ txpo = 1;
+ } else
+ #endif
+ if (self->tx_pad_config.pad_nr != 0) {
+ mp_raise_ValueError(MP_ERROR_TEXT("invalid tx pin"));
+ }
+
+ uart->USART.CTRLA.reg =
+ SERCOM_USART_CTRLA_DORD // Data order
+ | SERCOM_USART_CTRLA_FORM(self->parity != 0 ? 1 : 0) // Enable parity or not
+ | SERCOM_USART_CTRLA_RXPO(self->rx_pad_config.pad_nr) // Set Pad#
+ | SERCOM_USART_CTRLA_TXPO(txpo) // Set Pad#
+ | SERCOM_USART_CTRLA_MODE(1) // USART with internal clock
+ ;
+ uart->USART.CTRLB.reg =
+ SERCOM_USART_CTRLB_RXEN // Enable Rx & Tx
+ | SERCOM_USART_CTRLB_TXEN
+ | ((self->parity & 1) << SERCOM_USART_CTRLB_PMODE_Pos)
+ | (self->stop << SERCOM_USART_CTRLB_SBMODE_Pos)
+ | SERCOM_USART_CTRLB_CHSIZE((self->bits & 7) | (self->bits & 1))
+ ;
+ while (uart->USART.SYNCBUSY.bit.CTRLB) {
+ }
+
+ // USART is driven by the clock of GCLK Generator 2, freq by get_peripheral_freq()
+ // baud rate; 65536 * (1 - 16 * 115200/bus_freq)
+ uint32_t baud = 65536 - ((uint64_t)(65536 * 16) * self->baudrate + get_peripheral_freq() / 2) / get_peripheral_freq();
+ uart->USART.BAUD.bit.BAUD = baud; // Set Baud
+
+ sercom_register_irq(self->id, &common_uart_irq_handler);
+
+ // Enable RXC interrupt
+ uart->USART.INTENSET.reg = SERCOM_USART_INTENSET_RXC;
+ #if defined(MCU_SAMD21)
+ NVIC_EnableIRQ(SERCOM0_IRQn + self->id);
+ #elif defined(MCU_SAMD51)
+ NVIC_EnableIRQ(SERCOM0_0_IRQn + 4 * self->id + 2);
+ #endif
+ #if MICROPY_HW_UART_TXBUF
+ // Enable DRE interrupt
+ // SAMD21 has just 1 IRQ for all USART events, so no need for an additional NVIC enable
+ #if defined(MCU_SAMD51)
+ NVIC_EnableIRQ(SERCOM0_0_IRQn + 4 * self->id + 0);
+ #endif
+ #endif
+
+ sercom_enable(uart, 1);
+ }
+
+ return MP_OBJ_FROM_PTR(self);
+}
+
+STATIC mp_obj_t machine_uart_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, MP_OBJ_FUN_ARGS_MAX, true);
+
+ // Get UART bus.
+ int uart_id = mp_obj_get_int(args[0]);
+ if (uart_id < 0 || uart_id > SERCOM_INST_NUM) {
+ mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("UART(%d) doesn't exist"), uart_id);
+ }
+
+ // Create the UART object and fill it with defaults.
+ machine_uart_obj_t *self = mp_obj_malloc(machine_uart_obj_t, &machine_uart_type);
+ self->id = uart_id;
+ self->baudrate = DEFAULT_UART_BAUDRATE;
+ self->bits = 8;
+ self->stop = 0;
+ self->timeout = 1;
+ self->timeout_char = 1;
+ self->tx = 0xff;
+ self->rx = 0xff;
+ self->new = true;
+ MP_STATE_PORT(sercom_table[uart_id]) = self;
+
+ mp_map_t kw_args;
+ mp_map_init_fixed_table(&kw_args, n_kw, args + n_args);
+ return machine_uart_init_helper(self, n_args - 1, args + 1, &kw_args);
+}
+
+// uart.init(baud, [kwargs])
+STATIC mp_obj_t machine_uart_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
+ return machine_uart_init_helper(args[0], n_args - 1, args + 1, kw_args);
+}
+MP_DEFINE_CONST_FUN_OBJ_KW(machine_uart_init_obj, 1, machine_uart_init);
+
+STATIC mp_obj_t machine_uart_deinit(mp_obj_t self_in) {
+ machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ // Check if it is the active object.
+ if (MP_STATE_PORT(sercom_table)[self->id] == self) {
+ Sercom *uart = sercom_instance[self->id];
+ // Disable interrupts and de-register the IRQ
+ if (uart) {
+ uart->USART.INTENCLR.reg = 0xff;
+ sercom_register_irq(self->id, NULL);
+ sercom_enable(uart, 0);
+ }
+ }
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_uart_deinit_obj, machine_uart_deinit);
+
+STATIC mp_obj_t machine_uart_any(mp_obj_t self_in) {
+ machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ return MP_OBJ_NEW_SMALL_INT(ringbuf_avail(&self->read_buffer));
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_uart_any_obj, machine_uart_any);
+
+STATIC mp_obj_t machine_uart_sendbreak(mp_obj_t self_in) {
+ machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ uint32_t break_time_us = 13 * 1000000 / self->baudrate;
+
+ // Wait for the tx buffer to drain.
+ #if MICROPY_HW_UART_TXBUF
+ while (ringbuf_avail(&self->write_buffer) > 0) {
+ MICROPY_EVENT_POLL_HOOK
+ }
+ #endif
+ // Wait for the TX queue & register to clear
+ // Since the flags are not safe, just wait sufficiently long.
+ mp_hal_delay_us(2 * break_time_us);
+ // Disable MUX
+ PORT->Group[self->tx / 32].PINCFG[self->tx % 32].bit.PMUXEN = 0;
+ // Set TX pin to low for break time
+ mp_hal_pin_low(self->tx);
+ mp_hal_delay_us(break_time_us);
+ mp_hal_pin_high(self->tx);
+ // Enable Mux again
+ mp_hal_set_pin_mux(self->tx, self->tx_pad_config.alt_fct);
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_uart_sendbreak_obj, machine_uart_sendbreak);
+
+STATIC mp_obj_t machine_uart_txdone(mp_obj_t self_in) {
+ machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ Sercom *uart = sercom_instance[self->id];
+
+ if (uart->USART.INTFLAG.bit.DRE
+ #if MICROPY_HW_UART_TXBUF
+ && ringbuf_avail(&self->write_buffer) == 0
+ #endif
+ && uart->USART.INTFLAG.bit.TXC) {
+ return mp_const_true;
+ } else {
+ return mp_const_false;
+ }
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_uart_txdone_obj, machine_uart_txdone);
+
+STATIC const mp_rom_map_elem_t machine_uart_locals_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_uart_init_obj) },
+ { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_uart_deinit_obj) },
+
+ { MP_ROM_QSTR(MP_QSTR_any), MP_ROM_PTR(&machine_uart_any_obj) },
+ { MP_ROM_QSTR(MP_QSTR_sendbreak), MP_ROM_PTR(&machine_uart_sendbreak_obj) },
+ { MP_ROM_QSTR(MP_QSTR_txdone), MP_ROM_PTR(&machine_uart_txdone_obj) },
+
+ { MP_ROM_QSTR(MP_QSTR_flush), MP_ROM_PTR(&mp_stream_flush_obj) },
+ { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) },
+ { MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) },
+ { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) },
+ { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) },
+};
+STATIC MP_DEFINE_CONST_DICT(machine_uart_locals_dict, machine_uart_locals_dict_table);
+
+STATIC mp_uint_t machine_uart_read(mp_obj_t self_in, void *buf_in, mp_uint_t size, int *errcode) {
+ machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ uint64_t t = mp_hal_ticks_ms_64() + self->timeout;
+ uint64_t timeout_char = self->timeout_char;
+ uint8_t *dest = buf_in;
+
+ for (size_t i = 0; i < size; i++) {
+ // Wait for the first/next character
+ while (ringbuf_avail(&self->read_buffer) == 0) {
+ if (mp_hal_ticks_ms_64() > t) { // timed out
+ if (i <= 0) {
+ *errcode = MP_EAGAIN;
+ return MP_STREAM_ERROR;
+ } else {
+ return i;
+ }
+ }
+ MICROPY_EVENT_POLL_HOOK
+ }
+ *dest++ = ringbuf_get(&(self->read_buffer));
+ t = mp_hal_ticks_ms_64() + timeout_char;
+ }
+ return size;
+}
+
+STATIC mp_uint_t machine_uart_write(mp_obj_t self_in, const void *buf_in, mp_uint_t size, int *errcode) {
+ machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ size_t i = 0;
+ const uint8_t *src = buf_in;
+ Sercom *uart = sercom_instance[self->id];
+
+ #if MICROPY_HW_UART_TXBUF
+ uint64_t t = mp_hal_ticks_ms_64() + self->timeout;
+
+ while (i < size) {
+ // Wait for the first/next character to be sent.
+ while (ringbuf_free(&(self->write_buffer)) == 0) {
+ if (mp_hal_ticks_ms_64() > t) { // timed out
+ if (i <= 0) {
+ *errcode = MP_EAGAIN;
+ return MP_STREAM_ERROR;
+ } else {
+ return i;
+ }
+ }
+ MICROPY_EVENT_POLL_HOOK
+ }
+ ringbuf_put(&(self->write_buffer), *src++);
+ i++;
+ uart->USART.INTENSET.reg = SERCOM_USART_INTENSET_DRE; // kick off the IRQ
+ }
+
+ #else
+
+ while (i < size) {
+ while (!(uart->USART.INTFLAG.bit.DRE)) {
+ }
+ uart->USART.DATA.bit.DATA = *src++;
+ i++;
+ }
+ #endif
+ return size;
+}
+
+STATIC mp_uint_t machine_uart_ioctl(mp_obj_t self_in, mp_uint_t request, mp_uint_t arg, int *errcode) {
+ machine_uart_obj_t *self = self_in;
+ mp_uint_t ret;
+ Sercom *uart = sercom_instance[self->id];
+ if (request == MP_STREAM_POLL) {
+ uintptr_t flags = arg;
+ ret = 0;
+ if ((flags & MP_STREAM_POLL_RD) && (uart->USART.INTFLAG.bit.RXC != 0 || ringbuf_avail(&self->read_buffer) > 0)) {
+ ret |= MP_STREAM_POLL_RD;
+ }
+ if ((flags & MP_STREAM_POLL_WR) && (uart->USART.INTFLAG.bit.DRE != 0
+ #if MICROPY_HW_UART_TXBUF
+ || ringbuf_avail(&self->write_buffer) > 0
+ #endif
+ )) {
+ ret |= MP_STREAM_POLL_WR;
+ }
+ } else if (request == MP_STREAM_FLUSH) {
+ // The timeout is defined by the buffer size and the baudrate.
+ // Take the worst case assumtions at 13 bit symbol size times 2.
+ uint64_t timeout = mp_hal_ticks_ms_64() + (3
+ #if MICROPY_HW_UART_TXBUF
+ + self->write_buffer.size
+ #endif
+ ) * 13000 * 2 / self->baudrate;
+ do {
+ if (machine_uart_txdone((mp_obj_t)self) == mp_const_true) {
+ return 0;
+ }
+ MICROPY_EVENT_POLL_HOOK
+ } while (mp_hal_ticks_ms_64() < timeout);
+ *errcode = MP_ETIMEDOUT;
+ ret = MP_STREAM_ERROR;
+ } else {
+ *errcode = MP_EINVAL;
+ ret = MP_STREAM_ERROR;
+ }
+ return ret;
+}
+
+STATIC const mp_stream_p_t uart_stream_p = {
+ .read = machine_uart_read,
+ .write = machine_uart_write,
+ .ioctl = machine_uart_ioctl,
+ .is_text = false,
+};
+
+MP_DEFINE_CONST_OBJ_TYPE(
+ machine_uart_type,
+ MP_QSTR_UART,
+ MP_TYPE_FLAG_ITER_IS_STREAM,
+ make_new, machine_uart_make_new,
+ print, machine_uart_print,
+ protocol, &uart_stream_p,
+ locals_dict, &machine_uart_locals_dict
+ );
diff --git a/ports/samd/machine_wdt.c b/ports/samd/machine_wdt.c
new file mode 100644
index 000000000000..c0fbfdbfbc7d
--- /dev/null
+++ b/ports/samd/machine_wdt.c
@@ -0,0 +1,141 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2020-2021 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 "modmachine.h"
+
+#include "sam.h"
+
+#define MIN_TIMEOUT 512
+#define MAX_TIMEOUT 16384
+
+typedef struct _machine_wdt_obj_t {
+ mp_obj_base_t base;
+} machine_wdt_obj_t;
+
+extern mp_int_t log2i(mp_int_t num);
+
+STATIC const machine_wdt_obj_t machine_wdt = {{&machine_wdt_type}};
+
+STATIC void set_timeout(uint32_t timeout) {
+ // Set new timeout. Have to disable WDT first.
+
+ // Confine to the valid range
+ if (timeout < MIN_TIMEOUT) {
+ timeout = MIN_TIMEOUT;
+ } else if (timeout > MAX_TIMEOUT) {
+ timeout = MAX_TIMEOUT;
+ }
+
+ #if defined(MCU_SAMD21)
+ WDT->CTRL.reg = 0;
+ while (WDT->STATUS.reg & WDT_STATUS_SYNCBUSY) {
+ }
+ WDT->CONFIG.reg = log2i(timeout) - 3;
+ WDT->CTRL.reg = WDT_CTRL_ENABLE;
+ while (WDT->STATUS.reg & WDT_STATUS_SYNCBUSY) {
+ }
+ #elif defined(MCU_SAMD51)
+ WDT->CTRLA.reg = 0;
+ while (WDT->SYNCBUSY.reg & WDT_SYNCBUSY_ENABLE) {
+ }
+ WDT->CONFIG.reg = log2i(timeout) - 3;
+ WDT->CTRLA.reg = WDT_CTRLA_ENABLE;
+ while (WDT->SYNCBUSY.reg & WDT_SYNCBUSY_ENABLE) {
+ }
+ #endif
+}
+
+STATIC mp_obj_t machine_wdt_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
+ enum { ARG_id, ARG_timeout, ARG_lock };
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_id, MP_ARG_INT, {.u_int = 0} },
+ { MP_QSTR_timeout, MP_ARG_INT, {.u_int = 5000} },
+ };
+
+ // Parse the arguments.
+ mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
+ mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
+
+ #if defined(MCU_SAMD51)
+ // Verify the WDT id. SAMD51 only, saving a few bytes for SAMD21
+ mp_int_t id = args[ARG_id].u_int;
+ if (id != 0) {
+ mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("WDT(%d) doesn't exist"), id);
+ }
+ #endif
+
+ // Start the watchdog (timeout is in milliseconds).
+ uint32_t timeout = args[ARG_timeout].u_int;
+ // Configure the WDT
+ #if defined(MCU_SAMD21)
+
+ // Enable APBx clocks and GCLK clock
+ PM->APBAMASK.reg |= PM_APBAMASK_WDT;
+ GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK8 | GCLK_CLKCTRL_ID_WDT;
+
+ #elif defined(MCU_SAMD51)
+
+ // Enable APBx clocks and 1kHz clock
+ MCLK->APBAMASK.reg |= MCLK_APBAMASK_WDT;
+ OSC32KCTRL->OSCULP32K.bit.EN1K = 1;
+
+ #endif
+
+ set_timeout(timeout);
+
+ return MP_OBJ_FROM_PTR(&machine_wdt);
+}
+
+STATIC mp_obj_t machine_wdt_feed(mp_obj_t self_in) {
+ (void)self_in;
+ WDT->CLEAR.reg = 0xa5;
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_wdt_feed_obj, machine_wdt_feed);
+
+STATIC mp_obj_t machine_wdt_timeout_ms(mp_obj_t self_in, mp_obj_t timout_in) {
+ uint32_t timeout = mp_obj_get_int(timout_in);
+
+ set_timeout(timeout);
+
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(machine_wdt_timeout_ms_obj, machine_wdt_timeout_ms);
+
+STATIC const mp_rom_map_elem_t machine_wdt_locals_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_feed), MP_ROM_PTR(&machine_wdt_feed_obj) },
+ { MP_ROM_QSTR(MP_QSTR_timeout_ms), MP_ROM_PTR(&machine_wdt_timeout_ms_obj) },
+};
+STATIC MP_DEFINE_CONST_DICT(machine_wdt_locals_dict, machine_wdt_locals_dict_table);
+
+MP_DEFINE_CONST_OBJ_TYPE(
+ machine_wdt_type,
+ MP_QSTR_WDT,
+ MP_TYPE_FLAG_NONE,
+ make_new, machine_wdt_make_new,
+ locals_dict, &machine_wdt_locals_dict
+ );
diff --git a/ports/samd/main.c b/ports/samd/main.c
index d8c1c596c5b0..bc0e45ee64db 100644
--- a/ports/samd/main.c
+++ b/ports/samd/main.c
@@ -29,10 +29,16 @@
#include "py/gc.h"
#include "py/mperrno.h"
#include "py/stackctrl.h"
+#include "shared/readline/readline.h"
#include "shared/runtime/gchelper.h"
#include "shared/runtime/pyexec.h"
+#include "shared/runtime/softtimer.h"
extern uint8_t _sstack, _estack, _sheap, _eheap;
+extern void adc_deinit_all(void);
+extern void pin_irq_deinit_all(void);
+extern void pwm_deinit_all(void);
+extern void sercom_deinit_all(void);
void samd_main(void) {
mp_stack_set_top(&_estack);
@@ -42,12 +48,24 @@ void samd_main(void) {
gc_init(&_sheap, &_eheap);
mp_init();
+ // Initialise sub-systems.
+ readline_init0();
+
// Execute _boot.py to set up the filesystem.
- pyexec_frozen_module("_boot.py");
+ pyexec_frozen_module("_boot.py", false);
// Execute user scripts.
- pyexec_file_if_exists("boot.py");
- pyexec_file_if_exists("main.py");
+ int ret = pyexec_file_if_exists("boot.py");
+ if (ret & PYEXEC_FORCED_EXIT) {
+ goto soft_reset_exit;
+ }
+ // Do not execute main.py if boot.py failed
+ if (pyexec_mode_kind == PYEXEC_MODE_FRIENDLY_REPL && ret != 0) {
+ ret = pyexec_file_if_exists("main.py");
+ if (ret & PYEXEC_FORCED_EXIT) {
+ goto soft_reset_exit;
+ }
+ }
for (;;) {
if (pyexec_mode_kind == PYEXEC_MODE_RAW_REPL) {
@@ -61,7 +79,13 @@ void samd_main(void) {
}
}
+ soft_reset_exit:
mp_printf(MP_PYTHON_PRINTER, "MPY: soft reboot\n");
+ adc_deinit_all();
+ pin_irq_deinit_all();
+ pwm_deinit_all();
+ sercom_deinit_all();
+ soft_timer_deinit();
gc_sweep_all();
mp_deinit();
}
diff --git a/ports/samd/mcu/samd21/clock_config.c b/ports/samd/mcu/samd21/clock_config.c
new file mode 100644
index 000000000000..d3c8c719953d
--- /dev/null
+++ b/ports/samd/mcu/samd21/clock_config.c
@@ -0,0 +1,309 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * This file provides functions for configuring the clocks.
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2022 Robert Hammelrath
+ *
+ * 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/runtime.h"
+#include "py/mphal.h"
+#include "samd_soc.h"
+
+static uint32_t cpu_freq = CPU_FREQ;
+static uint32_t peripheral_freq = DFLL48M_FREQ;
+static uint32_t dfll48m_calibration;
+
+int sercom_gclk_id[] = {
+ GCLK_CLKCTRL_ID_SERCOM0_CORE, GCLK_CLKCTRL_ID_SERCOM1_CORE,
+ GCLK_CLKCTRL_ID_SERCOM2_CORE, GCLK_CLKCTRL_ID_SERCOM3_CORE,
+ GCLK_CLKCTRL_ID_SERCOM4_CORE, GCLK_CLKCTRL_ID_SERCOM5_CORE
+};
+
+uint32_t get_cpu_freq(void) {
+ return cpu_freq;
+}
+
+uint32_t get_peripheral_freq(void) {
+ return peripheral_freq;
+}
+
+void set_cpu_freq(uint32_t cpu_freq_arg) {
+
+ // Set 1 waitstate to be safe
+ NVMCTRL->CTRLB.reg = NVMCTRL_CTRLB_MANW | NVMCTRL_CTRLB_RWS(1);
+
+ int div = MAX(DFLL48M_FREQ / cpu_freq_arg, 1);
+ peripheral_freq = DFLL48M_FREQ / div;
+
+ // Enable GCLK output: 48MHz from DFLL48M on both CCLK0 and GCLK2
+ GCLK->GENDIV.reg = GCLK_GENDIV_ID(0) | GCLK_GENDIV_DIV(div);
+ GCLK->GENCTRL.reg = GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_DFLL48M | GCLK_GENCTRL_ID(0);
+ while (GCLK->STATUS.bit.SYNCBUSY) {
+ }
+ GCLK->GENDIV.reg = GCLK_GENDIV_ID(2) | GCLK_GENDIV_DIV(div);
+ GCLK->GENCTRL.reg = GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_DFLL48M | GCLK_GENCTRL_ID(2);
+ while (GCLK->STATUS.bit.SYNCBUSY) {
+ }
+ // The comparison is >=, such that for 48MHz still the FDPLL96 is used for the CPU clock.
+ if (cpu_freq_arg >= 48000000) {
+ cpu_freq = cpu_freq_arg;
+ // Connect GCLK1 to the FDPLL96 input.
+ GCLK->CLKCTRL.reg = GCLK_CLKCTRL_GEN_GCLK1 | GCLK_CLKCTRL_ID_FDPLL | GCLK_CLKCTRL_CLKEN;
+ while (GCLK->STATUS.bit.SYNCBUSY) {
+ }
+ // configure the FDPLL96
+ // CtrlB: Set the ref ource to GCLK, set the Wakup-Fast Flag.
+ SYSCTRL->DPLLCTRLB.reg = SYSCTRL_DPLLCTRLB_REFCLK_GCLK | SYSCTRL_DPLLCTRLB_WUF;
+ // Set the FDPLL ratio and enable the DPLL.
+ int ldr = cpu_freq / FDPLL_REF_FREQ;
+ int frac = ((cpu_freq - ldr * FDPLL_REF_FREQ) / (FDPLL_REF_FREQ / 16)) & 0x0f;
+ SYSCTRL->DPLLRATIO.reg = SYSCTRL_DPLLRATIO_LDR((frac << 16 | ldr) - 1);
+ SYSCTRL->DPLLCTRLA.reg = SYSCTRL_DPLLCTRLA_ENABLE;
+ // Wait for the DPLL lock.
+ while (!SYSCTRL->DPLLSTATUS.bit.LOCK) {
+ }
+ // Finally switch GCLK0 to FDPLL96M.
+ GCLK->GENCTRL.reg = GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_DPLL96M | GCLK_GENCTRL_ID(0);
+ while (GCLK->STATUS.bit.SYNCBUSY) {
+ }
+ } else {
+ cpu_freq = peripheral_freq;
+ // Disable the FDPLL96M in case it was enabled.
+ SYSCTRL->DPLLCTRLA.reg = 0;
+ }
+ if (cpu_freq >= 8000000) {
+ // Enable GCLK output: 48MHz on GCLK5 for USB
+ GCLK->GENDIV.reg = GCLK_GENDIV_ID(5) | GCLK_GENDIV_DIV(1);
+ GCLK->GENCTRL.reg = GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_DFLL48M | GCLK_GENCTRL_ID(5);
+ while (GCLK->STATUS.bit.SYNCBUSY) {
+ }
+ } else {
+ // Disable GCLK output on GCLK5 for USB, since USB is not reliable below 8 Mhz.
+ GCLK->GENCTRL.reg = GCLK_GENCTRL_ID(5);
+ while (GCLK->STATUS.bit.SYNCBUSY) {
+ }
+ }
+ // Set 0 waitstates for slower CPU clock
+ NVMCTRL->CTRLB.reg = NVMCTRL_CTRLB_MANW | NVMCTRL_CTRLB_RWS(cpu_freq > 24000000 ? 1 : 0);
+ SysTick_Config(cpu_freq / 1000);
+}
+
+void check_usb_recovery_mode(void) {
+ #if !MICROPY_HW_XOSC32K
+ mp_hal_delay_ms(500);
+ // Check USB status. If not connected, switch DFLL48M back to open loop
+ if (USB->DEVICE.DeviceEndpoint[0].EPCFG.reg == 0) {
+ // Set/keep the open loop mode of the device.
+ SYSCTRL->DFLLVAL.reg = dfll48m_calibration;
+ SYSCTRL->DFLLCTRL.reg = SYSCTRL_DFLLCTRL_CCDIS | SYSCTRL_DFLLCTRL_ENABLE;
+ }
+ #endif // MICROPY_HW_XOSC32K
+}
+
+// Purpose of the #defines for the clock configuration.
+//
+// Both CPU and periperal devices are clocked by the DFLL48M clock.
+// DFLL48M is either free running, or controlled by the 32kHz crystal, or
+// Synchronized with the USB clock.
+//
+// #define MICROPY_HW_XOSC32K (0 | 1)
+//
+// If MICROPY_HW_XOSC32K = 1, the 32kHz crystal is used as input for GCLK 1, which
+// serves as refernce clock source for the DFLL48M oscillator,
+// The crystal is used, unless MICROPY_HW_MCU_OSC32KULP is set.
+// In that case GCLK1 (and the CPU clock) is driven by the 32K Low power oscillator.
+// The reason for offering this option is a design flaw of the Adafruit
+// Feather boards, where the RGB Led and Debug signals interfere with the
+// crystal, causing the CPU to fail if it is driven by the crystal.
+//
+// If MICROPY_HW_XOSC32K = 0, the 32kHz signal for GCLK1 (and the CPU) is
+// created by dividing the 48MHz clock of DFLL48M, but not used otherwise.
+//
+// If MICROPY_HW_DFLL_USB_SYNC = 0, the DFLL48M oscillator is free running using
+// the pre-configured trim values. In that mode, the peripheral clock is
+// not exactly 48Mhz and has a substantional temperature drift.
+//
+// If MICROPY_HW_DFLL_USB_SYNC = 1, the DFLL48 is synchronized with the 1 kHz USB sync
+// signal. If after boot there is no USB sync withing 500ms, the configuratuion falls
+// back to a free running 48Mhz oscillator.
+//
+// In all modes, the 48MHz signal has a substantial jitter, largest when
+// MICROPY_HW_DFLL_USB_SYNC is active. That is caused by the repective
+// reference frequencies of 32kHz or 1 kHz being low. That affects most
+// PWM. Std Dev at 1kHz 0.156Hz (w. Crystal) up to 0.4 Hz (with USB sync).
+//
+// If none of the mentioned defines is set, the device uses the internal oscillators.
+
+void init_clocks(uint32_t cpu_freq) {
+
+ dfll48m_calibration = 0; // please the compiler
+
+ // SAMD21 Clock settings
+ //
+ // GCLK0: 48MHz, source: DFLL48M or FDPLL96M, usage: CPU
+ // GCLK1: 32kHz, source: XOSC32K or OSCULP32K, usage: FDPLL96M reference
+ // GCLK2: 1-48MHz, source: DFLL48M, usage: Peripherals
+ // GCLK3: 2Mhz, source: DFLL48M, usage: us-counter (TC4/TC5)
+ // GCLK4: 32kHz, source: XOSC32K, if crystal present, usage: DFLL48M reference
+ // GCLK5: 48MHz, source: DFLL48M, usage: USB
+ // GCLK8: 1kHz, source: XOSC32K or OSCULP32K, usage: WDT and RTC
+ // DFLL48M: Reference sources:
+ // - in closed loop mode: eiter XOSC32K or OSCULP32K or USB clock
+ // from GCLK4.
+ // - in open loop mode: None
+ // FDPLL96M: Reference source GCLK1
+ // Used for the CPU clock for freq >= 48Mhz
+
+ NVMCTRL->CTRLB.bit.MANW = 1; // errata "Spurious Writes"
+ NVMCTRL->CTRLB.bit.RWS = 1; // 1 read wait state for 48MHz
+
+ #if MICROPY_HW_XOSC32K
+ // Set up OSC32K according datasheet 17.6.3
+ SYSCTRL->XOSC32K.reg = SYSCTRL_XOSC32K_STARTUP(0x3) | SYSCTRL_XOSC32K_EN32K |
+ SYSCTRL_XOSC32K_XTALEN;
+ SYSCTRL->XOSC32K.bit.ENABLE = 1;
+ while (SYSCTRL->PCLKSR.bit.XOSC32KRDY == 0) {
+ }
+ // Set up the DFLL48 according to the data sheet 17.6.7.1.2
+ // Step 1: Set up the reference clock
+
+ #if MICROPY_HW_MCU_OSC32KULP
+ // Connect the GCLK1 to the XOSC32KULP
+ GCLK->GENDIV.reg = GCLK_GENDIV_ID(1) | GCLK_GENDIV_DIV(1);
+ GCLK->GENCTRL.reg = GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_OSCULP32K | GCLK_GENCTRL_ID(1);
+ #else
+ // Connect the GCLK1 to OSC32K
+ GCLK->GENDIV.reg = GCLK_GENDIV_ID(1) | GCLK_GENDIV_DIV(1);
+ GCLK->GENCTRL.reg = GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_XOSC32K | GCLK_GENCTRL_ID(1);
+ #endif
+
+ while (GCLK->STATUS.bit.SYNCBUSY) {
+ }
+
+ // Connect the GCLK4 to OSC32K
+ GCLK->GENDIV.reg = GCLK_GENDIV_ID(4) | GCLK_GENDIV_DIV(1);
+ GCLK->GENCTRL.reg = GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_XOSC32K | GCLK_GENCTRL_ID(4);
+ // Connect GCLK4 to the DFLL input.
+ GCLK->CLKCTRL.reg = GCLK_CLKCTRL_GEN_GCLK4 | GCLK_CLKCTRL_ID_DFLL48 | GCLK_CLKCTRL_CLKEN;
+ while (GCLK->STATUS.bit.SYNCBUSY) {
+ }
+
+ // Enable access to the DFLLCTRL reg acc. to Errata 1.2.1
+ SYSCTRL->DFLLCTRL.reg = SYSCTRL_DFLLCTRL_ENABLE;
+ while (SYSCTRL->PCLKSR.bit.DFLLRDY == 0) {
+ }
+ // Step 2: Set the coarse and fine values.
+ // Get the coarse value from the calib data. In case it is not set,
+ // set a midrange value.
+ uint32_t coarse = (*((uint32_t *)FUSES_DFLL48M_COARSE_CAL_ADDR) & FUSES_DFLL48M_COARSE_CAL_Msk)
+ >> FUSES_DFLL48M_COARSE_CAL_Pos;
+ if (coarse == 0x3f) {
+ coarse = 0x1f;
+ }
+ SYSCTRL->DFLLVAL.reg = SYSCTRL_DFLLVAL_COARSE(coarse) | SYSCTRL_DFLLVAL_FINE(512);
+ while (SYSCTRL->PCLKSR.bit.DFLLRDY == 0) {
+ }
+ // Step 3: Set the multiplication values. The offset of 16384 to the freq is for rounding.
+ SYSCTRL->DFLLMUL.reg = SYSCTRL_DFLLMUL_MUL((CPU_FREQ + 16384) / 32768) |
+ SYSCTRL_DFLLMUL_FSTEP(1) | SYSCTRL_DFLLMUL_CSTEP(1);
+ while (SYSCTRL->PCLKSR.bit.DFLLRDY == 0) {
+ }
+ // Step 4: Start the DFLL and wait for the PLL lock. We just wait for the fine lock, since
+ // coarse adjusting is bypassed.
+ SYSCTRL->DFLLCTRL.reg |= SYSCTRL_DFLLCTRL_MODE | SYSCTRL_DFLLCTRL_WAITLOCK | SYSCTRL_DFLLCTRL_STABLE |
+ SYSCTRL_DFLLCTRL_BPLCKC | SYSCTRL_DFLLCTRL_ENABLE;
+ while (SYSCTRL->PCLKSR.bit.DFLLLCKF == 0) {
+ }
+ // Set GCLK8 to 1 kHz.
+ GCLK->GENDIV.reg = GCLK_GENDIV_ID(8) | GCLK_GENDIV_DIV(32);
+ GCLK->GENCTRL.reg = GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_XOSC32K | GCLK_GENCTRL_ID(8);
+ while (GCLK->STATUS.bit.SYNCBUSY) {
+ }
+
+ #else // MICROPY_HW_XOSC32K
+
+ // Enable DFLL48M
+ SYSCTRL->DFLLCTRL.reg = SYSCTRL_DFLLCTRL_ENABLE;
+ while (!SYSCTRL->PCLKSR.bit.DFLLRDY) {
+ }
+
+ uint32_t coarse = (*((uint32_t *)FUSES_DFLL48M_COARSE_CAL_ADDR) & FUSES_DFLL48M_COARSE_CAL_Msk)
+ >> FUSES_DFLL48M_COARSE_CAL_Pos;
+ if (coarse == 0x3f) {
+ coarse = 0x1f;
+ }
+ SYSCTRL->DFLLVAL.reg = SYSCTRL_DFLLVAL_COARSE(coarse) | SYSCTRL_DFLLVAL_FINE(511);
+
+ #if MICROPY_HW_DFLL_USB_SYNC
+ // Configure the DFLL48M for USB clock recovery.
+ // Will have to switch back if no USB
+ SYSCTRL->DFLLSYNC.bit.READREQ = 1;
+ dfll48m_calibration = SYSCTRL->DFLLVAL.reg;
+ // Set the Multiplication factor.
+ SYSCTRL->DFLLMUL.reg = SYSCTRL_DFLLMUL_CSTEP(1) | SYSCTRL_DFLLMUL_FSTEP(1)
+ | SYSCTRL_DFLLMUL_MUL(48000);
+ // Set the mode to closed loop USB Recovery mode
+ SYSCTRL->DFLLCTRL.reg = SYSCTRL_DFLLCTRL_USBCRM | SYSCTRL_DFLLCTRL_CCDIS
+ | SYSCTRL_DFLLCTRL_MODE | SYSCTRL_DFLLCTRL_ENABLE;
+ #else
+ // Set/keep the open loop mode of the device.
+ SYSCTRL->DFLLCTRL.reg = SYSCTRL_DFLLCTRL_CCDIS | SYSCTRL_DFLLCTRL_ENABLE;
+ #endif
+
+ while (!SYSCTRL->PCLKSR.bit.DFLLRDY) {
+ }
+
+ // Connect the GCLK1 to the XOSC32KULP
+ GCLK->GENDIV.reg = GCLK_GENDIV_ID(1) | GCLK_GENDIV_DIV(1);
+ GCLK->GENCTRL.reg = GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_OSCULP32K | GCLK_GENCTRL_ID(1);
+ while (GCLK->STATUS.bit.SYNCBUSY) {
+ }
+ // Set GCLK8 to 1 kHz.
+ GCLK->GENDIV.reg = GCLK_GENDIV_ID(8) | GCLK_GENDIV_DIV(32);
+ GCLK->GENCTRL.reg = GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_OSCULP32K | GCLK_GENCTRL_ID(8);
+ while (GCLK->STATUS.bit.SYNCBUSY) {
+ }
+
+ #endif // MICROPY_HW_XOSC32K
+
+ set_cpu_freq(cpu_freq);
+
+ // Enable GCLK output: 2MHz on GCLK3 for TC4
+ GCLK->GENDIV.reg = GCLK_GENDIV_ID(3) | GCLK_GENDIV_DIV(24);
+ GCLK->GENCTRL.reg = GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_DFLL48M | GCLK_GENCTRL_ID(3);
+ while (GCLK->STATUS.bit.SYNCBUSY) {
+ }
+}
+
+void enable_sercom_clock(int id) {
+ // Enable synchronous clock. The bits are nicely arranged
+ PM->APBCMASK.reg |= 0x04 << id;
+ // Select multiplexer generic clock source and enable.
+ GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK2 | sercom_gclk_id[id];
+ // Wait while it updates synchronously.
+ while (GCLK->STATUS.bit.SYNCBUSY) {
+ }
+}
diff --git a/ports/samd/mcu/samd21/mpconfigmcu.h b/ports/samd/mcu/samd21/mpconfigmcu.h
new file mode 100644
index 000000000000..0c5bfe5ae7d8
--- /dev/null
+++ b/ports/samd/mcu/samd21/mpconfigmcu.h
@@ -0,0 +1,54 @@
+// Deinitions common to all SAMD21 boards
+#include "samd21.h"
+
+#define MICROPY_CONFIG_ROM_LEVEL (MICROPY_CONFIG_ROM_LEVEL_CORE_FEATURES)
+
+// MicroPython emitters
+#define MICROPY_EMIT_THUMB (0)
+#define MICROPY_EMIT_INLINE_THUMB (0)
+#define MICROPY_MODULE_BUILTIN_INIT (1)
+
+#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_FLOAT)
+
+#ifndef MICROPY_PY_BUILTINS_COMPLEX
+#define MICROPY_PY_BUILTINS_COMPLEX (0)
+#endif
+
+#ifndef MICROPY_PY_MATH
+#define MICROPY_PY_MATH (1)
+#endif
+
+#ifndef MICROPY_PY_CMATH
+#define MICROPY_PY_CMATH (0)
+#endif
+
+#define MICROPY_PY_URANDOM_SEED_INIT_FUNC (trng_random_u32(300))
+unsigned long trng_random_u32(int delay);
+
+#define VFS_BLOCK_SIZE_BYTES (1536) // 24x 64B flash pages;
+
+#ifndef MICROPY_HW_UART_TXBUF
+#define MICROPY_HW_UART_TXBUF (1)
+#endif
+
+#define MICROPY_PY_UOS_URANDOM (1)
+
+#ifndef MICROPY_PY_MACHINE_PIN_BOARD_CPU
+#define MICROPY_PY_MACHINE_PIN_BOARD_CPU (1)
+#endif
+
+#define CPU_FREQ (48000000)
+#define DFLL48M_FREQ (48000000)
+#define MAX_CPU_FREQ (54000000)
+#define FDPLL_REF_FREQ (32768)
+
+#define IRQ_PRI_PENDSV ((1 << __NVIC_PRIO_BITS) - 1)
+
+static inline uint32_t raise_irq_pri(uint32_t pri) {
+ (void)pri;
+ return 0;
+}
+
+static inline void restore_irq_pri(uint32_t basepri) {
+ (void)basepri;
+}
diff --git a/ports/samd/mcu/samd21/mpconfigmcu.mk b/ports/samd/mcu/samd21/mpconfigmcu.mk
new file mode 100644
index 000000000000..ddd3e8b41011
--- /dev/null
+++ b/ports/samd/mcu/samd21/mpconfigmcu.mk
@@ -0,0 +1,34 @@
+CFLAGS_MCU += -mtune=cortex-m0plus -mcpu=cortex-m0plus -msoft-float
+
+MPY_CROSS_MCU_ARCH = armv6m
+
+SRC_S += shared/runtime/gchelper_thumb1.s
+
+LIBM_SRC_C += $(addprefix lib/libm/,\
+ acoshf.c \
+ asinfacosf.c \
+ asinhf.c \
+ atan2f.c \
+ atanf.c \
+ atanhf.c \
+ ef_rem_pio2.c \
+ erf_lgamma.c \
+ fmodf.c \
+ kf_cos.c \
+ kf_rem_pio2.c \
+ kf_sin.c \
+ kf_tan.c \
+ log1pf.c \
+ math.c \
+ nearbyintf.c \
+ roundf.c \
+ sf_cos.c \
+ sf_erf.c \
+ sf_frexp.c \
+ sf_ldexp.c \
+ sf_modf.c \
+ sf_sin.c \
+ sf_tan.c \
+ wf_lgamma.c \
+ wf_tgamma.c \
+ )
diff --git a/ports/samd/mcu/samd21/pin-af-table.csv b/ports/samd/mcu/samd21/pin-af-table.csv
new file mode 100644
index 000000000000..6445d148b8fa
--- /dev/null
+++ b/ports/samd/mcu/samd21/pin-af-table.csv
@@ -0,0 +1,65 @@
+# The pin_cap_tables contain the information anbout pin mux set and pad
+# for some of the peripheral devices with many possible assignments.
+# The pin_cap_table is a subset from table 7-1 of the data sheet.
+# It contain the information about pin mux set and pad
+# The eic and adc columns contain the decimal numer for the respecitive
+# quantity, the columns for sercom, tc and tcc have in each cell
+# the device number in the upper nibble, and the pad number in the lower
+# nibble. If a signal is not available, the cell in the csv table is left empty.
+# The first column is the pin id, not the number of the board pin.
+# Rows not starting with pa, pb, pc or pd are ignored.
+# When editing the table with a spread sheet, take care to import the data as text.
+#
+# Pin,EIC,ADC,SERCOM1,SERCOM2,TC,TCC
+pa00,0,,,10,20,
+pa01,1,,,11,21,
+pa02,2,0,,,,
+pa03,3,1,,,,
+pb04,4,12,,,,
+pb05,5,13,,,,
+pb06,6,14,,,,
+pb07,7,15,,,,
+pb08,8,2,,40,40,
+pb09,9,3,,41,41,
+pa04,4,4,,00,00,
+pa05,5,5,,01,01,
+pa06,6,6,,02,10,
+pa07,7,7,,03,11,
+pa08,,16,00,20,00,12
+pa09,9,17,01,21,01,13
+pa10,10,18,02,22,10,02
+pa11,11,19,03,23,11,03
+pb10,10,,,42,50,04
+pb11,11,,,43,51,05
+pb12,12,,40,,40,06
+pb13,13,,41,,41,07
+pb14,14,,42,,50,
+pb15,15,,43,,51,
+pa12,12,,20,40,20,06
+pa13,13,,21,41,20,07
+pa14,14,,22,42,30,04
+pa15,15,,23,43,31,05
+pa16,0,,10,30,20,06
+pa17,1,,11,31,21,07
+pa18,2,,12,32,30,02
+pa19,3,,13,33,31,03
+pb16,9,,50,,60,04
+pb17,1,,51,,61,05
+pa20,4,,52,32,70,04
+pa21,5,,53,33,71,07
+pa22,6,,30,50,40,04
+pa23,7,,31,51,41,05
+pa24,12,,32,52,50,12
+pa25,13,,33,53,51,13
+pb22,6,,,52,70,
+pb23,7,,,53,71,
+pa27,15,,,,,
+pa28,8,,,,,
+pa30,10,,,12,10,
+pa31,11,,,13,11,
+pb30,14,,,50,00,12
+pb31,15,,,51,01,13
+pb00,0,8,,52,70,
+pb01,1,9,,53,71,
+pb02,2,10,,50,60,
+pb03,3,11,,51,61,
diff --git a/ports/samd/mcu/samd51/clock_config.c b/ports/samd/mcu/samd51/clock_config.c
new file mode 100644
index 000000000000..5cf543252ec6
--- /dev/null
+++ b/ports/samd/mcu/samd51/clock_config.c
@@ -0,0 +1,364 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * This file provides functions for configuring the clocks.
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2022 Robert Hammelrath
+ *
+ * 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/runtime.h"
+#include "py/mphal.h"
+#include "samd_soc.h"
+
+static uint32_t cpu_freq = CPU_FREQ;
+static uint32_t peripheral_freq = DFLL48M_FREQ;
+static uint32_t dfll48m_calibration;
+
+int sercom_gclk_id[] = {
+ SERCOM0_GCLK_ID_CORE, SERCOM1_GCLK_ID_CORE,
+ SERCOM2_GCLK_ID_CORE, SERCOM3_GCLK_ID_CORE,
+ SERCOM4_GCLK_ID_CORE, SERCOM5_GCLK_ID_CORE,
+ #if defined(SERCOM7_GCLK_ID_CORE)
+ SERCOM6_GCLK_ID_CORE, SERCOM7_GCLK_ID_CORE,
+ #endif
+};
+
+uint32_t get_cpu_freq(void) {
+ return cpu_freq;
+}
+
+uint32_t get_peripheral_freq(void) {
+ return peripheral_freq;
+}
+
+void set_cpu_freq(uint32_t cpu_freq_arg) {
+
+ // Setup GCLK0 for 48MHz as default state to keep the MCU running during config change.
+ GCLK->GENCTRL[0].reg = GCLK_GENCTRL_RUNSTDBY | GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_DFLL;
+ while (GCLK->SYNCBUSY.bit.GENCTRL0) {
+ }
+ // Setup DPLL0 for 120 MHz
+ // first: disable DPLL0 in case it is running
+ OSCCTRL->Dpll[0].DPLLCTRLA.bit.ENABLE = 0;
+ while (OSCCTRL->Dpll[0].DPLLSYNCBUSY.bit.ENABLE == 1) {
+ }
+ if (cpu_freq_arg > DFLL48M_FREQ) {
+
+ cpu_freq = cpu_freq_arg;
+ peripheral_freq = DFLL48M_FREQ;
+ // Now configure the registers
+ OSCCTRL->Dpll[0].DPLLCTRLB.reg = OSCCTRL_DPLLCTRLB_DIV(1) | OSCCTRL_DPLLCTRLB_LBYPASS |
+ OSCCTRL_DPLLCTRLB_REFCLK(0) | OSCCTRL_DPLLCTRLB_WUF | OSCCTRL_DPLLCTRLB_FILTER(0x01);
+
+ uint32_t div = cpu_freq / DPLLx_REF_FREQ;
+ uint32_t frac = (cpu_freq - div * DPLLx_REF_FREQ) / (DPLLx_REF_FREQ / 32);
+ OSCCTRL->Dpll[0].DPLLRATIO.reg = (frac << 16) + div - 1;
+ // enable it again
+ OSCCTRL->Dpll[0].DPLLCTRLA.reg = OSCCTRL_DPLLCTRLA_ENABLE | OSCCTRL_DPLLCTRLA_RUNSTDBY;
+
+ // Per errata 2.13.1
+ while (!(OSCCTRL->Dpll[0].DPLLSTATUS.bit.CLKRDY == 1)) {
+ }
+ // Setup GCLK0 for DPLL0 output (48 or 48-200MHz)
+ GCLK->GENCTRL[0].reg = GCLK_GENCTRL_RUNSTDBY | GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_DPLL0;
+ while (GCLK->SYNCBUSY.bit.GENCTRL0) {
+ }
+ // Set GCLK 2 back to 48 MHz
+ GCLK->GENCTRL[2].reg = GCLK_GENCTRL_DIV(1) | GCLK_GENCTRL_RUNSTDBY | GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_DFLL;
+ while (GCLK->SYNCBUSY.bit.GENCTRL2) {
+ }
+ } else {
+ int div = DFLL48M_FREQ / cpu_freq_arg;
+ // Setup GCLK1 for the low freq
+ GCLK->GENCTRL[2].reg = GCLK_GENCTRL_DIV(div) | GCLK_GENCTRL_RUNSTDBY | GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_DFLL;
+ while (GCLK->SYNCBUSY.bit.GENCTRL2) {
+ }
+ GCLK->GENCTRL[0].reg = GCLK_GENCTRL_DIV(div) | GCLK_GENCTRL_RUNSTDBY | GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_DFLL;
+ while (GCLK->SYNCBUSY.bit.GENCTRL0) {
+ }
+ peripheral_freq = DFLL48M_FREQ / div;
+ cpu_freq = DFLL48M_FREQ / div;
+ }
+ if (cpu_freq >= 8000000) {
+ // Setup GCLK5 for DFLL48M output (48 MHz)
+ GCLK->GENCTRL[5].reg = GCLK_GENCTRL_DIV(1) | GCLK_GENCTRL_RUNSTDBY | GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_DFLL;
+ while (GCLK->SYNCBUSY.bit.GENCTRL5) {
+ }
+ } else {
+ // Setup GCLK5 off if CPU Clk < 8 MHz
+ GCLK->GENCTRL[5].reg = 0;
+ while (GCLK->SYNCBUSY.bit.GENCTRL5) {
+ }
+ }
+ SysTick_Config(cpu_freq / 1000);
+}
+
+void check_usb_recovery_mode(void) {
+ #if !MICROPY_HW_XOSC32K
+ mp_hal_delay_ms(500);
+ // Check USB status. If not connected, switch DFLL48M back to open loop
+ if (USB->DEVICE.DeviceEndpoint[0].EPCFG.reg == 0) {
+ // as per Errata 2.8.3
+ OSCCTRL->DFLLMUL.reg = 0;
+ while (OSCCTRL->DFLLSYNC.bit.DFLLMUL == 1) {
+ }
+ // Set the mode to open loop mode
+ OSCCTRL->DFLLCTRLB.reg = 0;
+ while (OSCCTRL->DFLLSYNC.bit.DFLLCTRLB == 1) {
+ }
+ OSCCTRL->DFLLCTRLA.reg = OSCCTRL_DFLLCTRLA_RUNSTDBY | OSCCTRL_DFLLCTRLA_ENABLE;
+ while (OSCCTRL->DFLLSYNC.bit.ENABLE == 1) {
+ }
+ OSCCTRL->DFLLVAL.reg = dfll48m_calibration; // Reload DFLLVAL register
+ while (OSCCTRL->DFLLSYNC.bit.DFLLVAL == 1) {
+ }
+ // Set the mode to open loop mode
+ OSCCTRL->DFLLCTRLB.reg = 0;
+ while (OSCCTRL->DFLLSYNC.bit.DFLLCTRLB == 1) {
+ }
+ }
+ #endif // MICROPY_HW_XOSC32K
+}
+
+// Purpose of the #defines for the clock configuration.
+//
+// The CPU clock is generated by DPLL0, which takes 32768 Hz as reference frequency,
+// supplied through GCLK1.
+//
+// DFLL48M is used for the peripheral clock, e.g. for PWM, UART, SPI, I2C.
+// DFLL48M is either free running, or controlled by the 32kHz crystal, or
+// Synchronized with the USB clock.
+//
+// GCLK1 takes it's input either from the 32kHz crystal, the internal low power
+// RC oscillator or from DFLL48M.
+//
+// #define MICROPY_HW_XOSC32K (0 | 1)
+//
+// If MICROPY_HW_XOSC32K = 1, the 32kHz crystal is used for the DFLL48M oscillator
+// and for GCLK1, feeding the CPU, unless MICROPY_HW_MCU_OSC32KULP is set.
+// In that case GCLK1 (and the CPU clock) is driven by the 32K Low power oscillator.
+// The reason for offering this option is a design flaw of the Adafruit
+// Feather boards, where the RGB Led and Debug signals interfere with the
+// crystal, causing the CPU to fail if it is driven by the crystal. The
+// peripheral devices are affected as well, but continue it's operation.
+//
+// If MICROPY_HW_XOSC32K = 0, the 32kHz signal for GCLK1 (and the CPU) is
+// created by dividing the 48MHz clock of DFLL48M.
+//
+// If MICROPY_HW_DFLL_USB_SYNC = 0, the DFLL48M oscillator is free running using
+// the pre-configured trim values. In that mode, the peripheral clock is
+// not exactly 48Mhz and has a substantional temperature drift.
+//
+// If MICROPY_HW_DFLL_USB_SYNC = 1, the DFLL48 is synchronized with the 1 kHz USB sync
+// signal. If after boot there is no USB sync withing 500ms, the configuratuion falls
+// back to a free running 48Mhz oscillator.
+//
+// In all modes, the 48MHz signal has a substantial jitter, largest when
+// MICROPY_HW_DFLL_USB_SYNC is active. That is caused by the repective
+// reference frequencies of 32kHz or 1 kHz being low. That affects most
+// PWM. Std Dev at 1kHz 0.156Hz (w. Crystal) up to 0.4 Hz (with USB sync).
+//
+// If none of the mentioned defines is set, the device uses the internal oscillators.
+
+void init_clocks(uint32_t cpu_freq) {
+
+ dfll48m_calibration = 0; // please the compiler
+
+ // SAMD51 clock settings
+ //
+ // GCLK0: 48MHz, source: 48 - 200 MHz from DPLL0, usage: CPU
+ // GCLK1: 32kHz, source: OSCULP32K or DFLL48M, usage: ref_clk DPLL0
+ // GCLK2: 1-48MHz, source:DFLL48M, usage: Peripheral devices
+ // GCLK3: 16Mhz, source: DLLL48M, usage: us-counter (TC0/TC1)
+ // GCLK4: 32kHz, source: XOSC32K, if crystal present, usage: DFLL48M reference
+ // GCLK5: 48MHz, source: DFLL48M, usage: USB
+ // DFLL48M: Reference sources:
+ // - in closed loop mode: eiter XOSC32K or OSCULP32K or USB clock
+ // - in open loop mode: None
+ // DPLL0: 48 - 200 MHz
+
+ // Steps to set up clocks:
+ // Reset Clocks
+ // Switch GCLK0 to DFLL 48MHz
+ // Setup 32768 Hz source and DFLL48M in closed loop mode, if a crystal is present.
+ // Setup GCLK1 to the DPLL0 Reference freq. of 32768 Hz
+ // Setup GCLK1 to drive peripheral channel 1
+ // Setup DPLL0 to 120MHz
+ // Setup GCLK0 to 120MHz
+ // Setup GCLK2 to 48MHz for Peripherals
+ // Setup GCLK3 to 16MHz for TC0/TC1
+ // Setup GCLK4 to 32kHz crystal, if present
+ // Setup GCLK5 to 48 MHz
+
+ // Setup GCLK0 for 48MHz as default state to keep the MCU running during config change.
+ GCLK->GENCTRL[0].reg = GCLK_GENCTRL_RUNSTDBY | GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_DFLL;
+ while (GCLK->SYNCBUSY.bit.GENCTRL0) {
+ }
+
+ #if MICROPY_HW_XOSC32K
+ // OSCILLATOR CONTROL
+ // Enable the clock for RTC
+ OSC32KCTRL->RTCCTRL.reg = OSC32KCTRL_RTCCTRL_RTCSEL_XOSC1K;
+ // Setup XOSC32K
+ OSC32KCTRL->INTFLAG.reg = OSC32KCTRL_INTFLAG_XOSC32KRDY | OSC32KCTRL_INTFLAG_XOSC32KFAIL;
+ OSC32KCTRL->CFDCTRL.bit.CFDEN = 1; // Fall back to internal Osc on crystal fail
+ OSC32KCTRL->XOSC32K.reg =
+ OSC32KCTRL_XOSC32K_CGM_HS |
+ OSC32KCTRL_XOSC32K_XTALEN |
+ OSC32KCTRL_XOSC32K_EN32K |
+ OSC32KCTRL_XOSC32K_EN1K |
+ OSC32KCTRL_XOSC32K_RUNSTDBY |
+ OSC32KCTRL_XOSC32K_STARTUP(4) |
+ OSC32KCTRL_XOSC32K_ENABLE;
+ // make sure osc32kcrtl is ready
+ while (OSC32KCTRL->STATUS.bit.XOSC32KRDY == 0) {
+ }
+
+ #if MICROPY_HW_MCU_OSC32KULP
+ // Setup GCLK1 for 32kHz ULP
+ GCLK->GENCTRL[1].reg = GCLK_GENCTRL_RUNSTDBY | GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_OSCULP32K;
+ #else
+ // Setup GCLK1 for 32kHz crystal
+ GCLK->GENCTRL[1].reg = GCLK_GENCTRL_RUNSTDBY | GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_XOSC32K;
+ #endif
+
+ while (GCLK->SYNCBUSY.bit.GENCTRL1) {
+ }
+
+ // Setup GCLK4 for 32kHz crystal
+ GCLK->GENCTRL[4].reg = GCLK_GENCTRL_RUNSTDBY | GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_XOSC32K;
+ while (GCLK->SYNCBUSY.bit.GENCTRL4) {
+ }
+
+ // Set-up the DFLL48M in closed loop mode with input from the 32kHz crystal
+
+ // Step 1: Peripheral channel 0 is driven by GCLK4 and it feeds DFLL48M
+ GCLK->PCHCTRL[0].reg = GCLK_PCHCTRL_GEN_GCLK4 | GCLK_PCHCTRL_CHEN;
+ while (GCLK->PCHCTRL[0].bit.CHEN == 0) {
+ }
+ // Step 2: Set the multiplication values. The offset of 16384 to the freq is for rounding.
+ OSCCTRL->DFLLMUL.reg = OSCCTRL_DFLLMUL_MUL((DFLL48M_FREQ + DPLLx_REF_FREQ / 2) / DPLLx_REF_FREQ) |
+ OSCCTRL_DFLLMUL_FSTEP(1) | OSCCTRL_DFLLMUL_CSTEP(1);
+ while (OSCCTRL->DFLLSYNC.bit.DFLLMUL == 1) {
+ }
+ // Step 3: Set the mode to closed loop
+ OSCCTRL->DFLLCTRLB.reg = OSCCTRL_DFLLCTRLB_BPLCKC | OSCCTRL_DFLLCTRLB_STABLE | OSCCTRL_DFLLCTRLB_MODE;
+ while (OSCCTRL->DFLLSYNC.bit.DFLLCTRLB == 1) {
+ }
+ // Wait for lock fine
+ while (OSCCTRL->STATUS.bit.DFLLLCKF == 0) {
+ }
+ // Step 4: Start the DFLL.
+ OSCCTRL->DFLLCTRLA.reg = OSCCTRL_DFLLCTRLA_RUNSTDBY | OSCCTRL_DFLLCTRLA_ENABLE;
+ while (OSCCTRL->DFLLSYNC.bit.ENABLE == 1) {
+ }
+
+ #else // MICROPY_HW_XOSC32K
+
+ // Enable the clock for RTC
+ OSC32KCTRL->RTCCTRL.reg = OSC32KCTRL_RTCCTRL_RTCSEL_ULP1K;
+
+ // Derive GCLK1 from DFLL48M at DPLL0_REF_FREQ as defined in mpconfigboard.h (e.g. 32768 Hz)
+ GCLK->GENCTRL[1].reg = ((DFLL48M_FREQ + DPLLx_REF_FREQ / 2) / DPLLx_REF_FREQ) << GCLK_GENCTRL_DIV_Pos
+ | GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_DFLL;
+ while (GCLK->SYNCBUSY.bit.GENCTRL1) {
+ }
+
+ OSCCTRL->DFLLCTRLA.bit.RUNSTDBY = 1;
+ OSCCTRL->DFLLCTRLA.bit.ONDEMAND = 0;
+
+ OSCCTRL->DFLLCTRLA.bit.ENABLE = 1;
+ while (OSCCTRL->DFLLSYNC.bit.ENABLE == 1) {
+ }
+
+ #if MICROPY_HW_DFLL_USB_SYNC
+ // Configure the DFLL48M for USB clock recovery.
+ // Will have to switch back if no USB
+ dfll48m_calibration = OSCCTRL->DFLLVAL.reg;
+ // Set the Multiplication factor.
+ OSCCTRL->DFLLMUL.reg = OSCCTRL_DFLLMUL_MUL(48000) |
+ OSCCTRL_DFLLMUL_FSTEP(1) | OSCCTRL_DFLLMUL_CSTEP(1);
+ while (OSCCTRL->DFLLSYNC.bit.DFLLMUL == 1) {
+ }
+ // Set the mode to closed loop USB Recovery
+ OSCCTRL->DFLLCTRLB.reg = OSCCTRL_DFLLCTRLB_USBCRM | OSCCTRL_DFLLCTRLB_CCDIS | OSCCTRL_DFLLCTRLB_MODE;
+ while (OSCCTRL->DFLLSYNC.bit.DFLLCTRLB == 1) {
+ }
+ #endif
+
+ #endif // MICROPY_HW_XOSC32K
+
+ // Peripheral channel 1 is driven by GCLK1 and it feeds DPLL0
+ GCLK->PCHCTRL[1].reg = GCLK_PCHCTRL_GEN_GCLK1 | GCLK_PCHCTRL_CHEN;
+ while (GCLK->PCHCTRL[1].bit.CHEN == 0) {
+ }
+
+ set_cpu_freq(cpu_freq);
+
+ peripheral_freq = DFLL48M_FREQ; // To be changed if CPU_FREQ < 48M
+
+ // Setup GCLK2 for DFLL48M output (48 MHz), may be scaled down later by calls to set_cpu_freq
+ GCLK->GENCTRL[2].reg = GCLK_GENCTRL_DIV(1) | GCLK_GENCTRL_RUNSTDBY | GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_DFLL;
+ while (GCLK->SYNCBUSY.bit.GENCTRL2) {
+ }
+
+ // Setup GCLK3 for 16MHz, Used for TC0/1 counter
+ GCLK->GENCTRL[3].reg = GCLK_GENCTRL_DIV(3) | GCLK_GENCTRL_RUNSTDBY | GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_DFLL;
+ while (GCLK->SYNCBUSY.bit.GENCTRL3) {
+ }
+}
+
+void enable_sercom_clock(int id) {
+ GCLK->PCHCTRL[sercom_gclk_id[id]].reg = GCLK_PCHCTRL_CHEN | GCLK_PCHCTRL_GEN_GCLK2;
+ // no easy way to set the clocks, except enabling all of them
+ switch (id) {
+ case 0:
+ MCLK->APBAMASK.bit.SERCOM0_ = 1;
+ break;
+ case 1:
+ MCLK->APBAMASK.bit.SERCOM1_ = 1;
+ break;
+ case 2:
+ MCLK->APBBMASK.bit.SERCOM2_ = 1;
+ break;
+ case 3:
+ MCLK->APBBMASK.bit.SERCOM3_ = 1;
+ break;
+ case 4:
+ MCLK->APBDMASK.bit.SERCOM4_ = 1;
+ break;
+ case 5:
+ MCLK->APBDMASK.bit.SERCOM5_ = 1;
+ break;
+ #ifdef SERCOM7_GCLK_ID_CORE
+ case 6:
+ MCLK->APBDMASK.bit.SERCOM6_ = 1;
+ break;
+ case 7:
+ MCLK->APBDMASK.bit.SERCOM7_ = 1;
+ break;
+ #endif
+ }
+}
diff --git a/ports/samd/mcu/samd51/manifest.py b/ports/samd/mcu/samd51/manifest.py
new file mode 100644
index 000000000000..4a79f6818f8b
--- /dev/null
+++ b/ports/samd/mcu/samd51/manifest.py
@@ -0,0 +1,5 @@
+include("$(PORT_DIR)/boards/manifest.py")
+include("$(MPY_DIR)/extmod/uasyncio")
+require("onewire")
+require("ds18x20")
+require("dht")
diff --git a/ports/samd/mcu/samd51/mpconfigmcu.h b/ports/samd/mcu/samd51/mpconfigmcu.h
new file mode 100644
index 000000000000..5ac431b29707
--- /dev/null
+++ b/ports/samd/mcu/samd51/mpconfigmcu.h
@@ -0,0 +1,70 @@
+// Deinitions common to all SAMD51 boards
+#include "samd51.h"
+
+#define MICROPY_CONFIG_ROM_LEVEL (MICROPY_CONFIG_ROM_LEVEL_FULL_FEATURES)
+
+// MicroPython emitters
+#define MICROPY_EMIT_THUMB (1)
+#define MICROPY_EMIT_INLINE_THUMB (1)
+
+#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_FLOAT)
+
+#ifndef MICROPY_PY_BUILTINS_COMPLEX
+#define MICROPY_PY_BUILTINS_COMPLEX (0)
+#endif
+
+#ifndef MICROPY_PY_MATH
+#define MICROPY_PY_MATH (1)
+#define MP_NEED_LOG2 (1)
+#endif
+
+#ifndef MICROPY_PY_CMATH
+#define MICROPY_PY_CMATH (0)
+#endif
+
+#define MICROPY_PY_MACHINE_DHT_READINTO (1)
+#define MICROPY_PY_ONEWIRE (1)
+#define MICROPY_PY_UOS_URANDOM (1)
+#define MICROPY_PY_URANDOM_SEED_INIT_FUNC (trng_random_u32())
+unsigned long trng_random_u32(void);
+
+#ifndef MICROPY_PY_MACHINE_PIN_BOARD_CPU
+#define MICROPY_PY_MACHINE_PIN_BOARD_CPU (1)
+#endif
+
+// fatfs configuration used in ffconf.h
+#define MICROPY_FATFS_ENABLE_LFN (1)
+#define MICROPY_FATFS_RPATH (2)
+#define MICROPY_FATFS_MAX_SS (4096)
+#define MICROPY_FATFS_LFN_CODE_PAGE 437 /* 1=SFN/ANSI 437=LFN/U.S.(OEM) */
+
+#define VFS_BLOCK_SIZE_BYTES (1536) //
+
+#ifndef MICROPY_HW_UART_TXBUF
+#define MICROPY_HW_UART_TXBUF (1)
+#endif
+
+#define CPU_FREQ (120000000)
+#define DFLL48M_FREQ (48000000)
+#define MAX_CPU_FREQ (200000000)
+#define DPLLx_REF_FREQ (32768)
+
+#define NVIC_PRIORITYGROUP_4 ((uint32_t)0x00000003)
+#define IRQ_PRI_PENDSV NVIC_EncodePriority(NVIC_PRIORITYGROUP_4, 7, 0)
+
+static inline uint32_t raise_irq_pri(uint32_t pri) {
+ uint32_t basepri = __get_BASEPRI();
+ // If non-zero, the processor does not process any exception with a
+ // priority value greater than or equal to BASEPRI.
+ // When writing to BASEPRI_MAX the write goes to BASEPRI only if either:
+ // - Rn is non-zero and the current BASEPRI value is 0
+ // - Rn is non-zero and less than the current BASEPRI value
+ pri <<= (8 - __NVIC_PRIO_BITS);
+ __ASM volatile ("msr basepri_max, %0" : : "r" (pri) : "memory");
+ return basepri;
+}
+
+// "basepri" should be the value returned from raise_irq_pri
+static inline void restore_irq_pri(uint32_t basepri) {
+ __set_BASEPRI(basepri);
+}
diff --git a/ports/samd/mcu/samd51/mpconfigmcu.mk b/ports/samd/mcu/samd51/mpconfigmcu.mk
new file mode 100644
index 000000000000..8596f5982111
--- /dev/null
+++ b/ports/samd/mcu/samd51/mpconfigmcu.mk
@@ -0,0 +1,42 @@
+CFLAGS_MCU += -mtune=cortex-m4 -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard
+
+MPY_CROSS_MCU_ARCH = armv7m
+
+MICROPY_VFS_LFS2 ?= 1
+MICROPY_VFS_FAT ?= 1
+FROZEN_MANIFEST ?= mcu/$(MCU_SERIES_LOWER)/manifest.py
+
+SRC_S += shared/runtime/gchelper_thumb2.s
+
+SRC_C += \
+ fatfs_port.c \
+ drivers/dht/dht.c \
+
+LIBM_SRC_C += $(addprefix lib/libm/,\
+ acoshf.c \
+ asinfacosf.c \
+ asinhf.c \
+ atan2f.c \
+ atanf.c \
+ atanhf.c \
+ ef_rem_pio2.c \
+ erf_lgamma.c \
+ fmodf.c \
+ kf_cos.c \
+ kf_rem_pio2.c \
+ kf_sin.c \
+ kf_tan.c \
+ log1pf.c \
+ math.c \
+ nearbyintf.c \
+ roundf.c \
+ sf_cos.c \
+ sf_erf.c \
+ sf_frexp.c \
+ sf_ldexp.c \
+ sf_modf.c \
+ sf_sin.c \
+ sf_tan.c \
+ wf_lgamma.c \
+ wf_tgamma.c \
+ )
diff --git a/ports/samd/mcu/samd51/pin-af-table.csv b/ports/samd/mcu/samd51/pin-af-table.csv
new file mode 100644
index 000000000000..70a009ba5223
--- /dev/null
+++ b/ports/samd/mcu/samd51/pin-af-table.csv
@@ -0,0 +1,113 @@
+# The pin_cap_table is a subset from table 6-1 of the data sheet.
+# It contain the information about pin mux set and pad
+# for some of the peripheral devices with many possible assignments.
+# The colums represent the peripheral class, as defined in pin_cap_t. The
+# column number is equivalent to the mux class.
+# The eic and adc columns contain the decimal numer for the respecitive
+# quantity, the columns for sercom, tc and tcc have in each cell
+# the device number in the first, and the pad number in the second
+# digit. If a signal is not available, the cell in the csv table is left empty.
+# The first column is the pin id, not the number of the board pin.
+# Rows not starting with pa, pb, pc or pd are ignored.
+# When editing the table with a spread sheet, take care to import the data as text.
+#
+# Pin,EIC,ADC0,ADC1,SERCOM1,SERCOM2,TC,TCC1,TCC2
+pb03,9,15,,,51,61,,
+pa00,0,,,,10,20,,
+pa01,1,,,,11,21,,
+pc00,0,,10,,,,,
+pc01,1,,11,,,,,
+pc02,2,,4,,,,,
+pc03,3,,5,,,,,
+pa02,2,0,,,,,,
+pa03,3,10,,,,,,
+pb04,4,,6,,,,,
+pb05,5,,7,,,,,
+pd00,0,,14,,,,,
+pd01,1,,15,,,,,
+pb06,6,,8,,,,,
+pb07,7,,9,,,,,
+pb08,8,2,0,,40,40,,
+pb09,9,3,1,,41,41,,
+pa04,4,4,,,00,00,,
+pa05,5,5,,,01,01,,
+pa06,6,6,,,02,10,,
+pa07,7,7,,,03,11,,
+pc04,4,,,60,,,00,
+pc05,5,,,61,,,,
+pc06,6,,,62,,,,
+pc07,9,,,63,,,,
+pa08,,8,2,00,21,00,00,14
+pa09,9,9,3,01,20,01,01,15
+pa10,10,10,,02,22,10,02,16
+pa11,11,11,,03,23,11,03,17
+pb10,10,,,,42,50,04,10
+pb11,12,,,,43,51,05,11
+pb12,12,,,40,,40,30,00
+pb13,13,,,41,,41,31,01
+pb14,14,,,42,,50,40,02
+pb15,15,,,43,,51,41,03
+pd08,3,,,70,61,,01,
+pd09,4,,,71,60,,02,
+pd10,5,,,72,62,,03,
+pd11,6,,,73,63,,04,
+pd12,7,,,,,,05,
+pc10,10,,,62,72,,00,14
+pc11,11,,,63,73,,01,15
+pc12,12,,,70,61,,02,16
+pc13,13,,,71,60,,03,17
+pc14,14,,,72,62,,04,10
+pc15,15,,,73,63,,05,11
+pa12,12,,,20,41,20,06,12
+pa13,13,,,21,40,21,07,13
+pa14,14,,,22,42,30,20,12
+pa15,15,,,23,43,31,21,13
+pa16,0,,,10,31,20,10,04
+pa17,1,,,11,30,21,11,05
+pa18,2,,,12,32,30,12,06
+pa19,3,,,13,33,31,13,07
+pc16,0,,,60,01,,00,
+pc17,1,,,61,00,,01,
+pc18,2,,,62,02,,02,
+pc19,3,,,63,03,,03,
+pc20,4,,,,,,04,
+pc21,5,,,,,,05,
+pc22,6,,,10,31,,05,
+pc23,7,,,11,30,,07,
+pd20,10,,,12,32,,10,
+pd21,11,,,13,33,,11,
+pb16,0,,,50,,60,30,04
+pb17,1,,,51,,61,31,05
+pb18,2,,,52,72,,10,
+pb19,3,,,53,73,,11,
+pb20,4,,,30,71,,12,
+pb21,5,,,31,70,,13,
+pa20,4,,,52,32,70,14,00
+pa21,5,,,53,33,71,15,01
+pa22,6,,,30,51,40,16,02
+pa23,7,,,31,50,41,17,03
+pa24,8,,,32,52,50,22,
+pa25,9,,,33,53,51,,
+pb22,22,,,12,52,70,,
+pb23,7,,,13,53,71,,
+pb24,8,,,00,21,,,
+pb25,9,,,01,20,,,
+pb26,12,,,20,41,,12,
+pb27,13,,,21,40,,13,
+pb28,14,,,22,42,,14,
+pb29,15,,,23,43,,15,
+pc24,8,,,02,22,,,
+pc25,9,,,03,23,,,
+pc26,10,,,,,,,
+pc27,11,,,10,,,,
+pc28,12,,,11,,,,
+pa27,11,,,,,,,
+pa30,14,,,72,12,60,20,
+pa31,15,,,73,13,61,21,
+pb30,14,,,70,51,00,40,06
+pb31,15,,,71,50,01,41,07
+pc30,14,,12,,,,,
+pc31,15,,13,,,,,
+pb00,9,12,,,52,70,,
+pb01,1,13,,,53,71,,
+pb02,2,14,,,50,60,22,
diff --git a/ports/samd/modmachine.c b/ports/samd/modmachine.c
index 74e357175942..ec3e99f163a5 100644
--- a/ports/samd/modmachine.c
+++ b/ports/samd/modmachine.c
@@ -25,9 +25,16 @@
*/
#include "py/runtime.h"
+#include "extmod/machine_bitstream.h"
#include "extmod/machine_mem.h"
-#include "samd_soc.h"
+#include "extmod/machine_pulse.h"
+#include "extmod/machine_i2c.h"
+#include "extmod/machine_signal.h"
+#include "extmod/machine_spi.h"
+#include "drivers/dht/dht.h"
+#include "shared/runtime/pyexec.h"
#include "modmachine.h"
+#include "samd_soc.h"
// ASF 4
#include "hal_flash.h"
@@ -36,36 +43,58 @@
#include "hpl_pm_base.h"
#if MICROPY_PY_MACHINE
-
#if defined(MCU_SAMD21)
-#define DBL_TAP_ADDR ((volatile uint32_t *)(0x20000000 + 32 * 1024 - 4))
+#define DBL_TAP_ADDR ((volatile uint32_t *)(HMCRAMC0_ADDR + HMCRAMC0_SIZE - 4))
#elif defined(MCU_SAMD51)
-#define DBL_TAP_ADDR ((volatile uint32_t *)(0x20000000 + 192 * 1024 - 4))
+#define DBL_TAP_ADDR ((volatile uint32_t *)(HSRAM_ADDR + HSRAM_SIZE - 4))
#endif
+// A board may define a DPL_TAP_ADDR_ALT, which will be set as well
+// Needed at the moment for Sparkfun SAMD51 Thing Plus
#define DBL_TAP_MAGIC_LOADER 0xf01669ef
#define DBL_TAP_MAGIC_RESET 0xf02669ef
-MP_DEFINE_CONST_FUN_OBJ_0(machine_uart_init_obj, machine_uart_init);
-MP_DEFINE_CONST_FUN_OBJ_0(machine_uart_deinit_obj, machine_uart_deinit);
+#define LIGHTSLEEP_CPU_FREQ 200000
+
+extern bool EIC_occured;
+extern uint32_t _dbl_tap_addr;
+
+STATIC mp_obj_t machine_soft_reset(void) {
+ pyexec_system_exit = PYEXEC_FORCED_EXIT;
+ mp_raise_type(&mp_type_SystemExit);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_soft_reset_obj, machine_soft_reset);
STATIC mp_obj_t machine_reset(void) {
*DBL_TAP_ADDR = DBL_TAP_MAGIC_RESET;
+ #ifdef DBL_TAP_ADDR_ALT
+ *DBL_TAP_ADDR_ALT = DBL_TAP_MAGIC_RESET;
+ #endif
NVIC_SystemReset();
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_0(machine_reset_obj, machine_reset);
-STATIC mp_obj_t machine_bootloader(void) {
+NORETURN mp_obj_t machine_bootloader(size_t n_args, const mp_obj_t *args) {
*DBL_TAP_ADDR = DBL_TAP_MAGIC_LOADER;
+ #ifdef DBL_TAP_ADDR_ALT
+ *DBL_TAP_ADDR_ALT = DBL_TAP_MAGIC_LOADER;
+ #endif
NVIC_SystemReset();
- return mp_const_none;
}
-MP_DEFINE_CONST_FUN_OBJ_0(machine_bootloader_obj, machine_bootloader);
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_bootloader_obj, 0, 1, machine_bootloader);
-STATIC mp_obj_t machine_freq(void) {
- return MP_OBJ_NEW_SMALL_INT(CPU_FREQ);
+STATIC mp_obj_t machine_freq(size_t n_args, const mp_obj_t *args) {
+ if (n_args == 0) {
+ return MP_OBJ_NEW_SMALL_INT(get_cpu_freq());
+ } else {
+ uint32_t freq = mp_obj_get_int(args[0]);
+ if (freq >= 1000000 && freq <= MAX_CPU_FREQ) {
+ set_cpu_freq(freq);
+ }
+ return mp_const_none;
+ }
}
-MP_DEFINE_CONST_FUN_OBJ_0(machine_freq_obj, machine_freq);
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_freq_obj, 0, 1, machine_freq);
STATIC mp_obj_t machine_unique_id(void) {
// Each device has a unique 128-bit serial number which is a concatenation of four 32-bit
@@ -110,8 +139,93 @@ STATIC mp_obj_t machine_unique_id(void) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_unique_id_obj, machine_unique_id);
+STATIC mp_obj_t machine_idle(void) {
+ MICROPY_EVENT_POLL_HOOK;
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_idle_obj, machine_idle);
+
+STATIC mp_obj_t machine_disable_irq(void) {
+ uint32_t state = MICROPY_BEGIN_ATOMIC_SECTION();
+ return mp_obj_new_int(state);
+}
+MP_DEFINE_CONST_FUN_OBJ_0(machine_disable_irq_obj, machine_disable_irq);
+
+STATIC mp_obj_t machine_enable_irq(mp_obj_t state_in) {
+ uint32_t state = mp_obj_get_int(state_in);
+ MICROPY_END_ATOMIC_SECTION(state);
+ return mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_1(machine_enable_irq_obj, machine_enable_irq);
+
+STATIC mp_obj_t machine_reset_cause(void) {
+ #if defined(MCU_SAMD21)
+ return MP_OBJ_NEW_SMALL_INT(PM->RCAUSE.reg);
+ #elif defined(MCU_SAMD51)
+ return MP_OBJ_NEW_SMALL_INT(RSTC->RCAUSE.reg);
+ #else
+ return MP_OBJ_NEW_SMALL_INT(0);
+ #endif
+}
+MP_DEFINE_CONST_FUN_OBJ_0(machine_reset_cause_obj, machine_reset_cause);
+
+STATIC mp_obj_t machine_lightsleep(size_t n_args, const mp_obj_t *args) {
+ int32_t duration = -1;
+ uint32_t freq = get_cpu_freq();
+ if (n_args > 0) {
+ duration = mp_obj_get_int(args[0]);
+ }
+ EIC_occured = false;
+ // Slow down
+ set_cpu_freq(LIGHTSLEEP_CPU_FREQ);
+ #if defined(MCU_SAMD21)
+ // Switch the peripheral clock off
+ GCLK->GENCTRL.reg = GCLK_GENCTRL_ID(2);
+ while (GCLK->STATUS.bit.SYNCBUSY) {
+ }
+ // Switch the EIC temporarily to GCLK3, since GCLK2 is off
+ GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK3 | EIC_GCLK_ID;
+ if (duration > 0) {
+ uint32_t t0 = systick_ms;
+ while ((systick_ms - t0 < duration) && (EIC_occured == false)) {
+ __WFI();
+ }
+ } else {
+ while (EIC_occured == false) {
+ __WFI();
+ }
+ }
+ GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK2 | EIC_GCLK_ID;
+
+ #elif defined(MCU_SAMD51)
+ // Switch the peripheral clock off
+ GCLK->GENCTRL[2].reg = 0;
+ while (GCLK->SYNCBUSY.bit.GENCTRL2) {
+ }
+ // Switch the EIC temporarily to GCLK3, since GCLK2 is off
+ GCLK->PCHCTRL[EIC_GCLK_ID].reg = GCLK_PCHCTRL_CHEN | GCLK_PCHCTRL_GEN_GCLK3;
+ if (duration > 0) {
+ uint32_t t0 = systick_ms;
+ while ((systick_ms - t0 < duration) && (EIC_occured == false)) {
+ __WFI();
+ }
+ } else {
+ while (EIC_occured == false) {
+ __WFI();
+ }
+ }
+ GCLK->PCHCTRL[EIC_GCLK_ID].reg = GCLK_PCHCTRL_CHEN | GCLK_PCHCTRL_GEN_GCLK2;
+
+ #endif
+ // Speed up again
+ set_cpu_freq(freq);
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_lightsleep_obj, 0, 1, machine_lightsleep);
+
STATIC const mp_rom_map_elem_t machine_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_umachine) },
+ { MP_ROM_QSTR(MP_QSTR_soft_reset), MP_ROM_PTR(&machine_soft_reset_obj) },
{ MP_ROM_QSTR(MP_QSTR_reset), MP_ROM_PTR(&machine_reset_obj) },
{ MP_ROM_QSTR(MP_QSTR_bootloader), MP_ROM_PTR(&machine_bootloader_obj) },
{ MP_ROM_QSTR(MP_QSTR_freq), MP_ROM_PTR(&machine_freq_obj) },
@@ -119,10 +233,43 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_mem16), MP_ROM_PTR(&machine_mem16_obj) },
{ MP_ROM_QSTR(MP_QSTR_mem32), MP_ROM_PTR(&machine_mem32_obj) },
{ MP_ROM_QSTR(MP_QSTR_unique_id), MP_ROM_PTR(&machine_unique_id_obj) },
- { MP_ROM_QSTR(MP_QSTR_uart_init), MP_ROM_PTR(&machine_uart_init_obj) },
- { MP_ROM_QSTR(MP_QSTR_uart_deinit), MP_ROM_PTR(&machine_uart_deinit_obj) },
+
+ { MP_ROM_QSTR(MP_QSTR_ADC), MP_ROM_PTR(&machine_adc_type) },
+ { MP_ROM_QSTR(MP_QSTR_DAC), MP_ROM_PTR(&machine_dac_type) },
{ MP_ROM_QSTR(MP_QSTR_Pin), MP_ROM_PTR(&machine_pin_type) },
- { MP_ROM_QSTR(MP_QSTR_LED), MP_ROM_PTR(&machine_led_type) },
+ { MP_ROM_QSTR(MP_QSTR_Signal), MP_ROM_PTR(&machine_signal_type) },
+ { MP_ROM_QSTR(MP_QSTR_PWM), MP_ROM_PTR(&machine_pwm_type) },
+ { MP_ROM_QSTR(MP_QSTR_SoftI2C), MP_ROM_PTR(&mp_machine_soft_i2c_type) },
+ { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&machine_i2c_type) },
+ { MP_ROM_QSTR(MP_QSTR_SoftSPI), MP_ROM_PTR(&mp_machine_soft_spi_type) },
+ { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&machine_spi_type) },
+ { MP_ROM_QSTR(MP_QSTR_Timer), MP_ROM_PTR(&machine_timer_type) },
+ { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&machine_uart_type) },
+ { MP_ROM_QSTR(MP_QSTR_WDT), MP_ROM_PTR(&machine_wdt_type) },
+ #if MICROPY_PY_MACHINE_RTC
+ { MP_ROM_QSTR(MP_QSTR_RTC), MP_ROM_PTR(&machine_rtc_type) },
+ #endif
+
+ { MP_ROM_QSTR(MP_QSTR_idle), MP_ROM_PTR(&machine_idle_obj) },
+ { MP_ROM_QSTR(MP_QSTR_disable_irq), MP_ROM_PTR(&machine_disable_irq_obj) },
+ { MP_ROM_QSTR(MP_QSTR_enable_irq), MP_ROM_PTR(&machine_enable_irq_obj) },
+ { MP_ROM_QSTR(MP_QSTR_reset_cause), MP_ROM_PTR(&machine_reset_cause_obj) },
+ { MP_ROM_QSTR(MP_QSTR_time_pulse_us), MP_ROM_PTR(&machine_time_pulse_us_obj) },
+ { MP_ROM_QSTR(MP_QSTR_lightsleep), MP_ROM_PTR(&machine_lightsleep_obj) },
+
+ { MP_ROM_QSTR(MP_QSTR_bitstream), MP_ROM_PTR(&machine_bitstream_obj) },
+ #if MICROPY_PY_MACHINE_DHT_READINTO
+ { MP_ROM_QSTR(MP_QSTR_dht_readinto), MP_ROM_PTR(&dht_readinto_obj) },
+ #endif
+
+ // Class constants.
+ // Use numerical constants instead of the symbolic names,
+ // since the names differ between SAMD21 and SAMD51.
+ { MP_ROM_QSTR(MP_QSTR_PWRON_RESET), MP_ROM_INT(0x01) },
+ { MP_ROM_QSTR(MP_QSTR_HARD_RESET), MP_ROM_INT(0x10) },
+ { MP_ROM_QSTR(MP_QSTR_WDT_RESET), MP_ROM_INT(0x20) },
+ { MP_ROM_QSTR(MP_QSTR_SOFT_RESET), MP_ROM_INT(0x40) },
+ { MP_ROM_QSTR(MP_QSTR_DEEPSLEEP_RESET), MP_ROM_INT(0x80) },
};
STATIC MP_DEFINE_CONST_DICT(machine_module_globals, machine_module_globals_table);
diff --git a/ports/samd/modmachine.h b/ports/samd/modmachine.h
index 61bd2f4d2991..8b3059d9fc71 100644
--- a/ports/samd/modmachine.h
+++ b/ports/samd/modmachine.h
@@ -27,11 +27,23 @@
#define MICROPY_INCLUDED_SAMD_MODMACHINE_H
#include "py/obj.h"
+#include "shared/timeutils/timeutils.h"
+extern const mp_obj_type_t machine_adc_type;
+extern const mp_obj_type_t machine_dac_type;
+extern const mp_obj_type_t machine_i2c_type;
extern const mp_obj_type_t machine_pin_type;
-extern const mp_obj_type_t machine_led_type;
+extern const mp_obj_type_t machine_pwm_type;
+extern const mp_obj_type_t machine_spi_type;
+extern const mp_obj_type_t machine_timer_type;
+extern const mp_obj_type_t machine_uart_type;
+extern const mp_obj_type_t machine_wdt_type;
+#if MICROPY_PY_MACHINE_RTC
+extern const mp_obj_type_t machine_rtc_type;
+#endif
-mp_obj_t machine_uart_init(void);
-mp_obj_t machine_uart_deinit(void);
+NORETURN mp_obj_t machine_bootloader(size_t n_args, const mp_obj_t *args);
+
+void rtc_gettime(timeutils_struct_time_t *tm);
#endif // MICROPY_INCLUDED_SAMD_MODMACHINE_H
diff --git a/ports/samd/modsamd.c b/ports/samd/modsamd.c
index 68fd6b53e56d..7593a7bb0da3 100644
--- a/ports/samd/modsamd.c
+++ b/ports/samd/modsamd.c
@@ -24,14 +24,51 @@
* THE SOFTWARE.
*/
+#include "string.h"
#include "py/runtime.h"
+#include "py/mphal.h"
+
+#include "sam.h"
+#include "pin_af.h"
#include "samd_soc.h"
extern const mp_obj_type_t samd_flash_type;
+STATIC mp_obj_t samd_pininfo(mp_obj_t pin_obj) {
+ const machine_pin_obj_t *pin_af = pin_find(pin_obj);
+ #if defined(MCU_SAMD21)
+ mp_obj_t tuple[7] = {
+ tuple[0] = MP_OBJ_NEW_QSTR(pin_af->name),
+ tuple[1] = mp_obj_new_int(pin_af->eic),
+ tuple[2] = mp_obj_new_int(pin_af->adc0),
+ tuple[3] = mp_obj_new_int(pin_af->sercom1),
+ tuple[4] = mp_obj_new_int(pin_af->sercom2),
+ tuple[5] = mp_obj_new_int(pin_af->tcc1),
+ tuple[6] = mp_obj_new_int(pin_af->tcc2),
+ };
+ return mp_obj_new_tuple(7, tuple);
+ #elif defined(MCU_SAMD51)
+ mp_obj_t tuple[9] = {
+ tuple[0] = MP_OBJ_NEW_QSTR(pin_af->name),
+ tuple[1] = mp_obj_new_int(pin_af->eic),
+ tuple[2] = mp_obj_new_int(pin_af->adc0),
+ tuple[3] = mp_obj_new_int(pin_af->adc1),
+ tuple[4] = mp_obj_new_int(pin_af->sercom1),
+ tuple[5] = mp_obj_new_int(pin_af->sercom2),
+ tuple[6] = mp_obj_new_int(pin_af->tc),
+ tuple[7] = mp_obj_new_int(pin_af->tcc1),
+ tuple[8] = mp_obj_new_int(pin_af->tcc2),
+ };
+ return mp_obj_new_tuple(9, tuple);
+ #endif
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(samd_pininfo_obj, samd_pininfo);
+
STATIC const mp_rom_map_elem_t samd_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_samd) },
- { MP_ROM_QSTR(MP_QSTR_Flash), MP_ROM_PTR(&samd_flash_type) },
+ { MP_ROM_QSTR(MP_QSTR_Flash), MP_ROM_PTR(&samd_flash_type) },
+ { MP_ROM_QSTR(MP_QSTR_pininfo), MP_ROM_PTR(&samd_pininfo_obj) },
};
STATIC MP_DEFINE_CONST_DICT(samd_module_globals, samd_module_globals_table);
diff --git a/ports/samd/modules/_boot.py b/ports/samd/modules/_boot.py
index 84b02480b745..e183125f2e4b 100644
--- a/ports/samd/modules/_boot.py
+++ b/ports/samd/modules/_boot.py
@@ -6,11 +6,13 @@
bdev = samd.Flash()
# Try to mount the filesystem, and format the flash if it doesn't exist.
+fs_type = uos.VfsLfs2 if hasattr(uos, "VfsLfs2") else uos.VfsLfs1
+
try:
- vfs = uos.VfsLfs1(bdev)
+ vfs = fs_type(bdev)
except:
- uos.VfsLfs1.mkfs(bdev)
- vfs = uos.VfsLfs1(bdev)
+ fs_type.mkfs(bdev)
+ vfs = fs_type(bdev)
uos.mount(vfs, "/")
gc.collect()
diff --git a/ports/samd/moduos.c b/ports/samd/moduos.c
new file mode 100644
index 000000000000..3404919d24b5
--- /dev/null
+++ b/ports/samd/moduos.c
@@ -0,0 +1,113 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2016 Damien P. George
+ *
+ * use of the TRNG by
+ * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
+ * Copyright (c) 2019 Artur Pacholec
+ * Copyright (c) 2022 Robert Hammelrath
+ *
+ * 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 "modmachine.h"
+#include "sam.h"
+
+#if defined(MCU_SAMD51)
+static bool initialized = false;
+
+STATIC void trng_start(void) {
+ if (!initialized) {
+ MCLK->APBCMASK.bit.TRNG_ = 1;
+ REG_TRNG_CTRLA = TRNG_CTRLA_ENABLE;
+ initialized = true;
+ }
+}
+
+uint32_t trng_random_u32(void) {
+ trng_start();
+ while ((REG_TRNG_INTFLAG & TRNG_INTFLAG_DATARDY) == 0) {
+ }
+ return REG_TRNG_DATA;
+}
+
+#define TRNG_RANDOM_U32 trng_random_u32()
+#endif // defined(MCU_SAMD51)
+
+#if defined(MCU_SAMD21)
+extern volatile uint32_t rng_state;
+
+uint32_t trng_random_u32(int delay) {
+ mp_hal_delay_ms(delay); // wait a few cycles
+ uint32_t upper = rng_state;
+ mp_hal_delay_ms(delay); // wait again a few cycles
+ return (upper & 0xffff0000) | (rng_state >> 16);
+}
+
+#define trng_start()
+#define TRNG_RANDOM_U32 trng_random_u32(10)
+#endif
+
+#if MICROPY_PY_UOS_URANDOM
+STATIC mp_obj_t mp_uos_urandom(mp_obj_t num) {
+ mp_int_t n = mp_obj_get_int(num);
+ vstr_t vstr;
+ vstr_init_len(&vstr, n);
+ uint32_t rngval = 0;
+
+ trng_start();
+ for (int i = 0; i < n; i++) {
+ if ((i % 4) == 0) {
+ rngval = TRNG_RANDOM_U32;
+ }
+ vstr.buf[i] = rngval & 0xff;
+ rngval >>= 8;
+ }
+ return mp_obj_new_bytes_from_vstr(&vstr);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_uos_urandom_obj, mp_uos_urandom);
+
+#endif // MICROPY_PY_UOS_URANDOM
+
+#if MICROPY_PY_UOS_DUPTERM_BUILTIN_STREAM
+bool mp_uos_dupterm_is_builtin_stream(mp_const_obj_t stream) {
+ const mp_obj_type_t *type = mp_obj_get_type(stream);
+ return type == &machine_uart_type;
+}
+#endif
+
+#if MICROPY_PY_UOS_DUPTERM_NOTIFY
+STATIC mp_obj_t mp_uos_dupterm_notify(mp_obj_t obj_in) {
+ (void)obj_in;
+ for (;;) {
+ int c = mp_uos_dupterm_rx_chr();
+ if (c < 0) {
+ break;
+ }
+ ringbuf_put(&stdin_ringbuf, c);
+ }
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_uos_dupterm_notify_obj, mp_uos_dupterm_notify);
+#endif
diff --git a/ports/samd/modutime.c b/ports/samd/modutime.c
index bbeedcfda070..6fce203154ba 100644
--- a/ports/samd/modutime.c
+++ b/ports/samd/modutime.c
@@ -27,18 +27,20 @@
#include "py/runtime.h"
#include "extmod/utime_mphal.h"
#include "shared/timeutils/timeutils.h"
+#include "modmachine.h"
// localtime([secs])
STATIC mp_obj_t time_localtime(size_t n_args, const mp_obj_t *args) {
timeutils_struct_time_t tm;
mp_int_t seconds;
+
if (n_args == 0 || args[0] == mp_const_none) {
- // seconds = pyb_rtc_get_us_since_epoch() / 1000 / 1000;
- seconds = mp_obj_get_int(args[0]);
+ rtc_gettime(&tm);
} else {
seconds = mp_obj_get_int(args[0]);
+ timeutils_seconds_since_epoch_to_struct_time(seconds, &tm);
}
- timeutils_seconds_since_epoch_to_struct_time(seconds, &tm);
+
mp_obj_t tuple[8] = {
tuple[0] = mp_obj_new_int(tm.tm_year),
tuple[1] = mp_obj_new_int(tm.tm_mon),
@@ -46,8 +48,8 @@ STATIC mp_obj_t time_localtime(size_t n_args, const mp_obj_t *args) {
tuple[3] = mp_obj_new_int(tm.tm_hour),
tuple[4] = mp_obj_new_int(tm.tm_min),
tuple[5] = mp_obj_new_int(tm.tm_sec),
- tuple[6] = mp_obj_new_int(tm.tm_wday),
- tuple[7] = mp_obj_new_int(tm.tm_yday),
+ tuple[6] = mp_obj_new_int(timeutils_calc_weekday(tm.tm_year, tm.tm_mon, tm.tm_mday)),
+ tuple[7] = mp_obj_new_int(timeutils_year_day(tm.tm_year, tm.tm_mon, tm.tm_mday)),
};
return mp_obj_new_tuple(8, tuple);
}
@@ -72,7 +74,10 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(time_mktime_obj, time_mktime);
// time()
STATIC mp_obj_t time_time(void) {
- mp_raise_NotImplementedError("time");
+ timeutils_struct_time_t tm;
+ rtc_gettime(&tm);
+ return mp_obj_new_int_from_uint(timeutils_mktime(
+ tm.tm_year, tm.tm_mon, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(time_time_obj, time_time);
diff --git a/ports/samd/mpconfigport.h b/ports/samd/mpconfigport.h
index 1625496a2e14..153ad75820a5 100644
--- a/ports/samd/mpconfigport.h
+++ b/ports/samd/mpconfigport.h
@@ -28,6 +28,8 @@
// Board specific definitions
#include "mpconfigboard.h"
+// MCU-Specific definitions
+#include "mpconfigmcu.h"
// Memory allocation policies
#define MICROPY_GC_STACK_ENTRY_TYPE uint16_t
@@ -36,47 +38,42 @@
#define MICROPY_ALLOC_PATH_MAX (256)
#define MICROPY_QSTR_BYTES_IN_HASH (1)
+// MicroPython emitters
+#define MICROPY_PERSISTENT_CODE_LOAD (1)
+
// Compiler configuration
-#define MICROPY_COMP_CONST (0)
+#define MICROPY_COMP_CONST (1)
// Python internal features
#define MICROPY_ENABLE_GC (1)
+#define MICROPY_ENABLE_FINALISER (1)
#define MICROPY_KBD_EXCEPTION (1)
#define MICROPY_HELPER_REPL (1)
+#define MICROPY_REPL_AUTO_INDENT (1)
#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ)
#define MICROPY_ENABLE_SOURCE_LINE (1)
+#define MICROPY_STREAMS_NON_BLOCK (1)
#define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_TERSE)
-#define MICROPY_CPYTHON_COMPAT (0)
-#define MICROPY_CAN_OVERRIDE_BUILTINS (1)
#define MICROPY_PY_BUILTINS_HELP (1)
#define MICROPY_PY_BUILTINS_HELP_TEXT samd_help_text
#define MICROPY_PY_BUILTINS_HELP_MODULES (1)
-
-// fixes sys/usys import issue
+#define MICROPY_ENABLE_SCHEDULER (1)
+#define MICROPY_SCHEDULER_STATIC_NODES (1)
#define MICROPY_MODULE_WEAK_LINKS (1)
+#define MICROPY_HW_ENABLE_USBDEV (1)
+#define MICROPY_HW_USB_CDC_1200BPS_TOUCH (1)
+
// Control over Python builtins
-#define MICROPY_PY_ASYNC_AWAIT (0)
-#define MICROPY_PY_BUILTINS_STR_COUNT (0)
+#define MICROPY_PY_BUILTINS_BYTES_HEX (1)
#define MICROPY_PY_BUILTINS_MEMORYVIEW (1)
-#define MICROPY_PY_BUILTINS_SET (0)
-#define MICROPY_PY_BUILTINS_FROZENSET (0)
-#define MICROPY_PY_BUILTINS_PROPERTY (0)
-#define MICROPY_PY_BUILTINS_ENUMERATE (0)
-#define MICROPY_PY_BUILTINS_FILTER (0)
-#define MICROPY_PY_BUILTINS_REVERSED (0)
-#define MICROPY_PY_BUILTINS_NOTIMPLEMENTED (1)
-#define MICROPY_PY_BUILTINS_MIN_MAX (0)
-#define MICROPY_PY___FILE__ (0)
+#define MICROPY_PY_BUILTINS_INPUT (1)
#define MICROPY_PY_MICROPYTHON_MEM_INFO (1)
#define MICROPY_PY_ARRAY_SLICE_ASSIGN (1)
-#define MICROPY_PY_ATTRTUPLE (0)
-#define MICROPY_PY_COLLECTIONS (0)
#define MICROPY_PY_SYS (1)
#define MICROPY_PY_SYS_PLATFORM "samd"
#define MICROPY_PY_SYS_EXIT (1)
#define MICROPY_PY_SYS_STDFILES (1)
#define MICROPY_PY_SYS_MAXSIZE (1)
-#define MICROPY_PY_IO_FILEIO (1)
#define MICROPY_PY_IO (1)
#define MICROPY_PY_IO_IOBASE (1)
@@ -84,6 +81,7 @@
#define MICROPY_PY_UTIME_MP_HAL (1)
#define MICROPY_PY_MACHINE (1)
#define MICROPY_PY_UOS (1)
+#define MICROPY_PY_UOS_INCLUDEFILE "ports/samd/moduos.c"
#define MICROPY_READER_VFS (1)
#define MICROPY_VFS (1)
#define MICROPY_PY_UJSON (1)
@@ -94,23 +92,50 @@
#define MICROPY_PY_URANDOM (1)
#define MICROPY_PY_UZLIB (1)
#define MICROPY_PY_UASYNCIO (1)
-
-// Use VfsLfs's types for fileio/textio
-#define mp_type_fileio mp_type_vfs_lfs1_fileio
-#define mp_type_textio mp_type_vfs_lfs1_textio
-
-#define MICROPY_PORT_ROOT_POINTERS \
- const char *readline_hist[8];
+#define MICROPY_PY_MACHINE_I2C (1)
+#define MICROPY_PY_MACHINE_RTC (1)
+#define MICROPY_PY_MACHINE_SOFTI2C (1)
+#define MICROPY_PY_MACHINE_SPI (1)
+#define MICROPY_PY_MACHINE_SOFTSPI (1)
+#define MICROPY_HW_SOFTSPI_MIN_DELAY (1)
+#define MICROPY_HW_SOFTSPI_MAX_BAUDRATE (1000000)
+#define MICROPY_PY_MACHINE_TIMER (1)
+#define MICROPY_SOFT_TIMER_TICKS_MS systick_ms
+#define MICROPY_PY_OS_DUPTERM (3)
+#define MICROPY_PY_MACHINE_BITSTREAM (1)
+#define MICROPY_PY_MACHINE_PULSE (1)
+#define MICROPY_PY_MACHINE_PWM (1)
+#define MICROPY_PY_MACHINE_PWM_INIT (0)
+#define MICROPY_PY_MACHINE_PWM_DUTY_U16_NS (1)
+#define MICROPY_PY_MACHINE_PWM_INCLUDEFILE "ports/samd/machine_pwm.c"
+#define MICROPY_PY_MACHINE_PIN_MAKE_NEW mp_pin_make_new
#define MP_STATE_PORT MP_STATE_VM
+// Additional entries for use with pendsv_schedule_dispatch.
+#ifndef MICROPY_BOARD_PENDSV_ENTRIES
+#define MICROPY_BOARD_PENDSV_ENTRIES
+#endif
+
// Miscellaneous settings
+__attribute__((always_inline)) static inline void enable_irq(uint32_t state) {
+ __set_PRIMASK(state);
+}
+
+__attribute__((always_inline)) static inline uint32_t disable_irq(void) {
+ uint32_t state = __get_PRIMASK();
+ __disable_irq();
+ return state;
+}
+
+#define MICROPY_BEGIN_ATOMIC_SECTION() disable_irq()
+#define MICROPY_END_ATOMIC_SECTION(state) enable_irq(state)
#define MICROPY_EVENT_POLL_HOOK \
do { \
extern void mp_handle_pending(bool); \
mp_handle_pending(true); \
- __WFI(); \
+ __WFE(); \
} while (0);
#define MICROPY_MAKE_POINTER_CALLABLE(p) ((void *)((mp_uint_t)(p) | 1))
diff --git a/ports/samd/mphalport.c b/ports/samd/mphalport.c
index c19d542a8556..3dc6b70a8d9e 100644
--- a/ports/samd/mphalport.c
+++ b/ports/samd/mphalport.c
@@ -4,6 +4,7 @@
* The MIT License (MIT)
*
* Copyright (c) 2019 Damien P. George
+ * Copyright (c) 2022 Robert Hammelrath
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -27,61 +28,166 @@
#include "py/runtime.h"
#include "py/mphal.h"
#include "py/stream.h"
+#include "shared/runtime/interrupt_char.h"
+#include "extmod/misc.h"
#include "samd_soc.h"
#include "tusb.h"
-#if MICROPY_KBD_EXCEPTION
+#ifndef MICROPY_HW_STDIN_BUFFER_LEN
+#define MICROPY_HW_STDIN_BUFFER_LEN 128
+#endif
+
+extern volatile uint32_t ticks_us64_upper;
+
+STATIC uint8_t stdin_ringbuf_array[MICROPY_HW_STDIN_BUFFER_LEN];
+ringbuf_t stdin_ringbuf = { stdin_ringbuf_array, sizeof(stdin_ringbuf_array), 0, 0 };
+
+uint8_t cdc_itf_pending; // keep track of cdc interfaces which need attention to poll
+
+void poll_cdc_interfaces(void) {
+ // any CDC interfaces left to poll?
+ if (cdc_itf_pending && ringbuf_free(&stdin_ringbuf)) {
+ for (uint8_t itf = 0; itf < 8; ++itf) {
+ if (cdc_itf_pending & (1 << itf)) {
+ tud_cdc_rx_cb(itf);
+ if (!cdc_itf_pending) {
+ break;
+ }
+ }
+ }
+ }
+}
-void tud_cdc_rx_wanted_cb(uint8_t itf, char wanted_char) {
- (void)itf;
- (void)wanted_char;
- tud_cdc_read_char(); // discard interrupt char
- mp_sched_keyboard_interrupt();
+void tud_cdc_rx_cb(uint8_t itf) {
+ // consume pending USB data immediately to free usb buffer and keep the endpoint from stalling.
+ // in case the ringbuffer is full, mark the CDC interface that need attention later on for polling
+ cdc_itf_pending &= ~(1 << itf);
+ for (uint32_t bytes_avail = tud_cdc_n_available(itf); bytes_avail > 0; --bytes_avail) {
+ if (ringbuf_free(&stdin_ringbuf)) {
+ int data_char = tud_cdc_read_char();
+ #if MICROPY_KBD_EXCEPTION
+ if (data_char == mp_interrupt_char) {
+ // Clear the ring buffer
+ stdin_ringbuf.iget = stdin_ringbuf.iput = 0;
+ // and stop
+ mp_sched_keyboard_interrupt();
+ } else {
+ ringbuf_put(&stdin_ringbuf, data_char);
+ }
+ #else
+ ringbuf_put(&stdin_ringbuf, data_char);
+ #endif
+ } else {
+ cdc_itf_pending |= (1 << itf);
+ return;
+ }
+ }
}
-void mp_hal_set_interrupt_char(int c) {
- tud_cdc_set_wanted_char(c);
+void mp_hal_set_pin_mux(mp_hal_pin_obj_t pin, uint8_t mux) {
+ int pin_grp = pin / 32;
+ int port_grp = (pin % 32) / 2;
+ PORT->Group[pin_grp].PINCFG[pin % 32].bit.PMUXEN = 1; // Enable Mux
+ if (pin & 1) {
+ PORT->Group[pin_grp].PMUX[port_grp].bit.PMUXO = mux;
+ } else {
+ PORT->Group[pin_grp].PMUX[port_grp].bit.PMUXE = mux;
+ }
}
-#endif
+void mp_hal_clr_pin_mux(mp_hal_pin_obj_t pin) {
+ int pin_grp = pin / 32;
+ PORT->Group[pin_grp].PINCFG[pin % 32].bit.PMUXEN = 0; // Disable Mux
+}
void mp_hal_delay_ms(mp_uint_t ms) {
- ms += 1;
- uint32_t t0 = systick_ms;
- while (systick_ms - t0 < ms) {
- MICROPY_EVENT_POLL_HOOK
+ if (ms > 10) {
+ uint32_t t0 = systick_ms;
+ while (systick_ms - t0 < ms) {
+ MICROPY_EVENT_POLL_HOOK
+ }
+ } else {
+ mp_hal_delay_us(ms * 1000);
}
}
void mp_hal_delay_us(mp_uint_t us) {
- uint32_t ms = us / 1000 + 1;
- uint32_t t0 = systick_ms;
- while (systick_ms - t0 < ms) {
- __WFI();
+ if (us > 0) {
+ #if defined(MCU_SAMD21)
+ uint32_t start = mp_hal_ticks_us();
+ while ((mp_hal_ticks_us() - start) < us) {
+ }
+ #else
+ uint64_t stop = mp_hal_ticks_us_64() + us;
+ while (mp_hal_ticks_us_64() < stop) {
+ }
+ #endif
}
}
+uint64_t mp_hal_ticks_us_64(void) {
+ uint32_t us64_upper = ticks_us64_upper;
+ uint32_t us64_lower;
+ uint8_t intflag;
+ __disable_irq();
+ #if defined(MCU_SAMD21)
+ us64_lower = REG_TC4_COUNT32_COUNT;
+ intflag = TC4->COUNT32.INTFLAG.reg;
+ #elif defined(MCU_SAMD51)
+ TC0->COUNT32.CTRLBSET.reg = TC_CTRLBSET_CMD_READSYNC;
+ while (TC0->COUNT32.CTRLBSET.reg != 0) {
+ }
+ us64_lower = REG_TC0_COUNT32_COUNT;
+ intflag = TC0->COUNT32.INTFLAG.reg;
+ #endif
+ __enable_irq();
+ if ((intflag & TC_INTFLAG_OVF) && us64_lower < 0x10000000) {
+ // The timer counter overflowed before reading it but the IRQ handler
+ // has not yet been called, so perform the IRQ arithmetic now.
+ us64_upper++;
+ }
+ #if defined(MCU_SAMD21)
+ return ((uint64_t)us64_upper << 31) | (us64_lower >> 1);
+ #elif defined(MCU_SAMD51)
+ return ((uint64_t)us64_upper << 28) | (us64_lower >> 4);
+ #endif
+
+}
+
uintptr_t mp_hal_stdio_poll(uintptr_t poll_flags) {
uintptr_t ret = 0;
- if (tud_cdc_connected() && tud_cdc_available()) {
+
+ poll_cdc_interfaces();
+ if ((poll_flags & MP_STREAM_POLL_RD) && ringbuf_peek(&stdin_ringbuf) != -1) {
ret |= MP_STREAM_POLL_RD;
}
+
+ if ((poll_flags & MP_STREAM_POLL_WR) && tud_cdc_connected() && tud_cdc_write_available() > 0) {
+ ret |= MP_STREAM_POLL_WR;
+ }
+
+ #if MICROPY_PY_OS_DUPTERM
+ ret |= mp_uos_dupterm_poll(poll_flags);
+ #endif
return ret;
}
int mp_hal_stdin_rx_chr(void) {
for (;;) {
- if (USARTx->USART.INTFLAG.bit.RXC) {
- return USARTx->USART.DATA.bit.DATA;
+
+ poll_cdc_interfaces();
+ int c = ringbuf_get(&stdin_ringbuf);
+ if (c != -1) {
+ return c;
}
- if (tud_cdc_connected() && tud_cdc_available()) {
- uint8_t buf[1];
- uint32_t count = tud_cdc_read(buf, sizeof(buf));
- if (count) {
- return buf[0];
- }
+
+ #if MICROPY_PY_OS_DUPTERM
+ int dupterm_c = mp_uos_dupterm_rx_chr();
+ if (dupterm_c >= 0) {
+ return dupterm_c;
}
- __WFI();
+ #endif
+ MICROPY_EVENT_POLL_HOOK
}
}
@@ -92,17 +198,20 @@ void mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) {
if (n > CFG_TUD_CDC_EP_BUFSIZE) {
n = CFG_TUD_CDC_EP_BUFSIZE;
}
- while (n > tud_cdc_write_available()) {
- __WFI();
+ int timeout = 0;
+ // Wait with a max of USC_CDC_TIMEOUT ms
+ while (n > tud_cdc_write_available() && timeout++ < MICROPY_HW_USB_CDC_TX_TIMEOUT) {
+ MICROPY_EVENT_POLL_HOOK
+ }
+ if (timeout >= MICROPY_HW_USB_CDC_TX_TIMEOUT) {
+ break;
}
uint32_t n2 = tud_cdc_write(str + i, n);
tud_cdc_write_flush();
i += n2;
}
}
- while (len--) {
- while (!(USARTx->USART.INTFLAG.bit.DRE)) {
- }
- USARTx->USART.DATA.bit.DATA = *str++;
- }
+ #if MICROPY_PY_OS_DUPTERM
+ mp_uos_dupterm_tx_strn(str, len);
+ #endif
}
diff --git a/ports/samd/mphalport.h b/ports/samd/mphalport.h
index 2bbde4390e33..83ccf44222d3 100644
--- a/ports/samd/mphalport.h
+++ b/ports/samd/mphalport.h
@@ -4,6 +4,7 @@
* The MIT License (MIT)
*
* Copyright (c) 2019-2021 Damien P. George
+ * Copyright (c) 2022 Robert Hammelrath
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -26,26 +27,54 @@
#ifndef MICROPY_INCLUDED_SAMD_MPHALPORT_H
#define MICROPY_INCLUDED_SAMD_MPHALPORT_H
-#include "py/mpconfig.h"
#include "py/ringbuf.h"
+#include "py/mpconfig.h"
// ASF4
#include "hal_gpio.h"
+#include "hpl_time_measure.h"
+#include "sam.h"
+
+#define MICROPY_HW_USB_CDC_TX_TIMEOUT (500)
extern int mp_interrupt_char;
-extern ringbuf_t stdin_ringbuf;
extern volatile uint32_t systick_ms;
+uint64_t mp_hal_ticks_us_64(void);
void mp_hal_set_interrupt_char(int c);
+#define mp_hal_delay_us_fast mp_hal_delay_us
+
+static inline uint64_t mp_hal_ticks_ms_64(void) {
+ return mp_hal_ticks_us_64() / 1000;
+}
+
static inline mp_uint_t mp_hal_ticks_ms(void) {
- return systick_ms;
+ return (mp_uint_t)mp_hal_ticks_ms_64();
}
+
static inline mp_uint_t mp_hal_ticks_us(void) {
- return systick_ms * 1000;
+ return (mp_uint_t)mp_hal_ticks_us_64();
}
+
+#if defined(MCU_SAMD21)
+
+#define mp_hal_ticks_cpu mp_hal_ticks_us
+
+#elif defined(MCU_SAMD51)
+static inline void mp_hal_ticks_cpu_enable(void) {
+ CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
+ DWT->CYCCNT = 0;
+ DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;
+}
+
static inline mp_uint_t mp_hal_ticks_cpu(void) {
- return 0;
+ return (system_time_t)DWT->CYCCNT;
+}
+#endif
+
+static inline uint64_t mp_hal_time_ns(void) {
+ return mp_hal_ticks_us_64() * 1000;
}
// C-level pin HAL
@@ -55,9 +84,14 @@ static inline mp_uint_t mp_hal_ticks_cpu(void) {
#define MP_HAL_PIN_FMT "%u"
#define mp_hal_pin_obj_t uint
-extern uint32_t machine_pin_open_drain_mask;
+#define mp_hal_quiet_timing_enter() MICROPY_BEGIN_ATOMIC_SECTION()
+#define mp_hal_quiet_timing_exit(irq_state) MICROPY_END_ATOMIC_SECTION(irq_state)
+
+extern uint32_t machine_pin_open_drain_mask[];
mp_hal_pin_obj_t mp_hal_get_pin_obj(mp_obj_t pin_in);
+void mp_hal_set_pin_mux(mp_hal_pin_obj_t pin, uint8_t mux);
+void mp_hal_clr_pin_mux(mp_hal_pin_obj_t pin);
static inline unsigned int mp_hal_pin_name(mp_hal_pin_obj_t pin) {
return pin;
@@ -65,18 +99,32 @@ static inline unsigned int mp_hal_pin_name(mp_hal_pin_obj_t pin) {
static inline void mp_hal_pin_input(mp_hal_pin_obj_t pin) {
gpio_set_pin_direction(pin, GPIO_DIRECTION_IN);
- machine_pin_open_drain_mask &= ~(1 << pin);
+ machine_pin_open_drain_mask[pin / 32] &= ~(1 << (pin % 32));
}
static inline void mp_hal_pin_output(mp_hal_pin_obj_t pin) {
gpio_set_pin_direction(pin, GPIO_DIRECTION_OUT);
- machine_pin_open_drain_mask &= ~(1 << pin);
+ machine_pin_open_drain_mask[pin / 32] &= ~(1 << (pin % 32));
}
static inline void mp_hal_pin_open_drain(mp_hal_pin_obj_t pin) {
gpio_set_pin_direction(pin, GPIO_DIRECTION_IN);
- gpio_set_pin_level(pin, 0);
- machine_pin_open_drain_mask |= 1 << pin;
+ gpio_set_pin_pull_mode(pin, GPIO_PULL_UP);
+ machine_pin_open_drain_mask[pin / 32] |= 1 << (pin % 32);
+}
+
+static inline unsigned int mp_hal_get_pin_direction(mp_hal_pin_obj_t pin) {
+ return (PORT->Group[pin / 32].DIR.reg & (1 << (pin % 32))) ?
+ GPIO_DIRECTION_OUT : GPIO_DIRECTION_IN;
+}
+
+static inline unsigned int mp_hal_get_pull_mode(mp_hal_pin_obj_t pin) {
+ bool pull_en = (PORT->Group[pin / 32].PINCFG[pin % 32].reg & PORT_PINCFG_PULLEN) != 0;
+ if (pull_en) {
+ return gpio_get_pin_level(pin) ? GPIO_PULL_UP : GPIO_PULL_DOWN;
+ } else {
+ return GPIO_PULL_OFF;
+ }
}
static inline int mp_hal_pin_read(mp_hal_pin_obj_t pin) {
@@ -87,14 +135,22 @@ static inline void mp_hal_pin_write(mp_hal_pin_obj_t pin, int v) {
gpio_set_pin_level(pin, v);
}
-/*
+static inline void mp_hal_pin_low(mp_hal_pin_obj_t pin) {
+ gpio_set_pin_level(pin, 0);
+}
+
+static inline void mp_hal_pin_high(mp_hal_pin_obj_t pin) {
+ gpio_set_pin_level(pin, 1);
+}
+
static inline void mp_hal_pin_od_low(mp_hal_pin_obj_t pin) {
gpio_set_pin_direction(pin, GPIO_DIRECTION_OUT);
+ gpio_set_pin_level(pin, 0);
}
static inline void mp_hal_pin_od_high(mp_hal_pin_obj_t pin) {
gpio_set_pin_direction(pin, GPIO_DIRECTION_IN);
+ gpio_set_pin_pull_mode(pin, GPIO_PULL_UP);
}
-*/
#endif // MICROPY_INCLUDED_SAMD_MPHALPORT_H
diff --git a/examples/embedding/hello-embed.c b/ports/samd/pendsv.c
similarity index 51%
rename from examples/embedding/hello-embed.c
rename to ports/samd/pendsv.c
index 0b778986b3a5..00dd6068d1e1 100644
--- a/examples/embedding/hello-embed.c
+++ b/ports/samd/pendsv.c
@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2016 Paul Sokolovsky
+ * Copyright (c) 2013, 2014 Damien P. George
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -24,53 +24,48 @@
* THE SOFTWARE.
*/
-#include
-#include
#include
-#include "py/builtin.h"
-#include "py/compile.h"
#include "py/runtime.h"
-#include "py/gc.h"
-#include "py/stackctrl.h"
+#include "shared/runtime/interrupt_char.h"
+#include "sam.h"
+#include "pendsv.h"
-static char heap[16384];
-mp_obj_t execute_from_str(const char *str) {
- nlr_buf_t nlr;
- if (nlr_push(&nlr) == 0) {
- qstr src_name = 1/*MP_QSTR_*/;
- mp_lexer_t *lex = mp_lexer_new_from_str_len(src_name, str, strlen(str), false);
- mp_parse_tree_t pt = mp_parse(lex, MP_PARSE_FILE_INPUT);
- mp_obj_t module_fun = mp_compile(&pt, src_name, false);
- mp_call_function_0(module_fun);
- nlr_pop();
- return 0;
- } else {
- // uncaught exception
- return (mp_obj_t)nlr.ret_val;
- }
-}
+#if defined(PENDSV_DISPATCH_NUM_SLOTS)
+uint32_t pendsv_dispatch_active;
+pendsv_dispatch_t pendsv_dispatch_table[PENDSV_DISPATCH_NUM_SLOTS];
+#endif
-int main() {
- // Initialized stack limit
- mp_stack_set_limit(40000 * (sizeof(void *) / 4));
- // Initialize heap
- gc_init(heap, heap + sizeof(heap));
- // Initialize interpreter
- mp_init();
+void pendsv_init(void) {
+ #if defined(PENDSV_DISPATCH_NUM_SLOTS)
+ pendsv_dispatch_active = false;
+ #endif
- const char str[] = "print('Hello world of easy embedding!')";
- if (execute_from_str(str)) {
- printf("Error\n");
- }
+ // set PendSV interrupt at lowest priority
+ NVIC_SetPriority(PendSV_IRQn, IRQ_PRI_PENDSV);
}
-uint mp_import_stat(const char *path) {
- return MP_IMPORT_STAT_NO_EXIST;
+#if defined(PENDSV_DISPATCH_NUM_SLOTS)
+void pendsv_schedule_dispatch(size_t slot, pendsv_dispatch_t f) {
+ pendsv_dispatch_table[slot] = f;
+ pendsv_dispatch_active = true;
+ SCB->ICSR = SCB_ICSR_PENDSVSET_Msk;
}
-void nlr_jump_fail(void *val) {
- printf("FATAL: uncaught NLR %p\n", val);
- exit(1);
+void pendsv_dispatch_handler(void) {
+ for (size_t i = 0; i < PENDSV_DISPATCH_NUM_SLOTS; ++i) {
+ if (pendsv_dispatch_table[i] != NULL) {
+ pendsv_dispatch_t f = pendsv_dispatch_table[i];
+ pendsv_dispatch_table[i] = NULL;
+ f();
+ }
+ }
+}
+
+void PendSV_Handler(void) {
+ if (pendsv_dispatch_active) {
+ pendsv_dispatch_handler();
+ }
}
+#endif
diff --git a/ports/samd/pendsv.h b/ports/samd/pendsv.h
new file mode 100644
index 000000000000..6671fa4e28a8
--- /dev/null
+++ b/ports/samd/pendsv.h
@@ -0,0 +1,42 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2013, 2014 Damien P. George
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#ifndef MICROPY_INCLUDED_SAMD_PENDSV_H
+#define MICROPY_INCLUDED_SAMD_PENDSV_H
+
+enum {
+ PENDSV_DISPATCH_SOFT_TIMER, // For later & for having at least one entry
+ MICROPY_BOARD_PENDSV_ENTRIES
+ PENDSV_DISPATCH_MAX
+};
+
+#define PENDSV_DISPATCH_NUM_SLOTS PENDSV_DISPATCH_MAX
+
+typedef void (*pendsv_dispatch_t)(void);
+
+void pendsv_init(void);
+void pendsv_schedule_dispatch(size_t slot, pendsv_dispatch_t f);
+
+#endif // MICROPY_INCLUDED_SAMD_PENDSV_H
diff --git a/ports/samd/pin_af.c b/ports/samd/pin_af.c
new file mode 100644
index 000000000000..d92a62b70024
--- /dev/null
+++ b/ports/samd/pin_af.c
@@ -0,0 +1,199 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2022 Robert Hammelrath
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * This file provides and checks pin capabilities as required
+ * for USART, I2C, SPI, PWM, ADC
+ *
+ */
+
+#include
+#include "string.h"
+
+#include "modmachine.h"
+#include "py/runtime.h"
+#include "py/misc.h"
+#include "pin_af.h"
+#include "sam.h"
+
+
+extern const uint8_t tcc_channel_count[];
+
+#include "pin_af_table.c"
+
+// Just look for an table entry for a given pin and raise an error
+// in case of no match (which should not happen).
+
+const machine_pin_obj_t *get_pin_obj_ptr(int pin_id) {
+ for (int i = 0; i < MP_ARRAY_SIZE(pin_af_table); i++) {
+ if (pin_af_table[i]->pin_id == pin_id) { // Pin match
+ return pin_af_table[i];
+ }
+ }
+ mp_raise_ValueError(MP_ERROR_TEXT("not a Pin"));
+}
+
+#if MICROPY_PY_MACHINE_PIN_BOARD_CPU
+STATIC const machine_pin_obj_t *pin_find_named_pin(const mp_obj_dict_t *named_pins, mp_obj_t name) {
+ mp_map_t *named_map = mp_obj_dict_get_map((mp_obj_t)named_pins);
+ mp_map_elem_t *named_elem = mp_map_lookup(named_map, name, MP_MAP_LOOKUP);
+ if (named_elem != NULL && named_elem->value != NULL) {
+ return named_elem->value;
+ }
+ return NULL;
+}
+#endif
+
+const machine_pin_obj_t *pin_find(mp_obj_t pin) {
+ // Is already a object of the proper type
+ if (mp_obj_is_type(pin, &machine_pin_type)) {
+ return pin;
+ }
+ if (mp_obj_is_small_int(pin)) {
+ // Pin defined by pin number for PAnn, PBnn, etc.
+ return get_pin_obj_ptr(mp_obj_get_int(pin));
+ }
+
+ #if MICROPY_PY_MACHINE_PIN_BOARD_CPU
+ const machine_pin_obj_t *self = NULL;
+ // See if the pin name matches a board pin
+ self = pin_find_named_pin(&machine_pin_board_pins_locals_dict, pin);
+ if (self != NULL) {
+ return self;
+ }
+ // See if the pin name matches a cpu pin
+ self = pin_find_named_pin(&machine_pin_cpu_pins_locals_dict, pin);
+ if (self != NULL) {
+ return self;
+ }
+ #else
+ if (mp_obj_is_str(pin)) {
+ // Search by name
+ size_t slen;
+ const char *s = mp_obj_str_get_data(pin, &slen);
+ // Check for a string like PA02 or PD12
+ if (slen == 4 && s[0] == 'P' && strchr("ABCD", s[1]) != NULL &&
+ strchr("0123456789", s[2]) != NULL && strchr("0123456789", s[2]) != NULL) {
+ int num = (s[1] - 'A') * 32 + (s[2] - '0') * 10 + (s[3] - '0');
+ return get_pin_obj_ptr(num);
+ } else {
+ for (int i = 0; i < MP_ARRAY_SIZE(pin_af_table); i++) {
+ size_t len;
+ const char *name = (char *)qstr_data(pin_af_table[i]->name, &len);
+ if (slen == len && strncmp(s, name, slen) == 0) {
+ return pin_af_table[i];
+ }
+ }
+ }
+ }
+ #endif // MICROPY_PY_MACHINE_PIN_BOARD_CPU
+
+ mp_raise_ValueError(MP_ERROR_TEXT("not a Pin"));
+}
+
+const char *pin_name(int id) {
+ for (int i = 0; i < sizeof(pin_af_table); i++) {
+ if (pin_af_table[i]->pin_id == id) {
+ return qstr_str(pin_af_table[i]->name);
+ }
+ }
+ return "-";
+}
+
+// Test, wether the given pin is defined and has signals for sercom.
+// If that applies return the alt_fct and pad_nr.
+// If not, an error will be raised.
+
+sercom_pad_config_t get_sercom_config(int pin_id, uint8_t sercom_nr) {
+ const machine_pin_obj_t *pct_ptr = get_pin_obj_ptr(pin_id);
+ if ((pct_ptr->sercom1 >> 4) == sercom_nr) {
+ return (sercom_pad_config_t) {ALT_FCT_SERCOM1, pct_ptr->sercom1 & 0x0f};
+ } else if ((pct_ptr->sercom2 >> 4) == sercom_nr) {
+ return (sercom_pad_config_t) {ALT_FCT_SERCOM2, pct_ptr->sercom2 & 0x0f};
+ } else {
+ mp_raise_ValueError(MP_ERROR_TEXT("wrong serial device"));
+ }
+}
+
+// Test, wether the given pin is defined as ADC.
+// If that applies return the adc instance and channel.
+// If not, an error will be raised.
+
+adc_config_t get_adc_config(int pin_id, int32_t flag) {
+ const machine_pin_obj_t *pct_ptr = get_pin_obj_ptr(pin_id);
+ #if defined(MCU_SAMD51)
+ if (pct_ptr->adc1 != 0xff && (flag & (1 << (pct_ptr->adc1 + 16))) == 0) {
+ return (adc_config_t) {1, pct_ptr->adc1};
+ } else
+ #endif
+ if (pct_ptr->adc0 != 0xff && (flag & (1 << pct_ptr->adc0)) == 0) {
+ return (adc_config_t) {0, pct_ptr->adc0};
+ #if defined(MUC_SAMD51)
+ } else if (pct_ptr->adc1 != 0xff && (flag & (1 << (pct_ptr->adc1 + 16))) == 0) {
+ return (adc_config_t) {1, pct_ptr->adc1};
+ #endif
+ } else {
+ mp_raise_ValueError(MP_ERROR_TEXT("ADC pin used"));
+ }
+}
+
+// Test, wether the given pin is defined and has signals for pwm.
+// If that applies return the alt_fct, tcc number and channel number.
+// If not, an error will be raised.
+// The function either supplies a channel from a wanted device, or
+// tries to provide an unused device, if available.
+
+pwm_config_t get_pwm_config(int pin_id, int wanted_dev, uint8_t device_status[]) {
+ const machine_pin_obj_t *pct_ptr = get_pin_obj_ptr(pin_id);
+ uint8_t tcc1 = pct_ptr->tcc1;
+ uint8_t tcc2 = pct_ptr->tcc2;
+
+ if (wanted_dev != -1) {
+ if ((tcc1 >> 4) == wanted_dev) {
+ return (pwm_config_t) {ALT_FCT_TCC1, tcc1};
+ } else if ((tcc2 >> 4) == wanted_dev) {
+ return (pwm_config_t) {ALT_FCT_TCC2, tcc2};
+ } else {
+ mp_raise_ValueError(MP_ERROR_TEXT("wrong device or channel"));
+ }
+ } else {
+ pwm_config_t ret = {};
+ if ((tcc1 >> 4) < TCC_INST_NUM) {
+ ret = (pwm_config_t) {ALT_FCT_TCC1, tcc1};
+ if (tcc2 == 0xff) {
+ return ret;
+ }
+ }
+ if ((tcc2 >> 4) < TCC_INST_NUM) {
+ // if a device in slot 1 is not available or already in use, use the one in slot 2
+ if (tcc1 == 0xff || device_status[(ret.device_channel >> 4)] != 0) {
+ return (pwm_config_t) {ALT_FCT_TCC2, tcc2};
+ } else {
+ return ret;
+ }
+ } else {
+ mp_raise_ValueError(MP_ERROR_TEXT("not a PWM pin"));
+ }
+ }
+}
diff --git a/ports/samd/pin_af.h b/ports/samd/pin_af.h
new file mode 100644
index 000000000000..edab72aaed6a
--- /dev/null
+++ b/ports/samd/pin_af.h
@@ -0,0 +1,102 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2022 Robert Hammelrath
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * This file initialises provides and checks pin capabilities as required
+ * for USART, I2C, SPI, PWM, ADC
+ *
+ */
+
+#if defined(MCU_SAMD21)
+
+typedef struct _machine_pin_obj_t {
+ mp_obj_base_t base;
+ uint8_t pin_id;
+ qstr name;
+ uint8_t eic;
+ uint8_t adc0;
+ uint8_t sercom1;
+ uint8_t sercom2;
+ uint8_t tcc1;
+ uint8_t tcc2;
+} machine_pin_obj_t;
+
+#define ALT_FCT_TC 4
+#define ALT_FCT_TCC1 4
+#define ALT_FCT_TCC2 5
+
+#elif defined(MCU_SAMD51)
+
+typedef struct _machine_pin_obj_t {
+ mp_obj_base_t base;
+ uint8_t pin_id;
+ qstr name;
+ uint8_t eic;
+ uint8_t adc0;
+ uint8_t adc1;
+ uint8_t sercom1;
+ uint8_t sercom2;
+ uint8_t tc;
+ uint8_t tcc1;
+ uint8_t tcc2;
+} machine_pin_obj_t;
+
+#define ALT_FCT_TC 4
+#define ALT_FCT_TCC1 5
+#define ALT_FCT_TCC2 6
+
+#endif
+
+typedef struct _sercom_pad_config_t {
+ uint8_t alt_fct;
+ uint8_t pad_nr;
+} sercom_pad_config_t;
+
+typedef struct _adc_config_t {
+ uint8_t device;
+ uint8_t channel;
+} adc_config_t;
+
+typedef struct _pwm_config_t {
+ uint8_t alt_fct;
+ uint8_t device_channel;
+} pwm_config_t;
+
+#define ALT_FCT_EIC 0
+#define ALT_FCT_ADC 1
+#define ALT_FCT_DAC 1
+#define ALT_FCT_SERCOM1 2
+#define ALT_FCT_SERCOM2 3
+
+#if MICROPY_PY_MACHINE_PIN_BOARD_CPU
+extern const mp_obj_dict_t machine_pin_cpu_pins_locals_dict;
+extern const mp_obj_dict_t machine_pin_board_pins_locals_dict;
+#endif
+
+sercom_pad_config_t get_sercom_config(int pin_id, uint8_t sercom);
+adc_config_t get_adc_config(int pin_id, int32_t flag);
+pwm_config_t get_pwm_config(int pin_id, int wanted_dev, uint8_t used_dev[]);
+const machine_pin_obj_t *get_pin_obj_ptr(int pin_id);
+const char *pin_name(int id);
+const machine_pin_obj_t *pin_find(mp_obj_t pin);
diff --git a/ports/samd/samd_flash.c b/ports/samd/samd_flash.c
index 530e3d9c8e5b..6d9ee96895b0 100644
--- a/ports/samd/samd_flash.c
+++ b/ports/samd/samd_flash.c
@@ -53,11 +53,13 @@ typedef struct _samd_flash_obj_t {
uint32_t flash_size;
} samd_flash_obj_t;
+extern uint8_t _oflash_fs, _sflash_fs;
+
// Build a Flash storage at top.
STATIC samd_flash_obj_t samd_flash_obj = {
.base = { &samd_flash_type },
- .flash_base = MICROPY_HW_FLASH_STORAGE_BASE, // Board specific: mpconfigboard.h
- .flash_size = MICROPY_HW_FLASH_STORAGE_BYTES, // Board specific: mpconfigboard.h
+ .flash_base = (uint32_t)&_oflash_fs, // Get from MCU-Specific loader script.
+ .flash_size = (uint32_t)&_sflash_fs, // Get from MCU-Specific loader script.
};
// FLASH stuff
@@ -96,21 +98,17 @@ STATIC mp_obj_t eraseblock(uint32_t sector_in) {
}
STATIC mp_obj_t samd_flash_version(void) {
- printf("Flash Driver Version: %lu\n", flash_get_version());
- return mp_const_none;
+ return MP_OBJ_NEW_SMALL_INT(flash_get_version());
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(samd_flash_version_obj, samd_flash_version);
-STATIC MP_DEFINE_CONST_STATICMETHOD_OBJ(samd_flash_version_static_obj, MP_ROM_PTR(&samd_flash_version_obj));
STATIC mp_obj_t samd_flash_size(void) {
// ASF4 API calls
mp_int_t PAGES = flash_get_total_pages(&flash_desc);
mp_int_t PAGE_SIZE = flash_get_page_size(&flash_desc);
- printf("Flash Size: %u Bytes\n", PAGES * PAGE_SIZE);
- return mp_const_none;
+ return MP_OBJ_NEW_SMALL_INT(PAGES * PAGE_SIZE);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(samd_flash_size_obj, samd_flash_size);
-STATIC MP_DEFINE_CONST_STATICMETHOD_OBJ(samd_flash_size_static_obj, MP_ROM_PTR(&samd_flash_size_obj));
STATIC mp_obj_t samd_flash_readblocks(size_t n_args, const mp_obj_t *args) {
uint32_t offset = (mp_obj_get_int(args[1]) * BLOCK_SIZE) + samd_flash_obj.flash_base;
@@ -172,8 +170,8 @@ STATIC mp_obj_t samd_flash_ioctl(mp_obj_t self_in, mp_obj_t cmd_in, mp_obj_t arg
STATIC MP_DEFINE_CONST_FUN_OBJ_3(samd_flash_ioctl_obj, samd_flash_ioctl);
STATIC const mp_rom_map_elem_t samd_flash_locals_dict_table[] = {
- { MP_ROM_QSTR(MP_QSTR_flash_version), MP_ROM_PTR(&samd_flash_version_static_obj) },
- { MP_ROM_QSTR(MP_QSTR_flash_size), MP_ROM_PTR(&samd_flash_size_static_obj) },
+ { MP_ROM_QSTR(MP_QSTR_flash_version), MP_ROM_PTR(&samd_flash_version_obj) },
+ { MP_ROM_QSTR(MP_QSTR_flash_size), MP_ROM_PTR(&samd_flash_size_obj) },
{ MP_ROM_QSTR(MP_QSTR_flash_init), MP_ROM_PTR(&samd_flash_init_obj) },
{ MP_ROM_QSTR(MP_QSTR_readblocks), MP_ROM_PTR(&samd_flash_readblocks_obj) },
{ MP_ROM_QSTR(MP_QSTR_writeblocks), MP_ROM_PTR(&samd_flash_writeblocks_obj) },
@@ -181,9 +179,10 @@ STATIC const mp_rom_map_elem_t samd_flash_locals_dict_table[] = {
};
STATIC MP_DEFINE_CONST_DICT(samd_flash_locals_dict, samd_flash_locals_dict_table);
-const mp_obj_type_t samd_flash_type = {
- { &mp_type_type },
- .name = MP_QSTR_Flash,
- .make_new = samd_flash_make_new,
- .locals_dict = (mp_obj_dict_t *)&samd_flash_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ samd_flash_type,
+ MP_QSTR_Flash,
+ MP_TYPE_FLAG_NONE,
+ make_new, samd_flash_make_new,
+ locals_dict, &samd_flash_locals_dict
+ );
diff --git a/ports/samd/samd_isr.c b/ports/samd/samd_isr.c
index dcf80d28cab0..a12140313b24 100644
--- a/ports/samd/samd_isr.c
+++ b/ports/samd/samd_isr.c
@@ -24,14 +24,27 @@
* THE SOFTWARE.
*/
+#include "py/runtime.h"
+#include "py/mphal.h"
#include "samd_soc.h"
+#include "pendsv.h"
+#include "shared/runtime/softtimer.h"
+
typedef void (*ISR)(void);
extern uint32_t _estack, _sidata, _sdata, _edata, _sbss, _ebss;
+extern void Default_Handler(void);
+extern void SysTick_Handler(void);
+extern void PendSV_Handler(void);
+extern void EIC_Handler(void);
const ISR isr_vector[];
-uint32_t systick_ms;
+volatile uint32_t systick_ms;
+volatile uint32_t ticks_us64_upper;
+#if defined(MCU_SAMD21)
+volatile uint32_t rng_state;
+#endif
void Reset_Handler(void) __attribute__((naked));
void Reset_Handler(void) {
@@ -81,9 +94,125 @@ void Default_Handler(void) {
}
void SysTick_Handler(void) {
- systick_ms += 1;
+ #if defined(MCU_SAMD21)
+ // Use the phase jitter between the clocks to get some entropy
+ // and accumulate the random number register with a "spiced" LCG.
+ rng_state = (rng_state * 32310901 + 1) ^ (REG_TC4_COUNT32_COUNT >> 1);
+ #endif
+
+ uint32_t next_tick = systick_ms + 1;
+ systick_ms = next_tick;
+
+ if (soft_timer_next == next_tick) {
+ pendsv_schedule_dispatch(PENDSV_DISPATCH_SOFT_TIMER, soft_timer_handler);
+ }
+}
+
+void us_timer_IRQ(void) {
+ #if defined(MCU_SAMD21)
+ if (TC4->COUNT32.INTFLAG.reg & TC_INTFLAG_OVF) {
+ ticks_us64_upper++;
+ }
+ TC4->COUNT32.INTFLAG.reg = TC_INTFLAG_OVF;
+ #elif defined(MCU_SAMD51)
+ if (TC0->COUNT32.INTFLAG.reg & TC_INTFLAG_OVF) {
+ ticks_us64_upper++;
+ }
+ TC0->COUNT32.INTFLAG.reg = TC_INTFLAG_OVF;
+ #endif
+}
+
+// Sercom IRQ handler support
+void (*sercom_irq_handler_table[SERCOM_INST_NUM])(int num) = {};
+
+void sercom_register_irq(int sercom_id, void (*sercom_irq_handler)) {
+ if (sercom_id < SERCOM_INST_NUM) {
+ sercom_irq_handler_table[sercom_id] = sercom_irq_handler;
+ }
+}
+
+static inline void common_sercom_irq_handler(int sercom_id) {
+ if (sercom_irq_handler_table[sercom_id]) {
+ sercom_irq_handler_table[sercom_id](sercom_id);
+ }
+}
+
+void Sercom0_Handler(void) {
+ common_sercom_irq_handler(0);
+}
+void Sercom1_Handler(void) {
+ common_sercom_irq_handler(1);
}
+void Sercom2_Handler(void) {
+ common_sercom_irq_handler(2);
+}
+void Sercom3_Handler(void) {
+ common_sercom_irq_handler(3);
+}
+void Sercom4_Handler(void) {
+ common_sercom_irq_handler(4);
+}
+void Sercom5_Handler(void) {
+ common_sercom_irq_handler(5);
+}
+#if defined(MCU_SAMD51)
+void Sercom6_Handler(void) {
+ common_sercom_irq_handler(6);
+}
+void Sercom7_Handler(void) {
+ common_sercom_irq_handler(7);
+}
+#endif
+#if defined(MCU_SAMD21)
+const ISR isr_vector[] __attribute__((section(".isr_vector"))) = {
+ (ISR)&_estack,
+ &Reset_Handler,
+ &Default_Handler, // NMI_Handler
+ &Default_Handler, // HardFault_Handler
+ &Default_Handler, // MemManage_Handler
+ &Default_Handler, // BusFault_Handler
+ &Default_Handler, // UsageFault_Handler
+ 0,
+ 0,
+ 0,
+ 0,
+ &Default_Handler, // SVC_Handler
+ &Default_Handler, // DebugMon_Handler
+ 0,
+ &PendSV_Handler, // PendSV_Handler
+ &SysTick_Handler, // SysTick_Handler
+ 0, // 0 Power Manager (PM)
+ 0, // 1 System Control (SYSCTRL)
+ 0, // 2 Watchdog Timer (WDT)
+ 0, // 3 Real-Time Counter (RTC)
+ &EIC_Handler, // 4 External Interrupt Controller (EIC)
+ 0, // 5 Non-Volatile Memory Controller (NVMCTRL)
+ 0, // 6 Direct Memory Access Controller (DMAC)
+ USB_Handler_wrapper,// 7 Universal Serial Bus (USB)
+ 0, // 8 Event System Interface (EVSYS)
+ &Sercom0_Handler, // 9 Serial Communication Interface 0 (SERCOM0)
+ &Sercom1_Handler, // 10 SAMD21G18A Serial Communication Interface 1 (SERCOM1)
+ &Sercom2_Handler, // 11 SAMD21G18A Serial Communication Interface 2 (SERCOM2)
+ &Sercom3_Handler, // 12 SAMD21G18A Serial Communication Interface 3 (SERCOM3)
+ &Sercom4_Handler, // 13 SAMD21G18A Serial Communication Interface 4 (SERCOM4)
+ &Sercom5_Handler, // 14 SAMD21G18A Serial Communication Interface 5 (SERCOM5)
+ 0, // 15 Timer Counter Control 0 (TCC0)
+ 0, // 16 Timer Counter Control 1 (TCC1)
+ 0, // 17 Timer Counter Control 2 (TCC2)
+ 0, // 18 Basic Timer Counter 3 (TC3)
+ &us_timer_IRQ, // 19 Basic Timer Counter 4 (TC4)
+ 0, // 20 Basic Timer Counter 5 (TC5)
+ 0, // 21 Basic Timer Counter 6 (TC6)
+ 0, // 22 Basic Timer Counter 7 (TC7)
+ 0, // 23 Analog Digital Converter (ADC)
+ 0, // 24 Analog Comparators (AC)
+ 0, // 25 Digital Analog Converter (DAC)
+ 0, // 26 Peripheral Touch Controller (PTC)
+ 0, // 27 Inter-IC Sound Interface (I2S)
+
+};
+#else
const ISR isr_vector[] __attribute__((section(".isr_vector"))) = {
(ISR)&_estack,
&Reset_Handler,
@@ -99,154 +228,144 @@ const ISR isr_vector[] __attribute__((section(".isr_vector"))) = {
&Default_Handler, // SVC_Handler
&Default_Handler, // DebugMon_Handler
0,
- &Default_Handler, // PendSV_Handler
+ &PendSV_Handler, // PendSV_Handler
&SysTick_Handler, // SysTick_Handler
- 0, // line 0
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- #if defined(MCU_SAMD21)
- USB_Handler_wrapper, // line 7
- #else
- 0,
- #endif
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- #if defined(MCU_SAMD51)
- &USB_0_Handler_wrapper, // line 80
- &USB_1_Handler_wrapper,
- &USB_2_Handler_wrapper,
- &USB_3_Handler_wrapper,
- #else
- 0,
- 0,
- 0,
- 0,
- #endif
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
+ 0, // 0 Power Manager (PM)
+ 0, // 1 Main Clock (MCLK)
+ 0, // 2 Oscillators Control (OSCCTRL): OSCCTRL_XOSCFAIL_0, OSCCTRL_XOSCRDY_0
+ 0, // 3 Oscillators Control (OSCCTRL): OSCCTRL_XOSCFAIL_1, OSCCTRL_XOSCRDY_1
+ 0, // 4 Oscillators Control (OSCCTRL): OSCCTRL_DFLLLOCKC, OSCCTRL_DFLLLOCKF, OSCCTRL_DFLLOOB, OSCCTRL_DFLLRCS, OSCCTRL_DFLLRDY
+ 0, // 5 Oscillators Control (OSCCTRL): OSCCTRL_DPLLLCKF_0, OSCCTRL_DPLLLCKR_0, OSCCTRL_DPLLLDRTO_0, OSCCTRL_DPLLLTO_0
+ 0, // 6 Oscillators Control (OSCCTRL): OSCCTRL_DPLLLCKF_1, OSCCTRL_DPLLLCKR_1, OSCCTRL_DPLLLDRTO_1, OSCCTRL_DPLLLTO_1
+ 0, // 7 32kHz Oscillators Control (OSC32KCTRL)
+ 0, // 8 Supply Controller (SUPC): SUPC_B12SRDY, SUPC_B33SRDY, SUP
+ 0, // 9 Supply Controller (SUPC): SUPC_BOD12DET, SUPC_BOD33DET
+ 0, // 10 Watchdog Timer (WDT)
+ 0, // 11 Real-Time Counter (RTC)
+ &EIC_Handler, // 12 External Interrupt Controller (EIC): EIC_EXTINT_0
+ &EIC_Handler, // 13 External Interrupt Controller (EIC): EIC_EXTINT_1
+ &EIC_Handler, // 14 External Interrupt Controller (EIC): EIC_EXTINT_2
+ &EIC_Handler, // 15 External Interrupt Controller (EIC): EIC_EXTINT_3
+ &EIC_Handler, // 16 External Interrupt Controller (EIC): EIC_EXTINT_4
+ &EIC_Handler, // 17 External Interrupt Controller (EIC): EIC_EXTINT_5
+ &EIC_Handler, // 18 External Interrupt Controller (EIC): EIC_EXTINT_6
+ &EIC_Handler, // 19 External Interrupt Controller (EIC): EIC_EXTINT_7
+ &EIC_Handler, // 20 External Interrupt Controller (EIC): EIC_EXTINT_8
+ &EIC_Handler, // 21 External Interrupt Controller (EIC): EIC_EXTINT_9
+ &EIC_Handler, // 22 External Interrupt Controller (EIC): EIC_EXTINT_10
+ &EIC_Handler, // 23 External Interrupt Controller (EIC): EIC_EXTINT_11
+ &EIC_Handler, // 24 External Interrupt Controller (EIC): EIC_EXTINT_12
+ &EIC_Handler, // 25 External Interrupt Controller (EIC): EIC_EXTINT_13
+ &EIC_Handler, // 26 External Interrupt Controller (EIC): EIC_EXTINT_14
+ &EIC_Handler, // 27 External Interrupt Controller (EIC): EIC_EXTINT_15
+ 0, // 28 Frequency Meter (FREQM)
+ 0, // 29 Non-Volatile Memory Controller (NVMCTRL): NVMCTRL_0 - _7
+ 0, // 30 Non-Volatile Memory Controller (NVMCTRL): NVMCTRL_8 - _10
+ 0, // 31 Direct Memory Access Controller (DMAC): DMAC_SUSP_0, DMAC_TCMPL_0, DMAC_TERR_0
+ 0, // 32 Direct Memory Access Controller (DMAC): DMAC_SUSP_1, DMAC_TCMPL_1, DMAC_TERR_1
+ 0, // 33 Direct Memory Access Controller (DMAC): DMAC_SUSP_2, DMAC_TCMPL_2, DMAC_TERR_2
+ 0, // 34 Direct Memory Access Controller (DMAC): DMAC_SUSP_3, DMAC_TCMPL_3, DMAC_TERR_3
+ 0, // 35 Direct Memory Access Controller (DMAC): DMAC_SUSP_4 - _31, DMAC_TCMPL_4 _31, DMAC_TERR_4- _31
+ 0, // 36 Event System Interface (EVSYS): EVSYS_EVD_0, EVSYS_OVR_0
+ 0, // 37 Event System Interface (EVSYS): EVSYS_EVD_1, EVSYS_OVR_1
+ 0, // 38 Event System Interface (EVSYS): EVSYS_EVD_2, EVSYS_OVR_2
+ 0, // 39 Event System Interface (EVSYS): EVSYS_EVD_3, EVSYS_OVR_3
+ 0, // 40 Event System Interface (EVSYS): EVSYS_EVD_10, EVSYS_EVD_11
+ 0, // 41 Peripheral Access Controller (PAC)
+ 0, // 42 Trigger Allocator (TAL): TAL_BRK
+ 0, // 43 Trigger Allocator (TAL): TAL_IPS_x
+ 0,
+ 0, // 45 RAM ECC (RAMECC)
+ &Sercom0_Handler, // 46 Serial Communication Interface 0 (SERCOM0): SERCOM0_0
+ &Sercom0_Handler, // 47 Serial Communication Interface 0 (SERCOM0): SERCOM0_1
+ &Sercom0_Handler, // 48 Serial Communication Interface 0 (SERCOM0): SERCOM0_2
+ &Sercom0_Handler, // 49 Serial Communication Interface 0 (SERCOM0): SERCOM0_3 - 6
+ &Sercom1_Handler, // 50 Serial Communication Interface 1 (SERCOM1): SERCOM1_0
+ &Sercom1_Handler, // 51 Serial Communication Interface 1 (SERCOM1): SERCOM1_1
+ &Sercom1_Handler, // 52 Serial Communication Interface 1 (SERCOM1): SERCOM1_2
+ &Sercom1_Handler, // 53 Serial Communication Interface 1 (SERCOM1): SERCOM1_3 - 6
+ &Sercom2_Handler, // 54 Serial Communication Interface 2 (SERCOM2): SERCOM2_0
+ &Sercom2_Handler, // 55 Serial Communication Interface 2 (SERCOM2): SERCOM2_1
+ &Sercom2_Handler, // 56 Serial Communication Interface 2 (SERCOM2): SERCOM2_2
+ &Sercom2_Handler, // 57 Serial Communication Interface 2 (SERCOM2): SERCOM2_3 - 6
+ &Sercom3_Handler, // 58 Serial Communication Interface 3 (SERCOM3): SERCOM3_0
+ &Sercom3_Handler, // 59 Serial Communication Interface 3 (SERCOM3): SERCOM3_1
+ &Sercom3_Handler, // 60 Serial Communication Interface 3 (SERCOM3): SERCOM3_2
+ &Sercom3_Handler, // 61 Serial Communication Interface 3 (SERCOM3): SERCOM3_3 - 6
+ &Sercom4_Handler, // 62 Serial Communication Interface 4 (SERCOM4): SERCOM4_0
+ &Sercom4_Handler, // 63 Serial Communication Interface 4 (SERCOM4): SERCOM4_1
+ &Sercom4_Handler, // 64 Serial Communication Interface 4 (SERCOM4): SERCOM4_2
+ &Sercom4_Handler, // 65 Serial Communication Interface 4 (SERCOM4): SERCOM4_3 - 6
+ &Sercom5_Handler, // 66 Serial Communication Interface 5 (SERCOM5): SERCOM5_0
+ &Sercom5_Handler, // 67 Serial Communication Interface 5 (SERCOM5): SERCOM5_1
+ &Sercom5_Handler, // 68 Serial Communication Interface 5 (SERCOM5): SERCOM5_2
+ &Sercom5_Handler, // 69 Serial Communication Interface 5 (SERCOM5): SERCOM5_3 - 6
+ &Sercom6_Handler, // 70 Serial Communication Interface 6 (SERCOM6): SERCOM6_0
+ &Sercom6_Handler, // 71 Serial Communication Interface 6 (SERCOM6): SERCOM6_1
+ &Sercom6_Handler, // 72 Serial Communication Interface 6 (SERCOM6): SERCOM6_2
+ &Sercom6_Handler, // 73 Serial Communication Interface 6 (SERCOM6): SERCOM6_3 - 6
+ &Sercom7_Handler, // 74 Serial Communication Interface 7 (SERCOM7): SERCOM7_0
+ &Sercom7_Handler, // 75 Serial Communication Interface 7 (SERCOM7): SERCOM7_1
+ &Sercom7_Handler, // 76 Serial Communication Interface 7 (SERCOM7): SERCOM7_2
+ &Sercom7_Handler, // 77 Serial Communication Interface 7 (SERCOM7): SERCOM7_3 - 6
+ 0, // 78 Control Area Network 0 (CAN0)
+ 0, // 79 Control Area Network 1 (CAN1)
+ &USB_0_Handler_wrapper, // 80 Universal Serial Bus (USB): USB_EORSM_DNRS, ...
+ &USB_1_Handler_wrapper, // 81 Universal Serial Bus (USB): USB_SOF_HSOF
+ &USB_2_Handler_wrapper, // 82 Universal Serial Bus (USB): USB_TRCPT0_0 - _7
+ &USB_3_Handler_wrapper, // 83 Universal Serial Bus (USB): USB_TRCPT1_0 - _7
+ 0, // 84 Ethernet MAC (GMAC)
+ 0, // 85 Timer Counter Control 0 (TCC0): TCC0_CNT_A ...
+ 0, // 86 Timer Counter Control 0 (TCC0): TCC0_MC_0
+ 0, // 87 Timer Counter Control 0 (TCC0): TCC0_MC_1
+ 0, // 88 Timer Counter Control 0 (TCC0): TCC0_MC_2
+ 0, // 89 Timer Counter Control 0 (TCC0): TCC0_MC_3
+ 0, // 90 Timer Counter Control 0 (TCC0): TCC0_MC_4
+ 0, // 91 Timer Counter Control 0 (TCC0): TCC0_MC_5
+ 0, // 92 Timer Counter Control 1 (TCC1): TCC1_CNT_A ...
+ 0, // 93 Timer Counter Control 1 (TCC1): TCC1_MC_0
+ 0, // 94 Timer Counter Control 1 (TCC1): TCC1_MC_1
+ 0, // 95 Timer Counter Control 1 (TCC1): TCC1_MC_2
+ 0, // 96 Timer Counter Control 1 (TCC1): TCC1_MC_3
+ 0, // 97 Timer Counter Control 2 (TCC2): TCC2_CNT_A ...
+ 0, // 98 Timer Counter Control 2 (TCC2): TCC2_MC_0
+ 0, // 99 Timer Counter Control 2 (TCC2): TCC2_MC_1
+ 0, // 100 Timer Counter Control 2 (TCC2): TCC2_MC_2
+ 0, // 101 Timer Counter Control 3 (TCC3): TCC3_CNT_A ...
+ 0, // 102 Timer Counter Control 3 (TCC3): TCC3_MC_0
+ 0, // 103 Timer Counter Control 3 (TCC3): TCC3_MC_1
+ 0, // 104 Timer Counter Control 4 (TCC4): TCC4_CNT_A ...
+ 0, // 105 Timer Counter Control 4 (TCC4): TCC4_MC_0
+ 0, // 106 Timer Counter Control 4 (TCC4): TCC4_MC_1
+ &us_timer_IRQ, // 107 Basic Timer Counter 0 (TC0)
+ 0, // 108 Basic Timer Counter 1 (TC1)
+ 0, // 109 Basic Timer Counter 2 (TC2)
+ 0, // 110 Basic Timer Counter 3 (TC3)
+ 0, // 111 Basic Timer Counter 4 (TC4)
+ 0, // 112 Basic Timer Counter 5 (TC5)
+ 0, // 113 Basic Timer Counter 6 (TC6)
+ 0, // 114 Basic Timer Counter 7 (TC7)
+ 0, // 115 Quadrature Decoder (PDEC): PDEC_DIR_A, PDEC_ERR_A, PDEC_OVF, PDEC_VLC_A
+ 0, // 116 Quadrature Decoder (PDEC): PDEC_MC_0
+ 0, // 117 Quadrature Decoder (PDEC): PDEC_MC_1
+ 0, // 118 Analog Digital Converter 0 (ADC0): ADC0_OVERRUN, ADC0_WINMON
+ 0, // 119 Analog Digital Converter 0 (ADC0): ADC0_RESRDY
+ 0, // 120 Analog Digital Converter 1 (ADC1): ADC1_OVERRUN, ADC1_WINMON
+ 0, // 121 Analog Digital Converter 1 (ADC1): ADC1_RESRDY
+ 0, // 122 Analog Comparators (AC)
+ 0, // 123 Digital-to-Analog Converter (DAC): DAC_OVERRUN_A_x, DAC_UNDERRUN_A_x
+ 0, // 124 Digital-to-Analog Converter (DAC): DAC_EMPTY_0
+ 0, // 125 Digital-to-Analog Converter (DAC): DAC_EMPTY_1
+ 0, // 126 Digital-to-Analog Converter (DAC): DAC_RESRDY_0
+ 0, // 127 Digital-to-Analog Converter (DAC): DAC_RESRDY_1
+ 0, // 128 Inter-IC Sound Interface (I2S)
+ 0, // 129 Parallel Capture Controller (PCC)
+ 0, // 130 Advanced Encryption Standard (AES)
+ 0, // 131 True Random Generator (TRNG)
+ 0, // 132 Integrity Check Monitor (ICM)
+ 0, // 133 PUblic-Key Cryptography Controller (PUKCC)
+ 0, // 134 Quad SPI interface (QSPI)
+ 0, // 135 SD/MMC Host Controller 0 (SDHC0)
+ 0, // 136 SD/MMC Host Controller 1 (SDHC1)
};
+#endif
diff --git a/ports/samd/samd_soc.c b/ports/samd/samd_soc.c
index 7f4df1bb1c75..a81e7c68810d 100644
--- a/ports/samd/samd_soc.c
+++ b/ports/samd/samd_soc.c
@@ -10,6 +10,7 @@
* The MIT License (MIT)
*
* Copyright (c) 2019 Damien P. George
+ * Copyright (c) 2022 Robert Hammelrath
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -33,86 +34,23 @@
#include "py/runtime.h"
#include "modmachine.h"
#include "samd_soc.h"
+#include "sam.h"
#include "tusb.h"
+#include "mphalport.h"
-// "MP" macros defined in "boards/$(BOARD)/mpconfigboard.h"
-mp_obj_t machine_uart_init(void) {
- // Firstly, assign alternate function SERCOM PADs to GPIO pins.
- PORT->Group[MP_PIN_GRP].PINCFG[MP_TX_PIN].bit.PMUXEN = 1; // Enable
- PORT->Group[MP_PIN_GRP].PINCFG[MP_RX_PIN].bit.PMUXEN = 1; // Enable
- PORT->Group[MP_PIN_GRP].PMUX[MP_PERIPHERAL_MUX].reg = MP_PORT_FUNC; // Sets PMUXE & PMUXO in 1 hit.
- uint32_t rxpo = MP_RXPO_PAD; // 1=Pad1,3=Pad3 Rx data
- uint32_t txpo = MP_TXPO_PAD; // 0=pad0,1=Pad2 Tx data
-
- // Initialise the clocks
- #if defined(MCU_SAMD21)
- PM->APBCMASK.bit.MP_SERCOMx = 1; // Enable synchronous clock
- GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | MP_SERCOM_GCLK_ID_x_CORE; // Select multiplexer generic clock source and enable.
- // Wait while it updates synchronously.
- while (GCLK->STATUS.bit.SYNCBUSY) {
- }
- #elif defined(MCU_SAMD51)
- GCLK->PCHCTRL[MP_SERCOM_GCLK_ID_x_CORE].reg = GCLK_PCHCTRL_CHEN | GCLK_PCHCTRL_GEN_GCLK0;
- MCLK->APBBMASK.bit.MP_SERCOMx = 1;
- #endif
-
- // Setup the Peripheral.
- // Reset (clear) the peripheral registers.
- while (USARTx->USART.SYNCBUSY.bit.SWRST) {
- }
- USARTx->USART.CTRLA.bit.SWRST = 1; // Reset all Registers, disable peripheral
- while (USARTx->USART.SYNCBUSY.bit.SWRST) {
- }
-
- // Set the register bits as needed
- // (CMODE (async),CHSIZE (8),FORM (no parity),SBMODE (1 stop) already 0).
- USARTx->USART.CTRLA.reg = // USARTx = SERCOMx set in "boards/$(BOARD)/mpconfigboard.h"
- SERCOM_USART_CTRLA_DORD // Data order
- | SERCOM_USART_CTRLA_RXPO(rxpo) // Set Pad#
- | SERCOM_USART_CTRLA_TXPO(txpo) // Set Pad#
- | SERCOM_USART_CTRLA_MODE(1) // USART with internal clock
- ;
- USARTx->USART.CTRLB.reg = SERCOM_USART_CTRLB_RXEN | SERCOM_USART_CTRLB_TXEN; // Enable Rx & Tx
- while (USARTx->USART.SYNCBUSY.bit.CTRLB) {
- }
-
- // Baud rate is clock dependant.
- #if CPU_FREQ == 8000000
- uint32_t baud = 50437; // 115200 baud; 65536*(1 - 16 * 115200/8e6)
- #elif CPU_FREQ == 48000000
- uint32_t baud = 63019; // 115200 baud; 65536*(1 - 16 * 115200/48e6)
- #elif CPU_FREQ == 120000000
- uint32_t baud = 64529; // 115200 baud; 65536*(1 - 16 * 115200/120e6)
- #endif
- USARTx->USART.BAUD.bit.BAUD = baud; // Set Baud
- USARTx->USART.CTRLA.bit.ENABLE = 1; // Enable the peripheral
- // Wait for the Registers to update.
- while (USARTx->USART.SYNCBUSY.bit.ENABLE) {
- }
-
- return mp_const_none;
-}
-
-// Disconnect SERCOM from GPIO pins. (Can't SWRST, as that will totally kill USART).
-mp_obj_t machine_uart_deinit(void) {
- // Reset
- printf("Disabling the Alt-Funct, releasing the USART pins for GPIO... \n");
- PORT->Group[MP_PIN_GRP].PINCFG[MP_TX_PIN].bit.PMUXEN = 0; // Disable
- PORT->Group[MP_PIN_GRP].PINCFG[MP_RX_PIN].bit.PMUXEN = 0; // Disable
-
- return mp_const_none;
-}
-
+#if MICROPY_PY_MACHINE_RTC
+extern void machine_rtc_start(bool force);
+#endif
static void usb_init(void) {
// Init USB clock
#if defined(MCU_SAMD21)
- GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID_USB;
+ GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK5 | GCLK_CLKCTRL_ID_USB;
PM->AHBMASK.bit.USB_ = 1;
PM->APBBMASK.bit.USB_ = 1;
uint8_t alt = 6; // alt G, USB
#elif defined(MCU_SAMD51)
- GCLK->PCHCTRL[USB_GCLK_ID].reg = GCLK_PCHCTRL_CHEN | GCLK_PCHCTRL_GEN_GCLK1;
+ GCLK->PCHCTRL[USB_GCLK_ID].reg = GCLK_PCHCTRL_CHEN | GCLK_PCHCTRL_GEN_GCLK5;
while (GCLK->PCHCTRL[USB_GCLK_ID].bit.CHEN == 0) {
}
MCLK->AHBMASK.bit.USB_ = 1;
@@ -130,44 +68,63 @@ static void usb_init(void) {
tusb_init();
}
-void samd_init(void) {
+// Initialize the µs counter on TC 0/1 or TC4/5
+void init_us_counter(void) {
#if defined(MCU_SAMD21)
- NVMCTRL->CTRLB.bit.MANW = 1; // errata "Spurious Writes"
- NVMCTRL->CTRLB.bit.RWS = 1; // 1 read wait state for 48MHz
-
- // Enable DFLL48M
- SYSCTRL->DFLLCTRL.reg = SYSCTRL_DFLLCTRL_ENABLE;
- while (!SYSCTRL->PCLKSR.bit.DFLLRDY) {
- }
- SYSCTRL->DFLLMUL.reg = SYSCTRL_DFLLMUL_CSTEP(1) | SYSCTRL_DFLLMUL_FSTEP(1)
- | SYSCTRL_DFLLMUL_MUL(48000);
- uint32_t coarse = (*((uint32_t *)FUSES_DFLL48M_COARSE_CAL_ADDR) & FUSES_DFLL48M_COARSE_CAL_Msk)
- >> FUSES_DFLL48M_COARSE_CAL_Pos;
- if (coarse == 0x3f) {
- coarse = 0x1f;
- }
- uint32_t fine = 512;
- SYSCTRL->DFLLVAL.reg = SYSCTRL_DFLLVAL_COARSE(coarse) | SYSCTRL_DFLLVAL_FINE(fine);
- SYSCTRL->DFLLCTRL.reg = SYSCTRL_DFLLCTRL_CCDIS | SYSCTRL_DFLLCTRL_USBCRM
- | SYSCTRL_DFLLCTRL_MODE | SYSCTRL_DFLLCTRL_ENABLE;
- while (!SYSCTRL->PCLKSR.bit.DFLLRDY) {
+ PM->APBCMASK.bit.TC3_ = 1; // Enable TC3 clock
+ PM->APBCMASK.bit.TC4_ = 1; // Enable TC4 clock
+ // Select multiplexer generic clock source and enable.
+ GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK3 | GCLK_CLKCTRL_ID_TC4_TC5;
+ // Wait while it updates synchronously.
+ while (GCLK->STATUS.bit.SYNCBUSY) {
}
- GCLK->GENDIV.reg = GCLK_GENDIV_ID(0) | GCLK_GENDIV_DIV(1);
- GCLK->GENCTRL.reg = GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_DFLL48M | GCLK_GENCTRL_ID(0);
- while (GCLK->STATUS.bit.SYNCBUSY) {
+ // configure the timer
+ TC4->COUNT32.CTRLA.bit.MODE = TC_CTRLA_MODE_COUNT32_Val;
+ TC4->COUNT32.CTRLA.bit.RUNSTDBY = 1;
+ TC4->COUNT32.CTRLA.bit.ENABLE = 1;
+ while (TC4->COUNT32.STATUS.bit.SYNCBUSY) {
+ }
+ TC4->COUNT32.READREQ.reg = TC_READREQ_RREQ | TC_READREQ_RCONT | 0x10;
+ while (TC4->COUNT32.STATUS.bit.SYNCBUSY) {
}
+ // Enable the IRQ
+ TC4->COUNT32.INTENSET.reg = TC_INTENSET_OVF;
+ NVIC_EnableIRQ(TC4_IRQn);
#elif defined(MCU_SAMD51)
- GCLK->GENCTRL[1].reg = 1 << GCLK_GENCTRL_DIV_Pos | GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_DFLL;
- while (GCLK->SYNCBUSY.bit.GENCTRL1) {
+ MCLK->APBAMASK.bit.TC0_ = 1; // Enable TC0 clock
+ MCLK->APBAMASK.bit.TC1_ = 1; // Enable TC1 clock
+ // Peripheral channel 9 is driven by GCLK3, 8 MHz.
+ GCLK->PCHCTRL[TC0_GCLK_ID].reg = GCLK_PCHCTRL_GEN_GCLK3 | GCLK_PCHCTRL_CHEN;
+ while (GCLK->PCHCTRL[TC0_GCLK_ID].bit.CHEN == 0) {
+ }
+
+ // configure the timer
+ TC0->COUNT32.CTRLA.bit.PRESCALER = 0;
+ TC0->COUNT32.CTRLA.bit.MODE = TC_CTRLA_MODE_COUNT32_Val;
+ TC0->COUNT32.CTRLA.bit.RUNSTDBY = 1;
+ TC0->COUNT32.CTRLA.bit.ENABLE = 1;
+ while (TC0->COUNT32.SYNCBUSY.bit.ENABLE) {
}
+ // Enable the IRQ
+ TC0->COUNT32.INTENSET.reg = TC_INTENSET_OVF;
+ NVIC_EnableIRQ(TC0_IRQn);
#endif
+}
- SysTick_Config(CPU_FREQ / 1000);
- machine_uart_init();
+void samd_init(void) {
+ init_clocks(get_cpu_freq());
+ init_us_counter();
usb_init();
+ check_usb_recovery_mode();
+ #if defined(MCU_SAMD51)
+ mp_hal_ticks_cpu_enable();
+ #endif
+ #if MICROPY_PY_MACHINE_RTC
+ machine_rtc_start(false);
+ #endif
}
diff --git a/ports/samd/samd_soc.h b/ports/samd/samd_soc.h
index a07e68dbed64..e8560b50e846 100644
--- a/ports/samd/samd_soc.h
+++ b/ports/samd/samd_soc.h
@@ -28,6 +28,7 @@
#include
#include "sam.h"
+#include "clock_config.h"
void samd_init(void);
void samd_main(void);
@@ -38,4 +39,11 @@ void USB_1_Handler_wrapper(void);
void USB_2_Handler_wrapper(void);
void USB_3_Handler_wrapper(void);
+void sercom_enable(Sercom *spi, int state);
+void sercom_register_irq(int sercom_id, void (*sercom_irq_handler));
+
+#define SERCOM_IRQ_TYPE_UART (0)
+#define SERCOM_IRQ_TYPE_SPI (1)
+#define SERCOM_IRQ_TYPE_I2C (2)
+
#endif // MICROPY_INCLUDED_SAMD_SAMD_SOC_H
diff --git a/ports/stm32/Makefile b/ports/stm32/Makefile
index 90fc864f6916..eff53deed6c6 100644
--- a/ports/stm32/Makefile
+++ b/ports/stm32/Makefile
@@ -1,21 +1,27 @@
-# Select the board to build for: if not given on the command line,
-# then default to PYBV10.
+# Select the board to build for:
+ifdef BOARD_DIR
+# Custom board path - remove trailing slash and get the final component of
+# the path as the board name.
+BOARD ?= $(notdir $(BOARD_DIR:/=))
+else
+# If not given on the command line, then default to PYBV10.
BOARD ?= PYBV10
-
-# If the build directory is not given, make it reflect the board name.
-BUILD ?= build-$(BOARD)
-
BOARD_DIR ?= boards/$(BOARD)
+endif
+
ifeq ($(wildcard $(BOARD_DIR)/.),)
$(error Invalid BOARD specified: $(BOARD_DIR))
endif
+# If the build directory is not given, make it reflect the board name.
+BUILD ?= build-$(BOARD)
+
include ../../py/mkenv.mk
-include mpconfigport.mk
include $(BOARD_DIR)/mpconfigboard.mk
# Files that are generated and needed before the QSTR build.
-QSTR_GENERATED_HEADERS = $(BUILD)/pins_qstr.h $(BUILD)/modstm_qstr.h
+QSTR_GENERATED_HEADERS = $(GEN_PINS_QSTR) $(GEN_STMCONST_QSTR)
# qstr definitions (must come before including py.mk)
QSTR_DEFS += qstrdefsport.h $(QSTR_GENERATED_HEADERS)
@@ -36,8 +42,12 @@ CFLAGS_MOD += -DLV_USE_TINY_TTF=0
# include py core make definitions
include $(TOP)/py/py.mk
+include $(TOP)/extmod/extmod.mk
-GIT_SUBMODULES += lib/libhydrogen lib/lwip lib/mbedtls lib/stm32lib
+GIT_SUBMODULES += lib/libhydrogen lib/stm32lib
+
+query-variants:
+ $(ECHO) "VARIANTS:" $(BOARD_VARIANTS)
LD_DIR=boards
USBDEV_DIR=usbdev
@@ -56,6 +66,31 @@ OPENOCD_CONFIG ?= boards/openocd_stm32f4.cfg
include stm32.mk
+PLLVALUES = boards/pllvalues.py
+MAKE_PINS = boards/make-pins.py
+BOARD_PINS = $(BOARD_DIR)/pins.csv
+PREFIX_FILE = boards/stm32f4xx_prefix.c
+GEN_PINS_SRC = $(BUILD)/pins_$(BOARD).c
+GEN_PINS_HDR = $(HEADER_BUILD)/pins.h
+GEN_PINS_QSTR = $(BUILD)/pins_qstr.h
+GEN_PINS_AF_CONST = $(HEADER_BUILD)/pins_af_const.h
+GEN_PINS_AF_DEFS = $(HEADER_BUILD)/pins_af_defs.h
+GEN_PINS_AF_PY = $(BUILD)/pins_af.py
+
+INSERT_USB_IDS = $(TOP)/tools/insert-usb-ids.py
+FILE2H = $(TOP)/tools/file2h.py
+
+USB_IDS_FILE = mpconfigboard_common.h
+CDCINF_TEMPLATE = pybcdc.inf_template
+GEN_CDCINF_FILE = $(HEADER_BUILD)/pybcdc.inf
+GEN_CDCINF_HEADER = $(HEADER_BUILD)/pybcdc_inf.h
+
+GEN_PLLFREQTABLE_HDR = $(HEADER_BUILD)/pllfreqtable.h
+GEN_STMCONST_HDR = $(HEADER_BUILD)/modstm_const.h
+GEN_STMCONST_QSTR = $(BUILD)/modstm_qstr.h
+GEN_STMCONST_MPZ = $(HEADER_BUILD)/modstm_mpz.h
+CMSIS_MCU_HDR = $(STM32LIB_CMSIS_ABS)/Include/$(CMSIS_MCU_LOWER).h
+
# Select the cross compile prefix
CROSS_COMPILE ?= arm-none-eabi-
@@ -69,7 +104,7 @@ INC += -I$(USBDEV_DIR)/core/inc -I$(USBDEV_DIR)/class/inc
#INC += -I$(USBHOST_DIR)
INC += -Ilwip_inc
-CFLAGS += $(INC) -Wall -Wpointer-arith -Wno-error=format -Werror -Wdouble-promotion -Wfloat-conversion -std=gnu99 -nostdlib $(CFLAGS_MOD) $(CFLAGS_EXTRA)
+CFLAGS += $(INC) -Wall -Wpointer-arith -Wno-error=format -Werror -Wdouble-promotion -Wfloat-conversion -std=gnu99 -nostdlib $(CFLAGS_EXTRA)
CFLAGS += -D$(CMSIS_MCU) -DUSE_FULL_LL_DRIVER
CFLAGS += $(CFLAGS_MCU_$(MCU_SERIES))
CFLAGS += $(COPT)
@@ -89,22 +124,29 @@ endif
# Configure floating point support
ifeq ($(MICROPY_FLOAT_IMPL),double)
CFLAGS += -DMICROPY_FLOAT_IMPL=MICROPY_FLOAT_IMPL_DOUBLE
-else
-ifeq ($(MICROPY_FLOAT_IMPL),none)
+else ifeq ($(MICROPY_FLOAT_IMPL),none)
CFLAGS += -DMICROPY_FLOAT_IMPL=MICROPY_FLOAT_IMPL_NONE
else
CFLAGS += -DMICROPY_FLOAT_IMPL=MICROPY_FLOAT_IMPL_FLOAT
CFLAGS += -fsingle-precision-constant
endif
-endif
-LDFLAGS = -nostdlib -L $(LD_DIR) $(addprefix -T,$(LD_FILES)) -Map=$(@:.elf=.map) --cref
-LDFLAGS += --defsym=_estack_reserve=8
+LDFLAGS += -nostdlib -L $(LD_DIR) $(addprefix -T,$(LD_FILES)) -Wl,-Map=$(@:.elf=.map) -Wl,--cref
+LDFLAGS += -Wl,--defsym=_estack_reserve=8
LIBS += "$(shell $(CC) $(CFLAGS) -print-libgcc-file-name)"
# Remove uncalled code from the final image.
CFLAGS += -fdata-sections -ffunction-sections
-LDFLAGS += --gc-sections
+LDFLAGS += -Wl,--gc-sections
+
+ifeq ($(LTO),1)
+CFLAGS += -flto=auto
+# LTO requires passing compiler flags to the linker as it will run the assembler.
+# To avoid risk of missing something relevant, pass all flags except for preprocessor args
+LDFLAGS += $(filter-out -I%,$(filter-out -D%,$(CFLAGS)))
+
+$(BUILD)/stm32_it.o $(BUILD)/pendsv.o: CFLAGS += -fno-lto
+endif
# Debugging/Optimization
ifeq ($(DEBUG), 1)
@@ -113,19 +155,23 @@ COPT ?= -Og
# Disable text compression in debug builds
MICROPY_ROM_TEXT_COMPRESSION = 0
else
+ifneq ($(LTO), 1)
+CFLAGS += -g # always include debug info in the ELF, unless LTO is on
+endif
COPT ?= -Os -DNDEBUG
endif
# Flags for optional C++ source code
CXXFLAGS += $(filter-out -Wmissing-prototypes -Wold-style-definition -std=gnu99,$(CFLAGS))
-CXXFLAGS += $(CXXFLAGS_MOD)
-ifneq ($(SRC_CXX)$(SRC_MOD_CXX),)
+
+# TODO make this common -- shouldn't be using these "private" vars from py.mk
+ifneq ($(SRC_CXX)$(SRC_USERMOD_CXX)$(SRC_USERMOD_LIB_CXX),)
LIBSTDCPP_FILE_NAME = "$(shell $(CXX) $(CXXFLAGS) -print-file-name=libstdc++.a)"
LDFLAGS += -L"$(shell dirname $(LIBSTDCPP_FILE_NAME))"
endif
# Options for mpy-cross
-MPY_CROSS_FLAGS += -march=armv7m
+MPY_CROSS_FLAGS += -march=$(MPY_CROSS_MCU_ARCH_$(MCU_SERIES))
SHARED_SRC_C += $(addprefix shared/,\
libc/string0.c \
@@ -137,6 +183,7 @@ SHARED_SRC_C += $(addprefix shared/,\
runtime/interrupt_char.c \
runtime/mpirq.c \
runtime/pyexec.c \
+ runtime/softtimer.c \
runtime/stdout_helpers.c \
runtime/sys_stdio_mphal.c \
timeutils/timeutils.c \
@@ -235,12 +282,6 @@ ifeq ($(MICROPY_FLOAT_IMPL),double)
$(LIBM_O): CFLAGS := $(filter-out -Wdouble-promotion -Wfloat-conversion, $(CFLAGS))
endif
-EXTMOD_SRC_C += $(addprefix extmod/,\
- modonewire.c \
- modnetwork.c \
- modusocket.c \
- )
-
DRIVERS_SRC_C += $(addprefix drivers/,\
bus/softspi.c \
bus/softqspi.c \
@@ -263,7 +304,6 @@ SRC_C += \
irq.c \
pendsv.c \
systick.c \
- softtimer.c \
powerctrl.c \
powerctrlboot.c \
rfcore.c \
@@ -296,7 +336,6 @@ SRC_C += \
machine_i2c.c \
machine_i2s.c \
machine_spi.c \
- machine_timer.c \
machine_uart.c \
modmachine.c \
modpyb.c \
@@ -319,28 +358,28 @@ SRC_C += \
servo.c \
dac.c \
adc.c \
+ sdio.c \
$(wildcard $(BOARD_DIR)/*.c)
-SRC_CXX += \
- $(SRC_MOD_CXX)
-
SRC_O += \
$(STARTUP_FILE) \
$(SYSTEM_FILE)
-ifeq ($(MCU_SERIES),l0)
-CSUPEROPT = -Os # save some code space
-endif
-
ifeq ($(MCU_SERIES),$(filter $(MCU_SERIES),f0 g0 l0))
+CSUPEROPT = -Os # save some code space
SRC_O += \
resethandler_m0.o \
- shared/runtime/gchelper_m0.o
+ shared/runtime/gchelper_thumb1.o
+else ifeq ($(MCU_SERIES),l1)
+CFLAGS += -DUSE_HAL_DRIVER
+SRC_O += \
+ resethandler_m3.o \
+ shared/runtime/gchelper_thumb2.o
else
SRC_O += \
system_stm32.o \
resethandler.o \
- shared/runtime/gchelper_m3.o
+ shared/runtime/gchelper_thumb2.o
endif
HAL_SRC_C += $(addprefix $(STM32LIB_HAL_BASE)/Src/stm32$(MCU_SERIES)xx_,\
@@ -403,21 +442,17 @@ HAL_SRC_C += $(addprefix $(STM32LIB_HAL_BASE)/Src/stm32$(MCU_SERIES)xx_,\
)
endif
-ifeq ($(MCU_SERIES),$(filter $(MCU_SERIES),g0 g4))
- HAL_SRC_C += $(addprefix $(STM32LIB_HAL_BASE)/Src/stm32$(MCU_SERIES)xx_, hal_fdcan.c)
-endif
-
-ifeq ($(CMSIS_MCU),$(filter $(CMSIS_MCU),STM32H743xx STM32H747xx STM32H750xx STM32H7A3xx STM32H7A3xxQ STM32H7B3xx STM32H7B3xxQ))
- HAL_SRC_C += $(addprefix $(STM32LIB_HAL_BASE)/Src/stm32$(MCU_SERIES)xx_, hal_fdcan.c)
-else
-ifeq ($(MCU_SERIES),$(filter $(MCU_SERIES),f0 f4 f7 h7))
- HAL_SRC_C += $(addprefix $(STM32LIB_HAL_BASE)/Src/stm32$(MCU_SERIES)xx_, hal_can.c)
-else
-ifeq ($(MCU_SERIES),$(filter $(MCU_SERIES),l4))
+ifeq ($(MCU_SERIES),$(filter $(MCU_SERIES),f0 f4 f7))
+HAL_SRC_C += $(addprefix $(STM32LIB_HAL_BASE)/Src/stm32$(MCU_SERIES)xx_, hal_can.c)
+else ifeq ($(MCU_SERIES),$(filter $(MCU_SERIES),g0 g4 h7))
+HAL_SRC_C += $(addprefix $(STM32LIB_HAL_BASE)/Src/stm32$(MCU_SERIES)xx_, hal_fdcan.c)
+else ifeq ($(MCU_SERIES),$(filter $(MCU_SERIES),l4))
HAL_SRC_C += $(addprefix $(STM32LIB_HAL_BASE)/Src/Legacy/stm32$(MCU_SERIES)xx_, hal_can.c)
$(BUILD)/$(STM32LIB_HAL_BASE)/Src/Legacy/stm32$(MCU_SERIES)xx_hal_can.o: CFLAGS += -Wno-error=cpp
endif
-endif
+
+ifeq ($(CMSIS_MCU),$(filter $(CMSIS_MCU),STM32H747xx))
+ HAL_SRC_C += $(addprefix $(STM32LIB_HAL_BASE)/Src/stm32$(MCU_SERIES)xx_, hal_hsem.c)
endif
ifeq ($(MCU_SERIES),$(filter $(MCU_SERIES),f0 f4 f7 g0 l0))
@@ -441,103 +476,30 @@ USBDEV_SRC_C += $(addprefix $(USBDEV_DIR)/,\
class/src/usbd_msc_scsi.c \
)
-ifeq ($(MICROPY_PY_BLUETOOTH),1)
-CFLAGS_MOD += -DMICROPY_PY_BLUETOOTH=1
-CFLAGS_MOD += -DMICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE=1
-endif
-
-ifeq ($(MICROPY_PY_NETWORK_CYW43),1)
-CFLAGS_MOD += -DMICROPY_PY_NETWORK_CYW43=1
-SRC_C += sdio.c
-EXTMOD_SRC_C += extmod/network_cyw43.c
-DRIVERS_SRC_C += drivers/cyw43/cyw43_ctrl.c drivers/cyw43/cyw43_lwip.c
-LIBS += $(TOP)/drivers/cyw43/libcyw43.a
-endif
-
-ifneq ($(MICROPY_PY_NETWORK_WIZNET5K),0)
-WIZNET5K_DIR=drivers/wiznet5k
-INC += -I$(TOP)/$(WIZNET5K_DIR)
-CFLAGS_MOD += -DMICROPY_PY_WIZNET5K=$(MICROPY_PY_NETWORK_WIZNET5K) -D_WIZCHIP_=$(MICROPY_PY_NETWORK_WIZNET5K)
-ifeq ($(MICROPY_PY_LWIP),1)
-# When using MACRAW mode (with lwIP), maximum buffer space must be used for the raw socket
-CFLAGS_MOD += -DWIZCHIP_USE_MAX_BUFFER
-endif
-SRC_MOD += network_wiznet5k.c modnwwiznet5k.c
-SRC_MOD += $(addprefix $(WIZNET5K_DIR)/,\
- ethernet/w$(MICROPY_PY_NETWORK_WIZNET5K)/w$(MICROPY_PY_NETWORK_WIZNET5K).c \
- ethernet/wizchip_conf.c \
- ethernet/socket.c \
- internet/dns/dns.c \
- )
-endif
-
-# for CC3000 module
-ifeq ($(MICROPY_PY_CC3K),1)
-CC3000_DIR=drivers/cc3000
-INC += -I$(TOP)/$(CC3000_DIR)/inc
-CFLAGS_MOD += -DMICROPY_PY_CC3K=1
-SRC_MOD += modnwcc3k.c
-SRC_MOD += $(addprefix $(CC3000_DIR)/src/,\
- cc3000_common.c \
- evnt_handler.c \
- hci.c \
- netapp.c \
- nvmem.c \
- security.c \
- socket.c \
- wlan.c \
- ccspi.c \
- inet_ntop.c \
- inet_pton.c \
- patch.c \
- patch_prog.c \
- )
-endif
-
ifeq ($(MICROPY_SSL_MBEDTLS),1)
-CFLAGS_MOD += -DMBEDTLS_CONFIG_FILE='"mbedtls/mbedtls_config.h"'
-SRC_MOD += mbedtls/mbedtls_port.c
-# replace mbedtls' error.c by ours
-SRC_MOD := $(filter-out %/mbedtls/library/error.c, $(SRC_MOD))
-LIB_SRC_C += lib/mbedtls_errors/mp_mbedtls_errors.c
+LIB_SRC_C += mbedtls/mbedtls_port.c
endif
ifeq ($(MICROPY_PY_BLUETOOTH),1)
-
SRC_C += mpbthciport.c
ifeq ($(MICROPY_BLUETOOTH_NIMBLE),1)
-ifeq ($(MICROPY_BLUETOOTH_BTSTACK),1)
-$(error Cannot enable both NimBLE and BTstack at the same time)
-endif
-endif
-
-ifeq ($(MICROPY_BLUETOOTH_NIMBLE),1)
-GIT_SUBMODULES += lib/mynewt-nimble
-CFLAGS_MOD += -DMICROPY_PY_BLUETOOTH_ENABLE_L2CAP_CHANNELS=1
-include $(TOP)/extmod/nimble/nimble.mk
SRC_C += mpnimbleport.c
endif
ifeq ($(MICROPY_BLUETOOTH_BTSTACK),1)
-GIT_SUBMODULES += lib/btstack
-MICROPY_BLUETOOTH_BTSTACK_H4 ?= 1
-include $(TOP)/extmod/btstack/btstack.mk
SRC_C += mpbtstackport.c
+MICROPY_BLUETOOTH_BTSTACK_H4 ?= 1
endif
-ifeq ($(MICROPY_PY_NETWORK_CYW43),1)
-DRIVERS_SRC_C += drivers/cyw43/cywbt.c
-endif
-
-endif
+endif # MICROPY_PY_BLUETOOTH
ifeq ($(MICROPY_PY_LVGL),1)
CFLAGS += -DMICROPY_PY_LVGL
LIB_SRC_C += $(shell find $(LVGL_BINDING_DIR)/driver/stm32/$(BOARD)/*.c)
#LIB_SRC_C += $(shell find $(LVGL_BINDING_DIR)/driver/stm32/string1.c)
ifeq ($(MCU_SERIES),$(filter $(MCU_SERIES),f7))
-SRC_HAL += $(addprefix $(HAL_DIR)/Src/stm32$(MCU_SERIES)xx_,\
+HAL_SRC += $(addprefix $(HAL_DIR)/Src/stm32$(MCU_SERIES)xx_,\
hal_ltdc.c \
hal_ltdc_ex.c \
hal_dma2d.c \
@@ -545,19 +507,19 @@ SRC_HAL += $(addprefix $(HAL_DIR)/Src/stm32$(MCU_SERIES)xx_,\
endif
endif
+# SRC_O should be placed first to work around this LTO bug with binutils <2.35:
+# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83967
+OBJ += $(addprefix $(BUILD)/, $(SRC_O))
OBJ += $(PY_O)
OBJ += $(addprefix $(BUILD)/, $(LIB_SRC_C:.c=.o))
OBJ += $(LIBM_O)
OBJ += $(addprefix $(BUILD)/, $(SHARED_SRC_C:.c=.o))
-OBJ += $(addprefix $(BUILD)/, $(EXTMOD_SRC_C:.c=.o))
OBJ += $(addprefix $(BUILD)/, $(DRIVERS_SRC_C:.c=.o))
OBJ += $(addprefix $(BUILD)/, $(HAL_SRC_C:.c=.o))
OBJ += $(addprefix $(BUILD)/, $(USBDEV_SRC_C:.c=.o))
OBJ += $(addprefix $(BUILD)/, $(SRC_C:.c=.o))
OBJ += $(addprefix $(BUILD)/, $(SRC_CXX:.cpp=.o))
-OBJ += $(addprefix $(BUILD)/, $(SRC_O))
-OBJ += $(addprefix $(BUILD)/, $(SRC_MOD:.c=.o))
-OBJ += $(BUILD)/pins_$(BOARD).o
+OBJ += $(GEN_PINS_SRC:.c=.o)
# This file contains performance critical functions so turn up the optimisation
# level. It doesn't add much to the code size and improves performance a bit.
@@ -597,7 +559,7 @@ define RUN_DFU
$(ECHO) "Writing $(1) to the board"
$(if $(filter $(USE_PYDFU),1),\
$(Q)$(PYTHON) $(PYDFU) --vid $(BOOTLOADER_DFU_USB_VID) --pid $(BOOTLOADER_DFU_USB_PID) -u $(1),
- $(Q)$(DFU_UTIL) -a 0 -d $(BOOTLOADER_DFU_USB_VID):$(BOOTLOADER_DFU_USB_PID) -D $(1))
+ $(Q)$(DFU_UTIL) -a 0 -d $(BOOTLOADER_DFU_USB_VID):$(BOOTLOADER_DFU_USB_PID) -D $(1) -s :leave)
endef
define RUN_STLINK
@@ -612,7 +574,7 @@ endef
define GENERATE_ELF
$(ECHO) "LINK $(1)"
- $(Q)$(LD) $(LDFLAGS) -o $(1) $(2) $(LDFLAGS_MOD) $(LIBS)
+ $(Q)$(CC) $(LDFLAGS) -o $(1) $(2) $(LDFLAGS_MOD) $(LIBS)
$(Q)$(SIZE) $(1)
$(if $(filter-out $(TEXT0_ADDR),0x08000000), \
$(ECHO) "INFO: this build requires mboot to be installed first")
@@ -708,27 +670,8 @@ $(BUILD)/firmware.hex: $(BUILD)/firmware.elf
$(BUILD)/firmware.elf: $(OBJ)
$(call GENERATE_ELF,$@,$^)
-PLLVALUES = boards/pllvalues.py
-MAKE_PINS = boards/make-pins.py
-BOARD_PINS = $(BOARD_DIR)/pins.csv
-PREFIX_FILE = boards/stm32f4xx_prefix.c
-GEN_PINS_SRC = $(BUILD)/pins_$(BOARD).c
-GEN_PINS_HDR = $(HEADER_BUILD)/pins.h
-GEN_PINS_QSTR = $(BUILD)/pins_qstr.h
-GEN_PINS_AF_CONST = $(HEADER_BUILD)/pins_af_const.h
-GEN_PINS_AF_DEFS = $(HEADER_BUILD)/pins_af_defs.h
-GEN_PINS_AF_PY = $(BUILD)/pins_af.py
-
-INSERT_USB_IDS = $(TOP)/tools/insert-usb-ids.py
-FILE2H = $(TOP)/tools/file2h.py
-
-USB_IDS_FILE = mpconfigboard_common.h
-CDCINF_TEMPLATE = pybcdc.inf_template
-GEN_CDCINF_FILE = $(HEADER_BUILD)/pybcdc.inf
-GEN_CDCINF_HEADER = $(HEADER_BUILD)/pybcdc_inf.h
-
# List of sources for qstr extraction
-SRC_QSTR += $(SRC_C) $(SRC_CXX) $(SRC_MOD) $(LIB_SRC_C) $(SHARED_SRC_C) $(EXTMOD_SRC_C)
+SRC_QSTR += $(SRC_C) $(SRC_CXX) $(SHARED_SRC_C) $(LIB_SRC_C)
# Append any auto-generated sources that are needed by sources listed in
# SRC_QSTR
SRC_QSTR_AUTO_DEPS += $(GEN_CDCINF_HEADER)
@@ -757,15 +700,9 @@ $(BUILD)/%_$(BOARD).c $(HEADER_BUILD)/%.h $(HEADER_BUILD)/%_af_const.h $(HEADER_
--af-defs $(GEN_PINS_AF_DEFS) --af-defs-cmp-strings \
--af-py $(GEN_PINS_AF_PY) > $(GEN_PINS_SRC)
-$(BUILD)/pins_$(BOARD).o: $(BUILD)/pins_$(BOARD).c
+$(GEN_PINS_SRC:.c=.o): $(GEN_PINS_SRC)
$(call compile_c)
-GEN_PLLFREQTABLE_HDR = $(HEADER_BUILD)/pllfreqtable.h
-GEN_STMCONST_HDR = $(HEADER_BUILD)/modstm_const.h
-GEN_STMCONST_QSTR = $(BUILD)/modstm_qstr.h
-GEN_STMCONST_MPZ = $(HEADER_BUILD)/modstm_mpz.h
-CMSIS_MCU_HDR = $(STM32LIB_CMSIS_ABS)/Include/$(CMSIS_MCU_LOWER).h
-
modmachine.c: $(GEN_PLLFREQTABLE_HDR)
$(GEN_PLLFREQTABLE_HDR): $(PLLVALUES) | $(HEADER_BUILD)
$(ECHO) "GEN $@"
diff --git a/ports/stm32/README.md b/ports/stm32/README.md
index 6b5f096d73a5..15025c5ae15c 100644
--- a/ports/stm32/README.md
+++ b/ports/stm32/README.md
@@ -68,6 +68,23 @@ can be built via:
For more information about mboot see mboot/README.md.
+### Link Time Optimization
+
+Link Time Optimization (LTO) reduces the firmware binary size when enabled
+(typically 2-3% smaller). However it may make build time longer, particularly on
+older GCC versions.
+
+Currently LTO is enabled by default for some smaller STM32 boards with less
+flash, but disabled on other boards.
+
+To enable LTO, pass `LTO=1` on the command line:
+
+ $ make BOARD=boardname LTO=1
+
+To disable LTO, pass `LTO=0` in the same way.
+
+Note that `make clean BOARD=boardname` will be needed before changing the `LTO`
+setting of a firmware that is already built.
### Flashing the Firmware using DFU mode
diff --git a/ports/stm32/accel.c b/ports/stm32/accel.c
index b07791a9a0b5..19e16831ead8 100644
--- a/ports/stm32/accel.c
+++ b/ports/stm32/accel.c
@@ -281,11 +281,12 @@ STATIC const mp_rom_map_elem_t pyb_accel_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(pyb_accel_locals_dict, pyb_accel_locals_dict_table);
-const mp_obj_type_t pyb_accel_type = {
- { &mp_type_type },
- .name = MP_QSTR_Accel,
- .make_new = pyb_accel_make_new,
- .locals_dict = (mp_obj_dict_t *)&pyb_accel_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ pyb_accel_type,
+ MP_QSTR_Accel,
+ MP_TYPE_FLAG_NONE,
+ make_new, pyb_accel_make_new,
+ locals_dict, &pyb_accel_locals_dict
+ );
#endif // MICROPY_HW_HAS_MMA7660 || MICROPY_HW_HAS_KXTJ3
diff --git a/ports/stm32/adc.c b/ports/stm32/adc.c
index fcc7d51e4527..ba09c612d7cf 100644
--- a/ports/stm32/adc.c
+++ b/ports/stm32/adc.c
@@ -50,7 +50,7 @@
/// val = adc.read_core_vbat() # read MCU VBAT
/// val = adc.read_core_vref() # read MCU VREF
-/* ADC defintions */
+/* ADC definitions */
#define ADCx (ADC1)
#define PIN_ADC_MASK PIN_ADC1
#define pin_adc_table pin_adc1
@@ -118,6 +118,14 @@
#define ADC_CAL2 ((uint16_t *)(0x1FF1E840))
#define ADC_CAL_BITS (16)
+#elif defined(STM32L1)
+
+#define ADC_SCALE_V (VREFINT_CAL_VREF / 1000.0f)
+#define ADC_CAL_ADDRESS (VREFINT_CAL_ADDR)
+#define ADC_CAL1 (TEMPSENSOR_CAL1_ADDR)
+#define ADC_CAL2 (TEMPSENSOR_CAL2_ADDR)
+#define ADC_CAL_BITS (12)
+
#elif defined(STM32L4) || defined(STM32WB)
#define ADC_SCALE_V (VREFINT_CAL_VREF / 1000.0f)
@@ -146,13 +154,14 @@
#define VBAT_DIV (4)
#elif defined(STM32F722xx) || defined(STM32F723xx) || \
defined(STM32F732xx) || defined(STM32F733xx) || \
- defined(STM32F745xx) || \
- defined(STM32F746xx) || defined(STM32F765xx) || \
+ defined(STM32F745xx) || defined(STM32F746xx) || \
+ defined(STM32F756xx) || defined(STM32F765xx) || \
defined(STM32F767xx) || defined(STM32F769xx)
#define VBAT_DIV (4)
#elif defined(STM32G0) || defined(STM32G4)
#define VBAT_DIV (3)
-#elif defined(STM32H743xx) || defined(STM32H747xx) || \
+#elif defined(STM32H723xx) || defined(STM32H733xx) || \
+ defined(STM32H743xx) || defined(STM32H747xx) || \
defined(STM32H7A3xx) || defined(STM32H7A3xxQ) || \
defined(STM32H7B3xx) || defined(STM32H7B3xxQ) || \
defined(STM32H750xx)
@@ -163,6 +172,8 @@
defined(STM32L476xx) || defined(STM32L496xx) || \
defined(STM32WB55xx)
#define VBAT_DIV (3)
+#elif defined(STM32L152xE)
+// STM32L152xE does not have vbat.
#else
#error Unsupported processor
#endif
@@ -171,19 +182,25 @@
#define EOC_TIMEOUT (10)
/* Core temperature sensor definitions */
-#define CORE_TEMP_V25 (943) /* (0.76v/3.3v)*(2^ADC resoultion) */
-#define CORE_TEMP_AVG_SLOPE (3) /* (2.5mv/3.3v)*(2^ADC resoultion) */
+#define CORE_TEMP_V25 (943) /* (0.76v/3.3v)*(2^ADC resolution) */
+#define CORE_TEMP_AVG_SLOPE (3) /* (2.5mv/3.3v)*(2^ADC resolution) */
// scale and calibration values for VBAT and VREF
#define ADC_SCALE (ADC_SCALE_V / ((1 << ADC_CAL_BITS) - 1))
#define VREFIN_CAL ((uint16_t *)ADC_CAL_ADDRESS)
#ifndef __HAL_ADC_IS_CHANNEL_INTERNAL
+#if defined(STM32L1)
+#define __HAL_ADC_IS_CHANNEL_INTERNAL(channel) \
+ (channel == ADC_CHANNEL_VREFINT \
+ || channel == ADC_CHANNEL_TEMPSENSOR)
+#else
#define __HAL_ADC_IS_CHANNEL_INTERNAL(channel) \
(channel == ADC_CHANNEL_VBAT \
|| channel == ADC_CHANNEL_VREFINT \
|| channel == ADC_CHANNEL_TEMPSENSOR)
#endif
+#endif
typedef struct _pyb_obj_adc_t {
mp_obj_base_t base;
@@ -200,6 +217,14 @@ static inline uint32_t adc_get_internal_channel(uint32_t channel) {
if (channel == 16) {
channel = ADC_CHANNEL_TEMPSENSOR;
}
+ #elif defined(STM32L4)
+ if (channel == 0) {
+ channel = ADC_CHANNEL_VREFINT;
+ } else if (channel == 17) {
+ channel = ADC_CHANNEL_TEMPSENSOR;
+ } else if (channel == 18) {
+ channel = ADC_CHANNEL_VBAT;
+ }
#endif
return channel;
}
@@ -210,6 +235,10 @@ STATIC bool is_adcx_channel(int channel) {
return IS_ADC_CHANNEL(channel) || channel == ADC_CHANNEL_TEMPSENSOR;
#elif defined(STM32F0) || defined(STM32F4) || defined(STM32F7)
return IS_ADC_CHANNEL(channel);
+ #elif defined(STM32L1)
+ // The HAL of STM32L1 defines some channels those may not be available on package
+ return __HAL_ADC_IS_CHANNEL_INTERNAL(channel)
+ || (channel < MP_ARRAY_SIZE(pin_adcall_table) && pin_adcall_table[channel]);
#elif defined(STM32G0) || defined(STM32H7)
return __HAL_ADC_IS_CHANNEL_INTERNAL(channel)
|| IS_ADC_CHANNEL(__HAL_ADC_DECIMAL_NB_TO_CHANNEL(channel));
@@ -225,7 +254,7 @@ STATIC bool is_adcx_channel(int channel) {
STATIC void adc_wait_for_eoc_or_timeout(ADC_HandleTypeDef *adcHandle, int32_t timeout) {
uint32_t tickstart = HAL_GetTick();
- #if defined(STM32F4) || defined(STM32F7)
+ #if defined(STM32F4) || defined(STM32F7) || defined(STM32L1)
while ((adcHandle->Instance->SR & ADC_FLAG_EOC) != ADC_FLAG_EOC) {
#elif defined(STM32F0) || defined(STM32G0) || defined(STM32G4) || defined(STM32H7) || defined(STM32L4) || defined(STM32WB)
while (READ_BIT(adcHandle->Instance->ISR, ADC_FLAG_EOC) != ADC_FLAG_EOC) {
@@ -239,7 +268,7 @@ STATIC void adc_wait_for_eoc_or_timeout(ADC_HandleTypeDef *adcHandle, int32_t ti
}
STATIC void adcx_clock_enable(ADC_HandleTypeDef *adch) {
- #if defined(STM32F0) || defined(STM32F4) || defined(STM32F7)
+ #if defined(STM32F0) || defined(STM32F4) || defined(STM32F7) || defined(STM32L1)
ADCx_CLK_ENABLE();
#elif defined(STM32H7A3xx) || defined(STM32H7A3xxQ) || defined(STM32H7B3xx) || defined(STM32H7B3xxQ)
__HAL_RCC_ADC12_CLK_ENABLE();
@@ -299,6 +328,12 @@ STATIC void adcx_init_periph(ADC_HandleTypeDef *adch, uint32_t resolution) {
adch->Init.OversamplingMode = DISABLE;
adch->Init.LeftBitShift = ADC_LEFTBITSHIFT_NONE;
adch->Init.ConversionDataManagement = ADC_CONVERSIONDATA_DR;
+ #elif defined(STM32L1)
+ adch->Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1;
+ adch->Init.ScanConvMode = ADC_SCAN_DISABLE;
+ adch->Init.LowPowerAutoWait = DISABLE;
+ adch->Init.DataAlign = ADC_DATAALIGN_RIGHT;
+ adch->Init.DMAContinuousRequests = DISABLE;
#elif defined(STM32G0) || defined(STM32G4) || defined(STM32L4) || defined(STM32WB)
adch->Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1;
adch->Init.ScanConvMode = ADC_SCAN_DISABLE;
@@ -367,6 +402,12 @@ STATIC void adc_config_channel(ADC_HandleTypeDef *adc_handle, uint32_t channel)
sConfig.OffsetNumber = ADC_OFFSET_NONE;
sConfig.OffsetRightShift = DISABLE;
sConfig.OffsetSignedSaturation = DISABLE;
+ #elif defined(STM32L1)
+ if (__HAL_ADC_IS_CHANNEL_INTERNAL(channel)) {
+ sConfig.SamplingTime = ADC_SAMPLETIME_384CYCLES;
+ } else {
+ sConfig.SamplingTime = ADC_SAMPLETIME_384CYCLES;
+ }
#elif defined(STM32G0)
if (__HAL_ADC_IS_CHANNEL_INTERNAL(channel)) {
sConfig.SamplingTime = ADC_SAMPLETIME_160CYCLES_5;
@@ -555,7 +596,7 @@ STATIC mp_obj_t adc_read_timed(mp_obj_t self_in, mp_obj_t buf_in, mp_obj_t freq_
HAL_ADC_Start(&self->handle);
} else {
// for subsequent samples we can just set the "start sample" bit
- #if defined(STM32F4) || defined(STM32F7)
+ #if defined(STM32F4) || defined(STM32F7) || defined(STM32L1)
self->handle.Instance->CR2 |= (uint32_t)ADC_CR2_SWSTART;
#elif defined(STM32F0) || defined(STM32G0) || defined(STM32G4) || defined(STM32H7) || defined(STM32L4) || defined(STM32WB)
SET_BIT(self->handle.Instance->CR, ADC_CR_ADSTART);
@@ -665,7 +706,7 @@ STATIC mp_obj_t adc_read_timed_multi(mp_obj_t adc_array_in, mp_obj_t buf_array_i
adc_config_channel(&adc->handle, adc->channel);
// for the first sample we need to turn the ADC on
// ADC is started: set the "start sample" bit
- #if defined(STM32F4) || defined(STM32F7)
+ #if defined(STM32F4) || defined(STM32F7) || defined(STM32L1)
adc->handle.Instance->CR2 |= (uint32_t)ADC_CR2_SWSTART;
#elif defined(STM32F0) || defined(STM32G0) || defined(STM32G4) || defined(STM32H7) || defined(STM32L4) || defined(STM32WB)
SET_BIT(adc->handle.Instance->CR, ADC_CR_ADSTART);
@@ -703,13 +744,14 @@ STATIC const mp_rom_map_elem_t adc_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(adc_locals_dict, adc_locals_dict_table);
-const mp_obj_type_t pyb_adc_type = {
- { &mp_type_type },
- .name = MP_QSTR_ADC,
- .print = adc_print,
- .make_new = adc_make_new,
- .locals_dict = (mp_obj_dict_t *)&adc_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ pyb_adc_type,
+ MP_QSTR_ADC,
+ MP_TYPE_FLAG_NONE,
+ make_new, adc_make_new,
+ print, adc_print,
+ locals_dict, &adc_locals_dict
+ );
/******************************************************************************/
/* adc all object */
@@ -719,6 +761,8 @@ typedef struct _pyb_adc_all_obj_t {
ADC_HandleTypeDef handle;
} pyb_adc_all_obj_t;
+float adc_read_core_vref(ADC_HandleTypeDef *adcHandle);
+
void adc_init_all(pyb_adc_all_obj_t *adc_all, uint32_t resolution, uint32_t en_mask) {
switch (resolution) {
@@ -761,7 +805,11 @@ void adc_init_all(pyb_adc_all_obj_t *adc_all, uint32_t resolution, uint32_t en_m
}
int adc_get_resolution(ADC_HandleTypeDef *adcHandle) {
+ #if defined(STM32L1)
+ uint32_t res_reg = adcHandle->Instance->CR1 & ADC_CR1_RES_Msk;
+ #else
uint32_t res_reg = ADC_GET_RESOLUTION(adcHandle);
+ #endif
switch (res_reg) {
#if !defined(STM32H7)
@@ -813,6 +861,11 @@ float adc_read_core_temp_float(ADC_HandleTypeDef *adcHandle) {
return 0;
}
#else
+ #if defined(STM32L1) || defined(STM32L4)
+ // Update the reference correction factor before reading tempsensor
+ // because TS_CAL1 and TS_CAL2 of STM32L1/L4 are at VDDA=3.0V
+ adc_read_core_vref(adcHandle);
+ #endif
int32_t raw_value = adc_config_and_read_ref(adcHandle, ADC_CHANNEL_TEMPSENSOR);
#endif
float core_temp_avg_slope = (*ADC_CAL2 - *ADC_CAL1) / 80.0f;
@@ -820,8 +873,12 @@ float adc_read_core_temp_float(ADC_HandleTypeDef *adcHandle) {
}
float adc_read_core_vbat(ADC_HandleTypeDef *adcHandle) {
+ #if defined(STM32L152xE)
+ mp_raise_NotImplementedError(MP_ERROR_TEXT("read_core_vbat not supported"));
+ #else
uint32_t raw_value = adc_config_and_read_ref(adcHandle, ADC_CHANNEL_VBAT);
return raw_value * VBAT_DIV * ADC_SCALE * adc_refcor;
+ #endif
}
float adc_read_core_vref(ADC_HandleTypeDef *adcHandle) {
@@ -856,6 +913,9 @@ STATIC mp_obj_t adc_all_make_new(const mp_obj_type_t *type, size_t n_args, size_
STATIC mp_obj_t adc_all_read_channel(mp_obj_t self_in, mp_obj_t channel) {
pyb_adc_all_obj_t *self = MP_OBJ_TO_PTR(self_in);
uint32_t chan = adc_get_internal_channel(mp_obj_get_int(channel));
+ if (!is_adcx_channel(chan)) {
+ mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("not a valid ADC Channel: %d"), chan);
+ }
uint32_t data = adc_config_and_read_channel(&self->handle, chan);
return mp_obj_new_int(data);
}
@@ -908,11 +968,12 @@ STATIC const mp_rom_map_elem_t adc_all_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(adc_all_locals_dict, adc_all_locals_dict_table);
-const mp_obj_type_t pyb_adc_all_type = {
- { &mp_type_type },
- .name = MP_QSTR_ADCAll,
- .make_new = adc_all_make_new,
- .locals_dict = (mp_obj_dict_t *)&adc_all_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ pyb_adc_all_type,
+ MP_QSTR_ADCAll,
+ MP_TYPE_FLAG_NONE,
+ make_new, adc_all_make_new,
+ locals_dict, &adc_all_locals_dict
+ );
#endif // MICROPY_HW_ENABLE_ADC
diff --git a/ports/stm32/boardctrl.c b/ports/stm32/boardctrl.c
index 922f218e92f9..85a42a240ff0 100644
--- a/ports/stm32/boardctrl.c
+++ b/ports/stm32/boardctrl.c
@@ -24,13 +24,37 @@
* THE SOFTWARE.
*/
+#include
+
#include "py/runtime.h"
+#include "py/objstr.h"
#include "py/mphal.h"
#include "shared/runtime/pyexec.h"
#include "boardctrl.h"
+#include "powerctrl.h"
#include "led.h"
#include "usrsw.h"
+NORETURN void boardctrl_fatal_error(const char *msg) {
+ for (volatile uint delay = 0; delay < 10000000; delay++) {
+ }
+ led_state(1, 1);
+ led_state(2, 1);
+ led_state(3, 1);
+ led_state(4, 1);
+ mp_hal_stdout_tx_strn("\nFATAL ERROR:\n", 14);
+ mp_hal_stdout_tx_strn(msg, strlen(msg));
+ for (uint i = 0;;) {
+ led_toggle(((i++) & 3) + 1);
+ for (volatile uint delay = 0; delay < 10000000; delay++) {
+ }
+ if (i >= 16) {
+ // to conserve power
+ __WFI();
+ }
+ }
+}
+
STATIC void flash_error(int n) {
for (int i = 0; i < n; i++) {
led_state(PYB_LED_RED, 1);
@@ -43,8 +67,31 @@ STATIC void flash_error(int n) {
led_state(PYB_LED_GREEN, 0);
}
+#if MICROPY_HW_USES_BOOTLOADER
+void boardctrl_maybe_enter_mboot(size_t n_args, const void *args_in) {
+ const mp_obj_t *args = args_in;
+
+ if (n_args == 0 || !mp_obj_is_true(args[0])) {
+ // By default, with no args given, we enter the custom bootloader (mboot)
+ powerctrl_enter_bootloader(0x70ad0000, MBOOT_VTOR);
+ }
+
+ if (n_args == 1 && mp_obj_is_str_or_bytes(args[0])) {
+ // With a string/bytes given, pass its data to the custom bootloader
+ size_t len;
+ const char *data = mp_obj_str_get_data(args[0], &len);
+ void *mboot_region = (void *)*((volatile uint32_t *)MBOOT_VTOR);
+ memmove(mboot_region, data, len);
+ powerctrl_enter_bootloader(0x70ad0080, MBOOT_VTOR);
+ }
+}
+#endif
+
#if !MICROPY_HW_USES_BOOTLOADER
STATIC uint update_reset_mode(uint reset_mode) {
+ // Note: Must use HAL_Delay here as MicroPython is not yet initialised
+ // and mp_hal_delay_ms will attempt to invoke the scheduler.
+
#if MICROPY_HW_HAS_SWITCH
if (switch_get()) {
@@ -56,7 +103,7 @@ STATIC uint update_reset_mode(uint reset_mode) {
led_state(3, reset_mode & 2);
led_state(4, reset_mode & 4);
for (uint j = 0; j < 30; ++j) {
- mp_hal_delay_ms(20);
+ HAL_Delay(20);
if (!switch_get()) {
goto select_mode;
}
@@ -71,13 +118,13 @@ STATIC uint update_reset_mode(uint reset_mode) {
led_state(2, 0);
led_state(3, 0);
led_state(4, 0);
- mp_hal_delay_ms(50);
+ HAL_Delay(50);
led_state(2, reset_mode & 1);
led_state(3, reset_mode & 2);
led_state(4, reset_mode & 4);
- mp_hal_delay_ms(50);
+ HAL_Delay(50);
}
- mp_hal_delay_ms(400);
+ HAL_Delay(400);
#elif defined(MICROPY_HW_LED1)
@@ -90,11 +137,11 @@ STATIC uint update_reset_mode(uint reset_mode) {
break;
}
led_state(1, 1);
- mp_hal_delay_ms(100);
+ HAL_Delay(100);
led_state(1, 0);
- mp_hal_delay_ms(200);
+ HAL_Delay(200);
}
- mp_hal_delay_ms(400);
+ HAL_Delay(400);
if (!switch_get()) {
break;
}
@@ -106,11 +153,11 @@ STATIC uint update_reset_mode(uint reset_mode) {
for (uint i = 0; i < 2; i++) {
for (uint j = 0; j < reset_mode; j++) {
led_state(1, 1);
- mp_hal_delay_ms(100);
+ HAL_Delay(100);
led_state(1, 0);
- mp_hal_delay_ms(200);
+ HAL_Delay(200);
}
- mp_hal_delay_ms(400);
+ HAL_Delay(400);
}
#else
#error Need a reset mode update method
diff --git a/ports/stm32/boardctrl.h b/ports/stm32/boardctrl.h
index 0878a453b3db..8f4ce30eff80 100644
--- a/ports/stm32/boardctrl.h
+++ b/ports/stm32/boardctrl.h
@@ -33,10 +33,22 @@
#define MICROPY_BOARD_PENDSV_ENTRIES
#endif
+#ifndef MICROPY_BOARD_FATAL_ERROR
+#define MICROPY_BOARD_FATAL_ERROR boardctrl_fatal_error
+#endif
+
#ifndef MICROPY_BOARD_STARTUP
#define MICROPY_BOARD_STARTUP powerctrl_check_enter_bootloader
#endif
+#ifndef MICROPY_BOARD_ENTER_BOOTLOADER
+#if MICROPY_HW_USES_BOOTLOADER
+#define MICROPY_BOARD_ENTER_BOOTLOADER(nargs, args) boardctrl_maybe_enter_mboot(nargs, args)
+#else
+#define MICROPY_BOARD_ENTER_BOOTLOADER(nargs, args)
+#endif
+#endif
+
#ifndef MICROPY_BOARD_EARLY_INIT
#define MICROPY_BOARD_EARLY_INIT()
#endif
@@ -102,6 +114,8 @@ typedef struct _boardctrl_state_t {
bool log_soft_reset;
} boardctrl_state_t;
+NORETURN void boardctrl_fatal_error(const char *msg);
+void boardctrl_maybe_enter_mboot(size_t n_args, const void *args);
void boardctrl_before_soft_reset_loop(boardctrl_state_t *state);
void boardctrl_top_soft_reset_loop(boardctrl_state_t *state);
int boardctrl_run_boot_py(boardctrl_state_t *state);
diff --git a/ports/stm32/boards/ARDUINO_GIGA/bdev.c b/ports/stm32/boards/ARDUINO_GIGA/bdev.c
new file mode 100644
index 000000000000..caadc2b649ee
--- /dev/null
+++ b/ports/stm32/boards/ARDUINO_GIGA/bdev.c
@@ -0,0 +1,45 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2023 Arduino SA
+ *
+ * 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 "storage.h"
+#include "qspi.h"
+
+#if MICROPY_HW_SPIFLASH_ENABLE_CACHE
+// Shared cache for first and second SPI block devices
+STATIC mp_spiflash_cache_t spi_bdev_cache;
+#endif
+
+// First external SPI flash uses hardware QSPI interface
+const mp_spiflash_config_t spiflash_config = {
+ .bus_kind = MP_SPIFLASH_BUS_QSPI,
+ .bus.u_qspi.data = NULL,
+ .bus.u_qspi.proto = &qspi_proto,
+ #if MICROPY_HW_SPIFLASH_ENABLE_CACHE
+ .cache = &spi_bdev_cache,
+ #endif
+};
+
+spi_bdev_t spi_bdev;
diff --git a/ports/stm32/boards/ARDUINO_GIGA/board.json b/ports/stm32/boards/ARDUINO_GIGA/board.json
new file mode 100644
index 000000000000..f0595d4ad533
--- /dev/null
+++ b/ports/stm32/boards/ARDUINO_GIGA/board.json
@@ -0,0 +1,21 @@
+{
+ "deploy": [
+ "./deploy.md"
+ ],
+ "docs": "",
+ "features": [
+ "8MB SDRAM",
+ "16MB Flash",
+ "Dual-core processor",
+ "USB Full speed",
+ "CYW43 WiFi/BT Module"
+ ],
+ "images": [
+ "ABX00063_01.front_1000x750.jpg"
+ ],
+ "mcu": "stm32h7",
+ "product": "Arduino Giga",
+ "thumbnail": "",
+ "url": "https://store.arduino.cc/products/giga-r1-wifi",
+ "vendor": "Arduino"
+}
diff --git a/ports/stm32/boards/ARDUINO_GIGA/board_init.c b/ports/stm32/boards/ARDUINO_GIGA/board_init.c
new file mode 100644
index 000000000000..bdec04643bf4
--- /dev/null
+++ b/ports/stm32/boards/ARDUINO_GIGA/board_init.c
@@ -0,0 +1,95 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2023 Arduino SA
+ *
+ * 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 "storage.h"
+#include "sdram.h"
+
+void GIGA_board_startup(void) {
+}
+
+void GIGA_board_early_init(void) {
+ HAL_InitTick(0);
+
+ #if MICROPY_HW_ENABLE_INTERNAL_FLASH_STORAGE == 1
+ // The Arduino/mbed bootloader uses the MPU to protect sector 1
+ // which is used for the flash filesystem. The following code
+ // resets and disables all MPU regions configured in the bootloader.
+ HAL_MPU_Disable();
+ MPU_Region_InitTypeDef MPU_InitStruct;
+ MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
+ MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;
+ MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;
+ MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
+ MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL1;
+ MPU_InitStruct.SubRegionDisable = 0x00;
+ MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;
+
+ for (int i = MPU_REGION_NUMBER0; i < MPU_REGION_NUMBER15; i++) {
+ MPU_InitStruct.Number = i;
+ MPU_InitStruct.Enable = MPU_REGION_DISABLE;
+ HAL_MPU_ConfigRegion(&MPU_InitStruct);
+ }
+ #endif
+}
+
+void GIGA_board_enter_bootloader(void) {
+ RTC_HandleTypeDef RTCHandle;
+ RTCHandle.Instance = RTC;
+ HAL_RTCEx_BKUPWrite(&RTCHandle, RTC_BKP_DR0, 0xDF59);
+ NVIC_SystemReset();
+}
+
+void GIGA_board_low_power(int mode) {
+ switch (mode) {
+ case 0: // Leave stop mode.
+ sdram_leave_low_power();
+ break;
+ case 1: // Enter stop mode.
+ sdram_enter_low_power();
+ break;
+ case 2: // Enter standby mode.
+ sdram_enter_power_down();
+ break;
+ }
+
+ #if MICROPY_HW_ENABLE_INTERNAL_FLASH_STORAGE == 0
+ // Enable QSPI deepsleep for modes 1 and 2
+ mp_spiflash_deepsleep(&spi_bdev.spiflash, (mode != 0));
+ #endif
+
+ #if defined(M4_APP_ADDR)
+ // Signal Cortex-M4 to go to Standby mode.
+ if (mode == 2) {
+ __HAL_RCC_HSEM_CLK_ENABLE();
+ HAL_HSEM_FastTake(0);
+ HAL_HSEM_Release(0, 0);
+ __HAL_RCC_HSEM_CLK_DISABLE();
+ HAL_Delay(100);
+ }
+ #endif
+}
diff --git a/ports/stm32/boards/ARDUINO_GIGA/deploy.md b/ports/stm32/boards/ARDUINO_GIGA/deploy.md
new file mode 100644
index 000000000000..6013ef30ac7c
--- /dev/null
+++ b/ports/stm32/boards/ARDUINO_GIGA/deploy.md
@@ -0,0 +1,14 @@
+### Via dfu-util
+
+This board can programmed via DFU bootloader, using e.g. [dfu-util](http://dfu-util.sourceforge.net/).
+To enter the DFU bootloader, double tap the reset (blue) button, or you can use `machine.bootloader()` from the MicroPython REPL.
+
+```bash
+dfu-util -w -a 0 -d 2341:035b -D build-ARDUINO_GIGA/firmware.dfu
+```
+
+Or from MicroPython source repository:
+
+```bash
+make BOARD=ARDUINO_GIGA deploy
+```
diff --git a/ports/stm32/boards/ARDUINO_GIGA/manifest.py b/ports/stm32/boards/ARDUINO_GIGA/manifest.py
new file mode 100644
index 000000000000..b3c6b02e5ba0
--- /dev/null
+++ b/ports/stm32/boards/ARDUINO_GIGA/manifest.py
@@ -0,0 +1,12 @@
+include("$(PORT_DIR)/boards/manifest.py")
+
+# Networking
+require("bundle-networking")
+
+# Utils
+require("time")
+require("senml")
+require("logging")
+
+# Bluetooth
+require("aioble")
diff --git a/ports/stm32/boards/ARDUINO_GIGA/mbedtls_config_board.h b/ports/stm32/boards/ARDUINO_GIGA/mbedtls_config_board.h
new file mode 100644
index 000000000000..0e1703f1bf96
--- /dev/null
+++ b/ports/stm32/boards/ARDUINO_GIGA/mbedtls_config_board.h
@@ -0,0 +1,8 @@
+#ifndef MICROPY_INCLUDED_MBEDTLS_CONFIG_BOARD_H
+#define MICROPY_INCLUDED_MBEDTLS_CONFIG_BOARD_H
+
+#define MBEDTLS_ECP_NIST_OPTIM
+
+#include "ports/stm32/mbedtls/mbedtls_config.h"
+
+#endif /* MICROPY_INCLUDED_MBEDTLS_CONFIG_BOARD_H */
diff --git a/ports/stm32/boards/ARDUINO_GIGA/mpconfigboard.h b/ports/stm32/boards/ARDUINO_GIGA/mpconfigboard.h
new file mode 100644
index 000000000000..cc38b0a7ca03
--- /dev/null
+++ b/ports/stm32/boards/ARDUINO_GIGA/mpconfigboard.h
@@ -0,0 +1,318 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ * The MIT License (MIT)
+ * Copyright (c) 2023 Arduino SA
+ */
+
+#define MICROPY_HW_BOARD_NAME "GIGA"
+#define MICROPY_HW_MCU_NAME "STM32H747"
+#define MICROPY_PY_SYS_PLATFORM "Giga"
+#define MICROPY_HW_FLASH_FS_LABEL "Giga"
+
+#define MICROPY_OBJ_REPR (MICROPY_OBJ_REPR_C)
+#define UINT_FMT "%u"
+#define INT_FMT "%d"
+typedef int mp_int_t; // must be pointer size
+typedef unsigned int mp_uint_t; // must be pointer size
+
+#define MICROPY_FATFS_EXFAT (1)
+#define MICROPY_HW_ENABLE_RTC (1)
+#define MICROPY_HW_ENABLE_RNG (1)
+#define MICROPY_HW_ENABLE_ADC (1)
+#define MICROPY_HW_ENABLE_DAC (1)
+#define MICROPY_HW_ENABLE_USB (1)
+#define MICROPY_HW_HAS_SWITCH (1)
+#define MICROPY_HW_HAS_FLASH (1)
+#define MICROPY_HW_ENABLE_SERVO (1)
+#define MICROPY_HW_ENABLE_TIMER (1)
+#define MICROPY_HW_ENABLE_SDCARD (0)
+#define MICROPY_HW_ENABLE_MMCARD (0)
+
+// Flash storage config
+#define MICROPY_HW_SPIFLASH_ENABLE_CACHE (1)
+#define MICROPY_HW_ENABLE_INTERNAL_FLASH_STORAGE (1)
+
+#define MICROPY_BOARD_STARTUP GIGA_board_startup
+void GIGA_board_startup(void);
+
+#define MICROPY_BOARD_EARLY_INIT GIGA_board_early_init
+void GIGA_board_early_init(void);
+
+#define MICROPY_BOARD_ENTER_BOOTLOADER(nargs, args) GIGA_board_enter_bootloader()
+void GIGA_board_enter_bootloader(void);
+
+void GIGA_board_low_power(int mode);
+#define MICROPY_BOARD_LEAVE_STOP GIGA_board_low_power(0);
+#define MICROPY_BOARD_ENTER_STOP GIGA_board_low_power(1);
+#define MICROPY_BOARD_ENTER_STANDBY GIGA_board_low_power(2);
+
+void GIGA_board_osc_enable(int enable);
+#define MICROPY_BOARD_OSC_ENABLE GIGA_board_osc_enable(1);
+#define MICROPY_BOARD_OSC_DISABLE GIGA_board_osc_enable(0);
+
+// PLL1 480MHz/48MHz SDMMC and FDCAN
+// USB and RNG are clocked from the HSI48
+#define MICROPY_HW_CLK_PLLM (4)
+#define MICROPY_HW_CLK_PLLN (240)
+#define MICROPY_HW_CLK_PLLP (2)
+#define MICROPY_HW_CLK_PLLQ (20)
+#define MICROPY_HW_CLK_PLLR (2)
+#define MICROPY_HW_CLK_PLLVCI (RCC_PLL1VCIRANGE_2)
+#define MICROPY_HW_CLK_PLLVCO (RCC_PLL1VCOWIDE)
+#define MICROPY_HW_CLK_PLLFRAC (0)
+
+// PLL2 200MHz for FMC and QSPI.
+#define MICROPY_HW_CLK_PLL2M (4)
+#define MICROPY_HW_CLK_PLL2N (100)
+#define MICROPY_HW_CLK_PLL2P (2)
+#define MICROPY_HW_CLK_PLL2Q (2)
+#define MICROPY_HW_CLK_PLL2R (2)
+#define MICROPY_HW_CLK_PLL2VCI (RCC_PLL2VCIRANGE_2)
+#define MICROPY_HW_CLK_PLL2VCO (RCC_PLL2VCOWIDE)
+#define MICROPY_HW_CLK_PLL2FRAC (0)
+
+// PLL3 160MHz for ADC and SPI123
+#define MICROPY_HW_CLK_PLL3M (4)
+#define MICROPY_HW_CLK_PLL3N (80)
+#define MICROPY_HW_CLK_PLL3P (2)
+#define MICROPY_HW_CLK_PLL3Q (2)
+#define MICROPY_HW_CLK_PLL3R (2)
+#define MICROPY_HW_CLK_PLL3VCI (RCC_PLL3VCIRANGE_2)
+#define MICROPY_HW_CLK_PLL3VCO (RCC_PLL3VCOWIDE)
+#define MICROPY_HW_CLK_PLL3FRAC (0)
+
+// HSE in BYPASS mode.
+#define MICROPY_HW_CLK_USE_BYPASS (0)
+
+// Bus clock divider values
+#define MICROPY_HW_CLK_AHB_DIV (RCC_HCLK_DIV2)
+#define MICROPY_HW_CLK_APB1_DIV (RCC_APB1_DIV2)
+#define MICROPY_HW_CLK_APB2_DIV (RCC_APB2_DIV2)
+#define MICROPY_HW_CLK_APB3_DIV (RCC_APB3_DIV2)
+#define MICROPY_HW_CLK_APB4_DIV (RCC_APB4_DIV2)
+
+// Peripheral clock sources
+#define MICROPY_HW_RCC_HSI48_STATE (RCC_HSI48_ON)
+#define MICROPY_HW_RCC_USB_CLKSOURCE (RCC_USBCLKSOURCE_HSI48)
+#define MICROPY_HW_RCC_RTC_CLKSOURCE (RCC_RTCCLKSOURCE_LSI)
+#define MICROPY_HW_RCC_FMC_CLKSOURCE (RCC_FMCCLKSOURCE_PLL2)
+#define MICROPY_HW_RCC_RNG_CLKSOURCE (RCC_RNGCLKSOURCE_HSI48)
+#define MICROPY_HW_RCC_ADC_CLKSOURCE (RCC_ADCCLKSOURCE_PLL3)
+#define MICROPY_HW_RCC_SDMMC_CLKSOURCE (RCC_SDMMCCLKSOURCE_PLL)
+#define MICROPY_HW_RCC_FDCAN_CLKSOURCE (RCC_FDCANCLKSOURCE_PLL)
+#define MICROPY_HW_RCC_SPI123_CLKSOURCE (RCC_SPI123CLKSOURCE_PLL3)
+#define MICROPY_HW_RCC_I2C123_CLKSOURCE (RCC_I2C123CLKSOURCE_D2PCLK1)
+#define MICROPY_HW_RCC_QSPI_CLKSOURCE (RCC_QSPICLKSOURCE_PLL2)
+
+// SMPS configuration
+#define MICROPY_HW_PWR_SMPS_CONFIG (PWR_LDO_SUPPLY)
+
+// There is an external 32kHz oscillator
+#define RTC_ASYNCH_PREDIV (0)
+#define RTC_SYNCH_PREDIV (0x7fff)
+#define MICROPY_HW_RTC_USE_BYPASS (0)
+#define MICROPY_HW_RTC_USE_US (1)
+#define MICROPY_HW_RTC_USE_CALOUT (1)
+
+#if !MICROPY_HW_ENABLE_INTERNAL_FLASH_STORAGE
+// QSPI flash #1 for storage
+#define MICROPY_HW_QSPI_PRESCALER (2) // 100MHz
+#define MICROPY_HW_QSPIFLASH_SIZE_BITS_LOG2 (27)
+// Reserve 1MiB at the end for compatibility with alternate firmware that places WiFi blob here.
+#define MICROPY_HW_SPIFLASH_SIZE_BITS (120 * 1024 * 1024)
+#define MICROPY_HW_QSPIFLASH_CS (pyb_pin_QSPI2_CS)
+#define MICROPY_HW_QSPIFLASH_SCK (pyb_pin_QSPI2_CLK)
+#define MICROPY_HW_QSPIFLASH_IO0 (pyb_pin_QSPI2_D0)
+#define MICROPY_HW_QSPIFLASH_IO1 (pyb_pin_QSPI2_D1)
+#define MICROPY_HW_QSPIFLASH_IO2 (pyb_pin_QSPI2_D2)
+#define MICROPY_HW_QSPIFLASH_IO3 (pyb_pin_QSPI2_D3)
+
+// SPI flash #1, block device config
+extern const struct _mp_spiflash_config_t spiflash_config;
+extern struct _spi_bdev_t spi_bdev;
+#define MICROPY_HW_BDEV_IOCTL(op, arg) ( \
+ (op) == BDEV_IOCTL_NUM_BLOCKS ? (MICROPY_HW_SPIFLASH_SIZE_BITS / 8 / FLASH_BLOCK_SIZE) : \
+ (op) == BDEV_IOCTL_INIT ? spi_bdev_ioctl(&spi_bdev, (op), (uint32_t)&spiflash_config) : \
+ spi_bdev_ioctl(&spi_bdev, (op), (arg)) \
+ )
+#define MICROPY_HW_BDEV_READBLOCKS(dest, bl, n) spi_bdev_readblocks(&spi_bdev, (dest), (bl), (n))
+#define MICROPY_HW_BDEV_WRITEBLOCKS(src, bl, n) spi_bdev_writeblocks(&spi_bdev, (src), (bl), (n))
+#define MICROPY_HW_BDEV_SPIFLASH_EXTENDED (&spi_bdev)
+#endif
+
+// 4 wait states
+#define MICROPY_HW_FLASH_LATENCY FLASH_LATENCY_2
+
+// UART config
+#define MICROPY_HW_UART1_TX (pyb_pin_UART1_TX)
+#define MICROPY_HW_UART1_RX (pyb_pin_UART1_RX)
+#define MICROPY_HW_UART_REPL PYB_UART_1
+#define MICROPY_HW_UART_REPL_BAUD 115200
+
+#define MICROPY_HW_UART2_TX (pyb_pin_UART2_TX)
+#define MICROPY_HW_UART2_RX (pyb_pin_UART2_RX)
+
+#define MICROPY_HW_UART4_TX (pyb_pin_UART4_TX)
+#define MICROPY_HW_UART4_RX (pyb_pin_UART4_RX)
+
+#define MICROPY_HW_UART6_TX (pyb_pin_UART6_TX)
+#define MICROPY_HW_UART6_RX (pyb_pin_UART6_RX)
+
+#define MICROPY_HW_UART7_TX (pyb_pin_BT_TXD)
+#define MICROPY_HW_UART7_RX (pyb_pin_BT_RXD)
+#define MICROPY_HW_UART7_RTS (pyb_pin_BT_RTS)
+#define MICROPY_HW_UART7_CTS (pyb_pin_BT_CTS)
+
+// I2C busses
+#define MICROPY_HW_I2C1_SCL (pyb_pin_I2C1_SCL)
+#define MICROPY_HW_I2C1_SDA (pyb_pin_I2C1_SDA)
+
+#define MICROPY_HW_I2C2_SCL (pyb_pin_I2C2_SCL)
+#define MICROPY_HW_I2C2_SDA (pyb_pin_I2C2_SDA)
+
+#define MICROPY_HW_I2C4_SCL (pyb_pin_I2C4_SCL)
+#define MICROPY_HW_I2C4_SDA (pyb_pin_I2C4_SDA)
+
+// SPI config
+// #define MICROPY_HW_SPI1_NSS (pyb_pin_SPI1_NSS)
+#define MICROPY_HW_SPI1_SCK (pyb_pin_SPI1_SCK)
+#define MICROPY_HW_SPI1_MISO (pyb_pin_SPI1_MISO)
+#define MICROPY_HW_SPI1_MOSI (pyb_pin_SPI1_MOSI)
+
+#define MICROPY_HW_SPI5_NSS (pyb_pin_SPI5_NSS)
+#define MICROPY_HW_SPI5_SCK (pyb_pin_SPI5_SCK)
+#define MICROPY_HW_SPI5_MISO (pyb_pin_SPI5_MISO)
+#define MICROPY_HW_SPI5_MOSI (pyb_pin_SPI5_MOSI)
+
+// USRSW is pulled low. Pressing the button makes the input go high.
+#define MICROPY_HW_USRSW_PIN (pin_C13)
+#define MICROPY_HW_USRSW_PULL (GPIO_PULLDOWN)
+#define MICROPY_HW_USRSW_EXTI_MODE (GPIO_MODE_IT_RISING)
+#define MICROPY_HW_USRSW_PRESSED (1)
+
+// LEDs
+#define MICROPY_HW_LED1 (pyb_pin_LEDR) // red
+#define MICROPY_HW_LED2 (pyb_pin_LEDG) // green
+#define MICROPY_HW_LED3 (pyb_pin_LEDB) // yellow
+#define MICROPY_HW_LED_ON(pin) (mp_hal_pin_low(pin))
+#define MICROPY_HW_LED_OFF(pin) (mp_hal_pin_high(pin))
+
+// WiFi SDMMC
+#define MICROPY_HW_SDIO_SDMMC (1)
+#define MICROPY_HW_SDIO_CK (pyb_pin_WL_SDIO_CLK)
+#define MICROPY_HW_SDIO_CMD (pyb_pin_WL_SDIO_CMD)
+#define MICROPY_HW_SDIO_D0 (pyb_pin_WL_SDIO_0)
+#define MICROPY_HW_SDIO_D1 (pyb_pin_WL_SDIO_1)
+#define MICROPY_HW_SDIO_D2 (pyb_pin_WL_SDIO_2)
+#define MICROPY_HW_SDIO_D3 (pyb_pin_WL_SDIO_3)
+
+// CYW43 config
+#define CYW43_WIFI_NVRAM_INCLUDE_FILE "wifi_nvram_1dx.h"
+
+// USB config
+#define MICROPY_HW_USB_FS (1)
+
+#define MICROPY_HW_USB_CDC_RX_DATA_SIZE (1024)
+#define MICROPY_HW_USB_CDC_TX_DATA_SIZE (1024)
+#define MICROPY_HW_USB_CDC_1200BPS_TOUCH (1)
+
+// Bluetooth config
+#define MICROPY_HW_BLE_UART_ID (PYB_UART_7)
+#define MICROPY_HW_BLE_UART_BAUDRATE (115200)
+#define MICROPY_HW_BLE_UART_BAUDRATE_SECONDARY (3000000)
+
+// SDRAM
+#define MICROPY_HW_SDRAM_SIZE (64 / 8 * 1024 * 1024) // 64 Mbit
+#define MICROPY_HW_SDRAM_STARTUP_TEST (1)
+#define MICROPY_HW_SDRAM_TEST_FAIL_ON_ERROR (true)
+
+// Timing configuration for 200MHz/2=100MHz (10ns)
+#define MICROPY_HW_SDRAM_CLOCK_PERIOD 2
+#define MICROPY_HW_SDRAM_CAS_LATENCY 2
+#define MICROPY_HW_SDRAM_FREQUENCY (100000) // 100 MHz
+#define MICROPY_HW_SDRAM_TIMING_TMRD (2)
+#define MICROPY_HW_SDRAM_TIMING_TXSR (7)
+#define MICROPY_HW_SDRAM_TIMING_TRAS (5)
+#define MICROPY_HW_SDRAM_TIMING_TRC (7)
+#define MICROPY_HW_SDRAM_TIMING_TWR (2)
+#define MICROPY_HW_SDRAM_TIMING_TRP (3)
+#define MICROPY_HW_SDRAM_TIMING_TRCD (3)
+
+#define MICROPY_HW_SDRAM_ROW_BITS_NUM 12
+#define MICROPY_HW_SDRAM_MEM_BUS_WIDTH 16
+#define MICROPY_HW_SDRAM_REFRESH_CYCLES 4096
+
+#define MICROPY_HW_SDRAM_COLUMN_BITS_NUM 8
+#define MICROPY_HW_SDRAM_INTERN_BANKS_NUM 4
+#define MICROPY_HW_SDRAM_RPIPE_DELAY 0
+#define MICROPY_HW_SDRAM_RBURST (1)
+#define MICROPY_HW_SDRAM_WRITE_PROTECTION (0)
+
+#define MICROPY_HW_SDRAM_AUTOREFRESH_NUM (8)
+#define MICROPY_HW_SDRAM_BURST_LENGTH 1
+#define MICROPY_HW_SDRAM_REFRESH_RATE (64) // ms
+
+// SDRAM configuration
+#define MICROPY_HW_FMC_SDCKE0 (pin_H2)
+#define MICROPY_HW_FMC_SDNE0 (pin_H3)
+#define MICROPY_HW_FMC_SDNBL0 (pin_E0)
+#define MICROPY_HW_FMC_SDNBL1 (pin_E1)
+#define MICROPY_HW_FMC_SDCLK (pin_G8)
+#define MICROPY_HW_FMC_SDNCAS (pin_G15)
+#define MICROPY_HW_FMC_SDNRAS (pin_F11)
+#define MICROPY_HW_FMC_SDNWE (pin_H5)
+#define MICROPY_HW_FMC_BA0 (pin_G4)
+#define MICROPY_HW_FMC_BA1 (pin_G5)
+#define MICROPY_HW_FMC_NBL0 (pin_E0)
+#define MICROPY_HW_FMC_NBL1 (pin_E1)
+#define MICROPY_HW_FMC_A0 (pin_F0)
+#define MICROPY_HW_FMC_A1 (pin_F1)
+#define MICROPY_HW_FMC_A2 (pin_F2)
+#define MICROPY_HW_FMC_A3 (pin_F3)
+#define MICROPY_HW_FMC_A4 (pin_F4)
+#define MICROPY_HW_FMC_A5 (pin_F5)
+#define MICROPY_HW_FMC_A6 (pin_F12)
+#define MICROPY_HW_FMC_A7 (pin_F13)
+#define MICROPY_HW_FMC_A8 (pin_F14)
+#define MICROPY_HW_FMC_A9 (pin_F15)
+#define MICROPY_HW_FMC_A10 (pin_G0)
+#define MICROPY_HW_FMC_A11 (pin_G1)
+#define MICROPY_HW_FMC_A12 (pin_G2)
+#define MICROPY_HW_FMC_D0 (pin_D14)
+#define MICROPY_HW_FMC_D1 (pin_D15)
+#define MICROPY_HW_FMC_D2 (pin_D0)
+#define MICROPY_HW_FMC_D3 (pin_D1)
+#define MICROPY_HW_FMC_D4 (pin_E7)
+#define MICROPY_HW_FMC_D5 (pin_E8)
+#define MICROPY_HW_FMC_D6 (pin_E9)
+#define MICROPY_HW_FMC_D7 (pin_E10)
+#define MICROPY_HW_FMC_D8 (pin_E11)
+#define MICROPY_HW_FMC_D9 (pin_E12)
+#define MICROPY_HW_FMC_D10 (pin_E13)
+#define MICROPY_HW_FMC_D11 (pin_E14)
+#define MICROPY_HW_FMC_D12 (pin_E15)
+#define MICROPY_HW_FMC_D13 (pin_D8)
+#define MICROPY_HW_FMC_D14 (pin_D9)
+#define MICROPY_HW_FMC_D15 (pin_D10)
+
+#define MICROPY_HW_USB_VID 0x2341
+#define MICROPY_HW_USB_PID 0x0566
+#define MICROPY_HW_USB_PID_CDC_MSC (MICROPY_HW_USB_PID)
+#define MICROPY_HW_USB_PID_CDC_HID (MICROPY_HW_USB_PID)
+#define MICROPY_HW_USB_PID_CDC (MICROPY_HW_USB_PID)
+#define MICROPY_HW_USB_PID_MSC (MICROPY_HW_USB_PID)
+#define MICROPY_HW_USB_PID_CDC2_MSC (MICROPY_HW_USB_PID)
+#define MICROPY_HW_USB_PID_CDC2 (MICROPY_HW_USB_PID)
+#define MICROPY_HW_USB_PID_CDC3 (MICROPY_HW_USB_PID)
+#define MICROPY_HW_USB_PID_CDC3_MSC (MICROPY_HW_USB_PID)
+#define MICROPY_HW_USB_PID_CDC_MSC_HID (MICROPY_HW_USB_PID)
+#define MICROPY_HW_USB_PID_CDC2_MSC_HID (MICROPY_HW_USB_PID)
+#define MICROPY_HW_USB_PID_CDC3_MSC_HID (MICROPY_HW_USB_PID)
+#define MICROPY_HW_USB_LANGID_STRING 0x409
+#define MICROPY_HW_USB_MANUFACTURER_STRING "Arduino"
+#define MICROPY_HW_USB_PRODUCT_FS_STRING "Giga Virtual Comm Port in FS Mode"
+#define MICROPY_HW_USB_PRODUCT_HS_STRING "Giga Virtual Comm Port in HS Mode"
+#define MICROPY_HW_USB_INTERFACE_FS_STRING "Giga Interface"
+#define MICROPY_HW_USB_INTERFACE_HS_STRING "Giga Interface"
+#define MICROPY_HW_USB_CONFIGURATION_FS_STRING "Giga Config"
+#define MICROPY_HW_USB_CONFIGURATION_HS_STRING "Giga Config"
diff --git a/ports/stm32/boards/ARDUINO_GIGA/mpconfigboard.mk b/ports/stm32/boards/ARDUINO_GIGA/mpconfigboard.mk
new file mode 100644
index 000000000000..135b12b8c8c5
--- /dev/null
+++ b/ports/stm32/boards/ARDUINO_GIGA/mpconfigboard.mk
@@ -0,0 +1,28 @@
+USE_MBOOT = 0
+USE_PYDFU = 0
+# For dual core HAL drivers.
+CFLAGS += -DCORE_CM7
+
+# Arduino bootloader PID:VID
+BOOTLOADER_DFU_USB_VID = 0x2341
+BOOTLOADER_DFU_USB_PID = 0x0366
+
+# MCU settings
+MCU_SERIES = h7
+CMSIS_MCU = STM32H747xx
+MICROPY_FLOAT_IMPL = single
+AF_FILE = boards/stm32h743_af.csv
+LD_FILES = boards/ARDUINO_GIGA/stm32h747.ld
+TEXT0_ADDR = 0x08040000
+
+# MicroPython settings
+MICROPY_PY_BLUETOOTH = 1
+MICROPY_BLUETOOTH_NIMBLE = 1
+MICROPY_BLUETOOTH_BTSTACK = 0
+MICROPY_PY_LWIP = 1
+MICROPY_PY_NETWORK_CYW43 = 1
+MICROPY_PY_USSL = 1
+MICROPY_SSL_MBEDTLS = 1
+
+FROZEN_MANIFEST = $(BOARD_DIR)/manifest.py
+MBEDTLS_CONFIG_FILE = '"$(BOARD_DIR)/mbedtls_config_board.h"'
diff --git a/ports/stm32/boards/ARDUINO_GIGA/pins.csv b/ports/stm32/boards/ARDUINO_GIGA/pins.csv
new file mode 100644
index 000000000000..c27b5d8cd4f0
--- /dev/null
+++ b/ports/stm32/boards/ARDUINO_GIGA/pins.csv
@@ -0,0 +1,219 @@
+PA0,PA0
+PA1,PA1
+PA2,-PA2
+PA3,-PA3
+PA4,PA4
+PA5,-PA5
+PA6,-PA6
+PA7,-PA7
+PA8,PA8
+PA9,PA9
+PA10,PA10
+PA11,PA11
+PA12,PA12
+PA13,PA13
+PA14,PA14
+PA15,PA15
+PB0,-PB0
+PB1,-PB1
+PB2,PB2
+PB3,PB3
+PB4,PB4
+PB5,PB5
+PB6,PB6
+PB7,PB7
+PB8,PB8
+PB9,PB9
+PB10,PB10
+PB11,PB11
+PB12,PB12
+PB13,PB13
+PB14,PB14
+PB15,PB15
+PC0,-PC0
+PC1,-PC1
+PC2,PC2
+PC3,PC3
+PC4,-PC4
+PC5,-PC5
+PC6,PC6
+PC7,PC7
+PC8,PC8
+PC9,PC9
+PC10,PC10
+PC11,PC11
+PC12,PC12
+PC13,PC13
+PC14,PC14
+PC15,PC15
+PD0,PD0
+PD1,PD1
+PD2,PD2
+PD3,PD3
+PD4,PD4
+PD5,PD5
+PD6,PD6
+PD7,PD7
+PD8,PD8
+PD9,PD9
+PD10,PD10
+PD11,PD11
+PD12,PD12
+PD13,PD13
+PD14,PD14
+PD15,PD15
+PE0,PE0
+PE1,PE1
+PE2,PE2
+PE3,PE3
+PE4,PE4
+PE5,PE5
+PE6,PE6
+PE7,PE7
+PE8,PE8
+PE9,PE9
+PE10,PE10
+PE11,PE11
+PE12,PE12
+PE13,PE13
+PE14,PE14
+PE15,PE15
+PF0,PF0
+PF1,PF1
+PF2,PF2
+PF3,-PF3
+PF4,-PF4
+PF5,-PF5
+PF6,-PF6
+PF7,-PF7
+PF8,-PF8
+PF9,-PF9
+PF10,-PF10
+PF11,-PF11
+PF12,PF12
+PF13,PF13
+PF14,-PF14
+PF15,PF15
+PG0,PG0
+PG1,PG1
+PG2,PG2
+PG3,PG3
+PG4,PG4
+PG5,PG5
+PG6,PG6
+PG7,PG7
+PG8,PG8
+PG9,PG9
+PG10,PG10
+PG11,PG11
+PG12,PG12
+PG13,PG13
+PG14,PG14
+PG15,PG15
+PH0,PH0
+PH1,PH1
+PH2,-PH2
+PH3,-PH3
+PH4,-PH4
+PH5,-PH5
+PH6,PH6
+PH7,PH7
+PH8,PH8
+PH9,PH9
+PH10,PH10
+PH11,PH11
+PH12,PH12
+PH13,PH13
+PH14,PH14
+PH15,PH15
+PI0,PI0
+PI1,PI1
+PI2,PI2
+PI3,PI3
+PI4,PI4
+PI5,PI5
+PI6,PI6
+PI7,PI7
+PI8,PI8
+PI9,PI9
+PI10,PI10
+PI11,PI11
+PI12,PI12
+PI13,PI13
+PI14,PI14
+PI15,PI15
+PJ0,PJ0
+PJ1,PJ1
+PJ2,PJ2
+PJ3,PJ3
+PJ4,PJ4
+PJ5,PJ5
+PJ6,PJ6
+PJ7,PJ7
+PJ8,PJ8
+PJ9,PJ9
+PJ10,PJ10
+PJ11,PJ11
+PJ12,PJ12
+PJ13,PJ13
+PJ14,PJ14
+PJ15,PJ15
+PK0,PK0
+PK1,PK1
+PK2,PK2
+PK3,PK3
+PK4,PK4
+PK5,PK5
+PK6,PK6
+PK7,PK7
+UART1_TX,PA9
+UART1_RX,PB7
+UART2_TX,PD5
+UART2_RX,PD6
+UART4_TX,PH13
+UART4_RX,PI9
+UART6_TX,PG14
+UART6_RX,PC7
+-USB_DM,PA11
+-USB_DP,PA12
+BOOT0,BOOT0
+DAC1,PA4
+DAC2,PA5
+LEDR,PI12
+LEDG,PJ13
+LEDB,PE3
+I2C1_SDA,PB9
+I2C1_SCL,PB8
+I2C2_SDA,PB11
+I2C2_SCL,PH4
+I2C4_SDA,PH12
+I2C4_SCL,PB6
+-WL_REG_ON,PB10
+-WL_HOST_WAKE,PI8
+-WL_SDIO_0,PC8
+-WL_SDIO_1,PC9
+-WL_SDIO_2,PC10
+-WL_SDIO_3,PC11
+-WL_SDIO_CMD,PD2
+-WL_SDIO_CLK,PC12
+-BT_RXD,-PA8
+-BT_TXD,PF7
+-BT_CTS,-PF9
+-BT_RTS,-PF8
+-BT_REG_ON,PA10
+-BT_HOST_WAKE,PG3
+-BT_DEV_WAKE,PH7
+-QSPI2_CS,PG6
+-QSPI2_CLK,PF10
+-QSPI2_D0,PD11
+-QSPI2_D1,PD12
+-QSPI2_D2,PE2
+-QSPI2_D3,PF6
+-SPI1_NSS,NC
+-SPI1_SCK,PB3
+-SPI1_MISO,PG9
+-SPI1_MOSI,PD7
+-SPI5_NSS,PK1
+-SPI5_SCK,PH6
+-SPI5_MISO,PJ11
+-SPI5_MOSI,PJ10
\ No newline at end of file
diff --git a/ports/stm32/boards/ARDUINO_GIGA/stm32h747.ld b/ports/stm32/boards/ARDUINO_GIGA/stm32h747.ld
new file mode 100644
index 000000000000..d5bd9598f982
--- /dev/null
+++ b/ports/stm32/boards/ARDUINO_GIGA/stm32h747.ld
@@ -0,0 +1,47 @@
+/*
+ GNU linker script for STM32H747
+*/
+
+/* Specify the memory areas */
+MEMORY
+{
+ ITCM (xrw) : ORIGIN = 0x00000000, LENGTH = 64K
+ DTCM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K
+ RAM (xrw) : ORIGIN = 0x24000000, LENGTH = 512K /* AXI SRAM D1 */
+ SRAM1 (xrw) : ORIGIN = 0x30000000, LENGTH = 128K /* SRAM1 D2 */
+ SRAM2 (xrw) : ORIGIN = 0x30020000, LENGTH = 128K /* SRAM2 D2 */
+ SRAM3 (xrw) : ORIGIN = 0x30040000, LENGTH = 32K /* SRAM3 D2 */
+ SRAM4 (xrw) : ORIGIN = 0x38000000, LENGTH = 64K /* SRAM4 D3 */
+ FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 2048K /* Total available flash */
+ FLASH_EXT (rx) : ORIGIN = 0x90000000, LENGTH = 16384K /* 16MBs external QSPI flash */
+ FLASH_FS (r) : ORIGIN = 0x08020000, LENGTH = 128K /* sector 1 -> Flash storage */
+ FLASH_TEXT (rx) : ORIGIN = 0x08040000, LENGTH = 1792K /* Sector 0 -> Arduino Bootloader
+ Sector 1 -> Reserved for CM4/FS
+ Sectors 2 -> 15 firmware */
+}
+
+/* produce a link error if there is not this amount of RAM for these sections */
+_minimum_stack_size = 2K;
+_minimum_heap_size = 16K;
+
+/* Define the stack. The stack is full descending so begins just above last byte
+ of RAM. Note that EABI requires the stack to be 8-byte aligned for a call. */
+_estack = ORIGIN(RAM) + LENGTH(RAM) - _estack_reserve;
+_sstack = _estack - 16K; /* tunable */
+
+/* RAM extents for the garbage collector */
+_ram_start = ORIGIN(RAM);
+_ram_end = ORIGIN(RAM) + LENGTH(RAM);
+_heap_start = _ebss; /* heap starts just after statically allocated memory */
+_heap_end = _sstack;
+
+/* Note the following varilables are only used if the filesystem flash storage is enabled */
+/* Location of filesystem RAM cache */
+_micropy_hw_internal_flash_storage_ram_cache_start = ORIGIN(DTCM);
+_micropy_hw_internal_flash_storage_ram_cache_end = ORIGIN(DTCM) + LENGTH(DTCM);
+
+/* Location of filesystem flash storage */
+_micropy_hw_internal_flash_storage_start = ORIGIN(FLASH_FS);
+_micropy_hw_internal_flash_storage_end = ORIGIN(FLASH_FS) + LENGTH(FLASH_FS);
+
+INCLUDE common_blifs.ld
diff --git a/ports/stm32/boards/ARDUINO_GIGA/stm32h7xx_hal_conf.h b/ports/stm32/boards/ARDUINO_GIGA/stm32h7xx_hal_conf.h
new file mode 100644
index 000000000000..b3b2e00dbb90
--- /dev/null
+++ b/ports/stm32/boards/ARDUINO_GIGA/stm32h7xx_hal_conf.h
@@ -0,0 +1,51 @@
+/* This file is part of the MicroPython project, http://micropython.org/
+ * The MIT License (MIT)
+ * Copyright (c) 2019 Damien P. George
+ */
+#ifndef MICROPY_INCLUDED_STM32H7XX_HAL_CONF_H
+#define MICROPY_INCLUDED_STM32H7XX_HAL_CONF_H
+
+#include "boards/stm32h7xx_hal_conf_base.h"
+
+// Oscillator values in Hz
+#define HSE_VALUE (16000000)
+#define LSE_VALUE (32768)
+#define EXTERNAL_CLOCK_VALUE (12288000)
+
+// Oscillator timeouts in ms
+#define HSE_STARTUP_TIMEOUT (5000)
+#define LSE_STARTUP_TIMEOUT (5000)
+
+#define DATA_CACHE_ENABLE 1
+#define INSTRUCTION_CACHE_ENABLE 1
+#define DATA_CACHE_ENABLE 1
+#define INSTRUCTION_CACHE_ENABLE 1
+#define PREFETCH_ENABLE 1
+#define USE_RTOS 0
+
+#define HAL_HSEM_MODULE_ENABLED
+#define HAL_JPEG_MODULE_ENABLED
+#define HAL_LPTIM_MODULE_ENABLED
+#define HAL_LTDC_MODULE_ENABLED
+#define HAL_MDIOS_MODULE_ENABLED
+#define HAL_MDMA_MODULE_ENABLED
+#define HAL_MMC_MODULE_ENABLED
+#define HAL_NAND_MODULE_ENABLED
+#define HAL_OPAMP_MODULE_ENABLED
+#define HAL_QSPI_MODULE_ENABLED
+#define HAL_RNG_MODULE_ENABLED
+#define HAL_SAI_MODULE_ENABLED
+#define HAL_SMBUS_MODULE_ENABLED
+#define HAL_SPDIFRX_MODULE_ENABLED
+#define HAL_SRAM_MODULE_ENABLED
+#define HAL_SWPMI_MODULE_ENABLED
+
+#ifdef HAL_HSEM_MODULE_ENABLED
+#include "stm32h7xx_hal_hsem.h"
+#endif
+
+#ifdef HAL_MMC_MODULE_ENABLED
+#include "stm32h7xx_hal_mmc.h"
+#endif
+
+#endif // MICROPY_INCLUDED_STM32H7XX_HAL_CONF_H
diff --git a/ports/stm32/boards/ARDUINO_GIGA/wifi_nvram_1dx.h b/ports/stm32/boards/ARDUINO_GIGA/wifi_nvram_1dx.h
new file mode 100644
index 000000000000..7b98edad1157
--- /dev/null
+++ b/ports/stm32/boards/ARDUINO_GIGA/wifi_nvram_1dx.h
@@ -0,0 +1,49 @@
+static const uint8_t wifi_nvram_4343[] CYW43_RESOURCE_ATTRIBUTE =
+ // Type1DX_Final_nvram2.txt
+ // 2.4 GHz, 20 MHz BW mode
+ "manfid=0x2d0\x00"
+ "prodid=0x0726\x00"
+ "vendid=0x14e4\x00"
+ "devid=0x43e2\x00"
+ "boardtype=0x0726\x00"
+ "boardrev=0x1202\x00"
+ "boardnum=22\x00"
+ "macaddr=00:90:4c:c5:12:38\x00"
+ "sromrev=11\x00"
+ "boardflags=0x00404201\x00"
+ "boardflags3=0x04000000\x00"
+ "xtalfreq=37400\x00"
+ "nocrc=1\x00"
+ "ag0=0\x00"
+ "aa2g=1\x00"
+ "ccode=ALL\x00"
+ // "pa0itssit=0x20\x00"
+ "extpagain2g=0\x00"
+ "pa2ga0=-145,6667,-751\x00"
+ "AvVmid_c0=0x0,0xc8\x00"
+ "cckpwroffset0=2\x00"
+ "maxp2ga0=74\x00"
+ // "txpwrbckof=6\x00"
+ "cckbw202gpo=0\x00"
+ "legofdmbw202gpo=0x88888888\x00"
+ "mcsbw202gpo=0xaaaaaaaa\x00"
+ "propbw202gpo=0xdd\x00"
+ "ofdmdigfilttype=18\x00"
+ "ofdmdigfilttypebe=18\x00"
+ "papdmode=1\x00"
+ "papdvalidtest=1\x00"
+ "pacalidx2g=48\x00"
+ "papdepsoffset=-22\x00"
+ "papdendidx=58\x00"
+ "il0macaddr=00:90:4c:c5:12:38\x00"
+ "wl0id=0x431b\x00"
+ "muxenab=0x10\x00"
+ // BT COEX deferral limit setting
+ // "btc_params 8 45000\x00"
+ // "btc_params 10 20000\x00"
+ // "spurconfig=0x3\x00"
+ // Antenna diversity
+ "swdiv_en=1\x00"
+ "swdiv_gpio=1\x00"
+ "\x00\x00"
+;
diff --git a/ports/stm32/boards/ARDUINO_NICLA_VISION/bdev.c b/ports/stm32/boards/ARDUINO_NICLA_VISION/bdev.c
new file mode 100644
index 000000000000..caadc2b649ee
--- /dev/null
+++ b/ports/stm32/boards/ARDUINO_NICLA_VISION/bdev.c
@@ -0,0 +1,45 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2023 Arduino SA
+ *
+ * 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 "storage.h"
+#include "qspi.h"
+
+#if MICROPY_HW_SPIFLASH_ENABLE_CACHE
+// Shared cache for first and second SPI block devices
+STATIC mp_spiflash_cache_t spi_bdev_cache;
+#endif
+
+// First external SPI flash uses hardware QSPI interface
+const mp_spiflash_config_t spiflash_config = {
+ .bus_kind = MP_SPIFLASH_BUS_QSPI,
+ .bus.u_qspi.data = NULL,
+ .bus.u_qspi.proto = &qspi_proto,
+ #if MICROPY_HW_SPIFLASH_ENABLE_CACHE
+ .cache = &spi_bdev_cache,
+ #endif
+};
+
+spi_bdev_t spi_bdev;
diff --git a/ports/stm32/boards/ARDUINO_NICLA_VISION/board.json b/ports/stm32/boards/ARDUINO_NICLA_VISION/board.json
new file mode 100644
index 000000000000..801bc320b555
--- /dev/null
+++ b/ports/stm32/boards/ARDUINO_NICLA_VISION/board.json
@@ -0,0 +1,21 @@
+{
+ "deploy": [
+ "./deploy.md"
+ ],
+ "docs": "",
+ "features": [
+ "16MB Flash",
+ "Dual-core processor",
+ "USB High Speed Phy",
+ "CYW43 WiFi/BT Module",
+ "NXP SE050 crypto device"
+ ],
+ "images": [
+ "ABX00051_01.iso_1000x750.jpg"
+ ],
+ "mcu": "stm32h7",
+ "product": "Arduino Nicla Vision",
+ "thumbnail": "",
+ "url": "https://store.arduino.cc/products/nicla-vision",
+ "vendor": "Arduino"
+}
diff --git a/ports/stm32/boards/ARDUINO_NICLA_VISION/board_init.c b/ports/stm32/boards/ARDUINO_NICLA_VISION/board_init.c
new file mode 100644
index 000000000000..5ca495a60649
--- /dev/null
+++ b/ports/stm32/boards/ARDUINO_NICLA_VISION/board_init.c
@@ -0,0 +1,227 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2023 Arduino SA
+ *
+ * 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 "storage.h"
+#include "ulpi.h"
+
+void NICLAV_board_startup(void) {
+}
+
+void NICLAV_board_pmic_enable(int);
+
+void NICLAV_board_early_init(void) {
+ HAL_InitTick(0);
+
+ // Enable oscillator pin
+ // This is enabled in the bootloader anyway.
+ NICLAV_board_osc_enable(true);
+
+ // Re/Enable PMIC rails.
+ NICLAV_board_pmic_enable(true);
+
+ #if MICROPY_HW_ENABLE_INTERNAL_FLASH_STORAGE
+ // The Arduino/mbed bootloader uses the MPU to protect sector 1
+ // which is used for the flash filesystem. The following code
+ // resets and disables all MPU regions configured in the bootloader.
+ HAL_MPU_Disable();
+ MPU_Region_InitTypeDef MPU_InitStruct;
+ MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
+ MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;
+ MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;
+ MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
+ MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL1;
+ MPU_InitStruct.SubRegionDisable = 0x00;
+ MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;
+
+ for (int i = MPU_REGION_NUMBER0; i < MPU_REGION_NUMBER15; i++) {
+ MPU_InitStruct.Number = i;
+ MPU_InitStruct.Enable = MPU_REGION_DISABLE;
+ HAL_MPU_ConfigRegion(&MPU_InitStruct);
+ }
+ #endif
+
+ // Make sure PC2 and PC3 and PC2_C and PC3_C pads are connected
+ // through the analog switch for ULPI NXT and DIR pins.
+ HAL_SYSCFG_AnalogSwitchConfig(SYSCFG_SWITCH_PC2, SYSCFG_SWITCH_PC2_CLOSE);
+ HAL_SYSCFG_AnalogSwitchConfig(SYSCFG_SWITCH_PC3, SYSCFG_SWITCH_PC3_CLOSE);
+
+ #if MICROPY_HW_USB_HS_ULPI3320
+ // Make sure UPLI is Not in low-power mode.
+ ulpi_leave_low_power();
+ #endif
+}
+
+void NICLAV_board_enter_bootloader(void) {
+ RTC_HandleTypeDef RTCHandle;
+ RTCHandle.Instance = RTC;
+ HAL_RTCEx_BKUPWrite(&RTCHandle, RTC_BKP_DR0, 0xDF59);
+ NVIC_SystemReset();
+}
+
+void NICLAV_board_osc_enable(int enable) {
+ mp_hal_pin_config(pyb_pin_OSCEN, MP_HAL_PIN_MODE_OUTPUT, MP_HAL_PIN_PULL_UP, 0);
+ mp_hal_pin_config_speed(pyb_pin_OSCEN, MP_HAL_PIN_SPEED_LOW);
+ mp_hal_pin_write(pyb_pin_OSCEN, enable);
+}
+
+void NICLAV_board_pmic_enable(int enable) {
+ __HAL_RCC_GPIOF_CLK_ENABLE();
+
+ // Configure PMIC I2C GPIOs
+ GPIO_InitTypeDef GPIO_InitStructure;
+ GPIO_InitStructure.Pin = GPIO_PIN_0 | GPIO_PIN_1;
+ GPIO_InitStructure.Pull = GPIO_PULLUP;
+ GPIO_InitStructure.Speed = GPIO_SPEED_LOW;
+ GPIO_InitStructure.Mode = GPIO_MODE_AF_OD;
+ GPIO_InitStructure.Alternate = GPIO_AF4_I2C2;
+ HAL_GPIO_Init(GPIOF, &GPIO_InitStructure);
+
+ // Configure PMIC I2C
+ I2C_HandleTypeDef i2c;
+ i2c.Instance = I2C2;
+ i2c.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
+ i2c.Init.Timing = 0x20D09DE7;
+ i2c.Init.DualAddressMode = I2C_DUALADDRESS_DISABLED;
+ i2c.Init.GeneralCallMode = I2C_GENERALCALL_DISABLED;
+ i2c.Init.NoStretchMode = I2C_NOSTRETCH_DISABLED;
+ i2c.Init.OwnAddress1 = 0xFE;
+ i2c.Init.OwnAddress2 = 0xFE;
+ i2c.Init.OwnAddress2Masks = 0;
+
+ __HAL_RCC_I2C2_CLK_ENABLE();
+ __HAL_RCC_I2C2_FORCE_RESET();
+ __HAL_RCC_I2C2_RELEASE_RESET();
+ HAL_I2C_Init(&i2c);
+
+ // LDO1 2V8
+ HAL_I2C_Master_Transmit(&i2c, 0x08 << 1, (uint8_t [2]) {0x4D, (enable) ? 0x01 : 0x00}, 2, 1000);
+ // LDO2 1V8 CAM
+ HAL_I2C_Master_Transmit(&i2c, 0x08 << 1, (uint8_t [2]) {0x50, (enable) ? 0x01 : 0x00}, 2, 1000);
+ // LDO3 1V8
+ HAL_I2C_Master_Transmit(&i2c, 0x08 << 1, (uint8_t [2]) {0x53, (enable) ? 0x01 : 0x00}, 2, 1000);
+ // SW2 VDDIO_EXT
+ HAL_I2C_Master_Transmit(&i2c, 0x08 << 1, (uint8_t [2]) {0x3b, (enable) ? 0x81 : 0x80}, 2, 1000);
+ // SW3 3V3 (Leaving 3.3 on lowers ULPI current).
+ // HAL_I2C_Master_Transmit(&i2c, 0x08<<1, (uint8_t [2]) {0x41, (enable) ? 0x81 : 0x80}, 2, 1000);
+ // SW1 1V8 (Main supply is Never turned off)
+ // HAL_I2C_Master_Transmit(&i2c, 0x08<<1, (uint8_t [2]) {0x35, (enable) ? 0x81 : 0x80}, 2, 1000);
+
+ HAL_I2C_DeInit(&i2c);
+ __HAL_RCC_I2C2_FORCE_RESET();
+ __HAL_RCC_I2C2_RELEASE_RESET();
+ __HAL_RCC_I2C2_CLK_DISABLE();
+
+ HAL_GPIO_DeInit(GPIOF, GPIO_PIN_0);
+ HAL_GPIO_DeInit(GPIOF, GPIO_PIN_1);
+ __HAL_RCC_GPIOF_CLK_DISABLE();
+}
+
+static __attribute__((naked, noreturn)) void cm4_enter_standby(void) {
+ // Clear and mask D1 EXTIs.
+ EXTI_D1->PR1 = 0x3fffff;
+ EXTI_D1->IMR1 &= ~(0xFFFFu); // 16 lines
+
+ // Clear and mask D2 EXTIs.
+ EXTI_D2->IMR1 &= ~(0xFFFFu); // 16 lines
+ EXTI_D2->PR1 = 0x3fffff;
+
+ EXTI->D3PMR1 = 0;///0x0238FFFFu;
+ EXTI->D3PMR2 = 0;///0x003F020Cu;
+ EXTI->D3PMR3 = 0;///0x01000000u;
+
+ // Set D2/D2 PDDS bits.
+ PWR->CPUCR |= (PWR_CPUCR_PDDS_D2 | PWR_CPUCR_PDDS_D3);
+ PWR->CPU2CR |= (PWR_CPU2CR_PDDS_D2 | PWR_CPU2CR_PDDS_D3);
+ CLEAR_BIT(PWR->CPU2CR, PWR_CPU2CR_RUN_D3);
+
+ // Set SLEEPDEEP bit.
+ SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
+
+ // Enter CPU stop mode.
+ __WFI();
+}
+
+void NICLAV_board_low_power(int mode) {
+ switch (mode) {
+ case 0: // Leave stop mode.
+ ulpi_leave_low_power();
+ break;
+ case 1: // Enter stop mode.
+ ulpi_enter_low_power();
+ break;
+ case 2: // Enter standby mode.
+ ulpi_enter_low_power();
+ break;
+ }
+
+ #if (MICROPY_HW_ENABLE_INTERNAL_FLASH_STORAGE == 0)
+ // Enable QSPI deepsleep for modes 1 and 2
+ mp_spiflash_deepsleep(&spi_bdev.spiflash, (mode != 0));
+ #endif
+
+ if (mode == 2) {
+ if (RCC->GCR & RCC_GCR_BOOT_C2) {
+ // If CM4 is booted, it should be running a firmware
+ // that supports low-power mode entry via HSEM.
+ __HAL_RCC_HSEM_CLK_ENABLE();
+ HAL_HSEM_FastTake(0);
+ HAL_HSEM_Release(0, 0);
+ } else {
+ // If CM4 is not booted, rig an ISR vector, with a reset
+ // handler that points to standby function and boot it.
+ volatile extern char _cm4_ram_start[1024];
+
+ uint32_t *cm4_ram = (uint32_t *)_cm4_ram_start;
+ cm4_ram[0] = (uint32_t)(_cm4_ram_start + 1024);
+ cm4_ram[1] = ((uint32_t)&cm4_enter_standby) | 1;
+ SCB_CleanDCache_by_Addr((uint32_t *)_cm4_ram_start, 8);
+
+ HAL_PWREx_HoldCore(PWR_CORE_CPU2);
+ HAL_SYSCFG_CM4BootAddConfig(SYSCFG_BOOT_ADDR0, (uint32_t)_cm4_ram_start);
+ HAL_RCCEx_EnableBootCore(RCC_BOOT_C2);
+ }
+
+ // Wait for the CM4 to enter stop mode.
+ HAL_Delay(100);
+
+ // Disable all power rails, except core voltage.
+ NICLAV_board_pmic_enable(false);
+
+ // Reset all busses, peripherals, GPIO clocks etc..
+ RCC->AHB1RSTR = 0x0A00C023U;
+ RCC->AHB2RSTR = 0x00000271U;
+ RCC->AHB3RSTR = 0x00015031U;
+ RCC->AHB4RSTR = 0x0328077FU; // LSE GPIO port is masked.
+
+ RCC->APB1LRSTR = 0xE8FFC3FFU;
+ RCC->APB1HRSTR = 0x00000136U;
+ RCC->APB2RSTR = 0x31D73033U;
+ RCC->APB3RSTR = 0x00000018U;
+ RCC->APB4RSTR = 0x0020DEAAU;
+ }
+}
diff --git a/ports/stm32/boards/ARDUINO_NICLA_VISION/deploy.md b/ports/stm32/boards/ARDUINO_NICLA_VISION/deploy.md
new file mode 100644
index 000000000000..ad26ad20f89e
--- /dev/null
+++ b/ports/stm32/boards/ARDUINO_NICLA_VISION/deploy.md
@@ -0,0 +1,14 @@
+### Via dfu-util
+
+This board can programmed via DFU bootloader, using e.g. [dfu-util](http://dfu-util.sourceforge.net/).
+To enter the DFU bootloader, double tap the reset (blue) button, or you can use `machine.bootloader()` from the MicroPython REPL.
+
+```bash
+dfu-util -w -a 0 -d 2341:035b -D build-ARDUINO_NICLA_VISION/firmware.dfu
+```
+
+Or from MicroPython source repository:
+
+```bash
+make BOARD=ARDUINO_NICLA_VISION deploy
+```
diff --git a/ports/stm32/boards/ARDUINO_NICLA_VISION/manifest.py b/ports/stm32/boards/ARDUINO_NICLA_VISION/manifest.py
new file mode 100644
index 000000000000..b3c6b02e5ba0
--- /dev/null
+++ b/ports/stm32/boards/ARDUINO_NICLA_VISION/manifest.py
@@ -0,0 +1,12 @@
+include("$(PORT_DIR)/boards/manifest.py")
+
+# Networking
+require("bundle-networking")
+
+# Utils
+require("time")
+require("senml")
+require("logging")
+
+# Bluetooth
+require("aioble")
diff --git a/ports/stm32/boards/ARDUINO_NICLA_VISION/mbedtls_config_board.h b/ports/stm32/boards/ARDUINO_NICLA_VISION/mbedtls_config_board.h
new file mode 100644
index 000000000000..0e1703f1bf96
--- /dev/null
+++ b/ports/stm32/boards/ARDUINO_NICLA_VISION/mbedtls_config_board.h
@@ -0,0 +1,8 @@
+#ifndef MICROPY_INCLUDED_MBEDTLS_CONFIG_BOARD_H
+#define MICROPY_INCLUDED_MBEDTLS_CONFIG_BOARD_H
+
+#define MBEDTLS_ECP_NIST_OPTIM
+
+#include "ports/stm32/mbedtls/mbedtls_config.h"
+
+#endif /* MICROPY_INCLUDED_MBEDTLS_CONFIG_BOARD_H */
diff --git a/ports/stm32/boards/ARDUINO_NICLA_VISION/mpconfigboard.h b/ports/stm32/boards/ARDUINO_NICLA_VISION/mpconfigboard.h
new file mode 100644
index 000000000000..c47024b97d5e
--- /dev/null
+++ b/ports/stm32/boards/ARDUINO_NICLA_VISION/mpconfigboard.h
@@ -0,0 +1,240 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ * The MIT License (MIT)
+ * Copyright (c) 2023 Arduino SA
+ */
+
+#define MICROPY_HW_BOARD_NAME "NICLAVISION"
+#define MICROPY_HW_MCU_NAME "STM32H747"
+#define MICROPY_PY_SYS_PLATFORM "Nicla Vision"
+#define MICROPY_HW_FLASH_FS_LABEL "niclavision"
+
+#define MICROPY_OBJ_REPR (MICROPY_OBJ_REPR_C)
+#define UINT_FMT "%u"
+#define INT_FMT "%d"
+typedef int mp_int_t; // must be pointer size
+typedef unsigned int mp_uint_t; // must be pointer size
+
+#define MICROPY_FATFS_EXFAT (1)
+#define MICROPY_HW_ENABLE_RTC (1)
+#define MICROPY_HW_ENABLE_RNG (1)
+#define MICROPY_HW_ENABLE_ADC (1)
+#define MICROPY_HW_ENABLE_DAC (1)
+#define MICROPY_HW_ENABLE_USB (1)
+#define MICROPY_HW_HAS_SWITCH (0)
+#define MICROPY_HW_HAS_FLASH (1)
+#define MICROPY_HW_ENABLE_SERVO (1)
+#define MICROPY_HW_ENABLE_TIMER (1)
+#define MICROPY_HW_ENABLE_SDCARD (0)
+#define MICROPY_HW_ENABLE_MMCARD (0)
+
+// Flash storage config
+#define MICROPY_HW_SPIFLASH_ENABLE_CACHE (1)
+#define MICROPY_HW_ENABLE_INTERNAL_FLASH_STORAGE (0)
+
+#define MICROPY_BOARD_STARTUP NICLAV_board_startup
+void NICLAV_board_startup(void);
+
+#define MICROPY_BOARD_EARLY_INIT NICLAV_board_early_init
+void NICLAV_board_early_init(void);
+
+#define MICROPY_BOARD_ENTER_BOOTLOADER(nargs, args) NICLAV_board_enter_bootloader()
+void NICLAV_board_enter_bootloader(void);
+
+void NICLAV_board_low_power(int mode);
+#define MICROPY_BOARD_LEAVE_STOP NICLAV_board_low_power(0);
+#define MICROPY_BOARD_ENTER_STOP NICLAV_board_low_power(1);
+#define MICROPY_BOARD_ENTER_STANDBY NICLAV_board_low_power(2);
+
+void NICLAV_board_osc_enable(int enable);
+#define MICROPY_BOARD_OSC_ENABLE NICLAV_board_osc_enable(1);
+#define MICROPY_BOARD_OSC_DISABLE NICLAV_board_osc_enable(0);
+
+// PLL1 400MHz/50MHz for SDMMC and FDCAN
+// USB and RNG are clocked from the HSI48
+#define MICROPY_HW_CLK_PLLM (5)
+#define MICROPY_HW_CLK_PLLN (160)
+#define MICROPY_HW_CLK_PLLP (2)
+#define MICROPY_HW_CLK_PLLQ (16)
+#define MICROPY_HW_CLK_PLLR (2)
+#define MICROPY_HW_CLK_PLLVCI (RCC_PLL1VCIRANGE_2)
+#define MICROPY_HW_CLK_PLLVCO (RCC_PLL1VCOWIDE)
+#define MICROPY_HW_CLK_PLLFRAC (0)
+
+// PLL2 200MHz for FMC and QSPI.
+#define MICROPY_HW_CLK_PLL2M (5)
+#define MICROPY_HW_CLK_PLL2N (80)
+#define MICROPY_HW_CLK_PLL2P (2)
+#define MICROPY_HW_CLK_PLL2Q (2)
+#define MICROPY_HW_CLK_PLL2R (2)
+#define MICROPY_HW_CLK_PLL2VCI (RCC_PLL2VCIRANGE_2)
+#define MICROPY_HW_CLK_PLL2VCO (RCC_PLL2VCOWIDE)
+#define MICROPY_HW_CLK_PLL2FRAC (0)
+
+// PLL3 160MHz for ADC and SPI123
+#define MICROPY_HW_CLK_PLL3M (5)
+#define MICROPY_HW_CLK_PLL3N (160)
+#define MICROPY_HW_CLK_PLL3P (2)
+#define MICROPY_HW_CLK_PLL3Q (5)
+#define MICROPY_HW_CLK_PLL3R (2)
+#define MICROPY_HW_CLK_PLL3VCI (RCC_PLL3VCIRANGE_2)
+#define MICROPY_HW_CLK_PLL3VCO (RCC_PLL3VCOWIDE)
+#define MICROPY_HW_CLK_PLL3FRAC (0)
+
+// HSE in BYPASS mode.
+#define MICROPY_HW_CLK_USE_BYPASS (1)
+
+// Bus clock divider values
+#define MICROPY_HW_CLK_AHB_DIV (RCC_HCLK_DIV2)
+#define MICROPY_HW_CLK_APB1_DIV (RCC_APB1_DIV2)
+#define MICROPY_HW_CLK_APB2_DIV (RCC_APB2_DIV2)
+#define MICROPY_HW_CLK_APB3_DIV (RCC_APB3_DIV2)
+#define MICROPY_HW_CLK_APB4_DIV (RCC_APB4_DIV2)
+
+// Peripheral clock sources
+#define MICROPY_HW_RCC_HSI48_STATE (RCC_HSI48_ON)
+#define MICROPY_HW_RCC_USB_CLKSOURCE (RCC_USBCLKSOURCE_HSI48)
+#define MICROPY_HW_RCC_RTC_CLKSOURCE (RCC_RTCCLKSOURCE_LSI)
+#define MICROPY_HW_RCC_FMC_CLKSOURCE (RCC_FMCCLKSOURCE_PLL2)
+#define MICROPY_HW_RCC_RNG_CLKSOURCE (RCC_RNGCLKSOURCE_HSI48)
+#define MICROPY_HW_RCC_ADC_CLKSOURCE (RCC_ADCCLKSOURCE_PLL3)
+#define MICROPY_HW_RCC_SDMMC_CLKSOURCE (RCC_SDMMCCLKSOURCE_PLL)
+#define MICROPY_HW_RCC_FDCAN_CLKSOURCE (RCC_FDCANCLKSOURCE_PLL)
+#define MICROPY_HW_RCC_SPI123_CLKSOURCE (RCC_SPI123CLKSOURCE_PLL3)
+#define MICROPY_HW_RCC_I2C123_CLKSOURCE (RCC_I2C123CLKSOURCE_D2PCLK1)
+#define MICROPY_HW_RCC_QSPI_CLKSOURCE (RCC_QSPICLKSOURCE_PLL2)
+
+// SMPS configuration
+#define MICROPY_HW_PWR_SMPS_CONFIG (PWR_LDO_SUPPLY)
+
+// There is an external 32kHz oscillator
+#define RTC_ASYNCH_PREDIV (0)
+#define RTC_SYNCH_PREDIV (0x7fff)
+#define MICROPY_HW_RTC_USE_BYPASS (1)
+#define MICROPY_HW_RTC_USE_US (1)
+#define MICROPY_HW_RTC_USE_CALOUT (1)
+
+#if !MICROPY_HW_ENABLE_INTERNAL_FLASH_STORAGE
+// QSPI flash for storage
+#define MICROPY_HW_QSPI_PRESCALER (2) // 100MHz
+#define MICROPY_HW_QSPIFLASH_SIZE_BITS_LOG2 (27)
+// Reserve 1MiB at the end for compatibility with alternate firmware that places WiFi blob here.
+#define MICROPY_HW_SPIFLASH_SIZE_BITS (120 * 1024 * 1024)
+#define MICROPY_HW_QSPIFLASH_CS (pyb_pin_QSPI2_CS)
+#define MICROPY_HW_QSPIFLASH_SCK (pyb_pin_QSPI2_CLK)
+#define MICROPY_HW_QSPIFLASH_IO0 (pyb_pin_QSPI2_D0)
+#define MICROPY_HW_QSPIFLASH_IO1 (pyb_pin_QSPI2_D1)
+#define MICROPY_HW_QSPIFLASH_IO2 (pyb_pin_QSPI2_D2)
+#define MICROPY_HW_QSPIFLASH_IO3 (pyb_pin_QSPI2_D3)
+
+// SPI flash #1, block device config
+extern const struct _mp_spiflash_config_t spiflash_config;
+extern struct _spi_bdev_t spi_bdev;
+#define MICROPY_HW_BDEV_IOCTL(op, arg) ( \
+ (op) == BDEV_IOCTL_NUM_BLOCKS ? (MICROPY_HW_SPIFLASH_SIZE_BITS / 8 / FLASH_BLOCK_SIZE) : \
+ (op) == BDEV_IOCTL_INIT ? spi_bdev_ioctl(&spi_bdev, (op), (uint32_t)&spiflash_config) : \
+ spi_bdev_ioctl(&spi_bdev, (op), (arg)) \
+ )
+#define MICROPY_HW_BDEV_READBLOCKS(dest, bl, n) spi_bdev_readblocks(&spi_bdev, (dest), (bl), (n))
+#define MICROPY_HW_BDEV_WRITEBLOCKS(src, bl, n) spi_bdev_writeblocks(&spi_bdev, (src), (bl), (n))
+#define MICROPY_HW_BDEV_SPIFLASH_EXTENDED (&spi_bdev)
+#endif
+
+// 4 wait states
+#define MICROPY_HW_FLASH_LATENCY FLASH_LATENCY_2
+
+// UART config
+#define MICROPY_HW_UART1_TX (pyb_pin_BT_TXD)
+#define MICROPY_HW_UART1_RX (pyb_pin_BT_RXD)
+#define MICROPY_HW_UART1_RTS (pyb_pin_BT_RTS)
+#define MICROPY_HW_UART1_CTS (pyb_pin_BT_CTS)
+
+#define MICROPY_HW_UART4_TX (pin_B9)
+#define MICROPY_HW_UART4_RX (pin_B8)
+
+// LPUART1 config
+#define MICROPY_HW_LPUART1_TX (pin_A9)
+#define MICROPY_HW_LPUART1_RX (pin_A10)
+
+// I2C busses
+#define MICROPY_HW_I2C1_SCL (pin_B8)
+#define MICROPY_HW_I2C1_SDA (pin_B9)
+
+#define MICROPY_HW_I2C2_SCL (pin_F1)
+#define MICROPY_HW_I2C2_SDA (pin_F0)
+
+#define MICROPY_HW_I2C3_SCL (pin_A8)
+#define MICROPY_HW_I2C3_SDA (pin_C9)
+
+// SPI buses
+#define MICROPY_HW_SPI4_NSS (pin_E11)
+#define MICROPY_HW_SPI4_SCK (pin_E12)
+#define MICROPY_HW_SPI4_MISO (pin_E13)
+#define MICROPY_HW_SPI4_MOSI (pin_E14)
+
+#define MICROPY_HW_SPI5_NSS (pin_F6)
+#define MICROPY_HW_SPI5_SCK (pin_F7)
+#define MICROPY_HW_SPI5_MISO (pin_F8)
+#define MICROPY_HW_SPI5_MOSI (pin_F11)
+
+// FDCAN bus
+#define MICROPY_HW_CAN1_NAME "FDCAN1"
+#define MICROPY_HW_CAN1_TX (pin_A10)
+#define MICROPY_HW_CAN1_RX (pin_A9)
+#define MICROPY_HW_CAN_IS_RESERVED(id) (id != PYB_CAN_1)
+
+// LEDs
+#define MICROPY_HW_LED1 (pyb_pin_LEDR) // red
+#define MICROPY_HW_LED2 (pyb_pin_LEDG) // green
+#define MICROPY_HW_LED3 (pyb_pin_LEDB) // yellow
+#define MICROPY_HW_LED_ON(pin) (mp_hal_pin_low(pin))
+#define MICROPY_HW_LED_OFF(pin) (mp_hal_pin_high(pin))
+
+// WiFi SDMMC
+#define MICROPY_HW_SDIO_SDMMC (2)
+#define MICROPY_HW_SDIO_CK (pin_D6)
+#define MICROPY_HW_SDIO_CMD (pin_D7)
+#define MICROPY_HW_SDIO_D0 (pin_B14)
+#define MICROPY_HW_SDIO_D1 (pin_B15)
+#define MICROPY_HW_SDIO_D2 (pin_G11)
+#define MICROPY_HW_SDIO_D3 (pin_B4)
+
+// USB config
+#define MICROPY_HW_USB_HS (1)
+#define MICROPY_HW_USB_HS_ULPI_NXT (pin_C3)
+#define MICROPY_HW_USB_HS_ULPI_STP (pin_C0)
+#define MICROPY_HW_USB_HS_ULPI_DIR (pin_C2)
+#define MICROPY_HW_USB_HS_ULPI3320 (1)
+
+#define MICROPY_HW_USB_CDC_RX_DATA_SIZE (1024)
+#define MICROPY_HW_USB_CDC_TX_DATA_SIZE (1024)
+#define MICROPY_HW_USB_CDC_1200BPS_TOUCH (1)
+#define GPIO_AF10_OTG_HS (GPIO_AF10_OTG2_HS)
+
+// Bluetooth config
+#define MICROPY_HW_BLE_UART_ID (PYB_UART_1)
+#define MICROPY_HW_BLE_UART_BAUDRATE (115200)
+#define MICROPY_HW_BLE_UART_BAUDRATE_SECONDARY (3000000)
+#define MICROPY_HW_BLE_UART_BAUDRATE_DOWNLOAD_FIRMWARE (3000000)
+
+#define MICROPY_HW_USB_VID 0x2341
+#define MICROPY_HW_USB_PID 0x045F
+#define MICROPY_HW_USB_PID_CDC_MSC (MICROPY_HW_USB_PID)
+#define MICROPY_HW_USB_PID_CDC_HID (MICROPY_HW_USB_PID)
+#define MICROPY_HW_USB_PID_CDC (MICROPY_HW_USB_PID)
+#define MICROPY_HW_USB_PID_MSC (MICROPY_HW_USB_PID)
+#define MICROPY_HW_USB_PID_CDC2_MSC (MICROPY_HW_USB_PID)
+#define MICROPY_HW_USB_PID_CDC2 (MICROPY_HW_USB_PID)
+#define MICROPY_HW_USB_PID_CDC3 (MICROPY_HW_USB_PID)
+#define MICROPY_HW_USB_PID_CDC3_MSC (MICROPY_HW_USB_PID)
+#define MICROPY_HW_USB_PID_CDC_MSC_HID (MICROPY_HW_USB_PID)
+#define MICROPY_HW_USB_PID_CDC2_MSC_HID (MICROPY_HW_USB_PID)
+#define MICROPY_HW_USB_PID_CDC3_MSC_HID (MICROPY_HW_USB_PID)
+#define MICROPY_HW_USB_LANGID_STRING 0x409
+#define MICROPY_HW_USB_MANUFACTURER_STRING "Arduino"
+#define MICROPY_HW_USB_PRODUCT_FS_STRING "Nicla Vision Virtual Comm Port in FS Mode"
+#define MICROPY_HW_USB_PRODUCT_HS_STRING "Nicla Vision Virtual Comm Port in HS Mode"
+#define MICROPY_HW_USB_INTERFACE_FS_STRING "Nicla Vision Interface"
+#define MICROPY_HW_USB_INTERFACE_HS_STRING "Nicla Vision Interface"
+#define MICROPY_HW_USB_CONFIGURATION_FS_STRING "Nicla Vision Config"
+#define MICROPY_HW_USB_CONFIGURATION_HS_STRING "Nicla Vision Config"
diff --git a/ports/stm32/boards/ARDUINO_NICLA_VISION/mpconfigboard.mk b/ports/stm32/boards/ARDUINO_NICLA_VISION/mpconfigboard.mk
new file mode 100644
index 000000000000..ebe9775e8077
--- /dev/null
+++ b/ports/stm32/boards/ARDUINO_NICLA_VISION/mpconfigboard.mk
@@ -0,0 +1,28 @@
+USE_MBOOT = 0
+USE_PYDFU = 0
+# For dual core HAL drivers.
+CFLAGS += -DCORE_CM7
+
+# Arduino bootloader PID:VID
+BOOTLOADER_DFU_USB_VID = 0x2341
+BOOTLOADER_DFU_USB_PID = 0x035f
+
+# MCU settings
+MCU_SERIES = h7
+CMSIS_MCU = STM32H747xx
+MICROPY_FLOAT_IMPL = single
+AF_FILE = boards/stm32h743_af.csv
+LD_FILES = boards/ARDUINO_NICLA_VISION/stm32h747.ld
+TEXT0_ADDR = 0x08040000
+
+# MicroPython settings
+MICROPY_PY_BLUETOOTH = 1
+MICROPY_BLUETOOTH_NIMBLE = 1
+MICROPY_BLUETOOTH_BTSTACK = 0
+MICROPY_PY_LWIP = 1
+MICROPY_PY_NETWORK_CYW43 = 1
+MICROPY_PY_USSL = 1
+MICROPY_SSL_MBEDTLS = 1
+
+FROZEN_MANIFEST = $(BOARD_DIR)/manifest.py
+MBEDTLS_CONFIG_FILE = '"$(BOARD_DIR)/mbedtls_config_board.h"'
diff --git a/ports/stm32/boards/ARDUINO_NICLA_VISION/pins.csv b/ports/stm32/boards/ARDUINO_NICLA_VISION/pins.csv
new file mode 100644
index 000000000000..c092965aafe9
--- /dev/null
+++ b/ports/stm32/boards/ARDUINO_NICLA_VISION/pins.csv
@@ -0,0 +1,213 @@
+PA0,-PA0
+PA1,-PA1
+PA2,-PA2
+PA3,-PA3
+PA4,-PA4
+PA5,-PA5
+PA6,-PA6
+PA7,-PA7
+PA8,PA8
+PA9,PA9
+PA10,PA10
+PA11,PA11
+PA12,PA12
+PA13,PA13
+PA14,PA14
+PA15,PA15
+PB0,-PB0
+PB1,-PB1
+PB2,PB2
+PB3,PB3
+PB4,PB4
+PB5,PB5
+PB6,PB6
+PB7,PB7
+PB8,PB8
+PB9,PB9
+PB10,PB10
+PB11,PB11
+PB12,PB12
+PB13,PB13
+PB14,PB14
+PB15,PB15
+PC0,-PC0
+PC1,-PC1
+PC2,-PC2
+PC3,-PC3
+PC4,PC4
+PC5,-PC5
+PC6,PC6
+PC7,PC7
+PC8,PC8
+PC9,PC9
+PC10,PC10
+PC11,PC11
+PC12,PC12
+PC13,PC13
+PC14,PC14
+PC15,PC15
+PD0,PD0
+PD1,PD1
+PD2,PD2
+PD3,PD3
+PD4,PD4
+PD5,PD5
+PD6,PD6
+PD7,PD7
+PD8,PD8
+PD9,PD9
+PD10,PD10
+PD11,PD11
+PD12,PD12
+PD13,PD13
+PD14,PD14
+PD15,PD15
+PE0,PE0
+PE1,PE1
+PE2,PE2
+PE3,PE3
+PE4,PE4
+PE5,PE5
+PE6,PE6
+PE7,PE7
+PE8,PE8
+PE9,PE9
+PE10,PE10
+PE11,PE11
+PE12,PE12
+PE13,PE13
+PE14,PE14
+PE15,PE15
+PF0,PF0
+PF1,PF1
+PF2,PF2
+PF3,PF3
+PF4,-PF4
+PF5,-PF5
+PF6,-PF6
+PF7,-PF7
+PF8,-PF8
+PF9,-PF9
+PF10,-PF10
+PF11,-PF11
+PF12,PF12
+PF13,PF13
+PF14,-PF14
+PF15,PF15
+PG0,PG0
+PG1,PG1
+PG2,PG2
+PG3,PG3
+PG4,PG4
+PG5,PG5
+PG6,PG6
+PG7,PG7
+PG8,PG8
+PG9,PG9
+PG10,PG10
+PG11,PG11
+PG12,PG12
+PG13,PG13
+PG14,PG14
+PG15,PG15
+PH0,PH0
+PH1,PH1
+PH2,-PH2
+PH3,-PH3
+PH4,-PH4
+PH5,-PH5
+PH6,PH6
+PH7,PH7
+PH8,PH8
+PH9,PH9
+PH10,PH10
+PH11,PH11
+PH12,PH12
+PH13,PH13
+PH14,PH14
+PH15,PH15
+PI0,PI0
+PI1,PI1
+PI2,PI2
+PI3,PI3
+PI4,PI4
+PI5,PI5
+PI6,PI6
+PI7,PI7
+PI8,PI8
+PI9,PI9
+PI10,PI10
+PI11,PI11
+PI12,PI12
+PI13,PI13
+PI14,PI14
+PI15,PI15
+PJ0,PJ0
+PJ1,PJ1
+PJ2,PJ2
+PJ3,PJ3
+PJ4,PJ4
+PJ5,PJ5
+PJ6,PJ6
+PJ7,PJ7
+PJ8,PJ8
+PJ9,PJ9
+PJ10,PJ10
+PJ11,PJ11
+PJ12,PJ12
+PJ13,PJ13
+PJ14,PJ14
+PJ15,PJ15
+PK0,PK0
+PK1,PK1
+PK2,PK2
+PK3,PK3
+PK4,PK4
+PK5,PK5
+PK6,PK6
+PK7,PK7
+UART1_TX,PA9
+UART1_RX,PA10
+UART4_TX,-PA0
+UART4_RX,PI9
+UART6_TX,PG14
+UART6_RX,PG9
+UART8_TX,PJ8
+UART8_RX,PJ9
+USB_DM,PA11
+USB_DP,PA12
+BOOT0,BOOT0
+OSCEN,PH1
+DAC1,-PA4
+DAC2,-PA5
+LEDR,PE3
+LEDG,PC13
+LEDB,-PF4
+I2C1_SCL,PB8
+I2C1_SDA,PB9
+I2C2_SCL,PF1
+I2C2_SDA,PF0
+I2C3_SCL,PA8
+I2C3_SDA,PC9
+-WL_REG_ON,PG4
+-WL_HOST_WAKE,PD15
+-WL_SDIO_0,PB14
+-WL_SDIO_1,PB15
+-WL_SDIO_2,PG11
+-WL_SDIO_3,PB4
+-WL_SDIO_CMD,PD7
+-WL_SDIO_CLK,PD6
+-BT_RXD,PB7
+-BT_TXD,PB6
+-BT_CTS,PA11
+-BT_RTS,PA12
+-BT_REG_ON,-PF14
+-BT_HOST_WAKE,PD14
+-BT_DEV_WAKE,PE9
+-QSPI2_CS,PG6
+-QSPI2_CLK,-PF10
+-QSPI2_D0,PD11
+-QSPI2_D1,-PF9
+-QSPI2_D2,PE2
+-QSPI2_D3,PD13
+-SE05X_EN,-PG0
diff --git a/ports/stm32/boards/ARDUINO_NICLA_VISION/stm32h747.ld b/ports/stm32/boards/ARDUINO_NICLA_VISION/stm32h747.ld
new file mode 100644
index 000000000000..fcbfc94d4620
--- /dev/null
+++ b/ports/stm32/boards/ARDUINO_NICLA_VISION/stm32h747.ld
@@ -0,0 +1,49 @@
+/*
+ GNU linker script for STM32H747
+*/
+
+/* Specify the memory areas */
+MEMORY
+{
+ ITCM (xrw) : ORIGIN = 0x00000000, LENGTH = 64K
+ DTCM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K
+ RAM (xrw) : ORIGIN = 0x24000000, LENGTH = 512K /* AXI SRAM D1 */
+ SRAM1 (xrw) : ORIGIN = 0x30000000, LENGTH = 128K /* SRAM1 D2 */
+ SRAM2 (xrw) : ORIGIN = 0x30020000, LENGTH = 128K /* SRAM2 D2 */
+ SRAM3 (xrw) : ORIGIN = 0x30040000, LENGTH = 32K /* SRAM3 D2 */
+ SRAM4 (xrw) : ORIGIN = 0x38000000, LENGTH = 64K /* SRAM4 D3 */
+ FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 2048K /* Total available flash */
+ FLASH_EXT (rx) : ORIGIN = 0x90000000, LENGTH = 16384K /* 16MBs external QSPI flash */
+ FLASH_FS (r) : ORIGIN = 0x08020000, LENGTH = 128K /* sector 1 -> Flash storage */
+ FLASH_TEXT (rx) : ORIGIN = 0x08040000, LENGTH = 1792K /* Sector 0 -> Arduino Bootloader
+ Sector 1 -> Reserved for CM4/FS
+ Sectors 2 -> 15 firmware */
+}
+
+_cm4_ram_start = ORIGIN(SRAM4);
+
+/* produce a link error if there is not this amount of RAM for these sections */
+_minimum_stack_size = 2K;
+_minimum_heap_size = 16K;
+
+/* Define the stack. The stack is full descending so begins just above last byte
+ of RAM. Note that EABI requires the stack to be 8-byte aligned for a call. */
+_estack = ORIGIN(RAM) + LENGTH(RAM) - _estack_reserve;
+_sstack = _estack - 16K; /* tunable */
+
+/* RAM extents for the garbage collector */
+_ram_start = ORIGIN(RAM);
+_ram_end = ORIGIN(RAM) + LENGTH(RAM);
+_heap_start = _ebss; /* heap starts just after statically allocated memory */
+_heap_end = _sstack;
+
+/* Note the following varilables are only used if the filesystem flash storage is enabled */
+/* Location of filesystem RAM cache */
+_micropy_hw_internal_flash_storage_ram_cache_start = ORIGIN(DTCM);
+_micropy_hw_internal_flash_storage_ram_cache_end = ORIGIN(DTCM) + LENGTH(DTCM);
+
+/* Location of filesystem flash storage */
+_micropy_hw_internal_flash_storage_start = ORIGIN(FLASH_FS);
+_micropy_hw_internal_flash_storage_end = ORIGIN(FLASH_FS) + LENGTH(FLASH_FS);
+
+INCLUDE common_blifs.ld
diff --git a/ports/stm32/boards/ARDUINO_NICLA_VISION/stm32h7xx_hal_conf.h b/ports/stm32/boards/ARDUINO_NICLA_VISION/stm32h7xx_hal_conf.h
new file mode 100644
index 000000000000..737a2e5b0d24
--- /dev/null
+++ b/ports/stm32/boards/ARDUINO_NICLA_VISION/stm32h7xx_hal_conf.h
@@ -0,0 +1,51 @@
+/* This file is part of the MicroPython project, http://micropython.org/
+ * The MIT License (MIT)
+ * Copyright (c) 2019 Damien P. George
+ */
+#ifndef MICROPY_INCLUDED_STM32H7XX_HAL_CONF_H
+#define MICROPY_INCLUDED_STM32H7XX_HAL_CONF_H
+
+#include "boards/stm32h7xx_hal_conf_base.h"
+
+// Oscillator values in Hz
+#define HSE_VALUE (25000000)
+#define LSE_VALUE (32768)
+#define EXTERNAL_CLOCK_VALUE (12288000)
+
+// Oscillator timeouts in ms
+#define HSE_STARTUP_TIMEOUT (5000)
+#define LSE_STARTUP_TIMEOUT (5000)
+
+#define DATA_CACHE_ENABLE 1
+#define INSTRUCTION_CACHE_ENABLE 1
+#define DATA_CACHE_ENABLE 1
+#define INSTRUCTION_CACHE_ENABLE 1
+#define PREFETCH_ENABLE 1
+#define USE_RTOS 0
+
+#define HAL_HSEM_MODULE_ENABLED
+#define HAL_JPEG_MODULE_ENABLED
+#define HAL_LPTIM_MODULE_ENABLED
+#define HAL_LTDC_MODULE_ENABLED
+#define HAL_MDIOS_MODULE_ENABLED
+#define HAL_MDMA_MODULE_ENABLED
+#define HAL_MMC_MODULE_ENABLED
+#define HAL_NAND_MODULE_ENABLED
+#define HAL_OPAMP_MODULE_ENABLED
+#define HAL_QSPI_MODULE_ENABLED
+#define HAL_RNG_MODULE_ENABLED
+#define HAL_SAI_MODULE_ENABLED
+#define HAL_SMBUS_MODULE_ENABLED
+#define HAL_SPDIFRX_MODULE_ENABLED
+#define HAL_SRAM_MODULE_ENABLED
+#define HAL_SWPMI_MODULE_ENABLED
+
+#ifdef HAL_HSEM_MODULE_ENABLED
+#include "stm32h7xx_hal_hsem.h"
+#endif
+
+#ifdef HAL_MMC_MODULE_ENABLED
+#include "stm32h7xx_hal_mmc.h"
+#endif
+
+#endif // MICROPY_INCLUDED_STM32H7XX_HAL_CONF_H
diff --git a/ports/stm32/boards/ARDUINO_PORTENTA_H7/board.json b/ports/stm32/boards/ARDUINO_PORTENTA_H7/board.json
index 65cf4d4f8649..6467e43bb973 100644
--- a/ports/stm32/boards/ARDUINO_PORTENTA_H7/board.json
+++ b/ports/stm32/boards/ARDUINO_PORTENTA_H7/board.json
@@ -16,7 +16,7 @@
"images": [
"ABX00042_01.iso_1000x750.jpg"
],
- "mcu": "STM32H747",
+ "mcu": "stm32h7",
"product": "Arduino Portenta H7",
"thumbnail": "",
"url": "https://store.arduino.cc/products/portenta-h7",
diff --git a/ports/stm32/boards/ARDUINO_PORTENTA_H7/board_init.c b/ports/stm32/boards/ARDUINO_PORTENTA_H7/board_init.c
index 30b9e487601d..39f782877313 100644
--- a/ports/stm32/boards/ARDUINO_PORTENTA_H7/board_init.c
+++ b/ports/stm32/boards/ARDUINO_PORTENTA_H7/board_init.c
@@ -162,7 +162,7 @@ void PORTENTA_board_low_power(int mode) {
break;
}
- #if MICROPY_HW_ENABLE_INTERNAL_FLASH_STORAGE
+ #if !MICROPY_HW_ENABLE_INTERNAL_FLASH_STORAGE
// Enable QSPI deepsleep for modes 1 and 2
mp_spiflash_deepsleep(&spi_bdev.spiflash, (mode != 0));
#endif
diff --git a/ports/stm32/boards/ARDUINO_PORTENTA_H7/deploy.md b/ports/stm32/boards/ARDUINO_PORTENTA_H7/deploy.md
index 8de726b43b4c..7f738c579158 100644
--- a/ports/stm32/boards/ARDUINO_PORTENTA_H7/deploy.md
+++ b/ports/stm32/boards/ARDUINO_PORTENTA_H7/deploy.md
@@ -4,7 +4,7 @@ This board can programmed via DFU bootloader, using e.g. [dfu-util](http://dfu-u
To enter the DFU bootloader, double tap the reset (blue) button, or you can use `machine.bootloader()` from the MicroPython REPL.
```bash
-dfu-util -w -d 2341:035b -a 0 -d 0x8040000 -D firmware.dfu
+dfu-util -w -a 0 -d 2341:035b -D build-ARDUINO_PORTENTA_H7/firmware.dfu
```
Or from MicroPython source repository:
diff --git a/ports/stm32/boards/ARDUINO_PORTENTA_H7/manifest.py b/ports/stm32/boards/ARDUINO_PORTENTA_H7/manifest.py
index cd721d0ac45d..b3c6b02e5ba0 100644
--- a/ports/stm32/boards/ARDUINO_PORTENTA_H7/manifest.py
+++ b/ports/stm32/boards/ARDUINO_PORTENTA_H7/manifest.py
@@ -1,9 +1,12 @@
include("$(PORT_DIR)/boards/manifest.py")
-include("$(MPY_DIR)/extmod/webrepl/manifest.py")
-include(
- "$(MPY_LIB_DIR)/micropython/bluetooth/aioble/manifest.py",
- client=True,
- central=True,
- l2cap=True,
- security=True,
-)
+
+# Networking
+require("bundle-networking")
+
+# Utils
+require("time")
+require("senml")
+require("logging")
+
+# Bluetooth
+require("aioble")
diff --git a/ports/stm32/boards/ARDUINO_PORTENTA_H7/mbedtls_config_board.h b/ports/stm32/boards/ARDUINO_PORTENTA_H7/mbedtls_config_board.h
new file mode 100644
index 000000000000..0e1703f1bf96
--- /dev/null
+++ b/ports/stm32/boards/ARDUINO_PORTENTA_H7/mbedtls_config_board.h
@@ -0,0 +1,8 @@
+#ifndef MICROPY_INCLUDED_MBEDTLS_CONFIG_BOARD_H
+#define MICROPY_INCLUDED_MBEDTLS_CONFIG_BOARD_H
+
+#define MBEDTLS_ECP_NIST_OPTIM
+
+#include "ports/stm32/mbedtls/mbedtls_config.h"
+
+#endif /* MICROPY_INCLUDED_MBEDTLS_CONFIG_BOARD_H */
diff --git a/ports/stm32/boards/ARDUINO_PORTENTA_H7/mpconfigboard.h b/ports/stm32/boards/ARDUINO_PORTENTA_H7/mpconfigboard.h
index 30c909913c41..674154b316b3 100644
--- a/ports/stm32/boards/ARDUINO_PORTENTA_H7/mpconfigboard.h
+++ b/ports/stm32/boards/ARDUINO_PORTENTA_H7/mpconfigboard.h
@@ -9,6 +9,8 @@
#define MICROPY_PY_SYS_PLATFORM "Portenta"
#define MICROPY_HW_FLASH_FS_LABEL "portenta"
+#define MICROPY_PY_NETWORK_HOSTNAME_DEFAULT "Portenta"
+
#define MICROPY_OBJ_REPR (MICROPY_OBJ_REPR_C)
#define UINT_FMT "%u"
#define INT_FMT "%d"
@@ -38,7 +40,7 @@ void PORTENTA_board_startup(void);
#define MICROPY_BOARD_EARLY_INIT PORTENTA_board_early_init
void PORTENTA_board_early_init(void);
-#define MICROPY_BOARD_ENTER_BOOTLOADER PORTENTA_board_enter_bootloader
+#define MICROPY_BOARD_ENTER_BOOTLOADER(nargs, args) PORTENTA_board_enter_bootloader()
void PORTENTA_board_enter_bootloader(void);
void PORTENTA_board_low_power(int mode);
@@ -118,7 +120,8 @@ void PORTENTA_board_osc_enable(int enable);
// QSPI flash #1 for storage
#define MICROPY_HW_QSPI_PRESCALER (2) // 100MHz
#define MICROPY_HW_QSPIFLASH_SIZE_BITS_LOG2 (27)
-#define MICROPY_HW_SPIFLASH_SIZE_BITS (128 * 1024 * 1024)
+// Reserve 1MiB at the end for compatibility with alternate firmware that places WiFi blob here.
+#define MICROPY_HW_SPIFLASH_SIZE_BITS (120 * 1024 * 1024)
#define MICROPY_HW_QSPIFLASH_CS (pyb_pin_QSPI2_CS)
#define MICROPY_HW_QSPIFLASH_SCK (pyb_pin_QSPI2_CLK)
#define MICROPY_HW_QSPIFLASH_IO0 (pyb_pin_QSPI2_D0)
@@ -159,6 +162,9 @@ extern struct _spi_bdev_t spi_bdev;
#define MICROPY_HW_UART7_CTS (pyb_pin_BT_CTS)
// I2C busses
+#define MICROPY_HW_I2C1_SCL (pin_B6)
+#define MICROPY_HW_I2C1_SDA (pin_B7)
+
#define MICROPY_HW_I2C3_SCL (pin_H7)
#define MICROPY_HW_I2C3_SDA (pin_H8)
@@ -198,6 +204,7 @@ extern struct _spi_bdev_t spi_bdev;
#define MICROPY_HW_SDCARD_D1 (pin_B15)
#define MICROPY_HW_SDCARD_D2 (pin_B3)
#define MICROPY_HW_SDCARD_D3 (pin_B4)
+#define MICROPY_HW_SDCARD_MOUNT_AT_BOOT (0)
// USB config
#define MICROPY_HW_USB_HS (1)
@@ -206,8 +213,8 @@ extern struct _spi_bdev_t spi_bdev;
#define MICROPY_HW_USB_HS_ULPI_DIR (pin_I11)
#define MICROPY_HW_USB_HS_ULPI3320 (1)
-#define MICROPY_HW_USB_CDC_RX_DATA_SIZE (512)
-#define MICROPY_HW_USB_CDC_TX_DATA_SIZE (512)
+#define MICROPY_HW_USB_CDC_RX_DATA_SIZE (1024)
+#define MICROPY_HW_USB_CDC_TX_DATA_SIZE (1024)
#define MICROPY_HW_USB_CDC_1200BPS_TOUCH (1)
#define GPIO_AF10_OTG_HS (GPIO_AF10_OTG2_HS)
@@ -215,6 +222,7 @@ extern struct _spi_bdev_t spi_bdev;
#define MICROPY_HW_BLE_UART_ID (PYB_UART_7)
#define MICROPY_HW_BLE_UART_BAUDRATE (115200)
#define MICROPY_HW_BLE_UART_BAUDRATE_SECONDARY (3000000)
+#define MICROPY_HW_BLE_UART_BAUDRATE_DOWNLOAD_FIRMWARE (3000000)
// SDRAM
#define MICROPY_HW_SDRAM_SIZE (64 / 8 * 1024 * 1024) // 64 Mbit
diff --git a/ports/stm32/boards/ARDUINO_PORTENTA_H7/mpconfigboard.mk b/ports/stm32/boards/ARDUINO_PORTENTA_H7/mpconfigboard.mk
index e5b48d0644f0..3bfd40dc9245 100644
--- a/ports/stm32/boards/ARDUINO_PORTENTA_H7/mpconfigboard.mk
+++ b/ports/stm32/boards/ARDUINO_PORTENTA_H7/mpconfigboard.mk
@@ -10,7 +10,7 @@ BOOTLOADER_DFU_USB_PID = 0x035b
# MCU settings
MCU_SERIES = h7
CMSIS_MCU = STM32H747xx
-MICROPY_FLOAT_IMPL = double
+MICROPY_FLOAT_IMPL = single
AF_FILE = boards/stm32h743_af.csv
LD_FILES = boards/ARDUINO_PORTENTA_H7/stm32h747.ld
TEXT0_ADDR = 0x08040000
@@ -25,3 +25,4 @@ MICROPY_PY_USSL = 1
MICROPY_SSL_MBEDTLS = 1
FROZEN_MANIFEST = $(BOARD_DIR)/manifest.py
+MBEDTLS_CONFIG_FILE = '"$(BOARD_DIR)/mbedtls_config_board.h"'
diff --git a/ports/stm32/boards/ARDUINO_PORTENTA_H7/pins.csv b/ports/stm32/boards/ARDUINO_PORTENTA_H7/pins.csv
index b22da66dd4c0..6ab00f02ec40 100644
--- a/ports/stm32/boards/ARDUINO_PORTENTA_H7/pins.csv
+++ b/ports/stm32/boards/ARDUINO_PORTENTA_H7/pins.csv
@@ -231,3 +231,4 @@ I2C3_SCL,PH7
-QSPI2_D1,PD12
-QSPI2_D2,-PF7
-QSPI2_D3,PD13
+-SE05X_EN,-PI12
diff --git a/ports/stm32/boards/ARDUINO_PORTENTA_H7/stm32h747.ld b/ports/stm32/boards/ARDUINO_PORTENTA_H7/stm32h747.ld
index 650756a19f66..d5bd9598f982 100644
--- a/ports/stm32/boards/ARDUINO_PORTENTA_H7/stm32h747.ld
+++ b/ports/stm32/boards/ARDUINO_PORTENTA_H7/stm32h747.ld
@@ -44,27 +44,4 @@ _micropy_hw_internal_flash_storage_ram_cache_end = ORIGIN(DTCM) + LENGTH(DTCM);
_micropy_hw_internal_flash_storage_start = ORIGIN(FLASH_FS);
_micropy_hw_internal_flash_storage_end = ORIGIN(FLASH_FS) + LENGTH(FLASH_FS);
-/* define output sections */
-SECTIONS
-{
- .isr_vector :
- {
- . = ALIGN(4);
- KEEP(*(.isr_vector))
- . = ALIGN(4);
- } >FLASH_TEXT
-
- .text :
- {
- . = ALIGN(4);
- *(.text*)
- *(.rodata*)
- . = ALIGN(512);
- *(.big_const*)
- . = ALIGN(4);
- _etext = .;
- } >FLASH_TEXT
-
- INCLUDE common_extratext_data_in_flash_text.ld
- INCLUDE common_bss_heap_stack.ld
-}
+INCLUDE common_blifs.ld
diff --git a/ports/stm32/boards/B_L072Z_LRWAN1/mpconfigboard.h b/ports/stm32/boards/B_L072Z_LRWAN1/mpconfigboard.h
index d4996e6c74d6..dfcca72afb55 100644
--- a/ports/stm32/boards/B_L072Z_LRWAN1/mpconfigboard.h
+++ b/ports/stm32/boards/B_L072Z_LRWAN1/mpconfigboard.h
@@ -11,7 +11,6 @@
#define MICROPY_PY_BUILTINS_COMPLEX (0)
#define MICROPY_PY_GENERATOR_PEND_THROW (0)
#define MICROPY_PY_MATH (0)
-#define MICROPY_PY_IO_FILEIO (0)
#define MICROPY_PY_FRAMEBUF (0)
#define MICROPY_PY_USOCKET (0)
#define MICROPY_PY_NETWORK (0)
diff --git a/ports/stm32/boards/B_L072Z_LRWAN1/mpconfigboard.mk b/ports/stm32/boards/B_L072Z_LRWAN1/mpconfigboard.mk
index 03561f90ade3..708c3cf1336c 100644
--- a/ports/stm32/boards/B_L072Z_LRWAN1/mpconfigboard.mk
+++ b/ports/stm32/boards/B_L072Z_LRWAN1/mpconfigboard.mk
@@ -9,3 +9,6 @@ MICROPY_VFS_FAT = 0
# Don't include default frozen modules because MCU is tight on flash space
FROZEN_MANIFEST ?=
+
+# LTO reduces final binary size, may be slower to build depending on gcc version and hardware
+LTO ?= 1
diff --git a/ports/stm32/boards/GARATRONIC_PYBSTICK26_F411/manifest.py b/ports/stm32/boards/GARATRONIC_PYBSTICK26_F411/manifest.py
index b09c7ab92030..2600fc506241 100644
--- a/ports/stm32/boards/GARATRONIC_PYBSTICK26_F411/manifest.py
+++ b/ports/stm32/boards/GARATRONIC_PYBSTICK26_F411/manifest.py
@@ -1,2 +1 @@
-include("$(MPY_DIR)/extmod/uasyncio/manifest.py")
-freeze("$(MPY_DIR)/drivers/", ("display/ssd1306.py"))
+require("ssd1306")
diff --git a/ports/stm32/boards/LEGO_HUB_NO6/README.md b/ports/stm32/boards/LEGO_HUB_NO6/README.md
index 376d0f2b0e44..cc67b6a4bb6b 100644
--- a/ports/stm32/boards/LEGO_HUB_NO6/README.md
+++ b/ports/stm32/boards/LEGO_HUB_NO6/README.md
@@ -112,8 +112,8 @@ To use this feature, build the firmware (see above for details) then gzip it and
copy the resulting file to the Hub (eg using mpremote):
$ make BOARD=LEGO_HUB_NO6
- $ gzip boards/LEGO_HUB_NO6/firmware.dfu
- $ mpremote cp boards/LEGO_HUB_NO6/firmware.dfu.gz :
+ $ gzip build-LEGO_HUB_NO6/firmware.dfu
+ $ mpremote cp build-LEGO_HUB_NO6/firmware.dfu.gz :
Then get a REPL on the Hub and execute:
diff --git a/ports/stm32/boards/LEGO_HUB_NO6/appupdate.py b/ports/stm32/boards/LEGO_HUB_NO6/appupdate.py
index 65954454a582..57b24d3f2e60 100644
--- a/ports/stm32/boards/LEGO_HUB_NO6/appupdate.py
+++ b/ports/stm32/boards/LEGO_HUB_NO6/appupdate.py
@@ -2,13 +2,20 @@
# MIT license; Copyright (c) 2022 Damien P. George
from micropython import const
-import struct, machine, fwupdate, spiflash
+import struct, machine, fwupdate, spiflash, pyb
+
+_IOCTL_BLOCK_COUNT = const(4)
+_IOCTL_BLOCK_SIZE = const(5)
_SPIFLASH_UPDATE_KEY_ADDR = const(1020 * 1024)
_SPIFLASH_UPDATE_KEY_VALUE = const(0x12345678)
_FILESYSTEM_ADDR = const(0x8000_0000 + 1024 * 1024)
-_FILESYSTEM_LEN = const(31 * 1024 * 1024)
+
+# Roundabout way to get actual filesystem size from config.
+# This takes into account the 1M "reserved" section of the flash memory.
+flash = pyb.Flash(start=0)
+_FILESYSTEM_LEN = flash.ioctl(_IOCTL_BLOCK_COUNT, None) * flash.ioctl(_IOCTL_BLOCK_SIZE, None)
def update_app(filename):
@@ -23,8 +30,15 @@ def update_app(filename):
key = struct.pack("CCR2 = 2;
tim->EGR = 1; // UG
- mp_hal_pin_config(pin_B15, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, 9);
+ mp_hal_pin_config(pyb_pin_TLC_GS_CLK, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, 9);
}
static void hub_display_spi_init(void) {
@@ -93,9 +93,9 @@ static void hub_display_spi_init(void) {
spi->CR1 = SPI_CR1_SSM | SPI_CR1_SSI | 0 << SPI_CR1_BR_Pos | SPI_CR1_MSTR;
spi->CR1 |= SPI_CR1_SPE;
- mp_hal_pin_config(pin_A5, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, 5);
- mp_hal_pin_config(pin_A6, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, 5);
- mp_hal_pin_config(pin_A7, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, 5);
+ mp_hal_pin_config(pyb_pin_TLC_SCLK, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, 5);
+ mp_hal_pin_config(pyb_pin_TLC_SOUT, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, 5);
+ mp_hal_pin_config(pyb_pin_TLC_SIN, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, 5);
}
static void hub_display_spi_write(uint8_t value) {
@@ -123,9 +123,9 @@ static void hub_display_latch_ctrl(uint8_t dc, uint32_t mc, uint32_t bc, uint8_t
for (int i = 0; i < 42; ++i) {
hub_display_spi_write(dc);
}
- mp_hal_pin_high(pin_A15);
+ mp_hal_pin_high(pyb_pin_TLC_LAT);
mp_hal_delay_us(1);
- mp_hal_pin_low(pin_A15);
+ mp_hal_pin_low(pyb_pin_TLC_LAT);
}
void hub_display_set(uint8_t led, uint16_t value) {
@@ -142,17 +142,17 @@ void hub_display_update(void) {
for (int i = 0; i < 96; ++i) {
hub_display_spi_write(hub_display_gs_state[95 - i]);
}
- mp_hal_pin_high(pin_A15);
+ mp_hal_pin_high(pyb_pin_TLC_LAT);
mp_hal_delay_us(1);
- mp_hal_pin_low(pin_A15);
+ mp_hal_pin_low(pyb_pin_TLC_LAT);
}
void hub_display_on(void) {
if (hub_display_init) {
return;
}
- mp_hal_pin_output(pin_A15);
- mp_hal_pin_low(pin_A15);
+ mp_hal_pin_output(pyb_pin_TLC_LAT);
+ mp_hal_pin_low(pyb_pin_TLC_LAT);
hub_display_spi_init();
for (int i = 0; i < 2; ++i) {
hub_display_latch_ctrl(0xff, 0, 0x1fffff, 0x11);
@@ -171,10 +171,10 @@ void hub_display_off(void) {
__HAL_RCC_SPI1_CLK_DISABLE();
__HAL_RCC_SPI1_FORCE_RESET();
__HAL_RCC_SPI1_RELEASE_RESET();
- mp_hal_pin_config(pin_A5, MP_HAL_PIN_MODE_ANALOG, MP_HAL_PIN_PULL_NONE, 0);
- mp_hal_pin_config(pin_A6, MP_HAL_PIN_MODE_ANALOG, MP_HAL_PIN_PULL_NONE, 0);
- mp_hal_pin_config(pin_A7, MP_HAL_PIN_MODE_ANALOG, MP_HAL_PIN_PULL_NONE, 0);
- mp_hal_pin_config(pin_A15, MP_HAL_PIN_MODE_ANALOG, MP_HAL_PIN_PULL_NONE, 0);
- mp_hal_pin_config(pin_B15, MP_HAL_PIN_MODE_ANALOG, MP_HAL_PIN_PULL_NONE, 0);
+ mp_hal_pin_config(pyb_pin_TLC_SCLK, MP_HAL_PIN_MODE_ANALOG, MP_HAL_PIN_PULL_NONE, 0);
+ mp_hal_pin_config(pyb_pin_TLC_SOUT, MP_HAL_PIN_MODE_ANALOG, MP_HAL_PIN_PULL_NONE, 0);
+ mp_hal_pin_config(pyb_pin_TLC_SIN, MP_HAL_PIN_MODE_ANALOG, MP_HAL_PIN_PULL_NONE, 0);
+ mp_hal_pin_config(pyb_pin_TLC_LAT, MP_HAL_PIN_MODE_ANALOG, MP_HAL_PIN_PULL_NONE, 0);
+ mp_hal_pin_config(pyb_pin_TLC_GS_CLK, MP_HAL_PIN_MODE_ANALOG, MP_HAL_PIN_PULL_NONE, 0);
hub_display_init = false;
}
diff --git a/ports/stm32/boards/LEGO_HUB_NO6/manifest.py b/ports/stm32/boards/LEGO_HUB_NO6/manifest.py
index dc09d04c9f2b..1be4246e3788 100644
--- a/ports/stm32/boards/LEGO_HUB_NO6/manifest.py
+++ b/ports/stm32/boards/LEGO_HUB_NO6/manifest.py
@@ -1,5 +1,8 @@
+# Shared manifest for LEGO_HUB_NO6 & LEGO_HUB_NO7.
+
include("$(PORT_DIR)/boards/manifest.py")
# Modules for application firmware update.
-freeze("$(PORT_DIR)/mboot", "fwupdate.py", opt=3)
-freeze("$(BOARD_DIR)", ("spiflash.py", "appupdate.py"), opt=3)
+module("fwupdate.py", base_path="$(PORT_DIR)/mboot", opt=3)
+module("spiflash.py", opt=3)
+module("appupdate.py", opt=3)
diff --git a/ports/stm32/boards/LEGO_HUB_NO6/mboot_memory.ld b/ports/stm32/boards/LEGO_HUB_NO6/mboot_memory.ld
index dd914c8e88e3..f48f2056cae6 100644
--- a/ports/stm32/boards/LEGO_HUB_NO6/mboot_memory.ld
+++ b/ports/stm32/boards/LEGO_HUB_NO6/mboot_memory.ld
@@ -8,3 +8,6 @@ MEMORY
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 120K
}
+/* Location from which mboot is allowed to write to flash.
+ Must be the start of a flash erase sector. */
+_mboot_writable_flash_start = ORIGIN(FLASH_BL) + LENGTH(FLASH_BL);
diff --git a/ports/stm32/boards/LEGO_HUB_NO6/mpconfigboard.h b/ports/stm32/boards/LEGO_HUB_NO6/mpconfigboard.h
index cab46fa02d57..7f0b1fbe45c9 100644
--- a/ports/stm32/boards/LEGO_HUB_NO6/mpconfigboard.h
+++ b/ports/stm32/boards/LEGO_HUB_NO6/mpconfigboard.h
@@ -34,41 +34,40 @@
// UART buses
// Bluetooth HCI
-#define MICROPY_HW_UART2_CTS (pin_D3)
-#define MICROPY_HW_UART2_RTS (pin_D4)
-#define MICROPY_HW_UART2_TX (pin_D5)
-#define MICROPY_HW_UART2_RX (pin_D6)
+#define MICROPY_HW_UART2_CTS (pyb_pin_BT_CTS)
+#define MICROPY_HW_UART2_RTS (pyb_pin_BT_RTS)
+#define MICROPY_HW_UART2_TX (pyb_pin_BT_TX)
+#define MICROPY_HW_UART2_RX (pyb_pin_BT_RX)
// Port B
-#define MICROPY_HW_UART4_TX (pin_D1)
-#define MICROPY_HW_UART4_RX (pin_D0)
+#define MICROPY_HW_UART4_TX (pyb_pin_PORTB_TX)
+#define MICROPY_HW_UART4_RX (pyb_pin_PORTB_RX)
// Port D
-#define MICROPY_HW_UART5_TX (pin_C12)
-#define MICROPY_HW_UART5_RX (pin_D2)
+#define MICROPY_HW_UART5_TX (pyb_pin_PORTD_TX)
+#define MICROPY_HW_UART5_RX (pyb_pin_PORTD_RX)
// Port A
-#define MICROPY_HW_UART7_TX (pin_E8)
-#define MICROPY_HW_UART7_RX (pin_E7)
+#define MICROPY_HW_UART7_TX (pyb_pin_PORTA_TX)
+#define MICROPY_HW_UART7_RX (pyb_pin_PORTA_RX)
// Port C
-#define MICROPY_HW_UART8_TX (pin_E1)
-#define MICROPY_HW_UART8_RX (pin_E0)
+#define MICROPY_HW_UART8_TX (pyb_pin_PORTC_TX)
+#define MICROPY_HW_UART8_RX (pyb_pin_PORTC_RX)
// Port F
-#define MICROPY_HW_UART9_TX (pin_D15)
-#define MICROPY_HW_UART9_RX (pin_D14)
+#define MICROPY_HW_UART9_TX (pyb_pin_PORTF_TX)
+#define MICROPY_HW_UART9_RX (pyb_pin_PORTF_RX)
// Port E
-#define MICROPY_HW_UART10_TX (pin_E3)
-#define MICROPY_HW_UART10_RX (pin_E2)
+#define MICROPY_HW_UART10_TX (pyb_pin_PORTE_TX)
+#define MICROPY_HW_UART10_RX (pyb_pin_PORTE_RX)
// SPI buses
-#define MICROPY_HW_SPI1_NSS (pin_A4) // shared with DAC
-#define MICROPY_HW_SPI1_SCK (pin_A5) // shared with DAC
-#define MICROPY_HW_SPI1_MISO (pin_A6)
-#define MICROPY_HW_SPI1_MOSI (pin_A7)
-#define MICROPY_HW_SPI2_NSS (pin_B12)
-#define MICROPY_HW_SPI2_SCK (pin_B13)
-#define MICROPY_HW_SPI2_MISO (pin_C2)
-#define MICROPY_HW_SPI2_MOSI (pin_C3)
+#define MICROPY_HW_SPI1_SCK (pyb_pin_TLC_SCLK)
+#define MICROPY_HW_SPI1_MISO (pyb_pin_TLC_SOUT)
+#define MICROPY_HW_SPI1_MOSI (pyb_pin_TLC_SIN)
+#define MICROPY_HW_SPI2_NSS (pyb_pin_FLASH_NSS)
+#define MICROPY_HW_SPI2_SCK (pyb_pin_FLASH_SCK)
+#define MICROPY_HW_SPI2_MISO (pyb_pin_FLASH_MISO)
+#define MICROPY_HW_SPI2_MOSI (pyb_pin_FLASH_MOSI)
// USB config
-#define MICROPY_HW_USB_VBUS_DETECT_PIN (pin_A9)
+#define MICROPY_HW_USB_VBUS_DETECT_PIN (pyb_pin_USB_VBUS)
#define MICROPY_HW_USB_FS (1)
#define MICROPY_HW_USB_MSC (1)
diff --git a/ports/stm32/boards/LEGO_HUB_NO6/pins.csv b/ports/stm32/boards/LEGO_HUB_NO6/pins.csv
index 9e56e2c79de4..1d0b8f35d8d8 100644
--- a/ports/stm32/boards/LEGO_HUB_NO6/pins.csv
+++ b/ports/stm32/boards/LEGO_HUB_NO6/pins.csv
@@ -26,14 +26,14 @@ PORTD_M1,PB8
PORTD_M2,PB9
LSM6_SCL,PB10
,PB11
-,PB12
-,PB13
+FLASH_NSS,PB12
+FLASH_SCK,PB13
,PB14
TLC_GS_CLK,PB15
BAT_IMON_ADC,PC0
BAT_VMON_ADC,PC1
-,PC2
-,PC3
+FLASH_MISO,PC2
+FLASH_MOSI,PC3
CHGOK_CENBTN_3V3OK_ADC,PC4
PORTF_EN,PC5
PORTE_M1,PC6
diff --git a/ports/stm32/boards/LEGO_HUB_NO6/spiflash.py b/ports/stm32/boards/LEGO_HUB_NO6/spiflash.py
index e052f7738b70..e483ace95084 100644
--- a/ports/stm32/boards/LEGO_HUB_NO6/spiflash.py
+++ b/ports/stm32/boards/LEGO_HUB_NO6/spiflash.py
@@ -4,18 +4,34 @@
from micropython import const
_PAGE_SIZE = const(256) # maximum bytes writable in one SPI transfer
+_CMD_WRITE = const(0x02)
+_CMD_READ = const(0x03)
_CMD_RDSR = const(0x05)
_CMD_WREN = const(0x06)
_CMD_WRITE_32 = const(0x12)
_CMD_READ_32 = const(0x13)
+_CMD_SEC_ERASE = const(0x20)
_CMD_SEC_ERASE_32 = const(0x21)
-_CMD_C4READ_32 = const(0xEC)
+_CMD_JEDEC_ID = const(0x9F)
class SPIFlash:
def __init__(self, spi, cs):
self.spi = spi
self.cs = cs
+ self.id = self._get_id()
+ # flash chip on Hub No. 6 uses 32-bit addressing
+ _32_bit = self.id == b"\xef\x40\x19"
+ self._READ = _CMD_READ_32 if _32_bit else _CMD_READ
+ self._WRITE = _CMD_WRITE_32 if _32_bit else _CMD_WRITE
+ self._ERASE = _CMD_SEC_ERASE_32 if _32_bit else _CMD_SEC_ERASE
+
+ def _get_id(self):
+ self.cs(0)
+ self.spi.write(bytearray([_CMD_JEDEC_ID]))
+ buf = self.spi.read(3)
+ self.cs(1)
+ return buf
def _wait_wel1(self):
# wait WEL=1
@@ -52,11 +68,11 @@ def _flash_modify(self, cmd, addr, buf):
self._wait_wip0()
def erase_block(self, addr):
- self._flash_modify(_CMD_SEC_ERASE_32, addr, None)
+ self._flash_modify(self._ERASE, addr, None)
def readinto(self, addr, buf):
self.cs(0)
- self.spi.write(bytearray([_CMD_READ_32, addr >> 16, addr >> 8, addr]))
+ self.spi.write(bytearray([self._READ, addr >> 16, addr >> 8, addr]))
self.spi.readinto(buf)
self.cs(1)
@@ -67,7 +83,7 @@ def write(self, addr, buf):
buf_offset = 0
while remain:
l = min(_PAGE_SIZE - offset, remain)
- self._flash_modify(_CMD_WRITE_32, addr, buf[buf_offset : buf_offset + l])
+ self._flash_modify(self._WRITE, addr, buf[buf_offset : buf_offset + l])
remain -= l
addr += l
buf_offset += l
diff --git a/ports/stm32/boards/LEGO_HUB_NO7/README.md b/ports/stm32/boards/LEGO_HUB_NO7/README.md
new file mode 100644
index 000000000000..8159cf3f4713
--- /dev/null
+++ b/ports/stm32/boards/LEGO_HUB_NO7/README.md
@@ -0,0 +1,135 @@
+LEGO Hub No.7
+=============
+
+This board definition is for the LEGO Hub No. 7, a LEGO control unit with 1 button,
+2 RGB LEDs, 2 Powered Up ports, 6-DOF sensor, Bluetooth, USB, 4MiB external SPI
+flash storage, and a rechargeable battery.
+
+Features that are currently supported:
+- standard MicroPython
+- machine and bluetooth modules
+- filesystem
+- USB VCP, MSC and HID
+
+The Hub has a bootloader preinstalled at 0x08000000 (which is 32kiB in size) which
+cannot be erased. This bootloader is entered by holding down the button for 5 seconds,
+at which point the USB DFU device appears. If the battery is installed then the
+RGB LED will flash purple. If the battery is not installed, the LED will flash orange
+briefly and then the hub will turn off (so having the battery installed is required).
+When this bootloader is active, the flash from 0x08008000 and up can be erased
+and programmed via USB DFU.
+
+The built-in bootloader has some drawbacks: it cannot be entered programmatically,
+and it does not keep the Hub powered up when running from battery (which requires
+keeping BAT_PWR_EN high). As such, this board is configured to work with mboot as
+a secondary bootloader: mboot is placed at 0x08008000 and the main application
+firmware at 0x08010000. When mboot is installed it can be entered programatically
+via machine.bootloader().
+
+Backing up original Hub firmware
+--------------------------------
+
+Before installing MicroPython it is advised to backup the original LEGO firmware that
+the Hub comes installed with. To do this, enter the built-in bootloader by holding
+down the power button for 5 seconds while powering up the Hub via USB (you may
+need to take out the battery and disconnect USB to power off the Hub first). Then
+run the following command from the root of this repository:
+
+ $ cd ports/stm32
+ $ make BOARD=LEGO_HUB_NO7 backup-hub-firmware
+
+This will create a file called `lego_hub_firmware.dfu`. Put this file in a safe
+location. To restore it, enter the built-in bootloader again and run:
+
+ $ make BOARD=LEGO_HUB_NO7 restore-hub-firmware
+
+This will restore the original firmware but not the filesystem. To recreate the
+original filesystem the Hub must be updated using the appropriate LEGO PC
+application.
+
+Installing MicroPython
+----------------------
+
+You first need to build and install mboot, which only needs to be done once. From
+the root of this repository run:
+
+ $ cd ports/stm32/mboot
+ $ make BOARD=LEGO_HUB_NO7
+
+Now enter the built-in bootloader by holding down the power button for 5
+seconds while powering up the Hub via USB (you may need to take out the battery
+and disconnect USB to power off the Hub first). Then run:
+
+ $ make BOARD=LEGO_HUB_NO7 deploy
+
+mboot should now be installed. To enter mboot, remove USB and the battery.
+Connect the USB cable (the other end of the USB cable must be connected to
+something that provides power). The status light should start cycling through
+different colors. Replace the battery (the button will not work without the
+battery present). Press the button to activate the desired boot mode:
+
+- Status light is red - run application (normal boot).
+- Status light is green - run application in factory file system mode.
+- Status light is blue - run application in safe mode.
+- Status light is white - start DFU on the USB port.
+
+
+Now build MicroPython (start at the root of this repository):
+
+ $ cd mpy-cross
+ $ make
+ $ cd ../ports/stm32
+ $ make submodules
+ $ make BOARD=LEGO_HUB_NO7
+
+And deploy to the Hub (making sure mboot DFU is active, the center button is
+blinking red):
+
+ $ make BOARD=LEGO_HUB_NO7 deploy
+
+If successful, the Hub should now appear as a USB serial and mass storage device.
+
+Using MicroPython on the Hub
+----------------------------
+
+Access the MicroPython REPL using mpremote (pip install mpremote), or with any
+serial terminal program.
+
+To scan for BLE devices:
+
+ >>> import bluetooth
+ >>> ble = bluetooth.BLE()
+ >>> ble.irq(lambda *x: print(*x))
+ >>> ble.active(1)
+ >>> ble.gap_scan(2000, 625, 625)
+
+Use help("modules") to see available built-in modules.
+
+Updating MicroPython from the Hub's filesystem
+----------------------------------------------
+
+You can update the MicroPython application firmware using the instructions above
+for installing the firmware for the first time. The Hub also supports updating
+the application firmware from within MicroPython itself, using the on-board
+filesystem.
+
+To use this feature, build the firmware (see above for details) then gzip it and
+copy the resulting file to the Hub (eg using mpremote):
+
+ $ make BOARD=LEGO_HUB_NO7
+ $ gzip build-LEGO_HUB_NO7/firmware.dfu
+ $ mpremote cp build-LEGO_HUB_NO7/firmware.dfu.gz :
+
+Then get a REPL on the Hub and execute:
+
+ >>> import appupdate
+ >>> appupdate.update_app("firmware.dfu.gz")
+
+You can alternatively run this REPL command using mpremote:
+
+ $ mpremote exec --no-follow "import appupdate; appupdate.update_app('firmware.dfu.gz')"
+
+At that point the Hub should restart and the LED on the central button will flash
+different colours. Once the update is complete the LED will stop flashing and the
+Hub will appear again as a USB device. The application firmware is now updated
+and you can remove the firmware.dfu.gz file if desired.
diff --git a/ports/stm32/boards/LEGO_HUB_NO7/bdev.c b/ports/stm32/boards/LEGO_HUB_NO7/bdev.c
new file mode 100644
index 000000000000..f104c0f3f463
--- /dev/null
+++ b/ports/stm32/boards/LEGO_HUB_NO7/bdev.c
@@ -0,0 +1,3 @@
+// LEGO_HUB_NO7 is identical to LEGO_HUB_NO6 in this regard.
+
+#include "../LEGO_HUB_NO6/bdev.c"
diff --git a/ports/stm32/boards/LEGO_HUB_NO7/bluetooth_init_cc2564C_1.5.c b/ports/stm32/boards/LEGO_HUB_NO7/bluetooth_init_cc2564C_1.5.c
new file mode 100644
index 000000000000..6ea298f68839
--- /dev/null
+++ b/ports/stm32/boards/LEGO_HUB_NO7/bluetooth_init_cc2564C_1.5.c
@@ -0,0 +1,3 @@
+// LEGO_HUB_NO7 is identical to LEGO_HUB_NO6 in this regard.
+
+#include "../LEGO_HUB_NO6/bluetooth_init_cc2564C_1.5.c"
diff --git a/ports/stm32/boards/LEGO_HUB_NO7/board.json b/ports/stm32/boards/LEGO_HUB_NO7/board.json
new file mode 100644
index 000000000000..1ef02c17a063
--- /dev/null
+++ b/ports/stm32/boards/LEGO_HUB_NO7/board.json
@@ -0,0 +1,13 @@
+{
+ "deploy": [
+ "../deploy.md"
+ ],
+ "docs": "",
+ "features": [],
+ "images": [],
+ "mcu": "stm32f4",
+ "product": "Hub No.7",
+ "thumbnail": "",
+ "url": "",
+ "vendor": "LEGO"
+}
diff --git a/ports/stm32/boards/LEGO_HUB_NO7/board_init.c b/ports/stm32/boards/LEGO_HUB_NO7/board_init.c
new file mode 100644
index 000000000000..7b155b1c3cea
--- /dev/null
+++ b/ports/stm32/boards/LEGO_HUB_NO7/board_init.c
@@ -0,0 +1,212 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2021-2022 Damien P. George
+ * Copyright (c) 2022 David Lechner
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "py/mphal.h"
+#include "irq.h"
+
+void board_init(void) {
+ if (query_irq() == IRQ_STATE_DISABLED) {
+ enable_irq(IRQ_STATE_ENABLED);
+ }
+
+ // Enable 3V3 for all ports
+ mp_hal_pin_output(pyb_pin_PORT_3V3_EN);
+ mp_hal_pin_high(pyb_pin_PORT_3V3_EN);
+
+ // Port A
+ // Enable RX/TX buffer
+ mp_hal_pin_output(pyb_pin_PORTA_EN);
+ mp_hal_pin_low(pyb_pin_PORTA_EN);
+
+ // Port B
+ // Enable RX/TX buffer
+ mp_hal_pin_output(pyb_pin_PORTB_EN);
+ mp_hal_pin_low(pyb_pin_PORTB_EN);
+}
+
+#if BUILDING_MBOOT
+
+#include "drivers/memory/spiflash.h"
+#include "mboot/mboot.h"
+#include "boardctrl.h"
+#include "adc.h"
+#include "hub_display.h"
+
+#define RESET_MODE_NUM_STATES (4)
+#define RESET_MODE_TIMEOUT_CYCLES (8)
+
+// Location and value for the SPI flash update key. If this key exists at the defined
+// location then mboot will attempt to do a filesystem-load update of the main firmware.
+// This makes the update robust to power failures: if the update does not complete then
+// it will be restarted the next time it powers up. Only when it fully completes will
+// this key be erased, and then the application can run.
+#define SPIFLASH_UPDATE_KEY_ADDR (1020 * 1024)
+#define SPIFLASH_UPDATE_KEY_VALUE (0x12345678)
+
+static void board_led_pattern(int reset_mode, uint16_t brightness) {
+ switch (reset_mode) {
+ case BOARDCTRL_RESET_MODE_NORMAL:
+ // set status light to red
+ hub_display_set(3, brightness);
+ hub_display_set(4, 0);
+ hub_display_set(5, 0);
+ break;
+ case BOARDCTRL_RESET_MODE_SAFE_MODE:
+ // set status light to green
+ hub_display_set(3, 0);
+ hub_display_set(4, brightness);
+ hub_display_set(5, 0);
+ break;
+ case BOARDCTRL_RESET_MODE_FACTORY_FILESYSTEM:
+ // set status light to blue
+ hub_display_set(3, 0);
+ hub_display_set(4, 0);
+ hub_display_set(5, brightness);
+ break;
+ case BOARDCTRL_RESET_MODE_BOOTLOADER:
+ // set status light to white
+ hub_display_set(3, brightness);
+ hub_display_set(4, brightness);
+ hub_display_set(5, brightness);
+ break;
+ }
+
+ hub_display_update();
+}
+
+static void board_battery_init(void) {
+ mp_hal_pin_config(pyb_pin_BAT_VMON_ADC, MP_HAL_PIN_MODE_ADC, MP_HAL_PIN_PULL_NONE, 0);
+ adc_config(ADC1, 12);
+}
+
+// returns true if the battery is pressed, otherwise false
+static int board_battery_state(void) {
+ uint16_t value = adc_config_and_read_u16(ADC1, 6, ADC_SAMPLETIME_15CYCLES);
+ // If battery voltage is above USB voltage, then we consider the battery
+ // to be present.
+ return value > 41100; // 41100 is approx 5.5V
+}
+
+static void board_button_init(void) {
+ mp_hal_pin_input(pyb_pin_BUTTON);
+}
+
+// returns true if the button is pressed, otherwise false
+static int board_button_state(void) {
+ // button is active low
+ return !mp_hal_pin_read(pyb_pin_BUTTON);
+}
+
+void board_mboot_cleanup(int reset_mode) {
+ board_led_pattern(0, 0);
+ hub_display_off();
+}
+
+void board_mboot_led_init(void) {
+ hub_display_on();
+}
+
+void board_mboot_led_state(int led, int state) {
+ if (state) {
+ hub_display_set(3 + led, 0x7fff);
+ } else {
+ hub_display_set(3 + led, 0);
+ }
+
+ hub_display_update();
+}
+
+int board_mboot_get_reset_mode(uint32_t *initial_r0) {
+ board_battery_init();
+ board_button_init();
+ int reset_mode = BOARDCTRL_RESET_MODE_NORMAL;
+
+ if (board_battery_state()) {
+ // Battery is present, check flash for update key and start an update if the key exists.
+ // Otherwise, boot normally.
+
+ // Initialise the external SPI flash.
+ MBOOT_SPIFLASH_SPIFLASH->config = MBOOT_SPIFLASH_CONFIG;
+ mp_spiflash_init(MBOOT_SPIFLASH_SPIFLASH);
+
+ // Read in the key.
+ uint32_t buf;
+ mp_spiflash_read(MBOOT_SPIFLASH_SPIFLASH, SPIFLASH_UPDATE_KEY_ADDR, 4, (uint8_t *)&buf);
+
+ if (buf == SPIFLASH_UPDATE_KEY_VALUE) {
+ // The key has the correct value, so read in the FS-load elements and enter the bootloader.
+ mp_spiflash_read(MBOOT_SPIFLASH_SPIFLASH, SPIFLASH_UPDATE_KEY_ADDR + 4, ELEM_DATA_SIZE, ELEM_DATA_START);
+ *initial_r0 = MBOOT_INITIAL_R0_KEY_FSLOAD;
+ reset_mode = BOARDCTRL_RESET_MODE_BOOTLOADER;
+ }
+ } else {
+ // Battery is not present. Cycle through reset modes until button is pressed.
+ systick_init();
+ hub_display_on();
+ reset_mode = 0;
+ for (int i = 0; i < (RESET_MODE_NUM_STATES * RESET_MODE_TIMEOUT_CYCLES + 1) * 64; i++) {
+ if (i % 64 == 0) {
+ if (++reset_mode > RESET_MODE_NUM_STATES) {
+ reset_mode = BOARDCTRL_RESET_MODE_NORMAL;
+ }
+ board_led_pattern(reset_mode, 0x7fff);
+ }
+
+ if (board_button_state()) {
+ break;
+ }
+
+ mp_hal_delay_ms(19);
+ }
+
+ // Flash the selected reset mode.
+ for (int i = 0; i < 6; i++) {
+ board_led_pattern(reset_mode, 0x0fff);
+ mp_hal_delay_ms(50);
+ board_led_pattern(reset_mode, 0x7fff);
+ mp_hal_delay_ms(50);
+ }
+
+ mp_hal_delay_ms(300);
+ }
+
+ board_led_pattern(0, 0);
+ return reset_mode;
+}
+
+void board_mboot_state_change(int state, uint32_t arg) {
+ if (state == MBOOT_STATE_FSLOAD_END) {
+ // The FS-load update completed (either with success or failure), so erase the
+ // update key and write the result of the FS-load operation into flash.
+ mp_spiflash_erase_block(MBOOT_SPIFLASH_SPIFLASH, SPIFLASH_UPDATE_KEY_ADDR);
+ mp_spiflash_write(MBOOT_SPIFLASH_SPIFLASH, SPIFLASH_UPDATE_KEY_ADDR + 4, 4, (const uint8_t *)&arg);
+ }
+
+ mboot_state_change_default(state, arg);
+}
+
+#endif
diff --git a/ports/stm32/boards/LEGO_HUB_NO7/cc2564.c b/ports/stm32/boards/LEGO_HUB_NO7/cc2564.c
new file mode 100644
index 000000000000..e5bfe1b4d4ca
--- /dev/null
+++ b/ports/stm32/boards/LEGO_HUB_NO7/cc2564.c
@@ -0,0 +1,6 @@
+// LEGO_HUB_NO7 is nearly identical to LEGO_HUB_NO6 in this regard.
+
+#define CC2564_TIMER_BT_SLOWCLOCK_TIM 2
+#define CC2564_TIMER_BT_SLOWCLOCK_TIM_CH 2
+
+#include "../LEGO_HUB_NO6/cc2564.c"
diff --git a/ports/stm32/boards/LEGO_HUB_NO7/hub_display.c b/ports/stm32/boards/LEGO_HUB_NO7/hub_display.c
new file mode 100644
index 000000000000..e19485b0646f
--- /dev/null
+++ b/ports/stm32/boards/LEGO_HUB_NO7/hub_display.c
@@ -0,0 +1,190 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2021 Damien P. George
+ * Copyright (c) 2022 David Lechner
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "py/mphal.h"
+#include "hub_display.h"
+
+#include STM32_HAL_H
+
+#define I2C_ADDR 0x28
+
+// Registers
+#define DEVICE_CONFIG0 0x00
+#define DEVICE_CONFIG1 0x01
+#define LED_CONFIG0 0x02
+#define BANK_BRIGHTNESS 0x03
+#define BANK_A_COLOR 0x04
+#define BANK_B_COLOR 0x05
+#define BANK_C_COLOR 0x06
+#define LED0_BRIGHTNESS 0x07
+#define LED1_BRIGHTNESS 0x08
+#define LED2_BRIGHTNESS 0x09
+#define LED3_BRIGHTNESS 0x0A
+#define OUT0_COLOR 0x0B
+#define OUT1_COLOR 0x0C
+#define OUT2_COLOR 0x0D
+#define OUT3_COLOR 0x0E
+#define OUT4_COLOR 0x0F
+#define OUT5_COLOR 0x10
+#define OUT6_COLOR 0x11
+#define OUT7_COLOR 0x12
+#define OUT8_COLOR 0x13
+#define OUT9_COLOR 0x14
+#define OUT10_COLOR 0x15
+#define OUT11_COLOR 0x16
+#define RESET 0x17
+
+// Flags
+#define DEVICE_CONFIG0_CHIP_EN (1 << 6)
+#define DEVICE_CONFIG1_LOG_SCALE_EN (1 << 5)
+#define DEVICE_CONFIG1_POWER_SAVE_EN (1 << 4)
+#define DEVICE_CONFIG1_AUTO_INCR_EN (1 << 3)
+#define DEVICE_CONFIG1_PWM_DITHERING_EN (1 << 2)
+#define DEVICE_CONFIG1_MAX_CURRENT_OPTION (1 << 1)
+#define DEVICE_CONFIG1_LED_GLOBAL_OFF (1 << 0)
+#define LED_CONFIG0_LED3_BANK_EN (1 << 3)
+#define LED_CONFIG0_LED2_BANK_EN (1 << 2)
+#define LED_CONFIG0_LED1_BANK_EN (1 << 1)
+#define LED_CONFIG0_LED0_BANK_EN (1 << 0)
+
+#define LP50XX_NUM_CH 6
+
+// channel mapping:
+// CH 0 = battery LED - red
+// CH 1 = battery LED - green
+// CH 2 = battery LED - blue
+// CH 3 = status LED - red
+// CH 4 = status LED - green
+// CH 5 = status LED - blue
+
+#define FMPI2C_CONVERT_TIMINGS(PRESC, SCLDEL, SDADEL, SCLH, SCLL) \
+ (((PRESC) << FMPI2C_TIMINGR_PRESC_Pos) | \
+ ((SCLDEL) << FMPI2C_TIMINGR_SCLDEL_Pos) | \
+ ((SDADEL) << FMPI2C_TIMINGR_SDADEL_Pos) | \
+ ((SCLH) << FMPI2C_TIMINGR_SCLH_Pos) | \
+ ((SCLL) << FMPI2C_TIMINGR_SCLL_Pos))
+
+static FMPI2C_HandleTypeDef hub_display_i2c;
+static bool hub_display_init;
+
+static struct {
+ uint8_t reg;
+ uint8_t values[LP50XX_NUM_CH];
+} __attribute__((packed)) hub_display_data = {
+ .reg = OUT0_COLOR,
+};
+
+void HAL_FMPI2C_MspInit(FMPI2C_HandleTypeDef *hfmpi2c) {
+ __HAL_RCC_FMPI2C1_CLK_ENABLE();
+ mp_hal_pin_config(pyb_pin_LED_SCL, MP_HAL_PIN_MODE_ALT_OPEN_DRAIN, MP_HAL_PIN_PULL_NONE, 4);
+ mp_hal_pin_config(pyb_pin_LED_SDA, MP_HAL_PIN_MODE_ALT_OPEN_DRAIN, MP_HAL_PIN_PULL_NONE, 4);
+}
+
+void HAL_FMPI2C_MspDeInit(FMPI2C_HandleTypeDef *hfmpi2c) {
+ __HAL_RCC_FMPI2C1_CLK_DISABLE();
+ __HAL_RCC_FMPI2C1_FORCE_RESET();
+ __HAL_RCC_FMPI2C1_RELEASE_RESET();
+ mp_hal_pin_config(pyb_pin_LED_SCL, MP_HAL_PIN_MODE_ANALOG, MP_HAL_PIN_PULL_NONE, 0);
+ mp_hal_pin_config(pyb_pin_LED_SDA, MP_HAL_PIN_MODE_ANALOG, MP_HAL_PIN_PULL_NONE, 0);
+}
+
+static void hub_display_i2c_init(void) {
+ hub_display_i2c.Instance = FMPI2C1;
+ hub_display_i2c.Init.Timing = FMPI2C_CONVERT_TIMINGS(0, 4, 0, 19, 28);
+ hub_display_i2c.Init.OwnAddress1 = 0;
+ hub_display_i2c.Init.AddressingMode = FMPI2C_ADDRESSINGMODE_7BIT;
+ hub_display_i2c.Init.DualAddressMode = FMPI2C_DUALADDRESS_DISABLE;
+ hub_display_i2c.Init.OwnAddress2 = 0;
+ hub_display_i2c.Init.OwnAddress2Masks = FMPI2C_OA2_NOMASK;
+ hub_display_i2c.Init.GeneralCallMode = FMPI2C_GENERALCALL_DISABLE;
+ hub_display_i2c.Init.NoStretchMode = FMPI2C_NOSTRETCH_DISABLE;
+ HAL_FMPI2C_Init(&hub_display_i2c);
+}
+
+void hub_display_set(uint8_t led, uint16_t value) {
+ if (led >= LP50XX_NUM_CH) {
+ return;
+ }
+
+ hub_display_data.values[led] = value >> 8;
+}
+
+void hub_display_update(void) {
+ if (!hub_display_init) {
+ return;
+ }
+
+ HAL_FMPI2C_Master_Transmit(&hub_display_i2c, I2C_ADDR, (uint8_t *)&hub_display_data,
+ sizeof(hub_display_data), HAL_MAX_DELAY);
+}
+
+void hub_display_on(void) {
+ if (hub_display_init) {
+ return;
+ }
+
+ hub_display_i2c_init();
+ mp_hal_pin_output(pyb_pin_LED_EN);
+ mp_hal_pin_high(pyb_pin_LED_EN);
+
+ static const struct {
+ uint8_t reg;
+ uint8_t values[11];
+ } __attribute__((packed)) init_data = {
+ .reg = DEVICE_CONFIG0,
+ .values = {
+ [DEVICE_CONFIG0] = DEVICE_CONFIG0_CHIP_EN,
+ [DEVICE_CONFIG1] = DEVICE_CONFIG1_POWER_SAVE_EN | DEVICE_CONFIG1_PWM_DITHERING_EN | DEVICE_CONFIG1_AUTO_INCR_EN,
+ [LED_CONFIG0] = 0,
+ [BANK_BRIGHTNESS] = 0,
+ [BANK_A_COLOR] = 0,
+ [BANK_B_COLOR] = 0,
+ [BANK_C_COLOR] = 0,
+ [LED0_BRIGHTNESS] = 51, // battery LED
+ [LED1_BRIGHTNESS] = 38, // status LED
+ [LED2_BRIGHTNESS] = 0,
+ [LED3_BRIGHTNESS] = 0,
+ }
+ };
+
+ HAL_FMPI2C_Master_Transmit(&hub_display_i2c, I2C_ADDR, (uint8_t *)&init_data,
+ sizeof(init_data), HAL_MAX_DELAY);
+
+ hub_display_init = true;
+}
+
+void hub_display_off(void) {
+ if (!hub_display_init) {
+ return;
+ }
+
+ HAL_FMPI2C_DeInit(&hub_display_i2c);
+
+ mp_hal_pin_config(pyb_pin_LED_EN, MP_HAL_PIN_MODE_ANALOG, MP_HAL_PIN_PULL_NONE, 0);
+
+ hub_display_init = false;
+}
diff --git a/ports/stm32/boards/LEGO_HUB_NO7/hub_display.h b/ports/stm32/boards/LEGO_HUB_NO7/hub_display.h
new file mode 100644
index 000000000000..7623e128a804
--- /dev/null
+++ b/ports/stm32/boards/LEGO_HUB_NO7/hub_display.h
@@ -0,0 +1,4 @@
+void hub_display_on(void);
+void hub_display_off(void);
+void hub_display_update(void);
+void hub_display_set(uint8_t led, uint16_t value);
diff --git a/ports/stm32/boards/LEGO_HUB_NO7/manifest.py b/ports/stm32/boards/LEGO_HUB_NO7/manifest.py
new file mode 100644
index 000000000000..ee79864a982c
--- /dev/null
+++ b/ports/stm32/boards/LEGO_HUB_NO7/manifest.py
@@ -0,0 +1,2 @@
+# Use shared manifest.
+include("$(PORT_DIR)/boards/LEGO_HUB_NO6")
diff --git a/ports/stm32/boards/LEGO_HUB_NO7/mpconfigboard.h b/ports/stm32/boards/LEGO_HUB_NO7/mpconfigboard.h
new file mode 100644
index 000000000000..50fb6c0607f8
--- /dev/null
+++ b/ports/stm32/boards/LEGO_HUB_NO7/mpconfigboard.h
@@ -0,0 +1,152 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ * The MIT License (MIT)
+ * Copyright (c) 2021 Damien P. George
+ */
+
+#include
+
+#define MICROPY_HW_BOARD_NAME "LEGO Technic Hub No.7"
+#define MICROPY_HW_MCU_NAME "STM32F413"
+
+#define MICROPY_HW_HAS_SWITCH (0)
+#define MICROPY_HW_HAS_FLASH (1)
+#define MICROPY_PY_PYB_LEGACY (0)
+#define MICROPY_HW_ENTER_BOOTLOADER_VIA_RESET (0)
+#define MICROPY_HW_ENABLE_INTERNAL_FLASH_STORAGE (0)
+#define MICROPY_HW_ENABLE_RTC (1)
+#define MICROPY_HW_ENABLE_RNG (1)
+#define MICROPY_HW_ENABLE_DAC (1)
+#define MICROPY_HW_ENABLE_USB (1)
+#define MICROPY_HW_FLASH_FS_LABEL "HUB_NO7"
+
+// HSE is 16MHz, CPU freq set to 100MHz, buses at maximum freq
+#define MICROPY_HW_CLK_PLLM (16)
+#define MICROPY_HW_CLK_PLLN (200)
+#define MICROPY_HW_CLK_PLLP (RCC_PLLP_DIV2)
+#define MICROPY_HW_CLK_PLLQ (4)
+#define MICROPY_HW_CLK_AHB_DIV (RCC_SYSCLK_DIV1)
+#define MICROPY_HW_CLK_APB1_DIV (RCC_HCLK_DIV2)
+#define MICROPY_HW_CLK_APB2_DIV (RCC_HCLK_DIV1)
+
+// For 2.7 to 3.6 V, 75 to 100 MHz: 3 wait states.
+#define MICROPY_HW_FLASH_LATENCY FLASH_LATENCY_3
+
+// UART buses
+// Bluetooth HCI
+#define MICROPY_HW_UART2_CTS (pyb_pin_BT_CTS)
+#define MICROPY_HW_UART2_RTS (pyb_pin_BT_RTS)
+#define MICROPY_HW_UART2_TX (pyb_pin_BT_TX)
+#define MICROPY_HW_UART2_RX (pyb_pin_BT_RX)
+// Port B
+#define MICROPY_HW_UART3_TX (pyb_pin_PORTB_TX)
+#define MICROPY_HW_UART3_RX (pyb_pin_PORTB_RX)
+// Port A
+#define MICROPY_HW_UART5_TX (pyb_pin_PORTA_TX)
+#define MICROPY_HW_UART5_RX (pyb_pin_PORTA_RX)
+
+// SPI buses
+#define MICROPY_HW_SPI2_NSS (pyb_pin_FLASH_NSS)
+#define MICROPY_HW_SPI2_SCK (pyb_pin_FLASH_SCK)
+#define MICROPY_HW_SPI2_MISO (pyb_pin_FLASH_MISO)
+#define MICROPY_HW_SPI2_MOSI (pyb_pin_FLASH_MOSI)
+
+// USB config
+#define MICROPY_HW_USB_VBUS_DETECT_PIN (pyb_pin_USB_VBUS)
+#define MICROPY_HW_USB_FS (1)
+#define MICROPY_HW_USB_MSC (1)
+
+// Bluetooth config
+#define MICROPY_HW_BLE_UART_ID (PYB_UART_2)
+#define MICROPY_HW_BLE_UART_BAUDRATE (115200)
+#define MICROPY_HW_BLE_UART_BAUDRATE_SECONDARY (921600)
+#define MICROPY_HW_BLE_BTSTACK_CHIPSET_INSTANCE btstack_chipset_cc256x_instance()
+
+// SPI flash, for R/W storage
+// The first 1MiB is skipped because it's used by the built-in bootloader
+// Note: MICROPY_HW_SPIFLASH_OFFSET_BYTES must be a multiple of MP_SPIFLASH_ERASE_BLOCK_SIZE
+#define MICROPY_HW_SPIFLASH_OFFSET_BYTES (1024 * 1024)
+#define MICROPY_HW_SPIFLASH_BLOCKMAP(bl) ((bl) + MICROPY_HW_SPIFLASH_OFFSET_BYTES / FLASH_BLOCK_SIZE)
+#define MICROPY_HW_SPIFLASH_BLOCKMAP_EXT(bl) ((bl) + MICROPY_HW_SPIFLASH_OFFSET_BYTES / MP_SPIFLASH_ERASE_BLOCK_SIZE)
+#define MICROPY_HW_SPIFLASH_ENABLE_CACHE (1)
+#define MICROPY_HW_SPIFLASH_SIZE_BITS (32 * 1024 * 1024 - MICROPY_HW_SPIFLASH_OFFSET_BYTES * 8)
+#define MICROPY_HW_SPIFLASH_CS (MICROPY_HW_SPI2_NSS)
+#define MICROPY_HW_SPIFLASH_SCK (MICROPY_HW_SPI2_SCK)
+#define MICROPY_HW_SPIFLASH_MISO (MICROPY_HW_SPI2_MISO)
+#define MICROPY_HW_SPIFLASH_MOSI (MICROPY_HW_SPI2_MOSI)
+
+// SPI flash, block device config
+#define MICROPY_HW_BDEV_IOCTL(op, arg) ( \
+ (op) == BDEV_IOCTL_NUM_BLOCKS ? (MICROPY_HW_SPIFLASH_SIZE_BITS / 8 / FLASH_BLOCK_SIZE) : \
+ (op) == BDEV_IOCTL_INIT ? spi_bdev_ioctl(&spi_bdev, (op), (uint32_t)&spiflash_config) : \
+ spi_bdev_ioctl(&spi_bdev, (op), (arg)) \
+ )
+
+// Configuration for stardard block protocol (block size FLASH_BLOCK_SIZE).
+#define MICROPY_HW_BDEV_READBLOCKS(dest, bl, n) \
+ spi_bdev_readblocks(&spi_bdev, (dest), MICROPY_HW_SPIFLASH_BLOCKMAP(bl), (n))
+#define MICROPY_HW_BDEV_WRITEBLOCKS(src, bl, n) \
+ spi_bdev_writeblocks(&spi_bdev, (src), MICROPY_HW_SPIFLASH_BLOCKMAP(bl), (n))
+
+// Configuration for extended block protocol (block size MP_SPIFLASH_ERASE_BLOCK_SIZE).
+#define MICROPY_HW_BDEV_BLOCKSIZE_EXT (MP_SPIFLASH_ERASE_BLOCK_SIZE)
+#define MICROPY_HW_BDEV_READBLOCKS_EXT(dest, bl, off, len) \
+ (spi_bdev_readblocks_raw(&spi_bdev, (dest), MICROPY_HW_SPIFLASH_BLOCKMAP_EXT(bl), (off), (len)))
+#define MICROPY_HW_BDEV_WRITEBLOCKS_EXT(src, bl, off, len) \
+ (spi_bdev_writeblocks_raw(&spi_bdev, (src), MICROPY_HW_SPIFLASH_BLOCKMAP_EXT(bl), (off), (len)))
+#define MICROPY_HW_BDEV_ERASEBLOCKS_EXT(bl, len) \
+ (spi_bdev_eraseblocks_raw(&spi_bdev, MICROPY_HW_SPIFLASH_BLOCKMAP_EXT(bl), (len)))
+
+// Board control config
+#define MICROPY_BOARD_STARTUP board_init
+
+/******************************************************************************/
+// Bootloader configuration
+
+// Configure CPU frequency to 96MHz, to make updates from SPI flash faster
+#define MBOOT_CLK_PLLM (MICROPY_HW_CLK_VALUE / 1000000)
+#define MBOOT_CLK_PLLN (192)
+#define MBOOT_CLK_PLLP (RCC_PLLP_DIV2)
+#define MBOOT_CLK_PLLQ (4)
+#define MBOOT_CLK_AHB_DIV (RCC_SYSCLK_DIV1)
+#define MBOOT_CLK_APB1_DIV (RCC_HCLK_DIV4)
+#define MBOOT_CLK_APB2_DIV (RCC_HCLK_DIV2)
+#define MBOOT_FLASH_LATENCY FLASH_LATENCY_3
+
+#define MBOOT_FSLOAD (1)
+#define MBOOT_VFS_FAT (1)
+#define MBOOT_LEAVE_BOOTLOADER_VIA_RESET (0)
+
+#define MBOOT_SPIFLASH_ADDR (0x80000000)
+#define MBOOT_SPIFLASH_BYTE_SIZE (4 * 1024 * 1024)
+#define MBOOT_SPIFLASH_LAYOUT "/0x80000000/1024*4Kg"
+#define MBOOT_SPIFLASH_ERASE_BLOCKS_PER_PAGE (1)
+#define MBOOT_SPIFLASH_SPIFLASH (&board_mboot_spiflash)
+#define MBOOT_SPIFLASH_CONFIG (&board_mboot_spiflash_config)
+
+#define MBOOT_LED1 0
+#define MBOOT_LED2 1
+#define MBOOT_LED3 2
+#define MBOOT_BOARD_LED_INIT board_mboot_led_init
+#define MBOOT_BOARD_LED_STATE board_mboot_led_state
+
+#define MBOOT_BOARD_EARLY_INIT(initial_r0) board_init()
+#define MBOOT_BOARD_CLEANUP board_mboot_cleanup
+#define MBOOT_BOARD_GET_RESET_MODE board_mboot_get_reset_mode
+#define MBOOT_BOARD_STATE_CHANGE board_mboot_state_change
+
+/******************************************************************************/
+// Function declarations
+
+extern const struct _mp_spiflash_config_t spiflash_config;
+extern struct _spi_bdev_t spi_bdev;
+extern const struct _mp_spiflash_config_t board_mboot_spiflash_config;
+extern struct _mp_spiflash_t board_mboot_spiflash;
+
+void board_init(void);
+void board_mboot_cleanup(int reset_mode);
+void board_mboot_led_init(void);
+void board_mboot_led_state(int led, int state);
+int board_mboot_get_reset_mode(uint32_t *initial_r0);
+void board_mboot_state_change(int state, uint32_t arg);
+void *btstack_chipset_cc256x_instance(void);
diff --git a/ports/stm32/boards/LEGO_HUB_NO7/mpconfigboard.mk b/ports/stm32/boards/LEGO_HUB_NO7/mpconfigboard.mk
new file mode 100644
index 000000000000..c06f9a26ad45
--- /dev/null
+++ b/ports/stm32/boards/LEGO_HUB_NO7/mpconfigboard.mk
@@ -0,0 +1,50 @@
+MCU_SERIES = f4
+CMSIS_MCU = STM32F413xx
+AF_FILE = boards/stm32f413_af.csv
+LD_FILES = boards/LEGO_HUB_NO6/stm32f413xg.ld boards/common_bl.ld
+TEXT0_ADDR = 0x08010000
+
+BOOTLOADER_DFU_USB_VID ?= 0x0694
+BOOTLOADER_DFU_USB_PID ?= 0x000C
+
+# MicroPython settings
+MICROPY_PY_BLUETOOTH ?= 1
+MICROPY_BLUETOOTH_NIMBLE ?= 0
+MICROPY_BLUETOOTH_BTSTACK ?= 1
+MICROPY_VFS_LFS2 ?= 1
+
+# Board specific frozen modules
+FROZEN_MANIFEST ?= $(BOARD_DIR)/manifest.py
+
+SRC_HAL += $(STM32LIB_HAL_BASE)/Src/stm32f4xx_hal_fmpi2c.c
+
+ifneq ($(BUILDING_MBOOT),1)
+LIB_SRC_C += lib/btstack/chipset/cc256x/btstack_chipset_cc256x.c
+endif
+
+# Bootloader settings
+MBOOT_TEXT0_ADDR = 0x08008000
+MBOOT_LD_FILES = ../boards/LEGO_HUB_NO6/mboot_memory.ld stm32_sections.ld
+
+# Backup/restore original Hub firmware
+
+HUB_FIRMWARE = lego_hub_firmware.dfu
+HUB_FIRMWARE_ADDR = $(MBOOT_TEXT0_ADDR)
+HUB_FIRMWARE_SIZE = 0xf8000
+
+backup-hub-firmware:
+ $(Q)$(DFU_UTIL) -a 0 \
+ -d $(BOOTLOADER_DFU_USB_VID):$(BOOTLOADER_DFU_USB_PID) \
+ -U $(HUB_FIRMWARE).bin \
+ -s $(HUB_FIRMWARE_ADDR):$(HUB_FIRMWARE_SIZE)
+ $(Q)$(PYTHON) $(DFU) \
+ -b $(HUB_FIRMWARE_ADDR):$(HUB_FIRMWARE).bin \
+ -D $(BOOTLOADER_DFU_USB_VID):$(BOOTLOADER_DFU_USB_PID) \
+ $(HUB_FIRMWARE)
+ $(Q)$(RM) $(HUB_FIRMWARE).bin
+ $(ECHO) "Backup created in $(HUB_FIRMWARE)"
+
+restore-hub-firmware:
+ $(Q)$(DFU_UTIL) -a 0 \
+ -d $(BOOTLOADER_DFU_USB_VID):$(BOOTLOADER_DFU_USB_PID) \
+ -D $(HUB_FIRMWARE)
diff --git a/ports/stm32/boards/LEGO_HUB_NO7/pins.csv b/ports/stm32/boards/LEGO_HUB_NO7/pins.csv
new file mode 100644
index 000000000000..dd19518b78a9
--- /dev/null
+++ b/ports/stm32/boards/LEGO_HUB_NO7/pins.csv
@@ -0,0 +1,114 @@
+BT_CTS,PA0
+BT_RTS,PA1
+BT_TX,PA2
+BT_RX,PA3
+,PA4
+,PA5
+BAT_VMON_ADC,PA6
+BAT_IMON_ADC,PA7
+LSM6_SCL,PA8
+USB_VBUS,PA9
+CHGMODE,PA10
+USB_DM,PA11
+USB_DP,PA12
+,PA13
+,PA14
+,PA15
+BAT_NTC,PB0
+BAT_PWR_EN,PB1
+BUTTON,PB2
+BT_SLOWCLK,PB3
+PORTB_M1,PB4
+PORTB_M2,PB5
+PORTA_M1,PB6
+PORTA_M2,PB7
+PORTB_EN,PB8
+PORTA_EN,PB9
+FLASH_SCK,PB10
+,PB11
+FLASH_NSS,PB12
+LED_EN,PB13
+LED_SDA,PB14
+LED_SCL,PB15
+,PC0
+,PC1
+FLASH_MISO,PC2
+FLASH_MOSI,PC3
+CHG_IMON_ADC,PC4
+,PC5
+CHGOK,PC6
+PORT_3V3_EN,PC7
+BT_ENABLE,PC8
+LSM6_SDA,PC9
+PORTB_TX,PC10
+PORTB_RX,PC11
+PORTA_TX,PC12
+LSM6_INT1,PC13
+,PC14
+,PC15
+,PD0
+,PD1
+PORTA_RX,PD2
+,PD3
+,PD4
+,PD5
+,PD6
+,PD7
+,PD8
+,PD9
+,PD10
+,PD11
+,PD12
+,PD13
+,PD14
+,PD15
+,PE0
+,PE1
+,PE2
+,PE3
+,PE4
+,PE5
+,PE6
+,PE7
+,PE8
+,PE9
+,PE10
+,PE11
+,PE12
+,PE13
+,PE14
+,PE15
+,PF0
+,PF1
+,PF2
+,PF3
+,PF4
+,PF5
+,PF6
+,PF7
+,PF8
+,PF9
+,PF10
+,PF11
+,PF12
+,PF13
+,PF14
+,PF15
+,PG0
+,PG1
+,PG2
+,PG3
+,PG4
+,PG5
+,PG6
+,PG7
+,PG8
+,PG9
+,PG10
+,PG11
+,PG12
+,PG13
+,PG14
+,PG15
+,PH0
+,PH1
diff --git a/ports/stm32/boards/LEGO_HUB_NO7/stm32f4xx_hal_conf.h b/ports/stm32/boards/LEGO_HUB_NO7/stm32f4xx_hal_conf.h
new file mode 100644
index 000000000000..bd70912748a5
--- /dev/null
+++ b/ports/stm32/boards/LEGO_HUB_NO7/stm32f4xx_hal_conf.h
@@ -0,0 +1,23 @@
+/* This file is part of the MicroPython project, http://micropython.org/
+ * The MIT License (MIT)
+ * Copyright (c) 2019 Damien P. George
+ */
+#ifndef MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H
+#define MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H
+
+#include "boards/stm32f4xx_hal_conf_base.h"
+
+#include "stm32f4xx_hal_fmpi2c.h"
+
+#define HAL_FMPI2C_MODULE_ENABLED
+
+// Oscillator values in Hz
+#define HSE_VALUE (16000000)
+#define LSE_VALUE (32768)
+#define EXTERNAL_CLOCK_VALUE (12288000)
+
+// Oscillator timeouts in ms
+#define HSE_STARTUP_TIMEOUT (100)
+#define LSE_STARTUP_TIMEOUT (5000)
+
+#endif // MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H
diff --git a/ports/stm32/boards/NUCLEO_F091RC/mpconfigboard.h b/ports/stm32/boards/NUCLEO_F091RC/mpconfigboard.h
index 38fcb2f28e33..d44bfb0bb663 100644
--- a/ports/stm32/boards/NUCLEO_F091RC/mpconfigboard.h
+++ b/ports/stm32/boards/NUCLEO_F091RC/mpconfigboard.h
@@ -4,17 +4,20 @@
#define MICROPY_EMIT_THUMB (0)
#define MICROPY_EMIT_INLINE_THUMB (0)
#define MICROPY_OPT_COMPUTED_GOTO (0)
-#define MICROPY_PY_IO_FILEIO (0)
+#define MICROPY_PY_BUILTINS_COMPLEX (0)
#define MICROPY_PY_USOCKET (0)
#define MICROPY_PY_NETWORK (0)
#define MICROPY_PY_STM (0)
#define MICROPY_PY_PYB_LEGACY (0)
+#define MICROPY_PY_UHEAPQ (0)
+#define MICROPY_PY_UTIMEQ (0)
+#define MICROPY_PY_FRAMEBUF (0)
-#define MICROPY_HW_ENABLE_INTERNAL_FLASH_STORAGE (0)
#define MICROPY_HW_ENABLE_RTC (1)
#define MICROPY_HW_ENABLE_ADC (1)
#define MICROPY_HW_ENABLE_DAC (1)
#define MICROPY_HW_HAS_SWITCH (1)
+#define MICROPY_HW_HAS_FLASH (1)
// For system clock, enable one source:
// #define MICROPY_HW_CLK_USE_HSI (1) // internal 8MHz -> PLL = 48MHz.
diff --git a/ports/stm32/boards/NUCLEO_F091RC/mpconfigboard.mk b/ports/stm32/boards/NUCLEO_F091RC/mpconfigboard.mk
index 984fe2f90054..bb7142d1b3e2 100644
--- a/ports/stm32/boards/NUCLEO_F091RC/mpconfigboard.mk
+++ b/ports/stm32/boards/NUCLEO_F091RC/mpconfigboard.mk
@@ -5,6 +5,10 @@ LD_FILES = boards/stm32f091xc.ld boards/common_basic.ld
# MicroPython settings
MICROPY_VFS_FAT = 0
+MICROPY_VFS_LFS1 ?= 1
# Don't include default frozen modules because MCU is tight on flash space
FROZEN_MANIFEST ?=
+
+# LTO reduces final binary size, may be slower to build depending on gcc version and hardware
+LTO ?= 1
diff --git a/ports/stm32/boards/NUCLEO_F429ZI/manifest.py b/ports/stm32/boards/NUCLEO_F429ZI/manifest.py
new file mode 100644
index 000000000000..ebfecd4844ad
--- /dev/null
+++ b/ports/stm32/boards/NUCLEO_F429ZI/manifest.py
@@ -0,0 +1,2 @@
+include("$(PORT_DIR)/boards/manifest.py")
+require("bundle-networking")
diff --git a/ports/stm32/boards/NUCLEO_F429ZI/mpconfigboard.h b/ports/stm32/boards/NUCLEO_F429ZI/mpconfigboard.h
index 76f075546c45..dab3d442bb91 100644
--- a/ports/stm32/boards/NUCLEO_F429ZI/mpconfigboard.h
+++ b/ports/stm32/boards/NUCLEO_F429ZI/mpconfigboard.h
@@ -40,6 +40,12 @@
#define MICROPY_HW_UART_REPL_BAUD 115200
// I2C buses
+#define MICROPY_HW_I2C1_SCL (pin_B8) // Pin 2 on CN7
+#define MICROPY_HW_I2C1_SDA (pin_B9) // Pin 4 on CN7
+
+#define MICROPY_HW_I2C2_SCL (pin_B10) // Pin 32 on CN10
+#define MICROPY_HW_I2C2_SDA (pin_B11) // Pin 34 on CN10
+
#define MICROPY_HW_I2C3_SCL (pin_A8)
#define MICROPY_HW_I2C3_SDA (pin_C9)
diff --git a/ports/stm32/boards/NUCLEO_F429ZI/mpconfigboard.mk b/ports/stm32/boards/NUCLEO_F429ZI/mpconfigboard.mk
index 47b4432893c8..9e82be1dc735 100644
--- a/ports/stm32/boards/NUCLEO_F429ZI/mpconfigboard.mk
+++ b/ports/stm32/boards/NUCLEO_F429ZI/mpconfigboard.mk
@@ -9,3 +9,5 @@ TEXT1_ADDR = 0x08020000
MICROPY_PY_LWIP = 1
MICROPY_PY_USSL = 1
MICROPY_SSL_MBEDTLS = 1
+
+FROZEN_MANIFEST = $(BOARD_DIR)/manifest.py
diff --git a/ports/stm32/boards/NUCLEO_F439ZI/manifest.py b/ports/stm32/boards/NUCLEO_F439ZI/manifest.py
new file mode 100644
index 000000000000..ebfecd4844ad
--- /dev/null
+++ b/ports/stm32/boards/NUCLEO_F439ZI/manifest.py
@@ -0,0 +1,2 @@
+include("$(PORT_DIR)/boards/manifest.py")
+require("bundle-networking")
diff --git a/ports/stm32/boards/NUCLEO_F439ZI/mpconfigboard.mk b/ports/stm32/boards/NUCLEO_F439ZI/mpconfigboard.mk
index 52702b5112c8..69b0f80a2d2f 100644
--- a/ports/stm32/boards/NUCLEO_F439ZI/mpconfigboard.mk
+++ b/ports/stm32/boards/NUCLEO_F439ZI/mpconfigboard.mk
@@ -9,3 +9,5 @@ TEXT1_ADDR = 0x08020000
MICROPY_PY_LWIP = 1
MICROPY_PY_USSL = 1
MICROPY_SSL_MBEDTLS = 1
+
+FROZEN_MANIFEST = $(BOARD_DIR)/manifest.py
diff --git a/ports/stm32/boards/NUCLEO_F446RE/mpconfigboard.mk b/ports/stm32/boards/NUCLEO_F446RE/mpconfigboard.mk
index 64a80e992bce..3a922acebfbd 100644
--- a/ports/stm32/boards/NUCLEO_F446RE/mpconfigboard.mk
+++ b/ports/stm32/boards/NUCLEO_F446RE/mpconfigboard.mk
@@ -1,6 +1,6 @@
MCU_SERIES = f4
CMSIS_MCU = STM32F446xx
-AF_FILE = boards/stm32f429_af.csv
+AF_FILE = boards/stm32f446_af.csv
LD_FILES = boards/stm32f411.ld boards/common_ifs.ld
TEXT0_ADDR = 0x08000000
TEXT1_ADDR = 0x08020000
diff --git a/ports/stm32/boards/NUCLEO_F746ZG/manifest.py b/ports/stm32/boards/NUCLEO_F746ZG/manifest.py
new file mode 100644
index 000000000000..ebfecd4844ad
--- /dev/null
+++ b/ports/stm32/boards/NUCLEO_F746ZG/manifest.py
@@ -0,0 +1,2 @@
+include("$(PORT_DIR)/boards/manifest.py")
+require("bundle-networking")
diff --git a/ports/stm32/boards/NUCLEO_F746ZG/mpconfigboard.mk b/ports/stm32/boards/NUCLEO_F746ZG/mpconfigboard.mk
index 8b54dc84e113..9506b6759555 100644
--- a/ports/stm32/boards/NUCLEO_F746ZG/mpconfigboard.mk
+++ b/ports/stm32/boards/NUCLEO_F746ZG/mpconfigboard.mk
@@ -9,3 +9,5 @@ TEXT1_ADDR = 0x08020000
MICROPY_PY_LWIP = 1
MICROPY_PY_USSL = 1
MICROPY_SSL_MBEDTLS = 1
+
+FROZEN_MANIFEST = $(BOARD_DIR)/manifest.py
diff --git a/ports/stm32/boards/NUCLEO_F756ZG/board.json b/ports/stm32/boards/NUCLEO_F756ZG/board.json
new file mode 100644
index 000000000000..416c0b9154e1
--- /dev/null
+++ b/ports/stm32/boards/NUCLEO_F756ZG/board.json
@@ -0,0 +1,15 @@
+{
+ "deploy": [
+ "../deploy.md"
+ ],
+ "docs": "",
+ "features": [],
+ "images": [
+ "nucleo_f756zg.jpg"
+ ],
+ "mcu": "stm32f7",
+ "product": "Nucleo F756ZG",
+ "thumbnail": "",
+ "url": "",
+ "vendor": "ST Microelectronics"
+}
diff --git a/ports/stm32/boards/NUCLEO_F756ZG/manifest.py b/ports/stm32/boards/NUCLEO_F756ZG/manifest.py
new file mode 100644
index 000000000000..ebfecd4844ad
--- /dev/null
+++ b/ports/stm32/boards/NUCLEO_F756ZG/manifest.py
@@ -0,0 +1,2 @@
+include("$(PORT_DIR)/boards/manifest.py")
+require("bundle-networking")
diff --git a/ports/stm32/boards/NUCLEO_F756ZG/mpconfigboard.h b/ports/stm32/boards/NUCLEO_F756ZG/mpconfigboard.h
new file mode 100644
index 000000000000..fd0d328033b5
--- /dev/null
+++ b/ports/stm32/boards/NUCLEO_F756ZG/mpconfigboard.h
@@ -0,0 +1,88 @@
+// This board is only confirmed to operate using DFU mode and openocd.
+// DFU mode can be accessed by setting BOOT0 (see schematics)
+// To use openocd run "OPENOCD_CONFIG=boards/openocd_stm32f7.cfg" in
+// the make command.
+
+#define MICROPY_HW_BOARD_NAME "NUCLEO-F756ZG"
+#define MICROPY_HW_MCU_NAME "STM32F756"
+
+#define MICROPY_HW_HAS_SWITCH (1)
+#define MICROPY_HW_HAS_FLASH (1)
+#define MICROPY_HW_ENABLE_RNG (1)
+#define MICROPY_HW_ENABLE_RTC (1)
+#define MICROPY_HW_ENABLE_DAC (1)
+#define MICROPY_HW_ENABLE_USB (1)
+
+// HSE is 8MHz
+// VCOClock = HSE * PLLN / PLLM = 8 MHz * 216 / 4 = 432 MHz
+// SYSCLK = VCOClock / PLLP = 432 MHz / 2 = 216 MHz
+// USB/SDMMC/RNG Clock = VCOClock / PLLQ = 432 MHz / 9 = 48 MHz
+#define MICROPY_HW_CLK_PLLM (4)
+#define MICROPY_HW_CLK_PLLN (216)
+#define MICROPY_HW_CLK_PLLP (RCC_PLLP_DIV2)
+#define MICROPY_HW_CLK_PLLQ (9)
+
+// From the reference manual, for 2.7V to 3.6V
+// 151-180 MHz => 5 wait states
+// 181-210 MHz => 6 wait states
+// 211-216 MHz => 7 wait states
+#define MICROPY_HW_FLASH_LATENCY FLASH_LATENCY_7 // 210-216 MHz needs 7 wait states
+
+// UART config
+#define MICROPY_HW_UART2_TX (pin_D5)
+#define MICROPY_HW_UART2_RX (pin_D6)
+#define MICROPY_HW_UART2_RTS (pin_D4)
+#define MICROPY_HW_UART2_CTS (pin_D3)
+#define MICROPY_HW_UART3_TX (pin_D8)
+#define MICROPY_HW_UART3_RX (pin_D9)
+#define MICROPY_HW_UART6_TX (pin_G14)
+#define MICROPY_HW_UART6_RX (pin_G9)
+#define MICROPY_HW_UART_REPL PYB_UART_3
+#define MICROPY_HW_UART_REPL_BAUD 115200
+
+// I2C buses
+#define MICROPY_HW_I2C1_SCL (pin_B8)
+#define MICROPY_HW_I2C1_SDA (pin_B9)
+#define MICROPY_HW_I2C3_SCL (pin_H7)
+#define MICROPY_HW_I2C3_SDA (pin_H8)
+
+// SPI buses
+#define MICROPY_HW_SPI3_NSS (pin_A4)
+#define MICROPY_HW_SPI3_SCK (pin_B3)
+#define MICROPY_HW_SPI3_MISO (pin_B4)
+#define MICROPY_HW_SPI3_MOSI (pin_B5)
+
+// CAN buses
+#define MICROPY_HW_CAN1_TX (pin_B9)
+#define MICROPY_HW_CAN1_RX (pin_B8)
+#define MICROPY_HW_CAN2_TX (pin_B13)
+#define MICROPY_HW_CAN2_RX (pin_B12)
+
+// USRSW is pulled low. Pressing the button makes the input go high.
+#define MICROPY_HW_USRSW_PIN (pin_C13)
+#define MICROPY_HW_USRSW_PULL (GPIO_NOPULL)
+#define MICROPY_HW_USRSW_EXTI_MODE (GPIO_MODE_IT_RISING)
+#define MICROPY_HW_USRSW_PRESSED (1)
+
+// LEDs
+#define MICROPY_HW_LED1 (pin_B0) // green
+#define MICROPY_HW_LED2 (pin_B7) // blue
+#define MICROPY_HW_LED3 (pin_B14) // red
+#define MICROPY_HW_LED_ON(pin) (mp_hal_pin_high(pin))
+#define MICROPY_HW_LED_OFF(pin) (mp_hal_pin_low(pin))
+
+// USB config (CN13 - USB OTG FS)
+#define MICROPY_HW_USB_FS (1)
+#define MICROPY_HW_USB_VBUS_DETECT_PIN (pin_A9)
+#define MICROPY_HW_USB_OTG_ID_PIN (pin_A10)
+
+// Ethernet via RMII
+#define MICROPY_HW_ETH_MDC (pin_C1)
+#define MICROPY_HW_ETH_MDIO (pin_A2)
+#define MICROPY_HW_ETH_RMII_REF_CLK (pin_A1)
+#define MICROPY_HW_ETH_RMII_CRS_DV (pin_A7)
+#define MICROPY_HW_ETH_RMII_RXD0 (pin_C4)
+#define MICROPY_HW_ETH_RMII_RXD1 (pin_C5)
+#define MICROPY_HW_ETH_RMII_TX_EN (pin_G11)
+#define MICROPY_HW_ETH_RMII_TXD0 (pin_G13)
+#define MICROPY_HW_ETH_RMII_TXD1 (pin_B13)
diff --git a/ports/stm32/boards/NUCLEO_F756ZG/mpconfigboard.mk b/ports/stm32/boards/NUCLEO_F756ZG/mpconfigboard.mk
new file mode 100644
index 000000000000..90fc242f9ac6
--- /dev/null
+++ b/ports/stm32/boards/NUCLEO_F756ZG/mpconfigboard.mk
@@ -0,0 +1,13 @@
+MCU_SERIES = f7
+CMSIS_MCU = STM32F756xx
+AF_FILE = boards/stm32f746_af.csv
+LD_FILES = boards/stm32f746.ld boards/common_ifs.ld
+TEXT0_ADDR = 0x08000000
+TEXT1_ADDR = 0x08020000
+
+# MicroPython settings
+MICROPY_PY_LWIP = 1
+MICROPY_PY_USSL = 1
+MICROPY_SSL_MBEDTLS = 1
+
+FROZEN_MANIFEST = $(BOARD_DIR)/manifest.py
diff --git a/ports/stm32/boards/NUCLEO_F756ZG/pins.csv b/ports/stm32/boards/NUCLEO_F756ZG/pins.csv
new file mode 100644
index 000000000000..c129f7417b59
--- /dev/null
+++ b/ports/stm32/boards/NUCLEO_F756ZG/pins.csv
@@ -0,0 +1,77 @@
+A0,PA3
+A1,PC0
+A2,PC3
+A3,PF3
+A4,PF5
+A5,PF10
+D0,PG9
+D1,PG14
+D2,PF15
+D3,PE13
+D4,PF14
+D5,PE11
+D6,PE9
+D7,PF13
+D8,PF12
+D9,PD15
+D10,PD14
+D11,PA7
+D12,PA6
+D13,PA5
+D14,PB9
+D15,PB8
+D16,PC6
+D17,PB15
+D18,PB13
+D19,PB12
+D20,PA15
+D21,PC7
+D22,PB5
+D23,PB3
+D24,PA4
+D25,PB4
+LED1,PB0
+LED2,PB7
+LED3,PB14
+SW,PC13
+TP1,PH2
+TP2,PI8
+TP3,PH15
+AUDIO_INT,PD6
+AUDIO_SDA,PH8
+AUDIO_SCL,PH7
+EXT_SDA,PB9
+EXT_SCL,PB8
+EXT_RST,PG3
+SD_SW,PC13
+LCD_BL_CTRL,PK3
+LCD_INT,PI13
+LCD_SDA,PH8
+LCD_SCL,PH7
+OTG_FS_POWER,PD5
+OTG_FS_OVER_CURRENT,PD4
+OTG_HS_OVER_CURRENT,PE3
+USB_VBUS,PA9
+USB_ID,PA10
+USB_DM,PA11
+USB_DP,PA12
+VCP_TX,PD8
+VCP_RX,PD9
+UART2_TX,PD5
+UART2_RX,PD6
+UART2_RTS,PD4
+UART2_CTS,PD3
+UART6_TX,PG14
+UART6_RX,PG9
+SPI_B_NSS,PA4
+SPI_B_SCK,PB3
+SPI_B_MOSI,PB5
+ETH_MDC,PC1
+ETH_MDIO,PA2
+ETH_RMII_REF_CLK,PA1
+ETH_RMII_CRS_DV,PA7
+ETH_RMII_RXD0,PC4
+ETH_RMII_RXD1,PC5
+ETH_RMII_TX_EN,PG11
+ETH_RMII_TXD0,PG13
+ETH_RMII_TXD1,PB13
diff --git a/ports/stm32/boards/NUCLEO_F756ZG/stm32f7xx_hal_conf.h b/ports/stm32/boards/NUCLEO_F756ZG/stm32f7xx_hal_conf.h
new file mode 100644
index 000000000000..e241921ddd25
--- /dev/null
+++ b/ports/stm32/boards/NUCLEO_F756ZG/stm32f7xx_hal_conf.h
@@ -0,0 +1,19 @@
+/* This file is part of the MicroPython project, http://micropython.org/
+ * The MIT License (MIT)
+ * Copyright (c) 2019 Damien P. George
+ */
+#ifndef MICROPY_INCLUDED_STM32F7XX_HAL_CONF_H
+#define MICROPY_INCLUDED_STM32F7XX_HAL_CONF_H
+
+#include "boards/stm32f7xx_hal_conf_base.h"
+
+// Oscillator values in Hz
+#define HSE_VALUE (8000000)
+#define LSE_VALUE (32768)
+#define EXTERNAL_CLOCK_VALUE (12288000)
+
+// Oscillator timeouts in ms
+#define HSE_STARTUP_TIMEOUT (5000)
+#define LSE_STARTUP_TIMEOUT (5000)
+
+#endif // MICROPY_INCLUDED_STM32F7XX_HAL_CONF_H
diff --git a/ports/stm32/boards/NUCLEO_F767ZI/manifest.py b/ports/stm32/boards/NUCLEO_F767ZI/manifest.py
new file mode 100644
index 000000000000..ebfecd4844ad
--- /dev/null
+++ b/ports/stm32/boards/NUCLEO_F767ZI/manifest.py
@@ -0,0 +1,2 @@
+include("$(PORT_DIR)/boards/manifest.py")
+require("bundle-networking")
diff --git a/ports/stm32/boards/NUCLEO_F767ZI/mpconfigboard.mk b/ports/stm32/boards/NUCLEO_F767ZI/mpconfigboard.mk
index 0fdc1a6dcd17..6ef9d42f9d37 100644
--- a/ports/stm32/boards/NUCLEO_F767ZI/mpconfigboard.mk
+++ b/ports/stm32/boards/NUCLEO_F767ZI/mpconfigboard.mk
@@ -10,3 +10,5 @@ TEXT1_ADDR = 0x08020000
MICROPY_PY_LWIP = 1
MICROPY_PY_USSL = 1
MICROPY_SSL_MBEDTLS = 1
+
+FROZEN_MANIFEST = $(BOARD_DIR)/manifest.py
diff --git a/ports/stm32/boards/NUCLEO_G0B1RE/mpconfigboard.h b/ports/stm32/boards/NUCLEO_G0B1RE/mpconfigboard.h
index 6ba3e0115c9d..092ee177925e 100644
--- a/ports/stm32/boards/NUCLEO_G0B1RE/mpconfigboard.h
+++ b/ports/stm32/boards/NUCLEO_G0B1RE/mpconfigboard.h
@@ -6,6 +6,7 @@
#define MICROPY_HW_ENABLE_RNG (0)
#define MICROPY_HW_ENABLE_RTC (1)
#define MICROPY_HW_ENABLE_DAC (0)
+#define MICROPY_HW_ENABLE_USB (0) // can be enabled if USB cable connected to PA11/PA12
#define MICROPY_PY_PYB_LEGACY (0)
#define MICROPY_HW_ENABLE_INTERNAL_FLASH_STORAGE (1)
@@ -87,3 +88,9 @@
#define MICROPY_HW_LED1 (pin_A5) // Green LD2 LED on Nucleo
#define MICROPY_HW_LED_ON(pin) (mp_hal_pin_high(pin))
#define MICROPY_HW_LED_OFF(pin) (mp_hal_pin_low(pin))
+
+// USB config
+#define MICROPY_HW_USB_FS (1)
+#define MICROPY_HW_USB_MAIN_DEV (USB_PHY_FS_ID)
+#define MICROPY_HW_USB_MSC (0)
+#define MICROPY_HW_USB_HID (0)
diff --git a/ports/stm32/boards/NUCLEO_G0B1RE/mpconfigboard.mk b/ports/stm32/boards/NUCLEO_G0B1RE/mpconfigboard.mk
index 371e10d154cb..abc9b43ef036 100644
--- a/ports/stm32/boards/NUCLEO_G0B1RE/mpconfigboard.mk
+++ b/ports/stm32/boards/NUCLEO_G0B1RE/mpconfigboard.mk
@@ -1,4 +1,13 @@
MCU_SERIES = g0
CMSIS_MCU = STM32G0B1xx
AF_FILE = boards/stm32g0b1_af.csv
+
+ifeq ($(USE_MBOOT),1)
+LD_FILES = boards/stm32g0b1xe.ld boards/common_bl.ld
+TEXT0_ADDR = 0x08008000
+else
LD_FILES = boards/stm32g0b1xe.ld boards/common_basic.ld
+endif
+
+# LTO reduces final binary size, may be slower to build depending on gcc version and hardware
+LTO ?= 1
diff --git a/ports/stm32/boards/NUCLEO_H723ZG/board.json b/ports/stm32/boards/NUCLEO_H723ZG/board.json
new file mode 100644
index 000000000000..bf7dc0e2fb29
--- /dev/null
+++ b/ports/stm32/boards/NUCLEO_H723ZG/board.json
@@ -0,0 +1,15 @@
+{
+ "deploy": [
+ "../deploy.md"
+ ],
+ "docs": "",
+ "features": [],
+ "images": [
+ "nucleo_h723zg.jpg"
+ ],
+ "mcu": "stm32h7",
+ "product": "Nucleo H723ZG",
+ "thumbnail": "",
+ "url": "",
+ "vendor": "ST Microelectronics"
+}
diff --git a/ports/stm32/boards/NUCLEO_H723ZG/board_init.c b/ports/stm32/boards/NUCLEO_H723ZG/board_init.c
new file mode 100644
index 000000000000..96a2896e0858
--- /dev/null
+++ b/ports/stm32/boards/NUCLEO_H723ZG/board_init.c
@@ -0,0 +1,7 @@
+#include "py/mphal.h"
+
+void NUCLEO_H723ZG_board_early_init(void) {
+ // Turn off the USB switch.
+ mp_hal_pin_output(pyb_pin_OTG_FS_POWER);
+ mp_hal_pin_low(pyb_pin_OTG_FS_POWER);
+}
diff --git a/ports/stm32/boards/NUCLEO_H723ZG/manifest.py b/ports/stm32/boards/NUCLEO_H723ZG/manifest.py
new file mode 100644
index 000000000000..ebfecd4844ad
--- /dev/null
+++ b/ports/stm32/boards/NUCLEO_H723ZG/manifest.py
@@ -0,0 +1,2 @@
+include("$(PORT_DIR)/boards/manifest.py")
+require("bundle-networking")
diff --git a/ports/stm32/boards/NUCLEO_H723ZG/mpconfigboard.h b/ports/stm32/boards/NUCLEO_H723ZG/mpconfigboard.h
new file mode 100644
index 000000000000..095b7f4b1556
--- /dev/null
+++ b/ports/stm32/boards/NUCLEO_H723ZG/mpconfigboard.h
@@ -0,0 +1,116 @@
+#define MICROPY_HW_BOARD_NAME "NUCLEO_H723ZG"
+#define MICROPY_HW_MCU_NAME "STM32H723ZGT6"
+
+#define MICROPY_HW_ENABLE_RTC (1)
+#define MICROPY_HW_ENABLE_RNG (0) // RNG needs proper configuration
+#define MICROPY_HW_ENABLE_ADC (1)
+#define MICROPY_HW_ENABLE_DAC (1)
+#define MICROPY_HW_ENABLE_USB (1)
+#define MICROPY_HW_ENABLE_SDCARD (1)
+#define MICROPY_HW_HAS_SWITCH (1)
+#define MICROPY_HW_HAS_FLASH (1)
+
+#define MICROPY_BOARD_EARLY_INIT NUCLEO_H723ZG_board_early_init
+
+// There is no external HS crystal, instead it comes from ST-LINK MCO output which is 8MHz.
+// The following gives a 550MHz CPU speed.
+#define MICROPY_HW_CLK_USE_BYPASS (1)
+#define MICROPY_HW_CLK_PLLM (4)
+#define MICROPY_HW_CLK_PLLN (275)
+#define MICROPY_HW_CLK_PLLP (1)
+#define MICROPY_HW_CLK_PLLQ (4)
+#define MICROPY_HW_CLK_PLLR (2)
+#define MICROPY_HW_CLK_PLLVCI (RCC_PLL1VCIRANGE_1)
+#define MICROPY_HW_CLK_PLLVCO (RCC_PLL1VCOWIDE)
+#define MICROPY_HW_CLK_PLLFRAC (0)
+
+// The USB clock is set using PLL3
+#define MICROPY_HW_CLK_PLL3M (4)
+#define MICROPY_HW_CLK_PLL3N (120)
+#define MICROPY_HW_CLK_PLL3P (2)
+#define MICROPY_HW_CLK_PLL3Q (5)
+#define MICROPY_HW_CLK_PLL3R (2)
+#define MICROPY_HW_CLK_PLL3VCI (RCC_PLL3VCIRANGE_1)
+#define MICROPY_HW_CLK_PLL3VCO (RCC_PLL3VCOWIDE)
+#define MICROPY_HW_CLK_PLL3FRAC (0)
+
+// 4 wait states
+#define MICROPY_HW_FLASH_LATENCY FLASH_LATENCY_4
+
+// The board has an external 32kHz crystal attached
+#define MICROPY_HW_RTC_USE_LSE (1)
+
+// UART config
+#define MICROPY_HW_UART2_TX (pin_D5)
+#define MICROPY_HW_UART2_RX (pin_D6)
+#define MICROPY_HW_UART2_RTS (pin_D4)
+#define MICROPY_HW_UART2_CTS (pin_D3)
+#define MICROPY_HW_UART3_TX (pin_D8)
+#define MICROPY_HW_UART3_RX (pin_D9)
+#define MICROPY_HW_UART5_TX (pin_B6)
+#define MICROPY_HW_UART5_RX (pin_B12)
+#define MICROPY_HW_UART6_TX (pin_C6)
+#define MICROPY_HW_UART6_RX (pin_C7)
+#define MICROPY_HW_UART7_TX (pin_F7)
+#define MICROPY_HW_UART7_RX (pin_F6)
+#define MICROPY_HW_UART8_TX (pin_E1)
+#define MICROPY_HW_UART8_RX (pin_E0)
+
+#define MICROPY_HW_UART_REPL PYB_UART_3
+#define MICROPY_HW_UART_REPL_BAUD 115200
+
+// I2C buses
+#define MICROPY_HW_I2C1_SCL (pin_B8)
+#define MICROPY_HW_I2C1_SDA (pin_B9)
+#define MICROPY_HW_I2C2_SCL (pin_F1)
+#define MICROPY_HW_I2C2_SDA (pin_F0)
+#define MICROPY_HW_I2C4_SCL (pin_F14)
+#define MICROPY_HW_I2C4_SDA (pin_F15)
+
+// SPI buses
+#define MICROPY_HW_SPI3_NSS (pin_A4)
+#define MICROPY_HW_SPI3_SCK (pin_B3)
+#define MICROPY_HW_SPI3_MISO (pin_B4)
+#define MICROPY_HW_SPI3_MOSI (pin_B5)
+
+// USRSW is pulled low. Pressing the button makes the input go high.
+#define MICROPY_HW_USRSW_PIN (pin_C13)
+#define MICROPY_HW_USRSW_PULL (GPIO_NOPULL)
+#define MICROPY_HW_USRSW_EXTI_MODE (GPIO_MODE_IT_RISING)
+#define MICROPY_HW_USRSW_PRESSED (1)
+
+// LEDs
+#define MICROPY_HW_LED1 (pin_B0) // green
+#define MICROPY_HW_LED2 (pin_E1) // yellow
+#define MICROPY_HW_LED3 (pin_B14) // red
+#define MICROPY_HW_LED_ON(pin) (mp_hal_pin_high(pin))
+#define MICROPY_HW_LED_OFF(pin) (mp_hal_pin_low(pin))
+
+// USB config
+#define MICROPY_HW_USB_HS (1)
+#define MICROPY_HW_USB_HS_IN_FS (1)
+#define MICROPY_HW_USB_VBUS_DETECT_PIN (pin_A9)
+#define MICROPY_HW_USB_OTG_ID_PIN (pin_A10)
+
+// FDCAN bus
+#define MICROPY_HW_CAN1_NAME "FDCAN1"
+#define MICROPY_HW_CAN1_TX (pin_D1)
+#define MICROPY_HW_CAN1_RX (pin_D0)
+
+// SD card detect switch
+#define MICROPY_HW_SDCARD_DETECT_PIN (pin_G2)
+#define MICROPY_HW_SDCARD_DETECT_PULL (GPIO_PULLUP)
+#define MICROPY_HW_SDCARD_DETECT_PRESENT (GPIO_PIN_RESET)
+
+// Ethernet via RMII
+#define MICROPY_HW_ETH_MDC (pin_C1)
+#define MICROPY_HW_ETH_MDIO (pin_A2)
+#define MICROPY_HW_ETH_RMII_REF_CLK (pin_A1)
+#define MICROPY_HW_ETH_RMII_CRS_DV (pin_A7)
+#define MICROPY_HW_ETH_RMII_RXD0 (pin_C4)
+#define MICROPY_HW_ETH_RMII_RXD1 (pin_C5)
+#define MICROPY_HW_ETH_RMII_TX_EN (pin_G11)
+#define MICROPY_HW_ETH_RMII_TXD0 (pin_G13)
+#define MICROPY_HW_ETH_RMII_TXD1 (pin_B13)
+
+void NUCLEO_H723ZG_board_early_init(void);
diff --git a/ports/stm32/boards/NUCLEO_H723ZG/mpconfigboard.mk b/ports/stm32/boards/NUCLEO_H723ZG/mpconfigboard.mk
new file mode 100644
index 000000000000..287b51f6d83f
--- /dev/null
+++ b/ports/stm32/boards/NUCLEO_H723ZG/mpconfigboard.mk
@@ -0,0 +1,25 @@
+USE_MBOOT ?= 0
+
+# MCU settings
+MCU_SERIES = h7
+CMSIS_MCU = STM32H723xx
+MICROPY_FLOAT_IMPL = double
+AF_FILE = boards/stm32h723_af.csv
+
+ifeq ($(USE_MBOOT),1)
+# When using Mboot everything goes after the bootloader
+LD_FILES = boards/stm32h723.ld boards/common_bl.ld
+TEXT0_ADDR = 0x08020000
+else
+# When not using Mboot everything goes at the start of flash
+LD_FILES = boards/stm32h723.ld boards/common_basic.ld
+TEXT0_ADDR = 0x08000000
+endif
+
+# MicroPython settings
+MICROPY_PY_LWIP = 1
+MICROPY_PY_USSL = 1
+MICROPY_SSL_MBEDTLS = 1
+MICROPY_VFS_LFS2 = 1
+
+FROZEN_MANIFEST ?= $(BOARD_DIR)/manifest.py
diff --git a/ports/stm32/boards/NUCLEO_H723ZG/pins.csv b/ports/stm32/boards/NUCLEO_H723ZG/pins.csv
new file mode 100644
index 000000000000..450d6e432ae3
--- /dev/null
+++ b/ports/stm32/boards/NUCLEO_H723ZG/pins.csv
@@ -0,0 +1,130 @@
+A0,PA3
+A1,PC0
+A2,PC3
+A3,PB1
+A4,PC2
+A5,PF10
+A6,PF4
+A7,PF5
+A8,PF6
+D0,PB7
+D1,PB6
+D2,PG14
+D3,PE13
+D4,PE14
+D5,PE11
+D6,PE9
+D7,PG12
+D8,PF3
+D9,PD15
+D10,PD14
+D11,PB5
+D12,PA6
+D13,PA7
+D14,PB9
+D15,PB8
+D16,PC6
+D17,PB15
+D18,PB13
+D19,PB12
+D20,PA15
+D21,PC7
+D22,PB5
+D23,PB3
+D24,PA4
+D25,PB4
+D26,PG6
+D27,PB2
+D28,PD13
+D29,PD12
+D30,PD11
+D31,PE2
+D32,PA0
+D33,PB0
+D34,PE0
+D35,PB11
+D36,PB10
+D37,PE15
+D38,PE6
+D39,PE12
+D40,PE10
+D41,PE7
+D42,PE8
+D43,PC8
+D44,PC9
+D45,PC10
+D46,PC11
+D47,PC12
+D48,PD2
+D49,PG2
+D50,PG3
+D51,PD7
+D52,PD6
+D53,PD5
+D54,PD4
+D55,PD3
+D56,PE2
+D57,PE4
+D58,PE5
+D59,PE6
+D60,PE3
+D61,PF8
+D62,PF7
+D63,PF9
+D64,PG1
+D65,PG0
+D66,PD1
+D67,PD0
+D68,PF0
+D69,PF1
+D70,PF2
+D71,PE9
+D72,PB2
+DAC1,PA4
+DAC2,PA5
+LED1,PB0
+LED2,PE1
+LED3,PB14
+SW,PC13
+I2C1_SDA,PB9
+I2C1_SCL,PB8
+I2C2_SDA,PF0
+I2C2_SCL,PF1
+I2C4_SCL,PF14
+I2C4_SDA,PF15
+SD_D0,PC8
+SD_D1,PC9
+SD_D2,PC10
+SD_D3,PC11
+SD_CMD,PD2
+SD_CK,PC12
+SD_SW,PG2
+OTG_FS_POWER,PD10
+OTG_FS_OVER_CURRENT,PG7
+USB_VBUS,PA9
+USB_ID,PA10
+USB_DM,PA11
+USB_DP,PA12
+UART2_TX,PD5
+UART2_RX,PD6
+UART2_RTS,PD4
+UART2_CTS,PD3
+UART3_TX,PD8
+UART3_RX,PD9
+UART5_TX,PB6
+UART5_RX,PB12
+UART6_TX,PC6
+UART6_RX,PC7
+UART7_TX,PF7
+UART7_RX,PF6
+UART8_TX,PE1
+UART8_RX,PE0
+ETH_MDC,PC1
+ETH_MDIO,PA2
+ETH_RMII_REF_CLK,PA1
+ETH_RMII_CRS_DV,PA7
+ETH_RMII_RXD0,PC4
+ETH_RMII_RXD1,PC5
+ETH_RMII_TX_EN,PG11
+ETH_RMII_TXD0,PG13
+ETH_RMII_TXD1,PB13
diff --git a/ports/stm32/boards/NUCLEO_H723ZG/stm32h7xx_hal_conf.h b/ports/stm32/boards/NUCLEO_H723ZG/stm32h7xx_hal_conf.h
new file mode 100644
index 000000000000..45400cdcd734
--- /dev/null
+++ b/ports/stm32/boards/NUCLEO_H723ZG/stm32h7xx_hal_conf.h
@@ -0,0 +1,19 @@
+/* This file is part of the MicroPython project, http://micropython.org/
+ * The MIT License (MIT)
+ * Copyright (c) 2019 Damien P. George
+ */
+#ifndef MICROPY_INCLUDED_STM32H7XX_HAL_CONF_H
+#define MICROPY_INCLUDED_STM32H7XX_HAL_CONF_H
+
+#include "boards/stm32h7xx_hal_conf_base.h"
+
+// Oscillator values in Hz
+#define HSE_VALUE (8000000)
+#define LSE_VALUE (32768)
+#define EXTERNAL_CLOCK_VALUE (12288000)
+
+// Oscillator timeouts in ms
+#define HSE_STARTUP_TIMEOUT (5000)
+#define LSE_STARTUP_TIMEOUT (5000)
+
+#endif // MICROPY_INCLUDED_STM32H7XX_HAL_CONF_H
diff --git a/ports/stm32/boards/NUCLEO_H743ZI/manifest.py b/ports/stm32/boards/NUCLEO_H743ZI/manifest.py
new file mode 100644
index 000000000000..ebfecd4844ad
--- /dev/null
+++ b/ports/stm32/boards/NUCLEO_H743ZI/manifest.py
@@ -0,0 +1,2 @@
+include("$(PORT_DIR)/boards/manifest.py")
+require("bundle-networking")
diff --git a/ports/stm32/boards/NUCLEO_H743ZI/mpconfigboard.mk b/ports/stm32/boards/NUCLEO_H743ZI/mpconfigboard.mk
index 8a16c2f01032..ea95fd00743c 100644
--- a/ports/stm32/boards/NUCLEO_H743ZI/mpconfigboard.mk
+++ b/ports/stm32/boards/NUCLEO_H743ZI/mpconfigboard.mk
@@ -21,3 +21,5 @@ MICROPY_PY_LWIP = 1
MICROPY_PY_USSL = 1
MICROPY_SSL_MBEDTLS = 1
MICROPY_VFS_LFS2 = 1
+
+FROZEN_MANIFEST ?= $(BOARD_DIR)/manifest.py
diff --git a/ports/stm32/boards/NUCLEO_H743ZI2/board.json b/ports/stm32/boards/NUCLEO_H743ZI2/board.json
index 30361e6f1594..65f01de56559 100644
--- a/ports/stm32/boards/NUCLEO_H743ZI2/board.json
+++ b/ports/stm32/boards/NUCLEO_H743ZI2/board.json
@@ -5,7 +5,7 @@
"docs": "",
"features": [],
"images": [],
- "mcu": "stm32",
+ "mcu": "stm32h7",
"product": "Nucleo H743ZI2",
"thumbnail": "",
"url": "",
diff --git a/ports/stm32/boards/NUCLEO_H743ZI2/mpconfigboard.mk b/ports/stm32/boards/NUCLEO_H743ZI2/mpconfigboard.mk
index e49a4d0d6158..50df6ac62943 100644
--- a/ports/stm32/boards/NUCLEO_H743ZI2/mpconfigboard.mk
+++ b/ports/stm32/boards/NUCLEO_H743ZI2/mpconfigboard.mk
@@ -1 +1,3 @@
+FROZEN_MANIFEST ?= boards/NUCLEO_H743ZI/manifest.py
+
include boards/NUCLEO_H743ZI/mpconfigboard.mk
diff --git a/ports/stm32/boards/NUCLEO_L073RZ/mpconfigboard.h b/ports/stm32/boards/NUCLEO_L073RZ/mpconfigboard.h
index 9af925d45196..c8c809eb4899 100644
--- a/ports/stm32/boards/NUCLEO_L073RZ/mpconfigboard.h
+++ b/ports/stm32/boards/NUCLEO_L073RZ/mpconfigboard.h
@@ -11,7 +11,6 @@
#define MICROPY_PY_BUILTINS_COMPLEX (0)
#define MICROPY_PY_GENERATOR_PEND_THROW (0)
#define MICROPY_PY_MATH (0)
-#define MICROPY_PY_IO_FILEIO (0)
#define MICROPY_PY_FRAMEBUF (0)
#define MICROPY_PY_USOCKET (0)
#define MICROPY_PY_NETWORK (0)
diff --git a/ports/stm32/boards/NUCLEO_L073RZ/mpconfigboard.mk b/ports/stm32/boards/NUCLEO_L073RZ/mpconfigboard.mk
index f3673f00601f..72b13a70b215 100644
--- a/ports/stm32/boards/NUCLEO_L073RZ/mpconfigboard.mk
+++ b/ports/stm32/boards/NUCLEO_L073RZ/mpconfigboard.mk
@@ -8,3 +8,6 @@ MICROPY_VFS_FAT = 0
# Don't include default frozen modules because MCU is tight on flash space
FROZEN_MANIFEST ?=
+
+# LTO reduces final binary size, may be slower to build depending on gcc version and hardware
+LTO ?= 1
diff --git a/ports/stm32/boards/NUCLEO_L152RE/board.json b/ports/stm32/boards/NUCLEO_L152RE/board.json
new file mode 100644
index 000000000000..7b3427693755
--- /dev/null
+++ b/ports/stm32/boards/NUCLEO_L152RE/board.json
@@ -0,0 +1,15 @@
+{
+ "deploy": [
+ "./deploy.md"
+ ],
+ "docs": "",
+ "features": [],
+ "images": [
+ "nucleo_l152re.jpg"
+ ],
+ "mcu": "stm32l1",
+ "product": "Nucleo L152RE",
+ "thumbnail": "",
+ "url": "",
+ "vendor": "ST Microelectronics"
+}
diff --git a/ports/stm32/boards/NUCLEO_L152RE/deploy.md b/ports/stm32/boards/NUCLEO_L152RE/deploy.md
new file mode 100644
index 000000000000..0323981d2d66
--- /dev/null
+++ b/ports/stm32/boards/NUCLEO_L152RE/deploy.md
@@ -0,0 +1,31 @@
+### STM32 via ST-Link
+
+Nucleo and Discovery boards typically include a built-in ST-Link programmer.
+
+A `.bin` or `.hex` file can be flashed using [st-flash](https://github.com/stlink-org/stlink).
+
+```bash
+# Optional erase to clear existing filesystem.
+st-flash erase
+
+# Flash .bin
+st-flash write firmware.bin 0x08000000
+# or, flash .hex
+st-flash --format ihex write firmware.hex
+```
+
+A `.hex` file can be flashed using [STM32 Cube Programmer](https://www.st.com/en/development-tools/stm32cubeprog.html).
+
+```bash
+STM32_Programmer.sh -c port=SWD mode=UR dLPM -d firmware.hex -v -hardRst
+```
+
+### STM32 via DFU
+
+Boards with USB support can also be programmed via the ST DFU bootloader, using e.g. [dfu-util](http://dfu-util.sourceforge.net/) or [pydfu.py](https://github.com/micropython/micropython/blob/master/tools/pydfu.py).
+
+To enter the bootloader the `BOOT0` pin can be connected to `VCC` during reset, or you can use `machine.bootloader()` from the MicroPython REPL.
+
+```bash
+dfu-util --alt 0 -D firmware.dfu
+```
diff --git a/ports/stm32/boards/NUCLEO_L152RE/mpconfigboard.h b/ports/stm32/boards/NUCLEO_L152RE/mpconfigboard.h
new file mode 100644
index 000000000000..3609955893fe
--- /dev/null
+++ b/ports/stm32/boards/NUCLEO_L152RE/mpconfigboard.h
@@ -0,0 +1,74 @@
+#define MICROPY_HW_BOARD_NAME "NUCLEO-L152RE"
+#define MICROPY_HW_MCU_NAME "STM32L152xE"
+
+#define MICROPY_HW_HAS_SWITCH (1)
+#define MICROPY_HW_ENABLE_RTC (1)
+// This board has an external 32kHz crystal
+#define MICROPY_HW_RTC_USE_LSE (1)
+#define MICROPY_HW_ENABLE_SERVO (1)
+#define MICROPY_HW_ENABLE_DAC (1)
+
+// HSE is 8MHz, HSI is 16MHz CPU freq set to 32MHz
+// Default source for the clock is HSI.
+// For revisions of the board greater than C-01, HSE can be used as a
+// clock source by removing the #define MICROPY_HW_CLK_USE_HSE line
+#define MICROPY_HW_CLK_USE_HSI (1)
+
+#if MICROPY_HW_CLK_USE_HSI
+#define MICROPY_HW_CLK_PLLMUL (RCC_CFGR_PLLMUL6)
+#define MICROPY_HW_CLK_PLLDIV (RCC_CFGR_PLLDIV3)
+#else
+#define MICROPY_HW_CLK_PLLMUL (RCC_CFGR_PLLMUL12)
+#define MICROPY_HW_CLK_PLLDIV (RCC_CFGR_PLLDIV3)
+#endif
+
+// UART config
+#define MICROPY_HW_UART1_TX (pin_A9)
+#define MICROPY_HW_UART1_RX (pin_A10)
+#define MICROPY_HW_UART2_TX (pin_A2)
+#define MICROPY_HW_UART2_RX (pin_A3)
+#define MICROPY_HW_UART3_TX (pin_B10)
+#define MICROPY_HW_UART3_RX (pin_B11)
+#define MICROPY_HW_UART4_TX (pin_C10)
+#define MICROPY_HW_UART4_RX (pin_C11)
+#define MICROPY_HW_UART5_TX (pin_C12)
+#define MICROPY_HW_UART5_RX (pin_D2)
+// UART 2 connects to the STM32F103 (STLINK) on the Nucleo board
+// and this is exposed as a USB Serial port.
+#define MICROPY_HW_UART_REPL PYB_UART_2
+#define MICROPY_HW_UART_REPL_BAUD 115200
+
+// I2C buses
+#define MICROPY_HW_I2C1_SCL (pin_B8) // Arduino D15, pin 3 on CN10
+#define MICROPY_HW_I2C1_SDA (pin_B9) // D14, pin 5 on CN10
+#define MICROPY_HW_I2C2_SCL (pin_B10) // Arduino D6, pin 25 on CN10
+#define MICROPY_HW_I2C2_SDA (pin_B11) // Arduino D3, pin 31 on CN10
+
+// SPI buses
+#define MICROPY_HW_SPI1_NSS (pin_A15) // pin 17 on CN7
+#define MICROPY_HW_SPI1_SCK (pin_A5) // Arduino D13, pin 11 on CN10
+#define MICROPY_HW_SPI1_MISO (pin_A6) // Arduino D12, pin 13 on CN10
+#define MICROPY_HW_SPI1_MOSI (pin_A7) // Arduino D11, pin 15 on CN10
+
+#define MICROPY_HW_SPI2_NSS (pin_B12) // pin 16 on CN10
+#define MICROPY_HW_SPI2_SCK (pin_B13) // pin 30 on CN10
+#define MICROPY_HW_SPI2_MISO (pin_B14) // pin 28 on CN10
+#define MICROPY_HW_SPI2_MOSI (pin_B15) // pin 26 on CN10
+
+#define MICROPY_HW_SPI3_NSS (pin_A4) // Arduino A2, pin 32 on CN7
+#define MICROPY_HW_SPI3_SCK (pin_C10) // Arduino D3, pin 31 on CN10
+#define MICROPY_HW_SPI3_MISO (pin_C11) // Arduino D5, pin 27 on CN10
+#define MICROPY_HW_SPI3_MOSI (pin_C12) // Arduino D4, pin 29 on CN10
+
+// USRSW is pulled low. Pressing the button makes the input go high.
+#define MICROPY_HW_USRSW_PIN (pin_C13)
+#define MICROPY_HW_USRSW_PULL (GPIO_NOPULL)
+#define MICROPY_HW_USRSW_EXTI_MODE (GPIO_MODE_IT_FALLING)
+#define MICROPY_HW_USRSW_PRESSED (0)
+
+// LEDs
+#define MICROPY_HW_LED1 (pin_A5) // Green LD2 LED on Nucleo
+#define MICROPY_HW_LED_ON(pin) (mp_hal_pin_high(pin))
+#define MICROPY_HW_LED_OFF(pin) (mp_hal_pin_low(pin))
+
+#define MICROPY_HW_FLASH_LATENCY FLASH_LATENCY_1
diff --git a/ports/stm32/boards/NUCLEO_L152RE/mpconfigboard.mk b/ports/stm32/boards/NUCLEO_L152RE/mpconfigboard.mk
new file mode 100644
index 000000000000..a62a775ac8dd
--- /dev/null
+++ b/ports/stm32/boards/NUCLEO_L152RE/mpconfigboard.mk
@@ -0,0 +1,4 @@
+MCU_SERIES = l1
+CMSIS_MCU = STM32L152xE
+AF_FILE = boards/stm32l152_af.csv
+LD_FILES = boards/stm32l152xe.ld boards/common_basic.ld
diff --git a/ports/stm32/boards/NUCLEO_L152RE/pins.csv b/ports/stm32/boards/NUCLEO_L152RE/pins.csv
new file mode 100644
index 000000000000..035d933f5dd4
--- /dev/null
+++ b/ports/stm32/boards/NUCLEO_L152RE/pins.csv
@@ -0,0 +1,76 @@
+D0,PA3
+D1,PA2
+D2,PA10
+D3,PB3
+D4,PB5
+D5,PB4
+D6,PB10
+D7,PA8
+D8,PA9
+D9,PC7
+D10,PB6
+D11,PA7
+D12,PA6
+D13,PA5
+D14,PB9
+D15,PB8
+A0,PA0
+A1,PA1
+A2,PA4
+A3,PB0
+A4,PC1
+A5,PC0
+PA0,PA0
+PA1,PA1
+PA2,PA2
+PA3,PA3
+PA4,PA4
+PA5,PA5
+PA6,PA6
+PA7,PA7
+PA8,PA8
+PA9,PA9
+PA10,PA10
+PA11,PA11
+PA12,PA12
+PA15,PA15
+PB0,PB0
+PB1,PB1
+PB2,PB2
+PB3,PB3
+PB4,PB4
+PB5,PB5
+PB6,PB6
+PB7,PB7
+PB8,PB8
+PB9,PB9
+PB10,PB10
+PB11,PB11
+PB12,PB12
+PB13,PB13
+PB14,PB14
+PB15,PB15
+PC0,PC0
+PC1,PC1
+PC2,PC2
+PC3,PC3
+PC4,PC4
+PC5,PC5
+PC6,PC6
+PC7,PC7
+PC8,PC8
+PC9,PC9
+PC10,PC10
+PC11,PC11
+PC12,PC12
+PC13,PC13
+PC14,PC14
+PC15,PC15
+PD2,PD2
+PH0,PH0
+PH1,PH1
+LED_GREEN,PA5
+LED_ORANGE,PA5
+LED_RED,PA5
+LED_BLUE,PA4
+SW,PC13
diff --git a/ports/stm32/boards/NUCLEO_L152RE/stm32l1xx_hal_conf.h b/ports/stm32/boards/NUCLEO_L152RE/stm32l1xx_hal_conf.h
new file mode 100644
index 000000000000..7ee8204cbf06
--- /dev/null
+++ b/ports/stm32/boards/NUCLEO_L152RE/stm32l1xx_hal_conf.h
@@ -0,0 +1,10 @@
+/* This file is part of the MicroPython project, http://micropython.org/
+ * The MIT License (MIT)
+ * Copyright (c) 2019 Damien P. George
+ */
+#ifndef MICROPY_INCLUDED_STM32L1XX_HAL_CONF_H
+#define MICROPY_INCLUDED_STM32L1XX_HAL_CONF_H
+
+#include "boards/stm32l1xx_hal_conf_base.h"
+
+#endif // MICROPY_INCLUDED_STM32L1XX_HAL_CONF_H
diff --git a/ports/stm32/boards/NUCLEO_L432KC/mpconfigboard.mk b/ports/stm32/boards/NUCLEO_L432KC/mpconfigboard.mk
index a87b4710e74a..c3fff8100251 100644
--- a/ports/stm32/boards/NUCLEO_L432KC/mpconfigboard.mk
+++ b/ports/stm32/boards/NUCLEO_L432KC/mpconfigboard.mk
@@ -10,3 +10,6 @@ MICROPY_VFS_LFS1 ?= 1
# Don't include default frozen modules because MCU is tight on flash space
FROZEN_MANIFEST ?=
+
+# LTO reduces final binary size, may be slower to build depending on gcc version and hardware
+LTO ?= 1
diff --git a/ports/stm32/boards/NUCLEO_WB55/mpconfigboard.mk b/ports/stm32/boards/NUCLEO_WB55/mpconfigboard.mk
index 349ce46d7958..2e6ce1fe8f77 100644
--- a/ports/stm32/boards/NUCLEO_WB55/mpconfigboard.mk
+++ b/ports/stm32/boards/NUCLEO_WB55/mpconfigboard.mk
@@ -6,7 +6,7 @@ STARTUP_FILE = $(STM32LIB_CMSIS_BASE)/Source/Templates/gcc/startup_stm32wb55xx_c
ifeq ($(USE_MBOOT),1)
# When using Mboot all the text goes together after the bootloader
LD_FILES = boards/stm32wb55xg.ld boards/common_bl.ld
-TEXT0_ADDR = 0x08004000
+TEXT0_ADDR = 0x08008000
else
# When not using Mboot the text goes at the start of flash
LD_FILES = boards/stm32wb55xg.ld boards/common_basic.ld
diff --git a/ports/stm32/boards/NUCLEO_WB55/rfcore_firmware.py b/ports/stm32/boards/NUCLEO_WB55/rfcore_firmware.py
index 4085da90fd49..7cc81b4c682a 100644
--- a/ports/stm32/boards/NUCLEO_WB55/rfcore_firmware.py
+++ b/ports/stm32/boards/NUCLEO_WB55/rfcore_firmware.py
@@ -34,36 +34,54 @@
#
# To perform a firmware update:
#
-# 1. Generate "obfuscated" binary images using rfcore_makefirmware.py
-# ./boards/NUCLEO_WB55/rfcore_makefirmware.py ~/src/github.com/STMicroelectronics/STM32CubeWB/Projects/STM32WB_Copro_Wireless_Binaries/STM32WB5x/ /tmp
+# 1. Generate "obfuscated" binary images using rfcore_makefirmware.py, eg.
+# $ python3 ./boards/NUCLEO_WB55/rfcore_makefirmware.py ~/src/github.com/STMicroelectronics/STM32CubeWB/Projects/STM32WB_Copro_Wireless_Binaries/STM32WB5x/ /tmp
# This will generate /tmp/{fus_102,fus_110,ws_ble_hci}.bin
+# It may warn that stm32wb5x_FUS_fw_1_0_2.bin cannot be found, newer packs don't include this
+# which can be ignored unless your currently flashed FUS is older than 1.0.2
#
# 2. Copy required files to the device filesystem.
-# In general, it's always safe to copy all three files and the updater will
-# figure out what needs to be done. This is the recommended option.
-# However, if you already have the latest FUS (1.1.0) installed, then just the
-# WS firmware is required.
-# If a FUS binary is present, then the existing WS will be removed so it's a good
-# idea to always include the WS binary if updating FUS.
-# Note that a WS binary will not be installed unless FUS 1.1.0 is installed.
+# $ mpremote cp /tmp/fus_102.bin :
+# $ mpremote cp /tmp/fus_110.bin :
+# $ mpremote cp /tmp/ws_ble_hci.bin :
+# $ mpremote cp ./boards/NUCLEO_WB55/rfcore_firmware.py :
+# In general, it's always safe to copy all three files and the updater will
+# figure out what needs to be done. This is the recommended option.
+# However, if you already have the latest FUS (1.1.0) installed, then just the
+# WS firmware is required.
+# If a FUS binary is present, then the existing WS will be removed so it's a good
+# idea to always include the WS binary if updating FUS.
+# Note that a WS binary will not be installed unless FUS 1.1.0 is installed.
#
# 3. Ensure boot.py calls `rfcore_firmware.resume()`.
-# The WB55 will reset several times during the firmware update process, so this
-# script manages the update state using RTC backup registers.
-# `rfcore_firmware.resume()` will continue the update operation on startup to
-# resume any in-progress update operation, and either trigger another reset, or
-# return 0 to indicate that the operation completed successfully, or a reason
-# code (see REASON_* below) to indicate failure.
+# $ mpremote exec "import rfcore_firmware; rfcore_firmware.install_boot()"
+# The WB55 will reset several times during the firmware update process, so this
+# script manages the update state using RTC backup registers.
+# `rfcore_firmware.resume()` will continue the update operation on startup to
+# resume any in-progress update operation, and either trigger another reset, or
+# return 0 to indicate that the operation completed successfully, or a reason
+# code (see REASON_* below) to indicate failure.
#
# 4. Call rfcore_firmware.check_for_updates() to start the update process.
-# The device will then immediately reboot and when the firmware update completes,
-# the status will be returned from rfcore_firmware.resume(). See the REASON_ codes below.
-# You can use the built-in stm.rfcore_fw_version() to query the installed version
-# from your application code.
+# $ mpremote exec "import rfcore_firmware; rfcore_firmware.check_for_updates()"
+# The device will then immediately reboot and when the firmware update completes,
+# the status will be returned from rfcore_firmware.resume(). See the REASON_ codes below.
+# You can use the built-in stm.rfcore_fw_version() to query the installed version
+# from your application code.
import struct, os
-import machine, stm
-from micropython import const
+
+try:
+ import machine, stm
+ from ubinascii import crc32
+ from micropython import const
+except ImportError:
+ # cpython
+ from binascii import crc32
+
+ machine = stm = None
+ const = lambda x: x
+
_OGF_VENDOR = const(0x3F)
@@ -174,13 +192,6 @@
_PATH_FUS_110 = "fus_110.bin"
_PATH_WS_BLE_HCI = "ws_ble_hci.bin"
-# This address is correct for versions up to v1.8 (assuming existing firmware deleted).
-# Note any address from the end of the filesystem to the SFSA would be fine, but if
-# the FUS is fixed in the future to use the specified address then these are the "correct"
-# ones.
-_ADDR_FUS = 0x080EC000
-_ADDR_WS_BLE_HCI = 0x080DC000
-
# When installing the FUS/WS it can take a long time to return to the first
# GET_STATE HCI command.
# e.g. Installing stm32wb5x_BLE_Stack_full_fw.bin takes 3600ms to respond.
@@ -242,10 +253,79 @@ def write(self, addr, buf, sz, key=0):
machine.mem32[stm.FLASH + stm.FLASH_CR] = 0
-def _copy_file_to_flash(filename, addr):
+def validate_crc(f):
+ """Should match copy of function in rfcore_makefirmware.py to confirm operation"""
+ f.seek(0)
+ file_crc = 0
+ chunk = 16 * 1024
+ buff = bytearray(chunk)
+ while True:
+ read = f.readinto(buff)
+ if read < chunk:
+ file_crc = crc32(buff[0:read], file_crc)
+ break
+ file_crc = crc32(buff, file_crc)
+
+ file_crc = 0xFFFFFFFF & -file_crc - 1
+ f.seek(0)
+ return file_crc == 0
+
+
+def check_file_details(filename):
+ with open(filename, "rb") as f:
+ if not validate_crc(f):
+ raise ValueError("file validation failed: incorrect crc")
+
+ # Check the footer on the file
+ f.seek(-64, 2)
+ footer = f.read()
+ details = struct.unpack("<37sIIIIbbbII", footer)
+ (
+ src_filename,
+ addr_1m,
+ addr_640k,
+ addr_512k,
+ addr_256k,
+ vers_major,
+ vers_minor,
+ vers_patch,
+ KEY,
+ crc,
+ ) = details
+ src_filename = src_filename.strip(b"\x00").decode()
+ if KEY != _OBFUSCATION_KEY:
+ raise ValueError("file validation failed: incorrect key")
+
+ return (
+ src_filename,
+ addr_1m,
+ addr_640k,
+ addr_512k,
+ addr_256k,
+ (vers_major, vers_minor, vers_patch),
+ )
+
+
+def _copy_file_to_flash(filename):
flash = _Flash()
flash.unlock()
+ # Reset any previously stored address
+ _write_target_addr(0)
try:
+ (
+ src_filename,
+ addr_1m,
+ addr_640k,
+ addr_512k,
+ addr_256k,
+ vers,
+ ) = check_file_details(filename)
+
+ # TODO add support for querying the correct flash size on chip
+ addr = load_addr = addr_1m
+
+ log(f"Writing {src_filename} v{vers[0]}.{vers[1]}.{vers[2]} to addr: 0x{addr:x}")
+
# Erase the entire staging area in flash.
erase_addr = STAGING_AREA_START
sfr_sfsa = machine.mem32[stm.FLASH + stm.FLASH_SFR] & 0xFF
@@ -266,6 +346,9 @@ def _copy_file_to_flash(filename, addr):
flash.write(addr, buf, sz, _OBFUSCATION_KEY)
addr += 4096
+ # Cache the intended target load address
+ _write_target_addr(load_addr)
+
finally:
flash.lock()
@@ -308,17 +391,25 @@ def _fus_fwdelete():
return _run_sys_hci_cmd(_OGF_VENDOR, _OCF_FUS_FW_DELETE)
-def _fus_run_fwupgrade(addr):
+def _fus_run_fwupgrade():
# Note: Address is ignored by the FUS (see comments above).
+ addr = _read_target_addr()
+ if not addr:
+ log(f"Update failed: Invalid load address: 0x{addr:x}")
+ return False
+
+ log(f"Loading to: 0x{addr:x}")
return _run_sys_hci_cmd(_OGF_VENDOR, _OCF_FUS_FW_UPGRADE, struct.pack("= _FUS_VERSION_102 and fus_version < _FUS_VERSION_110:
log("FUS 1.0.2 detected")
- if _stat_and_start_copy(
- _PATH_FUS_110, _ADDR_FUS, _STATE_COPYING_FUS, _STATE_COPIED_FUS
- ):
+ if _stat_and_start_copy(_PATH_FUS_110, _STATE_COPYING_FUS, _STATE_COPIED_FUS):
continue
else:
log("FUS is up-to-date")
if fus_version >= _FUS_VERSION_110:
if _stat_and_start_copy(
- _PATH_WS_BLE_HCI, _ADDR_WS_BLE_HCI, _STATE_COPYING_WS, _STATE_COPIED_WS
+ _PATH_WS_BLE_HCI,
+ _STATE_COPYING_WS,
+ _STATE_COPIED_WS,
):
continue
else:
@@ -465,7 +562,7 @@ def resume():
if fus_is_idle():
log("FUS copy complete, installing")
_write_state(_STATE_INSTALLING_FUS)
- _fus_run_fwupgrade(_ADDR_FUS)
+ _fus_run_fwupgrade()
else:
log("FUS copy bad state")
_write_failure_state(REASON_FLASH_FUS_BAD_STATE)
@@ -519,7 +616,7 @@ def resume():
if fus_is_idle():
log("WS copy complete, installing")
_write_state(_STATE_INSTALLING_WS)
- _fus_run_fwupgrade(_ADDR_WS_BLE_HCI)
+ _fus_run_fwupgrade()
else:
log("WS copy bad state")
_write_failure_state(REASON_FLASH_WS_BAD_STATE)
@@ -556,9 +653,59 @@ def resume():
_write_failure_state(REASON_WS_VENDOR + result)
+def install_boot():
+ boot_py = "/flash/boot.py"
+ header = ""
+ mode = "w"
+ try:
+ with open(boot_py, "r") as boot:
+ header = "\n"
+ mode = "a"
+ for line in boot:
+ if "rfcore_firmware.resume()" in line:
+ print("Already installed.")
+ return
+
+ print("boot.py exists, adding upgrade handler.")
+ except OSError:
+ print("boot.py doesn't exists, adding with upgrade handler.")
+
+ with open(boot_py, mode) as boot:
+ boot.write(header)
+ boot.write("# Handle rfcore updates.\n")
+ boot.write("import rfcore_firmware\n")
+ boot.write("rfcore_firmware.resume()\n")
+
+
# Start a firmware update.
# This will immediately trigger a reset and start the update process on boot.
-def check_for_updates():
- log("Starting firmware update")
- _write_state(_STATE_WAITING_FOR_FUS)
- machine.reset()
+def check_for_updates(force=False):
+ (
+ src_filename,
+ addr_1m,
+ addr_640k,
+ addr_512k,
+ addr_256k,
+ vers_fus,
+ ) = check_file_details(_PATH_FUS_110)
+ (
+ src_filename,
+ addr_1m,
+ addr_640k,
+ addr_512k,
+ addr_256k,
+ vers_ws,
+ ) = check_file_details(_PATH_WS_BLE_HCI)
+ current_version_fus = stm.rfcore_fw_version(_FW_VERSION_FUS)
+ fus_uptodate = current_version_fus[0:3] == vers_fus
+
+ current_version_ws = stm.rfcore_fw_version(_FW_VERSION_WS)
+ ws_uptodate = current_version_ws[0:3] == vers_ws
+ if fus_uptodate and ws_uptodate and not force:
+ log(f"Already up to date: fus: {current_version_fus}, ws: {current_version_ws}")
+ else:
+ log(f"Starting firmware update")
+ log(f" - fus: {current_version_fus} -> {vers_fus}")
+ log(f" - ws: {current_version_ws} -> {vers_ws}")
+ _write_state(_STATE_WAITING_FOR_FUS)
+ machine.reset()
diff --git a/ports/stm32/boards/NUCLEO_WB55/rfcore_makefirmware.py b/ports/stm32/boards/NUCLEO_WB55/rfcore_makefirmware.py
index 23f3d20f0c9c..ebab7f576621 100755
--- a/ports/stm32/boards/NUCLEO_WB55/rfcore_makefirmware.py
+++ b/ports/stm32/boards/NUCLEO_WB55/rfcore_makefirmware.py
@@ -30,28 +30,69 @@
# rfcore_firmware.py as well as instructions on how to use.
import os
+import re
import struct
import sys
+from binascii import crc32
+from rfcore_firmware import validate_crc, _OBFUSCATION_KEY
-# Must match rfcore_firmware.py.
-_OBFUSCATION_KEY = 0x0573B55AA
_FIRMWARE_FILES = {
"stm32wb5x_FUS_fw_1_0_2.bin": "fus_102.bin",
"stm32wb5x_FUS_fw.bin": "fus_110.bin",
"stm32wb5x_BLE_HCILayer_fw.bin": "ws_ble_hci.bin",
}
+_RELEASE_NOTES = "Release_Notes.html"
+
+
+def get_details(release_notes, filename):
+ if not release_notes:
+ return None
+ file_details = re.findall(
+ rb"%s,(((0x[\d\S]+?),)+[vV][\d\.]+)[<,]" % filename.encode(),
+ release_notes,
+ flags=re.DOTALL,
+ )
+ # The release note has all past version details also, but current is at top
+ latest_details = file_details[0][0].split(b",")
+ addr_1m, addr_640k, addr_512k, addr_256k, version = latest_details
+ addr_1m = int(addr_1m, 0)
+ addr_640k = int(addr_640k, 0)
+ addr_512k = int(addr_512k, 0)
+ addr_256k = int(addr_256k, 0)
+ version = [int(v) for v in version.lower().lstrip(b"v").split(b".")]
+ return addr_1m, addr_640k, addr_512k, addr_256k, version
def main(src_path, dest_path):
- for src_file, dest_file in _FIRMWARE_FILES.items():
- src_file = os.path.join(src_path, src_file)
+ # Load the release note to parse for important details
+ with open(os.path.join(src_path, _RELEASE_NOTES), "rb") as f:
+ release_notes = f.read()
+ # remove some formatting
+ release_notes = re.sub(rb"?strong>", b"", release_notes)
+ # flatten tables
+ release_notes = re.sub(
+ rb"\W*\n*\W*",
+ b",",
+ release_notes.replace(b"
", b"").replace(b"
", b""),
+ )
+ if (
+ b"Wireless Coprocessor Binary,STM32WB5xxG(1M),STM32WB5xxY(640k),STM32WB5xxE(512K),STM32WB5xxC(256K),Version,"
+ not in release_notes
+ ):
+ raise SystemExit(
+ "Cannot determine binary load address, please confirm Coprocessor folder / Release Notes format."
+ )
+
+ for src_filename, dest_file in _FIRMWARE_FILES.items():
+ src_file = os.path.join(src_path, src_filename)
dest_file = os.path.join(dest_path, dest_file)
if not os.path.exists(src_file):
print("Unable to find: {}".format(src_file))
continue
sz = 0
with open(src_file, "rb") as src:
+ crc = 0
with open(dest_file, "wb") as dest:
while True:
b = src.read(4)
@@ -59,9 +100,71 @@ def main(src_path, dest_path):
break
(v,) = struct.unpack("FLASH_EXT
-
- .isr_vector :
- {
- . = ALIGN(4);
- KEEP(*(.isr_vector))
- . = ALIGN(4);
- } >FLASH_APP
-
- .text :
- {
- . = ALIGN(4);
- *(.text*)
- *(.rodata*)
- . = ALIGN(4);
- _etext = .;
- } >FLASH_APP
-
- INCLUDE common_extratext_data_in_flash_app.ld
- INCLUDE common_bss_heap_stack.ld
}
+
+INCLUDE common_bl.ld
diff --git a/ports/stm32/boards/PYBD_SF2/manifest.py b/ports/stm32/boards/PYBD_SF2/manifest.py
index 3819aa01b3dc..f096d1ad052e 100644
--- a/ports/stm32/boards/PYBD_SF2/manifest.py
+++ b/ports/stm32/boards/PYBD_SF2/manifest.py
@@ -1,2 +1,3 @@
include("$(PORT_DIR)/boards/manifest.py")
-include("$(MPY_DIR)/extmod/webrepl/manifest.py")
+include("$(PORT_DIR)/boards/manifest_pyboard.py")
+require("bundle-networking")
diff --git a/ports/stm32/boards/PYBD_SF2/mpconfigboard.h b/ports/stm32/boards/PYBD_SF2/mpconfigboard.h
index 6dfb8c38d23a..c92e6f75288b 100644
--- a/ports/stm32/boards/PYBD_SF2/mpconfigboard.h
+++ b/ports/stm32/boards/PYBD_SF2/mpconfigboard.h
@@ -27,6 +27,8 @@
#define MICROPY_HW_BOARD_NAME "PYBD-SF2W"
#define MICROPY_HW_MCU_NAME "STM32F722IEK"
+#define MICROPY_PY_NETWORK_HOSTNAME_DEFAULT "PYBD"
+
#define MICROPY_PY_PYB_LEGACY (1)
#define MICROPY_HW_ENABLE_INTERNAL_FLASH_STORAGE (0)
#define MICROPY_HW_HAS_SWITCH (1)
@@ -194,6 +196,7 @@ extern struct _spi_bdev_t spi_bdev2;
#define MICROPY_HW_BLE_UART_ID (PYB_UART_6)
#define MICROPY_HW_BLE_UART_BAUDRATE (115200)
#define MICROPY_HW_BLE_UART_BAUDRATE_SECONDARY (3000000)
+#define MICROPY_HW_BLE_UART_BAUDRATE_DOWNLOAD_FIRMWARE (3000000)
/******************************************************************************/
// Bootloader configuration
diff --git a/ports/stm32/boards/PYBD_SF6/f767.ld b/ports/stm32/boards/PYBD_SF6/f767.ld
index 5866f0b5cc2d..167d2c6a1e41 100644
--- a/ports/stm32/boards/PYBD_SF6/f767.ld
+++ b/ports/stm32/boards/PYBD_SF6/f767.ld
@@ -5,7 +5,6 @@
FLASH_APP .isr_vector
FLASH_APP .text
- FLASH_APP .big_const
FLASH_APP .data
RAM .data
@@ -39,29 +38,4 @@ _ram_end = ORIGIN(RAM) + LENGTH(RAM);
_heap_start = _ebss; /* heap starts just after statically allocated memory */
_heap_end = _sstack;
-ENTRY(Reset_Handler)
-
-/* Define output sections */
-SECTIONS
-{
- .isr_vector :
- {
- . = ALIGN(4);
- KEEP(*(.isr_vector))
- . = ALIGN(4);
- } >FLASH_APP
-
- .text :
- {
- . = ALIGN(4);
- *(.text*)
- *(.rodata*)
- . = ALIGN(512);
- *(.big_const*)
- . = ALIGN(4);
- _etext = .;
- } >FLASH_APP
-
- INCLUDE common_extratext_data_in_flash_app.ld
- INCLUDE common_bss_heap_stack.ld
-}
+INCLUDE common_bl.ld
diff --git a/ports/stm32/boards/PYBLITEV10/board.md b/ports/stm32/boards/PYBLITEV10/board.md
index 1511ffcf514f..b490d5404691 100644
--- a/ports/stm32/boards/PYBLITEV10/board.md
+++ b/ports/stm32/boards/PYBLITEV10/board.md
@@ -1 +1 @@
-The "standard" build is listed first and is the default firmware that the pyboards are shipped with. Use this firmware if you are uncertain. The "double FP" builds use double-precision floating point instead of the standard single precision. The "threading" builds contain the \_thread module and allow multithreading. The "network" builds have network drivers for CC3000 and WIZ820io included. All these different firmware are completely interchangeable and you can freely change from one to the other without losing the filesystem on your pyboard.
+The "standard" build is listed first and is the default firmware that the pyboards are shipped with. Use this firmware if you are uncertain. The "double FP" builds use double-precision floating point instead of the standard single precision. The "threading" builds contain the \_thread module and allow multithreading. The "network" builds have network drivers for WIZ820io included. All these different firmware are completely interchangeable and you can freely change from one to the other without losing the filesystem on your pyboard.
diff --git a/ports/stm32/boards/PYBLITEV10/mpconfigboard.mk b/ports/stm32/boards/PYBLITEV10/mpconfigboard.mk
index df9506522574..461886b63cab 100644
--- a/ports/stm32/boards/PYBLITEV10/mpconfigboard.mk
+++ b/ports/stm32/boards/PYBLITEV10/mpconfigboard.mk
@@ -4,3 +4,26 @@ AF_FILE = boards/stm32f411_af.csv
LD_FILES = boards/stm32f411.ld boards/common_ifs.ld
TEXT0_ADDR = 0x08000000
TEXT1_ADDR = 0x08020000
+
+# Provide different variants for the downloads page.
+BOARD_VARIANTS += "dp thread dp-thread network"
+
+ifeq ($(BOARD_VARIANT),dp)
+MICROPY_FLOAT_IMPL=double
+endif
+
+ifeq ($(BOARD_VARIANT),thread)
+CFLAGS += -DMICROPY_PY_THREAD=1
+endif
+
+ifeq ($(BOARD_VARIANT),dp-thread)
+MICROPY_FLOAT_IMPL=double
+CFLAGS += -DMICROPY_PY_THREAD=1
+endif
+
+ifeq ($(BOARD_VARIANT),network)
+MICROPY_PY_NETWORK_WIZNET5K=5200
+endif
+
+# PYB-specific frozen modules
+FROZEN_MANIFEST ?= boards/PYBV10/manifest.py
diff --git a/ports/stm32/boards/PYBV10/board.md b/ports/stm32/boards/PYBV10/board.md
index 1511ffcf514f..b490d5404691 100644
--- a/ports/stm32/boards/PYBV10/board.md
+++ b/ports/stm32/boards/PYBV10/board.md
@@ -1 +1 @@
-The "standard" build is listed first and is the default firmware that the pyboards are shipped with. Use this firmware if you are uncertain. The "double FP" builds use double-precision floating point instead of the standard single precision. The "threading" builds contain the \_thread module and allow multithreading. The "network" builds have network drivers for CC3000 and WIZ820io included. All these different firmware are completely interchangeable and you can freely change from one to the other without losing the filesystem on your pyboard.
+The "standard" build is listed first and is the default firmware that the pyboards are shipped with. Use this firmware if you are uncertain. The "double FP" builds use double-precision floating point instead of the standard single precision. The "threading" builds contain the \_thread module and allow multithreading. The "network" builds have network drivers for WIZ820io included. All these different firmware are completely interchangeable and you can freely change from one to the other without losing the filesystem on your pyboard.
diff --git a/ports/stm32/boards/PYBV10/manifest.py b/ports/stm32/boards/PYBV10/manifest.py
new file mode 100644
index 000000000000..ec0d4a26b785
--- /dev/null
+++ b/ports/stm32/boards/PYBV10/manifest.py
@@ -0,0 +1,2 @@
+include("$(PORT_DIR)/boards/manifest.py")
+include("$(PORT_DIR)/boards/manifest_pyboard.py")
diff --git a/ports/stm32/boards/PYBV10/mpconfigboard.mk b/ports/stm32/boards/PYBV10/mpconfigboard.mk
index cb78a7846d93..363f6b480616 100644
--- a/ports/stm32/boards/PYBV10/mpconfigboard.mk
+++ b/ports/stm32/boards/PYBV10/mpconfigboard.mk
@@ -14,3 +14,26 @@ endif
# MicroPython settings
MICROPY_VFS_LFS2 = 1
+
+# Provide different variants for the downloads page.
+BOARD_VARIANTS += "dp thread dp-thread network"
+
+ifeq ($(BOARD_VARIANT),dp)
+MICROPY_FLOAT_IMPL=double
+endif
+
+ifeq ($(BOARD_VARIANT),thread)
+CFLAGS += -DMICROPY_PY_THREAD=1
+endif
+
+ifeq ($(BOARD_VARIANT),dp-thread)
+MICROPY_FLOAT_IMPL=double
+CFLAGS += -DMICROPY_PY_THREAD=1
+endif
+
+ifeq ($(BOARD_VARIANT),network)
+MICROPY_PY_NETWORK_WIZNET5K=5200
+endif
+
+# PYB-specific frozen modules
+FROZEN_MANIFEST ?= $(BOARD_DIR)/manifest.py
diff --git a/ports/stm32/boards/PYBV11/board.md b/ports/stm32/boards/PYBV11/board.md
index 1511ffcf514f..b490d5404691 100644
--- a/ports/stm32/boards/PYBV11/board.md
+++ b/ports/stm32/boards/PYBV11/board.md
@@ -1 +1 @@
-The "standard" build is listed first and is the default firmware that the pyboards are shipped with. Use this firmware if you are uncertain. The "double FP" builds use double-precision floating point instead of the standard single precision. The "threading" builds contain the \_thread module and allow multithreading. The "network" builds have network drivers for CC3000 and WIZ820io included. All these different firmware are completely interchangeable and you can freely change from one to the other without losing the filesystem on your pyboard.
+The "standard" build is listed first and is the default firmware that the pyboards are shipped with. Use this firmware if you are uncertain. The "double FP" builds use double-precision floating point instead of the standard single precision. The "threading" builds contain the \_thread module and allow multithreading. The "network" builds have network drivers for WIZ820io included. All these different firmware are completely interchangeable and you can freely change from one to the other without losing the filesystem on your pyboard.
diff --git a/ports/stm32/boards/PYBV11/mpconfigboard.mk b/ports/stm32/boards/PYBV11/mpconfigboard.mk
index cb78a7846d93..857049f21596 100644
--- a/ports/stm32/boards/PYBV11/mpconfigboard.mk
+++ b/ports/stm32/boards/PYBV11/mpconfigboard.mk
@@ -14,3 +14,26 @@ endif
# MicroPython settings
MICROPY_VFS_LFS2 = 1
+
+# Provide different variants for the downloads page.
+BOARD_VARIANTS += "dp thread dp-thread network"
+
+ifeq ($(BOARD_VARIANT),dp)
+MICROPY_FLOAT_IMPL=double
+endif
+
+ifeq ($(BOARD_VARIANT),thread)
+CFLAGS += -DMICROPY_PY_THREAD=1
+endif
+
+ifeq ($(BOARD_VARIANT),dp-thread)
+MICROPY_FLOAT_IMPL=double
+CFLAGS += -DMICROPY_PY_THREAD=1
+endif
+
+ifeq ($(BOARD_VARIANT),network)
+MICROPY_PY_NETWORK_WIZNET5K=5200
+endif
+
+# PYB-specific frozen modules
+FROZEN_MANIFEST ?= boards/PYBV10/manifest.py
diff --git a/ports/stm32/boards/STM32F769DISC/board_init.c b/ports/stm32/boards/STM32F769DISC/board_init.c
index 6bb3dfb1f617..e89d187fece7 100644
--- a/ports/stm32/boards/STM32F769DISC/board_init.c
+++ b/ports/stm32/boards/STM32F769DISC/board_init.c
@@ -3,13 +3,17 @@
// This configuration is needed for mboot to be able to write to the external QSPI flash
+#if MICROPY_HW_SPIFLASH_ENABLE_CACHE
STATIC mp_spiflash_cache_t spi_bdev_cache;
+#endif
const mp_spiflash_config_t spiflash_config = {
.bus_kind = MP_SPIFLASH_BUS_QSPI,
.bus.u_qspi.data = NULL,
.bus.u_qspi.proto = &qspi_proto,
+ #if MICROPY_HW_SPIFLASH_ENABLE_CACHE
.cache = &spi_bdev_cache,
+ #endif
};
spi_bdev_t spi_bdev;
diff --git a/ports/stm32/boards/STM32F769DISC/f769_qspi.ld b/ports/stm32/boards/STM32F769DISC/f769_qspi.ld
index b6957a321332..b6515b066691 100644
--- a/ports/stm32/boards/STM32F769DISC/f769_qspi.ld
+++ b/ports/stm32/boards/STM32F769DISC/f769_qspi.ld
@@ -40,6 +40,8 @@ _heap_end = _sstack;
ENTRY(Reset_Handler)
+REGION_ALIAS("FLASH_COMMON", FLASH_APP);
+
SECTIONS
{
/* Define the code that goes in QSPI flash */
@@ -50,24 +52,8 @@ SECTIONS
. = ALIGN(4);
} >FLASH_QSPI
- /* The startup code goes first into main flash */
- .isr_vector :
- {
- . = ALIGN(4);
- KEEP(*(.isr_vector))
- . = ALIGN(4);
- } >FLASH_APP
-
- /* The program code and other data goes into flash */
- .text :
- {
- . = ALIGN(4);
- *(.text*)
- *(.rodata*)
- . = ALIGN(4);
- _etext = .;
- } >FLASH_APP
-
- INCLUDE common_extratext_data_in_flash_app.ld
+ INCLUDE common_isr.ld
+ INCLUDE common_text.ld
+ INCLUDE common_extratext_data_in_flash.ld
INCLUDE common_bss_heap_stack.ld
}
diff --git a/ports/stm32/boards/STM32F769DISC/manifest.py b/ports/stm32/boards/STM32F769DISC/manifest.py
new file mode 100644
index 000000000000..ebfecd4844ad
--- /dev/null
+++ b/ports/stm32/boards/STM32F769DISC/manifest.py
@@ -0,0 +1,2 @@
+include("$(PORT_DIR)/boards/manifest.py")
+require("bundle-networking")
diff --git a/ports/stm32/boards/STM32F769DISC/mpconfigboard.mk b/ports/stm32/boards/STM32F769DISC/mpconfigboard.mk
index dfee1a7ac79e..6457fc6046bd 100644
--- a/ports/stm32/boards/STM32F769DISC/mpconfigboard.mk
+++ b/ports/stm32/boards/STM32F769DISC/mpconfigboard.mk
@@ -44,3 +44,5 @@ endif
MICROPY_PY_LWIP = 1
MICROPY_PY_USSL = 1
MICROPY_SSL_MBEDTLS = 1
+
+FROZEN_MANIFEST = $(BOARD_DIR)/manifest.py
diff --git a/ports/stm32/boards/STM32F7DISC/manifest.py b/ports/stm32/boards/STM32F7DISC/manifest.py
new file mode 100644
index 000000000000..ebfecd4844ad
--- /dev/null
+++ b/ports/stm32/boards/STM32F7DISC/manifest.py
@@ -0,0 +1,2 @@
+include("$(PORT_DIR)/boards/manifest.py")
+require("bundle-networking")
diff --git a/ports/stm32/boards/STM32F7DISC/mpconfigboard.mk b/ports/stm32/boards/STM32F7DISC/mpconfigboard.mk
index 0ae95a724766..aa03c397033e 100644
--- a/ports/stm32/boards/STM32F7DISC/mpconfigboard.mk
+++ b/ports/stm32/boards/STM32F7DISC/mpconfigboard.mk
@@ -11,3 +11,5 @@ TEXT1_ADDR = 0x08020000
#MICROPY_PY_USSL = 1
#MICROPY_SSL_MBEDTLS = 1
MICROPY_PY_LVGL = 1
+
+FROZEN_MANIFEST = $(BOARD_DIR)/manifest.py
diff --git a/ports/stm32/boards/USBDONGLE_WB55/mpconfigboard.mk b/ports/stm32/boards/USBDONGLE_WB55/mpconfigboard.mk
index 349ce46d7958..2e6ce1fe8f77 100644
--- a/ports/stm32/boards/USBDONGLE_WB55/mpconfigboard.mk
+++ b/ports/stm32/boards/USBDONGLE_WB55/mpconfigboard.mk
@@ -6,7 +6,7 @@ STARTUP_FILE = $(STM32LIB_CMSIS_BASE)/Source/Templates/gcc/startup_stm32wb55xx_c
ifeq ($(USE_MBOOT),1)
# When using Mboot all the text goes together after the bootloader
LD_FILES = boards/stm32wb55xg.ld boards/common_bl.ld
-TEXT0_ADDR = 0x08004000
+TEXT0_ADDR = 0x08008000
else
# When not using Mboot the text goes at the start of flash
LD_FILES = boards/stm32wb55xg.ld boards/common_basic.ld
diff --git a/ports/stm32/boards/VCC_GND_F407ZG/manifest.py b/ports/stm32/boards/VCC_GND_F407ZG/manifest.py
new file mode 100644
index 000000000000..ebfecd4844ad
--- /dev/null
+++ b/ports/stm32/boards/VCC_GND_F407ZG/manifest.py
@@ -0,0 +1,2 @@
+include("$(PORT_DIR)/boards/manifest.py")
+require("bundle-networking")
diff --git a/ports/stm32/boards/VCC_GND_F407ZG/mpconfigboard.mk b/ports/stm32/boards/VCC_GND_F407ZG/mpconfigboard.mk
index c67807867ef1..a30a6137d3b3 100644
--- a/ports/stm32/boards/VCC_GND_F407ZG/mpconfigboard.mk
+++ b/ports/stm32/boards/VCC_GND_F407ZG/mpconfigboard.mk
@@ -8,3 +8,5 @@ TEXT1_ADDR = 0x08020000
MICROPY_PY_LWIP = 1
MICROPY_PY_USSL = 1
MICROPY_SSL_MBEDTLS = 1
+
+FROZEN_MANIFEST = $(BOARD_DIR)/manifest.py
diff --git a/ports/stm32/boards/common_basic.ld b/ports/stm32/boards/common_basic.ld
index dbda1b8b68ba..9916a4c2545d 100644
--- a/ports/stm32/boards/common_basic.ld
+++ b/ports/stm32/boards/common_basic.ld
@@ -12,31 +12,13 @@
ENTRY(Reset_Handler)
+REGION_ALIAS("FLASH_COMMON", FLASH);
+
/* define output sections */
SECTIONS
{
- /* The startup code goes first into FLASH */
- .isr_vector :
- {
- . = ALIGN(4);
- KEEP(*(.isr_vector)) /* Startup code */
-
- . = ALIGN(4);
- } >FLASH
-
- /* The program code and other data goes into FLASH */
- .text :
- {
- . = ALIGN(4);
- *(.text*) /* .text* sections (code) */
- *(.rodata*) /* .rodata* sections (constants, strings, etc.) */
- /* *(.glue_7) */ /* glue arm to thumb code */
- /* *(.glue_7t) */ /* glue thumb to arm code */
-
- . = ALIGN(4);
- _etext = .; /* define a global symbol at end of code */
- } >FLASH
-
+ INCLUDE common_isr.ld
+ INCLUDE common_text.ld
INCLUDE common_extratext_data_in_flash.ld
INCLUDE common_bss_heap_stack.ld
}
diff --git a/ports/stm32/boards/common_bl.ld b/ports/stm32/boards/common_bl.ld
index 21d809a3d233..b17fe9874313 100644
--- a/ports/stm32/boards/common_bl.ld
+++ b/ports/stm32/boards/common_bl.ld
@@ -12,31 +12,13 @@
ENTRY(Reset_Handler)
+REGION_ALIAS("FLASH_COMMON", FLASH_APP);
+
/* define output sections */
SECTIONS
{
- /* The startup code goes first into FLASH */
- .isr_vector :
- {
- . = ALIGN(4);
- KEEP(*(.isr_vector)) /* Startup code */
-
- . = ALIGN(4);
- } >FLASH_APP
-
- /* The program code and other data goes into FLASH */
- .text :
- {
- . = ALIGN(4);
- *(.text*) /* .text* sections (code) */
- *(.rodata*) /* .rodata* sections (constants, strings, etc.) */
- /* *(.glue_7) */ /* glue arm to thumb code */
- /* *(.glue_7t) */ /* glue thumb to arm code */
-
- . = ALIGN(4);
- _etext = .; /* define a global symbol at end of code */
- } >FLASH_APP
-
- INCLUDE common_extratext_data_in_flash_app.ld
+ INCLUDE common_isr.ld
+ INCLUDE common_text.ld
+ INCLUDE common_extratext_data_in_flash.ld
INCLUDE common_bss_heap_stack.ld
}
diff --git a/ports/stm32/boards/common_blifs.ld b/ports/stm32/boards/common_blifs.ld
index 5517a2d09c69..51969e1f9067 100644
--- a/ports/stm32/boards/common_blifs.ld
+++ b/ports/stm32/boards/common_blifs.ld
@@ -12,31 +12,13 @@
ENTRY(Reset_Handler)
+REGION_ALIAS("FLASH_COMMON", FLASH_TEXT);
+
/* define output sections */
SECTIONS
{
- /* The startup code goes first into FLASH */
- .isr_vector :
- {
- . = ALIGN(4);
- KEEP(*(.isr_vector)) /* Startup code */
-
- . = ALIGN(4);
- } >FLASH_TEXT
-
- /* The program code and other data goes into FLASH */
- .text :
- {
- . = ALIGN(4);
- *(.text*) /* .text* sections (code) */
- *(.rodata*) /* .rodata* sections (constants, strings, etc.) */
- /* *(.glue_7) */ /* glue arm to thumb code */
- /* *(.glue_7t) */ /* glue thumb to arm code */
-
- . = ALIGN(4);
- _etext = .; /* define a global symbol at end of code */
- } >FLASH_TEXT
-
- INCLUDE common_extratext_data_in_flash_text.ld
+ INCLUDE common_isr.ld
+ INCLUDE common_text.ld
+ INCLUDE common_extratext_data_in_flash.ld
INCLUDE common_bss_heap_stack.ld
}
diff --git a/ports/stm32/boards/common_bss_heap_stack.ld b/ports/stm32/boards/common_bss_heap_stack.ld
index 1bb2249e96c9..b079313c444b 100644
--- a/ports/stm32/boards/common_bss_heap_stack.ld
+++ b/ports/stm32/boards/common_bss_heap_stack.ld
@@ -26,3 +26,7 @@
. = . + _minimum_stack_size;
. = ALIGN(4);
} >RAM
+
+/* _bl_state symbol is used by MICROPY_HW_ENTER_BOOTLOADER_VIA_RESET, this is
+ the end of stack address but is accessed as a different type. */
+_bl_state = _estack;
diff --git a/ports/stm32/boards/common_extratext_data_in_flash.ld b/ports/stm32/boards/common_extratext_data_in_flash.ld
index eb9b86f49d8e..db4306641b71 100644
--- a/ports/stm32/boards/common_extratext_data_in_flash.ld
+++ b/ports/stm32/boards/common_extratext_data_in_flash.ld
@@ -6,7 +6,7 @@
__exidx_start = .;
*(.ARM.exidx*)
__exidx_end = .;
-} >FLASH
+} >FLASH_COMMON
/* Used by the start-up code to initialise data */
_sidata = LOADADDR(.data);
@@ -19,4 +19,4 @@ _sidata = LOADADDR(.data);
*(.data*)
. = ALIGN(4);
_edata = .;
-} >RAM AT> FLASH
+} >RAM AT> FLASH_COMMON
diff --git a/ports/stm32/boards/common_extratext_data_in_flash_app.ld b/ports/stm32/boards/common_extratext_data_in_flash_app.ld
deleted file mode 100644
index aba6bf57c88a..000000000000
--- a/ports/stm32/boards/common_extratext_data_in_flash_app.ld
+++ /dev/null
@@ -1,22 +0,0 @@
-/* This linker script fragment is intended to be included in SECTIONS. */
-
-/* For C++ exception handling */
-.ARM :
-{
- __exidx_start = .;
- *(.ARM.exidx*)
- __exidx_end = .;
-} >FLASH_APP
-
-/* Used by the start-up code to initialise data */
-_sidata = LOADADDR(.data);
-
-/* Initialised data section, start-up code will copy it from flash to RAM */
-.data :
-{
- . = ALIGN(4);
- _sdata = .;
- *(.data*)
- . = ALIGN(4);
- _edata = .;
-} >RAM AT> FLASH_APP
diff --git a/ports/stm32/boards/common_extratext_data_in_flash_text.ld b/ports/stm32/boards/common_extratext_data_in_flash_text.ld
deleted file mode 100644
index 5a29e47307a6..000000000000
--- a/ports/stm32/boards/common_extratext_data_in_flash_text.ld
+++ /dev/null
@@ -1,22 +0,0 @@
-/* This linker script fragment is intended to be included in SECTIONS. */
-
-/* For C++ exception handling */
-.ARM :
-{
- __exidx_start = .;
- *(.ARM.exidx*)
- __exidx_end = .;
-} >FLASH_TEXT
-
-/* Used by the start-up code to initialise data */
-_sidata = LOADADDR(.data);
-
-/* Initialised data section, start-up code will copy it from flash to RAM */
-.data :
-{
- . = ALIGN(4);
- _sdata = .;
- *(.data*)
- . = ALIGN(4);
- _edata = .;
-} >RAM AT> FLASH_TEXT
diff --git a/ports/stm32/boards/common_ifs.ld b/ports/stm32/boards/common_ifs.ld
index 733ca12f675b..1876e4156140 100644
--- a/ports/stm32/boards/common_ifs.ld
+++ b/ports/stm32/boards/common_ifs.ld
@@ -13,6 +13,8 @@
ENTRY(Reset_Handler)
+REGION_ALIAS("FLASH_COMMON", FLASH_TEXT);
+
/* define output sections */
SECTIONS
{
@@ -41,19 +43,7 @@ SECTIONS
. = ALIGN(4);
} >FLASH_ISR
- /* The program code and other data goes into FLASH */
- .text :
- {
- . = ALIGN(4);
- *(.text*) /* .text* sections (code) */
- *(.rodata*) /* .rodata* sections (constants, strings, etc.) */
- /* *(.glue_7) */ /* glue arm to thumb code */
- /* *(.glue_7t) */ /* glue thumb to arm code */
-
- . = ALIGN(4);
- _etext = .; /* define a global symbol at end of code */
- } >FLASH_TEXT
-
- INCLUDE common_extratext_data_in_flash_text.ld
+ INCLUDE common_text.ld
+ INCLUDE common_extratext_data_in_flash.ld
INCLUDE common_bss_heap_stack.ld
}
diff --git a/ports/stm32/boards/common_isr.ld b/ports/stm32/boards/common_isr.ld
new file mode 100644
index 000000000000..0f9b8bcaaddf
--- /dev/null
+++ b/ports/stm32/boards/common_isr.ld
@@ -0,0 +1,9 @@
+/* This linker script fragment is intended to be included in SECTIONS. */
+
+/* The startup code goes first into FLASH */
+.isr_vector :
+{
+ . = ALIGN(4);
+ KEEP(*(.isr_vector)) /* Startup code */
+ . = ALIGN(4);
+} >FLASH_COMMON
diff --git a/ports/stm32/boards/common_text.ld b/ports/stm32/boards/common_text.ld
new file mode 100644
index 000000000000..16eea43bae2c
--- /dev/null
+++ b/ports/stm32/boards/common_text.ld
@@ -0,0 +1,14 @@
+/* This linker script fragment is intended to be included in SECTIONS. */
+
+/* The program code and other data goes into FLASH */
+.text :
+{
+ . = ALIGN(4);
+ *(.text*) /* .text* sections (code) */
+ *(.rodata*) /* .rodata* sections (constants, strings, etc.) */
+/* *(.glue_7) */ /* glue arm to thumb code */
+/* *(.glue_7t) */ /* glue thumb to arm code */
+
+ . = ALIGN(4);
+ _etext = .; /* define a global symbol at end of code */
+} >FLASH_COMMON
diff --git a/ports/stm32/boards/make-pins.py b/ports/stm32/boards/make-pins.py
index 4e895f8f6040..002a6f75f261 100755
--- a/ports/stm32/boards/make-pins.py
+++ b/ports/stm32/boards/make-pins.py
@@ -506,7 +506,6 @@ def print_af_hdr(self, af_const_filename):
def print_af_defs(self, af_defs_filename, cmp_strings):
with open(af_defs_filename, "wt") as af_defs_file:
-
STATIC_AF_TOKENS = {}
for named_pin in self.cpu_pins:
for af in named_pin.pin().alt_fn:
diff --git a/ports/stm32/boards/manifest.py b/ports/stm32/boards/manifest.py
index db7c1acae10a..79b16b9a7b1a 100644
--- a/ports/stm32/boards/manifest.py
+++ b/ports/stm32/boards/manifest.py
@@ -1,5 +1,5 @@
-include("$(MPY_DIR)/extmod/uasyncio/manifest.py")
-freeze("$(MPY_DIR)/drivers/dht", "dht.py")
+include("$(MPY_DIR)/extmod/uasyncio")
+require("dht")
+require("onewire")
freeze("$(MPY_DIR)/drivers/display", ("lcd160cr.py", "lcd160cr_test.py"))
-freeze("$(MPY_DIR)/drivers/onewire", "onewire.py")
freeze("$(MPY_DIR)/lib/lv_bindings/lib", "lv_utils.py")
diff --git a/ports/stm32/boards/manifest_pyboard.py b/ports/stm32/boards/manifest_pyboard.py
new file mode 100644
index 000000000000..789365a43307
--- /dev/null
+++ b/ports/stm32/boards/manifest_pyboard.py
@@ -0,0 +1 @@
+require("lcd160cr")
diff --git a/ports/stm32/boards/pllvalues.py b/ports/stm32/boards/pllvalues.py
index e0fff40dd3fe..76320cc9c383 100644
--- a/ports/stm32/boards/pllvalues.py
+++ b/ports/stm32/boards/pllvalues.py
@@ -94,7 +94,7 @@ def compute_pll2(hse, sys, relax_pll48):
fallback = None
for P in mcu.range_p:
# VCO_OUT must be between 192MHz and 432MHz
- if not sys * P in mcu.range_vco_out:
+ if sys * P not in mcu.range_vco_out:
continue
NbyM = float(sys * P) / hse # float for Python 2
# scan M
diff --git a/ports/stm32/boards/stm32f091xc.ld b/ports/stm32/boards/stm32f091xc.ld
index 5bcc4c7275de..a8f0d3316ebf 100644
--- a/ports/stm32/boards/stm32f091xc.ld
+++ b/ports/stm32/boards/stm32f091xc.ld
@@ -5,8 +5,8 @@
/* Specify the memory areas */
MEMORY
{
- FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 256K
- FLASH_TEXT (rx) : ORIGIN = 0x08000000, LENGTH = 256K
+ FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 236K /* sectors 0-117 */
+ FLASH_FS (r) : ORIGIN = 0x0803B000, LENGTH = 20K /* sectors 118-127 */
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 32K
}
@@ -14,13 +14,21 @@ MEMORY
_minimum_stack_size = 2K;
_minimum_heap_size = 16K;
-/* Define the stack. The stack is full descending so begins just above last byte above last byte
- of RAM. Note that EABI requires the stack to be 8-byte aligned for a call. */
-_estack = ORIGIN(RAM) + LENGTH(RAM) - _estack_reserve;
-_sstack = _estack - 6K; /* tunable */
+/* Define the stack. The stack is full descending so begins just above last byte of RAM,
+ or bottom of FS cache. Note that EABI requires the stack to be 8-byte aligned for a call. */
/* RAM extents for the garbage collector */
_ram_start = ORIGIN(RAM);
_ram_end = ORIGIN(RAM) + LENGTH(RAM);
+
+_micropy_hw_internal_flash_storage_ram_cache_end = _ram_end;
+_micropy_hw_internal_flash_storage_ram_cache_start = _micropy_hw_internal_flash_storage_ram_cache_end - 2K; /* fs cache = 2K */
+
+_estack = _micropy_hw_internal_flash_storage_ram_cache_start - _estack_reserve;
+_sstack = _estack - 6K; /* tunable */
+
_heap_start = _ebss; /* heap starts just after statically allocated memory */
_heap_end = _sstack;
+
+_micropy_hw_internal_flash_storage_start = ORIGIN(FLASH_FS);
+_micropy_hw_internal_flash_storage_end = ORIGIN(FLASH_FS) + LENGTH(FLASH_FS);
diff --git a/ports/stm32/boards/stm32f446_af.csv b/ports/stm32/boards/stm32f446_af.csv
new file mode 100644
index 000000000000..0838ed089d8f
--- /dev/null
+++ b/ports/stm32/boards/stm32f446_af.csv
@@ -0,0 +1,116 @@
+Port,,AF0,AF1,AF2,AF3,AF4,AF5,AF6,AF7,AF8,AF9,AF10,AF11,AF12,AF13,AF14,AF15,
+,,SYS,TIM1/2,TIM3/4/5,TIM8/9/10/11/CEC,I2C1/2/3/4/CEC,SPI1/2/3/4,SPI2/3/4/SAI1,SPI2/3/USART1/2/3/UART5/SPDIFRX,SAI/USART6/UART4/5/SPDIFRX,CAN1/2/TIM12/13/14/QUADSPI,SAI2/QUADSPI/OTG2_HS/OTG1_FS,OTG1_FS,FMC/SDIO/OTG2_FS,DCMI,,SYS,
+PortA,PA0,,TIM2_CH1/TIM2_ETR,TIM5_CH1,TIM8_ETR,,,,USART2_CTS,UART4_TX,,,,,,,EVENTOUT,ADC123_IN0
+PortA,PA1,,TIM2_CH2,TIM5_CH2,,,,,USART2_RTS,UART4_RX,QUADSPI_BK1_IO3,SAI2_MCLK_B,,,,,EVENTOUT,ADC123_IN1
+PortA,PA2,,TIM2_CH3,TIM5_CH3,TIM9_CH1,,,,USART2_TX,SAI2_SCK_B,,,,,,,EVENTOUT,ADC123_IN2
+PortA,PA3,,TIM2_CH4,TIM5_CH4,TIM9_CH2,,,SAI1_FS_A,USART2_RX,,,OTG_HS_ULPI_D0,,,,,EVENTOUT,ADC123_IN3
+PortA,PA4,,,,,,SPI1_NSS/I2S1_WS,SPI3_NSS/I2S3_WS,USART2_CK,,,,,OTG_HS_SOF,DCMI_HSYNC,,EVENTOUT,ADC12_IN4
+PortA,PA5,,TIM2_CH1/TIM2_ETR,,TIM8_CH1N,,SPI1_SCK/I2S1_CK,,,,,OTG_HS_ULPI_CK,,,,,EVENTOUT,ADC12_IN5
+PortA,PA6,,TIM1_BKIN,TIM3_CH1,TIM8_BKIN,,SPI1_MISO,I2S2_MCK,,,TIM13_CH1,,,,DCMI_PIXCLK,,EVENTOUT,ADC12_IN6
+PortA,PA7,,TIM1_CH1N,TIM3_CH2,TIM8_CH1N,,SPI1_MOSI/I2S1_SD,,,,TIM14_CH1,,,FMC_SDNWE,,,EVENTOUT,ADC12_IN7
+PortA,PA8,MCO1,TIM1_CH1,,,I2C3_SCL,,,USART1_CK,,,OTG_FS_SOF,,,,,EVENTOUT,
+PortA,PA9,,TIM1_CH2,,,I2C3_SMBA,SPI2_SCK/I2S2_CK,SAI1_SD_B,USART1_TX,,,,,,DCMI_D0,,EVENTOUT,
+PortA,PA10,,TIM1_CH3,,,,,,USART1_RX,,,OTG_FS_ID,,,DCMI_D1,,EVENTOUT,
+PortA,PA11,,TIM1_CH4,,,,,,USART1_CTS,,CAN1_RX,OTG_FS_DM,,,,,EVENTOUT,
+PortA,PA12,,TIM1_ETR,,,,,,USART1_RTS,SAI2_FS_B,CAN1_TX,OTG_FS_DP,,,,,EVENTOUT,
+PortA,PA13,JTMS/SWDIO,,,,,,,,,,,,,,,EVENTOUT,
+PortA,PA14,JTCK/SWCLK,,,,,,,,,,,,,,,EVENTOUT,
+PortA,PA15,JTDI,TIM2_CH1/TIM2_ETR,,,HDMI_CEC,SPI1_NSS/I2S1_WS,SPI3_NSS/I2S3_WS,,UART4_RTS,,,,,,,EVENTOUT,
+PortB,PB0,,TIM1_CH2N,TIM3_CH3,TIM8_CH2N,,,,SPI3_MOSI/I2S3_SD,UART4_CTS,,OTG_HS_ULPI_D1,,SDIO_D1,,,EVENTOUT,ADC12_IN8
+PortB,PB1,,TIM1_CH3N,TIM3_CH4,TIM8_CH3N,,,,,,,OTG_HS_ULPI_D2,,SDIO_D2,,,EVENTOUT,ADC12_IN9
+PortB,PB2,,TIM2_CH4,,,,,SAI1_SD_A,SPI3_MOSI/I2S3_SD,,QUADSPI_CLK,OTG_HS_ULPI_D4,,SDIO_CK,,,EVENTOUT,
+PortB,PB3,JTDO/TRACESWO,TIM2_CH2,,,I2C2_SDA,SPI1_SCK/I2S1_CK,SPI3_SCK/I2S3_CK,,,,,,,,,EVENTOUT,
+PortB,PB4,NJTRST,,TIM3_CH1,,I2C3_SDA,SPI1_MISO,SPI3_MISO,SPI2_NSS/I2S2_WS,,,,,,,,EVENTOUT,
+PortB,PB5,,,TIM3_CH2,,I2C1_SMBA,SPI1_MOSI/I2S1_SD,SPI3_MOSI/I2S3_SD,,,CAN2_RX,OTG_HS_ULPI_D7,,FMC_SDCKE1,DCMI_D10,,EVENTOUT,
+PortB,PB6,,,TIM4_CH1,HDMI_CEC,I2C1_SCL,,,USART1_TX,,CAN2_TX,QUADSPI_BK1_NCS,,FMC_SDNE1,DCMI_D5,,EVENTOUT,
+PortB,PB7,,,TIM4_CH2,,I2C1_SDA,,,USART1_RX,SPDIF_RX0,,,,FMC_NL,DCMI_VSYNC,,EVENTOUT,
+PortB,PB8,,TIM2_CH1/TIM2_ETR,TIM4_CH3,TIM10_CH1,I2C1_SCL,,,,,CAN1_RX,,,SDIO_D4,DCMI_D6,,EVENTOUT,
+PortB,PB9,,TIM2_CH2,TIM4_CH4,TIM11_CH1,I2C1_SDA,SPI2_NSS/I2S2_WS,SAI1_FS_B,,,CAN1_TX,,,SDIO_D5,DCMI_D7,,EVENTOUT,
+PortB,PB10,,TIM2_CH3,,,I2C2_SCL,SPI2_SCK/I2S2_CK,SAI1_SCK_A,USART3_TX,,,OTG_HS_ULPI_D3,,,,,EVENTOUT,
+PortB,PB11,,TIM2_CH4,,,I2C2_SDA,,,USART3_RX,SAI2_SD_A,,,,,,,EVENTOUT,
+PortB,PB12,,TIM1_BKIN,,,I2C2_SMBA,SPI2_NSS/I2S2_WS,SAI1_SCK_B,USART3_CK,,CAN2_RX,OTG_HS_ULPI_D5,,OTG_HS_ID,,,EVENTOUT,
+PortB,PB13,,TIM1_CH1N,,,,SPI2_SCK/I2S2_CK,,USART3_CTS,,CAN2_TX,OTG_HS_ULPI_D6,,,,,EVENTOUT,
+PortB,PB14,,TIM1_CH2N,,TIM8_CH2N,,SPI2_MISO,,USART3_RTS,,TIM12_CH1,,,OTG_HS_DM,,,EVENTOUT,
+PortB,PB15,RTC_REFIN,TIM1_CH3N,,TIM8_CH3N,,SPI2_MOSI/I2S2_SD,,,,TIM12_CH2,,,OTG_HS_DP,,,EVENTOUT,
+PortC,PC0,,,,,,,SAI1_MCLK_B,,,,OTG_HS_ULPI_STP,,FMC_SDNWE,,,EVENTOUT,ADC123_IN10
+PortC,PC1,,,,,,SPI3_MOSI/I2S3_SD,SAI1_SD_A,SPI2_MOSI/I2S2_SD,,,,,,,,EVENTOUT,ADC123_IN11
+PortC,PC2,,,,,,SPI2_MISO,,,,,OTG_HS_ULPI_DIR,,FMC_SDNE0,,,EVENTOUT,ADC123_IN12
+PortC,PC3,,,,,,SPI2_MOSI/I2S2_SD,,,,,OTG_HS_ULPI_NXT,,FMC_SDCKE0,,,EVENTOUT,ADC123_IN13
+PortC,PC4,,,,,,I2S1_MCK,,,SPDIF_RX2,,,,FMC_SDNE0,,,EVENTOUT,ADC12_IN14
+PortC,PC5,,,,,,,,USART3_RX,SPDIF_RX3,,,,FMC_SDCKE0,,,EVENTOUT,ADC12_IN15
+PortC,PC6,,,TIM3_CH1,TIM8_CH1,FMPI2C1_SCL,I2S2_MCK,,,USART6_TX,,,,SDIO_D6,DCMI_D0,,EVENTOUT,
+PortC,PC7,,,TIM3_CH2,TIM8_CH2,FMPI2C1_SDA,SPI2_SCK/I2S2_CK,I2S3_MCK,SPDIF_RX1,USART6_RX,,,,SDIO_D7,DCMI_D1,,EVENTOUT,
+PortC,PC8,TRACED0,,TIM3_CH3,TIM8_CH3,,,,UART5_RTS,USART6_CK,,,,SDIO_D0,DCMI_D2,,EVENTOUT,
+PortC,PC9,MCO2,,TIM3_CH4,TIM8_CH4,I2C3_SDA,I2S_CKIN,,UART5_CTS,,QUADSPI_BK1_IO0,,,SDIO_D1,DCMI_D3,,EVENTOUT,
+PortC,PC10,,,,,,,SPI3_SCK/I2S3_CK,USART3_TX,UART4_TX,QUADSPI_BK1_IO1,,,SDIO_D2,DCMI_D8,,EVENTOUT,
+PortC,PC11,,,,,,,SPI3_MISO,USART3_RX,UART4_RX,QUADSPI_BK2_NCS,,,SDIO_D3,DCMI_D4,,EVENTOUT,
+PortC,PC12,,,,,I2C2_SDA,,SPI3_MOSI/I2S3_SD,USART3_CK,UART5_TX,,,,SDIO_CK,DCMI_D9,,EVENTOUT,
+PortC,PC13,,,,,,,,,,,,,,,,EVENTOUT,
+PortC,PC14,,,,,,,,,,,,,,,,EVENTOUT,
+PortC,PC15,,,,,,,,,,,,,,,,EVENTOUT,
+PortD,PD0,,,,,,SPI4_MISO,SPI3_MOSI/I2S3_SD,,,CAN1_RX,,,FMC_D2,,,EVENTOUT,
+PortD,PD1,,,,,,,,SPI2_NSS/I2S2_WS,,CAN1_TX,,,FMC_D3,,,EVENTOUT,
+PortD,PD2,,,TIM3_ETR,,,,,,UART5_RX,,,,SDIO_CMD,DCMI_D11,,EVENTOUT,
+PortD,PD3,TRACED1,,,,,SPI2_SCK/I2S2_CK,,USART2_CTS,,QUADSPI_CLK,,,FMC_CLK,DCMI_D5,,EVENTOUT,
+PortD,PD4,,,,,,,,USART2_RTS,,,,,FMC_NOE,,,EVENTOUT,
+PortD,PD5,,,,,,,,USART2_TX,,,,,FMC_NWE,,,EVENTOUT,
+PortD,PD6,,,,,,SPI3_MOSI/I2S3_SD,SAI1_SD_A,USART2_RX,,,,,FMC_NWAIT,DCMI_D10,,EVENTOUT,
+PortD,PD7,,,,,,,,USART2_CK,SPDIF_RX0,,,,FMC_NE1,,,EVENTOUT,
+PortD,PD8,,,,,,,,USART3_TX,SPDIF_RX1,,,,FMC_D13,,,EVENTOUT,
+PortD,PD9,,,,,,,,USART3_RX,,,,,FMC_D14,,,EVENTOUT,
+PortD,PD10,,,,,,,,USART3_CK,,,,,FMC_D15,,,EVENTOUT,
+PortD,PD11,,,,,FMPI2C1_SMBA,,,USART3_CTS,,QUADSPI_BK1_IO0,SAI2_SD_A,,FMC_A16,,,EVENTOUT,
+PortD,PD12,,,TIM4_CH1,,FMPI2C1_SCL,,,USART3_RTS,,QUADSPI_BK1_IO1,SAI2_FS_A,,FMC_A17,,,EVENTOUT,
+PortD,PD13,,,TIM4_CH2,,FMPI2C1_SDA,,,,,QUADSPI_BK1_IO3,SAI2_SCK_A,,FMC_A18,,,EVENTOUT,
+PortD,PD14,,,TIM4_CH3,,FMPI2C1_SCL,,,,SAI2_SCK_A,,,,FMC_D0,,,EVENTOUT,
+PortD,PD15,,,TIM4_CH4,,FMPI2C1_SDA,,,,,,,,FMC_D1,,,EVENTOUT,
+PortE,PE0,,,TIM4_ETR,,,,,,,,SAI2_MCLK_A,,FMC_NBL0,DCMI_D2,,EVENTOUT,
+PortE,PE1,,,,,,,,,,,,,FMC_NBL1,DCMI_D3,,EVENTOUT,
+PortE,PE2,TRACECLK,,,,,SPI4_SCK,SAI1_MCLK_A,,,QUADSPI_BK1_IO2,,,FMC_A23,,,EVENTOUT,
+PortE,PE3,TRACED0,,,,,,SAI1_SD_B,,,,,,FMC_A19,,,EVENTOUT,
+PortE,PE4,TRACED1,,,,,SPI4_NSS,SAI1_FS_A,,,,,,FMC_A20,DCMI_D4,,EVENTOUT,
+PortE,PE5,TRACED2,,,TIM9_CH1,,SPI4_MISO,SAI1_SCK_A,,,,,,FMC_A21,DCMI_D6,,EVENTOUT,
+PortE,PE6,TRACED3,,,TIM9_CH2,,SPI4_MOSI,SAI1_SD_A,,,,,,FMC_A22,DCMI_D7,,EVENTOUT,
+PortE,PE7,,TIM1_ETR,,,,,,,UART5_RX,,QUADSPI_BK2_IO0,,FMC_D4,,,EVENTOUT,
+PortE,PE8,,TIM1_CH1N,,,,,,,UART5_TX,,QUADSPI_BK2_IO1,,FMC_D5,,,EVENTOUT,
+PortE,PE9,,TIM1_CH1,,,,,,,,,QUADSPI_BK2_IO2,,FMC_D6,,,EVENTOUT,
+PortE,PE10,,TIM1_CH2N,,,,,,,,,QUADSPI_BK2_IO3,,FMC_D7,,,EVENTOUT,
+PortE,PE11,,TIM1_CH2,,,,SPI4_NSS,,,,,SAI2_SD_B,,FMC_D8,,,EVENTOUT,
+PortE,PE12,,TIM1_CH3N,,,,SPI4_SCK,,,,,SAI2_SCK_B,,FMC_D9,,,EVENTOUT,
+PortE,PE13,,TIM1_CH3,,,,SPI4_MISO,,,,,SAI2_FS_B,,FMC_D10,,,EVENTOUT,
+PortE,PE14,,TIM1_CH4,,,,SPI4_MOSI,,,,,SAI2_MCLK_B,,FMC_D11,,,EVENTOUT,
+PortE,PE15,,TIM1_BKIN,,,,,,,,,,,FMC_D12,,,EVENTOUT,
+PortF,PF0,,,,,I2C2_SDA,,,,,,,,FMC_A0,,,EVENTOUT,
+PortF,PF1,,,,,I2C2_SCL,,,,,,,,FMC_A1,,,EVENTOUT,
+PortF,PF2,,,,,I2C2_SMBA,,,,,,,,FMC_A2,,,EVENTOUT,
+PortF,PF3,,,,,,,,,,,,,FMC_A3,,,EVENTOUT,ADC3_IN9
+PortF,PF4,,,,,,,,,,,,,FMC_A4,,,EVENTOUT,ADC3_IN14
+PortF,PF5,,,,,,,,,,,,,FMC_A5,,,EVENTOUT,ADC3_IN15
+PortF,PF6,,,,TIM10_CH1,,,SAI1_SD_B,,,QUADSPI_BK1_IO3,,,,,,EVENTOUT,ADC3_IN4
+PortF,PF7,,,,TIM11_CH1,,,SAI1_MCLK_B,,,QUADSPI_BK1_IO2,,,,,,EVENTOUT,ADC3_IN5
+PortF,PF8,,,,,,,SAI1_SCK_B,,,TIM13_CH1,QUADSPI_BK1_IO0,,,,,EVENTOUT,ADC3_IN6
+PortF,PF9,,,,,,,SAI1_FS_B,,,TIM14_CH1,QUADSPI_BK1_IO1,,,,,EVENTOUT,ADC3_IN7
+PortF,PF10,,,,,,,,,,,,,,DCMI_D11,,EVENTOUT,ADC3_IN8
+PortF,PF11,,,,,,,,,,,SAI2_SD_B,,FMC_SDNRAS,DCMI_D12,,EVENTOUT,
+PortF,PF12,,,,,,,,,,,,,FMC_A6,,,EVENTOUT,
+PortF,PF13,,,,,FMPI2C1_SMBA,,,,,,,,FMC_A7,,,EVENTOUT,
+PortF,PF14,,,,,FMPI2C1_SCL,,,,,,,,FMC_A8,,,EVENTOUT,
+PortF,PF15,,,,,FMPI2C1_SDA,,,,,,,,FMC_A9,,,EVENTOUT,
+PortG,PG0,,,,,,,,,,,,,FMC_A10,,,EVENTOUT,
+PortG,PG1,,,,,,,,,,,,,FMC_A11,,,EVENTOUT,
+PortG,PG2,,,,,,,,,,,,,FMC_A12,,,EVENTOUT,
+PortG,PG3,,,,,,,,,,,,,FMC_A13,,,EVENTOUT,
+PortG,PG4,,,,,,,,,,,,,FMC_A14/FMC_BA0,,,EVENTOUT,
+PortG,PG5,,,,,,,,,,,,,FMC_A15/FMC_BA1,,,EVENTOUT,
+PortG,PG6,,,,,,,,,,,QUADSPI_BK1_NCS,,,DCMI_D12,,EVENTOUT,
+PortG,PG7,,,,,,,,,USART6_CK,,,,FMC_INT,DCMI_D13,,EVENTOUT,
+PortG,PG8,,,,,,,,SPDIFRX_IN2,USART6_RTS,,,,FMC_SDCLK,,,EVENTOUT,
+PortG,PG9,,,,,,,,SPDIFRX_IN3,USART6_RX,QUADSPI_BK2_IO2,SAI2_FS_B,,FMC_NE2/FMC_NCE3,DCMI_VSYNC,,EVENTOUT,
+PortG,PG10,,,,,,,,,,,SAI2_SD_B,,FMC_NE3,DCMI_D2,,EVENTOUT,
+PortG,PG11,,,,,,,SPI4_SCK,SPDIFRX_IN0,,,,,,DCMI_D3,,EVENTOUT,
+PortG,PG12,,,,,,,SPI4_MISO,SPDIFRX_IN1,USART6_RTS,,,,FMC_NE4,,,EVENTOUT,
+PortG,PG13,TRACED2,,,,,,SPI4_MOSI,,USART6_CTS,,,,FMC_A24,,,EVENTOUT,
+PortG,PG14,TRACED3,,,,,,SPI4_NSS,,USART6_TX,QUADSPI_BK2_IO3,,,FMC_A25,,,EVENTOUT,
+PortG,PG15,,,,,,,,,USART6_CTS,,,,FMC_SDNCAS,DCMI_D13,,EVENTOUT,
+PortH,PH0,,,,,,,,,,,,,,,,EVENTOUT,
+PortH,PH1,,,,,,,,,,,,,,,,EVENTOUT,
diff --git a/ports/stm32/boards/stm32g0b1xe.ld b/ports/stm32/boards/stm32g0b1xe.ld
index 4fe61a472ff7..8ec81e5bf9bb 100644
--- a/ports/stm32/boards/stm32g0b1xe.ld
+++ b/ports/stm32/boards/stm32g0b1xe.ld
@@ -3,6 +3,7 @@ MEMORY
{
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 352K
+ FLASH_APP (rx) : ORIGIN = 0x08008000, LENGTH = 320K
FLASH_FS (rx) : ORIGIN = 0x08058000, LENGTH = 160K /* starting @ 352K */
}
diff --git a/ports/stm32/boards/stm32g0xx_hal_conf_base.h b/ports/stm32/boards/stm32g0xx_hal_conf_base.h
index fc49ca945f3f..5ddcb0fa434b 100644
--- a/ports/stm32/boards/stm32g0xx_hal_conf_base.h
+++ b/ports/stm32/boards/stm32g0xx_hal_conf_base.h
@@ -27,16 +27,42 @@
#ifndef MICROPY_INCLUDED_STM32G0XX_HAL_CONF_BASE_H
#define MICROPY_INCLUDED_STM32G0XX_HAL_CONF_BASE_H
+// Enable various HAL modules
+#define HAL_MODULE_ENABLED
+#define HAL_ADC_MODULE_ENABLED
+#define HAL_CORTEX_MODULE_ENABLED
+#define HAL_DMA_MODULE_ENABLED
+#define HAL_EXTI_MODULE_ENABLED
+#define HAL_FLASH_MODULE_ENABLED
+#define HAL_GPIO_MODULE_ENABLED
+#define HAL_I2C_MODULE_ENABLED
+#define HAL_PCD_MODULE_ENABLED
+#define HAL_PWR_MODULE_ENABLED
+#define HAL_RCC_MODULE_ENABLED
+#define HAL_RTC_MODULE_ENABLED
+#define HAL_SPI_MODULE_ENABLED
+#define HAL_TIM_MODULE_ENABLED
+#define HAL_UART_MODULE_ENABLED
+#define HAL_USART_MODULE_ENABLED
+
// Oscillator values in Hz
-// These must come before the HAL headers because stm32g0xx_ll_rcc.h will define HSI_VALUE unless already defined
#define HSI_VALUE (16000000)
#define LSI_VALUE (32000)
#if defined(STM32G0C1xx) || defined(STM32G0B1xx) || defined(STM32G0B0xx)
#define HSI48_VALUE 48000000
#endif
-// Include various HAL modules for convenience
+// SysTick has the highest priority
+#define TICK_INT_PRIORITY (0x00)
+
+// Miscellaneous HAL settings
+#define USE_RTOS 0
+#define PREFETCH_ENABLE 1
+#define INSTRUCTION_CACHE_ENABLE 1
+#define USE_SPI_CRC 1
+#define USE_HAL_CRYP_SUSPEND_RESUME 1
+// Include various HAL modules for convenience
#include "stm32g0xx_hal_rcc.h"
#include "stm32g0xx_hal_gpio.h"
#include "stm32g0xx_hal_dma.h"
@@ -68,38 +94,10 @@
#include "stm32g0xx_hal_uart.h"
#include "stm32g0xx_hal_usart.h"
#include "stm32g0xx_hal_wwdg.h"
-
#include "stm32g0xx_ll_lpuart.h"
#include "stm32g0xx_ll_rtc.h"
#include "stm32g0xx_ll_usart.h"
-// Enable various HAL modules
-#define HAL_MODULE_ENABLED
-#define HAL_ADC_MODULE_ENABLED
-#define HAL_CORTEX_MODULE_ENABLED
-#define HAL_DMA_MODULE_ENABLED
-#define HAL_EXTI_MODULE_ENABLED
-#define HAL_FLASH_MODULE_ENABLED
-#define HAL_GPIO_MODULE_ENABLED
-#define HAL_I2C_MODULE_ENABLED
-#define HAL_PWR_MODULE_ENABLED
-#define HAL_RCC_MODULE_ENABLED
-#define HAL_RTC_MODULE_ENABLED
-#define HAL_SPI_MODULE_ENABLED
-#define HAL_TIM_MODULE_ENABLED
-#define HAL_UART_MODULE_ENABLED
-#define HAL_USART_MODULE_ENABLED
-
-// SysTick has the highest priority
-#define TICK_INT_PRIORITY (0x00)
-
-// Miscellaneous HAL settings
-#define USE_RTOS 0
-#define PREFETCH_ENABLE 1
-#define INSTRUCTION_CACHE_ENABLE 1
-#define USE_SPI_CRC 1
-#define USE_HAL_CRYP_SUSPEND_RESUME 1
-
// HAL parameter assertions are disabled
#define assert_param(expr) ((void)0)
diff --git a/ports/stm32/boards/stm32h723.ld b/ports/stm32/boards/stm32h723.ld
new file mode 100644
index 000000000000..d1e934ed312c
--- /dev/null
+++ b/ports/stm32/boards/stm32h723.ld
@@ -0,0 +1,46 @@
+/*
+ GNU linker script for STM32H723
+*/
+
+/* Specify the memory areas */
+MEMORY
+{
+ FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 768K /* sectors 0-5 */
+ FLASH_APP (rx) : ORIGIN = 0x08020000, LENGTH = 640K /* sectors 1-5 */
+ FLASH_FS (r) : ORIGIN = 0x080c0000, LENGTH = 256K /* sectors 6-7 */
+ DTCM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K /* Used for FS storage cache */
+ RAM (xrw) : ORIGIN = 0x24000000, LENGTH = 128K /* AXI SRAM (could extend +192K from ITCM) */
+ RAM_SRAM1 (xrw) : ORIGIN = 0x30000000, LENGTH = 16K /* SRAM1 */
+}
+
+/* produce a link error if there is not this amount of RAM for these sections */
+_minimum_stack_size = 2K;
+_minimum_heap_size = 16K;
+
+/* Define the stack. The stack is full descending so begins just above last byte
+ of RAM. Note that EABI requires the stack to be 8-byte aligned for a call. */
+_estack = ORIGIN(RAM) + LENGTH(RAM) - _estack_reserve;
+_sstack = _estack - 16K; /* tunable */
+
+/* RAM extents for the garbage collector */
+_ram_start = ORIGIN(RAM);
+_ram_end = ORIGIN(RAM) + LENGTH(RAM);
+_heap_start = _ebss; /* heap starts just after statically allocated memory */
+_heap_end = _sstack;
+
+/* Location of filesystem RAM cache */
+_micropy_hw_internal_flash_storage_ram_cache_start = ORIGIN(DTCM);
+_micropy_hw_internal_flash_storage_ram_cache_end = ORIGIN(DTCM) + LENGTH(DTCM);
+
+/* Location of filesystem flash storage */
+_micropy_hw_internal_flash_storage_start = ORIGIN(FLASH_FS);
+_micropy_hw_internal_flash_storage_end = ORIGIN(FLASH_FS) + LENGTH(FLASH_FS);
+
+/* Define output sections */
+SECTIONS
+{
+ .eth_buffers (NOLOAD) : {
+ . = ABSOLUTE(0x30000000);
+ *eth.o*(.bss.eth_dma)
+ } >RAM_SRAM1
+}
diff --git a/ports/stm32/boards/stm32h723_af.csv b/ports/stm32/boards/stm32h723_af.csv
new file mode 100644
index 000000000000..fe16b378dfa4
--- /dev/null
+++ b/ports/stm32/boards/stm32h723_af.csv
@@ -0,0 +1,116 @@
+Port,,AF0,AF1,AF2,AF3,AF4,AF5,AF6,AF7,AF8,AF9,AF10,AF11,AF12,AF13,AF14,AF15,
+,,SYS,FMC/LPTIM1/SAI4/TIM16/17/TIM1x/TIM2x,FDCAN3/PDM_SAI1/TIM3/4/5/12/15,DFSDM1/LCD/LPTIM2/3/4/5/LPUART1/OCTOSPIM_P1/2/TIM8,CEC/DCMI/PSSI/DFSDM1/I2C1/2/3/4/5/LPTIM2/OCTOSPIM_P1/TIM15/USART1/10,CEC/FDCAN3/SPI1/I2S1/SPI2/I2S2/SPI3/I2S3/SPI4/5/6,DFSDM1/I2C4/5/OCTOSPIM_P1/SAI1/SPI3/I2S3/UART4,SDMMC1/SPI2/I2S2/SPI3/I2S3/SPI6/UART7/USART1/2/3/6,LPUART1/SAI4/SDMMC1/SPDIFRX1/SPI6/UART4/5/8,FDCAN1/2/FMC/LCD/OCTOSPIM_P1/2/SAI4/SDMMC2/SPDIFRX1/TIM13/14,CRS/FMC/LCD/OCTOSPIM_P1/OTG1_FS/OTG1_HS/SAI4/SDMMC2/TIM8,DFSDM1/ETH/I2C4/LCD/MDIOS/OCTOSPIM_P1/SDMMC2/SWPMI1/TIM1x/TIM8/UART7/9/USART10,FMC/LCD/MDIOS/OCTOSPIM_P1/SDMMC1/TIM1x/TIM8,COMP/DCMI/PSSI/LCD/TIM1x/TIM23,LCD/TIM24/UART5,SYS,ADC
+PortA,PA0,,TIM2_CH1/TIM2_ETR,TIM5_CH1,TIM8_ETR,TIM15_BKIN,SPI6_NSS/I2S6_WS,,USART2_CTS/USART2_NSS,UART4_TX,SDMMC2_CMD,SAI4_SD_B,ETH_MII_CRS,FMC_A19,,,EVENTOUT,ADC123_IN0
+PortA,PA1,,TIM2_CH2,TIM5_CH2,LPTIM3_OUT,TIM15_CH1N,,,USART2_RTS/USART2_DE,UART4_RX,OCTOSPIM_P1_IO3,SAI4_MCLK_B,ETH_MII_RX_CLK/ETH_RMII_REF_CLK,OCTOSPIM_P1_DQS,,LCD_R2,EVENTOUT,ADC123_IN1
+PortA,PA2,,TIM2_CH3,TIM5_CH3,LPTIM4_OUT,TIM15_CH1,,OCTOSPIM_P1_IO0,USART2_TX,SAI4_SCK_B,,,ETH_MDIO,MDIOS_MDIO,,LCD_R1,EVENTOUT,ADC123_IN2
+PortA,PA3,,TIM2_CH4,TIM5_CH4,LPTIM5_OUT,TIM15_CH2,I2S6_MCK,OCTOSPIM_P1_IO2,USART2_RX,,LCD_B2,OTG_HS_ULPI_D0,ETH_MII_COL,OCTOSPIM_P1_CLK,,LCD_B5,EVENTOUT,ADC123_IN3
+PortA,PA4,D1PWREN,,TIM5_ETR,,,SPI1_NSS/I2S1_WS,SPI3_NSS/I2S3_WS,USART2_CK,SPI6_NSS/I2S6_WS,,,,FMC_D8/FMC_AD8,DCMI_HSYNC/PSSI_DE,LCD_VSYNC,EVENTOUT,ADC12_IN4
+PortA,PA5,D2PWREN,TIM2_CH1/TIM2_ETR,,TIM8_CH1N,,SPI1_SCK/I2S1_CK,,,SPI6_SCK/I2S6_CK,,OTG_HS_ULPI_CK,,FMC_D9/FMC_AD9,PSSI_D14,LCD_R4,EVENTOUT,ADC12_IN5
+PortA,PA6,,TIM1_BKIN,TIM3_CH1,TIM8_BKIN,,SPI1_MISO/I2S1_SDI,OCTOSPIM_P1_IO3,,SPI6_MISO/I2S6_SDI,TIM13_CH1,TIM8_BKIN_COMP12,MDIOS_MDC,TIM1_BKIN_COMP12,DCMI_PIXCLK/PSSI_PDCK,LCD_G2,EVENTOUT,ADC12_IN6
+PortA,PA7,,TIM1_CH1N,TIM3_CH2,TIM8_CH1N,,SPI1_MOSI/I2S1_SDO,,,SPI6_MOSI/I2S6_SDO,TIM14_CH1,OCTOSPIM_P1_IO2,ETH_MII_RX_DV/ETH_RMII_CRS_DV,FMC_SDNWE,,LCD_VSYNC,EVENTOUT,ADC12_IN7
+PortA,PA8,MCO1,TIM1_CH1,,TIM8_BKIN2,I2C3_SCL,,I2C5_SCL,USART1_CK,,,OTG_HS_SOF,UART7_RX,TIM8_BKIN2_COMP12,LCD_B3,LCD_R6,EVENTOUT,
+PortA,PA9,,TIM1_CH2,,LPUART1_TX,I2C3_SMBA,SPI2_SCK/I2S2_CK,I2C5_SMBA,USART1_TX,,,,ETH_TX_ER,,DCMI_D0/PSSI_D0,LCD_R5,EVENTOUT,
+PortA,PA10,,TIM1_CH3,,LPUART1_RX,,,,USART1_RX,,,OTG_HS_ID,MDIOS_MDIO,LCD_B4,DCMI_D1/PSSI_D1,LCD_B1,EVENTOUT,
+PortA,PA11,,TIM1_CH4,,LPUART1_CTS,,SPI2_NSS/I2S2_WS,UART4_RX,USART1_CTS/USART1_NSS,,FDCAN1_RX,,,,,LCD_R4,EVENTOUT,
+PortA,PA12,,TIM1_ETR,,LPUART1_RTS/LPUART1_DE,,SPI2_SCK/I2S2_CK,UART4_TX,USART1_RTS/USART1_DE,SAI4_FS_B,FDCAN1_TX,,,TIM1_BKIN2,,LCD_R5,EVENTOUT,
+PortA,PA13,JTMS/SWDIO,,,,,,,,,,,,,,,EVENTOUT,
+PortA,PA14,JTCK/SWCLK,,,,,,,,,,,,,,,EVENTOUT,
+PortA,PA15,JTDI,TIM2_CH1/TIM2_ETR,,,CEC,SPI1_NSS/I2S1_WS,SPI3_NSS/I2S3_WS,SPI6_NSS/I2S6_WS,UART4_RTS/UART4_DE,LCD_R3,,UART7_TX,,,LCD_B6,EVENTOUT,
+PortB,PB0,,TIM1_CH2N,TIM3_CH3,TIM8_CH2N,OCTOSPIM_P1_IO1,,DFSDM1_CKOUT,,UART4_CTS,LCD_R3,OTG_HS_ULPI_D1,ETH_MII_RXD2,,,LCD_G1,EVENTOUT,ADC12_IN8
+PortB,PB1,,TIM1_CH3N,TIM3_CH4,TIM8_CH3N,OCTOSPIM_P1_IO0,,DFSDM1_DATIN1,,,LCD_R6,OTG_HS_ULPI_D2,ETH_MII_RXD3,,,LCD_G0,EVENTOUT,ADC12_IN9
+PortB,PB2,RTC_OUT,SAI4_D1,SAI1_D1,,DFSDM1_CKIN1,,SAI1_SD_A,SPI3_MOSI/I2S3_SDO,SAI4_SD_A,OCTOSPIM_P1_CLK,OCTOSPIM_P1_DQS,ETH_TX_ER,,TIM23_ETR,,EVENTOUT,
+PortB,PB3,JTDO/TRACESWO,TIM2_CH2,,,,SPI1_SCK/I2S1_CK,SPI3_SCK/I2S3_CK,,SPI6_SCK/I2S6_CK,SDMMC2_D2,CRS_SYNC,UART7_RX,,,TIM24_ETR,EVENTOUT,
+PortB,PB4,NJTRST,TIM16_BKIN,TIM3_CH1,,,SPI1_MISO/I2S1_SDI,SPI3_MISO/I2S3_SDI,SPI2_NSS/I2S2_WS,SPI6_MISO/I2S6_SDI,SDMMC2_D3,,UART7_TX,,,,EVENTOUT,
+PortB,PB5,,TIM17_BKIN,TIM3_CH2,LCD_B5,I2C1_SMBA,SPI1_MOSI/I2S1_SDO,I2C4_SMBA,SPI3_MOSI/I2S3_SDO,SPI6_MOSI/I2S6_SDO,FDCAN2_RX,OTG_HS_ULPI_D7,ETH_PPS_OUT,FMC_SDCKE1,DCMI_D10/PSSI_D10,UART5_RX,EVENTOUT,
+PortB,PB6,,TIM16_CH1N,TIM4_CH1,,I2C1_SCL,CEC,I2C4_SCL,USART1_TX,LPUART1_TX,FDCAN2_TX,OCTOSPIM_P1_NCS,DFSDM1_DATIN5,FMC_SDNE1,DCMI_D5/PSSI_D5,UART5_TX,EVENTOUT,
+PortB,PB7,,TIM17_CH1N,TIM4_CH2,,I2C1_SDA,,I2C4_SDA,USART1_RX,LPUART1_RX,,,DFSDM1_CKIN5,FMC_NL,DCMI_VSYNC/PSSI_RDY,,EVENTOUT,
+PortB,PB8,,TIM16_CH1,TIM4_CH3,DFSDM1_CKIN7,I2C1_SCL,,I2C4_SCL,SDMMC1_CKIN,UART4_RX,FDCAN1_RX,SDMMC2_D4,ETH_MII_TXD3,SDMMC1_D4,DCMI_D6/PSSI_D6,LCD_B6,EVENTOUT,
+PortB,PB9,,TIM17_CH1,TIM4_CH4,DFSDM1_DATIN7,I2C1_SDA,SPI2_NSS/I2S2_WS,I2C4_SDA,SDMMC1_CDIR,UART4_TX,FDCAN1_TX,SDMMC2_D5,I2C4_SMBA,SDMMC1_D5,DCMI_D7/PSSI_D7,LCD_B7,EVENTOUT,
+PortB,PB10,,TIM2_CH3,,LPTIM2_IN1,I2C2_SCL,SPI2_SCK/I2S2_CK,DFSDM1_DATIN7,USART3_TX,,OCTOSPIM_P1_NCS,OTG_HS_ULPI_D3,ETH_MII_RX_ER,,,LCD_G4,EVENTOUT,
+PortB,PB11,,TIM2_CH4,,LPTIM2_ETR,I2C2_SDA,,DFSDM1_CKIN7,USART3_RX,,,OTG_HS_ULPI_D4,ETH_MII_TX_EN/ETH_RMII_TX_EN,,,LCD_G5,EVENTOUT,
+PortB,PB12,,TIM1_BKIN,,OCTOSPIM_P1_NCLK,I2C2_SMBA,SPI2_NSS/I2S2_WS,DFSDM1_DATIN1,USART3_CK,,FDCAN2_RX,OTG_HS_ULPI_D5,ETH_MII_TXD0/ETH_RMII_TXD0,OCTOSPIM_P1_IO0,TIM1_BKIN_COMP12,UART5_RX,EVENTOUT,
+PortB,PB13,,TIM1_CH1N,,LPTIM2_OUT,OCTOSPIM_P1_IO2,SPI2_SCK/I2S2_CK,DFSDM1_CKIN1,USART3_CTS/USART3_NSS,,FDCAN2_TX,OTG_HS_ULPI_D6,ETH_MII_TXD1/ETH_RMII_TXD1,SDMMC1_D0,DCMI_D2/PSSI_D2,UART5_TX,EVENTOUT,
+PortB,PB14,,TIM1_CH2N,TIM12_CH1,TIM8_CH2N,USART1_TX,SPI2_MISO/I2S2_SDI,DFSDM1_DATIN2,USART3_RTS/USART3_DE,UART4_RTS/UART4_DE,SDMMC2_D0,,,FMC_D10/FMC_AD10,,LCD_CLK,EVENTOUT,
+PortB,PB15,RTC_REFIN,TIM1_CH3N,TIM12_CH2,TIM8_CH3N,USART1_RX,SPI2_MOSI/I2S2_SDO,DFSDM1_CKIN2,,UART4_CTS,SDMMC2_D1,,,FMC_D11/FMC_AD11,,LCD_G7,EVENTOUT,
+PortC,PC0,,FMC_D12/FMC_AD12,,DFSDM1_CKIN0,,,DFSDM1_DATIN4,,SAI4_FS_B,FMC_A25,OTG_HS_ULPI_STP,LCD_G2,FMC_SDNWE,,LCD_R5,EVENTOUT,ADC123_IN10
+PortC,PC1,TRACED0,SAI4_D1,SAI1_D1,DFSDM1_DATIN0,DFSDM1_CKIN4,SPI2_MOSI/I2S2_SDO,SAI1_SD_A,,SAI4_SD_A,SDMMC2_CK,OCTOSPIM_P1_IO4,ETH_MDC,MDIOS_MDC,,LCD_G5,EVENTOUT,ADC123_IN11
+PortC,PC2,PWR_DEEPSLEEP,,,DFSDM1_CKIN1,OCTOSPIM_P1_IO5,SPI2_MISO/I2S2_SDI,DFSDM1_CKOUT,,,OCTOSPIM_P1_IO2,OTG_HS_ULPI_DIR,ETH_MII_TXD2,FMC_SDNE0,,,EVENTOUT,ADC123_IN12
+PortC,PC3,PWR_SLEEP,,,DFSDM1_DATIN1,OCTOSPIM_P1_IO6,SPI2_MOSI/I2S2_SDO,,,,OCTOSPIM_P1_IO0,OTG_HS_ULPI_NXT,ETH_MII_TX_CLK,FMC_SDCKE0,,,EVENTOUT,ADC123_IN13
+PortC,PC4,PWR_DEEPSLEEP,FMC_A22,,DFSDM1_CKIN2,,I2S1_MCK,,,,SPDIFRX1_IN3,SDMMC2_CKIN,ETH_MII_RXD0/ETH_RMII_RXD0,FMC_SDNE0,,LCD_R7,EVENTOUT,ADC12_IN14
+PortC,PC5,PWR_SLEEP,SAI4_D3,SAI1_D3,DFSDM1_DATIN2,PSSI_D15,,,,,SPDIFRX1_IN4,OCTOSPIM_P1_DQS,ETH_MII_RXD1/ETH_RMII_RXD1,FMC_SDCKE0,COMP1_OUT,LCD_DE,EVENTOUT,ADC12_IN15
+PortC,PC6,,,TIM3_CH1,TIM8_CH1,DFSDM1_CKIN3,I2S2_MCK,,USART6_TX,SDMMC1_D0DIR,FMC_NWAIT,SDMMC2_D6,,SDMMC1_D6,DCMI_D0/PSSI_D0,LCD_HSYNC,EVENTOUT,
+PortC,PC7,DBTRGIO,,TIM3_CH2,TIM8_CH2,DFSDM1_DATIN3,,I2S3_MCK,USART6_RX,SDMMC1_D123DIR,FMC_NE1,SDMMC2_D7,SWPMI_TX,SDMMC1_D7,DCMI_D1/PSSI_D1,LCD_G6,EVENTOUT,
+PortC,PC8,TRACED1,,TIM3_CH3,TIM8_CH3,,,,USART6_CK,UART5_RTS/UART5_DE,FMC_NE2/FMC_NCE,FMC_INT,SWPMI_RX,SDMMC1_D0,DCMI_D2/PSSI_D2,,EVENTOUT,
+PortC,PC9,MCO2,,TIM3_CH4,TIM8_CH4,I2C3_SDA,I2S_CKIN,I2C5_SDA,,UART5_CTS,OCTOSPIM_P1_IO0,LCD_G3,SWPMI_SUSPEND,SDMMC1_D1,DCMI_D3/PSSI_D3,LCD_B2,EVENTOUT,
+PortC,PC10,,,,DFSDM1_CKIN5,I2C5_SDA,,SPI3_SCK/I2S3_CK,USART3_TX,UART4_TX,OCTOSPIM_P1_IO1,LCD_B1,SWPMI_RX,SDMMC1_D2,DCMI_D8/PSSI_D8,LCD_R2,EVENTOUT,
+PortC,PC11,,,,DFSDM1_DATIN5,I2C5_SCL,,SPI3_MISO/I2S3_SDI,USART3_RX,UART4_RX,OCTOSPIM_P1_NCS,,,SDMMC1_D3,DCMI_D4/PSSI_D4,LCD_B4,EVENTOUT,
+PortC,PC12,TRACED3,FMC_D6/FMC_AD6,TIM15_CH1,,I2C5_SMBA,SPI6_SCK/I2S6_CK,SPI3_MOSI/I2S3_SDO,USART3_CK,UART5_TX,,,,SDMMC1_CK,DCMI_D9/PSSI_D9,LCD_R6,EVENTOUT,
+PortC,PC13,,,,,,,,,,,,,,,,EVENTOUT,
+PortC,PC14,,,,,,,,,,,,,,,,EVENTOUT,
+PortC,PC15,,,,,,,,,,,,,,,,EVENTOUT,
+PortD,PD0,,,,DFSDM1_CKIN6,,,,,UART4_RX,FDCAN1_RX,,UART9_CTS,FMC_D2/FMC_AD2,,LCD_B1,EVENTOUT,
+PortD,PD1,,,,DFSDM1_DATIN6,,,,,UART4_TX,FDCAN1_TX,,,FMC_D3/FMC_AD3,,,EVENTOUT,
+PortD,PD2,TRACED2,FMC_D7/FMC_AD7,TIM3_ETR,,TIM15_BKIN,,,,UART5_RX,LCD_B7,,,SDMMC1_CMD,DCMI_D11/PSSI_D11,LCD_B2,EVENTOUT,
+PortD,PD3,,,,DFSDM1_CKOUT,,SPI2_SCK/I2S2_CK,,USART2_CTS/USART2_NSS,,,,,FMC_CLK,DCMI_D5/PSSI_D5,LCD_G7,EVENTOUT,
+PortD,PD4,,,,,,,,USART2_RTS/USART2_DE,,,OCTOSPIM_P1_IO4,,FMC_NOE,,,EVENTOUT,
+PortD,PD5,,,,,,,,USART2_TX,,,OCTOSPIM_P1_IO5,,FMC_NWE,,,EVENTOUT,
+PortD,PD6,,SAI4_D1,SAI1_D1,DFSDM1_CKIN4,DFSDM1_DATIN1,SPI3_MOSI/I2S3_SDO,SAI1_SD_A,USART2_RX,SAI4_SD_A,,OCTOSPIM_P1_IO6,SDMMC2_CK,FMC_NWAIT,DCMI_D10/PSSI_D10,LCD_B2,EVENTOUT,
+PortD,PD7,,,,DFSDM1_DATIN4,,SPI1_MOSI/I2S1_SDO,DFSDM1_CKIN1,USART2_CK,,SPDIFRX1_IN1,OCTOSPIM_P1_IO7,SDMMC2_CMD,FMC_NE1,,,EVENTOUT,
+PortD,PD8,,,,DFSDM1_CKIN3,,,,USART3_TX,,SPDIFRX1_IN2,,,FMC_D13/FMC_AD13,,,EVENTOUT,
+PortD,PD9,,,,DFSDM1_DATIN3,,,,USART3_RX,,,,,FMC_D14/FMC_AD14,,,EVENTOUT,
+PortD,PD10,,,,DFSDM1_CKOUT,,,,USART3_CK,,,,,FMC_D15/FMC_AD15,,LCD_B3,EVENTOUT,
+PortD,PD11,,,,LPTIM2_IN2,I2C4_SMBA,,,USART3_CTS/USART3_NSS,,OCTOSPIM_P1_IO0,SAI4_SD_A,,FMC_A16/FMC_CLE,,,EVENTOUT,
+PortD,PD12,,LPTIM1_IN1,TIM4_CH1,LPTIM2_IN1,I2C4_SCL,FDCAN3_RX,,USART3_RTS/USART3_DE,,OCTOSPIM_P1_IO1,SAI4_FS_A,,FMC_A17/FMC_ALE,DCMI_D12/PSSI_D12,,EVENTOUT,
+PortD,PD13,,LPTIM1_OUT,TIM4_CH2,,I2C4_SDA,FDCAN3_TX,,,,OCTOSPIM_P1_IO3,SAI4_SCK_A,UART9_RTS/UART9_DE,FMC_A18,DCMI_D13/PSSI_D13,,EVENTOUT,
+PortD,PD14,,,TIM4_CH3,,,,,,UART8_CTS,,,UART9_RX,FMC_D0/FMC_AD0,,,EVENTOUT,
+PortD,PD15,,,TIM4_CH4,,,,,,UART8_RTS/UART8_DE,,,UART9_TX,FMC_D1/FMC_AD1,,,EVENTOUT,
+PortE,PE0,,LPTIM1_ETR,TIM4_ETR,,LPTIM2_ETR,,,,UART8_RX,,SAI4_MCLK_A,,FMC_NBL0,DCMI_D2/PSSI_D2,LCD_R0,EVENTOUT,
+PortE,PE1,,LPTIM1_IN2,,,,,,,UART8_TX,,,,FMC_NBL1,DCMI_D3/PSSI_D3,LCD_R6,EVENTOUT,
+PortE,PE2,TRACECLK,,SAI1_CK1,,USART10_RX,SPI4_SCK,SAI1_MCLK_A,,SAI4_MCLK_A,OCTOSPIM_P1_IO2,SAI4_CK1,ETH_MII_TXD3,FMC_A23,,,EVENTOUT,
+PortE,PE3,TRACED0,,,,TIM15_BKIN,,SAI1_SD_B,,SAI4_SD_B,,,USART10_TX,FMC_A19,,,EVENTOUT,
+PortE,PE4,TRACED1,,SAI1_D2,DFSDM1_DATIN3,TIM15_CH1N,SPI4_NSS,SAI1_FS_A,,SAI4_FS_A,,SAI4_D2,,FMC_A20,DCMI_D4/PSSI_D4,LCD_B0,EVENTOUT,
+PortE,PE5,TRACED2,,SAI1_CK2,DFSDM1_CKIN3,TIM15_CH1,SPI4_MISO,SAI1_SCK_A,,SAI4_SCK_A,,SAI4_CK2,,FMC_A21,DCMI_D6/PSSI_D6,LCD_G0,EVENTOUT,
+PortE,PE6,TRACED3,TIM1_BKIN2,SAI1_D1,,TIM15_CH2,SPI4_MOSI,SAI1_SD_A,,SAI4_SD_A,SAI4_D1,SAI4_MCLK_B,TIM1_BKIN2_COMP12,FMC_A22,DCMI_D7/PSSI_D7,LCD_G1,EVENTOUT,
+PortE,PE7,,TIM1_ETR,,DFSDM1_DATIN2,,,,UART7_RX,,,OCTOSPIM_P1_IO4,,FMC_D4/FMC_AD4,,,EVENTOUT,
+PortE,PE8,,TIM1_CH1N,,DFSDM1_CKIN2,,,,UART7_TX,,,OCTOSPIM_P1_IO5,,FMC_D5/FMC_AD5,COMP2_OUT,,EVENTOUT,
+PortE,PE9,,TIM1_CH1,,DFSDM1_CKOUT,,,,UART7_RTS/UART7_DE,,,OCTOSPIM_P1_IO6,,FMC_D6/FMC_AD6,,,EVENTOUT,
+PortE,PE10,,TIM1_CH2N,,DFSDM1_DATIN4,,,,UART7_CTS,,,OCTOSPIM_P1_IO7,,FMC_D7/FMC_AD7,,,EVENTOUT,
+PortE,PE11,,TIM1_CH2,,DFSDM1_CKIN4,,SPI4_NSS,,,,,SAI4_SD_B,OCTOSPIM_P1_NCS,FMC_D8/FMC_AD8,,LCD_G3,EVENTOUT,
+PortE,PE12,,TIM1_CH3N,,DFSDM1_DATIN5,,SPI4_SCK,,,,,SAI4_SCK_B,,FMC_D9/FMC_AD9,COMP1_OUT,LCD_B4,EVENTOUT,
+PortE,PE13,,TIM1_CH3,,DFSDM1_CKIN5,,SPI4_MISO,,,,,SAI4_FS_B,,FMC_D10/FMC_AD10,COMP2_OUT,LCD_DE,EVENTOUT,
+PortE,PE14,,TIM1_CH4,,,,SPI4_MOSI,,,,,SAI4_MCLK_B,,FMC_D11/FMC_AD11,,LCD_CLK,EVENTOUT,
+PortE,PE15,,TIM1_BKIN,,,,,,,,,,USART10_CK,FMC_D12/FMC_AD12,TIM1_BKIN_COMP12,LCD_R7,EVENTOUT,
+PortF,PF0,,,,,I2C2_SDA,,I2C5_SDA,,,OCTOSPIM_P2_IO0,,,FMC_A0,TIM23_CH1,,EVENTOUT,
+PortF,PF1,,,,,I2C2_SCL,,I2C5_SCL,,,OCTOSPIM_P2_IO1,,,FMC_A1,TIM23_CH2,,EVENTOUT,
+PortF,PF2,,,,,I2C2_SMBA,,I2C5_SMBA,,,OCTOSPIM_P2_IO2,,,FMC_A2,TIM23_CH3,,EVENTOUT,
+PortF,PF3,,,,,,,,,,OCTOSPIM_P2_IO3,,,FMC_A3,TIM23_CH4,,EVENTOUT,ADC3_IN9
+PortF,PF4,,,,,,,,,,OCTOSPIM_P2_CLK,,,FMC_A4,,,EVENTOUT,ADC3_IN14
+PortF,PF5,,,,,,,,,,OCTOSPIM_P2_NCLK,,,FMC_A5,,,EVENTOUT,ADC3_IN15
+PortF,PF6,,TIM16_CH1,FDCAN3_RX,,,SPI5_NSS,SAI1_SD_B,UART7_RX,SAI4_SD_B,,OCTOSPIM_P1_IO3,,,TIM23_CH1,,EVENTOUT,ADC3_IN4
+PortF,PF7,,TIM17_CH1,FDCAN3_TX,,,SPI5_SCK,SAI1_MCLK_B,UART7_TX,SAI4_MCLK_B,,OCTOSPIM_P1_IO2,,,TIM23_CH2,,EVENTOUT,ADC3_IN5
+PortF,PF8,,TIM16_CH1N,,,,SPI5_MISO,SAI1_SCK_B,UART7_RTS/UART7_DE,SAI4_SCK_B,TIM13_CH1,OCTOSPIM_P1_IO0,,,TIM23_CH3,,EVENTOUT,ADC3_IN6
+PortF,PF9,,TIM17_CH1N,,,,SPI5_MOSI,SAI1_FS_B,UART7_CTS,SAI4_FS_B,TIM14_CH1,OCTOSPIM_P1_IO1,,,TIM23_CH4,,EVENTOUT,ADC3_IN7
+PortF,PF10,,TIM16_BKIN,SAI1_D3,,PSSI_D15,,,,,OCTOSPIM_P1_CLK,SAI4_D3,,,DCMI_D11/PSSI_D11,LCD_DE,EVENTOUT,ADC3_IN8
+PortF,PF11,,,,,,SPI5_MOSI,,,,OCTOSPIM_P1_NCLK,SAI4_SD_B,,FMC_NRAS,DCMI_D12/PSSI_D12,TIM24_CH1,EVENTOUT,
+PortF,PF12,,,,,,,,,,OCTOSPIM_P2_DQS,,,FMC_A6,,TIM24_CH2,EVENTOUT,
+PortF,PF13,,,,DFSDM1_DATIN6,I2C4_SMBA,,,,,,,,FMC_A7,,TIM24_CH3,EVENTOUT,
+PortF,PF14,,,,DFSDM1_CKIN6,I2C4_SCL,,,,,,,,FMC_A8,,TIM24_CH4,EVENTOUT,
+PortF,PF15,,,,,I2C4_SDA,,,,,,,,FMC_A9,,,EVENTOUT,
+PortG,PG0,,,,,,,,,,OCTOSPIM_P2_IO4,,UART9_RX,FMC_A10,,,EVENTOUT,
+PortG,PG1,,,,,,,,,,OCTOSPIM_P2_IO5,,UART9_TX,FMC_A11,,,EVENTOUT,
+PortG,PG2,,,,TIM8_BKIN,,,,,,,,TIM8_BKIN_COMP12,FMC_A12,,TIM24_ETR,EVENTOUT,
+PortG,PG3,,,,TIM8_BKIN2,,,,,,,,TIM8_BKIN2_COMP12,FMC_A13,TIM23_ETR,,EVENTOUT,
+PortG,PG4,,TIM1_BKIN2,,,,,,,,,,TIM1_BKIN2_COMP12,FMC_A14/FMC_BA0,,,EVENTOUT,
+PortG,PG5,,TIM1_ETR,,,,,,,,,,,FMC_A15/FMC_BA1,,,EVENTOUT,
+PortG,PG6,,TIM17_BKIN,,,,,,,,,OCTOSPIM_P1_NCS,,FMC_NE3,DCMI_D12/PSSI_D12,LCD_R7,EVENTOUT,
+PortG,PG7,,,,,,,SAI1_MCLK_A,USART6_CK,,OCTOSPIM_P2_DQS,,,FMC_INT,DCMI_D13/PSSI_D13,LCD_CLK,EVENTOUT,
+PortG,PG8,,,,TIM8_ETR,,SPI6_NSS/I2S6_WS,,USART6_RTS/USART6_DE,SPDIFRX1_IN3,,,ETH_PPS_OUT,FMC_SDCLK,,LCD_G7,EVENTOUT,
+PortG,PG9,,,FDCAN3_TX,,,SPI1_MISO/I2S1_SDI,,USART6_RX,SPDIFRX1_IN4,OCTOSPIM_P1_IO6,SAI4_FS_B,SDMMC2_D0,FMC_NE2/FMC_NCE,DCMI_VSYNC/PSSI_RDY,,EVENTOUT,
+PortG,PG10,,,FDCAN3_RX,OCTOSPIM_P2_IO6,,SPI1_NSS/I2S1_WS,,,,LCD_G3,SAI4_SD_B,SDMMC2_D1,FMC_NE3,DCMI_D2/PSSI_D2,LCD_B2,EVENTOUT,
+PortG,PG11,,LPTIM1_IN2,,,USART10_RX,SPI1_SCK/I2S1_CK,,,SPDIFRX1_IN1,OCTOSPIM_P2_IO7,SDMMC2_D2,ETH_MII_TX_EN/ETH_RMII_TX_EN,,DCMI_D3/PSSI_D3,LCD_B3,EVENTOUT,
+PortG,PG12,,LPTIM1_IN1,,OCTOSPIM_P2_NCS,USART10_TX,SPI6_MISO/I2S6_SDI,,USART6_RTS/USART6_DE,SPDIFRX1_IN2,LCD_B4,SDMMC2_D3,ETH_MII_TXD1/ETH_RMII_TXD1,FMC_NE4,TIM23_CH1,LCD_B1,EVENTOUT,
+PortG,PG13,TRACED0,LPTIM1_OUT,,,USART10_CTS/USART10_NSS,SPI6_SCK/I2S6_CK,,USART6_CTS/USART6_NSS,,,SDMMC2_D6,ETH_MII_TXD0/ETH_RMII_TXD0,FMC_A24,TIM23_CH2,LCD_R0,EVENTOUT,
+PortG,PG14,TRACED1,LPTIM1_ETR,,,USART10_RTS/USART10_DE,SPI6_MOSI/I2S6_SDO,,USART6_TX,,OCTOSPIM_P1_IO7,SDMMC2_D7,ETH_MII_TXD1/ETH_RMII_TXD1,FMC_A25,TIM23_CH3,LCD_B0,EVENTOUT,
+PortG,PG15,,,,,,,,USART6_CTS/USART6_NSS,,OCTOSPIM_P2_DQS,,USART10_CK,FMC_NCAS,DCMI_D13/PSSI_D13,,EVENTOUT,
+PortH,PH0,,,,,,,,,,,,,,,,EVENTOUT,
+PortH,PH1,,,,,,,,,,,,,,,,EVENTOUT,
diff --git a/ports/stm32/boards/stm32h7xx_hal_conf_base.h b/ports/stm32/boards/stm32h7xx_hal_conf_base.h
index 08928ed5933c..9c5ec8cb2c59 100644
--- a/ports/stm32/boards/stm32h7xx_hal_conf_base.h
+++ b/ports/stm32/boards/stm32h7xx_hal_conf_base.h
@@ -101,4 +101,10 @@
// HAL parameter assertions are disabled
#define assert_param(expr) ((void)0)
+// The STM32H7xx HAL defines LPUART1 AF macros without numbers.
+#ifndef GPIO_AF3_LPUART1
+#define GPIO_AF3_LPUART1 GPIO_AF3_LPUART
+#define GPIO_AF8_LPUART1 GPIO_AF8_LPUART
+#endif
+
#endif // MICROPY_INCLUDED_STM32H7XX_HAL_CONF_BASE_H
diff --git a/ports/stm32/boards/stm32l152_af.csv b/ports/stm32/boards/stm32l152_af.csv
new file mode 100644
index 000000000000..a6f8e80c3028
--- /dev/null
+++ b/ports/stm32/boards/stm32l152_af.csv
@@ -0,0 +1,117 @@
+Port,,AF0,AF1,AF2,AF3,AF4,AF5,AF6,AF7,AF8,AF9,AF10,AF11,AF12,AF13,AF14,AF15,
+,,SYS_AF,TIM2,TIM3/TIM4/TIM5,TIM9/TIM10/TIM11,I2C1/I2C2,SPI1/SPI2,SPI3,USART1/USART2/USART3,UART4/UART5,,,,,,,,ADC
+PortA,PA0,,TIM2_CH1_ETR,TIM5_CH1,,,,,USART2_CTS,,,,,,,,EVENTOUT,ADC1_IN0
+PortA,PA1,,TIM2_CH2,TIM5_CH2,,,,,USART2_RTS,,,,,,,,EVENTOUT,ADC1_IN1
+PortA,PA2,,TIM2_CH3,TIM5_CH3,TIM9_CH1,,,,USART2_TX,,,,,,,,EVENTOUT,ADC1_IN2
+PortA,PA3,,TIM2_CH4,TIM5_CH4,TIM9_CH2,,,,USART2_RX,,,,,,,,EVENTOUT,ADC1_IN3
+PortA,PA4,,,,,,SPI1_NSS,SPI3_NSS/I2S3_WS,USART2_CK,,,,,,,,EVENTOUT,ADC1_IN4
+PortA,PA5,,TIM2_CH1_ETR,,,,SPI1_SCK,,,,,,,,,,EVENTOUT,ADC1_IN5
+PortA,PA6,,,TIM3_CH1,TIM10_CH1,,SPI1_MISO,,,,,,,,,,EVENTOUT,ADC1_IN6
+PortA,PA7,,,TIM3_CH2,TIM11_CH1,,SPI1_MOSI,,,,,,,,,,EVENTOUT,ADC1_IN7
+PortA,PA8,MCO,,,,,,,USART1_CK,,,,,,,,EVENTOUT,
+PortA,PA9,,,,,,,,USART1_TX,,,,,,,,EVENTOUT,
+PortA,PA10,,,,,,,,USART1_RX,,,,,,,,EVENTOUT,
+PortA,PA11,,,,,,SPI1_MISO,,USART1_CTS,,,,,,,,EVENTOUT,
+PortA,PA12,,,,,,SPI1_MOSI,,USART1_RTS,,,,,,,,EVENTOUT,
+PortA,PA13,JTMS/SWDIO,,,,,,,,,,,,,,,EVENTOUT,
+PortA,PA14,JTCK/SWCLK,,,,,,,,,,,,,,,EVENTOUT,
+PortA,PA15,JTDI,TIM2_CH1_ETR,,,,SPI1_NSS,SPI3_NSS/I2S3_WS,,,,,,,,,EVENTOUT,
+PortB,PB0,,,TIM3_CH3,,,,,,,,,,,,,EVENTOUT,ADC1_IN8
+PortB,PB1,,,TIM3_CH4,,,,,,,,,,,,,EVENTOUT,ADC1_IN9
+PortB,PB2,BOOT1,,,,,,,,,,,,,,,EVENTOUT,
+PortB,PB3,JTDO,TIM2_CH2,,,,SPI1_SCK,SPI3_SCK/I2S3_CK,,,,,,,,,EVENTOUT,
+PortB,PB4,NJTRST,,TIM3_CH1,,,SPI1_MISO,SPI3_MISO,,,,,,,,,EVENTOUT,
+PortB,PB5,,,TIM3_CH2,,I2C1_SMBA,SPI1_MOSI,SPI3_MOSI/I2S3_SD,,,,,,,,,EVENTOUT,
+PortB,PB6,,,TIM4_CH1,,I2C1_SCL,,,USART1_TX,,,,,,,,EVENTOUT,
+PortB,PB7,,,TIM4_CH2,,I2C1_SDA,,,USART1_RX,,,,,,,,EVENTOUT,
+PortB,PB8,,,TIM4_CH3,TIM10_CH1,I2C1_SCL,,,,,,,,,,,EVENTOUT,
+PortB,PB9,,,TIM4_CH4,TIM11_CH1,I2C1_SDA,,,,,,,,,,,EVENTOUT,
+PortB,PB10,,TIM2_CH3,,,I2C2_SCL,,,USART3_TX,,,,,,,,EVENTOUT,
+PortB,PB11,,TIM2_CH4,,,I2C2_SDA,,,USART3_RX,,,,,,,,EVENTOUT,
+PortB,PB12,,,,TIM10_CH1,I2C2_SMBA,SPI2_NSS/I2S2_WS,,USART3_CK,,,,,,,,EVENTOUT,ADC1_IN18
+PortB,PB13,,,,TIM9_CH1,,SPI2_SCK/I2S2_CK,,USART3_CTS,,,,,,,,EVENTOUT,ADC1_IN19
+PortB,PB14,,,,TIM9_CH2,,SPI2_MISO,,USART3_RTS,,,,,,,,EVENTOUT,ADC1_IN20
+PortB,PB15,,,,TIM11_CH1,,SPI2_MOSI/I2S2_SD,,,,,,,,,,EVENTOUT,ADC1_IN21
+PortC,PC0,,,,,,,,,,,,,,,,EVENTOUT,ADC1_IN10
+PortC,PC1,,,,,,,,,,,,,,,,EVENTOUT,ADC1_IN11
+PortC,PC2,,,,,,,,,,,,,,,,EVENTOUT,ADC1_IN12
+PortC,PC3,,,,,,,,,,,,,,,,EVENTOUT,ADC1_IN13
+PortC,PC4,,,,,,,,,,,,,,,,EVENTOUT,ADC1_IN14
+PortC,PC5,,,,,,,,,,,,,,,,EVENTOUT,ADC1_IN15
+PortC,PC6,,,TIM3_CH1,,,I2S2_MCK,,,,,,,,,,EVENTOUT,
+PortC,PC7,,,TIM3_CH2,,,,I2S3_MCK,,,,,,,,,EVENTOUT,
+PortC,PC8,,,TIM3_CH3,,,,,,,,,,,,,EVENTOUT,
+PortC,PC9,,,TIM3_CH4,,,,,,,,,,,,,EVENTOUT,
+PortC,PC10,,,,,,,SPI3_SCK/I2S3_CK,USART3_TX,UART4_TX,,,,,,,EVENTOUT,
+PortC,PC11,,,,,,,SPI3_MISO,USART3_RX,UART4_RX,,,,,,,EVENTOUT,
+PortC,PC12,,,,,,,SPI3_MOSI/I2S3_SD,USART3_CK,UART5_TX,,,,,,,EVENTOUT,
+PortC,PC13,,,,,,,,,,,,,,,,EVENTOUT,
+PortC,PC14,,,,,,,,,,,,,,,,EVENTOUT,
+PortC,PC15,,,,,,,,,,,,,,,,EVENTOUT,
+PortD,PD0,,,,TIM9_CH1,,SPI2_NSS/I2S2_WS,,,,,,,,,,EVENTOUT,
+PortD,PD1,,,,,,SPI2_SCK/I2S2_CK,,,,,,,,,,EVENTOUT,
+PortD,PD2,,,TIM3_ETR,,,,,,UART5_RX,,,,,,,EVENTOUT,
+PortD,PD3,,,,,,SPI2_MISO,,USART2_CTS,,,,,,,,EVENTOUT,
+PortD,PD4,,,,,,SPI2_MOSI/I2S2_SD,,USART2_RTS,,,,,,,,EVENTOUT,
+PortD,PD5,,,,,,,,USART2_TX,,,,,,,,EVENTOUT,
+PortD,PD6,,,,,,,,USART2_RX,,,,,,,,EVENTOUT,
+PortD,PD7,,,,TIM9_CH2,,,,USART2_CK,,,,,,,,EVENTOUT,
+PortD,PD8,,,,,,,,USART3_TX,,,,,,,,EVENTOUT,
+PortD,PD9,,,,,,,,USART3_RX,,,,,,,,EVENTOUT,
+PortD,PD10,,,,,,,,USART3_CK,,,,,,,,EVENTOUT,
+PortD,PD11,,,,,,,,USART3_CTS,,,,,,,,EVENTOUT,
+PortD,PD12,,,TIM4_CH1,,,,,USART3_RTS,,,,,,,,EVENTOUT,
+PortD,PD13,,,TIM4_CH2,,,,,,,,,,,,,EVENTOUT,
+PortD,PD14,,,TIM4_CH3,,,,,,,,,,,,,EVENTOUT,
+PortD,PD15,,,TIM4_CH4,,,,,,,,,,,,,EVENTOUT,
+PortE,PE0,,,TIM4_ETR,TIM10_CH1,,,,,,,,,,,,EVENTOUT,
+PortE,PE1,,,,TIM11_CH1,,,,,,,,,,,,EVENTOUT,
+PortE,PE2,TRACECK,,TIM3_ETR,,,,,,,,,,,,,EVENTOUT,
+PortE,PE3,TRACED0,,TIM3_CH1,,,,,,,,,,,,,EVENTOUT,
+PortE,PE4,TRACED1,,TIM3_CH2,,,,,,,,,,,,,EVENTOUT,
+PortE,PE5,TRACED2,,,TIM9_CH1,,,,,,,,,,,,EVENTOUT,
+PortE,PE6,TRACED3,,,TIM9_CH2,,,,,,,,,,,,EVENTOUT,
+PortE,PE7,,,,,,,,,,,,,,,,EVENTOUT,
+PortE,PE8,,,,,,,,,,,,,,,,EVENTOUT,
+PortE,PE9,,TIM2_CH1_ETR,,,,,,,,,,,,,,EVENTOUT,
+PortE,PE10,,TIM2_CH2,,,,,,,,,,,,,,EVENTOUT,
+PortE,PE11,,TIM2_CH3,,,,,,,,,,,,,,EVENTOUT,
+PortE,PE12,,TIM2_CH4,,,,SPI1_NSS,,,,,,,,,,EVENTOUT,
+PortE,PE13,,,,,,SPI1_SCK,,,,,,,,,,EVENTOUT,
+PortE,PE14,,,,,,SPI1_MISO,,,,,,,,,,EVENTOUT,
+PortE,PE15,,,,,,SPI1_MOSI,,,,,,,,,,EVENTOUT,
+PortF,PF0,,,,,,,,,,,,,,,,EVENTOUT,
+PortF,PF1,,,,,,,,,,,,,,,,EVENTOUT,
+PortF,PF2,,,,,,,,,,,,,,,,EVENTOUT,
+PortF,PF3,,,,,,,,,,,,,,,,EVENTOUT,
+PortF,PF4,,,,,,,,,,,,,,,,EVENTOUT,
+PortF,PF5,,,,,,,,,,,,,,,,EVENTOUT,
+PortF,PF6,,,TIM5_ETR,,,,,,,,,,,,,EVENTOUT,
+PortF,PF7,,,TIM5_CH2,,,,,,,,,,,,,EVENTOUT,
+PortF,PF8,,,TIM5_CH3,,,,,,,,,,,,,EVENTOUT,
+PortF,PF9,,,TIM5_CH4,,,,,,,,,,,,,EVENTOUT,
+PortF,PF10,,,,,,,,,,,,,,,,EVENTOUT,
+PortF,PF11,,,,,,,,,,,,,,,,EVENTOUT,
+PortF,PF12,,,,,,,,,,,,,,,,EVENTOUT,
+PortF,PF13,,,,,,,,,,,,,,,,EVENTOUT,
+PortF,PF14,,,,,,,,,,,,,,,,EVENTOUT,
+PortF,PF15,,,,,,,,,,,,,,,,EVENTOUT,
+PortG,PG0,,,,,,,,,,,,,,,,EVENTOUT,
+PortG,PG1,,,,,,,,,,,,,,,,EVENTOUT,
+PortG,PG2,,,,,,,,,,,,,,,,EVENTOUT,
+PortG,PG3,,,,,,,,,,,,,,,,EVENTOUT,
+PortG,PG4,,,,,,,,,,,,,,,,EVENTOUT,
+PortG,PG5,,,,,,,,,,,,,,,,EVENTOUT,
+PortG,PG6,,,,,,,,,,,,,,,,EVENTOUT,
+PortG,PG7,,,,,,,,,,,,,,,,EVENTOUT,
+PortG,PG8,,,,,,,,,,,,,,,,EVENTOUT,
+PortG,PG9,,,,,,,,,,,,,,,,EVENTOUT,
+PortG,PG10,,,,,,,,,,,,,,,,EVENTOUT,
+PortG,PG11,,,,,,,,,,,,,,,,EVENTOUT,
+PortG,PG12,,,,,,,,,,,,,,,,EVENTOUT,
+PortG,PG13,,,,,,,,,,,,,,,,EVENTOUT,
+PortG,PG14,,,,,,,,,,,,,,,,EVENTOUT,
+PortG,PG15,,,,,,,,,,,,,,,,EVENTOUT,
+PortH,PH0,,,,,,,,,,,,,,,,,
+PortH,PH1,,,,,,,,,,,,,,,,,
+PortH,PH2,,,,,,,,,,,,,,,,,
diff --git a/ports/stm32/boards/stm32l152xe.ld b/ports/stm32/boards/stm32l152xe.ld
new file mode 100644
index 000000000000..32f8444947e2
--- /dev/null
+++ b/ports/stm32/boards/stm32l152xe.ld
@@ -0,0 +1,37 @@
+/*
+ GNU linker script for STM32L152xE
+*/
+
+/* Specify the memory areas */
+MEMORY
+{
+ FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 512K /* entire flash */
+ FLASH_FS (rx) : ORIGIN = 0x08064000, LENGTH = 112K /* sectors 100-127 */
+ RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 81408
+ FS_CACHE (xrw) : ORIGIN = 0x20013e00, LENGTH = 512
+}
+
+/* produce a link error if there is not this amount of RAM for these sections */
+_minimum_stack_size = 2K;
+_minimum_heap_size = 16K;
+
+/* RAM extents for the garbage collector */
+_ram_start = ORIGIN(RAM);
+_ram_end = ORIGIN(RAM) + LENGTH(RAM);
+
+/* Define the stack. The stack is full descending so begins just above last byte
+ of RAM. Note that EABI requires the stack to be 8-byte aligned for a call. */
+_estack = ORIGIN(RAM) + LENGTH(RAM) - _estack_reserve;
+_sstack = _estack - 16K; /* tunable */
+
+/* RAM extents for the garbage collector */
+_ram_start = ORIGIN(RAM);
+_ram_end = ORIGIN(RAM) + LENGTH(RAM);
+_heap_start = _ebss; /* heap starts just after statically allocated memory */
+_heap_end = _sstack;
+
+/* Filesystem cache in RAM, and storage in flash */
+_micropy_hw_internal_flash_storage_ram_cache_start = ORIGIN(FS_CACHE);
+_micropy_hw_internal_flash_storage_ram_cache_end = ORIGIN(FS_CACHE) + LENGTH(FS_CACHE);
+_micropy_hw_internal_flash_storage_start = ORIGIN(FLASH_FS);
+_micropy_hw_internal_flash_storage_end = ORIGIN(FLASH_FS) + LENGTH(FLASH_FS);
diff --git a/ports/stm32/boards/stm32l1xx_hal_conf_base.h b/ports/stm32/boards/stm32l1xx_hal_conf_base.h
new file mode 100644
index 000000000000..b839fd29f0a3
--- /dev/null
+++ b/ports/stm32/boards/stm32l1xx_hal_conf_base.h
@@ -0,0 +1,99 @@
+/*
+ * 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_STM32L1XX_HAL_CONF_BASE_H
+#define MICROPY_INCLUDED_STM32L1XX_HAL_CONF_BASE_H
+
+// Include various HAL modules for convenience
+#include "stm32l1xx_hal_rcc.h"
+#include "stm32l1xx_hal_gpio.h"
+#include "stm32l1xx_hal_dma.h"
+#include "stm32l1xx_hal_cortex.h"
+#include "stm32l1xx_hal_adc.h"
+#include "stm32l1xx_hal_comp.h"
+#include "stm32l1xx_hal_crc.h"
+#include "stm32l1xx_hal_dac.h"
+#include "stm32l1xx_hal_flash.h"
+#include "stm32l1xx_hal_i2c.h"
+#include "stm32l1xx_hal_iwdg.h"
+#include "stm32l1xx_hal_pwr.h"
+#include "stm32l1xx_hal_rtc.h"
+#include "stm32l1xx_hal_spi.h"
+#include "stm32l1xx_hal_tim.h"
+#include "stm32l1xx_hal_uart.h"
+#include "stm32l1xx_hal_usart.h"
+#include "stm32l1xx_hal_wwdg.h"
+#include "stm32l1xx_hal_exti.h"
+#include "stm32l1xx_ll_adc.h"
+#include "stm32l1xx_ll_pwr.h"
+#include "stm32l1xx_ll_rtc.h"
+#include "stm32l1xx_ll_usart.h"
+
+// Enable various HAL modules
+#define HAL_MODULE_ENABLED
+#define HAL_ADC_MODULE_ENABLED
+#define HAL_CORTEX_MODULE_ENABLED
+#define HAL_CRC_MODULE_ENABLED
+#define HAL_DAC_MODULE_ENABLED
+#define HAL_DMA_MODULE_ENABLED
+#define HAL_EXTI_MODULE_ENABLED
+#define HAL_FLASH_MODULE_ENABLED
+#define HAL_GPIO_MODULE_ENABLED
+#define HAL_I2C_MODULE_ENABLED
+#define HAL_PWR_MODULE_ENABLED
+#define HAL_RCC_MODULE_ENABLED
+#define HAL_RTC_MODULE_ENABLED
+#define HAL_SPI_MODULE_ENABLED
+#define HAL_TIM_MODULE_ENABLED
+#define HAL_UART_MODULE_ENABLED
+#define HAL_USART_MODULE_ENABLED
+#define HAL_WWDG_MODULE_ENABLED
+
+// Oscillator values in Hz
+#define HSE_VALUE (8000000)
+#define HSI_VALUE (16000000)
+#define HSI48_VALUE (48000000)
+#define LSI_VALUE (37000)
+#define LSE_VALUE (32768)
+#define MSI_VALUE (2097000)
+
+// Oscillator timeouts in ms
+#define HSE_STARTUP_TIMEOUT (100)
+#define LSE_STARTUP_TIMEOUT (5000)
+
+// SysTick has the highest priority
+#define TICK_INT_PRIORITY (0x00)
+
+// Miscellaneous HAL settings
+#define DATA_CACHE_ENABLE 1
+#define INSTRUCTION_CACHE_ENABLE 1
+#define PREFETCH_ENABLE 1
+#define USE_SPI_CRC 0
+#define USE_RTOS 0
+
+// HAL parameter assertions are disabled
+#define assert_param(expr) ((void)0)
+
+#endif // MICROPY_INCLUDED_STM32L1XX_HAL_CONF_BASE_H
diff --git a/ports/stm32/boards/stm32wb55xg.ld b/ports/stm32/boards/stm32wb55xg.ld
index 841c32b8a0fb..9b1e5bca147d 100644
--- a/ports/stm32/boards/stm32wb55xg.ld
+++ b/ports/stm32/boards/stm32wb55xg.ld
@@ -6,7 +6,7 @@
MEMORY
{
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 512K /* sectors 0-127 */
- FLASH_APP (rx) : ORIGIN = 0x08004000, LENGTH = 496K /* sectors 4-127 */
+ FLASH_APP (rx) : ORIGIN = 0x08008000, LENGTH = 480K /* sectors 8-127 */
FLASH_FS (r) : ORIGIN = 0x08080000, LENGTH = 256K /* sectors 128-191 */
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 192K /* SRAM1 */
RAM2A (xrw) : ORIGIN = 0x20030000, LENGTH = 10K /* SRAM2A */
diff --git a/ports/stm32/boards/stm32wbxx_hal_conf_base.h b/ports/stm32/boards/stm32wbxx_hal_conf_base.h
index b03ad26864f9..25eb4b93ecd2 100644
--- a/ports/stm32/boards/stm32wbxx_hal_conf_base.h
+++ b/ports/stm32/boards/stm32wbxx_hal_conf_base.h
@@ -42,6 +42,7 @@
#include "stm32wbxx_hal_uart.h"
#include "stm32wbxx_hal_usart.h"
#include "stm32wbxx_ll_adc.h"
+#include "stm32wbxx_ll_hsem.h"
#include "stm32wbxx_ll_lpuart.h"
#include "stm32wbxx_ll_rtc.h"
#include "stm32wbxx_ll_usart.h"
@@ -79,4 +80,41 @@
// HAL parameter assertions are disabled
#define assert_param(expr) ((void)0)
+// Hardware Semaphores - ref: AN5289
+
+// Used to prevent conflicts after standby / sleep.
+// Each CPUs takes this semaphore at standby wakeup until conflicting elements are restored.
+// Note: this is used in WB55 reference examples, but not listed in AN5289 Rev 6
+#define CFG_HW_PWR_STANDBY_SEMID 10
+
+// Ensures that CPU2 does not update the BLE persistent data in SRAM2 when CPU1 is reading them
+#define CFG_HW_THREAD_NVM_SRAM_SEMID 9
+
+// Ensures that CPU2 does not update the Thread persistent data in SRAM2 when CPU1 is reading them
+#define CFG_HW_BLE_NVM_SRAM_SEMID 8
+
+// Used by CPU2 to prevent CPU1 from writing/erasing data in Flash memory
+#define CFG_HW_BLOCK_FLASH_REQ_BY_CPU2_SEMID 7
+
+// Used by CPU1 to prevent CPU2 from writing/erasing data in Flash memory
+#define CFG_HW_BLOCK_FLASH_REQ_BY_CPU1_SEMID 6
+
+// Used to manage the CLK48 clock configuration (RCC_CRRCR, RCC_CCIPR)
+#define CFG_HW_CLK48_CONFIG_SEMID 5
+
+// Used to manage the entry Stop Mode procedure
+#define CFG_HW_ENTRY_STOP_MODE_SEMID 4
+
+// Used to access the RCC (RCC_CR, RCC_EXTCFGR, RCC_CFGR, RCC_SMPSCR)
+#define CFG_HW_RCC_SEMID 3
+
+// Used to access the FLASH (all registers)
+#define CFG_HW_FLASH_SEMID 2
+
+// Used to access the PKA (all registers)
+#define CFG_HW_PKA_SEMID 1
+
+// Used to access the RNG (all registers)
+#define CFG_HW_RNG_SEMID 0
+
#endif // MICROPY_INCLUDED_STM32WBXX_HAL_CONF_BASE_H
diff --git a/ports/stm32/cyw43_configport.h b/ports/stm32/cyw43_configport.h
new file mode 100644
index 000000000000..4b6dde3c43f7
--- /dev/null
+++ b/ports/stm32/cyw43_configport.h
@@ -0,0 +1,155 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2022 Damien P. George
+ * Copyright (c) 2022 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_STM32_CYW43_CONFIGPORT_H
+#define MICROPY_INCLUDED_STM32_CYW43_CONFIGPORT_H
+
+// The board-level config will be included here, so it can set some CYW43 values.
+#include "py/mpconfig.h"
+#include "py/mperrno.h"
+#include "py/mphal.h"
+#include "extmod/modnetwork.h"
+#include "extint.h"
+#include "pendsv.h"
+#include "sdio.h"
+
+#define CYW43_USE_SPI (0)
+#define CYW43_LWIP (1)
+#define CYW43_USE_STATS (0)
+
+#ifndef CYW43_CHIPSET_FIRMWARE_INCLUDE_FILE
+#define CYW43_CHIPSET_FIRMWARE_INCLUDE_FILE "lib/cyw43-driver/firmware/w4343WA1_7_45_98_50_combined.h"
+#endif
+
+#ifndef CYW43_WIFI_NVRAM_INCLUDE_FILE
+#define CYW43_WIFI_NVRAM_INCLUDE_FILE "lib/cyw43-driver/firmware/wifi_nvram_1dx.h"
+#endif
+
+#define CYW43_IOCTL_TIMEOUT_US (1000000)
+#define CYW43_SLEEP_MAX (50)
+#define CYW43_NETUTILS (1)
+#define CYW43_CLEAR_SDIO_INT (1)
+
+#define CYW43_EPERM MP_EPERM // Operation not permitted
+#define CYW43_EIO MP_EIO // I/O error
+#define CYW43_EINVAL MP_EINVAL // Invalid argument
+#define CYW43_ETIMEDOUT MP_ETIMEDOUT // Connection timed out
+
+#define CYW43_THREAD_ENTER MICROPY_PY_LWIP_ENTER
+#define CYW43_THREAD_EXIT MICROPY_PY_LWIP_EXIT
+#define CYW43_THREAD_LOCK_CHECK
+
+#define CYW43_HOST_NAME mod_network_hostname
+
+#define CYW43_SDPCM_SEND_COMMON_WAIT __WFI();
+#define CYW43_DO_IOCTL_WAIT __WFI();
+
+#define CYW43_ARRAY_SIZE(a) MP_ARRAY_SIZE(a)
+
+#define CYW43_HAL_PIN_MODE_INPUT MP_HAL_PIN_MODE_INPUT
+#define CYW43_HAL_PIN_MODE_OUTPUT MP_HAL_PIN_MODE_OUTPUT
+#define CYW43_HAL_PIN_PULL_NONE MP_HAL_PIN_PULL_NONE
+#define CYW43_HAL_PIN_PULL_UP MP_HAL_PIN_PULL_UP
+#define CYW43_HAL_PIN_PULL_DOWN MP_HAL_PIN_PULL_DOWN
+
+#define CYW43_HAL_MAC_WLAN0 MP_HAL_MAC_WLAN0
+
+#define cyw43_hal_ticks_us mp_hal_ticks_us
+#define cyw43_hal_ticks_ms mp_hal_ticks_ms
+
+#define cyw43_hal_pin_obj_t mp_hal_pin_obj_t
+#define cyw43_hal_pin_config mp_hal_pin_config
+#define cyw43_hal_pin_read mp_hal_pin_read
+#define cyw43_hal_pin_low mp_hal_pin_low
+#define cyw43_hal_pin_high mp_hal_pin_high
+
+#define cyw43_hal_get_mac mp_hal_get_mac
+#define cyw43_hal_get_mac_ascii mp_hal_get_mac_ascii
+#define cyw43_hal_generate_laa_mac mp_hal_generate_laa_mac
+
+#define CYW43_PIN_WL_REG_ON pyb_pin_WL_REG_ON
+#define CYW43_PIN_WL_HOST_WAKE pyb_pin_WL_HOST_WAKE
+#define CYW43_PIN_WL_SDIO_1 pyb_pin_WL_SDIO_1
+
+#if MICROPY_HW_ENABLE_RF_SWITCH
+#define CYW43_PIN_WL_RFSW_VDD pyb_pin_WL_RFSW_VDD
+#endif
+
+#define cyw43_schedule_internal_poll_dispatch(func) pendsv_schedule_dispatch(PENDSV_DISPATCH_CYW43, func)
+
+void cyw43_post_poll_hook(void);
+
+static inline void cyw43_delay_us(uint32_t us) {
+ uint32_t start = mp_hal_ticks_us();
+ while (mp_hal_ticks_us() - start < us) {
+ }
+}
+
+static inline void cyw43_delay_ms(uint32_t ms) {
+ uint32_t us = ms * 1000;
+ uint32_t start = mp_hal_ticks_us();
+ while (mp_hal_ticks_us() - start < us) {
+ MICROPY_EVENT_POLL_HOOK;
+ }
+}
+
+static inline void cyw43_hal_pin_config_irq_falling(cyw43_hal_pin_obj_t pin, int enable) {
+ if (enable) {
+ extint_set(pin, GPIO_MODE_IT_FALLING);
+ }
+}
+
+static inline void cyw43_sdio_init(void) {
+ sdio_init(NVIC_EncodePriority(NVIC_PRIORITYGROUP_4, 14, 0));
+}
+
+static inline void cyw43_sdio_reinit(void) {
+ sdio_reenable();
+}
+
+static inline void cyw43_sdio_deinit(void) {
+ sdio_deinit();
+}
+
+static inline void cyw43_sdio_set_irq(bool enable) {
+ sdio_enable_irq(enable);
+}
+
+static inline void cyw43_sdio_enable_high_speed_4bit(void) {
+ sdio_enable_high_speed_4bit();
+}
+
+static inline int cyw43_sdio_transfer(uint32_t cmd, uint32_t arg, uint32_t *resp) {
+ return sdio_transfer(cmd, arg, resp);
+}
+
+static inline int cyw43_sdio_transfer_cmd53(bool write, uint32_t block_size, uint32_t arg, size_t len, uint8_t *buf) {
+ return sdio_transfer_cmd53(write, block_size, arg, len, buf);
+}
+
+#define CYW43_EVENT_POLL_HOOK MICROPY_EVENT_POLL_HOOK
+
+#endif // MICROPY_INCLUDED_STM32_CYW43_CONFIGPORT_H
diff --git a/ports/stm32/dac.c b/ports/stm32/dac.c
index c41bf858a7ed..feadbe5c5817 100644
--- a/ports/stm32/dac.c
+++ b/ports/stm32/dac.c
@@ -261,6 +261,8 @@ STATIC mp_obj_t pyb_dac_init_helper(pyb_dac_obj_t *self, size_t n_args, const mp
__HAL_RCC_DAC12_CLK_ENABLE();
#elif defined(STM32F0) || defined(STM32G0) || defined(STM32G4) || defined(STM32L4)
__HAL_RCC_DAC1_CLK_ENABLE();
+ #elif defined(STM32L1)
+ __HAL_RCC_DAC_CLK_ENABLE();
#else
#error Unsupported Processor
#endif
@@ -502,12 +504,13 @@ STATIC const mp_rom_map_elem_t pyb_dac_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(pyb_dac_locals_dict, pyb_dac_locals_dict_table);
-const mp_obj_type_t pyb_dac_type = {
- { &mp_type_type },
- .name = MP_QSTR_DAC,
- .print = pyb_dac_print,
- .make_new = pyb_dac_make_new,
- .locals_dict = (mp_obj_dict_t *)&pyb_dac_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ pyb_dac_type,
+ MP_QSTR_DAC,
+ MP_TYPE_FLAG_NONE,
+ make_new, pyb_dac_make_new,
+ print, pyb_dac_print,
+ locals_dict, &pyb_dac_locals_dict
+ );
#endif // MICROPY_HW_ENABLE_DAC
diff --git a/ports/stm32/dma.c b/ports/stm32/dma.c
index 2dc6e8e8b463..29306f1b271c 100644
--- a/ports/stm32/dma.c
+++ b/ports/stm32/dma.c
@@ -80,7 +80,7 @@ typedef union {
struct _dma_descr_t {
#if defined(STM32F4) || defined(STM32F7) || defined(STM32H7)
DMA_Stream_TypeDef *instance;
- #elif defined(STM32F0) || defined(STM32G0) || defined(STM32G4) || defined(STM32L0) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL)
+ #elif defined(STM32F0) || defined(STM32G0) || defined(STM32G4) || defined(STM32L0) || defined(STM32L1) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL)
DMA_Channel_TypeDef *instance;
#else
#error "Unsupported Processor"
@@ -398,6 +398,57 @@ static const uint8_t dma_irqn[NSTREAM] = {
DMA1_Channel4_5_6_7_IRQn,
};
+#elif defined(STM32L1)
+
+#define NCONTROLLERS (2)
+#define NSTREAMS_PER_CONTROLLER (7)
+#define NSTREAM (NCONTROLLERS * NSTREAMS_PER_CONTROLLER)
+
+#define DMA_SUB_INSTANCE_AS_UINT8(dma_request) (dma_request)
+
+#define DMA1_ENABLE_MASK (0x007f) // Bits in dma_enable_mask corresponding to DMA1
+#define DMA2_ENABLE_MASK (0x0f80) // Bits in dma_enable_mask corresponding to DMA2
+
+// These descriptors are ordered by DMAx_Channel number, and within a channel by request
+// number. The duplicate streams are ok as long as they aren't used at the same time.
+
+// DMA1 streams
+const dma_descr_t dma_SPI_1_RX = { DMA1_Channel2, 2, dma_id_1, &dma_init_struct_spi_i2c };
+#if MICROPY_HW_ENABLE_DAC
+const dma_descr_t dma_DAC_1_TX = { DMA1_Channel2, 2, dma_id_1, &dma_init_struct_dac };
+#endif
+const dma_descr_t dma_SPI_1_TX = { DMA1_Channel3, 3, dma_id_2, &dma_init_struct_spi_i2c };
+#if MICROPY_HW_ENABLE_DAC
+const dma_descr_t dma_DAC_2_TX = { DMA1_Channel3, 3, dma_id_2, &dma_init_struct_dac };
+#endif
+const dma_descr_t dma_SPI_2_RX = { DMA1_Channel4, 4, dma_id_3, &dma_init_struct_spi_i2c };
+const dma_descr_t dma_I2C_2_TX = { DMA1_Channel4, 4, dma_id_3, &dma_init_struct_spi_i2c };
+const dma_descr_t dma_SPI_2_TX = { DMA1_Channel5, 5, dma_id_4, &dma_init_struct_spi_i2c };
+const dma_descr_t dma_I2C_2_RX = { DMA1_Channel5, 5, dma_id_4, &dma_init_struct_spi_i2c };
+const dma_descr_t dma_I2C_1_TX = { DMA1_Channel6, 6, dma_id_5, &dma_init_struct_spi_i2c };
+const dma_descr_t dma_I2C_1_RX = { DMA1_Channel7, 7, dma_id_6, &dma_init_struct_spi_i2c };
+
+// DMA2 streams
+const dma_descr_t dma_SPI_3_RX = { DMA2_Channel1, 3, dma_id_7, &dma_init_struct_spi_i2c };
+const dma_descr_t dma_SPI_3_TX = { DMA2_Channel2, 3, dma_id_8, &dma_init_struct_spi_i2c };
+
+static const uint8_t dma_irqn[NSTREAM] = {
+ DMA1_Channel1_IRQn,
+ DMA1_Channel2_IRQn,
+ DMA1_Channel3_IRQn,
+ DMA1_Channel4_IRQn,
+ DMA1_Channel5_IRQn,
+ DMA1_Channel6_IRQn,
+ DMA1_Channel7_IRQn,
+ DMA2_Channel1_IRQn,
+ DMA2_Channel2_IRQn,
+ DMA2_Channel3_IRQn,
+ DMA2_Channel4_IRQn,
+ DMA2_Channel5_IRQn,
+ 0,
+ 0
+};
+
#elif defined(STM32L4)
#define NCONTROLLERS (2)
@@ -705,7 +756,7 @@ volatile dma_idle_count_t dma_idle;
#define DMA_INVALID_CHANNEL 0xff // Value stored in dma_last_channel which means invalid
-#if defined(STM32F0) || defined(STM32G0) || defined(STM32L0)
+#if defined(STM32F0) || defined(STM32G0) || defined(STM32L0) || defined(STM32L1)
#define DMA1_IS_CLK_ENABLED() ((RCC->AHBENR & RCC_AHBENR_DMA1EN) != 0)
#if defined(DMA2)
#define DMA2_IS_CLK_ENABLED() ((RCC->AHBENR & RCC_AHBENR_DMA2EN) != 0)
@@ -1080,7 +1131,7 @@ void DMA1_Channel4_5_6_7_IRQHandler(void) {
IRQ_EXIT(DMA1_Channel4_5_6_7_IRQn);
}
-#elif defined(STM32L4) || defined(STM32WB)
+#elif defined(STM32L1) || defined(STM32L4) || defined(STM32WB)
void DMA1_Channel1_IRQHandler(void) {
IRQ_ENTER(DMA1_Channel1_IRQn);
@@ -1166,6 +1217,7 @@ void DMA2_Channel5_IRQHandler(void) {
}
IRQ_EXIT(DMA2_Channel5_IRQn);
}
+#if !defined(STM32L1)
void DMA2_Channel6_IRQHandler(void) {
IRQ_ENTER(DMA2_Channel6_IRQn);
if (dma_handle[dma_id_12] != NULL) {
@@ -1180,6 +1232,7 @@ void DMA2_Channel7_IRQHandler(void) {
}
IRQ_EXIT(DMA2_Channel7_IRQn);
}
+#endif
#endif
@@ -1260,7 +1313,7 @@ void dma_init_handle(DMA_HandleTypeDef *dma, const dma_descr_t *dma_descr, uint3
#if defined(STM32G0) || defined(STM32G4) || defined(STM32H7) || defined(STM32L0) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL)
dma->Init.Request = dma_descr->sub_instance;
#else
- #if !defined(STM32F0)
+ #if !defined(STM32F0) && !defined(STM32L1)
dma->Init.Channel = dma_descr->sub_instance;
#endif
#endif
@@ -1284,7 +1337,7 @@ void dma_init(DMA_HandleTypeDef *dma, const dma_descr_t *dma_descr, uint32_t dir
dma_enable_clock(dma_id);
- #if defined(STM32G0) || defined(STM32G4) || defined(STM32H7) || defined(STM32L0) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL)
+ #if defined(STM32G0) || defined(STM32G4) || defined(STM32H7) || defined(STM32L0) || defined(STM32L1) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL)
// Always reset and configure the H7 and G0/G4/H7/L0/L4/WB/WL DMA peripheral
// (dma->State is set to HAL_DMA_STATE_RESET by memset above)
// TODO: understand how L0/L4 DMA works so this is not needed
@@ -1410,7 +1463,7 @@ static void dma_idle_handler(uint32_t tick) {
}
#endif
-#if defined(STM32F0) || defined(STM32G4) || defined(STM32L0) || defined(STM32L4)
+#if defined(STM32F0) || defined(STM32G4) || defined(STM32L0) || defined(STM32L1) || defined(STM32L4)
void dma_nohal_init(const dma_descr_t *descr, uint32_t config) {
DMA_Channel_TypeDef *dma = descr->instance;
@@ -1436,6 +1489,7 @@ void dma_nohal_init(const dma_descr_t *descr, uint32_t config) {
#elif defined(STM32G4)
uint32_t *dmamux_ctrl = (void *)(DMAMUX1_Channel0_BASE + 0x04 * descr->id);
*dmamux_ctrl = (*dmamux_ctrl & ~(0x7f)) | descr->sub_instance;
+ #elif defined(STM32L1)
#else
DMA_Request_TypeDef *dma_ctrl = (void *)(((uint32_t)dma & ~0xff) + (DMA1_CSELR_BASE - DMA1_BASE)); // DMA1_CSELR or DMA2_CSELR
uint32_t channel_number = (((uint32_t)dma & 0xff) - 0x08) / 20; // 0 through 6
diff --git a/ports/stm32/dma.h b/ports/stm32/dma.h
index 70c7e6a00523..37b8710c214c 100644
--- a/ports/stm32/dma.h
+++ b/ports/stm32/dma.h
@@ -100,6 +100,20 @@ extern const dma_descr_t dma_I2C_2_RX;
extern const dma_descr_t dma_I2C_1_TX;
extern const dma_descr_t dma_I2C_1_RX;
+#elif defined(STM32L1)
+extern const dma_descr_t dma_SPI_1_RX;
+extern const dma_descr_t dma_SPI_3_TX;
+extern const dma_descr_t dma_SPI_1_TX;
+extern const dma_descr_t dma_SPI_3_RX;
+extern const dma_descr_t dma_DAC_1_TX;
+extern const dma_descr_t dma_SPI_2_RX;
+extern const dma_descr_t dma_I2C_2_TX;
+extern const dma_descr_t dma_DAC_2_TX;
+extern const dma_descr_t dma_SPI_2_TX;
+extern const dma_descr_t dma_I2C_2_RX;
+extern const dma_descr_t dma_I2C_1_TX;
+extern const dma_descr_t dma_I2C_1_RX;
+
#elif defined(STM32L4) || defined(STM32WB) || defined(STM32WL)
extern const dma_descr_t dma_ADC_1_RX;
diff --git a/ports/stm32/eth.c b/ports/stm32/eth.c
index be418235e13d..1207a728c388 100644
--- a/ports/stm32/eth.c
+++ b/ports/stm32/eth.c
@@ -737,7 +737,7 @@ STATIC void eth_lwip_init(eth_t *self) {
n->name[0] = 'e';
n->name[1] = '0';
netif_add(n, &ipconfig[0], &ipconfig[1], &ipconfig[2], self, eth_netif_init, ethernet_input);
- netif_set_hostname(n, "MPY");
+ netif_set_hostname(n, mod_network_hostname);
netif_set_default(n);
netif_set_up(n);
diff --git a/ports/stm32/extint.c b/ports/stm32/extint.c
index fd4dca276bbe..f810bc4e0d41 100644
--- a/ports/stm32/extint.c
+++ b/ports/stm32/extint.c
@@ -24,10 +24,6 @@
* THE SOFTWARE.
*/
-#include
-#include
-#include
-
#include "py/runtime.h"
#include "py/gc.h"
#include "py/mphal.h"
@@ -36,6 +32,11 @@
#include "extint.h"
#include "irq.h"
+#if MICROPY_PY_NETWORK_CYW43 && defined(pyb_pin_WL_HOST_WAKE)
+#include "lib/cyw43-driver/src/cyw43.h"
+#include "lib/cyw43-driver/src/cyw43_stats.h"
+#endif
+
/// \moduleref pyb
/// \class ExtInt - configure I/O pins to interrupt on external events
///
@@ -210,7 +211,11 @@ STATIC const uint8_t nvic_irq_channel[EXTI_NUM_VECTORS] = {
#endif
ETH_WKUP_IRQn,
OTG_HS_WKUP_IRQn,
+ #if defined(STM32L1)
+ TAMPER_STAMP_IRQn,
+ #else
TAMP_STAMP_IRQn,
+ #endif
RTC_WKUP_IRQn,
#endif
@@ -545,53 +550,56 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(extint_obj_swint_obj, extint_obj_swint);
/// \classmethod regs()
/// Dump the values of the EXTI registers.
STATIC mp_obj_t extint_regs(void) {
+ const mp_print_t *print = &mp_plat_print;
+
#if defined(STM32G0) || defined(STM32G4) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL)
- printf("EXTI_IMR1 %08x\n", (unsigned int)EXTI->IMR1);
- printf("EXTI_IMR2 %08x\n", (unsigned int)EXTI->IMR2);
- printf("EXTI_EMR1 %08x\n", (unsigned int)EXTI->EMR1);
- printf("EXTI_EMR2 %08x\n", (unsigned int)EXTI->EMR2);
- printf("EXTI_RTSR1 %08x\n", (unsigned int)EXTI->RTSR1);
- printf("EXTI_RTSR2 %08x\n", (unsigned int)EXTI->RTSR2);
- printf("EXTI_FTSR1 %08x\n", (unsigned int)EXTI->FTSR1);
- printf("EXTI_FTSR2 %08x\n", (unsigned int)EXTI->FTSR2);
- printf("EXTI_SWIER1 %08x\n", (unsigned int)EXTI->SWIER1);
- printf("EXTI_SWIER2 %08x\n", (unsigned int)EXTI->SWIER2);
+ mp_printf(print, "EXTI_IMR1 %08x\n", (unsigned int)EXTI->IMR1);
+ mp_printf(print, "EXTI_IMR2 %08x\n", (unsigned int)EXTI->IMR2);
+ mp_printf(print, "EXTI_EMR1 %08x\n", (unsigned int)EXTI->EMR1);
+ mp_printf(print, "EXTI_EMR2 %08x\n", (unsigned int)EXTI->EMR2);
+ mp_printf(print, "EXTI_RTSR1 %08x\n", (unsigned int)EXTI->RTSR1);
+ mp_printf(print, "EXTI_RTSR2 %08x\n", (unsigned int)EXTI->RTSR2);
+ mp_printf(print, "EXTI_FTSR1 %08x\n", (unsigned int)EXTI->FTSR1);
+ mp_printf(print, "EXTI_FTSR2 %08x\n", (unsigned int)EXTI->FTSR2);
+ mp_printf(print, "EXTI_SWIER1 %08x\n", (unsigned int)EXTI->SWIER1);
+ mp_printf(print, "EXTI_SWIER2 %08x\n", (unsigned int)EXTI->SWIER2);
#if defined(STM32G0)
- printf("EXTI_RPR1 %08x\n", (unsigned int)EXTI->RPR1);
- printf("EXTI_FPR1 %08x\n", (unsigned int)EXTI->FPR1);
- printf("EXTI_RPR2 %08x\n", (unsigned int)EXTI->RPR2);
- printf("EXTI_FPR2 %08x\n", (unsigned int)EXTI->FPR2);
+ mp_printf(print, "EXTI_RPR1 %08x\n", (unsigned int)EXTI->RPR1);
+ mp_printf(print, "EXTI_FPR1 %08x\n", (unsigned int)EXTI->FPR1);
+ mp_printf(print, "EXTI_RPR2 %08x\n", (unsigned int)EXTI->RPR2);
+ mp_printf(print, "EXTI_FPR2 %08x\n", (unsigned int)EXTI->FPR2);
#else
- printf("EXTI_PR1 %08x\n", (unsigned int)EXTI->PR1);
- printf("EXTI_PR2 %08x\n", (unsigned int)EXTI->PR2);
+ mp_printf(print, "EXTI_PR1 %08x\n", (unsigned int)EXTI->PR1);
+ mp_printf(print, "EXTI_PR2 %08x\n", (unsigned int)EXTI->PR2);
#endif
#elif defined(STM32H7)
- printf("EXTI_IMR1 %08x\n", (unsigned int)EXTI_D1->IMR1);
- printf("EXTI_IMR2 %08x\n", (unsigned int)EXTI_D1->IMR2);
- printf("EXTI_IMR3 %08x\n", (unsigned int)EXTI_D1->IMR3);
- printf("EXTI_EMR1 %08x\n", (unsigned int)EXTI_D1->EMR1);
- printf("EXTI_EMR2 %08x\n", (unsigned int)EXTI_D1->EMR2);
- printf("EXTI_EMR3 %08x\n", (unsigned int)EXTI_D1->EMR3);
- printf("EXTI_RTSR1 %08x\n", (unsigned int)EXTI->RTSR1);
- printf("EXTI_RTSR2 %08x\n", (unsigned int)EXTI->RTSR2);
- printf("EXTI_RTSR3 %08x\n", (unsigned int)EXTI->RTSR3);
- printf("EXTI_FTSR1 %08x\n", (unsigned int)EXTI->FTSR1);
- printf("EXTI_FTSR2 %08x\n", (unsigned int)EXTI->FTSR2);
- printf("EXTI_FTSR3 %08x\n", (unsigned int)EXTI->FTSR3);
- printf("EXTI_SWIER1 %08x\n", (unsigned int)EXTI->SWIER1);
- printf("EXTI_SWIER2 %08x\n", (unsigned int)EXTI->SWIER2);
- printf("EXTI_SWIER3 %08x\n", (unsigned int)EXTI->SWIER3);
- printf("EXTI_PR1 %08x\n", (unsigned int)EXTI_D1->PR1);
- printf("EXTI_PR2 %08x\n", (unsigned int)EXTI_D1->PR2);
- printf("EXTI_PR3 %08x\n", (unsigned int)EXTI_D1->PR3);
+ mp_printf(print, "EXTI_IMR1 %08x\n", (unsigned int)EXTI_D1->IMR1);
+ mp_printf(print, "EXTI_IMR2 %08x\n", (unsigned int)EXTI_D1->IMR2);
+ mp_printf(print, "EXTI_IMR3 %08x\n", (unsigned int)EXTI_D1->IMR3);
+ mp_printf(print, "EXTI_EMR1 %08x\n", (unsigned int)EXTI_D1->EMR1);
+ mp_printf(print, "EXTI_EMR2 %08x\n", (unsigned int)EXTI_D1->EMR2);
+ mp_printf(print, "EXTI_EMR3 %08x\n", (unsigned int)EXTI_D1->EMR3);
+ mp_printf(print, "EXTI_RTSR1 %08x\n", (unsigned int)EXTI->RTSR1);
+ mp_printf(print, "EXTI_RTSR2 %08x\n", (unsigned int)EXTI->RTSR2);
+ mp_printf(print, "EXTI_RTSR3 %08x\n", (unsigned int)EXTI->RTSR3);
+ mp_printf(print, "EXTI_FTSR1 %08x\n", (unsigned int)EXTI->FTSR1);
+ mp_printf(print, "EXTI_FTSR2 %08x\n", (unsigned int)EXTI->FTSR2);
+ mp_printf(print, "EXTI_FTSR3 %08x\n", (unsigned int)EXTI->FTSR3);
+ mp_printf(print, "EXTI_SWIER1 %08x\n", (unsigned int)EXTI->SWIER1);
+ mp_printf(print, "EXTI_SWIER2 %08x\n", (unsigned int)EXTI->SWIER2);
+ mp_printf(print, "EXTI_SWIER3 %08x\n", (unsigned int)EXTI->SWIER3);
+ mp_printf(print, "EXTI_PR1 %08x\n", (unsigned int)EXTI_D1->PR1);
+ mp_printf(print, "EXTI_PR2 %08x\n", (unsigned int)EXTI_D1->PR2);
+ mp_printf(print, "EXTI_PR3 %08x\n", (unsigned int)EXTI_D1->PR3);
#else
- printf("EXTI_IMR %08x\n", (unsigned int)EXTI->IMR);
- printf("EXTI_EMR %08x\n", (unsigned int)EXTI->EMR);
- printf("EXTI_RTSR %08x\n", (unsigned int)EXTI->RTSR);
- printf("EXTI_FTSR %08x\n", (unsigned int)EXTI->FTSR);
- printf("EXTI_SWIER %08x\n", (unsigned int)EXTI->SWIER);
- printf("EXTI_PR %08x\n", (unsigned int)EXTI->PR);
+ mp_printf(print, "EXTI_IMR %08x\n", (unsigned int)EXTI->IMR);
+ mp_printf(print, "EXTI_EMR %08x\n", (unsigned int)EXTI->EMR);
+ mp_printf(print, "EXTI_RTSR %08x\n", (unsigned int)EXTI->RTSR);
+ mp_printf(print, "EXTI_FTSR %08x\n", (unsigned int)EXTI->FTSR);
+ mp_printf(print, "EXTI_SWIER %08x\n", (unsigned int)EXTI->SWIER);
+ mp_printf(print, "EXTI_PR %08x\n", (unsigned int)EXTI->PR);
#endif
+
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(extint_regs_fun_obj, extint_regs);
@@ -659,13 +667,14 @@ STATIC const mp_rom_map_elem_t extint_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(extint_locals_dict, extint_locals_dict_table);
-const mp_obj_type_t extint_type = {
- { &mp_type_type },
- .name = MP_QSTR_ExtInt,
- .print = extint_obj_print,
- .make_new = extint_make_new,
- .locals_dict = (mp_obj_dict_t *)&extint_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ extint_type,
+ MP_QSTR_ExtInt,
+ MP_TYPE_FLAG_NONE,
+ make_new, extint_make_new,
+ print, extint_obj_print,
+ locals_dict, &extint_locals_dict
+ );
void extint_init0(void) {
for (int i = 0; i < PYB_EXTI_NUM_VECTORS; i++) {
@@ -685,9 +694,9 @@ void Handle_EXTI_Irq(uint32_t line) {
mp_obj_t *cb = &MP_STATE_PORT(pyb_extint_callback)[line];
#if MICROPY_PY_NETWORK_CYW43 && defined(pyb_pin_WL_HOST_WAKE)
if (pyb_extint_callback_arg[line] == MP_OBJ_FROM_PTR(pyb_pin_WL_HOST_WAKE)) {
- extern void (*cyw43_poll)(void);
if (cyw43_poll) {
pendsv_schedule_dispatch(PENDSV_DISPATCH_CYW43, cyw43_poll);
+ CYW43_STAT_INC(IRQ_COUNT);
}
return;
}
@@ -720,3 +729,5 @@ void Handle_EXTI_Irq(uint32_t line) {
}
}
}
+
+MP_REGISTER_ROOT_POINTER(mp_obj_t pyb_extint_callback[PYB_EXTI_NUM_VECTORS]);
diff --git a/ports/stm32/extint.h b/ports/stm32/extint.h
index 95e29c97fdc7..84eb876d8d1f 100644
--- a/ports/stm32/extint.h
+++ b/ports/stm32/extint.h
@@ -43,7 +43,7 @@
#endif
#define EXTI_ETH_WAKEUP (19)
#define EXTI_USB_OTG_HS_WAKEUP (20)
-#if defined(STM32F0) || defined(STM32G4) || defined(STM32L4) || defined(STM32WL)
+#if defined(STM32F0) || defined(STM32G4) || defined(STM32L1) || defined(STM32L4) || defined(STM32WL)
#define EXTI_RTC_TIMESTAMP (19)
#define EXTI_RTC_WAKEUP (20)
#elif defined(STM32H7) || defined(STM32WB)
@@ -66,6 +66,7 @@ void extint_init0(void);
uint extint_register(mp_obj_t pin_obj, uint32_t mode, uint32_t pull, mp_obj_t callback_obj, bool override_callback_obj);
void extint_register_pin(const pin_obj_t *pin, uint32_t mode, bool hard_irq, mp_obj_t callback_obj);
+void extint_set(const pin_obj_t *pin, uint32_t mode);
void extint_enable(uint line);
void extint_disable(uint line);
diff --git a/ports/stm32/factoryreset.c b/ports/stm32/factoryreset.c
index 10eb3a17a7eb..2ac656db5950 100644
--- a/ports/stm32/factoryreset.c
+++ b/ports/stm32/factoryreset.c
@@ -42,12 +42,16 @@ static const char fresh_boot_py[] =
"\r\n"
"import machine\r\n"
"import pyb\r\n"
- "pyb.country('US') # ISO 3166-1 Alpha-2 code, eg US, GB, DE, AU\r\n"
"#pyb.main('main.py') # main script to run after this one\r\n"
#if MICROPY_HW_ENABLE_USB
"#pyb.usb_mode('VCP+MSC') # act as a serial and a storage device\r\n"
"#pyb.usb_mode('VCP+HID') # act as a serial device and a mouse\r\n"
#endif
+#if MICROPY_PY_NETWORK
+ "#import network\r\n"
+ "#network.country('US') # ISO 3166-1 Alpha-2 code, eg US, GB, DE, AU or XX for worldwide\r\n"
+ "#network.hostname('...') # DHCP/mDNS hostname\r\n"
+#endif
;
static const char fresh_main_py[] =
diff --git a/ports/stm32/flash.c b/ports/stm32/flash.c
index de537aba212d..12fa523cd56e 100644
--- a/ports/stm32/flash.c
+++ b/ports/stm32/flash.c
@@ -117,6 +117,12 @@ static const flash_layout_t flash_layout[] = {
{ (uint32_t)FLASH_BASE, (uint32_t)FLASH_PAGE_SIZE, 512 },
};
+#elif defined(STM32L1)
+
+static const flash_layout_t flash_layout[] = {
+ { (uint32_t)FLASH_BASE, 0x200, 1024 },
+};
+
#elif defined(STM32H7)
static const flash_layout_t flash_layout[] = {
@@ -127,7 +133,14 @@ static const flash_layout_t flash_layout[] = {
#error Unsupported processor
#endif
-#if (defined(STM32L4) && defined(SYSCFG_MEMRMP_FB_MODE)) || defined(STM32H7)
+#if defined(STM32H723xx) || defined(STM32H750xx)
+
+// get the bank of a given flash address
+static uint32_t get_bank(uint32_t addr) {
+ return FLASH_BANK_1;
+}
+
+#elif (defined(STM32L4) && defined(SYSCFG_MEMRMP_FB_MODE)) || defined(STM32H7)
// get the bank of a given flash address
static uint32_t get_bank(uint32_t addr) {
@@ -264,7 +277,7 @@ int flash_erase(uint32_t flash_dest, uint32_t num_word32) {
EraseInitStruct.Page = get_page(flash_dest);
EraseInitStruct.Banks = get_bank(flash_dest);
EraseInitStruct.NbPages = (4 * num_word32 + FLASH_PAGE_SIZE - 4) / FLASH_PAGE_SIZE;
- #elif defined(STM32L0)
+ #elif defined(STM32L0) || defined(STM32L1)
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR);
EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES;
EraseInitStruct.PageAddress = flash_dest;
@@ -286,6 +299,8 @@ int flash_erase(uint32_t flash_dest, uint32_t num_word32) {
#if defined(STM32H7)
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_ALL_ERRORS_BANK1 | FLASH_FLAG_ALL_ERRORS_BANK2);
+ #elif defined(STM32L1)
+ __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR);
#else
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR |
FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR | FLASH_FLAG_PGSERR);
diff --git a/ports/stm32/gccollect.c b/ports/stm32/gccollect.c
index bd697a2af3b5..083642bce344 100644
--- a/ports/stm32/gccollect.c
+++ b/ports/stm32/gccollect.c
@@ -24,23 +24,13 @@
* THE SOFTWARE.
*/
-#include
-#include
-
-#include "py/mpstate.h"
#include "py/gc.h"
#include "py/mpthread.h"
#include "shared/runtime/gchelper.h"
+#include "shared/runtime/softtimer.h"
#include "gccollect.h"
-#include "softtimer.h"
-#include "systick.h"
void gc_collect(void) {
- // get current time, in case we want to time the GC
- #if 0
- uint32_t start = mp_hal_ticks_us();
- #endif
-
// start the GC
gc_collect_start();
@@ -57,15 +47,4 @@ void gc_collect(void) {
// end the GC
gc_collect_end();
-
- #if 0
- // print GC info
- uint32_t ticks = mp_hal_ticks_us() - start;
- gc_info_t info;
- gc_info(&info);
- printf("GC@%lu %lums\n", start, ticks);
- printf(" " UINT_FMT " total\n", info.total);
- printf(" " UINT_FMT " : " UINT_FMT "\n", info.used, info.free);
- printf(" 1=" UINT_FMT " 2=" UINT_FMT " m=" UINT_FMT "\n", info.num_1block, info.num_2block, info.max_block);
- #endif
}
diff --git a/ports/stm32/i2c.c b/ports/stm32/i2c.c
index c63fe216247b..65271b352525 100644
--- a/ports/stm32/i2c.c
+++ b/ports/stm32/i2c.c
@@ -31,7 +31,7 @@
#if MICROPY_HW_ENABLE_HW_I2C
-#if defined(STM32F4)
+#if defined(STM32F4) || defined(STM32L1)
STATIC uint16_t i2c_timeout_ms[MICROPY_HW_MAX_I2C];
@@ -70,10 +70,11 @@ int i2c_init(i2c_t *i2c, mp_hal_pin_obj_t scl, mp_hal_pin_obj_t sda, uint32_t fr
// SM: MAX(4, PCLK1 / (F * 2))
// FM, 16:9 duty: 0xc000 | MAX(1, (PCLK1 / (F * (16 + 9))))
+ // (the PCLK1-1 and +1 at the end is to round the division up)
if (freq <= 100000) {
- i2c->CCR = MAX(4, PCLK1 / (freq * 2));
+ i2c->CCR = MAX(4, ((PCLK1 - 1) / (freq * 2) + 1));
} else {
- i2c->CCR = 0xc000 | MAX(1, PCLK1 / (freq * 25));
+ i2c->CCR = 0xc000 | MAX(1, ((PCLK1 - 1) / (freq * 25) + 1));
}
// SM: 1000ns / (1/PCLK1) + 1 = PCLK1 * 1e-6 + 1
@@ -268,11 +269,18 @@ int i2c_write(i2c_t *i2c, const uint8_t *src, size_t len, size_t next_len) {
return num_acks;
}
-#elif defined(STM32F0) || defined(STM32F7) || defined(STM32H7)
+#elif defined(STM32F0) || defined(STM32F7) || defined(STM32H7) || defined(STM32L4)
#if defined(STM32H7)
#define APB1ENR APB1LENR
#define RCC_APB1ENR_I2C1EN RCC_APB1LENR_I2C1EN
+#elif defined(STM32L4)
+#define APB1ENR APB1ENR1
+#define RCC_APB1ENR_I2C1EN RCC_APB1ENR1_I2C1EN
+#if defined(STM32L432xx)
+// Not a real peripheral, only needed for i2c_id calculation in i2c_init.
+#define I2C2_BASE (APB1PERIPH_BASE + 0x5800UL)
+#endif
#endif
STATIC uint16_t i2c_timeout_ms[MICROPY_HW_MAX_I2C];
@@ -302,6 +310,18 @@ int i2c_init(i2c_t *i2c, mp_hal_pin_obj_t scl, mp_hal_pin_obj_t sda, uint32_t fr
i2c->OAR1 = 0;
i2c->OAR2 = 0;
+ #if defined(STM32L4)
+ // These timing values are with f_I2CCLK=80MHz and are only approximate
+ if (freq >= 1000000) {
+ i2c->TIMINGR = 0x00300F33;
+ } else if (freq >= 400000) {
+ i2c->TIMINGR = 0x00702991;
+ } else if (freq >= 100000) {
+ i2c->TIMINGR = 0x10909CEC;
+ } else {
+ return -MP_EINVAL;
+ }
+ #else
// These timing values are for f_I2CCLK=54MHz and are only approximate
if (freq >= 1000000) {
i2c->TIMINGR = 0x50100103;
@@ -312,6 +332,7 @@ int i2c_init(i2c_t *i2c, mp_hal_pin_obj_t scl, mp_hal_pin_obj_t sda, uint32_t fr
} else {
return -MP_EINVAL;
}
+ #endif
i2c->TIMEOUTR = 0;
diff --git a/ports/stm32/i2c.h b/ports/stm32/i2c.h
index d494ad66d57f..04a7e928bdbd 100644
--- a/ports/stm32/i2c.h
+++ b/ports/stm32/i2c.h
@@ -47,8 +47,8 @@ extern const mp_obj_type_t pyb_i2c_type;
extern const pyb_i2c_obj_t pyb_i2c_obj[4];
void i2c_init0(void);
-void pyb_i2c_init(I2C_HandleTypeDef *i2c);
-void pyb_i2c_init_freq(const pyb_i2c_obj_t *self, mp_int_t freq);
+int pyb_i2c_init(I2C_HandleTypeDef *i2c);
+int pyb_i2c_init_freq(const pyb_i2c_obj_t *self, mp_int_t freq);
uint32_t pyb_i2c_get_baudrate(I2C_HandleTypeDef *i2c);
void i2c_ev_irq_handler(mp_uint_t i2c_id);
void i2c_er_irq_handler(mp_uint_t i2c_id);
diff --git a/ports/stm32/i2cslave.h b/ports/stm32/i2cslave.h
index 4a51bf378e92..3f9022aa70b7 100644
--- a/ports/stm32/i2cslave.h
+++ b/ports/stm32/i2cslave.h
@@ -43,6 +43,10 @@ static inline void i2c_slave_init(i2c_slave_t *i2c, int irqn, int irq_pri, int a
RCC->APB1ENR |= 1 << (RCC_APB1ENR_I2C1EN_Pos + i2c_idx);
volatile uint32_t tmp = RCC->APB1ENR; // Delay after enabling clock
(void)tmp;
+ #elif defined(STM32G0)
+ RCC->APBENR1 |= 1 << (RCC_APBENR1_I2C1EN_Pos + i2c_idx);
+ volatile uint32_t tmp = RCC->APBENR1; // Delay after enabling clock
+ (void)tmp;
#elif defined(STM32H7)
RCC->APB1LENR |= 1 << (RCC_APB1LENR_I2C1EN_Pos + i2c_idx);
volatile uint32_t tmp = RCC->APB1LENR; // Delay after enabling clock
diff --git a/ports/stm32/lcd.c b/ports/stm32/lcd.c
index a0e001d1fdad..e5d7f30efbd0 100644
--- a/ports/stm32/lcd.c
+++ b/ports/stm32/lcd.c
@@ -525,11 +525,12 @@ STATIC const mp_rom_map_elem_t pyb_lcd_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(pyb_lcd_locals_dict, pyb_lcd_locals_dict_table);
-const mp_obj_type_t pyb_lcd_type = {
- { &mp_type_type },
- .name = MP_QSTR_LCD,
- .make_new = pyb_lcd_make_new,
- .locals_dict = (mp_obj_dict_t *)&pyb_lcd_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ pyb_lcd_type,
+ MP_QSTR_LCD,
+ MP_TYPE_FLAG_NONE,
+ make_new, pyb_lcd_make_new,
+ locals_dict, &pyb_lcd_locals_dict
+ );
#endif // MICROPY_HW_HAS_LCD
diff --git a/ports/stm32/led.c b/ports/stm32/led.c
index 078327462ae1..e70c22532c5b 100644
--- a/ports/stm32/led.c
+++ b/ports/stm32/led.c
@@ -212,7 +212,6 @@ void led_state(pyb_led_t led, int state) {
}
const pin_obj_t *led_pin = pyb_led_obj[led - 1].led_pin;
- // printf("led_state(%d,%d)\n", led, state);
if (state == 0) {
// turn LED off
MICROPY_HW_LED_OFF(led_pin);
@@ -381,13 +380,14 @@ STATIC const mp_rom_map_elem_t led_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(led_locals_dict, led_locals_dict_table);
-const mp_obj_type_t pyb_led_type = {
- { &mp_type_type },
- .name = MP_QSTR_LED,
- .print = led_obj_print,
- .make_new = led_obj_make_new,
- .locals_dict = (mp_obj_dict_t *)&led_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ pyb_led_type,
+ MP_QSTR_LED,
+ MP_TYPE_FLAG_NONE,
+ make_new, led_obj_make_new,
+ print, led_obj_print,
+ locals_dict, &led_locals_dict
+ );
#else
// For boards with no LEDs, we leave an empty function here so that we don't
diff --git a/ports/stm32/machine_adc.c b/ports/stm32/machine_adc.c
index ad7c994ba111..34319e975332 100644
--- a/ports/stm32/machine_adc.c
+++ b/ports/stm32/machine_adc.c
@@ -42,7 +42,7 @@
#define ADCx_COMMON __LL_ADC_COMMON_INSTANCE(0)
#endif
-#if defined(STM32F0) || defined(STM32G0) || defined(STM32L0) || defined(STM32WL)
+#if defined(STM32F0) || defined(STM32G0) || defined(STM32L0) || defined(STM32L1) || defined(STM32WL)
#define ADC_STAB_DELAY_US (1)
#define ADC_TEMPSENSOR_DELAY_US (10)
#elif defined(STM32G4)
@@ -68,6 +68,9 @@
#elif defined(STM32G0) || defined(STM32L0) || defined(STM32WL)
#define ADC_SAMPLETIME_DEFAULT ADC_SAMPLETIME_12CYCLES_5
#define ADC_SAMPLETIME_DEFAULT_INT ADC_SAMPLETIME_160CYCLES_5
+#elif defined(STM32L1)
+#define ADC_SAMPLETIME_DEFAULT ADC_SAMPLETIME_384CYCLES
+#define ADC_SAMPLETIME_DEFAULT_INT ADC_SAMPLETIME_384CYCLES
#elif defined(STM32L4) || defined(STM32WB)
#define ADC_SAMPLETIME_DEFAULT ADC_SAMPLETIME_12CYCLES_5
#define ADC_SAMPLETIME_DEFAULT_INT ADC_SAMPLETIME_247CYCLES_5
@@ -239,7 +242,7 @@ void adc_config(ADC_TypeDef *adc, uint32_t bits) {
STATIC int adc_get_bits(ADC_TypeDef *adc) {
#if defined(STM32F0) || defined(STM32G0) || defined(STM32L0) || defined(STM32WL)
uint32_t res = (adc->CFGR1 & ADC_CFGR1_RES) >> ADC_CFGR1_RES_Pos;
- #elif defined(STM32F4) || defined(STM32F7)
+ #elif defined(STM32F4) || defined(STM32F7) || defined(STM32L1)
uint32_t res = (adc->CR1 & ADC_CR1_RES) >> ADC_CR1_RES_Pos;
#elif defined(STM32G4) || defined(STM32H7) || defined(STM32L4) || defined(STM32WB)
uint32_t res = (adc->CFGR & ADC_CFGR_RES) >> ADC_CFGR_RES_Pos;
@@ -312,7 +315,13 @@ STATIC void adc_config_channel(ADC_TypeDef *adc, uint32_t channel, uint32_t samp
#if defined(STM32H7A3xx) || defined(STM32H7A3xxQ) || defined(STM32H7B3xx) || defined(STM32H7B3xxQ)
ADC_Common_TypeDef *adc_common = ADC12_COMMON;
#elif defined(STM32H7)
+ #if defined(ADC_VER_V5_V90)
+ if (adc != ADC3) {
+ adc->PCSEL_RES0 |= 1 << channel;
+ }
+ #else
adc->PCSEL |= 1 << channel;
+ #endif
ADC_Common_TypeDef *adc_common = adc == ADC3 ? ADC3_COMMON : ADC12_COMMON;
#elif defined(STM32L4)
ADC_Common_TypeDef *adc_common = ADCx_COMMON;
@@ -492,12 +501,13 @@ STATIC const mp_rom_map_elem_t machine_adc_locals_dict_table[] = {
};
STATIC MP_DEFINE_CONST_DICT(machine_adc_locals_dict, machine_adc_locals_dict_table);
-const mp_obj_type_t machine_adc_type = {
- { &mp_type_type },
- .name = MP_QSTR_ADC,
- .print = machine_adc_print,
- .make_new = machine_adc_make_new,
- .locals_dict = (mp_obj_dict_t *)&machine_adc_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ machine_adc_type,
+ MP_QSTR_ADC,
+ MP_TYPE_FLAG_NONE,
+ make_new, machine_adc_make_new,
+ print, machine_adc_print,
+ locals_dict, &machine_adc_locals_dict
+ );
#endif
diff --git a/ports/stm32/machine_i2c.c b/ports/stm32/machine_i2c.c
index 262944585aaa..f4b0b3312562 100644
--- a/ports/stm32/machine_i2c.c
+++ b/ports/stm32/machine_i2c.c
@@ -38,7 +38,7 @@
#define I2C_POLL_DEFAULT_TIMEOUT_US (50000) // 50ms
-#if defined(STM32F0) || defined(STM32F4) || defined(STM32F7) || defined(STM32H7)
+#if defined(STM32F0) || defined(STM32F4) || defined(STM32F7) || defined(STM32H7) || defined(STM32L1) || defined(STM32L4)
typedef struct _machine_hard_i2c_obj_t {
mp_obj_base_t base;
@@ -49,23 +49,23 @@ typedef struct _machine_hard_i2c_obj_t {
STATIC const machine_hard_i2c_obj_t machine_hard_i2c_obj[MICROPY_HW_MAX_I2C] = {
#if defined(MICROPY_HW_I2C1_SCL)
- [0] = {{&machine_hard_i2c_type}, I2C1, MICROPY_HW_I2C1_SCL, MICROPY_HW_I2C1_SDA},
+ [0] = {{&machine_i2c_type}, I2C1, MICROPY_HW_I2C1_SCL, MICROPY_HW_I2C1_SDA},
#endif
#if defined(MICROPY_HW_I2C2_SCL)
- [1] = {{&machine_hard_i2c_type}, I2C2, MICROPY_HW_I2C2_SCL, MICROPY_HW_I2C2_SDA},
+ [1] = {{&machine_i2c_type}, I2C2, MICROPY_HW_I2C2_SCL, MICROPY_HW_I2C2_SDA},
#endif
#if defined(MICROPY_HW_I2C3_SCL)
- [2] = {{&machine_hard_i2c_type}, I2C3, MICROPY_HW_I2C3_SCL, MICROPY_HW_I2C3_SDA},
+ [2] = {{&machine_i2c_type}, I2C3, MICROPY_HW_I2C3_SCL, MICROPY_HW_I2C3_SDA},
#endif
#if defined(MICROPY_HW_I2C4_SCL)
- [3] = {{&machine_hard_i2c_type}, I2C4, MICROPY_HW_I2C4_SCL, MICROPY_HW_I2C4_SDA},
+ [3] = {{&machine_i2c_type}, I2C4, MICROPY_HW_I2C4_SCL, MICROPY_HW_I2C4_SDA},
#endif
};
STATIC void machine_hard_i2c_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
machine_hard_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in);
- #if defined(STM32F4)
+ #if defined(STM32F4) || defined(STM32L1)
uint32_t freq = self->i2c->CR2 & 0x3f;
uint32_t ccr = self->i2c->CCR;
@@ -140,16 +140,16 @@ typedef mp_machine_soft_i2c_obj_t machine_hard_i2c_obj_t;
STATIC machine_hard_i2c_obj_t machine_hard_i2c_obj[MICROPY_HW_MAX_I2C] = {
#if defined(MICROPY_HW_I2C1_SCL)
- [0] = {{&machine_hard_i2c_type}, 1, I2C_POLL_DEFAULT_TIMEOUT_US, MICROPY_HW_I2C1_SCL, MICROPY_HW_I2C1_SDA},
+ [0] = {{&machine_i2c_type}, 1, I2C_POLL_DEFAULT_TIMEOUT_US, MICROPY_HW_I2C1_SCL, MICROPY_HW_I2C1_SDA},
#endif
#if defined(MICROPY_HW_I2C2_SCL)
- [1] = {{&machine_hard_i2c_type}, 1, I2C_POLL_DEFAULT_TIMEOUT_US, MICROPY_HW_I2C2_SCL, MICROPY_HW_I2C2_SDA},
+ [1] = {{&machine_i2c_type}, 1, I2C_POLL_DEFAULT_TIMEOUT_US, MICROPY_HW_I2C2_SCL, MICROPY_HW_I2C2_SDA},
#endif
#if defined(MICROPY_HW_I2C3_SCL)
- [2] = {{&machine_hard_i2c_type}, 1, I2C_POLL_DEFAULT_TIMEOUT_US, MICROPY_HW_I2C3_SCL, MICROPY_HW_I2C3_SDA},
+ [2] = {{&machine_i2c_type}, 1, I2C_POLL_DEFAULT_TIMEOUT_US, MICROPY_HW_I2C3_SCL, MICROPY_HW_I2C3_SDA},
#endif
#if defined(MICROPY_HW_I2C4_SCL)
- [3] = {{&machine_hard_i2c_type}, 1, I2C_POLL_DEFAULT_TIMEOUT_US, MICROPY_HW_I2C4_SCL, MICROPY_HW_I2C4_SDA},
+ [3] = {{&machine_i2c_type}, 1, I2C_POLL_DEFAULT_TIMEOUT_US, MICROPY_HW_I2C4_SCL, MICROPY_HW_I2C4_SDA},
#endif
};
@@ -186,7 +186,7 @@ STATIC void machine_hard_i2c_init(machine_hard_i2c_obj_t *self, uint32_t freq, u
/******************************************************************************/
/* MicroPython bindings for machine API */
-#if defined(STM32F0) || defined(STM32F7) || defined(STM32H7)
+#if defined(STM32F0) || defined(STM32F7) || defined(STM32H7) || defined(STM32L4)
#define MACHINE_I2C_TIMINGR (1)
#else
#define MACHINE_I2C_TIMINGR (0)
@@ -236,13 +236,14 @@ STATIC const mp_machine_i2c_p_t machine_hard_i2c_p = {
.transfer = machine_hard_i2c_transfer,
};
-const mp_obj_type_t machine_hard_i2c_type = {
- { &mp_type_type },
- .name = MP_QSTR_I2C,
- .print = machine_hard_i2c_print,
- .make_new = machine_hard_i2c_make_new,
- .protocol = &machine_hard_i2c_p,
- .locals_dict = (mp_obj_dict_t *)&mp_machine_i2c_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ machine_i2c_type,
+ MP_QSTR_I2C,
+ MP_TYPE_FLAG_NONE,
+ make_new, machine_hard_i2c_make_new,
+ print, machine_hard_i2c_print,
+ protocol, &machine_hard_i2c_p,
+ locals_dict, &mp_machine_i2c_locals_dict
+ );
#endif // MICROPY_HW_ENABLE_HW_I2C
diff --git a/ports/stm32/machine_i2s.c b/ports/stm32/machine_i2s.c
index a9d0da43d442..83ac6bc124eb 100644
--- a/ports/stm32/machine_i2s.c
+++ b/ports/stm32/machine_i2s.c
@@ -1114,15 +1114,16 @@ STATIC const mp_stream_p_t i2s_stream_p = {
.is_text = false,
};
-const mp_obj_type_t machine_i2s_type = {
- { &mp_type_type },
- .name = MP_QSTR_I2S,
- .print = machine_i2s_print,
- .getiter = mp_identity_getiter,
- .iternext = mp_stream_unbuffered_iter,
- .protocol = &i2s_stream_p,
- .make_new = machine_i2s_make_new,
- .locals_dict = (mp_obj_dict_t *)&machine_i2s_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ machine_i2s_type,
+ MP_QSTR_I2S,
+ MP_TYPE_FLAG_ITER_IS_STREAM,
+ make_new, machine_i2s_make_new,
+ print, machine_i2s_print,
+ protocol, &i2s_stream_p,
+ locals_dict, &machine_i2s_locals_dict
+ );
+
+MP_REGISTER_ROOT_POINTER(struct _machine_i2s_obj_t *machine_i2s_obj[MICROPY_HW_MAX_I2S]);
#endif // MICROPY_HW_ENABLE_I2S
diff --git a/ports/stm32/machine_spi.c b/ports/stm32/machine_spi.c
index 37c026cefc33..ddbd42bf2936 100644
--- a/ports/stm32/machine_spi.c
+++ b/ports/stm32/machine_spi.c
@@ -32,12 +32,12 @@
// Implementation of hard SPI for machine module
STATIC const machine_hard_spi_obj_t machine_hard_spi_obj[] = {
- {{&machine_hard_spi_type}, &spi_obj[0]},
- {{&machine_hard_spi_type}, &spi_obj[1]},
- {{&machine_hard_spi_type}, &spi_obj[2]},
- {{&machine_hard_spi_type}, &spi_obj[3]},
- {{&machine_hard_spi_type}, &spi_obj[4]},
- {{&machine_hard_spi_type}, &spi_obj[5]},
+ {{&machine_spi_type}, &spi_obj[0]},
+ {{&machine_spi_type}, &spi_obj[1]},
+ {{&machine_spi_type}, &spi_obj[2]},
+ {{&machine_spi_type}, &spi_obj[3]},
+ {{&machine_spi_type}, &spi_obj[4]},
+ {{&machine_spi_type}, &spi_obj[5]},
};
STATIC void machine_hard_spi_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
@@ -91,7 +91,10 @@ mp_obj_t machine_hard_spi_make_new(const mp_obj_type_t *type, size_t n_args, siz
args[ARG_firstbit].u_int);
// init the SPI bus
- spi_init(self->spi, false);
+ int ret = spi_init(self->spi, false);
+ if (ret != 0) {
+ mp_raise_OSError(-ret);
+ }
return MP_OBJ_FROM_PTR(self);
}
@@ -116,7 +119,10 @@ STATIC void machine_hard_spi_init(mp_obj_base_t *self_in, size_t n_args, const m
args[ARG_firstbit].u_int);
// re-init the SPI bus
- spi_init(self->spi, false);
+ int ret = spi_init(self->spi, false);
+ if (ret != 0) {
+ mp_raise_OSError(-ret);
+ }
}
STATIC void machine_hard_spi_deinit(mp_obj_base_t *self_in) {
@@ -135,11 +141,12 @@ STATIC const mp_machine_spi_p_t machine_hard_spi_p = {
.transfer = machine_hard_spi_transfer,
};
-const mp_obj_type_t machine_hard_spi_type = {
- { &mp_type_type },
- .name = MP_QSTR_SPI,
- .print = machine_hard_spi_print,
- .make_new = machine_hard_spi_make_new,
- .protocol = &machine_hard_spi_p,
- .locals_dict = (mp_obj_dict_t *)&mp_machine_spi_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ machine_spi_type,
+ MP_QSTR_SPI,
+ MP_TYPE_FLAG_NONE,
+ make_new, machine_hard_spi_make_new,
+ print, machine_hard_spi_print,
+ protocol, &machine_hard_spi_p,
+ locals_dict, &mp_machine_spi_locals_dict
+ );
diff --git a/ports/stm32/machine_uart.c b/ports/stm32/machine_uart.c
index bf7bcfb9cd35..bb35bac5cc95 100644
--- a/ports/stm32/machine_uart.c
+++ b/ports/stm32/machine_uart.c
@@ -523,6 +523,12 @@ STATIC mp_obj_t pyb_uart_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_t *
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_uart_irq_obj, 1, pyb_uart_irq);
+// Since uart.write() waits up to the last byte, uart.txdone() always returns True.
+STATIC mp_obj_t machine_uart_txdone(mp_obj_t self_in) {
+ return mp_const_true;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_uart_txdone_obj, machine_uart_txdone);
+
STATIC const mp_rom_map_elem_t pyb_uart_locals_dict_table[] = {
// instance methods
@@ -538,11 +544,13 @@ STATIC const mp_rom_map_elem_t pyb_uart_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) },
/// \method write(buf)
{ MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) },
+ { MP_ROM_QSTR(MP_QSTR_flush), MP_ROM_PTR(&mp_stream_flush_obj) },
{ MP_ROM_QSTR(MP_QSTR_irq), MP_ROM_PTR(&pyb_uart_irq_obj) },
{ MP_ROM_QSTR(MP_QSTR_writechar), MP_ROM_PTR(&pyb_uart_writechar_obj) },
{ MP_ROM_QSTR(MP_QSTR_readchar), MP_ROM_PTR(&pyb_uart_readchar_obj) },
{ MP_ROM_QSTR(MP_QSTR_sendbreak), MP_ROM_PTR(&pyb_uart_sendbreak_obj) },
+ { MP_ROM_QSTR(MP_QSTR_txdone), MP_ROM_PTR(&machine_uart_txdone_obj) },
// class constants
{ MP_ROM_QSTR(MP_QSTR_RTS), MP_ROM_INT(UART_HWCONTROL_RTS) },
@@ -635,6 +643,9 @@ STATIC mp_uint_t pyb_uart_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t a
if ((flags & MP_STREAM_POLL_WR) && uart_tx_avail(self)) {
ret |= MP_STREAM_POLL_WR;
}
+ } else if (request == MP_STREAM_FLUSH) {
+ // Since uart.write() waits up to the last byte, uart.flush() always succeds.
+ ret = 0;
} else {
*errcode = MP_EINVAL;
ret = MP_STREAM_ERROR;
@@ -649,13 +660,12 @@ STATIC const mp_stream_p_t uart_stream_p = {
.is_text = false,
};
-const mp_obj_type_t pyb_uart_type = {
- { &mp_type_type },
- .name = MP_QSTR_UART,
- .print = pyb_uart_print,
- .make_new = pyb_uart_make_new,
- .getiter = mp_identity_getiter,
- .iternext = mp_stream_unbuffered_iter,
- .protocol = &uart_stream_p,
- .locals_dict = (mp_obj_dict_t *)&pyb_uart_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ pyb_uart_type,
+ MP_QSTR_UART,
+ MP_TYPE_FLAG_ITER_IS_STREAM,
+ make_new, pyb_uart_make_new,
+ print, pyb_uart_print,
+ protocol, &uart_stream_p,
+ locals_dict, &pyb_uart_locals_dict
+ );
diff --git a/ports/stm32/main.c b/ports/stm32/main.c
index 875584be8a24..cc0367b824e0 100644
--- a/ports/stm32/main.c
+++ b/ports/stm32/main.c
@@ -34,6 +34,7 @@
#include "py/mphal.h"
#include "shared/readline/readline.h"
#include "shared/runtime/pyexec.h"
+#include "shared/runtime/softtimer.h"
#include "lib/oofatfs/ff.h"
#include "lib/littlefs/lfs1.h"
#include "lib/littlefs/lfs1_util.h"
@@ -47,7 +48,9 @@
#if MICROPY_PY_LWIP
#include "lwip/init.h"
#include "lwip/apps/mdns.h"
-#include "drivers/cyw43/cyw43.h"
+#if MICROPY_PY_NETWORK_CYW43
+#include "lib/cyw43-driver/src/cyw43.h"
+#endif
#endif
#if MICROPY_PY_BLUETOOTH
@@ -65,7 +68,6 @@
#include "gccollect.h"
#include "factoryreset.h"
#include "modmachine.h"
-#include "softtimer.h"
#include "i2c.h"
#include "spi.h"
#include "uart.h"
@@ -97,41 +99,21 @@ STATIC pyb_uart_obj_t pyb_uart_repl_obj;
STATIC uint8_t pyb_uart_repl_rxbuf[MICROPY_HW_UART_REPL_RXBUF];
#endif
-void NORETURN __fatal_error(const char *msg) {
- for (volatile uint delay = 0; delay < 10000000; delay++) {
- }
- led_state(1, 1);
- led_state(2, 1);
- led_state(3, 1);
- led_state(4, 1);
- mp_hal_stdout_tx_strn("\nFATAL ERROR:\n", 14);
- mp_hal_stdout_tx_strn(msg, strlen(msg));
- for (uint i = 0;;) {
- led_toggle(((i++) & 3) + 1);
- for (volatile uint delay = 0; delay < 10000000; delay++) {
- }
- if (i >= 16) {
- // to conserve power
- __WFI();
- }
- }
-}
-
void nlr_jump_fail(void *val) {
printf("FATAL: uncaught exception %p\n", val);
mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(val));
- __fatal_error("");
+ MICROPY_BOARD_FATAL_ERROR("");
}
void abort(void) {
- __fatal_error("abort");
+ MICROPY_BOARD_FATAL_ERROR("abort");
}
#ifndef NDEBUG
void MP_WEAK __assert_func(const char *file, int line, const char *func, const char *expr) {
(void)func;
printf("Assertion '%s' failed, at file %s:%d\n", expr, file, line);
- __fatal_error("");
+ MICROPY_BOARD_FATAL_ERROR("");
}
#endif
@@ -202,7 +184,7 @@ MP_NOINLINE STATIC bool init_flash_fs(uint reset_mode) {
if (len != -1) {
// Detected a littlefs filesystem so create correct block device for it
mp_obj_t args[] = { MP_OBJ_NEW_QSTR(MP_QSTR_len), MP_OBJ_NEW_SMALL_INT(len) };
- bdev = pyb_flash_type.make_new(&pyb_flash_type, 0, 1, args);
+ bdev = MP_OBJ_TYPE_GET_SLOT(&pyb_flash_type, make_new)(&pyb_flash_type, 0, 1, args);
}
#endif
@@ -222,7 +204,7 @@ MP_NOINLINE STATIC bool init_flash_fs(uint reset_mode) {
}
if (ret != 0) {
- printf("MPY: can't mount flash\n");
+ mp_printf(&mp_plat_print, "MPY: can't mount flash\n");
return false;
}
@@ -307,7 +289,7 @@ STATIC bool init_sdcard_fs(void) {
}
if (first_part) {
- printf("MPY: can't mount SD card\n");
+ mp_printf(&mp_plat_print, "MPY: can't mount SD card\n");
return false;
} else {
return true;
@@ -316,6 +298,9 @@ STATIC bool init_sdcard_fs(void) {
#endif
void stm32_main(uint32_t reset_mode) {
+ // Low-level MCU initialisation.
+ stm32_system_init();
+
#if !defined(STM32F0) && defined(MICROPY_HW_VTOR)
// Change IRQ vector table if configured differently
SCB->VTOR = MICROPY_HW_VTOR;
@@ -394,8 +379,10 @@ void stm32_main(uint32_t reset_mode) {
// Enable D2 SRAM1/2/3 clocks.
__HAL_RCC_D2SRAM1_CLK_ENABLE();
__HAL_RCC_D2SRAM2_CLK_ENABLE();
+ #if defined(__HAL_RCC_D2SRAM3_CLK_ENABLE)
__HAL_RCC_D2SRAM3_CLK_ENABLE();
#endif
+ #endif
MICROPY_BOARD_EARLY_INIT();
@@ -572,7 +559,7 @@ void stm32_main(uint32_t reset_mode) {
// Run optional frozen boot code.
#ifdef MICROPY_BOARD_FROZEN_BOOT_FILE
- pyexec_frozen_module(MICROPY_BOARD_FROZEN_BOOT_FILE);
+ pyexec_frozen_module(MICROPY_BOARD_FROZEN_BOOT_FILE, false);
#endif
// Run boot.py (or whatever else a board configures at this stage).
@@ -679,3 +666,5 @@ void stm32_main(uint32_t reset_mode) {
goto soft_reset;
}
+
+MP_REGISTER_ROOT_POINTER(mp_obj_t pyb_config_main);
diff --git a/ports/stm32/make-stmconst.py b/ports/stm32/make-stmconst.py
index 554d66238445..44da3f07eb25 100644
--- a/ports/stm32/make-stmconst.py
+++ b/ports/stm32/make-stmconst.py
@@ -29,6 +29,7 @@ def convert_bytes_to_str(b):
# end compatibility code
+
# given a list of (name,regex) pairs, find the first one that matches the given line
def re_match_first(regexs, line):
for name, regex in regexs:
@@ -72,7 +73,7 @@ class Lexer:
("}", re.compile(r"}$")),
(
"} TypeDef",
- re.compile(r"} *(?P[A-Z][A-Za-z0-9_]+)_(?P([A-Za-z0-9_]+)?)TypeDef;$"),
+ re.compile(r"} *(?P[A-Z][A-Za-z0-9_]*)_(?P([A-Za-z0-9_]+)?)TypeDef;$"),
),
(
"IO reg",
diff --git a/ports/stm32/mbedtls/mbedtls_config.h b/ports/stm32/mbedtls/mbedtls_config.h
index 2e0cb7651a48..bdac07339984 100644
--- a/ports/stm32/mbedtls/mbedtls_config.h
+++ b/ports/stm32/mbedtls/mbedtls_config.h
@@ -26,75 +26,19 @@
#ifndef MICROPY_INCLUDED_MBEDTLS_CONFIG_H
#define MICROPY_INCLUDED_MBEDTLS_CONFIG_H
-// Set mbedtls configuration
-#define MBEDTLS_PLATFORM_MEMORY
-#define MBEDTLS_PLATFORM_NO_STD_FUNCTIONS
-#define MBEDTLS_DEPRECATED_REMOVED
-#define MBEDTLS_ENTROPY_HARDWARE_ALT
-#define MBEDTLS_AES_ROM_TABLES
-#define MBEDTLS_CIPHER_MODE_CBC
-#define MBEDTLS_ECP_DP_SECP192R1_ENABLED
-#define MBEDTLS_ECP_DP_SECP224R1_ENABLED
-#define MBEDTLS_ECP_DP_SECP256R1_ENABLED
-#define MBEDTLS_ECP_DP_SECP384R1_ENABLED
-#define MBEDTLS_ECP_DP_SECP521R1_ENABLED
-#define MBEDTLS_ECP_DP_SECP192K1_ENABLED
-#define MBEDTLS_ECP_DP_SECP224K1_ENABLED
-#define MBEDTLS_ECP_DP_SECP256K1_ENABLED
-#define MBEDTLS_ECP_DP_BP256R1_ENABLED
-#define MBEDTLS_ECP_DP_BP384R1_ENABLED
-#define MBEDTLS_ECP_DP_BP512R1_ENABLED
-#define MBEDTLS_ECP_DP_CURVE25519_ENABLED
-#define MBEDTLS_KEY_EXCHANGE_RSA_ENABLED
-#define MBEDTLS_NO_PLATFORM_ENTROPY
-#define MBEDTLS_PKCS1_V15
-#define MBEDTLS_SHA256_SMALLER
-#define MBEDTLS_SSL_PROTO_TLS1
-#define MBEDTLS_SSL_PROTO_TLS1_1
-#define MBEDTLS_SSL_PROTO_TLS1_2
-#define MBEDTLS_SSL_SERVER_NAME_INDICATION
+// Enable mbedtls modules.
+#define MBEDTLS_HAVE_TIME
+#define MBEDTLS_HAVE_TIME_DATE
-// Use a smaller output buffer to reduce size of SSL context
-#define MBEDTLS_SSL_MAX_CONTENT_LEN (16384)
-#define MBEDTLS_SSL_IN_CONTENT_LEN (MBEDTLS_SSL_MAX_CONTENT_LEN)
-#define MBEDTLS_SSL_OUT_CONTENT_LEN (4096)
+// Time hook.
+#include
+extern time_t stm32_rtctime_seconds(time_t *timer);
+#define MBEDTLS_PLATFORM_TIME_MACRO stm32_rtctime_seconds
-// Enable mbedtls modules
-#define MBEDTLS_AES_C
-#define MBEDTLS_ASN1_PARSE_C
-#define MBEDTLS_BIGNUM_C
-#define MBEDTLS_CIPHER_C
-#define MBEDTLS_CTR_DRBG_C
-// #define MBEDTLS_ECP_C
-#define MBEDTLS_ENTROPY_C
-#define MBEDTLS_ERROR_C
-#define MBEDTLS_MD_C
-#define MBEDTLS_MD5_C
-#define MBEDTLS_OID_C
-#define MBEDTLS_PKCS5_C
-#define MBEDTLS_PK_C
-#define MBEDTLS_PK_PARSE_C
-#define MBEDTLS_PLATFORM_C
-#define MBEDTLS_RSA_C
-#define MBEDTLS_SHA1_C
-#define MBEDTLS_SHA256_C
-#define MBEDTLS_SHA512_C
-#define MBEDTLS_SSL_CLI_C
-#define MBEDTLS_SSL_SRV_C
-#define MBEDTLS_SSL_TLS_C
-#define MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_KEY_EXCHANGE
-#define MBEDTLS_X509_CRT_PARSE_C
-#define MBEDTLS_X509_USE_C
+// Set MicroPython-specific options.
+#define MICROPY_MBEDTLS_CONFIG_BARE_METAL (1)
-// Memory allocation hooks
-#include
-#include
-void *m_tracked_calloc(size_t nmemb, size_t size);
-void m_tracked_free(void *ptr);
-#define MBEDTLS_PLATFORM_STD_CALLOC m_tracked_calloc
-#define MBEDTLS_PLATFORM_STD_FREE m_tracked_free
-#define MBEDTLS_PLATFORM_SNPRINTF_MACRO snprintf
-
-#include "mbedtls/check_config.h"
+// Include common mbedtls configuration.
+#include "extmod/mbedtls/mbedtls_config_common.h"
#endif /* MICROPY_INCLUDED_MBEDTLS_CONFIG_H */
diff --git a/ports/stm32/mbedtls/mbedtls_port.c b/ports/stm32/mbedtls/mbedtls_port.c
index 5c4f8d0f9973..cdfcd172a819 100644
--- a/ports/stm32/mbedtls/mbedtls_port.c
+++ b/ports/stm32/mbedtls/mbedtls_port.c
@@ -27,6 +27,11 @@
#include "rng.h"
#include "mbedtls_config.h"
+#if defined(MBEDTLS_HAVE_TIME) || defined(MBEDTLS_HAVE_TIME_DATE)
+#include "rtc.h"
+#include "shared/timeutils/timeutils.h"
+#endif
+
int mbedtls_hardware_poll(void *data, unsigned char *output, size_t len, size_t *olen) {
uint32_t val = 0;
int n = 0;
@@ -42,3 +47,34 @@ int mbedtls_hardware_poll(void *data, unsigned char *output, size_t len, size_t
}
return 0;
}
+
+#if defined(MBEDTLS_HAVE_TIME)
+time_t stm32_rtctime_seconds(time_t *timer) {
+ rtc_init_finalise();
+ RTC_DateTypeDef date;
+ RTC_TimeTypeDef time;
+ HAL_RTC_GetTime(&RTCHandle, &time, RTC_FORMAT_BIN);
+ HAL_RTC_GetDate(&RTCHandle, &date, RTC_FORMAT_BIN);
+ return timeutils_seconds_since_epoch(2000 + date.Year, date.Month, date.Date, time.Hours, time.Minutes, time.Seconds);
+}
+#endif
+
+#if defined(MBEDTLS_HAVE_TIME_DATE)
+struct tm *gmtime(const time_t *timep) {
+ static struct tm tm;
+ timeutils_struct_time_t tm_buf = {0};
+ timeutils_seconds_since_epoch_to_struct_time(*timep, &tm_buf);
+
+ tm.tm_sec = tm_buf.tm_sec;
+ tm.tm_min = tm_buf.tm_min;
+ tm.tm_hour = tm_buf.tm_hour;
+ tm.tm_mday = tm_buf.tm_mday;
+ tm.tm_mon = tm_buf.tm_mon - 1;
+ tm.tm_year = tm_buf.tm_year - 1900;
+ tm.tm_wday = tm_buf.tm_wday;
+ tm.tm_yday = tm_buf.tm_yday;
+ tm.tm_isdst = -1;
+
+ return &tm;
+}
+#endif
diff --git a/ports/stm32/mboot/Makefile b/ports/stm32/mboot/Makefile
index db39daf8820d..4e3f7597f7af 100755
--- a/ports/stm32/mboot/Makefile
+++ b/ports/stm32/mboot/Makefile
@@ -1,13 +1,17 @@
-# Select the board to build for: if not given on the command line,
-# then default to PYBV10.
+# Select the board to build for:
+ifdef BOARD_DIR
+# Custom board path - remove trailing slash and get the final component of
+# the path as the board name.
+BOARD ?= $(notdir $(BOARD_DIR:/=))
+else
+# If not given on the command line, then default to PYBV10.
BOARD ?= PYBV10
+BOARD_DIR ?= $(abspath ../boards/$(BOARD))
+endif
# If the build directory is not given, make it reflect the board name.
BUILD ?= build-$(BOARD)
-# Allow the directory containing the board configuration to be specified
-BOARD_DIR ?= $(abspath ../boards/$(BOARD))
-
# Set USE_MBOOT to 1 so that TEXT0_ADDR gets set properly for those boards
# that can be built with or without mboot.
USE_MBOOT ?= 1
@@ -58,7 +62,7 @@ INC += -I../$(USBDEV_DIR)/core/inc -I../$(USBDEV_DIR)/class/inc
# the compiler does not optimise these functions in terms of themselves.
CFLAGS_BUILTIN ?= -ffreestanding -fno-builtin -fno-lto
-CFLAGS = $(INC) -Wall -Wpointer-arith -Wdouble-promotion -Wfloat-conversion -Werror -std=gnu99 -nostdlib $(CFLAGS_MOD) $(CFLAGS_EXTRA)
+CFLAGS += $(INC) -Wall -Wpointer-arith -Wdouble-promotion -Wfloat-conversion -Werror -std=gnu99 -nostdlib $(CFLAGS_EXTRA)
CFLAGS += -D$(CMSIS_MCU)
CFLAGS += $(CFLAGS_MCU_$(MCU_SERIES))
CFLAGS += $(COPT)
@@ -75,8 +79,8 @@ CFLAGS += -DMICROPY_HW_STM32WB_FLASH_SYNCRONISATION=0
CFLAGS += -DBOOTLOADER_DFU_USB_VID=$(BOOTLOADER_DFU_USB_VID) -DBOOTLOADER_DFU_USB_PID=$(BOOTLOADER_DFU_USB_PID)
MBOOT_LD_FILES ?= stm32_memory.ld stm32_sections.ld
-LDFLAGS = -nostdlib -L . $(addprefix -T,$(MBOOT_LD_FILES)) -Map=$(@:.elf=.map) --cref
-LIBS = $(shell $(CC) $(CFLAGS) -print-libgcc-file-name)
+LDFLAGS += -nostdlib -L . $(addprefix -T,$(MBOOT_LD_FILES)) -Map=$(@:.elf=.map) --cref
+LIBS += $(shell $(CC) $(CFLAGS) -print-libgcc-file-name)
# Remove uncalled code from the final image.
CFLAGS += -fdata-sections -ffunction-sections
@@ -130,7 +134,12 @@ SRC_C += \
SRC_O += \
$(STARTUP_FILE) \
$(SYSTEM_FILE) \
- ports/stm32/resethandler.o \
+
+ifeq ($(MCU_SERIES),$(filter $(MCU_SERIES),f0 g0 l0))
+SRC_O += ports/stm32/resethandler_m0.o
+else
+SRC_O += ports/stm32/resethandler.o
+endif
ifeq ($(MBOOT_ENABLE_PACKING), 1)
@@ -213,6 +222,7 @@ PREFIX_FILE = ../boards/stm32f4xx_prefix.c
BOARD_PINS = $(BOARD_DIR)/pins.csv
HEADER_BUILD = $(BUILD)/genhdr
GEN_QSTRDEFS_GENERATED = $(HEADER_BUILD)/qstrdefs.generated.h
+GEN_ROOT_POINTERS = $(HEADER_BUILD)/root_pointers.h
GEN_PINS_SRC = $(BUILD)/pins_$(BOARD).c
GEN_PINS_HDR = $(HEADER_BUILD)/pins.h
GEN_PINS_QSTR = $(HEADER_BUILD)/pins_qstr.h
@@ -220,7 +230,7 @@ GEN_PINS_AF_CONST = $(HEADER_BUILD)/pins_af_const.h
GEN_PINS_AF_DEFS = $(HEADER_BUILD)/pins_af_defs.h
GEN_PINS_AF_PY = $(BUILD)/pins_af.py
-$(OBJ): $(GEN_QSTRDEFS_GENERATED) $(GEN_PINS_AF_DEFS)
+$(OBJ): $(GEN_QSTRDEFS_GENERATED) $(GEN_ROOT_POINTERS) $(GEN_PINS_AF_DEFS)
$(HEADER_BUILD):
$(MKDIR) -p $(BUILD)/genhdr
@@ -228,6 +238,9 @@ $(HEADER_BUILD):
$(GEN_QSTRDEFS_GENERATED): | $(HEADER_BUILD)
$(Q)echo "// empty" > $@
+$(GEN_ROOT_POINTERS): | $(HEADER_BUILD)
+ $(Q)echo "// empty" > $@
+
$(GEN_PINS_AF_DEFS): $(BOARD_PINS) $(MAKE_PINS) ../$(AF_FILE) $(PREFIX_FILE) | $(HEADER_BUILD)
$(ECHO) "GEN $@"
$(Q)$(PYTHON) $(MAKE_PINS) --board $(BOARD_PINS) --af ../$(AF_FILE) \
diff --git a/ports/stm32/mboot/main.c b/ports/stm32/mboot/main.c
index 734c6a3b7d4e..e2183f9c7237 100644
--- a/ports/stm32/mboot/main.c
+++ b/ports/stm32/mboot/main.c
@@ -108,9 +108,15 @@
// These bits are used to detect valid application firmware at APPLICATION_ADDR
#define APP_VALIDITY_BITS (0x00000003)
+// Symbol provided by the linker, at the address in flash where mboot can start erasing/writing.
+extern uint8_t _mboot_writable_flash_start;
+
// For 1ms system ticker.
volatile uint32_t systick_ms;
+// The sector number of the first sector that can be erased/written.
+int32_t first_writable_flash_sector;
+
// Global dfu state
dfu_context_t dfu_context SECTION_NOZERO_BSS;
@@ -365,6 +371,9 @@ void SystemClock_Config(void) {
#if defined(STM32F4) || defined(STM32F7)
#define AHBxENR AHB1ENR
#define AHBxENR_GPIOAEN_Pos RCC_AHB1ENR_GPIOAEN_Pos
+#elif defined(STM32G0)
+#define AHBxENR IOPENR
+#define AHBxENR_GPIOAEN_Pos RCC_IOPENR_GPIOAEN_Pos
#elif defined(STM32H7)
#define AHBxENR AHB4ENR
#define AHBxENR_GPIOAEN_Pos RCC_AHB4ENR_GPIOAEN_Pos
@@ -400,10 +409,11 @@ void mp_hal_pin_config_speed(uint32_t port_pin, uint32_t speed) {
/******************************************************************************/
// FLASH
-#if defined(STM32WB)
+#if defined(STM32G0)
+#define FLASH_END (FLASH_BASE + FLASH_SIZE - 1)
+#elif defined(STM32WB)
#define FLASH_END FLASH_END_ADDR
#endif
-#define APPLICATION_FLASH_LENGTH (FLASH_END + 1 - APPLICATION_ADDR)
#ifndef MBOOT_SPIFLASH_LAYOUT
#define MBOOT_SPIFLASH_LAYOUT ""
@@ -421,6 +431,8 @@ void mp_hal_pin_config_speed(uint32_t port_pin, uint32_t speed) {
#define FLASH_LAYOUT_STR "@Internal Flash /0x08000000/04*016Kg,01*064Kg,07*128Kg" MBOOT_SPIFLASH_LAYOUT MBOOT_SPIFLASH2_LAYOUT
#elif defined(STM32F765xx) || defined(STM32F767xx) || defined(STM32F769xx)
#define FLASH_LAYOUT_STR "@Internal Flash /0x08000000/04*032Kg,01*128Kg,07*256Kg" MBOOT_SPIFLASH_LAYOUT MBOOT_SPIFLASH2_LAYOUT
+#elif defined(STM32G0)
+#define FLASH_LAYOUT_STR "@Internal Flash /0x08000000/256*02Kg" MBOOT_SPIFLASH_LAYOUT MBOOT_SPIFLASH2_LAYOUT
#elif defined(STM32H743xx)
#define FLASH_LAYOUT_STR "@Internal Flash /0x08000000/16*128Kg" MBOOT_SPIFLASH_LAYOUT MBOOT_SPIFLASH2_LAYOUT
#elif defined(STM32H750xx)
@@ -431,7 +443,9 @@ void mp_hal_pin_config_speed(uint32_t port_pin, uint32_t speed) {
static int mboot_flash_mass_erase(void) {
// Erase all flash pages after mboot.
- int ret = flash_erase(APPLICATION_ADDR, APPLICATION_FLASH_LENGTH / sizeof(uint32_t));
+ uint32_t start_addr = (uint32_t)&_mboot_writable_flash_start;
+ uint32_t num_words = (FLASH_END + 1 - start_addr) / sizeof(uint32_t);
+ int ret = flash_erase(start_addr, num_words);
return ret;
}
@@ -439,7 +453,7 @@ static int mboot_flash_page_erase(uint32_t addr, uint32_t *next_addr) {
uint32_t sector_size = 0;
uint32_t sector_start = 0;
int32_t sector = flash_get_sector_info(addr, §or_start, §or_size);
- if (sector <= 0) {
+ if (sector < first_writable_flash_sector) {
// Don't allow to erase the sector with this bootloader in it, or invalid sectors
dfu_context.status = DFU_STATUS_ERROR_ADDRESS;
dfu_context.error = (sector == 0) ? MBOOT_ERROR_STR_OVERWRITE_BOOTLOADER_IDX
@@ -467,8 +481,8 @@ static int mboot_flash_page_erase(uint32_t addr, uint32_t *next_addr) {
static int mboot_flash_write(uint32_t addr, const uint8_t *src8, size_t len) {
int32_t sector = flash_get_sector_info(addr, NULL, NULL);
- if (sector <= 0) {
- // Don't allow to write the sector with this bootloader in it
+ if (sector < first_writable_flash_sector) {
+ // Don't allow to write the sector with this bootloader in it, or invalid sectors.
dfu_context.status = DFU_STATUS_ERROR_ADDRESS;
dfu_context.error = (sector == 0) ? MBOOT_ERROR_STR_OVERWRITE_BOOTLOADER_IDX
: MBOOT_ERROR_STR_INVALID_ADDRESS_IDX;
@@ -1304,6 +1318,9 @@ extern PCD_HandleTypeDef pcd_fs_handle;
extern PCD_HandleTypeDef pcd_hs_handle;
void stm32_main(uint32_t initial_r0) {
+ // Low-level MCU initialisation.
+ stm32_system_init();
+
#if defined(STM32H7)
// Configure write-once power options, and wait for voltage levels to be ready
PWR->CR3 = PWR_CR3_LDOEN;
@@ -1339,7 +1356,9 @@ void stm32_main(uint32_t initial_r0) {
#endif
#endif
+ #if __CORTEX_M >= 0x03
NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);
+ #endif
#if USE_CACHE && defined(STM32F7)
SCB_EnableICache();
@@ -1379,6 +1398,12 @@ void stm32_main(uint32_t initial_r0) {
__ASM volatile ("msr basepri_max, %0" : : "r" (pri) : "memory");
#endif
+ // Compute the first erasable/writable internal flash sector.
+ first_writable_flash_sector = flash_get_sector_info((uint32_t)&_mboot_writable_flash_start, NULL, NULL);
+ if (first_writable_flash_sector < 0) {
+ first_writable_flash_sector = INT32_MAX;
+ }
+
#if defined(MBOOT_SPIFLASH_ADDR)
MBOOT_SPIFLASH_SPIFLASH->config = MBOOT_SPIFLASH_CONFIG;
mp_spiflash_init(MBOOT_SPIFLASH_SPIFLASH);
@@ -1531,7 +1556,13 @@ void I2Cx_EV_IRQHandler(void) {
#if !USE_USB_POLLING
-#if defined(STM32WB)
+#if defined(STM32G0)
+
+void USB_UCPD1_2_IRQHandler(void) {
+ HAL_PCD_IRQHandler(&pcd_fs_handle);
+}
+
+#elif defined(STM32WB)
void USB_LP_IRQHandler(void) {
HAL_PCD_IRQHandler(&pcd_fs_handle);
diff --git a/ports/stm32/mboot/mboot.h b/ports/stm32/mboot/mboot.h
index d45f4c1efd15..2fce9a230d2b 100644
--- a/ports/stm32/mboot/mboot.h
+++ b/ports/stm32/mboot/mboot.h
@@ -169,6 +169,7 @@ typedef uint32_t mboot_addr_t;
extern volatile uint32_t systick_ms;
extern uint8_t _estack[ELEM_DATA_SIZE];
+extern int32_t first_writable_flash_sector;
void systick_init(void);
void led_init(void);
@@ -209,11 +210,7 @@ int mboot_get_reset_mode_default(void);
void mboot_state_change_default(mboot_state_t state, uint32_t arg);
static inline void mboot_state_change(mboot_state_t state, uint32_t arg) {
- #if defined(MBOOT_BOARD_STATE_CHANGE)
return MBOOT_BOARD_STATE_CHANGE(state, arg);
- #else
- return mboot_state_change_default(state, arg);
- #endif
}
#endif // MICROPY_INCLUDED_STM32_MBOOT_MBOOT_H
diff --git a/ports/stm32/mboot/stm32_memory.ld b/ports/stm32/mboot/stm32_memory.ld
index cfcac4096b6d..ef1b83f30bf7 100644
--- a/ports/stm32/mboot/stm32_memory.ld
+++ b/ports/stm32/mboot/stm32_memory.ld
@@ -8,3 +8,7 @@ MEMORY
FLASH_BL (rx) : ORIGIN = 0x08000000, LENGTH = 32K
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 120K
}
+
+/* Location from which mboot is allowed to write to flash.
+ Must be the start of a flash erase sector. */
+_mboot_writable_flash_start = ORIGIN(FLASH_BL) + LENGTH(FLASH_BL);
diff --git a/ports/stm32/modmachine.c b/ports/stm32/modmachine.c
index 5fca9b3e04c6..dee9689e3bab 100644
--- a/ports/stm32/modmachine.c
+++ b/ports/stm32/modmachine.c
@@ -24,15 +24,14 @@
* THE SOFTWARE.
*/
-#include
#include
#include "modmachine.h"
#include "py/gc.h"
#include "py/runtime.h"
-#include "py/objstr.h"
#include "py/mperrno.h"
#include "py/mphal.h"
+#include "drivers/dht/dht.h"
#include "extmod/machine_bitstream.h"
#include "extmod/machine_mem.h"
#include "extmod/machine_signal.h"
@@ -46,6 +45,7 @@
#include "gccollect.h"
#include "irq.h"
#include "powerctrl.h"
+#include "boardctrl.h"
#include "pybthread.h"
#include "rng.h"
#include "storage.h"
@@ -138,7 +138,7 @@ void machine_init(void) {
if (state & RCC_SR_IWDGRSTF || state & RCC_SR_WWDGRSTF) {
reset_cause = PYB_RESET_WDT;
} else if (state & RCC_SR_PORRSTF
- #if !defined(STM32F0) && !defined(STM32F412Zx)
+ #if !defined(STM32F0) && !defined(STM32F412Zx) && !defined(STM32L1)
|| state & RCC_SR_BORRSTF
#endif
) {
@@ -162,24 +162,26 @@ void machine_deinit(void) {
// machine.info([dump_alloc_table])
// Print out lots of information about the board.
STATIC mp_obj_t machine_info(size_t n_args, const mp_obj_t *args) {
+ const mp_print_t *print = &mp_plat_print;
+
// get and print unique id; 96 bits
{
byte *id = (byte *)MP_HAL_UNIQUE_ID_ADDRESS;
- printf("ID=%02x%02x%02x%02x:%02x%02x%02x%02x:%02x%02x%02x%02x\n", id[0], id[1], id[2], id[3], id[4], id[5], id[6], id[7], id[8], id[9], id[10], id[11]);
+ mp_printf(print, "ID=%02x%02x%02x%02x:%02x%02x%02x%02x:%02x%02x%02x%02x\n", id[0], id[1], id[2], id[3], id[4], id[5], id[6], id[7], id[8], id[9], id[10], id[11]);
}
- printf("DEVID=0x%04x\nREVID=0x%04x\n", (unsigned int)HAL_GetDEVID(), (unsigned int)HAL_GetREVID());
+ mp_printf(print, "DEVID=0x%04x\nREVID=0x%04x\n", (unsigned int)HAL_GetDEVID(), (unsigned int)HAL_GetREVID());
// get and print clock speeds
// SYSCLK=168MHz, HCLK=168MHz, PCLK1=42MHz, PCLK2=84MHz
{
#if defined(STM32F0) || defined(STM32G0)
- printf("S=%u\nH=%u\nP1=%u\n",
+ mp_printf(print, "S=%u\nH=%u\nP1=%u\n",
(unsigned int)HAL_RCC_GetSysClockFreq(),
(unsigned int)HAL_RCC_GetHCLKFreq(),
(unsigned int)HAL_RCC_GetPCLK1Freq());
#else
- printf("S=%u\nH=%u\nP1=%u\nP2=%u\n",
+ mp_printf(print, "S=%u\nH=%u\nP1=%u\nP2=%u\n",
(unsigned int)HAL_RCC_GetSysClockFreq(),
(unsigned int)HAL_RCC_GetHCLKFreq(),
(unsigned int)HAL_RCC_GetPCLK1Freq(),
@@ -189,35 +191,35 @@ STATIC mp_obj_t machine_info(size_t n_args, const mp_obj_t *args) {
// to print info about memory
{
- printf("_etext=%p\n", &_etext);
- printf("_sidata=%p\n", &_sidata);
- printf("_sdata=%p\n", &_sdata);
- printf("_edata=%p\n", &_edata);
- printf("_sbss=%p\n", &_sbss);
- printf("_ebss=%p\n", &_ebss);
- printf("_sstack=%p\n", &_sstack);
- printf("_estack=%p\n", &_estack);
- printf("_ram_start=%p\n", &_ram_start);
- printf("_heap_start=%p\n", &_heap_start);
- printf("_heap_end=%p\n", &_heap_end);
- printf("_ram_end=%p\n", &_ram_end);
+ mp_printf(print, "_etext=%p\n", &_etext);
+ mp_printf(print, "_sidata=%p\n", &_sidata);
+ mp_printf(print, "_sdata=%p\n", &_sdata);
+ mp_printf(print, "_edata=%p\n", &_edata);
+ mp_printf(print, "_sbss=%p\n", &_sbss);
+ mp_printf(print, "_ebss=%p\n", &_ebss);
+ mp_printf(print, "_sstack=%p\n", &_sstack);
+ mp_printf(print, "_estack=%p\n", &_estack);
+ mp_printf(print, "_ram_start=%p\n", &_ram_start);
+ mp_printf(print, "_heap_start=%p\n", &_heap_start);
+ mp_printf(print, "_heap_end=%p\n", &_heap_end);
+ mp_printf(print, "_ram_end=%p\n", &_ram_end);
}
// qstr info
{
size_t n_pool, n_qstr, n_str_data_bytes, n_total_bytes;
qstr_pool_info(&n_pool, &n_qstr, &n_str_data_bytes, &n_total_bytes);
- printf("qstr:\n n_pool=%u\n n_qstr=%u\n n_str_data_bytes=%u\n n_total_bytes=%u\n", n_pool, n_qstr, n_str_data_bytes, n_total_bytes);
+ mp_printf(print, "qstr:\n n_pool=%u\n n_qstr=%u\n n_str_data_bytes=%u\n n_total_bytes=%u\n", n_pool, n_qstr, n_str_data_bytes, n_total_bytes);
}
// GC info
{
gc_info_t info;
gc_info(&info);
- printf("GC:\n");
- printf(" %u total\n", info.total);
- printf(" %u : %u\n", info.used, info.free);
- printf(" 1=%u 2=%u m=%u\n", info.num_1block, info.num_2block, info.max_block);
+ mp_printf(print, "GC:\n");
+ mp_printf(print, " %u total\n", info.total);
+ mp_printf(print, " %u : %u\n", info.used, info.free);
+ mp_printf(print, " 1=%u 2=%u m=%u\n", info.num_1block, info.num_2block, info.max_block);
}
// free space on flash
@@ -229,7 +231,7 @@ STATIC mp_obj_t machine_info(size_t n_args, const mp_obj_t *args) {
fs_user_mount_t *vfs_fat = MP_OBJ_TO_PTR(vfs->obj);
DWORD nclst;
f_getfree(&vfs_fat->fatfs, &nclst);
- printf("LFS free: %u bytes\n", (uint)(nclst * vfs_fat->fatfs.csize * 512));
+ mp_printf(print, "LFS free: %u bytes\n", (uint)(nclst * vfs_fat->fatfs.csize * 512));
break;
}
}
@@ -237,12 +239,12 @@ STATIC mp_obj_t machine_info(size_t n_args, const mp_obj_t *args) {
}
#if MICROPY_PY_THREAD
- pyb_thread_dump();
+ pyb_thread_dump(print);
#endif
if (n_args == 1) {
// arg given means dump gc allocation table
- gc_dump_alloc_table();
+ gc_dump_alloc_table(print);
}
return mp_const_none;
@@ -270,7 +272,7 @@ STATIC mp_obj_t machine_soft_reset(void) {
MP_DEFINE_CONST_FUN_OBJ_0(machine_soft_reset_obj, machine_soft_reset);
// Activate the bootloader without BOOT* pins.
-STATIC NORETURN mp_obj_t machine_bootloader(size_t n_args, const mp_obj_t *args) {
+NORETURN mp_obj_t machine_bootloader(size_t n_args, const mp_obj_t *args) {
#if MICROPY_HW_ENABLE_USB
pyb_usb_dev_deinit();
#endif
@@ -280,21 +282,7 @@ STATIC NORETURN mp_obj_t machine_bootloader(size_t n_args, const mp_obj_t *args)
__disable_irq();
- #if MICROPY_HW_USES_BOOTLOADER
- if (n_args == 0 || !mp_obj_is_true(args[0])) {
- // By default, with no args given, we enter the custom bootloader (mboot)
- powerctrl_enter_bootloader(0x70ad0000, MBOOT_VTOR);
- }
-
- if (n_args == 1 && mp_obj_is_str_or_bytes(args[0])) {
- // With a string/bytes given, pass its data to the custom bootloader
- size_t len;
- const char *data = mp_obj_str_get_data(args[0], &len);
- void *mboot_region = (void *)*((volatile uint32_t *)MBOOT_VTOR);
- memmove(mboot_region, data, len);
- powerctrl_enter_bootloader(0x70ad0080, MBOOT_VTOR);
- }
- #endif
+ MICROPY_BOARD_ENTER_BOOTLOADER(n_args, args);
#if defined(STM32F7) || defined(STM32H7)
powerctrl_enter_bootloader(0, 0x1ff00000);
@@ -323,7 +311,7 @@ STATIC mp_obj_t machine_freq(size_t n_args, const mp_obj_t *args) {
return mp_obj_new_tuple(MP_ARRAY_SIZE(tuple), tuple);
} else {
// set
- #if defined(STM32F0) || defined(STM32L0) || defined(STM32L4) || defined(STM32G0)
+ #if defined(STM32F0) || defined(STM32L0) || defined(STM32L1) || defined(STM32L4) || defined(STM32G0)
mp_raise_NotImplementedError(MP_ERROR_TEXT("machine.freq set not supported yet"));
#else
mp_int_t sysclk = mp_obj_get_int(args[0]);
@@ -353,8 +341,7 @@ STATIC mp_obj_t machine_freq(size_t n_args, const mp_obj_t *args) {
if (ret == -MP_EINVAL) {
mp_raise_ValueError(MP_ERROR_TEXT("invalid freq"));
} else if (ret < 0) {
- void NORETURN __fatal_error(const char *msg);
- __fatal_error("can't change freq");
+ MICROPY_BOARD_FATAL_ERROR("can't change freq");
}
return mp_const_none;
#endif
@@ -427,6 +414,7 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = {
#if MICROPY_PY_MACHINE_PULSE
{ MP_ROM_QSTR(MP_QSTR_time_pulse_us), MP_ROM_PTR(&machine_time_pulse_us_obj) },
#endif
+ { MP_ROM_QSTR(MP_QSTR_dht_readinto), MP_ROM_PTR(&dht_readinto_obj) },
{ MP_ROM_QSTR(MP_QSTR_mem8), MP_ROM_PTR(&machine_mem8_obj) },
{ MP_ROM_QSTR(MP_QSTR_mem16), MP_ROM_PTR(&machine_mem16_obj) },
@@ -439,14 +427,14 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_ADC), MP_ROM_PTR(&machine_adc_type) },
#if MICROPY_PY_MACHINE_I2C
#if MICROPY_HW_ENABLE_HW_I2C
- { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&machine_hard_i2c_type) },
+ { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&machine_i2c_type) },
#else
{ MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&mp_machine_soft_i2c_type) },
#endif
{ MP_ROM_QSTR(MP_QSTR_SoftI2C), MP_ROM_PTR(&mp_machine_soft_i2c_type) },
#endif
#if MICROPY_PY_MACHINE_SPI
- { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&machine_hard_spi_type) },
+ { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&machine_spi_type) },
{ MP_ROM_QSTR(MP_QSTR_SoftSPI), MP_ROM_PTR(&mp_machine_soft_spi_type) },
#endif
#if MICROPY_HW_ENABLE_I2S
diff --git a/ports/stm32/modmachine.h b/ports/stm32/modmachine.h
index 0e6c000a801f..0c776280b416 100644
--- a/ports/stm32/modmachine.h
+++ b/ports/stm32/modmachine.h
@@ -30,12 +30,15 @@
extern const mp_obj_type_t machine_adc_type;
extern const mp_obj_type_t machine_timer_type;
-extern const mp_obj_type_t machine_hard_i2c_type;
+extern const mp_obj_type_t machine_i2c_type;
extern const mp_obj_type_t machine_i2s_type;
+extern const mp_obj_type_t machine_spi_type;
+extern const mp_obj_type_t machine_timer_type;
void machine_init(void);
void machine_deinit(void);
void machine_i2s_init0();
+NORETURN mp_obj_t machine_bootloader(size_t n_args, const mp_obj_t *args);
MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(machine_info_obj);
MP_DECLARE_CONST_FUN_OBJ_0(machine_unique_id_obj);
diff --git a/ports/stm32/modnwcc3k.c b/ports/stm32/modnwcc3k.c
deleted file mode 100644
index 952e535c2dbc..000000000000
--- a/ports/stm32/modnwcc3k.c
+++ /dev/null
@@ -1,608 +0,0 @@
-/*
- * This file is part of the MicroPython project, http://micropython.org/
- *
- * The MIT License (MIT)
- *
- * Copyright (c) 2014 Damien P. George
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include
-#include
-
-// CC3000 defines its own ENOBUFS (different to standard one!)
-#undef ENOBUFS
-
-#include "py/objtuple.h"
-#include "py/objlist.h"
-#include "py/stream.h"
-#include "py/runtime.h"
-#include "py/mperrno.h"
-#include "py/mphal.h"
-#include "shared/netutils/netutils.h"
-#include "extmod/modnetwork.h"
-#include "pin.h"
-#include "spi.h"
-
-#include "hci.h"
-#include "socket.h"
-#include "inet_ntop.h"
-#include "inet_pton.h"
-#include "ccspi.h"
-#include "wlan.h"
-#include "nvmem.h"
-#include "netapp.h"
-#include "patch_prog.h"
-
-#define MAX_ADDRSTRLEN (128)
-#define MAX_RX_PACKET (CC3000_RX_BUFFER_SIZE - CC3000_MINIMAL_RX_SIZE - 1)
-#define MAX_TX_PACKET (CC3000_TX_BUFFER_SIZE - CC3000_MINIMAL_TX_SIZE - 1)
-
-#define MAKE_SOCKADDR(addr, ip, port) \
- sockaddr addr; \
- addr.sa_family = AF_INET; \
- addr.sa_data[0] = port >> 8; \
- addr.sa_data[1] = port; \
- addr.sa_data[2] = ip[0]; \
- addr.sa_data[3] = ip[1]; \
- addr.sa_data[4] = ip[2]; \
- addr.sa_data[5] = ip[3];
-
-#define UNPACK_SOCKADDR(addr, ip, port) \
- port = (addr.sa_data[0] << 8) | addr.sa_data[1]; \
- ip[0] = addr.sa_data[2]; \
- ip[1] = addr.sa_data[3]; \
- ip[2] = addr.sa_data[4]; \
- ip[3] = addr.sa_data[5];
-
-STATIC int cc3k_socket_ioctl(mod_network_socket_obj_t *socket, mp_uint_t request, mp_uint_t arg, int *_errno);
-
-int CC3000_EXPORT(errno); // for cc3000 driver
-
-STATIC volatile uint32_t fd_closed_state = 0;
-STATIC volatile bool wlan_connected = false;
-STATIC volatile bool ip_obtained = false;
-
-STATIC int cc3k_get_fd_closed_state(int fd) {
- return fd_closed_state & (1 << fd);
-}
-
-STATIC void cc3k_set_fd_closed_state(int fd) {
- fd_closed_state |= 1 << fd;
-}
-
-STATIC void cc3k_reset_fd_closed_state(int fd) {
- fd_closed_state &= ~(1 << fd);
-}
-
-STATIC void cc3k_callback(long event_type, char *data, unsigned char length) {
- switch (event_type) {
- case HCI_EVNT_WLAN_UNSOL_CONNECT:
- wlan_connected = true;
- break;
- case HCI_EVNT_WLAN_UNSOL_DISCONNECT:
- // link down
- wlan_connected = false;
- ip_obtained = false;
- break;
- case HCI_EVNT_WLAN_UNSOL_DHCP:
- ip_obtained = true;
- break;
- case HCI_EVNT_BSD_TCP_CLOSE_WAIT:
- // mark socket for closure
- cc3k_set_fd_closed_state(data[0]);
- break;
- }
-}
-
-STATIC int cc3k_gethostbyname(mp_obj_t nic, const char *name, mp_uint_t len, uint8_t *out_ip) {
- uint32_t ip;
- // CC3000 gethostbyname is unreliable and usually returns -95 on first call
- for (int retry = 5; CC3000_EXPORT(gethostbyname)((char *)name, len, &ip) < 0; retry--) {
- if (retry == 0 || CC3000_EXPORT(errno) != -95) {
- return CC3000_EXPORT(errno);
- }
- mp_hal_delay_ms(50);
- }
-
- if (ip == 0) {
- // unknown host
- return -2;
- }
-
- out_ip[0] = ip >> 24;
- out_ip[1] = ip >> 16;
- out_ip[2] = ip >> 8;
- out_ip[3] = ip;
-
- return 0;
-}
-
-STATIC int cc3k_socket_socket(mod_network_socket_obj_t *socket, int *_errno) {
- if (socket->domain != MOD_NETWORK_AF_INET) {
- *_errno = MP_EAFNOSUPPORT;
- return -1;
- }
-
- mp_uint_t type;
- switch (socket->type) {
- case MOD_NETWORK_SOCK_STREAM:
- type = SOCK_STREAM;
- break;
- case MOD_NETWORK_SOCK_DGRAM:
- type = SOCK_DGRAM;
- break;
- case MOD_NETWORK_SOCK_RAW:
- type = SOCK_RAW;
- break;
- default:
- *_errno = MP_EINVAL;
- return -1;
- }
-
- // open socket
- int fd = CC3000_EXPORT(socket)(AF_INET, type, 0);
- if (fd < 0) {
- *_errno = CC3000_EXPORT(errno);
- return -1;
- }
-
- // clear socket state
- cc3k_reset_fd_closed_state(fd);
-
- // store state of this socket
- socket->fileno = fd;
-
- // make accept blocking by default
- int optval = SOCK_OFF;
- socklen_t optlen = sizeof(optval);
- CC3000_EXPORT(setsockopt)(socket->fileno, SOL_SOCKET, SOCKOPT_ACCEPT_NONBLOCK, &optval, optlen);
-
- return 0;
-}
-
-STATIC void cc3k_socket_close(mod_network_socket_obj_t *socket) {
- CC3000_EXPORT(closesocket)(socket->fileno);
-}
-
-STATIC int cc3k_socket_bind(mod_network_socket_obj_t *socket, byte *ip, mp_uint_t port, int *_errno) {
- MAKE_SOCKADDR(addr, ip, port)
- int ret = CC3000_EXPORT(bind)(socket->fileno, &addr, sizeof(addr));
- if (ret != 0) {
- *_errno = ret;
- return -1;
- }
- return 0;
-}
-
-STATIC int cc3k_socket_listen(mod_network_socket_obj_t *socket, mp_int_t backlog, int *_errno) {
- int ret = CC3000_EXPORT(listen)(socket->fileno, backlog);
- if (ret != 0) {
- *_errno = ret;
- return -1;
- }
- return 0;
-}
-
-STATIC int cc3k_socket_accept(mod_network_socket_obj_t *socket, mod_network_socket_obj_t *socket2, byte *ip, mp_uint_t *port, int *_errno) {
- // accept incoming connection
- int fd;
- sockaddr addr;
- socklen_t addr_len = sizeof(addr);
- if ((fd = CC3000_EXPORT(accept)(socket->fileno, &addr, &addr_len)) < 0) {
- if (fd == SOC_IN_PROGRESS) {
- *_errno = MP_EAGAIN;
- } else {
- *_errno = -fd;
- }
- return -1;
- }
-
- // clear socket state
- cc3k_reset_fd_closed_state(fd);
-
- // store state in new socket object
- socket2->fileno = fd;
-
- // return ip and port
- // it seems CC3000 returns little endian for accept??
- // UNPACK_SOCKADDR(addr, ip, *port);
- *port = (addr.sa_data[1] << 8) | addr.sa_data[0];
- ip[3] = addr.sa_data[2];
- ip[2] = addr.sa_data[3];
- ip[1] = addr.sa_data[4];
- ip[0] = addr.sa_data[5];
-
- return 0;
-}
-
-STATIC int cc3k_socket_connect(mod_network_socket_obj_t *socket, byte *ip, mp_uint_t port, int *_errno) {
- MAKE_SOCKADDR(addr, ip, port)
- int ret = CC3000_EXPORT(connect)(socket->fileno, &addr, sizeof(addr));
- if (ret != 0) {
- *_errno = CC3000_EXPORT(errno);
- return -1;
- }
- return 0;
-}
-
-STATIC mp_uint_t cc3k_socket_send(mod_network_socket_obj_t *socket, const byte *buf, mp_uint_t len, int *_errno) {
- if (cc3k_get_fd_closed_state(socket->fileno)) {
- CC3000_EXPORT(closesocket)(socket->fileno);
- *_errno = MP_EPIPE;
- return -1;
- }
-
- // CC3K does not handle fragmentation, and will overflow,
- // split the packet into smaller ones and send them out.
- mp_int_t bytes = 0;
- while (bytes < len) {
- int n = MIN((len - bytes), MAX_TX_PACKET);
- n = CC3000_EXPORT(send)(socket->fileno, (uint8_t *)buf + bytes, n, 0);
- if (n <= 0) {
- *_errno = CC3000_EXPORT(errno);
- return -1;
- }
- bytes += n;
- }
-
- return bytes;
-}
-
-STATIC mp_uint_t cc3k_socket_recv(mod_network_socket_obj_t *socket, byte *buf, mp_uint_t len, int *_errno) {
- // check the socket is open
- if (cc3k_get_fd_closed_state(socket->fileno)) {
- // socket is closed, but CC3000 may have some data remaining in buffer, so check
- fd_set rfds;
- FD_ZERO(&rfds);
- FD_SET(socket->fileno, &rfds);
- cc3000_timeval tv;
- tv.tv_sec = 0;
- tv.tv_usec = 1;
- int nfds = CC3000_EXPORT(select)(socket->fileno + 1, &rfds, NULL, NULL, &tv);
- if (nfds == -1 || !FD_ISSET(socket->fileno, &rfds)) {
- // no data waiting, so close socket and return 0 data
- CC3000_EXPORT(closesocket)(socket->fileno);
- return 0;
- }
- }
-
- // cap length at MAX_RX_PACKET
- len = MIN(len, MAX_RX_PACKET);
-
- // do the recv
- int ret = CC3000_EXPORT(recv)(socket->fileno, buf, len, 0);
- if (ret < 0) {
- *_errno = CC3000_EXPORT(errno);
- return -1;
- }
-
- return ret;
-}
-
-STATIC mp_uint_t cc3k_socket_sendto(mod_network_socket_obj_t *socket, const byte *buf, mp_uint_t len, byte *ip, mp_uint_t port, int *_errno) {
- MAKE_SOCKADDR(addr, ip, port)
- int ret = CC3000_EXPORT(sendto)(socket->fileno, (byte *)buf, len, 0, (sockaddr *)&addr, sizeof(addr));
- if (ret < 0) {
- *_errno = CC3000_EXPORT(errno);
- return -1;
- }
- return ret;
-}
-
-STATIC mp_uint_t cc3k_socket_recvfrom(mod_network_socket_obj_t *socket, byte *buf, mp_uint_t len, byte *ip, mp_uint_t *port, int *_errno) {
- sockaddr addr;
- socklen_t addr_len = sizeof(addr);
- mp_int_t ret = CC3000_EXPORT(recvfrom)(socket->fileno, buf, len, 0, &addr, &addr_len);
- if (ret < 0) {
- *_errno = CC3000_EXPORT(errno);
- return -1;
- }
- UNPACK_SOCKADDR(addr, ip, *port);
- return ret;
-}
-
-STATIC int cc3k_socket_setsockopt(mod_network_socket_obj_t *socket, mp_uint_t level, mp_uint_t opt, const void *optval, mp_uint_t optlen, int *_errno) {
- int ret = CC3000_EXPORT(setsockopt)(socket->fileno, level, opt, optval, optlen);
- if (ret < 0) {
- *_errno = CC3000_EXPORT(errno);
- return -1;
- }
- return 0;
-}
-
-STATIC int cc3k_socket_settimeout(mod_network_socket_obj_t *socket, mp_uint_t timeout_ms, int *_errno) {
- int ret;
- if (timeout_ms == 0 || timeout_ms == -1) {
- int optval;
- socklen_t optlen = sizeof(optval);
- if (timeout_ms == 0) {
- // set non-blocking mode
- optval = SOCK_ON;
- } else {
- // set blocking mode
- optval = SOCK_OFF;
- }
- ret = CC3000_EXPORT(setsockopt)(socket->fileno, SOL_SOCKET, SOCKOPT_RECV_NONBLOCK, &optval, optlen);
- if (ret == 0) {
- ret = CC3000_EXPORT(setsockopt)(socket->fileno, SOL_SOCKET, SOCKOPT_ACCEPT_NONBLOCK, &optval, optlen);
- }
- } else {
- // set timeout
- socklen_t optlen = sizeof(timeout_ms);
- ret = CC3000_EXPORT(setsockopt)(socket->fileno, SOL_SOCKET, SOCKOPT_RECV_TIMEOUT, &timeout_ms, optlen);
- }
-
- if (ret != 0) {
- *_errno = CC3000_EXPORT(errno);
- return -1;
- }
-
- return 0;
-}
-
-STATIC int cc3k_socket_ioctl(mod_network_socket_obj_t *socket, mp_uint_t request, mp_uint_t arg, int *_errno) {
- mp_uint_t ret;
- if (request == MP_STREAM_POLL) {
- mp_uint_t flags = arg;
- ret = 0;
- int fd = socket->fileno;
-
- // init fds
- fd_set rfds, wfds, xfds;
- FD_ZERO(&rfds);
- FD_ZERO(&wfds);
- FD_ZERO(&xfds);
-
- // set fds if needed
- if (flags & MP_STREAM_POLL_RD) {
- FD_SET(fd, &rfds);
-
- // A socked that just closed is available for reading. A call to
- // recv() returns 0 which is consistent with BSD.
- if (cc3k_get_fd_closed_state(fd)) {
- ret |= MP_STREAM_POLL_RD;
- }
- }
- if (flags & MP_STREAM_POLL_WR) {
- FD_SET(fd, &wfds);
- }
- if (flags & MP_STREAM_POLL_HUP) {
- FD_SET(fd, &xfds);
- }
-
- // call cc3000 select with minimum timeout
- cc3000_timeval tv;
- tv.tv_sec = 0;
- tv.tv_usec = 1;
- int nfds = CC3000_EXPORT(select)(fd + 1, &rfds, &wfds, &xfds, &tv);
-
- // check for error
- if (nfds == -1) {
- *_errno = CC3000_EXPORT(errno);
- return -1;
- }
-
- // check return of select
- if (FD_ISSET(fd, &rfds)) {
- ret |= MP_STREAM_POLL_RD;
- }
- if (FD_ISSET(fd, &wfds)) {
- ret |= MP_STREAM_POLL_WR;
- }
- if (FD_ISSET(fd, &xfds)) {
- ret |= MP_STREAM_POLL_HUP;
- }
- } else {
- *_errno = MP_EINVAL;
- ret = -1;
- }
- return ret;
-}
-
-/******************************************************************************/
-// MicroPython bindings; CC3K class
-
-typedef struct _cc3k_obj_t {
- mp_obj_base_t base;
-} cc3k_obj_t;
-
-STATIC const cc3k_obj_t cc3k_obj = {{(mp_obj_type_t *)&mod_network_nic_type_cc3k}};
-
-// \classmethod \constructor(spi, pin_cs, pin_en, pin_irq)
-// Initialise the CC3000 using the given SPI bus and pins and return a CC3K object.
-//
-// Note: pins were originally hard-coded to:
-// PYBv1.0: init(pyb.SPI(2), pyb.Pin.board.Y5, pyb.Pin.board.Y4, pyb.Pin.board.Y3)
-// [SPI on Y position; Y6=B13=SCK, Y7=B14=MISO, Y8=B15=MOSI]
-//
-// STM32F4DISC: init(pyb.SPI(2), pyb.Pin.cpu.A15, pyb.Pin.cpu.B10, pyb.Pin.cpu.B11)
-STATIC mp_obj_t cc3k_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
- // check arguments
- mp_arg_check_num(n_args, n_kw, 4, 4, false);
-
- // set the pins to use
- SpiInit(
- spi_from_mp_obj(args[0])->spi,
- pin_find(args[1]),
- pin_find(args[2]),
- pin_find(args[3])
- );
-
- // initialize and start the module
- wlan_init(cc3k_callback, NULL, NULL, NULL,
- ReadWlanInterruptPin, SpiResumeSpi, SpiPauseSpi, WriteWlanPin);
-
- if (wlan_start(0) != 0) {
- mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("failed to init CC3000 module"));
- }
-
- // set connection policy. this should be called explicitly by the user
- // wlan_ioctl_set_connection_policy(0, 0, 0);
-
- // Mask out all non-required events from the CC3000
- wlan_set_event_mask(HCI_EVNT_WLAN_KEEPALIVE |
- HCI_EVNT_WLAN_UNSOL_INIT |
- HCI_EVNT_WLAN_ASYNC_PING_REPORT |
- HCI_EVNT_WLAN_ASYNC_SIMPLE_CONFIG_DONE);
-
- // register with network module
- mod_network_register_nic((mp_obj_t)&cc3k_obj);
-
- return (mp_obj_t)&cc3k_obj;
-}
-
-// method connect(ssid, key=None, *, security=WPA2, bssid=None)
-STATIC mp_obj_t cc3k_connect(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
- static const mp_arg_t allowed_args[] = {
- { MP_QSTR_ssid, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
- { MP_QSTR_key, MP_ARG_OBJ, {.u_obj = mp_const_none} },
- { MP_QSTR_security, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = WLAN_SEC_WPA2} },
- { MP_QSTR_bssid, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
- };
-
- // 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(allowed_args), allowed_args, args);
-
- // get ssid
- size_t ssid_len;
- const char *ssid = mp_obj_str_get_data(args[0].u_obj, &ssid_len);
-
- // get key and sec
- size_t key_len = 0;
- const char *key = NULL;
- mp_uint_t sec = WLAN_SEC_UNSEC;
- if (args[1].u_obj != mp_const_none) {
- key = mp_obj_str_get_data(args[1].u_obj, &key_len);
- sec = args[2].u_int;
- }
-
- // get bssid
- const char *bssid = NULL;
- if (args[3].u_obj != mp_const_none) {
- bssid = mp_obj_str_get_str(args[3].u_obj);
- }
-
- // connect to AP
- if (wlan_connect(sec, (char *)ssid, ssid_len, (uint8_t *)bssid, (uint8_t *)key, key_len) != 0) {
- mp_raise_msg_varg(&mp_type_OSError, MP_ERROR_TEXT("could not connect to ssid=%s, sec=%d, key=%s\n"), ssid, sec, key);
- }
-
- return mp_const_none;
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_KW(cc3k_connect_obj, 1, cc3k_connect);
-
-STATIC mp_obj_t cc3k_disconnect(mp_obj_t self_in) {
- // should we check return value?
- wlan_disconnect();
- return mp_const_none;
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(cc3k_disconnect_obj, cc3k_disconnect);
-
-STATIC mp_obj_t cc3k_isconnected(mp_obj_t self_in) {
- return mp_obj_new_bool(wlan_connected && ip_obtained);
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(cc3k_isconnected_obj, cc3k_isconnected);
-
-STATIC mp_obj_t cc3k_ifconfig(mp_obj_t self_in) {
- tNetappIpconfigRetArgs ipconfig;
- netapp_ipconfig(&ipconfig);
-
- // render MAC address
- VSTR_FIXED(mac_vstr, 18);
- const uint8_t *mac = ipconfig.uaMacAddr;
- vstr_printf(&mac_vstr, "%02x:%02x:%02x:%02x:%02x:%02x", mac[5], mac[4], mac[3], mac[2], mac[1], mac[0]);
-
- // create and return tuple with ifconfig info
- mp_obj_t tuple[7] = {
- netutils_format_ipv4_addr(ipconfig.aucIP, NETUTILS_LITTLE),
- netutils_format_ipv4_addr(ipconfig.aucSubnetMask, NETUTILS_LITTLE),
- netutils_format_ipv4_addr(ipconfig.aucDefaultGateway, NETUTILS_LITTLE),
- netutils_format_ipv4_addr(ipconfig.aucDNSServer, NETUTILS_LITTLE),
- netutils_format_ipv4_addr(ipconfig.aucDHCPServer, NETUTILS_LITTLE),
- mp_obj_new_str(mac_vstr.buf, mac_vstr.len),
- mp_obj_new_str((const char *)ipconfig.uaSSID, strlen((const char *)ipconfig.uaSSID)),
- };
- return mp_obj_new_tuple(MP_ARRAY_SIZE(tuple), tuple);
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(cc3k_ifconfig_obj, cc3k_ifconfig);
-
-STATIC mp_obj_t cc3k_patch_version(mp_obj_t self_in) {
- uint8_t pver[2];
- mp_obj_tuple_t *t_pver;
-
- nvmem_read_sp_version(pver);
- t_pver = mp_obj_new_tuple(2, NULL);
- t_pver->items[0] = mp_obj_new_int(pver[0]);
- t_pver->items[1] = mp_obj_new_int(pver[1]);
- return t_pver;
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(cc3k_patch_version_obj, cc3k_patch_version);
-
-STATIC mp_obj_t cc3k_patch_program(mp_obj_t self_in, mp_obj_t key_in) {
- const char *key = mp_obj_str_get_str(key_in);
- if (key[0] == 'p' && key[1] == 'g' && key[2] == 'm' && key[3] == '\0') {
- patch_prog_start();
- } else {
- mp_print_str(&mp_plat_print, "pass 'pgm' as argument in order to program\n");
- }
- return mp_const_none;
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_2(cc3k_patch_program_obj, cc3k_patch_program);
-
-STATIC const mp_rom_map_elem_t cc3k_locals_dict_table[] = {
- { MP_ROM_QSTR(MP_QSTR_connect), MP_ROM_PTR(&cc3k_connect_obj) },
- { MP_ROM_QSTR(MP_QSTR_disconnect), MP_ROM_PTR(&cc3k_disconnect_obj) },
- { MP_ROM_QSTR(MP_QSTR_isconnected), MP_ROM_PTR(&cc3k_isconnected_obj) },
- { MP_ROM_QSTR(MP_QSTR_ifconfig), MP_ROM_PTR(&cc3k_ifconfig_obj) },
- { MP_ROM_QSTR(MP_QSTR_patch_version), MP_ROM_PTR(&cc3k_patch_version_obj) },
- { MP_ROM_QSTR(MP_QSTR_patch_program), MP_ROM_PTR(&cc3k_patch_program_obj) },
-
- // class constants
- { MP_ROM_QSTR(MP_QSTR_WEP), MP_ROM_INT(WLAN_SEC_WEP) },
- { MP_ROM_QSTR(MP_QSTR_WPA), MP_ROM_INT(WLAN_SEC_WPA) },
- { MP_ROM_QSTR(MP_QSTR_WPA2), MP_ROM_INT(WLAN_SEC_WPA2) },
-};
-
-STATIC MP_DEFINE_CONST_DICT(cc3k_locals_dict, cc3k_locals_dict_table);
-
-const mod_network_nic_type_t mod_network_nic_type_cc3k = {
- .base = {
- { &mp_type_type },
- .name = MP_QSTR_CC3K,
- .make_new = cc3k_make_new,
- .locals_dict = (mp_obj_dict_t *)&cc3k_locals_dict,
- },
- .gethostbyname = cc3k_gethostbyname,
- .socket = cc3k_socket_socket,
- .close = cc3k_socket_close,
- .bind = cc3k_socket_bind,
- .listen = cc3k_socket_listen,
- .accept = cc3k_socket_accept,
- .connect = cc3k_socket_connect,
- .send = cc3k_socket_send,
- .recv = cc3k_socket_recv,
- .sendto = cc3k_socket_sendto,
- .recvfrom = cc3k_socket_recvfrom,
- .setsockopt = cc3k_socket_setsockopt,
- .settimeout = cc3k_socket_settimeout,
- .ioctl = cc3k_socket_ioctl,
-};
diff --git a/ports/stm32/modnwwiznet5k.c b/ports/stm32/modnwwiznet5k.c
deleted file mode 100644
index 2d5044d5246b..000000000000
--- a/ports/stm32/modnwwiznet5k.c
+++ /dev/null
@@ -1,513 +0,0 @@
-/*
- * This file is part of the MicroPython project, http://micropython.org/
- *
- * The MIT License (MIT)
- *
- * Copyright (c) 2014 Damien P. George
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include
-#include
-#include
-
-#include "py/objlist.h"
-#include "py/runtime.h"
-#include "py/stream.h"
-#include "py/mperrno.h"
-#include "py/mphal.h"
-#include "shared/netutils/netutils.h"
-#include "extmod/modnetwork.h"
-#include "pin.h"
-#include "spi.h"
-
-#if MICROPY_PY_NETWORK_WIZNET5K && !MICROPY_PY_LWIP
-
-#include "ethernet/wizchip_conf.h"
-#include "ethernet/socket.h"
-#include "internet/dns/dns.h"
-
-/// \moduleref network
-
-typedef struct _wiznet5k_obj_t {
- mp_obj_base_t base;
- mp_uint_t cris_state;
- const spi_t *spi;
- const pin_obj_t *cs;
- const pin_obj_t *rst;
- uint8_t socket_used;
-} wiznet5k_obj_t;
-
-STATIC wiznet5k_obj_t wiznet5k_obj;
-
-STATIC void wiz_cris_enter(void) {
- wiznet5k_obj.cris_state = MICROPY_BEGIN_ATOMIC_SECTION();
-}
-
-STATIC void wiz_cris_exit(void) {
- MICROPY_END_ATOMIC_SECTION(wiznet5k_obj.cris_state);
-}
-
-STATIC void wiz_cs_select(void) {
- mp_hal_pin_low(wiznet5k_obj.cs);
-}
-
-STATIC void wiz_cs_deselect(void) {
- mp_hal_pin_high(wiznet5k_obj.cs);
-}
-
-STATIC void wiz_spi_read(uint8_t *buf, uint32_t len) {
- HAL_StatusTypeDef status = HAL_SPI_Receive(wiznet5k_obj.spi->spi, buf, len, 5000);
- (void)status;
-}
-
-STATIC void wiz_spi_write(const uint8_t *buf, uint32_t len) {
- HAL_StatusTypeDef status = HAL_SPI_Transmit(wiznet5k_obj.spi->spi, (uint8_t *)buf, len, 5000);
- (void)status;
-}
-
-STATIC int wiznet5k_gethostbyname(mp_obj_t nic, const char *name, mp_uint_t len, uint8_t *out_ip) {
- uint8_t dns_ip[MOD_NETWORK_IPADDR_BUF_SIZE] = {8, 8, 8, 8};
- uint8_t *buf = m_new(uint8_t, MAX_DNS_BUF_SIZE);
- DNS_init(0, buf);
- mp_int_t ret = DNS_run(dns_ip, (uint8_t *)name, out_ip);
- m_del(uint8_t, buf, MAX_DNS_BUF_SIZE);
- if (ret == 1) {
- // success
- return 0;
- } else {
- // failure
- return -2;
- }
-}
-
-STATIC int wiznet5k_socket_socket(mod_network_socket_obj_t *socket, int *_errno) {
- if (socket->domain != MOD_NETWORK_AF_INET) {
- *_errno = MP_EAFNOSUPPORT;
- return -1;
- }
-
- switch (socket->type) {
- case MOD_NETWORK_SOCK_STREAM:
- socket->type = Sn_MR_TCP;
- break;
- case MOD_NETWORK_SOCK_DGRAM:
- socket->type = Sn_MR_UDP;
- break;
- default:
- *_errno = MP_EINVAL;
- return -1;
- }
-
- if (socket->fileno == -1) {
- // get first unused socket number
- for (mp_uint_t sn = 0; sn < _WIZCHIP_SOCK_NUM_; sn++) {
- if ((wiznet5k_obj.socket_used & (1 << sn)) == 0) {
- wiznet5k_obj.socket_used |= (1 << sn);
- socket->fileno = sn;
- break;
- }
- }
- if (socket->fileno == -1) {
- // too many open sockets
- *_errno = MP_EMFILE;
- return -1;
- }
- }
-
- // WIZNET does not have a concept of pure "open socket". You need to know
- // if it's a server or client at the time of creation of the socket.
- // So, we defer the open until we know what kind of socket we want.
-
- // use "domain" to indicate that this socket has not yet been opened
- socket->domain = 0;
-
- return 0;
-}
-
-STATIC void wiznet5k_socket_close(mod_network_socket_obj_t *socket) {
- uint8_t sn = (uint8_t)socket->fileno;
- if (sn < _WIZCHIP_SOCK_NUM_) {
- wiznet5k_obj.socket_used &= ~(1 << sn);
- WIZCHIP_EXPORT(close)(sn);
- }
-}
-
-STATIC int wiznet5k_socket_bind(mod_network_socket_obj_t *socket, byte *ip, mp_uint_t port, int *_errno) {
- // open the socket in server mode (if port != 0)
- mp_int_t ret = WIZCHIP_EXPORT(socket)(socket->fileno, socket->type, port, 0);
- if (ret < 0) {
- wiznet5k_socket_close(socket);
- *_errno = -ret;
- return -1;
- }
-
- // indicate that this socket has been opened
- socket->domain = 1;
-
- // success
- return 0;
-}
-
-STATIC int wiznet5k_socket_listen(mod_network_socket_obj_t *socket, mp_int_t backlog, int *_errno) {
- mp_int_t ret = WIZCHIP_EXPORT(listen)(socket->fileno);
- if (ret < 0) {
- wiznet5k_socket_close(socket);
- *_errno = -ret;
- return -1;
- }
- return 0;
-}
-
-STATIC int wiznet5k_socket_accept(mod_network_socket_obj_t *socket, mod_network_socket_obj_t *socket2, byte *ip, mp_uint_t *port, int *_errno) {
- for (;;) {
- int sr = getSn_SR((uint8_t)socket->fileno);
- if (sr == SOCK_ESTABLISHED) {
- socket2->domain = socket->domain;
- socket2->type = socket->type;
- socket2->fileno = socket->fileno;
- getSn_DIPR((uint8_t)socket2->fileno, ip);
- *port = getSn_PORT(socket2->fileno);
-
- // WIZnet turns the listening socket into the client socket, so we
- // need to re-bind and re-listen on another socket for the server.
- // TODO handle errors, especially no-more-sockets error
- socket->domain = MOD_NETWORK_AF_INET;
- socket->fileno = -1;
- int _errno2;
- if (wiznet5k_socket_socket(socket, &_errno2) != 0) {
- // printf("(bad resocket %d)\n", _errno2);
- } else if (wiznet5k_socket_bind(socket, NULL, *port, &_errno2) != 0) {
- // printf("(bad rebind %d)\n", _errno2);
- } else if (wiznet5k_socket_listen(socket, 0, &_errno2) != 0) {
- // printf("(bad relisten %d)\n", _errno2);
- }
-
- return 0;
- }
- if (sr == SOCK_CLOSED || sr == SOCK_CLOSE_WAIT) {
- wiznet5k_socket_close(socket);
- *_errno = MP_ENOTCONN; // ??
- return -1;
- }
- mp_hal_delay_ms(1);
- }
-}
-
-STATIC int wiznet5k_socket_connect(mod_network_socket_obj_t *socket, byte *ip, mp_uint_t port, int *_errno) {
- // use "bind" function to open the socket in client mode
- if (wiznet5k_socket_bind(socket, ip, 0, _errno) != 0) {
- return -1;
- }
-
- // now connect
- MP_THREAD_GIL_EXIT();
- mp_int_t ret = WIZCHIP_EXPORT(connect)(socket->fileno, ip, port);
- MP_THREAD_GIL_ENTER();
-
- if (ret < 0) {
- wiznet5k_socket_close(socket);
- *_errno = -ret;
- return -1;
- }
-
- // success
- return 0;
-}
-
-STATIC mp_uint_t wiznet5k_socket_send(mod_network_socket_obj_t *socket, const byte *buf, mp_uint_t len, int *_errno) {
- MP_THREAD_GIL_EXIT();
- mp_int_t ret = WIZCHIP_EXPORT(send)(socket->fileno, (byte *)buf, len);
- MP_THREAD_GIL_ENTER();
-
- // TODO convert Wiz errno's to POSIX ones
- if (ret < 0) {
- wiznet5k_socket_close(socket);
- *_errno = -ret;
- return -1;
- }
- return ret;
-}
-
-STATIC mp_uint_t wiznet5k_socket_recv(mod_network_socket_obj_t *socket, byte *buf, mp_uint_t len, int *_errno) {
- MP_THREAD_GIL_EXIT();
- mp_int_t ret = WIZCHIP_EXPORT(recv)(socket->fileno, buf, len);
- MP_THREAD_GIL_ENTER();
-
- // TODO convert Wiz errno's to POSIX ones
- if (ret < 0) {
- wiznet5k_socket_close(socket);
- *_errno = -ret;
- return -1;
- }
- return ret;
-}
-
-STATIC mp_uint_t wiznet5k_socket_sendto(mod_network_socket_obj_t *socket, const byte *buf, mp_uint_t len, byte *ip, mp_uint_t port, int *_errno) {
- if (socket->domain == 0) {
- // socket not opened; use "bind" function to open the socket in client mode
- if (wiznet5k_socket_bind(socket, ip, 0, _errno) != 0) {
- return -1;
- }
- }
-
- MP_THREAD_GIL_EXIT();
- mp_int_t ret = WIZCHIP_EXPORT(sendto)(socket->fileno, (byte *)buf, len, ip, port);
- MP_THREAD_GIL_ENTER();
-
- if (ret < 0) {
- wiznet5k_socket_close(socket);
- *_errno = -ret;
- return -1;
- }
- return ret;
-}
-
-STATIC mp_uint_t wiznet5k_socket_recvfrom(mod_network_socket_obj_t *socket, byte *buf, mp_uint_t len, byte *ip, mp_uint_t *port, int *_errno) {
- uint16_t port2;
- MP_THREAD_GIL_EXIT();
- mp_int_t ret = WIZCHIP_EXPORT(recvfrom)(socket->fileno, buf, len, ip, &port2);
- MP_THREAD_GIL_ENTER();
- *port = port2;
- if (ret < 0) {
- wiznet5k_socket_close(socket);
- *_errno = -ret;
- return -1;
- }
- return ret;
-}
-
-STATIC int wiznet5k_socket_setsockopt(mod_network_socket_obj_t *socket, mp_uint_t level, mp_uint_t opt, const void *optval, mp_uint_t optlen, int *_errno) {
- // TODO
- *_errno = MP_EINVAL;
- return -1;
-}
-
-STATIC int wiznet5k_socket_settimeout(mod_network_socket_obj_t *socket, mp_uint_t timeout_ms, int *_errno) {
- // TODO
- *_errno = MP_EINVAL;
- return -1;
-
- /*
- if (timeout_ms == 0) {
- // set non-blocking mode
- uint8_t arg = SOCK_IO_NONBLOCK;
- WIZCHIP_EXPORT(ctlsocket)(socket->fileno, CS_SET_IOMODE, &arg);
- }
- */
-}
-
-STATIC int wiznet5k_socket_ioctl(mod_network_socket_obj_t *socket, mp_uint_t request, mp_uint_t arg, int *_errno) {
- if (request == MP_STREAM_POLL) {
- int ret = 0;
- if (arg & MP_STREAM_POLL_RD && getSn_RX_RSR(socket->fileno) != 0) {
- ret |= MP_STREAM_POLL_RD;
- }
- if (arg & MP_STREAM_POLL_WR && getSn_TX_FSR(socket->fileno) != 0) {
- ret |= MP_STREAM_POLL_WR;
- }
- return ret;
- } else {
- *_errno = MP_EINVAL;
- return MP_STREAM_ERROR;
- }
-}
-
-#if 0
-STATIC void wiznet5k_socket_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
- wiznet5k_socket_obj_t *self = self_in;
- print(env, "", self->sn, getSn_MR(self->sn));
-}
-
-STATIC mp_obj_t wiznet5k_socket_disconnect(mp_obj_t self_in) {
- mp_int_t ret = WIZCHIP_EXPORT(disconnect)(self->sn);
- return 0;
-}
-#endif
-
-/******************************************************************************/
-// MicroPython bindings
-
-/// \classmethod \constructor(spi, pin_cs, pin_rst)
-/// Create and return a WIZNET5K object.
-STATIC mp_obj_t wiznet5k_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
- // check arguments
- mp_arg_check_num(n_args, n_kw, 3, 3, false);
-
- // init the wiznet5k object
- wiznet5k_obj.base.type = (mp_obj_type_t *)&mod_network_nic_type_wiznet5k;
- wiznet5k_obj.cris_state = 0;
- wiznet5k_obj.spi = spi_from_mp_obj(args[0]);
- wiznet5k_obj.cs = pin_find(args[1]);
- wiznet5k_obj.rst = pin_find(args[2]);
- wiznet5k_obj.socket_used = 0;
-
- /*!< SPI configuration */
- SPI_InitTypeDef *init = &wiznet5k_obj.spi->spi->Init;
- init->Mode = SPI_MODE_MASTER;
- init->Direction = SPI_DIRECTION_2LINES;
- init->DataSize = SPI_DATASIZE_8BIT;
- init->CLKPolarity = SPI_POLARITY_LOW; // clock is low when idle
- init->CLKPhase = SPI_PHASE_1EDGE; // data latched on first edge, which is rising edge for low-idle
- init->NSS = SPI_NSS_SOFT;
- init->BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2; // clock freq = f_PCLK / this_prescale_value; Wiz820i can do up to 80MHz
- init->FirstBit = SPI_FIRSTBIT_MSB;
- init->TIMode = SPI_TIMODE_DISABLED;
- init->CRCCalculation = SPI_CRCCALCULATION_DISABLED;
- init->CRCPolynomial = 7; // unused
- spi_init(wiznet5k_obj.spi, false);
-
- mp_hal_pin_output(wiznet5k_obj.cs);
- mp_hal_pin_output(wiznet5k_obj.rst);
-
- mp_hal_pin_low(wiznet5k_obj.rst);
- mp_hal_delay_ms(1); // datasheet says 2us
- mp_hal_pin_high(wiznet5k_obj.rst);
- mp_hal_delay_ms(160); // datasheet says 150ms
-
- reg_wizchip_cris_cbfunc(wiz_cris_enter, wiz_cris_exit);
- reg_wizchip_cs_cbfunc(wiz_cs_select, wiz_cs_deselect);
- reg_wizchip_spi_cbfunc(wiz_spi_read, wiz_spi_write);
-
- uint8_t sn_size[16] = {2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; // 2k buffer for each socket
- ctlwizchip(CW_INIT_WIZCHIP, sn_size);
-
- // set some sensible default values; they are configurable using ifconfig method
- wiz_NetInfo netinfo = {
- .mac = {0x00, 0x08, 0xdc, 0xab, 0xcd, 0xef},
- .ip = {192, 168, 0, 18},
- .sn = {255, 255, 255, 0},
- .gw = {192, 168, 0, 1},
- .dns = {8, 8, 8, 8}, // Google public DNS
- .dhcp = NETINFO_STATIC,
- };
- ctlnetwork(CN_SET_NETINFO, (void *)&netinfo);
-
- // seems we need a small delay after init
- mp_hal_delay_ms(250);
-
- // register with network module
- mod_network_register_nic(&wiznet5k_obj);
-
- // return wiznet5k object
- return &wiznet5k_obj;
-}
-
-/// \method regs()
-/// Dump WIZNET5K registers.
-STATIC mp_obj_t wiznet5k_regs(mp_obj_t self_in) {
- // wiznet5k_obj_t *self = self_in;
- printf("Wiz CREG:");
- for (int i = 0; i < 0x50; ++i) {
- if (i % 16 == 0) {
- printf("\n %04x:", i);
- }
- #if MICROPY_PY_NETWORK_WIZNET5K == 5200
- uint32_t reg = i;
- #else
- uint32_t reg = _W5500_IO_BASE_ | i << 8;
- #endif
- printf(" %02x", WIZCHIP_READ(reg));
- }
- for (int sn = 0; sn < 4; ++sn) {
- printf("\nWiz SREG[%d]:", sn);
- for (int i = 0; i < 0x30; ++i) {
- if (i % 16 == 0) {
- printf("\n %04x:", i);
- }
- #if MICROPY_PY_NETWORK_WIZNET5K == 5200
- uint32_t reg = WIZCHIP_SREG_ADDR(sn, i);
- #else
- uint32_t reg = _W5500_IO_BASE_ | i << 8 | WIZCHIP_SREG_BLOCK(sn) << 3;
- #endif
- printf(" %02x", WIZCHIP_READ(reg));
- }
- }
- printf("\n");
- return mp_const_none;
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(wiznet5k_regs_obj, wiznet5k_regs);
-
-STATIC mp_obj_t wiznet5k_isconnected(mp_obj_t self_in) {
- (void)self_in;
- return mp_obj_new_bool(wizphy_getphylink() == PHY_LINK_ON);
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(wiznet5k_isconnected_obj, wiznet5k_isconnected);
-
-/// \method ifconfig([(ip, subnet, gateway, dns)])
-/// Get/set IP address, subnet mask, gateway and DNS.
-STATIC mp_obj_t wiznet5k_ifconfig(size_t n_args, const mp_obj_t *args) {
- wiz_NetInfo netinfo;
- ctlnetwork(CN_GET_NETINFO, &netinfo);
- if (n_args == 1) {
- // get
- mp_obj_t tuple[4] = {
- netutils_format_ipv4_addr(netinfo.ip, NETUTILS_BIG),
- netutils_format_ipv4_addr(netinfo.sn, NETUTILS_BIG),
- netutils_format_ipv4_addr(netinfo.gw, NETUTILS_BIG),
- netutils_format_ipv4_addr(netinfo.dns, NETUTILS_BIG),
- };
- return mp_obj_new_tuple(4, tuple);
- } else {
- // set
- mp_obj_t *items;
- mp_obj_get_array_fixed_n(args[1], 4, &items);
- netutils_parse_ipv4_addr(items[0], netinfo.ip, NETUTILS_BIG);
- netutils_parse_ipv4_addr(items[1], netinfo.sn, NETUTILS_BIG);
- netutils_parse_ipv4_addr(items[2], netinfo.gw, NETUTILS_BIG);
- netutils_parse_ipv4_addr(items[3], netinfo.dns, NETUTILS_BIG);
- ctlnetwork(CN_SET_NETINFO, &netinfo);
- return mp_const_none;
- }
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(wiznet5k_ifconfig_obj, 1, 2, wiznet5k_ifconfig);
-
-STATIC const mp_rom_map_elem_t wiznet5k_locals_dict_table[] = {
- { MP_ROM_QSTR(MP_QSTR_regs), MP_ROM_PTR(&wiznet5k_regs_obj) },
- { MP_ROM_QSTR(MP_QSTR_ifconfig), MP_ROM_PTR(&wiznet5k_ifconfig_obj) },
- { MP_ROM_QSTR(MP_QSTR_isconnected), MP_ROM_PTR(&wiznet5k_isconnected_obj) },
-};
-
-STATIC MP_DEFINE_CONST_DICT(wiznet5k_locals_dict, wiznet5k_locals_dict_table);
-
-const mod_network_nic_type_t mod_network_nic_type_wiznet5k = {
- .base = {
- { &mp_type_type },
- .name = MP_QSTR_WIZNET5K,
- .make_new = wiznet5k_make_new,
- .locals_dict = (mp_obj_dict_t *)&wiznet5k_locals_dict,
- },
- .gethostbyname = wiznet5k_gethostbyname,
- .socket = wiznet5k_socket_socket,
- .close = wiznet5k_socket_close,
- .bind = wiznet5k_socket_bind,
- .listen = wiznet5k_socket_listen,
- .accept = wiznet5k_socket_accept,
- .connect = wiznet5k_socket_connect,
- .send = wiznet5k_socket_send,
- .recv = wiznet5k_socket_recv,
- .sendto = wiznet5k_socket_sendto,
- .recvfrom = wiznet5k_socket_recvfrom,
- .setsockopt = wiznet5k_socket_setsockopt,
- .settimeout = wiznet5k_socket_settimeout,
- .ioctl = wiznet5k_socket_ioctl,
-};
-
-#endif // MICROPY_PY_NETWORK_WIZNET5K && !MICROPY_PY_LWIP
diff --git a/ports/stm32/modpyb.c b/ports/stm32/modpyb.c
index 96e719c6bf9d..94aa6e65d1be 100644
--- a/ports/stm32/modpyb.c
+++ b/ports/stm32/modpyb.c
@@ -30,7 +30,6 @@
#include "py/runtime.h"
#include "py/mphal.h"
#include "shared/runtime/pyexec.h"
-#include "drivers/dht/dht.h"
#include "stm32_it.h"
#include "irq.h"
#include "led.h"
@@ -53,11 +52,10 @@
#include "usb.h"
#include "portmodules.h"
#include "modmachine.h"
+#include "extmod/modnetwork.h"
#include "extmod/vfs.h"
#include "extmod/utime_mphal.h"
-char pyb_country_code[2];
-
#if MICROPY_PY_PYB
STATIC mp_obj_t pyb_fault_debug(mp_obj_t value) {
@@ -116,21 +114,18 @@ STATIC mp_obj_t pyb_repl_uart(size_t n_args, const mp_obj_t *args) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_repl_uart_obj, 0, 1, pyb_repl_uart);
+#if MICROPY_PY_NETWORK
+MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mod_network_country_obj);
+#else
+// Provide a no-op version of pyb.country for backwards compatibility on
+// boards that don't support networking.
STATIC mp_obj_t pyb_country(size_t n_args, const mp_obj_t *args) {
- if (n_args == 0) {
- return mp_obj_new_str(pyb_country_code, 2);
- } else {
- size_t len;
- const char *str = mp_obj_str_get_data(args[0], &len);
- if (len != 2) {
- mp_raise_ValueError(NULL);
- }
- pyb_country_code[0] = str[0];
- pyb_country_code[1] = str[1];
- return mp_const_none;
- }
+ (void)n_args;
+ (void)args;
+ return mp_const_none;
}
-STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_country_obj, 0, 1, pyb_country);
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_network_country_obj, 0, 1, pyb_country);
+#endif
STATIC const mp_rom_map_elem_t pyb_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_pyb) },
@@ -161,7 +156,9 @@ STATIC const mp_rom_map_elem_t pyb_module_globals_table[] = {
#endif
{ MP_ROM_QSTR(MP_QSTR_main), MP_ROM_PTR(&pyb_main_obj) },
{ MP_ROM_QSTR(MP_QSTR_repl_uart), MP_ROM_PTR(&pyb_repl_uart_obj) },
- { MP_ROM_QSTR(MP_QSTR_country), MP_ROM_PTR(&pyb_country_obj) },
+
+ // Deprecated (use network.country instead).
+ { MP_ROM_QSTR(MP_QSTR_country), MP_ROM_PTR(&mod_network_country_obj) },
#if MICROPY_HW_ENABLE_USB
{ MP_ROM_QSTR(MP_QSTR_usb_mode), MP_ROM_PTR(&pyb_usb_mode_obj) },
@@ -191,9 +188,6 @@ STATIC const mp_rom_map_elem_t pyb_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_mount), MP_ROM_PTR(&mp_vfs_mount_obj) },
#endif
- // This function is not intended to be public and may be moved elsewhere
- { MP_ROM_QSTR(MP_QSTR_dht_readinto), MP_ROM_PTR(&dht_readinto_obj) },
-
{ MP_ROM_QSTR(MP_QSTR_Timer), MP_ROM_PTR(&pyb_timer_type) },
#if MICROPY_HW_ENABLE_RNG
diff --git a/ports/stm32/moduos.c b/ports/stm32/moduos.c
index 1862564b611c..85d0edeca8a1 100644
--- a/ports/stm32/moduos.c
+++ b/ports/stm32/moduos.c
@@ -58,7 +58,7 @@ STATIC mp_obj_t mp_uos_urandom(mp_obj_t num) {
for (int i = 0; i < n; i++) {
vstr.buf[i] = rng_get();
}
- return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
+ return mp_obj_new_bytes_from_vstr(&vstr);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_uos_urandom_obj, mp_uos_urandom);
#endif
diff --git a/ports/stm32/mpbthciport.c b/ports/stm32/mpbthciport.c
index d3ddb40421e5..fe061a124088 100644
--- a/ports/stm32/mpbthciport.c
+++ b/ports/stm32/mpbthciport.c
@@ -29,8 +29,8 @@
#include "py/mphal.h"
#include "extmod/mpbthci.h"
#include "extmod/modbluetooth.h"
+#include "shared/runtime/softtimer.h"
#include "mpbthciport.h"
-#include "softtimer.h"
#include "pendsv.h"
#include "shared/runtime/mpirq.h"
@@ -116,7 +116,7 @@ int mp_bluetooth_hci_uart_init(uint32_t port, uint32_t baudrate) {
int mp_bluetooth_hci_uart_deinit(void) {
DEBUG_printf("mp_bluetooth_hci_uart_deinit (stm32 rfcore)\n");
-
+ rfcore_ble_reset();
return 0;
}
diff --git a/ports/stm32/mpbtstackport.c b/ports/stm32/mpbtstackport.c
index 795534042eae..728594d19c96 100644
--- a/ports/stm32/mpbtstackport.c
+++ b/ports/stm32/mpbtstackport.c
@@ -31,6 +31,8 @@
#if MICROPY_PY_BLUETOOTH && MICROPY_BLUETOOTH_BTSTACK
#include "lib/btstack/src/btstack.h"
+#include "lib/btstack/src/hci_transport_h4.h"
+#include "lib/btstack/platform/embedded/hci_dump_embedded_stdout.h"
#include "extmod/mpbthci.h"
#include "extmod/btstack/btstack_hci_uart.h"
#include "extmod/btstack/modbluetooth_btstack.h"
@@ -137,16 +139,10 @@ void mp_bluetooth_hci_poll(void) {
}
void mp_bluetooth_btstack_port_init(void) {
- static bool run_loop_init = false;
- if (!run_loop_init) {
- run_loop_init = true;
- btstack_run_loop_init(&mp_btstack_runloop_stm32);
- } else {
- mp_btstack_runloop_stm32.init();
- }
+ btstack_run_loop_init(&mp_btstack_runloop_stm32);
- // hci_dump_open(NULL, HCI_DUMP_STDOUT);
- const hci_transport_t *transport = hci_transport_h4_instance(&mp_bluetooth_btstack_hci_uart_block);
+ // hci_dump_init(hci_dump_embedded_stdout_get_instance());
+ const hci_transport_t *transport = hci_transport_h4_instance_for_uart(&mp_bluetooth_btstack_hci_uart_block);
hci_init(transport, &hci_transport_config_uart);
#ifdef MICROPY_HW_BLE_BTSTACK_CHIPSET_INSTANCE
diff --git a/ports/stm32/mpconfigboard_common.h b/ports/stm32/mpconfigboard_common.h
index 51bad18dd53e..b538f7823548 100644
--- a/ports/stm32/mpconfigboard_common.h
+++ b/ports/stm32/mpconfigboard_common.h
@@ -370,6 +370,16 @@
#define MICROPY_HW_MAX_UART (5)
#define MICROPY_HW_MAX_LPUART (1)
+// Configuration for STM32L1 series
+#elif defined(STM32L1)
+#define MP_HAL_UNIQUE_ID_ADDRESS (UID_BASE)
+#define PYB_EXTI_NUM_VECTORS (23)
+#define MICROPY_HW_MAX_I2C (2)
+// TODO: L1 has 9 timers but tim0 and tim1 don't exist.
+#define MICROPY_HW_MAX_TIMER (11)
+#define MICROPY_HW_MAX_UART (5)
+#define MICROPY_HW_MAX_LPUART (0)
+
// Configuration for STM32L4 series
#elif defined(STM32L4)
diff --git a/ports/stm32/mpconfigport.h b/ports/stm32/mpconfigport.h
index 35f823daf870..f92f4458bc65 100644
--- a/ports/stm32/mpconfigport.h
+++ b/ports/stm32/mpconfigport.h
@@ -65,7 +65,7 @@
#endif
// Python internal features
-#define MICROPY_TRACKED_ALLOC (MICROPY_SSL_MBEDTLS)
+#define MICROPY_TRACKED_ALLOC (MICROPY_SSL_MBEDTLS || MICROPY_BLUETOOTH_BTSTACK)
#define MICROPY_READER_VFS (1)
#define MICROPY_ENABLE_GC (1)
#define MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF (1)
@@ -126,6 +126,8 @@
#define MICROPY_PY_MACHINE_SPI_MSB (SPI_FIRSTBIT_MSB)
#define MICROPY_PY_MACHINE_SPI_LSB (SPI_FIRSTBIT_LSB)
#define MICROPY_PY_MACHINE_SOFTSPI (1)
+#define MICROPY_PY_MACHINE_TIMER (1)
+#define MICROPY_SOFT_TIMER_TICKS_MS uwTick
#endif
#define MICROPY_HW_SOFTSPI_MIN_DELAY (0)
#define MICROPY_HW_SOFTSPI_MAX_BAUDRATE (HAL_RCC_GetSysClockFreq() / 48)
@@ -158,18 +160,6 @@
#define MICROPY_FATFS_RPATH (2)
#define MICROPY_FATFS_MULTI_PARTITION (1)
-// TODO these should be generic, not bound to a particular FS implementation
-#if MICROPY_VFS_FAT
-#define mp_type_fileio mp_type_vfs_fat_fileio
-#define mp_type_textio mp_type_vfs_fat_textio
-#elif MICROPY_VFS_LFS1
-#define mp_type_fileio mp_type_vfs_lfs1_fileio
-#define mp_type_textio mp_type_vfs_lfs1_textio
-#elif MICROPY_VFS_LFS2
-#define mp_type_fileio mp_type_vfs_lfs2_fileio
-#define mp_type_textio mp_type_vfs_lfs2_textio
-#endif
-
#if MICROPY_PY_PYB
extern const struct _mp_obj_module_t pyb_module;
#define PYB_BUILTIN_MODULE_CONSTANTS \
@@ -209,23 +199,12 @@ extern const struct _mp_obj_type_t mp_network_cyw43_type;
#endif
#if MICROPY_PY_NETWORK_WIZNET5K
-#if MICROPY_PY_LWIP
extern const struct _mp_obj_type_t mod_network_nic_type_wiznet5k;
-#else
-extern const struct _mod_network_nic_type_t mod_network_nic_type_wiznet5k;
-#endif
#define MICROPY_HW_NIC_WIZNET5K { MP_ROM_QSTR(MP_QSTR_WIZNET5K), MP_ROM_PTR(&mod_network_nic_type_wiznet5k) },
#else
#define MICROPY_HW_NIC_WIZNET5K
#endif
-#if MICROPY_PY_CC3K
-extern const struct _mod_network_nic_type_t mod_network_nic_type_cc3k;
-#define MICROPY_HW_NIC_CC3K { MP_ROM_QSTR(MP_QSTR_CC3K), MP_ROM_PTR(&mod_network_nic_type_cc3k) },
-#else
-#define MICROPY_HW_NIC_CC3K
-#endif
-
// extra constants
#define MICROPY_PORT_CONSTANTS \
MACHINE_BUILTIN_MODULE_CONSTANTS \
@@ -240,93 +219,10 @@ extern const struct _mod_network_nic_type_t mod_network_nic_type_cc3k;
MICROPY_HW_NIC_ETH \
MICROPY_HW_NIC_CYW43 \
MICROPY_HW_NIC_WIZNET5K \
- MICROPY_HW_NIC_CC3K \
MICROPY_BOARD_NETWORK_INTERFACES \
#define MP_STATE_PORT MP_STATE_VM
-#if MICROPY_PY_LVGL
-#ifndef MICROPY_INCLUDED_PY_MPSTATE_H
-#define MICROPY_INCLUDED_PY_MPSTATE_H
-#include "lib/lv_bindings/lvgl/src/misc/lv_gc.h"
-#undef MICROPY_INCLUDED_PY_MPSTATE_H
-#else
-#include "lib/lv_bindings/lvgl/src/misc/lv_gc.h"
-#endif
-#else
-#define LV_ROOTS
-#endif
-
-#if MICROPY_PY_RK043FN48H
-#define RK043FN48H_ROOTS void* rk043fn48h_fb[2];
-#else
-#define RK043FN48H_ROOTS
-#endif
-
-#if MICROPY_BLUETOOTH_NIMBLE
-struct _mp_bluetooth_nimble_root_pointers_t;
-struct _mp_bluetooth_nimble_malloc_t;
-#define MICROPY_PORT_ROOT_POINTER_BLUETOOTH_NIMBLE struct _mp_bluetooth_nimble_malloc_t *bluetooth_nimble_memory; struct _mp_bluetooth_nimble_root_pointers_t *bluetooth_nimble_root_pointers;
-#else
-#define MICROPY_PORT_ROOT_POINTER_BLUETOOTH_NIMBLE
-#endif
-
-#if MICROPY_BLUETOOTH_BTSTACK
-struct _mp_bluetooth_btstack_root_pointers_t;
-#define MICROPY_PORT_ROOT_POINTER_BLUETOOTH_BTSTACK struct _mp_bluetooth_btstack_root_pointers_t *bluetooth_btstack_root_pointers;
-#else
-#define MICROPY_PORT_ROOT_POINTER_BLUETOOTH_BTSTACK
-#endif
-
-#ifndef MICROPY_BOARD_ROOT_POINTERS
-#define MICROPY_BOARD_ROOT_POINTERS
-#endif
-
-#define MICROPY_PORT_ROOT_POINTERS \
- LV_ROOTS \
- void *mp_lv_user_data; \
- RK043FN48H_ROOTS \
- const char *readline_hist[8]; \
- \
- mp_obj_t pyb_hid_report_desc; \
- \
- mp_obj_t pyb_config_main; \
- \
- mp_obj_t pyb_switch_callback; \
- \
- mp_obj_t pin_class_mapper; \
- mp_obj_t pin_class_map_dict; \
- \
- mp_obj_t pyb_extint_callback[PYB_EXTI_NUM_VECTORS]; \
- \
- /* pointers to all Timer objects (if they have been created) */ \
- struct _pyb_timer_obj_t *pyb_timer_obj_all[MICROPY_HW_MAX_TIMER]; \
- \
- /* stdio is repeated on this UART object if it's not null */ \
- struct _pyb_uart_obj_t *pyb_stdio_uart; \
- \
- /* pointers to all UART objects (if they have been created) */ \
- struct _pyb_uart_obj_t *pyb_uart_obj_all[MICROPY_HW_MAX_UART + MICROPY_HW_MAX_LPUART]; \
- \
- /* pointers to all CAN objects (if they have been created) */ \
- struct _pyb_can_obj_t *pyb_can_obj_all[MICROPY_HW_MAX_CAN]; \
- \
- /* pointers to all I2S objects (if they have been created) */ \
- struct _machine_i2s_obj_t *machine_i2s_obj[MICROPY_HW_MAX_I2S]; \
- \
- /* USB_VCP IRQ callbacks (if they have been set) */ \
- mp_obj_t pyb_usb_vcp_irq[MICROPY_HW_USB_CDC_NUM]; \
- \
- /* list of registered NICs */ \
- mp_obj_list_t mod_network_nic_list; \
- \
- /* root pointers for sub-systems */ \
- MICROPY_PORT_ROOT_POINTER_BLUETOOTH_NIMBLE \
- MICROPY_PORT_ROOT_POINTER_BLUETOOTH_BTSTACK \
- \
- /* root pointers defined by a board */ \
- MICROPY_BOARD_ROOT_POINTERS \
-
// type definitions for the specific machine
#define MICROPY_MAKE_POINTER_CALLABLE(p) ((void *)((uint32_t)(p) | 1))
@@ -401,6 +297,10 @@ static inline mp_uint_t disable_irq(void) {
#define MICROPY_PY_LWIP_REENTER MICROPY_PY_PENDSV_REENTER
#define MICROPY_PY_LWIP_EXIT MICROPY_PY_PENDSV_EXIT
+#ifndef MICROPY_PY_NETWORK_HOSTNAME_DEFAULT
+#define MICROPY_PY_NETWORK_HOSTNAME_DEFAULT "mpy-stm32"
+#endif
+
#if MICROPY_PY_BLUETOOTH_USE_SYNC_EVENTS
// Bluetooth code only runs in the scheduler, no locking/mutex required.
#define MICROPY_PY_BLUETOOTH_ENTER uint32_t atomic_state = 0;
@@ -418,6 +318,14 @@ static inline mp_uint_t disable_irq(void) {
#define MICROPY_PY_BLUETOOTH_HCI_READ_MODE MICROPY_PY_BLUETOOTH_HCI_READ_MODE_BYTE
#endif
+#ifndef MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE
+#define MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE (1)
+#endif
+
+#ifndef MICROPY_PY_BLUETOOTH_ENABLE_L2CAP_CHANNELS
+#define MICROPY_PY_BLUETOOTH_ENABLE_L2CAP_CHANNELS (MICROPY_BLUETOOTH_NIMBLE)
+#endif
+
// We need an implementation of the log2 function which is not a macro
#define MP_NEED_LOG2 (1)
diff --git a/ports/stm32/mpconfigport.mk b/ports/stm32/mpconfigport.mk
index 830ccf03123a..737ff9d3d29a 100644
--- a/ports/stm32/mpconfigport.mk
+++ b/ports/stm32/mpconfigport.mk
@@ -6,9 +6,6 @@
# 5500 : support for W5500 module
MICROPY_PY_NETWORK_WIZNET5K ?= 0
-# cc3k module for wifi support
-MICROPY_PY_CC3K ?= 0
-
# VFS FAT FS support
MICROPY_VFS_FAT ?= 1
diff --git a/ports/stm32/mphalport.c b/ports/stm32/mphalport.c
index 477192330bae..092d63e1bb19 100644
--- a/ports/stm32/mphalport.c
+++ b/ports/stm32/mphalport.c
@@ -87,7 +87,7 @@ void mp_hal_gpio_clock_enable(GPIO_TypeDef *gpio) {
// This logic assumes that all the GPIOx_EN bits are adjacent and ordered in one register
- #if defined(STM32F0)
+ #if defined(STM32F0) || defined(STM32L1)
#define AHBxENR AHBENR
#define AHBxENR_GPIOAEN_Pos RCC_AHBENR_GPIOAEN_Pos
#elif defined(STM32F4) || defined(STM32F7)
@@ -177,3 +177,5 @@ void mp_hal_get_mac_ascii(int idx, size_t chr_off, size_t chr_len, char *dest) {
*dest++ = hexchr[mac[chr_off >> 1] >> (4 * (1 - (chr_off & 1))) & 0xf];
}
}
+
+MP_REGISTER_ROOT_POINTER(struct _pyb_uart_obj_t *pyb_stdio_uart);
diff --git a/ports/stm32/mphalport.h b/ports/stm32/mphalport.h
index 47bb1f8c8441..728f5fefbded 100644
--- a/ports/stm32/mphalport.h
+++ b/ports/stm32/mphalport.h
@@ -14,9 +14,11 @@
#elif defined(STM32G4)
#define MICROPY_PLATFORM_VERSION "HAL1.3.0"
#elif defined(STM32H7)
-#define MICROPY_PLATFORM_VERSION "HAL1.6.0"
+#define MICROPY_PLATFORM_VERSION "HAL1.11.0"
#elif defined(STM32L0)
#define MICROPY_PLATFORM_VERSION "HAL1.11.2"
+#elif defined(STM32L1)
+#define MICROPY_PLATFORM_VERSION "HAL1.10.3"
#elif defined(STM32L4)
#define MICROPY_PLATFORM_VERSION "HAL1.17.0"
#elif defined(STM32WB)
@@ -96,11 +98,21 @@ static inline mp_uint_t mp_hal_ticks_cpu(void) {
#define mp_hal_pin_od_high(p) mp_hal_pin_high(p)
#define mp_hal_pin_read(p) (((p)->gpio->IDR >> (p)->pin) & 1)
#define mp_hal_pin_write(p, v) ((v) ? mp_hal_pin_high(p) : mp_hal_pin_low(p))
+#define mp_hal_pin_interrupt(pin, handler, trigger, hard) extint_register_pin(pin, trigger, hard, handler)
+
+enum mp_hal_pin_interrupt_trigger {
+ MP_HAL_PIN_TRIGGER_NONE,
+ MP_HAL_PIN_TRIGGER_FALL = GPIO_MODE_IT_FALLING,
+ MP_HAL_PIN_TRIGGER_RISE = GPIO_MODE_IT_RISING,
+};
void mp_hal_gpio_clock_enable(GPIO_TypeDef *gpio);
void mp_hal_pin_config(mp_hal_pin_obj_t pin, uint32_t mode, uint32_t pull, uint32_t alt);
bool mp_hal_pin_config_alt(mp_hal_pin_obj_t pin, uint32_t mode, uint32_t pull, uint8_t fn, uint8_t unit);
void mp_hal_pin_config_speed(mp_hal_pin_obj_t pin_obj, uint32_t speed);
+void extint_register_pin(const pin_obj_t *pin, uint32_t mode, bool hard_irq, mp_obj_t callback_obj);
+
+mp_obj_base_t *mp_hal_get_spi_obj(mp_obj_t spi_in);
enum {
MP_HAL_MAC_WLAN0 = 0,
diff --git a/ports/stm32/mpnetworkport.c b/ports/stm32/mpnetworkport.c
index 2f49328e110e..62f780a35a04 100644
--- a/ports/stm32/mpnetworkport.c
+++ b/ports/stm32/mpnetworkport.c
@@ -42,14 +42,22 @@
#include "lwip/dns.h"
#include "lwip/dhcp.h"
#include "lwip/apps/mdns.h"
+
+#if MICROPY_PY_NETWORK_CYW43
#include "extmod/network_cyw43.h"
-#include "drivers/cyw43/cyw43.h"
+#include "lib/cyw43-driver/src/cyw43.h"
+#endif
// Poll lwIP every 128ms
#define LWIP_TICK(tick) (((tick) & ~(SYSTICK_DISPATCH_NUM_SLOTS - 1) & 0x7f) == 0)
#if MICROPY_PY_NETWORK_WIZNET5K
void wiznet5k_poll(void);
+void wiznet5k_deinit(void);
+
+void wiznet5k_try_poll(void) {
+ pendsv_schedule_dispatch(PENDSV_DISPATCH_WIZNET, wiznet5k_poll);
+}
#endif
u32_t sys_now(void) {
diff --git a/ports/stm32/network_lan.c b/ports/stm32/network_lan.c
index f19916a1df09..556adebd8fe9 100644
--- a/ports/stm32/network_lan.c
+++ b/ports/stm32/network_lan.c
@@ -158,12 +158,13 @@ STATIC const mp_rom_map_elem_t network_lan_locals_dict_table[] = {
};
STATIC MP_DEFINE_CONST_DICT(network_lan_locals_dict, network_lan_locals_dict_table);
-const mp_obj_type_t network_lan_type = {
- { &mp_type_type },
- .name = MP_QSTR_LAN,
- .print = network_lan_print,
- .make_new = network_lan_make_new,
- .locals_dict = (mp_obj_dict_t *)&network_lan_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ network_lan_type,
+ MP_QSTR_LAN,
+ MP_TYPE_FLAG_NONE,
+ make_new, network_lan_make_new,
+ print, network_lan_print,
+ locals_dict, &network_lan_locals_dict
+ );
#endif // defined(MICROPY_HW_ETH_MDC)
diff --git a/ports/stm32/network_wiznet5k.c b/ports/stm32/network_wiznet5k.c
deleted file mode 100644
index 4675f3c2c2a1..000000000000
--- a/ports/stm32/network_wiznet5k.c
+++ /dev/null
@@ -1,465 +0,0 @@
-/*
- * This file is part of the MicroPython project, http://micropython.org/
- *
- * The MIT License (MIT)
- *
- * Copyright (c) 2014-2018 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 "extmod/modnetwork.h"
-#include "spi.h"
-
-#if MICROPY_PY_NETWORK_WIZNET5K && MICROPY_PY_LWIP
-
-#include "shared/netutils/netutils.h"
-#include "drivers/wiznet5k/ethernet/socket.h"
-#include "lwip/err.h"
-#include "lwip/dns.h"
-#include "lwip/dhcp.h"
-#include "netif/etharp.h"
-
-#define TRACE_ETH_TX (0x0002)
-#define TRACE_ETH_RX (0x0004)
-
-/*******************************************************************************/
-// Wiznet5k Ethernet driver in MACRAW mode
-
-typedef struct _wiznet5k_obj_t {
- mp_obj_base_t base;
- mp_uint_t cris_state;
- const spi_t *spi;
- mp_hal_pin_obj_t cs;
- mp_hal_pin_obj_t rst;
- uint8_t eth_frame[1514];
- uint32_t trace_flags;
- struct netif netif;
- struct dhcp dhcp_struct;
-} wiznet5k_obj_t;
-
-// Global object holding the Wiznet5k state
-STATIC wiznet5k_obj_t wiznet5k_obj;
-
-STATIC void wiznet5k_lwip_init(wiznet5k_obj_t *self);
-
-STATIC void wiz_cris_enter(void) {
- wiznet5k_obj.cris_state = MICROPY_BEGIN_ATOMIC_SECTION();
-}
-
-STATIC void wiz_cris_exit(void) {
- MICROPY_END_ATOMIC_SECTION(wiznet5k_obj.cris_state);
-}
-
-STATIC void wiz_cs_select(void) {
- mp_hal_pin_low(wiznet5k_obj.cs);
-}
-
-STATIC void wiz_cs_deselect(void) {
- mp_hal_pin_high(wiznet5k_obj.cs);
-}
-
-STATIC void wiz_spi_read(uint8_t *buf, uint32_t len) {
- HAL_StatusTypeDef status = HAL_SPI_Receive(wiznet5k_obj.spi->spi, buf, len, 5000);
- (void)status;
-}
-
-STATIC void wiz_spi_write(const uint8_t *buf, uint32_t len) {
- HAL_StatusTypeDef status = HAL_SPI_Transmit(wiznet5k_obj.spi->spi, (uint8_t *)buf, len, 5000);
- (void)status;
-}
-
-STATIC void wiznet5k_init(void) {
- // SPI configuration
- SPI_InitTypeDef *init = &wiznet5k_obj.spi->spi->Init;
- init->Mode = SPI_MODE_MASTER;
- init->Direction = SPI_DIRECTION_2LINES;
- init->DataSize = SPI_DATASIZE_8BIT;
- init->CLKPolarity = SPI_POLARITY_LOW; // clock is low when idle
- init->CLKPhase = SPI_PHASE_1EDGE; // data latched on first edge, which is rising edge for low-idle
- init->NSS = SPI_NSS_SOFT;
- init->BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2; // clock freq = f_PCLK / this_prescale_value; Wiz820i can do up to 80MHz
- init->FirstBit = SPI_FIRSTBIT_MSB;
- init->TIMode = SPI_TIMODE_DISABLED;
- init->CRCCalculation = SPI_CRCCALCULATION_DISABLED;
- init->CRCPolynomial = 7; // unused
- spi_init(wiznet5k_obj.spi, false);
-
- mp_hal_pin_output(wiznet5k_obj.cs);
- mp_hal_pin_output(wiznet5k_obj.rst);
-
- // Reset the chip
- mp_hal_pin_low(wiznet5k_obj.rst);
- mp_hal_delay_ms(1); // datasheet says 2us
- mp_hal_pin_high(wiznet5k_obj.rst);
- mp_hal_delay_ms(150); // datasheet says 150ms
-
- // Set physical interface callbacks
- reg_wizchip_cris_cbfunc(wiz_cris_enter, wiz_cris_exit);
- reg_wizchip_cs_cbfunc(wiz_cs_select, wiz_cs_deselect);
- reg_wizchip_spi_cbfunc(wiz_spi_read, wiz_spi_write);
-
- // Configure 16k buffers for fast MACRAW
- uint8_t sn_size[16] = {16, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0};
- ctlwizchip(CW_INIT_WIZCHIP, sn_size);
-
- // Seems we need a small delay after init
- mp_hal_delay_ms(250);
-
- // If the device doesn't have a MAC address then set one
- uint8_t mac[6];
- getSHAR(mac);
- if ((mac[0] | mac[1] | mac[2] | mac[3] | mac[4] | mac[5]) == 0) {
- mp_hal_get_mac(MP_HAL_MAC_ETH0, mac);
- setSHAR(mac);
- }
-
- // Hook the Wiznet into lwIP
- wiznet5k_lwip_init(&wiznet5k_obj);
-}
-
-STATIC void wiznet5k_deinit(void) {
- for (struct netif *netif = netif_list; netif != NULL; netif = netif->next) {
- if (netif == &wiznet5k_obj.netif) {
- netif_remove(netif);
- netif->flags = 0;
- break;
- }
- }
-}
-
-STATIC void wiznet5k_get_mac_address(wiznet5k_obj_t *self, uint8_t mac[6]) {
- (void)self;
- getSHAR(mac);
-}
-
-STATIC void wiznet5k_send_ethernet(wiznet5k_obj_t *self, size_t len, const uint8_t *buf) {
- uint8_t ip[4] = {1, 1, 1, 1}; // dummy
- int ret = WIZCHIP_EXPORT(sendto)(0, (byte *)buf, len, ip, 11); // dummy port
- if (ret != len) {
- printf("wiznet5k_send_ethernet: fatal error %d\n", ret);
- netif_set_link_down(&self->netif);
- netif_set_down(&self->netif);
- }
-}
-
-// Stores the frame in self->eth_frame and returns number of bytes in the frame, 0 for no frame
-STATIC uint16_t wiznet5k_recv_ethernet(wiznet5k_obj_t *self) {
- uint16_t len = getSn_RX_RSR(0);
- if (len == 0) {
- return 0;
- }
-
- byte ip[4];
- uint16_t port;
- int ret = WIZCHIP_EXPORT(recvfrom)(0, self->eth_frame, 1514, ip, &port);
- if (ret <= 0) {
- printf("wiznet5k_poll: fatal error len=%u ret=%d\n", len, ret);
- netif_set_link_down(&self->netif);
- netif_set_down(&self->netif);
- return 0;
- }
-
- return ret;
-}
-
-/*******************************************************************************/
-// Wiznet5k lwIP interface
-
-STATIC err_t wiznet5k_netif_output(struct netif *netif, struct pbuf *p) {
- wiznet5k_obj_t *self = netif->state;
- pbuf_copy_partial(p, self->eth_frame, p->tot_len, 0);
- if (self->trace_flags & TRACE_ETH_TX) {
- netutils_ethernet_trace(MP_PYTHON_PRINTER, p->tot_len, self->eth_frame, NETUTILS_TRACE_IS_TX | NETUTILS_TRACE_NEWLINE);
- }
- wiznet5k_send_ethernet(self, p->tot_len, self->eth_frame);
- return ERR_OK;
-}
-
-STATIC err_t wiznet5k_netif_init(struct netif *netif) {
- netif->linkoutput = wiznet5k_netif_output;
- netif->output = etharp_output;
- netif->mtu = 1500;
- netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET | NETIF_FLAG_IGMP;
- wiznet5k_get_mac_address(netif->state, netif->hwaddr);
- netif->hwaddr_len = sizeof(netif->hwaddr);
- int ret = WIZCHIP_EXPORT(socket)(0, Sn_MR_MACRAW, 0, 0);
- if (ret != 0) {
- printf("WIZNET fatal error in netifinit: %d\n", ret);
- return ERR_IF;
- }
-
- // Enable MAC filtering so we only get frames destined for us, to reduce load on lwIP
- setSn_MR(0, getSn_MR(0) | Sn_MR_MFEN);
-
- return ERR_OK;
-}
-
-STATIC void wiznet5k_lwip_init(wiznet5k_obj_t *self) {
- ip_addr_t ipconfig[4];
- ipconfig[0].addr = 0;
- ipconfig[1].addr = 0;
- ipconfig[2].addr = 0;
- ipconfig[3].addr = 0;
- netif_add(&self->netif, &ipconfig[0], &ipconfig[1], &ipconfig[2], self, wiznet5k_netif_init, ethernet_input);
- self->netif.name[0] = 'e';
- self->netif.name[1] = '0';
- netif_set_default(&self->netif);
- dns_setserver(0, &ipconfig[3]);
- dhcp_set_struct(&self->netif, &self->dhcp_struct);
- // Setting NETIF_FLAG_UP then clearing it is a workaround for dhcp_start and the
- // LWIP_DHCP_CHECK_LINK_UP option, so that the DHCP client schedules itself to
- // automatically start when the interface later goes up.
- self->netif.flags |= NETIF_FLAG_UP;
- dhcp_start(&self->netif);
- self->netif.flags &= ~NETIF_FLAG_UP;
-}
-
-void wiznet5k_poll(void) {
- wiznet5k_obj_t *self = &wiznet5k_obj;
- if (!(self->netif.flags & NETIF_FLAG_LINK_UP)) {
- return;
- }
- uint16_t len;
- while ((len = wiznet5k_recv_ethernet(self)) > 0) {
- if (self->trace_flags & TRACE_ETH_RX) {
- netutils_ethernet_trace(MP_PYTHON_PRINTER, len, self->eth_frame, NETUTILS_TRACE_NEWLINE);
- }
- struct pbuf *p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
- if (p != NULL) {
- pbuf_take(p, self->eth_frame, len);
- if (self->netif.input(p, &self->netif) != ERR_OK) {
- pbuf_free(p);
- }
- }
- }
-}
-
-/*******************************************************************************/
-// MicroPython bindings
-
-// WIZNET5K([spi, pin_cs, pin_rst])
-STATIC mp_obj_t wiznet5k_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
- // check arguments
- mp_arg_check_num(n_args, n_kw, 3, 3, false);
-
- const spi_t *spi = spi_from_mp_obj(args[0]);
- mp_hal_pin_obj_t cs = pin_find(args[1]);
- mp_hal_pin_obj_t rst = pin_find(args[2]);
-
- // Access the existing object, if it has been constructed with the same hardware interface
- if (wiznet5k_obj.base.type == (mp_obj_type_t *)&mod_network_nic_type_wiznet5k) {
- if (!(wiznet5k_obj.spi == spi && wiznet5k_obj.cs == cs && wiznet5k_obj.rst == rst
- && wiznet5k_obj.netif.flags != 0)) {
- wiznet5k_deinit();
- }
- }
-
- // Init the wiznet5k object
- wiznet5k_obj.base.type = (mp_obj_type_t *)&mod_network_nic_type_wiznet5k;
- wiznet5k_obj.cris_state = 0;
- wiznet5k_obj.spi = spi;
- wiznet5k_obj.cs = cs;
- wiznet5k_obj.rst = rst;
- wiznet5k_obj.trace_flags = 0;
-
- // Return wiznet5k object
- return MP_OBJ_FROM_PTR(&wiznet5k_obj);
-}
-
-STATIC mp_obj_t wiznet5k_regs(mp_obj_t self_in) {
- (void)self_in;
- printf("Wiz CREG:");
- for (int i = 0; i < 0x50; ++i) {
- if (i % 16 == 0) {
- printf("\n %04x:", i);
- }
- #if MICROPY_PY_NETWORK_WIZNET5K == 5200
- uint32_t reg = i;
- #else
- uint32_t reg = _W5500_IO_BASE_ | i << 8;
- #endif
- printf(" %02x", WIZCHIP_READ(reg));
- }
- for (int sn = 0; sn < 4; ++sn) {
- printf("\nWiz SREG[%d]:", sn);
- for (int i = 0; i < 0x30; ++i) {
- if (i % 16 == 0) {
- printf("\n %04x:", i);
- }
- #if MICROPY_PY_NETWORK_WIZNET5K == 5200
- uint32_t reg = WIZCHIP_SREG_ADDR(sn, i);
- #else
- uint32_t reg = _W5500_IO_BASE_ | i << 8 | WIZCHIP_SREG_BLOCK(sn) << 3;
- #endif
- printf(" %02x", WIZCHIP_READ(reg));
- }
- }
- printf("\n");
- return mp_const_none;
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(wiznet5k_regs_obj, wiznet5k_regs);
-
-STATIC mp_obj_t wiznet5k_isconnected(mp_obj_t self_in) {
- wiznet5k_obj_t *self = MP_OBJ_TO_PTR(self_in);
- return mp_obj_new_bool(
- wizphy_getphylink() == PHY_LINK_ON
- && (self->netif.flags & NETIF_FLAG_UP)
- && self->netif.ip_addr.addr != 0
- );
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(wiznet5k_isconnected_obj, wiznet5k_isconnected);
-
-STATIC mp_obj_t wiznet5k_active(size_t n_args, const mp_obj_t *args) {
- wiznet5k_obj_t *self = MP_OBJ_TO_PTR(args[0]);
- if (n_args == 1) {
- return mp_obj_new_bool(self->netif.flags & NETIF_FLAG_UP);
- } else {
- if (mp_obj_is_true(args[1])) {
- if (!(self->netif.flags & NETIF_FLAG_UP)) {
- wiznet5k_init();
- netif_set_link_up(&self->netif);
- netif_set_up(&self->netif);
- }
- } else {
- if (self->netif.flags & NETIF_FLAG_UP) {
- netif_set_down(&self->netif);
- netif_set_link_down(&self->netif);
- wiznet5k_deinit();
- }
- }
- return mp_const_none;
- }
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(wiznet5k_active_obj, 1, 2, wiznet5k_active);
-
-STATIC mp_obj_t wiznet5k_ifconfig(size_t n_args, const mp_obj_t *args) {
- wiznet5k_obj_t *self = MP_OBJ_TO_PTR(args[0]);
- return mod_network_nic_ifconfig(&self->netif, n_args - 1, args + 1);
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(wiznet5k_ifconfig_obj, 1, 2, wiznet5k_ifconfig);
-
-STATIC mp_obj_t wiznet5k_status(size_t n_args, const mp_obj_t *args) {
- wiznet5k_obj_t *self = MP_OBJ_TO_PTR(args[0]);
- (void)self;
-
- if (n_args == 1) {
- // No arguments: return link status
- if (self->netif.flags && wizphy_getphylink() == PHY_LINK_ON) {
- if ((self->netif.flags & NETIF_FLAG_UP) && self->netif.ip_addr.addr != 0) {
- return MP_OBJ_NEW_SMALL_INT(2);
- } else {
- return MP_OBJ_NEW_SMALL_INT(1);
- }
- } else {
- return MP_OBJ_NEW_SMALL_INT(0);
- }
- }
-
- mp_raise_ValueError(MP_ERROR_TEXT("unknown config param"));
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(wiznet5k_status_obj, 1, 2, wiznet5k_status);
-
-STATIC mp_obj_t wiznet5k_config(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) {
- wiznet5k_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_mac: {
- uint8_t buf[6];
- wiznet5k_get_mac_address(self, buf);
- return mp_obj_new_bytes(buf, 6);
- }
- 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_mac: {
- mp_buffer_info_t buf;
- mp_get_buffer_raise(e->value, &buf, MP_BUFFER_READ);
- if (buf.len != 6) {
- mp_raise_ValueError(NULL);
- }
- setSHAR(buf.buf);
- memcpy(self->netif.hwaddr, buf.buf, 6);
- break;
- }
- case MP_QSTR_trace: {
- self->trace_flags = mp_obj_get_int(e->value);
- break;
- }
- default:
- mp_raise_ValueError(MP_ERROR_TEXT("unknown config param"));
- }
- }
- }
-
- return mp_const_none;
- }
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_KW(wiznet5k_config_obj, 1, wiznet5k_config);
-
-STATIC mp_obj_t send_ethernet_wrapper(mp_obj_t self_in, mp_obj_t buf_in) {
- wiznet5k_obj_t *self = MP_OBJ_TO_PTR(self_in);
- mp_buffer_info_t buf;
- mp_get_buffer_raise(buf_in, &buf, MP_BUFFER_READ);
- wiznet5k_send_ethernet(self, buf.len, buf.buf);
- return mp_const_none;
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_2(send_ethernet_obj, send_ethernet_wrapper);
-
-STATIC const mp_rom_map_elem_t wiznet5k_locals_dict_table[] = {
- { MP_ROM_QSTR(MP_QSTR_regs), MP_ROM_PTR(&wiznet5k_regs_obj) },
- { MP_ROM_QSTR(MP_QSTR_isconnected), MP_ROM_PTR(&wiznet5k_isconnected_obj) },
- { MP_ROM_QSTR(MP_QSTR_active), MP_ROM_PTR(&wiznet5k_active_obj) },
- { MP_ROM_QSTR(MP_QSTR_ifconfig), MP_ROM_PTR(&wiznet5k_ifconfig_obj) },
- { MP_ROM_QSTR(MP_QSTR_status), MP_ROM_PTR(&wiznet5k_status_obj) },
- { MP_ROM_QSTR(MP_QSTR_config), MP_ROM_PTR(&wiznet5k_config_obj) },
-
- { MP_ROM_QSTR(MP_QSTR_send_ethernet), MP_ROM_PTR(&send_ethernet_obj) },
-};
-STATIC MP_DEFINE_CONST_DICT(wiznet5k_locals_dict, wiznet5k_locals_dict_table);
-
-const mp_obj_type_t mod_network_nic_type_wiznet5k = {
- { &mp_type_type },
- .name = MP_QSTR_WIZNET5K,
- .make_new = wiznet5k_make_new,
- .locals_dict = (mp_obj_dict_t *)&wiznet5k_locals_dict,
-};
-
-#endif // MICROPY_PY_NETWORK_WIZNET5K && MICROPY_PY_LWIP
diff --git a/ports/stm32/pendsv.h b/ports/stm32/pendsv.h
index 0733d355d311..f97581e99a30 100644
--- a/ports/stm32/pendsv.h
+++ b/ports/stm32/pendsv.h
@@ -35,6 +35,9 @@ enum {
#if MICROPY_PY_NETWORK_CYW43
PENDSV_DISPATCH_CYW43,
#endif
+ #if MICROPY_PY_NETWORK_WIZNET5K
+ PENDSV_DISPATCH_WIZNET,
+ #endif
#endif
#if MICROPY_PY_BLUETOOTH && !MICROPY_PY_BLUETOOTH_USE_SYNC_EVENTS
PENDSV_DISPATCH_BLUETOOTH_HCI,
diff --git a/ports/stm32/pin.c b/ports/stm32/pin.c
index b490a09b7faa..8503f3dbe0de 100644
--- a/ports/stm32/pin.c
+++ b/ports/stm32/pin.c
@@ -24,10 +24,6 @@
* THE SOFTWARE.
*/
-#include
-#include
-#include
-
#include "py/runtime.h"
#include "py/mphal.h"
#include "extmod/virtpin.h"
@@ -102,15 +98,17 @@ void pin_init0(void) {
// C API used to convert a user-supplied pin name into an ordinal pin number.
const pin_obj_t *pin_find(mp_obj_t user_obj) {
+ const mp_print_t *print = &mp_plat_print;
+
const pin_obj_t *pin_obj;
// If a pin was provided, then use it
if (mp_obj_is_type(user_obj, &pin_type)) {
pin_obj = MP_OBJ_TO_PTR(user_obj);
if (pin_class_debug) {
- printf("Pin map passed pin ");
+ mp_printf(print, "Pin map passed pin ");
mp_obj_print(MP_OBJ_FROM_PTR(pin_obj), PRINT_STR);
- printf("\n");
+ mp_printf(print, "\n");
}
return pin_obj;
}
@@ -122,11 +120,11 @@ const pin_obj_t *pin_find(mp_obj_t user_obj) {
mp_raise_ValueError(MP_ERROR_TEXT("Pin.mapper didn't return a Pin object"));
}
if (pin_class_debug) {
- printf("Pin.mapper maps ");
+ mp_printf(print, "Pin.mapper maps ");
mp_obj_print(user_obj, PRINT_REPR);
- printf(" to ");
+ mp_printf(print, " to ");
mp_obj_print(o, PRINT_STR);
- printf("\n");
+ mp_printf(print, "\n");
}
return MP_OBJ_TO_PTR(o);
}
@@ -140,11 +138,11 @@ const pin_obj_t *pin_find(mp_obj_t user_obj) {
if (elem != NULL && elem->value != MP_OBJ_NULL) {
mp_obj_t o = elem->value;
if (pin_class_debug) {
- printf("Pin.map_dict maps ");
+ mp_printf(print, "Pin.map_dict maps ");
mp_obj_print(user_obj, PRINT_REPR);
- printf(" to ");
+ mp_printf(print, " to ");
mp_obj_print(o, PRINT_STR);
- printf("\n");
+ mp_printf(print, "\n");
}
return MP_OBJ_TO_PTR(o);
}
@@ -154,11 +152,11 @@ const pin_obj_t *pin_find(mp_obj_t user_obj) {
pin_obj = pin_find_named_pin(&pin_board_pins_locals_dict, user_obj);
if (pin_obj) {
if (pin_class_debug) {
- printf("Pin.board maps ");
+ mp_printf(print, "Pin.board maps ");
mp_obj_print(user_obj, PRINT_REPR);
- printf(" to ");
+ mp_printf(print, " to ");
mp_obj_print(MP_OBJ_FROM_PTR(pin_obj), PRINT_STR);
- printf("\n");
+ mp_printf(print, "\n");
}
return pin_obj;
}
@@ -167,11 +165,11 @@ const pin_obj_t *pin_find(mp_obj_t user_obj) {
pin_obj = pin_find_named_pin(&pin_cpu_pins_locals_dict, user_obj);
if (pin_obj) {
if (pin_class_debug) {
- printf("Pin.cpu maps ");
+ mp_printf(print, "Pin.cpu maps ");
mp_obj_print(user_obj, PRINT_REPR);
- printf(" to ");
+ mp_printf(print, " to ");
mp_obj_print(MP_OBJ_FROM_PTR(pin_obj), PRINT_STR);
- printf("\n");
+ mp_printf(print, "\n");
}
return pin_obj;
}
@@ -592,15 +590,16 @@ STATIC const mp_pin_p_t pin_pin_p = {
.ioctl = pin_ioctl,
};
-const mp_obj_type_t pin_type = {
- { &mp_type_type },
- .name = MP_QSTR_Pin,
- .print = pin_print,
- .make_new = mp_pin_make_new,
- .call = pin_call,
- .protocol = &pin_pin_p,
- .locals_dict = (mp_obj_dict_t *)&pin_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ pin_type,
+ MP_QSTR_Pin,
+ MP_TYPE_FLAG_NONE,
+ make_new, mp_pin_make_new,
+ print, pin_print,
+ call, pin_call,
+ protocol, &pin_pin_p,
+ locals_dict, &pin_locals_dict
+ );
/// \moduleref pyb
/// \class PinAF - Pin Alternate Functions
@@ -669,9 +668,13 @@ STATIC const mp_rom_map_elem_t pin_af_locals_dict_table[] = {
};
STATIC MP_DEFINE_CONST_DICT(pin_af_locals_dict, pin_af_locals_dict_table);
-const mp_obj_type_t pin_af_type = {
- { &mp_type_type },
- .name = MP_QSTR_PinAF,
- .print = pin_af_obj_print,
- .locals_dict = (mp_obj_dict_t *)&pin_af_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ pin_af_type,
+ MP_QSTR_PinAF,
+ MP_TYPE_FLAG_NONE,
+ print, pin_af_obj_print,
+ locals_dict, &pin_af_locals_dict
+ );
+
+MP_REGISTER_ROOT_POINTER(mp_obj_t pin_class_mapper);
+MP_REGISTER_ROOT_POINTER(mp_obj_t pin_class_map_dict);
diff --git a/ports/stm32/pin_named_pins.c b/ports/stm32/pin_named_pins.c
index 3a8e0f9fce9d..8eeb4ed32b11 100644
--- a/ports/stm32/pin_named_pins.c
+++ b/ports/stm32/pin_named_pins.c
@@ -31,17 +31,19 @@
#include "py/mphal.h"
#include "pin.h"
-const mp_obj_type_t pin_cpu_pins_obj_type = {
- { &mp_type_type },
- .name = MP_QSTR_cpu,
- .locals_dict = (mp_obj_dict_t *)&pin_cpu_pins_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ pin_cpu_pins_obj_type,
+ MP_QSTR_cpu,
+ MP_TYPE_FLAG_NONE,
+ locals_dict, &pin_cpu_pins_locals_dict
+ );
-const mp_obj_type_t pin_board_pins_obj_type = {
- { &mp_type_type },
- .name = MP_QSTR_board,
- .locals_dict = (mp_obj_dict_t *)&pin_board_pins_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ pin_board_pins_obj_type,
+ MP_QSTR_board,
+ MP_TYPE_FLAG_NONE,
+ locals_dict, &pin_board_pins_locals_dict
+ );
const pin_obj_t *pin_find_named_pin(const mp_obj_dict_t *named_pins, mp_obj_t name) {
const mp_map_t *named_map = &named_pins->map;
diff --git a/ports/stm32/powerctrl.c b/ports/stm32/powerctrl.c
index 3b4a2d86e1e1..0ab80b487a67 100644
--- a/ports/stm32/powerctrl.c
+++ b/ports/stm32/powerctrl.c
@@ -29,14 +29,13 @@
#include "powerctrl.h"
#include "rtc.h"
#include "genhdr/pllfreqtable.h"
+#include "extmod/modbluetooth.h"
#if defined(STM32H7)
#define RCC_SR RSR
-#if defined(STM32H743xx) || defined(STM32H750xx)
-#define RCC_SR_SFTRSTF RCC_RSR_SFTRSTF
-#elif defined(STM32H747xx)
+#if defined(STM32H747xx)
#define RCC_SR_SFTRSTF RCC_RSR_SFT2RSTF
-#elif defined(STM32H7A3xx) || defined(STM32H7A3xxQ) || defined(STM32H7B3xx) || defined(STM32H7B3xxQ)
+#else
#define RCC_SR_SFTRSTF RCC_RSR_SFTRSTF
#endif
#define RCC_SR_RMVF RCC_RSR_RMVF
@@ -47,6 +46,8 @@
defined(STM32H7B3xx) || defined(STM32H7B3xxQ)
// TODO
#define POWERCTRL_GET_VOLTAGE_SCALING() PWR_REGULATOR_VOLTAGE_SCALE0
+#elif defined(STM32H723xx)
+#define POWERCTRL_GET_VOLTAGE_SCALING() LL_PWR_GetRegulVoltageScaling()
#else
#define POWERCTRL_GET_VOLTAGE_SCALING() \
(((PWR->CSR1 & PWR_CSR1_ACTVOS) && (SYSCFG->PWRCR & SYSCFG_PWRCR_ODEN)) ? \
@@ -78,7 +79,7 @@
// Location in RAM of bootloader state (just after the top of the stack).
// STM32H7 has ECC and writes to RAM must be 64-bit so they are fully committed
// to actual SRAM before a system reset occurs.
-#define BL_STATE_PTR ((uint64_t *)&_estack)
+#define BL_STATE_PTR ((uint64_t *)&_bl_state)
#define BL_STATE_KEY (0x5a5)
#define BL_STATE_KEY_MASK (0xfff)
#define BL_STATE_KEY_SHIFT (32)
@@ -87,7 +88,7 @@
#define BL_STATE_GET_REG(s) ((s) & 0xffffffff)
#define BL_STATE_GET_KEY(s) (((s) >> BL_STATE_KEY_SHIFT) & BL_STATE_KEY_MASK)
#define BL_STATE_GET_ADDR(s) (((s) >> BL_STATE_KEY_SHIFT) & ~BL_STATE_KEY_MASK)
-extern uint64_t _estack[];
+extern uint64_t _bl_state[];
#endif
static inline void powerctrl_disable_hsi_if_unused(void) {
@@ -143,7 +144,7 @@ void powerctrl_check_enter_bootloader(void) {
if (BL_STATE_GET_KEY(bl_state) == BL_STATE_KEY && (RCC->RCC_SR & RCC_SR_SFTRSTF)) {
// Reset by NVIC_SystemReset with bootloader data set -> branch to bootloader
RCC->RCC_SR = RCC_SR_RMVF;
- #if defined(STM32F0) || defined(STM32F4) || defined(STM32G0) || defined(STM32G4) || defined(STM32L0) || defined(STM32L4) || defined(STM32WB)
+ #if defined(STM32F0) || defined(STM32F4) || defined(STM32G0) || defined(STM32G4) || defined(STM32L0) || defined(STM32L1) || defined(STM32L4) || defined(STM32WB)
__HAL_SYSCFG_REMAPMEMORY_SYSTEMFLASH();
#endif
branch_to_bootloader(BL_STATE_GET_REG(bl_state), BL_STATE_GET_ADDR(bl_state));
@@ -286,7 +287,7 @@ int powerctrl_rcc_clock_config_pll(RCC_ClkInitTypeDef *rcc_init, uint32_t sysclk
#endif
-#if !defined(STM32F0) && !defined(STM32G0) && !defined(STM32L0) && !defined(STM32L4)
+#if !defined(STM32F0) && !defined(STM32G0) && !defined(STM32L0) && !defined(STM32L1) && !defined(STM32L4)
STATIC uint32_t calc_ahb_div(uint32_t wanted_div) {
#if defined(STM32H7)
@@ -676,9 +677,65 @@ int powerctrl_set_sysclk(uint32_t sysclk, uint32_t ahb, uint32_t apb1, uint32_t
return 0;
}
-#endif
+#if defined(STM32WB)
+
+static void powerctrl_switch_on_HSI(void) {
+ LL_RCC_HSI_Enable();
+ while (!LL_RCC_HSI_IsReady()) {
+ }
+ LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_HSI);
+ LL_RCC_SetSMPSClockSource(LL_RCC_SMPS_CLKSOURCE_HSI);
+ while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_HSI) {
+ }
+ return;
+}
+
+static void powerctrl_low_power_prep_wb55() {
+ // See WB55 specific documentation in AN5289 Rev 6, and in particular, Figure 6.
+ while (LL_HSEM_1StepLock(HSEM, CFG_HW_RCC_SEMID)) {
+ }
+ if (!LL_HSEM_1StepLock(HSEM, CFG_HW_ENTRY_STOP_MODE_SEMID)) {
+ if (LL_PWR_IsActiveFlag_C2DS() || LL_PWR_IsActiveFlag_C2SB()) {
+ // Release ENTRY_STOP_MODE semaphore
+ LL_HSEM_ReleaseLock(HSEM, CFG_HW_ENTRY_STOP_MODE_SEMID, 0);
+
+ powerctrl_switch_on_HSI();
+ }
+ } else {
+ powerctrl_switch_on_HSI();
+ }
+ // Release RCC semaphore
+ LL_HSEM_ReleaseLock(HSEM, CFG_HW_RCC_SEMID, 0);
+}
+
+static void powerctrl_low_power_exit_wb55() {
+ // Ensure the HSE/HSI clock configuration is correct so core2 can wake properly again.
+ // See WB55 specific documentation in AN5289 Rev 6, and in particular, Figure 7.
+ LL_HSEM_ReleaseLock(HSEM, CFG_HW_ENTRY_STOP_MODE_SEMID, 0);
+ // Acquire RCC semaphore before adjusting clocks.
+ while (LL_HSEM_1StepLock(HSEM, CFG_HW_RCC_SEMID)) {
+ }
+
+ if (LL_RCC_GetSysClkSource() == LL_RCC_SYS_CLKSOURCE_STATUS_HSI) {
+ // Restore the clock configuration of the application
+ LL_RCC_HSE_Enable();
+ __HAL_FLASH_SET_LATENCY(FLASH_LATENCY_1);
+ while (!LL_RCC_HSE_IsReady()) {
+ }
+ LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_HSE);
+ while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_HSE) {
+ }
+ }
+
+ // Release RCC semaphore
+ LL_HSEM_ReleaseLock(HSEM, CFG_HW_RCC_SEMID, 0);
+}
-#endif // !defined(STM32F0) && !defined(STM32L0) && !defined(STM32L4)
+#endif // defined(STM32WB)
+
+#endif // defined(STM32WB) || defined(STM32WL)
+
+#endif // !defined(STM32F0) && !defined(STM32G0) && !defined(STM32L0) && !defined(STM32L1) && !defined(STM32L4)
void powerctrl_enter_stop_mode(void) {
// Disable IRQs so that the IRQ that wakes the device from stop mode is not
@@ -708,7 +765,7 @@ void powerctrl_enter_stop_mode(void) {
__HAL_RCC_WAKEUPSTOP_CLK_CONFIG(RCC_STOP_WAKEUPCLOCK_MSI);
#endif
- #if !defined(STM32F0) && !defined(STM32G0) && !defined(STM32G4) && !defined(STM32L0) && !defined(STM32L4) && !defined(STM32WB) && !defined(STM32WL)
+ #if !defined(STM32F0) && !defined(STM32G0) && !defined(STM32G4) && !defined(STM32L0) && !defined(STM32L1) && !defined(STM32L4) && !defined(STM32WB) && !defined(STM32WL)
// takes longer to wake but reduces stop current
HAL_PWREx_EnableFlashPowerDown();
#endif
@@ -729,6 +786,10 @@ void powerctrl_enter_stop_mode(void) {
}
#endif
+ #if defined(STM32WB)
+ powerctrl_low_power_prep_wb55();
+ #endif
+
#if defined(STM32F7)
HAL_PWR_EnterSTOPMode((PWR_CR1_LPDS | PWR_CR1_LPUDS | PWR_CR1_FPDS | PWR_CR1_UDEN), PWR_STOPENTRY_WFI);
#else
@@ -762,6 +823,10 @@ void powerctrl_enter_stop_mode(void) {
}
#endif
+ #if defined(STM32WB)
+ powerctrl_low_power_exit_wb55();
+ #endif
+
#if !defined(STM32L4)
// enable clock
__HAL_RCC_HSE_CONFIG(MICROPY_HW_RCC_HSE_STATE);
@@ -875,6 +940,22 @@ void powerctrl_enter_standby_mode(void) {
MICROPY_BOARD_ENTER_STANDBY
#endif
+ #if defined(STM32H7)
+ // Note: According to ST reference manual, RM0399, Rev 3, Section 7.7.10,
+ // before entering Standby mode, voltage scale VOS0 must not be active.
+ uint32_t vscaling = POWERCTRL_GET_VOLTAGE_SCALING();
+ if (vscaling == PWR_REGULATOR_VOLTAGE_SCALE0) {
+ __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE3);
+ // Wait for PWR_FLAG_VOSRDY
+ while (!__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY)) {
+ }
+ }
+ #endif
+
+ #if defined(STM32WB) && MICROPY_PY_BLUETOOTH
+ mp_bluetooth_deinit();
+ #endif
+
// We need to clear the PWR wake-up-flag before entering standby, since
// the flag may have been set by a previous wake-up event. Furthermore,
// we need to disable the wake-up sources while clearing this flag, so
@@ -926,8 +1007,16 @@ void powerctrl_enter_standby_mode(void) {
// Restore EWUP state
PWR->CSR2 |= csr2_ewup;
#elif defined(STM32H7)
- EXTI_D1->PR1 = 0x3fffff;
- PWR->WKUPCR |= PWR_WAKEUP_FLAG1 | PWR_WAKEUP_FLAG2 | PWR_WAKEUP_FLAG3 | PWR_WAKEUP_FLAG4 | PWR_WAKEUP_FLAG5 | PWR_WAKEUP_FLAG6;
+ // Clear and mask D1 EXTIs.
+ EXTI_D1->PR1 = 0x3fffffu;
+ EXTI_D1->IMR1 &= ~(0xFFFFu); // 16 lines
+ #if defined(EXTI_D2)
+ // Clear and mask D2 EXTIs.
+ EXTI_D2->PR1 = 0x3fffffu;
+ EXTI_D2->IMR1 &= ~(0xFFFFu); // 16 lines
+ #endif
+ // Clear all wake-up flags.
+ PWR->WKUPCR |= PWR_WAKEUP_FLAG_ALL;
#elif defined(STM32G0) || defined(STM32G4) || defined(STM32L4) || defined(STM32WB)
// clear all wake-up flags
PWR->SCR |= PWR_SCR_CWUF5 | PWR_SCR_CWUF4 | PWR_SCR_CWUF3 | PWR_SCR_CWUF2 | PWR_SCR_CWUF1;
@@ -952,6 +1041,15 @@ void powerctrl_enter_standby_mode(void) {
PWR->CSR1 |= PWR_CSR1_EIWUP;
#endif
+ #if defined(NDEBUG) && defined(DBGMCU)
+ // Disable Debug MCU.
+ DBGMCU->CR = 0;
+ #endif
+
+ #if defined(STM32WB)
+ powerctrl_low_power_prep_wb55();
+ #endif
+
// enter standby mode
HAL_PWR_EnterSTANDBYMode();
// we never return; MCU is reset on exit from standby
diff --git a/ports/stm32/powerctrl.h b/ports/stm32/powerctrl.h
index eedc448b2b8a..e9adc529653f 100644
--- a/ports/stm32/powerctrl.h
+++ b/ports/stm32/powerctrl.h
@@ -29,6 +29,14 @@
#include
#include
+#if defined(STM32WB)
+void stm32_system_init(void);
+#else
+static inline void stm32_system_init(void) {
+ SystemInit();
+}
+#endif
+
void SystemClock_Config(void);
NORETURN void powerctrl_mcu_reset(void);
diff --git a/ports/stm32/powerctrlboot.c b/ports/stm32/powerctrlboot.c
index 555457c582e2..e970b81a9fcc 100644
--- a/ports/stm32/powerctrlboot.c
+++ b/ports/stm32/powerctrlboot.c
@@ -28,6 +28,24 @@
#include "irq.h"
#include "powerctrl.h"
+#if defined(STM32WB)
+void stm32_system_init(void) {
+ if (RCC->CR == 0x00000560 && RCC->CFGR == 0x00070005) {
+ // Wake from STANDBY with HSI enabled as system clock. The second core likely
+ // also needs HSI to remain enabled, so do as little as possible here.
+ #if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
+ // set CP10 and CP11 Full Access.
+ SCB->CPACR |= (3 << (10 * 2)) | (3 << (11 * 2));
+ #endif
+ // Disable all interrupts.
+ RCC->CIER = 0x00000000;
+ } else {
+ // Other start-up (eg POR), use standard system init code.
+ SystemInit();
+ }
+}
+#endif
+
void powerctrl_config_systick(void) {
// Configure SYSTICK to run at 1kHz (1ms interval)
SysTick->CTRL |= SYSTICK_CLKSOURCE_HCLK;
@@ -155,15 +173,14 @@ void SystemClock_Config(void) {
#if MICROPY_HW_ENABLE_RNG || MICROPY_HW_ENABLE_USB
// Enable the 48MHz internal oscillator
- RCC->CRRCR |= RCC_CRRCR_HSI48ON;
- RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN;
- SYSCFG->CFGR3 |= SYSCFG_CFGR3_ENREF_HSI48;
- while (!(RCC->CRRCR & RCC_CRRCR_HSI48RDY)) {
+ RCC->CR |= RCC_CR_HSI48ON;
+ RCC->APBENR2 |= RCC_APBENR2_SYSCFGEN;
+ while (!(RCC->CR & RCC_CR_HSI48RDY)) {
// Wait for HSI48 to be ready
}
- // Select RC48 as HSI48 for USB and RNG
- RCC->CCIPR |= RCC_CCIPR_HSI48SEL;
+ // Select HSI48 for USB
+ RCC->CCIPR2 &= ~(3 << RCC_CCIPR2_USBSEL_Pos);
#if MICROPY_HW_ENABLE_USB
// Synchronise HSI48 with 1kHz USB SoF
@@ -228,23 +245,90 @@ void SystemClock_Config(void) {
#endif
}
-#elif defined(STM32WB)
+#elif defined(STM32L1)
+
+void SystemClock_Config(void) {
+ // Enable power control peripheral
+ __HAL_RCC_PWR_CLK_ENABLE();
-#include "stm32wbxx_ll_hsem.h"
+ // Set power voltage scaling
+ __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
+
+ // Enable the FLASH 64-bit access
+ FLASH->ACR = FLASH_ACR_ACC64;
+ // Set flash latency to 1 because SYSCLK > 16MHz
+ FLASH->ACR |= MICROPY_HW_FLASH_LATENCY;
-// This semaphore protected access to the CLK48 configuration.
-// CPU1 should hold this semaphore while the USB peripheral is in use.
-// See AN5289 and https://github.com/micropython/micropython/issues/6316.
-#define CLK48_SEMID (5)
+ #if MICROPY_HW_CLK_USE_HSI
+ // Enable the 16MHz internal oscillator
+ RCC->CR |= RCC_CR_HSION;
+ while (!(RCC->CR & RCC_CR_HSIRDY)) {
+ }
+ RCC->CFGR = RCC_CFGR_PLLSRC_HSI;
+ #else
+ // Enable the 8MHz external oscillator
+ RCC->CR |= RCC_CR_HSEBYP;
+ RCC->CR |= RCC_CR_HSEON;
+ while (!(RCC->CR & RCC_CR_HSERDY)) {
+ }
+ RCC->CFGR = RCC_CFGR_PLLSRC_HSE;
+ #endif
+ // Use HSI16 and the PLL to get a 32MHz SYSCLK
+ RCC->CFGR |= MICROPY_HW_CLK_PLLMUL | MICROPY_HW_CLK_PLLDIV;
+ RCC->CR |= RCC_CR_PLLON;
+ while (!(RCC->CR & RCC_CR_PLLRDY)) {
+ // Wait for PLL to lock
+ }
+ RCC->CFGR |= RCC_CFGR_SW_PLL;
+
+ while ((RCC->CFGR & RCC_CFGR_SWS_Msk) != RCC_CFGR_SWS_PLL) {
+ // Wait for SYSCLK source to change
+ }
+
+ SystemCoreClockUpdate();
+ powerctrl_config_systick();
+
+ #if MICROPY_HW_ENABLE_USB
+ // Enable the 48MHz internal oscillator
+ RCC->CRRCR |= RCC_CRRCR_HSI48ON;
+ RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN;
+ SYSCFG->CFGR3 |= SYSCFG_CFGR3_ENREF_HSI48;
+ while (!(RCC->CRRCR & RCC_CRRCR_HSI48RDY)) {
+ // Wait for HSI48 to be ready
+ }
+
+ // Select RC48 as HSI48 for USB and RNG
+ RCC->CCIPR |= RCC_CCIPR_HSI48SEL;
+
+ // Synchronise HSI48 with 1kHz USB SoF
+ __HAL_RCC_CRS_CLK_ENABLE();
+ CRS->CR = 0x20 << CRS_CR_TRIM_Pos;
+ CRS->CFGR = 2 << CRS_CFGR_SYNCSRC_Pos | 0x22 << CRS_CFGR_FELIM_Pos
+ | __HAL_RCC_CRS_RELOADVALUE_CALCULATE(48000000, 1000) << CRS_CFGR_RELOAD_Pos;
+ #endif
+
+ // Disable the Debug Module in low-power mode due to prevent
+ // unexpected HardFault after __WFI().
+ #if !defined(NDEBUG)
+ DBGMCU->CR &= ~(DBGMCU_CR_DBG_SLEEP | DBGMCU_CR_DBG_STOP | DBGMCU_CR_DBG_STANDBY);
+ #endif
+}
+#elif defined(STM32WB)
void SystemClock_Config(void) {
+ while (LL_HSEM_1StepLock(HSEM, CFG_HW_RCC_SEMID)) {
+ }
+
// Enable the 32MHz external oscillator
RCC->CR |= RCC_CR_HSEON;
while (!(RCC->CR & RCC_CR_HSERDY)) {
}
// Prevent CPU2 from disabling CLK48.
- while (LL_HSEM_1StepLock(HSEM, CLK48_SEMID)) {
+ // This semaphore protected access to the CLK48 configuration.
+ // CPU1 should hold this semaphore while the USB peripheral is in use.
+ // See AN5289 and https://github.com/micropython/micropython/issues/6316.
+ while (LL_HSEM_1StepLock(HSEM, CFG_HW_CLK48_CONFIG_SEMID)) {
}
// Use HSE and the PLL to get a 64MHz SYSCLK
@@ -281,6 +365,9 @@ void SystemClock_Config(void) {
SystemCoreClockUpdate();
powerctrl_config_systick();
+
+ // Release RCC semaphore
+ LL_HSEM_ReleaseLock(HSEM, CFG_HW_RCC_SEMID, 0);
}
#elif defined(STM32WL)
diff --git a/ports/stm32/pyb_can.c b/ports/stm32/pyb_can.c
index 3fa0f6baea0d..69e807c79dfd 100644
--- a/ports/stm32/pyb_can.c
+++ b/ports/stm32/pyb_can.c
@@ -1072,13 +1072,16 @@ STATIC const mp_stream_p_t can_stream_p = {
.is_text = false,
};
-const mp_obj_type_t pyb_can_type = {
- { &mp_type_type },
- .name = MP_QSTR_CAN,
- .print = pyb_can_print,
- .make_new = pyb_can_make_new,
- .protocol = &can_stream_p,
- .locals_dict = (mp_obj_dict_t *)&pyb_can_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ pyb_can_type,
+ MP_QSTR_CAN,
+ MP_TYPE_FLAG_NONE,
+ make_new, pyb_can_make_new,
+ print, pyb_can_print,
+ protocol, &can_stream_p,
+ locals_dict, &pyb_can_locals_dict
+ );
+
+MP_REGISTER_ROOT_POINTER(struct _pyb_can_obj_t *pyb_can_obj_all[MICROPY_HW_MAX_CAN]);
#endif // MICROPY_HW_ENABLE_CAN
diff --git a/ports/stm32/pyb_i2c.c b/ports/stm32/pyb_i2c.c
index 2ca0793c189e..6bf04aa1b167 100644
--- a/ports/stm32/pyb_i2c.c
+++ b/ports/stm32/pyb_i2c.c
@@ -24,10 +24,8 @@
* THE SOFTWARE.
*/
-#include
-#include
-
#include "py/runtime.h"
+#include "py/mperrno.h"
#include "py/mphal.h"
#include "irq.h"
#include "pin.h"
@@ -137,7 +135,7 @@ const pyb_i2c_obj_t pyb_i2c_obj[] = {
#define PYB_I2C_TIMINGR (1)
-#if defined(STM32F745xx) || defined(STM32F746xx)
+#if defined(STM32F745xx) || defined(STM32F746xx) || defined(STM32F756xx)
// The value 0x40912732 was obtained from the DISCOVERY_I2Cx_TIMING constant
// defined in the STM32F7Cube file Drivers/BSP/STM32F746G-Discovery/stm32f7456g_discovery.h
@@ -208,11 +206,14 @@ const pyb_i2c_obj_t pyb_i2c_obj[] = {
#elif defined(STM32L4)
-// The value 0x90112626 was obtained from the DISCOVERY_I2C1_TIMING constant
-// defined in the STM32L4Cube file Drivers/BSP/STM32L476G-Discovery/stm32l476g_discovery.h
-#define MICROPY_HW_I2C_BAUDRATE_TIMING {{PYB_I2C_SPEED_STANDARD, 0x90112626}}
-#define MICROPY_HW_I2C_BAUDRATE_DEFAULT (PYB_I2C_SPEED_STANDARD)
-#define MICROPY_HW_I2C_BAUDRATE_MAX (PYB_I2C_SPEED_STANDARD)
+// generated using CubeMX
+#define MICROPY_HW_I2C_BAUDRATE_TIMING { \
+ {PYB_I2C_SPEED_STANDARD, 0x10909CEC}, \
+ {PYB_I2C_SPEED_FULL, 0x00702991}, \
+ {PYB_I2C_SPEED_FAST, 0x00300F33}, \
+}
+#define MICROPY_HW_I2C_BAUDRATE_DEFAULT (PYB_I2C_SPEED_FULL)
+#define MICROPY_HW_I2C_BAUDRATE_MAX (PYB_I2C_SPEED_FAST)
#else
#error "no I2C timings for this MCU"
@@ -287,7 +288,7 @@ void i2c_init0(void) {
#endif
}
-void pyb_i2c_init(I2C_HandleTypeDef *i2c) {
+int pyb_i2c_init(I2C_HandleTypeDef *i2c) {
int i2c_unit;
const pin_obj_t *scl_pin;
const pin_obj_t *sda_pin;
@@ -323,7 +324,7 @@ void pyb_i2c_init(I2C_HandleTypeDef *i2c) {
#endif
} else {
// I2C does not exist for this board (shouldn't get here, should be checked by caller)
- return;
+ return -MP_EINVAL;
}
// init the GPIO lines
@@ -335,10 +336,7 @@ void pyb_i2c_init(I2C_HandleTypeDef *i2c) {
// init the I2C device
if (HAL_I2C_Init(i2c) != HAL_OK) {
// init error
- // TODO should raise an exception, but this function is not necessarily going to be
- // called via Python, so may not be properly wrapped in an NLR handler
- printf("OSError: HAL_I2C_Init failed\n");
- return;
+ return -MP_EIO;
}
// invalidate the DMA channels so they are initialised on first use
@@ -368,6 +366,8 @@ void pyb_i2c_init(I2C_HandleTypeDef *i2c) {
HAL_NVIC_EnableIRQ(I2C4_ER_IRQn);
#endif
}
+
+ return 0; // success
}
void i2c_deinit(I2C_HandleTypeDef *i2c) {
@@ -408,7 +408,7 @@ void i2c_deinit(I2C_HandleTypeDef *i2c) {
}
}
-void pyb_i2c_init_freq(const pyb_i2c_obj_t *self, mp_int_t freq) {
+int pyb_i2c_init_freq(const pyb_i2c_obj_t *self, mp_int_t freq) {
I2C_InitTypeDef *init = &self->i2c->Init;
init->AddressingMode = I2C_ADDRESSINGMODE_7BIT;
@@ -425,7 +425,7 @@ void pyb_i2c_init_freq(const pyb_i2c_obj_t *self, mp_int_t freq) {
// init the I2C bus
i2c_deinit(self->i2c);
- pyb_i2c_init(self->i2c);
+ return pyb_i2c_init(self->i2c);
}
STATIC void i2c_reset_after_error(I2C_HandleTypeDef *i2c) {
@@ -472,7 +472,29 @@ void i2c_ev_irq_handler(mp_uint_t i2c_id) {
#if defined(STM32F4)
- if (hi2c->Instance->SR1 & I2C_FLAG_BTF && hi2c->State == HAL_I2C_STATE_BUSY_TX) {
+ if (hi2c->Instance->SR1 & I2C_FLAG_SB) {
+ if (hi2c->State == HAL_I2C_STATE_BUSY_TX) {
+ hi2c->Instance->DR = I2C_7BIT_ADD_WRITE(hi2c->Devaddress);
+ } else {
+ hi2c->Instance->DR = I2C_7BIT_ADD_READ(hi2c->Devaddress);
+ }
+ hi2c->Instance->CR2 |= I2C_CR2_DMAEN;
+ } else if (hi2c->Instance->SR1 & I2C_FLAG_ADDR) {
+ __IO uint32_t tmp_sr2;
+ if (hi2c->State == HAL_I2C_STATE_BUSY_RX) {
+ if (hi2c->XferCount == 1U) {
+ hi2c->Instance->CR1 &= ~I2C_CR1_ACK;
+ } else {
+ if (hi2c->XferCount == 2U) {
+ hi2c->Instance->CR1 &= ~I2C_CR1_ACK;
+ hi2c->Instance->CR1 |= I2C_CR1_POS;
+ }
+ hi2c->Instance->CR2 |= I2C_CR2_LAST;
+ }
+ }
+ tmp_sr2 = hi2c->Instance->SR2;
+ UNUSED(tmp_sr2);
+ } else if (hi2c->Instance->SR1 & I2C_FLAG_BTF && hi2c->State == HAL_I2C_STATE_BUSY_TX) {
if (hi2c->XferCount != 0U) {
hi2c->Instance->DR = *hi2c->pBuffPtr++;
hi2c->XferCount--;
@@ -679,7 +701,10 @@ STATIC mp_obj_t pyb_i2c_init_helper(const pyb_i2c_obj_t *self, size_t n_args, co
// init the I2C bus
i2c_deinit(self->i2c);
- pyb_i2c_init(self->i2c);
+ int ret = pyb_i2c_init(self->i2c);
+ if (ret != 0) {
+ mp_raise_OSError(-ret);
+ }
return mp_const_none;
}
@@ -926,7 +951,7 @@ STATIC mp_obj_t pyb_i2c_recv(size_t n_args, const mp_obj_t *pos_args, mp_map_t *
if (o_ret != MP_OBJ_NULL) {
return o_ret;
} else {
- return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
+ return mp_obj_new_bytes_from_vstr(&vstr);
}
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_i2c_recv_obj, 1, pyb_i2c_recv);
@@ -1002,7 +1027,7 @@ STATIC mp_obj_t pyb_i2c_mem_read(size_t n_args, const mp_obj_t *pos_args, mp_map
if (o_ret != MP_OBJ_NULL) {
return o_ret;
} else {
- return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
+ return mp_obj_new_bytes_from_vstr(&vstr);
}
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_i2c_mem_read_obj, 1, pyb_i2c_mem_read);
@@ -1094,12 +1119,13 @@ STATIC const mp_rom_map_elem_t pyb_i2c_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(pyb_i2c_locals_dict, pyb_i2c_locals_dict_table);
-const mp_obj_type_t pyb_i2c_type = {
- { &mp_type_type },
- .name = MP_QSTR_I2C,
- .print = pyb_i2c_print,
- .make_new = pyb_i2c_make_new,
- .locals_dict = (mp_obj_dict_t *)&pyb_i2c_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ pyb_i2c_type,
+ MP_QSTR_I2C,
+ MP_TYPE_FLAG_NONE,
+ make_new, pyb_i2c_make_new,
+ print, pyb_i2c_print,
+ locals_dict, &pyb_i2c_locals_dict
+ );
#endif // MICROPY_PY_PYB_LEGACY && MICROPY_HW_ENABLE_HW_I2C
diff --git a/ports/stm32/pyb_spi.c b/ports/stm32/pyb_spi.c
index abb7ba41db0d..a612f6950545 100644
--- a/ports/stm32/pyb_spi.c
+++ b/ports/stm32/pyb_spi.c
@@ -112,7 +112,10 @@ STATIC mp_obj_t pyb_spi_init_helper(const pyb_spi_obj_t *self, size_t n_args, co
}
// init the SPI bus
- spi_init(self->spi, init->NSS != SPI_NSS_SOFT);
+ int ret = spi_init(self->spi, init->NSS != SPI_NSS_SOFT);
+ if (ret != 0) {
+ mp_raise_OSError(-ret);
+ }
return mp_const_none;
}
@@ -229,7 +232,7 @@ STATIC mp_obj_t pyb_spi_recv(size_t n_args, const mp_obj_t *pos_args, mp_map_t *
if (o_ret != MP_OBJ_NULL) {
return o_ret;
} else {
- return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
+ return mp_obj_new_bytes_from_vstr(&vstr);
}
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_spi_recv_obj, 1, pyb_spi_recv);
@@ -298,7 +301,7 @@ STATIC mp_obj_t pyb_spi_send_recv(size_t n_args, const mp_obj_t *pos_args, mp_ma
if (o_ret != MP_OBJ_NULL) {
return o_ret;
} else {
- return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr_recv);
+ return mp_obj_new_bytes_from_vstr(&vstr_recv);
}
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_spi_send_recv_obj, 1, pyb_spi_send_recv);
@@ -350,11 +353,12 @@ STATIC const mp_machine_spi_p_t pyb_spi_p = {
.transfer = spi_transfer_machine,
};
-const mp_obj_type_t pyb_spi_type = {
- { &mp_type_type },
- .name = MP_QSTR_SPI,
- .print = pyb_spi_print,
- .make_new = pyb_spi_make_new,
- .protocol = &pyb_spi_p,
- .locals_dict = (mp_obj_dict_t *)&pyb_spi_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ pyb_spi_type,
+ MP_QSTR_SPI,
+ MP_TYPE_FLAG_NONE,
+ make_new, pyb_spi_make_new,
+ print, pyb_spi_print,
+ protocol, &pyb_spi_p,
+ locals_dict, &pyb_spi_locals_dict
+ );
diff --git a/ports/stm32/pybthread.c b/ports/stm32/pybthread.c
index 603bc2e4ec09..57c8d1fddefa 100644
--- a/ports/stm32/pybthread.c
+++ b/ports/stm32/pybthread.c
@@ -24,10 +24,8 @@
* THE SOFTWARE.
*/
-#include
-#include
-
#include "py/obj.h"
+#include "boardctrl.h"
#include "gccollect.h"
#include "irq.h"
#include "pybthread.h"
@@ -42,8 +40,6 @@
#define RAISE_IRQ_PRI() raise_irq_pri(IRQ_PRI_PENDSV)
#define RESTORE_IRQ_PRI(state) restore_irq_pri(state)
-extern void __fatal_error(const char *);
-
volatile int pyb_thread_enabled;
pyb_thread_t *volatile pyb_thread_all;
pyb_thread_t *volatile pyb_thread_cur;
@@ -57,7 +53,7 @@ static inline void pyb_thread_add_to_runable(pyb_thread_t *thread) {
static inline void pyb_thread_remove_from_runable(pyb_thread_t *thread) {
if (thread->run_next == thread) {
- __fatal_error("deadlock");
+ MICROPY_BOARD_FATAL_ERROR("deadlock");
}
thread->run_prev->run_next = thread->run_next;
thread->run_next->run_prev = thread->run_prev;
@@ -112,7 +108,7 @@ STATIC void pyb_thread_terminate(void) {
SCB->ICSR = SCB_ICSR_PENDSVSET_Msk;
enable_irq(irq_state);
// should not return
- __fatal_error("could not terminate");
+ MICROPY_BOARD_FATAL_ERROR("could not terminate");
}
uint32_t pyb_thread_new(pyb_thread_t *thread, void *stack, size_t stack_len, void *entry, void *arg) {
@@ -143,11 +139,11 @@ uint32_t pyb_thread_new(pyb_thread_t *thread, void *stack, size_t stack_len, voi
return (uint32_t)thread; // success
}
-void pyb_thread_dump(void) {
+void pyb_thread_dump(const mp_print_t *print) {
if (!pyb_thread_enabled) {
- printf("THREAD: only main thread\n");
+ mp_printf(print, "THREAD: only main thread\n");
} else {
- printf("THREAD:\n");
+ mp_printf(print, "THREAD:\n");
for (pyb_thread_t *th = pyb_thread_all; th != NULL; th = th->all_next) {
bool runable = false;
for (pyb_thread_t *th2 = pyb_thread_cur;; th2 = th2->run_next) {
@@ -159,11 +155,11 @@ void pyb_thread_dump(void) {
break;
}
}
- printf(" id=%p sp=%p sz=%u", th, th->stack, th->stack_len);
+ mp_printf(print, " id=%p sp=%p sz=%u", th, th->stack, th->stack_len);
if (runable) {
- printf(" (runable)");
+ mp_printf(print, " (runable)");
}
- printf("\n");
+ mp_printf(print, "\n");
}
}
}
diff --git a/ports/stm32/pybthread.h b/ports/stm32/pybthread.h
index 8e5ce2570cae..4532b0de7bab 100644
--- a/ports/stm32/pybthread.h
+++ b/ports/stm32/pybthread.h
@@ -26,6 +26,8 @@
#ifndef MICROPY_INCLUDED_STM32_PYBTHREAD_H
#define MICROPY_INCLUDED_STM32_PYBTHREAD_H
+#include "py/mpprint.h"
+
typedef struct _pyb_thread_t {
void *sp;
uint32_t local_state;
@@ -48,7 +50,7 @@ extern pyb_thread_t *volatile pyb_thread_cur;
void pyb_thread_init(pyb_thread_t *th);
void pyb_thread_deinit();
uint32_t pyb_thread_new(pyb_thread_t *th, void *stack, size_t stack_len, void *entry, void *arg);
-void pyb_thread_dump(void);
+void pyb_thread_dump(const mp_print_t *print);
static inline uint32_t pyb_thread_get_id(void) {
return (uint32_t)pyb_thread_cur;
diff --git a/ports/stm32/qspi.c b/ports/stm32/qspi.c
index 04e226697eea..a79e692e0ec8 100644
--- a/ports/stm32/qspi.c
+++ b/ports/stm32/qspi.c
@@ -196,7 +196,7 @@ STATIC int qspi_ioctl(void *self_in, uint32_t cmd) {
return 0; // success
}
-STATIC void qspi_write_cmd_data(void *self_in, uint8_t cmd, size_t len, uint32_t data) {
+STATIC int qspi_write_cmd_data(void *self_in, uint8_t cmd, size_t len, uint32_t data) {
(void)self_in;
QUADSPI->FCR = QUADSPI_FCR_CTCF; // clear TC flag
@@ -238,12 +238,17 @@ STATIC void qspi_write_cmd_data(void *self_in, uint8_t cmd, size_t len, uint32_t
// Wait for write to finish
while (!(QUADSPI->SR & QUADSPI_SR_TCF)) {
+ if (QUADSPI->SR & QUADSPI_SR_TEF) {
+ return -MP_EIO;
+ }
}
QUADSPI->FCR = QUADSPI_FCR_CTCF; // clear TC flag
+
+ return 0;
}
-STATIC void qspi_write_cmd_addr_data(void *self_in, uint8_t cmd, uint32_t addr, size_t len, const uint8_t *src) {
+STATIC int qspi_write_cmd_addr_data(void *self_in, uint8_t cmd, uint32_t addr, size_t len, const uint8_t *src) {
(void)self_in;
uint8_t adsize = MICROPY_HW_SPI_ADDR_IS_32BIT(addr) ? 3 : 2;
@@ -286,6 +291,9 @@ STATIC void qspi_write_cmd_addr_data(void *self_in, uint8_t cmd, uint32_t addr,
// Write out the data 1 byte at a time
while (len) {
while (!(QUADSPI->SR & QUADSPI_SR_FTF)) {
+ if (QUADSPI->SR & QUADSPI_SR_TEF) {
+ return -MP_EIO;
+ }
}
*(volatile uint8_t *)&QUADSPI->DR = *src++;
--len;
@@ -294,12 +302,17 @@ STATIC void qspi_write_cmd_addr_data(void *self_in, uint8_t cmd, uint32_t addr,
// Wait for write to finish
while (!(QUADSPI->SR & QUADSPI_SR_TCF)) {
+ if (QUADSPI->SR & QUADSPI_SR_TEF) {
+ return -MP_EIO;
+ }
}
QUADSPI->FCR = QUADSPI_FCR_CTCF; // clear TC flag
+
+ return 0;
}
-STATIC uint32_t qspi_read_cmd(void *self_in, uint8_t cmd, size_t len) {
+STATIC int qspi_read_cmd(void *self_in, uint8_t cmd, size_t len, uint32_t *dest) {
(void)self_in;
QUADSPI->FCR = QUADSPI_FCR_CTCF; // clear TC flag
@@ -320,15 +333,20 @@ STATIC uint32_t qspi_read_cmd(void *self_in, uint8_t cmd, size_t len) {
// Wait for read to finish
while (!(QUADSPI->SR & QUADSPI_SR_TCF)) {
+ if (QUADSPI->SR & QUADSPI_SR_TEF) {
+ return -MP_EIO;
+ }
}
QUADSPI->FCR = QUADSPI_FCR_CTCF; // clear TC flag
// Read result
- return QUADSPI->DR;
+ *dest = QUADSPI->DR;
+
+ return 0;
}
-STATIC void qspi_read_cmd_qaddr_qdata(void *self_in, uint8_t cmd, uint32_t addr, size_t len, uint8_t *dest) {
+STATIC int qspi_read_cmd_qaddr_qdata(void *self_in, uint8_t cmd, uint32_t addr, size_t len, uint8_t *dest) {
(void)self_in;
uint8_t adsize = MICROPY_HW_SPI_ADDR_IS_32BIT(addr) ? 3 : 2;
@@ -366,6 +384,9 @@ STATIC void qspi_read_cmd_qaddr_qdata(void *self_in, uint8_t cmd, uint32_t addr,
if (((uintptr_t)dest & 3) == 0) {
while (len >= 4) {
while (!(QUADSPI->SR & QUADSPI_SR_FTF)) {
+ if (QUADSPI->SR & QUADSPI_SR_TEF) {
+ return -MP_EIO;
+ }
}
*(uint32_t *)dest = QUADSPI->DR;
dest += 4;
@@ -376,12 +397,17 @@ STATIC void qspi_read_cmd_qaddr_qdata(void *self_in, uint8_t cmd, uint32_t addr,
// Read in remaining data 1 byte at a time
while (len) {
while (!((QUADSPI->SR >> QUADSPI_SR_FLEVEL_Pos) & 0x3f)) {
+ if (QUADSPI->SR & QUADSPI_SR_TEF) {
+ return -MP_EIO;
+ }
}
*dest++ = *(volatile uint8_t *)&QUADSPI->DR;
--len;
}
QUADSPI->FCR = QUADSPI_FCR_CTCF; // clear TC flag
+
+ return 0;
}
const mp_qspi_proto_t qspi_proto = {
diff --git a/ports/stm32/resethandler.s b/ports/stm32/resethandler.s
index 7f0973346ed3..e0e59321f787 100644
--- a/ports/stm32/resethandler.s
+++ b/ports/stm32/resethandler.s
@@ -62,8 +62,7 @@ Reset_Handler:
cmp r1, r2
bcc .bss_zero_loop
- /* Initialise the system and jump to the main code */
- bl SystemInit
+ /* Jump to the main code */
mov r0, r4
b stm32_main
diff --git a/ports/stm32/resethandler_m0.s b/ports/stm32/resethandler_m0.s
index bb88e8daefe9..868d6da907c3 100644
--- a/ports/stm32/resethandler_m0.s
+++ b/ports/stm32/resethandler_m0.s
@@ -66,8 +66,7 @@ Reset_Handler:
cmp r1, r2
bcc .bss_zero_loop
- /* Initialise the system and jump to the main code */
- bl SystemInit
+ /* Jump to the main code */
mov r0, r4
bl stm32_main
diff --git a/ports/stm32/resethandler_m3.s b/ports/stm32/resethandler_m3.s
new file mode 100644
index 000000000000..f29821696871
--- /dev/null
+++ b/ports/stm32/resethandler_m3.s
@@ -0,0 +1,74 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 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.
+ */
+
+ .syntax unified
+ .cpu cortex-m3
+ .fpu softvfp
+ .thumb
+
+ .section .text.Reset_Handler
+ .global Reset_Handler
+ .type Reset_Handler, %function
+
+Reset_Handler:
+ /* Save the first argument to pass through to stm32_main */
+ mov r4, r0
+
+ /* Load the stack pointer */
+ ldr r0, =_estack
+ mov sp, r0
+
+ /* Initialise the data section */
+ ldr r1, =_sidata
+ ldr r2, =_sdata
+ ldr r3, =_edata
+ b .data_copy_entry
+.data_copy_loop:
+ ldr r0, [r1]
+ adds r1, #4
+ str r0, [r2]
+ adds r2, #4
+.data_copy_entry:
+ cmp r2, r3
+ bcc .data_copy_loop
+
+ /* Zero out the BSS section */
+ movs r0, #0
+ ldr r1, =_sbss
+ ldr r2, =_ebss
+ b .bss_zero_entry
+.bss_zero_loop:
+ str r0, [r1]
+ adds r1, #4
+.bss_zero_entry:
+ cmp r1, r2
+ bcc .bss_zero_loop
+
+ /* Jump to the main code */
+ mov r0, r4
+ bl stm32_main
+
+ .size Reset_Handler, .-Reset_Handler
diff --git a/ports/stm32/rfcore.c b/ports/stm32/rfcore.c
index 55d6d17ad1b1..2a75f7c74a19 100644
--- a/ports/stm32/rfcore.c
+++ b/ports/stm32/rfcore.c
@@ -534,12 +534,23 @@ void rfcore_init(void) {
// Ensure LSE is running
rtc_init_finalise();
+ // In case we're waking from deepsleep, enforce core synchronisation
+ __HAL_RCC_HSEM_CLK_ENABLE();
+ while (LL_HSEM_1StepLock(HSEM, CFG_HW_PWR_STANDBY_SEMID)) {
+ }
+
// Select LSE as RF wakeup source
RCC->CSR = (RCC->CSR & ~RCC_CSR_RFWKPSEL) | 1 << RCC_CSR_RFWKPSEL_Pos;
// Initialise IPCC and shared memory structures
ipcc_init(IRQ_PRI_SDIO);
+ // When the device is out of standby, it is required to use the EXTI mechanism to wakeup CPU2
+ LL_C2_EXTI_EnableEvent_32_63(LL_EXTI_LINE_41);
+ LL_EXTI_EnableRisingTrig_32_63(LL_EXTI_LINE_41);
+
+ LL_HSEM_ReleaseLock(HSEM, CFG_HW_PWR_STANDBY_SEMID, 0);
+
// Boot the second core
__SEV();
__WFE();
@@ -589,18 +600,38 @@ static const struct {
void rfcore_ble_init(void) {
DEBUG_printf("rfcore_ble_init\n");
- // Clear any outstanding messages from ipcc_init.
- tl_check_msg(&ipcc_mem_sys_queue, IPCC_CH_SYS, NULL);
-
// Configure and reset the BLE controller.
- tl_sys_hci_cmd_resp(HCI_OPCODE(OGF_VENDOR, OCF_BLE_INIT), (const uint8_t *)&ble_init_params, sizeof(ble_init_params), 0);
- tl_ble_hci_cmd_resp(HCI_OPCODE(0x03, 0x0003), NULL, 0);
+ if (!rfcore_ble_reset()) {
+ // ble init can fail if core2 has previously locked up. Reset HSI & rfcore to retry.
+ LL_RCC_HSI_Disable();
+ mp_hal_delay_ms(100);
+ LL_RCC_HSI_Enable();
+
+ rfcore_init();
+ rfcore_ble_reset();
+ }
// Enable PES rather than SEM7 to moderate flash access between the cores.
uint8_t buf = 0; // FLASH_ACTIVITY_CONTROL_PES
tl_sys_hci_cmd_resp(HCI_OPCODE(OGF_VENDOR, OCF_C2_SET_FLASH_ACTIVITY_CONTROL), &buf, 1, 0);
}
+bool rfcore_ble_reset(void) {
+ DEBUG_printf("rfcore_ble_reset\n");
+
+ // Clear any outstanding messages from ipcc_init.
+ tl_check_msg(&ipcc_mem_sys_queue, IPCC_CH_SYS, NULL);
+
+ // Configure and reset the BLE controller.
+ int ret = tl_sys_hci_cmd_resp(HCI_OPCODE(OGF_VENDOR, OCF_BLE_INIT), (const uint8_t *)&ble_init_params, sizeof(ble_init_params), 500);
+
+ if (ret == -MP_ETIMEDOUT) {
+ return false;
+ }
+ tl_ble_hci_cmd_resp(HCI_OPCODE(0x03, 0x0003), NULL, 0);
+ return true;
+}
+
void rfcore_ble_hci_cmd(size_t len, const uint8_t *src) {
DEBUG_printf("rfcore_ble_hci_cmd\n");
diff --git a/ports/stm32/rfcore.h b/ports/stm32/rfcore.h
index 5c67f194e2e2..39267b325ec4 100644
--- a/ports/stm32/rfcore.h
+++ b/ports/stm32/rfcore.h
@@ -33,6 +33,7 @@ typedef void (*rfcore_ble_msg_callback_t)(void *, const uint8_t *, size_t);
void rfcore_init(void);
void rfcore_ble_init(void);
+bool rfcore_ble_reset(void);
void rfcore_ble_hci_cmd(size_t len, const uint8_t *src);
size_t rfcore_ble_check_msg(rfcore_ble_msg_callback_t cb, void *env);
void rfcore_ble_set_txpower(uint8_t level);
diff --git a/ports/stm32/rtc.c b/ports/stm32/rtc.c
index 55977791b8c2..92f64626a3ec 100644
--- a/ports/stm32/rtc.c
+++ b/ports/stm32/rtc.c
@@ -24,8 +24,6 @@
* THE SOFTWARE.
*/
-#include
-
#include "py/runtime.h"
#include "shared/timeutils/timeutils.h"
#include "extint.h"
@@ -91,6 +89,15 @@ STATIC bool rtc_need_init_finalise = false;
#define RCC_BDCR_LSEON RCC_CSR_LSEON
#define RCC_BDCR_LSERDY RCC_CSR_LSERDY
#define RCC_BDCR_LSEBYP RCC_CSR_LSEBYP
+#elif defined(STM32L1)
+#define BDCR CR
+#define RCC_BDCR_RTCEN RCC_CSR_RTCEN
+#define RCC_BDCR_RTCSEL RCC_CSR_RTCSEL
+#define RCC_BDCR_RTCSEL_0 RCC_CSR_RTCSEL_0
+#define RCC_BDCR_RTCSEL_1 RCC_CSR_RTCSEL_1
+#define RCC_BDCR_LSEON RCC_CSR_LSEON
+#define RCC_BDCR_LSERDY RCC_CSR_LSERDY
+#define RCC_BDCR_LSEBYP RCC_CSR_LSEBYP
#endif
void rtc_init_start(bool force_init) {
@@ -664,7 +671,15 @@ mp_obj_t pyb_rtc_wakeup(size_t n_args, const mp_obj_t *args) {
wucksel -= 1;
}
if (div <= 16) {
+ #if defined(STM32L1)
+ if (rtc_use_lse) {
+ wut = LSE_VALUE / div * ms / 1000;
+ } else {
+ wut = LSI_VALUE / div * ms / 1000;
+ }
+ #else
wut = 32768 / div * ms / 1000;
+ #endif
} else {
// use 1Hz clock
wucksel = 4;
@@ -754,8 +769,6 @@ mp_obj_t pyb_rtc_wakeup(size_t n_args, const mp_obj_t *args) {
NVIC_SetPriority(RTC_WKUP_IRQn, IRQ_PRI_RTC_WKUP);
HAL_NVIC_EnableIRQ(RTC_WKUP_IRQn);
-
- // printf("wut=%d wucksel=%d\n", wut, wucksel);
} else {
// clear WUTIE to disable interrupts
RTC->CR &= ~RTC_CR_WUTIE;
@@ -816,7 +829,6 @@ mp_obj_t pyb_rtc_calibration(size_t n_args, const mp_obj_t *args) {
HAL_RTCEx_SetSmoothCalib(&RTCHandle, RTC_SMOOTHCALIB_PERIOD_32SEC, cal_p, cal_m);
return mp_const_none;
} else {
- // printf("CALR = 0x%x\n", (mp_uint_t) RTCHandle.Instance->CALR); // DEBUG
// Test if CALP bit is set in CALR:
if (RTCHandle.Instance->CALR & 0x8000) {
cal = 512 - (RTCHandle.Instance->CALR & 0x1ff);
@@ -837,9 +849,10 @@ STATIC const mp_rom_map_elem_t pyb_rtc_locals_dict_table[] = {
};
STATIC MP_DEFINE_CONST_DICT(pyb_rtc_locals_dict, pyb_rtc_locals_dict_table);
-const mp_obj_type_t pyb_rtc_type = {
- { &mp_type_type },
- .name = MP_QSTR_RTC,
- .make_new = pyb_rtc_make_new,
- .locals_dict = (mp_obj_dict_t *)&pyb_rtc_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ pyb_rtc_type,
+ MP_QSTR_RTC,
+ MP_TYPE_FLAG_NONE,
+ make_new, pyb_rtc_make_new,
+ locals_dict, &pyb_rtc_locals_dict
+ );
diff --git a/ports/stm32/sdcard.c b/ports/stm32/sdcard.c
index 6f5892570baf..964ed49a67dd 100644
--- a/ports/stm32/sdcard.c
+++ b/ports/stm32/sdcard.c
@@ -872,21 +872,23 @@ STATIC const mp_rom_map_elem_t pyb_sdcard_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(pyb_sdcard_locals_dict, pyb_sdcard_locals_dict_table);
#if MICROPY_HW_ENABLE_SDCARD
-const mp_obj_type_t pyb_sdcard_type = {
- { &mp_type_type },
- .name = MP_QSTR_SDCard,
- .make_new = pyb_sdcard_make_new,
- .locals_dict = (mp_obj_dict_t *)&pyb_sdcard_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ pyb_sdcard_type,
+ MP_QSTR_SDCard,
+ MP_TYPE_FLAG_NONE,
+ make_new, pyb_sdcard_make_new,
+ locals_dict, &pyb_sdcard_locals_dict
+ );
#endif
#if MICROPY_HW_ENABLE_MMCARD
-const mp_obj_type_t pyb_mmcard_type = {
- { &mp_type_type },
- .name = MP_QSTR_MMCard,
- .make_new = pyb_mmcard_make_new,
- .locals_dict = (mp_obj_dict_t *)&pyb_sdcard_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ pyb_mmcard_type,
+ MP_QSTR_MMCard,
+ MP_TYPE_FLAG_NONE,
+ make_new, pyb_mmcard_make_new,
+ locals_dict, &pyb_sdcard_locals_dict
+ );
#endif
void sdcard_init_vfs(fs_user_mount_t *vfs, int part) {
diff --git a/ports/stm32/sdram.c b/ports/stm32/sdram.c
index 4ca79f270c6c..fb0e5a8688d3 100644
--- a/ports/stm32/sdram.c
+++ b/ports/stm32/sdram.c
@@ -11,6 +11,7 @@
#include
#include "py/runtime.h"
#include "py/mphal.h"
+#include "boardctrl.h"
#include "pin.h"
#include "pin_static_af.h"
#include "mpu.h"
@@ -50,7 +51,6 @@
#ifdef FMC_SDRAM_BANK
static void sdram_init_seq(SDRAM_HandleTypeDef *hsdram, FMC_SDRAM_CommandTypeDef *command);
-extern void __fatal_error(const char *msg);
bool sdram_init(void) {
SDRAM_HandleTypeDef hsdram;
@@ -244,7 +244,7 @@ static void sdram_init_seq(SDRAM_HandleTypeDef
#define REFRESH_COUNT (MICROPY_HW_SDRAM_REFRESH_RATE * 90000 / 8192 - 20)
HAL_SDRAM_ProgramRefreshRate(hsdram, REFRESH_COUNT);
- #if defined(STM32F7)
+ #if defined(STM32F7) || defined(STM32H7)
/* Enable MPU for the SDRAM Memory Region to allow non-aligned
accesses (hard-fault otherwise)
Initially disable all access for the entire SDRAM memory space,
@@ -325,7 +325,7 @@ bool __attribute__((optimize("Os"))) sdram_test(bool exhaustive) {
snprintf(error_buffer, sizeof(error_buffer),
"Data bus test failed at 0x%p expected 0x%x found 0x%lx",
&mem_base[0], (1 << i), ((volatile uint32_t *)mem_base)[0]);
- __fatal_error(error_buffer);
+ MICROPY_BOARD_FATAL_ERROR(error_buffer);
#endif
return false;
}
@@ -340,7 +340,7 @@ bool __attribute__((optimize("Os"))) sdram_test(bool exhaustive) {
snprintf(error_buffer, sizeof(error_buffer),
"Address bus test failed at 0x%p expected 0x%x found 0x%x",
&mem_base[i], pattern, mem_base[i]);
- __fatal_error(error_buffer);
+ MICROPY_BOARD_FATAL_ERROR(error_buffer);
#endif
return false;
}
@@ -355,7 +355,7 @@ bool __attribute__((optimize("Os"))) sdram_test(bool exhaustive) {
snprintf(error_buffer, sizeof(error_buffer),
"Address bus overlap at 0x%p expected 0x%x found 0x%x",
&mem_base[i], pattern, mem_base[i]);
- __fatal_error(error_buffer);
+ MICROPY_BOARD_FATAL_ERROR(error_buffer);
#endif
return false;
}
@@ -376,7 +376,7 @@ bool __attribute__((optimize("Os"))) sdram_test(bool exhaustive) {
snprintf(error_buffer, sizeof(error_buffer),
"Address bus slow test failed at 0x%p expected 0x%x found 0x%x",
&mem_base[i], ((i % 2) ? pattern : antipattern), mem_base[i]);
- __fatal_error(error_buffer);
+ MICROPY_BOARD_FATAL_ERROR(error_buffer);
#endif
return false;
}
diff --git a/ports/stm32/servo.c b/ports/stm32/servo.c
index 17084224637e..e0aa2d6b69f8 100644
--- a/ports/stm32/servo.c
+++ b/ports/stm32/servo.c
@@ -336,12 +336,13 @@ STATIC const mp_rom_map_elem_t pyb_servo_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(pyb_servo_locals_dict, pyb_servo_locals_dict_table);
-const mp_obj_type_t pyb_servo_type = {
- { &mp_type_type },
- .name = MP_QSTR_Servo,
- .print = pyb_servo_print,
- .make_new = pyb_servo_make_new,
- .locals_dict = (mp_obj_dict_t *)&pyb_servo_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ pyb_servo_type,
+ MP_QSTR_Servo,
+ MP_TYPE_FLAG_NONE,
+ make_new, pyb_servo_make_new,
+ print, pyb_servo_print,
+ locals_dict, &pyb_servo_locals_dict
+ );
#endif // MICROPY_HW_ENABLE_SERVO
diff --git a/ports/stm32/softtimer.h b/ports/stm32/softtimer.h
deleted file mode 100644
index 9c14f16d615c..000000000000
--- a/ports/stm32/softtimer.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * 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_STM32_SOFTTIMER_H
-#define MICROPY_INCLUDED_STM32_SOFTTIMER_H
-
-#include "py/pairheap.h"
-
-#define SOFT_TIMER_FLAG_PY_CALLBACK (1)
-#define SOFT_TIMER_FLAG_GC_ALLOCATED (2)
-
-#define SOFT_TIMER_MODE_ONE_SHOT (1)
-#define SOFT_TIMER_MODE_PERIODIC (2)
-
-typedef struct _soft_timer_entry_t {
- mp_pairheap_t pairheap;
- uint16_t flags;
- uint16_t mode;
- uint32_t expiry_ms;
- uint32_t delta_ms; // for periodic mode
- union {
- void (*c_callback)(struct _soft_timer_entry_t *);
- mp_obj_t py_callback;
- };
-} soft_timer_entry_t;
-
-extern volatile uint32_t soft_timer_next;
-
-void soft_timer_deinit(void);
-void soft_timer_handler(void);
-void soft_timer_gc_mark_all(void);
-
-void soft_timer_static_init(soft_timer_entry_t *entry, uint16_t mode, uint32_t delta_ms, void (*cb)(soft_timer_entry_t *));
-void soft_timer_insert(soft_timer_entry_t *entry, uint32_t initial_delta_ms);
-void soft_timer_remove(soft_timer_entry_t *entry);
-
-// The timer will be reinserted into the heap so that it is called after initial_delta_ms milliseconds.
-// After that, if it's periodic, it will continue to be called every entry->delta_ms milliseconds.
-static inline void soft_timer_reinsert(soft_timer_entry_t *entry, uint32_t initial_delta_ms) {
- soft_timer_remove(entry);
- soft_timer_insert(entry, initial_delta_ms);
-}
-
-#endif // MICROPY_INCLUDED_STM32_SOFTTIMER_H
diff --git a/ports/stm32/spi.c b/ports/stm32/spi.c
index 188376ec06d5..e61c837692b2 100644
--- a/ports/stm32/spi.c
+++ b/ports/stm32/spi.c
@@ -24,12 +24,11 @@
* THE SOFTWARE.
*/
-#include
-#include
-
#include "py/runtime.h"
+#include "py/mperrno.h"
#include "py/mphal.h"
#include "spi.h"
+#include "extmod/machine_spi.h"
// Possible DMA configurations for SPI buses:
// SPI1_TX: DMA2_Stream3.CHANNEL_3 or DMA2_Stream5.CHANNEL_3
@@ -46,22 +45,22 @@
// SPI6_RX: DMA2_Stream6.CHANNEL_1
#if defined(MICROPY_HW_SPI1_SCK)
-SPI_HandleTypeDef SPIHandle1 = {.Instance = NULL};
+STATIC SPI_HandleTypeDef SPIHandle1 = {.Instance = NULL};
#endif
#if defined(MICROPY_HW_SPI2_SCK)
-SPI_HandleTypeDef SPIHandle2 = {.Instance = NULL};
+STATIC SPI_HandleTypeDef SPIHandle2 = {.Instance = NULL};
#endif
#if defined(MICROPY_HW_SPI3_SCK)
-SPI_HandleTypeDef SPIHandle3 = {.Instance = NULL};
+STATIC SPI_HandleTypeDef SPIHandle3 = {.Instance = NULL};
#endif
#if defined(MICROPY_HW_SPI4_SCK)
-SPI_HandleTypeDef SPIHandle4 = {.Instance = NULL};
+STATIC SPI_HandleTypeDef SPIHandle4 = {.Instance = NULL};
#endif
#if defined(MICROPY_HW_SPI5_SCK)
-SPI_HandleTypeDef SPIHandle5 = {.Instance = NULL};
+STATIC SPI_HandleTypeDef SPIHandle5 = {.Instance = NULL};
#endif
#if defined(MICROPY_HW_SPI6_SCK)
-SPI_HandleTypeDef SPIHandle6 = {.Instance = NULL};
+STATIC SPI_HandleTypeDef SPIHandle6 = {.Instance = NULL};
#endif
const spi_t spi_obj[6] = {
@@ -295,7 +294,7 @@ void spi_set_params(const spi_t *spi_obj, uint32_t prescale, int32_t baudrate,
}
// TODO allow to take a list of pins to use
-void spi_init(const spi_t *self, bool enable_nss_pin) {
+int spi_init(const spi_t *self, bool enable_nss_pin) {
SPI_HandleTypeDef *spi = self->spi;
uint32_t irqn = 0;
const pin_obj_t *pins[4] = { NULL, NULL, NULL, NULL };
@@ -395,7 +394,7 @@ void spi_init(const spi_t *self, bool enable_nss_pin) {
#endif
} else {
// SPI does not exist for this board (shouldn't get here, should be checked by caller)
- return;
+ return -MP_EINVAL;
}
// init the GPIO lines
@@ -411,10 +410,7 @@ void spi_init(const spi_t *self, bool enable_nss_pin) {
// init the SPI device
if (HAL_SPI_Init(spi) != HAL_OK) {
// init error
- // TODO should raise an exception, but this function is not necessarily going to be
- // called via Python, so may not be properly wrapped in an NLR handler
- printf("OSError: HAL_SPI_Init failed\n");
- return;
+ return -MP_EIO;
}
// After calling HAL_SPI_Init() it seems that the DMA gets disconnected if
@@ -429,6 +425,8 @@ void spi_init(const spi_t *self, bool enable_nss_pin) {
#else
(void)irqn;
#endif
+
+ return 0; // success
}
void spi_deinit(const spi_t *spi_obj) {
@@ -677,7 +675,7 @@ const spi_t *spi_from_mp_obj(mp_obj_t o) {
if (mp_obj_is_type(o, &pyb_spi_type)) {
pyb_spi_obj_t *self = MP_OBJ_TO_PTR(o);
return self->spi;
- } else if (mp_obj_is_type(o, &machine_hard_spi_type)) {
+ } else if (mp_obj_is_type(o, &machine_spi_type)) {
machine_hard_spi_obj_t *self = MP_OBJ_TO_PTR(o);
return self->spi;
} else {
@@ -685,6 +683,20 @@ const spi_t *spi_from_mp_obj(mp_obj_t o) {
}
}
+mp_obj_base_t *mp_hal_get_spi_obj(mp_obj_t o) {
+ if (mp_obj_is_type(o, &machine_spi_type)) {
+ return MP_OBJ_TO_PTR(o);
+ }
+ #if MICROPY_PY_MACHINE_SOFTSPI
+ else if (mp_obj_is_type(o, &mp_machine_soft_spi_type)) {
+ return MP_OBJ_TO_PTR(o);
+ }
+ #endif
+ else {
+ mp_raise_TypeError(MP_ERROR_TEXT("expecting an SPI object"));
+ }
+}
+
/******************************************************************************/
// Implementation of low-level SPI C protocol
@@ -700,8 +712,7 @@ STATIC int spi_proto_ioctl(void *self_in, uint32_t cmd) {
self->spi->spi->Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
spi_set_params(self->spi, 0xffffffff, self->baudrate,
self->polarity, self->phase, self->bits, self->firstbit);
- spi_init(self->spi, false);
- break;
+ return spi_init(self->spi, false);
case MP_SPI_IOCTL_DEINIT:
spi_deinit(self->spi);
diff --git a/ports/stm32/spi.h b/ports/stm32/spi.h
index 17f1bf6c4ab9..fe7f2f6614c3 100644
--- a/ports/stm32/spi.h
+++ b/ports/stm32/spi.h
@@ -54,18 +54,11 @@ typedef struct _machine_hard_spi_obj_t {
const spi_t *spi;
} machine_hard_spi_obj_t;
-extern SPI_HandleTypeDef SPIHandle1;
-extern SPI_HandleTypeDef SPIHandle2;
-extern SPI_HandleTypeDef SPIHandle3;
-extern SPI_HandleTypeDef SPIHandle4;
-extern SPI_HandleTypeDef SPIHandle5;
-extern SPI_HandleTypeDef SPIHandle6;
-
extern const spi_t spi_obj[6];
extern const mp_spi_proto_t spi_proto;
extern const mp_obj_type_t pyb_spi_type;
-extern const mp_obj_type_t machine_hard_spi_type;
+extern const mp_obj_type_t machine_spi_type;
// A transfer of "len" bytes should take len*8*1000/baudrate milliseconds.
// To simplify the calculation we assume the baudrate is never less than 8kHz
@@ -73,7 +66,7 @@ extern const mp_obj_type_t machine_hard_spi_type;
#define SPI_TRANSFER_TIMEOUT(len) ((len) + 100)
void spi_init0(void);
-void spi_init(const spi_t *spi, bool enable_nss_pin);
+int spi_init(const spi_t *spi, bool enable_nss_pin);
void spi_deinit(const spi_t *spi_obj);
int spi_find_index(mp_obj_t id);
void spi_set_params(const spi_t *spi_obj, uint32_t prescale, int32_t baudrate,
diff --git a/ports/stm32/spibdev.c b/ports/stm32/spibdev.c
index afa6f4ecdccb..fecd4a991536 100644
--- a/ports/stm32/spibdev.c
+++ b/ports/stm32/spibdev.c
@@ -40,25 +40,29 @@ int32_t spi_bdev_ioctl(spi_bdev_t *bdev, uint32_t op, uint32_t arg) {
bdev->flash_tick_counter_last_write = 0;
return 0;
- case BDEV_IOCTL_IRQ_HANDLER:
+ case BDEV_IOCTL_IRQ_HANDLER: {
+ int ret = 0;
#if MICROPY_HW_SPIFLASH_ENABLE_CACHE
if ((bdev->spiflash.flags & 1) && HAL_GetTick() - bdev->flash_tick_counter_last_write >= 1000) {
- mp_spiflash_cache_flush(&bdev->spiflash);
+ ret = mp_spiflash_cache_flush(&bdev->spiflash);
led_state(PYB_LED_RED, 0); // indicate a clean cache with LED off
}
#endif
- return 0;
+ return ret;
+ }
- case BDEV_IOCTL_SYNC:
+ case BDEV_IOCTL_SYNC: {
+ int ret = 0;
#if MICROPY_HW_SPIFLASH_ENABLE_CACHE
if (bdev->spiflash.flags & 1) {
uint32_t basepri = raise_irq_pri(IRQ_PRI_FLASH); // prevent cache flushing and USB access
- mp_spiflash_cache_flush(&bdev->spiflash);
+ ret = mp_spiflash_cache_flush(&bdev->spiflash);
led_state(PYB_LED_RED, 0); // indicate a clean cache with LED off
restore_irq_pri(basepri);
}
#endif
- return 0;
+ return ret;
+ }
}
return -MP_EINVAL;
}
@@ -66,10 +70,10 @@ int32_t spi_bdev_ioctl(spi_bdev_t *bdev, uint32_t op, uint32_t arg) {
#if MICROPY_HW_SPIFLASH_ENABLE_CACHE
int spi_bdev_readblocks(spi_bdev_t *bdev, uint8_t *dest, uint32_t block_num, uint32_t num_blocks) {
uint32_t basepri = raise_irq_pri(IRQ_PRI_FLASH); // prevent cache flushing and USB access
- mp_spiflash_cached_read(&bdev->spiflash, block_num * FLASH_BLOCK_SIZE, num_blocks * FLASH_BLOCK_SIZE, dest);
+ int ret = mp_spiflash_cached_read(&bdev->spiflash, block_num * FLASH_BLOCK_SIZE, num_blocks * FLASH_BLOCK_SIZE, dest);
restore_irq_pri(basepri);
- return 0;
+ return ret;
}
int spi_bdev_writeblocks(spi_bdev_t *bdev, const uint8_t *src, uint32_t block_num, uint32_t num_blocks) {
@@ -87,10 +91,10 @@ int spi_bdev_writeblocks(spi_bdev_t *bdev, const uint8_t *src, uint32_t block_nu
int spi_bdev_readblocks_raw(spi_bdev_t *bdev, uint8_t *dest, uint32_t block_num, uint32_t block_offset, uint32_t num_bytes) {
uint32_t basepri = raise_irq_pri(IRQ_PRI_FLASH); // prevent cache flushing and USB access
- mp_spiflash_read(&bdev->spiflash, block_num * MP_SPIFLASH_ERASE_BLOCK_SIZE + block_offset, num_bytes, dest);
+ int ret = mp_spiflash_read(&bdev->spiflash, block_num * MP_SPIFLASH_ERASE_BLOCK_SIZE + block_offset, num_bytes, dest);
restore_irq_pri(basepri);
- return 0;
+ return ret;
}
int spi_bdev_writeblocks_raw(spi_bdev_t *bdev, const uint8_t *src, uint32_t block_num, uint32_t block_offset, uint32_t num_bytes) {
diff --git a/ports/stm32/stm32.mk b/ports/stm32/stm32.mk
index c55b243fe573..ae267a599596 100644
--- a/ports/stm32/stm32.mk
+++ b/ports/stm32/stm32.mk
@@ -48,7 +48,7 @@ CFLAGS_CORTEX_M += -mfpu=fpv5-d16 -mfloat-abi=hard
SUPPORTS_HARDWARE_FP_SINGLE = 1
SUPPORTS_HARDWARE_FP_DOUBLE = 1
else
-ifeq ($(MCU_SERIES),$(filter $(MCU_SERIES),f0 g0 l0 wl))
+ifeq ($(MCU_SERIES),$(filter $(MCU_SERIES),f0 g0 l0 l1 wl))
CFLAGS_CORTEX_M += -msoft-float
else
CFLAGS_CORTEX_M += -mfpu=fpv4-sp-d16 -mfloat-abi=hard
@@ -64,7 +64,20 @@ CFLAGS_MCU_f7 = $(CFLAGS_CORTEX_M) -mtune=cortex-m7 -mcpu=cortex-m7
CFLAGS_MCU_g0 = $(CFLAGS_CORTEX_M) -mtune=cortex-m0plus -mcpu=cortex-m0plus
CFLAGS_MCU_g4 = $(CFLAGS_CORTEX_M) -mtune=cortex-m4 -mcpu=cortex-m4
CFLAGS_MCU_l0 = $(CFLAGS_CORTEX_M) -mtune=cortex-m0plus -mcpu=cortex-m0plus
+CFLAGS_MCU_l1 = $(CFLAGS_CORTEX_M) -mtune=cortex-m3 -mcpu=cortex-m3
CFLAGS_MCU_l4 = $(CFLAGS_CORTEX_M) -mtune=cortex-m4 -mcpu=cortex-m4
CFLAGS_MCU_h7 = $(CFLAGS_CORTEX_M) -mtune=cortex-m7 -mcpu=cortex-m7
CFLAGS_MCU_wb = $(CFLAGS_CORTEX_M) -mtune=cortex-m4 -mcpu=cortex-m4
CFLAGS_MCU_wl = $(CFLAGS_CORTEX_M) -mtune=cortex-m4 -mcpu=cortex-m4
+
+MPY_CROSS_MCU_ARCH_f0 = armv6m
+MPY_CROSS_MCU_ARCH_f4 = armv7m
+MPY_CROSS_MCU_ARCH_f7 = armv7m
+MPY_CROSS_MCU_ARCH_g0 = armv6m
+MPY_CROSS_MCU_ARCH_g4 = armv7m
+MPY_CROSS_MCU_ARCH_l0 = armv6m
+MPY_CROSS_MCU_ARCH_l1 = armv7m
+MPY_CROSS_MCU_ARCH_l4 = armv7m
+MPY_CROSS_MCU_ARCH_h7 = armv7m
+MPY_CROSS_MCU_ARCH_wb = armv7m
+MPY_CROSS_MCU_ARCH_wl = armv7m
diff --git a/ports/stm32/stm32_it.c b/ports/stm32/stm32_it.c
index 738866175c7b..c64d70e55751 100644
--- a/ports/stm32/stm32_it.c
+++ b/ports/stm32/stm32_it.c
@@ -83,7 +83,6 @@
#include "i2c.h"
#include "usb.h"
-extern void __fatal_error(const char *);
#if defined(MICROPY_HW_USB_FS)
extern PCD_HandleTypeDef pcd_fs_handle;
#endif
@@ -192,7 +191,7 @@ void HardFault_C_Handler(ExceptionRegisters_t *regs) {
/* Go to infinite loop when Hard Fault exception occurs */
while (1) {
- __fatal_error("HardFault");
+ MICROPY_BOARD_FATAL_ERROR("HardFault");
}
}
@@ -246,7 +245,7 @@ void NMI_Handler(void) {
void MemManage_Handler(void) {
/* Go to infinite loop when Memory Manage exception occurs */
while (1) {
- __fatal_error("MemManage");
+ MICROPY_BOARD_FATAL_ERROR("MemManage");
}
}
@@ -258,7 +257,7 @@ void MemManage_Handler(void) {
void BusFault_Handler(void) {
/* Go to infinite loop when Bus Fault exception occurs */
while (1) {
- __fatal_error("BusFault");
+ MICROPY_BOARD_FATAL_ERROR("BusFault");
}
}
@@ -270,7 +269,7 @@ void BusFault_Handler(void) {
void UsageFault_Handler(void) {
/* Go to infinite loop when Usage Fault exception occurs */
while (1) {
- __fatal_error("UsageFault");
+ MICROPY_BOARD_FATAL_ERROR("UsageFault");
}
}
@@ -297,7 +296,15 @@ void DebugMon_Handler(void) {
/* file (startup_stm32f4xx.s). */
/******************************************************************************/
-#if defined(STM32L0) || defined(STM32L432xx)
+#if defined(STM32G0)
+
+#if MICROPY_HW_USB_FS
+void USB_UCPD1_2_IRQHandler(void) {
+ HAL_PCD_IRQHandler(&pcd_fs_handle);
+}
+#endif
+
+#elif defined(STM32L0) || defined(STM32L432xx)
#if MICROPY_HW_USB_FS
void USB_IRQHandler(void) {
@@ -521,11 +528,19 @@ void ETH_WKUP_IRQHandler(void) {
}
#endif
+#if defined(STM32L1)
+void TAMPER_STAMP_IRQHandler(void) {
+ IRQ_ENTER(TAMPER_STAMP_IRQn);
+ Handle_EXTI_Irq(EXTI_RTC_TIMESTAMP);
+ IRQ_EXIT(TAMPER_STAMP_IRQn);
+}
+#else
void TAMP_STAMP_IRQHandler(void) {
IRQ_ENTER(TAMP_STAMP_IRQn);
Handle_EXTI_Irq(EXTI_RTC_TIMESTAMP);
IRQ_EXIT(TAMP_STAMP_IRQn);
}
+#endif
void RTC_WKUP_IRQHandler(void) {
IRQ_ENTER(RTC_WKUP_IRQn);
@@ -699,6 +714,12 @@ void TIM6_DAC_LPTIM1_IRQHandler(void) {
timer_irq_handler(6);
IRQ_EXIT(TIM6_DAC_LPTIM1_IRQn);
}
+#elif defined(STM32L1)
+void TIM6_IRQHandler(void) {
+ IRQ_ENTER(TIM6_IRQn);
+ timer_irq_handler(6);
+ IRQ_EXIT(TIM6_IRQn);
+}
#else
void TIM6_DAC_IRQHandler(void) {
IRQ_ENTER(TIM6_DAC_IRQn);
@@ -765,6 +786,26 @@ void TIM8_TRG_COM_TIM14_IRQHandler(void) {
}
#endif
+#if defined(STM32L1)
+void TIM9_IRQHandler(void) {
+ IRQ_ENTER(TIM9_IRQn);
+ timer_irq_handler(9);
+ IRQ_EXIT(TIM9_IRQn);
+}
+
+void TIM10_IRQHandler(void) {
+ IRQ_ENTER(TIM9_IRQn);
+ timer_irq_handler(10);
+ IRQ_EXIT(TIM9_IRQn);
+}
+
+void TIM11_IRQHandler(void) {
+ IRQ_ENTER(TIM9_IRQn);
+ timer_irq_handler(11);
+ IRQ_EXIT(TIM9_IRQn);
+}
+#endif
+
#if defined(STM32G0)
void TIM14_IRQHandler(void) {
IRQ_ENTER(TIM14_IRQn);
diff --git a/ports/stm32/storage.c b/ports/stm32/storage.c
index c33a75f67100..4623225804ce 100644
--- a/ports/stm32/storage.c
+++ b/ports/stm32/storage.c
@@ -24,9 +24,6 @@
* THE SOFTWARE.
*/
-#include
-#include
-
#include "py/runtime.h"
#include "py/mperrno.h"
#include "extmod/vfs_fat.h"
@@ -144,7 +141,6 @@ static void build_partition(uint8_t *buf, int boot, int type, uint32_t start_blo
}
bool storage_read_block(uint8_t *dest, uint32_t block) {
- // printf("RD %u\n", block);
if (block == 0) {
// fake the MBR so we can decide on our own partition table
@@ -176,7 +172,6 @@ bool storage_read_block(uint8_t *dest, uint32_t block) {
}
bool storage_write_block(const uint8_t *src, uint32_t block) {
- // printf("WR %u\n", block);
if (block == 0) {
// can't write MBR, but pretend we did
return true;
@@ -453,13 +448,14 @@ STATIC const mp_rom_map_elem_t pyb_flash_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(pyb_flash_locals_dict, pyb_flash_locals_dict_table);
-const mp_obj_type_t pyb_flash_type = {
- { &mp_type_type },
- .name = MP_QSTR_Flash,
- .print = pyb_flash_print,
- .make_new = pyb_flash_make_new,
- .locals_dict = (mp_obj_dict_t *)&pyb_flash_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ pyb_flash_type,
+ MP_QSTR_Flash,
+ MP_TYPE_FLAG_NONE,
+ make_new, pyb_flash_make_new,
+ print, pyb_flash_print,
+ locals_dict, &pyb_flash_locals_dict
+ );
void pyb_flash_init_vfs(fs_user_mount_t *vfs) {
vfs->base.type = &mp_fat_vfs_type;
diff --git a/ports/stm32/system_stm32.c b/ports/stm32/system_stm32.c
index e67c32738c28..08f071cd2793 100644
--- a/ports/stm32/system_stm32.c
+++ b/ports/stm32/system_stm32.c
@@ -76,12 +76,11 @@
*/
#include "py/mphal.h"
+#include "boardctrl.h"
#include "powerctrl.h"
#if defined(STM32F4) || defined(STM32F7) || defined(STM32G4) || defined(STM32H7) || defined(STM32L4)
-void __fatal_error(const char *msg);
-
/**
* @brief System Clock Configuration
*
@@ -390,7 +389,7 @@ MP_WEAK void SystemClock_Config(void) {
#endif
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
- __fatal_error("HAL_RCC_OscConfig");
+ MICROPY_BOARD_FATAL_ERROR("HAL_RCC_OscConfig");
}
#if defined(MICROPY_HW_CLK_PLL2M)
@@ -478,20 +477,20 @@ MP_WEAK void SystemClock_Config(void) {
#endif
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) {
- __fatal_error("HAL_RCCEx_PeriphCLKConfig");
+ MICROPY_BOARD_FATAL_ERROR("HAL_RCCEx_PeriphCLKConfig");
}
#endif // defined(STM32H7)
#if defined(STM32F7)
/* Activate the OverDrive to reach the 200 MHz Frequency */
if (HAL_PWREx_EnableOverDrive() != HAL_OK) {
- __fatal_error("HAL_PWREx_EnableOverDrive");
+ MICROPY_BOARD_FATAL_ERROR("HAL_PWREx_EnableOverDrive");
}
#endif
#if defined(STM32G4)
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_8) != HAL_OK) {
- __fatal_error("HAL_RCC_ClockConfig");
+ MICROPY_BOARD_FATAL_ERROR("HAL_RCC_ClockConfig");
}
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_RTC | RCC_PERIPHCLK_LPUART1
| RCC_PERIPHCLK_RNG | RCC_PERIPHCLK_ADC12
@@ -503,14 +502,14 @@ MP_WEAK void SystemClock_Config(void) {
PeriphClkInitStruct.Adc12ClockSelection = RCC_ADC12CLKSOURCE_SYSCLK;
PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSE;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) {
- __fatal_error("HAL_RCCEx_PeriphCLKConfig");
+ MICROPY_BOARD_FATAL_ERROR("HAL_RCCEx_PeriphCLKConfig");
}
#else
uint32_t vco_out = RCC_OscInitStruct.PLL.PLLN * (MICROPY_HW_CLK_VALUE / 1000000) / RCC_OscInitStruct.PLL.PLLM;
uint32_t sysclk_mhz = vco_out / RCC_OscInitStruct.PLL.PLLP;
bool need_pll48 = vco_out % 48 != 0;
if (powerctrl_rcc_clock_config_pll(&RCC_ClkInitStruct, sysclk_mhz, need_pll48) != 0) {
- __fatal_error("HAL_RCC_ClockConfig");
+ MICROPY_BOARD_FATAL_ERROR("HAL_RCC_ClockConfig");
}
#endif
@@ -572,7 +571,7 @@ MP_WEAK void SystemClock_Config(void) {
| RCC_PLLSAI1_ADC1CLK;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) {
- __fatal_error("HAL_RCCEx_PeriphCLKConfig");
+ MICROPY_BOARD_FATAL_ERROR("HAL_RCCEx_PeriphCLKConfig");
}
__PWR_CLK_ENABLE();
diff --git a/ports/stm32/systick.c b/ports/stm32/systick.c
index 7d1e318ac054..76944d312afc 100644
--- a/ports/stm32/systick.c
+++ b/ports/stm32/systick.c
@@ -26,10 +26,10 @@
#include "py/runtime.h"
#include "py/mphal.h"
+#include "shared/runtime/softtimer.h"
#include "irq.h"
#include "pendsv.h"
#include "systick.h"
-#include "softtimer.h"
#include "pybthread.h"
extern __IO uint32_t uwTick;
diff --git a/ports/stm32/timer.c b/ports/stm32/timer.c
index 8181885e2ed7..8816c218f5e3 100644
--- a/ports/stm32/timer.c
+++ b/ports/stm32/timer.c
@@ -431,7 +431,7 @@ STATIC mp_obj_t compute_percent_from_pwm_value(uint32_t period, uint32_t cmp) {
#endif
}
-#if !defined(STM32L0)
+#if !defined(STM32L0) && !defined(STM32L1)
// Computes the 8-bit value for the DTG field in the BDTR register.
//
@@ -522,7 +522,7 @@ STATIC void pyb_timer_print(const mp_print_t *print, mp_obj_t self_in, mp_print_
self->tim.Init.ClockDivision == TIM_CLOCKDIVISION_DIV4 ? 4 :
self->tim.Init.ClockDivision == TIM_CLOCKDIVISION_DIV2 ? 2 : 1);
- #if !defined(STM32L0)
+ #if !defined(STM32L0) && !defined(STM32L1)
#if defined(IS_TIM_ADVANCED_INSTANCE)
if (IS_TIM_ADVANCED_INSTANCE(self->tim.Instance))
#elif defined(IS_TIM_BREAK_INSTANCE)
@@ -640,7 +640,7 @@ STATIC mp_obj_t pyb_timer_init_helper(pyb_timer_obj_t *self, size_t n_args, cons
args[ARG_div].u_int == 4 ? TIM_CLOCKDIVISION_DIV4 :
TIM_CLOCKDIVISION_DIV1;
- #if !defined(STM32L0)
+ #if !defined(STM32L0) && !defined(STM32L1)
init->RepetitionCounter = 0;
#endif
@@ -772,7 +772,7 @@ STATIC mp_obj_t pyb_timer_init_helper(pyb_timer_obj_t *self, size_t n_args, cons
// init TIM
HAL_TIM_Base_Init(&self->tim);
- #if !defined(STM32L0)
+ #if !defined(STM32L0) && !defined(STM32L1)
#if defined(IS_TIM_ADVANCED_INSTANCE)
if (IS_TIM_ADVANCED_INSTANCE(self->tim.Instance))
#elif defined(IS_TIM_BREAK_INSTANCE)
@@ -833,7 +833,7 @@ STATIC const uint32_t tim_instance_table[MICROPY_HW_MAX_TIMER] = {
TIM_ENTRY(5, TIM5_IRQn),
#endif
#if defined(TIM6)
- #if defined(STM32F412Zx)
+ #if defined(STM32F412Zx) || defined(STM32L1)
TIM_ENTRY(6, TIM6_IRQn),
#elif defined(STM32G0)
TIM_ENTRY(6, TIM6_DAC_LPTIM1_IRQn),
@@ -858,14 +858,26 @@ STATIC const uint32_t tim_instance_table[MICROPY_HW_MAX_TIMER] = {
#endif
#endif
#if defined(TIM9)
+ #if defined(STM32L1)
+ TIM_ENTRY(9, TIM9_IRQn),
+ #else
TIM_ENTRY(9, TIM1_BRK_TIM9_IRQn),
#endif
+ #endif
#if defined(TIM10)
+ #if defined(STM32L1)
+ TIM_ENTRY(10, TIM10_IRQn),
+ #else
TIM_ENTRY(10, TIM1_UP_TIM10_IRQn),
#endif
+ #endif
#if defined(TIM11)
+ #if defined(STM32L1)
+ TIM_ENTRY(11, TIM11_IRQn),
+ #else
TIM_ENTRY(11, TIM1_TRG_COM_TIM11_IRQn),
#endif
+ #endif
#if defined(TIM12)
TIM_ENTRY(12, TIM8_BRK_TIM12_IRQn),
#endif
@@ -936,7 +948,11 @@ STATIC mp_obj_t pyb_timer_make_new(const mp_obj_type_t *type, size_t n_args, siz
memset(tim, 0, sizeof(*tim));
tim->base.type = &pyb_timer_type;
tim->tim_id = tim_id;
+ #if defined(STM32L1)
+ tim->is_32bit = tim_id == 5;
+ #else
tim->is_32bit = tim_id == 2 || tim_id == 5;
+ #endif
tim->callback = mp_const_none;
uint32_t ti = tim_instance_table[tim_id - 1];
tim->tim.Instance = (TIM_TypeDef *)(ti & 0xffffff00);
@@ -1168,7 +1184,7 @@ STATIC mp_obj_t pyb_timer_channel(size_t n_args, const mp_obj_t *pos_args, mp_ma
}
oc_config.OCPolarity = TIM_OCPOLARITY_HIGH;
oc_config.OCFastMode = TIM_OCFAST_DISABLE;
- #if !defined(STM32L0)
+ #if !defined(STM32L0) && !defined(STM32L1)
oc_config.OCNPolarity = TIM_OCNPOLARITY_HIGH;
oc_config.OCIdleState = TIM_OCIDLESTATE_SET;
oc_config.OCNIdleState = TIM_OCNIDLESTATE_SET;
@@ -1180,7 +1196,7 @@ STATIC mp_obj_t pyb_timer_channel(size_t n_args, const mp_obj_t *pos_args, mp_ma
} else {
pyb_timer_channel_callback(MP_OBJ_FROM_PTR(chan), chan->callback);
}
- #if !defined(STM32L0)
+ #if !defined(STM32L0) && !defined(STM32L1)
// Start the complimentary channel too (if its supported)
if (IS_TIM_CCXN_INSTANCE(self->tim.Instance, TIMER_CHANNEL(chan))) {
HAL_TIMEx_PWMN_Start(&self->tim, TIMER_CHANNEL(chan));
@@ -1203,7 +1219,7 @@ STATIC mp_obj_t pyb_timer_channel(size_t n_args, const mp_obj_t *pos_args, mp_ma
oc_config.OCPolarity = TIM_OCPOLARITY_HIGH;
}
oc_config.OCFastMode = TIM_OCFAST_DISABLE;
- #if !defined(STM32L0)
+ #if !defined(STM32L0) && !defined(STM32L1)
if (oc_config.OCPolarity == TIM_OCPOLARITY_HIGH) {
oc_config.OCNPolarity = TIM_OCNPOLARITY_HIGH;
} else {
@@ -1222,7 +1238,7 @@ STATIC mp_obj_t pyb_timer_channel(size_t n_args, const mp_obj_t *pos_args, mp_ma
} else {
pyb_timer_channel_callback(MP_OBJ_FROM_PTR(chan), chan->callback);
}
- #if !defined(STM32L0)
+ #if !defined(STM32L0) && !defined(STM32L1)
// Start the complimentary channel too (if its supported)
if (IS_TIM_CCXN_INSTANCE(self->tim.Instance, TIMER_CHANNEL(chan))) {
HAL_TIMEx_OCN_Start(&self->tim, TIMER_CHANNEL(chan));
@@ -1471,13 +1487,14 @@ STATIC const mp_rom_map_elem_t pyb_timer_locals_dict_table[] = {
};
STATIC MP_DEFINE_CONST_DICT(pyb_timer_locals_dict, pyb_timer_locals_dict_table);
-const mp_obj_type_t pyb_timer_type = {
- { &mp_type_type },
- .name = MP_QSTR_Timer,
- .print = pyb_timer_print,
- .make_new = pyb_timer_make_new,
- .locals_dict = (mp_obj_dict_t *)&pyb_timer_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ pyb_timer_type,
+ MP_QSTR_Timer,
+ MP_TYPE_FLAG_NONE,
+ make_new, pyb_timer_make_new,
+ print, pyb_timer_print,
+ locals_dict, &pyb_timer_locals_dict
+ );
/// \moduleref pyb
/// \class TimerChannel - setup a channel for a timer.
@@ -1576,6 +1593,7 @@ STATIC mp_obj_t pyb_timer_channel_callback(mp_obj_t self_in, mp_obj_t callback)
switch (self->mode) {
case CHANNEL_MODE_PWM_NORMAL:
case CHANNEL_MODE_PWM_INVERTED:
+ HAL_TIM_PWM_Stop_IT(&self->timer->tim, TIMER_CHANNEL(self));
HAL_TIM_PWM_Start_IT(&self->timer->tim, TIMER_CHANNEL(self));
break;
case CHANNEL_MODE_OC_TIMING:
@@ -1584,9 +1602,11 @@ STATIC mp_obj_t pyb_timer_channel_callback(mp_obj_t self_in, mp_obj_t callback)
case CHANNEL_MODE_OC_TOGGLE:
case CHANNEL_MODE_OC_FORCED_ACTIVE:
case CHANNEL_MODE_OC_FORCED_INACTIVE:
+ HAL_TIM_OC_Stop_IT(&self->timer->tim, TIMER_CHANNEL(self));
HAL_TIM_OC_Start_IT(&self->timer->tim, TIMER_CHANNEL(self));
break;
case CHANNEL_MODE_IC:
+ HAL_TIM_IC_Stop_IT(&self->timer->tim, TIMER_CHANNEL(self));
HAL_TIM_IC_Start_IT(&self->timer->tim, TIMER_CHANNEL(self));
break;
}
@@ -1607,12 +1627,13 @@ STATIC const mp_rom_map_elem_t pyb_timer_channel_locals_dict_table[] = {
};
STATIC MP_DEFINE_CONST_DICT(pyb_timer_channel_locals_dict, pyb_timer_channel_locals_dict_table);
-STATIC const mp_obj_type_t pyb_timer_channel_type = {
- { &mp_type_type },
- .name = MP_QSTR_TimerChannel,
- .print = pyb_timer_channel_print,
- .locals_dict = (mp_obj_dict_t *)&pyb_timer_channel_locals_dict,
-};
+STATIC MP_DEFINE_CONST_OBJ_TYPE(
+ pyb_timer_channel_type,
+ MP_QSTR_TimerChannel,
+ MP_TYPE_FLAG_NONE,
+ print, pyb_timer_channel_print,
+ locals_dict, &pyb_timer_channel_locals_dict
+ );
STATIC void timer_handle_irq_channel(pyb_timer_obj_t *tim, uint8_t channel, mp_obj_t callback) {
uint32_t irq_mask = TIMER_IRQ_MASK(channel);
@@ -1684,3 +1705,5 @@ void timer_irq_handler(uint tim_id) {
}
}
}
+
+MP_REGISTER_ROOT_POINTER(struct _pyb_timer_obj_t *pyb_timer_obj_all[MICROPY_HW_MAX_TIMER]);
diff --git a/ports/stm32/uart.c b/ports/stm32/uart.c
index adcbe883686e..6d1240cf8d5a 100644
--- a/ports/stm32/uart.c
+++ b/ports/stm32/uart.c
@@ -38,7 +38,7 @@
#include "irq.h"
#include "pendsv.h"
-#if defined(STM32F4)
+#if defined(STM32F4) || defined(STM32L1)
#define UART_RXNE_IS_SET(uart) ((uart)->SR & USART_SR_RXNE)
#else
#if defined(STM32G0) || defined(STM32H7) || defined(STM32WL)
@@ -101,6 +101,11 @@
#define USART_CR2_IE_ALL (USART_CR2_IE_BASE)
#define USART_CR3_IE_ALL (USART_CR3_IE_BASE | USART_CR3_WUFIE)
+#elif defined(STM32L1)
+#define USART_CR1_IE_ALL (USART_CR1_IE_BASE)
+#define USART_CR2_IE_ALL (USART_CR2_IE_BASE)
+#define USART_CR3_IE_ALL (USART_CR3_IE_BASE)
+
#elif defined(STM32L4) || defined(STM32WB) || defined(STM32WL)
#define USART_CR1_IE_ALL (USART_CR1_IE_BASE | USART_CR1_EOBIE | USART_CR1_RTOIE | USART_CR1_CMIE)
#define USART_CR2_IE_ALL (USART_CR2_IE_BASE)
@@ -112,8 +117,6 @@
#endif
-extern void NORETURN __fatal_error(const char *msg);
-
typedef struct _pyb_uart_irq_map_t {
uint16_t irq_en;
uint16_t flag;
@@ -152,7 +155,7 @@ void uart_init0(void) {
RCC_PeriphClkInit.Usart16ClockSelection = RCC_USART16CLKSOURCE_D2PCLK2;
RCC_PeriphClkInit.Usart234578ClockSelection = RCC_USART234578CLKSOURCE_D2PCLK1;
if (HAL_RCCEx_PeriphCLKConfig(&RCC_PeriphClkInit) != HAL_OK) {
- __fatal_error("HAL_RCCEx_PeriphCLKConfig");
+ MICROPY_BOARD_FATAL_ERROR("HAL_RCCEx_PeriphCLKConfig");
}
#endif
}
@@ -582,7 +585,7 @@ bool uart_init(pyb_uart_obj_t *uart_obj,
huart.FifoMode = UART_FIFOMODE_ENABLE;
#endif
- #if !defined(STM32F4)
+ #if !defined(STM32F4) && !defined(STM32L1)
huart.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
#endif
@@ -1018,7 +1021,7 @@ STATIC bool uart_wait_flag_set(pyb_uart_obj_t *self, uint32_t flag, uint32_t tim
// an interrupt and the flag can be set quickly if the baudrate is large.
uint32_t start = HAL_GetTick();
for (;;) {
- #if defined(STM32F4)
+ #if defined(STM32F4) || defined(STM32L1)
if (self->uartx->SR & flag) {
return true;
}
@@ -1073,7 +1076,7 @@ size_t uart_tx_data(pyb_uart_obj_t *self, const void *src_in, size_t num_chars,
} else {
data = *src++;
}
- #if defined(STM32F4)
+ #if defined(STM32F4) || defined(STM32L1)
uart->DR = data;
#else
uart->TDR = data;
@@ -1111,7 +1114,7 @@ void uart_irq_handler(mp_uint_t uart_id) {
}
// Capture IRQ status flags.
- #if defined(STM32F4)
+ #if defined(STM32F4) || defined(STM32L1)
self->mp_irq_flags = self->uartx->SR;
bool rxne_is_set = self->mp_irq_flags & USART_SR_RXNE;
bool did_clear_sr = false;
@@ -1155,7 +1158,7 @@ void uart_irq_handler(mp_uint_t uart_id) {
}
// Clear other interrupt flags that can trigger this IRQ handler.
- #if defined(STM32F4)
+ #if defined(STM32F4) || defined(STM32L1)
if (did_clear_sr) {
// SR was cleared above. Re-enable IDLE if it should be enabled.
if (self->mp_irq_trigger & UART_FLAG_IDLE) {
@@ -1204,3 +1207,5 @@ const mp_irq_methods_t uart_irq_methods = {
.trigger = uart_irq_trigger,
.info = uart_irq_info,
};
+
+MP_REGISTER_ROOT_POINTER(struct _pyb_uart_obj_t *pyb_uart_obj_all[MICROPY_HW_MAX_UART + MICROPY_HW_MAX_LPUART]);
diff --git a/ports/stm32/uart.h b/ports/stm32/uart.h
index ec8a27591c1e..61d1ac439790 100644
--- a/ports/stm32/uart.h
+++ b/ports/stm32/uart.h
@@ -103,7 +103,7 @@ size_t uart_tx_data(pyb_uart_obj_t *self, const void *src_in, size_t num_chars,
void uart_tx_strn(pyb_uart_obj_t *uart_obj, const char *str, uint len);
static inline bool uart_tx_avail(pyb_uart_obj_t *self) {
- #if defined(STM32F4)
+ #if defined(STM32F4) || defined(STM32L1)
return self->uartx->SR & USART_SR_TXE;
#elif defined(STM32G0) || defined(STM32H7) || defined(STM32WL)
return self->uartx->ISR & USART_ISR_TXE_TXFNF;
diff --git a/ports/stm32/usb.c b/ports/stm32/usb.c
index 9a9600f89d6c..87306075a9af 100644
--- a/ports/stm32/usb.c
+++ b/ports/stm32/usb.c
@@ -67,7 +67,7 @@
#define MAX_ENDPOINT(dev_id) ((dev_id) == USB_PHY_FS_ID ? 3 : 5)
#elif defined(STM32F7)
#define MAX_ENDPOINT(dev_id) ((dev_id) == USB_PHY_FS_ID ? 5 : 8)
-#elif defined(STM32H7)
+#elif defined(STM32G0) || defined(STM32H7)
#define MAX_ENDPOINT(dev_id) (8)
#endif
@@ -367,6 +367,24 @@ usbd_cdc_itf_t *usb_vcp_get(int idx) {
return &usb_device.usbd_cdc_itf[idx];
}
+#if MICROPY_HW_USB_HID
+
+// return hid interface if hid is configured, NULL otherwise
+usbd_hid_itf_t *usbd_hid_get(void) {
+ #if defined(USE_HOST_MODE)
+ return NULL;
+ #else
+ uint8_t usb_mode = USBD_GetMode(&usb_device.usbd_cdc_msc_hid_state) & USBD_MODE_IFACE_MASK;
+ if (usb_mode == USBD_MODE_HID || usb_mode == USBD_MODE_CDC_HID || usb_mode == USBD_MODE_MSC_HID) {
+ return &usb_device.usbd_hid_itf;
+ } else {
+ return NULL;
+ }
+ #endif
+}
+
+#endif
+
/******************************************************************************/
// MicroPython bindings for USB
@@ -795,7 +813,7 @@ STATIC mp_obj_t pyb_usb_vcp_recv(size_t n_args, const mp_obj_t *args, mp_map_t *
return mp_obj_new_int(ret); // number of bytes read into given buffer
} else {
vstr.len = ret; // set actual number of bytes read
- return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); // create a new buffer
+ return mp_obj_new_bytes_from_vstr(&vstr); // create a new buffer
}
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_usb_vcp_recv_obj, 1, pyb_usb_vcp_recv);
@@ -918,16 +936,15 @@ STATIC const mp_stream_p_t pyb_usb_vcp_stream_p = {
.ioctl = pyb_usb_vcp_ioctl,
};
-const mp_obj_type_t pyb_usb_vcp_type = {
- { &mp_type_type },
- .name = MP_QSTR_USB_VCP,
- .print = pyb_usb_vcp_print,
- .make_new = pyb_usb_vcp_make_new,
- .getiter = mp_identity_getiter,
- .iternext = mp_stream_unbuffered_iter,
- .protocol = &pyb_usb_vcp_stream_p,
- .locals_dict = (mp_obj_dict_t *)&pyb_usb_vcp_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ pyb_usb_vcp_type,
+ MP_QSTR_USB_VCP,
+ MP_TYPE_FLAG_ITER_IS_STREAM,
+ make_new, pyb_usb_vcp_make_new,
+ print, pyb_usb_vcp_print,
+ protocol, &pyb_usb_vcp_stream_p,
+ locals_dict, &pyb_usb_vcp_locals_dict
+ );
/******************************************************************************/
// MicroPython bindings for USB HID
@@ -989,7 +1006,7 @@ STATIC mp_obj_t pyb_usb_hid_recv(size_t n_args, const mp_obj_t *args, mp_map_t *
return mp_obj_new_int(ret); // number of bytes read into given buffer
} else {
vstr.len = ret; // set actual number of bytes read
- return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); // create a new buffer
+ return mp_obj_new_bytes_from_vstr(&vstr); // create a new buffer
}
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_usb_hid_recv_obj, 1, pyb_usb_hid_recv);
@@ -1059,13 +1076,14 @@ STATIC const mp_stream_p_t pyb_usb_hid_stream_p = {
.ioctl = pyb_usb_hid_ioctl,
};
-const mp_obj_type_t pyb_usb_hid_type = {
- { &mp_type_type },
- .name = MP_QSTR_USB_HID,
- .make_new = pyb_usb_hid_make_new,
- .protocol = &pyb_usb_hid_stream_p,
- .locals_dict = (mp_obj_dict_t *)&pyb_usb_hid_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ pyb_usb_hid_type,
+ MP_QSTR_USB_HID,
+ MP_TYPE_FLAG_NONE,
+ make_new, pyb_usb_hid_make_new,
+ protocol, &pyb_usb_hid_stream_p,
+ locals_dict, &pyb_usb_hid_locals_dict
+ );
#endif // MICROPY_HW_USB_HID
@@ -1134,4 +1152,9 @@ void USR_KEYBRD_ProcessData(uint8_t pbuf) {
#endif // USE_HOST_MODE
+#if MICROPY_HW_USB_HID
+MP_REGISTER_ROOT_POINTER(mp_obj_t pyb_hid_report_desc);
+#endif
+MP_REGISTER_ROOT_POINTER(mp_obj_t pyb_usb_vcp_irq[MICROPY_HW_USB_CDC_NUM]);
+
#endif // MICROPY_HW_ENABLE_USB
diff --git a/ports/stm32/usbd_cdc_interface.c b/ports/stm32/usbd_cdc_interface.c
index b369524ca7ef..5432370a7468 100644
--- a/ports/stm32/usbd_cdc_interface.c
+++ b/ports/stm32/usbd_cdc_interface.c
@@ -42,12 +42,23 @@
#include "usbd_cdc_interface.h"
#include "pendsv.h"
-#include "py/obj.h"
+#include "py/runtime.h"
+#include "py/mphal.h"
#include "shared/runtime/interrupt_char.h"
#include "irq.h"
+#include "modmachine.h"
#if MICROPY_HW_ENABLE_USB
+#if !MICROPY_HW_USB_IS_MULTI_OTG
+#define USE_USB_CNTR_SOFM (1)
+#elif defined(STM32G0)
+#define USE_USB_CNTR_SOFM (1)
+#define USB USB_DRD_FS
+#else
+#define USE_USB_CNTR_SOFM (0)
+#endif
+
// CDC control commands
#define CDC_SEND_ENCAPSULATED_COMMAND 0x00
#define CDC_GET_ENCAPSULATED_RESPONSE 0x01
@@ -62,6 +73,14 @@
// Used to control the connect_state variable when USB host opens the serial port
static uint8_t usbd_cdc_connect_tx_timer;
+#if MICROPY_HW_USB_CDC_1200BPS_TOUCH
+static mp_sched_node_t mp_bootloader_sched_node;
+STATIC void usbd_cdc_run_bootloader_task(mp_sched_node_t *node) {
+ mp_hal_delay_ms(250);
+ machine_bootloader(0, NULL);
+}
+#endif
+
uint8_t *usbd_cdc_init(usbd_cdc_state_t *cdc_in) {
usbd_cdc_itf_t *cdc = (usbd_cdc_itf_t *)cdc_in;
@@ -81,6 +100,7 @@ uint8_t *usbd_cdc_init(usbd_cdc_state_t *cdc_in) {
} else {
cdc->flow |= USBD_CDC_FLOWCONTROL_CTS;
}
+ cdc->bitrate = 0;
// Return the buffer to place the first USB OUT packet
return cdc->rx_packet_buf;
@@ -121,22 +141,14 @@ int8_t usbd_cdc_control(usbd_cdc_state_t *cdc_in, uint8_t cmd, uint8_t *pbuf, ui
break;
case CDC_SET_LINE_CODING:
- #if 0
- LineCoding.bitrate = (uint32_t)(pbuf[0] | (pbuf[1] << 8) | \
- (pbuf[2] << 16) | (pbuf[3] << 24));
- LineCoding.format = pbuf[4];
- LineCoding.paritytype = pbuf[5];
- LineCoding.datatype = pbuf[6];
- /* Set the new configuration */
- #endif
+ cdc->bitrate = *((uint32_t *)pbuf);
break;
case CDC_GET_LINE_CODING:
- /* Add your code here */
- pbuf[0] = (uint8_t)(115200);
- pbuf[1] = (uint8_t)(115200 >> 8);
- pbuf[2] = (uint8_t)(115200 >> 16);
- pbuf[3] = (uint8_t)(115200 >> 24);
+ pbuf[0] = (uint8_t)(cdc->bitrate);
+ pbuf[1] = (uint8_t)(cdc->bitrate >> 8);
+ pbuf[2] = (uint8_t)(cdc->bitrate >> 16);
+ pbuf[3] = (uint8_t)(cdc->bitrate >> 24);
pbuf[4] = 0; // stop bits (1)
pbuf[5] = 0; // parity (none)
pbuf[6] = 8; // number of bits (8)
@@ -149,7 +161,7 @@ int8_t usbd_cdc_control(usbd_cdc_state_t *cdc_in, uint8_t cmd, uint8_t *pbuf, ui
// configure its serial port (in most cases to disable local echo)
cdc->connect_state = USBD_CDC_CONNECT_STATE_CONNECTING;
usbd_cdc_connect_tx_timer = 8; // wait for 8 SOF IRQs
- #if !MICROPY_HW_USB_IS_MULTI_OTG
+ #if USE_USB_CNTR_SOFM
USB->CNTR |= USB_CNTR_SOFM;
#else
PCD_HandleTypeDef *hpcd = cdc->base.usbd->pdev->pData;
@@ -157,6 +169,12 @@ int8_t usbd_cdc_control(usbd_cdc_state_t *cdc_in, uint8_t cmd, uint8_t *pbuf, ui
#endif
} else {
cdc->connect_state = USBD_CDC_CONNECT_STATE_DISCONNECTED;
+ #if MICROPY_HW_USB_CDC_1200BPS_TOUCH
+ if (cdc->bitrate == 1200) {
+ // Delay bootloader jump to allow the USB stack to service endpoints.
+ mp_sched_schedule_node(&mp_bootloader_sched_node, usbd_cdc_run_bootloader_task);
+ }
+ #endif
}
break;
}
@@ -254,7 +272,7 @@ void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd) {
--usbd_cdc_connect_tx_timer;
} else {
usbd_cdc_msc_hid_state_t *usbd = ((USBD_HandleTypeDef *)hpcd->pData)->pClassData;
- #if !MICROPY_HW_USB_IS_MULTI_OTG
+ #if USE_USB_CNTR_SOFM
USB->CNTR &= ~USB_CNTR_SOFM;
#else
hpcd->Instance->GINTMSK &= ~USB_OTG_GINTMSK_SOFM;
diff --git a/ports/stm32/usbd_cdc_interface.h b/ports/stm32/usbd_cdc_interface.h
index 76b5c9e79bb4..2daa43a521a2 100644
--- a/ports/stm32/usbd_cdc_interface.h
+++ b/ports/stm32/usbd_cdc_interface.h
@@ -62,6 +62,7 @@ typedef struct _usbd_cdc_itf_t {
volatile uint8_t connect_state; // indicates if we are connected
uint8_t attached_to_repl; // indicates if interface is connected to REPL
uint8_t flow; // USBD_CDC_FLOWCONTROL_* setting flags
+ uint32_t bitrate;
} usbd_cdc_itf_t;
// This is implemented in usb.c
diff --git a/ports/stm32/usbd_conf.c b/ports/stm32/usbd_conf.c
index d0f519d45670..3891d09ce169 100644
--- a/ports/stm32/usbd_conf.c
+++ b/ports/stm32/usbd_conf.c
@@ -49,6 +49,10 @@ PCD_HandleTypeDef pcd_hs_handle;
#define USB_OTG_FS USB
#endif
+#if defined(STM32G0)
+#define USB_OTG_FS USB_DRD_FS
+#endif
+
/*******************************************************************************
PCD BSP Routines
*******************************************************************************/
@@ -61,6 +65,22 @@ PCD_HandleTypeDef pcd_hs_handle;
void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd) {
#if MICROPY_HW_USB_FS
if (hpcd->Instance == USB_OTG_FS) {
+ // Configure USB GPIO's.
+
+ #if defined(STM32G0)
+
+ // These MCUs don't have an alternate function for USB but rather require
+ // the pins to be disconnected from all peripherals, ie put in analog mode.
+
+ mp_hal_pin_config(pin_A11, MP_HAL_PIN_MODE_ANALOG, MP_HAL_PIN_PULL_NONE, 0);
+ mp_hal_pin_config_speed(pin_A11, GPIO_SPEED_FREQ_VERY_HIGH);
+ mp_hal_pin_config(pin_A12, MP_HAL_PIN_MODE_ANALOG, MP_HAL_PIN_PULL_NONE, 0);
+ mp_hal_pin_config_speed(pin_A12, GPIO_SPEED_FREQ_VERY_HIGH);
+
+ #else
+
+ // Other MCUs have an alternate function for GPIO's to be in USB mode.
+
#if defined(STM32H7)
const uint32_t otg_alt = GPIO_AF10_OTG1_FS;
#elif defined(STM32L0)
@@ -78,6 +98,8 @@ void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd) {
mp_hal_pin_config(pin_A12, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, otg_alt);
mp_hal_pin_config_speed(pin_A12, GPIO_SPEED_FREQ_VERY_HIGH);
+ #endif
+
#if defined(MICROPY_HW_USB_VBUS_DETECT_PIN)
// USB VBUS detect pin is always A9
mp_hal_pin_config(MICROPY_HW_USB_VBUS_DETECT_PIN, MP_HAL_PIN_MODE_INPUT, MP_HAL_PIN_PULL_NONE, 0);
@@ -88,14 +110,16 @@ void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd) {
mp_hal_pin_config(MICROPY_HW_USB_OTG_ID_PIN, MP_HAL_PIN_MODE_ALT_OPEN_DRAIN, MP_HAL_PIN_PULL_UP, otg_alt);
#endif
- #if defined(STM32H7)
+ #if defined(STM32G0)
+ __HAL_RCC_USB_CLK_SLEEP_ENABLE();
+ #elif defined(STM32H7)
// Keep USB clock running during sleep or else __WFI() will disable the USB
__HAL_RCC_USB2_OTG_FS_CLK_SLEEP_ENABLE();
__HAL_RCC_USB2_OTG_FS_ULPI_CLK_SLEEP_DISABLE();
#endif
// Enable USB FS Clocks
- #if !MICROPY_HW_USB_IS_MULTI_OTG
+ #if !MICROPY_HW_USB_IS_MULTI_OTG || defined(STM32G0)
__HAL_RCC_USB_CLK_ENABLE();
#else
__USB_OTG_FS_CLK_ENABLE();
@@ -113,7 +137,10 @@ void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd) {
#endif
// Configure and enable USB FS interrupt
- #if defined(STM32L0)
+ #if defined(STM32G0)
+ NVIC_SetPriority(USB_UCPD1_2_IRQn, IRQ_PRI_OTG_FS);
+ HAL_NVIC_EnableIRQ(USB_UCPD1_2_IRQn);
+ #elif defined(STM32L0)
NVIC_SetPriority(USB_IRQn, IRQ_PRI_OTG_FS);
HAL_NVIC_EnableIRQ(USB_IRQn);
#elif defined(STM32L432xx)
@@ -135,6 +162,26 @@ void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd) {
if (hpcd->Instance == USB_OTG_HS) {
#if MICROPY_HW_USB_HS_IN_FS
+ // Configure USB GPIO's.
+
+ #if defined(STM32H723xx)
+
+ // These MCUs don't have an alternate function for USB but rather require
+ // the pins to be disconnected from all peripherals, ie put in analog mode.
+
+ #if defined(MICROPY_HW_USB_OTG_ID_PIN)
+ const uint32_t otg_alt = GPIO_AF10_OTG1_FS;
+ #endif
+
+ mp_hal_pin_config(pin_A11, MP_HAL_PIN_MODE_ANALOG, MP_HAL_PIN_PULL_NONE, 0);
+ mp_hal_pin_config_speed(pin_A11, GPIO_SPEED_FREQ_VERY_HIGH);
+ mp_hal_pin_config(pin_A12, MP_HAL_PIN_MODE_ANALOG, MP_HAL_PIN_PULL_NONE, 0);
+ mp_hal_pin_config_speed(pin_A12, GPIO_SPEED_FREQ_VERY_HIGH);
+
+ #else
+
+ // Other MCUs have an alternate function for GPIO's to be in USB mode.
+
#if defined(STM32H7A3xx) || defined(STM32H7A3xxQ) || defined(STM32H7B3xx) || defined(STM32H7B3xxQ)
const uint32_t otg_alt = GPIO_AF10_OTG1_FS;
#elif defined(STM32H7)
@@ -143,12 +190,13 @@ void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd) {
const uint32_t otg_alt = GPIO_AF12_OTG_HS_FS;
#endif
- // Configure USB FS GPIOs
mp_hal_pin_config(pin_B14, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, otg_alt);
mp_hal_pin_config_speed(pin_B14, GPIO_SPEED_FREQ_VERY_HIGH);
mp_hal_pin_config(pin_B15, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, otg_alt);
mp_hal_pin_config_speed(pin_B15, GPIO_SPEED_FREQ_VERY_HIGH);
+ #endif
+
#if defined(MICROPY_HW_USB_VBUS_DETECT_PIN)
// Configure VBUS Pin
mp_hal_pin_config(MICROPY_HW_USB_VBUS_DETECT_PIN, MP_HAL_PIN_MODE_INPUT, MP_HAL_PIN_PULL_NONE, 0);
@@ -214,7 +262,11 @@ void HAL_PCD_MspDeInit(PCD_HandleTypeDef *hpcd) {
#if MICROPY_HW_USB_FS
if (hpcd->Instance == USB_OTG_FS) {
/* Disable USB FS Clocks */
+ #if defined(STM32G0)
+ __HAL_RCC_USB_CLK_DISABLE();
+ #else
__USB_OTG_FS_CLK_DISABLE();
+ #endif
return;
}
#endif
@@ -392,7 +444,9 @@ USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev, int high_speed, const
pcd_fs_handle.Init.lpm_enable = DISABLE;
pcd_fs_handle.Init.battery_charging_enable = DISABLE;
#if MICROPY_HW_USB_IS_MULTI_OTG
+ #if !defined(STM32G0)
pcd_fs_handle.Init.use_dedicated_ep1 = 0;
+ #endif
pcd_fs_handle.Init.dma_enable = 0;
#if !defined(MICROPY_HW_USB_VBUS_DETECT_PIN)
pcd_fs_handle.Init.vbus_sensing_enable = 0; // No VBUS Sensing on USB0
@@ -409,7 +463,7 @@ USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev, int high_speed, const
HAL_PCD_Init(&pcd_fs_handle);
// Set FIFO buffer sizes
- #if !MICROPY_HW_USB_IS_MULTI_OTG
+ #if !MICROPY_HW_USB_IS_MULTI_OTG || defined(STM32G0)
uint32_t fifo_offset = USBD_PMA_RESERVE; // need to reserve some data at start of FIFO
for (size_t i = 0; i < USBD_PMA_NUM_FIFO; ++i) {
uint16_t ep_addr = ((i & 1) * 0x80) | (i >> 1);
diff --git a/ports/stm32/usbd_desc.c b/ports/stm32/usbd_desc.c
index fd50029fc5ac..3f6b74b800cb 100644
--- a/ports/stm32/usbd_desc.c
+++ b/ports/stm32/usbd_desc.c
@@ -156,6 +156,24 @@ STATIC uint8_t *USBD_StrDescriptor(USBD_HandleTypeDef *pdev, uint8_t idx, uint16
}
break;
+ #ifdef MICROPY_HW_USB_INTERFACE_CDC0_STRING
+ case USBD_IDX_INTERFACE_CDC0_STR:
+ str = MICROPY_HW_USB_INTERFACE_CDC0_STRING;
+ break;
+ #endif
+
+ #ifdef MICROPY_HW_USB_INTERFACE_CDC1_STRING
+ case USBD_IDX_INTERFACE_CDC1_STR:
+ str = MICROPY_HW_USB_INTERFACE_CDC1_STRING;
+ break;
+ #endif
+
+ #ifdef MICROPY_HW_USB_INTERFACE_CDC2_STRING
+ case USBD_IDX_INTERFACE_CDC2_STR:
+ str = MICROPY_HW_USB_INTERFACE_CDC2_STRING;
+ break;
+ #endif
+
default:
// invalid string index
return NULL;
diff --git a/ports/stm32/usbd_hid_interface.h b/ports/stm32/usbd_hid_interface.h
index 5d2c9ad870f1..b97d273f1528 100644
--- a/ports/stm32/usbd_hid_interface.h
+++ b/ports/stm32/usbd_hid_interface.h
@@ -16,6 +16,8 @@ typedef struct _usbd_hid_itf_t {
uint8_t report_in_buf[HID_DATA_FS_MAX_PACKET_SIZE];
} usbd_hid_itf_t;
+usbd_hid_itf_t *usbd_hid_get(void);
+
static inline int usbd_hid_rx_num(usbd_hid_itf_t *hid) {
return hid->report_in_len != USBD_HID_REPORT_INVALID;
}
diff --git a/ports/stm32/usbdev/class/src/usbd_cdc_msc_hid.c b/ports/stm32/usbdev/class/src/usbd_cdc_msc_hid.c
index 5e24730a0fac..c32c20ab58c6 100644
--- a/ports/stm32/usbdev/class/src/usbd_cdc_msc_hid.c
+++ b/ports/stm32/usbdev/class/src/usbd_cdc_msc_hid.c
@@ -438,6 +438,23 @@ static size_t make_cdc_desc(uint8_t *dest, int need_iad, uint8_t iface_num) {
memcpy(dest, cdc_class_desc_data + 8, sizeof(cdc_class_desc_data) - 8);
}
dest[2] = iface_num; // bInterfaceNumber, main class
+
+ #ifdef MICROPY_HW_USB_INTERFACE_CDC0_STRING
+ if (iface_num == CDC_IFACE_NUM_ALONE || iface_num == CDC_IFACE_NUM_WITH_MSC || iface_num == CDC_IFACE_NUM_WITH_HID) {
+ dest[8] = USBD_IDX_INTERFACE_CDC0_STR; // iInterface
+ }
+ #endif
+ #ifdef MICROPY_HW_USB_INTERFACE_CDC1_STRING
+ if (iface_num == CDC2_IFACE_NUM_WITH_CDC || iface_num == CDC2_IFACE_NUM_WITH_MSC) {
+ dest[8] = USBD_IDX_INTERFACE_CDC1_STR; // iInterface
+ }
+ #endif
+ #ifdef MICROPY_HW_USB_INTERFACE_CDC2_STRING
+ if (iface_num == CDC3_IFACE_NUM_WITH_CDC || iface_num == CDC3_IFACE_NUM_WITH_MSC) {
+ dest[8] = USBD_IDX_INTERFACE_CDC2_STR; // iInterface
+ }
+ #endif
+
dest[18] = iface_num + 1; // bDataInterface
dest[26] = iface_num + 0; // bMasterInterface
dest[27] = iface_num + 1; // bSlaveInterface
@@ -804,23 +821,6 @@ static uint8_t USBD_CDC_MSC_HID_DeInit(USBD_HandleTypeDef *pdev, uint8_t cfgidx)
}
static uint8_t USBD_CDC_MSC_HID_Setup(USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req) {
-
- /*
- printf("SU: %x %x %x %x\n", req->bmRequest, req->bRequest, req->wValue, req->wIndex);
-
- This is what we get when MSC is IFACE=0 and CDC is IFACE=1,2:
- SU: 21 22 0 1 -- USB_REQ_TYPE_CLASS | USB_REQ_RECIPIENT_INTERFACE; CDC_SET_CONTROL_LINE_STATE
- SU: 21 20 0 1 -- USB_REQ_TYPE_CLASS | USB_REQ_RECIPIENT_INTERFACE; CDC_SET_LINE_CODING
- SU: a1 fe 0 0 -- 0x80 | USB_REQ_TYPE_CLASS | USB_REQ_RECIPIENT_INTERFACE; BOT_GET_MAX_LUN; 0; 0
- SU: 21 22 3 1 -- USB_REQ_TYPE_CLASS | USB_REQ_RECIPIENT_INTERFACE; CDC_SET_CONTROL_LINE_STATE
-
- On a Mac OS X, with MSC then CDC:
- SU: a1 fe 0 0
- SU: 21 22 2 1
- SU: 21 22 3 1
- SU: 21 20 0 1
- */
-
usbd_cdc_msc_hid_state_t *usbd = pdev->pClassData;
// Work out the recipient of the setup request
diff --git a/ports/stm32/usbdev/class/src/usbd_msc_scsi.c b/ports/stm32/usbdev/class/src/usbd_msc_scsi.c
index 2eb716ccde43..78c8c5af1991 100644
--- a/ports/stm32/usbdev/class/src/usbd_msc_scsi.c
+++ b/ports/stm32/usbdev/class/src/usbd_msc_scsi.c
@@ -123,12 +123,6 @@ int8_t SCSI_ProcessCmd(USBD_HandleTypeDef *pdev,
uint8_t lun,
uint8_t *params)
{
- /*
- if (params[0] != SCSI_READ10 && params[0] != SCSI_WRITE10) {
- printf("SCSI_ProcessCmd(lun=%d, params=%x, %x)\n", lun, params[0], params[1]);
- }
- */
-
switch (params[0])
{
case SCSI_TEST_UNIT_READY:
diff --git a/ports/stm32/usbdev/core/inc/usbd_def.h b/ports/stm32/usbdev/core/inc/usbd_def.h
index 44c8dd8d93b2..fb29d57056b1 100644
--- a/ports/stm32/usbdev/core/inc/usbd_def.h
+++ b/ports/stm32/usbdev/core/inc/usbd_def.h
@@ -66,6 +66,9 @@
#define USBD_IDX_SERIAL_STR 0x03
#define USBD_IDX_CONFIG_STR 0x04
#define USBD_IDX_INTERFACE_STR 0x05
+#define USBD_IDX_INTERFACE_CDC0_STR 0x06
+#define USBD_IDX_INTERFACE_CDC1_STR 0x07
+#define USBD_IDX_INTERFACE_CDC2_STR 0x08
#define USB_REQ_TYPE_STANDARD 0x00
#define USB_REQ_TYPE_CLASS 0x20
diff --git a/ports/stm32/usrsw.c b/ports/stm32/usrsw.c
index 596efba0530a..170c01bd6d04 100644
--- a/ports/stm32/usrsw.c
+++ b/ports/stm32/usrsw.c
@@ -134,13 +134,16 @@ STATIC const mp_rom_map_elem_t pyb_switch_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(pyb_switch_locals_dict, pyb_switch_locals_dict_table);
-const mp_obj_type_t pyb_switch_type = {
- { &mp_type_type },
- .name = MP_QSTR_Switch,
- .print = pyb_switch_print,
- .make_new = pyb_switch_make_new,
- .call = pyb_switch_call,
- .locals_dict = (mp_obj_dict_t *)&pyb_switch_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ pyb_switch_type,
+ MP_QSTR_Switch,
+ MP_TYPE_FLAG_NONE,
+ make_new, pyb_switch_make_new,
+ print, pyb_switch_print,
+ call, pyb_switch_call,
+ locals_dict, &pyb_switch_locals_dict
+ );
+
+MP_REGISTER_ROOT_POINTER(mp_obj_t pyb_switch_callback);
#endif // MICROPY_HW_HAS_SWITCH
diff --git a/ports/stm32/wdt.c b/ports/stm32/wdt.c
index d794607bc0a7..e541e4d36b4f 100644
--- a/ports/stm32/wdt.c
+++ b/ports/stm32/wdt.c
@@ -102,9 +102,10 @@ STATIC const mp_rom_map_elem_t pyb_wdt_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(pyb_wdt_locals_dict, pyb_wdt_locals_dict_table);
-const mp_obj_type_t pyb_wdt_type = {
- { &mp_type_type },
- .name = MP_QSTR_WDT,
- .make_new = pyb_wdt_make_new,
- .locals_dict = (mp_obj_dict_t *)&pyb_wdt_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ pyb_wdt_type,
+ MP_QSTR_WDT,
+ MP_TYPE_FLAG_NONE,
+ make_new, pyb_wdt_make_new,
+ locals_dict, &pyb_wdt_locals_dict
+ );
diff --git a/ports/teensy/Makefile b/ports/teensy/Makefile
index fe46b0e061a2..70331c5dc704 100644
--- a/ports/teensy/Makefile
+++ b/ports/teensy/Makefile
@@ -1,7 +1,7 @@
include ../../py/mkenv.mk
# qstr definitions (must come before including py.mk)
-QSTR_DEFS = qstrdefsport.h $(BUILD)/pins_qstr.h
+QSTR_DEFS = qstrdefsport.h $(GEN_PINS_QSTR)
# MicroPython feature configurations
MICROPY_ROM_TEXT_COMPRESSION ?= 1
@@ -44,6 +44,7 @@ endif # USE_FROZEN
# include py core make definitions
include $(TOP)/py/py.mk
+include $(TOP)/extmod/extmod.mk
# If you set USE_ARDUINO_TOOLCHAIN=1 then this makefile will attempt to use
# the toolchain that comes with Teensyduino
@@ -65,6 +66,16 @@ $(info Using toolchain from PATH)
CROSS_COMPILE ?= arm-none-eabi-
endif
+MAKE_PINS = make-pins.py
+BOARD_PINS = teensy_pins.csv
+AF_FILE = mk20dx256_af.csv
+PREFIX_FILE = mk20dx256_prefix.c
+GEN_PINS_SRC = $(BUILD)/pins_gen.c
+GEN_PINS_HDR = $(HEADER_BUILD)/pins.h
+GEN_PINS_QSTR = $(BUILD)/pins_qstr.h
+GEN_PINS_AF_CONST = $(HEADER_BUILD)/pins_af_const.h
+GEN_PINS_AF_PY = $(BUILD)/pins_af.py
+
CFLAGS_TEENSY = -DF_CPU=96000000 -DUSB_SERIAL -D__MK20DX256__
CFLAGS_CORTEX_M4 = -mthumb -mtune=cortex-m4 -mcpu=cortex-m4 -msoft-float -mfloat-abi=soft -fsingle-precision-constant -Wdouble-promotion $(CFLAGS_TEENSY)
@@ -74,8 +85,8 @@ INC += -I$(TOP)/ports/stm32
INC += -I$(BUILD)
INC += -Icore
-CFLAGS = $(INC) -Wall -Wpointer-arith -Werror -std=c99 -nostdlib $(CFLAGS_CORTEX_M4)
-LDFLAGS = -nostdlib -T mk20dx256.ld -msoft-float -mfloat-abi=soft
+CFLAGS += $(INC) -Wall -Wpointer-arith -Werror -std=c99 -nostdlib $(CFLAGS_CORTEX_M4)
+LDFLAGS += -nostdlib -T mk20dx256.ld -msoft-float -mfloat-abi=soft
ifeq ($(USE_ARDUINO_TOOLCHAIN),1)
@@ -104,8 +115,9 @@ LIBS += -L $(dir $(LIBC_FILE_NAME)) -lc
LIBS += -L $(dir $(LIBGCC_FILE_NAME)) -lgcc
#Debugging/Optimization
+CFLAGS += -g # always include debug info in the ELF
ifdef DEBUG
-CFLAGS += -Og -ggdb
+CFLAGS += -Og
else
CFLAGS += -Os #-DNDEBUG
endif
@@ -152,10 +164,13 @@ SRC_TEENSY = $(addprefix core/,\
yield.c \
)
-OBJ = $(PY_O) $(addprefix $(BUILD)/, $(SRC_C:.c=.o) $(STM_SRC_C:.c=.o) $(SRC_TEENSY:.c=.o))
+OBJ += $(PY_O)
+OBJ += $(addprefix $(BUILD)/, $(SRC_C:.c=.o))
+OBJ += $(addprefix $(BUILD)/, $(STM_SRC_C:.c=.o))
+OBJ += $(addprefix $(BUILD)/, $(SRC_TEENSY:.c=.o))
OBJ += $(addprefix $(BUILD)/, $(SHARED_SRC_C:.c=.o))
-OBJ += $(BUILD)/shared/runtime/gchelper_m3.o
-OBJ += $(BUILD)/pins_gen.o
+OBJ += $(BUILD)/shared/runtime/gchelper_thumb2.o
+OBJ += $(GEN_PINS_SRC:.c=.o)
all: hex
hex: $(BUILD)/micropython.hex
@@ -193,16 +208,6 @@ $(BUILD)/%.hex: $(BUILD)/%.elf
$(ECHO) "HEX $<"
$(Q)$(OBJCOPY) -O ihex -R .eeprom "$<" "$@"
-MAKE_PINS = make-pins.py
-BOARD_PINS = teensy_pins.csv
-AF_FILE = mk20dx256_af.csv
-PREFIX_FILE = mk20dx256_prefix.c
-GEN_PINS_SRC = $(BUILD)/pins_gen.c
-GEN_PINS_HDR = $(HEADER_BUILD)/pins.h
-GEN_PINS_QSTR = $(BUILD)/pins_qstr.h
-GEN_PINS_AF_CONST = $(HEADER_BUILD)/pins_af_const.h
-GEN_PINS_AF_PY = $(BUILD)/pins_af.py
-
# List of sources for qstr extraction
SRC_QSTR += $(SRC_C) $(STM_SRC_C) $(SHARED_SRC_C)
# Append any auto-generated sources that are needed by sources listed in
@@ -222,7 +227,7 @@ $(BUILD)/%_gen.c $(HEADER_BUILD)/%.h $(HEADER_BUILD)/%_af_const.h $(BUILD)/%_qst
$(ECHO) "Create $@"
$(Q)$(PYTHON) $(MAKE_PINS) --board $(BOARD_PINS) --af $(AF_FILE) --prefix $(PREFIX_FILE) --hdr $(GEN_PINS_HDR) --qstr $(GEN_PINS_QSTR) --af-const $(GEN_PINS_AF_CONST) --af-py $(GEN_PINS_AF_PY) > $(GEN_PINS_SRC)
-$(BUILD)/pins_gen.o: $(BUILD)/pins_gen.c
+$(GEN_PINS_SRC:.c=.o): $(GEN_PINS_SRC)
$(call compile_c)
$(BUILD)/%.pp: $(BUILD)/%.c
diff --git a/ports/teensy/core/pins_teensy.c b/ports/teensy/core/pins_teensy.c
index b28f94a9ecb0..5817121fad38 100644
--- a/ports/teensy/core/pins_teensy.c
+++ b/ports/teensy/core/pins_teensy.c
@@ -181,7 +181,7 @@ void portb_isr(void)
void portc_isr(void)
{
- // TODO: these are inefficent. Use CLZ somehow....
+ // TODO: these are inefficient. Use CLZ somehow....
uint32_t isfr = PORTC_ISFR;
PORTC_ISFR = isfr;
if ((isfr & CORE_PIN9_BITMASK) && intFunc[9]) intFunc[9]();
diff --git a/ports/teensy/led.c b/ports/teensy/led.c
index d79e63cf7102..46c6ae492f85 100644
--- a/ports/teensy/led.c
+++ b/ports/teensy/led.c
@@ -134,10 +134,11 @@ STATIC const mp_rom_map_elem_t led_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(led_locals_dict, led_locals_dict_table);
-const mp_obj_type_t pyb_led_type = {
- { &mp_type_type },
- .name = MP_QSTR_LED,
- .print = led_obj_print,
- .make_new = led_obj_make_new,
- .locals_dict = (mp_obj_t)&led_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ pyb_led_type,
+ MP_QSTR_LED,
+ MP_TYPE_FLAG_NONE,
+ make_new, led_obj_make_new,
+ print, led_obj_print,
+ locals_dict, &led_locals_dict
+ );
diff --git a/ports/teensy/main.c b/ports/teensy/main.c
index 37a04c74f8af..fa27326e932d 100644
--- a/ports/teensy/main.c
+++ b/ports/teensy/main.c
@@ -298,7 +298,7 @@ int main(void) {
#endif
#if MICROPY_MODULE_FROZEN
- pyexec_frozen_module("boot.py");
+ pyexec_frozen_module("boot.py", false);
#else
if (!pyexec_file_if_exists("/boot.py")) {
flash_error(4);
@@ -310,7 +310,7 @@ int main(void) {
// run main script
#if MICROPY_MODULE_FROZEN
- pyexec_frozen_module("main.py");
+ pyexec_frozen_module("main.py", true);
#else
{
vstr_t *vstr = vstr_new(16);
diff --git a/ports/teensy/modpyb.c b/ports/teensy/modpyb.c
index 3939607ad06c..b48fecc18f39 100644
--- a/ports/teensy/modpyb.c
+++ b/ports/teensy/modpyb.c
@@ -111,7 +111,7 @@ STATIC mp_obj_t pyb_info(uint n_args, const mp_obj_t *args) {
if (n_args == 1) {
// arg given means dump gc allocation table
- gc_dump_alloc_table();
+ gc_dump_alloc_table(&mp_plat_print);
}
return mp_const_none;
diff --git a/ports/teensy/mpconfigport.h b/ports/teensy/mpconfigport.h
index db1f56757a21..f67eb66fab48 100644
--- a/ports/teensy/mpconfigport.h
+++ b/ports/teensy/mpconfigport.h
@@ -41,12 +41,6 @@ extern const struct _mp_obj_module_t pyb_module;
#define MP_STATE_PORT MP_STATE_VM
-#define MICROPY_PORT_ROOT_POINTERS \
- const char *readline_hist[8]; \
- mp_obj_t pin_class_mapper; \
- mp_obj_t pin_class_map_dict; \
- struct _pyb_uart_obj_t *pyb_stdio_uart; \
-
// type definitions for the specific machine
#define UINT_FMT "%u"
diff --git a/ports/teensy/teensy_hal.c b/ports/teensy/teensy_hal.c
index 342e7c6501dd..62a826517721 100644
--- a/ports/teensy/teensy_hal.c
+++ b/ports/teensy/teensy_hal.c
@@ -32,6 +32,11 @@ uintptr_t mp_hal_stdio_poll(uintptr_t poll_flags) {
ret |= MP_STREAM_POLL_RD;
}
}
+ if (poll_flags & MP_STREAM_POLL_WR) {
+ if (MP_STATE_PORT(pyb_stdio_uart) != NULL || usb_vcp_is_enabled()) {
+ ret |= MP_STREAM_POLL_WR;
+ }
+ }
return ret;
}
@@ -77,3 +82,5 @@ void mp_hal_gpio_clock_enable(GPIO_TypeDef *gpio) {
void extint_register_pin(const void *pin, uint32_t mode, int hard_irq, mp_obj_t callback_obj) {
mp_raise_NotImplementedError(NULL);
}
+
+MP_REGISTER_ROOT_POINTER(struct _pyb_uart_obj_t *pyb_stdio_uart);
diff --git a/ports/teensy/timer.c b/ports/teensy/timer.c
index 68dc965eb8bc..8c7609e4479e 100644
--- a/ports/teensy/timer.c
+++ b/ports/teensy/timer.c
@@ -746,13 +746,14 @@ STATIC const mp_rom_map_elem_t pyb_timer_locals_dict_table[] = {
};
STATIC MP_DEFINE_CONST_DICT(pyb_timer_locals_dict, pyb_timer_locals_dict_table);
-const mp_obj_type_t pyb_timer_type = {
- { &mp_type_type },
- .name = MP_QSTR_Timer,
- .print = pyb_timer_print,
- .make_new = pyb_timer_make_new,
- .locals_dict = (mp_obj_t)&pyb_timer_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ pyb_timer_type,
+ MP_QSTR_Timer,
+ MP_TYPE_FLAG_NONE,
+ make_new, pyb_timer_make_new,
+ print, pyb_timer_print,
+ locals_dict, &pyb_timer_locals_dict
+ );
/// \moduleref pyb
/// \class TimerChannel - setup a channel for a timer.
@@ -889,12 +890,13 @@ STATIC const mp_rom_map_elem_t pyb_timer_channel_locals_dict_table[] = {
};
STATIC MP_DEFINE_CONST_DICT(pyb_timer_channel_locals_dict, pyb_timer_channel_locals_dict_table);
-STATIC const mp_obj_type_t pyb_timer_channel_type = {
- { &mp_type_type },
- .name = MP_QSTR_TimerChannel,
- .print = pyb_timer_channel_print,
- .locals_dict = (mp_obj_t)&pyb_timer_channel_locals_dict,
-};
+STATIC MP_DEFINE_CONST_OBJ_TYPE(
+ pyb_timer_channel_type,
+ MP_QSTR_TimerChannel,
+ MP_TYPE_FLAG_NONE,
+ print, pyb_timer_channel_print,
+ locals_dict, &pyb_timer_channel_locals_dict
+ );
STATIC bool ftm_handle_irq_callback(pyb_timer_obj_t *self, mp_uint_t channel, mp_obj_t callback) {
// execute callback if it's set
diff --git a/ports/teensy/uart.c b/ports/teensy/uart.c
index 5b63fcb3cdd5..e71f676d0ae1 100644
--- a/ports/teensy/uart.c
+++ b/ports/teensy/uart.c
@@ -483,10 +483,11 @@ STATIC const mp_rom_map_elem_t pyb_uart_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(pyb_uart_locals_dict, pyb_uart_locals_dict_table);
-const mp_obj_type_t pyb_uart_type = {
- { &mp_type_type },
- .name = MP_QSTR_UART,
- .print = pyb_uart_print,
- .make_new = pyb_uart_make_new,
- .locals_dict = (mp_obj_t)&pyb_uart_locals_dict,
-};
+MP_DEFINE_CONST_OBJ_TYPE(
+ pyb_uart_type,
+ MP_QSTR_UART,
+ MP_TYPE_FLAG_NONE,
+ make_new, pyb_uart_make_new,
+ print, pyb_uart_print,
+ locals_dict, &pyb_uart_locals_dict
+ );
diff --git a/ports/unix/.gitignore b/ports/unix/.gitignore
deleted file mode 100644
index 3ca8f6cb2746..000000000000
--- a/ports/unix/.gitignore
+++ /dev/null
@@ -1,3 +0,0 @@
-micropython
-micropython-*
-*.gcov
diff --git a/ports/unix/Makefile b/ports/unix/Makefile
index adb81dfc00f8..e5f2363e3590 100644
--- a/ports/unix/Makefile
+++ b/ports/unix/Makefile
@@ -1,14 +1,21 @@
-# Select the variant to build for.
+# Select the variant to build for:
+ifdef VARIANT_DIR
+# Custom variant path - remove trailing slash and get the final component of
+# the path as the variant name.
+VARIANT ?= $(notdir $(VARIANT_DIR:/=))
+else
+# If not given on the command line, then default to standard.
VARIANT ?= standard
-
-# If the build directory is not given, make it reflect the variant name.
-BUILD ?= build-$(VARIANT)
-
VARIANT_DIR ?= variants/$(VARIANT)
+endif
+
ifeq ($(wildcard $(VARIANT_DIR)/.),)
$(error Invalid VARIANT specified: $(VARIANT_DIR))
endif
+# If the build directory is not given, make it reflect the variant name.
+BUILD ?= build-$(VARIANT)
+
include ../../py/mkenv.mk
-include mpconfigport.mk
include $(VARIANT_DIR)/mpconfigvariant.mk
@@ -28,8 +35,9 @@ UNAME_S := $(shell uname -s)
# include py core make definitions
include $(TOP)/py/py.mk
+include $(TOP)/extmod/extmod.mk
-GIT_SUBMODULES += lib/axtls lib/berkeley-db-1.xx lib/libffi
+GIT_SUBMODULES += lib/berkeley-db-1.xx
INC += -I.
INC += -I$(TOP)
@@ -38,7 +46,7 @@ INC += -I$(BUILD)
# compiler settings
CWARN = -Wall -Werror
CWARN += -Wextra -Wno-unused-parameter -Wpointer-arith -Wdouble-promotion -Wfloat-conversion
-CFLAGS += $(INC) $(CWARN) -std=gnu99 -DUNIX $(CFLAGS_MOD) $(COPT) -I$(VARIANT_DIR) $(CFLAGS_EXTRA)
+CFLAGS += $(INC) $(CWARN) -std=gnu99 -DUNIX $(COPT) -I$(VARIANT_DIR) $(CFLAGS_EXTRA)
# Debugging/Optimization
ifdef DEBUG
@@ -109,60 +117,39 @@ ifeq ($(MICROPY_FORCE_32BIT),1)
# starting with linux-libc-dev:i386
ifeq ($(MICROPY_PY_FFI),1)
ifeq ($(UNAME_S),Linux)
-CFLAGS_MOD += -I/usr/include/i686-linux-gnu
+CFLAGS += -I/usr/include/i686-linux-gnu
endif
endif
endif
ifeq ($(MICROPY_USE_READLINE),1)
INC += -I$(TOP)/shared/readline
-CFLAGS_MOD += -DMICROPY_USE_READLINE=1
+CFLAGS += -DMICROPY_USE_READLINE=1
SHARED_SRC_C_EXTRA += readline/readline.c
endif
ifeq ($(MICROPY_PY_TERMIOS),1)
-CFLAGS_MOD += -DMICROPY_PY_TERMIOS=1
-SRC_MOD += modtermios.c
+CFLAGS += -DMICROPY_PY_TERMIOS=1
endif
ifeq ($(MICROPY_PY_SOCKET),1)
-CFLAGS_MOD += -DMICROPY_PY_SOCKET=1
-SRC_MOD += modusocket.c
+CFLAGS += -DMICROPY_PY_SOCKET=1
endif
ifeq ($(MICROPY_PY_THREAD),1)
-CFLAGS_MOD += -DMICROPY_PY_THREAD=1 -DMICROPY_PY_THREAD_GIL=0
-LDFLAGS_MOD += $(LIBPTHREAD)
+CFLAGS += -DMICROPY_PY_THREAD=1 -DMICROPY_PY_THREAD_GIL=0
+LDFLAGS += $(LIBPTHREAD)
endif
-# If the variant enables it, enable modbluetooth.
-ifeq ($(MICROPY_PY_BLUETOOTH),1)
-
-HAVE_LIBUSB := $(shell (which pkg-config > /dev/null && pkg-config --exists libusb-1.0) 2>/dev/null && echo '1')
-
-# Only one stack can be enabled.
-ifeq ($(MICROPY_BLUETOOTH_NIMBLE),1)
-ifeq ($(MICROPY_BLUETOOTH_BTSTACK),1)
-$(error Cannot enable both NimBLE and BTstack at the same time)
-endif
-endif
+ifeq ($(MICROPY_PY_USSL),1)
+ifeq ($(MICROPY_SSL_AXTLS),1)
-# Default to btstack, but a variant (or make command line) can set NimBLE
-# explicitly (which is always via H4 UART).
-ifneq ($(MICROPY_BLUETOOTH_NIMBLE),1)
-ifneq ($(MICROPY_BLUETOOTH_BTSTACK),1)
-MICROPY_BLUETOOTH_BTSTACK ?= 1
endif
endif
-CFLAGS_MOD += -DMICROPY_PY_BLUETOOTH=1
-CFLAGS_MOD += -DMICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE=1
-
+# If the variant enables it, enable modbluetooth.
+ifeq ($(MICROPY_PY_BLUETOOTH),1)
ifeq ($(MICROPY_BLUETOOTH_BTSTACK),1)
+HAVE_LIBUSB := $(shell (which pkg-config > /dev/null && pkg-config --exists libusb-1.0) 2>/dev/null && echo '1')
# Figure out which BTstack transport to use.
-ifeq ($(MICROPY_BLUETOOTH_BTSTACK_H4),1)
-ifeq ($(MICROPY_BLUETOOTH_BTSTACK_USB),1)
-$(error Cannot enable BTstack support for USB and H4 UART at the same time)
-endif
-else
ifeq ($(HAVE_LIBUSB),1)
# Default to btstack-over-usb.
MICROPY_BLUETOOTH_BTSTACK_USB ?= 1
@@ -170,51 +157,40 @@ else
# Fallback to HCI controller via a H4 UART (e.g. Zephyr on nRF) over a /dev/tty serial port.
MICROPY_BLUETOOTH_BTSTACK_H4 ?= 1
endif
-endif
-
-# BTstack is enabled.
-GIT_SUBMODULES += lib/btstack
-include $(TOP)/extmod/btstack/btstack.mk
-SRC_BTSTACK += lib/btstack/platform/embedded/btstack_run_loop_embedded.c
-
-else
-
-# NimBLE is enabled.
-GIT_SUBMODULES += lib/mynewt-nimble
-CFLAGS_MOD += -DMICROPY_PY_BLUETOOTH_ENABLE_L2CAP_CHANNELS=1
-include $(TOP)/extmod/nimble/nimble.mk
+SRC_BTSTACK_C += lib/btstack/platform/embedded/btstack_run_loop_embedded.c
endif
-
endif
ifeq ($(MICROPY_PY_FFI),1)
ifeq ($(MICROPY_STANDALONE),1)
-LIBFFI_CFLAGS_MOD := -I$(shell ls -1d $(BUILD)/lib/libffi/out/lib/libffi-*/include)
+# Build libffi from source.
+GIT_SUBMODULES += lib/libffi
+DEPLIBS += libffi
+LIBFFI_CFLAGS := -I$(shell ls -1d $(BUILD)/lib/libffi/out/lib/libffi-*/include)
ifeq ($(MICROPY_FORCE_32BIT),1)
- LIBFFI_LDFLAGS_MOD = $(BUILD)/lib/libffi/out/lib32/libffi.a
+ LIBFFI_LDFLAGS = $(BUILD)/lib/libffi/out/lib32/libffi.a
else
- LIBFFI_LDFLAGS_MOD = $(BUILD)/lib/libffi/out/lib/libffi.a
+ LIBFFI_LDFLAGS = $(BUILD)/lib/libffi/out/lib/libffi.a
endif
else
-LIBFFI_CFLAGS_MOD := $(shell pkg-config --cflags libffi)
-LIBFFI_LDFLAGS_MOD := $(shell pkg-config --libs libffi)
+# Use system version of libffi.
+LIBFFI_CFLAGS := $(shell pkg-config --cflags libffi)
+LIBFFI_LDFLAGS := $(shell pkg-config --libs libffi)
endif
ifeq ($(UNAME_S),Linux)
-LIBFFI_LDFLAGS_MOD += -ldl
+LIBFFI_LDFLAGS += -ldl
endif
-CFLAGS_MOD += $(LIBFFI_CFLAGS_MOD) -DMICROPY_PY_FFI=1
-LDFLAGS_MOD += $(LIBFFI_LDFLAGS_MOD)
-SRC_MOD += modffi.c
+CFLAGS += $(LIBFFI_CFLAGS) -DMICROPY_PY_FFI=1
+LDFLAGS += $(LIBFFI_LDFLAGS)
endif
ifeq ($(MICROPY_PY_JNI),1)
# Path for 64-bit OpenJDK, should be adjusted for other JDKs
-CFLAGS_MOD += -I/usr/lib/jvm/java-7-openjdk-amd64/include -DMICROPY_PY_JNI=1
-SRC_MOD += modjni.c
+CFLAGS += -I/usr/lib/jvm/java-7-openjdk-amd64/include -DMICROPY_PY_JNI=1
endif
# Additional optional libraries
@@ -269,7 +245,10 @@ SRC_C += \
mpbtstackport_h4.c \
mpbtstackport_usb.c \
mpnimbleport.c \
- $(SRC_MOD) \
+ modtermios.c \
+ modusocket.c \
+ modffi.c \
+ modjni.c \
$(wildcard $(VARIANT_DIR)/*.c)
LIB_SRC_C += $(addprefix lib/,\
@@ -283,17 +262,14 @@ SHARED_SRC_C += $(addprefix shared/,\
)
SRC_CXX += \
- $(SRC_MOD_CXX)
OBJ = $(PY_O)
OBJ += $(addprefix $(BUILD)/, $(SRC_C:.c=.o))
OBJ += $(addprefix $(BUILD)/, $(SRC_CXX:.cpp=.o))
OBJ += $(addprefix $(BUILD)/, $(SHARED_SRC_C:.c=.o))
-OBJ += $(addprefix $(BUILD)/, $(EXTMOD_SRC_C:.c=.o))
-OBJ += $(addprefix $(BUILD)/, $(LIB_SRC_C:.c=.o))
# List of sources for qstr extraction
-SRC_QSTR += $(SRC_C) $(SRC_CXX) $(LIB_SRC_C) $(SHARED_SRC_C) $(EXTMOD_SRC_C)
+SRC_QSTR += $(SRC_C) $(SRC_CXX) $(SHARED_SRC_C) $(LIB_SRC_C)
# Append any auto-generated sources that are needed by sources listed in
# SRC_QSTR
SRC_QSTR_AUTO_DEPS +=
@@ -328,18 +304,18 @@ include $(TOP)/py/mkrules.mk
.PHONY: test test_full
-test: $(PROG) $(TOP)/tests/run-tests.py
+test: $(BUILD)/$(PROG) $(TOP)/tests/run-tests.py
$(eval DIRNAME=ports/$(notdir $(CURDIR)))
- cd $(TOP)/tests && MICROPY_MICROPYTHON=../$(DIRNAME)/$(PROG) ./run-tests.py
+ cd $(TOP)/tests && MICROPY_MICROPYTHON=../$(DIRNAME)/$(BUILD)/$(PROG) ./run-tests.py
-test_full: $(PROG) $(TOP)/tests/run-tests.py
+test_full: $(BUILD)/$(PROG) $(TOP)/tests/run-tests.py
$(eval DIRNAME=ports/$(notdir $(CURDIR)))
- cd $(TOP)/tests && MICROPY_MICROPYTHON=../$(DIRNAME)/$(PROG) ./run-tests.py
- cd $(TOP)/tests && MICROPY_MICROPYTHON=../$(DIRNAME)/$(PROG) ./run-tests.py -d thread
- cd $(TOP)/tests && MICROPY_MICROPYTHON=../$(DIRNAME)/$(PROG) ./run-tests.py --emit native
- cd $(TOP)/tests && MICROPY_MICROPYTHON=../$(DIRNAME)/$(PROG) ./run-tests.py --via-mpy $(RUN_TESTS_MPY_CROSS_FLAGS) -d basics float micropython
- cd $(TOP)/tests && MICROPY_MICROPYTHON=../$(DIRNAME)/$(PROG) ./run-tests.py --via-mpy $(RUN_TESTS_MPY_CROSS_FLAGS) --emit native -d basics float micropython
- cat $(TOP)/tests/basics/0prelim.py | ./$(PROG) | grep -q 'abc'
+ cd $(TOP)/tests && MICROPY_MICROPYTHON=../$(DIRNAME)/$(BUILD)/$(PROG) ./run-tests.py
+ cd $(TOP)/tests && MICROPY_MICROPYTHON=../$(DIRNAME)/$(BUILD)/$(PROG) ./run-tests.py -d thread
+ cd $(TOP)/tests && MICROPY_MICROPYTHON=../$(DIRNAME)/$(BUILD)/$(PROG) ./run-tests.py --emit native
+ cd $(TOP)/tests && MICROPY_MICROPYTHON=../$(DIRNAME)/$(BUILD)/$(PROG) ./run-tests.py --via-mpy $(RUN_TESTS_MPY_CROSS_FLAGS) -d basics float micropython
+ cd $(TOP)/tests && MICROPY_MICROPYTHON=../$(DIRNAME)/$(BUILD)/$(PROG) ./run-tests.py --via-mpy $(RUN_TESTS_MPY_CROSS_FLAGS) --emit native -d basics float micropython
+ cat $(TOP)/tests/basics/0prelim.py | ./$(BUILD)/$(PROG) | grep -q 'abc'
test_gcov: test_full
gcov -o $(BUILD)/py $(TOP)/py/*.c
@@ -353,7 +329,7 @@ else
CROSS_COMPILE_HOST =
endif
-deplibs: libffi axtls
+deplibs: $(DEPLIBS)
libffi: $(BUILD)/lib/libffi/include/ffi.h
@@ -364,21 +340,15 @@ $(TOP)/lib/libffi/configure: $(TOP)/lib/libffi/autogen.sh
# docs and depending on makeinfo
$(BUILD)/lib/libffi/include/ffi.h: $(TOP)/lib/libffi/configure
mkdir -p $(BUILD)/lib/libffi; cd $(BUILD)/lib/libffi; \
- $(abspath $(TOP))/lib/libffi/configure $(CROSS_COMPILE_HOST) --prefix=$$PWD/out --disable-structs CC="$(CC)" CXX="$(CXX)" LD="$(LD)" CFLAGS="-Os -fomit-frame-pointer -fstrict-aliasing -ffast-math -fno-exceptions"; \
+ $(abspath $(TOP))/lib/libffi/configure $(CROSS_COMPILE_HOST) --prefix=$$PWD/out --disable-shared --disable-structs CC="$(CC)" CXX="$(CXX)" LD="$(LD)" CFLAGS="-Os -fomit-frame-pointer -fstrict-aliasing -ffast-math -fno-exceptions"; \
$(MAKE) install-exec-recursive; $(MAKE) -C include install-data-am
-axtls: $(TOP)/lib/axtls/README
-
-$(TOP)/lib/axtls/README:
- @echo "You cloned without --recursive, fetching submodules for you."
- (cd $(TOP); git submodule update --init --recursive)
-
PREFIX = /usr/local
BINDIR = $(DESTDIR)$(PREFIX)/bin
-install: $(PROG)
+install: $(BUILD)/$(PROG)
install -d $(BINDIR)
- install $(PROG) $(BINDIR)/$(PROG)
+ install $(BUILD)/$(PROG) $(BINDIR)/$(PROG)
uninstall:
-rm $(BINDIR)/$(PROG)
diff --git a/ports/unix/README.md b/ports/unix/README.md
new file mode 100644
index 000000000000..a3a0dba75a13
--- /dev/null
+++ b/ports/unix/README.md
@@ -0,0 +1,74 @@
+The Unix version
+----------------
+
+The "unix" port requires a standard Unix-like environment with gcc and GNU
+make. This includes Linux, BSD, macOS, and Windows Subsystem for Linux. The
+x86 and x64 architectures are supported (i.e. x86 32- and 64-bit), as well as
+ARM and MIPS. Making a full-featured port to another architecture requires
+writing some assembly code for the exception handling and garbage collection.
+Alternatively, a fallback implementation based on setjmp/longjmp can be used.
+
+To build (see section below for required dependencies):
+
+ $ cd ports/unix
+ $ make submodules
+ $ make
+
+Then to give it a try:
+
+ $ ./build-standard/micropython
+ >>> list(5 * x + y for x in range(10) for y in [4, 2, 1])
+
+Use `CTRL-D` (i.e. EOF) to exit the shell.
+
+Learn about command-line options (in particular, how to increase heap size
+which may be needed for larger applications):
+
+ $ ./build-standard/micropython -h
+
+To run the complete testsuite, use:
+
+ $ make test
+
+The Unix port comes with a built-in package manager called `mip`, e.g.:
+
+ $ ./build-standard/micropython -m mip install hmac
+
+or
+
+ $ ./build-standard/micropython
+ >>> import mip
+ >>> mip.install("hmac")
+
+Browse available modules at [micropython-lib]
+(https://github.com/micropython/micropython-lib). See
+[Package management](https://docs.micropython.org/en/latest/reference/packages.html)
+for more information about `mip`.
+
+External dependencies
+---------------------
+
+The `libffi` library and `pkg-config` tool are required. On Debian/Ubuntu/Mint
+derivative Linux distros, install `build-essential`(includes toolchain and
+make), `libffi-dev`, and `pkg-config` packages.
+
+Other dependencies can be built together with MicroPython. This may
+be required to enable extra features or capabilities, and in recent
+versions of MicroPython, these may be enabled by default. To build
+these additional dependencies, in the unix port directory first execute:
+
+ $ make submodules
+
+This will fetch all the relevant git submodules (sub repositories) that
+the port needs. Use the same command to get the latest versions of
+submodules as they are updated from time to time. After that execute:
+
+ $ make deplibs
+
+This will build all available dependencies (regardless whether they are used
+or not). If you intend to build MicroPython with additional options
+(like cross-compiling), the same set of options should be passed to `make
+deplibs`. To actually enable/disable use of dependencies, edit the
+`ports/unix/mpconfigport.mk` file, which has inline descriptions of the
+options. For example, to build the SSL module, `MICROPY_PY_USSL` should be
+set to 1.
diff --git a/ports/unix/alloc.c b/ports/unix/alloc.c
index 7fe7b4dba4e7..e9cf521583d9 100644
--- a/ports/unix/alloc.c
+++ b/ports/unix/alloc.c
@@ -104,4 +104,6 @@ void ffi_closure_free(void *ptr) {
}
#endif
+MP_REGISTER_ROOT_POINTER(void *mmap_region_head);
+
#endif // MICROPY_EMIT_NATIVE || (MICROPY_PY_FFI && MICROPY_FORCE_PLAT_ALLOC_EXEC)
diff --git a/ports/unix/coverage.c b/ports/unix/coverage.c
index cf425ac4334f..f545674ceeb8 100644
--- a/ports/unix/coverage.c
+++ b/ports/unix/coverage.c
@@ -1,4 +1,5 @@
#include
+#include