From 9f0337f452cdddbbdfab9f3755b0fff1f41e2de5 Mon Sep 17 00:00:00 2001 From: Mattia Pennasilico Date: Mon, 10 Mar 2025 12:40:31 +0100 Subject: [PATCH 01/43] Release 4.2.4 --- package_full.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package_full.sh b/package_full.sh index e7fca45b2..2f9c1434e 100755 --- a/package_full.sh +++ b/package_full.sh @@ -1,5 +1,5 @@ #Get version from git(hub) tag -export VERSION="4.2.3" +export VERSION="4.2.4" FLAVOURS=`ls *.variables` From 9e8f862bae51e3191923e32283be1d6ac2351470 Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 12 Mar 2025 14:31:01 +0100 Subject: [PATCH 02/43] SocketHelpers: ping, fix build for generic M4 --- libraries/SocketWrapper/src/SocketHelpers.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libraries/SocketWrapper/src/SocketHelpers.cpp b/libraries/SocketWrapper/src/SocketHelpers.cpp index b7e39b42c..9360f9988 100644 --- a/libraries/SocketWrapper/src/SocketHelpers.cpp +++ b/libraries/SocketWrapper/src/SocketHelpers.cpp @@ -142,11 +142,14 @@ int arduino::MbedSocketClass::ping(SocketAddress &socketAddress, uint8_t ttl, ui { /* ttl is not supported by mbed ICMPSocket. Default value used is 255 */ (void)ttl; + int response = -1; +#if MBED_CONF_LWIP_RAW_SOCKET_ENABLED ICMPSocket s; s.set_timeout(timeout); s.open(getNetwork()); - int response = s.ping(socketAddress, timeout); + response = s.ping(socketAddress, timeout); s.close(); +#endif return response; } From 423d7153579394ae9c8f564f16e2fd3c120d8d08 Mon Sep 17 00:00:00 2001 From: Damiano Mazzella Date: Fri, 14 Mar 2025 10:28:50 +0100 Subject: [PATCH 03/43] Get the status of the display. --- libraries/Arduino_H7_Video/src/Arduino_H7_Video.cpp | 5 +++++ libraries/Arduino_H7_Video/src/Arduino_H7_Video.h | 7 +++++++ libraries/Arduino_H7_Video/src/H7DisplayShield.cpp | 10 ++++++++++ libraries/Arduino_H7_Video/src/H7DisplayShield.h | 3 +++ libraries/Arduino_H7_Video/src/anx7625.cpp | 5 +++++ libraries/Arduino_H7_Video/src/anx7625.h | 1 + 6 files changed, 31 insertions(+) diff --git a/libraries/Arduino_H7_Video/src/Arduino_H7_Video.cpp b/libraries/Arduino_H7_Video/src/Arduino_H7_Video.cpp index 460a1793a..7c11200d3 100644 --- a/libraries/Arduino_H7_Video/src/Arduino_H7_Video.cpp +++ b/libraries/Arduino_H7_Video/src/Arduino_H7_Video.cpp @@ -179,6 +179,11 @@ bool Arduino_H7_Video::isRotated() { return _rotated; } +int Arduino_H7_Video::getStatus() +{ + return _shield->getStatus(); +} + void Arduino_H7_Video::end() { #ifdef HAS_ARDUINOGRAPHICS ArduinoGraphics::end(); diff --git a/libraries/Arduino_H7_Video/src/Arduino_H7_Video.h b/libraries/Arduino_H7_Video/src/Arduino_H7_Video.h index 9f05f5ea0..12fd47cb7 100644 --- a/libraries/Arduino_H7_Video/src/Arduino_H7_Video.h +++ b/libraries/Arduino_H7_Video/src/Arduino_H7_Video.h @@ -106,6 +106,13 @@ class Arduino_H7_Video */ bool isRotated(); + /** + * @brief Get the status of the display. + * + * @return int The Status of the display. + */ + int getStatus(); + #ifdef HAS_ARDUINOGRAPHICS /** * @brief Clear the display. diff --git a/libraries/Arduino_H7_Video/src/H7DisplayShield.cpp b/libraries/Arduino_H7_Video/src/H7DisplayShield.cpp index e045f5abe..14904db70 100644 --- a/libraries/Arduino_H7_Video/src/H7DisplayShield.cpp +++ b/libraries/Arduino_H7_Video/src/H7DisplayShield.cpp @@ -18,6 +18,10 @@ int GigaDisplayShieldClass::getEdidMode(int h, int v) { return EDID_MODE_480x800_60Hz; } +int GigaDisplayShieldClass::getStatus() { + return 1; +} + int USBCVideoClass::init(int edidmode) { struct edid recognized_edid; int err_code = 0; @@ -57,5 +61,11 @@ int USBCVideoClass::getEdidMode(int h, int v) { return edidmode; } +int USBCVideoClass::getStatus() { + int detected = anx7625_get_hpd_event(0); + + return detected; +} + GigaDisplayShieldClass GigaDisplayShield; USBCVideoClass USBCVideo; \ No newline at end of file diff --git a/libraries/Arduino_H7_Video/src/H7DisplayShield.h b/libraries/Arduino_H7_Video/src/H7DisplayShield.h index c29f9d7eb..541c2c632 100644 --- a/libraries/Arduino_H7_Video/src/H7DisplayShield.h +++ b/libraries/Arduino_H7_Video/src/H7DisplayShield.h @@ -5,18 +5,21 @@ class H7DisplayShield { public: virtual int init(int edidmode) = 0; virtual int getEdidMode(int h, int v); + virtual int getStatus(); }; class GigaDisplayShieldClass : public H7DisplayShield { public: int init(int edidmode); int getEdidMode(int h, int v); + int getStatus(); }; class USBCVideoClass : public H7DisplayShield { public: int init(int edidmode); int getEdidMode(int h, int v); + int getStatus(); }; extern GigaDisplayShieldClass GigaDisplayShield; diff --git a/libraries/Arduino_H7_Video/src/anx7625.cpp b/libraries/Arduino_H7_Video/src/anx7625.cpp index 5f06e96c7..e69d5d832 100644 --- a/libraries/Arduino_H7_Video/src/anx7625.cpp +++ b/libraries/Arduino_H7_Video/src/anx7625.cpp @@ -630,6 +630,11 @@ bool anx7625_is_power_provider(uint8_t bus) { } } +int anx7625_get_hpd_event(uint8_t bus) { + int ret = anx7625_hpd_change_detect(bus);; + return ret; +} + int i2c_writeb(uint8_t bus, uint8_t saddr, uint8_t offset, uint8_t val) { char cmd[2]; cmd[0] = offset; diff --git a/libraries/Arduino_H7_Video/src/anx7625.h b/libraries/Arduino_H7_Video/src/anx7625.h index e6f8de7f2..146d09ec1 100644 --- a/libraries/Arduino_H7_Video/src/anx7625.h +++ b/libraries/Arduino_H7_Video/src/anx7625.h @@ -24,5 +24,6 @@ int anx7625_wait_hpd_event(uint8_t bus); int anx7625_get_cc_status(uint8_t bus, uint8_t *cc_status); int anx7625_read_system_status(uint8_t bus, uint8_t *sys_status); bool anx7625_is_power_provider(uint8_t bus); +int anx7625_get_hpd_event(uint8_t bus); #endif /* _ANX7625_H */ From 38c56fbff089a7e8424724fb4b874d491aa640d2 Mon Sep 17 00:00:00 2001 From: megacct <96644325+megacct@users.noreply.github.com> Date: Fri, 14 Mar 2025 19:27:53 +0000 Subject: [PATCH 04/43] Update MbedClient.cpp fix osPriority and name thread --- libraries/SocketWrapper/src/MbedClient.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/SocketWrapper/src/MbedClient.cpp b/libraries/SocketWrapper/src/MbedClient.cpp index 296b64943..d678b78db 100644 --- a/libraries/SocketWrapper/src/MbedClient.cpp +++ b/libraries/SocketWrapper/src/MbedClient.cpp @@ -71,7 +71,7 @@ void arduino::MbedClient::configureSocket(Socket *_s) { } mutex->lock(); if (reader_th == nullptr) { - reader_th = new rtos::Thread(osPriorityNormal - 2); + reader_th = new rtos::Thread(osPriorityNormal, OS_STACK_SIZE, nullptr, "readSocket"); reader_th->start(mbed::callback(this, &MbedClient::readSocket)); } mutex->unlock(); From e11f5c60c1894bbf3ee64498f46efd404bb9ec73 Mon Sep 17 00:00:00 2001 From: Damiano Mazzella Date: Mon, 17 Mar 2025 09:46:35 +0100 Subject: [PATCH 05/43] Update post review --- libraries/Arduino_H7_Video/docs/api.md | 10 ++++++++++ libraries/Arduino_H7_Video/src/Arduino_H7_Video.cpp | 4 ++-- libraries/Arduino_H7_Video/src/Arduino_H7_Video.h | 6 +++--- libraries/Arduino_H7_Video/src/H7DisplayShield.cpp | 2 +- libraries/Arduino_H7_Video/src/anx7625.cpp | 2 +- 5 files changed, 17 insertions(+), 7 deletions(-) diff --git a/libraries/Arduino_H7_Video/docs/api.md b/libraries/Arduino_H7_Video/docs/api.md index 356144b49..923393173 100644 --- a/libraries/Arduino_H7_Video/docs/api.md +++ b/libraries/Arduino_H7_Video/docs/api.md @@ -14,6 +14,7 @@ The main class for managing the video controller and the display. | `public ` [`Arduino_H7_Video`](#public-arduino_h7_videoint-width-int-height-h7displayshield-shield) | Construct a new Arduino_H7_Video object with the specified width, height, and display shield. | | `public int` [`begin`](#public-int-begin) | Initialize the video controller and display. | | `public void` [`end`](#public-void-end) | De-initialize the video controller and display. | +| `public bool` [`detect`](#public-bool-detect) | Checks if the display is connected. | | `public int` [`width`](#public-int-width) | Get the width of the display. | | `public int` [`height`](#public-int-height) | Get the height of the display. | | `public bool` [`isRotated`](#public-bool-isrotated) | Check if the display is rotated. | @@ -54,6 +55,15 @@ De-initialize the video controller and display. --- +### `public bool` [`detect`](#)`()` + +Checks if the display is connected. + +#### Returns +`bool`: True if the display is connected, False otherwis. + +--- + ### `public int` [`width`](#)`()` Get the width of the display. diff --git a/libraries/Arduino_H7_Video/src/Arduino_H7_Video.cpp b/libraries/Arduino_H7_Video/src/Arduino_H7_Video.cpp index 7c11200d3..0e1cc06af 100644 --- a/libraries/Arduino_H7_Video/src/Arduino_H7_Video.cpp +++ b/libraries/Arduino_H7_Video/src/Arduino_H7_Video.cpp @@ -179,9 +179,9 @@ bool Arduino_H7_Video::isRotated() { return _rotated; } -int Arduino_H7_Video::getStatus() +bool Arduino_H7_Video::getStatus() { - return _shield->getStatus(); + return (_shield->getStatus() > 0); } void Arduino_H7_Video::end() { diff --git a/libraries/Arduino_H7_Video/src/Arduino_H7_Video.h b/libraries/Arduino_H7_Video/src/Arduino_H7_Video.h index 12fd47cb7..8f40d37a0 100644 --- a/libraries/Arduino_H7_Video/src/Arduino_H7_Video.h +++ b/libraries/Arduino_H7_Video/src/Arduino_H7_Video.h @@ -107,11 +107,11 @@ class Arduino_H7_Video bool isRotated(); /** - * @brief Get the status of the display. + * @brief Checks if the display is connected. * - * @return int The Status of the display. + * @return true if the display is connected, false otherwise. */ - int getStatus(); + bool detect(); #ifdef HAS_ARDUINOGRAPHICS /** diff --git a/libraries/Arduino_H7_Video/src/H7DisplayShield.cpp b/libraries/Arduino_H7_Video/src/H7DisplayShield.cpp index 14904db70..b6010f3f0 100644 --- a/libraries/Arduino_H7_Video/src/H7DisplayShield.cpp +++ b/libraries/Arduino_H7_Video/src/H7DisplayShield.cpp @@ -19,7 +19,7 @@ int GigaDisplayShieldClass::getEdidMode(int h, int v) { } int GigaDisplayShieldClass::getStatus() { - return 1; + return 1; // TODO: Not implemented; } int USBCVideoClass::init(int edidmode) { diff --git a/libraries/Arduino_H7_Video/src/anx7625.cpp b/libraries/Arduino_H7_Video/src/anx7625.cpp index e69d5d832..3cfefce47 100644 --- a/libraries/Arduino_H7_Video/src/anx7625.cpp +++ b/libraries/Arduino_H7_Video/src/anx7625.cpp @@ -631,7 +631,7 @@ bool anx7625_is_power_provider(uint8_t bus) { } int anx7625_get_hpd_event(uint8_t bus) { - int ret = anx7625_hpd_change_detect(bus);; + int ret = anx7625_hpd_change_detect(bus); return ret; } From fbc07736a92abc28351c72149359e0266a32d714 Mon Sep 17 00:00:00 2001 From: Damiano Mazzella Date: Mon, 17 Mar 2025 09:48:30 +0100 Subject: [PATCH 06/43] Renamed getStatus sto detect --- libraries/Arduino_H7_Video/src/Arduino_H7_Video.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/Arduino_H7_Video/src/Arduino_H7_Video.cpp b/libraries/Arduino_H7_Video/src/Arduino_H7_Video.cpp index 0e1cc06af..2bb02ebc9 100644 --- a/libraries/Arduino_H7_Video/src/Arduino_H7_Video.cpp +++ b/libraries/Arduino_H7_Video/src/Arduino_H7_Video.cpp @@ -179,7 +179,7 @@ bool Arduino_H7_Video::isRotated() { return _rotated; } -bool Arduino_H7_Video::getStatus() +bool Arduino_H7_Video::detect() { return (_shield->getStatus() > 0); } From 83b55af6cb4d8968c40cae839fb495af4c98a291 Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 15 Oct 2024 11:43:17 +0200 Subject: [PATCH 07/43] GSM: extend number of connection retries to 10, cut down maximum wait time to 8s --- libraries/GSM/src/GSM.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/GSM/src/GSM.h b/libraries/GSM/src/GSM.h index 0b724f284..44424ee4b 100644 --- a/libraries/GSM/src/GSM.h +++ b/libraries/GSM/src/GSM.h @@ -129,9 +129,9 @@ class GSMClass : public MbedSocketClass { bool _at_debug = false; /* Internal cellular state machine retries. Values are in seconds. - * This array also defines the maximum number of retries to 6 + * This array also defines the maximum number of retries to CELLULAR_RETRY_ARRAY_SIZE */ - const uint16_t _retry_timeout[6] = {1, 2, 4, 8, 16, 32}; + const uint16_t _retry_timeout[CELLULAR_RETRY_ARRAY_SIZE] = {1, 2, 4, 8, 8, 8, 8, 8, 8, 8}; static constexpr int RSSI_UNKNOWN = 99; static const char * const sim_state_str[]; From 91ffd8d76b03b4d499530a4bbc4c2f7d55147a65 Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 15 Oct 2024 12:41:08 +0200 Subject: [PATCH 08/43] GSM: remove isReady --- libraries/GSM/src/GSM.cpp | 20 -------------------- libraries/GSM/src/GSM.h | 1 - 2 files changed, 21 deletions(-) diff --git a/libraries/GSM/src/GSM.cpp b/libraries/GSM/src/GSM.cpp index cf5f5b975..786cd0ee6 100644 --- a/libraries/GSM/src/GSM.cpp +++ b/libraries/GSM/src/GSM.cpp @@ -66,11 +66,6 @@ int arduino::GSMClass::begin(const char* pin, const char* apn, const char* usern _device = _context->get_device(); _device->modem_debug_on(_at_debug); - if (!isReady()) { - DEBUG_ERROR("Cellular device not ready"); - return 0; - } - _device->set_cmux_status_flag(_cmuxGSMenable); _device->set_retry_timeout_array(_retry_timeout, sizeof(_retry_timeout) / sizeof(_retry_timeout[0])); _device->attach(mbed::callback(this, &GSMClass::onStatusChange)); @@ -170,22 +165,7 @@ void arduino::GSMClass::reset() { delay(1); } -bool arduino::GSMClass::isReady(const int timeout) { - if (!_device) { - DEBUG_ERROR("No device found"); - return false; - } - const unsigned int start = millis(); - while (_device->is_ready() != NSAPI_ERROR_OK) { - if (millis() - start > timeout) { - DEBUG_WARNING("Timeout waiting device ready"); - return false; - } - delay(100); - } - return true; -} arduino::GSMClass GSM; diff --git a/libraries/GSM/src/GSM.h b/libraries/GSM/src/GSM.h index 44424ee4b..33b31f8ce 100644 --- a/libraries/GSM/src/GSM.h +++ b/libraries/GSM/src/GSM.h @@ -147,7 +147,6 @@ class GSMClass : public MbedSocketClass { void onStatusChange(nsapi_event_t ev, intptr_t in); void reset(); - bool isReady(const int timeout = 5000); }; } From 249f84cb59ba4f058489f372c039f2789347000a Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 15 Oct 2024 12:43:27 +0200 Subject: [PATCH 09/43] GSM: add end() implementation --- libraries/GSM/src/GSM.cpp | 2 +- libraries/GSM/src/GSM.h | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/libraries/GSM/src/GSM.cpp b/libraries/GSM/src/GSM.cpp index 786cd0ee6..d172591f0 100644 --- a/libraries/GSM/src/GSM.cpp +++ b/libraries/GSM/src/GSM.cpp @@ -110,7 +110,7 @@ bool arduino::GSMClass::isCmuxEnable() { } void arduino::GSMClass::end() { - + _device->shutdown(); } int arduino::GSMClass::disconnect() { diff --git a/libraries/GSM/src/GSM.h b/libraries/GSM/src/GSM.h index 33b31f8ce..406b258be 100644 --- a/libraries/GSM/src/GSM.h +++ b/libraries/GSM/src/GSM.h @@ -95,6 +95,9 @@ class GSMClass : public MbedSocketClass { */ int disconnect(void); + /* + * Reset internal state machine in order to be ready to reconnect again. + */ void end(void); unsigned long getTime(); From a66c946fcc2fb6b8587a034b8c5c213873d014fe Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 15 Oct 2024 12:44:15 +0200 Subject: [PATCH 10/43] GSM: fix comments alignment --- libraries/GSM/src/GSM.h | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/libraries/GSM/src/GSM.h b/libraries/GSM/src/GSM.h index 406b258be..36549d0fb 100644 --- a/libraries/GSM/src/GSM.h +++ b/libraries/GSM/src/GSM.h @@ -75,24 +75,24 @@ class GSMClass : public MbedSocketClass { } } - /* Start GSM connection. - * Configure the credentials into the device. - * - * param pin: Pointer to the pin string. - * param apn: Pointer to the apn string. - * param username: Pointer to the username string. - * param password: Pointer to the password string. - * param rat: Radio Access Technology. - * - * return: 0 in case of success, negative number in case of failure - */ + /* + * Start GSM connection. Configure the credentials into the device. + * + * param pin: Pointer to the pin string. + * param apn: Pointer to the apn string. + * param username: Pointer to the username string. + * param password: Pointer to the password string. + * param rat: Radio Access Technology. + * + * return: 0 in case of success, negative number in case of failure + */ int begin(const char* pin, const char* apn, const char* username, const char* password, RadioAccessTechnologyType rat = CATNB, uint32_t band = BAND_20, bool restart = true); /* - * Disconnect from the network - * - * return: one value of wl_status_t enum - */ + * Disconnect from the network + * + * return: one value of wl_status_t enum + */ int disconnect(void); /* From e1b61e22591a882764c956d0e256b4d8280511f7 Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 15 Oct 2024 12:51:17 +0200 Subject: [PATCH 11/43] GSM: add setTimeout function --- libraries/GSM/src/GSM.cpp | 5 +++++ libraries/GSM/src/GSM.h | 7 ++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/libraries/GSM/src/GSM.cpp b/libraries/GSM/src/GSM.cpp index d172591f0..18d280747 100644 --- a/libraries/GSM/src/GSM.cpp +++ b/libraries/GSM/src/GSM.cpp @@ -68,6 +68,7 @@ int arduino::GSMClass::begin(const char* pin, const char* apn, const char* usern _device->set_cmux_status_flag(_cmuxGSMenable); _device->set_retry_timeout_array(_retry_timeout, sizeof(_retry_timeout) / sizeof(_retry_timeout[0])); + _device->set_timeout(_timeout); _device->attach(mbed::callback(this, &GSMClass::onStatusChange)); _device->init(); @@ -101,6 +102,10 @@ int arduino::GSMClass::begin(const char* pin, const char* apn, const char* usern return connect_status == NSAPI_ERROR_OK ? 1 : 0; } +void arduino::GSMClass::setTimeout(unsigned long timeout) { + _timeout = timeout; +} + void arduino::GSMClass::enableCmux() { _cmuxGSMenable = true; } diff --git a/libraries/GSM/src/GSM.h b/libraries/GSM/src/GSM.h index 36549d0fb..f0cf1ff23 100644 --- a/libraries/GSM/src/GSM.h +++ b/libraries/GSM/src/GSM.h @@ -100,8 +100,12 @@ class GSMClass : public MbedSocketClass { */ void end(void); - unsigned long getTime(); + /* + * Change cellular state timeouts. Needs to be called before GSM.begin() + */ + void setTimeout(unsigned long timeout); + unsigned long getTime(); unsigned long getLocalTime(); bool setTime(unsigned long const epoch, int const timezone = 0); @@ -130,6 +134,7 @@ class GSMClass : public MbedSocketClass { mbed::CellularContext* _context = nullptr; mbed::CellularDevice* _device = nullptr; bool _at_debug = false; + unsigned long _timeout = 1000; /* Internal cellular state machine retries. Values are in seconds. * This array also defines the maximum number of retries to CELLULAR_RETRY_ARRAY_SIZE From 8b06fb3949e2aa5dfe973fdb0274864584634fab Mon Sep 17 00:00:00 2001 From: pennam Date: Wed, 16 Oct 2024 10:56:52 +0200 Subject: [PATCH 12/43] GSM: cleanup power on sequence and add comments --- libraries/GSM/src/GSM.cpp | 28 ++++++++++++++++++++++++---- libraries/GSM/src/GSM.h | 1 + 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/libraries/GSM/src/GSM.cpp b/libraries/GSM/src/GSM.cpp index 18d280747..a576801a5 100644 --- a/libraries/GSM/src/GSM.cpp +++ b/libraries/GSM/src/GSM.cpp @@ -46,10 +46,26 @@ mbed::CellularDevice *mbed::CellularDevice::get_default_instance() int arduino::GSMClass::begin(const char* pin, const char* apn, const char* username, const char* password, RadioAccessTechnologyType rat, uint32_t band, bool restart) { + /* Assume module is powered ON. Uncomment this line is you are using + * Edge Control without Arduino_ConnectionHandler + * #if defined (ARDUINO_EDGE_CONTROL) + * pinMode(ON_MKR2, OUTPUT); + * digitalWrite(ON_MKR2, HIGH); + * #endif + */ + + /* Ensure module is not under reset */ + pinMode(MBED_CONF_GEMALTO_CINTERION_RST, OUTPUT); + digitalWrite(MBED_CONF_GEMALTO_CINTERION_RST, LOW); + + /* Reset module if needed */ if (restart || isCmuxEnable()) { reset(); } + /* Create rising edge on pin ON */ + on(); + if (!_context) { _context = mbed::CellularContext::get_default_instance(); } @@ -59,9 +75,10 @@ int arduino::GSMClass::begin(const char* pin, const char* apn, const char* usern return 0; } - pinMode(MBED_CONF_GEMALTO_CINTERION_ON, INPUT_PULLDOWN); - +#if defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_PORTENTA_H7_M4) + /* This is needed to wakeup module if hw flow control is enabled */ static mbed::DigitalOut rts(MBED_CONF_GEMALTO_CINTERION_RTS, 0); +#endif _device = _context->get_device(); _device->modem_debug_on(_at_debug); @@ -159,10 +176,15 @@ NetworkInterface* arduino::GSMClass::getNetwork() { } void arduino::GSMClass::reset() { + /* Reset logic is inverted */ pinMode(MBED_CONF_GEMALTO_CINTERION_RST, OUTPUT); digitalWrite(MBED_CONF_GEMALTO_CINTERION_RST, HIGH); delay(800); digitalWrite(MBED_CONF_GEMALTO_CINTERION_RST, LOW); +} + +void arduino::GSMClass::on() { + /* Module needs a rising edge to power on */ pinMode(MBED_CONF_GEMALTO_CINTERION_ON, OUTPUT); digitalWrite(MBED_CONF_GEMALTO_CINTERION_ON, LOW); delay(1); @@ -171,6 +193,4 @@ void arduino::GSMClass::reset() { } - - arduino::GSMClass GSM; diff --git a/libraries/GSM/src/GSM.h b/libraries/GSM/src/GSM.h index f0cf1ff23..647e12bf0 100644 --- a/libraries/GSM/src/GSM.h +++ b/libraries/GSM/src/GSM.h @@ -155,6 +155,7 @@ class GSMClass : public MbedSocketClass { void onStatusChange(nsapi_event_t ev, intptr_t in); void reset(); + void on(); }; } From 1b2ddf36e88dbf8892377caf42b2a4e2b6099500 Mon Sep 17 00:00:00 2001 From: "Zachary J. Fields" Date: Thu, 27 Mar 2025 17:08:38 -0500 Subject: [PATCH 13/43] feat: Opta pin names to match serigraphy Enables a user to intuit the pin name of the input pins, without having to reference this file. --- variants/OPTA/pins_arduino.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/variants/OPTA/pins_arduino.h b/variants/OPTA/pins_arduino.h index 301ac30aa..107190dc8 100644 --- a/variants/OPTA/pins_arduino.h +++ b/variants/OPTA/pins_arduino.h @@ -68,6 +68,16 @@ static const uint8_t A6 = PIN_A6; static const uint8_t A7 = PIN_A7; #define ADC_RESOLUTION 12 +// Pin mapping to match serigraphy +static const uint8_t I1 = PIN_A0; +static const uint8_t I2 = PIN_A1; +static const uint8_t I3 = PIN_A2; +static const uint8_t I4 = PIN_A3; +static const uint8_t I5 = PIN_A4; +static const uint8_t I6 = PIN_A5; +static const uint8_t I7 = PIN_A6; +static const uint8_t I8 = PIN_A7; + // Digital pins // ----------- #define D0 (0u) From 77647149461f73488349ea4cbc5ec0997e384c6a Mon Sep 17 00:00:00 2001 From: Mattia Pennasilico Date: Thu, 3 Apr 2025 09:25:04 +0200 Subject: [PATCH 14/43] STM32H747_System: remove unused variable --- libraries/STM32H747_System/src/STM32H747_System.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libraries/STM32H747_System/src/STM32H747_System.cpp b/libraries/STM32H747_System/src/STM32H747_System.cpp index e54736b95..8789dfae7 100644 --- a/libraries/STM32H747_System/src/STM32H747_System.cpp +++ b/libraries/STM32H747_System/src/STM32H747_System.cpp @@ -6,7 +6,6 @@ extern RTC_HandleTypeDef RTCHandle; uint8_t STM32H747::readReg(uint8_t subAddress) { - char response = 0xFF; Wire1.beginTransmission(PMIC_ADDRESS); Wire1.write(subAddress); Wire1.endTransmission(false); @@ -115,4 +114,4 @@ bool STM32H747::useInternalOscillator(bool lowspeed) { digitalWrite(PH_1, LOW); return true; -} \ No newline at end of file +} From 84ba5612c8ba30814d1a661851d41c8c094ffb9c Mon Sep 17 00:00:00 2001 From: Leonardo Cavagnis Date: Fri, 18 Apr 2025 16:01:51 +0200 Subject: [PATCH 15/43] h7 video + lvgl: remove unused buffer --- libraries/Arduino_H7_Video/src/Arduino_H7_Video.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/libraries/Arduino_H7_Video/src/Arduino_H7_Video.cpp b/libraries/Arduino_H7_Video/src/Arduino_H7_Video.cpp index 2bb02ebc9..68ee9b01f 100644 --- a/libraries/Arduino_H7_Video/src/Arduino_H7_Video.cpp +++ b/libraries/Arduino_H7_Video/src/Arduino_H7_Video.cpp @@ -111,10 +111,6 @@ int Arduino_H7_Video::begin() { if (buf1 == NULL) { return 2; /* Insuff memory err */ } - static lv_color_t * buf2 = (lv_color_t*)malloc((width() * height() / 10)); /* Declare a buffer for 1/10 screen size */ - if (buf2 == NULL) { - return 2; /* Insuff memory err */ - } lv_display_t *display; if(_rotated) { From 571674f9c322de41e4f9316eaeeb771fe9bfd021 Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 29 Apr 2025 10:15:54 +0200 Subject: [PATCH 16/43] opta packaging: add MCUboot library --- opta.variables | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opta.variables b/opta.variables index dc36376d6..ecafac369 100755 --- a/opta.variables +++ b/opta.variables @@ -1,5 +1,5 @@ export FLAVOUR="opta" export VARIANTS=("OPTA GENERIC_STM32H747_M4") export FQBNS=("opta") -export LIBRARIES=("Ethernet SPI WiFi openamp_arduino ThreadDebug KernelDebug RPC USBHID Wire rpclib USBHOST mbed-memory-status Scheduler USBMSD SocketWrapper STM32H747_System MRI") +export LIBRARIES=("Ethernet SPI WiFi openamp_arduino ThreadDebug KernelDebug RPC USBHID Wire rpclib USBHOST mbed-memory-status Scheduler USBMSD SocketWrapper STM32H747_System MRI MCUboot") export BOOTLOADERS=("OPTA") From f2e34b440bc952ca0055f2ab06892a08ee235e42 Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 29 Apr 2025 10:17:17 +0200 Subject: [PATCH 17/43] GIGA: add Tools, security settings menu --- boards.txt | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/boards.txt b/boards.txt index ee8018487..79a40e70e 100644 --- a/boards.txt +++ b/boards.txt @@ -767,6 +767,9 @@ giga.menu.split.100_0=2MB M7 + M4 in SDRAM giga.menu.split.75_25=1.5MB M7 + 0.5MB M4 giga.menu.split.50_50=1MB M7 + 1MB M4 +giga.menu.security.none=None +giga.menu.security.sien=Signature + Encryption + giga.menu.target_core.cm7.build.variant=GIGA giga.menu.target_core.cm7.build.mcu=cortex-m7 giga.menu.target_core.cm7.build.fpu=-mfpu=fpv5-d16 @@ -792,6 +795,14 @@ giga.build.board=GIGA giga.build.ldscript=linker_script.ld giga.build.extra_ldflags=-DCM4_BINARY_START=0x08180000 giga.compiler.mbed.arch.define= +giga.build.slot_size=0x1E0000 +giga.build.header_size=0x20000 +giga.build.alignment=32 +giga.build.version=1.2.3+4 +giga.menu.security.sien.recipe.hooks.objcopy.postobjcopy.1.pattern="{tools.imgtool.path}/{tools.imgtool.cmd}" {tools.imgtool.flags} +giga.menu.security.sien.build.keys.keychain={runtime.platform.path}/libraries/MCUboot/default_keys +giga.menu.security.sien.build.keys.sign_key=ecdsa-p256-signing-priv-key.pem +giga.menu.security.sien.build.keys.encrypt_key=ecdsa-p256-encrypt-pub-key.pem giga.compiler.mbed.defines={build.variant.path}/defines.txt giga.compiler.mbed.ldflags={build.variant.path}/ldflags.txt giga.compiler.mbed.cflags={build.variant.path}/cflags.txt @@ -825,7 +836,12 @@ giga.upload.native_usb=true giga.upload.maximum_size=1966080 giga.upload.maximum_data_size=523624 -giga.menu.target_core.cm7.upload.address=0x08040000 +giga.menu.security.none.upload.interface=0 +giga.menu.security.sien.upload.interface=2 + +giga.menu.security.none.upload.address_m7=0x08040000 +giga.menu.security.sien.upload.address_m7=0xA0000000 +giga.menu.target_core.cm7.upload.address={upload.address_m7} giga.menu.target_core.cm7.menu.split.50_50.upload.maximum_size=786432 giga.menu.target_core.cm7.menu.split.75_25.upload.maximum_size=1441792 From a9991f4509cade126fb5c1ecf13aee6cbec4622f Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 29 Apr 2025 15:33:57 +0200 Subject: [PATCH 18/43] I2CSlave: fix slave write --- libraries/Wire/Wire.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/libraries/Wire/Wire.cpp b/libraries/Wire/Wire.cpp index 9b345d3e1..f7bb57bf8 100644 --- a/libraries/Wire/Wire.cpp +++ b/libraries/Wire/Wire.cpp @@ -124,7 +124,6 @@ size_t arduino::MbedI2C::write(const uint8_t* data, int len) { int arduino::MbedI2C::read() { int rv = -1; core_util_critical_section_enter(); - if (rxBuffer.available()) { rv = rxBuffer.read_char(); @@ -159,9 +158,7 @@ void arduino::MbedI2C::receiveThd() { onRequestCb(); } if (usedTxBuffer != 0) { - core_util_critical_section_enter(); slave->write((const char *) txBuffer, usedTxBuffer); - core_util_critical_section_exit(); usedTxBuffer = 0; } //slave->stop(); From 6ca44223cf2d38d2955a2268e83cb40b6427fbc5 Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 29 Apr 2025 16:31:02 +0200 Subject: [PATCH 19/43] I2CSlave: restore critical section with temp buffer --- libraries/Wire/Wire.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libraries/Wire/Wire.cpp b/libraries/Wire/Wire.cpp index f7bb57bf8..a382fc66f 100644 --- a/libraries/Wire/Wire.cpp +++ b/libraries/Wire/Wire.cpp @@ -158,8 +158,12 @@ void arduino::MbedI2C::receiveThd() { onRequestCb(); } if (usedTxBuffer != 0) { - slave->write((const char *) txBuffer, usedTxBuffer); + core_util_critical_section_enter(); + uint8_t tempTxBuffer[usedTxBuffer]; + memcpy(tempTxBuffer, txBuffer, sizeof(tempTxBuffer)); usedTxBuffer = 0; + core_util_critical_section_exit(); + slave->write((const char *) tempTxBuffer, sizeof(tempTxBuffer)); } //slave->stop(); break; From 6231980a20cf4e9d5b4e41ff4c572ccc5fe3f63c Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 29 Apr 2025 17:41:24 +0200 Subject: [PATCH 20/43] I2CSlave: do not use vla --- libraries/Wire/Wire.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/libraries/Wire/Wire.cpp b/libraries/Wire/Wire.cpp index a382fc66f..155ab4fc8 100644 --- a/libraries/Wire/Wire.cpp +++ b/libraries/Wire/Wire.cpp @@ -159,11 +159,12 @@ void arduino::MbedI2C::receiveThd() { } if (usedTxBuffer != 0) { core_util_critical_section_enter(); - uint8_t tempTxBuffer[usedTxBuffer]; - memcpy(tempTxBuffer, txBuffer, sizeof(tempTxBuffer)); + uint8_t tempTxBuffer[256]; + uint8_t usedTempTxBuffer = usedTxBuffer; + memcpy(tempTxBuffer, txBuffer, usedTempTxBuffer); usedTxBuffer = 0; core_util_critical_section_exit(); - slave->write((const char *) tempTxBuffer, sizeof(tempTxBuffer)); + slave->write((const char *) tempTxBuffer, usedTempTxBuffer); } //slave->stop(); break; From e407cc981e7872b9f1c649a16a2eba9d989a6d7f Mon Sep 17 00:00:00 2001 From: Mattia Pennasilico Date: Mon, 5 May 2025 08:42:53 +0200 Subject: [PATCH 21/43] openamp: add mbed_giga architecture --- libraries/openamp_arduino/library.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/openamp_arduino/library.properties b/libraries/openamp_arduino/library.properties index 51525e1a6..d2ebd4a2a 100644 --- a/libraries/openamp_arduino/library.properties +++ b/libraries/openamp_arduino/library.properties @@ -6,5 +6,5 @@ sentence=Enables the communication between H747 cores via shared memory and open paragraph= category=Communication url= -architectures=mbed,mbed_portenta,mbed_nicla,mbed_opta +architectures=mbed,mbed_portenta,mbed_nicla,mbed_opta,mbed_giga dot_a_linkage=true From 9ed95adc0fa27701eaf2bfb6372ccc7f71f89b0b Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 31 Oct 2024 08:52:44 +0100 Subject: [PATCH 22/43] GSM: GSM::end() add device shutdown command --- libraries/GSM/src/GSM.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libraries/GSM/src/GSM.cpp b/libraries/GSM/src/GSM.cpp index a576801a5..8fdb785c8 100644 --- a/libraries/GSM/src/GSM.cpp +++ b/libraries/GSM/src/GSM.cpp @@ -132,7 +132,9 @@ bool arduino::GSMClass::isCmuxEnable() { } void arduino::GSMClass::end() { - _device->shutdown(); + if(_device) { + _device->shutdown(); + } } int arduino::GSMClass::disconnect() { From 31759bdbb673727810d1afa51dd1b8b7a12c6772 Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 31 Oct 2024 08:53:25 +0100 Subject: [PATCH 23/43] GSM: don't disconnect if not connected --- libraries/GSM/src/GSM.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/libraries/GSM/src/GSM.cpp b/libraries/GSM/src/GSM.cpp index 8fdb785c8..e13b0744e 100644 --- a/libraries/GSM/src/GSM.cpp +++ b/libraries/GSM/src/GSM.cpp @@ -138,9 +138,14 @@ void arduino::GSMClass::end() { } int arduino::GSMClass::disconnect() { - if (_context) { + if (!_context) { + return 0; + } + + if (_context->is_connected()) { return _context->disconnect(); } + return 0; } From 04be7993d88028d310742d13d1b73b23c3ea1ed2 Mon Sep 17 00:00:00 2001 From: megacct <96644325+megacct@users.noreply.github.com> Date: Fri, 14 Mar 2025 19:19:57 +0000 Subject: [PATCH 24/43] SocketHelpers: expose ping timeout --- libraries/SocketWrapper/src/SocketHelpers.cpp | 12 ++++++------ libraries/SocketWrapper/src/SocketHelpers.h | 8 ++++---- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/libraries/SocketWrapper/src/SocketHelpers.cpp b/libraries/SocketWrapper/src/SocketHelpers.cpp index b7e39b42c..b113e510f 100644 --- a/libraries/SocketWrapper/src/SocketHelpers.cpp +++ b/libraries/SocketWrapper/src/SocketHelpers.cpp @@ -75,22 +75,22 @@ arduino::IPAddress arduino::MbedSocketClass::dnsIP(int n) { return ipAddressFromSocketAddress(ip); } -int arduino::MbedSocketClass::ping(const char *hostname, uint8_t ttl) +int arduino::MbedSocketClass::ping(const char *hostname, uint8_t ttl, uint32_t timeout) { SocketAddress socketAddress; gethostbyname(getNetwork(),hostname, &socketAddress); - return ping(socketAddress, ttl); + return ping(socketAddress, ttl, timeout); } -int arduino::MbedSocketClass::ping(const String &hostname, uint8_t ttl) +int arduino::MbedSocketClass::ping(const String &hostname, uint8_t ttl, uint32_t timeout) { - return ping(hostname.c_str(), ttl); + return ping(hostname.c_str(), ttl, timeout); } -int arduino::MbedSocketClass::ping(IPAddress host, uint8_t ttl) +int arduino::MbedSocketClass::ping(IPAddress host, uint8_t ttl, uint32_t timeout) { SocketAddress socketAddress = socketAddressFromIpAddress(host, 0); - return ping(socketAddress, ttl); + return ping(socketAddress, ttl, timeout); } void arduino::MbedSocketClass::config(arduino::IPAddress local_ip) { diff --git a/libraries/SocketWrapper/src/SocketHelpers.h b/libraries/SocketWrapper/src/SocketHelpers.h index e285d166c..428ab4a63 100644 --- a/libraries/SocketWrapper/src/SocketHelpers.h +++ b/libraries/SocketWrapper/src/SocketHelpers.h @@ -118,9 +118,9 @@ class MbedSocketClass { * * return: RTT in milliseconds or -1 on error */ - int ping(const char* hostname, uint8_t ttl = 255); - int ping(const String &hostname, uint8_t ttl = 255); - int ping(IPAddress host, uint8_t ttl = 255); + int ping(const char* hostname, uint8_t ttl = 255, uint32_t timeout = 5000); + int ping(const String &hostname, uint8_t ttl = 255, uint32_t timeout = 5000); + int ping(IPAddress host, uint8_t ttl = 255, uint32_t timeout = 5000); /* * Download a file from an HTTP endpoint and save it in the provided `target` location on the fs @@ -185,7 +185,7 @@ class MbedSocketClass { void body_callback(const char* data, uint32_t data_len); - int ping(SocketAddress &socketAddress, uint8_t ttl, uint32_t timeout = 5000); + int ping(SocketAddress &socketAddress, uint8_t ttl, uint32_t timeout); static arduino::IPAddress ipAddressFromSocketAddress(SocketAddress socketAddress); static SocketAddress socketAddressFromIpAddress(arduino::IPAddress ip, uint16_t port); static nsapi_error_t gethostbyname(NetworkInterface* interface, const char* aHostname, SocketAddress* socketAddress); From d95d934b03107a2266d7714504e643e9967c8628 Mon Sep 17 00:00:00 2001 From: pennam Date: Mon, 5 May 2025 14:43:31 +0200 Subject: [PATCH 25/43] GSMClient: retry write --- libraries/GSM/src/GSMClient.h | 20 ++++++++++++++++++++ libraries/GSM/src/GSMSSLClient.h | 19 +++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/libraries/GSM/src/GSMClient.h b/libraries/GSM/src/GSMClient.h index f29292fb9..cf7d49af5 100644 --- a/libraries/GSM/src/GSMClient.h +++ b/libraries/GSM/src/GSMClient.h @@ -26,9 +26,29 @@ namespace arduino { class GSMClient : public AClient { +private: NetworkInterface *getNetwork() { return GSM.getNetwork(); } + +public: + size_t write(uint8_t b) { + int ret = 0; + do { + ret = client->write(b); + delay(0); + } while (ret == 0 && status()); + return ret; + } + + size_t write(const uint8_t *buf, size_t size) { + int ret = 0; + do { + ret = client->write(buf, size); + delay(0); + } while (ret == 0 && status()); + return ret; + } }; } diff --git a/libraries/GSM/src/GSMSSLClient.h b/libraries/GSM/src/GSMSSLClient.h index cc7d3c194..add77b900 100644 --- a/libraries/GSM/src/GSMSSLClient.h +++ b/libraries/GSM/src/GSMSSLClient.h @@ -32,6 +32,25 @@ class GSMSSLClient : public arduino::ASslClient { NetworkInterface *getNetwork() { return GSM.getNetwork(); } + +public: + size_t write(uint8_t b) { + int ret = 0; + do { + ret = client->write(b); + delay(0); + } while (ret == 0 && status()); + return ret; + } + + size_t write(const uint8_t *buf, size_t size) { + int ret = 0; + do { + ret = client->write(buf, size); + delay(0); + } while (ret == 0 && status()); + return ret; + } }; } From 5816be99dd28458bc89923a40abf315d73efb864 Mon Sep 17 00:00:00 2001 From: pennam Date: Mon, 5 May 2025 14:44:43 +0200 Subject: [PATCH 26/43] patches: GEMALTO CINTERION fixes for connection retries --- ...RION-cleanup-stack-before-connection.patch | 29 +++++ ...TO-CINTERION-close-socket-on-timeout.patch | 25 +++++ ...ALTO-CINTERION-add-debug-for-urc_sis.patch | 33 ++++++ ...N-add-configuration-for-urcs-during-.patch | 33 ++++++ ...TO-CINTERION-fix-enable-cmux-command.patch | 57 ++++++++++ ...CINTERION-override-shutdown-function.patch | 42 ++++++++ ...N-use-default-timeout-to-close-socke.patch | 32 ++++++ ...ON-add-soft_power_off-and-soft_reset.patch | 102 ++++++++++++++++++ ...RION-disable-runtime-model-detection.patch | 71 ++++++++++++ patches/0257-GEMALTO-CONTERION-add-ping.patch | 53 +++++++++ ...-GEMALTO-CINTERION-fix-gethostbyname.patch | 25 +++++ ...hine-wait-and-retry-if-signal-qualit.patch | 26 +++++ ...N-fix-RECV-urc-while-reading-cornerc.patch | 26 +++++ ...ERION-add-1ms-sleep-in-socket-sendto.patch | 33 ++++++ 14 files changed, 587 insertions(+) create mode 100644 patches/0248-GEMALTO-CINTERION-cleanup-stack-before-connection.patch create mode 100644 patches/0249-GEMALTO-CINTERION-close-socket-on-timeout.patch create mode 100644 patches/0250-GEMALTO-CINTERION-add-debug-for-urc_sis.patch create mode 100644 patches/0251-GEMALTO-CINTERION-add-configuration-for-urcs-during-.patch create mode 100644 patches/0252-GEMALTO-CINTERION-fix-enable-cmux-command.patch create mode 100644 patches/0253-GEMALTO-CINTERION-override-shutdown-function.patch create mode 100644 patches/0254-GEMALTO-CINTERION-use-default-timeout-to-close-socke.patch create mode 100644 patches/0255-GEMALTO-CINTERION-add-soft_power_off-and-soft_reset.patch create mode 100644 patches/0256-GEMALTO-CINTERION-disable-runtime-model-detection.patch create mode 100644 patches/0257-GEMALTO-CONTERION-add-ping.patch create mode 100644 patches/0258-GEMALTO-CINTERION-fix-gethostbyname.patch create mode 100644 patches/0259-CellularStateMachine-wait-and-retry-if-signal-qualit.patch create mode 100644 patches/0260-GEMALTO-CINTERION-fix-RECV-urc-while-reading-cornerc.patch create mode 100644 patches/0261-GEMALTO-CINTERION-add-1ms-sleep-in-socket-sendto.patch diff --git a/patches/0248-GEMALTO-CINTERION-cleanup-stack-before-connection.patch b/patches/0248-GEMALTO-CINTERION-cleanup-stack-before-connection.patch new file mode 100644 index 000000000..d9cb9e31c --- /dev/null +++ b/patches/0248-GEMALTO-CINTERION-cleanup-stack-before-connection.patch @@ -0,0 +1,29 @@ +From f40d4a9d65ee9163921271697d316c1061aca946 Mon Sep 17 00:00:00 2001 +From: pennam +Date: Thu, 31 Oct 2024 11:05:18 +0100 +Subject: [PATCH] GEMALTO CINTERION: cleanup stack before connection + + Allows to re-connect after a disconnection +--- + .../GEMALTO/CINTERION/GEMALTO_CINTERION_CellularContext.cpp | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/connectivity/drivers/cellular/GEMALTO/CINTERION/GEMALTO_CINTERION_CellularContext.cpp b/connectivity/drivers/cellular/GEMALTO/CINTERION/GEMALTO_CINTERION_CellularContext.cpp +index 78955c599e..76c788cdaf 100644 +--- a/connectivity/drivers/cellular/GEMALTO/CINTERION/GEMALTO_CINTERION_CellularContext.cpp ++++ b/connectivity/drivers/cellular/GEMALTO/CINTERION/GEMALTO_CINTERION_CellularContext.cpp +@@ -35,6 +35,11 @@ nsapi_error_t GEMALTO_CINTERION_CellularContext::connect(const char *sim_pin, co + { + nsapi_error_t error = NSAPI_ERROR_OK; + ++ if (_stack) { ++ delete _stack; ++ _stack = NULL; ++ } ++ + set_sim_pin(sim_pin); + set_credentials(apn, uname, pwd); + +-- +2.45.2 + diff --git a/patches/0249-GEMALTO-CINTERION-close-socket-on-timeout.patch b/patches/0249-GEMALTO-CINTERION-close-socket-on-timeout.patch new file mode 100644 index 000000000..1fbb4021a --- /dev/null +++ b/patches/0249-GEMALTO-CINTERION-close-socket-on-timeout.patch @@ -0,0 +1,25 @@ +From 4b6c6ad0554c88c369fc4e2e5ed543d52117aa3f Mon Sep 17 00:00:00 2001 +From: pennam +Date: Thu, 31 Oct 2024 12:00:51 +0100 +Subject: [PATCH] GEMALTO CINTERION: close socket on timeout + +--- + .../GEMALTO/CINTERION/GEMALTO_CINTERION_CellularStack.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/connectivity/drivers/cellular/GEMALTO/CINTERION/GEMALTO_CINTERION_CellularStack.cpp b/connectivity/drivers/cellular/GEMALTO/CINTERION/GEMALTO_CINTERION_CellularStack.cpp +index ac2a54282a..41a01859e7 100644 +--- a/connectivity/drivers/cellular/GEMALTO/CINTERION/GEMALTO_CINTERION_CellularStack.cpp ++++ b/connectivity/drivers/cellular/GEMALTO/CINTERION/GEMALTO_CINTERION_CellularStack.cpp +@@ -59,7 +59,7 @@ void GEMALTO_CINTERION_CellularStack::urc_sis() + } + if (urc_code == 0) { + int urc_info_id = _at.read_int(); +- if (urc_info_id == 48) { ++ if (urc_info_id == 48 || urc_info_id == 20) { + tr_info("Socket closed %d", sock_id); + sock->closed = true; + if (sock->_cb) { +-- +2.45.2 + diff --git a/patches/0250-GEMALTO-CINTERION-add-debug-for-urc_sis.patch b/patches/0250-GEMALTO-CINTERION-add-debug-for-urc_sis.patch new file mode 100644 index 000000000..4c41b0918 --- /dev/null +++ b/patches/0250-GEMALTO-CINTERION-add-debug-for-urc_sis.patch @@ -0,0 +1,33 @@ +From 84e682a7f4c0c05dded7f12817f78c1cc9a66cfe Mon Sep 17 00:00:00 2001 +From: pennam +Date: Thu, 31 Oct 2024 12:01:47 +0100 +Subject: [PATCH] GEMALTO CINTERION: add debug for urc_sis + +--- + .../GEMALTO/CINTERION/GEMALTO_CINTERION_CellularStack.cpp | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/connectivity/drivers/cellular/GEMALTO/CINTERION/GEMALTO_CINTERION_CellularStack.cpp b/connectivity/drivers/cellular/GEMALTO/CINTERION/GEMALTO_CINTERION_CellularStack.cpp +index 41a01859e7..9a3f22dc3c 100644 +--- a/connectivity/drivers/cellular/GEMALTO/CINTERION/GEMALTO_CINTERION_CellularStack.cpp ++++ b/connectivity/drivers/cellular/GEMALTO/CINTERION/GEMALTO_CINTERION_CellularStack.cpp +@@ -47,6 +47,8 @@ void GEMALTO_CINTERION_CellularStack::urc_sis() + int sock_id = _at.read_int(); + int urc_code = _at.read_int(); + CellularSocket *sock = find_socket(sock_id); ++ ++ tr_info("urc_sis socket id %d urc code %d\n\r", sock_id, urc_code); + if (sock) { + // Currently only UDP is supported so there is need to handle only some error codes here, + // and others are detected on sendto/recvfrom responses. +@@ -59,6 +61,7 @@ void GEMALTO_CINTERION_CellularStack::urc_sis() + } + if (urc_code == 0) { + int urc_info_id = _at.read_int(); ++ tr_info("urcInfoId %d\n\r", urc_info_id); + if (urc_info_id == 48 || urc_info_id == 20) { + tr_info("Socket closed %d", sock_id); + sock->closed = true; +-- +2.45.2 + diff --git a/patches/0251-GEMALTO-CINTERION-add-configuration-for-urcs-during-.patch b/patches/0251-GEMALTO-CINTERION-add-configuration-for-urcs-during-.patch new file mode 100644 index 000000000..290452457 --- /dev/null +++ b/patches/0251-GEMALTO-CINTERION-add-configuration-for-urcs-during-.patch @@ -0,0 +1,33 @@ +From 5cc2a1998d37bad69a0b4e75b7d6f7b92e95935c Mon Sep 17 00:00:00 2001 +From: pennam +Date: Thu, 31 Oct 2024 12:03:00 +0100 +Subject: [PATCH] GEMALTO CINTERION: add configuration for urcs during + read + +--- + .../CINTERION/GEMALTO_CINTERION_CellularStack.cpp | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/connectivity/drivers/cellular/GEMALTO/CINTERION/GEMALTO_CINTERION_CellularStack.cpp b/connectivity/drivers/cellular/GEMALTO/CINTERION/GEMALTO_CINTERION_CellularStack.cpp +index 9a3f22dc3c..a96cb2b360 100644 +--- a/connectivity/drivers/cellular/GEMALTO/CINTERION/GEMALTO_CINTERION_CellularStack.cpp ++++ b/connectivity/drivers/cellular/GEMALTO/CINTERION/GEMALTO_CINTERION_CellularStack.cpp +@@ -527,8 +527,13 @@ sisw_retry: + return (_at.get_last_error() == NSAPI_ERROR_OK) ? accept_len : NSAPI_ERROR_DEVICE_ERROR; + } + +-#define DISABLE_URCs _at.at_cmd_discard("^SCFG", "=", "%s%s","Tcp/WithURCs","off") +-#define RESTORE_URCs_AND_RETURN(ret) do { _at.at_cmd_discard("^SCFG", "=", "%s%s","Tcp/WithURCs","on"); return ret; } while(0) ++#if defined GEMALTO_CINTERION_DISABLE_URC_READING ++ #define DISABLE_URCs _at.at_cmd_discard("^SCFG", "=", "%s%s","Tcp/WithURCs","off") ++ #define RESTORE_URCs_AND_RETURN(ret) do { _at.at_cmd_discard("^SCFG", "=", "%s%s","Tcp/WithURCs","on"); return ret; } while(0) ++#else ++ #define DISABLE_URCs ++ #define RESTORE_URCs_AND_RETURN(ret) do { return ret; } while(0) ++#endif + + nsapi_size_or_error_t GEMALTO_CINTERION_CellularStack::socket_recvfrom_impl(CellularSocket *socket, SocketAddress *address, + void *buffer, nsapi_size_t size) +-- +2.45.2 + diff --git a/patches/0252-GEMALTO-CINTERION-fix-enable-cmux-command.patch b/patches/0252-GEMALTO-CINTERION-fix-enable-cmux-command.patch new file mode 100644 index 000000000..711836c5d --- /dev/null +++ b/patches/0252-GEMALTO-CINTERION-fix-enable-cmux-command.patch @@ -0,0 +1,57 @@ +From a76136121ab8066a1ee4afab9254552752b96a5d Mon Sep 17 00:00:00 2001 +From: pennam +Date: Wed, 13 Nov 2024 08:28:13 +0100 +Subject: [PATCH] GEMALTO CINTERION: fix enable cmux command + +--- + .../cellular/source/framework/AT/AT_CellularDevice.cpp | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +diff --git a/connectivity/cellular/source/framework/AT/AT_CellularDevice.cpp b/connectivity/cellular/source/framework/AT/AT_CellularDevice.cpp +index 08229ba49b..3eccc4a5c0 100644 +--- a/connectivity/cellular/source/framework/AT/AT_CellularDevice.cpp ++++ b/connectivity/cellular/source/framework/AT/AT_CellularDevice.cpp +@@ -50,6 +50,7 @@ AT_CellularDevice::AT_CellularDevice(FileHandle *fh, char *delim): + _context_list(0), + _default_timeout(DEFAULT_AT_TIMEOUT), + _modem_debug_on(false), ++ _cmux_status(false), + _property_array(NULL) + { + MBED_ASSERT(fh); +@@ -243,10 +244,10 @@ nsapi_error_t AT_CellularDevice::get_sim_state(SimState &state) + + nsapi_error_t AT_CellularDevice::enable_cmux() + { +-setup_at_handler(); +- ++ setup_at_handler(); + _at.lock(); + for (int retry = 1; retry <= 3; retry++) { ++ is_ready(); + _at.clear_error(); + _at.flush(); + _at.at_cmd_discard("E0", ""); +@@ -259,10 +260,9 @@ setup_at_handler(); + tr_debug("Wait 100ms to init modem"); + rtos::ThisThread::sleep_for(100ms); // let modem have time to get ready + } +- return _at.unlock_return_error(); ++ return _at.unlock_return_error(); + } + +- + bool AT_CellularDevice::is_cmux_enabled() + { + return _cmux_status; +@@ -272,6 +272,7 @@ void AT_CellularDevice::set_cmux_status_flag(bool cmux_status) + { + _cmux_status = cmux_status; + } ++ + nsapi_error_t AT_CellularDevice::set_pin(const char *sim_pin) + { + // if SIM is already in ready state then settings the PIN +-- +2.45.2 + diff --git a/patches/0253-GEMALTO-CINTERION-override-shutdown-function.patch b/patches/0253-GEMALTO-CINTERION-override-shutdown-function.patch new file mode 100644 index 000000000..e100a7b01 --- /dev/null +++ b/patches/0253-GEMALTO-CINTERION-override-shutdown-function.patch @@ -0,0 +1,42 @@ +From 13bc587f70e1c4f9f61650cfd7c8ebc538bdcf09 Mon Sep 17 00:00:00 2001 +From: pennam +Date: Wed, 13 Nov 2024 08:29:14 +0100 +Subject: [PATCH] GEMALTO CINTERION: override shutdown function + +--- + .../cellular/GEMALTO/CINTERION/GEMALTO_CINTERION.cpp | 6 ++++++ + .../drivers/cellular/GEMALTO/CINTERION/GEMALTO_CINTERION.h | 1 + + 2 files changed, 7 insertions(+) + +diff --git a/connectivity/drivers/cellular/GEMALTO/CINTERION/GEMALTO_CINTERION.cpp b/connectivity/drivers/cellular/GEMALTO/CINTERION/GEMALTO_CINTERION.cpp +index 1f82199106..c00c1880e4 100644 +--- a/connectivity/drivers/cellular/GEMALTO/CINTERION/GEMALTO_CINTERION.cpp ++++ b/connectivity/drivers/cellular/GEMALTO/CINTERION/GEMALTO_CINTERION.cpp +@@ -92,6 +92,12 @@ nsapi_error_t GEMALTO_CINTERION::init() + return NSAPI_ERROR_OK; + } + ++nsapi_error_t GEMALTO_CINTERION::shutdown() ++{ ++ CellularDevice::shutdown(); ++ return NSAPI_ERROR_OK; ++} ++ + GEMALTO_CINTERION::Module GEMALTO_CINTERION::get_module() + { + return _module; +diff --git a/connectivity/drivers/cellular/GEMALTO/CINTERION/GEMALTO_CINTERION.h b/connectivity/drivers/cellular/GEMALTO/CINTERION/GEMALTO_CINTERION.h +index 21d5888383..e77078cb49 100644 +--- a/connectivity/drivers/cellular/GEMALTO/CINTERION/GEMALTO_CINTERION.h ++++ b/connectivity/drivers/cellular/GEMALTO/CINTERION/GEMALTO_CINTERION.h +@@ -55,6 +55,7 @@ protected: // AT_CellularDevice + + protected: + virtual nsapi_error_t init(); ++ virtual nsapi_error_t shutdown(); + + private: + static Module _module; +-- +2.45.2 + diff --git a/patches/0254-GEMALTO-CINTERION-use-default-timeout-to-close-socke.patch b/patches/0254-GEMALTO-CINTERION-use-default-timeout-to-close-socke.patch new file mode 100644 index 000000000..86975735d --- /dev/null +++ b/patches/0254-GEMALTO-CINTERION-use-default-timeout-to-close-socke.patch @@ -0,0 +1,32 @@ +From 62867abe6811f785373cae9e9b5cfe41774b846b Mon Sep 17 00:00:00 2001 +From: pennam +Date: Wed, 13 Nov 2024 08:30:47 +0100 +Subject: [PATCH] GEMALTO CINTERION: use default timeout to close + sockets + +--- + .../GEMALTO/CINTERION/GEMALTO_CINTERION_CellularStack.cpp | 4 ---- + 1 file changed, 4 deletions(-) + +diff --git a/connectivity/drivers/cellular/GEMALTO/CINTERION/GEMALTO_CINTERION_CellularStack.cpp b/connectivity/drivers/cellular/GEMALTO/CINTERION/GEMALTO_CINTERION_CellularStack.cpp +index a96cb2b360..f96ae481f0 100644 +--- a/connectivity/drivers/cellular/GEMALTO/CINTERION/GEMALTO_CINTERION_CellularStack.cpp ++++ b/connectivity/drivers/cellular/GEMALTO/CINTERION/GEMALTO_CINTERION_CellularStack.cpp +@@ -252,14 +252,10 @@ nsapi_error_t GEMALTO_CINTERION_CellularStack::socket_close_impl(int sock_id) + { + tr_debug("Cinterion close %d", sock_id); + +- _at.set_at_timeout(FAILURE_TIMEOUT); +- + _at.at_cmd_discard("^SISC", "=", "%d", sock_id); + + _at.clear_error(); // clear SISS even though SISC fails + +- _at.restore_at_timeout(); +- + return _at.get_last_error(); + } + +-- +2.45.2 + diff --git a/patches/0255-GEMALTO-CINTERION-add-soft_power_off-and-soft_reset.patch b/patches/0255-GEMALTO-CINTERION-add-soft_power_off-and-soft_reset.patch new file mode 100644 index 000000000..82bd81c15 --- /dev/null +++ b/patches/0255-GEMALTO-CINTERION-add-soft_power_off-and-soft_reset.patch @@ -0,0 +1,102 @@ +From 7c789f289225ef631952f0ddb8ac46d2d1de9191 Mon Sep 17 00:00:00 2001 +From: pennam +Date: Thu, 14 Nov 2024 15:57:07 +0100 +Subject: [PATCH] GEMALTO CINTERION: add soft_power_off() and + soft_reset() + +--- + .../include/cellular/framework/API/CellularDevice.h | 11 +++++++++++ + .../include/cellular/framework/AT/AT_CellularDevice.h | 2 ++ + .../source/framework/AT/AT_CellularDevice.cpp | 5 +++++ + .../cellular/GEMALTO/CINTERION/GEMALTO_CINTERION.cpp | 10 ++++++++++ + .../cellular/GEMALTO/CINTERION/GEMALTO_CINTERION.h | 2 ++ + 5 files changed, 30 insertions(+) + +diff --git a/connectivity/cellular/include/cellular/framework/API/CellularDevice.h b/connectivity/cellular/include/cellular/framework/API/CellularDevice.h +index 0c8d1a2db2..69455e1567 100644 +--- a/connectivity/cellular/include/cellular/framework/API/CellularDevice.h ++++ b/connectivity/cellular/include/cellular/framework/API/CellularDevice.h +@@ -201,6 +201,17 @@ public: //Pure virtual functions + */ + virtual nsapi_error_t soft_power_off() = 0; + ++ /** Resets the modem via AT command ++ * ++ * @remark CellularStateMachine disconnect or destruct does not reset the modem, ++ * but you need to do that yourself. ++ * ++ * @pre You must call shutdown to prepare the modem for reset. ++ * ++ * @return NSAPI_ERROR_OK on success ++ */ ++ virtual nsapi_error_t soft_reset() = 0; ++ + /** Open the SIM card by setting the pin code for SIM. + * + * @param sim_pin PIN for the SIM card +diff --git a/connectivity/cellular/include/cellular/framework/AT/AT_CellularDevice.h b/connectivity/cellular/include/cellular/framework/AT/AT_CellularDevice.h +index fa011a0968..0006b6c391 100755 +--- a/connectivity/cellular/include/cellular/framework/AT/AT_CellularDevice.h ++++ b/connectivity/cellular/include/cellular/framework/AT/AT_CellularDevice.h +@@ -80,6 +80,8 @@ public: + + virtual nsapi_error_t soft_power_off(); + ++ virtual nsapi_error_t soft_reset(); ++ + virtual nsapi_error_t set_pin(const char *sim_pin); + + virtual nsapi_error_t get_sim_state(SimState &state); +diff --git a/connectivity/cellular/source/framework/AT/AT_CellularDevice.cpp b/connectivity/cellular/source/framework/AT/AT_CellularDevice.cpp +index 3eccc4a5c0..d7dae05aa2 100644 +--- a/connectivity/cellular/source/framework/AT/AT_CellularDevice.cpp ++++ b/connectivity/cellular/source/framework/AT/AT_CellularDevice.cpp +@@ -187,6 +187,11 @@ nsapi_error_t AT_CellularDevice::soft_power_off() + return NSAPI_ERROR_OK; + } + ++nsapi_error_t AT_CellularDevice::soft_reset() ++{ ++ return NSAPI_ERROR_OK; ++} ++ + ATHandler *AT_CellularDevice::get_at_handler() + { + return &_at; +diff --git a/connectivity/drivers/cellular/GEMALTO/CINTERION/GEMALTO_CINTERION.cpp b/connectivity/drivers/cellular/GEMALTO/CINTERION/GEMALTO_CINTERION.cpp +index c00c1880e4..40e74ab98f 100644 +--- a/connectivity/drivers/cellular/GEMALTO/CINTERION/GEMALTO_CINTERION.cpp ++++ b/connectivity/drivers/cellular/GEMALTO/CINTERION/GEMALTO_CINTERION.cpp +@@ -98,6 +98,16 @@ nsapi_error_t GEMALTO_CINTERION::shutdown() + return NSAPI_ERROR_OK; + } + ++nsapi_error_t GEMALTO_CINTERION::soft_power_off() ++{ ++ return _at.at_cmd_discard("^SMSO=", "fast"); ++} ++ ++nsapi_error_t GEMALTO_CINTERION::soft_reset() ++{ ++ return _at.at_cmd_discard("+CFUN", "=1,1"); ++} ++ + GEMALTO_CINTERION::Module GEMALTO_CINTERION::get_module() + { + return _module; +diff --git a/connectivity/drivers/cellular/GEMALTO/CINTERION/GEMALTO_CINTERION.h b/connectivity/drivers/cellular/GEMALTO/CINTERION/GEMALTO_CINTERION.h +index e77078cb49..edc980209e 100644 +--- a/connectivity/drivers/cellular/GEMALTO/CINTERION/GEMALTO_CINTERION.h ++++ b/connectivity/drivers/cellular/GEMALTO/CINTERION/GEMALTO_CINTERION.h +@@ -56,6 +56,8 @@ protected: // AT_CellularDevice + protected: + virtual nsapi_error_t init(); + virtual nsapi_error_t shutdown(); ++ virtual nsapi_error_t soft_power_off(); ++ virtual nsapi_error_t soft_reset(); + + private: + static Module _module; +-- +2.45.2 + diff --git a/patches/0256-GEMALTO-CINTERION-disable-runtime-model-detection.patch b/patches/0256-GEMALTO-CINTERION-disable-runtime-model-detection.patch new file mode 100644 index 000000000..886e626f3 --- /dev/null +++ b/patches/0256-GEMALTO-CINTERION-disable-runtime-model-detection.patch @@ -0,0 +1,71 @@ +From 1082631c2a418ce76d003cccf247141f90433736 Mon Sep 17 00:00:00 2001 +From: pennam +Date: Thu, 14 Nov 2024 15:57:44 +0100 +Subject: [PATCH] GEMALTO CINTERION: disable runtime model detection + + cellular_properties must be configured in ctor to properly configure all network urcs +--- + .../GEMALTO/CINTERION/GEMALTO_CINTERION.cpp | 39 ++++++------------- + 1 file changed, 11 insertions(+), 28 deletions(-) + +diff --git a/connectivity/drivers/cellular/GEMALTO/CINTERION/GEMALTO_CINTERION.cpp b/connectivity/drivers/cellular/GEMALTO/CINTERION/GEMALTO_CINTERION.cpp +index 40e74ab98f..3754ad50ec 100644 +--- a/connectivity/drivers/cellular/GEMALTO/CINTERION/GEMALTO_CINTERION.cpp ++++ b/connectivity/drivers/cellular/GEMALTO/CINTERION/GEMALTO_CINTERION.cpp +@@ -29,6 +29,17 @@ GEMALTO_CINTERION::Module GEMALTO_CINTERION::_module; + + GEMALTO_CINTERION::GEMALTO_CINTERION(FileHandle *fh) : AT_CellularDevice(fh) + { ++#if defined(MBED_CONF_GEMALTO_CINTERION_ELS61) ++ init_module_els61(); ++#elif defined(MBED_CONF_GEMALTO_CINTERION_BGS2) ++ init_module_bgs2(); ++#elif defined(MBED_CONF_GEMALTO_CINTERION_EMS31) ++ init_module_ems31(); ++#elif defined(MBED_CONF_GEMALTO_CINTERION_EHS5E) ++ init_module_ehs5e(); ++#else ++ init_module_tx62(); ++#endif + } + + AT_CellularContext *GEMALTO_CINTERION::create_context_impl(ATHandler &at, const char *apn, bool cp_req, bool nonip_req) +@@ -60,35 +71,7 @@ nsapi_error_t GEMALTO_CINTERION::init() + if (err != NSAPI_ERROR_OK) { + return err; + } +- +- CellularInformation *information = open_information(); +- if (!information) { +- return NSAPI_ERROR_NO_MEMORY; +- } +- char model[sizeof("EHS5-E") + 1]; // sizeof need to be long enough to hold just the model text +- nsapi_error_t ret = information->get_model(model, sizeof(model)); +- close_information(); +- if (ret != NSAPI_ERROR_OK) { +- tr_error("Cellular model not found!"); +- return NSAPI_ERROR_DEVICE_ERROR; +- } +- if (memcmp(model, "ELS61", sizeof("ELS61") - 1) == 0) { +- init_module_els61(); +- } else if (memcmp(model, "BGS2", sizeof("BGS2") - 1) == 0) { +- init_module_bgs2(); +- } else if (memcmp(model, "EMS31", sizeof("EMS31") - 1) == 0) { +- init_module_ems31(); +- } else if (memcmp(model, "EHS5-E", sizeof("EHS5-E") - 1) == 0) { +- init_module_ehs5e(); +- } else if (memcmp(model, "TX62", sizeof("TX62") - 1) == 0) { +- init_module_tx62(); +- } else { +- tr_error("Cinterion model unsupported %s", model); +- return NSAPI_ERROR_UNSUPPORTED; +- } +- tr_info("Cinterion model %s (%d)", model, _module); + set_at_urcs(); +- + return NSAPI_ERROR_OK; + } + +-- +2.45.2 + diff --git a/patches/0257-GEMALTO-CONTERION-add-ping.patch b/patches/0257-GEMALTO-CONTERION-add-ping.patch new file mode 100644 index 000000000..de6012bdc --- /dev/null +++ b/patches/0257-GEMALTO-CONTERION-add-ping.patch @@ -0,0 +1,53 @@ +From 09a4787109efd233aded2b960fcdfa10587eec9d Mon Sep 17 00:00:00 2001 +From: pennam +Date: Thu, 14 Nov 2024 15:59:37 +0100 +Subject: [PATCH] GEMALTO CONTERION: add ping + +--- + .../GEMALTO_CINTERION_CellularStack.cpp | 17 +++++++++++++++++ + .../CINTERION/GEMALTO_CINTERION_CellularStack.h | 1 + + 2 files changed, 18 insertions(+) + +diff --git a/connectivity/drivers/cellular/GEMALTO/CINTERION/GEMALTO_CINTERION_CellularStack.cpp b/connectivity/drivers/cellular/GEMALTO/CINTERION/GEMALTO_CINTERION_CellularStack.cpp +index f96ae481f0..938cdbfef2 100644 +--- a/connectivity/drivers/cellular/GEMALTO/CINTERION/GEMALTO_CINTERION_CellularStack.cpp ++++ b/connectivity/drivers/cellular/GEMALTO/CINTERION/GEMALTO_CINTERION_CellularStack.cpp +@@ -224,6 +224,23 @@ void GEMALTO_CINTERION_CellularStack::PSMDisable() { + } + } + ++int GEMALTO_CINTERION_CellularStack::ping(const char *host, int ttl) ++{ ++ MBED_ASSERT(host); ++ ++ _at.lock(); ++ _at.set_at_timeout(ttl + 1000); ++ _at.cmd_start_stop("^SISX", "=", "%s%d%s%d%d", "Ping", _cid, host, 1, ttl); ++ _at.resp_start("^SISX: \"Ping\","); ++ _at.skip_param(3); //pingInfoType, conProfileId, ip-address ++ int rTT = _at.read_int(); //roundTripTime ++ _at.resp_stop(); ++ _at.clear_error(); ++ _at.restore_at_timeout(); ++ _at.unlock(); ++ return rTT; ++} ++ + nsapi_error_t GEMALTO_CINTERION_CellularStack::socket_stack_init() + { + _at.lock(); +diff --git a/connectivity/drivers/cellular/GEMALTO/CINTERION/GEMALTO_CINTERION_CellularStack.h b/connectivity/drivers/cellular/GEMALTO/CINTERION/GEMALTO_CINTERION_CellularStack.h +index f89da8c314..159ea68aa9 100644 +--- a/connectivity/drivers/cellular/GEMALTO/CINTERION/GEMALTO_CINTERION_CellularStack.h ++++ b/connectivity/drivers/cellular/GEMALTO/CINTERION/GEMALTO_CINTERION_CellularStack.h +@@ -43,6 +43,7 @@ public: + void stopGNSS(); + void PSMEnable(); + void PSMDisable(); ++ int ping(const char *host, int ttl); + + protected: + +-- +2.45.2 + diff --git a/patches/0258-GEMALTO-CINTERION-fix-gethostbyname.patch b/patches/0258-GEMALTO-CINTERION-fix-gethostbyname.patch new file mode 100644 index 000000000..730a4c690 --- /dev/null +++ b/patches/0258-GEMALTO-CINTERION-fix-gethostbyname.patch @@ -0,0 +1,25 @@ +From 46b1511db274990eb52e89c31e3e26af01d48d38 Mon Sep 17 00:00:00 2001 +From: pennam +Date: Thu, 14 Nov 2024 16:00:17 +0100 +Subject: [PATCH] GEMALTO CINTERION: fix gethostbyname() + + Add missing _at.unlock() +--- + .../GEMALTO/CINTERION/GEMALTO_CINTERION_CellularStack.cpp | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/connectivity/drivers/cellular/GEMALTO/CINTERION/GEMALTO_CINTERION_CellularStack.cpp b/connectivity/drivers/cellular/GEMALTO/CINTERION/GEMALTO_CINTERION_CellularStack.cpp +index 938cdbfef2..8f7b44818a 100644 +--- a/connectivity/drivers/cellular/GEMALTO/CINTERION/GEMALTO_CINTERION_CellularStack.cpp ++++ b/connectivity/drivers/cellular/GEMALTO/CINTERION/GEMALTO_CINTERION_CellularStack.cpp +@@ -309,6 +309,7 @@ nsapi_error_t GEMALTO_CINTERION_CellularStack::gethostbyname(const char *host, S + } else { + //Null string received + tr_info("Read %d bytes. Null string", size); ++ _at.unlock(); + return NSAPI_ERROR_NO_ADDRESS; + } + } +-- +2.45.2 + diff --git a/patches/0259-CellularStateMachine-wait-and-retry-if-signal-qualit.patch b/patches/0259-CellularStateMachine-wait-and-retry-if-signal-qualit.patch new file mode 100644 index 000000000..ebe18ff8c --- /dev/null +++ b/patches/0259-CellularStateMachine-wait-and-retry-if-signal-qualit.patch @@ -0,0 +1,26 @@ +From fd40e55bb7b121a0485bec2159672673b6c9bbf4 Mon Sep 17 00:00:00 2001 +From: pennam +Date: Thu, 14 Nov 2024 16:03:10 +0100 +Subject: [PATCH] CellularStateMachine: wait and retry if signal + quality is unknown + +--- + .../cellular/source/framework/device/CellularStateMachine.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/connectivity/cellular/source/framework/device/CellularStateMachine.cpp b/connectivity/cellular/source/framework/device/CellularStateMachine.cpp +index 37416ca72e..a87c9e0d02 100644 +--- a/connectivity/cellular/source/framework/device/CellularStateMachine.cpp ++++ b/connectivity/cellular/source/framework/device/CellularStateMachine.cpp +@@ -458,7 +458,7 @@ void CellularStateMachine::state_signal_quality() + { + _cb_data.error = _network.get_signal_quality(_signal_quality.rssi, &_signal_quality.ber); + +- if (_cb_data.error != NSAPI_ERROR_OK) { ++ if ((_cb_data.error != NSAPI_ERROR_OK) || (_signal_quality.rssi == CellularNetwork::SignalQuality::SignalQualityUnknown)) { + retry_state_or_fail(); + } else { + _cb_data.data = &_signal_quality; +-- +2.45.2 + diff --git a/patches/0260-GEMALTO-CINTERION-fix-RECV-urc-while-reading-cornerc.patch b/patches/0260-GEMALTO-CINTERION-fix-RECV-urc-while-reading-cornerc.patch new file mode 100644 index 000000000..6a9a09835 --- /dev/null +++ b/patches/0260-GEMALTO-CINTERION-fix-RECV-urc-while-reading-cornerc.patch @@ -0,0 +1,26 @@ +From b1dabe5a8983493bab170e2d8b8f2a1ba40e4199 Mon Sep 17 00:00:00 2001 +From: pennam +Date: Fri, 15 Nov 2024 11:37:52 +0100 +Subject: [PATCH] GEMALTO CINTERION fix RECV urc while reading + cornercase + +--- + .../GEMALTO/CINTERION/GEMALTO_CINTERION_CellularStack.cpp | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/connectivity/drivers/cellular/GEMALTO/CINTERION/GEMALTO_CINTERION_CellularStack.cpp b/connectivity/drivers/cellular/GEMALTO/CINTERION/GEMALTO_CINTERION_CellularStack.cpp +index 8f7b44818a..d164f85eb2 100644 +--- a/connectivity/drivers/cellular/GEMALTO/CINTERION/GEMALTO_CINTERION_CellularStack.cpp ++++ b/connectivity/drivers/cellular/GEMALTO/CINTERION/GEMALTO_CINTERION_CellularStack.cpp +@@ -598,6 +598,8 @@ sisr_retry: + if (len == 0) { + tr_debug("Socket %d no data", socket->id); + _at.resp_stop(); ++ _at.process_oob(); ++ socket->pending_bytes = 0; + RESTORE_URCs_AND_RETURN(NSAPI_ERROR_WOULD_BLOCK); + } + if (len == -1) { +-- +2.45.2 + diff --git a/patches/0261-GEMALTO-CINTERION-add-1ms-sleep-in-socket-sendto.patch b/patches/0261-GEMALTO-CINTERION-add-1ms-sleep-in-socket-sendto.patch new file mode 100644 index 000000000..41f843488 --- /dev/null +++ b/patches/0261-GEMALTO-CINTERION-add-1ms-sleep-in-socket-sendto.patch @@ -0,0 +1,33 @@ +From ec7cc4e660b366364d8b11e4ee6480c41141ff04 Mon Sep 17 00:00:00 2001 +From: pennam +Date: Wed, 26 Mar 2025 15:08:40 +0100 +Subject: [PATCH] GEMALTO CINTERION: add 1ms sleep in socket sendto + +--- + .../GEMALTO/CINTERION/GEMALTO_CINTERION_CellularStack.cpp | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/connectivity/drivers/cellular/GEMALTO/CINTERION/GEMALTO_CINTERION_CellularStack.cpp b/connectivity/drivers/cellular/GEMALTO/CINTERION/GEMALTO_CINTERION_CellularStack.cpp +index d164f85eb2..898f81cf66 100644 +--- a/connectivity/drivers/cellular/GEMALTO/CINTERION/GEMALTO_CINTERION_CellularStack.cpp ++++ b/connectivity/drivers/cellular/GEMALTO/CINTERION/GEMALTO_CINTERION_CellularStack.cpp +@@ -19,6 +19,7 @@ + #include "GEMALTO_CINTERION_CellularStack.h" + #include "GEMALTO_CINTERION.h" + #include "CellularLog.h" ++#include "platform/mbed_thread.h" + #include "rtos.h" + + using namespace std::chrono_literals; +@@ -538,6 +539,8 @@ sisw_retry: + socket->tx_ready = false; + } + ++ thread_sleep_for(1); // wait for modem to process the data; ++ + return (_at.get_last_error() == NSAPI_ERROR_OK) ? accept_len : NSAPI_ERROR_DEVICE_ERROR; + } + +-- +2.47.2 + From 4f84fc56d4f16cd394d849406994668e29bb2b53 Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 14 Nov 2024 16:11:00 +0100 Subject: [PATCH 27/43] GSM: change restart flag default value to false --- libraries/GSM/src/GSM.cpp | 4 +++- libraries/GSM/src/GSM.h | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/libraries/GSM/src/GSM.cpp b/libraries/GSM/src/GSM.cpp index e13b0744e..792091512 100644 --- a/libraries/GSM/src/GSM.cpp +++ b/libraries/GSM/src/GSM.cpp @@ -59,7 +59,9 @@ int arduino::GSMClass::begin(const char* pin, const char* apn, const char* usern digitalWrite(MBED_CONF_GEMALTO_CINTERION_RST, LOW); /* Reset module if needed */ - if (restart || isCmuxEnable()) { + const bool emergencyReset = restart || isCmuxEnable(); + DEBUG_INFO("Emergency reset %s", emergencyReset ? "enabled" : "disabled"); + if (emergencyReset) { reset(); } diff --git a/libraries/GSM/src/GSM.h b/libraries/GSM/src/GSM.h index 647e12bf0..6dea69aed 100644 --- a/libraries/GSM/src/GSM.h +++ b/libraries/GSM/src/GSM.h @@ -86,7 +86,7 @@ class GSMClass : public MbedSocketClass { * * return: 0 in case of success, negative number in case of failure */ - int begin(const char* pin, const char* apn, const char* username, const char* password, RadioAccessTechnologyType rat = CATNB, uint32_t band = BAND_20, bool restart = true); + int begin(const char* pin, const char* apn, const char* username, const char* password, RadioAccessTechnologyType rat = CATNB, uint32_t band = BAND_20, bool restart = false); /* * Disconnect from the network From 71f946026020895915973a2c315fa981913d5aca Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 14 Nov 2024 16:11:33 +0100 Subject: [PATCH 28/43] GSM: add debug print about cmux status --- libraries/GSM/src/GSM.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/GSM/src/GSM.cpp b/libraries/GSM/src/GSM.cpp index 792091512..683c6d762 100644 --- a/libraries/GSM/src/GSM.cpp +++ b/libraries/GSM/src/GSM.cpp @@ -85,6 +85,7 @@ int arduino::GSMClass::begin(const char* pin, const char* apn, const char* usern _device = _context->get_device(); _device->modem_debug_on(_at_debug); + DEBUG_INFO("CMUX %s", _cmuxGSMenable ? "enabled" : "disabled"); _device->set_cmux_status_flag(_cmuxGSMenable); _device->set_retry_timeout_array(_retry_timeout, sizeof(_retry_timeout) / sizeof(_retry_timeout[0])); _device->set_timeout(_timeout); From f23d294d663026fe9512cb9d4616f3ec0fa7319e Mon Sep 17 00:00:00 2001 From: pennam Date: Thu, 14 Nov 2024 16:17:00 +0100 Subject: [PATCH 29/43] GSM: add ping --- libraries/GSM/src/GSM.cpp | 30 ++++++++++++++++++++++++++++++ libraries/GSM/src/GSM.h | 3 +++ 2 files changed, 33 insertions(+) diff --git a/libraries/GSM/src/GSM.cpp b/libraries/GSM/src/GSM.cpp index 683c6d762..22aa1a4f3 100644 --- a/libraries/GSM/src/GSM.cpp +++ b/libraries/GSM/src/GSM.cpp @@ -140,6 +140,36 @@ void arduino::GSMClass::end() { } } +int arduino::GSMClass::ping(const char* hostname, int ttl) { + + mbed::GEMALTO_CINTERION_CellularStack* stack = (mbed::GEMALTO_CINTERION_CellularStack*)_context->get_stack(); + if (!stack) { + return -1; + } + return stack->ping(hostname, ttl); +} + +int arduino::GSMClass::ping(const String &hostname, int ttl) +{ + return ping(hostname.c_str(), ttl); +} + +int arduino::GSMClass::ping(IPAddress ip, int ttl) +{ + String host; + host.reserve(15); + + host += ip[0]; + host += '.'; + host += ip[1]; + host += '.'; + host += ip[2]; + host += '.'; + host += ip[3]; + + return ping(host, ttl); +} + int arduino::GSMClass::disconnect() { if (!_context) { return 0; diff --git a/libraries/GSM/src/GSM.h b/libraries/GSM/src/GSM.h index 6dea69aed..aaea837ff 100644 --- a/libraries/GSM/src/GSM.h +++ b/libraries/GSM/src/GSM.h @@ -115,6 +115,9 @@ class GSMClass : public MbedSocketClass { void trace(Stream& stream); void setTraceLevel(int trace_level, bool timestamp = false, bool at_trace = false); #endif + int ping(const char* hostname, int ttl = 5000); + int ping(const String& hostname, int ttl = 5000); + int ping(IPAddress host, int ttl = 5000); bool isConnected(); friend class GSMClient; From 8f450c85ebb225a5c880a365291253ce228f606c Mon Sep 17 00:00:00 2001 From: pennam Date: Fri, 15 Nov 2024 12:40:54 +0100 Subject: [PATCH 30/43] GSM: add software reset and power off --- libraries/GSM/src/GSM.cpp | 16 ++++++++++++++-- libraries/GSM/src/GSM.h | 12 +++++++++++- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/libraries/GSM/src/GSM.cpp b/libraries/GSM/src/GSM.cpp index 22aa1a4f3..513b7d0dc 100644 --- a/libraries/GSM/src/GSM.cpp +++ b/libraries/GSM/src/GSM.cpp @@ -62,7 +62,7 @@ int arduino::GSMClass::begin(const char* pin, const char* apn, const char* usern const bool emergencyReset = restart || isCmuxEnable(); DEBUG_INFO("Emergency reset %s", emergencyReset ? "enabled" : "disabled"); if (emergencyReset) { - reset(); + hardwareReset(); } /* Create rising edge on pin ON */ @@ -140,6 +140,18 @@ void arduino::GSMClass::end() { } } +void arduino::GSMClass::reset() { + if(_device) { + _device->soft_reset(); + } +} + +void arduino::GSMClass::off() { + if(_device) { + _device->soft_power_off(); + } +} + int arduino::GSMClass::ping(const char* hostname, int ttl) { mbed::GEMALTO_CINTERION_CellularStack* stack = (mbed::GEMALTO_CINTERION_CellularStack*)_context->get_stack(); @@ -215,7 +227,7 @@ NetworkInterface* arduino::GSMClass::getNetwork() { return _context; } -void arduino::GSMClass::reset() { +void arduino::GSMClass::hardwareReset() { /* Reset logic is inverted */ pinMode(MBED_CONF_GEMALTO_CINTERION_RST, OUTPUT); digitalWrite(MBED_CONF_GEMALTO_CINTERION_RST, HIGH); diff --git a/libraries/GSM/src/GSM.h b/libraries/GSM/src/GSM.h index aaea837ff..9f19cd3e0 100644 --- a/libraries/GSM/src/GSM.h +++ b/libraries/GSM/src/GSM.h @@ -100,6 +100,16 @@ class GSMClass : public MbedSocketClass { */ void end(void); + /* + * Send AT+CFUN=1,1 command to trigger a software reset. To be called only after end(); + */ + void reset(); + + /* + * Send AT^SMSO="fast command to power off the modem. To be called only after end(); + */ + void off(); + /* * Change cellular state timeouts. Needs to be called before GSM.begin() */ @@ -157,7 +167,7 @@ class GSMClass : public MbedSocketClass { static const char * getRegistrationStateString(const mbed::CellularNetwork::RegistrationStatus state); void onStatusChange(nsapi_event_t ev, intptr_t in); - void reset(); + void hardwareReset(); void on(); }; From 2f127e7a8cce0da5bd2ed653e9e5767f36962fea Mon Sep 17 00:00:00 2001 From: pennam Date: Mon, 5 May 2025 09:02:17 +0200 Subject: [PATCH 31/43] libmbed: rebuild H7 and EDGE_CONTROL --- .../cellular/framework/API/CellularDevice.h | 11 +++++++++++ .../cellular/framework/AT/AT_CellularDevice.h | 2 ++ .../GEMALTO/CINTERION/GEMALTO_CINTERION.h | 3 +++ .../GEMALTO_CINTERION_CellularStack.h | 1 + variants/EDGE_CONTROL/defines.txt | 2 +- variants/EDGE_CONTROL/libs/libmbed.a | Bin 7151856 -> 7154162 bytes variants/PORTENTA_H7_M7/defines.txt | 2 +- variants/PORTENTA_H7_M7/libs/libmbed.a | Bin 7759120 -> 7761506 bytes 8 files changed, 19 insertions(+), 2 deletions(-) diff --git a/cores/arduino/mbed/connectivity/cellular/include/cellular/framework/API/CellularDevice.h b/cores/arduino/mbed/connectivity/cellular/include/cellular/framework/API/CellularDevice.h index 0c8d1a2db..69455e156 100644 --- a/cores/arduino/mbed/connectivity/cellular/include/cellular/framework/API/CellularDevice.h +++ b/cores/arduino/mbed/connectivity/cellular/include/cellular/framework/API/CellularDevice.h @@ -201,6 +201,17 @@ class CellularDevice { */ virtual nsapi_error_t soft_power_off() = 0; + /** Resets the modem via AT command + * + * @remark CellularStateMachine disconnect or destruct does not reset the modem, + * but you need to do that yourself. + * + * @pre You must call shutdown to prepare the modem for reset. + * + * @return NSAPI_ERROR_OK on success + */ + virtual nsapi_error_t soft_reset() = 0; + /** Open the SIM card by setting the pin code for SIM. * * @param sim_pin PIN for the SIM card diff --git a/cores/arduino/mbed/connectivity/cellular/include/cellular/framework/AT/AT_CellularDevice.h b/cores/arduino/mbed/connectivity/cellular/include/cellular/framework/AT/AT_CellularDevice.h index fa011a096..0006b6c39 100755 --- a/cores/arduino/mbed/connectivity/cellular/include/cellular/framework/AT/AT_CellularDevice.h +++ b/cores/arduino/mbed/connectivity/cellular/include/cellular/framework/AT/AT_CellularDevice.h @@ -80,6 +80,8 @@ class AT_CellularDevice : public CellularDevice { virtual nsapi_error_t soft_power_off(); + virtual nsapi_error_t soft_reset(); + virtual nsapi_error_t set_pin(const char *sim_pin); virtual nsapi_error_t get_sim_state(SimState &state); diff --git a/cores/arduino/mbed/connectivity/drivers/cellular/GEMALTO/CINTERION/GEMALTO_CINTERION.h b/cores/arduino/mbed/connectivity/drivers/cellular/GEMALTO/CINTERION/GEMALTO_CINTERION.h index 21d588838..edc980209 100644 --- a/cores/arduino/mbed/connectivity/drivers/cellular/GEMALTO/CINTERION/GEMALTO_CINTERION.h +++ b/cores/arduino/mbed/connectivity/drivers/cellular/GEMALTO/CINTERION/GEMALTO_CINTERION.h @@ -55,6 +55,9 @@ class GEMALTO_CINTERION : public AT_CellularDevice { protected: virtual nsapi_error_t init(); + virtual nsapi_error_t shutdown(); + virtual nsapi_error_t soft_power_off(); + virtual nsapi_error_t soft_reset(); private: static Module _module; diff --git a/cores/arduino/mbed/connectivity/drivers/cellular/GEMALTO/CINTERION/GEMALTO_CINTERION_CellularStack.h b/cores/arduino/mbed/connectivity/drivers/cellular/GEMALTO/CINTERION/GEMALTO_CINTERION_CellularStack.h index f89da8c31..159ea68aa 100644 --- a/cores/arduino/mbed/connectivity/drivers/cellular/GEMALTO/CINTERION/GEMALTO_CINTERION_CellularStack.h +++ b/cores/arduino/mbed/connectivity/drivers/cellular/GEMALTO/CINTERION/GEMALTO_CINTERION_CellularStack.h @@ -43,6 +43,7 @@ class GEMALTO_CINTERION_CellularStack : public AT_CellularStack { void stopGNSS(); void PSMEnable(); void PSMDisable(); + int ping(const char *host, int ttl); protected: diff --git a/variants/EDGE_CONTROL/defines.txt b/variants/EDGE_CONTROL/defines.txt index 4fd396229..ac0303327 100644 --- a/variants/EDGE_CONTROL/defines.txt +++ b/variants/EDGE_CONTROL/defines.txt @@ -38,7 +38,7 @@ -DFEATURE_STORAGE=1 -D__FPU_PRESENT=1 -D__MBED__=1 --DMBED_BUILD_TIMESTAMP=1738678638.4581091 +-DMBED_BUILD_TIMESTAMP=1746428391.1444259 -D__MBED_CMSIS_RTOS_CM -DMBED_MPU_CUSTOM -DMBED_TICKLESS diff --git a/variants/EDGE_CONTROL/libs/libmbed.a b/variants/EDGE_CONTROL/libs/libmbed.a index d42e1137e8bf013fadd4935fc7cd99bfb805ba97..5a06e543650f67ed49da4cb7dae6346314c6680e 100644 GIT binary patch delta 106087 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 Ax&QzG delta 105943 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≤6>iJ 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 H(d~Z$4W(>- From ca1cd953f55d541d1310b0810050d54e8087391d Mon Sep 17 00:00:00 2001 From: pennam Date: Mon, 5 May 2025 16:12:51 +0200 Subject: [PATCH 32/43] QSPIFormat: use BlockDevice::get_default_instance() --- .../examples/QSPIFormat/QSPIFormat.ino | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/libraries/STM32H747_System/examples/QSPIFormat/QSPIFormat.ino b/libraries/STM32H747_System/examples/QSPIFormat/QSPIFormat.ino index 8d2b537dc..d788eb046 100644 --- a/libraries/STM32H747_System/examples/QSPIFormat/QSPIFormat.ino +++ b/libraries/STM32H747_System/examples/QSPIFormat/QSPIFormat.ino @@ -1,4 +1,4 @@ -#include "QSPIFBlockDevice.h" +#include "BlockDevice.h" #include "MBRBlockDevice.h" #include "LittleFileSystem.h" #include "FATFileSystem.h" @@ -8,10 +8,10 @@ #endif -QSPIFBlockDevice root(QSPI_SO0, QSPI_SO1, QSPI_SO2, QSPI_SO3, QSPI_SCK, QSPI_CS, QSPIF_POLARITY_MODE_1, 40000000); -mbed::MBRBlockDevice wifi_data(&root, 1); -mbed::MBRBlockDevice ota_data(&root, 2); -mbed::MBRBlockDevice user_data(&root, 3); +mbed::BlockDevice* root = mbed::BlockDevice::get_default_instance(); +mbed::MBRBlockDevice wifi_data(root, 1); +mbed::MBRBlockDevice ota_data(root, 2); +mbed::MBRBlockDevice user_data(root, 3); mbed::FATFileSystem wifi_data_fs("wlan"); mbed::FATFileSystem ota_data_fs("fs"); mbed::FileSystem * user_data_fs; @@ -60,14 +60,14 @@ void setup() { Serial.println("Do you want to proceed? Y/[n]"); if (true == waitResponse()) { - mbed::MBRBlockDevice::partition(&root, 1, 0x0B, 0, 1024 * 1024); + mbed::MBRBlockDevice::partition(root, 1, 0x0B, 0, 1024 * 1024); if(default_scheme) { - mbed::MBRBlockDevice::partition(&root, 3, 0x0B, 14 * 1024 * 1024, 14 * 1024 * 1024); - mbed::MBRBlockDevice::partition(&root, 2, 0x0B, 1024 * 1024, 14 * 1024 * 1024); + mbed::MBRBlockDevice::partition(root, 3, 0x0B, 14 * 1024 * 1024, 14 * 1024 * 1024); + mbed::MBRBlockDevice::partition(root, 2, 0x0B, 1024 * 1024, 14 * 1024 * 1024); // use space from 15.5MB to 16 MB for another fw, memory mapped } else { - mbed::MBRBlockDevice::partition(&root, 2, 0x0B, 1024 * 1024, 6 * 1024 * 1024); - mbed::MBRBlockDevice::partition(&root, 3, 0x0B, 6 * 1024 * 1024, 14 * 1024 * 1024); + mbed::MBRBlockDevice::partition(root, 2, 0x0B, 1024 * 1024, 6 * 1024 * 1024); + mbed::MBRBlockDevice::partition(root, 3, 0x0B, 6 * 1024 * 1024, 14 * 1024 * 1024); // use space from 15.5MB to 16 MB for another fw, memory mapped } From b9f1b32b9f6b92c8ed46d22b96c8322b77e0ec32 Mon Sep 17 00:00:00 2001 From: pennam Date: Mon, 5 May 2025 16:14:38 +0200 Subject: [PATCH 33/43] QSPIFormat: use mbed namespace --- .../examples/QSPIFormat/QSPIFormat.ino | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/libraries/STM32H747_System/examples/QSPIFormat/QSPIFormat.ino b/libraries/STM32H747_System/examples/QSPIFormat/QSPIFormat.ino index d788eb046..323a4af75 100644 --- a/libraries/STM32H747_System/examples/QSPIFormat/QSPIFormat.ino +++ b/libraries/STM32H747_System/examples/QSPIFormat/QSPIFormat.ino @@ -7,14 +7,15 @@ #error Format QSPI flash by uploading the sketch to the M7 core instead of the M4 core. #endif +using namespace mbed; -mbed::BlockDevice* root = mbed::BlockDevice::get_default_instance(); -mbed::MBRBlockDevice wifi_data(root, 1); -mbed::MBRBlockDevice ota_data(root, 2); -mbed::MBRBlockDevice user_data(root, 3); -mbed::FATFileSystem wifi_data_fs("wlan"); -mbed::FATFileSystem ota_data_fs("fs"); -mbed::FileSystem * user_data_fs; +BlockDevice* root = BlockDevice::get_default_instance(); +MBRBlockDevice wifi_data(root, 1); +MBRBlockDevice ota_data(root, 2); +MBRBlockDevice user_data(root, 3); +FATFileSystem wifi_data_fs("wlan"); +FATFileSystem ota_data_fs("fs"); +FileSystem * user_data_fs; bool waitResponse() { bool confirmation = false; @@ -60,14 +61,14 @@ void setup() { Serial.println("Do you want to proceed? Y/[n]"); if (true == waitResponse()) { - mbed::MBRBlockDevice::partition(root, 1, 0x0B, 0, 1024 * 1024); + MBRBlockDevice::partition(root, 1, 0x0B, 0, 1024 * 1024); if(default_scheme) { - mbed::MBRBlockDevice::partition(root, 3, 0x0B, 14 * 1024 * 1024, 14 * 1024 * 1024); + MBRBlockDevice::partition(root, 3, 0x0B, 14 * 1024 * 1024, 14 * 1024 * 1024); mbed::MBRBlockDevice::partition(root, 2, 0x0B, 1024 * 1024, 14 * 1024 * 1024); // use space from 15.5MB to 16 MB for another fw, memory mapped } else { - mbed::MBRBlockDevice::partition(root, 2, 0x0B, 1024 * 1024, 6 * 1024 * 1024); - mbed::MBRBlockDevice::partition(root, 3, 0x0B, 6 * 1024 * 1024, 14 * 1024 * 1024); + MBRBlockDevice::partition(root, 2, 0x0B, 1024 * 1024, 6 * 1024 * 1024); + MBRBlockDevice::partition(root, 3, 0x0B, 6 * 1024 * 1024, 14 * 1024 * 1024); // use space from 15.5MB to 16 MB for another fw, memory mapped } From 70aa36985a0f423a879281eda2e04e8d0310bb27 Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Mon, 23 Sep 2024 15:43:28 +0200 Subject: [PATCH 34/43] added an additional parition for provisioning in QSPIFormat sketch --- libraries/STM32H747_System/examples/QSPIFormat/QSPIFormat.ino | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libraries/STM32H747_System/examples/QSPIFormat/QSPIFormat.ino b/libraries/STM32H747_System/examples/QSPIFormat/QSPIFormat.ino index 323a4af75..0116521f6 100644 --- a/libraries/STM32H747_System/examples/QSPIFormat/QSPIFormat.ino +++ b/libraries/STM32H747_System/examples/QSPIFormat/QSPIFormat.ino @@ -12,7 +12,8 @@ using namespace mbed; BlockDevice* root = BlockDevice::get_default_instance(); MBRBlockDevice wifi_data(root, 1); MBRBlockDevice ota_data(root, 2); -MBRBlockDevice user_data(root, 3); +MBRBlockDevice kvstore_data(root, 3); +MBRBlockDevice user_data(root, 4); FATFileSystem wifi_data_fs("wlan"); FATFileSystem ota_data_fs("fs"); FileSystem * user_data_fs; From d6fecc0bb5751e3ee5ac30efef5466392c754ff4 Mon Sep 17 00:00:00 2001 From: pennam Date: Mon, 5 May 2025 16:30:11 +0200 Subject: [PATCH 35/43] QSPIFormat: remove partition scheme selection Make partition scheme 2 the default one. Always create 4 partitions. --- .../examples/QSPIFormat/QSPIFormat.ino | 58 +++++++------------ 1 file changed, 22 insertions(+), 36 deletions(-) diff --git a/libraries/STM32H747_System/examples/QSPIFormat/QSPIFormat.ino b/libraries/STM32H747_System/examples/QSPIFormat/QSPIFormat.ino index 0116521f6..c2112a381 100644 --- a/libraries/STM32H747_System/examples/QSPIFormat/QSPIFormat.ino +++ b/libraries/STM32H747_System/examples/QSPIFormat/QSPIFormat.ino @@ -46,32 +46,20 @@ void setup() { Serial.begin(115200); while (!Serial); - Serial.println("Available partition schemes:"); - Serial.println("\nPartition scheme 1"); - Serial.println("Partition 1: WiFi firmware and certificates 1MB"); - Serial.println("Partition 2: OTA and user data 13MB"); - Serial.println("\nPartition scheme 2"); + Serial.println("\nWARNING! Running the sketch all the content of the QSPI flash will be erased."); + Serial.println("The following partitions will be created:"); Serial.println("Partition 1: WiFi firmware and certificates 1MB"); Serial.println("Partition 2: OTA 5MB"); - Serial.println("Partition 3: User data 8MB"), - Serial.println("\nDo you want to use partition scheme 1? Y/[n]"); - Serial.println("If No, partition scheme 2 will be used."); - bool default_scheme = waitResponse(); - - Serial.println("\nWARNING! Running the sketch all the content of the QSPI flash will be erased."); + Serial.println("Partition 3: Provisioning KVStore 1MB"); + Serial.println("Partition 4: User data / OPTA PLC runtime 7MB"), Serial.println("Do you want to proceed? Y/[n]"); if (true == waitResponse()) { - MBRBlockDevice::partition(root, 1, 0x0B, 0, 1024 * 1024); - if(default_scheme) { - MBRBlockDevice::partition(root, 3, 0x0B, 14 * 1024 * 1024, 14 * 1024 * 1024); - mbed::MBRBlockDevice::partition(root, 2, 0x0B, 1024 * 1024, 14 * 1024 * 1024); - // use space from 15.5MB to 16 MB for another fw, memory mapped - } else { - MBRBlockDevice::partition(root, 2, 0x0B, 1024 * 1024, 6 * 1024 * 1024); - MBRBlockDevice::partition(root, 3, 0x0B, 6 * 1024 * 1024, 14 * 1024 * 1024); - // use space from 15.5MB to 16 MB for another fw, memory mapped - } + MBRBlockDevice::partition(root, 1, 0x0B, 0, 1 * 1024 * 1024); + MBRBlockDevice::partition(root, 2, 0x0B, 1 * 1024 * 1024, 6 * 1024 * 1024); + MBRBlockDevice::partition(root, 3, 0x0B, 6 * 1024 * 1024, 7 * 1024 * 1024); + MBRBlockDevice::partition(root, 4, 0x0B, 7 * 1024 * 1024, 14 * 1024 * 1024); + // use space from 15.5MB to 16 MB for another fw, memory mapped int err = wifi_data_fs.reformat(&wifi_data); if (err) { @@ -85,23 +73,21 @@ void setup() { return; } - if(!default_scheme) { - Serial.println("\nDo you want to use LittleFS to format user data partition? Y/[n]"); - Serial.println("If No, FatFS will be used to format user partition."); + Serial.println("\nDo you want to use LittleFS to format user data partition? Y/[n]"); + Serial.println("If No, FatFS will be used to format user partition."); - if (true == waitResponse()) { - Serial.println("Formatting user partition with LittleFS."); - user_data_fs = new mbed::LittleFileSystem("user"); - } else { - Serial.println("Formatting user partition with FatFS."); - user_data_fs = new mbed::FATFileSystem("user"); - } + if (true == waitResponse()) { + Serial.println("Formatting user partition with LittleFS."); + user_data_fs = new mbed::LittleFileSystem("user"); + } else { + Serial.println("Formatting user partition with FatFS."); + user_data_fs = new mbed::FATFileSystem("user"); + } - err = user_data_fs->reformat(&user_data); - if (err) { - Serial.println("Error formatting user partition"); - return; - } + err = user_data_fs->reformat(&user_data); + if (err) { + Serial.println("Error formatting user partition"); + return; } Serial.println("\nQSPI Flash formatted!"); } From 35c5c0e07c83c19e7f95ff73966e57cac4fdd9f6 Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Wed, 12 Mar 2025 11:18:14 +0100 Subject: [PATCH 36/43] removed trailing spaces --- libraries/STM32H747_System/examples/QSPIFormat/QSPIFormat.ino | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/STM32H747_System/examples/QSPIFormat/QSPIFormat.ino b/libraries/STM32H747_System/examples/QSPIFormat/QSPIFormat.ino index c2112a381..19c549538 100644 --- a/libraries/STM32H747_System/examples/QSPIFormat/QSPIFormat.ino +++ b/libraries/STM32H747_System/examples/QSPIFormat/QSPIFormat.ino @@ -3,7 +3,7 @@ #include "LittleFileSystem.h" #include "FATFileSystem.h" -#ifndef CORE_CM7 +#ifndef CORE_CM7 #error Format QSPI flash by uploading the sketch to the M7 core instead of the M4 core. #endif @@ -66,7 +66,7 @@ void setup() { Serial.println("Error formatting WiFi partition"); return; } - + err = ota_data_fs.reformat(&ota_data); if (err) { Serial.println("Error formatting OTA partition"); From 12ed4820f978f098c37e7233f3a7bfccf044332b Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Mon, 23 Sep 2024 14:03:08 +0200 Subject: [PATCH 37/43] erasing MBR table before creating a new partitioning scheme --- .../STM32H747_System/examples/QSPIFormat/QSPIFormat.ino | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libraries/STM32H747_System/examples/QSPIFormat/QSPIFormat.ino b/libraries/STM32H747_System/examples/QSPIFormat/QSPIFormat.ino index 19c549538..6b7470eb1 100644 --- a/libraries/STM32H747_System/examples/QSPIFormat/QSPIFormat.ino +++ b/libraries/STM32H747_System/examples/QSPIFormat/QSPIFormat.ino @@ -55,6 +55,12 @@ void setup() { Serial.println("Do you want to proceed? Y/[n]"); if (true == waitResponse()) { + if (root->init() != BD_ERROR_OK) { + Serial.println(F("Error: QSPI init failure.")); + return; + } + + root->erase(0x0, root->get_erase_size()); MBRBlockDevice::partition(root, 1, 0x0B, 0, 1 * 1024 * 1024); MBRBlockDevice::partition(root, 2, 0x0B, 1 * 1024 * 1024, 6 * 1024 * 1024); MBRBlockDevice::partition(root, 3, 0x0B, 6 * 1024 * 1024, 7 * 1024 * 1024); From 236ea5cc713acdb2f8cd110478c9ccbc84e0b601 Mon Sep 17 00:00:00 2001 From: Andrea Gilardoni Date: Wed, 12 Mar 2025 11:17:50 +0100 Subject: [PATCH 38/43] QSPIFormat: Added confirmation request before reformatting fs --- .../examples/QSPIFormat/QSPIFormat.ino | 35 +++++++++++++++---- 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/libraries/STM32H747_System/examples/QSPIFormat/QSPIFormat.ino b/libraries/STM32H747_System/examples/QSPIFormat/QSPIFormat.ino index 6b7470eb1..cf929dcd5 100644 --- a/libraries/STM32H747_System/examples/QSPIFormat/QSPIFormat.ino +++ b/libraries/STM32H747_System/examples/QSPIFormat/QSPIFormat.ino @@ -67,14 +67,29 @@ void setup() { MBRBlockDevice::partition(root, 4, 0x0B, 7 * 1024 * 1024, 14 * 1024 * 1024); // use space from 15.5MB to 16 MB for another fw, memory mapped - int err = wifi_data_fs.reformat(&wifi_data); - if (err) { + bool reformat = true; + + if(!wifi_data_fs.mount(&wifi_data)) { + Serial.println("\nPartition 1 already contains a filesystem, do you want to reformat it? Y/[n]"); + wifi_data_fs.unmount(); + + reformat = waitResponse(); + } + + if (reformat && wifi_data_fs.reformat(&wifi_data)) { Serial.println("Error formatting WiFi partition"); return; } - err = ota_data_fs.reformat(&ota_data); - if (err) { + reformat = true; + if(!ota_data_fs.mount(&ota_data)) { + Serial.println("\nPartition 2 already contains a filesystem, do you want to reformat it? Y/[n]"); + ota_data_fs.unmount(); + + reformat = waitResponse(); + } + + if (reformat && ota_data_fs.reformat(&ota_data)) { Serial.println("Error formatting OTA partition"); return; } @@ -90,11 +105,19 @@ void setup() { user_data_fs = new mbed::FATFileSystem("user"); } - err = user_data_fs->reformat(&user_data); - if (err) { + reformat = true; + if(!user_data_fs->mount(&user_data)) { + Serial.println("\nPartition 4 already contains a filesystem, do you want to reformat it? Y/[n]"); + user_data_fs->unmount(); + + reformat = waitResponse(); + } + + if (reformat && user_data_fs->reformat(&user_data)) { Serial.println("Error formatting user partition"); return; } + Serial.println("\nQSPI Flash formatted!"); } From edeaf3d1cedbd5fca3a11c47b0e8714506421738 Mon Sep 17 00:00:00 2001 From: pennam Date: Mon, 5 May 2025 17:36:39 +0200 Subject: [PATCH 39/43] QSPIFormat: add option to restore WiFi firmware and certificates --- .../examples/QSPIFormat/QSPIFormat.ino | 70 ++++++++++++++++++- .../examples/QSPIFormat/certificates.h | 1 + 2 files changed, 70 insertions(+), 1 deletion(-) create mode 120000 libraries/STM32H747_System/examples/QSPIFormat/certificates.h diff --git a/libraries/STM32H747_System/examples/QSPIFormat/QSPIFormat.ino b/libraries/STM32H747_System/examples/QSPIFormat/QSPIFormat.ino index cf929dcd5..0a8eb53fe 100644 --- a/libraries/STM32H747_System/examples/QSPIFormat/QSPIFormat.ino +++ b/libraries/STM32H747_System/examples/QSPIFormat/QSPIFormat.ino @@ -2,6 +2,8 @@ #include "MBRBlockDevice.h" #include "LittleFileSystem.h" #include "FATFileSystem.h" +#include "wiced_resource.h" +#include "certificates.h" #ifndef CORE_CM7 #error Format QSPI flash by uploading the sketch to the M7 core instead of the M4 core. @@ -41,6 +43,20 @@ bool waitResponse() { } } +void printProgress(uint32_t offset, uint32_t size, uint32_t threshold, bool reset) { + static int percent_done = 0; + if (reset == true) { + percent_done = 0; + Serial.println("Flashed " + String(percent_done) + "%"); + } else { + uint32_t percent_done_new = offset * 100 / size; + if (percent_done_new >= percent_done + threshold) { + percent_done = percent_done_new; + Serial.println("Flashed " + String(percent_done) + "%"); + } + } +} + void setup() { Serial.begin(115200); @@ -68,7 +84,6 @@ void setup() { // use space from 15.5MB to 16 MB for another fw, memory mapped bool reformat = true; - if(!wifi_data_fs.mount(&wifi_data)) { Serial.println("\nPartition 1 already contains a filesystem, do you want to reformat it? Y/[n]"); wifi_data_fs.unmount(); @@ -81,6 +96,16 @@ void setup() { return; } + bool restore = true; + if (reformat) { + Serial.println("\nDo you want to restore the WiFi firmware and certificates? Y/[n]"); + restore = waitResponse(); + } + + if (reformat && restore) { + flashWiFiFirmwareAndCertificates(); + } + reformat = true; if(!ota_data_fs.mount(&ota_data)) { Serial.println("\nPartition 2 already contains a filesystem, do you want to reformat it? Y/[n]"); @@ -124,6 +149,49 @@ void setup() { Serial.println("It's now safe to reboot or disconnect your board."); } +void flashWiFiFirmwareAndCertificates() { + extern const unsigned char wifi_firmware_image_data[]; + extern const resource_hnd_t wifi_firmware_image; + FILE* fp = fopen("/wlan/4343WA1.BIN", "wb"); + const int file_size = 421098; + int chunck_size = 1024; + int byte_count = 0; + + Serial.println("Flashing WiFi firmware"); + printProgress(byte_count, file_size, 10, true); + while (byte_count < file_size) { + if(byte_count + chunck_size > file_size) + chunck_size = file_size - byte_count; + int ret = fwrite(&wifi_firmware_image_data[byte_count], chunck_size, 1, fp); + if (ret != 1) { + Serial.println("Error writing firmware data"); + break; + } + byte_count += chunck_size; + printProgress(byte_count, file_size, 10, false); + } + fclose(fp); + + fp = fopen("/wlan/cacert.pem", "wb"); + + Serial.println("Flashing certificates"); + chunck_size = 128; + byte_count = 0; + printProgress(byte_count, cacert_pem_len, 10, true); + while (byte_count < cacert_pem_len) { + if(byte_count + chunck_size > cacert_pem_len) + chunck_size = cacert_pem_len - byte_count; + int ret = fwrite(&cacert_pem[byte_count], chunck_size, 1 ,fp); + if (ret != 1) { + Serial.println("Error writing certificates"); + break; + } + byte_count += chunck_size; + printProgress(byte_count, cacert_pem_len, 10, false); + } + fclose(fp); +} + void loop() { } diff --git a/libraries/STM32H747_System/examples/QSPIFormat/certificates.h b/libraries/STM32H747_System/examples/QSPIFormat/certificates.h new file mode 120000 index 000000000..7b4170776 --- /dev/null +++ b/libraries/STM32H747_System/examples/QSPIFormat/certificates.h @@ -0,0 +1 @@ +../WiFiFirmwareUpdater/certificates.h \ No newline at end of file From 5ccc517f6f5f425f5b24b6c5fde23e71cf9c3b88 Mon Sep 17 00:00:00 2001 From: pennam Date: Mon, 5 May 2025 18:08:44 +0200 Subject: [PATCH 40/43] fix transport_script path expansion --- boards.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/boards.txt b/boards.txt index 79a40e70e..048ca551d 100644 --- a/boards.txt +++ b/boards.txt @@ -444,7 +444,7 @@ nicla_sense.upload.native_usb=true nicla_sense.upload.maximum_size=527616 nicla_sense.upload.maximum_data_size=64288 nicla_sense.programmer.protocol=cmsis-dap -nicla_sense.programmer.transport_script={runtime.platform.path}/debugger/select_swd.cfg +nicla_sense.programmer.transport_script="{runtime.platform.path}/debugger/select_swd.cfg" nicla_sense.bootloader.tool=openocd nicla_sense.bootloader.tool.default=openocd @@ -499,7 +499,7 @@ nicla_voice.upload.native_usb=true nicla_voice.upload.maximum_size=527616 nicla_voice.upload.maximum_data_size=64288 nicla_voice.programmer.protocol=cmsis-dap -nicla_voice.programmer.transport_script={runtime.platform.path}/debugger/select_swd.cfg +nicla_voice.programmer.transport_script="{runtime.platform.path}/debugger/select_swd.cfg" nicla_voice.bootloader.tool=openocd nicla_voice.bootloader.tool.default=openocd From 45c9eae3d7f52f5cba4985a14730f3f6b10904d0 Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 6 May 2025 11:21:38 +0200 Subject: [PATCH 41/43] QSPIFormat: fix warnings --- .../examples/QSPIFormat/QSPIFormat.ino | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/libraries/STM32H747_System/examples/QSPIFormat/QSPIFormat.ino b/libraries/STM32H747_System/examples/QSPIFormat/QSPIFormat.ino index 0a8eb53fe..fa55824ce 100644 --- a/libraries/STM32H747_System/examples/QSPIFormat/QSPIFormat.ino +++ b/libraries/STM32H747_System/examples/QSPIFormat/QSPIFormat.ino @@ -22,6 +22,7 @@ FileSystem * user_data_fs; bool waitResponse() { bool confirmation = false; + bool proceed = false; while (confirmation == false) { if (Serial.available()) { char choice = Serial.read(); @@ -29,18 +30,19 @@ bool waitResponse() { case 'y': case 'Y': confirmation = true; - return true; + proceed = true; break; case 'n': case 'N': confirmation = true; - return false; + proceed = false; break; default: continue; } } } + return proceed; } void printProgress(uint32_t offset, uint32_t size, uint32_t threshold, bool reset) { @@ -151,11 +153,10 @@ void setup() { void flashWiFiFirmwareAndCertificates() { extern const unsigned char wifi_firmware_image_data[]; - extern const resource_hnd_t wifi_firmware_image; FILE* fp = fopen("/wlan/4343WA1.BIN", "wb"); - const int file_size = 421098; - int chunck_size = 1024; - int byte_count = 0; + const uint32_t file_size = 421098; + uint32_t chunck_size = 1024; + uint32_t byte_count = 0; Serial.println("Flashing WiFi firmware"); printProgress(byte_count, file_size, 10, true); From 752c1e964d678ec7dd2e3a59f846e40c6e32a0a3 Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 6 May 2025 11:22:16 +0200 Subject: [PATCH 42/43] QSPIFlash: add note about LittleFS and OPTA PLC runtime --- libraries/STM32H747_System/examples/QSPIFormat/QSPIFormat.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/STM32H747_System/examples/QSPIFormat/QSPIFormat.ino b/libraries/STM32H747_System/examples/QSPIFormat/QSPIFormat.ino index fa55824ce..1d4a90834 100644 --- a/libraries/STM32H747_System/examples/QSPIFormat/QSPIFormat.ino +++ b/libraries/STM32H747_System/examples/QSPIFormat/QSPIFormat.ino @@ -123,7 +123,7 @@ void setup() { Serial.println("\nDo you want to use LittleFS to format user data partition? Y/[n]"); Serial.println("If No, FatFS will be used to format user partition."); - + Serial.println("Note: LittleFS is not supported by the OPTA PLC runtime."); if (true == waitResponse()) { Serial.println("Formatting user partition with LittleFS."); user_data_fs = new mbed::LittleFileSystem("user"); From a831fd2485bfbeb75b55f3b38d9f510a17c4174e Mon Sep 17 00:00:00 2001 From: pennam Date: Tue, 6 May 2025 11:22:47 +0200 Subject: [PATCH 43/43] QSPIFormat: add option to perform a full erase --- .../STM32H747_System/examples/QSPIFormat/QSPIFormat.ino | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/libraries/STM32H747_System/examples/QSPIFormat/QSPIFormat.ino b/libraries/STM32H747_System/examples/QSPIFormat/QSPIFormat.ino index 1d4a90834..b3ecbf222 100644 --- a/libraries/STM32H747_System/examples/QSPIFormat/QSPIFormat.ino +++ b/libraries/STM32H747_System/examples/QSPIFormat/QSPIFormat.ino @@ -78,7 +78,14 @@ void setup() { return; } - root->erase(0x0, root->get_erase_size()); + Serial.println("Do you want to perform a full erase of the QSPI flash before proceeding? Y/[n]"); + if (true == waitResponse()) { + root->erase(0x0, root->size()); + } else { + // Erase only the first sector containing the MBR + root->erase(0x0, root->get_erase_size()); + } + MBRBlockDevice::partition(root, 1, 0x0B, 0, 1 * 1024 * 1024); MBRBlockDevice::partition(root, 2, 0x0B, 1 * 1024 * 1024, 6 * 1024 * 1024); MBRBlockDevice::partition(root, 3, 0x0B, 6 * 1024 * 1024, 7 * 1024 * 1024);