Merge pull request #15123 from jeromecoutant/PR_MXCHIP

STM32: introduce new wifi driver for B-U585I-IOT02A
pull/15127/head
Martin Kojtal 2021-10-04 09:43:40 +02:00 committed by GitHub
commit 6a9ccb3aa3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
32 changed files with 9580 additions and 0 deletions

View File

@ -7,6 +7,7 @@
^connectivity/drivers/emac
^connectivity/drivers/mbedtls
^connectivity/drivers/wifi/COMPONENT_WHD
^connectivity/drivers/wifi/TARGET_STM/COMPONENT_EMW3080B/mx_wifi
^connectivity/mbedtls
^features/frameworks
^connectivity/lwipstack/lwip

View File

@ -3,6 +3,8 @@
add_subdirectory(TARGET_WICED EXCLUDE_FROM_ALL)
add_subdirectory(TARGET_STM EXCLUDE_FROM_ALL)
add_subdirectory(COMPONENT_WHD EXCLUDE_FROM_ALL)
add_subdirectory(esp8266-driver)

View File

@ -0,0 +1,6 @@
# Copyright (c) 2020-2021 ARM Limited. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
if("EMW3080B" IN_LIST MBED_TARGET_LABELS)
add_subdirectory(COMPONENT_EMW3080B EXCLUDE_FROM_ALL)
endif()

View File

@ -0,0 +1,25 @@
# Copyright (c) 2020 ARM Limited. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
add_library(wifi-EMW3080B INTERFACE)
target_include_directories(mbed-wifi
INTERFACE
.
mx_wifi
mx_wifi/core
)
target_sources(mbed-wifi
INTERFACE
EMW3080BInterface.cpp
EMW3080B_EMAC.cpp
EMW3080B_UART.cpp
EMW3080B_SPI.cpp
mx_wifi_mbed_os.cpp
mx_wifi/mx_wifi.c
mx_wifi/core/checksumutils.c
mx_wifi/core/mx_wifi_hci.c
mx_wifi/core/mx_wifi_ipc.c
mx_wifi/core/mx_wifi_slip.c
)

View File

@ -0,0 +1,367 @@
/*
* Copyright (c) STMicroelectronics 2021
* 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.
*/
/* Includes ------------------------------------------------------------------*/
/* Private includes ----------------------------------------------------------*/
#include "EMW3080BInterface.h"
#if MX_WIFI_USE_SPI
#include "EMW3080B_SPI.h"
#else
#include "EMW3080B_UART.h"
#endif
#define DEBUG_SILENT 0
#define DEBUG_WARNING 1
#define DEBUG_INFO 2
#define DEBUG_LOG 3
#define DEFAULT_DEBUG DEBUG_SILENT
static EMW3080BInterface *emw3080b_object;
#if MX_WIFI_USE_SPI
static EMW3080B_SPI *emw3080b_protocol_context;
#else
static EMW3080B_UART *emw3080b_protocol_context;
#endif
static bool deepsleep_locked = false;
EMW3080BInterface::EMW3080BInterface(bool debug,
PinName mosi,
PinName miso,
PinName sclk,
PinName nss,
PinName notify,
PinName flow,
PinName reset,
PinName tx,
PinName rx,
EMAC &emac,
OnboardNetworkStack &stack
) : EMACInterface(emac, stack), _ssid(""), _isConnected(false)
{
emw3080b_object = this;
#if MX_WIFI_USE_SPI
emw3080b_protocol_context = new EMW3080B_SPI(debug, mosi, miso, sclk, nss, notify, flow, reset);
#else
emw3080b_protocol_context = new EMW3080B_UART(debug, tx, rx, reset);
#endif
if (debug) {
_debug_level = DEBUG_LOG;
} else {
_debug_level = DEFAULT_DEBUG;
}
probe();
}
int8_t IO_Init_static(uint16_t mode)
{
return emw3080b_protocol_context->IO_Init(mode);
}
int8_t IO_DeInit_static(void)
{
return emw3080b_protocol_context->IO_DeInit();
}
void IO_Delay_static(uint32_t delayms)
{
return emw3080b_protocol_context->IO_Delay(delayms);
}
uint16_t IO_Send_static(uint8_t *data, uint16_t len)
{
return emw3080b_protocol_context->IO_Send(data, len);
}
uint16_t IO_Receive_static(uint8_t *buffer, uint16_t buff_size)
{
return emw3080b_protocol_context->IO_Receive(buffer, buff_size);
}
MX_WIFIObject_t *wifi_obj_get(void)
{
if (emw3080b_object) {
return &emw3080b_object->MxWifiObj;
} else {
error("MxWifiObj is not initialized");
}
}
void EMW3080BInterface::probe(void)
{
if (MX_WIFI_RegisterBusIO(&MxWifiObj,
IO_Init_static,
IO_DeInit_static,
IO_Delay_static,
IO_Send_static,
IO_Receive_static) != 0) {
debug_if(_debug_level >= DEBUG_LOG, "EMW3080BInterface : MX_WIFI_RegisterBusIO failed \n");
return;
}
if (MX_WIFI_HardResetModule(&MxWifiObj)) {
debug_if(_debug_level >= DEBUG_WARNING, "EMW3080BInterface : MX_WIFI_HardResetModule failed \n");
return ;
}
/* wait for mxchip wifi reboot */
rtos::ThisThread::sleep_for(800ms);
if (MX_WIFI_Init(&MxWifiObj)) {
error("EMW3080BInterface : MX_WIFI_Init failed, you may have to update MXCHIP fimrware module to version 2.1.11\n");
}
debug_if(_debug_level >= DEBUG_INFO, "EMW3080BInterface : Product name: %s\n", MxWifiObj.SysInfo.Product_Name);
debug_if(_debug_level >= DEBUG_INFO, "EMW3080BInterface : Product ID: %s\n", MxWifiObj.SysInfo.Product_ID);
debug_if(_debug_level >= DEBUG_INFO, "EMW3080BInterface : FW revision: %s\n", MxWifiObj.SysInfo.FW_Rev);
debug_if(_debug_level >= DEBUG_INFO, "EMW3080BInterface : MAC %02x.%02x.%02x.%02x.%02x.%02x\n\n", MxWifiObj.SysInfo.MAC[0], MxWifiObj.SysInfo.MAC[1], MxWifiObj.SysInfo.MAC[2], MxWifiObj.SysInfo.MAC[3], MxWifiObj.SysInfo.MAC[4], MxWifiObj.SysInfo.MAC[5]);
}
void EMW3080BInterface::release(void)
{
return;
}
int EMW3080BInterface::set_credentials(const char *ssid, const char *pass, nsapi_security_t security)
{
if ((ssid == NULL) || (strlen(ssid) == 0) || (strlen(ssid) > 32)) {
debug_if(_debug_level >= DEBUG_WARNING, "EMW3080BInterface : bad credential\n");
return NSAPI_ERROR_PARAMETER;
}
if (security != NSAPI_SECURITY_NONE) {
if ((pass == NULL) || (strcmp(pass, "") == 0) || (strlen(pass) > 63)) {
debug_if(_debug_level >= DEBUG_WARNING, "EMW3080BInterface : bad security\n");
return NSAPI_ERROR_PARAMETER;
}
}
_mutex.lock();
memset(_ssid, 0, sizeof(_ssid));
strncpy(_ssid, ssid, sizeof(_ssid));
memset(_pass, 0, sizeof(_pass));
if (security != NSAPI_SECURITY_NONE) {
strncpy(_pass, pass, sizeof(_pass));
}
_sec = nsapi_sec2emw_sec(security);
_mutex.unlock();
debug_if(_debug_level >= DEBUG_LOG, "EMW3080BInterface : set credential OK %s %s \n", _ssid, _pass);
return NSAPI_ERROR_OK;
}
nsapi_error_t EMW3080BInterface::connect(const char *ssid, const char *pass, nsapi_security_t security,
uint8_t channel)
{
nsapi_error_t ret;
if (channel != 0) {
debug_if(_debug_level >= DEBUG_WARNING, "EMW3080BInterface : connect bad channel value, only 0 is supported\n");
ret = NSAPI_ERROR_UNSUPPORTED;
} else {
_mutex.lock();
nsapi_error_t credentials_status = set_credentials(ssid, pass, security);
_mutex.unlock();
if (credentials_status) {
debug_if(_debug_level >= DEBUG_WARNING, "EMW3080BInterface : connect unable to set credential\n");
ret = credentials_status;
} else {
ret = connect();
}
}
return ret;
}
nsapi_error_t EMW3080BInterface::connect()
{
nsapi_error_t ret ;
_mutex.lock();
/* Disable deepsleep as wakeup latency is too high */
if (!deepsleep_locked) {
deepsleep_locked = true;
sleep_manager_lock_deep_sleep();
}
MxWifiObj.NetSettings.DHCP_IsEnabled = true;
if (_ssid[0] == '\0') {
debug_if(_debug_level >= DEBUG_WARNING, "EMW3080BInterface : connect , ssid is missing\n");
ret = NSAPI_ERROR_NO_SSID;
} else if (_isConnected) {
debug_if(_debug_level >= DEBUG_WARNING, "EMW3080BInterface : connect is already connected\n");
ret = NSAPI_ERROR_IS_CONNECTED;
} else {
debug_if(_debug_level >= DEBUG_INFO, "EMW3080BInterface : connecting MX_WIFI\n");
if (MX_WIFI_Connect(
&MxWifiObj,
_ssid,
_pass,
_sec)) {
debug_if(_debug_level >= DEBUG_WARNING, "EMW3080BInterface : Connect failed; wrong parameter ?\n");
ret = NSAPI_ERROR_PARAMETER ;
} else {
// FIXME : MX_WIFI_Connect command needs to allocate a netbuffer to store the module answer (zero copy mechanism)
// potential issue is that netbuffer allocation is not ready because part of the EMAC class connect phase
debug_if(_debug_level >= DEBUG_INFO, "EMW3080BInterface : connecting EMAC\n");
ret = EMACInterface::connect();
/* EMAC is waiting for UP conection , UP means we join an hotspot and IP services running */
if (ret == NSAPI_ERROR_OK || ret == NSAPI_ERROR_IS_CONNECTED) {
debug_if(_debug_level >= DEBUG_LOG, "EMW3080BInterface : Connected to emac! (using ssid %s , passw %s )\n", _ssid, _pass);
_isConnected = true;
ret = NSAPI_ERROR_OK;
} else {
debug_if(_debug_level >= DEBUG_WARNING, "EMW3080BInterface : EMAC Fail to connect NSAPI_ERROR %d\n", ret);
(void) MX_WIFI_Disconnect(&MxWifiObj);
EMACInterface::disconnect();
ret = NSAPI_ERROR_CONNECTION_TIMEOUT;
}
}
}
_mutex.unlock();
return ret;
}
nsapi_error_t EMW3080BInterface::disconnect()
{
nsapi_error_t ret ;
_mutex.lock();
if (_isConnected == false) {
ret = NSAPI_ERROR_NO_CONNECTION;
} else {
debug_if(_debug_level >= DEBUG_INFO, "EMW3080BInterface : disconnecting MX_WIFI and EMAC\n");
if (MX_WIFI_Disconnect(&MxWifiObj)) {
debug_if(_debug_level >= DEBUG_WARNING, "MXWIFI disconnect command failed\n");
ret = NSAPI_ERROR_DEVICE_ERROR;
} else {
ret = NSAPI_ERROR_OK;
}
_isConnected = false;
EMACInterface::disconnect();
}
if (deepsleep_locked) {
deepsleep_locked = false;
sleep_manager_unlock_deep_sleep();
}
_mutex.unlock();
return ret;
}
int8_t EMW3080BInterface::get_rssi()
{
_mutex.lock();
int8_t ret = 0;
if (_isConnected) {
uint32_t count;
debug_if(_debug_level >= DEBUG_INFO, "EMW3080BInterface : Perform a scan for RSSI\n");
MX_WIFI_Scan(&MxWifiObj, MC_SCAN_ACTIVE, (char *)&_ssid[0], strlen(_ssid));
count = MX_WIFI_Get_scan_result(&MxWifiObj, (uint8_t *) _ap_info, MAX_AP_COUNT);
if (count == 0) {
debug_if(_debug_level >= DEBUG_WARNING, "EMW3080BInterface : Get RSSI , scan did not find HotSpot %s\n", _ssid);
} else {
if (count > 1) {
debug_if(_debug_level >= DEBUG_WARNING, "EMW3080BInterface : Get RSSI , scan find several HotSpot named %s, return strenght of first one\n", _ssid);
}
ret = _ap_info[0].rssi;
}
}
_mutex.unlock();
debug_if(_debug_level >= DEBUG_INFO, "EMW3080BInterface : Get RSSI return %d\n", ret);
return ret;
}
int EMW3080BInterface::scan(WiFiAccessPoint *res, unsigned int count)
{
_mutex.lock();
if (count == 0) {
return MAX_AP_COUNT;
} else {
if (count > MAX_AP_COUNT) {
count = MAX_AP_COUNT;
}
MX_WIFI_Scan(&MxWifiObj, MC_SCAN_PASSIVE, NULL, 0);
count = MX_WIFI_Get_scan_result(&MxWifiObj, (uint8_t *) _ap_info, count);
debug_if(_debug_level >= DEBUG_INFO, "EMW3080BInterface : Scan find %d HotSpot\n", count);
if (res != NULL) {
for (uint32_t i = 0; i < count ; i++) {
nsapi_wifi_ap_t ap;
debug_if(_debug_level >= DEBUG_LOG, "EMW3080BInterface : %" PRIu32 " SSID %s rssi %" PRIu32 "\n", i, _ap_info[i].ssid, _ap_info[i].rssi);
debug_if(_debug_level >= DEBUG_LOG, "EMW3080BInterface : BSSID %hhx:%hhx:%hhx:%hhx:%hhx:%hhx\n", _ap_info[i].bssid[0], _ap_info[i].bssid[1], _ap_info[i].bssid[2], _ap_info[i].bssid[3], _ap_info[i].bssid[4], _ap_info[i].bssid[5]);
memcpy(ap.ssid, _ap_info[i].ssid, 33);
memcpy(ap.bssid, _ap_info[i].bssid, 6);
ap.security = emw_sec2nsapi_sec(_ap_info[i].security);
ap.rssi = _ap_info[i].rssi;
ap.channel = _ap_info[i].channel;
res[i] = WiFiAccessPoint(ap);
}
}
}
_mutex.unlock();
return (int) count;
}
#if MBED_CONF_EMW3080B_PROVIDE_DEFAULT
WiFiInterface *WiFiInterface::get_default_instance()
{
static EMW3080BInterface emw;
return &emw;
}
#endif /* MBED_CONF_EMW3080B_PROVIDE_DEFAULT */
#if defined(MBED_CONF_NSAPI_PRESENT)
WiFiInterface *WiFiInterface::get_target_default_instance()
{
#if (DEFAULT_DEBUG == DEBUG_LOG)
printf("get_target_default_instance\n");
#endif /* MBED_CONF_NSAPI_PRESENT */
static EMW3080BInterface wifi;
return &wifi;
}
#endif /* MBED_CONF_NSAPI_PRESENT */

View File

@ -0,0 +1,207 @@
/* EMW3080B implementation of NetworkInterfaceAPI
* Copyright (c) STMicroelectronics 2021
* 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.
*/
#ifndef EMW3080B_INTERFACE_H
#define EMW3080B_INTERFACE_H
#if defined(MBED_CONF_NSAPI_PRESENT)
#include <inttypes.h>
#include "mbed.h"
#include "mbed_debug.h"
#include "mx_wifi.h"
#include "netsocket/WiFiInterface.h"
#include "netsocket/EMACInterface.h"
#include "netsocket/OnboardNetworkStack.h"
#include "EMW3080B_EMAC.h"
/** EMW3080BInterface class
* Implementation of the NetworkStack for the EMW3080B
*/
class EMW3080BInterface : public WiFiInterface, public EMACInterface {
public:
EMW3080BInterface(bool debug = MBED_CONF_EMW3080B_WIFI_DEBUG,
PinName mosi = MBED_CONF_EMW3080B_WIFI_MOSI,
PinName miso = MBED_CONF_EMW3080B_WIFI_MISO,
PinName sclk = MBED_CONF_EMW3080B_WIFI_SCLK,
PinName nss = MBED_CONF_EMW3080B_WIFI_NSS,
PinName notify = MBED_CONF_EMW3080B_WIFI_NOTIFY,
PinName flow = MBED_CONF_EMW3080B_WIFI_FLOW,
PinName reset = MBED_CONF_EMW3080B_WIFI_RESET,
PinName tx = MBED_CONF_EMW3080B_WIFI_TX,
PinName rx = MBED_CONF_EMW3080B_WIFI_RX,
EMAC &emac = EMW3080B_EMAC::get_instance(),
OnboardNetworkStack &stack = OnboardNetworkStack::get_default_instance()
);
/** Start the interface
*
* Attempts to connect to a WiFi network. Requires ssid and passphrase to be set.
* If passphrase is invalid, NSAPI_ERROR_AUTH_ERROR is returned.
*
* @return 0 on success, negative error code on failure
*/
nsapi_error_t connect();
/** Start the interface
*
* Attempts to connect to a WiFi network.
*
* @param ssid Name of the network to connect to
* @param pass Security passphrase to connect to the network
* @param security Type of encryption for connection (Default: NSAPI_SECURITY_NONE)
* @param channel This parameter is not supported, setting it to anything else than 0 will result in NSAPI_ERROR_UNSUPPORTED
* @return 0 on success, or error code on failure
*/
nsapi_error_t connect(const char *ssid, const char *pass, nsapi_security_t security = NSAPI_SECURITY_NONE, uint8_t channel = 0);
/** Stop the interface
* @return 0 on success, negative on failure
*/
nsapi_error_t disconnect();
/** Set the WiFi network credentials
*
* @param ssid Name of the network to connect to
* @param pass Security passphrase to connect to the network
* @param security Type of encryption for connection
* (defaults to NSAPI_SECURITY_NONE)
* @return 0 on success, or error code on failure
*/
nsapi_error_t set_credentials(const char *ssid, const char *pass, nsapi_security_t security = NSAPI_SECURITY_NONE);
/** Set the WiFi network channel - NOT SUPPORTED
*
* This function is not supported and will return NSAPI_ERROR_UNSUPPORTED
*
* @param channel Channel on which the connection is to be made, or 0 for any (Default: 0)
* @return Not supported, returns NSAPI_ERROR_UNSUPPORTED
*/
nsapi_error_t set_channel(uint8_t channel)
{
if (channel != 0) {
return NSAPI_ERROR_UNSUPPORTED;
}
return 0;
}
/** Gets the current radio signal strength for active connection
*
* @return Connection strength in dBm (negative value)
*/
int8_t get_rssi();
/** Scan for available networks
*
* This function will block.
*
* @param ap Pointer to allocated array to store discovered AP
* @param count Size of allocated @a res array, or 0 to only count available AP
* @param timeout Timeout in milliseconds; 0 for no timeout (Default: 0)
* @return Number of entries in @a, or if @a count was 0 number of available networks, negative on error
* see @a nsapi_error
*/
int scan(WiFiAccessPoint *res, unsigned count);
MX_WIFIObject_t MxWifiObj;
private:
nsapi_security_t emw_sec2nsapi_sec(mwifi_security_t sec)
{
nsapi_security_t sec_out;
switch (sec) {
case MX_WIFI_SEC_NONE:
sec_out = NSAPI_SECURITY_NONE;
break;
case MX_WIFI_SEC_WEP:
sec_out = NSAPI_SECURITY_WEP;
break;
case MX_WIFI_SEC_WPA_AES:
case MX_WIFI_SEC_WPA_TKIP:
sec_out = NSAPI_SECURITY_WPA;
break;
case MX_WIFI_SEC_WPA2_AES:
case MX_WIFI_SEC_WPA2_TKIP:
case MX_WIFI_SEC_WPA2_MIXED:
sec_out = NSAPI_SECURITY_WPA2;
break;
case MX_WIFI_SEC_AUTO:
sec_out = NSAPI_SECURITY_WPA_WPA2;
break;
default:
sec_out = NSAPI_SECURITY_WPA_WPA2;
break;
}
return sec_out;
}
MX_WIFI_SecurityType_t nsapi_sec2emw_sec(nsapi_security_t sec)
{
MX_WIFI_SecurityType_t mx_sec;
switch (sec) {
case NSAPI_SECURITY_NONE:
mx_sec = MX_WIFI_SEC_NONE;
break;
case NSAPI_SECURITY_WEP:
mx_sec = MX_WIFI_SEC_WEP;
break;
case NSAPI_SECURITY_WPA:
mx_sec = MX_WIFI_SEC_WPA_AES;
break;
case NSAPI_SECURITY_WPA2:
mx_sec = MX_WIFI_SEC_WPA2_AES;
break;
default:
mx_sec = MX_WIFI_SEC_AUTO;
break;
}
return mx_sec;
}
/* MXCHIP array size for SCAN is 2KB , so limits number of AP to 20 */
#define MAX_AP_COUNT 20
int8_t IO_Init(uint16_t mode);
int8_t IO_DeInit(void);
void IO_Delay(uint32_t delayms);
uint16_t IO_Send(uint8_t *data, uint16_t len);
uint16_t IO_Receive(uint8_t *buffer, uint16_t buff_size);
void probe(void);
void release(void);
char _ssid[33]; /* The longest possible name (defined in 802.11) +1 for the \0 */
char _pass[64]; /* The longest allowed passphrase + 1 */
mwifi_ap_info_t _ap_info[MAX_AP_COUNT];
MX_WIFI_SecurityType_t _sec;
volatile bool _isConnected;
Mutex _mutex;
uint8_t _debug_level;
};
#endif /* MBED_CONF_NSAPI_PRESENT */
#endif /* EMW3080B_INTERFACE_H */

