mirror of https://github.com/ARMmbed/mbed-os.git
Merge pull request #15123 from jeromecoutant/PR_MXCHIP
STM32: introduce new wifi driver for B-U585I-IOT02Apull/15127/head
commit
6a9ccb3aa3
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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()
|
|
@ -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
|
||||
)
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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_ */
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
};
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
};
|
|
@ -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
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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.
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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 */
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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 */
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
@ -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 */
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
/**
|
||||
* <h2><center>© 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 */
|
|
@ -0,0 +1,203 @@
|
|||
/**
|
||||
* <h2><center>© 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" */
|
|
@ -0,0 +1,154 @@
|
|||
/**
|
||||
* <h2><center>© 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 */
|
|
@ -69,6 +69,7 @@ endif()
|
|||
|
||||
target_link_libraries(mbed-netsocket
|
||||
INTERFACE
|
||||
mbed-wifi
|
||||
mbed-cellular
|
||||
mbed-nanostack-libservice
|
||||
)
|
||||
|
|
|
@ -4586,6 +4586,10 @@
|
|||
"ARDUINO_UNO"
|
||||
],
|
||||
"device_name": "STM32U585AIIx",
|
||||
"components_add": ["EMW3080B"],
|
||||
"overrides": {
|
||||
"network-default-interface-type": "WIFI"
|
||||
},
|
||||
"detect_code": [
|
||||
"887"
|
||||
]
|
||||
|
|
Loading…
Reference in New Issue