diff --git a/connectivity/cellular/include/cellular/framework/API/CellularDevice.h b/connectivity/cellular/include/cellular/framework/API/CellularDevice.h index 0c8d1a2db2c..69455e1567c 100644 --- a/connectivity/cellular/include/cellular/framework/API/CellularDevice.h +++ b/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/connectivity/cellular/include/cellular/framework/AT/AT_CellularDevice.h b/connectivity/cellular/include/cellular/framework/AT/AT_CellularDevice.h index fa011a09681..0006b6c3911 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 @@ 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/connectivity/cellular/source/framework/AT/AT_CellularDevice.cpp b/connectivity/cellular/source/framework/AT/AT_CellularDevice.cpp index 08229ba49ba..d7dae05aa23 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); @@ -186,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; @@ -243,10 +249,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 +265,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 +277,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 diff --git a/connectivity/cellular/source/framework/device/CellularStateMachine.cpp b/connectivity/cellular/source/framework/device/CellularStateMachine.cpp index 37416ca72ea..a87c9e0d02a 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; diff --git a/connectivity/drivers/cellular/GEMALTO/CINTERION/GEMALTO_CINTERION.cpp b/connectivity/drivers/cellular/GEMALTO/CINTERION/GEMALTO_CINTERION.cpp index 1f82199106e..3754ad50ec9 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,38 +71,26 @@ 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; +} +nsapi_error_t GEMALTO_CINTERION::shutdown() +{ + CellularDevice::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 21d5888383d..edc980209e2 100644 --- a/connectivity/drivers/cellular/GEMALTO/CINTERION/GEMALTO_CINTERION.h +++ b/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/connectivity/drivers/cellular/GEMALTO/CINTERION/GEMALTO_CINTERION_CellularContext.cpp b/connectivity/drivers/cellular/GEMALTO/CINTERION/GEMALTO_CINTERION_CellularContext.cpp index 78955c599e1..76c788cdaf5 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); diff --git a/connectivity/drivers/cellular/GEMALTO/CINTERION/GEMALTO_CINTERION_CellularStack.cpp b/connectivity/drivers/cellular/GEMALTO/CINTERION/GEMALTO_CINTERION_CellularStack.cpp index ac2a54282a2..898f81cf66e 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; @@ -47,6 +48,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,7 +62,8 @@ void GEMALTO_CINTERION_CellularStack::urc_sis() } if (urc_code == 0) { int urc_info_id = _at.read_int(); - if (urc_info_id == 48) { + 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; if (sock->_cb) { @@ -221,6 +225,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(); @@ -249,14 +270,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(); } @@ -293,6 +310,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; } } @@ -521,11 +539,18 @@ nsapi_size_or_error_t GEMALTO_CINTERION_CellularStack::socket_sendto_impl(Cellul 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; } -#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) @@ -576,6 +601,8 @@ nsapi_size_or_error_t GEMALTO_CINTERION_CellularStack::socket_recvfrom_impl(Cell 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) { diff --git a/connectivity/drivers/cellular/GEMALTO/CINTERION/GEMALTO_CINTERION_CellularStack.h b/connectivity/drivers/cellular/GEMALTO/CINTERION/GEMALTO_CINTERION_CellularStack.h index f89da8c3140..159ea68aa9e 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 @@ class GEMALTO_CINTERION_CellularStack : public AT_CellularStack { void stopGNSS(); void PSMEnable(); void PSMDisable(); + int ping(const char *host, int ttl); protected: diff --git a/connectivity/drivers/emac/COMPONENT_WHD/interface/WhdSTAInterface.cpp b/connectivity/drivers/emac/COMPONENT_WHD/interface/WhdSTAInterface.cpp index 509a2c0981e..e90c12b3197 100644 --- a/connectivity/drivers/emac/COMPONENT_WHD/interface/WhdSTAInterface.cpp +++ b/connectivity/drivers/emac/COMPONENT_WHD/interface/WhdSTAInterface.cpp @@ -211,7 +211,8 @@ WhdSTAInterface::WhdSTAInterface(WHD_EMAC &emac, OnboardNetworkStack &stack, Olm _security(NSAPI_SECURITY_NONE), _whd_emac(emac), _olm(&olm), - _iface_shared(shared) + _iface_shared(shared), + _timeout(7000) { } @@ -260,7 +261,7 @@ nsapi_error_t WhdSTAInterface::connect() { ScopedMutexLock lock(_iface_shared.mutex); -#define MAX_RETRY_COUNT ( 5 ) +#define MAX_RETRY_COUNT ( 1 ) int i; whd_result_t res; @@ -280,7 +281,7 @@ nsapi_error_t WhdSTAInterface::connect() _iface_shared.if_status_flags |= IF_STATUS_STA_UP; _iface_shared.default_if_cfg = DEFAULT_IF_STA; if (!_interface) { - nsapi_error_t err = _stack.add_ethernet_interface(_emac, true, &_interface); + nsapi_error_t err = _stack.add_ethernet_interface(_emac, true, &_interface, this); if (err != NSAPI_ERROR_OK) { _interface = NULL; return err; @@ -334,7 +335,7 @@ nsapi_error_t WhdSTAInterface::connect() res = (whd_result_t)whd_wifi_join(_whd_emac.ifp, &ssid, security, - (const uint8_t *)_pass, strlen(_pass)); + (const uint8_t *)_pass, strlen(_pass), _timeout); } else { @@ -345,7 +346,7 @@ nsapi_error_t WhdSTAInterface::connect() res = (whd_result_t)whd_wifi_join(_whd_emac.ifp, &ssid, security, - (const uint8_t *)_pass, key_length); + (const uint8_t *)_pass, key_length, _timeout); } if (res == WHD_SUCCESS) { break; diff --git a/connectivity/drivers/emac/COMPONENT_WHD/interface/WhdSTAInterface.h b/connectivity/drivers/emac/COMPONENT_WHD/interface/WhdSTAInterface.h index 4dd10989472..8d8f5407591 100644 --- a/connectivity/drivers/emac/COMPONENT_WHD/interface/WhdSTAInterface.h +++ b/connectivity/drivers/emac/COMPONENT_WHD/interface/WhdSTAInterface.h @@ -119,6 +119,12 @@ class WhdSTAInterface : public WiFiInterface, public EMACInterface { return 0; } + nsapi_error_t set_timeout(uint32_t timeout) + { + _timeout = timeout; + return NSAPI_ERROR_OK; + } + /** Set blocking status of interface. * Nonblocking mode unsupported. * @@ -257,6 +263,7 @@ class WhdSTAInterface : public WiFiInterface, public EMACInterface { nsapi_security_t _security; WHD_EMAC &_whd_emac; OlmInterface *_olm; + uint32_t _timeout; whd_interface_shared_info_t &_iface_shared; }; diff --git a/connectivity/drivers/emac/TARGET_STM/TARGET_STM32H7/TARGET_OPTA/stm32h7_eth_init.c b/connectivity/drivers/emac/TARGET_STM/TARGET_STM32H7/TARGET_OPTA/stm32h7_eth_init.c index 0572fae7a2a..8b9cc8bcd03 100644 --- a/connectivity/drivers/emac/TARGET_STM/TARGET_STM32H7/TARGET_OPTA/stm32h7_eth_init.c +++ b/connectivity/drivers/emac/TARGET_STM/TARGET_STM32H7/TARGET_OPTA/stm32h7_eth_init.c @@ -66,7 +66,10 @@ void HAL_ETH_MspInit(ETH_HandleTypeDef *heth) #if !(defined(DUAL_CORE) && defined(CORE_CM4)) /* Disable DCache for STM32H7 family */ + core_util_critical_section_enter(); + SCB_CleanInvalidateDCache(); SCB_DisableDCache(); + core_util_critical_section_exit(); #endif /* GPIO Ports Clock Enable */ diff --git a/connectivity/drivers/emac/TARGET_STM/TARGET_STM32H7/TARGET_PORTENTA_H7/stm32h7_eth_init.c b/connectivity/drivers/emac/TARGET_STM/TARGET_STM32H7/TARGET_PORTENTA_H7/stm32h7_eth_init.c index 643fc5acd36..7f5b4206cb5 100644 --- a/connectivity/drivers/emac/TARGET_STM/TARGET_STM32H7/TARGET_PORTENTA_H7/stm32h7_eth_init.c +++ b/connectivity/drivers/emac/TARGET_STM/TARGET_STM32H7/TARGET_PORTENTA_H7/stm32h7_eth_init.c @@ -68,6 +68,7 @@ void HAL_ETH_MspInit(ETH_HandleTypeDef *heth) #if !(defined(DUAL_CORE) && defined(CORE_CM4)) /* Disable DCache for STM32H7 family */ core_util_critical_section_enter(); + SCB_CleanInvalidateDCache(); SCB_DisableDCache(); core_util_critical_section_exit(); #endif diff --git a/connectivity/drivers/emac/TARGET_STM/stm32xx_emac.cpp b/connectivity/drivers/emac/TARGET_STM/stm32xx_emac.cpp index 0230a90665c..0e7d64ad349 100644 --- a/connectivity/drivers/emac/TARGET_STM/stm32xx_emac.cpp +++ b/connectivity/drivers/emac/TARGET_STM/stm32xx_emac.cpp @@ -402,6 +402,33 @@ bool STM32_EMAC::low_level_init_successful() } #endif // ETH_IP_VERSION_V2 +/** + * This function get the state of emac interface + */ +int STM32_EMAC::get_interface_status() { + return HAL_ETH_GetState(&EthHandle); +} + +/** + * This function returns true if the status of the interface is in the + * correct state for the trasmission + */ +bool STM32_EMAC::is_ready_to_tx() { + return (HAL_ETH_GetState(&EthHandle) == HAL_ETH_STATE_READY); +} + +/** + * This function reset the emac interface in case the status is in error + * Apparently there was not anything to recover from an error state + */ +void STM32_EMAC::restart() { + if(HAL_ETH_STATE_ERROR == HAL_ETH_GetState(&EthHandle)){ + HAL_ETH_Stop(&EthHandle); + HAL_ETH_Start(&EthHandle); + } +} + + /** * This function should do the actual transmission of the packet. The packet is * contained in the memory buffer chain that is passed to the function. diff --git a/connectivity/drivers/emac/TARGET_STM/stm32xx_emac.h b/connectivity/drivers/emac/TARGET_STM/stm32xx_emac.h index cfa67521774..ecc280b2f84 100644 --- a/connectivity/drivers/emac/TARGET_STM/stm32xx_emac.h +++ b/connectivity/drivers/emac/TARGET_STM/stm32xx_emac.h @@ -148,6 +148,13 @@ class STM32_EMAC : public EMAC { */ virtual void set_memory_manager(EMACMemoryManager &mem_mngr); + /* return the status of the interface as integer */ + int get_interface_status() override; + /* return true if the interface is in the correct state to transmit */ + bool is_ready_to_tx() override; + /* restart only if the interface is in error state */ + void restart() override; + // Called from driver functions ETH_HandleTypeDef EthHandle; osThreadId_t thread; /**< Processing thread */ diff --git a/connectivity/drivers/wifi/COMPONENT_WHD/wifi-host-driver/inc/whd_version.h b/connectivity/drivers/wifi/COMPONENT_WHD/wifi-host-driver/inc/whd_version.h index 1caef23b67d..5f69d8c3e08 100755 --- a/connectivity/drivers/wifi/COMPONENT_WHD/wifi-host-driver/inc/whd_version.h +++ b/connectivity/drivers/wifi/COMPONENT_WHD/wifi-host-driver/inc/whd_version.h @@ -15,6 +15,7 @@ * limitations under the License. */ -#define WHD_VERSION "v1.94.0" +/* This define is used by arduino::WiFiClass::firmwareVersion() do not prepend v */ +#define WHD_VERSION "1.94.0" #define WHD_BRANCH "v1.94.0" #define WHD_DATE "2021-04-27 16:54:34 +0800" diff --git a/connectivity/drivers/wifi/COMPONENT_WHD/wifi-host-driver/inc/whd_wifi_api.h b/connectivity/drivers/wifi/COMPONENT_WHD/wifi-host-driver/inc/whd_wifi_api.h index f3b73214cbb..291bd23de8e 100755 --- a/connectivity/drivers/wifi/COMPONENT_WHD/wifi-host-driver/inc/whd_wifi_api.h +++ b/connectivity/drivers/wifi/COMPONENT_WHD/wifi-host-driver/inc/whd_wifi_api.h @@ -281,7 +281,7 @@ extern uint32_t whd_wifi_stop_scan(whd_interface_t ifp); * Error code if an error occurred */ extern uint32_t whd_wifi_join(whd_interface_t ifp, const whd_ssid_t *ssid, whd_security_t auth_type, - const uint8_t *security_key, uint8_t key_length); + const uint8_t *security_key, uint8_t key_length, uint32_t timeout); /** Joins a specific Wi-Fi network * diff --git a/connectivity/drivers/wifi/COMPONENT_WHD/wifi-host-driver/src/whd_wifi_api.c b/connectivity/drivers/wifi/COMPONENT_WHD/wifi-host-driver/src/whd_wifi_api.c index 5294104ab4d..8a8f411ef98 100755 --- a/connectivity/drivers/wifi/COMPONENT_WHD/wifi-host-driver/src/whd_wifi_api.c +++ b/connectivity/drivers/wifi/COMPONENT_WHD/wifi-host-driver/src/whd_wifi_api.c @@ -294,6 +294,8 @@ static const uint16_t mcs_data_rate_lookup_table[32][2][2] = }, }; +static whd_wifi_join_timeout = DEFAULT_JOIN_ATTEMPT_TIMEOUT; + /****************************************************** * Static Function prototypes @@ -1334,7 +1336,7 @@ static uint32_t whd_wifi_join_wait_for_complete(whd_interface_t ifp, cy_semaphor while (!done) { - result = cy_rtos_get_semaphore(semaphore, DEFAULT_JOIN_ATTEMPT_TIMEOUT / 10, WHD_FALSE); + result = cy_rtos_get_semaphore(semaphore, whd_wifi_join_timeout / 10, WHD_FALSE); whd_assert("Get semaphore failed", (result == CY_RSLT_SUCCESS) || (result == CY_RTOS_TIMEOUT) ); REFERENCE_DEBUG_ONLY_VARIABLE(result); @@ -1345,7 +1347,7 @@ static uint32_t whd_wifi_join_wait_for_complete(whd_interface_t ifp, cy_semaphor } cy_rtos_get_time(¤t_time); - done = (whd_bool_t)( (current_time - start_time) >= DEFAULT_JOIN_ATTEMPT_TIMEOUT ); + done = (whd_bool_t)( (current_time - start_time) >= whd_wifi_join_timeout ); } if (result != WHD_SUCCESS) @@ -1574,7 +1576,7 @@ uint32_t whd_wifi_join_specific(whd_interface_t ifp, const whd_scan_result_t *ap } uint32_t whd_wifi_join(whd_interface_t ifp, const whd_ssid_t *ssid, whd_security_t auth_type, - const uint8_t *security_key, uint8_t key_length) + const uint8_t *security_key, uint8_t key_length, uint32_t timeout) { cy_semaphore_t join_sema; whd_result_t result; @@ -1616,6 +1618,7 @@ uint32_t whd_wifi_join(whd_interface_t ifp, const whd_ssid_t *ssid, whd_security ssid_params->SSID_len = htod32(ssid->length); memcpy(ssid_params->SSID, ssid->value, ssid_params->SSID_len); result = whd_cdc_send_ioctl(ifp, CDC_SET, WLC_SET_SSID, buffer, 0); + whd_wifi_join_timeout = timeout; if (result == WHD_SUCCESS) { diff --git a/connectivity/lwipstack/source/LWIPInterface.cpp b/connectivity/lwipstack/source/LWIPInterface.cpp index a1cfcf31c41..da964543c79 100644 --- a/connectivity/lwipstack/source/LWIPInterface.cpp +++ b/connectivity/lwipstack/source/LWIPInterface.cpp @@ -169,8 +169,12 @@ nsapi_error_t LWIP::Interface::set_dhcp() #if LWIP_DHCP if (dhcp_has_to_be_set) { + if(dhcp_started) { + dhcp_stop(&netif); + dhcp_started = false; + } + err_t err = dhcp_start(&netif); - dhcp_has_to_be_set = false; if (err) { connected = NSAPI_STATUS_DISCONNECTED; if (client_callback) { @@ -433,6 +437,7 @@ LWIP::Interface::Interface() : nsapi_error_t LWIP::add_ethernet_interface(EMAC &emac, bool default_if, OnboardNetworkStack::Interface **interface_out, NetworkInterface *user_network_interface) { #if LWIP_ETHERNET + const char *hostname; Interface *interface = new (std::nothrow) Interface(); if (!interface) { return NSAPI_ERROR_NO_MEMORY; @@ -441,6 +446,13 @@ nsapi_error_t LWIP::add_ethernet_interface(EMAC &emac, bool default_if, OnboardN interface->memory_manager = &memory_manager; interface->ppp_enabled = false; + if (user_network_interface) { + hostname = user_network_interface->get_hostname(); + if (hostname) { + netif_set_hostname(&interface->netif, hostname); + } + } + #if (MBED_MAC_ADDRESS_SUM != MBED_MAC_ADDR_INTERFACE) netif->interface.hwaddr[0] = MBED_MAC_ADDR_0; netif->interface.hwaddr[1] = MBED_MAC_ADDR_1; diff --git a/connectivity/lwipstack/source/LWIPInterfaceEMAC.cpp b/connectivity/lwipstack/source/LWIPInterfaceEMAC.cpp index 56fbcc0d904..ed4397879ef 100644 --- a/connectivity/lwipstack/source/LWIPInterfaceEMAC.cpp +++ b/connectivity/lwipstack/source/LWIPInterfaceEMAC.cpp @@ -27,15 +27,26 @@ #if LWIP_ETHERNET + err_t LWIP::Interface::emac_low_level_output(struct netif *netif, struct pbuf *p) { + bool ret = false; /* Increase reference counter since lwip stores handle to pbuf and frees it after output */ pbuf_ref(p); LWIP::Interface *mbed_if = static_cast(netif->state); - bool ret = mbed_if->emac->link_out(p); - return ret ? ERR_OK : ERR_IF; + + if(mbed_if->emac->is_ready_to_tx()) { + ret = mbed_if->emac->link_out(p); + } + else { + mbed_if->emac->restart(); + ret = mbed_if->emac->link_out(p); + } + + err_t rv = ret ? ERR_OK : ERR_IF; + return rv; } void LWIP::Interface::emac_input(emac_mem_buf_t *buf) diff --git a/connectivity/netsocket/include/netsocket/EMAC.h b/connectivity/netsocket/include/netsocket/EMAC.h index 515629b5a61..885bc92c017 100644 --- a/connectivity/netsocket/include/netsocket/EMAC.h +++ b/connectivity/netsocket/include/netsocket/EMAC.h @@ -176,6 +176,17 @@ class EMAC { * @param mem_mngr Pointer to memory manager */ virtual void set_memory_manager(EMACMemoryManager &mem_mngr) = 0; + + virtual bool is_ready_to_tx() { + return true; + } + + virtual void restart() { + } + + virtual int get_interface_status() { + return -1; + } }; diff --git a/connectivity/netsocket/include/netsocket/EMACInterface.h b/connectivity/netsocket/include/netsocket/EMACInterface.h index 8cf47cb7036..c06aeb850e5 100644 --- a/connectivity/netsocket/include/netsocket/EMACInterface.h +++ b/connectivity/netsocket/include/netsocket/EMACInterface.h @@ -83,6 +83,12 @@ class EMACInterface : public virtual NetworkInterface { /** @copydoc NetworkInterface::disconnect */ nsapi_error_t disconnect() override; + /** @copydoc NetworkInterface::get_hostname */ + const char *get_hostname() override; + + /** @copydoc NetworkInterface::set_hostname */ + nsapi_error_t set_hostname(const char *hostname) override; + /** @copydoc NetworkInterface::get_mac_address */ const char *get_mac_address() override; @@ -146,6 +152,8 @@ class EMACInterface : public virtual NetworkInterface { OnboardNetworkStack::Interface *_interface = nullptr; bool _dhcp = true; bool _blocking = true; + bool _hostname_set = false; + char _hostname[NSAPI_HOSTNAME_SIZE]; bool _hw_mac_addr_set = false; char _mac_address[NSAPI_MAC_SIZE]; char _ip_address[NSAPI_IPv6_SIZE] {}; diff --git a/connectivity/netsocket/include/netsocket/ICMPSocket.h b/connectivity/netsocket/include/netsocket/ICMPSocket.h index 1837bc8e096..5e1ee8fb03a 100644 --- a/connectivity/netsocket/include/netsocket/ICMPSocket.h +++ b/connectivity/netsocket/include/netsocket/ICMPSocket.h @@ -37,6 +37,10 @@ class ICMPSocket : public InternetDatagramSocket { */ ICMPSocket(); +#if MBED_CONF_LWIP_RAW_SOCKET_ENABLED + int ping(SocketAddress &socketAddress, uint32_t timeout); +#endif + #if !defined(DOXYGEN_ONLY) protected: diff --git a/connectivity/netsocket/include/netsocket/NetworkInterface.h b/connectivity/netsocket/include/netsocket/NetworkInterface.h index 9071a1e40bd..22355767cef 100644 --- a/connectivity/netsocket/include/netsocket/NetworkInterface.h +++ b/connectivity/netsocket/include/netsocket/NetworkInterface.h @@ -90,6 +90,24 @@ class NetworkInterface: public DNS { */ virtual void set_as_default(); + /** Get hostname. + * + * @return Hostname if configured, null otherwise + */ + virtual const char *get_hostname(); + + /** Set hostname. + * + * @param hostname Hostname string + * @retval NSAPI_ERROR_OK on success + * @retval NSAPI_ERROR_UNSUPPORTED if this feature is not supported + * @retval NSAPI_ERROR_PARAMETER if hostname is not valid + * @retval NSAPI_ERROR_BUSY if hostname couldn't be set (e.g. for + * LwIP stack, hostname can only be set before calling + * \c EthernetInterface::connect method) + */ + virtual nsapi_error_t set_hostname(const char *hostname); + /** Get the local MAC address. * * Provided MAC address is intended for info or debug purposes and diff --git a/connectivity/netsocket/include/netsocket/TLSSocketWrapper.h b/connectivity/netsocket/include/netsocket/TLSSocketWrapper.h index 2dc3b4b0004..79fe5c564de 100644 --- a/connectivity/netsocket/include/netsocket/TLSSocketWrapper.h +++ b/connectivity/netsocket/include/netsocket/TLSSocketWrapper.h @@ -379,6 +379,10 @@ class TLSSocketWrapper : public Socket { Socket *_transport; int _timeout = -1; + // Event flags + static const int READ_FLAG = 0x1u; + static const int WRITE_FLAG = 0x2u; + #ifdef MBEDTLS_X509_CRT_PARSE_C mbedtls_x509_crt *_cacert = nullptr; mbedtls_x509_crt *_clicert = nullptr; diff --git a/connectivity/netsocket/include/netsocket/WiFiInterface.h b/connectivity/netsocket/include/netsocket/WiFiInterface.h index 4fd7fc6fb8a..c13cab4312b 100644 --- a/connectivity/netsocket/include/netsocket/WiFiInterface.h +++ b/connectivity/netsocket/include/netsocket/WiFiInterface.h @@ -59,6 +59,13 @@ class WiFiInterface: public virtual NetworkInterface { */ virtual nsapi_error_t set_channel(uint8_t channel) = 0; + /** Set the Wi-Fi network join timeout. + * + * @param timeout joint timeout in milliseconds (Default: 7000). + * @return NSAPI_ERROR_OK on success, or error code on failure. + */ + virtual nsapi_error_t set_timeout(uint32_t timeout) = 0; + /** Get the current radio signal strength for active connection. * * @return Connection strength in dBm (negative value), diff --git a/connectivity/netsocket/include/netsocket/nsapi_types.h b/connectivity/netsocket/include/netsocket/nsapi_types.h index 3b496d5087a..28dbcc9a38d 100644 --- a/connectivity/netsocket/include/netsocket/nsapi_types.h +++ b/connectivity/netsocket/include/netsocket/nsapi_types.h @@ -196,6 +196,16 @@ typedef enum nsapi_security { */ #define NSAPI_IP_BYTES NSAPI_IPv6_BYTES +/** Maximum size of hostname + * + * According to RFC 1034 [1], Section 3.1 "Name space specifications and + * terminology", 63 is the maximum size of a hostname. +1 for the string + * terminator. + * + * [1] https://www.rfc-editor.org/rfc/rfc1034 + */ +#define NSAPI_HOSTNAME_SIZE 64 + /** Maximum size of MAC address representation */ #define NSAPI_MAC_SIZE 18 diff --git a/connectivity/netsocket/source/EMACInterface.cpp b/connectivity/netsocket/source/EMACInterface.cpp index f48bc0a185a..de8d9753d7c 100644 --- a/connectivity/netsocket/source/EMACInterface.cpp +++ b/connectivity/netsocket/source/EMACInterface.cpp @@ -88,6 +88,32 @@ nsapi_error_t EMACInterface::disconnect() return NSAPI_ERROR_NO_CONNECTION; } +const char *EMACInterface::get_hostname() +{ + if (_hostname_set) { + return _hostname; + } + return nullptr; +} + +nsapi_error_t EMACInterface::set_hostname(const char *hostname) +{ + if (!hostname || strlen(hostname) > NSAPI_HOSTNAME_SIZE - 1) { + return NSAPI_ERROR_PARAMETER; + } + + if (_interface) { + // can't set hostname once initialized + return NSAPI_ERROR_BUSY; + } + + memset(_hostname, 0, NSAPI_HOSTNAME_SIZE); + strncpy(_hostname, hostname, NSAPI_HOSTNAME_SIZE - 1); + _hostname_set = true; + + return NSAPI_ERROR_OK; +} + const char *EMACInterface::get_mac_address() { if (_interface && _interface->get_mac_address(_mac_address, sizeof(_mac_address))) { diff --git a/connectivity/netsocket/source/ICMPSocket.cpp b/connectivity/netsocket/source/ICMPSocket.cpp index f6c9b98de10..d8ea9548350 100644 --- a/connectivity/netsocket/source/ICMPSocket.cpp +++ b/connectivity/netsocket/source/ICMPSocket.cpp @@ -16,12 +16,73 @@ */ #include "ICMPSocket.h" +#if MBED_CONF_LWIP_RAW_SOCKET_ENABLED +#include "drivers/Timer.h" +#include "lwip/prot/icmp.h" +#include "lwip/inet_chksum.h" +#include "lwip/prot/ip4.h" +#endif ICMPSocket::ICMPSocket() { _socket_stats.stats_update_proto(this, NSAPI_ICMP); } +#if MBED_CONF_LWIP_RAW_SOCKET_ENABLED +int ICMPSocket::ping(SocketAddress &socketAddress, uint32_t timeout) +{ + struct __attribute__((__packed__)) { + struct icmp_echo_hdr header; + uint8_t data[32]; + } request; + + ICMPH_TYPE_SET(&request.header, ICMP_ECHO); + ICMPH_CODE_SET(&request.header, 0); + request.header.chksum = 0; + request.header.id = 0xAFAF; + request.header.seqno = random(); + + for (size_t i = 0; i < sizeof(request.data); i++) { + request.data[i] = i; + } + + request.header.chksum = inet_chksum(&request, sizeof(request)); + + int res = sendto(socketAddress, &request, sizeof(request)); + if (res <= 0){ + return -1; + } + + mbed::Timer timer; + timer.start(); + int elapsed = -1; + do { + struct __attribute__((__packed__)) { + struct ip_hdr ipHeader; + struct icmp_echo_hdr header; + } response; + + int rxSize = recvfrom(&socketAddress, &response, sizeof(response)); + if (rxSize < 0) { + // time out + break; + } + + if (rxSize < sizeof(response)) { + // too short + continue; + } + + if ((response.header.id == request.header.id) && (response.header.seqno == request.header.seqno)) { + elapsed = std::chrono::duration_cast(timer.elapsed_time()).count(); + timer.stop(); + } + } while (elapsed == -1 && std::chrono::duration_cast(timer.elapsed_time()).count() < timeout); + + return elapsed; +} +#endif + nsapi_protocol_t ICMPSocket::get_proto() { return NSAPI_ICMP; diff --git a/connectivity/netsocket/source/NetworkInterface.cpp b/connectivity/netsocket/source/NetworkInterface.cpp index 0f237f0e190..649df0f9b30 100644 --- a/connectivity/netsocket/source/NetworkInterface.cpp +++ b/connectivity/netsocket/source/NetworkInterface.cpp @@ -29,6 +29,16 @@ void NetworkInterface::set_as_default() } +const char *NetworkInterface::get_hostname() +{ + return 0; +} + +nsapi_error_t NetworkInterface::set_hostname(const char *hostname) +{ + return NSAPI_ERROR_UNSUPPORTED; +} + const char *NetworkInterface::get_mac_address() { return 0; diff --git a/connectivity/netsocket/source/TLSSocketWrapper.cpp b/connectivity/netsocket/source/TLSSocketWrapper.cpp index 1fb9c217694..3a66be2e5ec 100644 --- a/connectivity/netsocket/source/TLSSocketWrapper.cpp +++ b/connectivity/netsocket/source/TLSSocketWrapper.cpp @@ -381,7 +381,7 @@ nsapi_error_t TLSSocketWrapper::continue_handshake() ret = mbedtls_ssl_handshake(&_ssl); if (_timeout && (ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE)) { uint32_t flag; - flag = _event_flag.wait_any(1, _timeout); + flag = _event_flag.wait_any(WRITE_FLAG | READ_FLAG, _timeout); if (flag & osFlagsError) { break; } @@ -461,7 +461,7 @@ nsapi_error_t TLSSocketWrapper::send(const void *data, nsapi_size_t size) break; } else if (ret == MBEDTLS_ERR_SSL_WANT_WRITE || ret == MBEDTLS_ERR_SSL_WANT_READ) { uint32_t flag; - flag = _event_flag.wait_any(1, _timeout); + flag = _event_flag.wait_any(WRITE_FLAG, _timeout); if (flag & osFlagsError) { // Timeout break break; @@ -522,7 +522,7 @@ nsapi_size_or_error_t TLSSocketWrapper::recv(void *data, nsapi_size_t size) break; } else if (ret == MBEDTLS_ERR_SSL_WANT_WRITE || ret == MBEDTLS_ERR_SSL_WANT_READ) { uint32_t flag; - flag = _event_flag.wait_any(1, _timeout); + flag = _event_flag.wait_any(READ_FLAG, _timeout); if (flag & osFlagsError) { // Timeout break break; @@ -757,7 +757,6 @@ nsapi_error_t TLSSocketWrapper::close() int ret = 0; if (_handshake_completed) { - _transport->set_blocking(true); ret = mbedtls_ssl_close_notify(&_ssl); if (ret) { print_mbedtls_error("mbedtls_ssl_close_notify", ret); @@ -856,7 +855,7 @@ nsapi_error_t TLSSocketWrapper::listen(int) void TLSSocketWrapper::event() { - _event_flag.set(1); + _event_flag.set(READ_FLAG | WRITE_FLAG); if (_sigio) { _sigio(); } diff --git a/connectivity/netsocket/tests/UNITTESTS/doubles/NetworkInterface_stub.cpp b/connectivity/netsocket/tests/UNITTESTS/doubles/NetworkInterface_stub.cpp index 020a551ba97..c849704a35b 100644 --- a/connectivity/netsocket/tests/UNITTESTS/doubles/NetworkInterface_stub.cpp +++ b/connectivity/netsocket/tests/UNITTESTS/doubles/NetworkInterface_stub.cpp @@ -21,6 +21,16 @@ // Default network-interface state +const char *NetworkInterface::get_hostname() +{ + return 0; +} + +nsapi_error_t NetworkInterface::set_hostname(const char *hostname) +{ + return NSAPI_ERROR_UNSUPPORTED; +} + const char *NetworkInterface::get_mac_address() { return 0; diff --git a/connectivity/netsocket/tests/UNITTESTS/netsocket/NetworkInterface/test_NetworkInterface.cpp b/connectivity/netsocket/tests/UNITTESTS/netsocket/NetworkInterface/test_NetworkInterface.cpp index 1a928c36ee1..27433ffaa1f 100644 --- a/connectivity/netsocket/tests/UNITTESTS/netsocket/NetworkInterface/test_NetworkInterface.cpp +++ b/connectivity/netsocket/tests/UNITTESTS/netsocket/NetworkInterface/test_NetworkInterface.cpp @@ -68,6 +68,17 @@ TEST_F(TestNetworkInterface, constructor) } // get_default_instance is tested along with the implementations of NetworkInterface. +TEST_F(TestNetworkInterface, get_hostname) +{ + char *n = 0; + EXPECT_EQ(iface->get_hostname(), n); +} + +TEST_F(TestNetworkInterface, set_hostname) +{ + char *hostname; + EXPECT_EQ(iface->set_hostname(hostname), NSAPI_ERROR_UNSUPPORTED); +} TEST_F(TestNetworkInterface, get_mac_address) { diff --git a/drivers/source/Watchdog.cpp b/drivers/source/Watchdog.cpp index 3f21b94dfb1..daca0181483 100644 --- a/drivers/source/Watchdog.cpp +++ b/drivers/source/Watchdog.cpp @@ -72,9 +72,11 @@ bool Watchdog::stop() void Watchdog::kick() { - core_util_critical_section_enter(); - hal_watchdog_kick(); - core_util_critical_section_exit(); + if (_running) { + core_util_critical_section_enter(); + hal_watchdog_kick(); + core_util_critical_section_exit(); + } } bool Watchdog::is_running() const diff --git a/storage/blockdevice/COMPONENT_QSPIF/source/QSPIFBlockDevice.cpp b/storage/blockdevice/COMPONENT_QSPIF/source/QSPIFBlockDevice.cpp index cd21a7354db..b005aeb0f1e 100644 --- a/storage/blockdevice/COMPONENT_QSPIF/source/QSPIFBlockDevice.cpp +++ b/storage/blockdevice/COMPONENT_QSPIF/source/QSPIFBlockDevice.cpp @@ -1243,12 +1243,13 @@ int QSPIFBlockDevice::_set_write_enable() uint8_t status_value = 0; int status = -1; - if (false == _is_mem_ready()) { + if (_AT25SF128A_quirk && (false == _is_mem_ready())) { tr_error("Device not ready, set_write_enable failed"); return -1; } do { + if (QSPI_STATUS_OK != _qspi_send_general_command(QSPIF_INST_WREN, QSPI_NO_ADDRESS_COMMAND, NULL, 0, NULL, 0)) { tr_error("Sending WREN command FAILED"); break; diff --git a/targets/TARGET_RASPBERRYPI/TARGET_RP2040/CMakeLists.txt b/targets/TARGET_RASPBERRYPI/TARGET_RP2040/CMakeLists.txt index 4fadf6091ee..4e9bae47cef 100644 --- a/targets/TARGET_RASPBERRYPI/TARGET_RP2040/CMakeLists.txt +++ b/targets/TARGET_RASPBERRYPI/TARGET_RP2040/CMakeLists.txt @@ -36,6 +36,7 @@ target_include_directories(mbed-rp2040 pico-sdk/common/pico_base/include pico-sdk/common/pico_binary_info/include pico-sdk/common/pico_util/include + pico-sdk/common/pico_rand/include pico-sdk/boards/include pico-sdk/generated . @@ -71,6 +72,7 @@ target_sources(mbed-rp2040 pico-sdk/rp2_common/pico_bootrom/bootrom.c pico-sdk/rp2_common/pico_runtime/runtime.c pico-sdk/rp2_common/pico_platform/platform.c + pico-sdk/rp2_common/pico_rand/rand.c pico-sdk/common/pico_sync/mutex.c pico-sdk/common/pico_time/time.c pico-sdk/common/pico_sync/lock_core.c diff --git a/targets/TARGET_RASPBERRYPI/TARGET_RP2040/TOOLCHAIN_GCC_ARM/memmap_default.ld b/targets/TARGET_RASPBERRYPI/TARGET_RP2040/TOOLCHAIN_GCC_ARM/memmap_default.ld index ec8bac7e404..b748bab5fad 100644 --- a/targets/TARGET_RASPBERRYPI/TARGET_RP2040/TOOLCHAIN_GCC_ARM/memmap_default.ld +++ b/targets/TARGET_RASPBERRYPI/TARGET_RP2040/TOOLCHAIN_GCC_ARM/memmap_default.ld @@ -54,6 +54,10 @@ SECTIONS __flash_binary_start = .; } > FLASH + .second_stage_ota : { + KEEP (*(.second_stage_ota)) + } > FLASH + .boot2 : { __boot2_start__ = .; KEEP (*(.boot2)) @@ -179,7 +183,9 @@ SECTIONS .uninitialized_data (COPY): { . = ALIGN(4); + __uninitialized_data_start__ = .; *(.uninitialized_data*) + __uninitialized_data_end__ = .; } > RAM /* Start and end symbols must be word-aligned */ diff --git a/targets/TARGET_RASPBERRYPI/TARGET_RP2040/objects.h b/targets/TARGET_RASPBERRYPI/TARGET_RP2040/objects.h index f5f44a58f4a..0231968bb52 100644 --- a/targets/TARGET_RASPBERRYPI/TARGET_RP2040/objects.h +++ b/targets/TARGET_RASPBERRYPI/TARGET_RP2040/objects.h @@ -33,6 +33,7 @@ extern "C" { #include "pico/assert.h" #include "pico/time.h" #include "pico/types.h" +#include "pico/rand.h" #include "hardware/pwm.h" #include "hardware/adc.h" #include "hardware/resets.h" @@ -122,6 +123,12 @@ struct flash_s { uint32_t dummy; }; +#if DEVICE_TRNG +struct trng_s { + uint8_t not_used; +}; +#endif + typedef struct gpio_s gpio_t; typedef struct serial_s serial_t; diff --git a/targets/TARGET_RASPBERRYPI/TARGET_RP2040/pico-sdk/rp2_common/CMakeLists.txt b/targets/TARGET_RASPBERRYPI/TARGET_RP2040/pico-sdk/rp2_common/CMakeLists.txt index 4ca55becba2..ec89c3ff71e 100644 --- a/targets/TARGET_RASPBERRYPI/TARGET_RP2040/pico-sdk/rp2_common/CMakeLists.txt +++ b/targets/TARGET_RASPBERRYPI/TARGET_RP2040/pico-sdk/rp2_common/CMakeLists.txt @@ -49,6 +49,7 @@ if (NOT PICO_BARE_METAL) pico_add_subdirectory(pico_mem_ops) pico_add_subdirectory(pico_malloc) pico_add_subdirectory(pico_printf) + pico_add_subdirectory(pico_rand) pico_add_subdirectory(pico_stdio) pico_add_subdirectory(pico_stdio_semihosting) diff --git a/targets/TARGET_RASPBERRYPI/TARGET_RP2040/pico-sdk/rp2_common/hardware_sync/include/hardware/sync.h b/targets/TARGET_RASPBERRYPI/TARGET_RP2040/pico-sdk/rp2_common/hardware_sync/include/hardware/sync.h index 8f91d55955c..4f076aba021 100644 --- a/targets/TARGET_RASPBERRYPI/TARGET_RP2040/pico-sdk/rp2_common/hardware_sync/include/hardware/sync.h +++ b/targets/TARGET_RASPBERRYPI/TARGET_RP2040/pico-sdk/rp2_common/hardware_sync/include/hardware/sync.h @@ -70,6 +70,11 @@ typedef volatile uint32_t spin_lock_t; #define PICO_SPINLOCK_ID_HARDWARE_CLAIM 11 #endif +// PICO_CONFIG: PICO_SPINLOCK_ID_RAND, Spinlock ID for Random Number Generator, min=0, max=31, default=12, group=hardware_sync +#ifndef PICO_SPINLOCK_ID_RAND +#define PICO_SPINLOCK_ID_RAND 12 +#endif + // PICO_CONFIG: PICO_SPINLOCK_ID_OS1, First Spinlock ID reserved for use by low level OS style software, min=0, max=31, default=14, group=hardware_sync #ifndef PICO_SPINLOCK_ID_OS1 #define PICO_SPINLOCK_ID_OS1 14 diff --git a/targets/TARGET_RASPBERRYPI/TARGET_RP2040/pico-sdk/rp2_common/pico_platform/include/pico/platform.h b/targets/TARGET_RASPBERRYPI/TARGET_RP2040/pico-sdk/rp2_common/pico_platform/include/pico/platform.h index ee1d360cee9..ea16d9734e4 100644 --- a/targets/TARGET_RASPBERRYPI/TARGET_RP2040/pico-sdk/rp2_common/pico_platform/include/pico/platform.h +++ b/targets/TARGET_RASPBERRYPI/TARGET_RP2040/pico-sdk/rp2_common/pico_platform/include/pico/platform.h @@ -151,14 +151,14 @@ extern "C" { * * For example a `uint32_t` foo that will retain its value if the program is restarted by reset. * - * uint32_t __uninitialized_ram("my_group_name") foo; + * uint32_t __uninitialized_ram(foo); * - * The section attribute is `.uninitialized_ram.` + * The section attribute is `.uninitialized_data.` * * \param group a string suffix to use in the section name to distinguish groups that can be linker * garbage-collected independently */ -#define __uninitialized_ram(group) __attribute__((section(".uninitialized_ram." #group))) group +#define __uninitialized_ram(group) __attribute__((section(".uninitialized_data." #group))) group /*! \brief Section attribute macro for placement in flash even in a COPY_TO_RAM binary * \ingroup pico_platform diff --git a/targets/TARGET_RASPBERRYPI/TARGET_RP2040/pico-sdk/rp2_common/pico_rand/CMakeLists.txt b/targets/TARGET_RASPBERRYPI/TARGET_RP2040/pico-sdk/rp2_common/pico_rand/CMakeLists.txt new file mode 100644 index 00000000000..0e72bb5ab6b --- /dev/null +++ b/targets/TARGET_RASPBERRYPI/TARGET_RP2040/pico-sdk/rp2_common/pico_rand/CMakeLists.txt @@ -0,0 +1,13 @@ +pico_add_library(pico_rand) + +target_sources(pico_rand INTERFACE + ${CMAKE_CURRENT_LIST_DIR}/rand.c +) + +target_include_directories(pico_rand_headers INTERFACE ${CMAKE_CURRENT_LIST_DIR}/include) + +pico_mirrored_target_link_libraries(pico_rand INTERFACE + pico_unique_id + hardware_clocks + hardware_timer + hardware_sync) diff --git a/targets/TARGET_RASPBERRYPI/TARGET_RP2040/pico-sdk/rp2_common/pico_rand/include/pico/rand.h b/targets/TARGET_RASPBERRYPI/TARGET_RP2040/pico-sdk/rp2_common/pico_rand/include/pico/rand.h new file mode 100644 index 00000000000..20fc6d6cb14 --- /dev/null +++ b/targets/TARGET_RASPBERRYPI/TARGET_RP2040/pico-sdk/rp2_common/pico_rand/include/pico/rand.h @@ -0,0 +1,185 @@ +/* + * Copyright (c) 2022 Raspberry Pi (Trading) Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _PICO_RAND_H +#define _PICO_RAND_H + +#include "pico.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** \file pico/rand.h + * \defgroup pico_rand pico_rand + * + * Random Number Generator API + * + * This module generates random numbers at runtime utilizing a number of possible entropy + * sources and uses those sources to modify the state of a 128-bit 'Pseudo + * Random Number Generator' implemented in software. + * + * The random numbers (32 to 128 bit) to be supplied are read from the PRNG which is used + * to help provide a large number space. + * + * The following (multiple) sources of entropy are available (of varying quality), each enabled by a #define: + * + * - The Ring Oscillator (ROSC) (\ref PICO_RAND_ENTROPY_SRC_ROSC == 1): + * \ref PICO_RAND_ROSC_BIT_SAMPLE_COUNT bits are gathered from the ring oscillator "random bit" and mixed in each + * time. This should not be used if the ROSC is off, or the processor is running from + * the ROSC. + * \note the maximum throughput of ROSC bit sampling is controlled by PICO_RAND_MIN_ROSC_BIT_SAMPLE_TIME_US which defaults + * to 10us, i.e. 100,000 bits per second. + * - Time (\ref PICO_RAND_ENTROPY_SRC_TIME == 1): The 64-bit microsecond timer is mixed in each time. + * - Bus Performance Counter (\ref PICO_RAND_ENTROPY_SRC_BUS_PERF_COUNTER == 1): One of the bus fabric's performance + * counters is mixed in each time. + * + * \note All entropy sources are hashed before application to the PRNG state machine. + * + * The \em first time a random number is requested, the 128-bit PRNG state + * must be seeded. Multiple entropy sources are also available for the seeding operation: + * + * - The Ring Oscillator (ROSC) (\ref PICO_RAND_SEED_ENTROPY_SRC_ROSC == 1): + * 64 bits are gathered from the ring oscillator "random bit" and mixed into the seed. + * - Time (\ref PICO_RAND_SEED_ENTROPY_SRC_TIME == 1): The 64-bit microsecond timer is mixed into the seed. + * - Board Identifier (PICO_RAND_SEED_ENTROPY_SRC_BOARD_ID == 1): The board id via \ref pico_get_unique_board_id + * is mixed into the seed. + * - RAM hash (\ref PICO_RAND_SEED_ENTROPY_SRC_RAM_HASH (\ref PICO_RAND_SEED_ENTROPY_SRC_RAM_HASH): The hashed contents of a + * subset of RAM are mixed in. Initial RAM contents are undefined on power up, so provide a reasonable source of entropy. + * By default the last 1K of RAM (which usually contains the core 0 stack) is hashed, which may also provide for differences + * after each warm reset. + * + * With default settings, the seed generation takes approximately 1 millisecond while + * subsequent random numbers generally take between 10 and 20 microseconds to generate. + * + * pico_rand methods may be safely called from either core or from an IRQ, but be careful in the latter case as + * the calls may block for a number of microseconds waiting on more entropy. + */ + +// --------------- +// ENTROPY SOURCES +// --------------- + +// PICO_CONFIG: PICO_RAND_ENTROPY_SRC_ROSC, Enable/disable use of ROSC as an entropy source, type=bool, default=1, group=pico_rand +#ifndef PICO_RAND_ENTROPY_SRC_ROSC +#define PICO_RAND_ENTROPY_SRC_ROSC 1 +#endif + +// PICO_CONFIG: PICO_RAND_ENTROPY_SRC_TIME, Enable/disable use of hardware timestamp as an entropy source, type=bool, default=1, group=pico_rand +#ifndef PICO_RAND_ENTROPY_SRC_TIME +#define PICO_RAND_ENTROPY_SRC_TIME 1 +#endif + +// PICO_CONFIG: PICO_RAND_ENTROPY_SRC_BUS_PERF_COUNTER, Enable/disable use of a bus performance counter as an entropy source, type=bool, default=1, group=pico_rand +#ifndef PICO_RAND_ENTROPY_SRC_BUS_PERF_COUNTER +#define PICO_RAND_ENTROPY_SRC_BUS_PERF_COUNTER 1 +#endif + +// -------------------- +// SEED ENTROPY SOURCES +// -------------------- + +// PICO_CONFIG: PICO_RAND_SEED_ENTROPY_SRC_ROSC, Enable/disable use of ROSC as an entropy source for the random seed, type=bool, default=1, group=pico_rand +#ifndef PICO_RAND_SEED_ENTROPY_SRC_ROSC +#define PICO_RAND_SEED_ENTROPY_SRC_ROSC PICO_RAND_ENTROPY_SRC_ROSC +#endif + +// PICO_CONFIG: PICO_RAND_SEED_ENTROPY_SRC_TIME, Enable/disable use of hardware timestamp as an entropy source for the random seed, type=bool, default=1, group=pico_rand +#ifndef PICO_RAND_SEED_ENTROPY_SRC_TIME +#define PICO_RAND_SEED_ENTROPY_SRC_TIME PICO_RAND_ENTROPY_SRC_TIME +#endif + +// PICO_CONFIG: PICO_RAND_SEED_ENTROPY_SRC_BOARD_ID, Enable/disable use of board id as part of the random seed, type=bool, default=1, group=pico_rand +#ifndef PICO_RAND_SEED_ENTROPY_SRC_BOARD_ID +#define PICO_RAND_SEED_ENTROPY_SRC_BOARD_ID 0 +#endif + +// PICO_CONFIG: PICO_RAND_SEED_ENTROPY_SRC_RAM_HASH, Enable/disable use of a RAM hash as an entropy source for the random seed, type=bool, default=1, group=pico_rand +#ifndef PICO_RAND_SEED_ENTROPY_SRC_RAM_HASH +#define PICO_RAND_SEED_ENTROPY_SRC_RAM_HASH 1 +#endif + +// --------------------------------- +// PICO_RAND_ENTROPY_SRC_ROSC CONFIG +// --------------------------------- + +// PICO_CONFIG: PICO_RAND_ROSC_BIT_SAMPLE_COUNT, Number of samples to take of the ROSC random bit per random number generation , min=1, max=64, default=1, group=pico_rand +#ifndef PICO_RAND_ROSC_BIT_SAMPLE_COUNT +#define PICO_RAND_ROSC_BIT_SAMPLE_COUNT 1 +#endif + +// PICO_CONFIG: PICO_RAND_MIN_ROSC_BIT_SAMPLE_TIME_US, Define a default minimum time between sampling the ROSC random bit, min=5, max=20, default=10, group=pico_rand +#ifndef PICO_RAND_MIN_ROSC_BIT_SAMPLE_TIME_US +// (Arbitrary / tested) minimum time between sampling the ROSC random bit +#define PICO_RAND_MIN_ROSC_BIT_SAMPLE_TIME_US 10u +#endif + +// --------------------------------------------- +// PICO_RAND_ENTROPY_SRC_BUS_PERF_COUNTER CONFIG +// --------------------------------------------- + +// PICO_CONFIG: PICO_RAND_BUS_PERF_COUNTER_INDEX, Bus performance counter index to use for sourcing entropy, min=0, max=3, group=pico_rand +// this is deliberately undefined by default, meaning the code will pick that appears unused +//#define PICO_RAND_BUS_PERF_COUNTER_INDEX 0 + +// PICO_CONFIG: PICO_RAND_BUS_PERF_COUNTER_EVENT, Bus performance counter event to use for sourcing entropy, default=arbiter_sram5_perf_event_access, group=pico_rand +#ifndef PICO_RAND_BUS_PERF_COUNTER_EVENT +#define PICO_RAND_BUS_PERF_COUNTER_EVENT arbiter_sram5_perf_event_access +#endif + +// ------------------------------------------ +// PICO_RAND_SEED_ENTROPY_SRC_RAM_HASH CONFIG +// ------------------------------------------ + +// PICO_CONFIG: PICO_RAND_RAM_HASH_END, end of address in RAM (non-inclusive) to hash during pico_rand seed initialization, default=SRAM_END, group=pico_rand +#ifndef PICO_RAND_RAM_HASH_END +#define PICO_RAND_RAM_HASH_END SRAM_END +#endif +// PICO_CONFIG: PICO_RAND_RAM_HASH_START, start of address in RAM (inclusive) to hash during pico_rand seed initialization, default=PICO_RAND_RAM_HASH_END - 1024, group=pico_rand +#ifndef PICO_RAND_RAM_HASH_START +#define PICO_RAND_RAM_HASH_START (PICO_RAND_RAM_HASH_END - 1024u) +#endif + +// We provide a maximum of 128 bits entropy in one go +typedef struct rng_128 { + uint64_t r[2]; +} rng_128_t; + +/*! \brief Get 128-bit random number + * \ingroup pico_rand + * + * This method may be safely called from either core or from an IRQ, but be careful in the latter case as + * the call may block for a number of microseconds waiting on more entropy. + * + * \param rand128 Pointer to storage to accept a 128-bit random number + */ +void get_rand_128(rng_128_t *rand128); + +/*! \brief Get 64-bit random number + * \ingroup pico_rand + * + * This method may be safely called from either core or from an IRQ, but be careful in the latter case as + * the call may block for a number of microseconds waiting on more entropy. + * + * \return 64-bit random number + */ +uint64_t get_rand_64(void); + +/*! \brief Get 32-bit random number + * \ingroup pico_rand + * + * This method may be safely called from either core or from an IRQ, but be careful in the latter case as + * the call may block for a number of microseconds waiting on more entropy. + * + * \return 32-bit random number + */ +uint32_t get_rand_32(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/targets/TARGET_RASPBERRYPI/TARGET_RP2040/pico-sdk/rp2_common/pico_rand/rand.c b/targets/TARGET_RASPBERRYPI/TARGET_RP2040/pico-sdk/rp2_common/pico_rand/rand.c new file mode 100644 index 00000000000..c73b80321ee --- /dev/null +++ b/targets/TARGET_RASPBERRYPI/TARGET_RP2040/pico-sdk/rp2_common/pico_rand/rand.c @@ -0,0 +1,305 @@ +/* + * Copyright (c) 2022 Raspberry Pi (Trading) Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* xoroshiro128ss(), rotl(): + + Written in 2018 by David Blackman and Sebastiano Vigna (vigna@acm.org) + + To the extent possible under law, the author has dedicated all copyright + and related and neighboring rights to this software to the public domain + worldwide. This software is distributed without any warranty. + + See + + splitmix64() implementation: + + Written in 2015 by Sebastiano Vigna (vigna@acm.org) + To the extent possible under law, the author has dedicated all copyright + and related and neighboring rights to this software to the public domain + worldwide. This software is distributed without any warranty. + + See +*/ + +#include "pico/rand.h" +#if PICO_RAND_SEED_ENTROPY_SRC_BOARD_ID +#include "pico/unique_id.h" +#endif +#include "pico/time.h" +#include "hardware/clocks.h" +#include "hardware/structs/rosc.h" +#include "hardware/structs/bus_ctrl.h" +#include "hardware/sync.h" + +static bool rng_initialised = false; + +// Note: By design, do not initialise any of the variables that hold entropy, +// they may have useful junk in them, either from power-up or a previous boot. +static rng_128_t __uninitialized_ram(rng_state); +#if PICO_RAND_SEED_ENTROPY_SRC_RAM_HASH +static uint64_t __uninitialized_ram(ram_hash); +#endif + +#if PICO_RAND_ENTROPY_SRC_ROSC | PICO_RAND_SEED_ENTROPY_SRC_ROSC +static uint64_t __uninitialized_ram(rosc_samples); +#endif + +#if PICO_RAND_ENTROPY_SRC_BUS_PERF_COUNTER +static uint8_t bus_counter_idx; +#endif + +/* From the original source: + + This is a fixed-increment version of Java 8's SplittableRandom generator + See http://dx.doi.org/10.1145/2714064.2660195 and + http://docs.oracle.com/javase/8/docs/api/java/util/SplittableRandom.html + + It is a very fast generator passing BigCrush, and it can be useful if + for some reason you absolutely want 64 bits of state; otherwise, we + rather suggest to use a xoroshiro128+ (for moderately parallel + computations) or xorshift1024* (for massively parallel computations) + generator. + + Note: This can be called with any value (i.e. including 0) +*/ +static __noinline uint64_t splitmix64(uint64_t x) { + uint64_t z = x + 0x9E3779B97F4A7C15ull; + z = (z ^ (z >> 30)) * 0xBF58476D1CE4E5B9ull; + z = (z ^ (z >> 27)) * 0x94D049BB133111EBull; + return z ^ (z >> 31); +} + +/* From the original source: + + This is xoroshiro128** 1.0, one of our all-purpose, rock-solid, + small-state generators. It is extremely (sub-ns) fast and it passes all + tests we are aware of, but its state space is large enough only for + mild parallelism. + + For generating just floating-point numbers, xoroshiro128+ is even + faster (but it has a very mild bias, see notes in the comments). + + The state must be seeded so that it is not everywhere zero. If you have + a 64-bit seed, we suggest to seed a splitmix64 generator and use its + output to fill s. +*/ +static inline uint64_t rotl(const uint64_t x, int k) { + return (x << k) | (x >> (64 - k)); +} + +static __noinline uint64_t xoroshiro128ss(rng_128_t *local_rng_state) { + const uint64_t s0 = local_rng_state->r[0]; + uint64_t s1 = local_rng_state->r[1]; + + // Because the state is *modified* outside of this function, there is a + // 1 in 2^128 chance that it could be all zeroes (which is not allowed). + while (s0 == 0 && s1 == 0) { + s1 = time_us_64(); // should not be 0, but loop anyway + } + + const uint64_t result = rotl(s0 * 5, 7) * 9; + + s1 ^= s0; + local_rng_state->r[0] = rotl(s0, 24) ^ s1 ^ (s1 << 16); // a, b + local_rng_state->r[1] = rotl(s1, 37); // c + + return result; +} + +#if PICO_RAND_SEED_ENTROPY_SRC_RAM_HASH +static uint64_t sdbm_hash64_sram(uint64_t hash) { + // save some time by hashing a word at a time + for (uint i = (PICO_RAND_RAM_HASH_START + 3) & ~3; i < PICO_RAND_RAM_HASH_END; i+=4) { + uint32_t c = *(uint32_t *) i; + hash = (uint64_t) c + (hash << 6) + (hash << 16) - hash; + } + return hash; +} +#endif + +#if PICO_RAND_SEED_ENTROPY_SRC_ROSC | PICO_RAND_ENTROPY_SRC_ROSC +/* gather an additional n bits of entropy, and shift them into the 64 bit entropy counter */ +static uint64_t capture_additional_rosc_samples(uint n) { + static absolute_time_t next_sample_time; + + // provide an override if someone really wants it, but disabling ROSC as an entropy source makes more sense +#if !PICO_RAND_DISABLE_ROSC_CHECK + // check that the ROSC is running but that the processors are NOT running from it + hard_assert((rosc_hw->status & ROSC_STATUS_ENABLED_BITS) && + ((clocks_hw->clk[clk_sys].ctrl & CLOCKS_CLK_SYS_CTRL_AUXSRC_BITS) != (CLOCKS_CLK_SYS_CTRL_AUXSRC_VALUE_ROSC_CLKSRC << CLOCKS_CLK_SYS_CTRL_AUXSRC_LSB))); +#endif + + bool in_exception = __get_current_exception(); + assert(n); // save us having to special case samples for this + uint64_t samples = 0; + for(uint i=0; irandombit & 1u; + // use of relative time to now, rather than offset from before makes things + // a bit less predictable at the cost of some speed. + next_sample_time = make_timeout_time_us(PICO_RAND_MIN_ROSC_BIT_SAMPLE_TIME_US); + bit_done = true; + if (i == n - 1) { + // samples has our random bits, so let's mix them in now + samples = rosc_samples = (rosc_samples << n) | samples; + } + } + spin_unlock(lock, save); + } while (!bit_done); + } + return samples; +} +#endif + +static void initialise_rand(void) { + rng_128_t local_rng_state = local_rng_state; + uint which = 0; +#if PICO_RAND_SEED_ENTROPY_SRC_RAM_HASH + ram_hash = sdbm_hash64_sram(ram_hash); + local_rng_state.r[which] ^= splitmix64(ram_hash); + which ^= 1; +#endif + +#if PICO_RAND_SEED_ENTROPY_SRC_BOARD_ID + static_assert(PICO_UNIQUE_BOARD_ID_SIZE_BYTES == sizeof(uint64_t), + "Code below requires that 'board_id' is 64-bits in size"); + + // Note! The safety of the length assumption here is protected by a 'static_assert' above + union unique_id_u { + pico_unique_board_id_t board_id_native; + uint64_t board_id_u64; + } unique_id; + // Note! The safety of the length assumption here is protected by a 'static_assert' above + pico_get_unique_board_id(&unique_id.board_id_native); + local_rng_state.r[which] ^= splitmix64(unique_id.board_id_u64); + which ^= 1; +#endif + +#if PICO_RAND_SEED_ENTROPY_SRC_ROSC + // this is really quite slow (10ms per iteration), and I'm not sure that it adds value over the 64 random bits +// uint ref_khz = clock_get_hz(clk_ref) / 100; +// for (int i = 0; i < 5; i++) { +// // Apply hash of the rosc frequency, limited but still 'extra' entropy +// uint measurement = frequency_count_raw(CLOCKS_FC0_SRC_VALUE_ROSC_CLKSRC, ref_khz); +// local_rng_state.r[which] ^= splitmix64(measurement); +// (void) xoroshiro128ss(&local_rng_state); //churn to mix seed sources +// } + + // Gather a full ROSC sample array with sample bits + local_rng_state.r[which] ^= splitmix64(capture_additional_rosc_samples(8 * sizeof(rosc_samples))); + which ^= 1; +#endif + +#if PICO_RAND_SEED_ENTROPY_SRC_TIME + // Mix in hashed time. This is [possibly] predictable boot-to-boot + // but will vary application-to-application. + local_rng_state.r[which] ^= splitmix64(time_us_64()); + which ^= 1; +#endif + + spin_lock_t *lock = spin_lock_instance(PICO_SPINLOCK_ID_RAND); + uint32_t save = spin_lock_blocking(lock); + if (!rng_initialised) { +#if PICO_RAND_ENTROPY_SRC_BUS_PERF_COUNTER +#if !PICO_RAND_BUSCTRL_COUNTER_INDEX + int idx = -1; + for(uint i = 0; i < count_of(bus_ctrl_hw->counter); i++) { + if (bus_ctrl_hw->counter[i].sel == BUSCTRL_PERFSEL0_RESET) { + idx = (int)i; + break; + } + } + hard_assert(idx != -1); + bus_counter_idx = (uint8_t)idx; +#else + bus_counter_idx = (uint8_t)PICO_RAND_BUSCTRL_COUNTER_INDEX; +#endif + bus_ctrl_hw->counter[bus_counter_idx].sel = PICO_RAND_BUS_PERF_COUNTER_EVENT; +#endif + (void) xoroshiro128ss(&local_rng_state); + rng_state = local_rng_state; + rng_initialised = true; + } + spin_unlock(lock, save); +} + +uint64_t get_rand_64(void) { + if (!rng_initialised) { + // Do not provide 'RNs' until the system has been initialised. Note: + // The first initialisation can be quite time-consuming depending on + // the amount of RAM hashed, see RAM_HASH_START and RAM_HASH_END + initialise_rand(); + } + + static volatile uint8_t check_byte; + rng_128_t local_rng_state = rng_state; + uint8_t local_check_byte = check_byte; + // Modify PRNG state with the run-time entropy sources, + // hashed to reduce correlation with previous modifications. + uint which = 0; +#if PICO_RAND_ENTROPY_SRC_TIME + local_rng_state.r[which] ^= splitmix64(time_us_64()); + which ^= 1; +#endif +#if PICO_RAND_ENTROPY_SRC_ROSC + local_rng_state.r[which] ^= splitmix64(capture_additional_rosc_samples(PICO_RAND_ROSC_BIT_SAMPLE_COUNT)); + which ^= 1; +#endif +#if PICO_RAND_ENTROPY_SRC_BUS_PERF_COUNTER + uint32_t bus_counter_value = bus_ctrl_hw->counter[bus_counter_idx].value; + // counter is saturating, so clear it if it has reached saturation + if (bus_counter_value == BUSCTRL_PERFCTR0_BITS) { + bus_ctrl_hw->counter[bus_counter_idx].value = 0; + } + local_rng_state.r[which] ^= splitmix64(bus_counter_value); + which ^= 1; +#endif + + spin_lock_t *lock = spin_lock_instance(PICO_SPINLOCK_ID_RAND); + uint32_t save = spin_lock_blocking(lock); + if (local_check_byte != check_byte) { + // someone got a random number in the interim, so mix it in + local_rng_state.r[0] ^= rng_state.r[0]; + local_rng_state.r[1] ^= rng_state.r[1]; + } + // Generate a 64-bit RN from the modified PRNG state. + // Note: This also "churns" the 128-bit state for next time. + uint64_t rand64 = xoroshiro128ss(&local_rng_state); + rng_state = local_rng_state; + check_byte++; + spin_unlock(lock, save); + + return rand64; +} + +void get_rand_128(rng_128_t *ptr128) { + ptr128->r[0] = get_rand_64(); + ptr128->r[1] = get_rand_64(); +} + +uint32_t get_rand_32(void) { + return (uint32_t) get_rand_64(); +} diff --git a/targets/TARGET_RASPBERRYPI/TARGET_RP2040/trng_api.c b/targets/TARGET_RASPBERRYPI/TARGET_RP2040/trng_api.c new file mode 100644 index 00000000000..b0886badcc8 --- /dev/null +++ b/targets/TARGET_RASPBERRYPI/TARGET_RP2040/trng_api.c @@ -0,0 +1,64 @@ +/* mbed Microcontroller Library + * Copyright (c) 2018 GigaDevice Semiconductor Inc. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#if DEVICE_TRNG + +#include "trng_api.h" + +/** Initialize the TRNG peripheral + * + * @param obj The TRNG object + */ +void trng_init(trng_t *obj) +{ + (void)obj; +} + +/** Deinitialize the TRNG peripheral + * + * @param obj The TRNG object + */ +void trng_free(trng_t *obj) +{ + (void)obj; +} + +/** Get random data from TRNG peripheral + * + * @param obj The TRNG object + * @param output The pointer to an output array + * @param length The size of output data, to avoid buffer overwrite + * @param output_length The length of generated data + * @return 0 success, -1 fail + */ +int trng_get_bytes(trng_t *obj, uint8_t *output, size_t length, size_t *output_length) +{ + (void)obj; + *output_length = 0; + uint32_t random[16]; + + while (*output_length < length) { + get_rand_128((rng_128_t*)random); + for (uint8_t i = 0; (i < 16) && (*output_length < length) ; i++) { + *output++ = random[i]; + *output_length += 1; + random[i] = 0; + } + } + return 0; +} +#endif /* DEVICE_TRNG */ diff --git a/targets/TARGET_STM/TARGET_STM32H7/STM32Cube_FW/STM32H7xx_HAL_Driver/stm32h7xx_hal_eth.c b/targets/TARGET_STM/TARGET_STM32H7/STM32Cube_FW/STM32H7xx_HAL_Driver/stm32h7xx_hal_eth.c index decff79455a..df797092fc1 100644 --- a/targets/TARGET_STM/TARGET_STM32H7/STM32Cube_FW/STM32H7xx_HAL_Driver/stm32h7xx_hal_eth.c +++ b/targets/TARGET_STM/TARGET_STM32H7/STM32Cube_FW/STM32H7xx_HAL_Driver/stm32h7xx_hal_eth.c @@ -2341,13 +2341,7 @@ HAL_StatusTypeDef HAL_ETH_SetWakeUpFilter(ETH_HandleTypeDef *heth, uint32_t *pFi */ HAL_ETH_StateTypeDef HAL_ETH_GetState(ETH_HandleTypeDef *heth) { - HAL_ETH_StateTypeDef ret; - HAL_ETH_StateTypeDef gstate = heth->gState; - HAL_ETH_StateTypeDef rxstate =heth->RxState; - - ret = gstate; - ret |= rxstate; - return ret; + return heth->gState; } /** diff --git a/targets/TARGET_STM/TARGET_STM32H7/STM32Cube_FW/system_stm32h7xx_dualcore_boot_cm4_cm7.c b/targets/TARGET_STM/TARGET_STM32H7/STM32Cube_FW/system_stm32h7xx_dualcore_boot_cm4_cm7.c index b4a4cc78263..8e0017de2aa 100644 --- a/targets/TARGET_STM/TARGET_STM32H7/STM32Cube_FW/system_stm32h7xx_dualcore_boot_cm4_cm7.c +++ b/targets/TARGET_STM/TARGET_STM32H7/STM32Cube_FW/system_stm32h7xx_dualcore_boot_cm4_cm7.c @@ -232,7 +232,7 @@ __weak void SystemInit (void) /* Configure the Vector Table location add offset address ------------------*/ #ifdef VECT_TAB_SRAM SCB->VTOR = D2_AXISRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */ -#elif !defined(NO_VTOR_RELOCATE) +#else #include "nvic_addr.h" // MBED SCB->VTOR = NVIC_FLASH_VECTOR_ADDRESS; // MBED #endif diff --git a/targets/TARGET_STM/TARGET_STM32H7/TARGET_STM32H747xI/TARGET_GENERIC_STM32H747_M4/PinNames.h b/targets/TARGET_STM/TARGET_STM32H7/TARGET_STM32H747xI/TARGET_GENERIC_STM32H747_M4/PinNames.h index 97d48334d7f..04a34504a70 100644 --- a/targets/TARGET_STM/TARGET_STM32H7/TARGET_STM32H747xI/TARGET_GENERIC_STM32H747_M4/PinNames.h +++ b/targets/TARGET_STM/TARGET_STM32H7/TARGET_STM32H747xI/TARGET_GENERIC_STM32H747_M4/PinNames.h @@ -43,7 +43,7 @@ extern "C" { #endif -#define DUAL_PAD 0xF00 +#define DUAL_PAD 0x800 typedef enum { ALT0 = 0x100, diff --git a/targets/TARGET_STM/TARGET_STM32H7/TARGET_STM32H747xI/TARGET_NICLA_VISION/PinNames.h b/targets/TARGET_STM/TARGET_STM32H7/TARGET_STM32H747xI/TARGET_NICLA_VISION/PinNames.h index 9f14a66d67e..42d24cd79d2 100644 --- a/targets/TARGET_STM/TARGET_STM32H7/TARGET_STM32H747xI/TARGET_NICLA_VISION/PinNames.h +++ b/targets/TARGET_STM/TARGET_STM32H7/TARGET_STM32H747xI/TARGET_NICLA_VISION/PinNames.h @@ -467,6 +467,11 @@ typedef enum { NC = (int)0xFFFFFFFF } PinName; +// Standardized LED and button names +#define LED1 LED_RED +#define LED2 LED_GREEN +#define LED3 LED_BLUE + #ifdef __cplusplus } #endif diff --git a/targets/TARGET_STM/TARGET_STM32H7/TARGET_STM32H747xI/TARGET_STM32H747xI_CM4/TOOLCHAIN_GCC_ARM/stm32h747xI_CM4.ld b/targets/TARGET_STM/TARGET_STM32H7/TARGET_STM32H747xI/TARGET_STM32H747xI_CM4/TOOLCHAIN_GCC_ARM/stm32h747xI_CM4.ld index ea81a18b117..7d2651dcb48 100644 --- a/targets/TARGET_STM/TARGET_STM32H7/TARGET_STM32H747xI/TARGET_STM32H747xI_CM4/TOOLCHAIN_GCC_ARM/stm32h747xI_CM4.ld +++ b/targets/TARGET_STM/TARGET_STM32H7/TARGET_STM32H747xI/TARGET_STM32H747xI_CM4/TOOLCHAIN_GCC_ARM/stm32h747xI_CM4.ld @@ -38,10 +38,16 @@ MEMORY { FLASH (rx) : ORIGIN = MBED_APP_START, LENGTH = MBED_APP_SIZE - RAM (rwx) : ORIGIN = MBED_RAM_START + VECTORS_SIZE, LENGTH = MBED_RAM_SIZE - VECTORS_SIZE + RAM_D2 (rwx) : ORIGIN = MBED_RAM_START + VECTORS_SIZE, LENGTH = MBED_RAM_SIZE - VECTORS_SIZE RAM_D3 (xrw) : ORIGIN = 0x38000000, LENGTH = 64K } +#if (CM4_BINARY_START == 0x60000000) +REGION_ALIAS("RAM", FLASH); +#else +REGION_ALIAS("RAM", RAM_D2); +#endif + /* Linker script to place sections and symbol values. Should be used together * with other linker script that defines memory regions FLASH and RAM. * It references following symbols, which must be defined in code: diff --git a/targets/TARGET_STM/tools/STM32_gen_PeripheralPins.py b/targets/TARGET_STM/tools/STM32_gen_PeripheralPins.py index 44a95f9c023..903ce5f7e0b 100644 --- a/targets/TARGET_STM/tools/STM32_gen_PeripheralPins.py +++ b/targets/TARGET_STM/tools/STM32_gen_PeripheralPins.py @@ -491,7 +491,7 @@ def print_header(): if DUAL_PAD: line_to_write = (""" -#define DUAL_PAD 0xF00 +#define DUAL_PAD 0x800 """) out_h_file.write(line_to_write) diff --git a/targets/targets.json b/targets/targets.json index 9a124223369..83fa8c930a3 100644 --- a/targets/targets.json +++ b/targets/targets.json @@ -9700,7 +9700,8 @@ "USTICKER", "WATCHDOG", "USBDEVICE", - "RESET_REASON" + "RESET_REASON", + "TRNG" ] }, "NANO_RP2040_CONNECT": {