View File

@ -0,0 +1,336 @@
/*
* Copyright (c) STMicroelectronics 2021
* 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.
*/
#include "EMW3080B_EMAC.h"
#include "mx_wifi_ipc.h"
#include "lwip/etharp.h"
#include "lwip/ethip6.h"
#define DEBUG_SILENT 0
#define DEBUG_WARNING 1
#define DEBUG_INFO 2
#define DEBUG_LOG 3
#define DEFAULT_DEBUG DEBUG_SILENT
EMW3080B_EMAC::EMW3080B_EMAC()
{
_debug_level = DEFAULT_DEBUG;
}
uint32_t EMW3080B_EMAC::get_mtu_size() const
{
debug_if(_debug_level >= DEBUG_INFO, "EMW3080B_EMAC : get_mtu_size %d\n", MX_WIFI_MTU_SIZE);
return MX_WIFI_MTU_SIZE;
}
uint32_t EMW3080B_EMAC::get_align_preference() const
{
debug_if(_debug_level >= DEBUG_INFO, "EMW3080B_EMAC : get_align_preference 0\n");
return 0;
}
void EMW3080B_EMAC::add_multicast_group(const uint8_t *addr)
{
debug_if(_debug_level >= DEBUG_WARNING, "EMW3080B_EMAC : add_multicast_group is not supported\n");
}
void EMW3080B_EMAC::remove_multicast_group(const uint8_t *addr)
{
debug_if(_debug_level >= DEBUG_WARNING, "EMW3080B_EMAC : remove_multicast_group is not supported\n");
}
void EMW3080B_EMAC::set_all_multicast(bool all)
{
debug_if(_debug_level >= DEBUG_WARNING, "EMW3080B_EMAC : set_all_multicast not supported\n");
/* No-op at this stage */
}
void EMW3080B_EMAC::power_down()
{
debug_if(_debug_level >= DEBUG_INFO, "EMW3080B_EMAC : power_down\n");
}
bool EMW3080B_EMAC::power_up()
{
debug_if(_debug_level >= DEBUG_INFO, "EMW3080B_EMAC : power_up\n");
return true;
}
bool EMW3080B_EMAC::get_hwaddr(uint8_t *addr) const
{
bool ret;
debug_if(_debug_level >= DEBUG_INFO, "EMW3080B_EMAC : get_hwaddr\n");
MX_WIFIObject_t *pMxWifiObj = wifi_obj_get();
if (pMxWifiObj) {
addr[0] = pMxWifiObj->SysInfo.MAC[0];
addr[1] = pMxWifiObj->SysInfo.MAC[1];
addr[2] = pMxWifiObj->SysInfo.MAC[2];
addr[3] = pMxWifiObj->SysInfo.MAC[3];
addr[4] = pMxWifiObj->SysInfo.MAC[4];
addr[5] = pMxWifiObj->SysInfo.MAC[5];
ret = true;
} else {
ret = false;
}
return ret;
}
void EMW3080B_EMAC::set_hwaddr(const uint8_t *addr)
{
debug_if(_debug_level >= DEBUG_WARNING, "EMW3080B_EMAC : set_hwaddr ignoring this command ,not possible to set MAC address for MXCHIP device\n");
}
uint8_t EMW3080B_EMAC::get_hwaddr_size() const
{
debug_if(_debug_level >= DEBUG_INFO, "EMW3080B_EMAC : get_hwaddr_size %u\n", EMW3080B_HWADDR_SIZE);
return EMW3080B_HWADDR_SIZE;
}
static void emac_data_callback(mx_buf_t *buffer, void *user_args)
{
/* to retrieve the C++ class */
EMW3080B_EMAC emac = EMW3080B_EMAC::get_instance();
emac.mx_wifi_netlink_input_callback(buffer);
}
void EMW3080B_EMAC::set_link_input_cb(emac_link_input_cb_t input_cb)
{
debug_if(_debug_level >= DEBUG_INFO, "EMW3080B_EMAC : set_link_input_cb\n");
if (MX_WIFI_STATUS_OK != MX_WIFI_Network_bypass_mode_set(wifi_obj_get(), 1, emac_data_callback, NULL)) {
error("EMW3080B_EMAC : can not set set_link_input_cb\n");
} else {
_emac_input_data_cb = input_cb;
}
}
extern "C" {
void emac_status_changed(uint8_t cate, uint8_t status, void *arg)
{
/* to retrieve the C++ class */
EMW3080B_EMAC emac = EMW3080B_EMAC::get_instance();
emac.mx_wifi_status_changed(cate, status, arg);
}
}
void EMW3080B_EMAC::mx_wifi_status_changed(uint8_t cate, uint8_t status, void *arg)
{
bool mx_wifi_driver_up;
if ((uint8_t)MC_STATION == cate) {
switch (status) {
case MWIFI_EVENT_STA_DOWN:
mx_wifi_driver_up = false;
break;
case MWIFI_EVENT_STA_UP:
mx_wifi_driver_up = true;
break;
default:
debug_if(_debug_level >= DEBUG_WARNING, "EMW3080B_EMAC : mx_wifi_status_changed get unknown Event from EMW3080B\n");
mx_wifi_driver_up = false;
break;
}
debug_if(_debug_level >= DEBUG_INFO, "EMW3080B_EMAC : Interface is %s (calling)\n", mx_wifi_driver_up ? "UP" : "DOWN");
if (_emac_link_state_cb) {
_emac_link_state_cb(mx_wifi_driver_up);
}
} else if ((uint8_t)MC_SOFTAP == cate) {
switch (status) {
case MWIFI_EVENT_AP_DOWN:
break;
case MWIFI_EVENT_AP_UP:
break;
default:
break;
}
} else {
/* nothing */
}
}
void EMW3080B_EMAC::set_link_state_cb(emac_link_state_change_cb_t state_cb)
{
_emac_link_state_cb = state_cb;
if (MX_WIFI_RegisterStatusCallback_if(
wifi_obj_get(),
emac_status_changed,
NULL /* void * arg */,
(mwifi_if_t)MC_STATION)) {
debug_if(_debug_level >= DEBUG_WARNING, "EMW3080B_EMAC : Fail to register callback\n");
return ;
}
}
EMACMemoryManager *emac3080b_global_memory_manager = NULL;
void EMW3080B_EMAC::set_memory_manager(EMACMemoryManager &mem_mngr)
{
debug_if(_debug_level >= DEBUG_INFO, "EMW3080B_EMAC : set_memory_manager\n");
_memory_manager = &mem_mngr;
emac3080b_global_memory_manager = &mem_mngr;
}
#define EMW_PROTOCOL_HEADROOM sizeof(wifi_bypass_out_cparams_t)
bool EMW3080B_EMAC::link_out(emac_mem_buf_t *buf)
{
bool ret = true;
emac_mem_buf_t *q;
uint32_t m = 0;
uint32_t len = 0;
int32_t mx_ret;
#if MX_WIFI_TX_BUFFER_NO_COPY
for (q = buf; q != NULL; q = _memory_manager->get_next(q)) {
len += _memory_manager->get_len(q);
}
mx_buf_t *net = mx_buf_alloc(len + EMW_PROTOCOL_HEADROOM);
if (net != NULL) {
MX_NET_BUFFER_HIDE_HEADER(net, EMW_PROTOCOL_HEADROOM);
MX_NET_BUFFER_SET_PAYLOAD_SIZE(net, len);
uint8_t *payload = MX_NET_BUFFER_PAYLOAD(net);
for (q = buf; q != NULL; q = _memory_manager->get_next(q)) {
memcpy(payload, _memory_manager->get_ptr(q), _memory_manager->get_len(q));
payload += _memory_manager->get_len(q);
debug_if(_debug_level >= DEBUG_LOG, "EMW3080B_EMAC : TX seg %" PRIu32 " %" PRIu32 " bytes\n", m, _memory_manager->get_len(q));
m++;
}
debug_if(_debug_level >= DEBUG_LOG, "EMW3080B_EMAC : %" PRIu32 " TX %" PRIu32 "\n", m, MX_NET_BUFFER_GET_PAYLOAD_SIZE(net));
mx_ret = MX_WIFI_Network_bypass_netlink_output(
wifi_obj_get(),
MX_NET_BUFFER_PAYLOAD(net),
MX_NET_BUFFER_GET_PAYLOAD_SIZE(net),
STATION_IDX
);
debug_if(_debug_level >= DEBUG_LOG, "EMW3080B_EMAC : TX done lust e zero %" PRIu32 "\n", mx_ret);
MX_NET_BUFFER_FREE(net);
if (mx_ret != MX_WIFI_STATUS_OK) {
debug_if(_debug_level >= DEBUG_WARNING, "EMW3080B_EMAC : link_out : failed to send buffer\n");
ret = false;
}
#else
/* copy is managed internally */
ret = MX_WIFI_Network_bypass_netlink_output(
wifi_obj_get(),
_memory_manager->get_ptr(q),
_memory_manager->get_len(q),
STATION_IDX
);
#endif /* MX_WIFI_TX_BUFFER_NO_COPY */
} else
{
error("EMW3080B_EMAC : unable to allocate %" PRIu32 " bytes\n", len);
}
_memory_manager->free(buf);
return ret;
}
void EMW3080B_EMAC::get_ifname(char *name, uint8_t size) const
{
debug_if(_debug_level >= DEBUG_INFO, "EMW3080B_EMAC : get_ifname\n");
if (size > 0) {
strncpy(name, "st", size - 1);
name[size - 1] = '\0';
}
}
EMW3080B_EMAC &EMW3080B_EMAC::get_instance()
{
static EMW3080B_EMAC emac;
return emac;
}
void EMW3080B_EMAC::mx_wifi_netlink_input_callback(mx_buf_t *buffer)
{
struct eth_hdr *ethernet_header;
uint16_t ethertype;
uint32_t len = 0U;
if (buffer != NULL) {
len = MX_NET_BUFFER_GET_PAYLOAD_SIZE(buffer);
if ((len > 0U) && (len <= (uint32_t) MX_WIFI_MTU_SIZE)) {
/* points to packet payload, which starts with an Ethernet header */
ethernet_header = (struct eth_hdr *) MX_NET_BUFFER_PAYLOAD(buffer);
ethertype = lwip_htons(ethernet_header->type);
switch (ethertype) {
case ETHTYPE_IP:
/* case ETHTYPE_IPV6: */
case ETHTYPE_ARP:
/* PPPoE packet */
case ETHTYPE_PPPOEDISC:
case ETHTYPE_PPPOE: {
debug_if(_debug_level >= DEBUG_LOG, "EMW3080B_EMAC : process input packet 0x%02x, len=%" PRIu32 "\n", ethertype, len);
emac_mem_buf_t *p, *q;
uint32_t index = 0;
p = _memory_manager->alloc_pool(len, 0);
if (p != NULL) {
uint8_t *src = (uint8_t *) ethernet_header;
uint32_t m = 0;
for (q = p; q != NULL; q = _memory_manager->get_next(q)) {
uint8_t *dest = (uint8_t *) _memory_manager->get_ptr(q);
memcpy(dest, &src[index], _memory_manager->get_len(q));
index += _memory_manager->get_len(q);
if (index >= len) {
break;
}
m++;
}
if (_emac_input_data_cb) {
_emac_input_data_cb(p);
}
} else {
debug_if(_debug_level >= DEBUG_WARNING, "EMW3080B_EMAC : fail to allocate emac_mem_buf_t %" PRIu32 " bytes\n", len);
}
}
break;
default:
break;
}
}
MX_NET_BUFFER_FREE(buffer);
}
}

View File

@ -0,0 +1,173 @@
/*
* Copyright (c) STMicroelectronics 2021
* 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.
*/
#ifndef EMW3080B_EMAC_H_
#define EMW3080B_EMAC_H_
#include <inttypes.h>
#include "mbed.h"
#include "mbed_debug.h"
#include "EMACInterface.h"
#include "WiFiInterface.h"
#include "mx_wifi.h"
extern EMACMemoryManager *emac3080b_global_memory_manager ;
class EMW3080B_EMAC : public EMAC {
public:
EMW3080B_EMAC();
static EMW3080B_EMAC &get_instance();
/**
* Return maximum transmission unit
*
* @return MTU in bytes
*/
virtual uint32_t get_mtu_size() const;
/**
* Gets memory buffer alignment preference
*
* Gets preferred memory buffer alignment of the Emac device. IP stack may or may not
* align link out memory buffer chains using the alignment.
*
* @return Memory alignment requirement in bytes
*/
virtual uint32_t get_align_preference() const;
/**
* Return interface name
*
* @param name Pointer to where the name should be written
* @param size Maximum number of character to copy
*/
virtual void get_ifname(char *name, uint8_t size) const;
/**
* Returns size of the underlying interface HW address size.
*
* @return HW address size in bytes
*/
virtual uint8_t get_hwaddr_size() const;
/**
* Return interface-supplied HW address
*
* Copies HW address to provided memory, @param addr has to be of correct size see @a get_hwaddr_size
*
* HW address need not be provided if this interface does not have its own HW
* address configuration; stack will choose address from central system
* configuration if the function returns false and does not write to addr.
*
* @param addr HW address for underlying interface
* @return true if HW address is available
*/
virtual bool get_hwaddr(uint8_t *addr) const;
/**
* Set HW address for interface
*
* Provided address has to be of correct size, see @a get_hwaddr_size
*
* Called to set the MAC address to actually use - if @a get_hwaddr is provided
* the stack would normally use that, but it could be overridden, eg for test
* purposes.
*
* @param addr Address to be set
*/
virtual void set_hwaddr(const uint8_t *addr);
/**
* Sends the packet over the link
*
* That can not be called from an interrupt context.
*
* @param buf Packet to be send
* @return True if the packet was send successfully, False otherwise
*/
virtual bool link_out(emac_mem_buf_t *buf);
/**
* Initializes the HW
*
* @return True on success, False in case of an error.
*/
virtual bool power_up();
/**
* Deinitializes the HW
*
*/
virtual void power_down();
/**
* Sets a callback that needs to be called for packets received for that interface
*
* @param input_cb Function to be register as a callback
*/
virtual void set_link_input_cb(emac_link_input_cb_t input_cb);
/**
* Sets a callback that needs to be called on link status changes for given interface
*
* @param state_cb Function to be register as a callback
*/
virtual void set_link_state_cb(emac_link_state_change_cb_t state_cb);
/** Add device to a multicast group
*
* @param address A multicast group hardware address
*/
virtual void add_multicast_group(const uint8_t *address);
/** Remove device from a multicast group
*
* @param address A multicast group hardware address
*/
virtual void remove_multicast_group(const uint8_t *address);
/** Request reception of all multicast packets
*
* @param all True to receive all multicasts
* False to receive only multicasts addressed to specified groups
*/
virtual void set_all_multicast(bool all);
/** Sets memory manager that is used to handle memory buffers
*
* @param mem_mngr Pointer to memory manager
*/
virtual void set_memory_manager(EMACMemoryManager &mem_mngr);
void mx_wifi_status_changed(uint8_t cate, uint8_t status, void *arg);
void mx_wifi_netlink_input_callback(mx_buf_t *buffer);
#define EMW3080B_HWADDR_SIZE 6
emac_link_input_cb_t _emac_link_input_cb; /**< Callback for incoming data */
emac_link_state_change_cb_t _emac_link_state_cb;
emac_link_input_cb_t _emac_input_data_cb;
EMACMemoryManager *_memory_manager;
uint8_t _mac_addr[EMW3080B_HWADDR_SIZE];
uint8_t _debug_level;
};
#endif /* EMW3080B_EMAC_H_ */

View File

@ -0,0 +1,409 @@
/*
* Copyright (c) STMicroelectronics 2021
* 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.
*/
/* Includes ------------------------------------------------------------------*/
/* Private includes ----------------------------------------------------------*/
#include "EMW3080B_SPI.h"
#define DEBUG_SILENT 0
#define DEBUG_WARNING 1
#define DEBUG_INFO 2
#define DEBUG_LOG 3
#define DEFAULT_DEBUG DEBUG_SILENT
static EMW3080B_SPI *emw3080B_spi_object;
EMW3080B_SPI::EMW3080B_SPI(bool debug,
PinName mosi,
PinName miso,
PinName sclk,
PinName nss,
PinName notify,
PinName flow,
PinName reset
): SPI(mosi, miso, sclk), _resetpin(reset), _nsspin(nss), _notifypin(notify), _flowpin(flow)
{
if (debug) {
_debug_level = DEBUG_INFO; // too much real time impact with DEBUG_LOG
} else {
_debug_level = DEFAULT_DEBUG;
}
_notify_irq = new InterruptIn(notify);
_flow_irq = new InterruptIn(flow);
_notify_irq->rise(NULL);
_flow_irq->rise(NULL);
emw3080B_spi_object = this;
/* MXWIFI supports 30 Mhz SPI clock but Mbed implementation is limitted to 5 Mhz */
/* DMA implementation would be required to increase this supported frequency */
SPI::frequency(5000000);
/* Phase 0 and One edge => mode 0 */
SPI::format(8, 0);
SPI::set_default_write_value(0);
SEM_INIT(spi_transfer_done_sem, 1);
}
int flow_rise_count = 0;
int notify_rise_count = 0;
void EMW3080B_SPI::flow_rise()
{
flow_rise_count++;
SEM_SIGNAL(spi_flow_rise_sem);
}
void EMW3080B_SPI::notify_rise()
{
notify_rise_count++;
if (SEM_SIGNAL(spi_txrx_sem) != SEM_OK) {
error("failed to signal spi_txrx_sem\n");
}
}
#pragma pack(1)
typedef struct _spi_header {
uint8_t type;
uint16_t len;
uint16_t lenx;
uint8_t dummy[3];
} spi_header_t;
#pragma pack()
/* Private define ------------------------------------------------------------*/
/* SPI protocol */
#define SPI_WRITE (0x0A)
#define SPI_READ (0x0B)
#define SPI_HEADER_SIZE (5)
#define SPI_DATA_SIZE (MX_WIFI_HCI_DATA_SIZE)
#define SPI_WAITING_FLOW_HIGH_TIMEOUT (100) /* ms unit */
#define SPI_MAX_TRANSMIT_DURATION (500) /* ms unit */
/* SPI CS */
#define MX_WIFI_SPI_CS_HIGH() _nsspin = 1
#define MX_WIFI_SPI_CS_LOW() _nsspin = 0
/**
* @brief Initialize SPI
* @param None
* @retval None
*/
int8_t EMW3080B_SPI::IO_Init(uint16_t mode)
{
int8_t ret = 0;
if (MX_WIFI_RESET == mode) {
/* HW reset */
MX_WIFI_SPI_CS_HIGH();
_resetpin = 0;
rtos::ThisThread::sleep_for(100ms);
_resetpin = 1;
rtos::ThisThread::sleep_for(1200ms);
} else {
ret = mx_wifi_spi_txrx_start();
}
return ret;
}
/**
* @brief DeInitialize SPI
* @param None
* @retval None
*/
int8_t EMW3080B_SPI::IO_DeInit(void)
{
mx_wifi_spi_txrx_stop();
return 0;
}
void EMW3080B_SPI::IO_Delay(uint32_t delayms)
{
return;
}
uint16_t EMW3080B_SPI::IO_Send(uint8_t *data, uint16_t len)
{
if ((NULL == data) || (0 == len) || (len > SPI_DATA_SIZE)) {
return 0;
}
spi_tx_data = data;
spi_tx_len = len;
if (SEM_SIGNAL(spi_txrx_sem) != SEM_OK) {
/* Happen if received thread did not have a chance to run on time, need to increase priority */
debug_if(_debug_level >= DEBUG_WARNING, "EMW3080B_SPI : spi semaphore has been already notified\n");
}
return len;
}
uint16_t EMW3080B_SPI::IO_Receive(uint8_t *buffer, uint16_t buff_size)
{
return 0U;
}
int8_t EMW3080B_SPI::wait_flow_high(uint32_t timeout)
{
int8_t ret = 0;
if (SEM_WAIT(spi_flow_rise_sem, timeout, NULL) != SEM_OK) {
debug_if(_debug_level >= DEBUG_WARNING, "EMW3080B_SPI : wait_flow_high semaphore failed, timeout\n");
ret = -1;
}
return ret;
}
int spi_handler_count = 0;
int spi_handler_event_value = 0;
void EMW3080B_SPI::spi_handler(int event)
{
spi_handler_count++;
spi_handler_event_value = event;
SEM_SIGNAL(spi_transfer_done_sem);
}
int32_t EMW3080B_SPI::TransmitReceive(uint8_t *txdata, uint8_t *rxdata, uint32_t datalen,
uint32_t timeout)
{
int32_t ret = 0;
debug_if(_debug_level >= DEBUG_LOG, "EMW3080B_SPI : Spi Tx Rx %" PRIu32 "\n", datalen);
SPI::transfer((const uint8_t *) txdata, (int) datalen, rxdata, (int) datalen, callback(this, &EMW3080B_SPI::spi_handler), SPI_EVENT_COMPLETE);
if (SEM_WAIT(spi_transfer_done_sem, timeout, NULL) != SEM_OK) {
debug_if(_debug_level >= DEBUG_WARNING, "EMW3080B_SPI : Timeout on TransmitReceive %d\n", spi_handler_count);
ret = -1;
}
return ret;
}
int32_t EMW3080B_SPI::Transmit(uint8_t *txdata, uint32_t datalen, uint32_t timeout)
{
int32_t ret = 0;
debug_if(_debug_level >= DEBUG_LOG, "EMW3080B_SPI : Spi Tx %" PRIu32 "\n", datalen);
SPI::transfer((const uint8_t *) txdata, (int) datalen, (uint8_t *)NULL, (int) datalen, callback(this, &EMW3080B_SPI::spi_handler), SPI_EVENT_COMPLETE);
if (SEM_WAIT(spi_transfer_done_sem, timeout, NULL) != SEM_OK) {
debug_if(_debug_level >= DEBUG_WARNING, "EMW3080B_SPI : Timeout on Transmit\n");
ret = -1;
}
return ret;
}
int32_t EMW3080B_SPI::Receive(uint8_t *rxdata, uint32_t datalen, uint32_t timeout)
{
int32_t ret = 0;
debug_if(_debug_level >= DEBUG_LOG, "EMW3080B_SPI : Spi Rx %" PRIu32 "\n", datalen);
SPI::transfer((const uint8_t *) NULL, (int) datalen, rxdata, (int) datalen, callback(this, &EMW3080B_SPI::spi_handler), SPI_EVENT_COMPLETE);
if (SEM_WAIT(spi_transfer_done_sem, timeout, NULL) != SEM_OK) {
debug_if(_debug_level >= DEBUG_WARNING, "EMW3080B_SPI : Timeout on Receive\n");
ret = -1;
}
return ret;
}
void EMW3080B_SPI::process_txrx_poll(uint32_t timeout)
{
spi_header_t mheader, sheader;
int32_t ret;
uint8_t *txdata;
uint8_t *p = NULL;
uint16_t datalen;
static mx_buf_t *netb = NULL;
bool first_miss = true;
MX_WIFI_SPI_CS_HIGH();
while (netb == NULL) {
netb = MX_NET_BUFFER_ALLOC(MX_WIFI_BUFFER_SIZE);
if (netb == NULL) {
rtos::ThisThread::sleep_for(1ms);
if (true == first_miss) {
first_miss = false;
debug_if(_debug_level >= DEBUG_WARNING, "EMW3080B_SPI : Running Out of buffer for RX\n");
}
}
}
/* waiting for data to be sent or to be received */
if (SEM_WAIT(spi_txrx_sem, timeout, NULL) == SEM_OK) {
if (spi_tx_data == NULL) {
if (_notifypin == 0) {
/* tx data null means no data to send , _flowpin low means no data to received */
error("EMW3080B_SPI : Nothing to process but wake UP!!!\n");
}
txdata = NULL;
mheader.len = 0;
} else {
mheader.len = spi_tx_len;
txdata = spi_tx_data;
}
mheader.type = SPI_WRITE;
mheader.lenx = ~mheader.len;
mheader.dummy[0] = 0;
mheader.dummy[1] = 0;
mheader.dummy[2] = 0;
MX_WIFI_SPI_CS_LOW();
/* wait EMW to be ready */
if (wait_flow_high(SPI_WAITING_FLOW_HIGH_TIMEOUT) != 0) {
MX_WIFI_SPI_CS_HIGH();
debug_if(_debug_level >= DEBUG_WARNING, "EMW3080B_SPI : wait flow high timeout, notify_rise_count %d flow_rise_count %d flow is %d\n", notify_rise_count, flow_rise_count, (int)_flowpin);
}
/* transmit only header part */
sheader.type = 0;
sheader.len = 0;
if (TransmitReceive((uint8_t *)&mheader, (uint8_t *)&sheader, sizeof(mheader), SPI_MAX_TRANSMIT_DURATION)) {
MX_WIFI_SPI_CS_HIGH();
debug_if(_debug_level >= DEBUG_WARNING, "EMW3080B_SPI : Send mheader error\r\n");
}
if (sheader.type != SPI_READ) {
MX_WIFI_SPI_CS_HIGH();
debug_if(_debug_level >= DEBUG_WARNING, "EMW3080B_SPI : Invalid SPI type %02x\r\n", sheader.type);
}
if ((sheader.len ^ sheader.lenx) != 0xFFFF) {
MX_WIFI_SPI_CS_HIGH();
debug_if(_debug_level >= DEBUG_WARNING, "EMW3080B_SPI : Invalid len %04x-%04x\r\n", sheader.len, sheader.lenx);
}
/* send or received header must be not null */
if ((sheader.len == 0) && (mheader.len == 0)) {
MX_WIFI_SPI_CS_HIGH();
return;
}
if ((sheader.len > SPI_DATA_SIZE) || (mheader.len > SPI_DATA_SIZE)) {
MX_WIFI_SPI_CS_HIGH();
debug_if(_debug_level >= DEBUG_WARNING, "EMW3080B_SPI : SPI length invalid: %d-%d\r\n", sheader.len, mheader.len);
}
/* keep max length */
if (mheader.len > sheader.len) {
datalen = mheader.len;
} else {
datalen = sheader.len;
}
/* allocate a buffer */
if (sheader.len > 0) {
/* get payload */
p = MX_NET_BUFFER_PAYLOAD(netb);
} else {
p = NULL;
}
/* flow must be high */
if (wait_flow_high(SPI_WAITING_FLOW_HIGH_TIMEOUT) != 0) {
MX_WIFI_SPI_CS_HIGH();
debug_if(_debug_level >= DEBUG_WARNING, "EMW3080B_SPI : timeout waiting for flow high after transfer !\r\n");
}
/* transmit and received */
if (NULL != txdata) {
spi_tx_data = NULL;
spi_tx_len = 0;
if (NULL != p) {
ret = TransmitReceive(txdata, p, datalen, SPI_MAX_TRANSMIT_DURATION);
} else {
ret = Transmit(txdata, datalen, SPI_MAX_TRANSMIT_DURATION);
}
} else {
ret = Receive(p, datalen, SPI_MAX_TRANSMIT_DURATION);
}
if (ret) {
MX_WIFI_SPI_CS_HIGH();
debug_if(_debug_level >= DEBUG_WARNING, "EMW3080B_SPI : Transmit/Receive data timeout\r\n");
}
/* resize the input buffer and sent it back to processing thread */
if (sheader.len > 0) {
MX_NET_BUFFER_SET_PAYLOAD_SIZE(netb, sheader.len);
mx_wifi_hci_input(netb);
netb = NULL;
}
MX_WIFI_SPI_CS_HIGH();
}
}
void mx_wifi_spi_txrx_task(void)
{
while (1) {
emw3080B_spi_object->process_txrx_poll(WAIT_FOREVER);
}
}
int8_t EMW3080B_SPI::mx_wifi_spi_txrx_start(void)
{
int8_t ret = 0;
SEM_INIT(spi_txrx_sem, 2);
SEM_INIT(spi_flow_rise_sem, 1);
SEM_INIT(spi_transfer_done_sem, 1);
_notify_irq->rise(callback(this, &EMW3080B_SPI::notify_rise));
_flow_irq->rise(callback(this, &EMW3080B_SPI::flow_rise));
if (THREAD_OK == THREAD_INIT(MX_WIFI_TxRxThreadId,
mx_wifi_spi_txrx_task, NULL,
MX_WIFI_SPI_THREAD_STACK_SIZE,
MX_WIFI_SPI_THREAD_PRIORITY)) {
ret = 0;
} else {
ret = -1;
}
return ret;
}
int8_t EMW3080B_SPI::mx_wifi_spi_txrx_stop(void)
{
THREAD_DEINIT(MX_WIFI_TxRxThreadId);
_notify_irq->rise(NULL);
_flow_irq->rise(NULL);
SEM_DEINIT(spi_txrx_sem);
SEM_DEINIT(spi_flow_rise_sem);
SEM_DEINIT(spi_transfer_done_sem);
return 0;
}

View File

@ -0,0 +1,85 @@
/*
* Copyright (c) STMicroelectronics 2021
* 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.
*/
/* Includes ------------------------------------------------------------------*/
#include <inttypes.h>
/* Private includes ----------------------------------------------------------*/
#include "mbed.h"
#include "mbed_debug.h"
#include "mbed_error.h"
#include "mx_wifi.h"
#include "core/mx_wifi_hci.h"
class EMW3080B_SPI : public SPI {
public:
EMW3080B_SPI(bool debug = MBED_CONF_EMW3080B_WIFI_DEBUG,
PinName mosi = MBED_CONF_EMW3080B_WIFI_MOSI,
PinName miso = MBED_CONF_EMW3080B_WIFI_MISO,
PinName sclk = MBED_CONF_EMW3080B_WIFI_SCLK,
PinName nss = MBED_CONF_EMW3080B_WIFI_NSS,
PinName notify = MBED_CONF_EMW3080B_WIFI_NOTIFY,
PinName flow = MBED_CONF_EMW3080B_WIFI_FLOW,
PinName reset = MBED_CONF_EMW3080B_WIFI_RESET
);
private:
DigitalOut _resetpin;
DigitalOut _nsspin;
DigitalIn _notifypin;
DigitalIn _flowpin;
InterruptIn *_notify_irq;
InterruptIn *_flow_irq;
void flow_rise(void);
void notify_rise(void);
int8_t wait_flow_high(uint32_t timeout);
SEM_DECLARE(spi_txrx_sem);
SEM_DECLARE(spi_flow_rise_sem);
SEM_DECLARE(spi_transfer_done_sem);
uint8_t *spi_tx_data = NULL;
uint16_t spi_tx_len = 0;
int32_t TransmitReceive(uint8_t *txdata, uint8_t *rxdata, uint32_t datalen, uint32_t timeout);
int32_t Transmit(uint8_t *txdata, uint32_t datalen, uint32_t timeout);
int32_t Receive(uint8_t *rxdata, uint32_t datalen, uint32_t timeout);
void spi_handler(int event);
int8_t mx_wifi_spi_txrx_start(void);
int8_t mx_wifi_spi_txrx_stop(void);
THREAD_DECLARE(MX_WIFI_TxRxThreadId);
public:
int8_t IO_Init(uint16_t mode);
int8_t IO_DeInit(void);
void IO_Delay(uint32_t delayms);
uint16_t IO_Send(uint8_t *data, uint16_t len);
uint16_t IO_Receive(uint8_t *buffer, uint16_t buff_size);
void process_txrx_poll(uint32_t timeout);
uint8_t _debug_level;
};

View File

@ -0,0 +1,144 @@
/*
* Copyright (c) STMicroelectronics 2021
* 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.
*/
/* Includes ------------------------------------------------------------------*/
/* Private includes ----------------------------------------------------------*/
#include "EMW3080B_UART.h"
#define DEBUG_SILENT 0
#define DEBUG_WARNING 1
#define DEBUG_INFO 2
#define DEBUG_LOG 3
#define DEFAULT_DEBUG DEBUG_SILENT
//#define DEBUG_UART_DATA 1
static EMW3080B_UART *emw3080b_uart_object;
EMW3080B_UART::EMW3080B_UART(bool debug,
PinName tx,
PinName rx,
PinName reset
): BufferedSerial(tx, rx, 230400), _resetpin(reset)
{
emw3080b_uart_object = this;
if (debug) {
_debug_level = DEBUG_LOG;
} else {
_debug_level = DEFAULT_DEBUG;
}
}
#if DEBUG_UART_DATA
void debug_print(char *prefix, uint8_t *data, uint16_t len);
void debug_print(char *prefix, uint8_t *data, uint16_t len)
{
if (NULL != data) {
printf("%s[%d]:\n", prefix, len);
for (int32_t i = 0; i < len; i++) {
printf(" %02x", data[i]);
}
printf("\n");
for (int32_t i = 0; i < len; i++) {
printf(" %c ", data[i]);
}
printf("\n");
}
}
#else
#define debug_print(...)
#endif /* DEBUG_UART_DATA */
void EMW3080B_UART::process_txrx_poll(void)
{
uint8_t c;
ssize_t n;
mx_buf_t *nbuf = NULL;
n = read(&c, 1);
if (n == 1) {
nbuf = slip_input_byte(c);
if (NULL != nbuf) {
debug_print("URX", MX_NET_BUFFER_PAYLOAD(nbuf), MX_NET_BUFFER_GET_PAYLOAD_SIZE(nbuf));
mx_wifi_hci_input(nbuf);
}
}
}
void HWInterfaceReceivedPollTask(void)
{
while (true) {
emw3080b_uart_object->process_txrx_poll();
}
}
int8_t EMW3080B_UART::IO_Init(uint16_t mode)
{
int8_t rc = 0;
if (MX_WIFI_RESET == mode) {
/* HW reset */
_resetpin = 0;
rtos::ThisThread::sleep_for(100ms);
_resetpin = 1;
rtos::ThisThread::sleep_for(1200ms);
} else {
if (THREAD_OK == THREAD_INIT(MX_WIFI_UARTRecvThreadId,
HWInterfaceReceivedPollTask, NULL,
MX_WIFI_UART_THREAD_STACK_SIZE, MX_WIFI_UART_THREAD_PRIORITY)) {
rc = MX_WIFI_STATUS_OK;
} else {
rc = MX_WIFI_STATUS_ERROR;
}
}
return rc;
}
int8_t EMW3080B_UART::IO_DeInit(void)
{
int8_t rc = 0;
THREAD_DEINIT(MX_WIFI_UARTRecvThreadId);
return rc;
}
void EMW3080B_UART::IO_Delay(uint32_t delayms)
{
printf("%s %d\n", __FILE__, __LINE__);
return;
}
uint16_t EMW3080B_UART::IO_Send(uint8_t *pdata, uint16_t len)
{
uint16_t rc;
debug_print("UTX", pdata, len);
rc = write(pdata, len);
return rc;
}
uint16_t EMW3080B_UART::IO_Receive(uint8_t *pdata, uint16_t request_len)
{
return 0;
}

View File

@ -0,0 +1,53 @@
/*
* Copyright (c) STMicroelectronics 2021
* 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.
*/
/* Includes ------------------------------------------------------------------*/
/* Private includes ----------------------------------------------------------*/
#include "mbed.h"
#include "mbed_debug.h"
#include "mbed_error.h"
#include "mx_wifi.h"
#include "core/mx_wifi_hci.h"
#include "core/mx_wifi_slip.h"
class EMW3080B_UART : public BufferedSerial {
public:
EMW3080B_UART(bool debug,
PinName tx,
PinName rx,
PinName reset
);
private:
DigitalOut _resetpin;
THREAD_DECLARE(MX_WIFI_UARTRecvThreadId);
public:
void process_txrx_poll(void);
int8_t IO_Init(uint16_t mode);
int8_t IO_DeInit(void);
void IO_Delay(uint32_t delayms);
uint16_t IO_Send(uint8_t *data, uint16_t len);
uint16_t IO_Receive(uint8_t *buffer, uint16_t buff_size);
uint8_t _debug_level;
};

View File

@ -0,0 +1,146 @@
# EMW3080B WiFi driver for STM32
## License
This software is licensed under terms that can be found in the [license](mx_wifi/LICENSE.md) file
## Currently supported platforms
EMW3080B module is available
- with an [ARDUINO extension board](https://www.seeedstudio.com/IOT-AT3080-IoT-development-board-p-4021.html)
- with a ST Discovery kit for IoT node : [B-U585I-IOT02A](https://os.mbed.com/platforms/ST-Discovery-B-U585I-IOT02A/)
## Configuration
B_U585I_IOT02A default configuration is enabled in [mbed_lib.json](mbed_lib.json)
For Arduino shield, the UART interface is used.
See in mbed_lib.json, B_U585I_IOT02A__ARDUINO_SHIELD configuration example you need to add in your local mbed_app.json.
```
"YOUR_TARGET": {
"emw3080b.wifi-spi-interface": false,
"emw3080b.wifi-tx": "ARDUINO_UNO_D1",
"emw3080b.wifi-rx": "ARDUINO_UNO_D0",
"emw3080b.wifi-reset": "ARDUINO_UNO_D13",
"emw3080b.provide-default": true
},
```
## Code Structure
The Mbed EMW3080B driver relies on the [STM32 EMW3080B BSP driver](https://github.com/STMicroelectronics/STM32CubeU5/tree/main/Drivers/BSP/Components/mx_wifi)
- COMPONENT_emw3080b/EMW3080BInterface.cpp : WiFiInterface class implementation (derived from EMACInterface )
- COMPONENT_emw3080b/EMW3080B_EMAC.cpp : EMAC interface
- COMPONENT_emw3080b/EMW3080B_SPI.cpp : SPI communication protocol implementation
- COMPONENT_emw3080b/EMW3080B_UART.cpp : UART communication protocol implementation
- COMPONENT_emw3080b/mx_wifi/* : [STM32 EMW3080B BSP driver](https://github.com/STMicroelectronics/STM32CubeU5/tree/main/Drivers/BSP/Components/mx_wifi)
## Debug
Some debug print on console can help to debug if necessary.
Either update your mbed_app.json:
```
"YOUR_TARGET": {
"emw3080b.wifi-debug": true
},
```
Either update manually the different .cpp source files to choose the appropriate level of VERBOSITY.
`#define DEFAULT_DEBUG DEBUG_SILENT` ==> choose DEBUG_WARNING/DEBUG_INFO/DEBUG_LOG
NB: in file "EMW3080B_SPI.cpp", DEBUG_LOG may have side effect due to real time issue.
## Validation
- netsocket tests: https://github.com/ARMmbed/mbed-os/tree/master/connectivity/netsocket/tests/TESTS/netsocket
- network-wifi tests: https://github.com/ARMmbed/mbed-os/tree/master/connectivity/netsocket/tests/TESTS/network/wifi
## Open point
TODO: netbuffer allocator feedback to choose appropriate memory mngt (copy or not) and fix concern regarding potential race when starting EMACinterface.
## Limitations
Performance of SPI limitted to 5Mhz.
## Firmware version & firmware update
The recommended firmware version is V2.1.11
NB: with older FW version, you could get an assert:
```
++ MbedOS Error Info ++
Error Status: 0x80FF0100 Code: 256 Module: 255
Error Message: Fatal Run-time error
Location: 0x801CB73
Error Value: 0xFFFFFFFE
Current Thread: lwip_tcpip Id: 0x20006058 Entry: 0x802064D StackSize: 0x4B0 StackMem: 0x20006698 SP: 0x20006ACC
For more info, visit: https://mbed.com/s/error?error=0x8003010D&tgt=B_U585I_IOT02A
-- MbedOS Error Info --
EMW3080BInterface : MX_WIFI_Init failed, you may have to update MXCHIP fimrware module to version 2.1.11
```
### How to get FW version ?
Enable DEBUG_INFO in EMW3080BInterface.cpp
```
EMW3080BInterface : Product name: MXCHIP-WIFI
EMW3080BInterface : Product ID: EMW3080B
EMW3080BInterface : FW revision: V2.1.11
```
### How to upgrade FW for B_U585I_IOT02A ?
Latest FW binary is provided in:
https://www.st.com/en/development-tools/x-wifi-emw3080b.html#get-software
Start TeraTerm (115200)
Drag and drop `EMW3080updateV2.1.11RevC.bin` into `NOD_U585AI`drive
You should get:
```
################### Welcome to EMW3080 firmware update utility 1.0.0 for board RevB or RevC ###################
STM32>Configured for MXchip embedded FW ST-EMW3080B_V2.1.11_SPI.OTA.BIN 0x8000234 / 546080 bytes
STM32>Don't forget to connect EMW3080 Boot to GND thanks to switch SW2 , move it to position "0" (instead of NC) to have boot loader running !
STM32>Push user button (Blue) to flash EMW3080 device or enter command
STM32>MCU system clock 160 MHz , Uart Baud rate 921600 , Software emulated UART bit duration 173 cycles
" help" print this message
" boot" Boot EMW3080 (needed before using mx command)
" mx" mx [cmd] : send command to mxchip device (can not use cmd which require ymodem protocol)
" flash" flash mxchip firmware (same as pushing blue button)
" check" check mxchip firmware
STM32>
```
- on switch SW2 (with 2 white switches), move BOOT one (Id 1) from NC to O position
- press blue button (User B3)
Wait till:
```
STM32>Flash successfull, move back switch to original position, reset the device to get back to prompt
```
So:
- move switch back to postion NC
- Reset

View File

@ -0,0 +1,73 @@
{
"name": "emw3080b",
"config": {
"wifi-spi-interface": {
"help": "SPI interface if true / UART interface if false",
"value": "NC"
},
"wifi-miso": {
"help": "SPI-MISO connection to external device",
"value": "NC"
},
"wifi-mosi": {
"help": "SPI-MOSI connection to external device",
"value": "NC"
},
"wifi-sclk": {
"help": "SPI-CLOCK connection to external device",
"value": "NC"
},
"wifi-nss": {
"help": "SPI chip select of external device",
"value": "NC"
},
"wifi-notify": {
"help": "EMW3080B notify from externam device",
"value": "NC"
},
"wifi-flow": {
"help": "EMW3080B flow from externam device",
"value": "NC"
},
"wifi-reset": {
"help": "EMW3080B reset to external device",
"value": "NC"
},
"wifi-tx": {
"help": "EMW3080B uart tx to external device",
"value": "NC"
},
"wifi-rx": {
"help": "EMW3080B uart rx from external device",
"value": "NC"
},
"wifi-debug": {
"help": "Defines whether logging is on or off",
"value": false
},
"provide-default": {
"help": "Provide default WifiInterface. [true/false]",
"value": false
}
},
"target_overrides": {
"B_U585I_IOT02A": {
"wifi-spi-interface": true,
"wifi-miso": "PD_3",
"wifi-mosi": "PD_4",
"wifi-sclk": "PD_1",
"wifi-nss": "PB_12",
"wifi-notify": "PD_14",
"wifi-flow": "PG_15",
"wifi-reset": "PF_15",
"provide-default": true
},
"B_U585I_IOT02A__ARDUINO_SHIELD": {
"wifi-spi-interface": false,
"wifi-tx": "ARDUINO_UNO_D1",
"wifi-rx": "ARDUINO_UNO_D0",
"wifi-reset": "ARDUINO_UNO_D13",
"provide-default": true
}
}
}

View File

@ -0,0 +1,80 @@
SLA0044 Rev5/February 2018
## Software license agreement
### __ULTIMATE LIBERTY SOFTWARE LICENSE AGREEMENT__
BY INSTALLING, COPYING, DOWNLOADING, ACCESSING OR OTHERWISE USING THIS SOFTWARE
OR ANY PART THEREOF (AND THE RELATED DOCUMENTATION) FROM STMICROELECTRONICS
INTERNATIONAL N.V, SWISS BRANCH AND/OR ITS AFFILIATED COMPANIES
(STMICROELECTRONICS), THE RECIPIENT, ON BEHALF OF HIMSELF OR HERSELF, OR ON
BEHALF OF ANY ENTITY BY WHICH SUCH RECIPIENT IS EMPLOYED AND/OR ENGAGED AGREES
TO BE BOUND BY THIS SOFTWARE LICENSE AGREEMENT.
Under STMicroelectronics intellectual property rights, the redistribution,
reproduction and use in source and binary forms of the software or any part
thereof, with or without modification, are permitted provided that the following
conditions are met:
1. Redistribution of source code (modified or not) must retain any copyright
notice, this list of conditions and the disclaimer set forth below as items 10
and 11.
2. Redistributions in binary form, except as embedded into microcontroller or
microprocessor device manufactured by or for STMicroelectronics or a software
update for such device, must reproduce any copyright notice provided with the
binary code, this list of conditions, and the disclaimer set forth below as
items 10 and 11, in documentation and/or other materials provided with the
distribution.
3. Neither the name of STMicroelectronics nor the names of other contributors to
this software may be used to endorse or promote products derived from this
software or part thereof without specific written permission.
4. This software or any part thereof, including modifications and/or derivative
works of this software, must be used and execute solely and exclusively on or in
combination with a microcontroller or microprocessor device manufactured by or
for STMicroelectronics.
5. No use, reproduction or redistribution of this software partially or totally
may be done in any manner that would subject this software to any Open Source
Terms. “Open Source Terms” shall mean any open source license which requires as
part of distribution of software that the source code of such software is
distributed therewith or otherwise made available, or open source license that
substantially complies with the Open Source definition specified at
www.opensource.org and any other comparable open source license such as for
example GNU General Public License (GPL), Eclipse Public License (EPL), Apache
Software License, BSD license or MIT license.
6. STMicroelectronics has no obligation to provide any maintenance, support or
updates for the software.
7. The software is and will remain the exclusive property of STMicroelectronics
and its licensors. The recipient will not take any action that jeopardizes
STMicroelectronics and its licensors' proprietary rights or acquire any rights
in the software, except the limited rights specified hereunder.
8. The recipient shall comply with all applicable laws and regulations affecting
the use of the software or any part thereof including any applicable export
control law or regulation.
9. Redistribution and use of this software or any part thereof other than as
permitted under this license is void and will automatically terminate your
rights under this license.
10. THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY RIGHTS, WHICH ARE
DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT SHALL
STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
11. EXCEPT AS EXPRESSLY PERMITTED HEREUNDER, NO LICENSE OR OTHER RIGHTS, WHETHER
EXPRESS OR IMPLIED, ARE GRANTED UNDER ANY PATENT OR OTHER INTELLECTUAL PROPERTY
RIGHTS OF STMICROELECTRONICS OR ANY THIRD PARTY.

View File

@ -0,0 +1,266 @@
/**
******************************************************************************
* @file checksum_utils.c
* @author MCD Application Team
* @brief Host driver checksum utils of MXCHIP Wi-Fi component.
******************************************************************************
* @attention
*
* Copyright (c) 2021 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
/*cstat -MISRAC2012-* */
#include "stdio.h"
/*cstat +MISRAC2012-* */
#include "checksumutils.h"
#ifdef CHECKSUM_DEBUG
#define DEBUG_LOG printf
#else
#define DEBUG_LOG
#endif /* CHECKSUM_DEBUG */
#ifdef USE_STM32L_CRC
/* User-defined polynomial */
#define CRC_POLYNOMIAL_16B 0x1021 /* X^16 + X^12 + X^5 + 1, CRC-CCITT generating polynomial */
/* User-defined CRC init value */
/* As the CRC is 16-bit long, the init value is 16-bit long as well */
#define CRC_INIT_VALUE 0x0000 /* 0x5AB */
#endif /* USE_STM32L_CRC */
static uint8_t UpdateCRC8(uint8_t crcIn, uint8_t byte);
static uint8_t UpdateCRC8(uint8_t crcIn, uint8_t byte)
{
uint8_t crc = crcIn;
uint8_t i;
crc ^= byte;
for (i = 0; i < (uint8_t)8; i++)
{
if ((crc & (uint8_t)0x01) > 0u)
{
crc = (crc >> 1) ^ (uint8_t)0x8C;
}
else
{
crc >>= 1;
}
}
return crc;
}
void CRC8_Init(CRC8_Context *inContext)
{
inContext->crc = 0;
}
void CRC8_Update(CRC8_Context *inContext, const uint8_t *inSrc, size_t inLen)
{
const uint8_t *src = (const uint8_t *) inSrc;
const uint8_t *srcEnd = &(src[inLen]);
while (src < srcEnd)
{
inContext->crc = UpdateCRC8(inContext->crc, *src);
src++;
}
}
void CRC8_Final(CRC8_Context *inContext, uint8_t *outResult)
{
*outResult = inContext->crc & 0xffu;
}
/*************************************CRC16******************************************/
#ifdef USE_STM32L_CRC
/**
* @brief CRC16 init function
*/
int8_t HW_CRC16_Init(CRC_HandleTypeDef *CrcHandle)
{
/****************************************************************************/
/* */
/* CRC peripheral initialization */
/* */
/****************************************************************************/
if (NULL == CrcHandle)
{
DEBUG_LOG("*** CRC16_Init: CrcHandle null error!\n");
return -1;
}
CrcHandle->Instance = CRC;
/* The default polynomial is not used. The one to be used must be defined
in CrcHandle.Init.GeneratingPolynomial */
CrcHandle->Init.DefaultPolynomialUse = DEFAULT_POLYNOMIAL_DISABLE;
/* Set the value of the generating polynomial.
The one used in that example is the 16-bit long CRC generating
polynomial X^16 + X^12 + X^5 + 1 */
CrcHandle->Init.GeneratingPolynomial = CRC_POLYNOMIAL_16B;
/* The user-defined generating polynomial yields a 16-bit long CRC */
CrcHandle->Init.CRCLength = CRC_POLYLENGTH_16B;
/* The default init value is not used */
CrcHandle->Init.DefaultInitValueUse = DEFAULT_INIT_VALUE_DISABLE;
/* User init value is used instead */
CrcHandle->Init.InitValue = CRC_INIT_VALUE;
/* The input data are inverted by word */
CrcHandle->Init.InputDataInversionMode = CRC_INPUTDATA_INVERSION_NONE;
/* The bit reversal is done on a full word basis.
The input stream yielded by CRC16_DATA8[] is the sequence of
bytes 0x4D, 0x3C, 0x2B, 0x1A, 0xBE, 0x71, ...
meaning that the first word written in the CRC DR register is
0x4D3C2B1A.
Bit reversal done by the hardware on the full word leads to the actual
CRC processing of
0x58D43CB2.
Similarly, the second word written in the peripheral is 0xBE71C98A, leading to
the processing of 0x51938E7D after hardware input data reversal.
Note that when the software writes less than a word in the peripheral (to minimize the
number of write accesses for a given number of bytes), the bit-reversal operation
is carried out only on the inputted data.
Therefore, the last written data is the last byte 0x5E, processed as 0x7A
by the hardware after bit-reversal to wrap-up the CRC computation.
This means that the field InputDataInversionMode set to CRC_INPUTDATA_INVERSION_WORD
applied to {0x4D, 0x3C, 0x2B, 0x1A, 0xBE, 0x71, 0xC9, 0x8A, 0x5E}
yields the same result as InputDataInversionMode set to CRC_INPUTDATA_INVERSION_NONE
applied to {0x58, 0xD4, 0x3C, 0xB2, 0x51, 0x93, 0x8E, 0x7D, 0x7A}.
*/
/* The output data are inverted */
CrcHandle->Init.OutputDataInversionMode = CRC_OUTPUTDATA_INVERSION_DISABLE;
/* Output data reversal can only be done at bit level.
The expected CRC is 0x5043 after output data reversal, meaning
that the CRC before the reversal operation is 0xC20A. */
/* The input data are bytes (8-bit long data) */
CrcHandle->InputDataFormat = CRC_INPUTDATA_FORMAT_BYTES;
/* De-initialize the CRC peripheral */
if (HAL_CRC_DeInit(CrcHandle) != HAL_OK)
{
/* Initialization Error */
DEBUG_LOG("*** CRC16_Init: HAL_CRC_DeInit error!\n");
return -1;
}
/* Then, initialize the CRC handle */
if (HAL_CRC_Init(CrcHandle) != HAL_OK)
{
/* Initialization Error */
DEBUG_LOG("*** CRC16_Init: HAL_CRC_Init error!\n");
return -1;
}
return 0; /* init success */
}
int8_t HW_CRC16_Update(CRC_HandleTypeDef *CrcHandle, uint8_t *input_data, uint32_t input_len, uint16_t *crc16_out)
{
/****************************************************************************/
/* */
/* CRC computation */
/* */
/****************************************************************************/
/* Used for storing CRC Value */
__IO uint32_t uwCRCValue = 0;
if (NULL == CrcHandle)
{
DEBUG_LOG("*** CRC16_Update: CrcHandle null error!\n");
return -1;
}
/* The 16-bit long CRC of the 9-byte buffer is computed. After peripheral initialization,
the CRC calculator is initialized with the user-defined value that is 0x5ABE.
The computed CRC is stored in uint32_t uwCRCValue. The 16-bit long CRC is made of
uwCRCValue 16 LSB bits. */
uwCRCValue = HAL_CRC_Accumulate(CrcHandle, (uint32_t *)input_data, input_len);
*crc16_out = (uint16_t)(uwCRCValue & 0x0000FFFF);
return 0;
}
#else /* SOFTWARE CRC16 */
static uint16_t UpdateCRC16(uint16_t crcIn, uint8_t byte)
{
uint32_t crc = crcIn;
uint32_t in = (uint32_t)byte | (uint32_t)0x100;
do
{
crc <<= 1;
in <<= 1;
if ((in & (uint32_t)0x100) > 0u)
{
++crc;
}
if ((crc & (uint32_t)0x10000) > 0u)
{
crc ^= (uint32_t)0x1021;
}
} while (!((in & (uint32_t)0x10000) > 0u));
return (uint16_t)(crc & (uint32_t)0xffffu);
}
void CRC16_Init(CRC16_Context *inContext)
{
inContext->crc = 0;
}
void CRC16_Update(CRC16_Context *inContext, const uint8_t *inSrc, size_t inLen)
{
const uint8_t *src = (const uint8_t *) inSrc;
const uint8_t *srcEnd = &(src[inLen]);
while (src < srcEnd)
{
inContext->crc = UpdateCRC16(inContext->crc, *src);
src++;
}
}
void CRC16_Final(CRC16_Context *inContext, uint16_t *outResult)
{
inContext->crc = UpdateCRC16(inContext->crc, 0);
inContext->crc = UpdateCRC16(inContext->crc, 0);
*outResult = inContext->crc & 0xffffu;
}
#endif /* USE_STM32L_CRC */

View File

@ -0,0 +1,142 @@
/**
******************************************************************************
* @file checksumutils.h
* @author MCD Application Team
* @brief Header for checksumutils.c module
******************************************************************************
* @attention
*
* Copyright (c) 2021 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef CHECKSUM_UTILS_H
#define CHECKSUM_UTILS_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
/*cstat -MISRAC2012-* */
#include <stddef.h>
#include <stdint.h>
/*cstat +MISRAC2012-* */
/* NOTE: MUST ENABLE STM32L HARDWARE CRC periph before use this API
#define USE_STM32L_CRC
*/
#ifdef USE_STM32L_CRC
/*cstat -MISRAC2012-* */
#include "stm32l4xx_hal.h"
/*cstat +MISRAC2012-* */
#endif /* USE_STM32L_CRC */
/********************* CRC8 MXOS Check **************************************
******************CRC-8 XMODEM x8+x5+x4+1******************************
****************************************************************************/
typedef struct
{
uint8_t crc;
} CRC8_Context;
/**
* @brief initialize the CRC8 Context
*
* @param inContext holds CRC8 result
*
* @retval none
*/
void CRC8_Init(CRC8_Context *inContext);
/**
* @brief Calculate the CRC8 result
*
* @param inContext holds CRC8 result during calculation process
* @param inSrc input data
* @param inLen length of input data
*
* @retval none
*/
void CRC8_Update(CRC8_Context *inContext, const uint8_t *inSrc, size_t inLen);
/**
* @brief output CRC8 result
*
* @param inContext holds CRC8 result
* @param outResutl holds CRC8 final result
*
* @retval none
*/
void CRC8_Final(CRC8_Context *inContext, uint8_t *outResult);
/********************* CRC16 MXOS Check **************************************
******************CRC-16/XMODEM x16+x12+x5+1******************************
******************************************************************************/
#ifdef USE_STM32L_CRC
int8_t HW_CRC16_Init(CRC_HandleTypeDef *CrcHandle);
int8_t HW_CRC16_Update(CRC_HandleTypeDef *CrcHandle, uint8_t *input_data, uint32_t input_len, uint16_t *crc16_out);
#else
typedef struct
{
uint16_t crc;
} CRC16_Context;
/**
* @brief initialize the CRC16 Context
*
* @param inContext holds CRC16 result
*
* @retval none
*/
void CRC16_Init(CRC16_Context *inContext);
/**
* @brief Calculate the CRC16 result
*
* @param inContext holds CRC16 result during calculation process
* @param inSrc input data
* @param inLen length of input data
*
* @retval none
*/
void CRC16_Update(CRC16_Context *inContext, const uint8_t *inSrc, size_t inLen);
/**
* @brief output CRC16 result
*
* @param inContext holds CRC16 result
* @param outResutl holds CRC16 final result
*
* @retval none
*/
void CRC16_Final(CRC16_Context *inContext, uint16_t *outResult);
#endif /* USE_STM32L_CRC */
#ifdef __cplusplus
}
#endif
#endif /* CHECKSUM_UTILS_H */

View File

@ -0,0 +1,44 @@
/**
******************************************************************************
* @file mx_rtos_abs.h
* @author MCD Application Team
* @brief Header for mx_wifi.c module
******************************************************************************
* @attention
*
* Copyright (c) 2021 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef MX_RTOS_ABS_H
#define MX_RTOS_ABS_H
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/* Includes ------------------------------------------------------------------*/
#include "mx_wifi_conf.h"
#include "stdlib.h"
#include "stddef.h"
#if MX_WIFI_USE_CMSIS_OS
#else
#endif /* MX_WIFI_USE_CMSIS_OS */
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* MX_RTOS_ABS_H */

View File

@ -0,0 +1,182 @@
/**
******************************************************************************
* @file mx_wifi_hci.c
* @author MCD Application Team
* @brief Host driver HCI protocol of MXCHIP Wi-Fi component.
******************************************************************************
* @attention
*
* Copyright (c) 2021 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
/*cstat -MISRAC2012-* */
#include "stdlib.h"
/*cstat +MISRAC2012-* */
#include <inttypes.h>
#include "mx_wifi_conf.h"
#include "mx_wifi_hci.h"
#include "mx_wifi_slip.h"
#include "checksumutils.h"
#ifdef MX_WIFI_HCI_DEBUG
#define DEBUG_LOG(M, ...) printf((M), ##__VA_ARGS__)
#else
#define DEBUG_LOG(M, ...)
#endif /* MX_WIFI_HCI_DEBUG */
#define DEBUG_ERROR(M, ...) printf((M), ##__VA_ARGS__)
/* Private defines -----------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* HCI low level function */
static hci_send_func_t tcl_output = NULL;
/* HCI recv data queue */
static FIFO_DECLARE(hci_pkt_fifo);
static bool mx_wifi_hci_pkt_verify(uint8_t *data, uint16_t len);
/* Private functions ---------------------------------------------------------*/
static bool mx_wifi_hci_pkt_verify(uint8_t *data, uint16_t len)
{
/* here each uart slip frame or spi frame as a hci packet */
return true;
}
/* Global functions ----------------------------------------------------------*/
int32_t mx_wifi_hci_init(hci_send_func_t low_level_send)
{
int32_t ret = 0;
tcl_output = low_level_send;
if (0 == ret)
{
FIFO_INIT(hci_pkt_fifo, MX_WIFI_MAX_RX_BUFFER_COUNT);
}
return ret;
}
int32_t mx_wifi_hci_deinit(void)
{
FIFO_DEINIT(hci_pkt_fifo);
return 0;
}
int32_t mx_wifi_hci_send(uint8_t *payload, uint16_t len)
{
int32_t ret = 0;
uint16_t sent = 0;
#if MX_WIFI_USE_SPI
sent = tcl_output(payload, len);
if (len != sent)
{
DEBUG_ERROR("tcl_output(spi) error sent=%d !\n", sent);
ret = -1;
}
else
{
ret = 0;
}
#else
uint8_t *slip_frame = NULL;
uint16_t slip_len = 0;
slip_frame = slip_transfer(payload, len, &slip_len);
if ((NULL != slip_frame) && (slip_len > 0))
{
sent = tcl_output(slip_frame, slip_len);
if (slip_len == sent)
{
ret = 0;
}
else
{
DEBUG_ERROR("tcl_output(uart) error sent=%d !\r\n", sent);
ret = -1;
}
MX_WIFI_FREE(slip_frame);
slip_frame = NULL;
}
else
{
DEBUG_ERROR("create slip frame error!\r\n");
ret = -2;
}
#endif /* MX_WIFI_USE_SPI */
return ret;
}
void process_txrx_poll(uint32_t timeout);
mx_buf_t *mx_wifi_hci_recv(uint32_t timeout)
{
mx_buf_t *nbuf;
nbuf = (mx_buf_t*) FIFO_POP(hci_pkt_fifo, timeout, process_txrx_poll);
if (nbuf != NULL)
{
MX_STAT(out_fifo);
}
return nbuf;
}
void mx_wifi_hci_free(mx_buf_t *nbuf)
{
if (NULL != nbuf)
{
(void) MX_NET_BUFFER_FREE(nbuf);
}
}
/**
* @brief LOW LEVEL INTERFACE
*/
void mx_wifi_hci_input(mx_buf_t *netbuf)
{
if (NULL != netbuf)
{
uint8_t *data = MX_NET_BUFFER_PAYLOAD(netbuf);
uint32_t len = MX_NET_BUFFER_GET_PAYLOAD_SIZE(netbuf);
if ((NULL != data) && (len > 0))
{
if (mx_wifi_hci_pkt_verify(data, len))
{
if (FIFO_OK != FIFO_PUSH(hci_pkt_fifo, netbuf, WAIT_FOREVER, NULL))
{
DEBUG_ERROR("push tcl input queue err!\n");
MX_NET_BUFFER_FREE(netbuf);
}
else
{
DEBUG_LOG("\nhci input len %"PRIu32" nbuf : %p\n", len, netbuf);
MX_STAT(in_fifo);
}
}
else
{
DEBUG_LOG("input bad tcl pkt!\n");
MX_NET_BUFFER_FREE(netbuf);
}
}
}
}

View File

@ -0,0 +1,77 @@
/**
******************************************************************************
* @file mx_wifi_hci.h
* @author MCD Application Team
* @brief Header for mx_wifi_hci.c module
******************************************************************************
* @attention
*
* Copyright (c) 2021 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef MX_WIFI_HCI_H
#define MX_WIFI_HCI_H
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/* Includes ------------------------------------------------------------------*/
/*cstat -MISRAC2012-* */
#include "stdint.h"
#include "string.h"
#include "stdbool.h"
#include "stdio.h"
/*cstat +MISRAC2012-* */
#include "mx_wifi_ipc.h"
/**
* @brief CONFIGURATIONS
*/
/* #define MX_WIFI_HCI_DEBUG */
/**
* @brief HCI PACKET
*/
#define MX_WIFI_HCI_DATA_SIZE (MIPC_PKT_MAX_SIZE)
/**
* @brief PROTOTYPES
*/
typedef struct _hci_pkt_s
{
uint16_t len;
uint8_t *data;
} hci_pkt_t;
typedef uint16_t (*hci_send_func_t)(uint8_t *data, uint16_t size);
/**
* @brief API
*/
int32_t mx_wifi_hci_init(hci_send_func_t low_level_send);
int32_t mx_wifi_hci_send(uint8_t *payload, uint16_t len);
mx_buf_t *mx_wifi_hci_recv(uint32_t timeout);
void mx_wifi_hci_free(mx_buf_t *nbuf);
int32_t mx_wifi_hci_deinit(void);
/**
* @brief LOW LEVEL INTERFACE
*/
void mx_wifi_hci_input(mx_buf_t *netbuf);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* MX_WIFI_HCI_H */

View File

@ -0,0 +1,421 @@
/**
******************************************************************************
* @file mx_wifi_ipc.c
* @author MCD Application Team
* @brief Host driver IPC protocol of MXCHIP Wi-Fi component.
******************************************************************************
* @attention
*
* Copyright (c) 2021 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
/*cstat -MISRAC2012-* */
#include <stdint.h>
#include <stdio.h>
/*cstat +MISRAC2012-* */
#include <inttypes.h>
#include "mx_wifi.h"
#include "mx_wifi_ipc.h"
#include "mx_wifi_hci.h"
#ifdef MX_WIFI_IPC_DEBUG
#define DEBUG_LOG(M, ...) printf((M), ##__VA_ARGS__)
#define DEBUG_ERROR(M, ...) printf((M), ##__VA_ARGS__)
#else
#define DEBUG_LOG(M, ...)
#define DEBUG_ERROR(M, ...) printf((M), ##__VA_ARGS__)
#endif /* MX_WIFI_IPC_DEBUG */
#define MIPC_REQ_LIST_SIZE (64)
/**
* @brief IPC API event handlers
*/
typedef void (*event_callback_t)(mx_buf_t *mx_buff);
typedef struct _event_item_s
{
uint16_t api_id;
void (*callback)(mx_buf_t *mx_buff);
} event_item_t;
event_item_t event_table[3] =
{
/* system */
{MIPC_API_SYS_REBOOT_EVENT, mapi_reboot_event_callback},
/* wifi */
{MIPC_API_WIFI_STATUS_EVENT, mapi_wifi_status_event_callback},
{MIPC_API_WIFI_BYPASS_INPUT_EVENT, mapi_wifi_netlink_input_callback},
};
/**
* @brief IPC API request list
*/
typedef struct _mipc_req_s
{
uint32_t req_id;
SEM_DECLARE(resp_flag);
uint16_t *rbuffer_size; /* in/out*/
uint8_t *rbuffer;
} mipc_req_t;
static mipc_req_t pending_request;
static uint32_t get_new_req_id(void);
static uint32_t mpic_get_req_id(uint8_t *buffer_in);
static uint16_t mpic_get_api_id(uint8_t *buffer_in);
static uint32_t mipc_event(mx_buf_t *netbuf);
/* unique sequence number */
static uint32_t get_new_req_id(void)
{
static uint32_t id = 1;
return id++;
}
static uint32_t mpic_get_req_id(uint8_t *buffer_in)
{
return *((uint32_t *) & (buffer_in[MIPC_PKT_REQ_ID_OFFSET]));
}
static uint16_t mpic_get_api_id(uint8_t *buffer_in)
{
return *((uint16_t *) & (buffer_in[MIPC_PKT_API_ID_OFFSET]));
}
static uint32_t mipc_event(mx_buf_t *netbuf)
{
uint32_t req_id = MIPC_REQ_ID_NONE;
uint16_t api_id = MIPC_API_ID_NONE;
uint32_t i;
void (*callback)(mx_buf_t *mx_buff);
if (NULL != netbuf)
{
uint8_t *buffer_in = MX_NET_BUFFER_PAYLOAD(netbuf);
uint32_t buffer_size = MX_NET_BUFFER_GET_PAYLOAD_SIZE(netbuf);
if ((NULL != buffer_in) && (buffer_size >= MIPC_PKT_MIN_SIZE))
{
req_id = mpic_get_req_id(buffer_in);
api_id = mpic_get_api_id(buffer_in);
DEBUG_LOG("req_id: 0x%08"PRIx32", api_id: 0x%04x\n", req_id, api_id);
if ((0 == (api_id & MIPC_API_EVENT_BASE)) && (MIPC_REQ_ID_NONE != req_id))
{
/* cmd response must match pending req id */
MX_ASSERT(pending_request.req_id == req_id);
{
/* return params */
if ((pending_request.rbuffer_size != NULL) && (*(pending_request.rbuffer_size) > 0)
&& (NULL != pending_request.rbuffer))
{
*(pending_request.rbuffer_size) = *(pending_request.rbuffer_size) < (buffer_size - MIPC_PKT_MIN_SIZE) ? \
*(pending_request.rbuffer_size) : (buffer_size - MIPC_PKT_MIN_SIZE);
memcpy(pending_request.rbuffer, buffer_in + MIPC_PKT_PARAMS_OFFSET, *(pending_request.rbuffer_size));
}
pending_request.req_id = 0xFFFFFFFF;
if (SEM_OK != SEM_SIGNAL(pending_request.resp_flag))
{
DEBUG_ERROR("Failed to signal command response\n");
while (1);
}
MX_STAT(cmd_get_answer);
mx_wifi_hci_free(netbuf);
}
}
else /* event callback */
{
for (i = 0; i < sizeof(event_table) / sizeof(event_item_t); i++)
{
if (event_table[i].api_id == api_id)
{
callback = event_table[i].callback;
if (NULL != callback)
{
DEBUG_LOG("callback with %p\n", buffer_in);
callback(netbuf);
break;
}
}
}
if (i == sizeof(event_table) / sizeof(event_item_t))
{
DEBUG_ERROR("unknown event: 0x%04x !\n", api_id);
mx_wifi_hci_free(netbuf);
}
}
}
else
{
DEBUG_LOG("unknown buffer content\n");
mx_wifi_hci_free(netbuf);
}
}
return req_id;
}
/*******************************************************************************
* IPC API implementations for mx_wifi over HCI
******************************************************************************/
/**
* @brief mxchip ipc protocol init
* @param ipc_send low level send function
* @return int32_t status code
*/
int32_t mipc_init(mipc_send_func_t ipc_send)
{
int32_t ret;
pending_request.req_id = 0xFFFFFFFF;
SEM_INIT(pending_request.resp_flag, 1);
ret = mx_wifi_hci_init(ipc_send);
return ret;
}
int32_t mipc_deinit(void)
{
int32_t ret;
SEM_DEINIT(pending_request.resp_flag);
ret = mx_wifi_hci_deinit();
return ret;
}
int32_t mipc_request(uint16_t api_id, uint8_t *cparams, uint16_t cparams_size,
uint8_t *rbuffer, uint16_t *rbuffer_size, uint32_t timeout_ms)
{
int32_t ret = MIPC_CODE_ERROR;
uint8_t *cbuf;
uint8_t *pos;
uint16_t cbuf_size;
uint32_t req_id;
bool copy_buffer = true;
LOCK(wifi_obj_get()->lockcmd);
if (cparams_size <= MX_WIFI_IPC_PAYLOAD_SIZE)
{
/* create cmd data */
cbuf_size = sizeof(req_id) + sizeof(api_id) + cparams_size;
#if MX_WIFI_TX_BUFFER_NO_COPY
if (api_id == MIPC_API_WIFI_BYPASS_OUT_CMD)
{
cbuf = cparams - sizeof(req_id) - sizeof(api_id);
copy_buffer = false;
}
else
#endif /* MX_WIFI_TX_BUFFER_NO_COPY */
{
cbuf = (uint8_t *)MX_WIFI_MALLOC(cbuf_size);
}
if (NULL != cbuf)
{
/* get an uniq identifier */
req_id = get_new_req_id();
/* copy the protocol parameter to the head part of the buffer */
pos = cbuf;
memcpy(pos, &req_id, sizeof(req_id));
pos += sizeof(req_id);
memcpy(pos, &api_id, sizeof(api_id));
pos += sizeof(api_id);
if ((true == copy_buffer) && (cparams_size > 0))
{
memcpy(pos, cparams, cparams_size);
}
/* a single pending request due to LOCK usage on command */
if (pending_request.req_id != 0xFFFFFFFF)
{
DEBUG_LOG("Error req_id must be 0xffffffff here %"PRIu32"\n", pending_request.req_id);
while (1);
}
pending_request.req_id = req_id;
pending_request.rbuffer = rbuffer;
pending_request.rbuffer_size = rbuffer_size;
/* static int iter=0; */
/* printf("%d push %d\n",iter++,cbuf_size); */
/* send the command */
DEBUG_LOG("cmd %"PRIu32"\n", req_id);
ret = mx_wifi_hci_send(cbuf, cbuf_size);
if (ret == 0)
{
/* wait for command answer */
if (SEM_WAIT(pending_request.resp_flag, timeout_ms, mipc_poll) != SEM_OK)
{
DEBUG_ERROR("Error: command 0x%04x timeout(%"PRIu32" ms) waiting answer %"PRIu32"\n",
api_id, timeout_ms, pending_request.req_id);
pending_request.req_id = 0xFFFFFFFF;
ret = MIPC_CODE_ERROR;
}
}
else
{
DEBUG_ERROR("Failed to send command to Hci\n");
while (1);
}
DEBUG_LOG("done %"PRIu32"\n", req_id);
if (true == copy_buffer)
{
MX_WIFI_FREE(cbuf);
}
}
}
UNLOCK(wifi_obj_get()->lockcmd);
return ret;
}
/**
* @brief mipc poll
* @param timeout_ms timeout in ms
* @return int32_t 0 if success, otherwise failed
*/
void mipc_poll(uint32_t timeout)
{
mx_buf_t *nbuf;
/* process the received data inside RX buffer */
nbuf = mx_wifi_hci_recv(timeout);
if (NULL != nbuf)
{
uint32_t len = MX_NET_BUFFER_GET_PAYLOAD_SIZE(nbuf);
DEBUG_LOG("\nhci recv len %"PRIu32"\n", len);
if (len > 0)
{
mipc_event(nbuf);
}
else
{
MX_NET_BUFFER_FREE(nbuf);
}
}
}
int32_t mipc_echo(uint8_t *in, uint16_t in_len, uint8_t *out, uint16_t *out_len,
uint32_t timeout)
{
int32_t ret = MIPC_CODE_ERROR;
if ((NULL != in) && (NULL != out) && (NULL != out_len))
{
ret = mipc_request(MIPC_API_SYS_ECHO_CMD, in, in_len, out, out_len, timeout);
if (MIPC_CODE_SUCCESS == ret)
{
ret = MIPC_CODE_SUCCESS;
}
else
{
*out_len = 0;
}
}
return ret;
}
/*******************************************************************************
* IPC API event callbacks
******************************************************************************/
/* system */
void mapi_reboot_event_callback(mx_buf_t *buff)
{
if (buff != NULL)
{
mx_wifi_hci_free(buff);
}
DEBUG_LOG("\nEVENT: reboot done.\n");
}
/* wifi */
void mapi_wifi_status_event_callback(mx_buf_t *nbuf)
{
uint8_t cate;
mwifi_status_t status;
mx_wifi_status_callback_t status_cb = NULL;
void *cb_args = NULL;
if (NULL != nbuf)
{
uint8_t *payload = MX_NET_BUFFER_PAYLOAD(nbuf);
status = *((mwifi_status_t *)(payload + MIPC_PKT_PARAMS_OFFSET));
DEBUG_LOG("\nEVENT: wifi status: %02x\r\n", status);
mx_wifi_hci_free(nbuf);
switch (status)
{
case MWIFI_EVENT_STA_UP:
case MWIFI_EVENT_STA_DOWN:
case MWIFI_EVENT_STA_GOT_IP:
cate = MC_STATION;
status_cb = wifi_obj_get()->Runtime.status_cb[0];
cb_args = wifi_obj_get()->Runtime.callback_arg[0];
break;
case MWIFI_EVENT_AP_UP:
case MWIFI_EVENT_AP_DOWN:
cate = MC_SOFTAP;
status_cb = wifi_obj_get()->Runtime.status_cb[0];
cb_args = wifi_obj_get()->Runtime.callback_arg[0];
break;
default:
cate = MC_SOFTAP;
MX_ASSERT(false);
break;
}
if (NULL != status_cb)
{
status_cb(cate, status, cb_args);
}
}
}
void mapi_wifi_netlink_input_callback(mx_buf_t *nbuf)
{
wifi_bypass_in_rparams_t *in_rprarams;
/* DEBUG_LOG("IP stack in %d\n",len); */
if (NULL != nbuf)
{
uint8_t *buffer_in = MX_NET_BUFFER_PAYLOAD(nbuf);
MX_STAT(callback);
in_rprarams = (wifi_bypass_in_rparams_t *)(buffer_in + MIPC_PKT_PARAMS_OFFSET);
MX_NET_BUFFER_HIDE_HEADER(nbuf, MIPC_PKT_PARAMS_OFFSET + sizeof(wifi_bypass_in_rparams_t));
if ((NULL != wifi_obj_get()->Runtime.netlink_input_cb) && \
(in_rprarams->tot_len > 0))
{
wifi_obj_get()->Runtime.netlink_input_cb(nbuf,
wifi_obj_get()->Runtime.netlink_user_args);
}
else
{
MX_NET_BUFFER_FREE(nbuf);
}
}
}

View File

@ -0,0 +1,657 @@
/**
******************************************************************************
* @file mx_wifi_ipc.h
* @author MCD Application Team
* @brief Header for mx_wifi_ipc.c module
******************************************************************************
* @attention
*
* Copyright (c) 2021 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef MX_WIFI_IPC_H
#define MX_WIFI_IPC_H
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/* Includes ------------------------------------------------------------------*/
/*cstat -MISRAC2012-* */
#include <stdint.h>
#include <string.h>
#include <stdbool.h>
#include <stdio.h>
/*cstat +MISRAC2012-* */
#include "mx_wifi.h"
/* Exported Constants --------------------------------------------------------*/
/* #define MX_WIFI_IPC_DEBUG */
#define MX_API_VERSION ("2.0.0")
/**
* @brief IPC error code
*/
#define MIPC_CODE_SUCCESS (0)
#define MIPC_CODE_ERROR (-1)
#define MIPC_CODE_TIMEOUT (-2)
#define MIPC_CODE_NO_MEMORY (-3)
/**
* @brief IPC packet
*/
/*
* |--------+--------+--------------------|
* | req_id | api_id | args (<p1>...<pn>) |
* |--------+--------+--------------------|
* | 4Bytes | 2Btyes | nBytes |
* |--------+--------+--------------------|
*/
#define MIPC_PKT_REQ_ID_OFFSET (0)
#define MIPC_PKT_REQ_ID_SIZE (4)
#define MIPC_PKT_API_ID_OFFSET (MIPC_PKT_REQ_ID_OFFSET + MIPC_PKT_REQ_ID_SIZE)
#define MIPC_PKT_API_ID_SIZE (2)
#define MIPC_PKT_PARAMS_OFFSET (MIPC_PKT_API_ID_OFFSET + MIPC_PKT_API_ID_SIZE)
#define MIPC_HEADER_SIZE (MIPC_PKT_REQ_ID_SIZE + MIPC_PKT_API_ID_SIZE)
#define MIPC_PKT_MIN_SIZE (MIPC_HEADER_SIZE)
#define MIPC_PKT_MAX_SIZE (MIPC_HEADER_SIZE + MX_WIFI_IPC_PAYLOAD_SIZE)
/**
* @brief IPC api id
*/
#define MIPC_REQ_ID_NONE (0x00000000)
#define MIPC_API_ID_NONE (0x0000)
#define MIPC_API_CMD_BASE (MIPC_API_ID_NONE)
#define MIPC_API_EVENT_BASE (0x8000)
/**
* API CMD
*/
/* system */
#define MIPC_API_SYS_CMD_BASE (MIPC_API_CMD_BASE + 0x0000)
#define MIPC_API_SYS_ECHO_CMD (MIPC_API_SYS_CMD_BASE + 0x0001)
#define MIPC_API_SYS_REBOOT_CMD (MIPC_API_SYS_CMD_BASE + 0x0002)
#define MIPC_API_SYS_VERSION_CMD (MIPC_API_SYS_CMD_BASE + 0x0003)
#define MIPC_API_SYS_RESET_CMD (MIPC_API_SYS_CMD_BASE + 0x0004)
/* wifi */
#define MIPC_API_WIFI_CMD_BASE (MIPC_API_CMD_BASE + 0x0100)
#define MIPC_API_WIFI_GET_MAC_CMD (MIPC_API_WIFI_CMD_BASE + 0x0001)
#define MIPC_API_WIFI_SCAN_CMD (MIPC_API_WIFI_CMD_BASE + 0x0002)
#define MIPC_API_WIFI_CONNECT_CMD (MIPC_API_WIFI_CMD_BASE + 0x0003)
#define MIPC_API_WIFI_DISCONNECT_CMD (MIPC_API_WIFI_CMD_BASE + 0x0004)
#define MIPC_API_WIFI_SOFTAP_START_CMD (MIPC_API_WIFI_CMD_BASE + 0x0005)
#define MIPC_API_WIFI_SOFTAP_STOP_CMD (MIPC_API_WIFI_CMD_BASE + 0x0006)
#define MIPC_API_WIFI_GET_IP_CMD (MIPC_API_WIFI_CMD_BASE + 0x0007)
#define MIPC_API_WIFI_GET_LINKINFO_CMD (MIPC_API_WIFI_CMD_BASE + 0x0008)
#define MIPC_API_WIFI_PS_ON_CMD (MIPC_API_WIFI_CMD_BASE + 0x0009)
#define MIPC_API_WIFI_PS_OFF_CMD (MIPC_API_WIFI_CMD_BASE + 0x000a)
#define MIPC_API_WIFI_PING_CMD (MIPC_API_WIFI_CMD_BASE + 0x000b)
#define MIPC_API_WIFI_BYPASS_SET_CMD (MIPC_API_WIFI_CMD_BASE + 0x000c)
#define MIPC_API_WIFI_BYPASS_GET_CMD (MIPC_API_WIFI_CMD_BASE + 0x000d)
#define MIPC_API_WIFI_BYPASS_OUT_CMD (MIPC_API_WIFI_CMD_BASE + 0x000e)
/* socket */
#define MIPC_API_SOCKET_CMD_BASE (MIPC_API_CMD_BASE + 0x0200)
#define MIPC_API_SOCKET_CREATE_CMD (MIPC_API_SOCKET_CMD_BASE + 0x0001)
#define MIPC_API_SOCKET_CONNECT_CMD (MIPC_API_SOCKET_CMD_BASE + 0x0002)
#define MIPC_API_SOCKET_SEND_CMD (MIPC_API_SOCKET_CMD_BASE + 0x0003)
#define MIPC_API_SOCKET_SENDTO_CMD (MIPC_API_SOCKET_CMD_BASE + 0x0004)
#define MIPC_API_SOCKET_RECV_CMD (MIPC_API_SOCKET_CMD_BASE + 0x0005)
#define MIPC_API_SOCKET_RECVFROM_CMD (MIPC_API_SOCKET_CMD_BASE + 0x0006)
#define MIPC_API_SOCKET_SHUTDOWN_CMD (MIPC_API_SOCKET_CMD_BASE + 0x0007)
#define MIPC_API_SOCKET_CLOSE_CMD (MIPC_API_SOCKET_CMD_BASE + 0x0008)
#define MIPC_API_SOCKET_GETSOCKOPT_CMD (MIPC_API_SOCKET_CMD_BASE + 0x0009)
#define MIPC_API_SOCKET_SETSOCKOPT_CMD (MIPC_API_SOCKET_CMD_BASE + 0x000a)
#define MIPC_API_SOCKET_BIND_CMD (MIPC_API_SOCKET_CMD_BASE + 0x000b)
#define MIPC_API_SOCKET_LISTEN_CMD (MIPC_API_SOCKET_CMD_BASE + 0x000c)
#define MIPC_API_SOCKET_ACCEPT_CMD (MIPC_API_SOCKET_CMD_BASE + 0x000d)
#define MIPC_API_SOCKET_SELECT_CMD (MIPC_API_SOCKET_CMD_BASE + 0x000e)
#define MIPC_API_SOCKET_GETSOCKNAME_CMD (MIPC_API_SOCKET_CMD_BASE + 0x000f)
#define MIPC_API_SOCKET_GETPEERNAME_CMD (MIPC_API_SOCKET_CMD_BASE + 0x0010)
#define MIPC_API_SOCKET_GETHOSTBYNAME_CMD (MIPC_API_SOCKET_CMD_BASE + 0x0011)
/* TLS cmd */
#define MIPC_API_TLS_SET_VER_CMD (MIPC_API_SOCKET_CMD_BASE + 0x0081)
#define MIPC_API_TLS_SET_CLIENT_CERT_CMD (MIPC_API_SOCKET_CMD_BASE + 0x0082)
#define MIPC_API_TLS_SET_SERVER_CERT_CMD (MIPC_API_SOCKET_CMD_BASE + 0x0083)
#define MIPC_API_TLS_ACCEPT_CMD (MIPC_API_SOCKET_CMD_BASE + 0x0084)
#define MIPC_API_TLS_CONNECT_SNI_CMD (MIPC_API_SOCKET_CMD_BASE + 0x0085)
#define MIPC_API_TLS_SEND_CMD (MIPC_API_SOCKET_CMD_BASE + 0x0086)
#define MIPC_API_TLS_RECV_CMD (MIPC_API_SOCKET_CMD_BASE + 0x0087)
#define MIPC_API_TLS_CLOSE_CMD (MIPC_API_SOCKET_CMD_BASE + 0x0088)
#define MIPC_API_TLS_SET_NONBLOCK_CMD (MIPC_API_SOCKET_CMD_BASE + 0x0089)
#define MIPC_API_MDNS_CMD_BASE (MIPC_API_CMD_BASE + 0x0300)
#define MIPC_API_MDNS_START_CMD (MIPC_API_MDNS_CMD_BASE + 0x0001)
#define MIPC_API_MDNS_STOP_CMD (MIPC_API_MDNS_CMD_BASE + 0x0002)
#define MIPC_API_MDNS_ANNOUNCE_CMD (MIPC_API_MDNS_CMD_BASE + 0x0003)
#define MIPC_API_MDNS_DEANNOUNCE_CMD (MIPC_API_MDNS_CMD_BASE + 0x0004)
#define MIPC_API_MDNS_DEANNOUNCE_ALL_CMD (MIPC_API_MDNS_CMD_BASE + 0x0005)
#define MIPC_API_MDNS_IFACE_STATE_CHANGE_CMD (MIPC_API_MDNS_CMD_BASE + 0x0006)
#define MIPC_API_MDNS_SET_HOSTNAME_CMD (MIPC_API_MDNS_CMD_BASE + 0x0007)
#define MIPC_API_MDNS_SET_TXT_REC_CMD (MIPC_API_MDNS_CMD_BASE + 0x0008)
/**
* API EVENT
*/
/* system */
#define MIPC_API_SYS_EVENT_BASE (MIPC_API_EVENT_BASE + 0x0000)
#define MIPC_API_SYS_REBOOT_EVENT (MIPC_API_SYS_EVENT_BASE + 0x0001)
/* wifi */
#define MIPC_API_WIFI_EVENT_BASE (MIPC_API_EVENT_BASE + 0x0100)
#define MIPC_API_WIFI_STATUS_EVENT (MIPC_API_WIFI_EVENT_BASE + 0x0001)
#define MIPC_API_WIFI_BYPASS_INPUT_EVENT (MIPC_API_WIFI_EVENT_BASE + 0x0002)
/* Exported macro-------------------------------------------------------------*/
/* Exported typedef ----------------------------------------------------------*/
typedef uint16_t (*mipc_send_func_t)(uint8_t *data, uint16_t size);
/* Exported functions --------------------------------------------------------*/
/* MX_IPC */
int32_t mipc_init(mipc_send_func_t ipc_send);
int32_t mipc_deinit(void);
/* ipc api request */
int32_t mipc_request(uint16_t api_id, uint8_t *cparams, uint16_t cparams_size,
uint8_t *rbuffer, uint16_t *rbuffer_size, uint32_t timeout_ms);
/* ipc handle response/event */
void mipc_poll(uint32_t timeout);
/* ipc echo test */
int32_t mipc_echo(uint8_t *in, uint16_t in_len, uint8_t *out, uint16_t *out_len,
uint32_t timeout);
/* Module API event callbacks ------------------------------------------------*/
/* system */
void mapi_reboot_event_callback(mx_buf_t *buff);
/* wifi */
#pragma pack(1)
typedef struct _wifi_scan_cparams_s
{
int8_t ssid[33]; /* 32 + 1 '\0' string end */
} wifi_scan_cparams_t;
typedef struct _wifi_scan_rparams_s
{
uint8_t num;
mwifi_ap_info_t ap[1]; /* ap info array memory */
} wifi_scan_rparams_t;
typedef struct
{
uint8_t bssid[6]; /**< bssid of access-point */
uint8_t channel; /**< channel of access-point */
mwifi_security_t security; /**< security of access-point */
} mwifi_connect_attr_t;
typedef struct _wifi_connect_cparams_s
{
int8_t ssid[33]; /* 32 + 1 '\0' string end */
int8_t key[65]; /* 64 + 1 '\0' string end */
int32_t key_len;
uint8_t use_attr;
uint8_t use_ip;
mwifi_connect_attr_t attr;
mwifi_ip_attr_t ip;
} wifi_connect_cparams_t;
typedef struct
{
int32_t is_connected; /**< The link to wlan is established or not, 0: disconnected, 1: connected. */
int32_t rssi; /**< Signal strength of the current connected AP */
int8_t ssid[33]; /**< SSID of the current connected wlan */
uint8_t bssid[6]; /**< BSSID of the current connected wlan */
int8_t key[65]; /**< The passphrase/PSK of the connected AP */
int32_t channel; /**< Channel of the current connected wlan */
mwifi_security_t security; /**< security of access-point */
} mwifi_link_info_t;
typedef struct _wifi_get_linkinof_rparams_s
{
int32_t status;
mwifi_link_info_t info;
} wifi_get_linkinof_rparams_t;
typedef struct _wifi_get_ip_rparams_s
{
int32_t status;
mwifi_ip_attr_t ip;
} wifi_get_ip_rparams_t;
typedef struct _wifi_softap_start_cparams_s
{
int8_t ssid[32];
int8_t key[64];
int32_t channel;
mwifi_ip_attr_t ip;
} wifi_softap_start_cparams_t;
/* ping */
typedef struct wifi_ping_cparams_s
{
char hostname[255];
int32_t count;
int32_t delay_ms;
} wifi_ping_cparams_t;
typedef struct wifi_ping_rparams_s
{
int32_t num;
int32_t delay_ms[1];
} wifi_ping_rparams_t;
typedef struct wifi_bypass_set_cparams_s
{
int32_t mode;
} wifi_bypass_set_cparams_t;
typedef struct wifi_bypass_get_rparams_s
{
int32_t mode;
} wifi_bypass_get_rparams_t;
typedef struct wifi_bypass_out_cparams_s
{
int32_t idx;
uint8_t useless[16];
uint16_t data_len;
} wifi_bypass_out_cparams_t;
typedef struct wifi_bypass_in_rparams_s
{
int32_t idx;
uint8_t useless[16];
uint16_t tot_len;
} wifi_bypass_in_rparams_t;
#pragma pack()
void mapi_wifi_status_event_callback(mx_buf_t *nbuf);
void mapi_wifi_netlink_input_callback(mx_buf_t *nbuf);
#if MX_WIFI_NETWORK_BYPASS_MODE == 0
/* socket */
#pragma pack(1)
/* create */
typedef struct _socket_create_cparams_s
{
int32_t domain;
int32_t type;
int32_t protocol;
} socket_create_cparams_t;
typedef struct _socket_create_rparams_s
{
int32_t fd;
} socket_create_rparams_t;
/* setsockopt */
typedef struct _socket_setsockopt_cparams_s
{
int32_t socket;
int32_t level;
int32_t optname;
socklen_t optlen;
uint8_t optval[16];
} socket_setsockopt_cparams_t;
typedef struct _socket_setsockopt_rparams_s
{
int32_t status;
} socket_setsockopt_rparams_t;
/* getsockopt */
typedef struct _socket_getsockopt_cparams_s
{
int32_t socket;
int32_t level;
int32_t optname;
} socket_getsockopt_cparams_t;
typedef struct _socket_getsockopt_rparams_s
{
int32_t status;
socklen_t optlen;
uint8_t optval[16];
} socket_getsockopt_rparams_t;
/* bind */
typedef struct _socket_bind_cparams_s
{
int32_t socket;
struct sockaddr addr;
socklen_t length;
} socket_bind_cparams_t;
typedef struct _socket_bind_rparams_s
{
int32_t status;
} socket_bind_rparams_t;
/* connect */
typedef struct _socket_connect_cparams_s
{
int32_t socket;
struct sockaddr addr;
socklen_t length;
} socket_connect_cparams_t;
typedef struct _socket_connect_rparams_s
{
int32_t status;
} socket_connect_rparams_t;
/* shutdown */
typedef struct _socket_shutdown_cparams_s
{
int32_t filedes;
int32_t how;
} socket_shutdown_cparams_t;
typedef struct _socket_shutdown_rparams_s
{
int32_t status;
} socket_shutdown_rparams_t;
/* close */
typedef struct _socket_close_cparams_s
{
int32_t filedes;
} socket_close_cparams_t;
typedef struct _socket_close_rparams_s
{
int32_t status;
} socket_close_rparams_t;
/* send */
typedef struct _socket_send_cparams_s
{
int32_t socket;
size_t size;
int32_t flags;
uint8_t buffer[1];
} socket_send_cparams_t;
typedef struct _socket_send_rparams_s
{
int32_t sent;
} socket_send_rparams_t;
/* sendto */
typedef struct _socket_sendto_cparams_s
{
int32_t socket;
size_t size;
int32_t flags;
struct sockaddr addr;
socklen_t length;
uint8_t buffer[1];
} socket_sendto_cparams_t;
typedef struct _socket_sendto_rparams_s
{
int32_t sent;
} socket_sendto_rparams_t;
/* recv */
typedef struct _socket_recv_cparams_s
{
int32_t socket;
size_t size;
int32_t flags;
} socket_recv_cparams_t;
typedef struct _socket_recv_rparams_s
{
int32_t received;
uint8_t buffer[1];
} socket_recv_rparams_t;
/* recvfrom */
typedef struct _socket_recvfrom_cparams_s
{
int32_t socket;
size_t size;
int32_t flags;
} socket_recvfrom_cparams_t;
typedef struct _socket_recvfrom_rparams_s
{
int32_t received;
struct sockaddr addr;
socklen_t length;
uint8_t buffer[1];
} socket_recvfrom_rparams_t;
/* gethostbyname */
typedef struct _socket_gethostbyname_cparams_s
{
char name[253];
} socket_gethostbyname_cparams_t;
typedef struct _socket_gethostbyname_rparams_s
{
int32_t status;
uint32_t s_addr;
} socket_gethostbyname_rparams_t;
/* getpeername */
typedef struct _socket_getpeername_cparams_s
{
int32_t s;
} socket_getpeername_cparams_t;
typedef struct _socket_getpeername_rparams_s
{
int32_t status;
struct sockaddr name;
socklen_t namelen;
} socket_getpeername_rparams_t;
/* getsockname */
typedef struct _socket_getsockname_cparams_s
{
int32_t s;
} socket_getsockname_cparams_t;
typedef struct _socket_getsockname_rparams_s
{
int32_t status;
struct sockaddr name;
socklen_t namelen;
} socket_getsockname_rparams_t;
/* listen */
typedef struct _socket_listen_cparams_s
{
int32_t socket;
int32_t n;
} socket_listen_cparams_t;
typedef struct _socket_listen_rparams_s
{
int32_t status;
} socket_listen_rparams_t;
/* accept */
typedef struct _socket_accept_cparams_s
{
int32_t socket;
} socket_accept_cparams_t;
typedef struct _socket_accept_rparams_s
{
int32_t socket;
struct sockaddr addr;
socklen_t length;
} socket_accept_rparams_t;
/* tls */
/* tls set ver */
typedef struct _tls_set_ver_cparams_s
{
mtls_ver_t version;
} tls_set_ver_cparams_t;
typedef struct _tls_set_ver_rparams_s
{
int32_t ret;
} tls_set_ver_rparams_t;
/* tls set client cert */
typedef struct _tls_set_client_cert_cparams_s
{
uint16_t cert_pem_size;
uint16_t private_key_pem_size;
char cert_data[1]; /* cert_pem + private_key_pem */
} tls_set_client_cert_cparams_t;
typedef struct _tls_set_client_cert_rparams_s
{
int32_t ret;
} tls_set_client_cert_rparams_t;
/* tls set server cert */
typedef struct _tls_set_server_cert_cparams_s
{
uint16_t cert_pem_size;
uint16_t private_key_pem_size;
uint16_t verify_ca_size;
char cert_data[1]; /* cert_pem + private_key_pem + verify_ca */
} tls_set_server_cert_cparams_t;
typedef struct _tls_set_server_cert_rparams_s
{
int32_t ret;
} tls_set_server_cert_rparams_t;
/* tls accept */
typedef struct _tls_accept_cparams_s
{
int32_t fd;
} tls_accept_cparams_t;
typedef struct _tls_accept_rparams_s
{
mtls_t tls;
} tls_accept_rparams_t;
/* tls connect_sni */
typedef struct _tls_connect_sni_cparams_s
{
struct sockaddr addr;
socklen_t length;
char sni_servername[128];
int32_t calen;
char ca[1];
} tls_connect_sni_cparams_t;
typedef struct _tls_connect_sni_rparams_s
{
mtls_t tls;
int32_t errno;
} tls_connect_sni_rparams_t;
/* tls send */
typedef struct _tls_send_cparams_s
{
mtls_t tls;
size_t size;
uint8_t buffer[1];
} tls_send_cparams_t;
typedef struct _tls_send_rparams_s
{
int32_t sent;
} tls_send_rparams_t;
/* tls recv */
typedef struct _tls_recv_cparams_s
{
mtls_t tls;
size_t size;
} tls_recv_cparams_t;
typedef struct _tls_recv_rparams_s
{
int32_t received;
uint8_t buffer[1];
} tls_recv_rparams_t;
/* tls close */
typedef struct _tls_close_cparams_s
{
mtls_t tls;
} tls_close_cparams_t;
typedef struct _tls_close_rparams_s
{
int32_t ret;
} tls_close_rparams_t;
/* tls nonblock */
typedef struct _tls_set_nonblock_cparams_s
{
mtls_t tls;
int32_t nonblock;
} tls_set_nonblock_cparams_t;
typedef struct _tls_set_nonblock_rparams_s
{
int32_t ret;
} tls_set_nonblock_rparams_t;
#pragma pack()
#pragma pack(1)
typedef struct mdns_start_cparams_s
{
char domain[MDNS_MAX_LABEL_LEN + 1];
char hostname[MDNS_MAX_LABEL_LEN + 1];
} mdns_start_cparams_t;
typedef struct mdns_announce_cparams_s
{
uint8_t iface;
struct mc_mdns_service service_data;
} mdns_announce_cparams_t, mdns_deannounce_cparams_t;
typedef struct mdns_deannounce_all_cparams_s
{
uint8_t iface;
} mdns_deannounce_all_cparams_t;
typedef struct mdns_iface_state_change_cparams_s
{
uint8_t iface;
uint8_t state;
} mdns_iface_state_change_cparams_t;
typedef struct mdns_set_hostname_cparams_s
{
char hostname[MDNS_MAX_LABEL_LEN + 1];
} mdns_set_hostname_cparams_t;
typedef struct mdns_set_txt_rec_cparams_s
{
struct mc_mdns_service service_data;
char keyvals[MDNS_MAX_KEYVAL_LEN + 1];
char separator;
} mdns_set_txt_rec_cparams_t;
#pragma pack()
#endif /* MX_WIFI_NETWORK_BYPASS_MODE */
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* MX_WIFI_IPC_H */

View File

@ -0,0 +1,203 @@
/**
******************************************************************************
* @file mx_wifi_slip.c
* @author MCD Application Team
* @brief Host driver SLIP protocol of MXCHIP Wi-Fi component.
******************************************************************************
* @attention
*
* Copyright (c) 2021 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
/*cstat -MISRAC2012-* */
#include "stdio.h"
#include "stdlib.h"
/*cstat +MISRAC2012-* */
#include "mx_wifi_conf.h"
#include "mx_wifi_slip.h"
#include "mx_wifi_ipc.h"
/* debug function */
#ifdef MX_WIFI_SLIP_DEBUG
#define DEBUG_LOG(M, ...) printf((M), ##__VA_ARGS__)
#else
#define DEBUG_LOG(M, ...)
#endif /* MX_WIFI_SLIP_DEBUG */
#define DEBUG_WARNING(...)
/* slip buffer number */
#define SLIP_BUFFER_SIZE (MIPC_PKT_MAX_SIZE + 100)
enum
{
SLIP_STATE_IDLE, /* NOT START */
SLIP_STATE_CONTINUE, /* receive data to buffer */
SLIP_STATE_GOT_ESCAPE /* last byte is escape */
};
uint8_t *slip_transfer(uint8_t *data, uint16_t len, uint16_t *outlen)
{
uint16_t i;
uint16_t j;
uint16_t inc = 2;
uint8_t *buff = NULL;
for (i = 0; i < len; i++)
{
if ((data[i] == SLIP_START) || (data[i] == SLIP_END) || (data[i] == SLIP_ESCAPE))
{
inc++;
}
}
buff = (uint8_t *)MX_WIFI_MALLOC(len + inc);
if (buff == NULL)
{
return NULL;
}
buff[0] = SLIP_START;
for (i = 0, j = 1; i < len; i++)
{
if (data[i] == SLIP_START)
{
buff[j++] = SLIP_ESCAPE;
buff[j++] = SLIP_ESCAPE_START;
}
else if (data[i] == SLIP_END)
{
buff[j++] = SLIP_ESCAPE;
buff[j++] = SLIP_ESCAPE_END;
}
else if (data[i] == SLIP_ESCAPE)
{
buff[j++] = SLIP_ESCAPE;
buff[j++] = SLIP_ESCAPE_ES;
}
else
{
buff[j++] = data[i];
}
}
buff[j++] = SLIP_END;
*outlen = j;
return buff;
}
mx_buf_t *slip_input_byte(uint8_t data)
{
mx_buf_t *outgoing_nbuf = NULL;
static uint16_t slip_state = SLIP_STATE_IDLE;
static uint16_t slip_index = 0;
static uint8_t *slip_buffer = NULL;
static mx_buf_t *nbuf = NULL;
if (slip_buffer == NULL)
{
bool first_miss = true;
do
{
nbuf = MX_NET_BUFFER_ALLOC(SLIP_BUFFER_SIZE);
if (nbuf == NULL)
{
DELAYms(1);
if (true == first_miss)
{
first_miss = false;
DEBUG_WARNING("Running Out of buffer for RX\n");
}
}
} while (NULL == nbuf);
slip_buffer = MX_NET_BUFFER_PAYLOAD(nbuf);
}
if (slip_index >= SLIP_BUFFER_SIZE)
{
slip_index = 0;
slip_state = SLIP_STATE_IDLE;
}
switch (slip_state)
{
case SLIP_STATE_GOT_ESCAPE:
if (data == SLIP_START)
{
slip_index = 0;
}
else if (data == SLIP_ESCAPE_START)
{
slip_buffer[slip_index++] = SLIP_START;
}
else if (data == SLIP_ESCAPE_ES)
{
slip_buffer[slip_index++] = SLIP_ESCAPE;
}
else if (data == SLIP_ESCAPE_END)
{
slip_buffer[slip_index++] = SLIP_END;
}
else
{
goto RESET;
}
slip_state = SLIP_STATE_CONTINUE;
break;
case SLIP_STATE_IDLE:
if (data == SLIP_START)
{
slip_index = 0;
slip_state = SLIP_STATE_CONTINUE;
}
break;
case SLIP_STATE_CONTINUE: /* continue */
if (data == SLIP_START)
{
slip_index = 0;
slip_state = SLIP_STATE_CONTINUE;
}
else if (data == SLIP_END)
{
outgoing_nbuf = nbuf;
slip_buffer = NULL;
MX_NET_BUFFER_SET_PAYLOAD_SIZE(nbuf, slip_index);
nbuf = NULL;
goto RESET;
}
else if (data == SLIP_ESCAPE)
{
slip_state = SLIP_STATE_GOT_ESCAPE;
}
else
{
slip_buffer[slip_index++] = data;
}
break;
default:
break;
}
return outgoing_nbuf;
RESET:
slip_index = 0;
slip_state = SLIP_STATE_IDLE;
return outgoing_nbuf;
}

View File

@ -0,0 +1,74 @@
/**
******************************************************************************
* @file mx_wifi_slip.h
* @author MCD Application Team
* @brief Header for mx_wifi_slip.c module
******************************************************************************
* @attention
*
* Copyright (c) 2021 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef MX_WIFI_SLIP_H
#define MX_WIFI_SLIP_H
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/* Includes ------------------------------------------------------------------*/
#include "mx_wifi_conf.h"
/*
* CONFIGURATIONS
*/
#define MX_WIFI_SLIP_DEBUG
/* SLIP_PACKET
* |--------+---------+--------|
* | START | PAYLOAD | END |
* |--------+---------+--------|
* | 1Bytes | nBytes | 1Bytes |
* |--------+---------+--------|
*/
/*
* API
*/
/* transfer HCI data to SLIP data,
* return the SLIP buffer */
uint8_t *slip_transfer(uint8_t *data, uint16_t len, uint16_t *outlen);
/* PHY receive one serial byte to SLIP,
* return SLIP frame
* NOTE: use slip_buf_free to free slip buffer if data process finished. */
mx_buf_t *slip_input_byte(uint8_t data);
/* free slip frame buffer returned by slip_input_byte */
void slip_buf_free(uint8_t *buf);
enum
{
SLIP_START = 0xC0,
SLIP_END = 0xD0,
SLIP_ESCAPE = 0xDB,
SLIP_ESCAPE_START = 0xDC,
SLIP_ESCAPE_ES = 0xDD,
SLIP_ESCAPE_END = 0xDE
};
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* MX_WIFI_SLIP_H */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,251 @@
/**
******************************************************************************
* @file mx_wifi_conf_template.h
* @author MCD Application Team
* @brief Header for mx_wifi_conf_template module
******************************************************************************
* @attention
*
* Copyright (c) 2021 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef MX_WIFI_CONF_TEMPLATE_H
#define MX_WIFI_CONF_TEMPLATE_H
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/* Includes ------------------------------------------------------------------*/
#include <stdint.h>
int32_t mxwifi_probe(void **ll_drv_context);
/* use SPI interface by default */
#ifndef MX_WIFI_USE_SPI
#define MX_WIFI_USE_SPI (1)
#endif /* MX_WIFI_USE_SPI */
/* do not use RTOS but bare metal approach by default */
#ifndef MX_WIFI_USE_CMSIS_OS
#define MX_WIFI_USE_CMSIS_OS (0)
#endif /* MX_WIFI_USE_CMSIS_OS */
/* Use At command mode by default, TCP/IP stack is running on module */
#ifndef MX_WIFI_NETWORK_BYPASS_MODE
#define MX_WIFI_NETWORK_BYPASS_MODE (0)
#endif /* MX_WIFI_NETWORK_BYPASS_MODE */
/* Do not copy TX buffer */
#ifndef MX_WIFI_TX_BUFFER_NO_COPY
#define MX_WIFI_TX_BUFFER_NO_COPY (1)
#endif /* MX_WIFI_TX_BUFFER_NO_COPY */
/* DEBUG LOG */
/* #define MX_WIFI_API_DEBUG */
/* #define MX_WIFI_IPC_DEBUG */
/* #define MX_WIFI_HCI_DEBUG */
/* #define MX_WIFI_SLIP_DEBUG */
/* #define MX_WIFI_IO_DEBUG */
/* check if OS primitive are already declared */
/* if not, include default declaration */
#ifndef LOCK_DECLARE
#if (MX_WIFI_USE_CMSIS_OS == 1)
#include "mx_wifi_cmsis_os.h"
#define MX_WIFI_BARE_OS 0
#else
#if (MX_WIFI_USE_MBED_OS == 1)
#include "mx_wifi_mbed_os.h"
#define MX_WIFI_BARE_OS 0
#else
#include "mx_wifi_bare_os.h"
#define MX_WIFI_BARE_OS 1
#endif /* mx_wifi_mbed_os.h */
#endif /* MX_WIFI_USE_CMSIS_OS */
#else
/* OS rempa are declared externally , so OS is present */
#define MX_WIFI_BARE_OS 0
#endif /* LOCK_DECLARE */
#define MX_WIFI_PRODUCT_NAME ("MXCHIP-WIFI")
#define MX_WIFI_PRODUCT_ID ("EMW3080B")
#ifndef MX_WIFI_USE_SPI
#define MX_WIFI_USE_SPI (0)
#endif /* MX_WIFI_USE_SPI */
#ifndef MX_WIFI_UART_BAUDRATE
#define MX_WIFI_UART_BAUDRATE (115200*2)
#endif /* MX_WIFI_UART_BAUDRATE */
#ifndef MX_WIFI_MTU_SIZE
#define MX_WIFI_MTU_SIZE (1500)
#endif /* MX_WIFI_MTU_SIZE */
#define MX_WIFI_BYPASS_HEADER_SIZE (28) /* MX_IPC_header(6) + sizeof(bypass_in_t)(22),
* set with PBUF_LINK_ENCAPSULATION_HLEN */
#define MX_WIFI_PBUF_LINK_HLEN (14) /* link header (PBUF_LINK_HLEN) set in lwip */
#if (MX_WIFI_NETWORK_BYPASS_MODE==1)
/* Use lwip PBUF_POOL_BUFSIZE = TCP_MSS + 40 + PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN. */
#define MX_WIFI_BUFFER_SIZE \
(MX_WIFI_MTU_SIZE + MX_WIFI_BYPASS_HEADER_SIZE + MX_WIFI_PBUF_LINK_HLEN)
#else
#define MX_WIFI_BUFFER_SIZE (2500) /* bigger buffer size */
#endif /* (MX_WIFI_NETWORK_BYPASS_MODE==1) */
/* MX_WIFI_BUFFER_SIZE - MX_IPC_header */
#define MX_WIFI_IPC_PAYLOAD_SIZE ((MX_WIFI_BUFFER_SIZE) - 6)
/* MX_WIFI_IPC_PAYLOAD_SIZE - socket_api_params_header */
#define MX_WIFI_SOCKET_DATA_SIZE ((MX_WIFI_IPC_PAYLOAD_SIZE)-12)
#ifndef MX_WIFI_CMD_TIMEOUT
#define MX_WIFI_CMD_TIMEOUT (10000)
#endif
#define MX_WIFI_MAX_SOCKET_NBR (8)
#define MX_WIFI_MAX_DETECTED_AP (10)
#define MX_WIFI_MAX_SSID_NAME_SIZE 32
#define MX_WIFI_MAX_PSWD_NAME_SIZE 64
#define MX_WIFI_PRODUCT_NAME_SIZE 32
#define MX_WIFI_PRODUCT_ID_SIZE 32
#define MX_WIFI_FW_REV_SIZE 24
#ifndef MX_WIFI_SPI_THREAD_PRIORITY
#define MX_WIFI_SPI_THREAD_PRIORITY (OSPRIORITYREALTIME)
#endif /* MX_WIFI_SPI_THREAD_PRIORITY */
#ifndef MX_WIFI_SPI_THREAD_STACK_SIZE
#define MX_WIFI_SPI_THREAD_STACK_SIZE (1024)
#endif /* MX_WIFI_SPI_THREAD_STACK_SIZE */
#ifndef MX_WIFI_UART_THREAD_PRIORITY
#define MX_WIFI_UART_THREAD_PRIORITY (OSPRIORITYREALTIME)
#endif /* MX_WIFI_UART_THREAD_PRIORITY */
#ifndef MX_WIFI_UART_THREAD_STACK_SIZE
#define MX_WIFI_UART_THREAD_STACK_SIZE (1024)
#endif /* MX_WIFI_UART_THREAD_STACK_SIZE */
#ifndef MX_WIFI_RECEIVED_THREAD_PRIORITY
#define MX_WIFI_RECEIVED_THREAD_PRIORITY (OSPRIORITYABOVENORMAL)
#endif /* MX_WIFI_RECEIVED_THREAD_PRIORITY */
#ifndef MX_WIFI_RECEIVED_THREAD_STACK_SIZE
#define MX_WIFI_RECEIVED_THREAD_STACK_SIZE (1024)
#endif /* MX_WIFI_RECEIVED_THREAD_STACK_SIZE*/
#ifndef MX_WIFI_TRANSMIT_THREAD_PRIORITY
#define MX_WIFI_TRANSMIT_THREAD_PRIORITY (OSPRIORITYABOVENORMAL)
#endif /* MX_WIFI_TRANSMIT_THREAD_PRIORITY */
#ifndef MX_WIFI_TRANSMIT_THREAD_STACK_SIZE
#define MX_WIFI_TRANSMIT_THREAD_STACK_SIZE (1024)
#endif /* MX_WIFI_TRANSMIT_THREAD_STACK_SIZE */
/* Maximum number of RX buffer that can be queued by Hardware interface (SPI/UART) */
/* This is used to size internal queue, and avoid to block the IP thread if it can still push some buffers */
/* Impact on Memory foot print is weak , one single void* per place in the queue */
#ifndef MX_WIFI_MAX_RX_BUFFER_COUNT
#define MX_WIFI_MAX_RX_BUFFER_COUNT (2)
#endif /* MX_WIFI_MAX_RX_BUFFER_COUNT */
/* Maximum number of TX buffer that can be queued by IP stack (LwIP or Netx) without blocking the calling thread */
/* This is used to size internal queue, and avoid to block the IP thread if it can still push some buffers */
/* Impact on Memory foot print is one single void* per place in the queue, but it may lead to over allocation */
/* TCP/IP stack (LwIP for instance ) */
#ifndef MX_WIFI_MAX_TX_BUFFER_COUNT
#define MX_WIFI_MAX_TX_BUFFER_COUNT (4)
#endif /* MX_WIFI_MAX_TX_BUFFER_COUNT */
/**
* For the TX buffer, by default no-copy feature is enabled, meaning that
* the IP buffer are used in the whole process and should come with
* available room in front of payload to accommodate transport header buffer.
* This is managed in interface between driver and IP stack
*/
/**
* For LwIP "PBUF_LINK_ENCAPSULATION_HLEN" must be defined as > MX_WIFI_MIN_TX_HEADER_SIZE,
* see net_mx_wifi/c file for implementation.
*/
#define MX_WIFI_MIN_TX_HEADER_SIZE (28)
#ifndef MX_WIFI_TX_BUFFER_NO_COPY
#define MX_WIFI_TX_BUFFER_NO_COPY (1)
#endif /* MX_WIFI_TX_BUFFER_NO_COPY */
/* Sizeof the circular buffer for Uart mode, when buffer is hlaf full data are transmitted to next stage */
#ifndef MX_CIRCULAR_UART_RX_BUFFER_SIZE
#define MX_CIRCULAR_UART_RX_BUFFER_SIZE (400)
#endif /* MX_CIRCULAR_UART_RX_BUFFER_SIZE */
#ifndef MX_STAT_ON
#define MX_STAT_ON 0
#endif /* MX_STAT_ON */
#if MX_STAT_ON == 1
typedef struct
{
uint32_t alloc;
uint32_t free;
uint32_t cmd_get_answer;
uint32_t callback;
uint32_t in_fifo;
uint32_t out_fifo;
} mx_stat_t;
extern mx_stat_t mx_stat;
#define MX_STAT_LOG() \
(void) printf("Number of allocated buffer for Rx and command answer %ld\n", mx_stat.alloc);\
(void) printf("Number of free buffer %ld\n",mx_stat.free);\
(void) printf("Number of command answer %ld , callback %ld, sum of both %ld (should match alloc && free)\n",\
mx_stat.cmd_get_answer,mx_stat.callback,mx_stat.cmd_get_answer+mx_stat.callback);\
(void) printf("Number of posted answer (callback + cmd answer) %ld, processed answer %ld\n",\
mx_stat.in_fifo,mx_stat.out_fifo);\
#define MX_STAT_INIT() (void) memset((void*)&mx_stat, 0, sizeof(mx_stat))
#define MX_STAT(A) mx_stat.A++
#define MX_STAT_DECLARE() mx_stat_t mx_stat
#else
#define MX_STAT_INIT()
#define MX_STAT(A)
#define MX_STAT_LOG()
#define MX_STAT_DECLARE()
#endif /* MX_STAT_ON */
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* MX_WIFI_CONF_TEMPLATE_H */

View File

@ -0,0 +1,32 @@
/**
* <h2><center>&copy; Copyright (c) 2021 STMicroelectronics.
* SPDX-License-Identifier: BSD-3-Clause
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef MX_WIFI_CONF_H
#define MX_WIFI_CONF_H
/* Define your Hardware config UART or SPI */
#define MX_WIFI_USE_SPI (MBED_CONF_EMW3080B_WIFI_SPI_INTERFACE)
/* Bypass mode or AT command */
#define MX_WIFI_NETWORK_BYPASS_MODE (1)
#define MX_WIFI_USE_MBED_OS (1)
//#define MX_WIFI_TX_BUFFER_NO_COPY (0)
/* Includes ------------------------------------------------------------------*/
#include "mx_wifi_mbed_os.h"
#include "mx_wifi_conf_template.h"
#endif /* MX_WIFI_CONF_H */

View File

@ -0,0 +1,203 @@
/**
* <h2><center>&copy; Copyright (c) 2021 STMicroelectronics.
* SPDX-License-Identifier: BSD-3-Clause
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#include "EMW3080B_EMAC.h"
#include "mx_wifi_mbed_os.h"
extern "C"
{
#if BASIC_MALLOC == 0
mx_buf_t *mx_buf_alloc(uint32_t len)
{
emac_mem_buf_t *p = emac3080b_global_memory_manager->alloc_pool(len, 0);
return (mx_buf_t *) p;
}
void mx_buf_free(mx_buf_t *netb_in)
{
emac_mem_buf_t *netb = (emac_mem_buf_t *) netb_in;
emac3080b_global_memory_manager->free(netb);
}
void mx_buf_hide_header(mx_buf_t *netb_in, int32_t n)
{
if (n <= 0) {
error("Hiding header is not supported\n");
} else {
emac_mem_buf_t *netb = (emac_mem_buf_t *) netb_in;
ssize_t len = emac3080b_global_memory_manager->get_len(netb);
uint8_t *pdata = (uint8_t *) emac3080b_global_memory_manager->get_ptr(netb);
memmove(pdata, pdata + n, len);
}
}
uint8_t *mx_buf_payload(mx_buf_t *netb_in)
{
emac_mem_buf_t *netb = (emac_mem_buf_t *) netb_in;
return (uint8_t *) emac3080b_global_memory_manager->get_ptr(netb);
}
uint32_t mx_buf_get_size(mx_buf_t *netb_in)
{
emac_mem_buf_t *netb = (emac_mem_buf_t *) netb_in;
return emac3080b_global_memory_manager->get_len(netb);
}
void mx_buf_set_size(mx_buf_t *netb_in, int32_t n)
{
emac_mem_buf_t *netb = (emac_mem_buf_t *) netb_in;
return emac3080b_global_memory_manager->set_len(netb, n);
}
#endif /* BASIC_ALLOC */
void mbed_delay(uint32_t delay)
{
ThisThread::sleep_for(std::chrono::duration<uint32_t, std::milli>(delay));
}
void *mbed_mutex_new(void)
{
void *m;
m = new Mutex();
return (void *) m;
}
void mbed_mutex_delete(void *m)
{
delete ((Mutex *) m);
}
void mbed_mutex_lock(void *mutexin)
{
Mutex *mutex = (Mutex *) mutexin;
mutex->lock();
}
void mbed_mutex_unlock(void *mutexin)
{
Mutex *mutex = (Mutex *) mutexin;
mutex->unlock();
}
void *mbed_sem_new(uint32_t count)
{
Semaphore *sem;
sem = new Semaphore(count);
for (uint32_t ii = 0; ii < count ; ii++) {
sem->acquire();
}
return (void *) sem;
}
void mbed_sem_delete(void *insem)
{
Semaphore *sem = (Semaphore *) insem;
delete sem;
}
bool mbed_sem_signal(void *semin)
{
bool ret;
Semaphore *sem = (Semaphore *) semin;
ret = (sem->release() == osOK);
return ret;
}
bool mbed_sem_wait(void *semin, uint32_t timeout)
{
bool ret;
Semaphore *sem = (Semaphore *) semin;
ret = sem->try_acquire_for(std::chrono::duration<uint32_t, std::milli>(timeout));
return ret;
}
#define QSIZE 10
void *mbed_queue_new(uint32_t count)
{
Queue<uint32_t, QSIZE> *queue;
queue = new Queue<uint32_t, QSIZE> ;
return (void *) queue;
}
void mbed_queue_delete(void *queuein)
{
Queue<uint32_t, QSIZE> *queue = (Queue<uint32_t, QSIZE> *) queuein;
delete queue;
}
void *mbed_queue_pop(void *queuein, uint32_t timeout)
{
uint32_t *message = NULL;
Queue<uint32_t, QSIZE> *queue = (Queue<uint32_t, QSIZE> *) queuein;
while (true) {
if (queue->try_get_for(std::chrono::duration<uint32_t, std::milli>(timeout), &message)) {
break;
}
}
return (void *) message;
}
bool mbed_queue_push(void *queuein, void *value, uint32_t timeout)
{
Queue<uint32_t, QSIZE> *queue = (Queue<uint32_t, QSIZE> *) queuein;
return queue->try_put_for(std::chrono::duration<uint32_t, std::milli>(timeout), (uint32_t *)value);
}
void *mbed_thread_new(void (*thread_entry)(void), uint32_t stacksize, uint32_t prio_in)
{
osPriority_t priority;
priority = osPriorityNormal;
if (prio_in == OSPRIORITYREALTIME) {
priority = osPriorityRealtime;
}
if (prio_in == OSPRIORITYABOVENORMAL) {
priority = osPriorityAboveNormal;
}
Thread *thread = new Thread(priority, stacksize);
if (thread) {
thread->start(callback(thread_entry));
}
return (void *) thread;
}
void mbed_thread_delete(void *threadin)
{
Thread *thread = (Thread *) threadin;
thread->join();
}
void mbed_thread_terminate(void *threadin)
{
Thread *thread = (Thread *) threadin;
thread->terminate();
}
} /* end of extern "C" */

View File

@ -0,0 +1,154 @@
/**
* <h2><center>&copy; Copyright (c) 2021 STMicroelectronics.
* SPDX-License-Identifier: BSD-3-Clause
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef MX_WIFI_CMSIS_OS_H
#define MX_WIFI_CMSIS_OS_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include <stdlib.h>
#include <stdbool.h>
#include <stdint.h>
#include "mbed_assert.h"
#ifndef MX_WIFI_MALLOC
#define MX_WIFI_MALLOC malloc
#endif /* MX_WIFI_MALLOC */
#ifndef MX_WIFI_FREE
#define MX_WIFI_FREE free
#endif /* MX_WIFI_FREE */
#define BASIC_MALLOC 1
/* Assume that OS is not used when bypass is disabled */
#if BASIC_MALLOC
typedef struct mx_buf {
uint32_t len;
uint32_t header_len;
uint8_t data[1];
} mx_buf_t;
static inline mx_buf_t *mx_buf_alloc(uint32_t len)
{
mx_buf_t *p = (mx_buf_t *) MX_WIFI_MALLOC(len + sizeof(mx_buf_t) -1U);
if (NULL != p) {
p->len = len;
p->header_len = 0;
}
return p;
}
#define MX_NET_BUFFER_ALLOC(len) mx_buf_alloc(len)
#define MX_NET_BUFFER_FREE(p) MX_WIFI_FREE(p)
#define MX_NET_BUFFER_HIDE_HEADER(p, n) (p)->header_len += (n)
#define MX_NET_BUFFER_PAYLOAD(p) &(p)->data[(p)->header_len]
#define MX_NET_BUFFER_SET_PAYLOAD_SIZE(p, size) (p)->len = (size)
#define MX_NET_BUFFER_GET_PAYLOAD_SIZE(p) (p)->len
#else /* BASIC_ALLOC */
#define MX_NET_BUFFER_ALLOC(len) mx_buf_alloc((len))
#define MX_NET_BUFFER_FREE(p) mx_buf_free((p))
#define MX_NET_BUFFER_HIDE_HEADER(p, n) mx_buf_hide_header((p),(n))
#define MX_NET_BUFFER_PAYLOAD(p) mx_buf_payload((p))
#define MX_NET_BUFFER_SET_PAYLOAD_SIZE(p, size) mx_buf_set_size((p),(size))
#define MX_NET_BUFFER_GET_PAYLOAD_SIZE(p) mx_buf_get_size((p))
typedef void mx_buf_t;
mx_buf_t *mx_buf_alloc(uint32_t len);
void mx_buf_free(mx_buf_t *p);
void mx_buf_hide_header(mx_buf_t *p, int32_t n);
uint8_t *mx_buf_payload(mx_buf_t *p);
uint32_t mx_buf_get_size(mx_buf_t *p);
void mx_buf_set_size(mx_buf_t *p, int32_t n);
#endif /* BASIC_ALLOC */
void mbed_delay(uint32_t delay);
void *mbed_mutex_new(void);
void mbed_mutex_delete(void *);
void mbed_mutex_lock(void *);
void mbed_mutex_unlock(void *);
void *mbed_sem_new(uint32_t count);
void mbed_sem_delete(void *sem);
bool mbed_sem_signal(void *sem);
bool mbed_sem_wait(void *sem, uint32_t timeout);
void *mbed_queue_new(uint32_t count);
void mbed_queue_delete(void *sem);
void *mbed_queue_pop(void *sem, uint32_t timeout);
bool mbed_queue_push(void *sem, void *value, uint32_t timeout);
void *mbed_thread_new(void (*thread_entry)(void), uint32_t stacksize, uint32_t priority);
void mbed_thread_delete(void *thread);
void mbed_thread_terminate(void *thread);
#define MX_ASSERT(a) MBED_ASSERT(a)
#define LOCK_DECLARE(A) void* A
#define LOCK_INIT(A) A = mbed_mutex_new()
#define LOCK_DEINIT(A) mbed_mutex_delete(A)
#define LOCK(A) mbed_mutex_lock(A)
#define UNLOCK(A) mbed_mutex_unlock(A)
#define SEM_DECLARE(A) void *A
#define SEM_INIT(A,COUNT) A = mbed_sem_new(COUNT);
#define SEM_DEINIT(A) mbed_sem_delete(A)
#define SEM_SIGNAL(A) mbed_sem_signal(A)
#define SEM_WAIT(A,TIMEOUT,IDLE_FUNC) mbed_sem_wait(A,TIMEOUT)
#define THREAD_DECLARE(A) void *A
#define THREAD_INIT(A, THREAD_FUNC, THREAD_CONTEXT, STACKSIZE, PRIORITY) (((A = mbed_thread_new((THREAD_CONTEXT_FUNC_TYPE)THREAD_FUNC,STACKSIZE, PRIORITY))!= NULL)?true:false)
#define THREAD_DEINIT(A) mbed_thread_delete(A)
#define THREAD_TERMINATE(A) mbed_thread_terminate(A)
#define THREAD_CONTEXT_TYPE void
#define THREAD_CONTEXT_FUNC_TYPE void (*)(void)
#define FIFO_DECLARE(QUEUE) void* QUEUE
#define FIFO_PUSH(QUEUE, VALUE, TIMEOUT, IDLE_FUNC) mbed_queue_push(QUEUE, VALUE, TIMEOUT)
#define FIFO_POP(QUEUE, TIMEOUT, IDLE_FUNC) mbed_queue_pop(QUEUE, TIMEOUT)
#define FIFO_INIT(QUEUE,QSIZE) QUEUE = mbed_queue_new(QSIZE)
#define FIFO_DEINIT(QUEUE) mbed_queue_delete(QUEUE)
#define WAIT_FOREVER 0xffffffff
#define SEM_OK true
#define THREAD_OK true
#define QUEUE_OK true
#define FIFO_OK true
#define OSPRIORITYNORMAL 1
#define OSPRIORITYREALTIME 2
#define OSPRIORITYABOVENORMAL 3
#define DELAYms(n) mbed_delay(n)
#ifdef __cplusplus
}
#endif
#endif /* MX_WIFI_MBED_OS_H */

View File

@ -69,6 +69,7 @@ endif()
target_link_libraries(mbed-netsocket
INTERFACE
mbed-wifi
mbed-cellular
mbed-nanostack-libservice
)

View File

@ -4586,6 +4586,10 @@
"ARDUINO_UNO"
],
"device_name": "STM32U585AIIx",
"components_add": ["EMW3080B"],
"overrides": {
"network-default-interface-type": "WIFI"
},
"detect_code": [
"887"
]